1 #include "config.h"
2 #include "phosphor-ldap-config/ldap_config.hpp"
3 #include "phosphor-ldap-config/ldap_config_mgr.hpp"
4 #include "phosphor-ldap-config/ldap_config_serialize.hpp"
5 
6 #include <phosphor-logging/log.hpp>
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <sdbusplus/bus.hpp>
9 #include <xyz/openbmc_project/Common/error.hpp>
10 #include <sdbusplus/bus.hpp>
11 #include <gmock/gmock.h>
12 #include <gtest/gtest.h>
13 
14 #include <filesystem>
15 #include <fstream>
16 #include <string>
17 #include <sys/types.h>
18 
19 namespace phosphor
20 {
21 namespace ldap
22 {
23 namespace fs = std::filesystem;
24 namespace ldap_base = sdbusplus::xyz::openbmc_project::User::Ldap::server;
25 using Config = phosphor::ldap::Config;
26 static constexpr const char* dbusPersistFile = "Config";
27 
28 class TestLDAPConfig : public testing::Test
29 {
30   public:
31     TestLDAPConfig() : bus(sdbusplus::bus::new_default())
32     {
33     }
34     void SetUp() override
35     {
36         using namespace phosphor::ldap;
37         char tmpldap[] = "/tmp/ldap_test.XXXXXX";
38         dir = fs::path(mkdtemp(tmpldap));
39         fs::path tslCacertFilePath{TLS_CACERT_FILE};
40         tslCacertFile = tslCacertFilePath.filename().c_str();
41         fs::path confFilePath{LDAP_CONFIG_FILE};
42         ldapconfFile = confFilePath.filename().c_str();
43         std::fstream fs;
44         fs.open(dir / defaultNslcdFile, std::fstream::out);
45         fs.close();
46         fs.open(dir / nsSwitchFile, std::fstream::out);
47         fs.close();
48     }
49 
50     void TearDown() override
51     {
52         fs::remove_all(dir);
53     }
54 
55   protected:
56     fs::path dir;
57     std::string tslCacertFile;
58     std::string ldapconfFile;
59     sdbusplus::bus::bus bus;
60 };
61 
62 class MockConfigMgr : public phosphor::ldap::ConfigMgr
63 {
64   public:
65     MockConfigMgr(sdbusplus::bus::bus& bus, const char* path,
66                   const char* filePath, const char* dbusPersistentFile,
67                   const char* caCertFile) :
68         phosphor::ldap::ConfigMgr(bus, path, filePath, dbusPersistentFile,
69                                   caCertFile)
70     {
71     }
72     MOCK_METHOD1(restartService, void(const std::string& service));
73     MOCK_METHOD1(stopService, void(const std::string& service));
74     std::unique_ptr<Config>& getOpenLdapConfigPtr()
75     {
76         return openLDAPConfigPtr;
77     }
78 
79     std::string configBindPassword()
80     {
81         return getADConfigPtr()->lDAPBindPassword;
82     }
83 
84     std::unique_ptr<Config>& getADConfigPtr()
85     {
86         return ADConfigPtr;
87     }
88     void restore()
89     {
90         // TODO enable it in later commit.
91         // phosphor::ldap::ConfigMgr::restore();
92         return;
93     }
94 
95     void createDefaultObjects()
96     {
97         phosphor::ldap::ConfigMgr::createDefaultObjects();
98     }
99 
100     friend class TestLDAPConfig;
101 };
102 
103 TEST_F(TestLDAPConfig, testCreate)
104 {
105     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
106     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
107     auto dbusPersistentFilePath =
108         std::string(dir.c_str()) + "/" + dbusPersistFile;
109 
110     if (fs::exists(configFilePath))
111     {
112         fs::remove(configFilePath);
113     }
114     EXPECT_FALSE(fs::exists(configFilePath));
115     MockConfigMgr manager(bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
116                           dbusPersistentFilePath.c_str(),
117                           tlsCacertfile.c_str());
118 
119     EXPECT_CALL(manager, stopService("nslcd.service")).Times(2);
120     EXPECT_CALL(manager, restartService("nslcd.service")).Times(2);
121     EXPECT_CALL(manager, restartService("nscd.service")).Times(2);
122     manager.createConfig(
123         "ldap://9.194.251.136/", "cn=Users,dc=com", "cn=Users,dc=corp",
124         "MyLdap12", ldap_base::Create::SearchScope::sub,
125         ldap_base::Create::Type::ActiveDirectory, "uid", "gid");
126     manager.getADConfigPtr()->enabled(true);
127 
128     manager.createConfig("ldap://9.194.251.137/", "cn=Users",
129                          "cn=Users,dc=test", "MyLdap123",
130                          ldap_base::Create::SearchScope::sub,
131                          ldap_base::Create::Type::OpenLdap, "uid", "gid");
132     manager.getOpenLdapConfigPtr()->enabled(false);
133 
134     // Below setting of username/groupname attr is to make sure
135     // that in-active config should not call the start/stop service.
136     manager.getOpenLdapConfigPtr()->userNameAttribute("abc");
137     EXPECT_EQ(manager.getOpenLdapConfigPtr()->userNameAttribute(), "abc");
138 
139     manager.getOpenLdapConfigPtr()->groupNameAttribute("def");
140     EXPECT_EQ(manager.getOpenLdapConfigPtr()->groupNameAttribute(), "def");
141 
142     EXPECT_TRUE(fs::exists(configFilePath));
143     EXPECT_EQ(manager.getADConfigPtr()->lDAPServerURI(),
144               "ldap://9.194.251.136/");
145     EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDN(), "cn=Users,dc=com");
146     EXPECT_EQ(manager.getADConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp");
147     EXPECT_EQ(manager.getADConfigPtr()->lDAPSearchScope(),
148               ldap_base::Config::SearchScope::sub);
149     EXPECT_EQ(manager.getADConfigPtr()->lDAPType(),
150               ldap_base::Config::Type::ActiveDirectory);
151 
152     EXPECT_EQ(manager.getADConfigPtr()->userNameAttribute(), "uid");
153     EXPECT_EQ(manager.getADConfigPtr()->groupNameAttribute(), "gid");
154     EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDNPassword(), "");
155     EXPECT_EQ(manager.configBindPassword(), "MyLdap12");
156     // change the password
157     manager.getADConfigPtr()->lDAPBindDNPassword("MyLdap14");
158     EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDNPassword(), "");
159     EXPECT_EQ(manager.configBindPassword(), "MyLdap14");
160 }
161 
162 TEST_F(TestLDAPConfig, testDefaultObject)
163 {
164     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
165     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
166     auto dbusPersistentFilePath =
167         std::string(dir.c_str()) + "/" + dbusPersistFile;
168 
169     if (fs::exists(configFilePath))
170     {
171         fs::remove(configFilePath);
172     }
173     EXPECT_FALSE(fs::exists(configFilePath));
174 
175     MockConfigMgr manager(bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
176                           dbusPersistentFilePath.c_str(),
177                           tlsCacertfile.c_str());
178 
179     EXPECT_CALL(manager, stopService("nslcd.service")).Times(2);
180 
181     manager.createDefaultObjects();
182 
183     EXPECT_NE(nullptr, manager.getADConfigPtr());
184     EXPECT_NE(nullptr, manager.getOpenLdapConfigPtr());
185     EXPECT_EQ(manager.getADConfigPtr()->lDAPType(),
186               ldap_base::Config::Type::ActiveDirectory);
187     EXPECT_EQ(manager.getOpenLdapConfigPtr()->lDAPType(),
188               ldap_base::Config::Type::OpenLdap);
189 }
190 /*
191 TEST_F(TestLDAPConfig, testRestores)
192 {
193     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
194     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
195     auto dbusPersistentFilePath =
196         std::string(dir.c_str()) + "/" + dbusPersistFile;
197 
198     if (fs::exists(configFilePath))
199     {
200         fs::remove(configFilePath);
201     }
202     EXPECT_FALSE(fs::exists(configFilePath));
203     MockConfigMgr* managerPtr = new MockConfigMgr(
204         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
205         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
206     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2);
207     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
208     managerPtr->createConfig(
209         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
210         "MyLdap12", ldap_base::Create::SearchScope::sub,
211         ldap_base::Create::Type::ActiveDirectory, "uid", "gid");
212     managerPtr->getConfigPtr()->enabled(false);
213 
214     EXPECT_TRUE(fs::exists(configFilePath));
215     EXPECT_FALSE(managerPtr->getConfigPtr()->enabled());
216     managerPtr->getConfigPtr()->enabled(true);
217     // Delete LDAP configuration
218     managerPtr->deleteObject();
219     EXPECT_TRUE(fs::exists(configFilePath));
220     // Restore from configFilePath
221     managerPtr->restore(configFilePath.c_str());
222     // validate restored properties
223     EXPECT_TRUE(managerPtr->getConfigPtr()->enabled());
224     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
225               "ldap://9.194.251.138/");
226     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(), "cn=Users,dc=com");
227     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp");
228     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
229               ldap_base::Config::SearchScope::sub);
230     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
231               ldap_base::Config::Type::ActiveDirectory);
232     EXPECT_EQ(managerPtr->getConfigPtr()->userNameAttribute(), "uid");
233     EXPECT_EQ(managerPtr->getConfigPtr()->groupNameAttribute(), "gid");
234     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDNPassword(), "");
235     EXPECT_EQ(managerPtr->configBindPassword(), "MyLdap12");
236     delete managerPtr;
237 }
238 
239 TEST_F(TestLDAPConfig, testLDAPServerURI)
240 {
241     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
242     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
243     auto dbusPersistentFilePath =
244         std::string(dir.c_str()) + "/" + dbusPersistFile;
245 
246     if (fs::exists(configFilePath))
247     {
248         fs::remove(configFilePath);
249     }
250     EXPECT_FALSE(fs::exists(configFilePath));
251     MockConfigMgr* managerPtr = new MockConfigMgr(
252         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
253         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
254     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
255     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
256 
257     managerPtr->createConfig(
258         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
259         "MyLdap12", ldap_base::Create::SearchScope::sub,
260         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
261     managerPtr->getConfigPtr()->enabled(true);
262 
263     // Change LDAP Server URI
264     managerPtr->getConfigPtr()->lDAPServerURI("ldap://9.194.251.139/");
265     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
266               "ldap://9.194.251.139/");
267     // Change LDAP Server URI
268     EXPECT_THROW(
269         managerPtr->getConfigPtr()->lDAPServerURI("ldaps://9.194.251.139/"),
270         NoCACertificate);
271     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
272               "ldap://9.194.251.139/");
273     // Delete LDAP configuration
274     managerPtr->deleteObject();
275 
276     managerPtr->restore(configFilePath.c_str());
277     // Check LDAP Server URI
278     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPServerURI(),
279               "ldap://9.194.251.139/");
280     delete managerPtr;
281 }
282 
283 TEST_F(TestLDAPConfig, testLDAPBindDN)
284 {
285     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
286     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
287     auto dbusPersistentFilePath =
288         std::string(dir.c_str()) + "/" + dbusPersistFile;
289 
290     if (fs::exists(configFilePath))
291     {
292         fs::remove(configFilePath);
293     }
294     EXPECT_FALSE(fs::exists(configFilePath));
295     MockConfigMgr* managerPtr = new MockConfigMgr(
296         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
297         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
298     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
299     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
300 
301     managerPtr->createConfig(
302         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
303         "MyLdap12", ldap_base::Create::SearchScope::sub,
304         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
305     managerPtr->getConfigPtr()->enabled(true);
306 
307     // Change LDAP BindDN
308     managerPtr->getConfigPtr()->lDAPBindDN(
309         "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
310     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(),
311               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
312     // Change LDAP BindDN
313     EXPECT_THROW(
314         {
315             try
316             {
317                 managerPtr->getConfigPtr()->lDAPBindDN("");
318             }
319             catch (const InvalidArgument& e)
320             {
321                 throw;
322             }
323         },
324         InvalidArgument);
325     // Delete LDAP configuration
326     managerPtr->deleteObject();
327 
328     managerPtr->restore(configFilePath.c_str());
329     // Check LDAP BindDN after restoring
330     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBindDN(),
331               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
332     delete managerPtr;
333 }
334 
335 TEST_F(TestLDAPConfig, testLDAPBaseDN)
336 {
337     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
338     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
339     auto dbusPersistentFilePath =
340         std::string(dir.c_str()) + "/" + dbusPersistFile;
341 
342     if (fs::exists(configFilePath))
343     {
344         fs::remove(configFilePath);
345     }
346     EXPECT_FALSE(fs::exists(configFilePath));
347     MockConfigMgr* managerPtr = new MockConfigMgr(
348         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
349         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
350     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
351     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
352     managerPtr->createConfig(
353         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
354         "MyLdap12", ldap_base::Create::SearchScope::sub,
355         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
356     managerPtr->getConfigPtr()->enabled(true);
357     // Change LDAP BaseDN
358     managerPtr->getConfigPtr()->lDAPBaseDN(
359         "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
360     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(),
361               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
362     // Change LDAP BaseDN
363     EXPECT_THROW(
364         {
365             try
366             {
367                 managerPtr->getConfigPtr()->lDAPBaseDN("");
368             }
369             catch (const InvalidArgument& e)
370             {
371                 throw;
372             }
373         },
374         InvalidArgument);
375     // Delete LDAP configuration
376     managerPtr->deleteObject();
377 
378     managerPtr->restore(configFilePath.c_str());
379     // Check LDAP BaseDN after restoring
380     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPBaseDN(),
381               "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com");
382     delete managerPtr;
383 }
384 
385 TEST_F(TestLDAPConfig, testSearchScope)
386 {
387     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
388     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
389     auto dbusPersistentFilePath =
390         std::string(dir.c_str()) + "/" + dbusPersistFile;
391 
392     if (fs::exists(configFilePath))
393     {
394         fs::remove(configFilePath);
395     }
396     EXPECT_FALSE(fs::exists(configFilePath));
397     MockConfigMgr* managerPtr = new MockConfigMgr(
398         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
399         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
400     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
401     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
402     managerPtr->createConfig(
403         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
404         "MyLdap12", ldap_base::Create::SearchScope::sub,
405         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
406     managerPtr->getConfigPtr()->enabled(true);
407 
408     // Change LDAP SearchScope
409     managerPtr->getConfigPtr()->lDAPSearchScope(
410         ldap_base::Config::SearchScope::one);
411     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
412               ldap_base::Config::SearchScope::one);
413     // Delete LDAP configuration
414     managerPtr->deleteObject();
415 
416     managerPtr->restore(configFilePath.c_str());
417     // Check LDAP SearchScope after restoring
418     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPSearchScope(),
419               ldap_base::Config::SearchScope::one);
420     delete managerPtr;
421 }
422 
423 TEST_F(TestLDAPConfig, testLDAPType)
424 {
425     auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile;
426     auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile;
427     auto dbusPersistentFilePath =
428         std::string(dir.c_str()) + "/" + dbusPersistFile;
429 
430     if (fs::exists(configFilePath))
431     {
432         fs::remove(configFilePath);
433     }
434     EXPECT_FALSE(fs::exists(configFilePath));
435     MockConfigMgr* managerPtr = new MockConfigMgr(
436         bus, LDAP_CONFIG_ROOT, configFilePath.c_str(),
437         dbusPersistentFilePath.c_str(), tlsCacertfile.c_str());
438     EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(3);
439     EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(2);
440     managerPtr->createConfig(
441         "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp",
442         "MyLdap12", ldap_base::Create::SearchScope::sub,
443         ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2");
444     managerPtr->getConfigPtr()->enabled(true);
445 
446     // Change LDAP type
447     managerPtr->getConfigPtr()->lDAPType(ldap_base::Config::Type::OpenLdap);
448     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
449               ldap_base::Config::Type::OpenLdap);
450     // Delete LDAP configuration
451     managerPtr->deleteObject();
452 
453     managerPtr->restore(configFilePath.c_str());
454     // Check LDAP type after restoring
455     EXPECT_EQ(managerPtr->getConfigPtr()->lDAPType(),
456               ldap_base::Config::Type::OpenLdap);
457     delete managerPtr;
458 }
459 */
460 } // namespace ldap
461 } // namespace phosphor
462