import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / 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 = 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 = realloc(buf, buflen);
177                 goto again;
178         }
179         if (status == NSS_STATUS_NOTFOUND) {
180                 return NULL;
181         }
182         if (status != NSS_STATUS_SUCCESS) {
183                 report_nss_error("getgrent", status);
184                 return NULL;
185         }
186         return &grp;
187 }
188
189 static struct group *nss_getgrnam(const char *name)
190 {
191         NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, 
192                                       size_t , int *) = find_fn("getgrnam_r");
193         static struct group grp;
194         static char *buf;
195         static int buflen = 1000;
196         NSS_STATUS status;
197
198         if (!_nss_getgrnam_r)
199                 return NULL;
200
201         if (!buf) 
202                 buf = malloc(buflen);
203 again:  
204         status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
205         if (status == NSS_STATUS_TRYAGAIN) {
206                 buflen *= 2;
207                 buf = realloc(buf, buflen);
208                 goto again;
209         }
210         if (status == NSS_STATUS_NOTFOUND) {
211                 return NULL;
212         }
213         if (status != NSS_STATUS_SUCCESS) {
214                 report_nss_error("getgrnam", status);
215                 return NULL;
216         }
217         return &grp;
218 }
219
220 static struct group *nss_getgrgid(gid_t gid)
221 {
222         NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, 
223                                       size_t , int *) = find_fn("getgrgid_r");
224         static struct group grp;
225         static char *buf;
226         static int buflen = 1000;
227         NSS_STATUS status;
228         
229         if (!_nss_getgrgid_r)
230                 return NULL;
231
232         if (!buf) 
233                 buf = malloc(buflen);
234
235 again:  
236         status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
237         if (status == NSS_STATUS_TRYAGAIN) {
238                 buflen *= 2;
239                 buf = realloc(buf, buflen);
240                 goto again;
241         }
242         if (status == NSS_STATUS_NOTFOUND) {
243                 return NULL;
244         }
245         if (status != NSS_STATUS_SUCCESS) {
246                 report_nss_error("getgrgid", status);
247                 return NULL;
248         }
249         return &grp;
250 }
251
252 static void nss_setgrent(void)
253 {
254         NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
255         NSS_STATUS status;
256
257         if (!_nss_setgrent)
258                 return;
259
260         status = _nss_setgrent();
261         if (status != NSS_STATUS_SUCCESS) {
262                 report_nss_error("setgrent", status);
263         }
264 }
265
266 static void nss_endgrent(void)
267 {
268         NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
269         NSS_STATUS status;
270
271         if (!_nss_endgrent)
272                 return;
273
274         status = _nss_endgrent();
275         if (status != NSS_STATUS_SUCCESS) {
276                 report_nss_error("endgrent", status);
277         }
278 }
279
280 static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *start, long int *size)
281 {
282         NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *,
283                                       long int *, gid_t **, long int , int *) = 
284                 find_fn("initgroups_dyn");
285         NSS_STATUS status;
286
287         if (!_nss_initgroups) 
288                 return NSS_STATUS_UNAVAIL;
289
290         status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno);
291         if (status != NSS_STATUS_SUCCESS) {
292                 report_nss_error("initgroups", status);
293         }
294         return status;
295 }
296
297 static void print_passwd(struct passwd *pwd)
298 {
299         printf("%s:%s:%lu:%lu:%s:%s:%s\n", 
300                pwd->pw_name,
301                pwd->pw_passwd,
302                (unsigned long)pwd->pw_uid,
303                (unsigned long)pwd->pw_gid,
304                pwd->pw_gecos,
305                pwd->pw_dir,
306                pwd->pw_shell);
307 }
308
309 static void print_group(struct group *grp)
310 {
311         int i;
312         printf("%s:%s:%lu: ", 
313                grp->gr_name,
314                grp->gr_passwd,
315                (unsigned long)grp->gr_gid);
316         
317         if (!grp->gr_mem[0]) {
318                 printf("\n");
319                 return;
320         }
321         
322         for (i=0; grp->gr_mem[i+1]; i++) {
323                 printf("%s, ", grp->gr_mem[i]);
324         }
325         printf("%s\n", grp->gr_mem[i]);
326 }
327
328 static void nss_test_initgroups(char *name, gid_t gid)
329 {
330         long int size = 16;
331         long int start = 1;
332         gid_t *groups = NULL;
333         int i;
334         NSS_STATUS status;
335
336         groups = (gid_t *)malloc(size * sizeof(gid_t));
337         groups[0] = gid;
338
339         status = nss_initgroups(name, gid, &groups, &start, &size);
340         if (status == NSS_STATUS_UNAVAIL) {
341                 printf("No initgroups fn\n");
342                 return;
343         }
344
345         for (i=0; i<start-1; i++) {
346                 printf("%lu, ", (unsigned long)groups[i]);
347         }
348         printf("%lu\n", (unsigned long)groups[i]);
349 }
350
351
352 static void nss_test_users(void)
353 {
354         struct passwd *pwd;
355
356         nss_setpwent();
357         /* loop over all users */
358         while ((pwd = nss_getpwent())) {
359                 printf("Testing user %s\n", pwd->pw_name);
360                 printf("getpwent:   "); print_passwd(pwd);
361                 pwd = nss_getpwuid(pwd->pw_uid);
362                 if (!pwd) {
363                         total_errors++;
364                         printf("ERROR: can't getpwuid\n");
365                         continue;
366                 }
367                 printf("getpwuid:   "); print_passwd(pwd);
368                 pwd = nss_getpwnam(pwd->pw_name);
369                 if (!pwd) {
370                         total_errors++;
371                         printf("ERROR: can't getpwnam\n");
372                         continue;
373                 }
374                 printf("getpwnam:   "); print_passwd(pwd);
375                 printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid);
376                 printf("\n");
377         }
378         nss_endpwent();
379 }
380
381 static void nss_test_groups(void)
382 {
383         struct group *grp;
384
385         nss_setgrent();
386         /* loop over all groups */
387         while ((grp = nss_getgrent())) {
388                 printf("Testing group %s\n", grp->gr_name);
389                 printf("getgrent: "); print_group(grp);
390                 grp = nss_getgrnam(grp->gr_name);
391                 if (!grp) {
392                         total_errors++;
393                         printf("ERROR: can't getgrnam\n");
394                         continue;
395                 }
396                 printf("getgrnam: "); print_group(grp);
397                 grp = nss_getgrgid(grp->gr_gid);
398                 if (!grp) {
399                         total_errors++;
400                         printf("ERROR: can't getgrgid\n");
401                         continue;
402                 }
403                 printf("getgrgid: "); print_group(grp);
404                 printf("\n");
405         }
406         nss_endgrent();
407 }
408
409 static void nss_test_errors(void)
410 {
411         struct passwd *pwd;
412         struct group *grp;
413
414         pwd = getpwnam("nosuchname");
415         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
416                 total_errors++;
417                 printf("ERROR Non existant user gave error %d\n", last_error);
418         }
419
420         pwd = getpwuid(0xFFF0);
421         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
422                 total_errors++;
423                 printf("ERROR Non existant uid gave error %d\n", last_error);
424         }
425
426         grp = getgrnam("nosuchgroup");
427         if (grp || last_error != NSS_STATUS_NOTFOUND) {
428                 total_errors++;
429                 printf("ERROR Non existant group gave error %d\n", last_error);
430         }
431
432         grp = getgrgid(0xFFF0);
433         if (grp || last_error != NSS_STATUS_NOTFOUND) {
434                 total_errors++;
435                 printf("ERROR Non existant gid gave error %d\n", last_error);
436         }
437 }
438
439  int main(int argc, char *argv[])
440 {       
441         if (argc > 1) so_path = argv[1];
442         if (argc > 2) nss_name = argv[2];
443
444         nss_test_users();
445         nss_test_groups();
446         nss_test_errors();
447
448         printf("total_errors=%d\n", total_errors);
449
450         return total_errors;
451 }