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 24static const char *so_path = "/lib/libnss_winbind.so"; 25static const char *nss_name = "winbind"; 26static int nss_errno; 27static NSS_STATUS last_error; 28static int total_errors; 29 30static 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 53static 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 61static 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 80static 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 99static 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 118static 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 128static 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 139static 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_array_p(char, buflen); 149 150again: 151 status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno); 152 if (status == NSS_STATUS_TRYAGAIN) { 153 buflen *= 2; 154 buf = realloc_p(buf, char, 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 167static 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_array_p(char, buflen); 177again: 178 status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno); 179 if (status == NSS_STATUS_TRYAGAIN) { 180 buflen *= 2; 181 buf = realloc_p(buf, char, 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 194static 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_array_p(char, buflen); 204again: 205 status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno); 206 if (status == NSS_STATUS_TRYAGAIN) { 207 buflen *= 2; 208 buf = realloc_p(buf, char, 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 221static 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 231static 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 241static 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 257static 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 269static 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 288static 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 312static 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 341static 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 369static 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} 412