Use libutil and libypclnt in chpass for passwd manipulations.
authorPeter Avalos <pavalos@theshell.com>
Sun, 28 Dec 2008 17:40:34 +0000 (12:40 -0500)
committerPeter Avalos <pavalos@theshell.com>
Sat, 3 Jan 2009 16:47:24 +0000 (11:47 -0500)
While I'm here, WARNS and style cleanups.

Obtained-from: FreeBSD

16 files changed:
lib/libutil/Makefile
lib/libutil/libutil.h
lib/libutil/pw_scan.c [deleted file]
usr.bin/chpass/Makefile
usr.bin/chpass/chpass.1
usr.bin/chpass/chpass.c
usr.bin/chpass/chpass.h
usr.bin/chpass/edit.c
usr.bin/chpass/field.c
usr.bin/chpass/pathnames.h [deleted file]
usr.bin/chpass/pw_copy.c [deleted file]
usr.bin/chpass/pw_copy.h [deleted file]
usr.bin/chpass/pw_yp.c [deleted file]
usr.bin/chpass/pw_yp.h [deleted file]
usr.bin/chpass/table.c
usr.bin/chpass/util.c

index b919c04..8228efc 100644 (file)
@@ -10,7 +10,7 @@ SRCS= flopen.c login.c login_tty.c logout.c logwtmp.c pty.c \
        login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
        login_crypt.c _secure_path.c uucplock.c property.c auth.c \
        realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
-       dehumanize_number.c humanize_number.c pw_scan.c pw_util.c
+       dehumanize_number.c humanize_number.c pw_util.c
 INCS=  libutil.h login_cap.h
 WARNS?=        2
 
index f90a60d..e00676c 100644 (file)
@@ -1,6 +1,13 @@
 /*
  * Copyright (c) 1996  Peter Wemm <peter@FreeBSD.org>.
  * All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, is permitted provided that the following conditions
@@ -10,6 +17,9 @@
  * 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. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -30,8 +40,6 @@
 #ifndef _LIBUTIL_H_
 #define        _LIBUTIL_H_
 
-#include <sys/cdefs.h>
-
 #ifdef _PWD_H_
 #define        _PWSCAN_MASTER  0x01
 #define        _PWSCAN_WARN    0x02
@@ -82,7 +90,6 @@ char   *fparseln(FILE *, size_t *, size_t *, const char[3], int);
 #endif
 
 #ifdef _PWD_H_
-int    __pw_scan(char *, struct passwd *, int);
 int    pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw);
 struct passwd *pw_dup(const struct passwd *_pw);
 int    pw_edit(int _notsetuid);
diff --git a/lib/libutil/pw_scan.c b/lib/libutil/pw_scan.c
deleted file mode 100644 (file)
index 5ba6c1f..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- *     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.
- * 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.
- *
- * $FreeBSD: src/lib/libc/gen/pw_scan.c,v 1.25 2004/01/18 21:33:25 charnier Exp $
- * $DragonFly: src/lib/libutil/pw_scan.c,v 1.3 2007/12/30 13:44:33 matthias Exp $
- */
-
-/*
- * This module is used to "verify" password entries by chpass(1) and
- * pwd_mkdb(8).
- */
-
-#include <sys/param.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <libutil.h>
-
-/*
- * Some software assumes that IDs are short.  We should emit warnings
- * for id's which cannot be stored in a short, but we are more liberal
- * by default, warning for IDs greater than USHRT_MAX.
- *
- * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
- * on the existence of PW_SCAN_BIG_IDS in the environment.
- */
-static int     pw_big_ids_warning = -1;
-
-int
-__pw_scan(char *bp, struct passwd *pw, int flags)
-{
-       uid_t id;
-       int root;
-       char *ep, *p, *sh;
-
-       if (pw_big_ids_warning == -1)
-               pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
-
-       pw->pw_fields = 0;
-       if (!(pw->pw_name = strsep(&bp, ":")))          /* login */
-               goto fmt;
-       root = !strcmp(pw->pw_name, "root");
-       if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
-               pw->pw_fields |= _PWF_NAME;
-
-       if (!(pw->pw_passwd = strsep(&bp, ":")))        /* passwd */
-               goto fmt;
-       if (pw->pw_passwd[0])
-               pw->pw_fields |= _PWF_PASSWD;
-
-       if (!(p = strsep(&bp, ":")))                    /* uid */
-               goto fmt;
-       if (p[0])
-               pw->pw_fields |= _PWF_UID;
-       else {
-               if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
-                       if (flags & _PWSCAN_WARN)
-                               warnx("no uid for user %s", pw->pw_name);
-                       return (0);
-               }
-       }
-       id = strtoul(p, &ep, 10);
-       if (errno == ERANGE) {
-               if (flags & _PWSCAN_WARN)
-                       warnx("%s > max uid value (%lu)", p, ULONG_MAX);
-               return (0);
-       }
-       if (*ep != '\0') {
-               if (flags & _PWSCAN_WARN)
-                       warnx("%s uid is incorrect", p);
-               return (0);
-       }
-       if (root && id) {
-               if (flags & _PWSCAN_WARN)
-                       warnx("root uid should be 0");
-               return (0);
-       }
-       if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
-               warnx("%s > recommended max uid value (%u)", p, USHRT_MAX);
-               /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
-       }
-       pw->pw_uid = id;
-
-       if (!(p = strsep(&bp, ":")))                    /* gid */
-               goto fmt;
-       if (p[0])
-               pw->pw_fields |= _PWF_GID;
-       else {
-               if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
-                       if (flags & _PWSCAN_WARN)
-                               warnx("no gid for user %s", pw->pw_name);
-                       return (0);
-               }
-       }
-       id = strtoul(p, &ep, 10);
-       if (errno == ERANGE) {
-               if (flags & _PWSCAN_WARN)
-                       warnx("%s > max gid value (%lu)", p, ULONG_MAX);
-               return (0);
-       }
-       if (*ep != '\0') {
-               if (flags & _PWSCAN_WARN)
-                       warnx("%s gid is incorrect", p);
-               return (0);
-       }
-       if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
-               warnx("%s > recommended max gid value (%u)", p, USHRT_MAX);
-               /* return (0); This should not be fatal! */
-       }
-       pw->pw_gid = id;
-
-       if (flags & _PWSCAN_MASTER ) {
-               if (!(pw->pw_class = strsep(&bp, ":"))) /* class */
-                       goto fmt;
-               if (pw->pw_class[0])
-                       pw->pw_fields |= _PWF_CLASS;
-               
-               if (!(p = strsep(&bp, ":")))            /* change */
-                       goto fmt;
-               if (p[0])
-                       pw->pw_fields |= _PWF_CHANGE;
-               pw->pw_change = atol(p);
-               
-               if (!(p = strsep(&bp, ":")))            /* expire */
-                       goto fmt;
-               if (p[0])
-                       pw->pw_fields |= _PWF_EXPIRE;
-               pw->pw_expire = atol(p);
-       }
-       if (!(pw->pw_gecos = strsep(&bp, ":")))         /* gecos */
-               goto fmt;
-       if (pw->pw_gecos[0])
-               pw->pw_fields |= _PWF_GECOS;
-
-       if (!(pw->pw_dir = strsep(&bp, ":")))           /* directory */
-               goto fmt;
-       if (pw->pw_dir[0])
-               pw->pw_fields |= _PWF_DIR;
-
-       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 (flags & _PWSCAN_WARN)
-                                       warnx("warning, unknown root shell");
-                               break;
-                       }
-                       if (!strcmp(p, sh))
-                               break;
-               }
-               endusershell();
-       }
-       if (p[0])
-               pw->pw_fields |= _PWF_SHELL;
-
-       if ((p = strsep(&bp, ":"))) {                   /* too many */
-fmt:           
-               if (flags & _PWSCAN_WARN)
-                       warnx("corrupted entry");
-               return (0);
-       }
-       return (1);
-}
index 900d150..5d12028 100644 (file)
@@ -1,64 +1,39 @@
 #      @(#)Makefile    8.2 (Berkeley) 4/2/94
-# $FreeBSD: src/usr.bin/chpass/Makefile,v 1.20.2.3 2001/12/19 04:49:11 dd Exp $
+# $FreeBSD: src/usr.bin/chpass/Makefile,v 1.30 2004/12/29 08:13:20 ache Exp $
 # $DragonFly: src/usr.bin/chpass/Makefile,v 1.4 2007/08/27 16:50:52 pavalos Exp $
 
+.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../lib/libc/gen
+
 PROG=  chpass
-SRCS=  chpass.c edit.c field.c pw_copy.c pw_scan.c pw_util.c pw_yp.c \
-       table.c util.c ypxfr_misc.c ${GENSRCS}
-GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c yppasswd_private.h \
-       yppasswd_private_clnt.c yppasswd_private_xdr.c
+SRCS=  chpass.c edit.c field.c pw_scan.c table.c util.c
+BINOWN=        root
 BINMODE=4555
-WARNS?=        0
-.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../usr.sbin/vipw \
-       ${.CURDIR}/../../libexec/ypxfr \
-       ${.CURDIR}/../../usr.sbin/rpc.yppasswdd \
-       ${.CURDIR}/../../lib/libc/gen
-CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../usr.sbin/vipw -I${.CURDIR}/../../lib/libc/gen
+.if !defined(NO_NIS)
+CFLAGS+= -DYP
+.endif
+#Some people need this, uncomment to activate
+#CFLAGS+=-DRESTRICT_FULLNAME_CHANGE
+CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../lib/libc/gen -I.
+
+DPADD= ${LIBCRYPT} ${LIBUTIL}
+LDADD= -lcrypt -lutil
+.if !defined(NO_NIS)
+DPADD+=        ${LIBYPCLNT}
+LDADD+=        -lypclnt
+.endif
+
 LINKS= ${BINDIR}/chpass ${BINDIR}/chfn
 LINKS+=        ${BINDIR}/chpass ${BINDIR}/chsh
+.if !defined(NO_NIS)
 LINKS+=        ${BINDIR}/chpass ${BINDIR}/ypchpass
 LINKS+=        ${BINDIR}/chpass ${BINDIR}/ypchfn
 LINKS+=        ${BINDIR}/chpass ${BINDIR}/ypchsh
+.endif
 
 MLINKS=        chpass.1 chfn.1 chpass.1 chsh.1
+.if !defined(NO_NIS)
 MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1
