Changeset 1825 for trunk/server/common/oursrc
- Timestamp:
- Apr 29, 2011, 9:22:38 PM (13 years ago)
- Location:
- trunk/server/common/oursrc/nss_nonlocal
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server/common/oursrc/nss_nonlocal/Makefile.am
r782 r1825 5 5 libnss_nonlocal_la_LDFLAGS = \ 6 6 -version-info 2:0:0 \ 7 -export-symbols-regex '^_nss_nonlocal_' 8 9 noinst_PROGRAMS = .linktest 10 _linktest_SOURCES = 11 _linktest_LDADD = libnss_nonlocal.la 12 _linktest_LDFLAGS = -nostdlib -entry=0 7 -export-symbols-regex '^_nss_nonlocal_' \ 8 -no-undefined -Wl,-z,defs 13 9 14 10 install-exec-hook: -
trunk/server/common/oursrc/nss_nonlocal/README
r1553 r1825 9 9 group: compat nonlocal 10 10 group_nonlocal: hesiod 11 12 The module also assigns special properties to two local groups and one 13 local user, if they exist: 14 15 • If the local group ‘nss-nonlocal-users’ exists, then nonlocal users 16 will be automatically added to it. Furthermore, if a local user is 17 added to this group, then that user will inherit any nonlocal gids 18 from a nonlocal user of the same name, as supplementary gids. 19 20 • If the local group ‘nss-local-users’ exists, then local users will 21 be automatically added to it. 22 23 • If the local user ‘nss-nonlocal-users’ is added to a local group, 24 then the local group will inherit the nonlocal membership of a group 25 of the same gid. 11 26 12 27 Copyright © 2007–2010 Anders Kaseorg <andersk@mit.edu> and Tim Abbott -
trunk/server/common/oursrc/nss_nonlocal/configure.ac
r1553 r1825 1 AC_INIT([nss_nonlocal], [ 1.11], [andersk@mit.edu])1 AC_INIT([nss_nonlocal], [2.0], [andersk@mit.edu]) 2 2 AC_CANONICAL_TARGET 3 3 AM_INIT_AUTOMAKE([-Wall -Werror foreign]) … … 9 9 AC_PROG_INSTALL 10 10 AC_PROG_LIBTOOL 11 12 AC_HEADER_STDBOOL 11 13 12 14 case "$target_cpu" in -
trunk/server/common/oursrc/nss_nonlocal/nonlocal-group.c
r1553 r1825 34 34 #include <syslog.h> 35 35 #include <errno.h> 36 #include <pwd.h> 36 37 #include <grp.h> 37 38 #include <nss.h> … … 39 40 #include "nonlocal.h" 40 41 42 /* 43 * If the MAGIC_NONLOCAL_GROUPNAME local group exists, then nonlocal 44 * users will be automatically added to it. Furthermore, if a local 45 * user is added to this group, then that user will inherit any 46 * nonlocal gids from a nonlocal user of the same name, as 47 * supplementary gids. 48 */ 41 49 #define MAGIC_NONLOCAL_GROUPNAME "nss-nonlocal-users" 50 51 /* 52 * If the MAGIC_LOCAL_GROUPNAME local group exists, then local users 53 * will be automatically added to it. 54 */ 42 55 #define MAGIC_LOCAL_GROUPNAME "nss-local-users" 56 57 /* 58 * If the MAGIC_NONLOCAL_USERNAME local user is added to a local 59 * group, then the local group will inherit the nonlocal membership of 60 * a group of the same gid. 61 */ 62 #define MAGIC_NONLOCAL_USERNAME "nss-nonlocal-users" 43 63 44 64 … … 52 72 53 73 54 static service_user * 55 nss_group_nonlocal_database(void) 56 { 57 static service_user *nip = NULL; 58 if (nip == NULL) 59 __nss_database_lookup("group_nonlocal", NULL, "", &nip); 60 61 return nip; 62 } 63 64 65 enum nss_status 66 check_nonlocal_gid(const char *user, gid_t gid, int *errnop) 67 { 68 static const char *fct_name = "getgrgid_r"; 69 static service_user *startp = NULL; 70 static void *fct_start = NULL; 71 enum nss_status status; 72 service_user *nip; 73 union { 74 enum nss_status (*l)(gid_t gid, struct group *grp, 75 char *buffer, size_t buflen, int *errnop); 76 void *ptr; 77 } fct; 74 static service_user *__nss_group_nonlocal_database; 75 76 static int 77 internal_function 78 __nss_group_nonlocal_lookup(service_user **ni, const char *fct_name, 79 void **fctp) 80 { 81 if (__nss_group_nonlocal_database == NULL 82 && __nss_database_lookup("group_nonlocal", NULL, NULL, 83 &__nss_group_nonlocal_database) < 0) 84 return -1; 85 86 *ni = __nss_group_nonlocal_database; 87 88 *fctp = __nss_lookup_function(*ni, fct_name); 89 return 0; 90 } 91 92 93 enum nss_status 94 check_nonlocal_gid(const char *user, const char *group, gid_t gid, int *errnop) 95 { 96 enum nss_status status; 78 97 struct group gbuf; 79 int old_errno = errno; 80 98 char *buf; 81 99 size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 82 char *buf = malloc(buflen); 83 if (buf == NULL) { 84 *errnop = ENOMEM; 85 errno = old_errno; 86 return NSS_STATUS_TRYAGAIN; 87 } 88 89 if (fct_start == NULL && 90 __nss_group_lookup(&startp, fct_name, &fct_start) != 0) { 91 free(buf); 92 return NSS_STATUS_UNAVAIL; 93 } 94 nip = startp; 95 fct.ptr = fct_start; 96 do { 97 morebuf: 98 if (fct.l == _nss_nonlocal_getgrgid_r) 99 status = NSS_STATUS_NOTFOUND; 100 else 101 status = DL_CALL_FCT(fct.l, (gid, &gbuf, buf, buflen, errnop)); 102 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) { 103 free(buf); 104 buflen *= 2; 105 buf = malloc(buflen); 106 if (buf == NULL) { 107 *errnop = ENOMEM; 108 errno = old_errno; 109 return NSS_STATUS_TRYAGAIN; 100 const struct walk_nss w = { 101 .lookup = &__nss_group_lookup, .fct_name = "getgrgid_r", 102 .status = &status, .errnop = errnop, .buf = &buf, .buflen = &buflen 103 }; 104 const __typeof__(&_nss_nonlocal_getgrgid_r) self = &_nss_nonlocal_getgrgid_r; 105 #define args (gid, &gbuf, buf, buflen, errnop) 106 #include "walk_nss.h" 107 #undef args 108 109 if (status == NSS_STATUS_TRYAGAIN) 110 return status; 111 else if (status != NSS_STATUS_SUCCESS) 112 return NSS_STATUS_SUCCESS; 113 114 if (group == NULL || strcmp(gbuf.gr_name, group) == 0) { 115 char *const *mem; 116 for (mem = gbuf.gr_mem; *mem != NULL; mem++) 117 if (strcmp(*mem, MAGIC_NONLOCAL_USERNAME) == 0) { 118 status = check_nonlocal_user(*mem, errnop); 119 if (status == NSS_STATUS_TRYAGAIN) { 120 free(buf); 121 return status; 122 } else if (status == NSS_STATUS_NOTFOUND) { 123 free(buf); 124 return NSS_STATUS_SUCCESS; 125 } 126 break; 110 127 } 111 goto morebuf; 112 } 113 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 114 115 if (status == NSS_STATUS_SUCCESS) { 116 syslog(LOG_DEBUG, "nss_nonlocal: removing local group %u (%s) from non-local user %s\n", gbuf.gr_gid, gbuf.gr_name, user); 117 status = NSS_STATUS_NOTFOUND; 118 } else if (status != NSS_STATUS_TRYAGAIN) { 119 status = NSS_STATUS_SUCCESS; 120 } 121 128 } 129 130 syslog(LOG_DEBUG, "nss_nonlocal: removing local group %u (%s) from non-local user %s\n", gbuf.gr_gid, gbuf.gr_name, user); 122 131 free(buf); 123 return status;132 return NSS_STATUS_NOTFOUND; 124 133 } 125 134 … … 134 143 errno = 0; 135 144 gid = strtoul(grp->gr_name, &end, 10); 136 if (errno == 0 && *end == '\0' && (gid_t)gid == gid) 137 status = check_nonlocal_gid(user, gid, errnop); 138 errno = old_errno; 145 if (errno == 0 && *end == '\0' && (gid_t)gid == gid) { 146 errno = old_errno; 147 status = check_nonlocal_gid(user, grp->gr_name, gid, errnop); 148 } else 149 errno = old_errno; 139 150 if (status != NSS_STATUS_SUCCESS) 140 151 return status; 141 152 142 return check_nonlocal_gid(user, grp->gr_ gid, errnop);153 return check_nonlocal_gid(user, grp->gr_name, grp->gr_gid, errnop); 143 154 } 144 155 … … 146 157 get_local_group(const char *name, struct group *grp, char **buffer, int *errnop) 147 158 { 148 static const char *fct_name = "getgrnam_r"; 149 static service_user *startp = NULL; 150 static void *fct_start = NULL; 151 enum nss_status status; 152 service_user *nip; 153 union { 154 enum nss_status (*l)(const char *name, struct group *grp, 155 char *buffer, size_t buflen, int *errnop); 156 void *ptr; 157 } fct; 158 size_t buflen; 159 int old_errno = errno; 160 161 buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 162 *buffer = malloc(buflen); 163 if (*buffer == NULL) { 164 *errnop = ENOMEM; 165 errno = old_errno; 166 return NSS_STATUS_TRYAGAIN; 167 } 168 169 if (fct_start == NULL && 170 __nss_group_lookup(&startp, fct_name, &fct_start) != 0) { 171 free(*buffer); 172 *buffer = NULL; 173 return NSS_STATUS_UNAVAIL; 174 } 175 nip = startp; 176 fct.ptr = fct_start; 177 do { 178 morebuf: 179 if (fct.l == _nss_nonlocal_getgrnam_r) 180 status = NSS_STATUS_NOTFOUND; 181 else 182 status = DL_CALL_FCT(fct.l, (name, grp, *buffer, buflen, errnop)); 183 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) { 184 free(*buffer); 185 buflen *= 2; 186 *buffer = malloc(buflen); 187 if (*buffer == NULL) { 188 *errnop = ENOMEM; 189 errno = old_errno; 190 return NSS_STATUS_TRYAGAIN; 191 } 192 goto morebuf; 193 } 194 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 195 196 if (status != NSS_STATUS_SUCCESS) { 197 free(*buffer); 198 *buffer = NULL; 199 } 200 159 enum nss_status status; 160 size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); 161 const struct walk_nss w = { 162 .lookup = &__nss_group_lookup, .fct_name = "getgrnam_r", 163 .status = &status, .errnop = errnop, .buf = buffer, .buflen = &buflen 164 }; 165 const __typeof__(&_nss_nonlocal_getgrnam_r) self = &_nss_nonlocal_getgrnam_r; 166 #define args (name, grp, *buffer, buflen, errnop) 167 #include "walk_nss.h" 168 #undef args 201 169 return status; 202 170 } 203 171 204 static service_user *grent_ nip = NULL;172 static service_user *grent_startp, *grent_nip; 205 173 static void *grent_fct_start; 206 174 static union { … … 214 182 _nss_nonlocal_setgrent(int stayopen) 215 183 { 216 static const char *fct_name = "setgrent"; 217 static void *fct_start = NULL; 218 enum nss_status status; 219 service_user *nip; 220 union { 221 enum nss_status (*l)(int stayopen); 222 void *ptr; 223 } fct; 224 225 nip = nss_group_nonlocal_database(); 226 if (nip == NULL) 227 return NSS_STATUS_UNAVAIL; 228 if (fct_start == NULL) 229 fct_start = __nss_lookup_function(nip, fct_name); 230 fct.ptr = fct_start; 231 do { 232 if (fct.ptr == NULL) 233 status = NSS_STATUS_UNAVAIL; 234 else 235 status = DL_CALL_FCT(fct.l, (stayopen)); 236 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 184 enum nss_status status; 185 const struct walk_nss w = { 186 .lookup = &__nss_group_nonlocal_lookup, .fct_name = "setgrent", 187 .status = &status 188 }; 189 const __typeof__(&_nss_nonlocal_setgrent) self = NULL; 190 #define args (stayopen) 191 #include "walk_nss.h" 192 #undef args 237 193 if (status != NSS_STATUS_SUCCESS) 238 194 return status; 239 195 240 grent_nip = nip;241 196 if (grent_fct_start == NULL) 242 grent_fct_start = __nss_lookup_function(nip, grent_fct_name); 197 __nss_group_nonlocal_lookup(&grent_startp, grent_fct_name, 198 &grent_fct_start); 199 grent_nip = grent_startp; 243 200 grent_fct.ptr = grent_fct_start; 244 201 return NSS_STATUS_SUCCESS; … … 248 205 _nss_nonlocal_endgrent(void) 249 206 { 250 static const char *fct_name = "endgrent"; 251 static void *fct_start = NULL; 252 enum nss_status status; 253 service_user *nip; 254 union { 255 enum nss_status (*l)(void); 256 void *ptr; 257 } fct; 207 enum nss_status status; 208 const struct walk_nss w = { 209 .lookup = &__nss_group_nonlocal_lookup, .fct_name = "endgrent", 210 .status = &status 211 }; 212 const __typeof__(&_nss_nonlocal_endgrent) self = NULL; 258 213 259 214 grent_nip = NULL; 260 215 261 nip = nss_group_nonlocal_database(); 262 if (nip == NULL) 263 return NSS_STATUS_UNAVAIL; 264 if (fct_start == NULL) 265 fct_start = __nss_lookup_function(nip, fct_name); 266 fct.ptr = fct_start; 267 do { 268 if (fct.ptr == NULL) 269 status = NSS_STATUS_UNAVAIL; 270 else 271 status = DL_CALL_FCT(fct.l, ()); 272 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 216 #define args () 217 #include "walk_nss.h" 218 #undef args 273 219 return status; 274 220 } … … 315 261 char *buffer, size_t buflen, int *errnop) 316 262 { 317 static const char *fct_name = "getgrnam_r"; 318 static void *fct_start = NULL; 319 enum nss_status status; 320 service_user *nip; 321 union { 322 enum nss_status (*l)(const char *name, struct group *grp, 323 char *buffer, size_t buflen, int *errnop); 324 void *ptr; 325 } fct; 263 enum nss_status status; 264 const struct walk_nss w = { 265 .lookup = &__nss_group_nonlocal_lookup, .fct_name = "getgrnam_r", 266 .status = &status, .errnop = errnop 267 }; 268 const __typeof__(&_nss_nonlocal_getgrnam_r) self = NULL; 326 269 327 270 char *nonlocal_ignore = getenv(NONLOCAL_IGNORE_ENV); … … 329 272 return NSS_STATUS_UNAVAIL; 330 273 331 nip = nss_group_nonlocal_database(); 332 if (nip == NULL) 333 return NSS_STATUS_UNAVAIL; 334 if (fct_start == NULL) 335 fct_start = __nss_lookup_function(nip, fct_name); 336 fct.ptr = fct_start; 337 do { 338 if (fct.ptr == NULL) 339 status = NSS_STATUS_UNAVAIL; 340 else 341 status = DL_CALL_FCT(fct.l, (name, grp, buffer, buflen, errnop)); 342 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 343 break; 344 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 274 #define args (name, grp, buffer, buflen, errnop) 275 #include "walk_nss.h" 276 #undef args 345 277 if (status != NSS_STATUS_SUCCESS) 346 278 return status; … … 358 290 char *buffer, size_t buflen, int *errnop) 359 291 { 360 static const char *fct_name = "getgrgid_r"; 361 static void *fct_start = NULL; 362 enum nss_status status; 363 service_user *nip; 364 union { 365 enum nss_status (*l)(gid_t gid, struct group *grp, 366 char *buffer, size_t buflen, int *errnop); 367 void *ptr; 368 } fct; 292 enum nss_status status; 293 const struct walk_nss w = { 294 .lookup = &__nss_group_nonlocal_lookup, .fct_name = "getgrgid_r", 295 .status = &status, .errnop = errnop 296 }; 297 const __typeof__(&_nss_nonlocal_getgrgid_r) self = NULL; 369 298 370 299 char *nonlocal_ignore = getenv(NONLOCAL_IGNORE_ENV); … … 372 301 return NSS_STATUS_UNAVAIL; 373 302 374 nip = nss_group_nonlocal_database(); 375 if (nip == NULL) 376 return NSS_STATUS_UNAVAIL; 377 if (fct_start == NULL) 378 fct_start = __nss_lookup_function(nip, fct_name); 379 fct.ptr = fct_start; 380 do { 381 if (fct.ptr == NULL) 382 status = NSS_STATUS_UNAVAIL; 383 else 384 status = DL_CALL_FCT(fct.l, (gid, grp, buffer, buflen, errnop)); 385 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 386 break; 387 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 303 #define args (gid, grp, buffer, buflen, errnop) 304 #include "walk_nss.h" 305 #undef args 388 306 if (status != NSS_STATUS_SUCCESS) 389 307 return status; … … 397 315 } 398 316 317 static bool 318 add_group(gid_t group, long int *start, long int *size, gid_t **groupsp, 319 long int limit, int *errnop, enum nss_status *status) 320 { 321 int i, old_errno = errno; 322 for (i = 0; i < *start; ++i) 323 if ((*groupsp)[i] == group) 324 return true; 325 if (*start + 1 > *size) { 326 gid_t *newgroups; 327 long int newsize = 2 * *size; 328 if (limit > 0) { 329 if (*size >= limit) { 330 *status = NSS_STATUS_SUCCESS; 331 return false; 332 } 333 if (newsize > limit) 334 newsize = limit; 335 } 336 newgroups = realloc(*groupsp, newsize * sizeof((*groupsp)[0])); 337 errno = old_errno; 338 if (newgroups == NULL) { 339 *errnop = ENOMEM; 340 *status = NSS_STATUS_TRYAGAIN; 341 return false; 342 } 343 *groupsp = newgroups; 344 *size = newsize; 345 } 346 (*groupsp)[(*start)++] = group; 347 return true; 348 } 349 399 350 enum nss_status 400 351 _nss_nonlocal_initgroups_dyn(const char *user, gid_t group, long int *start, … … 402 353 int *errnop) 403 354 { 404 static const char *fct_name = "initgroups_dyn"; 405 static void *fct_start = NULL; 406 enum nss_status status; 407 service_user *nip; 408 union { 409 enum nss_status (*l)(const char *user, gid_t group, long int *start, 410 long int *size, gid_t **groupsp, long int limit, 411 int *errnop); 412 void *ptr; 413 } fct; 355 enum nss_status status; 356 const struct walk_nss w = { 357 .lookup = &__nss_group_nonlocal_lookup, .fct_name = "initgroups_dyn", 358 .status = &status, .errnop = errnop 359 }; 360 const __typeof__(&_nss_nonlocal_initgroups_dyn) self = NULL; 414 361 415 362 struct group local_users_group, nonlocal_users_group; 416 gid_t local_users_gid, gid; 417 int is_local = 0; 363 bool is_nonlocal = true; 418 364 char *buffer; 419 int old_errno;420 365 int in, out, i; 421 366 422 /* Check that the user is a nonlocal user before adding any groups. */ 367 /* Check that the user is a nonlocal user, or a member of the 368 * MAGIC_NONLOCAL_GROUPNAME group, before adding any groups. */ 423 369 status = check_nonlocal_user(user, errnop); 424 if (status == NSS_STATUS_TRYAGAIN) 425 return status; 426 else if (status != NSS_STATUS_SUCCESS) 427 is_local = 1; 428 429 old_errno = errno; 430 431 status = get_local_group(MAGIC_LOCAL_GROUPNAME, 432 &local_users_group, &buffer, errnop); 433 if (status == NSS_STATUS_SUCCESS) { 434 local_users_gid = local_users_group.gr_gid; 435 free(buffer); 436 } else if (status == NSS_STATUS_TRYAGAIN) { 437 return status; 438 } else { 439 syslog(LOG_WARNING, "nss_nonlocal: Group %s does not exist locally!", 440 MAGIC_LOCAL_GROUPNAME); 441 local_users_gid = -1; 442 } 443 444 if (is_local) { 445 gid = local_users_gid; 446 } else { 447 status = get_local_group(MAGIC_NONLOCAL_GROUPNAME, 448 &nonlocal_users_group, &buffer, errnop); 370 if (status == NSS_STATUS_TRYAGAIN) { 371 return status; 372 } else if (status != NSS_STATUS_SUCCESS) { 373 is_nonlocal = false; 374 375 status = get_local_group(MAGIC_LOCAL_GROUPNAME, 376 &local_users_group, &buffer, errnop); 449 377 if (status == NSS_STATUS_SUCCESS) { 450 gid = nonlocal_users_group.gr_gid;451 378 free(buffer); 379 if (!add_group(local_users_group.gr_gid, start, size, groupsp, 380 limit, errnop, &status)) 381 return status; 452 382 } else if (status == NSS_STATUS_TRYAGAIN) { 453 383 return status; 454 384 } else { 455 syslog(LOG_WARNING, "nss_nonlocal: Group %s does not exist locally!",456 MAGIC_NONLOCAL_GROUPNAME);457 gid = -1;458 } 459 } 460 461 if (gid != -1) {462 int i;463 for (i = 0; i < *start; ++i) 464 if ((*groupsp)[i] == gid)465 break;466 if (i >= *start) {467 if (*start + 1 > *size) {468 gid_t *newgroups;469 long int newsize = 2 * *size;470 if (limit > 0) {471 if (*size >= limit)472 return NSS_STATUS_SUCCESS;473 i f (newsize > limit)474 newsize = limit;385 syslog(LOG_WARNING, 386 "nss_nonlocal: Group %s does not exist locally!", 387 MAGIC_LOCAL_GROUPNAME); 388 } 389 } 390 391 status = get_local_group(MAGIC_NONLOCAL_GROUPNAME, 392 &nonlocal_users_group, &buffer, errnop); 393 if (status == NSS_STATUS_SUCCESS) { 394 free(buffer); 395 if (is_nonlocal) { 396 if (!add_group(nonlocal_users_group.gr_gid, start, size, groupsp, 397 limit, errnop, &status)) 398 return status; 399 } else { 400 int i; 401 for (i = 0; i < *start; ++i) { 402 if ((*groupsp)[i] == nonlocal_users_group.gr_gid) { 403 is_nonlocal = true; 404 break; 475 405 } 476 newgroups = realloc(*groupsp, newsize * sizeof((*groupsp)[0])); 477 if (newgroups == NULL) { 478 *errnop = ENOMEM; 479 errno = old_errno; 480 return NSS_STATUS_TRYAGAIN; 406 } 407 408 if (is_nonlocal) { 409 struct passwd pwbuf; 410 char *buf; 411 int nonlocal_errno = *errnop; 412 status = get_nonlocal_passwd(user, &pwbuf, &buf, errnop); 413 414 if (status == NSS_STATUS_SUCCESS) { 415 nonlocal_errno = *errnop; 416 status = check_nonlocal_gid(user, NULL, pwbuf.pw_gid, 417 &nonlocal_errno); 418 free(buf); 481 419 } 482 *groupsp = newgroups; 483 *size = newsize; 420 421 if (status == NSS_STATUS_SUCCESS) { 422 if (!add_group(pwbuf.pw_gid, start, size, groupsp, limit, 423 errnop, &status)) 424 return status; 425 } else if (status == NSS_STATUS_TRYAGAIN) { 426 *errnop = nonlocal_errno; 427 return status; 428 } 484 429 } 485 (*groupsp)[(*start)++] = gid; 486 } 487 } 488 489 if (is_local) 430 } 431 } else if (status == NSS_STATUS_TRYAGAIN) { 432 if (is_nonlocal) 433 return status; 434 } else { 435 syslog(LOG_WARNING, "nss_nonlocal: Group %s does not exist locally!", 436 MAGIC_NONLOCAL_GROUPNAME); 437 } 438 439 if (!is_nonlocal) 490 440 return NSS_STATUS_SUCCESS; 491 441 492 442 in = out = *start; 493 443 494 nip = nss_group_nonlocal_database(); 495 if (nip == NULL) 496 return NSS_STATUS_UNAVAIL; 497 if (fct_start == NULL) 498 fct_start = __nss_lookup_function(nip, fct_name); 499 fct.ptr = fct_start; 500 501 do { 502 if (fct.ptr == NULL) 503 status = NSS_STATUS_UNAVAIL; 504 else 505 status = DL_CALL_FCT(fct.l, (user, group, start, size, groupsp, limit, errnop)); 506 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 507 break; 508 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 444 #define args (user, group, start, size, groupsp, limit, errnop) 445 #include "walk_nss.h" 446 #undef args 509 447 if (status != NSS_STATUS_SUCCESS) 510 448 return status; … … 519 457 continue; 520 458 521 /* Don't let users get into MAGIC_LOCAL_GROUPNAME from nonlocal reasons. */ 522 if (local_users_gid == (*groupsp)[in]) { 523 syslog(LOG_WARNING, "nss_nonlocal: Nonlocal user %s removed from special local users group %s", 524 user, MAGIC_LOCAL_GROUPNAME); 525 continue; 526 } 527 528 status = check_nonlocal_gid(user, (*groupsp)[in], &nonlocal_errno); 459 status = check_nonlocal_gid(user, NULL, (*groupsp)[in], 460 &nonlocal_errno); 529 461 if (status == NSS_STATUS_SUCCESS) { 530 462 (*groupsp)[out++] = (*groupsp)[in]; -
trunk/server/common/oursrc/nss_nonlocal/nonlocal-passwd.c
r1553 r1825 50 50 51 51 52 static service_user * 53 nss_passwd_nonlocal_database(void) 54 { 55 static service_user *nip = NULL; 56 if (nip == NULL) 57 __nss_database_lookup("passwd_nonlocal", NULL, "", &nip); 58 59 return nip; 52 static service_user *__nss_passwd_nonlocal_database; 53 54 static int 55 internal_function 56 __nss_passwd_nonlocal_lookup(service_user **ni, const char *fct_name, 57 void **fctp) 58 { 59 if (__nss_passwd_nonlocal_database == NULL 60 && __nss_database_lookup("passwd_nonlocal", NULL, NULL, 61 &__nss_passwd_nonlocal_database) < 0) 62 return -1; 63 64 *ni = __nss_passwd_nonlocal_database; 65 66 *fctp = __nss_lookup_function(*ni, fct_name); 67 return 0; 60 68 } 61 69 … … 64 72 check_nonlocal_uid(const char *user, uid_t uid, int *errnop) 65 73 { 66 static const char *fct_name = "getpwuid_r"; 67 static service_user *startp = NULL; 68 static void *fct_start = NULL; 69 enum nss_status status; 70 service_user *nip; 71 union { 72 enum nss_status (*l)(uid_t uid, struct passwd *pwd, 73 char *buffer, size_t buflen, int *errnop); 74 void *ptr; 75 } fct; 74 enum nss_status status; 76 75 struct passwd pwbuf; 77 int old_errno = errno; 78 76 char *buf; 79 77 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); 80 char *buf = malloc(buflen); 81 if (buf == NULL) { 82 *errnop = ENOMEM; 83 errno = old_errno; 84 return NSS_STATUS_TRYAGAIN; 85 } 86 87 if (fct_start == NULL && 88 __nss_passwd_lookup(&startp, fct_name, &fct_start) != 0) { 89 free(buf); 90 return NSS_STATUS_UNAVAIL; 91 } 92 nip = startp; 93 fct.ptr = fct_start; 94 do { 95 morebuf: 96 if (fct.l == _nss_nonlocal_getpwuid_r) 97 status = NSS_STATUS_NOTFOUND; 98 else 99 status = DL_CALL_FCT(fct.l, (uid, &pwbuf, buf, buflen, errnop)); 100 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) { 101 free(buf); 102 buflen *= 2; 103 buf = malloc(buflen); 104 if (buf == NULL) { 105 *errnop = ENOMEM; 106 errno = old_errno; 107 return NSS_STATUS_TRYAGAIN; 108 } 109 goto morebuf; 110 } 111 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 78 const struct walk_nss w = { 79 .lookup = &__nss_passwd_lookup, .fct_name = "getpwuid_r", 80 .status = &status, .errnop = errnop, .buf = &buf, .buflen = &buflen 81 }; 82 const __typeof__(&_nss_nonlocal_getpwuid_r) self = &_nss_nonlocal_getpwuid_r; 83 #define args (uid, &pwbuf, buf, buflen, errnop) 84 #include "walk_nss.h" 85 #undef args 112 86 113 87 if (status == NSS_STATUS_SUCCESS) { 114 88 syslog(LOG_ERR, "nss_nonlocal: possible spoofing attack: non-local user %s has same UID as local user %s!\n", user, pwbuf.pw_name); 89 free(buf); 115 90 status = NSS_STATUS_NOTFOUND; 116 91 } else if (status != NSS_STATUS_TRYAGAIN) { … … 118 93 } 119 94 120 free(buf);121 95 return status; 122 96 } … … 132 106 errno = 0; 133 107 uid = strtoul(pwd->pw_name, &end, 10); 134 if (errno == 0 && *end == '\0' && (uid_t)uid == uid) 108 if (errno == 0 && *end == '\0' && (uid_t)uid == uid) { 109 errno = old_errno; 135 110 status = check_nonlocal_uid(user, uid, errnop); 136 errno = old_errno; 111 } else { 112 errno = old_errno; 113 } 137 114 if (status != NSS_STATUS_SUCCESS) 138 115 return status; … … 144 121 check_nonlocal_user(const char *user, int *errnop) 145 122 { 146 static const char *fct_name = "getpwnam_r"; 147 static service_user *startp = NULL; 148 static void *fct_start = NULL; 149 enum nss_status status; 150 service_user *nip; 151 union { 152 enum nss_status (*l)(const char *name, struct passwd *pwd, 153 char *buffer, size_t buflen, int *errnop); 154 void *ptr; 155 } fct; 123 enum nss_status status; 156 124 struct passwd pwbuf; 157 int old_errno = errno; 158 125 char *buf; 159 126 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); 160 char *buf = malloc(buflen); 161 if (buf == NULL) { 162 *errnop = ENOMEM; 163 errno = old_errno; 164 return NSS_STATUS_TRYAGAIN; 165 } 166 167 if (fct_start == NULL && 168 __nss_passwd_lookup(&startp, fct_name, &fct_start) != 0) { 127 const struct walk_nss w = { 128 .lookup = __nss_passwd_lookup, .fct_name = "getpwnam_r", 129 .status = &status, .errnop = errnop, .buf = &buf, .buflen = &buflen 130 }; 131 const __typeof__(&_nss_nonlocal_getpwnam_r) self = &_nss_nonlocal_getpwnam_r; 132 #define args (user, &pwbuf, buf, buflen, errnop) 133 #include "walk_nss.h" 134 #undef args 135 136 if (status == NSS_STATUS_SUCCESS) { 169 137 free(buf); 170 return NSS_STATUS_UNAVAIL;171 }172 nip = startp;173 fct.ptr = fct_start;174 do {175 morebuf:176 if (fct.l == _nss_nonlocal_getpwnam_r)177 status = NSS_STATUS_NOTFOUND;178 else179 status = DL_CALL_FCT(fct.l, (user, &pwbuf, buf, buflen, errnop));180 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) {181 free(buf);182 buflen *= 2;183 buf = malloc(buflen);184 if (buf == NULL) {185 *errnop = ENOMEM;186 errno = old_errno;187 return NSS_STATUS_TRYAGAIN;188 }189 goto morebuf;190 }191 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);192 193 if (status == NSS_STATUS_SUCCESS)194 138 status = NSS_STATUS_NOTFOUND; 195 else if (status != NSS_STATUS_TRYAGAIN)139 } else if (status != NSS_STATUS_TRYAGAIN) { 196 140 status = NSS_STATUS_SUCCESS; 197 198 free(buf); 141 } 142 199 143 return status; 200 144 } 201 145 202 203 static service_user *pwent_nip = NULL; 146 enum nss_status 147 get_nonlocal_passwd(const char *name, struct passwd *pwd, char **buffer, 148 int *errnop) 149 { 150 enum nss_status status; 151 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); 152 const struct walk_nss w = { 153 .lookup = __nss_passwd_nonlocal_lookup, .fct_name = "getpwnam_r", 154 .status = &status, .errnop = errnop, .buf = buffer, .buflen = &buflen 155 }; 156 const __typeof__(&_nss_nonlocal_getpwnam_r) self = NULL; 157 #define args (name, pwd, *buffer, buflen, errnop) 158 #include "walk_nss.h" 159 #undef args 160 return status; 161 } 162 163 164 static service_user *pwent_startp, *pwent_nip; 204 165 static void *pwent_fct_start; 205 166 static union { … … 213 174 _nss_nonlocal_setpwent(int stayopen) 214 175 { 215 static const char *fct_name = "setpwent"; 216 static void *fct_start = NULL; 217 enum nss_status status; 218 service_user *nip; 219 union { 220 enum nss_status (*l)(int stayopen); 221 void *ptr; 222 } fct; 223 224 nip = nss_passwd_nonlocal_database(); 225 if (nip == NULL) 226 return NSS_STATUS_UNAVAIL; 227 if (fct_start == NULL) 228 fct_start = __nss_lookup_function(nip, fct_name); 229 fct.ptr = fct_start; 230 do { 231 if (fct.ptr == NULL) 232 status = NSS_STATUS_UNAVAIL; 233 else 234 status = DL_CALL_FCT(fct.l, (stayopen)); 235 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 236 if (status != NSS_STATUS_SUCCESS) 237 return status; 238 239 pwent_nip = nip; 176 enum nss_status status; 177 const struct walk_nss w = { 178 .lookup = &__nss_passwd_nonlocal_lookup, .fct_name = "setpwent", 179 .status = &status 180 }; 181 const __typeof__(&_nss_nonlocal_setpwent) self = NULL; 182 #define args (stayopen) 183 #include "walk_nss.h" 184 #undef args 185 if (status != NSS_STATUS_SUCCESS) 186 return status; 187 240 188 if (pwent_fct_start == NULL) 241 pwent_fct_start = __nss_lookup_function(nip, pwent_fct_name); 189 __nss_passwd_nonlocal_lookup(&pwent_startp, pwent_fct_name, 190 &pwent_fct_start); 191 pwent_nip = pwent_startp; 242 192 pwent_fct.ptr = pwent_fct_start; 243 193 return NSS_STATUS_SUCCESS; … … 247 197 _nss_nonlocal_endpwent(void) 248 198 { 249 static const char *fct_name = "endpwent"; 250 static void *fct_start = NULL; 251 enum nss_status status; 252 service_user *nip; 253 union { 254 enum nss_status (*l)(void); 255 void *ptr; 256 } fct; 199 enum nss_status status; 200 const struct walk_nss w = { 201 .lookup = &__nss_passwd_nonlocal_lookup, .fct_name = "endpwent", 202 .status = &status 203 }; 204 const __typeof__(&_nss_nonlocal_endpwent) self = NULL; 257 205 258 206 pwent_nip = NULL; 259 207 260 nip = nss_passwd_nonlocal_database(); 261 if (nip == NULL) 262 return NSS_STATUS_UNAVAIL; 263 if (fct_start == NULL) 264 fct_start = __nss_lookup_function(nip, fct_name); 265 fct.ptr = fct_start; 266 do { 267 if (fct.ptr == NULL) 268 status = NSS_STATUS_UNAVAIL; 269 else 270 status = DL_CALL_FCT(fct.l, ()); 271 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 208 #define args () 209 #include "walk_nss.h" 210 #undef args 272 211 return status; 273 212 } … … 314 253 char *buffer, size_t buflen, int *errnop) 315 254 { 316 static const char *fct_name = "getpwnam_r"; 317 static void *fct_start = NULL; 318 enum nss_status status; 319 service_user *nip; 320 union { 321 enum nss_status (*l)(const char *name, struct passwd *pwd, 322 char *buffer, size_t buflen, int *errnop); 323 void *ptr; 324 } fct; 255 enum nss_status status; 325 256 int group_errno; 257 const struct walk_nss w = { 258 .lookup = __nss_passwd_nonlocal_lookup, .fct_name = "getpwnam_r", 259 .status = &status, .errnop = errnop 260 }; 261 const __typeof__(&_nss_nonlocal_getpwnam_r) self = NULL; 326 262 327 263 char *nonlocal_ignore = getenv(NONLOCAL_IGNORE_ENV); … … 329 265 return NSS_STATUS_UNAVAIL; 330 266 331 nip = nss_passwd_nonlocal_database(); 332 if (nip == NULL) 333 return NSS_STATUS_UNAVAIL; 334 if (fct_start == NULL) 335 fct_start = __nss_lookup_function(nip, fct_name); 336 fct.ptr = fct_start; 337 do { 338 if (fct.ptr == NULL) 339 status = NSS_STATUS_UNAVAIL; 340 else 341 status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop)); 342 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 343 break; 344 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 267 #define args (name, pwd, buffer, buflen, errnop) 268 #include "walk_nss.h" 269 #undef args 345 270 if (status != NSS_STATUS_SUCCESS) 346 271 return status; … … 355 280 return status; 356 281 357 if (check_nonlocal_gid(name, pwd->pw_gid, &group_errno) !=282 if (check_nonlocal_gid(name, NULL, pwd->pw_gid, &group_errno) != 358 283 NSS_STATUS_SUCCESS) 359 284 pwd->pw_gid = 65534 /* nogroup */; … … 365 290 char *buffer, size_t buflen, int *errnop) 366 291 { 367 static const char *fct_name = "getpwuid_r"; 368 static void *fct_start = NULL; 369 enum nss_status status; 370 service_user *nip; 371 union { 372 enum nss_status (*l)(uid_t uid, struct passwd *pwd, 373 char *buffer, size_t buflen, int *errnop); 374 void *ptr; 375 } fct; 292 enum nss_status status; 376 293 int group_errno; 294 const struct walk_nss w = { 295 .lookup = &__nss_passwd_nonlocal_lookup, .fct_name = "getpwuid_r", 296 .status = &status, .errnop = errnop 297 }; 298 const __typeof__(&_nss_nonlocal_getpwuid_r) self = NULL; 377 299 378 300 char *nonlocal_ignore = getenv(NONLOCAL_IGNORE_ENV); … … 380 302 return NSS_STATUS_UNAVAIL; 381 303 382 nip = nss_passwd_nonlocal_database(); 383 if (nip == NULL) 384 return NSS_STATUS_UNAVAIL; 385 if (fct_start == NULL) 386 fct_start = __nss_lookup_function(nip, fct_name); 387 fct.ptr = fct_start; 388 do { 389 if (fct.ptr == NULL) 390 status = NSS_STATUS_UNAVAIL; 391 else 392 status = DL_CALL_FCT(fct.l, (uid, pwd, buffer, buflen, errnop)); 393 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 394 break; 395 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 304 #define args (uid, pwd, buffer, buflen, errnop) 305 #include "walk_nss.h" 306 #undef args 396 307 if (status != NSS_STATUS_SUCCESS) 397 308 return status; … … 406 317 return status; 407 318 408 if (check_nonlocal_gid(pwd->pw_name, pwd->pw_gid, &group_errno) !=319 if (check_nonlocal_gid(pwd->pw_name, NULL, pwd->pw_gid, &group_errno) != 409 320 NSS_STATUS_SUCCESS) 410 321 pwd->pw_gid = 65534 /* nogroup */; -
trunk/server/common/oursrc/nss_nonlocal/nonlocal-shadow.c
r1553 r1825 40 40 41 41 42 static service_user * 43 nss_shadow_nonlocal_database(void) 42 static service_user *__nss_shadow_nonlocal_database; 43 44 static int 45 internal_function 46 __nss_shadow_nonlocal_lookup(service_user **ni, const char *fct_name, 47 void **fctp) 44 48 { 45 static service_user *nip = NULL; 46 if (nip == NULL) 47 __nss_database_lookup("shadow_nonlocal", NULL, "", &nip); 49 if (__nss_shadow_nonlocal_database == NULL 50 && __nss_database_lookup("shadow_nonlocal", NULL, NULL, 51 &__nss_shadow_nonlocal_database) < 0) 52 return -1; 48 53 49 return nip; 54 *ni = __nss_shadow_nonlocal_database; 55 56 *fctp = __nss_lookup_function(*ni, fct_name); 57 return 0; 50 58 } 51 59 52 60 53 static service_user *spent_ nip = NULL;61 static service_user *spent_startp, *spent_nip; 54 62 static void *spent_fct_start; 55 63 static union { … … 63 71 _nss_nonlocal_setspent(int stayopen) 64 72 { 65 static const char *fct_name = "setspent";66 static void *fct_start = NULL;67 73 enum nss_status status; 68 service_user *nip; 69 union { 70 enum nss_status (*l)(int stayopen); 71 void *ptr; 72 } fct; 73 74 nip = nss_shadow_nonlocal_database(); 75 if (nip == NULL) 76 return NSS_STATUS_UNAVAIL; 77 if (fct_start == NULL) 78 fct_start = __nss_lookup_function(nip, fct_name); 79 fct.ptr = fct_start; 80 do { 81 if (fct.ptr == NULL) 82 status = NSS_STATUS_UNAVAIL; 83 else 84 status = DL_CALL_FCT(fct.l, (stayopen)); 85 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 74 const struct walk_nss w = { 75 .lookup = &__nss_shadow_nonlocal_lookup, .fct_name = "setspent", 76 .status = &status 77 }; 78 const __typeof__(&_nss_nonlocal_setspent) self = NULL; 79 #define args (stayopen) 80 #include "walk_nss.h" 81 #undef args 86 82 if (status != NSS_STATUS_SUCCESS) 87 83 return status; 88 84 89 spent_nip = nip;90 85 if (spent_fct_start == NULL) 91 spent_fct_start = __nss_lookup_function(nip, spent_fct_name); 86 __nss_shadow_nonlocal_lookup(&spent_startp, spent_fct_name, 87 &spent_fct_start); 88 spent_nip = spent_startp; 92 89 spent_fct.ptr = spent_fct_start; 93 90 return NSS_STATUS_SUCCESS; … … 97 94 _nss_nonlocal_endspent(void) 98 95 { 99 static const char *fct_name = "endspent";100 static void *fct_start = NULL;101 96 enum nss_status status; 102 service_user *nip;103 union { 104 enum nss_status (*l)(void);105 void *ptr;106 } fct;97 const struct walk_nss w = { 98 .lookup = &__nss_shadow_nonlocal_lookup, .fct_name = "endspent", 99 .status = &status 100 }; 101 const __typeof__(&_nss_nonlocal_endspent) self = NULL; 107 102 108 103 spent_nip = NULL; 109 104 110 nip = nss_shadow_nonlocal_database(); 111 if (nip == NULL) 112 return NSS_STATUS_UNAVAIL; 113 if (fct_start == NULL) 114 fct_start = __nss_lookup_function(nip, fct_name); 115 fct.ptr = fct_start; 116 do { 117 if (fct.ptr == NULL) 118 status = NSS_STATUS_UNAVAIL; 119 else 120 status = DL_CALL_FCT(fct.l, ()); 121 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 105 #define args () 106 #include "walk_nss.h" 107 #undef args 122 108 return status; 123 109 } … … 154 140 char *buffer, size_t buflen, int *errnop) 155 141 { 156 static const char *fct_name = "getspnam_r";157 static void *fct_start = NULL;158 142 enum nss_status status; 159 service_user *nip; 160 union { 161 enum nss_status (*l)(const char *name, struct spwd *pwd, 162 char *buffer, size_t buflen, int *errnop); 163 void *ptr; 164 } fct; 165 166 nip = nss_shadow_nonlocal_database(); 167 if (nip == NULL) 168 return NSS_STATUS_UNAVAIL; 169 if (fct_start == NULL) 170 fct_start = __nss_lookup_function(nip, fct_name); 171 fct.ptr = fct_start; 172 do { 173 if (fct.ptr == NULL) 174 status = NSS_STATUS_UNAVAIL; 175 else 176 status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop)); 177 if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) 178 break; 179 } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0); 143 const struct walk_nss w = { 144 .lookup = __nss_shadow_nonlocal_lookup, .fct_name = "getspnam_r", 145 .status = &status, .errnop = errnop 146 }; 147 const __typeof__(&_nss_nonlocal_getspnam_r) self = NULL; 148 #define args (name, pwd, buffer, buflen, errnop) 149 #include "walk_nss.h" 150 #undef args 180 151 if (status != NSS_STATUS_SUCCESS) 181 152 return status; -
trunk/server/common/oursrc/nss_nonlocal/nonlocal.h
r782 r1825 1 /* 2 * nonlocal.h 3 * common definitions for nss_nonlocal proxy 4 * 5 * Copyright © 2007–2010 Anders Kaseorg <andersk@mit.edu> and Tim 6 * Abbott <tabbott@mit.edu> 7 * 8 * This file is part of nss_nonlocal. 9 * 10 * nss_nonlocal is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public License 12 * as published by the Free Software Foundation; either version 2.1 of 13 * the License, or (at your option) any later version. 14 * 15 * nss_nonlocal is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with nss_nonlocal; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23 * 02110-1301 USA 24 */ 25 1 26 #ifndef NONLOCAL_H 2 27 #define NONLOCAL_H … … 4 29 #include "config.h" 5 30 31 #ifdef HAVE_STDBOOL_H 32 # include <stdbool.h> 33 #else 34 # ifndef HAVE__BOOL 35 # ifdef __cplusplus 36 typedef bool _Bool; 37 # else 38 # define _Bool signed char 39 # endif 40 # endif 41 # define bool _Bool 42 # define false 0 43 # define true 1 44 # define __bool_true_false_are_defined 1 45 #endif 46 47 #include "nsswitch-internal.h" 48 #include <pwd.h> 49 50 struct walk_nss { 51 enum nss_status *status; 52 int (*lookup)(service_user **ni, const char *fct_name, 53 void **fctp) internal_function; 54 const char *fct_name; 55 int *errnop; 56 char **buf; 57 size_t *buflen; 58 }; 59 6 60 enum nss_status check_nonlocal_uid(const char *user, uid_t uid, int *errnop); 7 enum nss_status check_nonlocal_gid(const char *user, gid_t gid, int *errnop); 61 enum nss_status check_nonlocal_gid(const char *user, const char *group, 62 gid_t gid, int *errnop); 8 63 enum nss_status check_nonlocal_user(const char *user, int *errnop); 64 enum nss_status get_nonlocal_passwd(const char *name, struct passwd *pwd, 65 char **buffer, int *errnop); 9 66 10 67 #define NONLOCAL_IGNORE_ENV "NSS_NONLOCAL_IGNORE"
Note: See TracChangeset
for help on using the changeset viewer.