1 /*
2    test_myldap.c - simple test for the myldap module
3    This file is part of the nss-pam-ldapd library.
4 
5    Copyright (C) 2007-2014 Arthur de Jong
6 
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11 
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16 
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301 USA
21 */
22 
23 #include "config.h"
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <pthread.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <signal.h>
31 
32 #include "common.h"
33 
34 #include "nslcd/log.h"
35 #include "nslcd/cfg.h"
36 #include "nslcd/myldap.h"
37 
38 struct worker_args {
39   int id;
40 };
41 
42 /* the maxium number of results to print (all results are retrieved) */
43 #define MAXRESULTS 10
44 
45 /* This is a very basic search test, it performs a test to get certain
46    entries from the database. It currently just prints out the DNs for
47    the entries. */
test_search(void)48 static void test_search(void)
49 {
50   MYLDAP_SESSION *session;
51   MYLDAP_SEARCH *search;
52   MYLDAP_ENTRY *entry;
53   const char *attrs[] = { "uid", "cn", "gid", NULL };
54   int i;
55   int rc;
56   /* initialize session */
57   printf("test_myldap: test_search(): getting session...\n");
58   session = myldap_create_session();
59   assert(session != NULL);
60   /* perform search */
61   printf("test_myldap: test_search(): doing search...\n");
62   search = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
63                          "(objectclass=posixAccount)", attrs, NULL);
64   assert(search != NULL);
65   /* go over results */
66   printf("test_myldap: test_search(): get results...\n");
67   for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++)
68   {
69     if (i < MAXRESULTS)
70       printf("test_myldap: test_search(): [%d] DN %s\n",
71              i, myldap_get_dn(entry));
72     else if (i == MAXRESULTS)
73       printf("test_myldap: test_search(): ...\n");
74   }
75   printf("test_myldap: test_search(): %d entries returned: %s\n",
76          i, ldap_err2string(rc));
77   assert(rc == LDAP_SUCCESS);
78   /* perform another search */
79   printf("test_myldap: test_search(): doing search...\n");
80   search = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
81                          "(objectclass=posixGroup)", attrs, NULL);
82   assert(search != NULL);
83   /* go over results */
84   printf("test_myldap: test_search(): get results...\n");
85   for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++)
86   {
87     if (i < MAXRESULTS)
88       printf("test_myldap: test_search(): [%d] DN %s\n",
89              i, myldap_get_dn(entry));
90     else if (i == MAXRESULTS)
91       printf("test_myldap: test_search(): ...\n");
92   }
93   printf("test_myldap: test_search(): %d entries returned: %s\n",
94          i, ldap_err2string(rc));
95   assert(rc == LDAP_SUCCESS);
96   /* clean up */
97   myldap_session_close(session);
98 }
99 
test_get(void)100 static void test_get(void)
101 {
102   MYLDAP_SESSION *session;
103   MYLDAP_SEARCH *search1, *search2;
104   MYLDAP_ENTRY *entry;
105   const char *attrs1[] = { "cn", "userPassword", "memberUid", "gidNumber", "member", NULL };
106   const char *attrs2[] = { "uid", NULL };
107   int rc;
108   /* initialize session */
109   printf("test_myldap: test_get(): getting session...\n");
110   session = myldap_create_session();
111   assert(session != NULL);
112   /* perform search */
113   printf("test_myldap: test_get(): doing search...\n");
114   search1 = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
115                           "(&(|(objectClass=posixGroup)(objectClass=groupOfNames))(cn=testgroup2))",
116                           attrs1, NULL);
117   assert(search1 != NULL);
118   /* get one entry */
119   entry = myldap_get_entry(search1, &rc);
120   assert(entry != NULL);
121   printf("test_myldap: test_get(): got DN %s\n", myldap_get_dn(entry));
122   /* get some attribute values */
123   assert(myldap_get_values(entry, "gidNumber") != NULL);
124   assert(myldap_get_values(entry, "memberUid") == NULL);
125   assert(myldap_get_values(entry, "member") != NULL);
126   /* perform another search */
127   printf("test_myldap: test_get(): doing get...\n");
128   search2 = myldap_search(session, "cn=Test User2,ou=people,dc=test,dc=tld",
129                           LDAP_SCOPE_BASE,
130                           "(objectclass=posixAccount)", attrs2, NULL);
131   assert(search2 != NULL);
132   /* get one entry */
133   entry = myldap_get_entry(search2, &rc);
134   assert(entry != NULL);
135   printf("test_myldap: test_get(): got DN %s\n", myldap_get_dn(entry));
136   /* test if searches are ok */
137   assert(myldap_get_entry(search1, &rc) == NULL);
138   assert(myldap_get_entry(search2, &rc) == NULL);
139   /* clean up */
140   myldap_session_close(session);
141 }
142 
143 /* This search prints a number of attributes from a search */
test_get_values(void)144 static void test_get_values(void)
145 {
146   MYLDAP_SESSION *session;
147   MYLDAP_SEARCH *search;
148   MYLDAP_ENTRY *entry;
149   const char *attrs[] = { "uidNumber", "cn", "gidNumber", "uid", "objectClass", NULL };
150   const char **vals;
151   const char *rdnval;
152   int i;
153   /* initialize session */
154   printf("test_myldap: test_get_values(): getting session...\n");
155   session = myldap_create_session();
156   assert(session != NULL);
157   /* perform search */
158   search = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
159                          "(&(objectClass=posixAccount)(uid=*))", attrs, NULL);
160   assert(search != NULL);
161   /* go over results */
162   for (i = 0; (entry = myldap_get_entry(search, NULL)) != NULL; i++)
163   {
164     if (i < MAXRESULTS)
165       printf("test_myldap: test_get_values(): [%d] DN %s\n",
166              i, myldap_get_dn(entry));
167     else if (i == MAXRESULTS)
168       printf("test_myldap: test_get_values(): ...\n");
169     /* try to get uid from attribute */
170     vals = myldap_get_values(entry, "uidNumber");
171     assert((vals != NULL) && (vals[0] != NULL));
172     if (i < MAXRESULTS)
173       printf("test_myldap: test_get_values(): [%d] uidNumber=%s\n",
174              i, vals[0]);
175     /* try to get gid from attribute */
176     vals = myldap_get_values(entry, "gidNumber");
177     assert((vals != NULL) && (vals[0] != NULL));
178     if (i < MAXRESULTS)
179       printf("test_myldap: test_get_values(): [%d] gidNumber=%s\n",
180              i, vals[0]);
181     /* write LDF_STRING(PASSWD_NAME) */
182     vals = myldap_get_values(entry, "uid");
183     assert((vals != NULL) && (vals[0] != NULL));
184     if (i < MAXRESULTS)
185       printf("test_myldap: test_get_values(): [%d] uid=%s\n", i, vals[0]);
186     /* get rdn values */
187     rdnval = myldap_get_rdn_value(entry, "cn");
188     if (i < MAXRESULTS)
189       printf("test_myldap: test_get_values(): [%d] cdrdn=%s\n",
190              i, rdnval == NULL ? "NULL" : rdnval);
191     rdnval = myldap_get_rdn_value(entry, "uid");
192     if (i < MAXRESULTS)
193       printf("test_myldap: test_get_values(): [%d] uidrdn=%s\n",
194              i, rdnval == NULL ? "NULL" : rdnval);
195     /* check objectclass */
196     assert(myldap_has_objectclass(entry, "posixAccount"));
197   }
198   /* clean up */
199   myldap_session_close(session);
200 }
201 
test_get_rdnvalues(void)202 static void test_get_rdnvalues(void)
203 {
204   MYLDAP_SESSION *session;
205   MYLDAP_SEARCH *search;
206   MYLDAP_ENTRY *entry;
207   const char *attrs[] = { "cn", "uid", NULL };
208   int rc;
209   char buf[80];
210   const char *rdnval;
211   /* initialize session */
212   printf("test_myldap: test_get_rdnvalues(): getting session...\n");
213   session = myldap_create_session();
214   assert(session != NULL);
215   /* perform search */
216   printf("test_myldap: test_get_rdnvalues(): doing search...\n");
217   search = myldap_search(session, "cn=Aka Ashbach+uid=aashbach,ou=lotsofpeople,dc=test,dc=tld",
218                     LDAP_SCOPE_BASE, "(objectClass=*)", attrs, NULL);
219   assert(search != NULL);
220   /* get one entry */
221   entry = myldap_get_entry(search, &rc);
222   assert(entry != NULL);
223   printf("test_myldap: test_get_rdnvalues(): got DN %s\n",
224          myldap_get_dn(entry));
225   /* get some values from DN */
226   rdnval = myldap_get_rdn_value(entry, "uid");
227   printf("test_myldap: test_get_rdnvalues(): DN.uid=%s\n",
228            rdnval == NULL ? "NULL" : rdnval);
229   rdnval = myldap_get_rdn_value(entry, "cn");
230   printf("test_myldap: test_get_rdnvalues(): DN.cn=%s\n",
231            rdnval == NULL ? "NULL" : rdnval);
232   rdnval = myldap_get_rdn_value(entry, "uidNumber");
233   printf("test_myldap: test_get_rdnvalues(): DN.uidNumber=%s\n",
234            rdnval == NULL ? "NULL" : rdnval);
235   /* clean up */
236   myldap_session_close(session);
237   /* some tests */
238   rdnval = myldap_cpy_rdn_value("cn=Aka Ashbach+uid=aashbach,ou=lotsofpeople,dc=test,dc=tld",
239                                 "uid", buf, sizeof(buf));
240   printf("test_myldap: test_get_rdnvalues(): DN.uid=%s\n",
241            rdnval == NULL ? "NULL" : rdnval);
242   rdnval = myldap_cpy_rdn_value("cn=Aka Ashbach+uid=aashbach,ou=lotsofpeople,dc=test,dc=tld",
243                                 "cn", buf, sizeof(buf));
244   printf("test_myldap: test_get_rdnvalues(): DN.cn=%s\n",
245            rdnval == NULL ? "NULL" : rdnval);
246   rdnval = myldap_cpy_rdn_value("cn=Aka Ashbach+uid=aashbach,ou=lotsofpeople,dc=test,dc=tld",
247                                 "uidNumber", buf, sizeof(buf));
248   printf("test_myldap: test_get_rdnvalues(): DN.uidNumber=%s\n",
249            rdnval == NULL ? "NULL" : rdnval);
250 }
251 
252 /* this method tests to see if we can perform two searches within
253    one session */
test_two_searches(void)254 static void test_two_searches(void)
255 {
256   MYLDAP_SESSION *session;
257   MYLDAP_SEARCH *search1, *search2;
258   MYLDAP_ENTRY *entry;
259   const char *attrs[] = { "uidNumber", "cn", "gidNumber", "uid", "objectClass", NULL };
260   const char **vals;
261   /* initialize session */
262   printf("test_myldap: test_two_searches(): getting session...\n");
263   session = myldap_create_session();
264   assert(session != NULL);
265   /* perform search1 */
266   search1 = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
267                           "(&(objectClass=posixAccount)(uid=*))",
268                           attrs, NULL);
269   assert(search1 != NULL);
270   /* get a result from search1 */
271   entry = myldap_get_entry(search1, NULL);
272   assert(entry != NULL);
273   printf("test_myldap: test_two_searches(): [search1] DN %s\n",
274          myldap_get_dn(entry));
275   vals = myldap_get_values(entry, "cn");
276   assert((vals != NULL) && (vals[0] != NULL));
277   printf("test_myldap: test_two_searches(): [search1] cn=%s\n", vals[0]);
278   /* start a second search */
279   search2 = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
280                           "(&(objectclass=posixGroup)(gidNumber=*))",
281                           attrs, NULL);
282   assert(search2 != NULL);
283   /* get a result from search2 */
284   entry = myldap_get_entry(search2, NULL);
285   assert(entry != NULL);
286   printf("test_myldap: test_two_searches(): [search2] DN %s\n",
287          myldap_get_dn(entry));
288   vals = myldap_get_values(entry, "cn");
289   assert((vals != NULL) && (vals[0] != NULL));
290   printf("test_myldap: test_two_searches(): [search2] cn=%s\n", vals[0]);
291   /* get another result from search1 */
292   entry = myldap_get_entry(search1, NULL);
293   assert(entry != NULL);
294   printf("test_myldap: test_two_searches(): [search1] DN %s\n",
295          myldap_get_dn(entry));
296   vals = myldap_get_values(entry, "cn");
297   assert((vals != NULL) && (vals[0] != NULL));
298   printf("test_myldap: test_two_searches(): [search1] cn=%s\n", vals[0]);
299   /* stop search1 */
300   myldap_search_close(search1);
301   /* get another result from search2 */
302   entry = myldap_get_entry(search2, NULL);
303   assert(entry != NULL);
304   printf("test_myldap: test_two_searches(): [search2] DN %s\n",
305          myldap_get_dn(entry));
306   vals = myldap_get_values(entry, "cn");
307   assert((vals != NULL) && (vals[0] != NULL));
308   printf("test_myldap: test_two_searches(): [search2] cn=%s\n", vals[0]);
309   /* clean up */
310   myldap_session_close(session);
311 }
312 
313 /* perform a simple search */
worker(void * arg)314 static void *worker(void *arg)
315 {
316   MYLDAP_SESSION *session;
317   MYLDAP_SEARCH *search;
318   MYLDAP_ENTRY *entry;
319   const char *attrs[] = { "uid", "cn", "gid", NULL };
320   struct worker_args *args = (struct worker_args *)arg;
321   int i;
322   int rc;
323   /* initialize session */
324   session = myldap_create_session();
325   assert(session != NULL);
326   /* perform search */
327   search = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
328                          "(objectclass=posixAccount)", attrs, NULL);
329   assert(search != NULL);
330   /* go over results */
331   for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++)
332   {
333     if (i < MAXRESULTS)
334       printf("test_myldap: test_threads(): [worker %d] [%d] DN %s\n",
335              args->id, i, myldap_get_dn(entry));
336     else if (i == MAXRESULTS)
337       printf("test_myldap: test_threads(): [worker %d] ...\n", args->id);
338   }
339   printf("test_myldap: test_threads(): [worker %d] DONE: %s\n",
340          args->id, ldap_err2string(rc));
341   assert(rc == LDAP_SUCCESS);
342   /* clean up */
343   myldap_session_close(session);
344   return 0;
345 }
346 
347 /* thread ids of all running threads */
348 #define NUM_THREADS 5
349 pthread_t my_threads[NUM_THREADS];
350 
test_threads(void)351 static void test_threads(void)
352 {
353   int i;
354   struct worker_args args[NUM_THREADS];
355   /* start worker threads */
356   for (i = 0; i < NUM_THREADS; i++)
357   {
358     args[i].id = i;
359     assert(pthread_create(&my_threads[i], NULL, worker, &(args[i])) == 0);
360   }
361   /* wait for all threads to die */
362   for (i = 0; i < NUM_THREADS; i++)
363   {
364     assert(pthread_join(my_threads[i], NULL) == 0);
365   }
366 }
367 
test_connections(void)368 static void test_connections(void)
369 {
370   MYLDAP_SESSION *session;
371   MYLDAP_SEARCH *search;
372   const char *attrs[] = { "uid", "cn", "gid", NULL };
373   char *old_uris[NSS_LDAP_CONFIG_MAX_URIS + 1];
374   int i;
375   /* save the old URIs */
376   for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
377   {
378     old_uris[i] = nslcd_cfg->uris[i].uri;
379     nslcd_cfg->uris[i].uri = NULL;
380   }
381   /* set new URIs */
382   i = 0;
383   nslcd_cfg->uris[i++].uri = "ldapi://%2fdev%2fnull/";
384   nslcd_cfg->uris[i++].uri = "ldap://10.10.10.10/";
385   nslcd_cfg->uris[i++].uri = "ldapi://%2fdev%2fnonexistent/";
386   nslcd_cfg->uris[i++].uri = "ldap://nosuchhost/";
387   nslcd_cfg->uris[i++].uri = NULL;
388   /* initialize session */
389   printf("test_myldap: test_connections(): getting session...\n");
390   session = myldap_create_session();
391   assert(session != NULL);
392   /* perform search */
393   printf("test_myldap: test_connections(): doing search...\n");
394   search = myldap_search(session, nslcd_cfg->bases[0], LDAP_SCOPE_SUBTREE,
395                          "(objectclass=posixAccount)", attrs, NULL);
396   assert(search == NULL);
397   /* clean up */
398   myldap_session_close(session);
399   /* restore the old URIs */
400   for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++)
401     nslcd_cfg->uris[i].uri = old_uris[i];
402 }
403 
404 /* test whether myldap_escape() handles buffer overlows correctly */
test_escape(void)405 static void test_escape(void)
406 {
407   char buffer[1024];
408   assert(myldap_escape("test", buffer, 4) != 0);
409   assert(myldap_escape("t*st", buffer, 5) != 0);
410   assert(myldap_escape("t*st", buffer, 20) == 0);
411   assertstreq(buffer, "t\\2ast");
412 }
413 
414 /* the main program... */
main(int UNUSED (argc),char UNUSED (* argv[]))415 int main(int UNUSED(argc), char UNUSED(*argv[]))
416 {
417   char *srcdir;
418   char fname[100];
419   struct sigaction act;
420   /* build the name of the file */
421   srcdir = getenv("srcdir");
422   if (srcdir == NULL)
423     srcdir = ".";
424   snprintf(fname, sizeof(fname), "%s/nslcd-test.conf", srcdir);
425   fname[sizeof(fname) - 1] = '\0';
426   /* initialize configuration */
427   cfg_init(fname);
428   /* partially initialize logging */
429   log_setdefaultloglevel(LOG_DEBUG);
430   /* ignore SIGPIPE */
431   memset(&act, 0, sizeof(struct sigaction));
432   act.sa_handler = SIG_IGN;
433   sigemptyset(&act.sa_mask);
434   act.sa_flags = SA_RESTART | SA_NOCLDSTOP;
435   assert(sigaction(SIGPIPE, &act, NULL) == 0);
436   /* do tests */
437   test_search();
438   test_get();
439   test_get_values();
440   test_get_rdnvalues();
441   test_two_searches();
442   test_threads();
443   test_connections();
444   test_escape();
445   return 0;
446 }
447