And here's a run at Stage 2.  This adapts a subset of programs to use the
pid_*() locking supplied.  The attached patch updates: <pwd.h>, libutil
(libutil.h and pw_util.c), chpass (chpass.c), pw (pw.c), pwd_mkdb
(Makefile, pwd_mkdb.8, pwd_mkdb.c), vipw (vipw.c).  This does NOT include
passwd(1), since that does its dirty work in PAM, which I definately
don't feel like delving into.

Note that this patch MAY be a little off when applied over the previous
patch; I'm working on them in seperate trees, to try and keep the stages
discrete.  But a little manual fiddling should get them reconciled in
short order.


-- 
Matthew Fuller     (MF4839)   |  [EMAIL PROTECTED]
Systems/Network Administrator |  http://www.over-yonder.net/~fullermd/

"The only reason I'm burning my candle at both ends, is because I
      haven't figured out how to light the middle yet"
Index: include/pwd.h
===================================================================
RCS file: /usr/cvs/src/include/pwd.h,v
retrieving revision 1.12
diff -u -r1.12 pwd.h
--- include/pwd.h       9 Jun 2002 19:39:18 -0000       1.12
+++ include/pwd.h       23 Jun 2002 18:16:21 -0000
@@ -66,6 +66,9 @@
 #define        _PATH_MASTERPASSWD      "/etc/master.passwd"
 #define        _MASTERPASSWD           "master.passwd"
 
+#define        _PATH_PWDLOCK           "/var/run/pwd.lock"
+#define        _MODE_PWDLOCK           (S_IRUSR | S_IWUSR)
+
 #define        _PATH_MP_DB             "/etc/pwd.db"
 #define        _MP_DB                  "pwd.db"
 #define        _PATH_SMP_DB            "/etc/spwd.db"
Index: lib/libutil/libutil.h
===================================================================
RCS file: /usr/cvs/src/lib/libutil/libutil.h,v
retrieving revision 1.37
diff -u -r1.37 libutil.h
--- lib/libutil/libutil.h       8 May 2002 00:50:07 -0000       1.37
+++ lib/libutil/libutil.h       23 Jun 2002 18:38:18 -0000
@@ -95,6 +95,8 @@
 int    pw_init(const char *_dir, const char *_master);
 char   *pw_make(struct passwd *_pw);
 int    pw_mkdb(const char *_user);
+int    pw_globlock(int);
+int    pw_globunlock(void);
 int    pw_lock(void);
 struct passwd *pw_scan(const char *_line, int _flags);
 const char *pw_tempname(void);
@@ -124,6 +126,9 @@
 #define        FPARSELN_UNESCCOMM      0x04
 #define        FPARSELN_UNESCREST      0x08
 #define        FPARSELN_UNESCALL       0x0f
+
+/* pw_globlock() */
+#define        PW_NOBLOCK              PID_NOBLOCK
 
 /* pw_scan() */
 #define PWSCAN_MASTER          0x01
Index: lib/libutil/pw_util.c
===================================================================
RCS file: /usr/cvs/src/lib/libutil/pw_util.c,v
retrieving revision 1.25
diff -u -r1.25 pw_util.c
--- lib/libutil/pw_util.c       8 May 2002 14:52:32 -0000       1.25
+++ lib/libutil/pw_util.c       23 Jun 2002 18:46:19 -0000
@@ -79,6 +79,7 @@
 static char passwd_dir[PATH_MAX];
 static char tempname[PATH_MAX];
 static int initialized;
+static int globlocked = 0;
 
 void
 pw_cont(int sig)
@@ -163,6 +164,28 @@
 }
 
 /*
+ * Lock the password subsystem globally.
+ */
+int
+pw_globlock(int flags)
+{
+       int retval;
+
+       if( (retval=pid_begin(_PATH_PWDLOCK, _MODE_PWDLOCK, flags)) == 0 );
+               globlocked=1;
+       return(retval);
+}
+
+/*
+ * Unlock the global lock
+ */
+int pw_globunlock(void)
+{
+       
+       return(pid_end(_PATH_PWDLOCK));
+}
+
+/*
  * Lock the master password file.
  */
 int
@@ -258,10 +281,10 @@
        case 0:
                /* child */
                if (user == NULL)
-                       execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
+                       execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-n",
                            "-d", passwd_dir, tempname, NULL);
                else
-                       execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
+                       execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-n",
                            "-d", passwd_dir, "-u", user, tempname, NULL);
                _exit(1);
        default:
@@ -353,6 +376,11 @@
        }
        if (lockfd != -1)
                close(lockfd);
+       if (globlocked != 0)
+       {
+               globlocked=0;
+               pid_end(_PATH_PWDLOCK);
+       }
        errno = serrno;
 }
 
Index: usr.bin/chpass/chpass.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/chpass/chpass.c,v
retrieving revision 1.23
diff -u -r1.23 chpass.c
--- usr.bin/chpass/chpass.c     8 May 2002 00:54:28 -0000       1.23
+++ usr.bin/chpass/chpass.c     23 Jun 2002 18:42:25 -0000
@@ -258,6 +258,8 @@
        case _PWF_FILES:
                if (pw_init(NULL, NULL))
                        err(1, "pw_init()");
