summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2002-05-16 03:50:42 +0000
committermillert <millert@openbsd.org>2002-05-16 03:50:42 +0000
commitfc7f3601ee932ec9c65cea8778ce19514e39d038 (patch)
tree6f10865f714d48be4d9706cdd4c23f5351446c48
parentRe-enable RNG on the 5601 (it needs to be disabled on some 5805 variants, (diff)
downloadwireguard-openbsd-fc7f3601ee932ec9c65cea8778ce19514e39d038.tar.xz
wireguard-openbsd-fc7f3601ee932ec9c65cea8778ce19514e39d038.zip
Change S/Key stuff from using a flat file (/etc/skeykeys) to a directory
where each user gets their own file, which is owned by that user. An old S/Key database may be converted by running "skeyinit -C" as root. Programs that need to access the S/Key database no longer need to be setuid root. They must now be setgid auth instead.
-rw-r--r--include/paths.h3
-rw-r--r--lib/libskey/shlib_version2
-rw-r--r--lib/libskey/skey.35
-rw-r--r--lib/libskey/skey.h12
-rw-r--r--lib/libskey/skeylogin.c577
-rw-r--r--usr.bin/skeyaudit/Makefile6
-rw-r--r--usr.bin/skeyaudit/skeyaudit.114
-rw-r--r--usr.bin/skeyaudit/skeyaudit.c11
-rw-r--r--usr.bin/skeyinit/Makefile6
-rw-r--r--usr.bin/skeyinit/skeyinit.154
-rw-r--r--usr.bin/skeyinit/skeyinit.c298
11 files changed, 462 insertions, 526 deletions
diff --git a/include/paths.h b/include/paths.h
index f9ff85dc591..181bd2fc2e1 100644
--- a/include/paths.h
+++ b/include/paths.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: paths.h,v 1.18 2000/06/10 20:01:06 deraadt Exp $ */
+/* $OpenBSD: paths.h,v 1.19 2002/05/16 03:50:42 millert Exp $ */
/* $NetBSD: paths.h,v 1.7 1994/10/26 00:56:12 cgd Exp $ */
/*
@@ -66,7 +66,6 @@
#define _PATH_RSH "/usr/bin/rsh"
#define _PATH_SENDMAIL "/usr/sbin/sendmail"
#define _PATH_SHELLS "/etc/shells"
-#define _PATH_SKEYKEYS "/etc/skeykeys"
#define _PATH_TTY "/dev/tty"
#define _PATH_UNIX "/bsd"
#define _PATH_VI "/usr/bin/vi"
diff --git a/lib/libskey/shlib_version b/lib/libskey/shlib_version
index b52599a164f..012c14171d3 100644
--- a/lib/libskey/shlib_version
+++ b/lib/libskey/shlib_version
@@ -1,2 +1,2 @@
-major=2
+major=3
minor=0
diff --git a/lib/libskey/skey.3 b/lib/libskey/skey.3
index 81e344b6561..11540cf1706 100644
--- a/lib/libskey/skey.3
+++ b/lib/libskey/skey.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: skey.3,v 1.3 2002/04/30 16:31:42 mpech Exp $
+.\" $OpenBSD: skey.3,v 1.4 2002/05/16 03:50:42 millert Exp $
.\"
.\" Copyright (c) 2001 Todd C. Miller <Todd.Miller@courtesan.com>
.\" All rights reserved.
@@ -333,6 +333,9 @@ The S/Key database remains open after a call to
If no error was encountered accessing the S/Key database, the read/write
file pointer is set to the beginning of the record or at EOF if
there are no more records.
+.br
+Because it exposes other users' S/Key records, only the superuser may use
+.Fn skeygetnext .
.Pp
The
.Fn skeylookup
diff --git a/lib/libskey/skey.h b/lib/libskey/skey.h
index 37d9bd269fe..750dd8095f2 100644
--- a/lib/libskey/skey.h
+++ b/lib/libskey/skey.h
@@ -10,23 +10,22 @@
*
* Main client header
*
- * $OpenBSD: skey.h,v 1.17 2002/02/16 21:27:28 millert Exp $
+ * $OpenBSD: skey.h,v 1.18 2002/05/16 03:50:42 millert Exp $
*/
#ifndef _SKEY_H_
#define _SKEY_H_ 1
-#include <sys/cdefs.h>
+#include <dirent.h>
/* Server-side data structure for reading keys file during login */
struct skey {
FILE *keyfile;
+ DIR *keydir;
char *logname;
char *seed;
char *val;
- int n;
- int len;
- long recstart; /* needed so reread of buffer is efficient */
+ unsigned int n;
char buf[256];
};
@@ -61,6 +60,9 @@ struct mc {
/* Location of random file for bogus challenges */
#define _SKEY_RAND_FILE_PATH_ "/var/db/host.random"
+/* Directory for S/Key per-user files */
+#define _PATH_SKEYDIR "/etc/skey"
+
__BEGIN_DECLS
void f(char *);
int keycrunch(char *, char *, char *);
diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c
index 0cd761b75ed..34f3996611a 100644
--- a/lib/libskey/skeylogin.c
+++ b/lib/libskey/skeylogin.c
@@ -9,8 +9,8 @@
* Angelos D. Keromytis <adk@adk.gr>
*
* S/Key verification check, lookups, and authentication.
- *
- * $OpenBSD: skeylogin.c,v 1.41 2002/02/16 21:27:28 millert Exp $
+ *
+ * $OpenBSD: skeylogin.c,v 1.42 2002/05/16 03:50:42 millert Exp $
*/
#include <sys/param.h>
@@ -20,7 +20,6 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <sys/types.h>
#include <ctype.h>
#include <err.h>
@@ -41,8 +40,8 @@ static char *tgetline(int, char *, size_t, int);
/*
* Return an skey challenge string for user 'name'. If successful,
- * fill in the caller's skey structure and return(0). If unsuccessful
- * (e.g., if name is unknown) return(-1).
+ * fill in the caller's skey structure and return (0). If unsuccessful
+ * (e.g., if name is unknown) return (-1).
*
* The file read/write pointer is left at the start of the
* record.
@@ -61,7 +60,7 @@ skeychallenge(mp, name, ss)
(void)sprintf(ss, "otp-%.*s %d %.*s", SKEY_MAX_HASHNAME_LEN,
skey_get_algorithm(), mp->n - 1,
SKEY_MAX_SEED_LEN, mp->seed);
- return(0);
+ return (0);
case 1: /* User not found */
(void)fclose(mp->keyfile);
@@ -70,126 +69,99 @@ skeychallenge(mp, name, ss)
default: /* File error */
skey_fakeprompt(name, ss);
- return(-1);
+ return (-1);
}
}
-/*
+/*
* Find an entry in the One-time Password database and lock it.
*
* Return codes:
* -1: error in opening database or unable to lock entry
* 0: entry found, file R/W pointer positioned at beginning of record
- * 1: entry not found, file R/W pointer positioned at EOF
+ * 1: entry not found
*/
int
skeylookup(mp, name)
struct skey *mp;
char *name;
{
- FILE *keyfile;
- int rval;
- int locked = 0;
- long recstart = 0;
- char *cp, *ht = NULL;
struct stat statbuf;
- struct flock fl;
+ size_t nread;
+ char *cp, filename[PATH_MAX];
+ FILE *keyfile;
+ int fd;
- /* Open _PATH_SKEYKEYS if it exists, else return an error */
- if (stat(_PATH_SKEYKEYS, &statbuf) == 0 &&
- (keyfile = mp->keyfile = fopen(_PATH_SKEYKEYS, "r+")) != NULL) {
- if ((statbuf.st_mode & 0007777) != 0600)
- fchmod(fileno(keyfile), 0600);
- } else {
- mp->keyfile = NULL;
- return(-1);
+ /* Open the user's databse entry, creating it as needed. */
+ /* XXX - really want "/etc/skeys/L/USER" where L is 1st char of USER */
+ mp->keyfile = NULL;
+ if (snprintf(filename, sizeof(filename), "%s/%s", _PATH_SKEYDIR,
+ name) >= sizeof(filename)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if ((fd = open(filename, O_RDWR | O_NOFOLLOW | O_NONBLOCK,
+ S_IRUSR | S_IWUSR)) == -1) {
+ if (errno == ENOENT)
+ goto not_found;
+ return (-1);
}
- /* Look up user name in database */
- while (!feof(keyfile)) {
- mp->recstart = recstart = ftell(keyfile);
- if (fgets(mp->buf, sizeof(mp->buf), keyfile) == NULL)
- break;
- if (mp->buf[0] == '#')
- continue; /* Comment */
- mp->len = strlen(mp->buf);
- cp = mp->buf + mp->len - 1;
- while (cp >= mp->buf && (*cp == '\n' || *cp == '\r'))
- *cp-- = '\0';
- if ((mp->logname = strtok(mp->buf, " \t")) == NULL ||
- strcmp(mp->logname, name) != 0)
- continue;
- if ((cp = strtok(NULL, " \t")) == NULL)
- continue;
- /* Save hash type if specified, else use md4 */
- if (isalpha(*cp)) {
- ht = cp;
- if ((cp = strtok(NULL, " \t")) == NULL)
- continue;
- } else {
- ht = "md4";
- }
- mp->n = atoi(cp);
- if ((mp->seed = strtok(NULL, " \t")) == NULL)
- continue;
- if ((mp->val = strtok(NULL, " \t")) == NULL)
- continue;
-
- /* Set hash type */
- if (ht && skey_set_algorithm(ht) == NULL) {
- warnx("Unknown hash algorithm %s, using %s", ht,
- skey_get_algorithm());
- }
- (void)fseek(keyfile, recstart, SEEK_SET);
-
- /* If we already aquired the lock we are done */
- if (locked)
- return(0);
-
- /* Ortherwise, we must lock the record */
- fl.l_start = mp->recstart;
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
-
- /* If we get the lock on the first try we are done */
- rval = fcntl(fileno(mp->keyfile), F_SETLK, &fl);
- if (rval == 0)
- return(0);
- else if (errno != EAGAIN)
- break;
-
- /*
- * Wait until we our lock is granted...
- * Since we didn't get the lock on the first try, someone
- * else may have modified the record. We need to make
- * sure the entry hasn't changed name (it could have been
- * commented out) and re-read it.
- */
- if (fcntl(fileno(mp->keyfile), F_SETLKW, &fl) == -1)
- break;
-
- rval = fread(mp->logname, fl.l_len, 1, mp->keyfile);
- if (rval != fl.l_len ||
- memcmp(mp->logname, name, rval) != 0) {
- /* username no longer matches so unlock */
- fl.l_type = F_UNLCK;
- fcntl(fileno(mp->keyfile), F_SETLK, &fl);
- } else {
- locked = 1;
- }
- (void)fseek(keyfile, recstart, SEEK_SET);
+ /* Lock and stat the user's skey file. */
+ if (flock(fd, LOCK_EX) != 0 || fstat(fd, &statbuf) != 0) {
+ close(fd);
+ return (-1);
+ }
+ if (statbuf.st_size == 0)
+ goto not_found;
+
+ /* Sanity checks. */
+ if ((statbuf.st_mode & ALLPERMS) != (S_IRUSR | S_IWUSR) ||
+ !S_ISREG(statbuf.st_mode) || statbuf.st_nlink != 1 ||
+ (keyfile = fdopen(fd, "r+")) == NULL) {
+ close(fd);
+ return (-1);
}
- /* No entry found, fill in what we can... */
+ /* At this point, we are committed. */
+ memset(mp, 0, sizeof(*mp));
+ mp->keyfile = keyfile;
+
+ if ((nread = fread(mp->buf, 1, sizeof(mp->buf), keyfile)) == 0 ||
+ !isspace(mp->buf[nread - 1]))
+ goto bad_keyfile;
+ mp->buf[nread - 1] = '\0';
+
+ if ((mp->logname = strtok(mp->buf, " \t\n\r")) == NULL ||
+ strcmp(mp->logname, name) != 0)
+ goto bad_keyfile;
+ if ((cp = strtok(NULL, " \t\n\r")) == NULL)
+ goto bad_keyfile;
+ if (skey_set_algorithm(cp) == NULL)
+ goto bad_keyfile;
+ if ((cp = strtok(NULL, " \t\n\r")) == NULL)
+ goto bad_keyfile;
+ mp->n = atoi(cp); /* XXX - use strtol() */
+ if ((mp->seed = strtok(NULL, " \t\n\r")) == NULL)
+ goto bad_keyfile;
+ if ((mp->val = strtok(NULL, " \t\n\r")) == NULL)
+ goto bad_keyfile;
+
+ (void)fseek(keyfile, 0L, SEEK_SET);
+ return (0);
+
+ bad_keyfile:
+ fclose(keyfile);
+ return (-1);
+
+ not_found:
+ /* No existing entry, fill in what we can and return */
memset(mp, 0, sizeof(*mp));
strlcpy(mp->buf, name, sizeof(mp->buf));
mp->logname = mp->buf;
- mp->len = strlen(mp->buf);
- mp->keyfile = keyfile;
- mp->recstart = ftell(keyfile);
- return(1);
+ if (fd != -1)
+ close(fd);
+ return (1);
}
/*
@@ -198,92 +170,38 @@ skeylookup(mp, name)
* Return codes:
* -1: error in opening database
* 0: next entry found and stored in mp
- * 1: no more entries, file R/W pointer positioned at EOF
+ * 1: no more entries, keydir is closed.
*/
int
skeygetnext(mp)
struct skey *mp;
{
+ struct dirent entry, *dp;
int rval;
- int locked = 0;
- char *cp;
- struct stat statbuf;
- struct flock fl;
-
- /* Open _PATH_SKEYKEYS if it exists, else return an error */
- if (mp->keyfile == NULL) {
- if (stat(_PATH_SKEYKEYS, &statbuf) == 0 &&
- (mp->keyfile = fopen(_PATH_SKEYKEYS, "r+")) != NULL) {
- if ((statbuf.st_mode & 0007777) != 0600)
- fchmod(fileno(mp->keyfile), 0600);
- } else {
- return(-1);
- }
- } else {
- /* Unlock existing record */
- fl.l_start = mp->recstart;
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
-
- fcntl(fileno(mp->keyfile), F_SETLK, &fl);
- }
- /* Look up next user in database */
- while (!feof(mp->keyfile)) {
- mp->recstart = ftell(mp->keyfile);
- if (fgets(mp->buf, sizeof(mp->buf), mp->keyfile) != mp->buf)
- break;
- if (mp->buf[0] == '#')
- continue; /* Comment */
- mp->len = strlen(mp->buf);
- cp = mp->buf + mp->len - 1;
- while (cp >= mp->buf && (*cp == '\n' || *cp == '\r'))
- *cp-- = '\0';
- if ((mp->logname = strtok(mp->buf, " \t")) == NULL)
- continue;
- if ((cp = strtok(NULL, " \t")) == NULL)
- continue;
- /* Save hash type if specified, else use md4 */
- if (isalpha(*cp)) {
- if ((cp = strtok(NULL, " \t")) == NULL)
- continue;
- }
- mp->n = atoi(cp);
- if ((mp->seed = strtok(NULL, " \t")) == NULL)
- continue;
- if ((mp->val = strtok(NULL, " \t")) == NULL)
- continue;
-
- /* If we already locked the record, we are done */
- if (locked)
- break;
+ if (mp->keyfile != NULL) {
+ fclose(mp->keyfile);
+ mp->keyfile = NULL;
+ }
- /* Got a real entry, lock it */
- fl.l_start = mp->recstart;
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
+ /* Open _PATH_SKEYDIR if it exists, else return an error */
+ if (mp->keydir == NULL && (mp->keydir = opendir(_PATH_SKEYDIR)) == NULL)
+ return (-1);
- rval = fcntl(fileno(mp->keyfile), F_SETLK, &fl);
- if (rval == 0)
+ rval = 1;
+ while ((readdir_r(mp->keydir, &entry, &dp)) == 0 && dp == &entry) {
+ /* Skip dot files and zero-length files. */
+ if (entry.d_name[0] != '.' &&
+ (rval = skeylookup(mp, entry.d_name) != 1))
break;
- else if (errno != EAGAIN)
- return(-1);
-
- /*
- * Someone else has the entry locked, wait
- * until the lock is free, then re-read the entry.
- */
- rval = fcntl(fileno(mp->keyfile), F_SETLKW, &fl);
- if (rval == -1) /* Can't get exclusive lock */
- return(-1);
- locked = 1;
- (void)fseek(mp->keyfile, mp->recstart, SEEK_SET);
+ };
+
+ if (dp == NULL) {
+ closedir(mp->keydir);
+ mp->keydir = NULL;
}
- return(feof(mp->keyfile));
+
+ return (rval);
}
/*
@@ -304,106 +222,72 @@ skeyverify(mp, response)
char key[SKEY_BINKEY_SIZE];
char fkey[SKEY_BINKEY_SIZE];
char filekey[SKEY_BINKEY_SIZE];
- time_t now;
- struct tm *tm;
- struct flock fl;
- char tbuf[27];
+ size_t nread;
char *cp;
- int len;
+
+ if (response == NULL)
+ goto verify_failure;
/*
* The record should already be locked but lock it again
* just to be safe. We don't wait for the lock to become
* available since we should already have it...
*/
- fl.l_start = mp->recstart;
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
- if (fcntl(fileno(mp->keyfile), F_SETLK, &fl) != 0) {
- (void)fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(-1);
- }
-
- time(&now);
- tm = localtime(&now);
- (void)strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm);
-
- if (response == NULL) {
- (void)fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(-1);
- }
- rip(response);
+ if (flock(fileno(mp->keyfile), LOCK_EX | LOCK_NB) != 0)
+ goto verify_failure;
/* Convert response to binary */
- if (etob(key, response) != 1 && atob8(key, response) != 0) {
- /* Neither english words nor ascii hex */
- (void)fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(-1);
- }
+ rip(response);
+ if (etob(key, response) != 1 && atob8(key, response) != 0)
+ goto verify_failure; /* Neither english words nor ascii hex */
/* Compute fkey = f(key) */
(void)memcpy(fkey, key, sizeof(key));
- (void)fflush(stdout);
f(fkey);
- /* Reread the file record NOW */
- (void)fseek(mp->keyfile, mp->recstart, SEEK_SET);
- if (fgets(mp->buf, sizeof(mp->buf), mp->keyfile) == NULL) {
- (void)fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(-1);
- }
- len = strlen(mp->buf) - 1;
- cp = mp->buf + len;
- while (cp >= mp->buf && (*cp == '\n' || *cp == '\r'))
- *cp-- = '\0';
- mp->logname = strtok(mp->buf, " \t");
- cp = strtok(NULL, " \t") ;
- if (isalpha(*cp))
- cp = strtok(NULL, " \t") ;
- mp->seed = strtok(NULL, " \t");
- mp->val = strtok(NULL, " \t");
- /* And convert file value to hex for comparison */
+ /*
+ * Reread the file record NOW in case it has been modified.
+ * The only field we really need to worry about is mp->val.
+ */
+ (void)fseek(mp->keyfile, 0L, SEEK_SET);
+ if ((nread = fread(mp->buf, 1, sizeof(mp->buf), mp->keyfile)) == 0 ||
+ !isspace(mp->buf[nread - 1]))
+ goto verify_failure;
+ if ((mp->logname = strtok(mp->buf, " \t\r\n")) == NULL)
+ goto verify_failure;
+ if ((cp = strtok(NULL, " \t\r\n")) == NULL)
+ goto verify_failure;
+ if ((cp = strtok(NULL, " \t\r\n")) == NULL)
+ goto verify_failure;
+ if ((mp->seed = strtok(NULL, " \t\r\n")) == NULL)
+ goto verify_failure;
+ if ((mp->val = strtok(NULL, " \t\r\n")) == NULL)
+ goto verify_failure;
+
+ /* Convert file value to hex and compare. */
atob8(filekey, mp->val);
-
- /* Do actual comparison */
- if (memcmp(filekey, fkey, SKEY_BINKEY_SIZE) != 0){
- /* Wrong response */
- (void)fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(1);
- }
+ if (memcmp(filekey, fkey, SKEY_BINKEY_SIZE) != 0)
+ goto verify_failure; /* Wrong response */
/*
- * Update key in database by overwriting entire record. Note
- * that we must write exactly the same number of bytes as in
- * the original record (note fixed width field for N)
+ * Update key in database.
+ * XXX - check return values of things that write to disk.
*/
btoa8(mp->val,key);
mp->n--;
- (void)fseek(mp->keyfile, mp->recstart, SEEK_SET);
- len -= strlen(mp->logname) + strlen(skey_get_algorithm()) +
- strlen(mp->val) + strlen(tbuf) + 9;
- /*
- * If we run out of room it is because we read an old-style
- * md4 entry without an explicit hash type.
- */
- if (len < strlen(mp->seed))
- (void)fprintf(mp->keyfile, "%s %04d %-16s %s %-21s\n",
- mp->logname, mp->n, mp->seed, mp->val, tbuf);
- else
- (void)fprintf(mp->keyfile, "%s %s %04d %-*s %s %-21s\n",
- mp->logname, skey_get_algorithm(), mp->n,
- len, mp->seed, mp->val, tbuf);
+ (void)fseek(mp->keyfile, 0L, SEEK_SET);
+ (void)fprintf(mp->keyfile, "%s\n%s\n%04d\n%s\n%s\n", mp->logname,
+ skey_get_algorithm(), mp->n, mp->seed, mp->val);
+ (void)fflush(mp->keyfile);
+ (void)ftruncate(fileno(mp->keyfile), ftello(mp->keyfile));
+ (void)fclose(mp->keyfile);
+ mp->keyfile = NULL;
+ return (0);
+ verify_failure:
(void)fclose(mp->keyfile);
mp->keyfile = NULL;
- return(0);
+ return (-1);
}
/*
@@ -418,15 +302,15 @@ skey_haskey(username)
{
struct skey skey;
int i;
-
+
i = skeylookup(&skey, username);
if (skey.keyfile != NULL) {
fclose(skey.keyfile);
skey.keyfile = NULL;
}
- return(i);
+ return (i);
}
-
+
/*
* skey_keyinfo()
*
@@ -444,15 +328,15 @@ skey_keyinfo(username)
i = skeychallenge(&skey, username, str);
if (i == -1)
- return(0);
+ return (0);
if (skey.keyfile != NULL) {
fclose(skey.keyfile);
skey.keyfile = NULL;
}
- return(str);
+ return (str);
}
-
+
/*
* skey_passcheck()
*
@@ -472,12 +356,12 @@ skey_passcheck(username, passwd)
i = skeylookup(&skey, username);
if (i == -1 || i == 1)
- return(-1);
+ return (-1);
if (skeyverify(&skey, passwd) == 0)
- return(skey.n);
+ return (skey.n);
- return(-1);
+ return (-1);
}
#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
@@ -488,18 +372,18 @@ skey_passcheck(username, passwd)
*/
static u_int32_t
hash_collapse(s)
- u_char *s;
+ u_char *s;
{
- int len, target;
+ int len, target;
u_int32_t i;
-
+
if ((strlen(s) % sizeof(u_int32_t)) == 0)
target = strlen(s); /* Multiple of 4 */
else
target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
-
+
for (i = 0, len = 0; len < target; len += 4)
- i ^= ROUND(s + len);
+ i ^= ROUND(s + len);
return i;
}
@@ -576,7 +460,7 @@ skey_fakeprompt(username, skeyprompt)
SHA1Update(&ctx, secret, secretlen);
SHA1Update(&ctx, username, strlen(username));
SHA1End(&ctx, up);
-
+
/* Zero out */
memset(secret, 0, secretlen);
@@ -584,9 +468,9 @@ skey_fakeprompt(username, skeyprompt)
SHA1Init(&ctx);
SHA1Update(&ctx, up, strlen(up));
SHA1End(&ctx, up);
-
+
ptr = hash_collapse(up + 4);
-
+
for (i = 4; i < 9; i++) {
pbuf[i] = (ptr % 10) + '0';
ptr /= 10;
@@ -663,9 +547,9 @@ skey_authenticate(username)
"\nWarning! Key initialization needed soon. (%d logins left)\n",
skey.n);
}
- return(0);
+ return (0);
}
- return(-1);
+ return (-1);
}
/*
@@ -676,26 +560,23 @@ skey_authenticate(username)
* 0: Database updated
*
* The database file is always closed by this call.
+ * XXX - do we still need this function?
*/
int
skeyzero(mp)
struct skey *mp;
{
+ int rval;
/*
- * Seek to the right place and write comment character
- * which effectively zero's out the entry.
+ * We truncate the file rather than unlinking it since we
+ * may not have write perms on the directory.
*/
- (void)fseek(mp->keyfile, mp->recstart, SEEK_SET);
- if (fputc('#', mp->keyfile) == EOF) {
- fclose(mp->keyfile);
- mp->keyfile = NULL;
- return(-1);
- }
-
+ fflush(mp->keyfile);
+ rval = ftruncate(fileno(mp->keyfile), (off_t)0);
(void)fclose(mp->keyfile);
mp->keyfile = NULL;
- return(0);
+ return (rval);
}
/*
@@ -709,18 +590,10 @@ int
skey_unlock(mp)
struct skey *mp;
{
- struct flock fl;
-
if (mp->logname == NULL || mp->keyfile == NULL)
- return(-1);
-
- fl.l_start = mp->recstart;
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_UNLCK;
- fl.l_whence = SEEK_SET;
+ return (-1);
- return(fcntl(fileno(mp->keyfile), F_SETLK, &fl));
+ return (flock(fileno(mp->keyfile), LOCK_UN));
}
/*
@@ -728,63 +601,63 @@ skey_unlock(mp)
*/
static char *
tgetline(fd, buf, bufsiz, timeout)
- int fd;
- char *buf;
- size_t bufsiz;
- int timeout;
+ int fd;
+ char *buf;
+ size_t bufsiz;
+ int timeout;
{
- size_t left;
- int n;
- fd_set *readfds = NULL;
- struct timeval tv;
- char c;
- char *cp;
-
- if (bufsiz == 0)
- return(NULL); /* sanity */
-
- cp = buf;
- left = bufsiz;
-
- /*
- * Timeout of <= 0 means no timeout.
- */
- if (timeout > 0) {
- /* Setup for select(2) */
- n = howmany(fd + 1, NFDBITS) * sizeof(fd_mask);
- if ((readfds = (fd_set *) malloc(n)) == NULL)
- return(NULL);
- (void) memset(readfds, 0, n);
-
- /* Set timeout for select */
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
-
- while (--left) {
- FD_SET(fd, readfds);
-
- /* Make sure there is something to read (or timeout) */
- while ((n = select(fd + 1, readfds, 0, 0, &tv)) == -1 &&
- (errno == EINTR || errno == EAGAIN))
- ;
- if (n == 0) {
- free(readfds);
- return(NULL); /* timeout */
- }
-
- /* Read a character, exit loop on error, EOF or EOL */
- n = read(fd, &c, 1);
- if (n != 1 || c == '\n' || c == '\r')
- break;
- *cp++ = c;
- }
- free(readfds);
- } else {
- /* Keep reading until out of space, EOF, error, or newline */
- while (--left && (n = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r')
- *cp++ = c;
- }
- *cp = '\0';
-
- return(cp == buf ? NULL : buf);
+ size_t left;
+ int n;
+ fd_set *readfds = NULL;
+ struct timeval tv;
+ char c;
+ char *cp;
+
+ if (bufsiz == 0)
+ return (NULL); /* sanity */
+
+ cp = buf;
+ left = bufsiz;
+
+ /*
+ * Timeout of <= 0 means no timeout.
+ */
+ if (timeout > 0) {
+ /* Setup for select(2) */
+ n = howmany(fd + 1, NFDBITS) * sizeof(fd_mask);
+ if ((readfds = (fd_set *) malloc(n)) == NULL)
+ return (NULL);
+ (void) memset(readfds, 0, n);
+
+ /* Set timeout for select */
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ while (--left) {
+ FD_SET(fd, readfds);
+
+ /* Make sure there is something to read (or timeout) */
+ while ((n = select(fd + 1, readfds, 0, 0, &tv)) == -1 &&
+ (errno == EINTR || errno == EAGAIN))
+ ;
+ if (n == 0) {
+ free(readfds);
+ return (NULL); /* timeout */
+ }
+
+ /* Read a character, exit loop on error, EOF or EOL */
+ n = read(fd, &c, 1);
+ if (n != 1 || c == '\n' || c == '\r')
+ break;
+ *cp++ = c;
+ }
+ free(readfds);
+ } else {
+ /* Keep reading until out of space, EOF, error, or newline */
+ while (--left && (n = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r')
+ *cp++ = c;
+ }
+ *cp = '\0';
+
+ return (cp == buf ? NULL : buf);
}
diff --git a/usr.bin/skeyaudit/Makefile b/usr.bin/skeyaudit/Makefile
index 967b6727fbb..00f643b060d 100644
--- a/usr.bin/skeyaudit/Makefile
+++ b/usr.bin/skeyaudit/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.2 1997/09/21 11:50:51 deraadt Exp $
+# $OpenBSD: Makefile,v 1.3 2002/05/16 03:50:42 millert Exp $
PROG= skeyaudit
-BINOWN= root
-BINMODE=4555
+BINGRP= auth
+BINMODE=2555
DPADD= ${LIBSKEY}
LDADD= -lskey
diff --git a/usr.bin/skeyaudit/skeyaudit.1 b/usr.bin/skeyaudit/skeyaudit.1
index 2fa5b00e1fa..30192984c03 100644
--- a/usr.bin/skeyaudit/skeyaudit.1
+++ b/usr.bin/skeyaudit/skeyaudit.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: skeyaudit.1,v 1.8 2000/11/09 17:52:38 aaron Exp $
+.\" $OpenBSD: skeyaudit.1,v 1.9 2002/05/16 03:50:42 millert Exp $
.\"
.Dd 22 July 1997
.Dt SKEYAUDIT 1
@@ -13,8 +13,8 @@
.Op Fl l Ar limit
.Sh DESCRIPTION
.Nm
-searches through the file
-.Pa /etc/skeykeys
+searches through the files in
+.Pa /etc/skey
for users whose S/Key sequence number is less than
.Ar limit ,
and mails them a reminder to run
@@ -25,7 +25,7 @@ The options are as follows:
.Bl -tag -width Ds
.It Fl a
Check all keys in
-.Pa /etc/skeykeys .
+.Pa /etc/skey
This option is only available to the superuser and
is useful to run regularly via
.Xr cron 8 .
@@ -37,9 +37,9 @@ The limit used to determine whether or not a user should be notified.
The default is to notify if there are fewer than 12 keys left.
.El
.Sh FILES
-.Bl -tag -width /etc/skeykeys -compact
-.It Pa /etc/skeykeys
-S/Key key information database
+.Bl -tag -width /etc/skey
+.It Pa /etc/skey
+directory containing user entries for S/Key
.El
.Sh SEE ALSO
.Xr skey 1 ,
diff --git a/usr.bin/skeyaudit/skeyaudit.c b/usr.bin/skeyaudit/skeyaudit.c
index 9a8f576fdf9..900d255cb6c 100644
--- a/usr.bin/skeyaudit/skeyaudit.c
+++ b/usr.bin/skeyaudit/skeyaudit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: skeyaudit.c,v 1.12 2002/02/16 21:27:52 millert Exp $ */
+/* $OpenBSD: skeyaudit.c,v 1.13 2002/05/16 03:50:42 millert Exp $ */
/*
* Copyright (c) 1997, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -58,9 +58,6 @@ main(argc, argv)
int ch, errs = 0, left = 0, aflag = 0, iflag = 0, limit = 12;
char *name;
- if (geteuid() != 0)
- errx(1, "must be setuid root");
-
while ((ch = getopt(argc, argv, "ail:")) != -1)
switch(ch) {
case 'a':
@@ -100,7 +97,7 @@ main(argc, argv)
notify(pw, left, iflag);
}
if (ch == -1)
- errx(-1, "cannot open %s", _PATH_SKEYKEYS);
+ errx(-1, "cannot open %s", _PATH_SKEYDIR);
else
(void)fclose(key.keyfile);
} else {
@@ -116,11 +113,11 @@ main(argc, argv)
left = key.n - 1;
break;
case -1: /* File error */
- errx(errs, "cannot open %s", _PATH_SKEYKEYS);
+ errx(errs, "cannot open %s", _PATH_SKEYDIR);
break;
case 1: /* Unknown user */
warnx("%s is not listed in %s", name,
- _PATH_SKEYKEYS);
+ _PATH_SKEYDIR);
}
(void)fclose(key.keyfile);
diff --git a/usr.bin/skeyinit/Makefile b/usr.bin/skeyinit/Makefile
index f2beaf1f55e..d4cea9f3d10 100644
--- a/usr.bin/skeyinit/Makefile
+++ b/usr.bin/skeyinit/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 1997/09/21 11:50:55 deraadt Exp $
+# $OpenBSD: Makefile,v 1.7 2002/05/16 03:50:42 millert Exp $
PROG= skeyinit
-BINOWN=root
-BINMODE=4555
+BINGRP=auth
+BINMODE=2555
DPADD= ${LIBSKEY}
LDADD= -lskey
diff --git a/usr.bin/skeyinit/skeyinit.1 b/usr.bin/skeyinit/skeyinit.1
index d11e1825702..91ba68e3338 100644
--- a/usr.bin/skeyinit/skeyinit.1
+++ b/usr.bin/skeyinit/skeyinit.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: skeyinit.1,v 1.20 2001/06/20 22:25:08 millert Exp $
+.\" $OpenBSD: skeyinit.1,v 1.21 2002/05/16 03:50:42 millert Exp $
.\" $NetBSD: skeyinit.1,v 1.4 1995/07/07 22:24:09 jtc Exp $
.\" @(#)skeyinit.1 1.1 10/28/93
.\"
@@ -11,7 +11,12 @@
.Sh SYNOPSIS
.Nm skeyinit
.Op Fl s
+.Op Fl x
.Op Fl z
+.Op Fl C
+.Op Fl D
+.Op Fl E
+.Op Fl a Ar auth-type
.Op Fl n Ar count
.Oo
.Fl md4 | Fl md5 | Fl sha1 |
@@ -49,8 +54,25 @@ S/Key challenge and allowed to proceed if it is correct.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl x
-Displays pass phrase in hexadecimal instead of ASCII.
+.It Fl C
+Converts from the old-style
+.Pa /etc/skeykeys
+database to a new-style database where user records are stored in the
+.Pa /etc/skey
+directory.
+If an entry already exists in the new-style database it will not
+be overwritten.
+.Pa
+.It Fl D
+Disables access to the S/Key database.
+Only the superuser may use the
+.Fl D
+option.
+.It Fl E
+Enables access to the S/Key database.
+Only the superuser may use the
+.Fl E
+option.
.It Fl s
Set secure mode where the user is expected to have used a secure
machine to generate the first one-time password.
@@ -76,8 +98,15 @@ count and seed.
You can then "cut-and-paste" or type the words into the
.Nm
window.
+.It Fl x
+Displays pass phrase in hexadecimal instead of ASCII.
.It Fl z
Allows the user to zero their S/Key entry.
+.It Fl a Ar auth-type
+Specify an authentication type such as
+.Dq krb4
+or
+.Dq krb5 .
.It Fl n Ar count
Start the
.Nm skey
@@ -99,17 +128,20 @@ By default the current user is operated on.
.Sh ERRORS
.Bl -tag -compact -width "skey disabled"
.It "skey disabled"
-.Pa /etc/skeykeys
-does not exist.
-It must be created by the superuser in order to use
-.Nm skeyinit .
+.Pa /etc/skey
+does not exist or is not accessable by the user.
+The superuser may enable
+.Nm
+via the
+.Fl E
+flag.
.El
.Sh FILES
-.Bl -tag -width /etc/skeykeys
-.It Pa /etc/skeykeys
-database of information for S/Key system
+.Bl -tag -width /etc/skey
+.It Pa /etc/skey
+directory containing user entries for S/Key
.El
.Sh SEE ALSO
.Xr skey 1
.Sh AUTHORS
-Phil Karn, Neil M. Haller, John S. Walden, Scott Chasin
+Phil Karn, Neil M. Haller, John S. Walden, Scott Chasin, Todd Miller
diff --git a/usr.bin/skeyinit/skeyinit.c b/usr.bin/skeyinit/skeyinit.c
index 791bc429e73..c340f0ec003 100644
--- a/usr.bin/skeyinit/skeyinit.c
+++ b/usr.bin/skeyinit/skeyinit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: skeyinit.c,v 1.31 2002/02/16 21:27:52 millert Exp $ */
+/* $OpenBSD: skeyinit.c,v 1.32 2002/05/16 03:50:42 millert Exp $ */
/* OpenBSD S/Key (skeyinit.c)
*
@@ -14,12 +14,13 @@
#include <sys/param.h>
#include <sys/file.h>
-#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <ctype.h>
#include <err.h>
#include <errno.h>
-#include <ctype.h>
#include <pwd.h>
#include <readpassphrase.h>
#include <stdio.h>
@@ -31,37 +32,35 @@
#include <utmp.h>
#include <skey.h>
+#include <bsd_auth.h>
#ifndef SKEY_NAMELEN
#define SKEY_NAMELEN 4
#endif
-void lockeof(struct skey *, char *);
void usage(char *);
void secure_mode(int *, char *, char *, char *, char *, size_t);
void normal_mode(char *, int, char *, char *, char *);
void timedout(int);
+void convert_db(void);
+void enable_db(int);
int
main(argc, argv)
int argc;
char *argv[];
{
- int rval, i, l, n=0, defaultsetup=1, zerokey=0, hexmode=0;
- int oldmd4=0;
- time_t now;
- size_t seedlen;
+ int rval, i, l, n, defaultsetup, zerokey, hexmode, enable, convert;
char hostname[MAXHOSTNAMELEN];
- char passwd[SKEY_MAX_PW_LEN+2];
- char seed[SKEY_MAX_SEED_LEN+2], defaultseed[SKEY_MAX_SEED_LEN+1];
- char tbuf[27], buf[256], key[SKEY_BINKEY_SIZE];
- char lastc, me[UT_NAMESIZE+1], *salt, *p, *ht=NULL;
+ char seed[SKEY_MAX_SEED_LEN + 2], defaultseed[SKEY_MAX_SEED_LEN + 1];
+ char buf[256], key[SKEY_BINKEY_SIZE], filename[PATH_MAX], *ht;
+ char lastc, me[UT_NAMESIZE + 1], *p, *auth_type;
struct skey skey;
struct passwd *pp;
- struct tm *tm;
- if (geteuid() != 0)
- errx(1, "must be setuid root.");
+ n = zerokey = hexmode = enable = convert = 0;
+ defaultsetup = 1;
+ ht = auth_type = NULL;
/* Build up a default seed based on the hostname and time */
if (gethostname(hostname, sizeof(hostname)) < 0)
@@ -75,9 +74,6 @@ main(argc, argv)
*p++ = hostname[i];
}
*p = '\0';
- (void)time(&now);
- (void)sprintf(tbuf, "%05ld", (long) (now % 100000));
- (void)strncat(defaultseed, tbuf, sizeof(defaultseed) - 5);
if ((pp = getpwuid(getuid())) == NULL)
err(1, "no user with uid %d", getuid());
@@ -85,14 +81,19 @@ main(argc, argv)
if ((pp = getpwnam(me)) == NULL)
err(1, "Who are you?");
- salt = pp->pw_passwd;
for (i = 1; i < argc && argv[i][0] == '-' && strcmp(argv[i], "--");) {
if (argv[i][2] == '\0') {
/* Single character switch */
switch (argv[i][1]) {
+ case 'a':
+ if (argv[++i] == NULL || argv[i][0] == '\0')
+ usage(argv[0]);
+ auth_type = argv[i];
+ break;
case 's':
defaultsetup = 0;
+ auth_type = "skey";
break;
case 'x':
hexmode = 1;
@@ -107,6 +108,15 @@ main(argc, argv)
errx(1, "count must be > 0 and < %d",
SKEY_MAX_SEQ);
break;
+ case 'C':
+ convert = 1;
+ break;
+ case 'D':
+ enable = -1;
+ break;
+ case 'E':
+ enable = 1;
+ break;
default:
usage(argv[0]);
}
@@ -119,11 +129,21 @@ main(argc, argv)
}
i++;
}
+ argv += i;
+ argc -= i;
- /* check for optional user string */
- if (argc - i > 1) {
+ if (argc > 1 || (enable && convert) || (enable && argc) ||
+ (convert && argc))
usage(argv[0]);
- } else if (argv[i]) {
+
+ /* Handle -C, -D, and -E */
+ if (enable)
+ enable_db(enable);
+ if (convert)
+ convert_db();
+
+ /* Check for optional user string. */
+ if (argc == 1) {
if ((pp = getpwnam(argv[i])) == NULL) {
if (getuid() == 0) {
static struct passwd _pp;
@@ -134,42 +154,23 @@ main(argc, argv)
} else {
errx(1, "User unknown: %s", argv[i]);
}
- } else if (strcmp(pp->pw_name, me) != 0) {
- if (getuid() != 0) {
- /* Only root can change other's passwds */
- errx(1, "Permission denied.");
- }
+ } else if (strcmp(pp->pw_name, me) != 0 && getuid() != 0) {
+ /* Only root can change other's S/Keys. */
+ errx(1, "Permission denied.");
}
}
if (defaultsetup)
- fputs("Reminder - Only use this method if you are directly connected\n or have an encrypted channel. If you are using telnet\n or rlogin, hit return now and use skeyinit -s.\n", stderr);
+ fputs("Reminder - Only use this method if you are directly "
+ "connected\n or have an encrypted channel. If "
+ "you are using telnet,\n hit return now and use "
+ "skeyinit -s.\n", stderr);
if (getuid() != 0) {
- /* XXX - use BSD auth */
- passwd[0] = '\0';
- if (!defaultsetup && skeychallenge(&skey, me, buf) == 0) {
- printf("Enter S/Key password below or hit return twice "
- "to enter standard password.\n%s\n", buf);
- fflush(stdout);
- if (!readpassphrase("S/Key Password: ", passwd,
- sizeof(passwd), 0) || passwd[0] == '\0') {
- readpassphrase("S/Key Password: [echo on] ",
- passwd, sizeof(passwd), RPP_ECHO_ON);
- }
- }
- if (passwd[0]) {
- if (skeyverify(&skey, passwd) != 0)
- errx(1, "Password incorrect.");
- } else {
- fflush(stdout);
- readpassphrase("Password: ", passwd, sizeof(passwd), 0);
- if (strcmp(crypt(passwd, salt), pp->pw_passwd)) {
- if (passwd[0])
- warnx("Password incorrect.");
- exit(1);
- }
- }
+ if ((pp = pw_dup(pp)) == NULL)
+ err(1, NULL);
+ if (!auth_userokay(pp->pw_name, auth_type, NULL, NULL))
+ errx(1, "Password incorrect");
}
/*
@@ -229,17 +230,24 @@ main(argc, argv)
errx(1, "You have no entry to zero.");
(void)printf("[Adding %s with %s]\n", pp->pw_name,
ht ? ht : skey_get_algorithm());
- lockeof(&skey, pp->pw_name);
+ if (snprintf(filename, sizeof(filename), "%s/%s",
+ _PATH_SKEYDIR, pp->pw_name) >= sizeof(filename)) {
+ errno = ENAMETOOLONG;
+ err(1, "Cannot create S/Key entry");
+ }
+ if ((l = open(filename, O_RDWR | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR)) == -1 ||
+ flock(l, LOCK_EX) != 0 ||
+ (skey.keyfile = fdopen(l, "r+")) == NULL)
+ err(1, "Cannot create S/Key entry");
break;
}
+ if (fchown(fileno(skey.keyfile), pp->pw_uid, -1) != 0 ||
+ fchmod(fileno(skey.keyfile), S_IRUSR | S_IWUSR) != 0)
+ err(1, "can't set owner/mode for %s", pp->pw_name);
if (n == 0)
n = 99;
- /* Do we have an old-style md4 entry? */
- if (rval == 0 && strcmp("md4", skey_get_algorithm()) == 0 &&
- strcmp("md4", skey.logname + strlen(skey.logname) + 1) != 0)
- oldmd4 = 1;
-
/* Set hash type if asked to */
if (ht && strcmp(ht, skey_get_algorithm()) != 0)
skey_set_algorithm(ht);
@@ -251,55 +259,14 @@ main(argc, argv)
normal_mode(pp->pw_name, n, key, seed, defaultseed);
alarm(0);
- (void)time(&now);
- tm = localtime(&now);
- (void)strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm);
-
- /* If this is an exiting entry, compute the line length and seed pad */
- seedlen = SKEY_MAX_SEED_LEN;
- if (rval == 0) {
- int nlen;
-
- nlen = strlen(pp->pw_name) + 1 + strlen(skey_get_algorithm()) +
- 1 + 4 + 1 + strlen(seed) + 1 + 16 + 1 + strlen(tbuf) + 1;
-
- /*
- * If there was no hash type (md4) add one unless we
- * are short on space.
- */
- if (oldmd4) {
- if (nlen > skey.len)
- nlen -= 4;
- else
- oldmd4 = 0;
- }
-
- /* If new entry is longer than the old, comment out the old. */
- if (nlen > skey.len) {
- (void)skeyzero(&skey);
- /* Re-open keys file and seek to the end */
- if (skeylookup(&skey, pp->pw_name) == -1)
- err(1, "cannot reopen database");
- lockeof(&skey, pp->pw_name);
- } else {
- /* Compute how much to space-pad the seed */
- seedlen = strlen(seed) + (skey.len - nlen);
- }
- }
-
+ /* XXX - why use malloc here? */
if ((skey.val = (char *)malloc(16 + 1)) == NULL)
err(1, "Can't allocate memory");
btoa8(skey.val, key);
- /* Don't save algorithm type for md4 (maintain record length) */
- /* XXX - should check return values of fprintf + fclose */
- if (oldmd4)
- (void)fprintf(skey.keyfile, "%s %04d %-*s %s %-21s\n",
- pp->pw_name, n, seedlen, seed, skey.val, tbuf);
- else
- (void)fprintf(skey.keyfile, "%s %s %04d %-*s %s %-21s\n",
- pp->pw_name, skey_get_algorithm(), n, seedlen, seed,
- skey.val, tbuf);
+ (void)fseek(skey.keyfile, 0L, SEEK_SET);
+ (void)fprintf(skey.keyfile, "%s\n%s\n%04d\n%s\n%s\n",
+ pp->pw_name, skey_get_algorithm(), n, seed, skey.val);
(void)fclose(skey.keyfile);
(void)printf("\nID %s skey is otp-%s %d %s\n", pp->pw_name,
@@ -310,35 +277,6 @@ main(argc, argv)
}
void
-lockeof(mp, user)
- struct skey *mp;
- char *user;
-{
- struct flock fl;
-
- fseek(mp->keyfile, 0, SEEK_END);
-dolock:
- fl.l_start = ftell(mp->keyfile);
- fl.l_len = mp->len;
- fl.l_pid = getpid();
- fl.l_type = F_WRLCK;
- fl.l_whence = SEEK_SET;
-
- if (fcntl(fileno(mp->keyfile), F_SETLKW, &fl) == -1)
- err(1, "Can't lock database");
-
- /* Make sure we are still at the end. */
- fseek(mp->keyfile, 0, SEEK_END);
- if (fl.l_start == ftell(mp->keyfile))
- return; /* still at EOF */
-
- fclose(mp->keyfile);
- if (skeylookup(mp, user) != 1)
- errx(1, "user %s already added", user);
- goto dolock;
-}
-
-void
secure_mode(count, key, seed, defaultseed, buf, bufsiz)
int *count;
char *key;
@@ -483,6 +421,97 @@ normal_mode(username, n, key, seed, defaultseed)
f(key);
}
+void
+enable_db(op)
+ int op;
+{
+ if (op == 1) {
+ /* enable */
+ if (mkdir(_PATH_SKEYDIR, 01730) != 0 && errno != EEXIST)
+ err(1, "can't mkdir %s", _PATH_SKEYDIR);
+ if (chmod(_PATH_SKEYDIR, 01730) != 0)
+ err(1, "can't chmod %s", _PATH_SKEYDIR);
+ } else {
+ /* disable */
+ if (chmod(_PATH_SKEYDIR, 0) != 0 && errno != ENOENT)
+ err(1, "can't chmod %s", _PATH_SKEYDIR);
+ }
+ exit(0);
+}
+
+#define _PATH_SKEYKEYS "/etc/skeykeys"
+void
+convert_db(void)
+{
+ struct passwd *pp;
+ uid_t uid;
+ FILE *keyfile;
+ FILE *newfile;
+ char buf[256], *logname, *hashtype, *seed, *val, *cp;
+ char filename[PATH_MAX];
+ int fd, n;
+
+ if ((keyfile = fopen(_PATH_SKEYKEYS, "r")) == NULL)
+ err(1, "can't open %s", _PATH_SKEYKEYS);
+ if (flock(fileno(keyfile), LOCK_EX) != 0)
+ err(1, "can't lock %s", _PATH_SKEYKEYS);
+ if (mkdir(_PATH_SKEYDIR, 01730) != 0 && errno != EEXIST)
+ err(1, "can't mkdir %s", _PATH_SKEYDIR);
+ if (chmod(_PATH_SKEYDIR, 01730) != 0)
+ err(1, "can't chmod %s", _PATH_SKEYDIR);
+
+ /*
+ * Loop over each entry in _PATH_SKEYKEYS, creating a file
+ * in _PATH_SKEYDIR for each one.
+ */
+ while (fgets(buf, sizeof(buf), keyfile) != NULL) {
+ if (buf[0] == '#')
+ continue;
+ if ((logname = strtok(buf, " \t")) == NULL)
+ continue;
+ if ((cp = strtok(NULL, " \t")) == NULL)
+ continue;
+ if (isalpha(*cp)) {
+ hashtype = cp;
+ if ((cp = strtok(NULL, " \t")) == NULL)
+ continue;
+ } else
+ hashtype = "md4";
+ n = atoi(cp);
+ if ((seed = strtok(NULL, " \t")) == NULL)
+ continue;
+ if ((val = strtok(NULL, " \t")) == NULL)
+ continue;
+
+ if ((pp = getpwnam(logname)) != NULL)
+ uid = pp->pw_uid;
+ else
+ uid = 0;
+
+ /* Now write the new-style record. */
+ if (snprintf(filename, sizeof(filename), "%s/%s", _PATH_SKEYDIR,
+ logname) >= sizeof(filename)) {
+ errno = ENAMETOOLONG;
+ warn("%s", logname);
+ continue;
+ }
+ fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+ if (fd == -1 || flock(fd, LOCK_EX) != 0 ||
+ (newfile = fdopen(fd, "r+")) == NULL) {
+ warn("%s", logname);
+ continue;
+ }
+ (void)fprintf(newfile, "%s\n%s\n%04d\n%s\n%s\n", logname,
+ hashtype, n, seed, val);
+ (void)fchown(fileno(newfile), uid, -1);
+ (void)fclose(newfile);
+ }
+ printf("%s has been populated. NOTE: %s has *not* been removed.\n"
+ "It should be removed once you have verified that the new keys "
+ "work.\n", _PATH_SKEYDIR, _PATH_SKEYKEYS);
+ exit(0);
+}
+
#define TIMEOUT_MSG "Timed out waiting for input.\n"
void
timedout(signo)
@@ -497,7 +526,8 @@ void
usage(s)
char *s;
{
- (void)fprintf(stderr,
- "Usage: %s [-s] [-x] [-z] [-n count] [-md4|-md5|-sha1|-rmd160] [user]\n", s);
+ (void)fprintf(stderr, "usage: %s [-s] [-x] [-z] [-C] [-D] [-E] "
+ "[-a auth_type] [-n count]\n "
+ "[-md4|-md5|-sha1|-rmd160] [user]\n", s);
exit(1);
}