Switch to NetBSD passwd format

Based on work by Vivek Prakash and Gianluca Guida.

See UPDATING about caveats on currently existing accounts.

	. restores netbsd libc pwcache functions
This commit is contained in:
Ben Gras
2011-09-30 10:18:10 +00:00
parent cedeabb357
commit 5c00743626
96 changed files with 10891 additions and 1220 deletions

View File

@@ -3,6 +3,7 @@
.if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no")
LIBC_DIR= nbsd_libc
LIBM_DIR= nbsd_libm
LIBUTIL_DIR= libutil
LIBCOMPAT_DIR= nbsd_libcompat_minix
LIBMINLIB_DIR= nbsd_libminlib
LIBASYN_DIR= nbsd_libasyn
@@ -10,12 +11,13 @@ LIBASYN_DIR= nbsd_libasyn
LIBC_DIR?= libc
LIBM_DIR?= libm
LIBUTIL_DIR?= libminixutil
LIBCOMPAT_DIR?=
LIBMINLIB_DIR?=
LIBASYN_DIR?=
SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \
libedit ${LIBM_DIR} libsys libtimers libminixutil libbz2 libl libhgfs \
libedit ${LIBM_DIR} libsys libtimers ${LIBUTIL_DIR} libbz2 libl libhgfs \
libz libfetch libarchive libvtreefs libaudiodriver libmthread \
libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \
libddekit libminixfs libbdev

View File

@@ -41,7 +41,6 @@ SRCS+= \
bcopy.c \
bzero.c \
configfile.c \
crypt.c \
ctermid.c \
cuserid.c \
dirname.c \
@@ -64,7 +63,6 @@ SRCS+= \
getpagesize.c \
getpass.c \
getprogname.c \
getpwent.c \
getsubopt.c \
getttyent.c \
getw.c \
@@ -85,7 +83,6 @@ SRCS+= \
popen.c \
putenv.c \
putw.c \
pwcache.c \
random.c \
read_tsc.S \
read_tsc_64.c \
@@ -125,3 +122,9 @@ SRCS+= \
vwarnx.c \
warn.c \
warnx.c
# XXX To be removed after full
# XXX switch to NetBSD passwd.
SRCS+= \
getpwent.c \
pwcache.c

View File

@@ -1,115 +0,0 @@
/* crypt() - one-way password encryption function Author: Kees J. Bot
* 7 Feb 1994
* This routine does not encrypt anything, it uses the pwdauth
* program to do the hard work.
*/
#define nil ((void*)0)
#define pipe _pipe
#define fork _fork
#define close _close
#define dup2 _dup2
#define execl _execl
#define read _read
#define _exit __exit
#define write _write
#define waitpid _waitpid
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/wait.h>
/* Set-uid root program to read /etc/shadow or encrypt passwords. */
static char PWDAUTH[] = "/usr/lib/pwdauth";
#define LEN 1024
static void tell(const char *s0, ...)
{
va_list ap;
const char *s;
va_start(ap, s0);
s= s0;
while (s != nil) {
(void) write(2, s, strlen(s));
s= va_arg(ap, const char *);
}
va_end(ap);
}
char *crypt(const char *key, const char *salt)
{
pid_t pid;
int status;
int pfd[2];
static char pwdata[LEN];
char *p= pwdata;
const char *k= key;
const char *s= salt;
int n;
/* Fill pwdata[] with the key and salt. */
while ((*p++ = *k++) != 0) if (p == pwdata+LEN-1) goto fail;
while ((*p++ = *s++) != 0) if (p == pwdata+LEN-0) goto fail;
if (pipe(pfd) < 0) goto fail;
/* Prefill the pipe. */
(void) write(pfd[1], pwdata, p - pwdata);
switch ((pid= fork())) {
case -1:
close(pfd[0]);
close(pfd[1]);
goto fail;
case 0:
/* Connect both input and output to the pipe. */
if (pfd[0] != 0) {
dup2(pfd[0], 0);
close(pfd[0]);
}
if (pfd[1] != 1) {
dup2(pfd[1], 1);
close(pfd[1]);
}
execl(PWDAUTH, PWDAUTH, (char *) nil);
tell("crypt(): ", PWDAUTH, ": ", strerror(errno), "\r\n",
(char *) nil);
/* No pwdauth? Fail! */
(void) read(0, pwdata, LEN);
_exit(1);
}
close(pfd[1]);
status= -1;
while (waitpid(pid, &status, 0) == -1 && errno == EINTR) {}
if (status != 0) {
close(pfd[0]);
goto fail;
}
/* Read and return the result. Check if it contains exactly one
* string.
*/
n= read(pfd[0], pwdata, LEN);
close(pfd[0]);
if (n < 0) goto fail;
p = pwdata + n;
n = 0;
while (p > pwdata) if (*--p == 0) n++;
if (n != 1) goto fail;
return pwdata;
fail:
pwdata[0] = salt[0] ^ 1; /* make result != salt */
pwdata[1] = 0;
return pwdata;
}
/*
* $PchId: crypt.c,v 1.5 1996/04/11 07:46:11 philip Exp $
*/

