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