1 #include "ldap_config_mgr.hpp" 2 3 #include "ldap_config.hpp" 4 #include "utils.hpp" 5 6 #include <phosphor-logging/elog-errors.hpp> 7 #include <phosphor-logging/elog.hpp> 8 #include <phosphor-logging/lg2.hpp> 9 #include <xyz/openbmc_project/Common/error.hpp> 10 11 #include <filesystem> 12 #include <fstream> 13 #include <sstream> 14 15 namespace phosphor 16 { 17 namespace ldap 18 { 19 20 constexpr auto nslcdService = "nslcd.service"; 21 constexpr auto nscdService = "nscd.service"; 22 constexpr auto ldapScheme = "ldap"; 23 constexpr auto ldapsScheme = "ldaps"; 24 25 using namespace phosphor::logging; 26 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 27 namespace fs = std::filesystem; 28 using Argument = xyz::openbmc_project::Common::InvalidArgument; 29 using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed; 30 31 using Line = std::string; 32 using Key = std::string; 33 using Val = std::string; 34 using ConfigInfo = std::map<Key, Val>; 35 36 void ConfigMgr::startOrStopService(const std::string& service, bool start) 37 { 38 if (start) 39 { 40 restartService(service); 41 } 42 else 43 { 44 stopService(service); 45 } 46 } 47 48 void ConfigMgr::restartService(const std::string& service) 49 { 50 try 51 { 52 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 53 SYSTEMD_INTERFACE, "RestartUnit"); 54 method.append(service.c_str(), "replace"); 55 bus.call_noreply(method); 56 } 57 catch (const sdbusplus::exception_t& ex) 58 { 59 lg2::error("Failed to restart service {SERVICE}: {ERR}", "SERVICE", 60 service, "ERR", ex); 61 elog<InternalFailure>(); 62 } 63 } 64 void ConfigMgr::stopService(const std::string& service) 65 { 66 try 67 { 68 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 69 SYSTEMD_INTERFACE, "StopUnit"); 70 method.append(service.c_str(), "replace"); 71 bus.call_noreply(method); 72 } 73 catch (const sdbusplus::exception_t& ex) 74 { 75 lg2::error("Failed to stop service {SERVICE}: {ERR}", "SERVICE", 76 service, "ERR", ex); 77 elog<InternalFailure>(); 78 } 79 } 80 81 std::string ConfigMgr::createConfig( 82 std::string ldapServerURI, std::string ldapBindDN, std::string ldapBaseDN, 83 std::string ldapBindDNPassword, CreateIface::SearchScope ldapSearchScope, 84 CreateIface::Create::Type ldapType, std::string groupNameAttribute, 85 std::string userNameAttribute) 86 { 87 bool secureLDAP = false; 88 89 if (isValidLDAPURI(ldapServerURI, ldapsScheme)) 90 { 91 secureLDAP = true; 92 } 93 else if (isValidLDAPURI(ldapServerURI, ldapScheme)) 94 { 95 secureLDAP = false; 96 } 97 else 98 { 99 lg2::error("Bad LDAP Server URI {URI}", "URI", ldapServerURI); 100 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"), 101 Argument::ARGUMENT_VALUE(ldapServerURI.c_str())); 102 } 103 104 if (secureLDAP && !fs::exists(tlsCacertFile.c_str())) 105 { 106 lg2::error("LDAP server CA certificate not found at {PATH}", "PATH", 107 tlsCacertFile); 108 elog<NoCACertificate>(); 109 } 110 111 if (ldapBindDN.empty()) 112 { 113 lg2::error("'{BINDDN}' is not a valid LDAP BindDN", "BINDDN", 114 ldapBindDN); 115 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"), 116 Argument::ARGUMENT_VALUE(ldapBindDN.c_str())); 117 } 118 119 if (ldapBaseDN.empty()) 120 { 121 lg2::error("'{BASEDN}' is not a valid LDAP BaseDN", "BASEDN", 122 ldapBaseDN); 123 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"), 124 Argument::ARGUMENT_VALUE(ldapBaseDN.c_str())); 125 } 126 127 // With current implementation we support only two default LDAP server. 128 // which will be always there but when the support comes for additional 129 // account providers then the create config would be used to create the 130 // additional config. 131 132 std::string objPath; 133 134 if (static_cast<ConfigIface::Type>(ldapType) == ConfigIface::Type::OpenLdap) 135 { 136 openLDAPConfigPtr.reset(nullptr); 137 objPath = openLDAPDbusObjectPath; 138 openLDAPConfigPtr = std::make_unique<Config>( 139 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 140 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN, 141 ldapBaseDN, std::move(ldapBindDNPassword), 142 static_cast<ConfigIface::SearchScope>(ldapSearchScope), 143 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute, 144 userNameAttribute, *this); 145 } 146 else 147 { 148 ADConfigPtr.reset(nullptr); 149 objPath = adDbusObjectPath; 150 ADConfigPtr = std::make_unique<Config>( 151 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 152 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN, 153 ldapBaseDN, std::move(ldapBindDNPassword), 154 static_cast<ConfigIface::SearchScope>(ldapSearchScope), 155 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute, 156 userNameAttribute, *this); 157 } 158 restartService(nscdService); 159 return objPath; 160 } 161 162 void ConfigMgr::createDefaultObjects() 163 { 164 if (!openLDAPConfigPtr) 165 { 166 openLDAPConfigPtr = std::make_unique<Config>( 167 bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(), 168 tlsCacertFile.c_str(), tlsCertFile.c_str(), 169 ConfigIface::Type::OpenLdap, *this); 170 openLDAPConfigPtr->emit_object_added(); 171 } 172 if (!ADConfigPtr) 173 { 174 ADConfigPtr = std::make_unique<Config>( 175 bus, adDbusObjectPath.c_str(), configFilePath.c_str(), 176 tlsCacertFile.c_str(), tlsCertFile.c_str(), 177 ConfigIface::Type::ActiveDirectory, *this); 178 ADConfigPtr->emit_object_added(); 179 } 180 } 181 182 bool ConfigMgr::enableService(Config& config, bool value) 183 { 184 if (value) 185 { 186 if (openLDAPConfigPtr && openLDAPConfigPtr->enabled()) 187 { 188 elog<NotAllowed>(NotAllowedArgument::REASON( 189 "OpenLDAP service is already active")); 190 } 191 if (ADConfigPtr && ADConfigPtr->enabled()) 192 { 193 elog<NotAllowed>(NotAllowedArgument::REASON( 194 "ActiveDirectory service is already active")); 195 } 196 } 197 return config.enableService(value); 198 } 199 200 void ConfigMgr::restore() 201 { 202 createDefaultObjects(); 203 // Restore the ldap config and their mappings 204 if (ADConfigPtr->deserialize()) 205 { 206 // Restore the role mappings 207 ADConfigPtr->restoreRoleMapping(); 208 ADConfigPtr->emit_object_added(); 209 } 210 if (openLDAPConfigPtr->deserialize()) 211 { 212 // Restore the role mappings 213 openLDAPConfigPtr->restoreRoleMapping(); 214 openLDAPConfigPtr->emit_object_added(); 215 } 216 217 startOrStopService(phosphor::ldap::nslcdService, 218 ADConfigPtr->enabled() || openLDAPConfigPtr->enabled()); 219 } 220 221 } // namespace ldap 222 } // namespace phosphor 223