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