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