1e1f4db62SRatan Gupta #include "ldap_config_mgr.hpp" 237fb3feeSRatan Gupta #include "ldap_config.hpp" 3e1f4db62SRatan Gupta 4e1f4db62SRatan Gupta #include "utils.hpp" 5e1f4db62SRatan Gupta #include <filesystem> 6e1f4db62SRatan Gupta #include <fstream> 7e1f4db62SRatan Gupta #include <sstream> 8e1f4db62SRatan Gupta 9e1f4db62SRatan Gupta namespace phosphor 10e1f4db62SRatan Gupta { 11e1f4db62SRatan Gupta namespace ldap 12e1f4db62SRatan Gupta { 13e1f4db62SRatan Gupta 14e1f4db62SRatan Gupta constexpr auto nscdService = "nscd.service"; 15e1f4db62SRatan Gupta constexpr auto LDAPscheme = "ldap"; 16e1f4db62SRatan Gupta constexpr auto LDAPSscheme = "ldaps"; 17e1f4db62SRatan Gupta 18e1f4db62SRatan Gupta using namespace phosphor::logging; 19e1f4db62SRatan Gupta using namespace sdbusplus::xyz::openbmc_project::Common::Error; 20e1f4db62SRatan Gupta namespace fs = std::filesystem; 21e1f4db62SRatan Gupta using Argument = xyz::openbmc_project::Common::InvalidArgument; 22*c5481d1cSRatan Gupta using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 23*c5481d1cSRatan Gupta using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed; 24e1f4db62SRatan Gupta 25e1f4db62SRatan Gupta using Line = std::string; 26e1f4db62SRatan Gupta using Key = std::string; 27e1f4db62SRatan Gupta using Val = std::string; 28e1f4db62SRatan Gupta using ConfigInfo = std::map<Key, Val>; 29e1f4db62SRatan Gupta 30e1f4db62SRatan Gupta void ConfigMgr::startOrStopService(const std::string& service, bool start) 31e1f4db62SRatan Gupta { 32e1f4db62SRatan Gupta if (start) 33e1f4db62SRatan Gupta { 34e1f4db62SRatan Gupta restartService(service); 35e1f4db62SRatan Gupta } 36e1f4db62SRatan Gupta else 37e1f4db62SRatan Gupta { 38e1f4db62SRatan Gupta stopService(service); 39e1f4db62SRatan Gupta } 40e1f4db62SRatan Gupta } 41e1f4db62SRatan Gupta 42e1f4db62SRatan Gupta void ConfigMgr::restartService(const std::string& service) 43e1f4db62SRatan Gupta { 44e1f4db62SRatan Gupta try 45e1f4db62SRatan Gupta { 46e1f4db62SRatan Gupta auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 47e1f4db62SRatan Gupta SYSTEMD_INTERFACE, "RestartUnit"); 48e1f4db62SRatan Gupta method.append(service.c_str(), "replace"); 49e1f4db62SRatan Gupta bus.call_noreply(method); 50e1f4db62SRatan Gupta } 51e1f4db62SRatan Gupta catch (const sdbusplus::exception::SdBusError& ex) 52e1f4db62SRatan Gupta { 53e1f4db62SRatan Gupta log<level::ERR>("Failed to restart service", 54e1f4db62SRatan Gupta entry("SERVICE=%s", service.c_str()), 55e1f4db62SRatan Gupta entry("ERR=%s", ex.what())); 56e1f4db62SRatan Gupta elog<InternalFailure>(); 57e1f4db62SRatan Gupta } 58e1f4db62SRatan Gupta } 59e1f4db62SRatan Gupta void ConfigMgr::stopService(const std::string& service) 60e1f4db62SRatan Gupta { 61e1f4db62SRatan Gupta try 62e1f4db62SRatan Gupta { 63e1f4db62SRatan Gupta auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 64e1f4db62SRatan Gupta SYSTEMD_INTERFACE, "StopUnit"); 65e1f4db62SRatan Gupta method.append(service.c_str(), "replace"); 66e1f4db62SRatan Gupta bus.call_noreply(method); 67e1f4db62SRatan Gupta } 68e1f4db62SRatan Gupta catch (const sdbusplus::exception::SdBusError& ex) 69e1f4db62SRatan Gupta { 70e1f4db62SRatan Gupta log<level::ERR>("Failed to stop service", 71e1f4db62SRatan Gupta entry("SERVICE=%s", service.c_str()), 72e1f4db62SRatan Gupta entry("ERR=%s", ex.what())); 73e1f4db62SRatan Gupta elog<InternalFailure>(); 74e1f4db62SRatan Gupta } 75e1f4db62SRatan Gupta } 76e1f4db62SRatan Gupta 77e1f4db62SRatan Gupta std::string ConfigMgr::createConfig( 78e1f4db62SRatan Gupta std::string lDAPServerURI, std::string lDAPBindDN, std::string lDAPBaseDN, 79e1f4db62SRatan Gupta std::string lDAPBindDNPassword, CreateIface::SearchScope lDAPSearchScope, 80e1f4db62SRatan Gupta CreateIface::Create::Type lDAPType, std::string groupNameAttribute, 81e1f4db62SRatan Gupta std::string userNameAttribute) 82e1f4db62SRatan Gupta { 83e1f4db62SRatan Gupta bool secureLDAP = false; 84e1f4db62SRatan Gupta 85e1f4db62SRatan Gupta if (isValidLDAPURI(lDAPServerURI, LDAPSscheme)) 86e1f4db62SRatan Gupta { 87e1f4db62SRatan Gupta secureLDAP = true; 88e1f4db62SRatan Gupta } 89e1f4db62SRatan Gupta else if (isValidLDAPURI(lDAPServerURI, LDAPscheme)) 90e1f4db62SRatan Gupta { 91e1f4db62SRatan Gupta secureLDAP = false; 92e1f4db62SRatan Gupta } 93e1f4db62SRatan Gupta else 94e1f4db62SRatan Gupta { 95e1f4db62SRatan Gupta log<level::ERR>("bad LDAP Server URI", 96e1f4db62SRatan Gupta entry("LDAPSERVERURI=%s", lDAPServerURI.c_str())); 97e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("lDAPServerURI"), 98e1f4db62SRatan Gupta Argument::ARGUMENT_VALUE(lDAPServerURI.c_str())); 99e1f4db62SRatan Gupta } 100e1f4db62SRatan Gupta 101e1f4db62SRatan Gupta if (secureLDAP && !fs::exists(tlsCacertFile.c_str())) 102e1f4db62SRatan Gupta { 103e1f4db62SRatan Gupta log<level::ERR>("LDAP server's CA certificate not provided", 104e1f4db62SRatan Gupta entry("TLSCACERTFILE=%s", tlsCacertFile.c_str())); 105e1f4db62SRatan Gupta elog<NoCACertificate>(); 106e1f4db62SRatan Gupta } 107e1f4db62SRatan Gupta 108e1f4db62SRatan Gupta if (lDAPBindDN.empty()) 109e1f4db62SRatan Gupta { 110e1f4db62SRatan Gupta log<level::ERR>("Not a valid LDAP BINDDN", 111e1f4db62SRatan Gupta entry("LDAPBINDDN=%s", lDAPBindDN.c_str())); 112e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"), 113e1f4db62SRatan Gupta Argument::ARGUMENT_VALUE(lDAPBindDN.c_str())); 114e1f4db62SRatan Gupta } 115e1f4db62SRatan Gupta 116e1f4db62SRatan Gupta if (lDAPBaseDN.empty()) 117e1f4db62SRatan Gupta { 118e1f4db62SRatan Gupta log<level::ERR>("Not a valid LDAP BASEDN", 119e1f4db62SRatan Gupta entry("LDAPBASEDN=%s", lDAPBaseDN.c_str())); 120e1f4db62SRatan Gupta elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"), 121e1f4db62SRatan Gupta Argument::ARGUMENT_VALUE(lDAPBaseDN.c_str())); 122e1f4db62SRatan Gupta } 123e1f4db62SRatan Gupta 12427d4c011SRatan Gupta // With current implementation we support only two default LDAP server. 12527d4c011SRatan Gupta // which will be always there but when the support comes for additional 12627d4c011SRatan Gupta // account providers then the create config would be used to create the 12727d4c011SRatan Gupta // additional config. 128e1f4db62SRatan Gupta 12927d4c011SRatan Gupta std::string objPath; 13027d4c011SRatan Gupta 13127d4c011SRatan Gupta if (static_cast<ConfigIface::Type>(lDAPType) == ConfigIface::Type::OpenLdap) 13227d4c011SRatan Gupta { 13327d4c011SRatan Gupta openLDAPConfigPtr.reset(nullptr); 13427d4c011SRatan Gupta objPath = openLDAPDbusObjectPath; 13527d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>( 136e1f4db62SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 137e1f4db62SRatan Gupta secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN, 138e1f4db62SRatan Gupta std::move(lDAPBindDNPassword), 139e1f4db62SRatan Gupta static_cast<ConfigIface::SearchScope>(lDAPSearchScope), 140e1f4db62SRatan Gupta static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute, 141e1f4db62SRatan Gupta userNameAttribute, *this); 14227d4c011SRatan Gupta } 14327d4c011SRatan Gupta else 14427d4c011SRatan Gupta { 14527d4c011SRatan Gupta ADConfigPtr.reset(nullptr); 14627d4c011SRatan Gupta objPath = ADDbusObjectPath; 14727d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>( 14827d4c011SRatan Gupta bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(), 14927d4c011SRatan Gupta secureLDAP, lDAPServerURI, lDAPBindDN, lDAPBaseDN, 15027d4c011SRatan Gupta std::move(lDAPBindDNPassword), 15127d4c011SRatan Gupta static_cast<ConfigIface::SearchScope>(lDAPSearchScope), 15227d4c011SRatan Gupta static_cast<ConfigIface::Type>(lDAPType), false, groupNameAttribute, 15327d4c011SRatan Gupta userNameAttribute, *this); 15427d4c011SRatan Gupta } 155e1f4db62SRatan Gupta restartService(nscdService); 156e1f4db62SRatan Gupta return objPath; 157e1f4db62SRatan Gupta } 158e1f4db62SRatan Gupta 15927d4c011SRatan Gupta void ConfigMgr::createDefaultObjects() 160e1f4db62SRatan Gupta { 16127d4c011SRatan Gupta if (!openLDAPConfigPtr) 162e1f4db62SRatan Gupta { 16327d4c011SRatan Gupta openLDAPConfigPtr = std::make_unique<Config>( 16427d4c011SRatan Gupta bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(), 16521e88cb5SRatan Gupta tlsCacertFile.c_str(), ConfigIface::Type::OpenLdap, *this); 16621e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added(); 167e1f4db62SRatan Gupta } 16827d4c011SRatan Gupta if (!ADConfigPtr) 169e1f4db62SRatan Gupta { 17027d4c011SRatan Gupta ADConfigPtr = std::make_unique<Config>( 17127d4c011SRatan Gupta bus, ADDbusObjectPath.c_str(), configFilePath.c_str(), 17221e88cb5SRatan Gupta tlsCacertFile.c_str(), ConfigIface::Type::ActiveDirectory, *this); 17321e88cb5SRatan Gupta ADConfigPtr->emit_object_added(); 17421e88cb5SRatan Gupta } 17521e88cb5SRatan Gupta } 17621e88cb5SRatan Gupta 177*c5481d1cSRatan Gupta bool ConfigMgr::enableService(Config& config, bool value) 178*c5481d1cSRatan Gupta { 179*c5481d1cSRatan Gupta if (value) 180*c5481d1cSRatan Gupta { 181*c5481d1cSRatan Gupta if (openLDAPConfigPtr && openLDAPConfigPtr->enabled()) 182*c5481d1cSRatan Gupta { 183*c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON( 184*c5481d1cSRatan Gupta "OpenLDAP service is already active")); 185*c5481d1cSRatan Gupta } 186*c5481d1cSRatan Gupta if (ADConfigPtr && ADConfigPtr->enabled()) 187*c5481d1cSRatan Gupta { 188*c5481d1cSRatan Gupta elog<NotAllowed>(NotAllowedArgument::REASON( 189*c5481d1cSRatan Gupta "ActiveDirectory service is already active")); 190*c5481d1cSRatan Gupta } 191*c5481d1cSRatan Gupta } 192*c5481d1cSRatan Gupta return config.enableService(value); 193*c5481d1cSRatan Gupta } 194*c5481d1cSRatan Gupta 19521e88cb5SRatan Gupta void ConfigMgr::restore() 19621e88cb5SRatan Gupta { 19721e88cb5SRatan Gupta createDefaultObjects(); 19821e88cb5SRatan Gupta // Restore the ldap config and their mappings 19921e88cb5SRatan Gupta if (ADConfigPtr->deserialize()) 20021e88cb5SRatan Gupta { 20121e88cb5SRatan Gupta // Restore the role mappings in later commit 20221e88cb5SRatan Gupta ADConfigPtr->emit_object_added(); 20321e88cb5SRatan Gupta } 20421e88cb5SRatan Gupta if (openLDAPConfigPtr->deserialize()) 20521e88cb5SRatan Gupta { 20621e88cb5SRatan Gupta // Restore the role mappings in later commit 20721e88cb5SRatan Gupta openLDAPConfigPtr->emit_object_added(); 208e1f4db62SRatan Gupta } 209e1f4db62SRatan Gupta } 210e1f4db62SRatan Gupta 211e1f4db62SRatan Gupta } // namespace ldap 212e1f4db62SRatan Gupta } // namespace phosphor 213