summaryrefslogtreecommitdiff
path: root/lib/libskey
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-05-16 03:50:43 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-05-16 03:50:43 +0000
commit7d3f36452983f797e42ce4414ba46a3137027bdc (patch)
tree0be21071c07d945fedd70b25fec868aaf556e149 /lib/libskey
parent6988d5e220bd608ba319da0b339bfba04dba556b (diff)
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.
Diffstat (limited to 'lib/libskey')
-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
4 files changed, 237 insertions, 359 deletions
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);
}