Handle the problem cited in PR#1328 (no checking for I/O errors).
Improve some of the error messages to provide more accurate information. Repaired a bug by inspection (function pointer reference through a free'd DB structure!! How did this *ever* work?)
This commit is contained in:
parent
ddf189f7da
commit
dd15ee1ce0
@ -1,4 +1,4 @@
|
||||
/*-
|
||||
/*
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Portions Copyright(C) 1994, Jason Downs. All rights reserved.
|
||||
@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pwd_mkdb.c,v 1.10 1997/10/17 12:18:22 lukem Exp $");
|
||||
__RCSID("$NetBSD: pwd_mkdb.c,v 1.11 1998/04/13 23:12:45 fair Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -83,11 +83,16 @@ static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
|
||||
static struct passwd pwd; /* password structure */
|
||||
static char *pname; /* password file name */
|
||||
static char prefix[MAXPATHLEN];
|
||||
static char oldpwdfile[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
||||
static char pwd_db_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
||||
static char pwd_Sdb_tmp[MAX(MAXPATHLEN, LINE_MAX * 2)];
|
||||
|
||||
void cleanup __P((void));
|
||||
void error __P((char *));
|
||||
void wr_error __P((char *));
|
||||
int main __P((int, char **));
|
||||
void mv __P((char *, char *));
|
||||
void rm __P((char *));
|
||||
int scan __P((FILE *, struct passwd *, int *));
|
||||
void usage __P((void));
|
||||
|
||||
@ -102,7 +107,7 @@ main(argc, argv)
|
||||
sigset_t set;
|
||||
int ch, cnt, len, makeold, tfd, flags;
|
||||
char *p, *t;
|
||||
char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], buf2[MAXPATHLEN], tbuf[1024];
|
||||
char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
|
||||
int hasyp = 0;
|
||||
DBT ypdata, ypkey;
|
||||
|
||||
@ -151,11 +156,12 @@ main(argc, argv)
|
||||
error(pname);
|
||||
|
||||
/* Open the temporary insecure password database. */
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix, _PATH_MP_DB);
|
||||
dp = dbopen(buf,
|
||||
(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 (dp == NULL)
|
||||
error(buf);
|
||||
error(pwd_db_tmp);
|
||||
clean = FILE_INSECURE;
|
||||
|
||||
/*
|
||||
@ -166,12 +172,13 @@ main(argc, argv)
|
||||
* everyone.
|
||||
*/
|
||||
if (makeold) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
|
||||
if ((tfd = open(buf,
|
||||
(void)snprintf(oldpwdfile, sizeof(oldpwdfile), "%s.orig",
|
||||
pname);
|
||||
if ((tfd = open(oldpwdfile,
|
||||
O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
|
||||
error(buf);
|
||||
error(oldpwdfile);
|
||||
if ((oldfp = fdopen(tfd, "w")) == NULL)
|
||||
error(buf);
|
||||
error(oldpwdfile);
|
||||
clean = FILE_ORIG;
|
||||
}
|
||||
|
||||
@ -235,27 +242,31 @@ main(argc, argv)
|
||||
memmove(tbuf + 1, pwd.pw_name, len);
|
||||
key.size = len + 1;
|
||||
if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
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)
|
||||
error("put");
|
||||
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)
|
||||
error("put");
|
||||
wr_error(pwd_db_tmp);
|
||||
|
||||
/* Create original format password file entry */
|
||||
if (makeold)
|
||||
if (makeold) {
|
||||
(void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
|
||||
pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
|
||||
pwd.pw_dir, pwd.pw_shell);
|
||||
if (ferror(oldfp)) {
|
||||
wr_error(oldpwdfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store YP token, if needed. */
|
||||
@ -266,21 +277,28 @@ main(argc, argv)
|
||||
ypdata.size = 0;
|
||||
|
||||
if ((dp->put)(dp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
wr_error(pwd_db_tmp);
|
||||
}
|
||||
|
||||
(void)(dp->close)(dp);
|
||||
if ((dp->close)(dp) < 0) {
|
||||
wr_error(pwd_db_tmp);
|
||||
}
|
||||
if (makeold) {
|
||||
(void)fflush(oldfp);
|
||||
(void)fclose(oldfp);
|
||||
if (fflush(oldfp) == EOF) {
|
||||
wr_error(oldpwdfile);
|
||||
}
|
||||
if (fclose(oldfp) == EOF) {
|
||||
wr_error(oldpwdfile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the temporary encrypted password database. */
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix, _PATH_SMP_DB);
|
||||
edp = dbopen(buf,
|
||||
(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 (!edp)
|
||||
error(buf);
|
||||
error(pwd_Sdb_tmp);
|
||||
clean = FILE_SECURE;
|
||||
|
||||
rewind(fp);
|
||||
@ -311,21 +329,21 @@ main(argc, argv)
|
||||
len = strlen(pwd.pw_name);
|
||||
memmove(tbuf + 1, pwd.pw_name, len);
|
||||
key.size = len + 1;
|
||||
if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
|
||||
/* Store secure by number. */
|
||||
tbuf[0] = _PW_KEYBYNUM;
|
||||
memmove(tbuf + 1, &cnt, sizeof(cnt));
|
||||
key.size = sizeof(cnt) + 1;
|
||||
if ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
|
||||
/* 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 ((dp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
}
|
||||
|
||||
@ -336,37 +354,49 @@ main(argc, argv)
|
||||
ypdata.data = (u_char *)NULL;
|
||||
ypdata.size = 0;
|
||||
|
||||
if((dp->put)(edp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
|
||||
if((edp->put)(edp, &ypkey, &ypdata, R_NOOVERWRITE) == -1)
|
||||
error("put");
|
||||
}
|
||||
|
||||
(void)(edp->close)(edp);
|
||||
if ((edp->close)(edp) < 0) {
|
||||
wr_error(_PATH_SMP_DB);
|
||||
}
|
||||
|
||||
/* Set master.passwd permissions, in case caller forgot. */
|
||||
(void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
|
||||
(void)fclose(fp);
|
||||
if (fclose(fp) == EOF) {
|
||||
wr_error(pname);
|
||||
}
|
||||
|
||||
/* Install as the real password files. */
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix, _PATH_MP_DB);
|
||||
(void)snprintf(buf2, sizeof(buf2), "%s%s", prefix, _PATH_MP_DB);
|
||||
mv(buf, buf2);
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix, _PATH_SMP_DB);
|
||||
(void)snprintf(buf2, sizeof(buf2), "%s%s", prefix, _PATH_SMP_DB);
|
||||
mv(buf, buf2);
|
||||
if (makeold) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
|
||||
(void)snprintf(buf2, sizeof(buf2), "%s%s", prefix,
|
||||
_PATH_PASSWD);
|
||||
mv(buf, buf2);
|
||||
{
|
||||
char destination[MAXPATHLEN];
|
||||
|
||||
(void)snprintf(destination, sizeof(destination),
|
||||
"%s%s", prefix, _PATH_MP_DB);
|
||||
mv(pwd_db_tmp, destination);
|
||||
|
||||
(void)snprintf(destination, sizeof(destination),
|
||||
"%s%s", prefix, _PATH_SMP_DB);
|
||||
mv(pwd_Sdb_tmp, destination);
|
||||
|
||||
if (makeold) {
|
||||
(void)snprintf(destination, sizeof(destination),
|
||||
"%s%s", prefix, _PATH_PASSWD);
|
||||
mv(oldpwdfile, destination);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the master password LAST -- chpass(1),
|
||||
* passwd(1) and vipw(8) all use flock(2) on it to
|
||||
* block other incarnations of themselves. The rename
|
||||
* means that everything is unlocked, as the original
|
||||
* file can no longer be accessed.
|
||||
*/
|
||||
(void)snprintf(destination, sizeof(destination),
|
||||
"%s%s", prefix, _PATH_MASTERPASSWD);
|
||||
mv(pname, destination);
|
||||
}
|
||||
/*
|
||||
* Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
|
||||
* all use flock(2) on it to block other incarnations of themselves.
|
||||
* The rename means that everything is unlocked, as the original file
|
||||
* can no longer be accessed.
|
||||
*/
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s", prefix, _PATH_MASTERPASSWD);
|
||||
mv(pname, buf);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -417,6 +447,20 @@ mv(from, to)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wr_error(name)
|
||||
char *name;
|
||||
{
|
||||
char errbuf[BUFSIZ];
|
||||
int sverrno = errno;
|
||||
|
||||
(void)snprintf(errbuf, sizeof(errbuf),
|
||||
"attempt to write %s failed", name);
|
||||
|
||||
errno = sverrno;
|
||||
error(errbuf);
|
||||
}
|
||||
|
||||
void
|
||||
error(name)
|
||||
char *name;
|
||||
@ -424,9 +468,22 @@ error(name)
|
||||
|
||||
warn(name);
|
||||
cleanup();
|
||||
#ifdef think_about_this_a_while_longer
|
||||
fputs("NOTE: possible inconsistencies between text files and databases\n", stderr);
|
||||
fputs("re-run pwd_mkdb when you have fixed the problem.\n", stderr);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
rm(victim)
|
||||
char *victim;
|
||||
{
|
||||
if (unlink(victim) < 0) {
|
||||
warn("unlink(%s)", victim);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cleanup()
|
||||
{
|
||||
@ -434,18 +491,13 @@ cleanup()
|
||||
|
||||
switch(clean) {
|
||||
case FILE_ORIG:
|
||||
(void)snprintf(buf, sizeof(buf), "%s.orig", pname);
|
||||
(void)unlink(buf);
|
||||
rm(oldpwdfile);
|
||||
/* FALLTHROUGH */
|
||||
case FILE_SECURE:
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix,
|
||||
_PATH_SMP_DB);
|
||||
(void)unlink(buf);
|
||||
rm(pwd_Sdb_tmp);
|
||||
/* FALLTHROUGH */
|
||||
case FILE_INSECURE:
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s.tmp", prefix,
|
||||
_PATH_MP_DB);
|
||||
(void)unlink(buf);
|
||||
rm(pwd_db_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user