View File

@@ -17,7 +17,7 @@ SRCS= efun.c getbootfile.c \
passwd.c pw_scan.c pidfile.c pidlock.c pty.c \
raise_default_signal.c \
secure_path.c snprintb.c \
ttyaction.c
ttyaction.c login_cap.c
#disklabel_dkcksum.c disklabel_scan.c \
#if_media.c \
#sockaddr_snprintf.c
@@ -25,7 +25,6 @@ SRCS= efun.c getbootfile.c \
#getmaxpartitions.c
#stat_flags.c
#getrawpartition.c
#login_cap.c
#ttymsg.c
#parsedate.y

View File

@@ -3,5 +3,6 @@
.PATH: ${.CURDIR}/compat
CPPFLAGS+=-I${.CURDIR}/../libc -I${.CURDIR}/../../sys
SRCS+=compat_passwd.c compat_loginx.c compat_login.c compat_parsedate.c \
SRCS+=compat_passwd.c compat_loginx.c compat_parsedate.c \
compat_login_cap.c
# compat_login.c

View File

@@ -417,12 +417,16 @@ static struct {
{ RLIMIT_FSIZE, R_CSIZE, "filesize", },
{ RLIMIT_DATA, R_CSIZE, "datasize", },
{ RLIMIT_STACK, R_CSIZE, "stacksize", },
#ifndef __minix
{ RLIMIT_RSS, R_CSIZE, "memoryuse", },
{ RLIMIT_MEMLOCK, R_CSIZE, "memorylocked", },
{ RLIMIT_NPROC, R_CNUMB, "maxproc", },
#endif
{ RLIMIT_NOFILE, R_CNUMB, "openfiles", },
{ RLIMIT_CORE, R_CSIZE, "coredumpsize", },
#ifdef RLIMIT_SBSIZE
{ RLIMIT_SBSIZE, R_CSIZE, "sbsize", },
#endif
{ -1, 0, 0 }
};
@@ -472,11 +476,13 @@ gsetrl(login_cap_t *lc, int what, const char *name, int type)
return (-1);
}
#ifndef __minix
if (setrlimit(what, &rl)) {
syslog(LOG_ERR, "%s: setting resource limit %s: %m",
lc->lc_class, name);
return (-1);
}
#endif
#undef RCUR
#undef RMAX
return (0);
@@ -570,6 +576,7 @@ setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
if (!lc)
flc = lc = login_getclass(pwd ? pwd->pw_class : NULL);
#define LOGIN_SETLOGIN 0
/*
* Without the pwd entry being passed we cannot set either
* the group or the login. We could complain about it.

View File

@@ -59,6 +59,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
/*
* XXX Undefine the renames of these functions so that we don't
* XXX rename the versions found in the host's <pwd.h> by mistake!
*/
#undef group_from_gid
#undef user_from_uid
#endif
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
@@ -81,6 +91,18 @@ __RCSID("$NetBSD: pwcache.c,v 1.31 2010/03/23 20:28:59 drochner Exp $");
#include <string.h>
#include <unistd.h>
#if HAVE_NBTOOL_CONFIG_H
/* XXX Now, re-apply the renaming that we undid above. */
#define group_from_gid __nbcompat_group_from_gid
#define user_from_uid __nbcompat_user_from_uid
#endif
#ifdef __weak_alias
__weak_alias(user_from_uid,_user_from_uid)
__weak_alias(group_from_gid,_group_from_gid)
__weak_alias(pwcache_groupdb,_pwcache_groupdb)
#endif
#if !HAVE_PWCACHE_USERDB || HAVE_NBTOOL_CONFIG_H
#include "pwcache.h"
@@ -226,6 +248,273 @@ grptb_start(void)
return (0);
}
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
user_from_uid(uid_t uid, int noname)
{
struct passwd *pw;
UIDC *ptr, **pptr;
if ((uidtb == NULL) && (uidtb_start() < 0))
return (NULL);
/*
* see if we have this uid cached
*/
pptr = uidtb + (uid % UID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
/*
* have an entry for this uid
*/
if (!noname || (ptr->valid == VALID))
return (ptr->name);
return (NULL);
}
/*
* No entry for this uid, we will add it
*/
if (!pwopn) {
if (_pwcache_setpassent != NULL)
(*_pwcache_setpassent)(1);
++pwopn;
}
if (ptr == NULL)
*pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
if ((pw = (*_pwcache_getpwuid)(uid)) == NULL) {
/*
* no match for this uid in the local password file
* a string that is the uid in numeric format
*/
if (ptr == NULL)
return (NULL);
ptr->uid = uid;
(void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid);
ptr->valid = INVALID;
if (noname)
return (NULL);
} else {
/*
* there is an entry for this uid in the password file
*/
if (ptr == NULL)
return (pw->pw_name);
ptr->uid = uid;
(void)strlcpy(ptr->name, pw->pw_name, UNMLEN);
ptr->valid = VALID;
}
return (ptr->name);
}
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
group_from_gid(gid_t gid, int noname)
{
struct group *gr;
GIDC *ptr, **pptr;
if ((gidtb == NULL) && (gidtb_start() < 0))
return (NULL);
/*
* see if we have this gid cached
*/
pptr = gidtb + (gid % GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
/*
* have an entry for this gid
*/
if (!noname || (ptr->valid == VALID))
return (ptr->name);
return (NULL);
}
/*
* No entry for this gid, we will add it
*/
if (!gropn) {
if (_pwcache_setgroupent != NULL)
(*_pwcache_setgroupent)(1);
++gropn;
}
if (ptr == NULL)
*pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
if ((gr = (*_pwcache_getgrgid)(gid)) == NULL) {
/*
* no match for this gid in the local group file, put in
* a string that is the gid in numberic format
*/
if (ptr == NULL)
return (NULL);
ptr->gid = gid;
(void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid);
ptr->valid = INVALID;
if (noname)
return (NULL);
} else {
/*
* there is an entry for this group in the group file
*/
if (ptr == NULL)
return (gr->gr_name);
ptr->gid = gid;
(void)strlcpy(ptr->name, gr->gr_name, GNMLEN);
ptr->valid = VALID;
}
return (ptr->name);
}
/*
* uid_from_user()
* caches the uid for a given user name. We use a simple hash table.
* Return
* the uid (if any) for a user name, or a -1 if no match can be found
*/
int
uid_from_user(const char *name, uid_t *uid)
{
struct passwd *pw;
UIDC *ptr, **pptr;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return (-1);
if ((usrtb == NULL) && (usrtb_start() < 0))
return (-1);
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = usrtb + st_hash(name, namelen, UNM_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
if (ptr->valid == INVALID)
return (-1);
*uid = ptr->uid;
return (0);
}
if (!pwopn) {
if (_pwcache_setpassent != NULL)
(*_pwcache_setpassent)(1);
++pwopn;
}
if (ptr == NULL)
*pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching uid
*/
if (ptr == NULL) {
if ((pw = (*_pwcache_getpwnam)(name)) == NULL)
return (-1);
*uid = pw->pw_uid;
return (0);
}
(void)strlcpy(ptr->name, name, UNMLEN);
if ((pw = (*_pwcache_getpwnam)(name)) == NULL) {
ptr->valid = INVALID;
return (-1);
}
ptr->valid = VALID;
*uid = ptr->uid = pw->pw_uid;
return (0);
}
/*
* gid_from_group()
* caches the gid for a given group name. We use a simple hash table.
* Return
* the gid (if any) for a group name, or a -1 if no match can be found
*/
int
gid_from_group(const char *name, gid_t *gid)
{
struct group *gr;
GIDC *ptr, **pptr;
size_t namelen;
/*
* return -1 for mangled names
*/
if (name == NULL || ((namelen = strlen(name)) == 0))
return (-1);
if ((grptb == NULL) && (grptb_start() < 0))
return (-1);
/*
* look up in hash table, if found and valid return the uid,
* if found and invalid, return a -1
*/
pptr = grptb + st_hash(name, namelen, GID_SZ);
ptr = *pptr;
if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
if (ptr->valid == INVALID)
return (-1);
*gid = ptr->gid;
return (0);
}
if (!gropn) {
if (_pwcache_setgroupent != NULL)
(*_pwcache_setgroupent)(1);
++gropn;
}
if (ptr == NULL)
*pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
/*
* no match, look it up, if no match store it as an invalid entry,
* or store the matching gid
*/
if (ptr == NULL) {
if ((gr = (*_pwcache_getgrnam)(name)) == NULL)
return (-1);
*gid = gr->gr_gid;
return (0);
}
(void)strlcpy(ptr->name, name, GNMLEN);
if ((gr = (*_pwcache_getgrnam)(name)) == NULL) {
ptr->valid = INVALID;
return (-1);
}
ptr->valid = VALID;
*gid = ptr->gid = gr->gr_gid;
return (0);
}
#define FLUSHTB(arr, len, fail) \
do { \
if (arr != NULL) { \

View File

@@ -24,11 +24,6 @@ SRCS+= nlist.c
# NetBSD's 'mtab' format.
SRCS+= mtab.c
# Minix legacy passwd format
# These should be removed when we switch to
# NetBSD's 'passwd' db-based format.
SRCS+= getpwent.c
# fttyslot(fd), a Minix-specific extension
SRCS+= fttyslot.c
@@ -36,11 +31,6 @@ SRCS+= fttyslot.c
# Now considered "compat" feature in NetBSD.
SRCS+= cuserid.c
# XXX: hack
# user_from_uid(), uid_from_user()
# group_from_gid(), gid_from_group()
SRCS+= passwd.c
.include "include/Makefile.inc"
.include <bsd.own.mk>

View File

@@ -1,156 +0,0 @@
/* getpwent(), getpwuid(), getpwnam() - password file routines
*
* Author: Kees J. Bot
* 31 Jan 1994
*/
#include <sys/types.h>
#include <compat/pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define arraysize(a) (sizeof(a) / sizeof((a)[0]))
#define arraylimit(a) ((a) + arraysize(a))
static char PASSWD[]= "/etc/passwd"; /* The password file. */
static const char *pwfile; /* Current password file. */
static char buf[1024]; /* Read buffer. */
static char pwline[256]; /* One line from the password file. */
static struct passwd entry; /* Entry to fill and return. */
static int pwfd= -1; /* Filedescriptor to the file. */
static char *bufptr; /* Place in buf. */
static ssize_t buflen= 0; /* Remaining characters in buf. */
static char *lineptr; /* Place in the line. */
void endpwent(void)
/* Close the password file. */
{
if (pwfd >= 0) {
(void) close(pwfd);
pwfd= -1;
buflen= 0;
}
}
int setpwent(void)
/* Open the password file. */
{
if (pwfd >= 0) endpwent();
if (pwfile == NULL) pwfile= PASSWD;
if ((pwfd= open(pwfile, O_RDONLY)) < 0) return -1;
(void) fcntl(pwfd, F_SETFD, fcntl(pwfd, F_GETFD) | FD_CLOEXEC);
return 0;
}
void setpwfile(const char *file)
/* Prepare for reading an alternate password file. */
{
endpwent();
pwfile= file;
}
static int getline(void)
/* Get one line from the password file, return 0 if bad or EOF. */
{
lineptr= pwline;
do {
if (buflen == 0) {
if ((buflen= read(pwfd, buf, sizeof(buf))) <= 0)
return 0;
bufptr= buf;
}
if (lineptr == arraylimit(pwline)) return 0;
buflen--;
} while ((*lineptr++ = *bufptr++) != '\n');
lineptr= pwline;
return 1;
}
static char *scan_colon(void)
/* Scan for a field separator in a line, return the start of the field. */
{
char *field= lineptr;
char *last;
for (;;) {
last= lineptr;
if (*lineptr == 0) return NULL;
if (*lineptr == '\n') break;
if (*lineptr++ == ':') break;
}
*last= 0;
return field;
}
struct passwd *getpwent(void)
/* Read one entry from the password file. */
{
char *p;
/* Open the file if not yet open. */
if (pwfd < 0 && setpwent() < 0) return NULL;
/* Until a good line is read. */
for (;;) {
if (!getline()) return NULL; /* EOF or corrupt. */
if ((entry.pw_name= scan_colon()) == NULL) continue;
if ((entry.pw_passwd= scan_colon()) == NULL) continue;
if ((p= scan_colon()) == NULL) continue;
entry.pw_uid= strtol(p, NULL, 0);
if ((p= scan_colon()) == NULL) continue;
entry.pw_gid= strtol(p, NULL, 0);
if ((entry.pw_gecos= scan_colon()) == NULL) continue;
if ((entry.pw_dir= scan_colon()) == NULL) continue;
if ((entry.pw_shell= scan_colon()) == NULL) continue;
if (*lineptr == 0) return &entry;
}
}
struct passwd *getpwuid(uid_t uid)
/* Return the password file entry belonging to the user-id. */
{
struct passwd *pw;
endpwent();
while ((pw= getpwent()) != NULL && pw->pw_uid != uid) {}
endpwent();
return pw;
}
struct passwd *getpwnam(const char *name)
/* Return the password file entry belonging to the user name. */
{
struct passwd *pw;
endpwent();
while ((pw= getpwent()) != NULL && strcmp(pw->pw_name, name) != 0) {}
endpwent();
return pw;
}
#ifndef L_cuserid
#define L_cuserid 9
#endif
char *getlogin()
{
static char userid[L_cuserid];
struct passwd *pw_entry;
pw_entry = getpwuid(getuid());
if (pw_entry == (struct passwd *)NULL) return((char *)NULL);
strcpy(userid, pw_entry->pw_name);
return(userid);
}

View File

@@ -1,95 +0,0 @@
/*
* grotesque hack to get these functions working.
*/
#include <sys/types.h>
#include <compat/pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
/*
* group_from_gid()
* caches the name (if any) for the gid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
group_from_gid(gid_t gid, int noname)
{
static char buf[16];
struct group *g = getgrgid(gid);
if (g == NULL) {
if (noname) {
return NULL;
} else {
sprintf(buf, "%d", gid);
return buf;
}
}
return g->gr_name;
}
/*
* user_from_uid()
* caches the name (if any) for the uid. If noname clear, we always
* return the stored name (if valid or invalid match).
* We use a simple hash table.
* Return
* Pointer to stored name (or a empty string)
*/
const char *
user_from_uid(uid_t uid, int noname)
{
static char buf[16];
struct passwd *p = getpwuid(uid);
if (p == NULL) {
if (noname) {
return NULL;
} else {
sprintf(buf, "%d", uid);
return buf;
}
}
return p->pw_name;
}
/*
* uid_from_user()
* caches the uid for a given user name. We use a simple hash table.
* Return
* the uid (if any) for a user name, or a -1 if no match can be found
*/
int
uid_from_user(const char *name, uid_t *uid)
{
struct passwd *p = getpwnam(name);
if (p == NULL) {
return -1;
}
*uid = p->pw_uid;
return *uid;
}
/*
* gid_from_group()
* caches the gid for a given group name. We use a simple hash table.
* Return
* the gid (if any) for a group name, or a -1 if no match can be found
*/
int
gid_from_group(const char *name, gid_t *gid)
{
struct group *g = getgrnam(name);
if (g == NULL) {
return -1;
}
*gid = g->gr_gid;
return *gid;
}