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