-
-CFLAGS+=-DYP -I. -I${.CURDIR}/../../libexec/ypxfr \
-       -I${.CURDIR}/../../usr.sbin/rpc.yppasswdd -Dyp_error=warnx
-
-#Some people need this, uncomment to activate
-#CFLAGS+=-DRESTRICT_FULLNAME_CHANGE
-
-DPADD= ${LIBRPCSVC} ${LIBCRYPT} ${LIBMD}
-LDADD+=        -lrpcsvc -lcrypt -lmd
-
-CLEANFILES= ${GENSRCS}
-
-RPCGEN= rpcgen -C
-RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x
-RPCSRC_PW= ${DESTDIR}/usr/include/rpcsvc/yppasswd.x
-RPCSRC_PRIV= ${.CURDIR}/../../usr.sbin/rpc.yppasswdd/yppasswd_private.x
-
-yp.h: ${RPCSRC}
-       ${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
-
-yp_clnt.c: ${RPCSRC}
-       ${RPCGEN} -l -o ${.TARGET} ${RPCSRC}
-
-yppasswd.h: ${RPCSRC_PW}
-       ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PW}
-
-yppasswd_clnt.c: ${RPCSRC_PW}
-       ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PW}
-
-yppasswd_private.h: ${RPCSRC_PRIV}
-       ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV}
-
-yppasswd_private_xdr.c: ${RPCSRC_PRIV}
-       ${RPCGEN} -c -o ${.TARGET} ${RPCSRC_PRIV}
-
-yppasswd_private_clnt.c: ${RPCSRC_PRIV}
-       ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PRIV}
+.endif
 
 beforeinstall:
 .for i in chpass chfn chsh ypchpass ypchfn ypchsh
index 90d4d21..8cd7fda 100644 (file)
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)chpass.1   8.2 (Berkeley) 12/30/93
-.\" $FreeBSD: src/usr.bin/chpass/chpass.1,v 1.23.2.10 2003/02/24 23:04:38 trhodes Exp $
+.\" $FreeBSD: src/usr.bin/chpass/chpass.1,v 1.39 2005/08/02 21:38:02 seanc Exp $
 .\" $DragonFly: src/usr.bin/chpass/chpass.1,v 1.4 2006/02/17 19:38:58 swildner Exp $
 .\"
 .Dd December 30, 1993
@@ -51,7 +51,6 @@
 .Op Fl e Ar expiretime
 .Op Fl s Ar newshell
 .Op user
-.Pp
 .Nm
 .Op Fl oly
 .Op Fl a Ar list
@@ -164,7 +163,8 @@ Both of these fields should be unique across the system (and often
 across a group of systems) as they control file access.
 .Pp
 While it is possible to have multiple entries with identical login names
-and/or identical user id's, it is usually a mistake to do so.  Routines
+and/or identical user id's, it is usually a mistake to do so.
+Routines
 that manipulate these files will often return only one of the multiple
 entries, and that one by random selection.
 .Pp
@@ -216,7 +216,7 @@ and
 numbers and finally
 .Ar other information
 which is a single comma delimited string to represent any additional
-gcos fields (typically used for site specific user information).
+gecos fields (typically used for site specific user information).
 Note that
 .Xr finger 1
 will display the office location and office phone together under the
@@ -395,7 +395,7 @@ is compiled with NIS support:
 Force
 .Nm
 to modify the local copy of a user's password
-information in the even that a user exists in both
+information in the event that a user exists in both
 the local and NIS databases.
 .It Fl y
 Opposite effect of
@@ -450,7 +450,8 @@ When invoked by the super-user on the NIS master server,
 allows unrestricted changes to the NIS passwd maps using dedicated,
 non-RPC-based mechanism (in this case, a
 .Ux
-domain socket). The
+domain socket).
+The
 .Fl o
 flag can be used to force
 .Nm
@@ -476,6 +477,7 @@ the list of approved shells
 .Xr getusershell 3 ,
 .Xr login.conf 5 ,
 .Xr passwd 5 ,
+.Xr pw 8 ,
 .Xr pwd_mkdb 8 ,
 .Xr vipw 8
 .Rs
index e861a85..658ef33 100644 (file)
@@ -1,6 +1,13 @@
 /*-
  * Copyright (c) 1988, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * @(#) Copyright (c) 1988, 1993, 1994 The Regents of the University of California.  All rights reserved.
  * @(#)chpass.c        8.4 (Berkeley) 4/2/94
- * $FreeBSD: src/usr.bin/chpass/chpass.c,v 1.16.2.4 2002/08/11 14:16:42 dwmalone Exp $
+ * $FreeBSD: src/usr.bin/chpass/chpass.c,v 1.28 2006/09/25 15:06:24 marck Exp $
  * $DragonFly: src/usr.bin/chpass/chpass.c,v 1.4 2003/11/03 19:31:28 eirikn Exp $
  */
 
 #include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/signal.h>
-#include <sys/time.h>
-#include <sys/resource.h>
 
-#include <ctype.h>
 #include <err.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
-#include <pw_scan.h>
-#include <pw_util.h>
-#include "pw_copy.h"
 #ifdef YP
-#include <rpcsvc/yp.h>
-int yp_errno = YP_TRUE;
-#include "pw_yp.h"
+#include <ypclnt.h>
 #endif
 
+#include <pw_scan.h>
+#include <libutil.h>
+
 #include "chpass.h"
-#include "pathnames.h"
 
-char *tempname;
-uid_t uid;
+int master_mode;
 
-void   baduser(void);
-void   usage(void);
+static void    baduser(void);
+static void    usage(void);
 
 int
 main(int argc, char **argv)
 {
        enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op;
-       struct passwd *pw = NULL, lpw, old_pw, *pold_pw;
-       char *username = NULL;
+       struct passwd lpw, *old_pw, *pw;
        int ch, pfd, tfd;
+       const char *password;
        char *arg = NULL;
+       uid_t uid;
 #ifdef YP
-       int force_local = 0;
-       int force_yp = 0;
+       struct ypclnt *ypclnt;
+       const char *yp_domain = NULL, *yp_host = NULL;
 #endif
 
+       pw = old_pw = NULL;
        op = EDITENTRY;
 #ifdef YP
-       while ((ch = getopt(argc, argv, "a:p:s:e:d:h:oly")) != -1)
+       while ((ch = getopt(argc, argv, "a:p:s:e:d:h:loy")) != -1)
 #else
        while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1)
 #endif
-               switch(ch) {
+               switch (ch) {
                case 'a':
                        op = LOADENTRY;
                        arg = optarg;
@@ -107,188 +105,189 @@ main(int argc, char **argv)
                        arg = optarg;
                        break;
 #ifdef YP
-               case 'h':
-#ifdef PARANOID
-                       if (getuid()) {
-                               warnx("Only the superuser can use the -h flag");
-                       } else {
-#endif
-                               yp_server = optarg;
-#ifdef PARANOID
-                       }
-#endif
-                       break;
                case 'd':
-#ifdef PARANOID
-                       if (getuid()) {
-                               warnx("Only the superuser can use the -d flag");
-                       } else {
-#endif
-                               yp_domain = optarg;
-                               if (yp_server == NULL)
-                                       yp_server = "localhost";
-#ifdef PARANOID
-                       }
-#endif
-                       break;
-               case 'l':
-                       _use_yp = 0;
-                       force_local = 1;
+                       yp_domain = optarg;
                        break;
-               case 'y':
-                       _use_yp = force_yp = 1;
+               case 'h':
+                       yp_host = optarg;
                        break;
+               case 'l':
                case 'o':
-                       force_old++;
+               case 'y':
+                       /* compatibility */
                        break;
 #endif
                case '?':
                default:
                        usage();
                }
+
        argc -= optind;
        argv += optind;
 
+       if (argc > 1)
+               usage();
+
        uid = getuid();
 
        if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) {
-               switch(argc) {
-#ifdef YP
-               case 0:
-                       GETPWUID(uid)
-                       get_yp_master(1); /* XXX just to set the suser flag */
-                       break;
-               case 1:
-                       GETPWNAM(*argv)
-                       get_yp_master(1); /* XXX just to set the suser flag */
-#else
-               case 0:
-                       if (!(pw = getpwuid(uid)))
+               if (argc == 0) {
+                       if ((pw = getpwuid(uid)) == NULL)
                                errx(1, "unknown user: uid %lu",
                                    (unsigned long)uid);
-                       break;
-               case 1:
-                       if (!(pw = getpwnam(*argv)))
+               } else {
+                       if ((pw = getpwnam(*argv)) == NULL)
                                errx(1, "unknown user: %s", *argv);
-#endif
-                       if (uid && uid != pw->pw_uid)
+                       if (uid != 0 && uid != pw->pw_uid)
                                baduser();
-                       break;
-               default:
-                       usage();
                }
 
                /* Make a copy for later verification */
-               old_pw = *pw;
-               old_pw.pw_gecos = strdup(old_pw.pw_gecos);
-               pold_pw = &old_pw;
+               if ((pw = pw_dup(pw)) == NULL ||
+                   (old_pw = pw_dup(pw)) == NULL)
+                       err(1, "pw_dup");
        }
 
+#ifdef YP
+       if (pw != NULL && (pw->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
+               ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+               master_mode = (ypclnt != NULL &&
+                   ypclnt_connect(ypclnt) != -1 &&
+                   ypclnt_havepasswdd(ypclnt) == 1);
+               ypclnt_free(ypclnt);
+       } else
+#endif
+       master_mode = (uid == 0);
+
        if (op == NEWSH) {
                /* protect p_shell -- it thinks NULL is /bin/sh */
                if (!arg[0])
                        usage();
-               if (p_shell(arg, pw, (ENTRY *)NULL))
-                       pw_error((char *)NULL, 0, 1);
+               if (p_shell(arg, pw, (ENTRY *)NULL) == -1)
+                       exit(1);
        }
 
        if (op == NEWEXP) {
                if (uid)        /* only root can change expire */
                        baduser();
-               if (p_expire(arg, pw, (ENTRY *)NULL))
-                       pw_error((char *)NULL, 0, 1);
+               if (p_expire(arg, pw, (ENTRY *)NULL) == -1)
+                       exit(1);
        }
 
        if (op == LOADENTRY) {
                if (uid)
                        baduser();
                pw = &lpw;
+               old_pw = NULL;
                if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER))
                        exit(1);
-               if ((pold_pw = getpwnam(pw->pw_name)) != NULL) {
-                       old_pw = *pold_pw;
-                       old_pw.pw_gecos = strdup(old_pw.pw_gecos);
-               }
        }
