* Copyright (c) 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* 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
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)pwd_mkdb.c 5.5 (Berkeley) 5/6/91";
#define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
#define PERM_SECURE (S_IRUSR|S_IWUSR)
char *progname
= "pwd_mkdb";
static enum state
{ FILE_INSECURE
, FILE_SECURE
, FILE_ORIG
} clean
;
static struct passwd pwd
; /* password structure */
static char *pname
; /* password file name */
register int len
, makeold
;
char buf
[MAX(MAXPATHLEN
, LINE_MAX
* 2)], tbuf
[1024];
while ((ch
= getopt(argc
, argv
, "pv")) != EOF
)
case 'p': /* create V7 "file.orig" */
case 'v': /* backward compatible */
* This could be done to allow the user to interrupt. Probably
sigaddset(&set
, SIGTSTP
);
sigaddset(&set
, SIGQUIT
);
sigaddset(&set
, SIGTERM
);
(void)sigprocmask(SIG_BLOCK
, &set
, (sigset_t
*)NULL
);
/* Open the original password file */
if (!(fp
= fopen(pname
, "r")))
/* Open the temporary insecure password database. */
(void)sprintf(buf
, "%s.tmp", _PATH_MP_DB
);
dp
= hash_open(buf
, O_WRONLY
|O_CREAT
|O_EXCL
, PERM_INSECURE
, NULL
);
/* Open the temporary encrypted password database. */
(void)sprintf(buf
, "%s.tmp", _PATH_SMP_DB
);
edp
= hash_open(buf
, O_WRONLY
|O_CREAT
|O_EXCL
, PERM_SECURE
, NULL
);
* Open file for old password file. Minor trickiness -- don't want to
* chance the file already existing, since someone (stupidly) might
* still be using this for permission checking. So, open it first and
* fdopen the resulting fd. Don't really care who reads it.
(void)sprintf(buf
, "%s.orig", pname
);
O_WRONLY
|O_CREAT
|O_EXCL
, PERM_INSECURE
)) < 0)
if (!(oldfp
= fdopen(tfd
, "w")))
* The databases actually contain three copies of the original data.
* Each password file entry is converted into a rough approximation
* of a ``struct passwd'', with the strings placed inline. This
* object is then stored as the data for three separate keys. The
* first key * is the pw_name field prepended by the _PW_KEYBYNAME
* character. The second key is the pw_uid field prepended by the
* _PW_KEYBYUID character. The third key is the line number in the
* original file prepended by the _PW_KEYBYNUM character. (The special
* characters are prepended to ensure that the keys do not collide.)
data
.data
= (u_char
*)buf
;
key
.data
= (u_char
*)tbuf
;
for (cnt
= 1; scan(fp
, &pwd
); ++cnt
) {
#define COMPACT(e) t = e; while (*p++ = *t++);
/* Create insecure data. */
bcopy((char *)&pwd
.pw_uid
, p
, sizeof(int));
bcopy((char *)&pwd
.pw_gid
, p
, sizeof(int));
bcopy((char *)&pwd
.pw_change
, p
, sizeof(time_t));
bcopy((char *)&pwd
.pw_expire
, p
, sizeof(time_t));
/* Store insecure by name. */
len
= strlen(pwd
.pw_name
);
bcopy(pwd
.pw_name
, tbuf
+ 1, len
);
if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Store insecure by number. */
bcopy((char *)&cnt
, tbuf
+ 1, sizeof(cnt
));
key
.size
= sizeof(cnt
) + 1;
if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Store insecure by uid. */
bcopy((char *)&pwd
.pw_uid
, tbuf
+ 1, sizeof(pwd
.pw_uid
));
key
.size
= sizeof(pwd
.pw_uid
) + 1;
if ((dp
->put
)(dp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Create secure data. */
bcopy((char *)&pwd
.pw_uid
, p
, sizeof(int));
bcopy((char *)&pwd
.pw_gid
, p
, sizeof(int));
bcopy((char *)&pwd
.pw_change
, p
, sizeof(time_t));
bcopy((char *)&pwd
.pw_expire
, p
, sizeof(time_t));
/* Store secure by name. */
len
= strlen(pwd
.pw_name
);
bcopy(pwd
.pw_name
, tbuf
+ 1, len
);
if ((dp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Store secure by number. */
bcopy((char *)&cnt
, tbuf
+ 1, sizeof(cnt
));
key
.size
= sizeof(cnt
) + 1;
if ((dp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Store secure by uid. */
bcopy((char *)&pwd
.pw_uid
, tbuf
+ 1, sizeof(pwd
.pw_uid
));
key
.size
= sizeof(pwd
.pw_uid
) + 1;
if ((dp
->put
)(edp
, &key
, &data
, R_NOOVERWRITE
) == -1)
/* Create original format password file entry */
(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
);
/* Set master.passwd permissions, in case caller forgot. */
(void)fchmod(fileno(fp
), S_IRUSR
|S_IWUSR
);
/* Install as the real password files. */
(void)sprintf(buf
, "%s.tmp", _PATH_MP_DB
);
(void)sprintf(buf
, "%s.tmp", _PATH_SMP_DB
);
(void)sprintf(buf
, "%s.orig", pname
);
* 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.
mv(pname
, _PATH_MASTERPASSWD
);
static char line
[LINE_MAX
];
if (!fgets(line
, sizeof(line
), fp
))
* ``... if I swallow anything evil, put your fingers down my
if (!(p
= index(line
, '\n'))) {
(void)fprintf(stderr
, "pwd_mkdb: line too long\n");
if (!pw_scan(line
, pw
)) {
(void)fprintf(stderr
, "pwd_mkdb: at line #%d.\n", lcnt
);
(void)sprintf(buf
, "%s to %s", from
, to
);
(void)fprintf(stderr
, "pwd_mkdb: %s: %s\n", name
, strerror(errno
));
(void)sprintf(buf
, "%s.orig", pname
);
(void)sprintf(buf
, "%s.tmp", _PATH_SMP_DB
);
(void)sprintf(buf
, "%s.tmp", _PATH_MP_DB
);
(void)fprintf(stderr
, "usage: pwd_mkdb [-p] file\n");