1e1f4db62SRatan Gupta #include "ldap_config_mgr.hpp" 2e1f4db62SRatan Gupta 39638afb9SPatrick Williams #include "ldap_config.hpp" 4e1f4db62SRatan Gupta #include "utils.hpp" 59638afb9SPatrick Williams 6e1f4db62SRatan Gupta #include <filesystem> 7e1f4db62SRatan Gupta #include <fstream> 8e1f4db62SRatan Gupta #include <sstream> 9e1f4db62SRatan Gupta 10e1f4db62SRatan Gupta namespace phosphor 11e1f4db62SRatan Gupta { 12e1f4db62SRatan Gupta namespace ldap 13e1f4db62SRatan Gupta { 14e1f4db62SRatan Gupta 15372c5668SAlexander Filippov constexpr auto nslcdService = "nslcd.service"; 16e1f4db62SRatan Gupta constexpr auto nscdService = "nscd.service"; 17*78d85042SNan Zhou constexpr auto ldapScheme = "ldap"; 18*78d85042SNan Zhou constexpr auto ldapsScheme = "ldaps"; 19e1f4db62SRatan Gupta 20e1f4db62SRatan Gupta using namespace phosphor::logging; 21e1f4db62SRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error; 22e1f4db62SRatan Gupta namespace fs = std::filesystem; 23e1f4db62SRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument; 24c5481d1cSRatan Gupta using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 25c5481d1cSRatan Gupta using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed; 26e1f4db62SRatan Gupta 27e1f4db62SRatan Gupta using Line = std::string; 28e1f4db62SRatan Gupta using Key = std::string; 29e1f4db62SRatan Gupta using Val = std::string; 30e1f4db62SRatan Gupta using ConfigInfo = std::map<Key, Val>; 31e1f4db62SRatan Gupta 32e1f4db62SRatan Gupta void ConfigMgr::startOrStopService(const std::string& service, bool start) 33e1f4db62SRatan Gupta { 34e1f4db62SRatan Gupta if (start) 35e1f4db62SRatan Gupta { 36e1f4db62SRatan Gupta restartService(service); 37e1f4db62SRatan Gupta } 38e1f4db62SRatan Gupta else 39e1f4db62SRatan Gupta { 40e1f4db62SRatan Gupta stopService(service); 41e1f4db62SRatan Gupta } 42e1f4db62SRatan Gupta } 43e1f4db62SRatan Gupta 44e1f4db62SRatan Gupta void ConfigMgr::restartService(const std::string& service) 45e1f4db62SRatan Gupta { 46e1f4db62SRatan Gupta try 47e1f4db62SRatan Gupta { 48e1f4db62SRatan Gupta auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 49e1f4db62SRatan Gupta SYSTEMD_INTERFACE, "RestartUnit"); 50e1f4db62SRatan Gupta method.append(service.c_str(), "replace"); 51e1f4db62SRatan Gupta bus.call_noreply(method); 52e1f4db62SRatan Gupta } 53b3ef4e1aSPatrick Williams catch (const sdbusplus::exception_t& ex) 54e1f4db62SRatan Gupta { 55e1f4db62SRatan Gupta log<level::ERR>("Failed to restart service", 56e1f4db62SRatan Gupta entry("SERVICE=%s", service.c_str()), 57e1f4db62SRatan Gupta entry("ERR=%s", ex.what())); 58e1f4db62SRatan Gupta elog<InternalFailure>(); 59e1f4db62SRatan Gupta } 60e1f4db62SRatan Gupta } 61e1f4db62SRatan Gupta void ConfigMgr::stopService(const std::string& service) 62e1f4db62SRatan Gupta { 63e1f4db62SRatan Gupta try 64e1f4db62SRatan Gupta { 65e1f4db62SRatan Gupta auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 66e1f4db62SRatan Gupta SYSTEMD_INTERFACE, "StopUnit"); 67e1f4db62SRatan Gupta method.append(service.c_str(), "replace"); 68e1f4db62SRatan Gupta bus.call_noreply(method); 69e1f4db62SRatan Gupta } 70b3ef4e1aSPatrick Williams catch (const sdbusplus::exception_t& ex) 71e1f4db62SRatan Gupta { 72e1f4db62SRatan Gupta log<level::ERR>("Failed to stop service", 73e1f4db62SRatan Gupta entry("SERVICE=%s", service.c_str()), 74e1f4db62SRatan Gupta entry("ERR=%s", ex.what())); 75e1f4db62SRatan Gupta elog<InternalFailure>(); 76e1f4db62SRatan Gupta } 77e1f4db62SRatan Gupta } 78e1f4db62SRatan Gupta 79e1f4db62SRatan Gupta std::string ConfigMgr::createConfig( 80e6500a49SPatrick Williams std::string ldapServerURI, std::string ldapBindDN, std::string ldapBaseDN, 81e6500a49SPatrick Williams std::string ldapBindDNPassword, CreateIface::SearchScope ldapSearchScope, 82e6500a49SPatrick Williams CreateIface::Create::Type ldapType, std::string groupNameAttribute, 83e1f4db62SRatan Gupta std::string userNameAttribute) 84e1f4db62SRatan Gupta { 85e1f4db62SRatan Gupta bool secureLDAP = false; 86e1f4db62SRatan Gupta 87*78d85042SNan Zhou if (isValidLDAPURI(ldapServerURI, ldapsScheme)) 88e1f4db62SRatan Gupta { 89e1f4db62SRatan Gupta secureLDAP = true; 90e1f4db62SRatan Gupta } 91*78d85042SNan Zhou else if (isValidLDAPURI(ldapServerURI, ldapScheme)) 92e1f4db62SRatan Gupta { 93e1f4db62SRatan Gupta secureLDAP = false; 94e1f4db62SRatan Gupta } 95e1f4db62SRatan Gupta else 96e1f4db62SRatan Gupta { 97e1f4db62SRatan Gupta log<level::ERR>("bad LDAP Server URI", 98e6500a49SPatrick Williams entry("LDAPSERVERURI=%s", ldapServerURI.c_str())); 99e6500a49SPatrick Williams elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"), 100e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapServerURI.c_str())); 101e1f4db62SRatan Gupta } 102e1f4db62SRatan Gupta 103e1f4db62SRatan Gupta if (secureLDAP && !fs::exists(tlsCacertFile.c_str())) 104e1f4db62SRatan Gupta { 105e1f4db62SRatan Gupta log<level::ERR>("LDAP server's CA certificate not provided", 106e1f4db62SRatan Gupta entry("TLSCACERTFILE=%s", tlsCacertFile.c_str())); 107e1f4db62SRatan Gupta elog<NoCACertificate>(); 108e1f4db62SRatan Gupta } 109e1f4db62SRatan Gupta 110e6500a49SPatrick Williams if (ldapBindDN.empty()) 111e1f4db62SRatan Gupta { 112e1f4db62SRatan Gupta log<level::ERR>("Not a valid LDAP BINDDN", 113e6500a49SPatrick Williams entry("LDAPBINDDN=%s", ldapBindDN.c_str())); 114e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"), 115e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapBindDN.c_str())); 116e1f4db62SRatan Gupta } 117e1f4db62SRatan Gupta 118e6500a49SPatrick Williams if (ldapBaseDN.empty()) 119e1f4db62SRatan Gupta { 120e1f4db62SRatan Gupta log<level::ERR>("Not a valid LDAP BASEDN", 121e6500a49SPatrick Williams entry("LDAPBASEDN=%s", ldapBaseDN.c_str())); 122e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"), 123e6500a49SPatrick Williams Argument::ARGUMENT_VALUE(ldapBaseDN.c_str())); 124e1f4db62SRatan Gupta } 125e1f4db62SRatan Gupta 12627d4c011SRatan Gupta // With current implementation we support only two default LDAP server. 12727d4c011SRatan Gupta // which will be always there but when the support comes for additional 12827d4c011SRatan Gupta // account providers then the create config would be used to create the 12927d4c011SRatan Gupta // additional config. 130e1f4db62SRatan Gupta 13127d4c011SRatan Gupta std::string objPath; 13227d4c011SRatan Gupta 133e6500a49SPatrick Williams if (static_cast<ConfigIface::Type>(ldapType) == ConfigIface::Type::OpenLdap) 13427d4c011SRatan Gupta { 13527d4c011SRatan Gupta openLDAPConfigPtr.reset(nullptr); 13627d4c011SRatan Gupta objPath = openLDAPDbusObjectPath; 13727d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>( 138e1f4db62SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 139e6500a49SPatrick Williams tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN, 140e6500a49SPatrick Williams ldapBaseDN, std::move(ldapBindDNPassword), 141e6500a49SPatrick Williams static_cast<ConfigIface::SearchScope>(ldapSearchScope), 142e6500a49SPatrick Williams static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute, 143e1f4db62SRatan Gupta userNameAttribute, *this); 14427d4c011SRatan Gupta } 14527d4c011SRatan Gupta else 14627d4c011SRatan Gupta { 14727d4c011SRatan Gupta ADConfigPtr.reset(nullptr); 148*78d85042SNan Zhou objPath = adDbusObjectPath; 14927d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>( 15027d4c011SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 151e6500a49SPatrick Williams tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN, 152e6500a49SPatrick Williams ldapBaseDN, std::move(ldapBindDNPassword), 153e6500a49SPatrick Williams static_cast<ConfigIface::SearchScope>(ldapSearchScope), 154e6500a49SPatrick Williams static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute, 15527d4c011SRatan Gupta userNameAttribute, *this); 15627d4c011SRatan Gupta } 157e1f4db62SRatan Gupta restartService(nscdService); 158e1f4db62SRatan Gupta return objPath; 159e1f4db62SRatan Gupta } 160e1f4db62SRatan Gupta 16127d4c011SRatan Gupta void ConfigMgr::createDefaultObjects() 162e1f4db62SRatan Gupta { 16327d4c011SRatan Gupta if (!openLDAPConfigPtr) 164e1f4db62SRatan Gupta { 16527d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>( 16627d4c011SRatan Gupta bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(), 167ab4fcb4cSRatan Gupta tlsCacertFile.c_str(), tlsCertFile.c_str(), 168ab4fcb4cSRatan Gupta ConfigIface::Type::OpenLdap, *this); 16921e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added(); 170e1f4db62SRatan Gupta } 17127d4c011SRatan Gupta if (!ADConfigPtr) 172e1f4db62SRatan Gupta { 17327d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>( 174*78d85042SNan Zhou bus, adDbusObjectPath.c_str(), configFilePath.c_str(), 175ab4fcb4cSRatan Gupta tlsCacertFile.c_str(), tlsCertFile.c_str(), 176ab4fcb4cSRatan Gupta ConfigIface::Type::ActiveDirectory, *this); 17721e88cb5SRatan Gupta ADConfigPtr->emit_object_added(); 17821e88cb5SRatan Gupta } 17921e88cb5SRatan Gupta } 18021e88cb5SRatan Gupta 181c5481d1cSRatan Gupta bool ConfigMgr::enableService(Config& config, bool value) 182c5481d1cSRatan Gupta { 183c5481d1cSRatan Gupta if (value) 184c5481d1cSRatan Gupta { 185c5481d1cSRatan Gupta if (openLDAPConfigPtr && openLDAPConfigPtr->enabled()) 186c5481d1cSRatan Gupta { 187c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON( 188c5481d1cSRatan Gupta "OpenLDAP service is already active")); 189c5481d1cSRatan Gupta } 190c5481d1cSRatan Gupta if (ADConfigPtr && ADConfigPtr->enabled()) 191c5481d1cSRatan Gupta { 192c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON( 193c5481d1cSRatan Gupta "ActiveDirectory service is already active")); 194c5481d1cSRatan Gupta } 195c5481d1cSRatan Gupta } 196c5481d1cSRatan Gupta return config.enableService(value); 197c5481d1cSRatan Gupta } 198c5481d1cSRatan Gupta 19921e88cb5SRatan Gupta void ConfigMgr::restore() 20021e88cb5SRatan Gupta { 20121e88cb5SRatan Gupta createDefaultObjects(); 20221e88cb5SRatan Gupta // Restore the ldap config and their mappings 20321e88cb5SRatan Gupta if (ADConfigPtr->deserialize()) 20421e88cb5SRatan Gupta { 2057b04c352SRatan Gupta // Restore the role mappings 2067b04c352SRatan Gupta ADConfigPtr->restoreRoleMapping(); 20721e88cb5SRatan Gupta ADConfigPtr->emit_object_added(); 20821e88cb5SRatan Gupta } 20921e88cb5SRatan Gupta if (openLDAPConfigPtr->deserialize()) 21021e88cb5SRatan Gupta { 2117b04c352SRatan Gupta // Restore the role mappings 2127b04c352SRatan Gupta openLDAPConfigPtr->restoreRoleMapping(); 21321e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added(); 214e1f4db62SRatan Gupta } 215372c5668SAlexander Filippov 216372c5668SAlexander Filippov startOrStopService(phosphor::ldap::nslcdService, 217372c5668SAlexander Filippov ADConfigPtr->enabled() || openLDAPConfigPtr->enabled()); 218e1f4db62SRatan Gupta } 219e1f4db62SRatan Gupta 220e1f4db62SRatan Gupta } // namespace ldap 221e1f4db62SRatan Gupta } // namespace phosphor 222