Subject: Re: pwd_mkdb
To: Takahiro Kambe <taca@sky.yamashina.kyoto.jp>
From: Perry E. Metzger <perry@piermont.com>
List: current-users
Date: 04/12/1999 11:45:53
you should send-pr this patch so it is not lost!
Takahiro Kambe <taca@sky.yamashina.kyoto.jp> writes:
> [1 <text/plain; us-ascii (7bit)>]
> Good evening.
>
> In message <19990408182918.A8407@pyy.jmp.fi>
> on Thu, 8 Apr 1999 18:29:19 +0300,
> Jukka Marin <jmarin@pyy.jmp.fi> wrote:
> > > > > I think "-u" option is valuable to implement.
> > > >
> > > > Is there any hope of seeing the -u option in the near future?
> > > O.K., I'll try to implement it this weekend. :-)
> I've called from my boss, and must go to the office today. :-(
> So I don't have much time, I made "-u" option for pwd_mkdb(8), mainly
> borrow codes from FreeBSD version.
>
> > Great! I looked into pwd_mkdb.c and the db(3) man page, but I'd rather
> > leave it to someone who knows what he/she is doing... ;-)
> >
> > Please let me know when a patch is available and I'll try it out right
> > away (a patch for NetBSD 1.3.3 would be the best for me).
> Though I attach the patch, this isn't test verfy much. Please don't use
> this on production systems.
>
> Some note:
>
> In this patch, pw_mkdb_user() is added into passwd and chpass. This
> functionality should be in libutil(3), lib/libutil/passwd.c. It might
> be simple that adding an argument to pw_mkdb(), but it breaks binary
> ompatibitity. So, I add newly pw_mkdb_user().
>
> Thanks in adivese.
>
> P.S.
> I want to change the subject when talking about 1.5 release. :-)
>
> --
> Takahiro Kambe <taca@sky.yamashina.kyoto.jp>
>
> [2 diff <text/plain; us-ascii (7bit)>]
> Index: usr.sbin/pwd_mkdb/pwd_mkdb.c
> --- usr.sbin/pwd_mkdb/pwd_mkdb.c.orig Thu Jan 14 00:45:30 1999
> +++ usr.sbin/pwd_mkdb/pwd_mkdb.c Mon Apr 12 00:00:18 1999
> @@ -91,9 +91,11 @@
> void error __P((char *));
> void wr_error __P((char *));
> int main __P((int, char **));
> +void cp __P((char *, char *, mode_t));
> void mv __P((char *, char *));
> void rm __P((char *));
> int scan __P((FILE *, struct passwd *, int *));
> +int check_user_db __P((char *));
> void usage __P((void));
>
> int
> @@ -105,17 +107,22 @@
> DBT data, key;
> FILE *fp, *oldfp;
> sigset_t set;
> - int ch, cnt, len, makeold, tfd, flags;
> + int ch, cnt, len, makeold, tfd, flags, fflag;
> char *p;
> const char *t;
> char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
> + char pwd_db[MAXPATHLEN], pwd_sdb[MAXPATHLEN];
> int hasyp = 0;
> DBT ypdata, ypkey;
> + char *username;
> + int method, methoduid;
>
> oldfp = NULL;
> strcpy(prefix, "/");
> makeold = 0;
> - while ((ch = getopt(argc, argv, "d:pv")) != -1)
> + username = NULL;
> +
> + while ((ch = getopt(argc, argv, "cd:pu:v")) != -1)
> switch(ch) {
> case 'd':
> strncpy(prefix, optarg, sizeof(prefix));
> @@ -124,6 +131,9 @@
> case 'p': /* create V7 "file.orig" */
> makeold = 1;
> break;
> + case 'u': /* only update this record */
> + username = optarg;
> + break;
> case 'v': /* backward compatible */
> break;
> case '?':
> @@ -133,7 +143,7 @@
> argc -= optind;
> argv += optind;
>
> - if (argc != 1)
> + if (argc != 1 || (username && (*username == '+' || *username == '-')))
> usage();
>
> /*
> @@ -156,11 +166,25 @@
> if (!(fp = fopen(pname, "r")))
> error(pname);
>
> - /* Open the temporary insecure password database. */
> (void)snprintf(pwd_db_tmp, sizeof(pwd_db_tmp), "%s%s.tmp", prefix,
> _PATH_MP_DB);
> - dp = dbopen(pwd_db_tmp,
> - O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
> +
> + if (username) {
> + (void)snprintf(pwd_db, sizeof(pwd_db), "%s/%s", prefix,
> + _PATH_MP_DB);
> + clean = FILE_INSECURE;
> + cp(pwd_db, pwd_db_tmp, PERM_INSECURE);
> + fflag = O_RDWR;
> + method = 0;
> + methoduid = check_user_db(username);
> + } else {
> + fflag = O_RDWR|O_CREAT|O_EXCL;
> + method = R_NOOVERWRITE;
> + methoduid = R_NOOVERWRITE;
> + }
> +
> + /* Open the temporary insecure password database. */
> + dp = dbopen(pwd_db_tmp, fflag, PERM_INSECURE, DB_HASH, &openinfo);
> if (dp == NULL)
> error(pwd_db_tmp);
> clean = FILE_INSECURE;
> @@ -220,47 +244,49 @@
> cnt);
> }
>
> - /* Create insecure data. */
> - p = buf;
> - COMPACT(pwd.pw_name);
> - COMPACT("*");
> - memmove(p, &pwd.pw_uid, sizeof(int));
> - p += sizeof(int);
> - memmove(p, &pwd.pw_gid, sizeof(int));
> - p += sizeof(int);
> - memmove(p, &pwd.pw_change, sizeof(time_t));
> - p += sizeof(time_t);
> - COMPACT(pwd.pw_class);
> - COMPACT(pwd.pw_gecos);
> - COMPACT(pwd.pw_dir);
> - COMPACT(pwd.pw_shell);
> - memmove(p, &pwd.pw_expire, sizeof(time_t));
> - p += sizeof(time_t);
> - memmove(p, &flags, sizeof(int));
> - p += sizeof(int);
> - data.size = p - buf;
> -
> - /* Store insecure by name. */
> - tbuf[0] = _PW_KEYBYNAME;
> - len = strlen(pwd.pw_name);
> - memmove(tbuf + 1, pwd.pw_name, len);
> - key.size = len + 1;
> - if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
> - wr_error(pwd_db_tmp);
> -
> - /* Store insecure by number. */
> - tbuf[0] = _PW_KEYBYNUM;
> - memmove(tbuf + 1, &cnt, sizeof(cnt));
> - key.size = sizeof(cnt) + 1;
> - if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
> + if (!username || (strcmp(username, pwd.pw_name) == 0)) {
> + /* Create insecure data. */
> + p = buf;
> + COMPACT(pwd.pw_name);
> + COMPACT("*");
> + memmove(p, &pwd.pw_uid, sizeof(int));
> + p += sizeof(int);
> + memmove(p, &pwd.pw_gid, sizeof(int));
> + p += sizeof(int);
> + memmove(p, &pwd.pw_change, sizeof(time_t));
> + p += sizeof(time_t);
> + COMPACT(pwd.pw_class);
> + COMPACT(pwd.pw_gecos);
> + COMPACT(pwd.pw_dir);
> + COMPACT(pwd.pw_shell);
> + memmove(p, &pwd.pw_expire, sizeof(time_t));
> + p += sizeof(time_t);
> + memmove(p, &flags, sizeof(int));
> + p += sizeof(int);
> + data.size = p - buf;
> +
> + /* Store insecure by name. */
> + tbuf[0] = _PW_KEYBYNAME;
> + len = strlen(pwd.pw_name);
> + memmove(tbuf + 1, pwd.pw_name, len);
> + key.size = len + 1;
> + if ((dp->put)(dp, &key, &data, method) == -1)
> wr_error(pwd_db_tmp);
>
> - /* Store insecure by uid. */
> - tbuf[0] = _PW_KEYBYUID;
> - memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
> - key.size = sizeof(pwd.pw_uid) + 1;
> - if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
> - wr_error(pwd_db_tmp);
> + /* Store insecure by number. */
> + tbuf[0] = _PW_KEYBYNUM;
> + memmove(tbuf + 1, &cnt, sizeof(cnt));
> + key.size = sizeof(cnt) + 1;
> + if ((dp->put)(dp, &key, &data, method) == -1)
> + wr_error(pwd_db_tmp);
> +
> + /* Store insecure by uid. */
> + tbuf[0] = _PW_KEYBYUID;
> + memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
> + key.size = sizeof(pwd.pw_uid) + 1;
> + if ((dp->put)(dp, &key, &data, methoduid) == -1)
> + wr_error(pwd_db_tmp);
> + }
>
> /* Create original format password file entry */
> if (makeold) {
> @@ -274,13 +300,13 @@
> }
>
> /* Store YP token, if needed. */
> - if(hasyp) {
> + if (hasyp) {
> ypkey.data = (u_char *)__yp_token;
> ypkey.size = strlen(__yp_token);
> ypdata.data = (u_char *)NULL;
> ypdata.size = 0;
>
> - if ((dp->put)(dp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
> + if ((dp->put)(dp, &ypkey, &ypdata, method) == -1)
> wr_error(pwd_db_tmp);
> }
>
> @@ -296,11 +322,22 @@
> }
> }
>
> - /* Open the temporary encrypted password database. */
> (void)snprintf(pwd_Sdb_tmp, sizeof(pwd_Sdb_tmp), "%s%s.tmp", prefix,
> _PATH_SMP_DB);
> - edp = dbopen(pwd_Sdb_tmp,
> - O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
> +
> + if (username) {
> + (void)snprintf(pwd_sdb, sizeof(pwd_sdb), "%s/%s", prefix,
> + _PATH_SMP_DB);
> +
> + clean = FILE_SECURE;
> + cp(pwd_sdb, pwd_Sdb_tmp, PERM_SECURE);
> + fflag = O_RDWR;
> + } else {
> + fflag = O_RDWR|O_CREAT|O_EXCL;
> + }
> +
> + /* Open the temporary encrypted password database. */
> + edp = dbopen(pwd_Sdb_tmp, fflag, PERM_SECURE, DB_HASH, &openinfo);
> if (!edp)
> error(pwd_Sdb_tmp);
> clean = FILE_SECURE;
> @@ -308,57 +345,59 @@
> rewind(fp);
> for (cnt = 1; scan(fp, &pwd, &flags); ++cnt) {
>
> - /* Create secure data. */
> - p = buf;
> - COMPACT(pwd.pw_name);
> - COMPACT(pwd.pw_passwd);
> - memmove(p, &pwd.pw_uid, sizeof(int));
> - p += sizeof(int);
> - memmove(p, &pwd.pw_gid, sizeof(int));
> - p += sizeof(int);
> - memmove(p, &pwd.pw_change, sizeof(time_t));
> - p += sizeof(time_t);
> - COMPACT(pwd.pw_class);
> - COMPACT(pwd.pw_gecos);
> - COMPACT(pwd.pw_dir);
> - COMPACT(pwd.pw_shell);
> - memmove(p, &pwd.pw_expire, sizeof(time_t));
> - p += sizeof(time_t);
> - memmove(p, &flags, sizeof(int));
> - p += sizeof(int);
> - data.size = p - buf;
> -
> - /* Store secure by name. */
> - tbuf[0] = _PW_KEYBYNAME;
> - len = strlen(pwd.pw_name);
> - memmove(tbuf + 1, pwd.pw_name, len);
> - key.size = len + 1;
> - if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
> - wr_error(pwd_Sdb_tmp);
> -
> - /* Store secure by number. */
> - tbuf[0] = _PW_KEYBYNUM;
> - memmove(tbuf + 1, &cnt, sizeof(cnt));
> - key.size = sizeof(cnt) + 1;
> - if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
> - wr_error(pwd_Sdb_tmp);
> -
> - /* Store secure by uid. */
> - tbuf[0] = _PW_KEYBYUID;
> - memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
> - key.size = sizeof(pwd.pw_uid) + 1;
> - if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
> - wr_error(pwd_Sdb_tmp);
> + if (!username || (strcmp(username, pwd.pw_name) == 0)) {
> + /* Create secure data. */
> + p = buf;
> + COMPACT(pwd.pw_name);
> + COMPACT(pwd.pw_passwd);
> + memmove(p, &pwd.pw_uid, sizeof(int));
> + p += sizeof(int);
> + memmove(p, &pwd.pw_gid, sizeof(int));
> + p += sizeof(int);
> + memmove(p, &pwd.pw_change, sizeof(time_t));
> + p += sizeof(time_t);
> + COMPACT(pwd.pw_class);
> + COMPACT(pwd.pw_gecos);
> + COMPACT(pwd.pw_dir);
> + COMPACT(pwd.pw_shell);
> + memmove(p, &pwd.pw_expire, sizeof(time_t));
> + p += sizeof(time_t);
> + memmove(p, &flags, sizeof(int));
> + p += sizeof(int);
> + data.size = p - buf;
> +
> + /* Store secure by name. */
> + tbuf[0] = _PW_KEYBYNAME;
> + len = strlen(pwd.pw_name);
> + memmove(tbuf + 1, pwd.pw_name, len);
> + key.size = len + 1;
> + if ((edp->put)(edp, &key, &data, method) == -1)
> + wr_error(pwd_Sdb_tmp);
> +
> + /* Store secure by number. */
> + tbuf[0] = _PW_KEYBYNUM;
> + memmove(tbuf + 1, &cnt, sizeof(cnt));
> + key.size = sizeof(cnt) + 1;
> + if ((edp->put)(edp, &key, &data, method) == -1)
> + wr_error(pwd_Sdb_tmp);
> +
> + /* Store secure by uid. */
> + tbuf[0] = _PW_KEYBYUID;
> + memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
> + key.size = sizeof(pwd.pw_uid) + 1;
> + if ((edp->put)(edp, &key, &data, methoduid) == -1)
> + wr_error(pwd_Sdb_tmp);
> + }
> }
>
> /* Store YP token, if needed. */
> - if(hasyp) {
> + if (hasyp) {
> ypkey.data = (u_char *)__yp_token;
> ypkey.size = strlen(__yp_token);
> ypdata.data = (u_char *)NULL;
> ypdata.size = 0;
>
> - if((edp->put)(edp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
> + if((edp->put)(edp, &ypkey, &ypdata, method) == -1)
> wr_error(pwd_Sdb_tmp);
> }
>
> @@ -405,6 +444,61 @@
> }
>
> int
> +check_user_db(username)
> + char *username;
> +{
> + DB *pw_db;
> + DBT data, key;
> + int len;
> + char *p;
> + char buf[MAX(MAXPATHLEN, LINE_MAX * 2)];
> + int methoduid = 0;
> +
> + /*
> + * Do some trouble to check if we should store this users
> + * uid. Don't use getpwnam/getpwuid as that interferes
> + * with NIS.
> + */
> + pw_db = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL);
> + if (!pw_db)
> + error(_PATH_MP_DB);
> + buf[0] = _PW_KEYBYNAME;
> + len = strlen(username);
> +
> + /* Only check that username fits in buffer */
> + memmove(buf + 1, username, MIN(len, sizeof(buf) - 1));
> + key.data = (u_char *)buf;
> + key.size = len + 1;
> + if ((pw_db->get)(pw_db, &key, &data, 0) == 0) {
> + p = (char *)data.data;
> +
> + /* jump over pw_name and pw_passwd, to get to pw_uid */
> + while (*p++)
> + ;
> + while (*p++)
> + ;
> +
> + buf[0] = _PW_KEYBYUID;
> + memmove(buf + 1, p, sizeof(int));
> + key.data = (u_char *)buf;
> + key.size = sizeof(int) + 1;
> +
> + if ((pw_db->get)(pw_db, &key, &data, 0) == 0) {
> + /* First field of data.data holds pw_pwname */
> + if (strcmp(data.data, username))
> + methoduid = R_NOOVERWRITE;
> + } else {
> + methoduid = R_NOOVERWRITE;
> + }
> + } else {
> + methoduid = R_NOOVERWRITE;
> + }
> + if ((pw_db->close)(pw_db))
> + error("close pw_db");
> + return methoduid;
> +}
> +
> +int
> scan(fp, pw, flags)
> FILE *fp;
> struct passwd *pw;
> @@ -440,6 +534,37 @@
> return (1);
> }
>
> +void
> +cp(from, to, mode)
> + char *from, *to;
> + mode_t mode;
> +{
> + static char buf[MAXBSIZE];
> + int from_fd, rcount, to_fd, wcount;
> +
> + if ((from_fd = open(from, O_RDONLY, 0)) < 0)
> + error(from);
> + if ((to_fd = open(to, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0)
> + error(to);
> + while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
> + wcount = write(to_fd, buf, rcount);
> + if (rcount != wcount || wcount == -1) {
> + int sverrno = errno;
> +
> + (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
> + errno = sverrno;
> + error(buf);
> + }
> + }
> + if (rcount < 0) {
> + int sverrno = errno;
> +
> + (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
> + errno = sverrno;
> + error(buf);
> + }
> +}
> +
> void
> mv(from, to)
> char *from, *to;
> @@ -510,6 +635,6 @@
> usage()
> {
>
> - (void)fprintf(stderr, "usage: pwd_mkdb [-p] [-d directory] file\n");
> + (void)fprintf(stderr, "usage: pwd_mkdb [-p] [-d directory] [-p user] file\n");
> exit(1);
> }
> Index: usr.bin/chpass/chpass.c
> --- usr.bin/chpass/chpass.c.orig Mon Feb 15 08:38:04 1999
> +++ usr.bin/chpass/chpass.c Mon Apr 12 00:03:50 1999
> @@ -82,6 +82,7 @@
> void baduser __P((void));
> int main __P((int, char **));
> void usage __P((void));
> +int pw_mkdb_user __P((char *));
>
> int
> main(argc, argv)
> @@ -279,7 +280,7 @@
> pw_copy(pfd, tfd, pw, (op == LOADENTRY) ? NULL : &old_pw);
>
> /* Now finish the passwd file update. */
> - if (pw_mkdb() < 0)
> + if (pw_mkdb_user(pw->pw_name) < 0)
> pw_error(NULL, 0, 1);
>
> exit(0);
> @@ -303,3 +304,37 @@
> #endif
> exit(1);
> }
> +
> +#include <sys/wait.h>
> +
> +int
> +pw_mkdb_user(username)
> + char *username;
> +{
> + int pstat;
> + pid_t pid;
> +
> + pid = vfork();
> + if (pid == 0) {
> + if (username)
> + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
> + "-u", username,
> + _PATH_MASTERPASSWD_LOCK, NULL);
> + else
> + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
> + _PATH_MASTERPASSWD_LOCK, NULL);
> + _exit(1);
> + }
> + pid = waitpid(pid, &pstat, 0);
> + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
> + return(-1);
> + return(0);
> +}
> +
> +#if 0
> +int
> +pw_mkdb()
> +{
> + return pw_mkdb_user(NULL);
> +}
> +#endif
> Index: usr.bin/passwd/local_passwd.c
> --- usr.bin/passwd/local_passwd.c.orig Thu Jan 14 00:44:43 1999
> +++ usr.bin/passwd/local_passwd.c Mon Apr 12 00:03:58 1999
> @@ -60,6 +60,8 @@
>
> static char *getnewpasswd __P((struct passwd *));
>
> +int pw_mkdb_user __P((char *username));
> +
> static uid_t uid;
>
> char *tempname;
> @@ -182,7 +184,41 @@
>
> pw_copy(pfd, tfd, pw, &old_pw);
>
> - if (pw_mkdb() < 0)
> + if (pw_mkdb_user(uname) < 0)
> pw_error((char *)NULL, 0, 1);
> return (0);
> }
> +
> +#include <sys/wait.h>
> +
> +int
> +pw_mkdb_user(username)
> + char *username;
> +{
> + int pstat;
> + pid_t pid;
> +
> + pid = vfork();
> + if (pid == 0) {
> + if (username)
> + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
> + "-u", username,
> + _PATH_MASTERPASSWD_LOCK, NULL);
> + else
> + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
> + _PATH_MASTERPASSWD_LOCK, NULL);
> + _exit(1);
> + }
> + pid = waitpid(pid, &pstat, 0);
> + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
> + return(-1);
> + return(0);
> +}
> +
> +#if 0
> +int
> +pw_mkdb()
> +{
> + return pw_mkdb_user(NULL);
> +}
> +#endif