Subject: misc/106: installing in /usr/src/etc with DESTDIR sets fails on pwd_mkdb
To: None <gnats-admin>
From: None <peter@alice.wonderland.org>
List: netbsd-bugs
Date: 01/30/1994 06:05:04
>Number:         106
>Category:       misc
>Synopsis:       pwd_mkdb fails due to hard coded paths used
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (Misc Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 30 06:05:02 1994
>Originator:     Peter Galbavy
>Organization:
Wonderland
>Release:        NetBSD-current (Jan 30 1994)
>Environment:
486DX, NetBSD-current
System: NetBSD alice.wonderland.org 0.9a ALICE#0 i386

>Description:
The line:

        (cd ${DESTDIR}/etc; pwd_mkdb -p master.passwd)

in ${BSDSRCDIR}/etc/Makefile will always fail if DESTDIR != ""

This is because "pwm_mkdb" uses lines like:

        (void)sprintf(buf, "%s.tmp", _PATH_MP_DB);
and
        mv(pname, _PATH_MASTERPASSWD);

which are got from file /usr/include/pwd.h, and (I guess sensibly for
security reasons) these are hardcoded.
>How-To-Repeat:
On a scratch machine try "cd /usr/src/etc ; make distribution DESTDIR=/tmp"
as an example. This will trash your existing passwd file (actually
the db format file which getpwent() etc uses).
>Fix:
I took a look and thought of maybe using chroot in the makefile, but this
is not so good an idea and not portable.

The best fix would be something like adding YAO (yet another option) to
say build relative to XXX; eg "pwd_mkdb -p master.passwd -d ${DESTDIR}"

Here is a quick hack, that allows a "-d rootdir" to be used. I have not
made diffs to /usr/src/etc/Makefile and the man page to pwd_mkdb. This
had had minimal testing, please look at it hard for me :-)

---
*** usr.sbin/pwd_mkdb/pwd_mkdb.c.orig	Sun Jan 30 13:27:42 1994
--- usr.sbin/pwd_mkdb/pwd_mkdb.c	Sun Jan 30 13:44:15 1994
***************
*** 63,68 ****
--- 63,72 ----
  static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
  static struct passwd pwd;			/* password structure */
  static char *pname;				/* password file name */
+ static char path_passwd[MAX(MAXPATHLEN, LINE_MAX * 2)];
+ static char path_masterpasswd[MAX(MAXPATHLEN, LINE_MAX * 2)];
+ static char path_mp_db[MAX(MAXPATHLEN, LINE_MAX * 2)];
+ static char path_smp_db[MAX(MAXPATHLEN, LINE_MAX * 2)];
  
  main(argc, argv)
  	int argc;
***************
*** 77,91 ****
  	DBT data, key;
  	int ch, cnt, tfd;
  	char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
  
  	makeold = 0;
