d2b17f0f6352d9f8f69788acda669906a5aeb754
[vlendec/samba-autobuild/.git] / source3 / torture / nsstest.c
1 /* 
2    Unix SMB/CIFS implementation.
3    nss tester for winbindd
4    Copyright (C) Andrew Tridgell 2001
5    Copyright (C) Tim Potter 2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program 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
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 static const char *so_path = "/lib/libnss_winbind.so";
25 static const char *nss_name = "winbind";
26 static int nss_errno;
27 static NSS_STATUS last_error;
28 static int total_errors;
29
30 static void *find_fn(const char *name)
31 {
32         pstring s;
33         static void *h;
34         void *res;
35
36         pstr_sprintf(s, "_nss_%s_%s", nss_name, name);
37
38         if (!h) {
39                 h = sys_dlopen(so_path, RTLD_LAZY);
40         }
41         if (!h) {
42                 printf("Can't open shared library %s\n", so_path);
43                 exit(1);
44         }
45         res = sys_dlsym(h, s);
46         if (!res) {
47                 printf("Can't find function %s\n", s);
48                 total_errors++;
49                 return NULL;
50         }
51         return res;
52 }
53
54 static void report_nss_error(const char *who, NSS_STATUS status)
55 {
56         last_error = status;
57         total_errors++;
58         printf("ERROR %s: NSS_STATUS=%d  %d (nss_errno=%d)\n", 
59                who, status, NSS_STATUS_SUCCESS, nss_errno);
60 }
61
62 static struct passwd *nss_getpwent(void)
63 {
64         NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, 
65                                       size_t , int *) = find_fn("getpwent_r");
66         static struct passwd pwd;
67         static char buf[1000];
68         NSS_STATUS status;
69
70         if (!_nss_getpwent_r)
71                 return NULL;
72
73         status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno);
74         if (status == NSS_STATUS_NOTFOUND) {
75                 return NULL;
76         }
77         if (status != NSS_STATUS_SUCCESS) {
78                 report_nss_error("getpwent", status);
79                 return NULL;
80         }
81         return &pwd;
82 }
83
84 static struct passwd *nss_getpwnam(const char *name)
85 {
86         NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, 
87                                       size_t , int *) = find_fn("getpwnam_r");
88         static struct passwd pwd;
89         static char buf[1000];
90         NSS_STATUS status;
91
92         if (!_nss_getpwnam_r)
93                 return NULL;
94         
95         status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno);
96         if (status == NSS_STATUS_NOTFOUND) {
97                 return NULL;
98         }
99         if (status != NSS_STATUS_SUCCESS) {
100                 report_nss_error("getpwnam", status);
101                 return NULL;
102         }
103         return &pwd;
104 }
105
106 static struct passwd *nss_getpwuid(uid_t uid)
107 {
108         NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, 
109                                       size_t , int *) = find_fn("getpwuid_r");
110         static struct passwd pwd;
111         static char buf[1000];
112         NSS_STATUS status;
113
114         if (!_nss_getpwuid_r)
115                 return NULL;
116         
117         status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno);
118         if (status == NSS_STATUS_NOTFOUND) {
119                 return NULL;
120         }
121         if (status != NSS_STATUS_SUCCESS) {
122                 report_nss_error("getpwuid", status);
123                 return NULL;
124         }
125         return &pwd;
126 }
127
128 static void nss_setpwent(void)
129 {
130         NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent");
131         NSS_STATUS status;
132         
133         if (!_nss_setpwent)
134                 return;
135
136         status = _nss_setpwent();
137         if (status != NSS_STATUS_SUCCESS) {
138                 report_nss_error("setpwent", status);
139         }
140 }
141
142 static void nss_endpwent(void)
143 {
144         NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent");
145         NSS_STATUS status;
146
147         if (!_nss_endpwent)
148                 return;
149
150         status = _nss_endpwent();
151         if (status != NSS_STATUS_SUCCESS) {
152                 report_nss_error("endpwent", status);
153         }
154 }
155
156
157 static struct group *nss_getgrent(void)
158 {
159         NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, 
160                                       size_t , int *) = find_fn("getgrent_r");
161         static struct group grp;
162         static char *buf;
163         static int buflen = 1024;
164         NSS_STATUS status;
165
166         if (!_nss_getgrent_r)
167                 return NULL;
168
169         if (!buf) 
170                 buf = SMB_MALLOC(buflen);
171
172 again:  
173         status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno);
174         if (status == NSS_STATUS_TRYAGAIN) {
175                 buflen *= 2;
176                 buf = SMB_REALLOC(buf, buflen);
177                 if (!buf) {
178                         return NULL;
179                 }
180                 goto again;
181         }
182         if (status == NSS_STATUS_NOTFOUND) {
183                 return NULL;
184         }
185         if (status != NSS_STATUS_SUCCESS) {
186                 report_nss_error("getgrent", status);
187                 return NULL;
188         }
189         return &grp;
190 }
191
192 static struct group *nss_getgrnam(const char *name)
193 {
194         NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, 
195                                       size_t , int *) = find_fn("getgrnam_r");
196         static struct group grp;
197         static char *buf;
198         static int buflen = 1000;
199         NSS_STATUS status;
200
201         if (!_nss_getgrnam_r)
202                 return NULL;
203
204         if (!buf) 
205                 buf = SMB_MALLOC(buflen);
206 again:  
207         status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
208         if (status == NSS_STATUS_TRYAGAIN) {
209                 buflen *= 2;
210                 buf = SMB_REALLOC(buf, buflen);
211                 if (!buf) {
212                         return NULL;
213                 }
214                 goto again;
215         }
216         if (status == NSS_STATUS_NOTFOUND) {
217                 return NULL;
218         }
219         if (status != NSS_STATUS_SUCCESS) {
220                 report_nss_error("getgrnam", status);
221                 return NULL;
222         }
223         return &grp;
224 }
225
226 static struct group *nss_getgrgid(gid_t gid)
227 {
228         NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, 
229                                       size_t , int *) = find_fn("getgrgid_r");
230         static struct group grp;
231         static char *buf;
232         static int buflen = 1000;
233         NSS_STATUS status;
234         
235         if (!_nss_getgrgid_r)
236                 return NULL;
237
238         if (!buf) 
239                 buf = SMB_MALLOC(buflen);
240
241 again:  
242         status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
243         if (status == NSS_STATUS_TRYAGAIN) {
244                 buflen *= 2;
245                 buf = SMB_REALLOC(buf, buflen);
246                 if (!buf) {
247                         return NULL;
248                 }
249                 goto again;
250         }
251         if (status == NSS_STATUS_NOTFOUND) {
252                 return NULL;
253         }
254         if (status != NSS_STATUS_SUCCESS) {
255                 report_nss_error("getgrgid", status);
256                 return NULL;
257         }
258         return &grp;
259 }
260
261 static void nss_setgrent(void)
262 {
263         NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
264         NSS_STATUS status;
265
266         if (!_nss_setgrent)
267                 return;
268
269         status = _nss_setgrent();
270         if (status != NSS_STATUS_SUCCESS) {
271                 report_nss_error("setgrent", status);
272         }
273 }
274
275 static void nss_endgrent(void)
276 {
277         NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
278         NSS_STATUS status;
279
280         if (!_nss_endgrent)
281                 return;
282
283         status = _nss_endgrent();
284         if (status != NSS_STATUS_SUCCESS) {
285                 report_nss_error("endgrent", status);
286         }
287 }
288
289 static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *start, long int *size)
290 {
291         NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *,
292                                       long int *, gid_t **, long int , int *) = 
293                 find_fn("initgroups_dyn");
294         NSS_STATUS status;
295
296         if (!_nss_initgroups) 
297                 return NSS_STATUS_UNAVAIL;
298
299         status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno);
300         if (status != NSS_STATUS_SUCCESS) {
301                 report_nss_error("initgroups", status);
302         }
303         return status;
304 }
305
306 static void print_passwd(struct passwd *pwd)
307 {
308         printf("%s:%s:%lu:%lu:%s:%s:%s\n", 
309                pwd->pw_name,
310                pwd->pw_passwd,
311                (unsigned long)pwd->pw_uid,
312                (unsigned long)pwd->pw_gid,
313                pwd->pw_gecos,
314                pwd->pw_dir,
315                pwd->pw_shell);
316 }
317
318 static void print_group(struct group *grp)
319 {
320         int i;
321         printf("%s:%s:%lu: ", 
322                grp->gr_name,
323                grp->gr_passwd,
324                (unsigned long)grp->gr_gid);
325         
326         if (!grp->gr_mem[0]) {
327                 printf("\n");
328                 return;
329         }
330         
331         for (i=0; grp->gr_mem[i+1]; i++) {
332                 printf("%s, ", grp->gr_mem[i]);
333         }
334         printf("%s\n", grp->gr_mem[i]);
335 }
336
337 static void nss_test_initgroups(char *name, gid_t gid)
338 {
339         long int size = 16;
340         long int start = 1;
341         gid_t *groups = NULL;
342         int i;
343         NSS_STATUS status;
344
345         groups = SMB_MALLOC_ARRAY(gid_t, size);
346         groups[0] = gid;
347
348         status = nss_initgroups(name, gid, &groups, &start, &size);
349         if (status == NSS_STATUS_UNAVAIL) {
350                 printf("No initgroups fn\n");
351                 return;
352         }
353
354         for (i=0; i<start-1; i++) {
355                 printf("%lu, ", (unsigned long)groups[i]);
356         }
357         printf("%lu\n", (unsigned long)groups[i]);
358 }
359
360
361 static void nss_test_users(void)
362 {
363         struct passwd *pwd;
364
365         nss_setpwent();
366         /* loop over all users */
367         while ((pwd = nss_getpwent())) {
368                 printf("Testing user %s\n", pwd->pw_name);
369                 printf("getpwent:   "); print_passwd(pwd);
370                 pwd = nss_getpwuid(pwd->pw_uid);
371                 if (!pwd) {
372                         total_errors++;
373                         printf("ERROR: can't getpwuid\n");
374                         continue;
375                 }
376                 printf("getpwuid:   "); print_passwd(pwd);
377                 pwd = nss_getpwnam(pwd->pw_name);
378                 if (!pwd) {
379                         total_errors++;
380                         printf("ERROR: can't getpwnam\n");
381                         continue;
382                 }
383                 printf("getpwnam:   "); print_passwd(pwd);
384                 printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid);
385                 printf("\n");
386         }
387         nss_endpwent();
388 }
389
390 static void nss_test_groups(void)
391 {
392         struct group *grp;
393
394         nss_setgrent();
395         /* loop over all groups */
396         while ((grp = nss_getgrent())) {
397                 printf("Testing group %s\n", grp->gr_name);
398                 printf("getgrent: "); print_group(grp);
399                 grp = nss_getgrnam(grp->gr_name);
400                 if (!grp) {
401                         total_errors++;
402                         printf("ERROR: can't getgrnam\n");
403                         continue;
404                 }
405                 printf("getgrnam: "); print_group(grp);
406                 grp = nss_getgrgid(grp->gr_gid);
407                 if (!grp) {
408                         total_errors++;
409                         printf("ERROR: can't getgrgid\n");
410                         continue;
411                 }
412                 printf("getgrgid: "); print_group(grp);
413                 printf("\n");
414         }
415         nss_endgrent();
416 }
417
418 static void nss_test_errors(void)
419 {
420         struct passwd *pwd;
421         struct group *grp;
422
423         pwd = getpwnam("nosuchname");
424         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
425                 total_errors++;
426                 printf("ERROR Non existant user gave error %d\n", last_error);
427         }
428
429         pwd = getpwuid(0xFFF0);
430         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
431                 total_errors++;
432                 printf("ERROR Non existant uid gave error %d\n", last_error);
433         }
434
435         grp = getgrnam("nosuchgroup");
436         if (grp || last_error != NSS_STATUS_NOTFOUND) {
437                 total_errors++;
438                 printf("ERROR Non existant group gave error %d\n", last_error);
439         }
440
441         grp = getgrgid(0xFFF0);
442         if (grp || last_error != NSS_STATUS_NOTFOUND) {
443                 total_errors++;
444                 printf("ERROR Non existant gid gave error %d\n", last_error);
445         }
446 }
447
448  int main(int argc, char *argv[])
449 {       
450         if (argc > 1) so_path = argv[1];
451         if (argc > 2) nss_name = argv[2];
452
453         nss_test_users();
454         nss_test_groups();
455         nss_test_errors();
456
457         printf("total_errors=%d\n", total_errors);
458
459         return total_errors;
460 }