-       username = pw->pw_name;
 
        if (op == NEWPW) {
                if (uid)
                        baduser();
 
-               if(strchr(arg, ':')) {
+               if (strchr(arg, ':'))
                        errx(1, "invalid format for password");
-               }
                pw->pw_passwd = arg;
        }
 
-       /*
-        * The temporary file/file descriptor usage is a little tricky here.
-        * 1:   We start off with two fd's, one for the master password
-        *      file (used to lock everything), and one for a temporary file.
-        * 2:   Display() gets an fp for the temporary file, and copies the
-        *      user's information into it.  It then gives the temporary file
-        *      to the user and closes the fp, closing the underlying fd.
-        * 3:   The user edits the temporary file some number of times.
-        * 4:   Verify() gets an fp for the temporary file, and verifies the
-        *      contents.  It can't use an fp derived from the step #2 fd,
-        *      because the user's editor may have created a new instance of
-        *      the file.  Once the file is verified, its contents are stored
-        *      in a password structure.  The verify routine closes the fp,
-        *      closing the underlying fd.
-        * 5:   Delete the temporary file.
-        * 6:   Get a new temporary file/fd.  Pw_copy() gets an fp for it
-        *      file and copies the master password file into it, replacing
-        *      the user record with a new one.  We can't use the first
-        *      temporary file for this because it was owned by the user.
-        *      Pw_copy() closes its fp, flushing the data and closing the
-        *      underlying file descriptor.  We can't close the master
-        *      password fp, or we'd lose the lock.
-        * 7:   Call pw_mkdb() (which renames the temporary file) and exit.
-        *      The exit closes the master passwd fp/fd.
-        */
-       pw_init();
-       tfd = pw_tmp();
-
        if (op == EDITENTRY) {
-               display(tfd, pw);
-               edit(pw);
-               (void)unlink(tempname);
-               tfd = pw_tmp();
+               /*
+                * We don't really need pw_*() here, but pw_edit() (used
+                * by edit()) is just too useful...
+                */
+               if (pw_init(NULL, NULL))
+                       err(1, "pw_init()");
+               if ((tfd = pw_tmp(-1)) == -1) {
+                       pw_fini();
+                       err(1, "pw_tmp()");
+               }
+               free(pw);
+               pw = edit(pw_tempname(), old_pw);
+               pw_fini();
+               if (pw == NULL)
+                       err(1, "edit()");
+               /*
+                * pw_equal does not check for crypted passwords, so we
+                * should do it explicitly
+                */
+               if (pw_equal(old_pw, pw) &&
+                   strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0)
+                       errx(0, "user information unchanged");
        }
 
-#ifdef YP
-       if (_use_yp) {
-               yp_submit(pw);
-               (void)unlink(tempname);
+       if (old_pw && !master_mode) {
+               password = getpass("Password: ");
+               if (strcmp(crypt(password, old_pw->pw_passwd),
+                   old_pw->pw_passwd) != 0)
+                       baduser();
        } else {
-#endif /* YP */
-       pfd = pw_lock();
-       pw_copy(pfd, tfd, pw, pold_pw);
+               password = "";
+       }
 
-       if (!pw_mkdb(username))
-               pw_error((char *)NULL, 0, 1);
+       if (old_pw != NULL)
+               pw->pw_fields |= (old_pw->pw_fields & _PWF_SOURCE);
+       switch (pw->pw_fields & _PWF_SOURCE) {
 #ifdef YP
-       }
+       case _PWF_NIS:
+               ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+               if (ypclnt == NULL ||
+                   ypclnt_connect(ypclnt) == -1 ||
+                   ypclnt_passwd(ypclnt, pw, password) == -1) {
+                       warnx("%s", ypclnt->error);
+                       ypclnt_free(ypclnt);
+                       exit(1);
+               }
+               ypclnt_free(ypclnt);
+               errx(0, "NIS user information updated");
 #endif /* YP */
-       exit(0);
+       case 0:
+       case _PWF_FILES:
+               if (pw_init(NULL, NULL))
+                       err(1, "pw_init()");
+               if ((pfd = pw_lock()) == -1) {
+                       pw_fini();
+                       err(1, "pw_lock()");
+               }
+               if ((tfd = pw_tmp(-1)) == -1) {
+                       pw_fini();
+                       err(1, "pw_tmp()");
+               }
+               if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
+                       pw_fini();
+                       err(1, "pw_copy");
+               }
+               if (pw_mkdb(pw->pw_name) == -1) {
+                       pw_fini();
+                       err(1, "pw_mkdb()");
+               }
+               pw_fini();
+               errx(0, "user information updated");
+               break;
+       default:
+               errx(1, "unsupported passwd source");
+       }
 }
 
-void
+static void
 baduser(void)
 {
+
        errx(1, "%s", strerror(EACCES));
 }
 
-void
+static void
 usage(void)
 {
 
-       (void)fprintf(stderr,
+       fprintf(stderr,
+           "usage: chpass%s %s [user]\n",
 #ifdef YP
-               "usage: chpass [-o] [-l] [-y] [-d domain] [-h host] [-a list] [-p encpass] [-s shell] [-e mmm dd yy] [user]\n");
+           " [-d domain] [-h host]",
 #else
-               "usage: chpass [-a list] [-p encpass] [-s shell] [-e mmm dd yy] [user]\n");
+           "",
 #endif
+           "[-a list] [-p encpass] [-s shell] [-e mmm dd yy]");
        exit(1);
 }
index 0a9f4df..7e74cf0 100644 (file)
@@ -1,6 +1,13 @@
 /*
  * Copyright (c) 1988, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  *
  *     @(#)chpass.h    8.4 (Berkeley) 4/2/94
+ * $FreeBSD: src/usr.bin/chpass/chpass.h,v 1.7 2004/01/18 21:46:39 charnier Exp $
  * $DragonFly: src/usr.bin/chpass/chpass.h,v 1.3 2003/11/03 19:31:28 eirikn Exp $
  */
 
 struct passwd;
 
 typedef struct _entry {
-       char *prompt;
-       int (*func)(), restricted, len;
+       const char *prompt;
+       int (*func)(char *, struct passwd *, struct _entry *);
+       int restricted;
+       size_t len;
        char *except, *save;
 } ENTRY;
 