! 	while ((ch = getopt(argc, argv, "pv")) != EOF)
  		switch(ch) {
  		case 'p':			/* create V7 "file.orig" */
  			makeold = 1;
  			break;
  		case 'v':			/* backward compatible */
  			break;
  		case '?':
  		default:
  			usage();
--- 81,100 ----
  	DBT data, key;
  	int ch, cnt, tfd;
  	char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
+ 	char *destdir;
+ 	extern char *optarg;
  
  	makeold = 0;
! 	while ((ch = getopt(argc, argv, "pvd:")) != EOF)
  		switch(ch) {
  		case 'p':			/* create V7 "file.orig" */
  			makeold = 1;
  			break;
  		case 'v':			/* backward compatible */
  			break;
+ 		case 'd':
+ 			destdir = optarg;
+ 			break;
  		case '?':
  		default:
  			usage();
***************
*** 97,102 ****
--- 106,129 ----
  		usage();
  
  	/*
+ 	 * Changes to allow building in a destdir. peter@wonderland.org
+ 	 *
+ 	 * Basically, this just replaces the direct references to _PATH
+ 	 * macros with strings.
+ 	 */
+ 	if (destdir) {
+ 		sprintf(path_passwd, "%s/%s", destdir, _PATH_PASSWD);
+ 		sprintf(path_masterpasswd, "%s/%s", destdir, _PATH_MASTERPASSWD);
+ 		sprintf(path_mp_db, "%s/%s", destdir, _PATH_MP_DB);
+ 		sprintf(path_smp_db, "%s/%s", destdir, _PATH_SMP_DB);
+ 	} else {
+ 		strcpy(path_passwd, _PATH_PASSWD);
+ 		strcpy(path_masterpasswd, _PATH_MASTERPASSWD);
+ 		strcpy(path_mp_db, _PATH_MP_DB);
+ 		strcpy(path_smp_db, _PATH_SMP_DB);
+ 	}
+ 
+ 	/*
  	 * This could be done to allow the user to interrupt.  Probably
  	 * not worth the effort.
  	 */
***************
*** 114,127 ****
  		error(pname);
  
  	/* Open the temporary insecure password database. */
! 	(void)sprintf(buf, "%s.tmp", _PATH_MP_DB);
  	dp = dbopen(buf, O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, NULL);
  	if (!dp)
  		error(buf);
  	clean = FILE_INSECURE;
  
  	/* Open the temporary encrypted password database. */
! 	(void)sprintf(buf, "%s.tmp", _PATH_SMP_DB);
  	edp = dbopen(buf, O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, NULL);
  	if (!edp)
  		error(buf);
--- 141,154 ----
  		error(pname);
  
  	/* Open the temporary insecure password database. */
! 	(void)sprintf(buf, "%s.tmp", path_mp_db);
  	dp = dbopen(buf, O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, NULL);
  	if (!dp)
  		error(buf);
  	clean = FILE_INSECURE;
  
  	/* Open the temporary encrypted password database. */
! 	(void)sprintf(buf, "%s.tmp", path_smp_db);
  	edp = dbopen(buf, O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, NULL);
  	if (!edp)
  		error(buf);
***************
*** 256,268 ****
  	(void)fclose(fp);
  
  	/* Install as the real password files. */
! 	(void)sprintf(buf, "%s.tmp", _PATH_MP_DB);
! 	mv(buf, _PATH_MP_DB);
! 	(void)sprintf(buf, "%s.tmp", _PATH_SMP_DB);
! 	mv(buf, _PATH_SMP_DB);
  	if (makeold) {
  		(void)sprintf(buf, "%s.orig", pname);
! 		mv(buf, _PATH_PASSWD);
  	}
  	/*
  	 * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
--- 283,295 ----
  	(void)fclose(fp);
  
  	/* Install as the real password files. */
! 	(void)sprintf(buf, "%s.tmp", path_mp_db);
! 	mv(buf, path_mp_db);
! 	(void)sprintf(buf, "%s.tmp", path_smp_db);
! 	mv(buf, path_smp_db);
  	if (makeold) {
  		(void)sprintf(buf, "%s.orig", pname);
! 		mv(buf, path_passwd);
  	}
  	/*
  	 * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
***************
*** 270,276 ****
  	 * The rename means that everything is unlocked, as the original file
  	 * can no longer be accessed.
  	 */
! 	mv(pname, _PATH_MASTERPASSWD);
  	exit(0);
  }
  
--- 297,303 ----
  	 * The rename means that everything is unlocked, as the original file
  	 * can no longer be accessed.
  	 */
! 	mv(pname, path_masterpasswd);
  	exit(0);
  }
  
***************
*** 336,352 ****
  		(void)unlink(buf);
  		/* FALLTHROUGH */
  	case FILE_SECURE:
! 		(void)sprintf(buf, "%s.tmp", _PATH_SMP_DB);
  		(void)unlink(buf);
  		/* FALLTHROUGH */
  	case FILE_INSECURE:
! 		(void)sprintf(buf, "%s.tmp", _PATH_MP_DB);
  		(void)unlink(buf);
  	}
  }
  
  usage()
  {
! 	(void)fprintf(stderr, "usage: pwd_mkdb [-p] file\n");
  	exit(1);
  }
--- 363,379 ----
  		(void)unlink(buf);
  		/* FALLTHROUGH */
  	case FILE_SECURE:
! 		(void)sprintf(buf, "%s.tmp", path_smp_db);
  		(void)unlink(buf);
  		/* FALLTHROUGH */
  	case FILE_INSECURE:
! 		(void)sprintf(buf, "%s.tmp", path_mp_db);
  		(void)unlink(buf);
  	}
  }
  
  usage()
  {
! 	(void)fprintf(stderr, "usage: pwd_mkdb [-p] [-d rootdir] file\n");
  	exit(1);
  }
>Audit-Trail:
>Unformatted:

------------------------------------------------------------------------------