pw: Sync with FreeBSD
authorPeter Avalos <pavalos@dragonflybsd.org>
Sun, 6 May 2012 19:11:50 +0000 (12:11 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sun, 6 May 2012 19:27:48 +0000 (12:27 -0700)
* Spelling fixes.
* Stop hard-coding default directory mode as 0777.
* Use arc4random_uniform() to avoid "modulo bias".
* Before updating the password database, the pw(8) utility first
  performs a sanity check by invoking "pwd_mkdb -C".  However, if this
  failed it silently returned success.  Fix this so it fails the update
  operation instead.
* Increase the size of the salt in pw(8) from 8 to 32.
* Make it possible to have a '/' in the salt.
* Add the groupmod '-d' option to pw to allow the deletion of existing
  users from a group without the need to perform the same operation by
  replacing the existing list via the '-M' option.  The '-M' option
  requires someone to fetch the existing members with pw, deleting the
  undesired members from the list and sending the altered list back.
* Do the right thing with symlinks in the skeleton directory.
* Accept passwords which contain whitespace.
* Introduce the new option -M to allow to set the permissions of the
  user's newly created home directory.
* Use strlcpy(3).
* Shift file locking to source file instead of temp file.
* Add a `-H <fd>' option that is like `-h <fd>', but accepts an already
  encrypted password on the specified file descriptor.

DragonFly-bug: <http://bugs.dragonflybsd.org/issue2362>
Obtained-from:  FreeBSD

20 files changed:
usr.sbin/pw/Makefile
usr.sbin/pw/bitmap.h
usr.sbin/pw/cpdir.c
usr.sbin/pw/edgroup.c
usr.sbin/pw/fileupd.c
usr.sbin/pw/grupd.c
usr.sbin/pw/psdate.c
usr.sbin/pw/psdate.h
usr.sbin/pw/pw.8
usr.sbin/pw/pw.c
usr.sbin/pw/pw.conf.5
usr.sbin/pw/pw.h
usr.sbin/pw/pw_conf.c
usr.sbin/pw/pw_group.c
usr.sbin/pw/pw_log.c
usr.sbin/pw/pw_user.c
usr.sbin/pw/pw_vpw.c
usr.sbin/pw/pwupd.c
usr.sbin/pw/pwupd.h
usr.sbin/pw/rm_r.c

index 0e03e2b..b8fdc24 100644 (file)
@@ -1,5 +1,4 @@
 # $FreeBSD: src/usr.sbin/pw/Makefile,v 1.11.2.3 2001/06/21 02:16:32 dd Exp $
-# $DragonFly: src/usr.sbin/pw/Makefile,v 1.3 2008/10/29 18:18:04 swildner Exp $
 
 PROG=  pw
 SRCS=  pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \
@@ -9,10 +8,7 @@ WARNS?=        2
 
 MAN=   pw.conf.5 pw.8
 
-#RND=  -DUSE_MD5RAND
 LDADD= -lcrypt -lutil
 DPADD= ${LIBCRYPT} ${LIBUTIL}
 
-BINMODE=0555
-
 .include <bsd.prog.mk>
index ad07486..c9328a1 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/bitmap.h,v 1.4 1999/08/28 01:19:16 peter Exp $
- * $DragonFly: src/usr.sbin/pw/bitmap.h,v 1.3 2003/11/03 19:31:41 eirikn Exp $
+ * $FreeBSD: src/usr.sbin/pw/bitmap.h,v 1.5 2002/07/11 19:07:35 alfred Exp $
  */
 
 #ifndef _BITMAP_H_
index 619eea0..98a1a87 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/cpdir.c,v 1.5.2.1 2000/08/14 19:01:35 jhb Exp $
+ * $FreeBSD: src/usr.sbin/pw/cpdir.c,v 1.11 2012/02/14 10:17:03 kevlo Exp $
  */
 
 #include <err.h>
 #include <sys/param.h>
 #include <dirent.h>
 
+#include "pw.h"
 #include "pwupd.h"
 
 void
 copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)
 {
-       int             rc = 0;
        char            src[MAXPATHLEN];
        char            dst[MAXPATHLEN];
+       char            lnk[MAXPATHLEN];
+       int             len;
 
        if (mkdir(dir, mode) != 0 && errno != EEXIST) {
                warn("mkdir(%s)", dir);
@@ -58,9 +60,7 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
 
                ++counter;
                chown(dir, uid, gid);
-               if (skel == NULL || *skel == '\0')
-                       rc = 1;
-               else {
+               if (skel != NULL && *skel != '\0') {
                        DIR            *d = opendir(skel);
 
                        if (d != NULL) {
@@ -71,7 +71,7 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
 
                                        if (snprintf(src, sizeof(src), "%s/%s", skel, p) >= (int)sizeof(src))
                                                warn("warning: pathname too long '%s/%s' (skel not copied)", skel, p);
-                                       else if (stat(src, &st) == 0) {
+                                       else if (lstat(src, &st) == 0) {
                                                if (strncmp(p, "dot.", 4) == 0) /* Conversion */
                                                        p += 3;
                                                if (snprintf(dst, sizeof(dst), "%s/%s", dir, p) >= (int)sizeof(dst))
@@ -79,12 +79,16 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
                                                else {
                                                    if (S_ISDIR(st.st_mode)) {  /* Recurse for this */
                                                        if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) {
-                                                               copymkdir(dst, src, (st.st_mode & 0777), uid, gid);
-                                                               chflags(dst, st.st_flags);      /* propogate flags */
+                                                               copymkdir(dst, src, st.st_mode & _DEF_DIRMODE, uid, gid);
+                                                               chflags(dst, st.st_flags);      /* propagate flags */
                                                        }
+                                                   } else if (S_ISLNK(st.st_mode) && (len = readlink(src, lnk, sizeof(lnk) - 1)) != -1) {
+                                                       lnk[len] = '\0';
+                                                       symlink(lnk, dst);
+                                                       lchown(dst, uid, gid);
                                                        /*
-                                                        * Note: don't propogate special attributes
-                                                        * but do propogate file flags
+                                                        * Note: don't propagate special attributes
+                                                        * but do propagate file flags
                                                         */
                                                    } else if (S_ISREG(st.st_mode) && (outfd = open(dst, O_RDWR | O_CREAT | O_EXCL, st.st_mode)) != -1) {
                                                        if ((infd = open(src, O_RDONLY)) == -1) {
@@ -102,7 +106,7 @@ copymkdir(char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid
                                                                        write(outfd, copybuf, b);
                                                                close(infd);
                                                                /*
-                                                                * Propogate special filesystem flags
+                                                                * Propagate special filesystem flags
                                                                 */
                                                                fchown(outfd, uid, gid);
                                                                fchflags(outfd, st.st_flags);
index a982b6e..d9f5de1 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/edgroup.c,v 1.8 1999/08/28 01:19:16 peter Exp $
- * $DragonFly: src/usr.sbin/pw/edgroup.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/edgroup.c,v 1.9 2004/03/08 20:31:37 kensmith Exp $
  */
 
 #include <stdio.h>
@@ -66,7 +65,7 @@ editgroups(char *name, char **groups)
        strcpy(grouptmp, groupfile);
        strcat(grouptmp, ".new");
 
-       if ((infd = open(groupfile, O_RDWR | O_CREAT, 0644)) != -1) {
+       if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) {
                FILE           *infp;
 
                if ((infp = fdopen(infd, "r+")) == NULL)
@@ -74,7 +73,7 @@ editgroups(char *name, char **groups)
                else {
                        int             outfd;
 
-                       if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, 0644)) != -1) {
+                       if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC, 0644)) != -1) {
                                FILE           *outfp;
 
                                if ((outfp = fdopen(outfd, "w+")) == NULL)
@@ -205,8 +204,7 @@ editgroups(char *name, char **groups)
 
                                                        /*
                                                         * This is a gross hack, but we may have corrupted the
-                                                        * original file. Unfortunately, it will lose preservation
-                                                        * of the inode.
+                                                        * original file.
                                                         */
                                                        if (fflush(infp) == EOF || ferror(infp))
                                                                rc = rename(grouptmp, groupfile) == 0;
index ac20688..326827d 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/fileupd.c,v 1.9 1999/10/26 04:27:13 davidn Exp $
- * $DragonFly: src/usr.sbin/pw/fileupd.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/fileupd.c,v 1.10 2004/03/08 20:31:37 kensmith Exp $
  */
 
 #include <stdio.h>
@@ -74,7 +73,7 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const
        if (pfxlen <= 1)
                rc = EINVAL;
        else {
-               int    infd = open(filename, O_RDWR | O_CREAT, fmode);
+               int    infd = open(filename, O_RDWR | O_CREAT | O_EXLOCK, fmode);
 
                if (infd == -1)
                        rc = errno;
@@ -90,7 +89,7 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const
 
                                strcpy(file, filename);
                                strcat(file, ".new");
-                               outfd = open(file, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, fmode);
+                               outfd = open(file, O_RDWR | O_CREAT | O_TRUNC, fmode);
                                if (outfd == -1)
                                        rc = errno;
                                else {
@@ -181,8 +180,6 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const
                                                                 * to 'file'.
                                                                 * This is a gross hack, but we may have
                                                                 * corrupted the original file
-                                                                * Unfortunately, it will lose the inode
-                                                                * and hence the lock.
                                                                 */
                                                                if (fflush(infp) == EOF || ferror(infp))
                                                                        rename(file, filename);
index b92bbd7..e6ff9a8 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/grupd.c,v 1.8 1999/10/26 04:27:14 davidn Exp $
- * $DragonFly: src/usr.sbin/pw/grupd.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/grupd.c,v 1.10 2001/08/30 06:32:17 dd Exp $
  */
 
 #include <stdio.h>
index 6d34eae..1b35be0 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/psdate.c,v 1.6.2.1 2000/06/28 19:19:04 ache Exp $
- * $DragonFly: src/usr.sbin/pw/psdate.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/psdate.c,v 1.8 2004/06/17 14:07:16 robert Exp $
  */
 
 #include <stdio.h>
@@ -232,8 +231,8 @@ parse_date(time_t dt, char const * str)
                 * Skip past any weekday prefix
                 */
                weekday(&str);
-               str = strncpy(tmp, str, sizeof tmp - 1);
-               tmp[sizeof tmp - 1] = '\0';
+               strlcpy(tmp, str, sizeof(tmp));
+               str = tmp;
                T = localtime(&dt);
 
                /*
@@ -273,19 +272,15 @@ parse_date(time_t dt, char const * str)
                        if ((q = strpbrk(p, " \t")) != NULL) {  /* Time first? */
                                int             l = q - str;
 
-                               strncpy(timestr, str, l);
-                               timestr[l] = '\0';
-                               strncpy(datestr, q + 1, sizeof datestr);
-                               datestr[sizeof datestr - 1] = '\0';
+                               strlcpy(timestr, str, l + 1);
+                               strlcpy(datestr, q + 1, sizeof(datestr));
                                parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
                                parse_datesub(datestr, &T->tm_mday, &T->tm_mon, &T->tm_year);
                        } else if ((q = strrchr(tmp, ' ')) != NULL) {   /* Time last */
                                int             l = q - tmp;
 
-                               strncpy(timestr, q + 1, sizeof timestr);
-                               timestr[sizeof timestr - 1] = '\0';
-                               strncpy(datestr, tmp, l);
-                               datestr[l] = '\0';
+                               strlcpy(timestr, q + 1, sizeof(timestr));
+                               strlcpy(datestr, tmp, l + 1);
                        } else  /* Bail out */
                                return dt;
                        parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
index f234cad..56a7445 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/psdate.h,v 1.4 1999/08/28 01:19:17 peter Exp $
- * $DragonFly: src/usr.sbin/pw/psdate.h,v 1.3 2003/11/03 19:31:41 eirikn Exp $
+ * $FreeBSD: src/usr.sbin/pw/psdate.h,v 1.5 2002/07/11 19:07:35 alfred Exp $
  */
 
 #ifndef _PSDATE_H_
index dd9dcb9..7464a73 100644 (file)
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.sbin/pw/pw.8,v 1.19.2.12 2003/05/08 15:01:44 trhodes Exp $
-.\" $DragonFly: src/usr.sbin/pw/pw.8,v 1.5 2008/05/02 02:05:08 swildner Exp $
+.\" $FreeBSD: src/usr.sbin/pw/pw.8,v 1.45 2011/12/22 03:36:54 eadler Exp $
 .\"
-.Dd December 9, 1996
+.Dd December 21, 2011
 .Dt PW 8
 .Os
 .Sh NAME
 .Op Fl g Ar group
 .Op Fl G Ar grouplist
 .Op Fl m
+.Op Fl M Ar mode
 .Op Fl k Ar dir
 .Op Fl w Ar method
 .Op Fl s Ar shell
 .Op Fl o
 .Op Fl L Ar class
-.Op Fl h Ar fd
+.Op Fl h Ar fd | Fl H Ar fd
 .Op Fl N
 .Op Fl P
 .Op Fl Y
@@ -69,6 +69,7 @@
 .Op Fl g Ar group
 .Op Fl G Ar grouplist
 .Op Fl k Ar dir
+.Op Fl M Ar mode
 .Op Fl u Ar min , Ns Ar max
 .Op Fl i Ar min , Ns Ar max
 .Op Fl w Ar method
 .Op Fl G Ar grouplist
 .Op Fl l Ar name
 .Op Fl m
+.Op Fl M Ar mode
 .Op Fl k Ar dir
 .Op Fl w Ar method
 .Op Fl s Ar shell
 .Op Fl L Ar class
-.Op Fl h Ar fd
+.Op Fl h Ar fd | Fl H Ar fd
 .Op Fl N
 .Op Fl P
 .Op Fl Y
 .Op Fl g Ar gid
 .Op Fl M Ar members
 .Op Fl o
-.Op Fl h Ar fd
+.Op Fl h Ar fd | Fl H Ar fd
 .Op Fl N
 .Op Fl P
 .Op Fl Y
 .Op Fl l Ar name
 .Op Fl M Ar members
 .Op Fl m Ar newmembers
-.Op Fl h Ar fd
+.Op Fl d Ar oldmembers
+.Op Fl h Ar fd | Fl H Ar fd
 .Op Fl N
 .Op Fl P
 .Op Fl Y
@@ -399,7 +402,7 @@ may be defined by either its name or group number.
 .It Fl G Ar grouplist
 Set additional group memberships for an account.
 .Ar grouplist
-is a comma-separated list of group names or group numbers.
+is a comma, space or tab-separated list of group names or group numbers.
 The user's name is added to the group lists in
 .Pa /etc/group ,
 and
@@ -428,6 +431,11 @@ The new home directory is populated with the contents of the
 .Ar skeleton
 directory, which typically contains a set of shell configuration files that the
 user may personalize to taste.
+Files in this directory are usually named
+.Pa dot . Ns Aq Ar config
+where the
+.Pa dot
+prefix will be stripped.
 When
 .Fl m
 is used on an account with
@@ -444,6 +452,16 @@ option (see below), bearing the name of the new account.
 This can be overridden by the
 .Fl d
 option on the command line, if desired.
+.It Fl M Ar mode
+Create the user's home directory with the specified
+.Ar mode ,
+modified by the current
+.Xr umask 2 .
+If omitted, it is derived from the parent process'
+.Xr umask 2 .
+This option is only useful in combination with the
+.Fl m
+flag.
 .It Fl k Ar dir
 Set the
 .Ar skeleton
@@ -508,6 +526,12 @@ is given as the argument
 then the password will be set to
 .Ql \&* ,
 rendering the account inaccessible via password-based login.
+.It Fl H Ar fd
+Read an encrypted password string from the specified file descriptor.
+This is like
+.Fl h ,
+but the password should be supplied already encrypted in a form
+suitable for writing directly to the password database.
 .El
 .Pp
 It is possible to use
@@ -592,6 +616,9 @@ Set the default
 directory, from which prototype shell and other initialization files are copied when
 .Nm
 creates a user's home directory.
+See description of
+.Fl k
+for naming conventions of these files.
 .It Xo
 .Fl u Ar min , Ns Ar max ,
 .Fl i Ar min , Ns Ar max
@@ -689,6 +716,17 @@ are also removed if the user's uid is unique and not also used by another accoun
 system.
 .Pp
 The
+.Ar usermod
+command adds one additional option:
+.Bl -tag -width "-G grouplist"
+.It Fl l Ar name
+This option allows changing of an existing account name to
+.Ql \&name .
+The new name must not already exist, and any attempt to duplicate an
+existing account name will be rejected.
+.El
+.Pp
+The
 .Ar usershow
 command allows viewing of an account in one of two formats.
 By default, the format is identical to the format used in
@@ -752,6 +790,15 @@ of existing users to a group without replacing the existing list of
 members.
 Login names or user ids may be used, and duplicate users are
 silently eliminated.
+.It Fl d Ar oldmembers
+Similar to
+.Fl M ,
+this option allows the
+.Em deletion
+of existing users from a group without replacing the existing list of
+members.
+Login names or user ids may be used, and duplicate users are
+silently eliminated.
 .El
 .Pp
 .Ar groupadd
@@ -807,12 +854,48 @@ The
 and
 .Ar unlock
 commands take a user name or uid of the account to lock or unlock,
-respectively.  The
+respectively.
+The
 .Fl V ,
 .Fl C ,
 and
 .Fl q
 options as described above are accepted by these commands.
+.Sh NOTES
+For a summary of options available with each command, you can use
+.Dl pw [command] help
+For example,
+.Dl pw useradd help
+lists all available options for the useradd operation.
+.Pp
+The
+.Nm
+utility allows 8-bit characters in the passwd GECOS field (user's full name,
+office, work and home phone number subfields), but disallows them in
+user login and group names.
+Use 8-bit characters with caution, as connection to the Internet will
+require that your mail transport program supports 8BITMIME, and will
+convert headers containing 8-bit characters to 7-bit quoted-printable
+format.
+.Xr sendmail 8
+does support this.
+Use of 8-bit characters in the GECOS field should be used in
+conjunction with the user's default locale and character set
+and should not be implemented without their use.
+Using 8-bit characters may also affect other
+programs that transmit the contents of the GECOS field over the
+Internet, such as
+.Xr fingerd 8 ,
+and a small number of TCP/IP clients, such as IRC, where full names
+specified in the passwd file may be used by default.
+.Pp
+The
+.Nm
+utility writes a log to the
+.Pa /var/log/userlog
+file when actions such as user or group additions or deletions occur.
+The location of this logfile can be changed in
+.Xr pw.conf 5 .
 .Sh FILES
 .Bl -tag -width /etc/master.passwd.new -compact
 .It Pa /etc/master.passwd
@@ -834,7 +917,7 @@ Pw default options file
 .It Pa /var/log/userlog
 User/group modification logfile
 .El
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 The
 .Nm
 utility returns EXIT_SUCCESS on successful operation, otherwise
@@ -905,44 +988,10 @@ Update error for passwd or group database files.
 No base home directory configured.
 .El
 .El
-.Sh NOTES
-For a summary of options available with each command, you can use
-.Dl pw [command] help
-For example,
-.Dl pw useradd help
-lists all available options for the useradd operation.
-.Pp
-The
-.Nm
-utility allows 8-bit characters in the passwd GECOS field (user's full name,
-office, work and home phone number subfields), but disallows them in
-user login and group names.
-Use 8-bit characters with caution, as connection to the Internet will
-require that your mail transport program supports 8BITMIME, and will
-convert headers containing 8-bit characters to 7-bit quoted-printable
-format.
-.Xr sendmail 8
-does support this.
-Use of 8-bit characters in the GECOS field should be used in
-conjunction with the user's default locale and character set
-and should not be implemented without their use.
-Using 8-bit characters may also affect other
-programs that transmit the contents of the GECOS field over the
-Internet, such as
-.Xr fingerd 8 ,
-and a small number of TCP/IP clients, such as IRC, where full names
-specified in the passwd file may be used by default.
-.Pp
-The
-.Nm
-utility writes a log to the
-.Pa /var/log/userlog
-file when actions such as user or group additions or deletions occur.
-The location of this logfile can be changed in
-.Xr pw.conf 5 .
 .Sh SEE ALSO
 .Xr chpass 1 ,
 .Xr passwd 1 ,
+.Xr umask 2 ,
 .Xr group 5 ,
 .Xr login.conf 5 ,
 .Xr passwd 5 ,
index 1608377..f9e3112 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw.c,v 1.18.2.5 2001/07/19 01:46:55 kris Exp $
- * $DragonFly: src/usr.sbin/pw/pw.c,v 1.3 2004/12/18 22:48:04 swildner Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw.c,v 1.33 2008/02/23 01:25:22 scf Exp $
  */
 
 #include <err.h>
@@ -104,18 +103,18 @@ main(int argc, char *argv[])
        static const char *opts[W_NUM][M_NUM] =
        {
                { /* user */
-                       "V:C:qn:u:c:d:e:p:g:G:mk:s:oL:i:w:h:Db:NPy:Y",
+                       "V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
                        "V:C:qn:u:rY",
-                       "V:C:qn:u:c:d:e:p:g:G:ml:k:s:w:L:h:FNPY",
+                       "V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
                        "V:C:qn:u:FPa7",
                        "V:C:q",
                        "V:C:q",
                        "V:C:q"
                },
                { /* grp  */
-                       "V:C:qn:g:h:M:pNPY",
+                       "V:C:qn:g:h:H:M:opNPY",
                        "V:C:qn:g:Y",
-                       "V:C:qn:g:l:h:FM:m:NPY",
+                       "V:C:qn:d:g:l:h:H:FM:m:NPY",
                        "V:C:qn:g:FPa",
                        "V:C:q"
                 }
@@ -127,7 +126,6 @@ main(int argc, char *argv[])
                pw_group
        };
 
-       umask(0);               /* We wish to handle this manually */
        LIST_INIT(&arglist);
 
        setlocale(LC_ALL, "");
@@ -224,7 +222,7 @@ main(int argc, char *argv[])
                        setgrdir(etcpath);
                }
        }
-    
+
        /*
         * Now, let's do the common initialisation
         */
@@ -309,10 +307,12 @@ cmdhelp(int mode, int which)
                                "\t-g grp         initial group\n"
                                "\t-G grp1,grp2   additional groups\n"
                                "\t-m [ -k dir ]  create and set up home\n"
+                               "\t-M mode        home directory permissions\n"
                                "\t-s shell       name of login shell\n"
                                "\t-o             duplicate uid ok\n"
                                "\t-L class       user class\n"
                                "\t-h fd          read password on fd\n"
+                               "\t-H fd          read encrypted password on fd\n"
                                "\t-Y             update NIS maps\n"
                                "\t-N             no update\n"
                                "  Setting defaults:\n"
@@ -325,6 +325,7 @@ cmdhelp(int mode, int which)
                                "\t-G grp1,grp2   additional groups\n"
                                "\t-L class       default user class\n"
                                "\t-k dir         default home skeleton\n"
+                               "\t-M mode        home directory permissions\n"
                                "\t-u min,max     set min,max uids\n"
                                "\t-i min,max     set min,max gids\n"
                                "\t-w method      set default password method\n"
@@ -352,9 +353,11 @@ cmdhelp(int mode, int which)
                                "\t-l name        new login name\n"
                                "\t-L class       user class\n"
                                "\t-m [ -k dir ]  create and set up home\n"
+                               "\t-M mode        home directory permissions\n"
                                "\t-s shell       name of login shell\n"
                                "\t-w method      set new password using method\n"
                                "\t-h fd          read password on fd\n"
+                               "\t-H fd          read encrypted password on fd\n"
                                "\t-Y             update NIS maps\n"
                                "\t-N             no update\n",
                                "usage: pw usershow [uid|name] [switches]\n"
@@ -403,6 +406,7 @@ cmdhelp(int mode, int which)
                                "\t-g gid         group id\n"
                                "\t-M usr1,usr2   replaces users as group members\n"
                                "\t-m usr1,usr2   add users as group members\n"
+                               "\t-d usr1,usr2   delete users as group members\n"
                                "\t-l name        new group name\n"
                                "\t-Y             update NIS maps\n"
                                "\t-N             no update\n",
@@ -428,10 +432,10 @@ cmdhelp(int mode, int which)
 struct carg    *
 getarg(struct cargs * _args, int ch)
 {
-       struct carg    *c = _args->lh_first;
+       struct carg    *c = LIST_FIRST(_args);
 
        while (c != NULL && c->ch != ch)
-               c = c->list.le_next;
+               c = LIST_NEXT(c, list);
        return c;
 }
 
index 2d04080..88c8572 100644 (file)
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.sbin/pw/pw.conf.5,v 1.10.2.3 2001/07/22 12:41:27 dd Exp $
-.\" $DragonFly: src/usr.sbin/pw/pw.conf.5,v 1.2 2003/06/17 04:30:01 dillon Exp $
+.\" $FreeBSD: src/usr.sbin/pw/pw.conf.5,v 1.16 2007/03/30 11:23:10 le Exp $
 .\"
-.Dd December 9, 1996
+.Dd March 30, 2007
 .Dt PW.CONF 5
 .Os
 .Sh NAME
 .Nd format of the pw.conf configuration file
 .Sh DESCRIPTION
 The file
-.Aq Pa /etc/pw.conf
+.In /etc/pw.conf
 contains configuration data for the
 .Xr pw 8
-program.
+utility.
 The
 .Xr pw 8
-program is used for maintenance of the system password and group
+utility is used for maintenance of the system password and group
 files, allowing users and groups to be added, deleted and changed.
 This file may be modified via the
 .Xr pw 8
@@ -50,7 +49,7 @@ command and the
 option, or by editing it directly with a text editor.
 .Pp
 Each line in
-.Aq Pa /etc/pw.conf
+.Pa /etc/pw.conf
 is treated either a comment or as configuration data;
 blank lines and lines commencing with a
 .Ql \&#
@@ -68,7 +67,9 @@ reuse gaps in uid sequences
 .It reusegids
 reuse gaps in gid sequences
 .It nispasswd
-path to the NIS passwd database
+path to the
+.Tn NIS
+passwd database
 .It skeleton
 where to obtain default home contents
 .It newmail
@@ -77,6 +78,8 @@ mail to send to new users
 log user/group modifications to this file
 .It home
 root directory for home directories
+.It homemode
+permissions for home directory
 .It shellpath
 paths in which to locate shell programs
 .It shells
@@ -125,8 +128,9 @@ The final option causes
 .Xr pw 8
 to respond by printing a randomly generated password on stdout.
 This is the preferred and most secure option.
-.Xr Pw 8
-also provides a method of setting a specific password for the new
+The
+.Xr pw 8
+utility also provides a method of setting a specific password for the new
 user via a filehandle (command lines are not secure).
 .Pp
 Both
@@ -155,7 +159,9 @@ user's uid and gid the same.
 If the new user's uid is currently in use as a group id, then the next
 available group id is chosen instead.
 .Pp
-On NIS servers which maintain a separate passwd database to
+On
+.Tn NIS
+servers which maintain a separate passwd database to
 .Pa /etc/master.passwd ,
 this option allows the additional file to be concurrently updated
 as user records are added, modified or removed.
@@ -169,7 +175,8 @@ new home directory is constructed.
 This is
 .Pa /usr/share/skel
 by default.
-.Xr Pw 8 Ns 's
+The
+.Xr pw 8 Ns 's
 .Fl m
 option causes the user's home directory to be created and populated
 using the files contained in the
@@ -198,8 +205,15 @@ keyword is mandatory.
 This specifies the location of the directory in which all new user
 home directories are created.
 .Pp
+The
+.Ar homemode
+keyword is optional.
+It specifies the creation mask of the user's home directory and is modified by
+.Xr umask 2 .
+.Pp
+The
 .Ar shellpath
-specifies a list of directories - separated by colons
+keyword specifies a list of directories - separated by colons
 .Ql \&:
 - which contain the programs used by the login shells.
 .Pp
@@ -233,8 +247,9 @@ irrespective of the
 .Em umask
 normally used by the user.
 .Pp
+The
 .Ar extragroups
-provides an automatic means of placing new users into groups within
+keyword provides an automatic means of placing new users into groups within
 the
 .Pa /etc/groups
 file.
@@ -258,7 +273,7 @@ The
 .Ar maxuid ,
 .Ar mingid ,
 .Ar maxgid
-keywords determines the allowed ranges of automatically allocated user
+keywords determine the allowed ranges of automatically allocated user
 and group id numbers.
 The default values for both user and group ids are 1000 and 32000 as
 minimum and maximum respectively.
@@ -296,6 +311,7 @@ as comments.
 .El
 .Sh SEE ALSO
 .Xr passwd 1 ,
+.Xr umask 2 ,
 .Xr group 5 ,
 .Xr login.conf 5 ,
 .Xr passwd 5 ,
index 8d2d1e1..d02b33c 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw.h,v 1.10.2.2 2001/07/19 01:46:55 kris Exp $
- * $DragonFly: src/usr.sbin/pw/pw.h,v 1.3 2005/05/07 23:42:39 corecode Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw.h,v 1.16 2011/03/08 20:13:29 jkim Exp $
  */
 
 #include <stdio.h>
@@ -82,6 +81,7 @@ struct userconf
        char    *newmail;               /* Mail to send to new accounts */
        char    *logfile;               /* Where to log changes */
        char    *home;                  /* Where to create home directory */
+       mode_t  homemode;               /* Home directory permissions */
        char    *shelldir;              /* Where shells are located */
        char    **shells;               /* List of shells */
        char    *shell_default;         /* Default shell */
@@ -95,6 +95,7 @@ struct userconf
        int     numgroups;              /* (internal) size of default_group array */
 };
 
+#define        _DEF_DIRMODE    (S_IRWXU | S_IRWXG | S_IRWXO)
 #define _PATH_PW_CONF  "/etc/pw.conf"
 #define _UC_MAXLINE    1024
 #define _UC_MAXSHELLS  32
index f9e4723..05c91fc 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw_conf.c,v 1.10.2.2 2001/01/14 08:41:19 dougb Exp $
- * $DragonFly: src/usr.sbin/pw/pw_conf.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw_conf.c,v 1.16 2011/03/08 20:13:29 jkim Exp $
  */
 
 #include <string.h>
@@ -45,6 +44,7 @@ enum {
        _UC_NEWMAIL,
        _UC_LOGFILE,
        _UC_HOMEROOT,
+       _UC_HOMEMODE,
        _UC_SHELLPATH,
        _UC_SHELLS,
        _UC_DEFAULTSHELL,
@@ -88,6 +88,7 @@ static struct userconf config =
        NULL,                   /* Mail to send to new accounts */
        "/var/log/userlog",     /* Where to log changes */
        "/home",                /* Where to create home directory */
+       _DEF_DIRMODE,           /* Home directory perms, modified by umask */
        "/bin",                 /* Where shells are located */
        system_shells,          /* List of shells (first is default) */
        bourne_shell,           /* Default shell */
@@ -112,6 +113,7 @@ static char const *comments[_UC_FIELDS] =
        "\n# Mail this file to new user (/etc/newuser.msg or no)\n",
        "\n# Log add/change/remove information in this file\n",
        "\n# Root directory in which $HOME directory is created\n",
+       "\n# Mode for the new $HOME directory, will be modified by umask\n",
        "\n# Colon separated list of directories containing valid shells\n",
        "\n# Comma separated list of available shells (without paths)\n",
        "\n# Default shell (without path)\n",
@@ -137,6 +139,7 @@ static char const *kwds[] =
        "newmail",
        "logfile",
        "home",
+       "homemode",
        "shellpath",
        "shells",
        "defaultshell",
@@ -253,6 +256,7 @@ read_userconfig(char const * file)
                                static char const toks[] = " \t\r\n,=";
                                char           *q = strtok(NULL, toks);
                                int             i = 0;
+                               mode_t          *modeset;
 
                                while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0)
                                        ++i;
@@ -292,6 +296,12 @@ read_userconfig(char const * file)
                                        config.home = (q == NULL || !boolean_val(q, 1))
                                                ? "/home" : newstr(q);
                                        break;
+                               case _UC_HOMEMODE:
+                                       modeset = setmode(q);
+                                       config.homemode = (q == NULL || !boolean_val(q, 1))
+                                               ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE);
+                                       free(modeset);
+                                       break;
                                case _UC_SHELLPATH:
                                        config.shelldir = (q == NULL || !boolean_val(q, 1))
                                                ? "/bin" : newstr(q);
@@ -411,6 +421,10 @@ write_userconfig(char const * file)
                                case _UC_HOMEROOT:
                                        val = config.home;
                                        break;
+                               case _UC_HOMEMODE:
+                                       sprintf(buf, "%04o", config.homemode);
+                                       quote = 0;
+                                       break;
                                case _UC_SHELLPATH:
                                        val = config.shelldir;
                                        break;
@@ -418,6 +432,8 @@ write_userconfig(char const * file)
                                        for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) {
                                                char    lbuf[64];
                                                int     l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", system_shells[j]);
+                                               if (l < 0)
+                                                       l = 0;
                                                if (l + k + 1 < len || extendline(&buf, &len, len + LNBUFSZ) != -1) {
                                                        strcpy(buf + k, lbuf);
                                                        k += l;
@@ -436,6 +452,8 @@ write_userconfig(char const * file)
                                        for (j = k = 0; j < config.numgroups && config.groups[j] != NULL; j++) {
                                                char    lbuf[64];
                                                int     l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", config.groups[j]);
+                                               if (l < 0)
+                                                       l = 0;
                                                if (l + k + 1 < len || extendline(&buf, &len, len + 1024) != -1) {
                                                        strcpy(buf + k, lbuf);
                                                        k +=  l;
index f3ca55c..3ba7e7d 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw_group.c,v 1.12.2.1 2000/06/28 19:19:04 ache Exp $
- * $DragonFly: src/usr.sbin/pw/pw_group.c,v 1.3 2004/09/25 20:38:21 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw_group.c,v 1.16 2008/02/23 01:25:22 scf Exp $
  */
 
 #include <ctype.h>
 #include <err.h>
 #include <termios.h>
+#include <stdbool.h>
 #include <unistd.h>
 
 #include "pw.h"
 #include "bitmap.h"
 
 
+static struct passwd *lookup_pwent(const char *user);
+static void    delete_members(char ***members, int *grmembers, int *i,
+    struct carg *arg, struct group *grp);
 static int      print_group(struct group * grp, int pretty);
 static gid_t    gr_gidpolicy(struct userconf * cnf, struct cargs * args);
 
@@ -168,11 +171,13 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
         * software.
         */
 
-       if ((arg = getarg(args, 'h')) != NULL) {
+       if ((arg = getarg(args, 'h')) != NULL ||
+           (arg = getarg(args, 'H')) != NULL) {
                if (strcmp(arg->val, "-") == 0)
                        grp->gr_passwd = "*";   /* No access */
                else {
                        int             fd = atoi(arg->val);
+                       int             precrypt = (arg->ch == 'H');
                        int             b;
                        int             istty = isatty(fd);
                        struct termios  t;
@@ -206,41 +211,49 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
                                *p = '\0';
                        if (!*line)
                                errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
-                       grp->gr_passwd = pw_pwcrypt(line);
+                       if (precrypt) {
+                               if (strchr(line, ':') != NULL)
+                                       return EX_DATAERR;
+                               grp->gr_passwd = line;
+                       } else
+                               grp->gr_passwd = pw_pwcrypt(line);
                }
        }
 
-       if (((arg = getarg(args, 'M')) != NULL || (arg = getarg(args, 'm')) != NULL) && arg->val) {
+       if (((arg = getarg(args, 'M')) != NULL ||
+           (arg = getarg(args, 'd')) != NULL ||
+           (arg = getarg(args, 'm')) != NULL) && arg->val) {
                int     i = 0;
                char   *p;
                struct passwd   *pwd;
 
                /* Make sure this is not stay NULL with -M "" */
                extendarray(&members, &grmembers, 200);
-               if (arg->ch == 'm') {
+               if (arg->ch == 'd')
+                       delete_members(&members, &grmembers, &i, arg, grp);
+               else if (arg->ch == 'm') {
                        int     k = 0;
 
                        while (grp->gr_mem[k] != NULL) {
-                               if (extendarray(&members, &grmembers, i + 2) != -1) {
+                               if (extendarray(&members, &grmembers, i + 2) != -1)
                                        members[i++] = grp->gr_mem[k];
-                               }
                                k++;
                        }
                }
-               for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
-                       int     j;
-                       if ((pwd = GETPWNAM(p)) == NULL) {
-                               if (!isdigit((unsigned char)*p) || (pwd = getpwuid((uid_t) atoi(p))) == NULL)
-                                       errx(EX_NOUSER, "user `%s' does not exist", p);
+
+               if (arg->ch != 'd')
+                       for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
+                               int     j;
+
+                               /*
+                                * Check for duplicates
+                                */
+                               pwd = lookup_pwent(p);
+                               for (j = 0; j < i && strcmp(members[j], pwd->pw_name) != 0; j++)
+                                       ;
+                               if (j == i && extendarray(&members, &grmembers, i + 2) != -1)
+                                       members[i++] = newstr(pwd->pw_name);
                        }
-                       /*
-                        * Check for duplicates
-                        */
-                       for (j = 0; j < i && strcmp(members[j], pwd->pw_name)!=0; j++)
-                               ;
-                       if (j == i && extendarray(&members, &grmembers, i + 2) != -1)
-                               members[i++] = newstr(pwd->pw_name);
-               }
                while (i < grmembers)
                        members[i++] = NULL;
                grp->gr_mem = members;
@@ -275,6 +288,63 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
 }
 
 
+/*
+ * Lookup a passwd entry using a name or UID.
+ */
+static struct passwd *
+lookup_pwent(const char *user)
+{
+       struct passwd *pwd;
+
+       if ((pwd = GETPWNAM(user)) == NULL &&
+           (!isdigit((unsigned char)*user) ||
+           (pwd = getpwuid((uid_t) atoi(user))) == NULL))
+               errx(EX_NOUSER, "user `%s' does not exist", user);
+
+       return (pwd);
+}
+
+
+/*
+ * Delete requested members from a group.
+ */
+static void
+delete_members(char ***members, int *grmembers, int *i, struct carg *arg,
+    struct group *grp)
+{
+       bool matchFound;
+       char *user;
+       char *valueCopy;
+       char *valuePtr;
+       int k;
+       struct passwd *pwd;
+
+       k = 0;
+       while (grp->gr_mem[k] != NULL) {
+               matchFound = false;
+               if ((valueCopy = strdup(arg->val)) == NULL)
+                       errx(EX_UNAVAILABLE, "out of memory");
+               valuePtr = valueCopy;
+               while ((user = strsep(&valuePtr, ", \t")) != NULL) {
+                       pwd = lookup_pwent(user);
+                       if (strcmp(grp->gr_mem[k], pwd->pw_name) == 0) {
+                               matchFound = true;
+                               break;
+                       }
+               }
+               free(valueCopy);
+
+               if (!matchFound &&
+                   extendarray(members, grmembers, *i + 2) != -1)
+                       (*members)[(*i)++] = grp->gr_mem[k];
+
+               k++;
+       }
+
+       return;
+}
+
+
 static          gid_t
 gr_gidpolicy(struct userconf * cnf, struct cargs * args)
 {
index c5ede74..e432b6b 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw_log.c,v 1.5.2.1 2000/06/28 19:19:04 ache Exp $
- * $DragonFly: src/usr.sbin/pw/pw_log.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw_log.c,v 1.6 2000/06/22 16:48:41 ache Exp $
  */
 
 #include <fcntl.h>
index 6755e99..de7bd35 100644 (file)
  * 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.sbin/pw/pw_user.c,v 1.34.2.13 2003/02/01 21:20:10 gad Exp $
- * $DragonFly: src/usr.sbin/pw/pw_user.c,v 1.4 2004/11/30 20:12:21 joerg Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw_user.c,v 1.72 2012/02/22 06:27:20 kevlo Exp $
  */
 
 #include <ctype.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <unistd.h>
-#include <utmp.h>
 #include <login_cap.h>
-#if defined(USE_MD5RAND)
-#include <md5.h>
-#endif
 #include "pw.h"
 #include "bitmap.h"
 
-#if (MAXLOGNAME-1) > UT_NAMESIZE
-#define LOGNAMESIZE UT_NAMESIZE
-#else
 #define LOGNAMESIZE (MAXLOGNAME-1)
-#endif
 
 static         char locked_str[] = "*LOCKED*";
 
@@ -65,7 +55,7 @@ static char    *pw_shellpolicy(struct userconf * cnf, struct cargs * args, char
 static char    *pw_password(struct userconf * cnf, struct cargs * args, char const * user);
 static char    *shell_path(char const * path, char *shells[], char *sh);
 static void     rmat(uid_t uid);
-static void    rmskey(char const * name);
+static void     rmopie(char const * name);
 
 /*-
  * -C config      configuration file
@@ -84,6 +74,7 @@ static void   rmskey(char const * name);
  * -L class       user class
  * -l name        new login name
  * -h fd          password filehandle
+ * -H fd          encrypted password filehandle
  * -F             force print or add
  *   Setting defaults:
  * -D             set user defaults
@@ -112,6 +103,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
        struct stat     st;
        char            line[_PASSWORD_LEN+1];
        FILE           *fp;
+       char *dmode_c;
+       void *set = NULL;
 
        static struct passwd fakeuser =
        {
@@ -125,9 +118,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                "/nonexistent",
                "/bin/sh",
                0
-#if defined(__DragonFly__)
                ,0
-#endif
        };
 
 
@@ -153,6 +144,15 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                cnf->home = arg->val;
        }
 
+       if ((arg = getarg(args, 'M')) != NULL) {
+               dmode_c = arg->val;
+               if ((set = setmode(dmode_c)) == NULL)
+                       errx(EX_DATAERR, "invalid directory creation mode '%s'",
+                           dmode_c);
+               cnf->homemode = getmode(set, _DEF_DIRMODE);
+               free(set);
+       }
+
        /*
         * If we'll need to use it or we're updating it,
         * then create the base home directory if necessary
@@ -178,19 +178,23 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                        if (strchr(cnf->home+1, '/') == NULL) {
                                strcpy(dbuf, "/usr");
                                strncat(dbuf, cnf->home, MAXPATHLEN-5);
-                               if (mkdir(dbuf, 0755) != -1 || errno == EEXIST) {
+                               if (mkdir(dbuf, _DEF_DIRMODE) != -1 || errno == EEXIST) {
                                        chown(dbuf, 0, 0);
-                                       symlink(dbuf, cnf->home);
+                                       /*
+                                        * Skip first "/" and create symlink:
+                                        * /home -> usr/home
+                                        */
+                                       symlink(dbuf+1, cnf->home);
                                }
                                /* If this falls, fall back to old method */
                        }
-                       p = strncpy(dbuf, cnf->home, sizeof dbuf);
-                       dbuf[MAXPATHLEN-1] = '\0';
+                       strlcpy(dbuf, cnf->home, sizeof(dbuf));
+                       p = dbuf;
                        if (stat(dbuf, &st) == -1) {
                                while ((p = strchr(++p, '/')) != NULL) {
                                        *p = '\0';
                                        if (stat(dbuf, &st) == -1) {
-                                               if (mkdir(dbuf, 0755) == -1)
+                                               if (mkdir(dbuf, _DEF_DIRMODE) == -1)
                                                        goto direrr;
                                                chown(dbuf, 0, 0);
                                        } else if (!S_ISDIR(st.st_mode))
@@ -199,7 +203,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                }
                        }
                        if (stat(dbuf, &st) == -1) {
-                               if (mkdir(dbuf, 0755) == -1) {
+                               if (mkdir(dbuf, _DEF_DIRMODE) == -1) {
                                direrr: err(EX_OSFILE, "mkdir '%s'", dbuf);
                                }
                                chown(dbuf, 0, 0);
@@ -374,10 +378,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
 
                        if (!PWALTDIR()) {
                                /*
-                                * Remove skey record from /etc/skeykeys
+                                * Remove opie record from /etc/opiekeys
                                 */
 
-                               rmskey(pwd->pw_name);
+                               rmopie(pwd->pw_name);
 
                                /*
                                 * Remove crontabs
@@ -393,7 +397,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                         * invalidated by deletion
                         */
                        sprintf(file, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
-                       strlcpy(home, pwd->pw_dir, sizeof home);
+                       strlcpy(home, pwd->pw_dir, sizeof(home));
 
                        rc = delpwent(pwd);
                        if (rc == -1)
@@ -533,7 +537,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                }
 
                if ((arg  = getarg(args, 'd')) != NULL) {
-                       edited = strcmp(pwd->pw_dir, arg->val) != 0;
+                       if (strcmp(pwd->pw_dir, arg->val))
+                               edited = 1;
                        if (stat(pwd->pw_dir = arg->val, &st) == -1) {
                                if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0)
                                  warnx("WARNING: home `%s' does not exist", pwd->pw_dir);
@@ -541,7 +546,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                warnx("WARNING: home `%s' is not a directory", pwd->pw_dir);
                }
 
-               if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) {
+               if ((arg = getarg(args, 'w')) != NULL &&
+                   getarg(args, 'h') == NULL && getarg(args, 'H') == NULL) {
                        login_cap_t *lc;
 
                        lc = login_getpwclass(pwd);
@@ -599,7 +605,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                }
        }
 
-       if ((arg = getarg(args, 'h')) != NULL) {
+       if ((arg = getarg(args, 'h')) != NULL ||
+           (arg = getarg(args, 'H')) != NULL) {
                if (strcmp(arg->val, "-") == 0) {
                        if (!pwd->pw_passwd || *pwd->pw_passwd != '*') {
                                pwd->pw_passwd = "*";   /* No access */
@@ -607,6 +614,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                        }
                } else {
                        int             fd = atoi(arg->val);
+                       int             precrypt = (arg->ch == 'H');
                        int             b;
                        int             istty = isatty(fd);
                        struct termios  t;
@@ -621,7 +629,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                        /* Disable echo */
                                        n.c_lflag &= ~(ECHO);
                                        tcsetattr(fd, TCSANOW, &n);
-                                       printf("%sassword for user %s:", (mode == M_UPDATE) ? "New p" : "P", pwd->pw_name);
+                                       printf("%s%spassword for user %s:",
+                                            (mode == M_UPDATE) ? "new " : "",
+                                            precrypt ? "encrypted " : "",
+                                            pwd->pw_name);
                                        fflush(stdout);
                                }
                        }
@@ -632,20 +643,27 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
                                fflush(stdout);
                        }
                        if (b < 0) {
-                               warn("-h file descriptor");
+                               warn("-%c file descriptor", precrypt ? 'H' :
+                                   'h');
                                return EX_IOERR;
                        }
                        line[b] = '\0';
-                       if ((p = strpbrk(line, " \t\r\n")) != NULL)
+                       if ((p = strpbrk(line, "\r\n")) != NULL)
                                *p = '\0';
                        if (!*line)
                                errx(EX_DATAERR, "empty password read on file descriptor %d", fd);
-                       lc = login_getpwclass(pwd);
-                       if (lc == NULL ||
-                           login_setcryptfmt(lc, "md5", NULL) == NULL)
-                               warn("setting crypt(3) format");
-                       login_close(lc);
-                       pwd->pw_passwd = pw_pwcrypt(line);
+                       if (precrypt) {
+                               if (strchr(line, ':') != NULL)
+                                       return EX_DATAERR;
+                               pwd->pw_passwd = line;
+                       } else {
+                               lc = login_getpwclass(pwd);
+                               if (lc == NULL ||
+                                   login_setcryptfmt(lc, "md5", NULL) == NULL)
+                                       warn("setting crypt(3) format");
+                               login_close(lc);
+                               pwd->pw_passwd = pw_pwcrypt(line);
+                       }
                        edited = 1;
                }
        }
@@ -742,7 +760,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
         * existing files will *not* be overwritten.
         */
        if (!PWALTDIR() && getarg(args, 'm') != NULL && pwd->pw_dir && *pwd->pw_dir == '/' && pwd->pw_dir[1]) {
-               copymkdir(pwd->pw_dir, cnf->dotdir, 0755, pwd->pw_uid, pwd->pw_gid);
+               copymkdir(pwd->pw_dir, cnf->dotdir, cnf->homemode, pwd->pw_uid, pwd->pw_gid);
                pw_log(cnf, mode, W_USER, "%s(%ld) home %s made",
                       pwd->pw_name, (long) pwd->pw_uid, pwd->pw_dir);
        }
@@ -887,9 +905,9 @@ pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer
                        if ((grp = GETGRNAM(nam)) != NULL)
                                gid = grp->gr_gid;
                }
-               a_gid = grpargs.lh_first;
+               a_gid = LIST_FIRST(&grpargs);
                while (a_gid != NULL) {
-                       struct carg    *t = a_gid->list.le_next;
+                       struct carg    *t = LIST_NEXT(a_gid, list);
                        LIST_REMOVE(a_gid, list);
                        a_gid = t;
                }
@@ -960,8 +978,7 @@ shell_path(char const * path, char *shells[], char *sh)
                /*
                 * We need to search paths
                 */
-               strncpy(paths, path, sizeof paths);
-               paths[sizeof paths - 1] = '\0';
+               strlcpy(paths, path, sizeof(paths));
                for (p = strtok(paths, ": \t\r\n"); p != NULL; p = strtok(NULL, ": \t\r\n")) {
                        int             i;
                        static char     shellpath[256];
@@ -996,13 +1013,15 @@ pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell)
        return shell_path(cnf->shelldir, cnf->shells, sh ? sh : cnf->shell_default);
 }
 
-static char const chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.";
+#define        SALTSIZE        32
+
+static char const chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
 
 char           *
 pw_pwcrypt(char *password)
 {
        int             i;
-       char            salt[12];
+       char            salt[SALTSIZE + 1];
        char            *cryptpw;
 
        static char     buf[256];
@@ -1010,9 +1029,9 @@ pw_pwcrypt(char *password)
        /*
         * Calculate a salt value
         */
-       for (i = 0; i < 8; i++)
-               salt[i] = chars[arc4random() % 63];
-       salt[i] = '\0';
+       for (i = 0; i < SALTSIZE; i++)
+               salt[i] = chars[arc4random_uniform(sizeof(chars) - 1)];
+       salt[SALTSIZE] = '\0';
 
        cryptpw = crypt(password, salt);
        if (cryptpw == NULL)
@@ -1020,75 +1039,25 @@ pw_pwcrypt(char *password)
        return strcpy(buf, cryptpw);
 }
 
-#if defined(USE_MD5RAND)
-u_char *
-pw_getrand(u_char *buf, int len)       /* cryptographically secure rng */
-{
-       int i;
-       for (i=0;i<len;i+=16) {
-               u_char ubuf[16];
-
-               MD5_CTX md5_ctx;
-               struct timeval tv, tvo;
-               struct rusage ru;
-               int n=0;
-               int t;
-
-               MD5Init (&md5_ctx);
-               t=getpid();
-               MD5Update (&md5_ctx, (u_char*)&t, sizeof t);
-               t=getppid();
-               MD5Update (&md5_ctx, (u_char*)&t, sizeof t);
-               gettimeofday (&tvo, NULL);
-               do {
-                       getrusage (RUSAGE_SELF, &ru);
-                       MD5Update (&md5_ctx, (u_char*)&ru, sizeof ru);
-                       gettimeofday (&tv, NULL);
-                       MD5Update (&md5_ctx, (u_char*)&tv, sizeof tv);
-               } while (n++<20 || tv.tv_usec-tvo.tv_usec<100*1000);
-               MD5Final (ubuf, &md5_ctx);
-               memcpy(buf+i, ubuf, MIN(16, len-i));
-       }
-       return buf;
-}
-
-#else  /* Portable version */
-
-static u_char *
-pw_getrand(u_char *buf, int len)
-{
-       int i;
-
-       srandomdev();
-       for (i = 0; i < len; i++) {
-               unsigned long val = random();
-               /* Use all bits in the random value */
-               buf[i]=(u_char)((val >> 24) ^ (val >> 16) ^ (val >> 8) ^ val);
-       }
-       return buf;
-}
-
-#endif
 
 static char    *
 pw_password(struct userconf * cnf, struct cargs * args, char const * user)
 {
        int             i, l;
        char            pwbuf[32];
-       u_char          rndbuf[sizeof pwbuf];
 
        switch (cnf->default_password) {
        case -1:                /* Random password */
                l = (arc4random() % 8 + 8);     /* 8 - 16 chars */
-               pw_getrand(rndbuf, l);
                for (i = 0; i < l; i++)
-                       pwbuf[i] = chars[rndbuf[i] % (sizeof(chars)-1)];
+                       pwbuf[i] = chars[arc4random_uniform(sizeof(chars)-1)];
                pwbuf[i] = '\0';
 
                /*
                 * We give this information back to the user
                 */
-               if (getarg(args, 'h') == NULL && getarg(args, 'N') == NULL) {
+               if (getarg(args, 'h') == NULL && getarg(args, 'H') == NULL &&
+                   getarg(args, 'N') == NULL) {
                        if (isatty(STDOUT_FILENO))
                                printf("Password for '%s' is: ", user);
                        printf("%s\n", pwbuf);
@@ -1104,8 +1073,7 @@ pw_password(struct userconf * cnf, struct cargs * args, char const * user)
                return "*";
 
        case 1:         /* user's name */
-               strncpy(pwbuf, user, sizeof pwbuf);
-               pwbuf[sizeof pwbuf - 1] = '\0';
+               strlcpy(pwbuf, user, sizeof(pwbuf));
                break;
        }
        return pw_pwcrypt(pwbuf);
@@ -1130,17 +1098,14 @@ print_user(struct passwd * pwd, int pretty, int v7)
                struct tm *    tptr;
 
                if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
-                       strncpy(uname, p, sizeof uname);
-                       uname[sizeof uname - 1] = '\0';
+                       strlcpy(uname, p, sizeof(uname));
                        if ((p = strtok(NULL, ",")) != NULL) {
-                               strncpy(office, p, sizeof office);
-                               office[sizeof office - 1] = '\0';
+                               strlcpy(office, p, sizeof(office));
                                if ((p = strtok(NULL, ",")) != NULL) {
-                                       strncpy(wphone, p, sizeof wphone);
-                                       wphone[sizeof wphone - 1] = '\0';
+                                       strlcpy(wphone, p, sizeof(wphone));
                                        if ((p = strtok(NULL, "")) != NULL) {
-                                               strncpy(hphone, p, sizeof hphone);
-                                               hphone[sizeof hphone - 1] = '\0';
+                                               strlcpy(hphone, p,
+                                                   sizeof(hphone));
                                        }
                                }
                        }
@@ -1277,10 +1242,10 @@ rmat(uid_t uid)
 }
 
 static void
-rmskey(char const * name)
+rmopie(char const * name)
 {
-       static const char etcskey[] = "/etc/skeykeys";
-       FILE   *fp = fopen(etcskey, "r+");
+       static const char etcopie[] = "/etc/opiekeys";
+       FILE   *fp = fopen(etcopie, "r+");
 
        if (fp != NULL) {
                char    tmp[1024];
index de7a961..7026749 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pw_vpw.c,v 1.3 2000/01/15 00:20:21 davidn Exp $
- * $DragonFly: src/usr.sbin/pw/pw_vpw.c,v 1.4 2005/12/05 02:40:27 swildner Exp $
+ * $FreeBSD: src/usr.sbin/pw/pw_vpw.c,v 1.4 2004/06/17 14:07:16 robert Exp $
  */
 
 #include <stdio.h>
@@ -57,8 +56,7 @@ vnextpwent(char const * nam, uid_t uid, int doclose)
        struct passwd * pw = NULL;
        static char pwtmp[1024];
 
-        strncpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof pwtmp);
-        pwtmp[sizeof pwtmp - 1] = '\0';
+        strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp));
 
         if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) {
                 int done = 0;
@@ -205,8 +203,7 @@ vnextgrent(char const * nam, gid_t gid, int doclose)
        static int memlen = 0;
 
        extendline(&grtmp, &grlen, MAXPATHLEN);
-       strncpy(grtmp, getgrpath(_GROUP), MAXPATHLEN);
-       grtmp[MAXPATHLEN - 1] = '\0';
+       strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN);
 
        if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) {
                int done = 0;
index fa1c8d2..2c15cde 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pwupd.c,v 1.12.2.4 2001/12/21 15:21:32 nectar Exp $
- * $DragonFly: src/usr.sbin/pw/pwupd.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/pwupd.c,v 1.21 2008/07/17 13:47:59 jhb Exp $
  */
 
 #include <stdio.h>
@@ -109,7 +108,8 @@ fmtpwentry(char *buf, struct passwd * pwd, int type)
        int             l;
        char           *pw;
 
-       pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
+       pw = (type == PWF_MASTER) ?
+           ((pwd->pw_passwd == NULL) ? "" : pwd->pw_passwd) : "*";
 
        if (type == PWF_PASSWD)
                l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
@@ -145,7 +145,8 @@ pw_update(struct passwd * pwd, char const * user, int mode)
         * Note: -C is only available in FreeBSD 2.2 and above
         */
 #ifdef HAVE_PWDB_C
-       if (pwdb("-C", NULL) == 0) {    /* Check only */
+       rc = pwdb("-C", NULL);  /* Check only */
+       if (rc == 0) {
 #else
        {                               /* No -C */
 #endif
@@ -164,6 +165,8 @@ pw_update(struct passwd * pwd, char const * user, int mode)
                else
                        fmtpwentry(pwbuf, pwd, PWF_PASSWD);
 
+               if (l < 0)
+                       l = 0;
                rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
                if (rc == 0) {
 
index 7c890a5..3d57e18 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/pwupd.h,v 1.7 2000/01/15 00:20:22 davidn Exp $
- * $DragonFly: src/usr.sbin/pw/pwupd.h,v 1.4 2004/02/10 02:59:43 rob Exp $
+ * $FreeBSD: src/usr.sbin/pw/pwupd.h,v 1.8 2002/07/11 19:07:35 alfred Exp $
  */
 
 #ifndef _PWUPD_H_
index 3452551..021076d 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/pw/rm_r.c,v 1.5.2.1 2001/07/30 10:19:54 dd Exp $
- * $DragonFly: src/usr.sbin/pw/rm_r.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
+ * $FreeBSD: src/usr.sbin/pw/rm_r.c,v 1.6 2001/06/24 20:25:20 dd Exp $
  */
 
 #include <stdio.h>