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