/*! @decl mapping(string:string) all(string map) *! *! Returns the whole map as a mapping. *! *! @[map] is the YP-map to search in. This must be the full map name, *! you have to use @tt{passwd.byname@} instead of just @tt{passwd@}. */ static void f_all(INT32 args) { int err, num=0; char *retval, *retkey; int retlen, retkeylen; char *map; struct mapping *res_map; check_all_args(NULL, args, BIT_STRING, 0); map = sp[-1].u.string->str; res_map = allocate_mapping( (this->last_size?this->last_size+2:40) ); if(!(err = yp_first(this->domain, map, &retkey,&retkeylen, &retval,&retlen))) do { push_string(make_shared_binary_string(retkey, retkeylen)); push_string(make_shared_binary_string(retval, retlen)); mapping_insert( res_map, sp-2, sp-1 ); pop_stack(); pop_stack(); err = yp_next(this->domain, map, retkey, retkeylen, &retkey, &retkeylen, &retval, &retlen); num++; } while(!err); if(err != YPERR_NOMORE) { free_mapping( res_map ); YPERROR( err ); } this->last_size = num; pop_n_elems(args); push_mapping( res_map ); }
/*! @decl void map(string map, function(string, string:void) fun) *! *! For each entry in @[map], call the function specified by @[fun]. *! *! @[fun] will get two arguments, the first being the key, and the *! second the value. *! *! @[map] is the YP-map to search in. This must be the full map name. *! eg @tt{passwd.byname@} instead of just @tt{passwd@}. */ static void f_map(INT32 args) { int err; char *retval, *retkey; int retlen, retkeylen; char *map; struct svalue *f = &sp[-1]; check_all_args(NULL, args, BIT_STRING, BIT_FUNCTION|BIT_ARRAY, 0 ); map = sp[-2].u.string->str; if(!(err = yp_first(this->domain,map, &retkey,&retkeylen, &retval, &retlen))) do { push_string(make_shared_binary_string(retkey, retkeylen)); push_string(make_shared_binary_string(retval, retlen)); apply_svalue( f, 2 ); err = yp_next(this->domain, map, retkey, retkeylen, &retkey, &retkeylen, &retval, &retlen); } while(!err); if(err != YPERR_NOMORE) YPERROR( err ); }
VALUE rb_yp_next(VALUE self, VALUE domain, VALUE map, VALUE inkey) { char *key, *val; int keylen, vallen; int res; VALUE vkey, vval; if( domain == Qnil ) { domain = rb_yp_get_default_domain(self); }; res = yp_next(STR2CSTR(domain), STR2CSTR(map), STR2CSTR(inkey), RSTRING(inkey)->len, &key, &keylen, &val, &vallen); rb_yp_check_yperr(res); if( keylen > 0 ) { vkey = rb_tainted_str_new(key, keylen); } else { vkey = Qnil; }; if( vallen > 0 ) { vval = rb_tainted_str_new(val, vallen); } else { vval = Qnil; }; return rb_assoc_new(vkey, vval); };
/** char* get_nis_passwdf(char* usrid) usrid の NIS のパスワードファイル情報を得る. @param userid 調べるユーザ名 @return userid のパスワードファイル情報(パスワードファイルの1行).要 free */ char* get_nis_passwdf(char* usrid) { const char* inmap="passwd.byname"; int ret, keylen, vallen, usrlen; char* domainname; char* key; char* val; char* uname; char* nis; usrlen = strlen(usrid); uname = (char*)malloc(usrlen + 2); if (uname==NULL) return NULL; strncpy(uname, usrid, usrlen); uname[usrlen] = ':'; uname[usrlen+1] = '\0'; yp_get_default_domain(&domainname); ret = yp_first(domainname, inmap, &key, &keylen, &val, &vallen); while(ret==0){ if (!strncmp(val, uname, usrlen+1)) { free(uname); nis = (char*)malloc(strlen(val)+1); if (nis==NULL) return NULL; strncpy(nis, val, strlen(val)+1); return nis; } ret = yp_next(domainname, inmap, key, keylen, &key, &keylen, &val, &vallen); } free(uname); return NULL; }
static enum nss_status internal_nis_getetherent_r (struct ether *eth, char *buffer, size_t buflen) { struct parser_data *data = (void *) buffer; char *domain, *result, *outkey; int len, keylen, parse_res; if (yp_get_default_domain (&domain)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ do { enum nss_status retval; char *p; if (new_start) retval = yperr2nss (yp_first (domain, "ethers.byaddr", &outkey, &keylen, &result, &len)); else retval = yperr2nss ( yp_next (domain, "ethers.byaddr", oldkey, oldkeylen, &outkey, &keylen, &result, &len)); if (retval != NSS_STATUS_SUCCESS) { if (retval == NSS_STATUS_TRYAGAIN) __set_errno (EAGAIN); return retval; } if ((size_t) (len + 1) > buflen) { free (result); __set_errno (ERANGE); return NSS_STATUS_TRYAGAIN; } p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); parse_res = _nss_files_parse_etherent (p, eth, data, buflen); if (!parse_res && errno == ERANGE) return NSS_STATUS_TRYAGAIN; free (oldkey); oldkey = outkey; oldkeylen = keylen; new_start = 0; } while (!parse_res); return NSS_STATUS_SUCCESS; }
/*ARGSUSED*/ static int _nis_initshells(void *rv, void *cb_data, va_list ap) { static char *ypdomain; char *key, *data; char *lastkey; int keylen, datalen; int r; if (sl) sl_free(sl, 1); sl = sl_init(); if (ypdomain == NULL) { switch (yp_get_default_domain(&ypdomain)) { case 0: break; case YPERR_RESRC: return NS_TRYAGAIN; default: return NS_UNAVAIL; } } /* * `key' and `data' point to strings dynamically allocated by * the yp_... functions. * `data' is directly put into the stringlist of shells. */ key = data = NULL; if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen)) return NS_UNAVAIL; do { data[datalen] = '\0'; /* clear trailing \n */ sl_add(sl, data); lastkey = key; r = yp_next(ypdomain, "shells", lastkey, keylen, &key, &keylen, &data, &datalen); free(lastkey); } while (r == 0); if (r == YPERR_NOMORE) { /* * `data' and `key' ought to be NULL - do not try to free them. */ return NS_SUCCESS; } return NS_UNAVAIL; }
static int _getservent_yp(struct servent_data *sed) { char *lastkey, *result; int resultlen; int rv; if (!sed->yp_domain) { if (yp_get_default_domain(&sed->yp_domain)) return (0); } if (!sed->yp_stepping) { free(sed->yp_key); rv = yp_first(sed->yp_domain, "services.byname", &sed->yp_key, &sed->yp_keylen, &result, &resultlen); if (rv) { sed->yp_stepping = 0; return(0); } sed->yp_stepping = 1; } else { lastkey = sed->yp_key; rv = yp_next(sed->yp_domain, "services.byname", sed->yp_key, sed->yp_keylen, &sed->yp_key, &sed->yp_keylen, &result, &resultlen); free(lastkey); if (rv) { sed->yp_stepping = 0; return (0); } } /* getservent() expects lines terminated with \n -- make it happy */ snprintf(sed->line, sizeof sed->line, "%.*s\n", resultlen, result); free(result); return(1); }
static int grscan(int search, gid_t gid, const char *name, struct group *p_gr, struct group_storage *gs, int *foundyp) { char *cp, **m; char *bp, *endp; u_long ul; #ifdef YP char *key, *data; int keylen, datalen; int r; #endif char **members; char *line; int saved_errno; if (gs == NULL) return 0; members = gs->members; line = gs->line; saved_errno = errno; for (;;) { #ifdef YP if (__ypmode) { if (__ypcurrent) { r = yp_next(__ypdomain, "group.byname", __ypcurrent, __ypcurrentlen, &key, &keylen, &data, &datalen); free(__ypcurrent); __ypcurrent = key; __ypcurrentlen = keylen; } else { r = yp_first(__ypdomain, "group.byname", &__ypcurrent, &__ypcurrentlen, &data, &datalen); } if (r) { __ypmode = 0; __ypcurrent = NULL; if (r == YPERR_NOMORE) continue; else return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; goto parse; } #endif if (!fgets(line, sizeof(gs->line), _gr_fp)) { if (feof(_gr_fp) && !ferror(_gr_fp)) errno = saved_errno; return 0; } bp = line; /* skip lines that are too big */ if (!strchr(line, '\n')) { int ch; while ((ch = getc_unlocked(_gr_fp)) != '\n' && ch != EOF) ; continue; } #ifdef YP if (line[0] == '+' || line[0] == '-') { if (__ypdomain == NULL && yp_get_default_domain(&__ypdomain)) goto parse; switch (yp_bind(__ypdomain)) { case 0: break; case YPERR_BADARGS: case YPERR_YPBIND: goto parse; default: return 0; } } if (line[0] == '+') { switch (line[1]) { case ':': case '\0': case '\n': if (foundyp) { *foundyp = 1; errno = saved_errno; return 0; } if (!search) { __ypmode = 1; continue; } if (name) { r = yp_match(__ypdomain, "group.byname", name, strlen(name), &data, &datalen); } else { char buf[20]; snprintf(buf, sizeof buf, "%u", gid); r = yp_match(__ypdomain, "group.bygid", buf, strlen(buf), &data, &datalen); } switch (r) { case 0: break; case YPERR_KEY: continue; default: return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; p_gr->gr_name = strsep(&bp, ":\n"); if (__ypexclude_is(&__ypexhead, p_gr->gr_name)) continue; p_gr->gr_passwd = strsep(&bp, ":\n"); if (!(cp = strsep(&bp, ":\n"))) continue; if (name) { ul = strtoul(cp, &endp, 10); if (*endp != '\0' || endp == cp || ul >= GID_MAX) continue; p_gr->gr_gid = ul; } else p_gr->gr_gid = gid; goto found_it; default: bp = strsep(&bp, ":\n") + 1; if ((search && name && strcmp(bp, name)) || __ypexclude_is(&__ypexhead, bp)) continue; r = yp_match(__ypdomain, "group.byname", bp, strlen(bp), &data, &datalen); switch (r) { case 0: break; case YPERR_KEY: continue; default: return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; } } else if (line[0] == '-') { if (__ypexclude_add(&__ypexhead, strsep(&line, ":\n") + 1)) return 0; if (foundyp) { *foundyp = -1; errno = saved_errno; return 0; } continue; } parse: #endif p_gr->gr_name = strsep(&bp, ":\n"); if (search && name && strcmp(p_gr->gr_name, name)) continue; #ifdef YP if (__ypmode && __ypexclude_is(&__ypexhead, p_gr->gr_name)) continue; #endif p_gr->gr_passwd = strsep(&bp, ":\n"); if (!(cp = strsep(&bp, ":\n"))) continue; ul = strtoul(cp, &endp, 10); if (endp == cp || *endp != '\0' || ul >= GID_MAX) continue; p_gr->gr_gid = ul; if (search && name == NULL && p_gr->gr_gid != gid) continue; #ifdef YP found_it: #endif cp = NULL; if (bp == NULL) continue; for (m = p_gr->gr_mem = members;; bp++) { if (m == &members[MAXGRP - 1]) break; if (*bp == ',') { if (cp) { *bp = '\0'; *m++ = cp; cp = NULL; } } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { if (cp) { *bp = '\0'; *m++ = cp; } break; } else if (cp == NULL) cp = bp; } *m = NULL; errno = saved_errno; return 1; } /* NOTREACHED */ }
static enum nss_status internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen, int *errnop) { struct parser_data *data = (void *) buffer; char *domain, *result, *outkey; int len, keylen, parse_res; if (yp_get_default_domain (&domain)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ do { enum nss_status retval; char *p; if (new_start) retval = yperr2nss (yp_first (domain, "shadow.byname", &outkey, &keylen, &result, &len)); else retval = yperr2nss ( yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey, &keylen, &result, &len)); if (retval != NSS_STATUS_SUCCESS) { if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } if ((size_t) (len + 1) > buflen) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop); if (parse_res == -1) { free (outkey); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } free (oldkey); oldkey = outkey; oldkeylen = keylen; new_start = 0; } while (!parse_res); return NSS_STATUS_SUCCESS; }
struct passwd * getpwent(void) { #ifdef YP static char *name = NULL; char *map; #endif char bf[1 + sizeof(_pw_keynum)]; struct passwd *pw = NULL; DBT key; _THREAD_PRIVATE_MUTEX_LOCK(pw); if (!_pw_db && !__initdb()) goto done; #ifdef YP map = PASSWD_BYNAME; if (__getpwent_has_yppw == -1) __getpwent_has_yppw = __has_yppw(); again: if (__getpwent_has_yppw && (__ypmode != YPMODE_NONE)) { const char *user, *host, *dom; int keylen, datalen, r, s; char *key, *data = NULL; if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) { __ypmode = YPMODE_NONE; goto again; } } switch (__ypmode) { case YPMODE_FULL: if (__ypcurrent) { r = yp_next(__ypdomain, map, __ypcurrent, __ypcurrentlen, &key, &keylen, &data, &datalen); free(__ypcurrent); __ypcurrent = NULL; if (r != 0) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } __ypcurrent = key; __ypcurrentlen = keylen; } else { r = yp_first(__ypdomain, map, &__ypcurrent, &__ypcurrentlen, &data, &datalen); if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_NETGRP: s = getnetgrent(&host, &user, &dom); if (s == 0) { /* end of group */ endnetgrent(); __ypmode = YPMODE_NONE; goto again; } if (user && *user) { r = yp_match(__ypdomain, map, user, strlen(user), &data, &datalen); } else goto again; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { /* * if the netgroup is invalid, keep looking * as there may be valid users later on. */ if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_USER: if (name) { r = yp_match(__ypdomain, map, name, strlen(name), &data, &datalen); __ypmode = YPMODE_NONE; free(name); name = NULL; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); } else { /* XXX */ __ypmode = YPMODE_NONE; goto again; } break; case YPMODE_NONE: /* NOTREACHED */ break; } __ypline[datalen] = '\0'; if (__ypparse(&_pw_passwd, __ypline, __yp_pw_flags)) goto again; pw = &_pw_passwd; goto done; } #endif ++_pw_keynum; bf[0] = _PW_KEYBYNUM; bcopy((char *)&_pw_keynum, &bf[1], sizeof(_pw_keynum)); key.data = (u_char *)bf; key.size = 1 + sizeof(_pw_keynum); if (__hashpw(&key, _pw_string, sizeof _pw_string, &_pw_passwd, &_pw_flags)) { #ifdef YP static long long __yppbuf[_PW_BUF_LEN / sizeof(long long)]; const char *user, *host, *dom; /* if we don't have YP at all, don't bother. */ if (__getpwent_has_yppw) { if (_pw_passwd.pw_name[0] == '+') { /* set the mode */ switch (_pw_passwd.pw_name[1]) { case '\0': __ypmode = YPMODE_FULL; break; case '@': __ypmode = YPMODE_NETGRP; setnetgrent(_pw_passwd.pw_name + 2); break; default: __ypmode = YPMODE_USER; name = strdup(_pw_passwd.pw_name + 1); break; } __ypproto_set(&_pw_passwd, __yppbuf, _pw_flags, &__yp_pw_flags); goto again; } else if (_pw_passwd.pw_name[0] == '-') { /* an attempted exclusion */ switch (_pw_passwd.pw_name[1]) { case '\0': break; case '@': setnetgrent(_pw_passwd.pw_name + 2); while (getnetgrent(&host, &user, &dom)) { if (user && *user) __ypexclude_add(&__ypexhead, user); } endnetgrent(); break; default: __ypexclude_add(&__ypexhead, _pw_passwd.pw_name + 1); break; } goto again; } } #endif pw = &_pw_passwd; goto done; } done: _THREAD_PRIVATE_MUTEX_UNLOCK(pw); return (pw); }
u_int32_t NIS_query(void *c, dsrecord *pattern, dsrecord **list) { agent_private *ap; u_int32_t cat; dsattribute *a; dsdata *k; dsrecord *lastrec; char *map; dsrecord *item = NULL; int match; char *key, *val, *lastkey; int status, keylen, vallen, lastlen; char scratch[4096]; int single_item, stamp; if (c == NULL) return 1; if (pattern == NULL) return 1; if (list == NULL) return 1; *list = NULL; lastrec = NULL; single_item = 0; stamp = 0; ap = (agent_private *)c; k = cstring_to_dsdata(CATEGORY_KEY); a = dsrecord_attribute(pattern, k, SELECT_META_ATTRIBUTE); dsdata_release(k); if (a == NULL) return 1; if (a->count == 0) return 1; cat = atoi(dsdata_to_cstring(a->value[0])); dsattribute_release(a); map = categoryMap[cat]; if (map == NULL) return 1; k = cstring_to_dsdata(STAMP_KEY); a = dsrecord_attribute(pattern, k, SELECT_META_ATTRIBUTE); dsdata_release(k); if (a != NULL) { dsrecord_remove_attribute(pattern, a, SELECT_META_ATTRIBUTE); stamp = 1; } dsattribute_release(a); if (stamp == 1) { item = dsrecord_new(); add_validation(item); *list = item; return 0; } k = cstring_to_dsdata(SINGLE_KEY); a = dsrecord_attribute(pattern, k, SELECT_META_ATTRIBUTE); dsdata_release(k); if (a != NULL) { dsattribute_release(a); single_item = 1; } key = NULL; val = NULL; vallen = 0; lastkey = NULL; syslock_lock(rpcLock); status = yp_first(ap->nis_domain_name, map, &key, &keylen, &val, &vallen); if (status != 0) { syslock_unlock(rpcLock); return 1; } while (status == 0) { switch (cat) { case LUCategoryNetgroup: bcopy(key, scratch, keylen); scratch[keylen] = ' '; bcopy(val, scratch+keylen+1, vallen); scratch[keylen + vallen + 1] = '\0'; break; case LUCategoryAlias: bcopy(key, scratch, keylen); scratch[keylen] = ':'; scratch[keylen + 1] = ' '; bcopy(val, scratch+keylen+2, vallen); scratch[keylen + vallen + 2] = '\0'; break; default: bcopy(val, scratch, vallen); scratch[vallen] = '\0'; } freeString(val); val = NULL; vallen = 0; item = parse(scratch, cat); freeString(lastkey); lastkey = NULL; if (item != NULL) { match = dsrecord_match_select(item, pattern, SELECT_ATTRIBUTE); if (match == 1) { add_validation(item); if (*list == NULL) *list = dsrecord_retain(item); else lastrec->next = dsrecord_retain(item); lastrec = item; if (single_item == 1) { dsrecord_release(item); break; } } dsrecord_release(item); } lastkey = key; lastlen = keylen; status = yp_next(ap->nis_domain_name, map, lastkey, lastlen, &key, &keylen, &val, &vallen); } syslock_unlock(rpcLock); freeString(lastkey); return 0; }
static enum nss_status internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, int *errnop, int *herrnop) { struct parser_data *data = (void *) buffer; char *domain; if (__glibc_unlikely (yp_get_default_domain (&domain))) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ int parse_res; do { char *result; char *outkey; int len; int keylen; int yperr; if (new_start) yperr = yp_first (domain, "networks.byname", &outkey, &keylen, &result, &len); else yperr = yp_next (domain, "networks.byname", oldkey, oldkeylen, &outkey, &keylen, &result, &len); if (__glibc_unlikely (yperr != YPERR_SUCCESS)) { enum nss_status retval = yperr2nss (yperr); if (retval == NSS_STATUS_TRYAGAIN) { *herrnop = NETDB_INTERNAL; *errnop = errno; } return retval; } if (__glibc_unlikely ((size_t) (len + 1) > buflen)) { free (result); *errnop = ERANGE; *herrnop = NETDB_INTERNAL; return NSS_STATUS_TRYAGAIN; } char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop); if (__glibc_unlikely (parse_res == -1)) { free (outkey); *herrnop = NETDB_INTERNAL; *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } free (oldkey); oldkey = outkey; oldkeylen = keylen; new_start = 0; } while (!parse_res); return NSS_STATUS_SUCCESS; }
static int nis_rpcent(void *retval, void *mdata, va_list ap) { char *name; int number; struct rpcent *rpc; char *buffer; size_t bufsize; int *errnop; char **rp; char **aliases; int aliases_size; char *lastkey; char *resultbuf; int resultbuflen; char buf[YPMAXRECORD + 2]; struct nis_state *st; int rv; enum nss_lookup_type how; int no_name_active; how = (enum nss_lookup_type)mdata; switch (how) { case nss_lt_name: name = va_arg(ap, char *); break; case nss_lt_id: number = va_arg(ap, int); break; case nss_lt_all: break; default: return (NS_NOTFOUND); } rpc = va_arg(ap, struct rpcent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); *errnop = nis_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); if (st->domain[0] == '\0') { if (getdomainname(st->domain, sizeof(st->domain)) != 0) { *errnop = errno; return (NS_UNAVAIL); } } no_name_active = 0; do { switch (how) { case nss_lt_name: if (!st->no_name_map) { snprintf(buf, sizeof buf, "%s", name); rv = yp_match(st->domain, "rpc.byname", buf, strlen(buf), &resultbuf, &resultbuflen); switch (rv) { case 0: break; case YPERR_MAP: st->stepping = 0; no_name_active = 1; how = nss_lt_all; rv = NS_NOTFOUND; continue; default: rv = NS_NOTFOUND; goto fin; } } else { st->stepping = 0; no_name_active = 1; how = nss_lt_all; rv = NS_NOTFOUND; continue; } break; case nss_lt_id: snprintf(buf, sizeof buf, "%d", number); if (yp_match(st->domain, "rpc.bynumber", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; goto fin; } break; case nss_lt_all: if (!st->stepping) { rv = yp_first(st->domain, "rpc.bynumber", &st->current, &st->currentlen, &resultbuf, &resultbuflen); if (rv) { rv = NS_NOTFOUND; goto fin; } st->stepping = 1; } else { lastkey = st->current; rv = yp_next(st->domain, "rpc.bynumber", st->current, st->currentlen, &st->current, &st->currentlen, &resultbuf, &resultbuflen); free(lastkey); if (rv) { st->stepping = 0; rv = NS_NOTFOUND; goto fin; } } break; } /* we need a room for additional \n symbol */ if (bufsize <= resultbuflen + 1 + _ALIGNBYTES + sizeof(char *)) { *errnop = ERANGE; rv = NS_RETURN; break; } aliases=(char **)_ALIGN(&buffer[resultbuflen+2]); aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *); if (aliases_size < 1) { *errnop = ERANGE; rv = NS_RETURN; break; } /* * rpcent_unpack expects lines terminated with \n -- make it happy */ memcpy(buffer, resultbuf, resultbuflen); buffer[resultbuflen] = '\n'; buffer[resultbuflen+1] = '\0'; free(resultbuf); if (rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop) != 0) { if (*errnop == 0) rv = NS_NOTFOUND; else rv = NS_RETURN; } else { if ((how == nss_lt_all) && (no_name_active != 0)) { if (strcmp(rpc->r_name, name) == 0) goto done; for (rp = rpc->r_aliases; *rp != NULL; rp++) { if (strcmp(*rp, name) == 0) goto done; } rv = NS_NOTFOUND; continue; done: rv = NS_SUCCESS; } else rv = NS_SUCCESS; } } while (!(rv & NS_TERMINATE) && (how == nss_lt_all)); fin: if ((rv == NS_SUCCESS) && (retval != NULL)) *((struct rpcent **)retval) = rpc; return (rv); }
struct spwd *getspent (void) { #ifdef USE_NIS int nis_1_user = 0; struct spwd *val; char buf[BUFSIZ]; #endif if (NULL == shadow) { setspent (); } #ifdef USE_NIS again: /* * See if we are reading from the local file. */ if (nis_state == native || nis_state == native2) { /* * Get the next entry from the shadow file. Return NULL * right away if there is none. */ val = fgetspent (shadow); if (NULL == val) return 0; /* * If this entry began with a NIS escape character, we have * to see if this is just a single user, or if the entire * map is being asked for. */ if (IS_NISCHAR (val->sp_namp[0])) { if (val->sp_namp[1]) nis_1_user = 1; else nis_state = start; } /* * If this isn't a NIS user and this isn't an escape to go * use a NIS map, it must be a regular local user. */ if (nis_1_user == 0 && nis_state != start) return val; /* * If this is an escape to use an NIS map, switch over to * that bunch of code. */ if (nis_state == start) goto again; /* * NEEDSWORK. Here we substitute pieces-parts of this entry. */ return 0; } else { if (!nis_bound) { if (bind_nis ()) { nis_state = native2; goto again; } } if (nis_state == start) { if (yp_first (nis_domain, "shadow.bynam", &nis_key, &nis_keylen, &nis_val, &nis_vallen)) { nis_state = native2; goto again; } nis_state = middle; } else if (nis_state == middle) { if (yp_next (nis_domain, "shadow.bynam", nis_key, nis_keylen, &nis_key, &nis_keylen, &nis_val, &nis_vallen)) { nis_state = native2; goto again; } } return my_sgetspent (nis_val); } #else return (fgetspent (shadow)); #endif }
static enum nss_status internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen, int *errnop) { /* If we read the entire database at setpwent time we just iterate over the data we have in memory. */ bool batch_read = intern.start != NULL; char *domain = NULL; if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ int parse_res; do { char *result; char *outkey; int len; int keylen; if (batch_read) { struct response_t *bucket; handle_batch_read: bucket = intern.next; if (__builtin_expect (intern.offset >= bucket->size, 0)) { if (bucket->next == NULL) return NSS_STATUS_NOTFOUND; /* We look at all the content in the current bucket. Go on to the next. */ bucket = intern.next = bucket->next; intern.offset = 0; } for (result = &bucket->mem[intern.offset]; isspace (*result); ++result) ++intern.offset; len = strlen (result); } else { int yperr; if (new_start) { /* Maybe we should read the database in one piece. */ if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) && internal_nis_setgrent () == NSS_STATUS_SUCCESS && intern.start != NULL) { batch_read = true; goto handle_batch_read; } yperr = yp_first (domain, "group.byname", &outkey, &keylen, &result, &len); } else yperr = yp_next (domain, "group.byname", oldkey, oldkeylen, &outkey, &keylen, &result, &len); if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { enum nss_status retval = yperr2nss (yperr); if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } } if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { if (!batch_read) free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; if (!batch_read) free (result); parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, errnop); if (__builtin_expect (parse_res == -1, 0)) { if (!batch_read) free (outkey); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } if (batch_read) intern.offset += len + 1; else { free (oldkey); oldkey = outkey; oldkeylen = keylen; new_start = 0; } } while (parse_res < 1); return NSS_STATUS_SUCCESS; }
/* * __grscan_nis * Search NIS for the next desired entry. * If search is zero, return the next entry. * If search is non-zero, look for a specific name (if name != NULL), * or a specific gid (if name == NULL). */ int __grscan_nis(int *retval, struct group *grp, char *buffer, size_t buflen, struct __grstate_nis *state, int search, const char *name, gid_t gid) { const char *map; char *key, *data; int nisr, rv, keylen, datalen; _DIAGASSERT(retval != NULL); _DIAGASSERT(grp != NULL); _DIAGASSERT(buffer != NULL); _DIAGASSERT(state != NULL); /* name is NULL to indicate searching for gid */ *retval = 0; if (state->domain == NULL) { /* only start if NIS not setup */ rv = __grstart_nis(state); if (rv != NS_SUCCESS) return rv; } next_nis_entry: key = NULL; data = NULL; rv = NS_SUCCESS; if (! search) { /* find next entry */ if (state->done) /* exhausted search */ return NS_NOTFOUND; map = "group.byname"; if (state->current) { /* already searching */ nisr = yp_next(state->domain, map, state->current, state->currentlen, &key, &keylen, &data, &datalen); free(state->current); state->current = NULL; switch (nisr) { case 0: state->current = key; state->currentlen = keylen; key = NULL; break; case YPERR_NOMORE: rv = NS_NOTFOUND; state->done = 1; break; default: rv = NS_UNAVAIL; break; } } else { /* new search */ if (yp_first(state->domain, map, &state->current, &state->currentlen, &data, &datalen)) { rv = NS_UNAVAIL; } } } else { /* search for specific item */ if (name) { /* find group name */ snprintf(buffer, buflen, "%s", name); map = "group.byname"; } else { /* find gid */ snprintf(buffer, buflen, "%u", (unsigned int)gid); map = "group.bygid"; } nisr = yp_match(state->domain, map, buffer, (int)strlen(buffer), &data, &datalen); switch (nisr) { case 0: break; case YPERR_KEY: rv = NS_NOTFOUND; break; default: rv = NS_UNAVAIL; break; } } if (rv == NS_SUCCESS) { /* validate data */ data[datalen] = '\0'; /* clear trailing \n */ if (_gr_parse(data, grp, buffer, buflen)) { if (! search) { /* just want this one */ rv = NS_SUCCESS; } else if ((name && strcmp(name, grp->gr_name) == 0) || (!name && gid == grp->gr_gid)) { /* want specific */ rv = NS_SUCCESS; } } else { /* dodgy entry */ if (!search) { /* try again if ! searching */ free(data); goto next_nis_entry; } } } if (rv != NS_SUCCESS && rv != NS_NOTFOUND) *retval = errno; if (key) free(key); if (data) free(data); return rv; }
static int nis_servent(void *retval, void *mdata, va_list ap) { char *resultbuf, *lastkey; int resultbuflen; char buf[YPMAXRECORD + 2]; struct nis_state *st; int rv; enum nss_lookup_type how; char *name; char *proto; int port; struct servent *serv; char *buffer; size_t bufsize; int *errnop; name = NULL; proto = NULL; how = (enum nss_lookup_type)mdata; switch (how) { case nss_lt_name: name = va_arg(ap, char *); proto = va_arg(ap, char *); break; case nss_lt_id: port = va_arg(ap, int); proto = va_arg(ap, char *); break; case nss_lt_all: break; default: return NS_NOTFOUND; }; serv = va_arg(ap, struct servent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); errnop = va_arg(ap, int *); *errnop = nis_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); if (st->yp_domain[0] == '\0') { if (getdomainname(st->yp_domain, sizeof st->yp_domain)) { *errnop = errno; return (NS_UNAVAIL); } } do { switch (how) { case nss_lt_name: snprintf(buf, sizeof(buf), "%s/%s", name, proto); if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; goto fin; } break; case nss_lt_id: snprintf(buf, sizeof(buf), "%d/%s", ntohs(port), proto); /* * We have to be a little flexible * here. Ideally you're supposed to have both * a services.byname and a services.byport * map, but some systems have only * services.byname. FreeBSD cheats a little by * putting the services.byport information in * the same map as services.byname so that * either case will work. We allow for both * possibilities here: if there is no * services.byport map, we try services.byname * instead. */ rv = yp_match(st->yp_domain, "services.byport", buf, strlen(buf), &resultbuf, &resultbuflen); if (rv) { if (rv == YPERR_MAP) { if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; goto fin; } } else { rv = NS_NOTFOUND; goto fin; } } break; case nss_lt_all: if (!st->yp_stepping) { free(st->yp_key); rv = yp_first(st->yp_domain, "services.byname", &st->yp_key, &st->yp_keylen, &resultbuf, &resultbuflen); if (rv) { rv = NS_NOTFOUND; goto fin; } st->yp_stepping = 1; } else { lastkey = st->yp_key; rv = yp_next(st->yp_domain, "services.byname", st->yp_key, st->yp_keylen, &st->yp_key, &st->yp_keylen, &resultbuf, &resultbuflen); free(lastkey); if (rv) { st->yp_stepping = 0; rv = NS_NOTFOUND; goto fin; } } break; }; rv = parse_result(serv, buffer, bufsize, resultbuf, resultbuflen, errnop); free(resultbuf); } while (!(rv & NS_TERMINATE) && how == nss_lt_all); fin: if (rv == NS_SUCCESS && retval != NULL) *(struct servent **)retval = serv; return (rv); }
static enum nss_status internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { /* If we read the entire database at setpwent time we just iterate over the data we have in memory. */ bool batch_read = intern.start != NULL; char *domain = NULL; if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ int parse_res; do { char *result; char *outkey; int len; int keylen; if (batch_read) { struct response_t *bucket; handle_batch_read: bucket = intern.next; if (__glibc_unlikely (intern.offset >= bucket->size)) { if (bucket->next == NULL) return NSS_STATUS_NOTFOUND; /* We look at all the content in the current bucket. Go on to the next. */ bucket = intern.next = bucket->next; intern.offset = 0; } for (result = &bucket->mem[intern.offset]; isspace (*result); ++result) ++intern.offset; len = strlen (result); } else { int yperr; if (new_start) { /* Maybe we should read the database in one piece. */ if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) && internal_nis_setpwent () == NSS_STATUS_SUCCESS && intern.start != NULL) { batch_read = true; goto handle_batch_read; } yperr = yp_first (domain, "passwd.byname", &outkey, &keylen, &result, &len); } else yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen, &outkey, &keylen, &result, &len); if (__glibc_unlikely (yperr != YPERR_SUCCESS)) { enum nss_status retval = yperr2nss (yperr); if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } } /* Check for adjunct style secret passwords. They can be recognized by a password starting with "##". We do not use it if the passwd.adjunct.byname table is supposed to be used as a shadow.byname replacement. */ char *p = strchr (result, ':'); size_t namelen; char *result2; int len2; if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0 && p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && (namelen = p - result, yp_match (domain, "passwd.adjunct.byname", result, namelen, &result2, &len2)) == YPERR_SUCCESS) { /* We found a passwd.adjunct.byname entry. Merge encrypted password therein into original result. */ char *encrypted = strchr (result2, ':'); char *endp; size_t restlen; if (encrypted == NULL || (endp = strchr (++encrypted, ':')) == NULL || (p = strchr (p + 1, ':')) == NULL) { /* Invalid format of the entry. This never should happen unless the data from which the NIS table is generated is wrong. We simply ignore it. */ free (result2); goto non_adjunct; } restlen = len - (p - result); if (__builtin_expect ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen, 0)) { free (result2); free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen), ":", 1), encrypted, endp - encrypted), p, restlen + 1); p = buffer; free (result2); } else { non_adjunct: if (__glibc_unlikely ((size_t) (len + 1) > buflen)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } p = buffer; *((char *) mempcpy (buffer, result, len)) = '\0'; } while (isspace (*p)) ++p; if (!batch_read) free (result); parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen, errnop); if (__glibc_unlikely (parse_res == -1)) { if (!batch_read) free (outkey); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } if (batch_read) intern.offset += len + 1; else { free (oldkey); oldkey = outkey; oldkeylen = keylen; new_start = false; } } while (parse_res < 1); return NSS_STATUS_SUCCESS; }