1) Added s/key support .
2 Added optional excessive login logging. 3) Added login acces control on a per host/tty base. 4) See skey(1) for skey descriptions and src/usr.bin/login/README for the logging and access control features. -Guido
This commit is contained in:
parent
9eb28b5fde
commit
110af3d672
44
etc/login.access
Normal file
44
etc/login.access
Normal file
@ -0,0 +1,44 @@
|
||||
# Login access control table.
|
||||
#
|
||||
# When someone logs in, the table is scanned for the first entry that
|
||||
# matches the (user, host) combination, or, in case of non-networked
|
||||
# logins, the first entry that matches the (user, tty) combination. The
|
||||
# permissions field of that table entry determines whether the login will
|
||||
# be accepted or refused.
|
||||
#
|
||||
# Format of the login access control table is three fields separated by a
|
||||
# ":" character:
|
||||
#
|
||||
# permission : users : origins
|
||||
#
|
||||
# The first field should be a "+" (access granted) or "-" (access denied)
|
||||
# character. The second field should be a list of one or more login names,
|
||||
# group names, or ALL (always matches). The third field should be a list
|
||||
# of one or more tty names (for non-networked logins), host names, domain
|
||||
# names (begin with "."), host addresses, internet network numbers (end
|
||||
# with "."), ALL (always matches) or LOCAL (matches any string that does
|
||||
# not contain a "." character). If you run NIS you can use @netgroupname
|
||||
# in host or user patterns.
|
||||
#
|
||||
# The EXCEPT operator makes it possible to write very compact rules.
|
||||
#
|
||||
# The group file is searched only when a name does not match that of the
|
||||
# logged-in user. Only groups are matched in which users are explicitly
|
||||
# listed: the program does not look at a user's primary group id value.
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
# Disallow console logins to all but a few accounts.
|
||||
#
|
||||
#-:ALL EXCEPT wheel shutdown sync:console
|
||||
#
|
||||
# Disallow non-local logins to privileged accounts (group wheel).
|
||||
#
|
||||
#-:wheel:ALL EXCEPT LOCAL .win.tue.nl
|
||||
#
|
||||
# Some accounts are not allowed to login from anywhere:
|
||||
#
|
||||
#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL
|
||||
#
|
||||
# All other accounts are allowed to login from anywhere.
|
||||
#
|
8
etc/skey.access
Normal file
8
etc/skey.access
Normal file
@ -0,0 +1,8 @@
|
||||
# First word says if UNIX passwords are to be permitted or denied.
|
||||
# remainder of the rule is a networknumber and mask. A rule matches a
|
||||
# host if any of its addresses satisfies:
|
||||
#
|
||||
# network = (address & mask)
|
||||
#
|
||||
#what network mask
|
||||
permit 0.0.0.0 0.0.0.0
|
7
lib/libskey/Makefile
Normal file
7
lib/libskey/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 5.4 (Berkeley) 5/7/91
|
||||
|
||||
LIB= skey
|
||||
SRCS= authfile.c md4.c put.c skey_crypt.c skeylogin.c skeysubr.c
|
||||
CFLAGS+=-DMPU8086
|
||||
.include <bsd.lib.mk>
|
||||
|
170
lib/libskey/authfile.c
Normal file
170
lib/libskey/authfile.c
Normal file
@ -0,0 +1,170 @@
|
||||
/* Portions taken from the skey distribution on Oct 21 1993 */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if (MAXHOSTNAMELEN < 64) /* AIX weirdness */
|
||||
#undef MAXHOSTNAMELEN
|
||||
#endif
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 255
|
||||
#endif
|
||||
|
||||
#include "skey.h"
|
||||
|
||||
static int isaddr();
|
||||
static int rdnets();
|
||||
|
||||
#define MAXADDR 16 /* how many addresses can a machine
|
||||
* have? */
|
||||
|
||||
/*
|
||||
* Turn host into an IP address and then look it up in the authorization
|
||||
* database to determine if ordinary password logins are OK
|
||||
*/
|
||||
int authfile(host)
|
||||
char *host;
|
||||
{
|
||||
char *addr[MAXADDR];
|
||||
char **ap;
|
||||
long n;
|
||||
struct hostent *hp;
|
||||
char **lp;
|
||||
struct hostent *xp;
|
||||
int addr_length;
|
||||
|
||||
if (strlen(host) == 0) {
|
||||
/* Local login, okay */
|
||||
return 1;
|
||||
}
|
||||
if (isaddr(host)) {
|
||||
return rdnets(inet_addr(host));
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Stash away a copy of the host address list because it will be
|
||||
* clobbered by other gethostbyXXX() calls.
|
||||
*/
|
||||
|
||||
hp = gethostbyname(host);
|
||||
if (hp == NULL) {
|
||||
syslog(LOG_ERR, "unknown host: %s", host);
|
||||
return 0;
|
||||
}
|
||||
if (hp->h_addrtype != AF_INET) {
|
||||
syslog(LOG_ERR, "unknown network family: %d", hp->h_addrtype);
|
||||
return 0;
|
||||
}
|
||||
for (lp = hp->h_addr_list, ap = addr; ap < addr + MAXADDR; lp++, ap++) {
|
||||
if (*lp == NULL) {
|
||||
*ap = 0;
|
||||
break;
|
||||
} else {
|
||||
if ((*ap = malloc(hp->h_length)) == 0) {
|
||||
syslog(LOG_ERR, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
memcpy(*ap, *lp, hp->h_length);
|
||||
}
|
||||
}
|
||||
addr_length = hp->h_length;
|
||||
|
||||
/*
|
||||
* See if any of the addresses matches a pattern in the control file.
|
||||
* Report and skip the address if it does not belong to the remote
|
||||
* host. Assume localhost == localhost.domain.
|
||||
*/
|
||||
|
||||
#define NEQ(x,y) (strcasecmp((x),(y)) != 0)
|
||||
|
||||
while (ap-- > addr) {
|
||||
memcpy((char *) &n, *ap, addr_length);
|
||||
if (rdnets(n)) {
|
||||
if ((hp = gethostbyaddr(*ap, addr_length, AF_INET)) == 0
|
||||
|| (NEQ(host, hp->h_name) && NEQ(host, "localhost"))) {
|
||||
syslog(LOG_ERR, "IP address %s not registered for host %s",
|
||||
inet_ntoa(*(struct in_addr *) * ap), host);
|
||||
continue;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int rdnets(host)
|
||||
unsigned long host;
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[128],
|
||||
*cp;
|
||||
long pattern,
|
||||
mask;
|
||||
char *strtok();
|
||||
int permit_it = 0;
|
||||
|
||||
fp = fopen("/etc/skey.access", "r");
|
||||
if (fp == NULL)
|
||||
return 1; /* XXX */
|
||||
while (fgets(buf, sizeof(buf), fp), !feof(fp)) {
|
||||
if (buf[0] == '#')
|
||||
continue; /* Comment */
|
||||
cp = strtok(buf, " \t");
|
||||
if (cp == NULL)
|
||||
continue;
|
||||
/* two choices permit or deny */
|
||||
if (strncasecmp(cp, "permit", 4) == 0) {
|
||||
permit_it = 1;
|
||||
} else {
|
||||
if (strncasecmp(cp, "deny", 4) == 0) {
|
||||
permit_it = 0;
|
||||
} else {
|
||||
continue; /* ignore this it is not
|
||||
* permit/deny */
|
||||
}
|
||||
}
|
||||
cp = strtok(NULL, " \t");
|
||||
if (cp == NULL)
|
||||
continue; /* Invalid line */
|
||||
pattern = inet_addr(cp);
|
||||
cp = strtok(NULL, " \t");
|
||||
if (cp == NULL)
|
||||
continue; /* Invalid line */
|
||||
mask = inet_addr(cp);
|
||||
if ((host & mask) == pattern) {
|
||||
fclose(fp);
|
||||
return permit_it;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if string appears to be an IP address in dotted decimal;
|
||||
* return FALSE otherwise (i.e., if string is a domain name)
|
||||
*/
|
||||
static int isaddr(s)
|
||||
register char *s;
|
||||
{
|
||||
char c;
|
||||
|
||||
if (s == NULL)
|
||||
return 1; /* Can't happen */
|
||||
|
||||
while ((c = *s++) != '\0') {
|
||||
if (c != '[' && c != ']' && !isdigit(c) && c != '.')
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
316
lib/libskey/md4.c
Normal file
316
lib/libskey/md4.c
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* md4.c -- Implementation of MD4 Message Digest Algorithm
|
||||
* Updated: 2/16/90 by Ronald L. Rivest
|
||||
* (C) 1990 RSA Data Security, Inc.
|
||||
*
|
||||
* Portability nits fixed and reformatted - 2/12/91 Phil Karn
|
||||
*/
|
||||
|
||||
/*
|
||||
* To use MD4:
|
||||
* -- Include md4.h in your program
|
||||
* -- Declare an MDstruct MD to hold the state of the digest computation.
|
||||
* -- Initialize MD using MDbegin(&MD)
|
||||
* -- For each full block (64 bytes) X you wish to process, call
|
||||
* MDupdate(&MD,X,512)
|
||||
* (512 is the number of bits in a full block.)
|
||||
* -- For the last block (less than 64 bytes) you wish to process,
|
||||
* MDupdate(&MD,X,n)
|
||||
* where n is the number of bits in the partial block. A partial
|
||||
* block terminates the computation, so every MD computation should
|
||||
* terminate by processing a partial block, even if it has n = 0.
|
||||
* -- The message digest is available in MD.buffer[0] ... MD.buffer[3].
|
||||
* (Least-significant byte of each word should be output first.)
|
||||
* -- You can print out the digest using MDprint(&MD)
|
||||
*/
|
||||
|
||||
/* Implementation notes:
|
||||
* This implementation assumes that longs are 32-bit quantities.
|
||||
* If the machine stores the least-significant byte of an long in the
|
||||
* least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be
|
||||
* set to TRUE. Otherwise (eg., SUNS), LOWBYTEFIRST should be set to
|
||||
* FALSE. Note that on machines with LOWBYTEFIRST FALSE the routine
|
||||
* MDupdate modifies has a side-effect on its input array (the order of bytes
|
||||
* in each word are reversed). If this is undesired a call to MDreverse(X) can
|
||||
* reverse the bytes of X back into order after each call to MDupdate.
|
||||
*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#if (defined(__MSDOS__) || defined(MPU8086) || defined(MPU8080) \
|
||||
|| defined(vax) || defined (MIPSEL))
|
||||
#define LOWBYTEFIRST TRUE /* Low order bytes are first in memory */
|
||||
#else /* Almost all other machines are big-endian */
|
||||
#define LOWBYTEFIRST FALSE
|
||||
#endif
|
||||
|
||||
|
||||
/* Compile-time includes */
|
||||
#include <stdio.h>
|
||||
#include "md4.h"
|
||||
|
||||
/* Compile-time declarations of MD4 ``magic constants'' */
|
||||
#define I0 0x67452301 /* Initial values for MD buffer */
|
||||
#define I1 0xefcdab89
|
||||
#define I2 0x98badcfe
|
||||
#define I3 0x10325476
|
||||
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
|
||||
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
|
||||
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
|
||||
* (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
|
||||
* Table 2, page 660.
|
||||
*/
|
||||
#define fs1 3 /* round 1 shift amounts */
|
||||
#define fs2 7
|
||||
#define fs3 11
|
||||
#define fs4 19
|
||||
#define gs1 3 /* round 2 shift amounts */
|
||||
#define gs2 5
|
||||
#define gs3 9
|
||||
#define gs4 13
|
||||
#define hs1 3 /* round 3 shift amounts */
|
||||
#define hs2 9
|
||||
#define hs3 11
|
||||
#define hs4 15
|
||||
|
||||
|
||||
/* Compile-time macro declarations for MD4.
|
||||
* Note: The ``rot'' operator uses the variable ``tmp''.
|
||||
* It assumes tmp is declared as unsigned long, so that the >>
|
||||
* operator will shift in zeros rather than extending the sign bit.
|
||||
*/
|
||||
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
|
||||
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
|
||||
#define h(X,Y,Z) (X^Y^Z)
|
||||
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
|
||||
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
|
||||
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
|
||||
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
|
||||
|
||||
void MDreverse __ARGS((unsigned long *X));
|
||||
|
||||
/* MDprint(MDp)
|
||||
* Print message digest buffer MDp as 32 hexadecimal digits.
|
||||
* Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
|
||||
* Each byte is printed with high-order hexadecimal digit first.
|
||||
* This is a user-callable routine.
|
||||
*/
|
||||
void
|
||||
MDprint(MDp)
|
||||
MDptr MDp;
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for(i=0;i<4;i++)
|
||||
for(j=0;j<32;j=j+8)
|
||||
printf("%02lx",(MDp->buffer[i]>>j) & 0xFF);
|
||||
}
|
||||
|
||||
/* MDbegin(MDp)
|
||||
* Initialize message digest buffer MDp.
|
||||
* This is a user-callable routine.
|
||||
*/
|
||||
void
|
||||
MDbegin(MDp)
|
||||
MDptr MDp;
|
||||
{
|
||||
int i;
|
||||
|
||||
MDp->buffer[0] = I0;
|
||||
MDp->buffer[1] = I1;
|
||||
MDp->buffer[2] = I2;
|
||||
MDp->buffer[3] = I3;
|
||||
for(i=0;i<8;i++)
|
||||
MDp->count[i] = 0;
|
||||
MDp->done = 0;
|
||||
}
|
||||
|
||||
/* MDreverse(X)
|
||||
* Reverse the byte-ordering of every long in X.
|
||||
* Assumes X is an array of 16 longs.
|
||||
* The macro revx reverses the byte-ordering of the next word of X.
|
||||
*/
|
||||
#define revx { t = (*X << 16) | (*X >> 16); \
|
||||
*X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
|
||||
void
|
||||
MDreverse(X)
|
||||
unsigned long *X;
|
||||
{
|
||||
register unsigned long t;
|
||||
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
revx;
|
||||
}
|
||||
|
||||
/* MDblock(MDp,X)
|
||||
* Update message digest buffer MDp->buffer using 16-word data block X.
|
||||
* Assumes all 16 words of X are full of data.
|
||||
* Does not update MDp->count.
|
||||
* This routine is not user-callable.
|
||||
*/
|
||||
static void
|
||||
MDblock(MDp,X)
|
||||
MDptr MDp;
|
||||
unsigned long *X;
|
||||
{
|
||||
register unsigned long tmp, A, B, C, D;
|
||||
|
||||
#if LOWBYTEFIRST == FALSE
|
||||
MDreverse(X);
|
||||
#endif
|
||||
A = MDp->buffer[0];
|
||||
B = MDp->buffer[1];
|
||||
C = MDp->buffer[2];
|
||||
D = MDp->buffer[3];
|
||||
/* Update the message digest buffer */
|
||||
ff(A,B,C,D,0,fs1); /* Round 1 */
|
||||
ff(D,A,B,C,1,fs2);
|
||||
ff(C,D,A,B,2,fs3);
|
||||
ff(B,C,D,A,3,fs4);
|
||||
ff(A,B,C,D,4,fs1);
|
||||
ff(D,A,B,C,5,fs2);
|
||||
ff(C,D,A,B,6,fs3);
|
||||
ff(B,C,D,A,7,fs4);
|
||||
ff(A,B,C,D,8,fs1);
|
||||
ff(D,A,B,C,9,fs2);
|
||||
ff(C,D,A,B,10,fs3);
|
||||
ff(B,C,D,A,11,fs4);
|
||||
ff(A,B,C,D,12,fs1);
|
||||
ff(D,A,B,C,13,fs2);
|
||||
ff(C,D,A,B,14,fs3);
|
||||
ff(B,C,D,A,15,fs4);
|
||||
gg(A,B,C,D,0,gs1); /* Round 2 */
|
||||
gg(D,A,B,C,4,gs2);
|
||||
gg(C,D,A,B,8,gs3);
|
||||
gg(B,C,D,A,12,gs4);
|
||||
gg(A,B,C,D,1,gs1);
|
||||
gg(D,A,B,C,5,gs2);
|
||||
gg(C,D,A,B,9,gs3);
|
||||
gg(B,C,D,A,13,gs4);
|
||||
gg(A,B,C,D,2,gs1);
|
||||
gg(D,A,B,C,6,gs2);
|
||||
gg(C,D,A,B,10,gs3);
|
||||
gg(B,C,D,A,14,gs4);
|
||||
gg(A,B,C,D,3,gs1);
|
||||
gg(D,A,B,C,7,gs2);
|
||||
gg(C,D,A,B,11,gs3);
|
||||
gg(B,C,D,A,15,gs4);
|
||||
hh(A,B,C,D,0,hs1); /* Round 3 */
|
||||
hh(D,A,B,C,8,hs2);
|
||||
hh(C,D,A,B,4,hs3);
|
||||
hh(B,C,D,A,12,hs4);
|
||||
hh(A,B,C,D,2,hs1);
|
||||
hh(D,A,B,C,10,hs2);
|
||||
hh(C,D,A,B,6,hs3);
|
||||
hh(B,C,D,A,14,hs4);
|
||||
hh(A,B,C,D,1,hs1);
|
||||
hh(D,A,B,C,9,hs2);
|
||||
hh(C,D,A,B,5,hs3);
|
||||
hh(B,C,D,A,13,hs4);
|
||||
hh(A,B,C,D,3,hs1);
|
||||
hh(D,A,B,C,11,hs2);
|
||||
hh(C,D,A,B,7,hs3);
|
||||
hh(B,C,D,A,15,hs4);
|
||||
MDp->buffer[0] += A;
|
||||
MDp->buffer[1] += B;
|
||||
MDp->buffer[2] += C;
|
||||
MDp->buffer[3] += D;
|
||||
}
|
||||
|
||||
/* MDupdate(MDp,X,count)
|
||||
* Input: MDp -- an MDptr
|
||||
* X -- a pointer to an array of unsigned characters.
|
||||
* count -- the number of bits of X to use.
|
||||
* (if not a multiple of 8, uses high bits of last byte.)
|
||||
* Update MDp using the number of bits of X given by count.
|
||||
* This is the basic input routine for an MD4 user.
|
||||
* The routine completes the MD computation when count < 512, so
|
||||
* every MD computation should end with one call to MDupdate with a
|
||||
* count less than 512. A call with count 0 will be ignored if the
|
||||
* MD has already been terminated (done != 0), so an extra call with count
|
||||
* 0 can be given as a ``courtesy close'' to force termination if desired.
|
||||
*/
|
||||
void
|
||||
MDupdate(MDp,X,count)
|
||||
MDptr MDp;
|
||||
unsigned char *X;
|
||||
unsigned int count;
|
||||
{
|
||||
int i,bit,byte,mask;
|
||||
unsigned long tmp;
|
||||
unsigned char XX[64];
|
||||
unsigned char *p;
|
||||
|
||||
/* return with no error if this is a courtesy close with count
|
||||
* zero and MDp->done is true.
|
||||
*/
|
||||
if(count == 0 && MDp->done)
|
||||
return;
|
||||
/* check to see if MD is already done and report error */
|
||||
if(MDp->done){
|
||||
printf("\nError: MDupdate MD already done.");
|
||||
return;
|
||||
}
|
||||
/* Add count to MDp->count */
|
||||
tmp = count;
|
||||
p = MDp->count;
|
||||
while(tmp){
|
||||
tmp += *p;
|
||||
*p++ = tmp;
|
||||
tmp = tmp >> 8;
|
||||
}
|
||||
/* Process data */
|
||||
if(count == 512){
|
||||
/* Full block of data to handle */
|
||||
MDblock(MDp,(unsigned long *)X);
|
||||
} else if(count > 512){
|
||||
/* Check for count too large */
|
||||
printf("\nError: MDupdate called with illegal count value %ld.",count);
|
||||
return;
|
||||
} else {
|
||||
/* partial block -- must be last block so finish up
|
||||
* Find out how many bytes and residual bits there are
|
||||
*/
|
||||
byte = count >> 3;
|
||||
bit = count & 7;
|
||||
/* Copy X into XX since we need to modify it */
|
||||
for(i=0;i<=byte;i++)
|
||||
XX[i] = X[i];
|
||||
for(i=byte+1;i<64;i++)
|
||||
XX[i] = 0;
|
||||
/* Add padding '1' bit and low-order zeros in last byte */
|
||||
mask = 1 << (7 - bit);
|
||||
XX[byte] = (XX[byte] | mask) & ~( mask - 1);
|
||||
/* If room for bit count, finish up with this block */
|
||||
if(byte <= 55){
|
||||
for(i=0;i<8;i++)
|
||||
XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned long *)XX);
|
||||
} else {
|
||||
/* need to do two blocks to finish up */
|
||||
MDblock(MDp,(unsigned long *)XX);
|
||||
for(i=0;i<56;i++)
|
||||
XX[i] = 0;
|
||||
for(i=0;i<8;i++)
|
||||
XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned long *)XX);
|
||||
}
|
||||
/* Set flag saying we're done with MD computation */
|
||||
MDp->done = 1;
|
||||
}
|
||||
}
|
||||
/* End of md4.c */
|
50
lib/libskey/md4.h
Normal file
50
lib/libskey/md4.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifdef __STDC__
|
||||
#define __ARGS(X) X /* For ANSI C */
|
||||
#else
|
||||
#define __ARGS(X) ()
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* md4.h -- Header file for implementation of MD4 Message Digest Algorithm
|
||||
* Updated: 2/13/90 by Ronald L. Rivest
|
||||
* (C) 1990 RSA Data Security, Inc.
|
||||
* Reformatted and de-linted - 2/12/91 Phil Karn
|
||||
*/
|
||||
|
||||
/* MDstruct is the data structure for a message digest computation. */
|
||||
typedef struct {
|
||||
unsigned long buffer[4];/* Holds 4-word result of MD computation */
|
||||
unsigned char count[8]; /* Number of bits processed so far */
|
||||
unsigned int done; /* Nonzero means MD computation finished */
|
||||
} MDstruct, *MDptr;
|
||||
|
||||
/* MDbegin(MD)
|
||||
* Input: MD -- an MDptr
|
||||
* Initialize the MDstruct prepatory to doing a message digest computation.
|
||||
*/
|
||||
extern void MDbegin __ARGS((MDptr MDp));
|
||||
|
||||
/* MDupdate(MD,X,count)
|
||||
* Input: MD -- an MDptr
|
||||
* X -- a pointer to an array of unsigned characters.
|
||||
* count -- the number of bits of X to use (an unsigned int).
|
||||
* Updates MD using the first ``count'' bits of X.
|
||||
* The array pointed to by X is not modified.
|
||||
* If count is not a multiple of 8, MDupdate uses high bits of last byte.
|
||||
* This is the basic input routine for a user.
|
||||
* The routine terminates the MD computation when count < 512, so
|
||||
* every MD computation should end with one call to MDupdate with a
|
||||
* count less than 512. Zero is OK for a count.
|
||||
*/
|
||||
extern void MDupdate __ARGS((MDptr MDp,unsigned char *X,unsigned int count));
|
||||
|
||||
/* MDprint(MD)
|
||||
* Input: MD -- an MDptr
|
||||
* Prints message digest buffer MD as 32 hexadecimal digits.
|
||||
* Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
|
||||
* Each byte is printed with high-order hexadecimal digit first.
|
||||
*/
|
||||
extern void MDprint __ARGS((MDptr MDp));
|
||||
|
||||
/* End of md4.h */
|
2289
lib/libskey/put.c
Normal file
2289
lib/libskey/put.c
Normal file
File diff suppressed because it is too large
Load Diff
38
lib/libskey/skey_crypt.c
Normal file
38
lib/libskey/skey_crypt.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* Author: Wietse Venema, Eindhoven University of Technology. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "skey.h"
|
||||
|
||||
/* skey_crypt - return encrypted UNIX passwd if s/key or regular password ok */
|
||||
|
||||
char *skey_crypt(pp, salt, pwd, pwok)
|
||||
char *pp;
|
||||
char *salt;
|
||||
struct passwd *pwd;
|
||||
int pwok;
|
||||
{
|
||||
struct skey skey;
|
||||
char *p;
|
||||
char *crypt();
|
||||
|
||||
/* Try s/key authentication even when the UNIX password is permitted. */
|
||||
|
||||
if (pwd != 0 && skeylookup(&skey, pwd->pw_name) == 0
|
||||
&& skeyverify(&skey, pp) == 0) {
|
||||
/* s/key authentication succeeded */
|
||||
return (pwd->pw_passwd);
|
||||
}
|
||||
|
||||
/* When s/key authentication does not work, always invoke crypt(). */
|
||||
|
||||
p = crypt(pp, salt);
|
||||
if (pwok && pwd != 0 && strcmp(p, pwd->pw_passwd) == 0)
|
||||
return (pwd->pw_passwd);
|
||||
|
||||
/* The user does not exist or entered bad input. */
|
||||
|
||||
return (":");
|
||||
}
|
328
lib/libskey/skeylogin.c
Normal file
328
lib/libskey/skeylogin.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* Login code for S/KEY Authentication. S/KEY is a trademark
|
||||
* of Bellcore.
|
||||
*
|
||||
* Mink is the former name of the S/KEY authentication system.
|
||||
* Many references for mink may still be found in this program. */
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef QUOTA
|
||||
#include <sys/quota.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include "skey.h"
|
||||
|
||||
#define KEYFILE "/etc/skeykeys"
|
||||
|
||||
char *skipspace();
|
||||
int skeylookup __ARGS((struct skey *mp,char *name));
|
||||
|
||||
#define setpriority(x,y,z) /* nothing */
|
||||
|
||||
/* Issue a skey challenge 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.
|
||||
*
|
||||
* The file read/write pointer is left at the start of the
|
||||
* record.
|
||||
*/
|
||||
int
|
||||
getskeyprompt(mp,name,prompt)
|
||||
struct skey *mp;
|
||||
char *name;
|
||||
char *prompt;
|
||||
{
|
||||
int rval;
|
||||
|
||||
sevenbit(name);
|
||||
rval = skeylookup(mp,name);
|
||||
strcpy(prompt,"s/key 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);
|
||||
return 0;
|
||||
case 1: /* User not found */
|
||||
fclose(mp->keyfile);
|
||||
return -1;
|
||||
}
|
||||
return -1; /* Can't happen */
|
||||
}
|
||||
/* Return a 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.
|
||||
*
|
||||
* The file read/write pointer is left at the start of the
|
||||
* record.
|
||||
*/
|
||||
int
|
||||
skeychallenge(mp,name, ss)
|
||||
struct skey *mp;
|
||||
char *name;
|
||||
char *ss;
|
||||
{
|
||||
int rval;
|
||||
|
||||
rval = skeylookup(mp,name);
|
||||
switch(rval){
|
||||
case -1: /* File error */
|
||||
return -1;
|
||||
case 0: /* Lookup succeeded, issue challenge */
|
||||
sprintf(ss, "s/key %d %s",mp->n - 1,mp->seed);
|
||||
return 0;
|
||||
case 1: /* User not found */
|
||||
fclose(mp->keyfile);
|
||||
return -1;
|
||||
}
|
||||
return -1; /* Can't happen */
|
||||
}
|
||||
|
||||
/* Find an entry in the One-time Password database.
|
||||
* Return codes:
|
||||
* -1: error in opening database
|
||||
* 0: entry found, file R/W pointer positioned at beginning of record
|
||||
* 1: entry not found, file R/W pointer positioned at EOF
|
||||
*/
|
||||
int
|
||||
skeylookup(mp,name)
|
||||
struct skey *mp;
|
||||
char *name;
|
||||
{
|
||||
int found;
|
||||
int len;
|
||||
long recstart;
|
||||
char *cp;
|
||||
struct stat statbuf;
|
||||
|
||||
/* See if the KEYFILE exists, and create it if not */
|
||||
if(stat(KEYFILE,&statbuf) == -1 && errno == ENOENT){
|
||||
mp->keyfile = fopen(KEYFILE,"w+");
|
||||
(void) chmod(KEYFILE, 0644);
|
||||
} else {
|
||||
/* Otherwise open normally for update */
|
||||
mp->keyfile = fopen(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 */
|
||||
found = 0;
|
||||
while(!feof(mp->keyfile)){
|
||||
recstart = ftell(mp->keyfile);
|
||||
mp->recstart = recstart;
|
||||
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)
|
||||
continue;
|
||||
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(strlen(mp->logname) == len
|
||||
&& strncmp(mp->logname,name,len) == 0){
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
fseek(mp->keyfile,recstart,0);
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
/* Verify response to a s/key challenge.
|
||||
*
|
||||
* Return codes:
|
||||
* -1: Error of some sort; database unchanged
|
||||
* 0: Verify successful, database updated
|
||||
* 1: Verify failed, database unchanged
|
||||
*
|
||||
* The database file is always closed by this call.
|
||||
*/
|
||||
int
|
||||
skeyverify(mp,response)
|
||||
struct skey *mp;
|
||||
char *response;
|
||||
{
|
||||
struct timeval startval;
|
||||
struct timeval endval;
|
||||
long microsec;
|
||||
char key[8];
|
||||
char fkey[8];
|
||||
char filekey[8];
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
char tbuf[27],buf[60];
|
||||
char me[80];
|
||||
int rval;
|
||||
char *cp;
|
||||
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm);
|
||||
|
||||
if(response == NULL){
|
||||
fclose(mp->keyfile);
|
||||
return -1;
|
||||
}
|
||||
rip(response);
|
||||
|
||||
/* Convert response to binary */
|
||||
if(etob(key,response) != 1 && atob8(key,response) != 0){
|
||||
/* Neither english words or ascii hex */
|
||||
fclose(mp->keyfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute fkey = f(key) */
|
||||
memcpy(fkey,key,sizeof(key));
|
||||
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
|
||||
*/
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, -4);
|
||||
/*
|
||||
gettimeofday(&startval, (char *)0 );
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
return -1;
|
||||
}
|
||||
rip(mp->buf);
|
||||
mp->logname = strtok(mp->buf," \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 */
|
||||
if(memcmp(filekey,fkey,8) != 0){
|
||||
/* Wrong response */
|
||||
setpriority(PRIO_PROCESS, 0, 0);
|
||||
fclose(mp->keyfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
*/
|
||||
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);
|
||||
/*
|
||||
gettimeofday(&endval, (char *)0 );
|
||||
microsec = (endval.tv_sec - startval.tv_sec) * 1000000 + (endval.tv_usec - startval.tv_usec);
|
||||
fprintf(stderr, "window= %d micro seconds \n" , microsec);
|
||||
*/
|
||||
|
||||
|
||||
fclose(mp->keyfile);
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert 8-byte hex-ascii string to binary array
|
||||
* Returns 0 on success, -1 on error
|
||||
*/
|
||||
atob8(out,in)
|
||||
register char *out,*in;
|
||||
{
|
||||
register int i;
|
||||
register int val;
|
||||
|
||||
if(in == NULL || out == NULL)
|
||||
return -1;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
if((in = skipspace(in)) == NULL)
|
||||
return -1;
|
||||
if((val = htoi(*in++)) == -1)
|
||||
return -1;
|
||||
*out = val << 4;
|
||||
|
||||
if((in = skipspace(in)) == NULL)
|
||||
return -1;
|
||||
if((val = htoi(*in++)) == -1)
|
||||
return -1;
|
||||
*out++ |= val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
skipspace(cp)
|
||||
register char *cp;
|
||||
{
|
||||
while(*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
|
||||
if(*cp == '\0')
|
||||
return NULL;
|
||||
else
|
||||
return cp;
|
||||
}
|
||||
|
||||
/* Convert 8-byte binary array to hex-ascii string */
|
||||
int
|
||||
btoa8(out,in)
|
||||
register char *out,*in;
|
||||
{
|
||||
register int i;
|
||||
|
||||
if(in == NULL || out == NULL)
|
||||
return -1;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
sprintf(out,"%02x",*in++ & 0xff);
|
||||
out += 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Convert hex digit to binary integer */
|
||||
int
|
||||
htoi(c)
|
||||
register char c;
|
||||
{
|
||||
if('0' <= c && c <= '9')
|
||||
return c - '0';
|
||||
if('a' <= c && c <= 'f')
|
||||
return 10 + c - 'a';
|
||||
if('A' <= c && c <= 'F')
|
||||
return 10 + c - 'A';
|
||||
return -1;
|
||||
}
|
225
lib/libskey/skeysubr.c
Normal file
225
lib/libskey/skeysubr.c
Normal file
@ -0,0 +1,225 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __MSDOS__
|
||||
#include <dos.h>
|
||||
#endif
|
||||
#ifdef unix /* Assume POSIX */
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#include "md4.h"
|
||||
#include "skey.h"
|
||||
|
||||
#if (defined(__MSDOS__) || defined(MPU8086) || defined(MPU8080) \
|
||||
|| defined(vax) || defined (MIPSEL))
|
||||
#define LITTLE_ENDIAN /* Low order bytes are first in memory */
|
||||
#endif /* Almost all other machines are big-endian */
|
||||
|
||||
/* Crunch a key:
|
||||
* concatenate the seed and the password, run through MD4 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 */
|
||||
{
|
||||
char *buf;
|
||||
MDstruct md;
|
||||
unsigned int buflen;
|
||||
#ifndef LITTLE_ENDIAN
|
||||
int i;
|
||||
register long tmp;
|
||||
#endif
|
||||
|
||||
buflen = strlen(seed) + strlen(passwd);
|
||||
if((buf = malloc(buflen+1)) == NULL)
|
||||
return -1;
|
||||
strcpy(buf,seed);
|
||||
strcat(buf,passwd);
|
||||
|
||||
/* Crunch the key through MD4 */
|
||||
sevenbit(buf);
|
||||
MDbegin(&md);
|
||||
MDupdate(&md,(unsigned char *)buf,8*buflen);
|
||||
|
||||
free(buf);
|
||||
|
||||
/* Fold result from 128 to 64 bits */
|
||||
md.buffer[0] ^= md.buffer[2];
|
||||
md.buffer[1] ^= md.buffer[3];
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
/* Only works on byte-addressed little-endian machines!! */
|
||||
memcpy(result,(char *)md.buffer,8);
|
||||
#else
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */
|
||||
void
|
||||
f(x)
|
||||
char *x;
|
||||
{
|
||||
MDstruct md;
|
||||
#ifndef LITTLE_ENDIAN
|
||||
register long tmp;
|
||||
#endif
|
||||
|
||||
MDbegin(&md);
|
||||
MDupdate(&md,(unsigned char *)x,64);
|
||||
|
||||
/* Fold 128 to 64 bits */
|
||||
md.buffer[0] ^= md.buffer[2];
|
||||
md.buffer[1] ^= md.buffer[3];
|
||||
|
||||
#ifdef LITTLE_ENDIAN
|
||||
/* Only works on byte-addressed little-endian machines!! */
|
||||
memcpy(x,(char *)md.buffer,8);
|
||||
|
||||
#else
|
||||
/* 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Strip trailing cr/lf from a line of text */
|
||||
void
|
||||
rip(buf)
|
||||
char *buf;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if((cp = strchr(buf,'\r')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
if((cp = strchr(buf,'\n')) != NULL)
|
||||
*cp = '\0';
|
||||
}
|
||||
/************************/
|
||||
#ifdef __MSDOS__
|
||||
char *
|
||||
readpass(buf,n)
|
||||
char *buf;
|
||||
int n;
|
||||
{
|
||||
int i;
|
||||
char *cp;
|
||||
|
||||
for(cp=buf,i = 0; i < n ; i++)
|
||||
if ((*cp++ = bdos(7,0,0)) == '\r')
|
||||
break;
|
||||
*cp = '\0';
|
||||
printf("\n");
|
||||
rip(buf);
|
||||
return buf;
|
||||
}
|
||||
#else
|
||||
char *
|
||||
readpass(buf,n)
|
||||
char *buf;
|
||||
int n;
|
||||
{
|
||||
struct termios saved_ttymode;
|
||||
struct termios noecho_ttymode;
|
||||
|
||||
/* Save normal line editing modes */
|
||||
tcgetattr(0, &saved_ttymode);
|
||||
|
||||
/* Turn off echoing */
|
||||
tcgetattr(0, &noecho_ttymode);
|
||||
noecho_ttymode.c_lflag &= ~ECHO;
|
||||
tcsetattr(0, TCSANOW, &noecho_ttymode);
|
||||
fgets(buf,n,stdin);
|
||||
rip(buf);
|
||||
|
||||
/* Restore previous tty modes */
|
||||
tcsetattr(0, TCSANOW, &saved_ttymode);
|
||||
|
||||
/*
|
||||
after the secret key is taken from the keyboard, the line feed is
|
||||
written to standard error instead of standard output. That means that
|
||||
anyone using the program from a terminal won't notice, but capturing
|
||||
standard output will get the key words without a newline in front of
|
||||
them.
|
||||
*/
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
sevenbit(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* removebackspaced over charaters from the string*/
|
||||
backspace(buf)
|
||||
char *buf;
|
||||
{
|
||||
char bs = 0x8;
|
||||
char *cp = buf;
|
||||
char *out = buf;
|
||||
|
||||
while(*cp){
|
||||
if( *cp == bs ) {
|
||||
if(out == buf){
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
cp++;
|
||||
out--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*out++ = *cp++;
|
||||
}
|
||||
|
||||
}
|
||||
*out = '\0';
|
||||
|
||||
}
|
||||
sevenbit(s)
|
||||
char *s;
|
||||
{
|
||||
/* make sure there are only 7 bit code in the line*/
|
||||
while(*s){
|
||||
*s = 0x7f & ( *s);
|
||||
s++;
|
||||
}
|
||||
}
|
21
usr.bin/key/Makefile
Normal file
21
usr.bin/key/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
# @(#)Makefile 5.6 (Berkeley) 3/5/91
|
||||
#
|
||||
|
||||
PROG= key
|
||||
MAN1= key.1 skey.1
|
||||
CFLAGS+=-I${.CURDIR}/../../lib
|
||||
|
||||
|
||||
DPADD= /usr/bin/libskey.a
|
||||
LDADD= -lskey
|
||||
|
||||
.if exists(/usr/lib/libcrypt.a)
|
||||
DPADD+= ${LIBCRYPT}
|
||||
LDADD+= -lcrypt
|
||||
.endif
|
||||
|
||||
SRCS= skey.c
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
100
usr.bin/key/README.WZV
Normal file
100
usr.bin/key/README.WZV
Normal file
@ -0,0 +1,100 @@
|
||||
One of the nice things of S/Key is that it still leaves you the option
|
||||
to use regular UNIX passwords. In fact, the presence of S/Key support
|
||||
is completely invisible for a user until she has set up a password with
|
||||
the keyinit command. You can permit regular UNIX passwords for local
|
||||
logins, while at the same time insisting on S/Key passwords for logins
|
||||
from outside.
|
||||
|
||||
ORIGIN
|
||||
|
||||
These files are modified versions of the s/key files found on
|
||||
thumper.bellcore.com at 21 oct 1993. They have been fixed to
|
||||
run on top of SunOS 4.1.3 and Solaris 2.3.
|
||||
|
||||
Installation is described at the end of this file.
|
||||
|
||||
USAGE
|
||||
|
||||
Use the keyinit command to set up a new series of s/key passwords.
|
||||
|
||||
wzv_6% keyinit
|
||||
Updating wietse:
|
||||
Old key: wz173500
|
||||
Reminder - Only use this method if you are direct connected.
|
||||
If you are using telnet or dial-in exit with no password and use keyinit -s.
|
||||
Enter secret password:
|
||||
Again secret password:
|
||||
|
||||
ID wietse s/key is 99 wz173501
|
||||
BLAH BLA BLAH BLAH BLAH BLA
|
||||
|
||||
Be sure to make your secret password sufficiently long. Try using a
|
||||
full sentence instead of just one single word.
|
||||
|
||||
You will have to do a "keyinit" on every system that you want to login
|
||||
on using one-time passwords.
|
||||
|
||||
Whenever you log into an s/key protected system you will see
|
||||
something like:
|
||||
|
||||
login: wietse
|
||||
s/key 98 wz173501
|
||||
Password:
|
||||
|
||||
In this case you can either enter your regular UNIX password or
|
||||
your one-time s/key password. For example, I open a local window
|
||||
to compute the password:
|
||||
|
||||
local% key 98 wz173501
|
||||
Reminder - Do not use key while logged in via telnet or rlogin.
|
||||
Enter secret password:
|
||||
BLAH BLA BLAH BLAH BLAH BLA
|
||||
|
||||
The "BLAH BLA BLAH BLAH BLAH BLA" is the one-time s/key password.
|
||||
|
||||
If you have to type the one-time password in by hand, it is convenient
|
||||
to have echo turned on so that you can correct typing errors. Just type
|
||||
a newline at the "Password:" prompt:
|
||||
|
||||
login: wietse
|
||||
s/key 98 wz173501
|
||||
Password: (turning echo on)
|
||||
Password:BLAH BLA BLAH BLAH BLAH BLA
|
||||
|
||||
The 98 in the challenge will be 97 the next time, and so on. You'll get
|
||||
a warning when you are about to run out of s/key passwords, so that you
|
||||
will have to run the keyinit command again.
|
||||
|
||||
Sometimes it is more practical to carry a piece of paper with a small
|
||||
series of one-time passwords. You can generate the list with:
|
||||
|
||||
% key -n 10 98 wz173501
|
||||
98: BLAH BLA BLAH BLAH BLAH BLA
|
||||
97: ...
|
||||
96: ...
|
||||
|
||||
Be careful when printing material like this!
|
||||
|
||||
INSTALLATION
|
||||
|
||||
To install, do: make sunos4 (or whatever), then: make install.
|
||||
|
||||
The UNIX password is always permitted with non-network logins. By
|
||||
default, UNIX passwords are always permitted (the Bellcore code by
|
||||
default disallows UNIX passwords but I think that is too painful). In
|
||||
order to permit UNIX passwords only with logins from specific networks,
|
||||
create a file /etc/skey.access. For example,
|
||||
|
||||
# First word says if UNIX passwords are to be permitted or denied.
|
||||
# remainder of the rule is a networknumber and mask. A rule matches a
|
||||
# host if any of its addresses satisfies:
|
||||
#
|
||||
# network = (address & mask)
|
||||
#
|
||||
#what network mask
|
||||
permit 131.155.210.0 255.255.255.0
|
||||
deny 0.0.0.0 0.0.0.0
|
||||
|
||||
This particular example will permit UNIX passwords with logins from any
|
||||
host on network 131.155.210, but will insist on one-time passwords in
|
||||
all other cases.
|
49
usr.bin/key/key.1
Normal file
49
usr.bin/key/key.1
Normal file
@ -0,0 +1,49 @@
|
||||
.ll 6i
|
||||
.pl 10.5i
|
||||
.\" @(#)key.1 1.0 (Bellcore) 12/2/91
|
||||
.\"
|
||||
.lt 6.0i
|
||||
.TH KEY 1 "2 December 1991"
|
||||
.AT 3
|
||||
.SH NAME
|
||||
key \- Stand\-alone program for computing responses to S/Key challenges.
|
||||
.SH SYNOPSIS
|
||||
.B key [\-n <count>] <Sequence> <key>
|
||||
.SH DESCRIPTION
|
||||
.I key
|
||||
Takes the optional count of the number of one time access
|
||||
passwords to print
|
||||
along with a (maximum) sequence number and key as command line args,
|
||||
it prompts for the user's secret password, and produces both word
|
||||
and hex format responses.
|
||||
.SH EXAMPLE
|
||||
.sh
|
||||
Usage example:
|
||||
.sp 0
|
||||
>key \-n 5 99 th91334
|
||||
.sp 0
|
||||
Enter password: <your secret password is entered here>
|
||||
.sp 0
|
||||
OMEN US HORN OMIT BACK AHOY
|
||||
.sp 0
|
||||
.... 4 more passwords.
|
||||
.sp 0
|
||||
>
|
||||
.LP
|
||||
.SH OPTIONS
|
||||
.LP
|
||||
.B \-n <count>
|
||||
the number of one time access passwords to print.
|
||||
The default is one.
|
||||
.SH DIAGNOSTICS
|
||||
.SH BUGS
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
.BR skey(1),
|
||||
.BR keyinit(1),
|
||||
.BR keysu(1),
|
||||
.BR keyinfo(1)
|
||||
.SH AUTHOR
|
||||
Command by Phil Karn, Neil M. Haller, John S. Walden
|
||||
.SH CONTACT
|
||||
staff@thumper.bellcore.com
|
59
usr.bin/key/skey.1
Normal file
59
usr.bin/key/skey.1
Normal file
@ -0,0 +1,59 @@
|
||||
.ll 6i
|
||||
.pl 10.5i
|
||||
.\" @(#)skey.1 1.1 10/28/93
|
||||
.\"
|
||||
.lt 6.0i
|
||||
.TH KEY 1 "28 October 1993"
|
||||
.AT 3
|
||||
.SH NAME
|
||||
S/key \- A proceedure to use one time passwords for accessing computer systems.
|
||||
.SH DESCRIPTION
|
||||
.I S/key
|
||||
is a proceedure for using one time password to authenticate access to
|
||||
compter systems. It uses 64 bits of information transformed by the
|
||||
MD4 algorithm. The user supplies the 64 bits in the form of 6 English
|
||||
words that are generated by a secure computer.
|
||||
Example use of the S/key program
|
||||
.I key
|
||||
.sp
|
||||
Usage example:
|
||||
.sp 0
|
||||
>key 99 th91334
|
||||
.sp 0
|
||||
Enter password: <your secret password is intered here>
|
||||
.sp 0
|
||||
OMEN US HORN OMIT BACK AHOY
|
||||
.sp 0
|
||||
>
|
||||
.sp
|
||||
The programs that are part of the S/Key system are keyinit, key, and
|
||||
keyinfo. Keyinit is used to get your ID set up, key is
|
||||
used to get the one time password each time,
|
||||
keyinfo is used to extract information from the S/Key database.
|
||||
.sp
|
||||
When you run "keyinit" you inform the system of your
|
||||
secret password. Running "key" then generates the
|
||||
one-time passwords, and also requires your secret
|
||||
password. If however, you misspell your password
|
||||
while running "key", you will get a list of passwords
|
||||
that will not work, and no indication about the problem.
|
||||
.sp
|
||||
Password sequence numbers count backward from 99. If you
|
||||
don't know this, the syntax for "key" will be confusing.
|
||||
.sp
|
||||
You can enter the passwords using small letters, even
|
||||
though the "key" program gives them in caps.
|
||||
.sp
|
||||
Macintosh and a general purpose PC use
|
||||
are available.
|
||||
.sp
|
||||
Under FreeBSD, you can control, with /etc/skey.access, from which
|
||||
hosts and/or networks the use of S/Key passwords is obligated.
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
.BR keyinit(1),
|
||||
.BR key(1),
|
||||
.BR keyinfo(1)
|
||||
.BR skey.access(5)
|
||||
.SH AUTHOR
|
||||
Phil Karn, Neil M. Haller, John S. Walden, Scott Chasin
|
128
usr.bin/key/skey.c
Normal file
128
usr.bin/key/skey.c
Normal file
@ -0,0 +1,128 @@
|
||||
/* Stand-alone program for computing responses to S/Key challenges.
|
||||
* Takes the iteration count and seed as command line args, prompts
|
||||
* for the user's key, and produces both word and hex format responses.
|
||||
*
|
||||
* Usage example:
|
||||
* >skey 88 ka9q2
|
||||
* Enter password:
|
||||
* OMEN US HORN OMIT BACK AHOY
|
||||
* C848 666B 6435 0A93
|
||||
* >
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __MSDOS__
|
||||
#include <dos.h>
|
||||
#else /* Assume BSD unix */
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "libskey/md4.h"
|
||||
#include "libskey/skey.h"
|
||||
|
||||
char *readpass();
|
||||
void usage();
|
||||
int getopt();
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
int
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int n,cnt,i;
|
||||
char passwd[256],passwd2[256];
|
||||
char key[8];
|
||||
char *seed;
|
||||
char buf[33];
|
||||
char *slash;
|
||||
|
||||
cnt = 1;
|
||||
while((i = getopt(argc,argv,"n:")) != EOF){
|
||||
switch(i){
|
||||
case 'n':
|
||||
cnt = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* could be in the form <number>/<seed> */
|
||||
if(argc <= optind + 1){
|
||||
/*look for / in it */
|
||||
if(argc <= optind){
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
slash = strchr(argv[optind], '/');
|
||||
if(slash == NULL){
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
*slash++ = '\0';
|
||||
seed = slash;
|
||||
|
||||
if((n = atoi(argv[optind])) < 0){
|
||||
fprintf(stderr,"%s not positive\n",argv[optind]);
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if((n = atoi(argv[optind])) < 0){
|
||||
fprintf(stderr,"%s not positive\n",argv[optind]);
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
seed = argv[++optind];
|
||||
}
|
||||
fprintf(stderr,"Reminder - Do not use this program while logged in via telnet or rlogin.\n");
|
||||
|
||||
/* Get user's secret password */
|
||||
for(;;){
|
||||
fprintf(stderr,"Enter secret password: ");
|
||||
readpass(passwd,sizeof(passwd));
|
||||
break;
|
||||
/************
|
||||
fprintf(stderr,"Again secret password: ");
|
||||
readpass(passwd2,sizeof(passwd));
|
||||
if(strcmp(passwd,passwd2) == 0) break;
|
||||
fprintf(stderr, "Sorry no match\n");
|
||||
**************/
|
||||
|
||||
}
|
||||
|
||||
/* Crunch seed and password into starting key */
|
||||
if(keycrunch(key,seed,passwd) != 0){
|
||||
fprintf(stderr,"%s: key crunch failed\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if(cnt == 1){
|
||||
while(n-- != 0)
|
||||
f(key);
|
||||
printf("%s\n",btoe(buf,key));
|
||||
#ifdef HEXIN
|
||||
printf("%s\n",put8(buf,key));
|
||||
#endif
|
||||
} else {
|
||||
for(i=0;i<=n-cnt;i++)
|
||||
f(key);
|
||||
for(;i<=n;i++){
|
||||
#ifdef HEXIN
|
||||
printf("%d: %-29s %s\n",i,btoe(buf,key),put8(buf,key));
|
||||
#else
|
||||
printf("%d: %-29s\n",i,btoe(buf,key));
|
||||
#endif
|
||||
f(key);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
usage(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr,"Usage: %s [-n count] <sequence #>[/] <key> \n",s);
|
||||
}
|
||||
|
9
usr.bin/keyinfo/Makefile
Normal file
9
usr.bin/keyinfo/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# @(#)Makefile 5.5 (Berkeley) 7/1/90
|
||||
|
||||
MAN1= keyinfo.1
|
||||
|
||||
beforeinstall:
|
||||
install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
|
||||
${.CURDIR}/keyinfo.sh ${DESTDIR}${BINDIR}/keyinfo
|
||||
|
||||
.include <bsd.prog.mk>
|
40
usr.bin/keyinfo/keyinfo.1
Normal file
40
usr.bin/keyinfo/keyinfo.1
Normal file
@ -0,0 +1,40 @@
|
||||
.ll 6i
|
||||
.pl 10.5i
|
||||
.\" @(#)keyinfo.1 1.1 (Bellcore) 7/20/93
|
||||
.\"
|
||||
.lt 6.0i
|
||||
.TH KEYINFO 1 "20 July 1993"
|
||||
.AT 3
|
||||
.SH NAME
|
||||
keyinfo \- display current S/Key sequence number and seed
|
||||
.SH SYNOPSIS
|
||||
.B keyinfo [username]
|
||||
.SH DESCRIPTION
|
||||
.I keyinfo
|
||||
takes an optional user name and displays the user\'s current sequence
|
||||
number and seed found in the S/Key database /etc/skeykeys.
|
||||
.sp 1
|
||||
The command can be useful when generating a list of passwords for use
|
||||
on a field trip, by combining with the command
|
||||
.I key
|
||||
in the form:
|
||||
.sp
|
||||
>key \-n <number of passwords to print> `keyinfo`|lpr
|
||||
.SH EXAMPLE
|
||||
.sh
|
||||
Usage example:
|
||||
.sp 0
|
||||
>keyinfo
|
||||
.sp 0
|
||||
0098 ws91340
|
||||
.LP
|
||||
.SH ARGUMENTS
|
||||
.TP
|
||||
.B username
|
||||
The S/key user to display the information for. The default is
|
||||
to display S/Key information on the user who invokes the command.
|
||||
.SH SEE ALSO
|
||||
.BR keyinit(1),
|
||||
.BR key(1)
|
||||
.SH AUTHOR
|
||||
Command by Phil Karn, Neil M. Haller, John S. Walden
|
10
usr.bin/keyinfo/keyinfo.sh
Normal file
10
usr.bin/keyinfo/keyinfo.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
# search /etc/skeykeys for the skey string for this user OR user specified
|
||||
# in 1st parameter
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
|
||||
test -f /etc/skeykeys && {
|
||||
WHO=${1-`id | sed 's/^[^(]*(\([^)]*\).*/\1/'`}
|
||||
awk '/^'${WHO}'[ ]/ { print $2-1, $3 }' /etc/skeykeys
|
||||
}
|
21
usr.bin/keyinit/Makefile
Normal file
21
usr.bin/keyinit/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
# @(#)Makefile 5.6 (Berkeley) 3/5/91
|
||||
#
|
||||
|
||||
PROG= keyinit
|
||||
MAN1= keyinit.1
|
||||
CFLAGS+=-I${.CURDIR}/../../lib
|
||||
DPADD= /usr/bin/libskey.a
|
||||
LDADD= -lskey
|
||||
|
||||
.if exists(/usr/lib/libcrypt.a)
|
||||
DPADD+= ${LIBCRYPT}
|
||||
LDADD+= -lcrypt
|
||||
.endif
|
||||
|
||||
SRCS= skeyinit.c
|
||||
|
||||
BINOWN= root
|
||||
BINMODE=4555
|
||||
|
||||
.include <bsd.prog.mk>
|
64
usr.bin/keyinit/keyinit.1
Normal file
64
usr.bin/keyinit/keyinit.1
Normal file
@ -0,0 +1,64 @@
|
||||
.ll 6i
|
||||
.pl 10.5i
|
||||
.\" @(#)keyinit.1 1.0 (Bellcore) 7/20/93
|
||||
.\"
|
||||
.lt 6.0i
|
||||
.TH KEYINIT 1 "20 July 1993"
|
||||
.AT 3
|
||||
.SH NAME
|
||||
keyinit \- Change password or add user to S/Key authentication system.
|
||||
.SH SYNOPSIS
|
||||
.B keyinit [\-s] [<user ID >]
|
||||
.SH DESCRIPTION
|
||||
.I keyinit
|
||||
initializes the system so you can use S/Key one-time passwords to
|
||||
login. The program will ask you to enter a secret pass phrase; enter a
|
||||
phrase of several words in response. After the S/Key database has been
|
||||
updated you can login using either your regular UNIX password or using
|
||||
S/Key one-time passwords.
|
||||
.PP
|
||||
When logging in from another machine you can avoid typing a real
|
||||
password over the network, by typing your S/Key pass phrase to the
|
||||
\fIkey\fR command on the local machine: the program will respond with
|
||||
the one-time password that you should use to log into the remote
|
||||
machine. This is most conveniently done with cut-and-paste operations
|
||||
using a mouse. Alternatively, you can pre-compute one-time passwords
|
||||
using the \fIkey\fR command and carry them with you on a piece of paper.
|
||||
.PP
|
||||
\fIkeyinit\fR requires you to type your secret password, so it should
|
||||
be used only on a secure terminal. For example, on the console of a
|
||||
workstation. If you are using \fIkeyinit\fR while logged in over an
|
||||
untrusted network, follow the instructions given below with the \-s
|
||||
option.
|
||||
.SH OPTIONS
|
||||
.IP \-s
|
||||
Set secure mode where the user is expected to have used a secure
|
||||
machine to generate the first one time password. Without the \-s the
|
||||
system will assume you are direct connected over secure communications
|
||||
and prompt you for your secret password.
|
||||
The \-s option also allows one to set the seed and count for complete
|
||||
control of the parameters. You can use keyinit -s in compination with
|
||||
the
|
||||
.I key
|
||||
command to set the seed and count if you do not like the defaults.
|
||||
To do this run keyinit in one window and put in your count and seed
|
||||
then run key in another window to generate the correct 6 english words
|
||||
for that count and seed. You can then
|
||||
"cut" and "paste" them or copy them into the keyinit window.
|
||||
.sp
|
||||
.LP
|
||||
.B <user ID>
|
||||
the ID for the user to be changed/added
|
||||
.SH DIAGNOSTICS
|
||||
.SH FILES
|
||||
.TP
|
||||
/etc/skeykeys data base of information for S/Key system.
|
||||
.SH BUGS
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
.BR skey(1),
|
||||
.BR key(1),
|
||||
.BR keysu(1),
|
||||
.BR keyinfo(1)
|
||||
.SH AUTHOR
|
||||
Command by Phil Karn, Neil M. Haller, John S. Walden
|
195
usr.bin/keyinit/skeyinit.c
Normal file
195
usr.bin/keyinit/skeyinit.c
Normal file
@ -0,0 +1,195 @@
|
||||
/* change password or add user to S/KEY authentication system.
|
||||
* S/KEY is a tradmark of Bellcore */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include "libskey/skey.h"
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
char * readpass();
|
||||
|
||||
int skeylookup __ARGS((struct skey *mp,char *name));
|
||||
|
||||
#define NAMELEN 2
|
||||
int
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct skey skey;
|
||||
int rval,n,nn,i,defaultsetup;
|
||||
char seed[18],tmp[80],key[8];
|
||||
struct passwd *ppuser,*pp;
|
||||
char defaultseed[17], passwd[256],passwd2[256] ;
|
||||
|
||||
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
char tbuf[27],buf[60];
|
||||
char lastc, me[80];
|
||||
int l;
|
||||
|
||||
time(&now);
|
||||
#if 0 /* Choose a more random seed */
|
||||
tm = localtime(&now);
|
||||
strftime(tbuf, sizeof(tbuf), "%M%j", tm);
|
||||
#else
|
||||
sprintf(tbuf, "%05ld", (long) (now % 100000));
|
||||
#endif
|
||||
gethostname(defaultseed,NAMELEN);
|
||||
strcpy(&defaultseed[NAMELEN],tbuf);
|
||||
|
||||
pp = ppuser = getpwuid(getuid());
|
||||
strcpy(me,pp->pw_name);
|
||||
defaultsetup = 1;
|
||||
if( argc > 1){
|
||||
if(strcmp("-s", argv[1]) == 0)
|
||||
defaultsetup = 0;
|
||||
else
|
||||
pp = getpwnam(argv[1]);
|
||||
if(argc > 2)
|
||||
pp = getpwnam(argv[2]);
|
||||
|
||||
}
|
||||
if(pp == NULL){
|
||||
printf("User unknown\n");
|
||||
return 1;
|
||||
}
|
||||
if(strcmp( pp->pw_name,me) != 0){
|
||||
if(getuid() != 0){
|
||||
/* Only root can change other's passwds */
|
||||
printf("Permission denied.\n");
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
rval = skeylookup(&skey,pp->pw_name);
|
||||
switch(rval){
|
||||
case -1:
|
||||
perror("error in opening database");
|
||||
return 1;
|
||||
case 0:
|
||||
printf("Updating %s:\n",pp->pw_name);
|
||||
printf("Old key: %s\n",skey.seed);
|
||||
/* lets be nice if they have a skey.seed that ends in 0-8 just add one*/
|
||||
l = strlen(skey.seed);
|
||||
if( l > 0){
|
||||
lastc = skey.seed[l-1];
|
||||
if( isdigit(lastc) && lastc != '9' ){
|
||||
strcpy(defaultseed, skey.seed);
|
||||
defaultseed[l-1] = lastc + 1;
|
||||
}
|
||||
if( isdigit(lastc) && lastc == '9' && l < 16){
|
||||
strcpy(defaultseed, skey.seed);
|
||||
defaultseed[l-1] = '0';
|
||||
defaultseed[l] = '0';
|
||||
defaultseed[l+1] = '\0';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
skey.val = 0; /* XXX */
|
||||
printf("Adding %s:\n",pp->pw_name);
|
||||
break;
|
||||
}
|
||||
n = 99;
|
||||
if( ! defaultsetup){
|
||||
printf("Reminder you need the 6 english words from the skey command.\n");
|
||||
for(i=0;;i++){
|
||||
if(i >= 2) exit(1);
|
||||
printf("Enter sequence count from 1 to 10000: ");
|
||||
fgets(tmp,sizeof(tmp),stdin);
|
||||
n = atoi(tmp);
|
||||
if(n > 0 && n < 10000)
|
||||
break; /* Valid range */
|
||||
printf("Count must be > 0 and < 10000\n");
|
||||
}
|
||||
}
|
||||
if( !defaultsetup){
|
||||
printf("Enter new key [default %s]: ", defaultseed);
|
||||
fflush(stdout);
|
||||
fgets(seed,sizeof(seed),stdin);
|
||||
rip(seed);
|
||||
if(strlen(seed) > 16){
|
||||
printf("Seed truncated to 16 chars\n");
|
||||
seed[16] = '\0';
|
||||
}
|
||||
if( seed[0] == '\0') strcpy(seed,defaultseed);
|
||||
for(i=0;;i++){
|
||||
if(i >= 2) exit(1);
|
||||
printf("s/key %d %s\ns/key access password: ",n,seed);
|
||||
fgets(tmp,sizeof(tmp),stdin);
|
||||
rip(tmp);
|
||||
backspace(tmp);
|
||||
if(tmp[0] == '?'){
|
||||
printf("Enter 6 English words from secure S/Key calculation.\n");
|
||||
continue;
|
||||
}
|
||||
if(tmp[0] == '\0'){
|
||||
exit(1);
|
||||
}
|
||||
if(etob(key,tmp) == 1 || atob8(key,tmp) == 0)
|
||||
break; /* Valid format */
|
||||
printf("Invalid format, try again with 6 English words.\n");
|
||||
}
|
||||
} else {
|
||||
/* Get user's secret password */
|
||||
fprintf(stderr,"Reminder - Only use this method if you are directly connected.\n");
|
||||
fprintf(stderr,"If you are using telnet or rlogin exit with no password and use keyinit -s.\n");
|
||||
for(i=0;;i++){
|
||||
if(i >= 2) exit(1);
|
||||
fprintf(stderr,"Enter secret password: ");
|
||||
readpass(passwd,sizeof(passwd));
|
||||
if(passwd[0] == '\0'){
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,"Again secret password: ");
|
||||
readpass(passwd2,sizeof(passwd));
|
||||
if(passwd2[0] == '\0'){
|
||||
exit(1);
|
||||
}
|
||||
if(strlen(passwd) < 4 && strlen(passwd2) < 4) {
|
||||
fprintf(stderr, "Sorry your password must be longer\n\r");
|
||||
exit(1);
|
||||
}
|
||||
if(strcmp(passwd,passwd2) == 0) break;
|
||||
fprintf(stderr, "Sorry no match\n");
|
||||
|
||||
|
||||
}
|
||||
strcpy(seed,defaultseed);
|
||||
|
||||
/* Crunch seed and password into starting key */
|
||||
if(keycrunch(key,seed,passwd) != 0){
|
||||
fprintf(stderr,"%s: key crunch failed\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
nn = n;
|
||||
while(nn-- != 0)
|
||||
f(key);
|
||||
}
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
strftime(tbuf, sizeof(tbuf), " %b %d,%Y %T", tm);
|
||||
if (skey.val == NULL)
|
||||
skey.val = (char *) malloc(16+1);
|
||||
|
||||
|
||||
btoa8(skey.val,key);
|
||||
fprintf(skey.keyfile,"%s %04d %-16s %s %-21s\n",pp->pw_name,n,
|
||||
seed,skey.val, tbuf);
|
||||
fclose(skey.keyfile);
|
||||
printf("\nID %s s/key is %d %s\n",pp->pw_name,n,seed);
|
||||
printf("%s\n",btoe(buf,key));
|
||||
#ifdef HEXIN
|
||||
printf("%s\n",put8(buf,key));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user