From d5dd91cdf59d18f9cfff6072a73247438e00ea4e Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 27 Sep 1996 15:39:01 +0000 Subject: Deal with both MD4 and MD5 s/key's --- lib/libskey/Makefile | 16 ++- lib/libskey/put.c | 349 +++++++++++++++++++++++----------------------- lib/libskey/shlib_version | 2 +- lib/libskey/skey.h | 27 ++-- lib/libskey/skeylogin.c | 159 ++++++++++----------- lib/libskey/skeysubr.c | 327 +++++++++++++++++++++++++++---------------- 6 files changed, 483 insertions(+), 397 deletions(-) (limited to 'lib/libskey') diff --git a/lib/libskey/Makefile b/lib/libskey/Makefile index 7e616b17dc6..31cbc14f78b 100644 --- a/lib/libskey/Makefile +++ b/lib/libskey/Makefile @@ -1,7 +1,17 @@ -# $Id: Makefile,v 1.1 1995/10/18 08:43:11 deraadt Exp $ +# $Id: Makefile,v 1.2 1996/09/27 15:38:57 millert Exp $ LIB= skey -SRCS= skeylogin.c skeysubr.c md4.c put.c -CFLAGS+= -DUSE_ECHO +SRCS= skeylogin.c skeysubr.c put.c +HDRS= skey.h +#CFLAGS+= -DSKEY_MDX_DEFAULT=4 + +includes: + @cd ${.CURDIR}; for i in $(HDRS); do \ + j="cmp -s $$i ${DESTDIR}/usr/include/`basename $$i` || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 $$i \ + ${DESTDIR}/usr/include"; \ + echo $$j; \ + eval "$$j"; \ + done .include diff --git a/lib/libskey/put.c b/lib/libskey/put.c index 1a493f1e35c..83d65d795cd 100644 --- a/lib/libskey/put.c +++ b/lib/libskey/put.c @@ -8,7 +8,7 @@ * * Dictionary lookup and extraction. * - * $Id: put.c,v 1.1 1995/10/18 08:43:11 deraadt Exp $ + * $Id: put.c,v 1.2 1996/09/27 15:38:58 millert Exp $ */ #include @@ -2078,36 +2078,40 @@ char Wp[2048][4] = { * Returns a pointer to a static buffer */ char * - btoe (engout, c) - char *c, *engout; +btoe (engout, c) + char *c, *engout; { - char cp[9]; /* add in room for the parity 2 bits */ - int p, i; + char cp[10]; /* add in room for the parity 2 bits + extract() slop */ + int p, i; - engout[0] = '\0'; - memcpy (cp, c, 8); - /* compute parity */ - for (p = 0, i = 0; i < 64; i += 2) - p += extract (cp, i, 2); + engout[0] = '\0'; - cp[8] = (char) p << 6; + /* workaround for extract() reads beyond end of data */ + (void) memset(cp, 0, sizeof(cp)); + (void) memcpy(cp, c, 8); - strncat (engout, &Wp[extract (cp, 0, 11)][0], 4); - strcat (engout, " "); - strncat (engout, &Wp[extract (cp, 11, 11)][0], 4); - strcat (engout, " "); - strncat (engout, &Wp[extract (cp, 22, 11)][0], 4); - strcat (engout, " "); - strncat (engout, &Wp[extract (cp, 33, 11)][0], 4); - strcat (engout, " "); - strncat (engout, &Wp[extract (cp, 44, 11)][0], 4); - strcat (engout, " "); - strncat (engout, &Wp[extract (cp, 55, 11)][0], 4); + /* compute parity */ + for (p = 0, i = 0; i < 64; i += 2) + p += extract (cp, i, 2); + + cp[8] = (char) p << 6; + + (void) strncat (engout, &Wp[extract (cp, 0, 11)][0], 4); + (void) strcat (engout, " "); + (void) strncat (engout, &Wp[extract (cp, 11, 11)][0], 4); + (void) strcat (engout, " "); + (void) strncat (engout, &Wp[extract (cp, 22, 11)][0], 4); + (void) strcat (engout, " "); + (void) strncat (engout, &Wp[extract (cp, 33, 11)][0], 4); + (void) strcat (engout, " "); + (void) strncat (engout, &Wp[extract (cp, 44, 11)][0], 4); + (void) strcat (engout, " "); + (void) strncat (engout, &Wp[extract (cp, 55, 11)][0], 4); #ifdef notdef - printf ("engout is %s\n\r", engout); + (void) fprintf (stderr, "engout is %s\n\r", engout); #endif - return (engout); + return (engout); } /* convert English to binary @@ -2117,70 +2121,66 @@ char * * -2 words OK but parity is wrong */ int - etob (out, e) - char *out; - char *e; +etob (out, e) + char *out; + char *e; { - char *word; - int i, p, v, l, low, high; - char b[9]; - char input[36]; + char *word; + int i, p, v, l, low, high; + char b[9]; + char input[36]; - if (e == NULL) - return -1; + if (e == NULL) + return -1; - strncpy (input, e, sizeof (input)); - memset (b, 0, sizeof (b)); - memset (out, 0, 8); - for (i = 0, p = 0; i < 6; i++, p += 11) - { - if ((word = strtok (i == 0 ? input : NULL, " ")) == NULL) - return -1; + (void) strncpy (input, e, sizeof (input)); + (void) memset (b, 0, sizeof (b)); + (void) memset (out, 0, 8); + for (i = 0, p = 0; i < 6; i++, p += 11) { + if ((word = strtok (i == 0 ? input : NULL, " ")) == NULL) + return -1; - l = strlen (word); - if (l > 4 || l < 1) - return -1; - else if (l < 4) - { - low = 0; - high = 570; - } - else - { - low = 571; - high = 2047; - } - standard (word); + l = strlen (word); + if (l > 4 || l < 1) { + return -1; + } else if (l < 4) { + low = 0; + high = 570; + } else { + low = 571; + high = 2047; + } + standard (word); - if ((v = wsrch (word, low, high)) < 0) - return 0; + if ((v = wsrch (word, low, high)) < 0) + return 0; - insert (b, v, p, 11); - } + insert (b, v, p, 11); + } - /* now check the parity of what we got */ - for (p = 0, i = 0; i < 64; i += 2) - p += extract (b, i, 2); + /* now check the parity of what we got */ + for (p = 0, i = 0; i < 64; i += 2) + p += extract (b, i, 2); - if ((p & 3) != extract (b, 64, 2)) - return -2; + if ((p & 3) != extract (b, 64, 2)) + return -2; - memcpy (out, b, 8); + (void) memcpy (out, b, 8); - return 1; + return 1; } /* Display 8 bytes as a series of 16-bit hex digits */ char * - put8 (out, s) - char *out; - char *s; +put8 (out, s) + char *out; + char *s; { - sprintf (out, "%02X%02X %02X%02X %02X%02X %02X%02X", - s[0] & 0xff, s[1] & 0xff, s[2] & 0xff, - s[3] & 0xff, s[4] & 0xff, s[5] & 0xff, - s[6] & 0xff, s[7] & 0xff); - return out; + (void) sprintf (out, "%02X%02X %02X%02X %02X%02X %02X%02X", + s[0] & 0xff, s[1] & 0xff, s[2] & 0xff, + s[3] & 0xff, s[4] & 0xff, s[5] & 0xff, + s[6] & 0xff, s[7] & 0xff); + return out; } #ifdef notdef @@ -2188,135 +2188,130 @@ char * * Provided as a possible alternative to btoe() */ char * - btoc (cp) - char *cp; +btoc (cp) + char *cp; { - int i; - static char out[31]; + int i; + static char out[31]; - /* code out put by characters 6 bits each added to 0x21 (!) */ - for (i = 0; i <= 10; i++) - { - /* last one is only 4 bits not 6 */ - out[i] = '!' + extract (cp, 6 * i, i >= 10 ? 4 : 6); - } - out[i] = '\0'; - return (out); + /* code out put by characters 6 bits each added to 0x21 (!) */ + for (i = 0; i <= 10; i++) { + /* last one is only 4 bits not 6 */ + out[i] = '!' + extract (cp, 6 * i, i >= 10 ? 4 : 6); + } + out[i] = '\0'; + return (out); } - #endif /* Internal subroutines for word encoding/decoding */ /* Dictionary binary search */ static int - wsrch (w, low, high) - char *w; - int low, high; +wsrch (w, low, high) + char *w; + int low, high; { - int i, j; + int i, j; + + for (;;) { + i = (low + high) / 2; - for (;;) - { - i = (low + high) / 2; - if ((j = strncmp (w, Wp[i], 4)) == 0) - return i; /* Found it */ - if (high == low + 1) - { - /* Avoid effects of integer truncation in /2 */ - if (strncmp (w, Wp[high], 4) == 0) - return high; - else - return -1; - } - if (low >= high) - return -1; /* I don't *think* this can happen... */ - if (j < 0) - high = i; /* Search lower half */ - else - low = i; /* Search upper half */ - } + if ((j = strncmp (w, Wp[i], 4)) == 0) + return i; /* Found it */ + + if (high == low + 1) { + /* Avoid effects of integer truncation in /2 */ + if (strncmp (w, Wp[high], 4) == 0) + return high; + else + return -1; + } + + if (low >= high) + return -1; /* I don't *think* this can happen... */ + if (j < 0) + high = i; /* Search lower half */ + else + low = i; /* Search upper half */ + } } + static void - insert (s, x, start, length) - char *s; - int x; - int start, length; +insert (s, x, start, length) + char *s; + int x; + int start, length; { - unsigned char cl; - unsigned char cc; - unsigned char cr; - unsigned long y; - int shift; + unsigned char cl; + unsigned char cc; + unsigned char cr; + unsigned long y; + int shift; - assert (length <= 11); - assert (start >= 0); - assert (length >= 0); - assert (start + length <= 66); + assert (length <= 11); + assert (start >= 0); + assert (length >= 0); + assert (start + length <= 66); - shift = ((8 - ((start + length) % 8)) % 8); - y = (long) x << shift; - cl = (y >> 16) & 0xff; - cc = (y >> 8) & 0xff; - cr = y & 0xff; - if (shift + length > 16) - { - s[start / 8] |= cl; - s[start / 8 + 1] |= cc; - s[start / 8 + 2] |= cr; - } - else if (shift + length > 8) - { - s[start / 8] |= cc; - s[start / 8 + 1] |= cr; - } - else - { - s[start / 8] |= cr; - } + shift = ((8 - ((start + length) % 8)) % 8); + y = (long) x << shift; + cl = (y >> 16) & 0xff; + cc = (y >> 8) & 0xff; + cr = y & 0xff; + if (shift + length > 16) { + s[start / 8] |= cl; + s[start / 8 + 1] |= cc; + s[start / 8 + 2] |= cr; + } else if (shift + length > 8) { + s[start / 8] |= cc; + s[start / 8 + 1] |= cr; + } else { + s[start / 8] |= cr; + } } static void - standard (word) - register char *word; +standard (word) + register char *word; { - while (*word) - { - if (!isascii (*word)) - break; - if (islower (*word)) - *word = toupper (*word); - if (*word == '1') - *word = 'L'; - if (*word == '0') - *word = 'O'; - if (*word == '5') - *word = 'S'; - word++; - } + while (*word) { + if (!isascii(*word)) + break; + if (islower(*word)) + *word = toupper(*word); + if (*word == '1') + *word = 'L'; + if (*word == '0') + *word = 'O'; + if (*word == '5') + *word = 'S'; + word++; + } } /* Extract 'length' bits from the char array 's' starting with bit 'start' */ static unsigned long - extract (s, start, length) - char *s; - int start, length; +extract (s, start, length) + char *s; + int start, length; { - unsigned char cl; - unsigned char cc; - unsigned char cr; - unsigned long x; + unsigned char cl; + unsigned char cc; + unsigned char cr; + unsigned long x; + + assert (length <= 11); + assert (start >= 0); + assert (length >= 0); + assert (start + length <= 66); - assert (length <= 11); - assert (start >= 0); - assert (length >= 0); - assert (start + length <= 66); + cl = s[start / 8]; + cc = s[start / 8 + 1]; + cr = s[start / 8 + 2]; + x = ((long) (cl << 8 | cc) << 8 | cr); + x = x >> (24 - (length + (start % 8))); + x = (x & (0xffff >> (16 - length))); - cl = s[start / 8]; - cc = s[start / 8 + 1]; - cr = s[start / 8 + 2]; - x = ((long) (cl << 8 | cc) << 8 | cr); - x = x >> (24 - (length + (start % 8))); - x = (x & (0xffff >> (16 - length))); - return (x); + return (x); } diff --git a/lib/libskey/shlib_version b/lib/libskey/shlib_version index 97c9f92d6b8..3d7c908e43d 100644 --- a/lib/libskey/shlib_version +++ b/lib/libskey/shlib_version @@ -1,2 +1,2 @@ major=0 -minor=0 +minor=1 diff --git a/lib/libskey/skey.h b/lib/libskey/skey.h index 1d7f596a9ea..e9de0d4c84d 100644 --- a/lib/libskey/skey.h +++ b/lib/libskey/skey.h @@ -11,7 +11,7 @@ * * Main client header * - * $Id: skey.h,v 1.2 1995/12/20 09:48:23 deraadt Exp $ + * $Id: skey.h,v 1.3 1996/09/27 15:38:59 millert Exp $ */ #if defined(__TURBOC__) || defined(__STDC__) || defined(LATTICE) @@ -33,23 +33,21 @@ /* Server-side data structure for reading keys file during login */ struct skey { - FILE *keyfile; - char buf[256]; - char *logname; - int n; - char *seed; - char *val; - long recstart; /* needed so reread of buffer is efficient */ - - + FILE *keyfile; + char buf[256]; + char *logname; + int n; + char *seed; + char *val; + long recstart; /* needed so reread of buffer is efficient */ }; /* Client-side structure for scanning data stream for challenge */ struct mc { - char buf[256]; - int skip; - int cnt; + char buf[256]; + int skip; + int cnt; }; void f __ARGS ((char *x)); @@ -75,4 +73,5 @@ int getskeyprompt __ARGS ((struct skey *, char *, char *)); int atob8 __ARGS((char *, char *)); int btoa8 __ARGS((char *, char *)); int htoi __ARGS((char)); - +int skey_get_MDX __ARGS(()); +int skey_set_MDX __ARGS((int)); diff --git a/lib/libskey/skeylogin.c b/lib/libskey/skeylogin.c index 000a61b6200..e72bc313241 100644 --- a/lib/libskey/skeylogin.c +++ b/lib/libskey/skeylogin.c @@ -8,7 +8,7 @@ * * S/KEY verification check, lookups, and authentication. * - * $Id: skeylogin.c,v 1.2 1995/12/20 09:48:24 deraadt Exp $ + * $Id: skeylogin.c,v 1.3 1996/09/27 15:38:59 millert Exp $ */ #include @@ -20,7 +20,6 @@ #include #include - #include #include #include @@ -44,7 +43,7 @@ int skeylookup __ARGS((struct skey *, char *)); * record. */ int -getskeyprompt(mp,name,prompt) +getskeyprompt(mp, name, prompt) struct skey *mp; char *name; char *prompt; @@ -52,16 +51,17 @@ getskeyprompt(mp,name,prompt) int rval; sevenbit(name); - rval = skeylookup(mp,name); - strcpy(prompt,"s/key 55 latour1\n"); + rval = skeylookup(mp, name); + (void)strcpy(prompt, "s/key MD0 55 latour1\n"); switch (rval) { case -1: /* File error */ return -1; case 0: /* Lookup succeeded, return challenge */ - sprintf(prompt,"s/key %d %s\n",mp->n - 1,mp->seed); + (void)sprintf(prompt, "s/key MD%d %d %s\n", skey_get_MDX(), + mp->n - 1, mp->seed); return 0; case 1: /* User not found */ - fclose(mp->keyfile); + (void)fclose(mp->keyfile); return -1; } return -1; /* Can't happen */ @@ -87,10 +87,11 @@ skeychallenge(mp,name, ss) case -1: /* File error */ return -1; case 0: /* Lookup succeeded, issue challenge */ - sprintf(ss, "s/key %d %s",mp->n - 1,mp->seed); + (void)sprintf(ss, "s/key MD%d %d %s", skey_get_MDX(), + mp->n - 1, mp->seed); return 0; case 1: /* User not found */ - fclose(mp->keyfile); + (void)fclose(mp->keyfile); return -1; } return -1; /* Can't happen */ @@ -107,59 +108,68 @@ skeylookup(mp,name) struct skey *mp; char *name; { - int found; - int len; - long recstart; + int found, len; + long recstart = 0; char *cp; struct stat statbuf; - /* See if the _PATH_KEYFILE exists, and create it if not */ - - if (stat(_PATH_KEYFILE,&statbuf) == -1 && errno == ENOENT) { - mp->keyfile = fopen(_PATH_KEYFILE,"w+"); + /* See if _PATH_KEYFILE exists, and create it if not */ + if (stat(_PATH_KEYFILE, &statbuf) == -1 && errno == ENOENT) { + mp->keyfile = fopen(_PATH_KEYFILE, "w+"); if (mp->keyfile) chmod(_PATH_KEYFILE, 0644); } else { /* Otherwise open normally for update */ - mp->keyfile = fopen(_PATH_KEYFILE,"r+"); + mp->keyfile = fopen(_PATH_KEYFILE, "r+"); } if (mp->keyfile == NULL) return -1; /* Look up user name in database */ len = strlen(name); - if( len > 8 ) len = 8; /* Added 8/2/91 - nmh */ + /* XXX - do we really want to limit it to 8 char usernames? */ + if (len > 8) + len = 8; /* Added 8/2/91 - nmh */ found = 0; while (!feof(mp->keyfile)) { recstart = ftell(mp->keyfile); mp->recstart = recstart; - if (fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf) { + if (fgets(mp->buf, sizeof(mp->buf), mp->keyfile) != mp->buf) { break; } rip(mp->buf); if (mp->buf[0] == '#') continue; /* Comment */ - if ((mp->logname = strtok(mp->buf," \t")) == NULL) + if ((mp->logname = strtok(mp->buf, " \t")) == NULL) continue; - if ((cp = strtok(NULL," \t")) == NULL) + if ((cp = strtok(NULL, " \t")) == NULL) continue; + /* Set MDX if specified, else use MD4 */ + if (cp[0] == 'M' && cp[1] == 'D') { + skey_set_MDX(atoi(&cp[2])); + if ((cp = strtok(NULL, " \t")) == NULL) + continue; + } else { + skey_set_MDX(4); + } mp->n = atoi(cp); - if ((mp->seed = strtok(NULL," \t")) == NULL) + if ((mp->seed = strtok(NULL, " \t")) == NULL) continue; - if ((mp->val = strtok(NULL," \t")) == NULL) + if ((mp->val = strtok(NULL, " \t")) == NULL) continue; - if (strlen(mp->logname) == len - && strncmp(mp->logname,name,len) == 0){ + if (strlen(mp->logname) == len && + strncmp(mp->logname, name, len) == 0) { found = 1; break; } } if (found) { - fseek(mp->keyfile,recstart,0); + (void)fseek(mp->keyfile, recstart, SEEK_SET); return 0; } else return 1; } + /* Verify response to a s/key challenge. * * Return codes: @@ -184,10 +194,10 @@ skeyverify(mp,response) time(&now); tm = localtime(&now); - strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm); + (void)strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm); if (response == NULL) { - fclose(mp->keyfile); + (void)fclose(mp->keyfile); return -1; } rip(response); @@ -195,47 +205,44 @@ skeyverify(mp,response) /* Convert response to binary */ if (etob(key, response) != 1 && atob8(key, response) != 0) { /* Neither english words or ascii hex */ - fclose(mp->keyfile); + (void)fclose(mp->keyfile); return -1; } /* Compute fkey = f(key) */ - memcpy(fkey,key,sizeof(key)); - fflush (stdout); - + (void)memcpy(fkey,key,sizeof(key)); + (void)fflush(stdout); f(fkey); + /* * in order to make the window of update as short as possible * we must do the comparison here and if OK write it back * other wise the same password can be used twice to get in * to the system */ + (void)setpriority(PRIO_PROCESS, 0, -4); - setpriority(PRIO_PROCESS, 0, -4); - - /* reread the file record NOW*/ - - fseek(mp->keyfile,mp->recstart,0); - if (fgets(mp->buf,sizeof(mp->buf),mp->keyfile) != mp->buf){ - setpriority(PRIO_PROCESS, 0, 0); - fclose(mp->keyfile); + /* reread the file record NOW */ + (void)fseek(mp->keyfile, mp->recstart, SEEK_SET); + if (fgets(mp->buf, sizeof(mp->buf), mp->keyfile) != mp->buf) { + (void)setpriority(PRIO_PROCESS, 0, 0); + (void)fclose(mp->keyfile); return -1; } rip(mp->buf); mp->logname = strtok(mp->buf," \t"); cp = strtok(NULL," \t") ; + cp = strtok(NULL," \t") ; mp->seed = strtok(NULL," \t"); mp->val = strtok(NULL," \t"); /* And convert file value to hex for comparison */ atob8(filekey,mp->val); /* Do actual comparison */ - fflush (stdout); - if (memcmp(filekey,fkey,8) != 0){ /* Wrong response */ - setpriority(PRIO_PROCESS, 0, 0); - fclose(mp->keyfile); + (void)setpriority(PRIO_PROCESS, 0, 0); + (void)fclose(mp->keyfile); return 1; } @@ -246,50 +253,47 @@ skeyverify(mp,response) */ btoa8(mp->val,key); mp->n--; - fseek(mp->keyfile,mp->recstart,0); - fprintf(mp->keyfile, "%s %04d %-16s %s %-21s\n", - mp->logname,mp->n,mp->seed, mp->val, tbuf); + (void)fseek(mp->keyfile, mp->recstart, SEEK_SET); + (void)fprintf(mp->keyfile, "%s MD%d %04d %-16s %s %-21s\n", + mp->logname, skey_get_MDX(), mp->n, mp->seed, mp->val, tbuf); - fclose(mp->keyfile); + (void)fclose(mp->keyfile); - setpriority(PRIO_PROCESS, 0, 0); + (void)setpriority(PRIO_PROCESS, 0, 0); return 0; } - /* - * skey_haskey () + * skey_haskey() * * Returns: 1 user doesnt exist, -1 fle error, 0 user exists. * */ - int -skey_haskey (username) +skey_haskey(username) char *username; { - int i; struct skey skey; - return (skeylookup (&skey, username)); + return(skeylookup(&skey, username)); } /* - * skey_keyinfo () + * skey_keyinfo() * * Returns the current sequence number and * seed for the passed user. * */ char * -skey_keyinfo (username) +skey_keyinfo(username) char *username; { int i; - static char str [50]; + static char str[50]; struct skey skey; - i = skeychallenge (&skey, username, str); + i = skeychallenge(&skey, username, str); if (i == -1) return 0; @@ -297,7 +301,7 @@ skey_keyinfo (username) } /* - * skey_passcheck () + * skey_passcheck() * * Check to see if answer is the correct one to the current * challenge. @@ -305,26 +309,25 @@ skey_keyinfo (username) * Returns: 0 success, -1 failure * */ - int -skey_passcheck (username, passwd) +skey_passcheck(username, passwd) char *username, *passwd; { int i; struct skey skey; - i = skeylookup (&skey, username); + i = skeylookup(&skey, username); if (i == -1 || i == 1) return -1; - if (skeyverify (&skey, passwd) == 0) + if (skeyverify(&skey, passwd) == 0) return skey.n; return -1; } /* - * skey_authenticate () + * skey_authenticate() * * Used when calling program will allow input of the user's * response to the challenge. @@ -332,33 +335,33 @@ skey_passcheck (username, passwd) * Returns: 0 success, -1 failure * */ - int -skey_authenticate (username) +skey_authenticate(username) char *username; { int i; char pbuf[256], skeyprompt[50]; struct skey skey; - /* Attempt a S/Key challenge */ - i = skeychallenge (&skey, username, skeyprompt); + /* Attempt an S/Key challenge */ + i = skeychallenge(&skey, username, skeyprompt); if (i == -2) return 0; - printf("[%s]\n", skeyprompt); - fflush(stdout); + (void)fprintf(stderr, "[%s]\n", skeyprompt); + (void)fflush(stderr); - printf("Response: "); - readskey(pbuf, sizeof (pbuf)); + (void)fputs("Response: ", stderr); + readskey(pbuf, sizeof(pbuf)); rip(pbuf); /* Is it a valid response? */ - if (i == 0 && skeyverify (&skey, pbuf) == 0) { + if (i == 0 && skeyverify(&skey, pbuf) == 0) { if (skey.n < 5) { - printf ("\nWarning! Key initialization needed soon. "); - printf ("(%d logins left)\n", skey.n); + (void)fprintf(stderr, + "\nWarning! Key initialization needed soon. (%d logins left)\n", + skey.n); } return 0; } @@ -382,13 +385,13 @@ skeyzero(mp, response) * Seek to the right place and write comment character * which effectively zero's out the entry. */ - fseek(mp->keyfile, mp->recstart, 0); + (void)fseek(mp->keyfile, mp->recstart, SEEK_SET); if (fputc('#', mp->keyfile) == EOF) { fclose(mp->keyfile); return -1; } - fclose(mp->keyfile); + (void)fclose(mp->keyfile); return 0; } diff --git a/lib/libskey/skeysubr.c b/lib/libskey/skeysubr.c index 232927a1ed5..9cd20eef327 100644 --- a/lib/libskey/skeysubr.c +++ b/lib/libskey/skeysubr.c @@ -10,7 +10,7 @@ * * S/KEY misc routines. * - * $Id: skeysubr.c,v 1.1 1995/10/18 08:43:11 deraadt Exp $ + * $Id: skeysubr.c,v 1.2 1996/09/27 15:39:00 millert Exp $ */ #include @@ -18,64 +18,109 @@ #include #include #include +#include +#include -#include "md4.h" #include "skey.h" -struct termios newtty; -struct termios oldtty; +/* Default MDX function to use (currently 4 or 5) */ +#ifndef SKEY_MDX_DEFAULT +#define SKEY_MDX_DEFAULT 5 +#endif static void trapped __ARGS((int sig)); -static void set_term __ARGS((void)); -static void unset_term __ARGS((void)); -static void echo_off __ARGS((void)); +static void f_MD4 __ARGS ((char *x)); +static void f_MD5 __ARGS ((char *x)); +static int keycrunch_MD4 __ARGS ((char *result, char *seed, char *passwd)); +static int keycrunch_MD5 __ARGS ((char *result, char *seed, char *passwd)); -/* Crunch a key: - * concatenate the seed and the password, run through MD4 and +static int skey_MDX = 0; +static int skey_echo; + +/* + * Crunch a key: + * concatenate the seed and the password, run through MD4/5 and * collapse to 64 bits. This is defined as the user's starting key. */ int -keycrunch(result,seed,passwd) -char *result; /* 8-byte result */ -char *seed; /* Seed, any length */ -char *passwd; /* Password, any length */ +keycrunch(result, seed, passwd) + char *result; /* 8-byte result */ + char *seed; /* Seed, any length */ + char *passwd; /* Password, any length */ +{ + switch (skey_get_MDX()) { + /* + * Need a default case to appease gc even though + * skey_set_MDX() guantaees we get back 4 or 5 + */ + case 4 : return(keycrunch_MD4(result, seed, passwd)); + default : return(keycrunch_MD5(result, seed, passwd)); + } + /* NOTREACHED */ +} + +static int +keycrunch_MD4(result, seed, passwd) + char *result; /* 8-byte result */ + char *seed; /* Seed, any length */ + char *passwd; /* Password, any length */ { char *buf; - MDstruct md; + MD4_CTX md; + u_int32_t results[4]; unsigned int buflen; - int i; - register long tmp; - + buflen = strlen(seed) + strlen(passwd); if ((buf = (char *)malloc(buflen+1)) == NULL) return -1; - strcpy(buf,seed); - strcat(buf,passwd); + (void)strcpy(buf, seed); + (void)strcat(buf, passwd); /* Crunch the key through MD4 */ sevenbit(buf); - MDbegin(&md); - MDupdate(&md,(unsigned char *)buf,8*buflen); + MD4Init(&md); + MD4Update(&md, (unsigned char *)buf, buflen); + MD4Final((unsigned char *)results ,&md); + (void)free(buf); + + /* Fold result from 128 to 64 bits */ + results[0] ^= results[2]; + results[1] ^= results[3]; + + (void)memcpy((void *)result, (void *)results, 8); + + return 0; +} + +static int +keycrunch_MD5(result, seed, passwd) + char *result; /* 8-byte result */ + char *seed; /* Seed, any length */ + char *passwd; /* Password, any length */ +{ + char *buf; + MD5_CTX md; + u_int32_t results[4]; + unsigned int buflen; + + buflen = strlen(seed) + strlen(passwd); + if ((buf = (char *)malloc(buflen+1)) == NULL) + return -1; + (void)strcpy(buf, seed); + (void)strcat(buf, passwd); - free(buf); + /* Crunch the key through MD5 */ + sevenbit(buf); + MD5Init(&md); + MD5Update(&md, (unsigned char *)buf, buflen); + MD5Final((unsigned char *)results ,&md); + (void)free(buf); /* Fold result from 128 to 64 bits */ - md.buffer[0] ^= md.buffer[2]; - md.buffer[1] ^= md.buffer[3]; - - /* Default (but slow) code that will convert to - * little-endian byte ordering on any machine - */ - for (i=0; i<2; i++) { - tmp = md.buffer[i]; - *result++ = tmp; - tmp >>= 8; - *result++ = tmp; - tmp >>= 8; - *result++ = tmp; - tmp >>= 8; - *result++ = tmp; - } + results[0] ^= results[2]; + results[1] ^= results[3]; + + (void)memcpy((void *)result, (void *)results, 8); return 0; } @@ -85,36 +130,51 @@ void f(x) char *x; { - MDstruct md; - register long tmp; + switch (skey_get_MDX()) { + /* + * Need a default case to appease gc even though + * skey_set_MDX() guantaees we get back 4 or 5 + */ + case 4 : return(f_MD4(x)); + default : return(f_MD5(x)); + } + /* NOTREACHED */ +} + +void +f_MD4(x) + char *x; +{ + MD4_CTX md; + u_int32_t results[4]; + + MD4Init(&md); + MD4Update(&md, (unsigned char *)x, 8); + MD4Final((unsigned char *)results, &md); + + /* Fold 128 to 64 bits */ + results[0] ^= results[2]; + results[1] ^= results[3]; + + (void)memcpy((void *)x, (void *)results, 8); +} + +void +f_MD5(x) + char *x; +{ + MD5_CTX md; + u_int32_t results[4]; - MDbegin(&md); - MDupdate(&md,(unsigned char *)x,64); + MD5Init(&md); + MD5Update(&md, (unsigned char *)x, 8); + MD5Final((unsigned char *)results, &md); /* Fold 128 to 64 bits */ - md.buffer[0] ^= md.buffer[2]; - md.buffer[1] ^= md.buffer[3]; - - /* Default (but slow) code that will convert to - * little-endian byte ordering on any machine - */ - tmp = md.buffer[0]; - *x++ = tmp; - tmp >>= 8; - *x++ = tmp; - tmp >>= 8; - *x++ = tmp; - tmp >>= 8; - *x++ = tmp; - - tmp = md.buffer[1]; - *x++ = tmp; - tmp >>= 8; - *x++ = tmp; - tmp >>= 8; - *x++ = tmp; - tmp >>= 8; - *x = tmp; + results[0] ^= results[2]; + results[1] ^= results[3]; + + (void)memcpy((void *)x, (void *)results, 8); } /* Strip trailing cr/lf from a line of text */ @@ -122,31 +182,46 @@ void rip(buf) char *buf; { - char *cp; - - if ((cp = strchr(buf,'\r')) != NULL) - *cp = '\0'; + buf += strcspn(buf, "\r\n"); - if ((cp = strchr(buf,'\n')) != NULL) - *cp = '\0'; + if (*buf) + *buf = '\0'; } char * -readpass (buf,n) +readpass(buf, n) char *buf; int n; { - set_term(); - echo_off(); + struct termios term; + void (*old_handler) __P(()); - fgets(buf, n, stdin); + /* Catch SIGINT and save old signal handler */ + old_handler = signal(SIGINT, trapped); + /* Turn off echoing */ + (void) tcgetattr(fileno(stdin), &term); + if ((skey_echo = (term.c_lflag & ECHO))) { + term.c_lflag &= ~ECHO; + (void)tcsetattr(fileno(stdin), TCSAFLUSH|TCSASOFT, &term); + } + + (void)fgets(buf, n, stdin); rip(buf); - printf("\n"); + + (void)putc('\n', stderr); + (void)fflush(stderr); + + /* Restore echo and signal handler */ + if (skey_echo) { + term.c_lflag |= ECHO; + (void)tcsetattr(fileno(stdin), TCSAFLUSH|TCSASOFT, &term); + } + if (old_handler != SIG_ERR) + (void)signal(SIGINT, old_handler); sevenbit(buf); - unset_term(); return buf; } @@ -155,10 +230,11 @@ readskey(buf, n) char *buf; int n; { - fgets (buf, n, stdin); - + (void)fgets(buf, n, stdin); rip(buf); - printf ("\n"); + + (void)putc('\n', stderr); + (void)fflush(stderr); sevenbit (buf); @@ -166,43 +242,26 @@ readskey(buf, n) } static void -set_term() -{ - fflush(stdout); - tcgetattr(fileno(stdin), &newtty); - tcgetattr(fileno(stdin), &oldtty); - - signal (SIGINT, trapped); -} - -static void -echo_off() +trapped(sig) + int sig; { - newtty.c_lflag &= ~(ICANON | ECHO | ECHONL); - newtty.c_cc[VMIN] = 1; - newtty.c_cc[VTIME] = 0; - newtty.c_cc[VINTR] = 3; + (void)fputs("^C\n", stderr); + (void)fflush(stderr); - tcsetattr(fileno(stdin), TCSADRAIN, &newtty); -} + /* Turn on echo if we turned it off */ + if (skey_echo) { + struct termios term; -static void -unset_term() -{ - tcsetattr(fileno(stdin), TCSADRAIN, &oldtty); -} + (void) tcgetattr(fileno(stdin), &term); + term.c_lflag |= ECHO; + (void)tcsetattr(fileno(stdin), TCSAFLUSH|TCSASOFT, &term); + } -static void -trapped(sig) - int sig; -{ - signal(SIGINT, trapped); - printf("^C\n"); - unset_term(); exit(-1); } -/* Convert 8-byte hex-ascii string to binary array +/* + * Convert 8-byte hex-ascii string to binary array * Returns 0 on success, -1 on error */ int @@ -241,14 +300,13 @@ btoa8(out, in) if (in == NULL || out == NULL) return -1; - for (i=0;i<8;i++) { - sprintf(out,"%02x",*in++ & 0xff); + for (i=0; i < 8; i++) { + (void)sprintf(out, "%02x", *in++ & 0xff); out += 2; } return 0; } - /* Convert hex digit to binary integer */ int htoi(c) @@ -263,6 +321,7 @@ htoi(c) return -1; } +/* Skip leading spaces from the string */ char * skipspace(cp) register char *cp; @@ -276,10 +335,10 @@ skipspace(cp) return cp; } -/* removebackspaced over charaters from the string */ +/* Remove backspaced over charaters from the string */ void backspace(buf) -char *buf; + char *buf; { char bs = 0x8; char *cp = buf; @@ -290,10 +349,9 @@ char *buf; if (out == buf) { cp++; continue; - } - else { - cp++; - out--; + } else { + cp++; + out--; } } else { *out++ = *cp++; @@ -303,11 +361,7 @@ char *buf; *out = '\0'; } -/* sevenbit () - * - * Make sure line is all seven bits. - */ - +/* Make sure line is all seven bits */ void sevenbit(s) char *s; @@ -315,3 +369,28 @@ sevenbit(s) while (*s) *s++ &= 0x7f; } + +/* Set MDX type (returns previous) */ +int +skey_set_MDX(new) + int new; +{ + int old; + + if (new != 4 && new != 5) + return -1; + + old = skey_get_MDX(); + skey_MDX = new; + return old; +} + +/* Get current MDX type */ +int +skey_get_MDX() +{ + if (skey_MDX == 0) + skey_MDX = SKEY_MDX_DEFAULT; + + return skey_MDX; +} -- cgit v1.2.3