@@ -51,12 +61,12 @@ typedef struct _entry {
 #define        E_SHELL         13
 
 extern ENTRY list[];
-extern uid_t uid;
+extern int master_mode;
 
 int     atot(char *, time_t *);
-void    display(int, struct passwd *);
-void    edit(struct passwd *);
-char    *ok_shell(char *);
+struct passwd *edit(const char *, struct passwd *);
+int     ok_shell(char *);
+char   *dup_shell(char *);
 int     p_change(char *, struct passwd *, ENTRY *);
 int     p_class(char *, struct passwd *, ENTRY *);
 int     p_expire(char *, struct passwd *, ENTRY *);
@@ -64,9 +74,7 @@ int    p_gecos(char *, struct passwd *, ENTRY *);
 int     p_gid(char *, struct passwd *, ENTRY *);
 int     p_hdir(char *, struct passwd *, ENTRY *);
 int     p_login(char *, struct passwd *, ENTRY *);
-int     p_login(char *, struct passwd *, ENTRY *);
 int     p_passwd(char *, struct passwd *, ENTRY *);
 int     p_shell(char *, struct passwd *, ENTRY *);
 int     p_uid(char *, struct passwd *, ENTRY *);
-char    *ttoa(time_t);
-int     verify(struct passwd *);
+char   *ttoa(time_t);
index 44a5940..d1ef633 100644 (file)
@@ -1,6 +1,13 @@
 /*-
  * Copyright (c) 1990, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/chpass/edit.c,v 1.16.2.2 2001/08/02 01:48:22 obrien Exp $
- * $DragonFly: src/usr.bin/chpass/edit.c,v 1.3 2003/10/02 17:42:26 hmp Exp $
- *
  * @(#)edit.c  8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/usr.bin/chpass/edit.c,v 1.23 2003/04/09 18:18:42 des Exp $
+ * $DragonFly: src/usr.bin/chpass/edit.c,v 1.3 2003/10/02 17:42:26 hmp Exp $
  */
 
 #include <sys/param.h>
@@ -42,7 +48,6 @@
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
-#include <md5.h>
 #include <paths.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <unistd.h>
 
 #include <pw_scan.h>
-#include <pw_util.h>
+#include <libutil.h>
 
 #include "chpass.h"
-#ifdef YP
-#include "pw_yp.h"
-#endif /* YP */
 
-extern char *tempname;
+static int display(const char *tfn, struct passwd *pw);
+static struct passwd *verify(const char *tfn, struct passwd *pw);
 
-void
-edit(struct passwd *pw)
+struct passwd *
+edit(const char *tfn, struct passwd *pw)
 {
-       struct stat begin, end;
-       char *begin_sum, *end_sum;
+       struct passwd *npw;
+       char *line;
+       size_t len;
 
+       if (display(tfn, pw) == -1)
+               return (NULL);
        for (;;) {
-               if (stat(tempname, &begin))
-                       pw_error(tempname, 1, 1);
-               begin_sum = MD5File(tempname, (char *)NULL);
-               pw_edit(1);
-               if (stat(tempname, &end))
-                       pw_error(tempname, 1, 1);
-               end_sum = MD5File(tempname, (char *)NULL);
-               if ((begin.st_mtime == end.st_mtime) &&
-                   (strcmp(begin_sum, end_sum) == 0)) {
-                       warnx("no changes made");
-                       pw_error(NULL, 0, 0);
-               }
-               free(begin_sum);
-               free(end_sum);
-               if (verify(pw))
+               switch (pw_edit(1)) {
+               case -1:
+                       return (NULL);
+               case 0:
+                       return (pw_dup(pw));
+               default:
                        break;
-               pw_prompt();
+               }
+               if ((npw = verify(tfn, pw)) != NULL)
+                       return (npw);
+               free(npw);
+               printf("re-edit the password file? ");
+               fflush(stdout);
+               if ((line = fgetln(stdin, &len)) == NULL) {
+                       warn("fgetln()");
+                       return (NULL);
+               }
+               if (len > 0 && (*line == 'N' || *line == 'n'))
+                       return (NULL);
        }
 }
 
@@ -92,35 +100,31 @@ edit(struct passwd *pw)
  *     print out the file for the user to edit; strange side-effect:
  *     set conditional flag if the user gets to edit the shell.
  */
-void
-display(int fd, struct passwd *pw)
+static int
+display(const char *tfn, struct passwd *pw)
 {
        FILE *fp;
-       char *bp, *p, *ttoa();
+       char *bp, *gecos, *p;
 
-       if (!(fp = fdopen(fd, "w")))
-               pw_error(tempname, 1, 1);
+       if ((fp = fopen(tfn, "w")) == NULL) {
+               warn("%s", tfn);
+               return (-1);
+       }
 
-       (void)fprintf(fp,
-#ifdef YP
-           "#Changing %s information for %s.\n", _use_yp ? "NIS" : "user database", pw->pw_name);
-       if (!uid && (!_use_yp || suser_override)) {
-#else
-           "#Changing user database information for %s.\n", pw->pw_name);
-       if (!uid) {
-#endif /* YP */
-               (void)fprintf(fp, "Login: %s\n", pw->pw_name);
-               (void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
-               (void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
-               (void)fprintf(fp, "Gid [# or name]: %lu\n",
+       fprintf(fp, "#Changing user information for %s.\n", pw->pw_name);
+       if (master_mode) {
+               fprintf(fp, "Login: %s\n", pw->pw_name);
+               fprintf(fp, "Password: %s\n", pw->pw_passwd);
+               fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
+               fprintf(fp, "Gid [# or name]: %lu\n",
                    (unsigned long)pw->pw_gid);
-               (void)fprintf(fp, "Change [month day year]: %s\n",
+               fprintf(fp, "Change [month day year]: %s\n",
                    ttoa(pw->pw_change));
-               (void)fprintf(fp, "Expire [month day year]: %s\n",
+               fprintf(fp, "Expire [month day year]: %s\n",
                    ttoa(pw->pw_expire));
-               (void)fprintf(fp, "Class: %s\n", pw->pw_class);
-               (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
-               (void)fprintf(fp, "Shell: %s\n",
+               fprintf(fp, "Class: %s\n", pw->pw_class);
+               fprintf(fp, "Home directory: %s\n", pw->pw_dir);
+               fprintf(fp, "Shell: %s\n",
                    *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
        }
        /* Only admin can change "restricted" shells. */
@@ -131,135 +135,156 @@ display(int fd, struct passwd *pw)
                 * necklace, but there's not much else to do.
                 */
 #else
-       else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) || !uid)
+       else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) ||
+           master_mode)
                /*
                 * If change not restrict (table.c) and standard shell
                 *      OR if root, then allow editing of shell.
                 */
 #endif
-               (void)fprintf(fp, "Shell: %s\n",
+               fprintf(fp, "Shell: %s\n",
                    *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
        else
-         list[E_SHELL].restricted = 1;
-       bp = pw->pw_gecos;
+               list[E_SHELL].restricted = 1;
+
+       if ((bp = gecos = strdup(pw->pw_gecos)) == NULL) {
+               warn(NULL);
+               fclose(fp);
+               return (-1);
+       }
 
        p = strsep(&bp, ",");
        p = strdup(p ? p : "");
        list[E_NAME].save = p;
-       if (!list[E_NAME].restricted || !uid)
-         (void)fprintf(fp, "Full Name: %s\n", p);
+       if (!list[E_NAME].restricted || master_mode)
+               fprintf(fp, "Full Name: %s\n", p);
 
-        p = strsep(&bp, ",");
+       p = strsep(&bp, ",");
        p = strdup(p ? p : "");
        list[E_LOCATE].save = p;
-       if (!list[E_LOCATE].restricted || !uid)
-         (void)fprintf(fp, "Office Location: %s\n", p);
+       if (!list[E_LOCATE].restricted || master_mode)
+               fprintf(fp, "Office Location: %s\n", p);
 
-        p = strsep(&bp, ",");
+       p = strsep(&bp, ",");
        p = strdup(p ? p : "");
        list[E_BPHONE].save = p;
-       if (!list[E_BPHONE].restricted || !uid)
-         (void)fprintf(fp, "Office Phone: %s\n", p);
+       if (!list[E_BPHONE].restricted || master_mode)
+               fprintf(fp, "Office Phone: %s\n", p);
 
-        p = strsep(&bp, ",");
+       p = strsep(&bp, ",");
        p = strdup(p ? p : "");
        list[E_HPHONE].save = p;
-       if (!list[E_HPHONE].restricted || !uid)
-         (void)fprintf(fp, "Home Phone: %s\n", p);
+       if (!list[E_HPHONE].restricted || master_mode)
+               fprintf(fp, "Home Phone: %s\n", p);
 
        bp = strdup(bp ? bp : "");
        list[E_OTHER].save = bp;
-       if (!list[E_OTHER].restricted || !uid)
-         (void)fprintf(fp, "Other information: %s\n", bp);
+       if (!list[E_OTHER].restricted || master_mode)
+               fprintf(fp, "Other information: %s\n", bp);
 
-       (void)fchown(fd, getuid(), getgid());
-       (void)fclose(fp);
+       free(gecos);
+
+       fchown(fileno(fp), getuid(), getgid());
+       fclose(fp);
+       return (0);
 }
 
-int
-verify(struct passwd *pw)
+static struct passwd *
+verify(const char *tfn, struct passwd *pw)
 {
+       struct passwd *npw;
        ENTRY *ep;
-       char *p;
+       char *buf, *p, *val;
        struct stat sb;
        FILE *fp;
-       int len, line;
-       static char buf[LINE_MAX];
+       int line;
+       size_t len;
 
-       if (!(fp = fopen(tempname, "r")))
-               pw_error(tempname, 1, 1);
-       if (fstat(fileno(fp), &sb))
-               pw_error(tempname, 1, 1);
+       if ((pw = pw_dup(pw)) == NULL)
+               return (NULL);
+       if ((fp = fopen(tfn, "r")) == NULL ||
+           fstat(fileno(fp), &sb) == -1) {
+               warn("%s", tfn);
+               free(pw);
+               return (NULL);
+       }
        if (sb.st_size == 0) {
                warnx("corrupted temporary file");
-               goto bad;
+               fclose(fp);
+               free(pw);
+               return (NULL);
        }
-       line = 0;
-       while (fgets(buf, sizeof(buf), fp)) {
-               line++;
-               if (!buf[0] || buf[0] == '#')
+       val = NULL;
+       for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
+               if (*buf == '\0' || *buf == '#')
                        continue;
-               if (!(p = strchr(buf, '\n'))) {
-                       warnx("line %d too long", line);
-                       goto bad;
-               }
-               *p = '\0';
+               while (len > 0 && isspace(buf[len - 1]))
+                       --len;
                for (ep = list;; ++ep) {
                        if (!ep->prompt) {
-                               warnx("unrecognized field on line %d", line);
+                               warnx("%s: unrecognized field on line %d",
+                                   tfn, line);
+                               goto bad;
+                       }
+                       if (ep->len > len)
+                               continue;
+                       if (strncasecmp(buf, ep->prompt, ep->len) != 0)
+                               continue;
+                       if (ep->restricted && !master_mode) {
+                               warnx("%s: you may not change the %s field",
+                                   tfn, ep->prompt);
+                               goto bad;
+                       }
+                       for (p = buf; p < buf + len && *p != ':'; ++p)
+                               /* nothing */ ;
+                       if (*p != ':') {
+                               warnx("%s: line %d corrupted", tfn, line);
                                goto bad;
                        }
-                       if (!strncasecmp(buf, ep->prompt, ep->len)) {
-                               if (ep->restricted && uid) {
-                                       warnx(
-                                           "you may not change the %s field",
-                                               ep->prompt);
-                                       goto bad;
-                               }
-                               if (!(p = strchr(buf, ':'))) {
-                                       warnx("line %d corrupted", line);
-                                       goto bad;
-                               }
-                               while (isspace(*++p));
-                               if (ep->except && strpbrk(p, ep->except)) {
-                                       warnx(
-                                  "illegal character in the \"%s\" field",
-                                           ep->prompt);
-                                       goto bad;
-                               }
-                               if ((ep->func)(p, pw, ep)) {
-bad:                                   (void)fclose(fp);
-                                       return (0);
-                               }
-                               break;
+                       while (++p < buf + len && isspace(*p))
+                               /* nothing */ ;
+                       free(val);
+                       asprintf(&val, "%.*s", (int)(buf + len - p), p);
+                       if (val == NULL)
+                               goto bad;
+                       if (ep->except && strpbrk(val, ep->except)) {
+                               warnx("%s: invalid character in \"%s\" field '%s'",
+                                   tfn, ep->prompt, val);
+                               goto bad;
                        }
+                       if ((ep->func)(val, pw, ep))
+                               goto bad;
+                       break;
                }
        }
-       (void)fclose(fp);
+       free(val);
+       fclose(fp);
 
        /* Build the gecos field. */
-       len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
-           strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) +
-           strlen(list[E_OTHER].save) + 5;
-       if (!(p = malloc(len)))
-               err(1, NULL);
-       (void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s,%s", list[E_NAME].save,
-           list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save,
-           list[E_OTHER].save);
-
-       while ((len = strlen(pw->pw_gecos)) && pw->pw_gecos[len - 1] == ',')
-               pw->pw_gecos[len - 1] = '\0';
-
-       if (snprintf(buf, sizeof(buf),
-           "%s:%s:%lu:%lu:%s:%ld:%ld:%s:%s:%s",
-           pw->pw_name, pw->pw_passwd, (unsigned long)pw->pw_uid, 
-           (unsigned long)pw->pw_gid, pw->pw_class, (long)pw->pw_change,
-           (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir,
-           pw->pw_shell) >= sizeof(buf)) {
-               warnx("entries too long");
-               free(p);
-               return (0);
+       len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save,
+           list[E_LOCATE].save, list[E_BPHONE].save,
+           list[E_HPHONE].save, list[E_OTHER].save);
+       if (p == NULL) {
+               warn("asprintf()");
+               free(pw);
+               return (NULL);
        }
+       while (len > 0 && p[len - 1] == ',')
+               p[--len] = '\0';
+       pw->pw_gecos = p;
+       buf = pw_make(pw);
+       free(pw);
        free(p);
-       return (__pw_scan(buf, pw, _PWSCAN_WARN|_PWSCAN_MASTER));
+       if (buf == NULL) {
+               warn("pw_make()");
+               return (NULL);
+       }
+       npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER);
+       free(buf);
+       return (npw);
+bad:
+       free(pw);
+       free(val);
+       fclose(fp);
+       return (NULL);
 }
index 8f539b5..5d3b4c8 100644 (file)
@@ -1,6 +1,13 @@
 /*
  * Copyright (c) 1988, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,6 +38,7 @@
  * SUCH DAMAGE.
  *
  * @(#)field.c 8.4 (Berkeley) 4/2/94
+ * $FreeBSD: src/usr.bin/chpass/field.c,v 1.9 2004/01/18 21:46:39 charnier Exp $
  * $DragonFly: src/usr.bin/chpass/field.c,v 1.3 2003/10/02 17:42:26 hmp Exp $
  */
 
 #include <err.h>
 #include <errno.h>
 #include <grp.h>
+#include <paths.h>
 #include <pwd.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 
 #include "chpass.h"
-#include "pathnames.h"
 
 /* ARGSUSED */
 int
-p_login(char *p, struct passwd *pw, ENTRY *ep)
+p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        if (!*p) {
                warnx("empty login field");
-               return (1);
+               return (-1);
        }
        if (*p == '-') {
                warnx("login names may not begin with a hyphen");
-               return (1);
+               return (-1);
        }
        if (!(pw->pw_name = strdup(p))) {
                warnx("can't save entry");
-               return (1);
+               return (-1);
        }
        if (strchr(p, '.'))
                warnx("\'.\' is dangerous in a login name");
@@ -78,13 +84,11 @@ p_login(char *p, struct passwd *pw, ENTRY *ep)
 
 /* ARGSUSED */
 int
-p_passwd(char *p, struct passwd *pw, ENTRY *ep)
+p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
-       if (!*p)
-               pw->pw_passwd = "";     /* "NOLOGIN"; */
-       else if (!(pw->pw_passwd = strdup(p))) {
+       if (!(pw->pw_passwd = strdup(p))) {
                warnx("can't save password entry");
-               return (1);
+               return (-1);
        }
 
        return (0);
@@ -92,24 +96,24 @@ p_passwd(char *p, struct passwd *pw, ENTRY *ep)
 
 /* ARGSUSED */
 int
-p_uid(char *p, struct passwd *pw, ENTRY *ep)
+p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        uid_t id;
        char *np;
 
        if (!*p) {
                warnx("empty uid field");
-               return (1);
+               return (-1);
        }
        if (!isdigit(*p)) {
                warnx("illegal uid");
-               return (1);
+               return (-1);
        }
        errno = 0;
        id = strtoul(p, &np, 10);
-       if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+       if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
                warnx("illegal uid");
-               return (1);
+               return (-1);
        }
        pw->pw_uid = id;
        return (0);
@@ -117,7 +121,7 @@ p_uid(char *p, struct passwd *pw, ENTRY *ep)
 
 /* ARGSUSED */
 int
-p_gid(char *p, struct passwd *pw, ENTRY *ep)
+p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        struct group *gr;
        gid_t id;
@@ -125,21 +129,21 @@ p_gid(char *p, struct passwd *pw, ENTRY *ep)
 
        if (!*p) {
                warnx("empty gid field");
-               return (1);
+               return (-1);
        }
        if (!isdigit(*p)) {
                if (!(gr = getgrnam(p))) {
                        warnx("unknown group %s", p);
-                       return (1);
+                       return (-1);
                }
                pw->pw_gid = gr->gr_gid;
                return (0);
        }
        errno = 0;
        id = strtoul(p, &np, 10);
-       if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+       if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
                warnx("illegal gid");
-               return (1);
+               return (-1);
        }
        pw->pw_gid = id;
        return (0);
@@ -147,13 +151,11 @@ p_gid(char *p, struct passwd *pw, ENTRY *ep)
 
 /* ARGSUSED */
 int
-p_class(char *p, struct passwd *pw, ENTRY *ep)
+p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
-       if (!*p)
-               pw->pw_class = "";
-       else if (!(pw->pw_class = strdup(p))) {
+       if (!(pw->pw_class = strdup(p))) {
                warnx("can't save entry");
-               return (1);
+               return (-1);
        }
 
        return (0);
@@ -161,79 +163,77 @@ p_class(char *p, struct passwd *pw, ENTRY *ep)
 
 /* ARGSUSED */
 int
-p_change(char *p, struct passwd *pw, ENTRY *ep)
+p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        if (!atot(p, &pw->pw_change))
                return (0);
        warnx("illegal date for change field");
-       return (1);
+       return (-1);
 }
 
 /* ARGSUSED */
 int
-p_expire(char *p, struct passwd *pw, ENTRY *ep)
+p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        if (!atot(p, &pw->pw_expire))
                return (0);
        warnx("illegal date for expire field");
-       return (1);
+       return (-1);
 }
 
 /* ARGSUSED */
 int
-p_gecos(char *p, struct passwd *pw, ENTRY *ep)
+p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
 {
-       if (!*p)
-               ep->save = "";
-       else if (!(ep->save = strdup(p))) {
+       if (!(ep->save = strdup(p))) {
                warnx("can't save entry");
-               return (1);
+               return (-1);
        }
        return (0);
 }
 
 /* ARGSUSED */
 int
-p_hdir(char *p, struct passwd *pw, ENTRY *ep)
+p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
        if (!*p) {
                warnx("empty home directory field");
-               return (1);
+               return (-1);
        }
        if (!(pw->pw_dir = strdup(p))) {
                warnx("can't save entry");
-               return (1);
+               return (-1);
        }
        return (0);
 }
 
 /* ARGSUSED */
 int
-p_shell(char *p, struct passwd *pw, ENTRY *ep)
+p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
 {
-       char *t, *ok_shell();
        struct stat sbuf;
 
        if (!*p) {
-               pw->pw_shell = _PATH_BSHELL;
+               pw->pw_shell = strdup(_PATH_BSHELL);
                return (0);
        }
        /* only admin can change from or to "restricted" shells */
-       if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
+       if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
                warnx("%s: current shell non-standard", pw->pw_shell);
-               return (1);
+               return (-1);
        }
-       if (!(t = ok_shell(p))) {
-               if (uid) {
+       if (!ok_shell(p)) {
+               if (!master_mode) {
                        warnx("%s: non-standard shell", p);
-                       return (1);
+                       return (-1);
                }
+               pw->pw_shell = strdup(p);
        }
        else
-               p = t;
-       if (!(pw->pw_shell = strdup(p))) {
+               pw->pw_shell = dup_shell(p);
+       if (!pw->pw_shell) {
                warnx("can't save entry");
-               return (1);
+               return (-1);
        }
        if (stat(pw->pw_shell, &sbuf) < 0) {
                if (errno == ENOENT)
@@ -244,7 +244,7 @@ p_shell(char *p, struct passwd *pw, ENTRY *ep)
                return (0);
        }
        if (!S_ISREG(sbuf.st_mode)) {
-               warnx("WARNING: shell '%s' is not a regular file", 
+               warnx("WARNING: shell '%s' is not a regular file",
                        pw->pw_shell);
                return (0);
        }
diff --git a/usr.bin/chpass/pathnames.h b/usr.bin/chpass/pathnames.h
deleted file mode 100644 (file)
index 30f3c0d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1989, 1993
- *     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.
- *
- *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
- */
-
-#include <paths.h>
-
-#undef _PATH_TMP
-#define        _PATH_TMP       "/tmp/chpass.XXXXXX"
diff --git a/usr.bin/chpass/pw_copy.c b/usr.bin/chpass/pw_copy.c
deleted file mode 100644 (file)
index 392e038..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993, 1994
- *     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.
- *
- * $FreeBSD: src/usr.bin/chpass/pw_copy.c,v 1.9.2.2 2002/03/24 09:00:03 cjc Exp $
- * $DragonFly: src/usr.bin/chpass/pw_copy.c,v 1.3 2003/10/02 17:42:26 hmp Exp $
- *
- * @(#)pw_copy.c       8.4 (Berkeley) 4/2/94
- */
-
-/*
- * This module is used to copy the master password file, replacing a single
- * record, by chpass(1) and passwd(1).
- */
-
-#include <err.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <pw_scan.h>
-#include <pw_util.h>
-
-#include "pw_copy.h"
-
-extern char *tempname;
-
-/* for use in pw_copy(). Compare a pw entry to a pw struct. */
-static int
-pw_equal(char *buf, struct passwd *pw)
-{
-       struct passwd buf_pw;
-       int len;
-
-       len = strlen (buf);
-       if (buf[len-1] == '\n')
-               buf[len-1] = '\0';
-       if (!__pw_scan(buf, &buf_pw, _PWSCAN_MASTER))
-               return 0;
-       return (strcmp(pw->pw_name, buf_pw.pw_name) == 0
-           && pw->pw_uid == buf_pw.pw_uid
-           && pw->pw_gid == buf_pw.pw_gid
-           && strcmp(pw->pw_class, buf_pw.pw_class) == 0
-           && (long)pw->pw_change == (long)buf_pw.pw_change
-           && (long)pw->pw_expire == (long)buf_pw.pw_expire
-           && strcmp(pw->pw_gecos, buf_pw.pw_gecos) == 0
-           && strcmp(pw->pw_dir, buf_pw.pw_dir) == 0
-           && strcmp(pw->pw_shell, buf_pw.pw_shell) == 0);
-}
-
-
-void
-pw_copy(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw)
-{
-       FILE *from, *to;
-       int done;
-       char *p, buf[8192];
-       char uidstr[20];
-       char gidstr[20];
-       char chgstr[20];
-       char expstr[20];
-
-       snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long)pw->pw_uid);
-       snprintf(gidstr, sizeof(gidstr), "%lu", (unsigned long)pw->pw_gid);
-       snprintf(chgstr, sizeof(chgstr), "%ld", (long)pw->pw_change);
-       snprintf(expstr, sizeof(expstr), "%ld", (long)pw->pw_expire);
-
-       if (!(from = fdopen(ffd, "r")))
-               pw_error(_PATH_MASTERPASSWD, 1, 1);
-       if (!(to = fdopen(tfd, "w")))
-               pw_error(tempname, 1, 1);
-
-       for (done = 0; fgets(buf, sizeof(buf), from);) {
-               if (!strchr(buf, '\n')) {
-                       warnx("%s: line too long", _PATH_MASTERPASSWD);
-                       pw_error(NULL, 0, 1);
-               }
-               if (done) {
-                       (void)fprintf(to, "%s", buf);
-                       if (ferror(to))
-                               goto err;
-                       continue;
-               }
-               for (p = buf; *p != '\n'; p++)
-                       if (*p != ' ' && *p != '\t')
-                               break;
-               if (*p == '#' || *p == '\n') {
-                       (void)fprintf(to, "%s", buf);
-                       if (ferror(to))
-                               goto err;
-                       continue;
-               }
-               if (!(p = strchr(buf, ':'))) {
-                       warnx("%s: corrupted entry", _PATH_MASTERPASSWD);
-                       pw_error(NULL, 0, 1);
-               }
-               *p = '\0';
-               if (strcmp(buf, pw->pw_name)) {
-                       *p = ':';
-                       (void)fprintf(to, "%s", buf);
-                       if (ferror(to))
-                               goto err;
-                       continue;
-               }
-               *p = ':';
-               if (old_pw && !pw_equal(buf, old_pw)) {
-                       warnx("%s: entry inconsistent",
-                             _PATH_MASTERPASSWD);
-                       pw_error(NULL, 0, 1);
-               }
-               (void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
-                   pw->pw_name, pw->pw_passwd,
-                   pw->pw_fields & _PWF_UID ? uidstr : "",
-                   pw->pw_fields & _PWF_GID ? gidstr : "",
-                   pw->pw_class,
-                   pw->pw_fields & _PWF_CHANGE ? chgstr : "",
-                   pw->pw_fields & _PWF_EXPIRE ? expstr : "",
-                   pw->pw_gecos, pw->pw_dir, pw->pw_shell);
-               done = 1;
-               if (ferror(to))
-                       goto err;
-       }
-       if (!done) {
-#ifdef YP
-       /* Ultra paranoid: shouldn't happen. */
-               if (getuid())  {
-                       warnx("%s: not found in %s -- permission denied",
-                                       pw->pw_name, _PATH_MASTERPASSWD);
-                       pw_error(NULL, 0, 1);
-               } else
-#endif /* YP */
-               (void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
-                   pw->pw_name, pw->pw_passwd,
-                   pw->pw_fields & _PWF_UID ? uidstr : "",
-                   pw->pw_fields & _PWF_GID ? gidstr : "",
-                   pw->pw_class,
-                   pw->pw_fields & _PWF_CHANGE ? chgstr : "",
-                   pw->pw_fields & _PWF_EXPIRE ? expstr : "",
-                   pw->pw_gecos, pw->pw_dir, pw->pw_shell);
-       }
-
-       if (ferror(to))
-err:           pw_error(NULL, 1, 1);
-       (void)fclose(to);
-}
diff --git a/usr.bin/chpass/pw_copy.h b/usr.bin/chpass/pw_copy.h
deleted file mode 100644 (file)
index c43859e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 1994
- *     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.
- *
- *     @(#)pw_copy.h   8.1 (Berkeley) 4/2/94
- *     $FreeBSD: src/usr.bin/chpass/pw_copy.h,v 1.1.1.1.14.1 2002/03/24 09:00:03 cjc Exp $
- *     $DragonFly: src/usr.bin/chpass/pw_copy.h,v 1.3 2003/11/03 19:31:28 eirikn Exp $
- */
-
-void    pw_copy(int, int, struct passwd *, struct passwd *);
diff --git a/usr.bin/chpass/pw_yp.c b/usr.bin/chpass/pw_yp.c
deleted file mode 100644 (file)
index d4f2a8b..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 1995
- *     Bill Paul <wpaul@ctr.columbia.edu>.  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 Bill Paul.
- * 4. Neither the name of the author nor the names of any co-contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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.
- *
- * NIS interface routines for chpass
- *
- * Written by Bill Paul <wpaul@ctr.columbia.edu>
- * Center for Telecommunications Research
- * Columbia University, New York City
- *
- * $FreeBSD: src/usr.bin/chpass/pw_yp.c,v 1.16.2.1 2002/02/15 00:46:56 des Exp $
- * $DragonFly: src/usr.bin/chpass/pw_yp.c,v 1.5 2005/05/07 22:29:39 corecode Exp $
- */
-
-#ifdef YP
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netdb.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pwd.h>
-#include <errno.h>
-#include <err.h>
-#include <unistd.h>
-#include <db.h>
-#include <fcntl.h>
-#include <utmp.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <limits.h>
-#include <rpc/rpc.h>
-#include <rpcsvc/yp.h>
-struct dom_binding {};
-#include <rpcsvc/ypclnt.h>
-#include <rpcsvc/yppasswd.h>
-#include <pw_util.h>
-#include "pw_yp.h"
-#include "ypxfr_extern.h"
-#include "yppasswd_private.h"
-
-#define PERM_SECURE (S_IRUSR|S_IWUSR)
-HASHINFO openinfo = {
-        4096,           /* bsize */
-        32,             /* ffactor */
-        256,            /* nelem */
-        2048 * 1024,    /* cachesize */
-        NULL,           /* hash */
-        0,              /* lorder */
-};
-
-int force_old = 0;
-int _use_yp = 0;
-int suser_override = 0;
-int yp_in_pw_file = 0;
-char *yp_domain = NULL;
-char *yp_server = NULL;
-
-extern char *tempname;
-
-/* Save the local and NIS password information */
-struct passwd local_password;
-struct passwd yp_password;
-
-void copy_yp_pass(char *p, int x, int m)
-{
-       char *t, *s = p;
-       static char *buf;
-
-       yp_password.pw_fields = 0;
-
-       buf = (char *)realloc(buf, m + 10);
-       bzero(buf, m + 10);
-
-       /* Turn all colons into NULLs */
-       while (strchr(s, ':')) {
-               s = (strchr(s, ':') + 1);
-               *(s - 1)= '\0';
-       }
-
-       t = buf;
-#define EXPAND(e)       e = t; while ((*t++ = *p++));
-        EXPAND(yp_password.pw_name);
-       yp_password.pw_fields |= _PWF_NAME;
-        EXPAND(yp_password.pw_passwd);
-       yp_password.pw_fields |= _PWF_PASSWD;
-       yp_password.pw_uid = atoi(p);
-        p += (strlen(p) + 1);
-       yp_password.pw_fields |= _PWF_UID;
-       yp_password.pw_gid = atoi(p);
-        p += (strlen(p) + 1);
-       yp_password.pw_fields |= _PWF_GID;
-       if (x) {
-               EXPAND(yp_password.pw_class);
-               yp_password.pw_fields |= _PWF_CLASS;
-               yp_password.pw_change = atol(p);
-               p += (strlen(p) + 1);
-               yp_password.pw_fields |= _PWF_CHANGE;
-               yp_password.pw_expire = atol(p);
-               p += (strlen(p) + 1);
-               yp_password.pw_fields |= _PWF_EXPIRE;
-       }
-        EXPAND(yp_password.pw_gecos);
-       yp_password.pw_fields |= _PWF_GECOS;
-        EXPAND(yp_password.pw_dir);
-       yp_password.pw_fields |= _PWF_DIR;
-        EXPAND(yp_password.pw_shell);
-       yp_password.pw_fields |= _PWF_SHELL;
-
-       return;
-}
-
-void copy_local_pass(char *p, int m)
-{
-       char *t;
-       static char *buf;
-
-       buf = (char *)realloc(buf, m + 10);
-       bzero(buf, m + 10);
-
-       t = buf;
-        EXPAND(local_password.pw_name);
-        EXPAND(local_password.pw_passwd);
-        bcopy(p, (char *)&local_password.pw_uid, sizeof(int));
-        p += sizeof(int);
-        bcopy(p, (char *)&local_password.pw_gid, sizeof(int));
-        p += sizeof(int);
-               bcopy(p, (char *)&local_password.pw_change, sizeof(time_t));
-               p += sizeof(time_t);
-               EXPAND(local_password.pw_class);
-        EXPAND(local_password.pw_gecos);
-        EXPAND(local_password.pw_dir);
-        EXPAND(local_password.pw_shell);
-        bcopy(p, (char *)&local_password.pw_expire, sizeof(time_t));
-        p += sizeof(time_t);
-        bcopy(p, (char *)&local_password.pw_fields, sizeof local_password.pw_fields);
-        p += sizeof local_password.pw_fields;
-
-       return;
-}
-
-/*
- * It is not mandatory that an NIS master server also be a client.
- * However, if the NIS master is not configured as a client, then the
- * domain name will not be set and ypbind will not be running, so we
- * will be unable to use the ypclnt routines inside libc. We therefore
- * need our own magic version of yp_match() which we can use in any
- * environment.
- */
-static int my_yp_match(char *server, char *domain, char *map, char *key,
-                       unsigned long keylen, char **result, unsigned long *resultlen)
-{
-       ypreq_key ypkey;
-       ypresp_val *ypval;
-       CLIENT *clnt;
-       static char buf[YPMAXRECORD + 2];
-
-       bzero((char *)buf, sizeof(buf));
-
-       /*
-        * Don't make this a fatal error. The inability to contact
-        * a server is, for our purposes, equivalent to not finding
-        * the record we were looking for. Letting use_yp() know
-        * that the lookup failed is sufficient.
-        */
-       if ((clnt = clnt_create(server, YPPROG,YPVERS,"udp")) == NULL) {
-               return(1);
-#ifdef notdef
-               warnx("failed to create UDP handle: %s",
-                                       clnt_spcreateerror(server));
-               pw_error(tempname, 0, 1);
-#endif
-       }
-
-       ypkey.domain = domain;
-       ypkey.map = map;
-       ypkey.key.keydat_len = keylen;
-       ypkey.key.keydat_val = key;
-
-       if ((ypval = ypproc_match_2(&ypkey, clnt)) == NULL) {
-               clnt_destroy(clnt);
-               return(1);
-#ifdef notdef
-               warnx("%s",clnt_sperror(clnt,"YPPROC_MATCH failed"));
-               pw_error(tempname, 0, 1);
-#endif
-       }
-
-       clnt_destroy(clnt);
-
-       if (ypval->stat != YP_TRUE) {
-               xdr_free(xdr_ypresp_val, (char *)ypval);
-               return(1);
-#ifdef notdef
-               int stat = ypval->stat;
-               xdr_free(xdr_ypresp_val, (char *)ypval);
-               if (stat == YP_NOMAP && strstr(map, "master.passwd"))
-                       return(1);
-               if (stat == YP_NOKEY)
-                       return(1);
-               warnx("ypmatch failed: %s", yperr_string(ypprot_err(stat)));
-               pw_error(tempname, 0, 1);
-#endif
-       }
-
-
-       strncpy((char *)&buf, ypval->val.valdat_val, ypval->val.valdat_len);
-
-       *result = (char *)&buf;
-       *resultlen = ypval->val.valdat_len;
-
-       xdr_free(xdr_ypresp_val, (char *)ypval);
-
-       return(0);
-}
-
-/*
- * Check if the user we're working with is local or in NIS.
- */
-/* which: 0 = use username, 1 = use uid */
-int use_yp (char *user, uid_t uid, int which)
-{
-       int user_local = 0, user_yp = 0, user_exists = 0;
-       DB *dbp;
-       DBT key,data;
-       char bf[UT_NAMESIZE + 2];
-       char *result;
-       char *server;
-       long resultlen;
-       char ubuf[UT_NAMESIZE + 2];
-
-       if (which) {
-               snprintf(ubuf, sizeof(ubuf), "%lu", (unsigned long)uid);
-               user = (char *)&ubuf;
-       }
-
-       /* Grope around for the user in the usual way */
-       if (which) {
-               if (getpwuid(uid) != NULL)
-                       user_exists = 1;
-       } else {
-               if (getpwnam(user) != NULL)
-                       user_exists = 1;
-       }
-
-       /* Now grope directly through the user database */
-       if ((dbp = dbopen(_PATH_SMP_DB, O_RDONLY, PERM_SECURE,
-                       DB_HASH, &openinfo)) == NULL) {
-                       warn("error opening database: %s.", _PATH_MP_DB);
-                       pw_error(tempname, 0, 1);
-       }
-
-       /* Is NIS turned on */
-       bf[0] = _PW_KEYYPENABLED;
-       key.data = (u_char *)bf;
-       key.size = 1;
-       yp_in_pw_file = !(dbp->get)(dbp,&key,&data,0);
-       if (_yp_check(NULL) || (yp_domain && yp_server)) {
-               server = get_yp_master(0);
-
-               /* Is the user in the NIS passwd map */
-               if (!my_yp_match(server, yp_domain, which ? "passwd.byuid" :
-                                       "passwd.byname", user, strlen(user),
-                   &result, &resultlen)) {
-                       user_yp = user_exists = 1;
-                       *(char *)(result + resultlen) = '\0';
-                       copy_yp_pass(result, 0, resultlen);
-               }
-               /* Is the user in the NIS master.passwd map */
-               if (user_yp && !my_yp_match(server, yp_domain, which ?
-                       "master.passwd.byuid" : "master.passwd.byname",
-                   user, strlen(user),
-                   &result, &resultlen)) {
-                       *(char *)(result + resultlen) = '\0';
-                       copy_yp_pass(result, 1, resultlen);
-               }
-       }
-
-       /* Is the user in the local password database */
-
-       bf[0] = which ? _PW_KEYBYUID : _PW_KEYBYNAME;
-       if (which)
-               bcopy((char *)&uid, bf + 1, sizeof(uid));
-       else
-               bcopy((char *)user, bf + 1, MIN(strlen(user), UT_NAMESIZE));
-       key.data = (u_char *)bf;
-       key.size = which ? sizeof(uid) + 1 : strlen(user) + 1;
-       if (!(dbp->get)(dbp,&key,&data,0)) {
-               user_local = 1;
-               copy_local_pass(data.data, data.size);
-       }
-
-       (dbp->close)(dbp);
-
-       if (user_local && user_yp && user_exists)
-               return(USER_YP_AND_LOCAL);
-       else if (!user_local && user_yp && user_exists)
-               return(USER_YP_ONLY);
-       else if (user_local && !user_yp && user_exists)
-               return(USER_LOCAL_ONLY);
-       else if (!user_exists)
-               return(USER_UNKNOWN);
-
-       return(-1);
-}
-
-/*
- * Find the name of the NIS master server for this domain
- * and make sure it's running yppasswdd.
- */
-char *get_yp_master(int getserver)
-{
-       char *mastername;
-       int rval, localport;
-       struct stat st;
-       char                    *sockname = YP_SOCKNAME;
-
-       /*
-        * Sometimes we are called just to probe for rpc.yppasswdd and
-        * set the suser_override flag. Just return NULL and leave
-        * suser_override at 0 if _use_yp doesn't indicate that NIS is
-        * in use and we weren't called from use_yp() itself.
-        * Without this check, we might try probing and fail with an NIS
-        * error in non-NIS environments.
-        */
-       if ((_use_yp == USER_UNKNOWN || _use_yp == USER_LOCAL_ONLY) &&
-                                                               getserver)
-               return(NULL);
-
-       /* Get default NIS domain. */
-
-       if (yp_domain == NULL && (rval = yp_get_default_domain(&yp_domain))) {
-               warnx("can't get local NIS domain name: %s",yperr_string(rval));
-               pw_error(tempname, 0, 1);
-       }
-
-       /* Get master server of passwd map. */
-
-       if ((mastername = ypxfr_get_master(yp_domain, "passwd.byname",
-                               yp_server, yp_server ? 0 : 1)) == NULL) {
-               warnx("can't get name of master NIS server");
-               pw_error(tempname, 0, 1);
-       }
-
-       if (!getserver)
-               return(mastername);
-
-       /* Check if yppasswdd is out there. */
-
-       if ((rval = getrpcport(mastername, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
-               IPPROTO_UDP)) == 0) {
-               warnx("rpc.yppasswdd is not running on the NIS master server");
-               pw_error(tempname, 0, 1);
-       }
-
-       /*
-        * Make sure it's on a reserved port.
-        * XXX Might break with yppasswdd servers running on Solaris 2.x.
-        */
-
-       if (rval >= IPPORT_RESERVED) {
-               warnx("rpc.yppasswdd server not running on reserved port");
-               pw_error(tempname, 0, 1);
-       }
-
-       /* See if _we_ are the master server. */
-       if (!force_old && !getuid() && (localport = getrpcport("localhost",
-               YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) != 0) {
-               if (localport == rval && stat(sockname, &st) != -1) {
-                       suser_override = 1;
-                       mastername = "localhost";
-               }
-       }
-
-       /* Everything checks out: return the name of the server. */
-
-       return (mastername);
-}
-
-/*
- * Ask the user for his NIS password and submit the new information
- * to yppasswdd. Note that rpc.yppasswdd requires password authentication
- * and only allows changes to existing records rather than the addition
- * of new records. (To do actual updates we would need something like
- * secure RPC and ypupdated, which FreeBSD doesn't have yet.) The FreeBSD
- * rpc.yppasswdd has some special hooks to allow the superuser update
- * information without specifying a password, however this only works
- * for the superuser on the NIS master server.
- */
-void yp_submit(struct passwd *pw)
-{
-       struct yppasswd yppasswd;
-       struct master_yppasswd master_yppasswd;
-       CLIENT *clnt;
-       char *master, *password;
-       int *status = NULL;
-       struct rpc_err err;
-       char                    *sockname = YP_SOCKNAME;
-
-       _use_yp = 1;
-
-       /* Get NIS master server name */
-
-       master = get_yp_master(1);
-
-       /* Populate the yppasswd structure that gets handed to yppasswdd. */
-
-       if (suser_override) {
-               master_yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd);
-               master_yppasswd.newpw.pw_name = strdup(pw->pw_name);
-               master_yppasswd.newpw.pw_uid = pw->pw_uid;
-               master_yppasswd.newpw.pw_gid = pw->pw_gid;
-               master_yppasswd.newpw.pw_expire = pw->pw_expire;
-               master_yppasswd.newpw.pw_change = pw->pw_change;
-               master_yppasswd.newpw.pw_fields = pw->pw_fields;
-               master_yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos);
-               master_yppasswd.newpw.pw_dir = strdup(pw->pw_dir);
-               master_yppasswd.newpw.pw_shell = strdup(pw->pw_shell);
-               master_yppasswd.newpw.pw_class = pw->pw_class != NULL ?
-                                               strdup(pw->pw_class) : "";
-               master_yppasswd.oldpass = ""; /* not really needed */
-               master_yppasswd.domain = yp_domain;
-       } else {
-               yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd);
-               yppasswd.newpw.pw_name = strdup(pw->pw_name);
-               yppasswd.newpw.pw_uid = pw->pw_uid;
-               yppasswd.newpw.pw_gid = pw->pw_gid;
-               yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos);
-               yppasswd.newpw.pw_dir = strdup(pw->pw_dir);
-               yppasswd.newpw.pw_shell = strdup(pw->pw_shell);
-               yppasswd.oldpass = "";
-       }
-
-       /* Get the user's password for authentication purposes. */
-
-       printf ("Changing NIS information for %s on %s\n",
-                                       pw->pw_name, master);
-
-       if (pw->pw_passwd[0] && !suser_override) {
-               password = getpass("Please enter password: ");
-               if (strncmp(crypt(password,pw->pw_passwd),
-                               pw->pw_passwd,strlen(pw->pw_passwd))) {
-                       warnx("Password incorrect.");
-                       pw_error(tempname, 0, 1);
-               }
-               yppasswd.oldpass = password;    /* XXX */
-       }
-
-       if (suser_override) {
-               /* Talk to server via AF_UNIX socket. */
-               clnt = clnt_create(sockname, MASTER_YPPASSWDPROG,
-                                       MASTER_YPPASSWDVERS, "unix");
-               if (clnt == NULL) {
-                       warnx("failed to contact rpc.yppasswdd: %s",
-                               clnt_spcreateerror(master));
-                       pw_error(tempname, 0, 1);
-               }
-       } else {
-               /* Create a handle to yppasswdd. */
-
-               if ((clnt = clnt_create(master, YPPASSWDPROG,
-                                       YPPASSWDVERS, "udp")) == NULL) {
-                       warnx("failed to contact rpc.yppasswdd: %s",
-                               clnt_spcreateerror(master));
-                       pw_error(tempname, 0, 1);
-               }
-       }
-
-       clnt->cl_auth = authunix_create_default();
-
-       if (suser_override)
-               status = yppasswdproc_update_master_1(&master_yppasswd, clnt);
-       else
-               status = yppasswdproc_update_1(&yppasswd, clnt);
-
-       clnt_geterr(clnt, &err);
-
-       auth_destroy(clnt->cl_auth);
-       clnt_destroy(clnt);
-
-       /* Call failed: signal the error. */
-
-       if (err.re_status != RPC_SUCCESS || status == NULL || *status) {
-               warnx("NIS update failed: %s", clnt_sperrno(err.re_status));
-               pw_error(NULL, 0, 1);
-       }
-
-       /* Success. */
-
-       if (suser_override)
-               warnx("NIS information changed on host %s, domain %s",
-                       master, yp_domain);
-       else
-               warnx("NIS information changed on host %s", master);
-
-       return;
-}
-#endif /* YP */
diff --git a/usr.bin/chpass/pw_yp.h b/usr.bin/chpass/pw_yp.h
deleted file mode 100644 (file)
index d99f0ee..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 1995
- *     Bill Paul <wpaul@ctr.columbia.edu>.  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 Bill Paul.
- * 4. Neither the name of the author nor the names of any co-contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Bill Paul 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.
- *
- * NIS interface routines for chpass
- *
- * Written by Bill Paul <wpaul@ctr.columbia.edu>
- * Center for Telecommunications Research
- * Columbia University, New York City
- *
- * $FreeBSD: src/usr.bin/chpass/pw_yp.h,v 1.7.2.1 2002/02/15 00:46:56 des Exp $
- * $DragonFly: src/usr.bin/chpass/pw_yp.h,v 1.2 2003/06/17 04:29:25 dillon Exp $
- */
-
-#ifdef YP
-#include <sys/types.h>
-#include <rpc/rpc.h>
-#include <rpc/auth.h>
-#include <rpc/auth_unix.h>
-/* Four possible return codes from use_yp() */
-#define USER_UNKNOWN 0
-#define USER_YP_ONLY 1
-#define USER_LOCAL_ONLY 2
-#define USER_YP_AND_LOCAL 3
-
-extern int             force_old;
-extern int             _use_yp;
-extern int             suser_override;
-extern struct passwd   local_password;
-extern struct passwd   yp_password;
-extern void            copy_yp_pass(char *, int, int);
-extern char            *yp_domain;
-extern char            *yp_server;
-extern void            yp_submit(struct passwd *);
-extern int             use_yp(char *, uid_t, int);
-extern char            *get_yp_master(int);
-extern int             yp_in_pw_file;
-
-/*
- * Yucky.
- */
-#define GETPWUID(X) \
-       _use_yp = use_yp(NULL, X, 1);                                   \
-                                                                       \
-       if (_use_yp == USER_UNKNOWN) {                                  \
-               errx(1, "unknown user: uid %u", X);                     \
-       }                                                               \
-                                                                       \
-       if (_use_yp == USER_YP_ONLY) {                                  \
-               if (!force_local) {                                     \
-                       _use_yp = 1;                                    \
-                       pw = (struct passwd *)&yp_password;             \
-               } else                                                  \
-                       errx(1, "unknown local user: uid %u", X);       \
-       } else if (_use_yp == USER_LOCAL_ONLY) {                        \
-               if (!force_yp) {                                        \
-                       _use_yp = 0;                                    \
-                       pw = (struct passwd *)&local_password;          \
-               } else                                                  \
-                       errx(1, "unknown NIS user: uid %u", X);         \
-       } else if (_use_yp == USER_YP_AND_LOCAL) {                      \
-               if (!force_local && (force_yp || yp_in_pw_file)) {      \
-                       _use_yp = 1;                                    \
-                       pw = (struct passwd *)&yp_password;             \
-               } else {                                                \
-                       _use_yp = 0;                                    \
-                       pw = (struct passwd *)&local_password;          \
-               }                                                       \
-       }
-
-#define GETPWNAM(X) \
-       _use_yp = use_yp(X, 0, 0);                                      \
-                                                                       \
-       if (_use_yp == USER_UNKNOWN) {                                  \
-               errx(1, "unknown user: %s", X);                         \
-       }                                                               \
-                                                                       \
-       if (_use_yp == USER_YP_ONLY) {                                  \
-               if (!force_local) {                                     \
-                       _use_yp = 1;                                    \
-                       pw = (struct passwd *)&yp_password;             \
-               } else                                                  \
-                       errx(1, "unknown local user: %s.", X);          \
-       } else if (_use_yp == USER_LOCAL_ONLY) {                        \
-               if (!force_yp) {                                        \
-                       _use_yp = 0;                                    \
-                       pw = (struct passwd *)&local_password;          \
-               } else                                                  \
-                       errx(1, "unknown NIS user: %s.", X);            \
-       } else if (_use_yp == USER_YP_AND_LOCAL) {                      \
-               if (!force_local && (force_yp || yp_in_pw_file)) {      \
-                       _use_yp = 1;                                    \
-                       pw = (struct passwd *)&yp_password;             \
-               } else {                                                \
-                       _use_yp = 0;                                    \
-                       pw = (struct passwd *)&local_password;          \
-               }                                                       \
-       }
-
-#endif /* YP */
index aca01fd..723b51e 100644 (file)
@@ -31,6 +31,7 @@
  * SUCH DAMAGE.
  *
  * @(#)table.c 8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/usr.bin/chpass/table.c,v 1.10 2003/05/03 19:44:45 obrien Exp $
  */
 
 #include <sys/types.h>
@@ -41,23 +42,23 @@ char e1[] = ": ";
 char e2[] = ":,";
 
 ENTRY list[] = {
-       { "login",              p_login,  1,   5, e1,   },
-       { "password",           p_passwd, 1,   8, e1,   },
-       { "uid",                p_uid,    1,   3, e1,   },
-       { "gid",                p_gid,    1,   3, e1,   },
-       { "class",              p_class,  1,   5, e1,   },
-       { "change",             p_change, 1,   6, NULL, },
-       { "expire",             p_expire, 1,   6, NULL, },
+       { "login",              p_login,  1,   5, e1,   NULL },
+       { "password",           p_passwd, 1,   8, e1,   NULL },
+       { "uid",                p_uid,    1,   3, e1,   NULL },
+       { "gid",                p_gid,    1,   3, e1,   NULL },
+       { "class",              p_class,  1,   5, e1,   NULL },
+       { "change",             p_change, 1,   6, NULL, NULL },
+       { "expire",             p_expire, 1,   6, NULL, NULL },
 #ifdef RESTRICT_FULLNAME_CHANGE                /* do not allow fullname changes */
-       { "full name",          p_gecos,  1,   9, e2,   },
+       { "full name",          p_gecos,  1,   9, e2,   NULL },
 #else
-       { "full name",          p_gecos,  0,   9, e2,   },
+       { "full name",          p_gecos,  0,   9, e2,   NULL },
 #endif
-       { "office phone",       p_gecos,  0,  12, e2,   },
-       { "home phone",         p_gecos,  0,  10, e2,   },
-       { "office location",    p_gecos,  0,  15, e2,   },
-       { "other information",  p_gecos,  0,  11, e1,   },
-       { "home directory",     p_hdir,   1,  14, e1,   },
-       { "shell",              p_shell,  0,   5, e1,   },
-       { NULL, 0, },
+       { "office phone",       p_gecos,  0,  12, e2,   NULL },
+       { "home phone",         p_gecos,  0,  10, e2,   NULL },
+       { "office location",    p_gecos,  0,  15, e2,   NULL },
+       { "other information",  p_gecos,  0,  11, e1,   NULL },
+       { "home directory",     p_hdir,   1,  14, e1,   NULL },
+       { "shell",              p_shell,  0,   5, e1,   NULL },
+       { NULL, NULL, 0, 0, NULL, NULL },
 };
index f5e9e23..54e3c43 100644 (file)
@@ -1,6 +1,13 @@
 /*-
  * Copyright (c) 1988, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  *
  * @(#)util.c  8.4 (Berkeley) 4/2/94
- * $FreeBSD: src/usr.bin/chpass/util.c,v 1.8.2.1 2002/03/21 10:33:01 cjc Exp $
+ * $FreeBSD: src/usr.bin/chpass/util.c,v 1.13 2004/01/18 21:46:39 charnier Exp $
  * $DragonFly: src/usr.bin/chpass/util.c,v 1.3 2003/10/02 17:42:26 hmp Exp $
  */
 
 #include <sys/types.h>
 
 #include <ctype.h>
-#include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -46,9 +52,8 @@
 #include <unistd.h>
 
 #include "chpass.h"
-#include "pathnames.h"
 
-static char *months[] =
+static const char *months[] =
        { "January", "February", "March", "April", "May", "June",
          "July", "August", "September", "October", "November",
          "December", NULL };
@@ -61,7 +66,7 @@ ttoa(time_t tval)
 
        if (tval) {
                tp = localtime(&tval);
-               (void)sprintf(tbuf, "%s %d, %d", months[tp->tm_mon],
+               sprintf(tbuf, "%s %d, %d", months[tp->tm_mon],
                    tp->tm_mday, tp->tm_year + 1900);
        }
        else
@@ -73,7 +78,8 @@ int
 atot(char *p, time_t *store)
 {
        static struct tm *lt;
-       char *t, **mp;
+       char *t;
+       const char **mp;
        time_t tval;
        int day, month, year;
 
@@ -83,7 +89,7 @@ atot(char *p, time_t *store)
        }
        if (!lt) {
                unsetenv("TZ");
-               (void)time(&tval);
+               time(&tval);
                lt = localtime(&tval);
        }
        if (!(t = strtok(p, " \t")))
@@ -128,18 +134,45 @@ bad:              return (1);
        return (0);
 }
 
-char *
+int
 ok_shell(char *name)
 {
        char *p, *sh;
 
        setusershell();
        while ((sh = getusershell())) {
-               if (!strcmp(name, sh))
-                       return (name);
+               if (!strcmp(name, sh)) {
+                       endusershell();
+                       return (1);
+               }
                /* allow just shell name, but use "real" path */
-               if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0)
-                       return (sh);
+               if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+                       endusershell();
+                       return (1);
+               }
+       }
+       endusershell();
+       return (0);
+}
+
+char *
+dup_shell(char *name)
+{
+       char *p, *sh, *ret;
+
+       setusershell();
+       while ((sh = getusershell())) {
+               if (!strcmp(name, sh)) {
+                       endusershell();
+                       return (strdup(name));
+               }
+               /* allow just shell name, but use "real" path */
+               if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+                       ret = strdup(sh);
+                       endusershell();
+                       return (ret);
+               }
        }
+       endusershell();
        return (NULL);
 }