Beispiel #1
0
/*! @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 );
}
Beispiel #2
0
/*! @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 );
}
Beispiel #3
0
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);
};
Beispiel #4
0
/**
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
/*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;
}
Beispiel #7
0
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);
}
Beispiel #8
0
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 */
}
Beispiel #9
0
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;
}
Beispiel #10
0
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);
}
Beispiel #11
0
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;
}
Beispiel #12
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;
}
Beispiel #13
0
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);
}
Beispiel #14
0
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;
}
Beispiel #16
0
/*
 * __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;
}
Beispiel #17
0
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);
}
Beispiel #18
0
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;
}