+               if (pw_globlock(PW_NOBLOCK) < 0)
+                       err(1, "pw_globlock()");
                if ((pfd = pw_lock()) == -1) {
                        pw_fini();
                        err(1, "pw_lock()");
Index: usr.sbin/pw/pw.c
===================================================================
RCS file: /usr/cvs/src/usr.sbin/pw/pw.c,v
retrieving revision 1.26
diff -u -r1.26 pw.c
--- usr.sbin/pw/pw.c    9 Jul 2001 09:24:01 -0000       1.26
+++ usr.sbin/pw/pw.c    23 Jun 2002 18:35:28 -0000
@@ -31,8 +31,10 @@
 
 #include <err.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <locale.h>
 #include <paths.h>
+#include <pwd.h>
 #include <sys/wait.h>
 #include "pw.h"
 
@@ -202,6 +204,12 @@
                errx(EX_NOPERM, "you must be root to run this program");
 
        /*
+        * Grab global lock before doing anything
+        */
+       if(pid_begin(_PATH_PWDLOCK, _MODE_PWDLOCK, PID_NOBLOCK) < 0)
+               err(EX_UNAVAILABLE, "%s", _PATH_PWDLOCK);
+
+       /*
         * We should immediately look for the -q 'quiet' switch so that we
         * don't bother with extraneous errors
         */
@@ -259,6 +267,10 @@
                                pw_log(cnf, mode, which, "NIS maps updated");
                }
        }
+
+       /* Release the lock */
+       pid_end(_PATH_PWDLOCK);
+
        return ch;
 }
 
Index: usr.sbin/pwd_mkdb/Makefile
===================================================================
RCS file: /usr/cvs/src/usr.sbin/pwd_mkdb/Makefile,v
retrieving revision 1.8
diff -u -r1.8 Makefile
--- usr.sbin/pwd_mkdb/Makefile  20 Jul 2001 06:20:15 -0000      1.8
+++ usr.sbin/pwd_mkdb/Makefile  23 Jun 2002 18:37:06 -0000
@@ -8,5 +8,9 @@
 SRCS=  pw_scan.c pwd_mkdb.c
 
 CFLAGS+= -I${.CURDIR}/../../lib/libc/gen               # for pw_scan.h
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+LDADD= -lutil
+DPADD= ${LIBUTIL}
 
 .include <bsd.prog.mk>
Index: usr.sbin/pwd_mkdb/pwd_mkdb.8
===================================================================
RCS file: /usr/cvs/src/usr.sbin/pwd_mkdb/pwd_mkdb.8,v
retrieving revision 1.19
diff -u -r1.19 pwd_mkdb.8
--- usr.sbin/pwd_mkdb/pwd_mkdb.8        16 May 2002 02:28:35 -0000      1.19
+++ usr.sbin/pwd_mkdb/pwd_mkdb.8        23 Jun 2002 18:48:48 -0000
@@ -42,6 +42,7 @@
 .Nm
 .Op Fl C
 .Op Fl N
+.Op Fl n
 .Op Fl p
 .Op Fl d Ar directory
 .Op Fl s Ar cachesize
@@ -76,6 +77,13 @@
 to exit with an error if it cannot obtain a lock on the file.  By default,
 we block waiting for a lock on the source file.  The lock is held through
 the rebuilding of the database.
+.It Fl n
+Tell
+.Nm
+to not attempt to grab the auth subsystem lock.  This is really intended
+only to be used internally by programs such as 
+.Xr vipw 8 ;
+use with caution.
 .It Fl p
 Create a Version 7 style password file and install it into
 .Pa /etc/passwd .
Index: usr.sbin/pwd_mkdb/pwd_mkdb.c
===================================================================
RCS file: /usr/cvs/src/usr.sbin/pwd_mkdb/pwd_mkdb.c,v
retrieving revision 1.38
diff -u -r1.38 pwd_mkdb.c
--- usr.sbin/pwd_mkdb/pwd_mkdb.c        9 Mar 2002 03:52:14 -0000       1.38
+++ usr.sbin/pwd_mkdb/pwd_mkdb.c        23 Jun 2002 18:38:01 -0000
@@ -59,6 +59,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <libutil.h>
 
 #include "pw_scan.h"
 
@@ -111,6 +112,7 @@
        u_int method, methoduid;
        int Cflag;
        int nblock = 0;
+       int nolock = 0;
 
        Cflag = 0;
        strcpy(prefix, _PATH_PWD);
@@ -138,6 +140,9 @@
                case 'N':                       /* do not wait for lock */
                        nblock = LOCK_NB;
                        break;
+               case 'n':                       /* do not globlock */
+                       nolock = 1;
+                       break;
                default:
                        usage();
                }
@@ -178,6 +183,9 @@
 
                if (!(fp = fopen(pname, "r")))
                        error(pname);
+               if (nolock != 1)
+                       if(pw_globlock(PW_NOBLOCK) < 0)
+                               error("pw_globlock");
                if (flock(fileno(fp), LOCK_EX|nblock) < 0)
                        error("flock");
                if (fstat(fileno(fp), &st) < 0)
@@ -484,6 +492,10 @@
         */
        if (fclose(fp) == EOF)
                error("close fp");
+
+       if (nolock != 1)
+               if(pw_globunlock() < 0)
+                               error("pw_globunlock");
 
        exit(0);
 }
Index: usr.sbin/vipw/vipw.c
===================================================================
RCS file: /usr/cvs/src/usr.sbin/vipw/vipw.c,v
retrieving revision 1.13
diff -u -r1.13 vipw.c
--- usr.sbin/vipw/vipw.c        8 May 2002 00:54:28 -0000       1.13
+++ usr.sbin/vipw/vipw.c        23 Jun 2002 18:40:50 -0000
@@ -96,6 +96,10 @@
                pw_fini();
                err(1, "pw_lock()");
        }
+       if (pw_globlock(PW_NOBLOCK) < 0) {
+               pw_fini();
+               err(1, "pw_globlock()");
+       }
        if ((tfd = pw_tmp(pfd)) == -1) {
                pw_fini();
                err(1, "pw_tmp()");

Reply via email to