r23792: convert Samba4 to GPLv3
[jelmer/samba4-debian.git] / source / 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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21
22 #include "nsswitch/nsstest.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         char s[1024];
33         static void *h;
34         void *res;
35
36         snprintf(s,sizeof(s), "_nss_%s_%s", nss_name, name);
37
38         if (!h) {
39                 h = 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 = dlsym(h, s);
46         if (!res) {
47                 printf("Can't find function %s\n", s);
48                 return NULL;
49         }
50         return res;
51 }
52
53 static void report_nss_error(const char *who, NSS_STATUS status)
54 {
55         last_error = status;
56         total_errors++;
57         printf("ERROR %s: NSS_STATUS=%d  %d (nss_errno=%d)\n", 
58                who, status, NSS_STATUS_SUCCESS, nss_errno);
59 }
60
61 static struct passwd *nss_getpwent(void)
62 {
63         NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, 
64                                       size_t , int *) = find_fn("getpwent_r");
65         static struct passwd pwd;
66         static char buf[1000];
67         NSS_STATUS status;
68
69         status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno);
70         if (status == NSS_STATUS_NOTFOUND) {
71                 return NULL;
72         }
73         if (status != NSS_STATUS_SUCCESS) {
74                 report_nss_error("getpwent", status);
75                 return NULL;
76         }
77         return &pwd;
78 }
79
80 static struct passwd *nss_getpwnam(const char *name)
81 {
82         NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, 
83                                       size_t , int *) = find_fn("getpwnam_r");
84         static struct passwd pwd;
85         static char buf[1000];
86         NSS_STATUS status;
87         
88         status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno);
89         if (status == NSS_STATUS_NOTFOUND) {
90                 return NULL;
91         }
92         if (status != NSS_STATUS_SUCCESS) {
93                 report_nss_error("getpwnam", status);
94                 return NULL;
95         }
96         return &pwd;
97 }
98
99 static struct passwd *nss_getpwuid(uid_t uid)
100 {
101         NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, 
102                                       size_t , int *) = find_fn("getpwuid_r");
103         static struct passwd pwd;
104         static char buf[1000];
105         NSS_STATUS status;
106         
107         status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno);
108         if (status == NSS_STATUS_NOTFOUND) {
109                 return NULL;
110         }
111         if (status != NSS_STATUS_SUCCESS) {
112                 report_nss_error("getpwuid", status);
113                 return NULL;
114         }
115         return &pwd;
116 }
117
118 static void nss_setpwent(void)
119 {
120         NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent");
121         NSS_STATUS status;
122         status = _nss_setpwent();
123         if (status != NSS_STATUS_SUCCESS) {
124                 report_nss_error("setpwent", status);
125         }
126 }
127
128 static void nss_endpwent(void)
129 {
130         NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent");
131         NSS_STATUS status;
132         status = _nss_endpwent();
133         if (status != NSS_STATUS_SUCCESS) {
134                 report_nss_error("endpwent", status);
135         }
136 }
137
138
139 static struct group *nss_getgrent(void)
140 {
141         NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, 
142                                       size_t , int *) = find_fn("getgrent_r");
143         static struct group grp;
144         static char *buf;
145         static int buflen = 1024;
146         NSS_STATUS status;
147
148         if (!buf) buf = malloc(buflen);
149
150 again:  
151         status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno);
152         if (status == NSS_STATUS_TRYAGAIN) {
153                 buflen *= 2;
154                 buf = realloc(buf, buflen);
155                 goto again;
156         }
157         if (status == NSS_STATUS_NOTFOUND) {
158                 return NULL;
159         }
160         if (status != NSS_STATUS_SUCCESS) {
161                 report_nss_error("getgrent", status);
162                 return NULL;
163         }
164         return &grp;
165 }
166
167 static struct group *nss_getgrnam(const char *name)
168 {
169         NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, 
170                                       size_t , int *) = find_fn("getgrnam_r");
171         static struct group grp;
172         static char *buf;
173         static int buflen = 1000;
174         NSS_STATUS status;
175
176         if (!buf) buf = malloc(buflen);
177 again:  
178         status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
179         if (status == NSS_STATUS_TRYAGAIN) {
180                 buflen *= 2;
181                 buf = realloc(buf, buflen);
182                 goto again;
183         }
184         if (status == NSS_STATUS_NOTFOUND) {
185                 return NULL;
186         }
187         if (status != NSS_STATUS_SUCCESS) {
188                 report_nss_error("getgrnam", status);
189                 return NULL;
190         }
191         return &grp;
192 }
193
194 static struct group *nss_getgrgid(gid_t gid)
195 {
196         NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, 
197                                       size_t , int *) = find_fn("getgrgid_r");
198         static struct group grp;
199         static char *buf;
200         static int buflen = 1000;
201         NSS_STATUS status;
202         
203         if (!buf) buf = malloc(buflen);
204 again:  
205         status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
206         if (status == NSS_STATUS_TRYAGAIN) {
207                 buflen *= 2;
208                 buf = realloc(buf, buflen);
209                 goto again;
210         }
211         if (status == NSS_STATUS_NOTFOUND) {
212                 return NULL;
213         }
214         if (status != NSS_STATUS_SUCCESS) {
215                 report_nss_error("getgrgid", status);
216                 return NULL;
217         }
218         return &grp;
219 }
220
221 static void nss_setgrent(void)
222 {
223         NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
224         NSS_STATUS status;
225         status = _nss_setgrent();
226         if (status != NSS_STATUS_SUCCESS) {
227                 report_nss_error("setgrent", status);
228         }
229 }
230
231 static void nss_endgrent(void)
232 {
233         NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
234         NSS_STATUS status;
235         status = _nss_endgrent();
236         if (status != NSS_STATUS_SUCCESS) {
237                 report_nss_error("endgrent", status);
238         }
239 }
240
241 static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *start, long int *size)
242 {
243         NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *,
244                                       long int *, gid_t **, long int , int *) = 
245                 find_fn("initgroups_dyn");
246         NSS_STATUS status;
247
248         if (!_nss_initgroups) return NSS_STATUS_UNAVAIL;
249
250         status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno);
251         if (status != NSS_STATUS_SUCCESS) {
252                 report_nss_error("initgroups", status);
253         }
254         return status;
255 }
256
257 static void print_passwd(struct passwd *pwd)
258 {
259         printf("%s:%s:%d:%d:%s:%s:%s\n", 
260                pwd->pw_name,
261                pwd->pw_passwd,
262                pwd->pw_uid,
263                pwd->pw_gid,
264                pwd->pw_gecos,
265                pwd->pw_dir,
266                pwd->pw_shell);
267 }
268
269 static void print_group(struct group *grp)
270 {
271         int i;
272         printf("%s:%s:%d: ", 
273                grp->gr_name,
274                grp->gr_passwd,
275                grp->gr_gid);
276         
277         if (!grp->gr_mem[0]) {
278                 printf("\n");
279                 return;
280         }
281         
282         for (i=0; grp->gr_mem[i+1]; i++) {
283                 printf("%s, ", grp->gr_mem[i]);
284         }
285         printf("%s\n", grp->gr_mem[i]);
286 }
287
288 static void nss_test_initgroups(char *name, gid_t gid)
289 {
290         long int size = 16;
291         long int start = 1;
292         gid_t *groups = NULL;
293         int i;
294         NSS_STATUS status;
295
296         groups = (gid_t *)malloc_array_p(gid_t, size);
297         groups[0] = gid;
298
299         status = nss_initgroups(name, gid, &groups, &start, &size);
300         if (status == NSS_STATUS_UNAVAIL) {
301                 printf("No initgroups fn\n");
302                 return;
303         }
304
305         for (i=0; i<start-1; i++) {
306                 printf("%d, ", groups[i]);
307         }
308         printf("%d\n", groups[i]);
309 }
310
311
312 static void nss_test_users(void)
313 {
314         struct passwd *pwd;
315
316         nss_setpwent();
317         /* loop over all users */
318         while ((pwd = nss_getpwent())) {
319                 printf("Testing user %s\n", pwd->pw_name);
320                 printf("getpwent:   "); print_passwd(pwd);
321                 pwd = nss_getpwuid(pwd->pw_uid);
322                 if (!pwd) {
323                         total_errors++;
324                         printf("ERROR: can't getpwuid\n");
325                         continue;
326                 }
327                 printf("getpwuid:   "); print_passwd(pwd);
328                 pwd = nss_getpwnam(pwd->pw_name);
329                 if (!pwd) {
330                         total_errors++;
331                         printf("ERROR: can't getpwnam\n");
332                         continue;
333                 }
334                 printf("getpwnam:   "); print_passwd(pwd);
335                 printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid);
336                 printf("\n");
337         }
338         nss_endpwent();
339 }
340
341 static void nss_test_groups(void)
342 {
343         struct group *grp;
344
345         nss_setgrent();
346         /* loop over all groups */
347         while ((grp = nss_getgrent())) {
348                 printf("Testing group %s\n", grp->gr_name);
349                 printf("getgrent: "); print_group(grp);
350                 grp = nss_getgrnam(grp->gr_name);
351                 if (!grp) {
352                         total_errors++;
353                         printf("ERROR: can't getgrnam\n");
354                         continue;
355                 }
356                 printf("getgrnam: "); print_group(grp);
357                 grp = nss_getgrgid(grp->gr_gid);
358                 if (!grp) {
359                         total_errors++;
360                         printf("ERROR: can't getgrgid\n");
361                         continue;
362                 }
363                 printf("getgrgid: "); print_group(grp);
364                 printf("\n");
365         }
366         nss_endgrent();
367 }
368
369 static void nss_test_errors(void)
370 {
371         struct passwd *pwd;
372         struct group *grp;
373
374         pwd = getpwnam("nosuchname");
375         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
376                 total_errors++;
377                 printf("ERROR Non existant user gave error %d\n", last_error);
378         }
379
380         pwd = getpwuid(0xFFF0);
381         if (pwd || last_error != NSS_STATUS_NOTFOUND) {
382                 total_errors++;
383                 printf("ERROR Non existant uid gave error %d\n", last_error);
384         }
385
386         grp = getgrnam("nosuchgroup");
387         if (grp || last_error != NSS_STATUS_NOTFOUND) {
388                 total_errors++;
389                 printf("ERROR Non existant group gave error %d\n", last_error);
390         }
391
392         grp = getgrgid(0xFFF0);
393         if (grp || last_error != NSS_STATUS_NOTFOUND) {
394                 total_errors++;
395                 printf("ERROR Non existant gid gave error %d\n", last_error);
396         }
397 }
398
399  int main(int argc, char *argv[])
400 {       
401         if (argc > 1) so_path = argv[1];
402         if (argc > 2) nss_name = argv[2];
403
404         nss_test_users();
405         nss_test_groups();
406         nss_test_errors();
407
408         printf("total_errors=%d\n", total_errors);
409
410         return total_errors;
411 }