* move pw_scan() from libutil to libc

* add support for YP "master.passwd.by*" (master.passwd in YP, including
  pw_passwd) and "passwd.adjunct.by*" (SunOS `secure' maps (?)), based
  on code in FreeBSD and partially from OpenBSD.
  this is only used if euid == 0.
  with this, the YP "passwd.by*" maps can have `*' in the pw_passwd field.
* use pw_scan() to parse YP "passwd.by*" and "master.passwd.by*" entries

XXX: i didn't test the "passwd.adjunct" support...
This commit is contained in:
lukem 1998-06-08 03:17:59 +00:00
parent 32e5dd1f22
commit 9557a71026
3 changed files with 240 additions and 42 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.90 1998/04/28 17:54:41 fair Exp $
# $NetBSD: Makefile.inc,v 1.91 1998/06/08 03:17:59 lukem Exp $
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
# gen sources
@ -15,7 +15,7 @@ SRCS+= _errno.c alarm.c assert.c basename.c clock.c closedir.c \
getusershell.c __glob13.c glob.c initgroups.c isatty.c \
isctype.c lockf.c nice.c nlist.c nlist_aout.c \
nlist_ecoff.c nlist_elf32.c nlist_elf64.c opendir.c \
pause.c popen.c psignal.c pwcache.c raise.c readdir.c \
pause.c popen.c psignal.c pwcache.c pw_scan.c raise.c readdir.c \
rewinddir.c scandir.c seekdir.c setdomainname.c \
sethostname.c setjmperr.c setmode.c setproctitle.c \
siginterrupt.c siglist.c signal.c signame.c sigsetops.c \

View File

@ -1,4 +1,4 @@
/* $NetBSD: getpwent.c,v 1.25 1998/02/10 03:56:33 mrg Exp $ */
/* $NetBSD: getpwent.c,v 1.26 1998/06/08 03:18:00 lukem Exp $ */
/*
* Copyright (c) 1988, 1993
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
#else
__RCSID("$NetBSD: getpwent.c,v 1.25 1998/02/10 03:56:33 mrg Exp $");
__RCSID("$NetBSD: getpwent.c,v 1.26 1998/06/08 03:18:00 lukem Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -93,6 +93,8 @@ const char __yp_token[] = "__YP!"; /* Let pwd_mkdb pull this in. */
enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_USER, YPMODE_NETGRP };
static enum _ypmode __ypmode;
enum _ypmap { YPMAP_NONE, YPMAP_ADJUNCT, YPMAP_MASTER };
static char *__ypcurrent, *__ypdomain;
static int __ypcurrentlen;
static struct passwd *__ypproto = (struct passwd *)NULL;
@ -104,12 +106,19 @@ static DB *__ypexclude = (DB *)NULL;
static int __has_yppw __P((void));
static int __ypexclude_add __P((const char *));
static int __ypexclude_is __P((const char *));
static int __ypmaptype __P((void));
static void __ypproto_set __P((void));
static int __ypparse __P((struct passwd *, char *));
/* macros for deciding which YP maps to use. */
#define PASSWD_BYNAME (__ypmaptype() == YPMAP_MASTER \
? "master.passwd.byname" : "passwd.byname")
#define PASSWD_BYUID (__ypmaptype() == YPMAP_MASTER \
? "master.passwd.byuid" : "passwd.byuid")
static int
__ypexclude_add(name)
const char *name;
const char *name;
{
DBT key, data;
@ -137,7 +146,7 @@ const char *name;
static int
__ypexclude_is(name)
const char *name;
const char *name;
{
DBT key, data;
@ -232,35 +241,61 @@ __ypproto_set()
}
static int
__ypparse(pw, s)
struct passwd *pw;
char *s;
__ypmaptype()
{
char *bp, *cp, *ep;
unsigned long id;
static int maptype = -1;
int order, r;
/* since this is currently using strsep(), parse it first */
bp = s;
pw->pw_name = strsep(&bp, ":\n");
pw->pw_passwd = strsep(&bp, ":\n");
if (!(cp = strsep(&bp, ":\n")))
if (maptype != -1)
return (maptype);
maptype = YPMAP_NONE;
if (geteuid() != 0)
return (maptype);
if (!__ypdomain) {
if( _yp_check(&__ypdomain) == 0)
return (maptype);
}
r = yp_order(__ypdomain, "master.passwd.byname", &order);
if (r == 0) {
maptype = YPMAP_MASTER;
return (maptype);
}
/*
* NIS+ in YP compat mode doesn't support
* YPPROC_ORDER -- no point in continuing.
*/
if (r == YPERR_YPERR)
return (maptype);
/* master.passwd doesn't exist -- try passwd.adjunct */
if (r == YPERR_MAP) {
r = yp_order(__ypdomain, "passwd.adjunct.byname", &order);
if (r == 0)
maptype = YPMAP_ADJUNCT;
return (maptype);
}
return (maptype);
}
static int
__ypparse(pw, s)
struct passwd *pw;
char *s;
{
static char adjunctpw[YPMAXRECORD + 2];
int flags, maptype;
maptype = __ypmaptype();
flags = _PASSWORD_NOWARN;
if (maptype != YPMAP_MASTER)
flags |= _PASSWORD_OLDFMT;
if (! pw_scan(s, pw, &flags))
return 1;
id = strtoul(cp, &ep, 10);
if (id > UID_MAX || *ep != '\0')
return 1;
pw->pw_uid = (uid_t)id;
if (!(cp = strsep(&bp, ":\n")))
return 1;
id = strtoul(cp, &ep, 10);
if (id > GID_MAX || *ep != '\0')
return 1;
pw->pw_gid = (gid_t)id;
pw->pw_change = 0;
pw->pw_class = "";
pw->pw_gecos = strsep(&bp, ":\n");
pw->pw_dir = strsep(&bp, ":\n");
pw->pw_shell = strsep(&bp, ":\n");
pw->pw_expire = 0;
/* now let the prototype override, if set. */
if(__ypproto != (struct passwd *)NULL) {
@ -279,6 +314,23 @@ char *s;
if(__ypproto->pw_shell != (char *)NULL)
pw->pw_shell = __ypproto->pw_shell;
}
if ((maptype == YPMAP_ADJUNCT) &&
(strstr(pw->pw_passwd, "##") != NULL)) {
char *data, *bp;
int datalen;
if (yp_match(__ypdomain, "passwd.adjunct.byname", pw->pw_name,
strlen(pw->pw_name), &data, &datalen) == 0) {
if (datalen > sizeof(adjunctpw) - 1)
datalen = sizeof(adjunctpw) - 1;
strncpy(adjunctpw, data, datalen);
/* skip name to get password */
if ((bp = strsep(&data, ":")) != NULL &&
(bp = strsep(&data, ":")) != NULL)
pw->pw_passwd = bp;
}
}
return 0;
}
#endif
@ -317,7 +369,7 @@ again:
data = NULL;
if(__ypcurrent) {
key = NULL;
r = yp_next(__ypdomain, "passwd.byname",
r = yp_next(__ypdomain, PASSWD_BYNAME,
__ypcurrent, __ypcurrentlen,
&key, &keylen, &data, &datalen);
free(__ypcurrent);
@ -331,7 +383,7 @@ again:
__ypcurrentlen = keylen;
}
} else {
r = yp_first(__ypdomain, "passwd.byname",
r = yp_first(__ypdomain, PASSWD_BYNAME,
&__ypcurrent, &__ypcurrentlen,
&data, &datalen);
}
@ -355,7 +407,7 @@ again:
}
if(user && *user) {
data = NULL;
r = yp_match(__ypdomain, "passwd.byname",
r = yp_match(__ypdomain, PASSWD_BYNAME,
user, strlen(user),
&data, &datalen);
} else
@ -376,7 +428,7 @@ again:
case YPMODE_USER:
if(name != (char *)NULL) {
data = NULL;
r = yp_match(__ypdomain, "passwd.byname",
r = yp_match(__ypdomain, PASSWD_BYNAME,
name, strlen(name),
&data, &datalen);
__ypmode = YPMODE_NONE;
@ -535,7 +587,7 @@ getpwnam(name)
__ypcurrent = NULL;
}
r = yp_match(__ypdomain,
"passwd.byname",
PASSWD_BYNAME,
name, strlen(name),
&__ypcurrent, &__ypcurrentlen);
if(r != 0) {
@ -561,7 +613,7 @@ pwnam_netgrp:
} else {
if(user && *user) {
r = yp_match(__ypdomain,
"passwd.byname",
PASSWD_BYNAME,
user, strlen(user),
&__ypcurrent,
&__ypcurrentlen);
@ -587,7 +639,7 @@ pwnam_netgrp:
}
user = _pw_passwd.pw_name + 1;
r = yp_match(__ypdomain,
"passwd.byname",
PASSWD_BYNAME,
user, strlen(user),
&__ypcurrent,
&__ypcurrentlen);
@ -720,7 +772,7 @@ getpwuid(uid)
free(__ypcurrent);
__ypcurrent = NULL;
}
r = yp_match(__ypdomain, "passwd.byuid",
r = yp_match(__ypdomain, PASSWD_BYUID,
uidbuf, strlen(uidbuf),
&__ypcurrent, &__ypcurrentlen);
if(r != 0) {
@ -746,7 +798,7 @@ pwuid_netgrp:
} else {
if(user && *user) {
r = yp_match(__ypdomain,
"passwd.byname",
PASSWD_BYNAME,
user, strlen(user),
&__ypcurrent,
&__ypcurrentlen);
@ -772,7 +824,7 @@ pwuid_netgrp:
}
user = _pw_passwd.pw_name + 1;
r = yp_match(__ypdomain,
"passwd.byname",
PASSWD_BYNAME,
user, strlen(user),
&__ypcurrent,
&__ypcurrentlen);

146
lib/libc/gen/pw_scan.c Normal file
View File

@ -0,0 +1,146 @@
/* $NetBSD: pw_scan.c,v 1.1 1998/06/08 03:18:00 lukem Exp $ */
/*
* Copyright (c) 1987, 1993, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: pw_scan.c,v 1.1 1998/06/08 03:18:00 lukem Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <err.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
pw_scan(bp, pw, flags)
char *bp;
struct passwd *pw;
int *flags;
{
unsigned long id;
int root, inflags;
char *p, *sh, *ep;
inflags = 0;
if (flags != (int *)NULL) {
inflags = *flags;
*flags = 0;
}
if (!(pw->pw_name = strsep(&bp, ":"))) /* login */
goto fmt;
root = !strcmp(pw->pw_name, "root");
if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */
goto fmt;
if (!(p = strsep(&bp, ":"))) /* uid */
goto fmt;
id = strtoul(p, &ep, 10);
if (root && id) {
if (!(inflags & _PASSWORD_NOWARN))
warnx("root uid should be 0");
return (0);
}
if (id > UID_MAX || *ep != '\0') {
if (!(inflags & _PASSWORD_NOWARN))
warnx("invalid uid '%s'", p);
return (0);
}
pw->pw_uid = (uid_t)id;
if ((*p == '\0') && (flags != (int *)NULL))
*flags |= _PASSWORD_NOUID;
if (!(p = strsep(&bp, ":"))) /* gid */
goto fmt;
id = strtoul(p, &ep, 10);
if (id > GID_MAX || *ep != '\0') {
if (!(inflags & _PASSWORD_NOWARN))
warnx("invalid gid '%s'", p);
return (0);
}
pw->pw_gid = (gid_t)id;
if ((*p == '\0') && (flags != (int *)NULL))
*flags |= _PASSWORD_NOGID;
if (inflags & _PASSWORD_OLDFMT) {
pw->pw_class = "";
pw->pw_change = 0;
pw->pw_expire = 0;
*flags |= (_PASSWORD_NOCHG | _PASSWORD_NOEXP);
} else {
pw->pw_class = strsep(&bp, ":"); /* class */
if (!(p = strsep(&bp, ":"))) /* change */
goto fmt;
pw->pw_change = atol(p);
if ((*p == '\0') && (flags != (int *)NULL))
*flags |= _PASSWORD_NOCHG;
if (!(p = strsep(&bp, ":"))) /* expire */
goto fmt;
pw->pw_expire = atol(p);
if ((*p == '\0') && (flags != (int *)NULL))
*flags |= _PASSWORD_NOEXP;
}
pw->pw_gecos = strsep(&bp, ":"); /* gecos */
pw->pw_dir = strsep(&bp, ":"); /* directory */
if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */
goto fmt;
p = pw->pw_shell;
if (root && *p) /* empty == /bin/sh */
for (setusershell();;) {
if (!(sh = getusershell())) {
if (!(inflags & _PASSWORD_NOWARN))
warnx("warning, unknown root shell");
break;
}
if (!strcmp(p, sh))
break;
}
if ((p = strsep(&bp, ":"))) { /* too many */
fmt:
if (!(inflags & _PASSWORD_NOWARN))
warnx("corrupted entry");
return (0);
}
return (1);
}