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