diff options
author | nsayer <nsayer@FreeBSD.org> | 1999-08-16 11:24:29 +0000 |
---|---|---|
committer | nsayer <nsayer@FreeBSD.org> | 1999-08-16 11:24:29 +0000 |
commit | 189690bcceec94a2b595d9e6d6beca23cd68b5cd (patch) | |
tree | 131b7d42306f643dcbd0094169238875d98500cf /contrib/telnet/libtelnet | |
parent | 07419aec715eccc813e53ff53f4dd3dfe4c1298a (diff) | |
download | FreeBSD-src-189690bcceec94a2b595d9e6d6beca23cd68b5cd.zip FreeBSD-src-189690bcceec94a2b595d9e6d6beca23cd68b5cd.tar.gz |
Add SRA authentication to src/crypto/telnet.
SRA does a Diffie-Hellmen exchange and then DES-encrypts the
authentication data. If the authentication is successful, it also
sets up a session key for DES encryption.
SRA was originally developed at Texas A&M University.
This code is probably export restricted (despite the fact that I
originally found it at a University in Germany).
SRA is not perfect. It is vulnerable to monkey-in-the-middle attacks
and does not use tremendously large DH constants (and thus an individual
exchange probably could be factored in a few days on modern CPU
horsepower). It does not, however, require any changes in user or
administrative behavior and foils session hijacking and sniffing.
The goal of this commit is that telnet and telnetd end up in the DES
distribution and that therefore an encrypted session telnet becomes
standard issue for FreeBSD.
Diffstat (limited to 'contrib/telnet/libtelnet')
-rw-r--r-- | contrib/telnet/libtelnet/Makefile | 19 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/auth-proto.h | 8 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/auth.c | 10 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/enc-proto.h | 2 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/encrypt.c | 15 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/encrypt.h | 5 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/pk.c | 266 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/pk.h | 41 | ||||
-rw-r--r-- | contrib/telnet/libtelnet/sra.c | 478 |
9 files changed, 840 insertions, 4 deletions
diff --git a/contrib/telnet/libtelnet/Makefile b/contrib/telnet/libtelnet/Makefile new file mode 100644 index 0000000..3ef7f94 --- /dev/null +++ b/contrib/telnet/libtelnet/Makefile @@ -0,0 +1,19 @@ +# From: @(#)Makefile 8.2 (Berkeley) 12/15/93 +# $Id: Makefile,v 1.1.1.1.6.5 1996/06/30 12:50:37 markm Exp $ + +INTERNALSTATICLIB= YES + +LIB= telnet +SRCS= encrypt.c genget.c getent.c misc.c + +# SRA Authentication & DES Encryption +CFLAGS+= -I.. -DHAS_CGETENT -DENCRYPTION -DAUTHENTICATION -DSRA +CFLAGS+= -DDES_ENCRYPTION +LDADD+= -ldes -lmp +SRCS+= auth.c enc_des.c sra.c pk.c + +#don't bother to install +install: + /usr/bin/true + +.include <bsd.lib.mk> diff --git a/contrib/telnet/libtelnet/auth-proto.h b/contrib/telnet/libtelnet/auth-proto.h index a1e9aa4..c62fe5f 100644 --- a/contrib/telnet/libtelnet/auth-proto.h +++ b/contrib/telnet/libtelnet/auth-proto.h @@ -97,4 +97,12 @@ void kerberos5_reply P((Authenticator *, unsigned char *, int)); int kerberos5_status P((Authenticator *, char *, int)); void kerberos5_printsub P((unsigned char *, int, unsigned char *, int)); #endif +#ifdef SRA +int sra_init P((Authenticator *, int)); +int sra_send P((Authenticator *)); +void sra_is P((Authenticator *, unsigned char *, int)); +void sra_reply P((Authenticator *, unsigned char *, int)); +int sra_status P((Authenticator *, char *, int)); +void sra_printsub P((unsigned char *, int, unsigned char *, int)); +#endif #endif diff --git a/contrib/telnet/libtelnet/auth.c b/contrib/telnet/libtelnet/auth.c index 4262b55..d574b1e 100644 --- a/contrib/telnet/libtelnet/auth.c +++ b/contrib/telnet/libtelnet/auth.c @@ -185,6 +185,16 @@ Authenticator authenticators[] = { rsaencpwd_status, rsaencpwd_printsub }, #endif +#ifdef SRA + { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY, + sra_init, + sra_send, + sra_is, + sra_reply, + sra_status, + sra_printsub }, + +#endif { 0, }, }; diff --git a/contrib/telnet/libtelnet/enc-proto.h b/contrib/telnet/libtelnet/enc-proto.h index 8e15ffd..8cec406 100644 --- a/contrib/telnet/libtelnet/enc-proto.h +++ b/contrib/telnet/libtelnet/enc-proto.h @@ -94,6 +94,7 @@ int encrypt_cmd P((int, char **)); void encrypt_display P((void)); #endif +#ifdef DES_ENCRYPTION void krbdes_encrypt P((unsigned char *, int)); int krbdes_decrypt P((int)); int krbdes_is P((unsigned char *, int)); @@ -122,5 +123,6 @@ int ofb64_reply P((unsigned char *, int)); void ofb64_session P((Session_Key *, int)); int ofb64_keyid P((int, unsigned char *, int *)); void ofb64_printsub P((unsigned char *, int, unsigned char *, int)); +#endif /* DES_ENCRYPTION */ #endif /* ENCRYPTION */ diff --git a/contrib/telnet/libtelnet/encrypt.c b/contrib/telnet/libtelnet/encrypt.c index 41dd5cc..e1ac1c4 100644 --- a/contrib/telnet/libtelnet/encrypt.c +++ b/contrib/telnet/libtelnet/encrypt.c @@ -104,10 +104,17 @@ static char *Name = "Noname"; #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) -static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) - | typemask(ENCTYPE_DES_OFB64); -static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) - | typemask(ENCTYPE_DES_OFB64); +static long i_support_encrypt = 0 +#ifdef DES_ENCRYPTION + | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) +#endif + |0; +static long i_support_decrypt = 0 +#ifdef DES_ENCRYPTION + | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) +#endif + |0; + static long i_wont_support_encrypt = 0; static long i_wont_support_decrypt = 0; #define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) diff --git a/contrib/telnet/libtelnet/encrypt.h b/contrib/telnet/libtelnet/encrypt.h index 1c942dc..14be826 100644 --- a/contrib/telnet/libtelnet/encrypt.h +++ b/contrib/telnet/libtelnet/encrypt.h @@ -60,9 +60,14 @@ #define DIR_DECRYPT 1 #define DIR_ENCRYPT 2 +#include <des.h> typedef unsigned char Block[8]; typedef unsigned char *BlockT; +#if 0 typedef struct { Block __; } Schedule[16]; +#else +#define Schedule des_key_schedule +#endif #define VALIDKEY(key) ( key[0] | key[1] | key[2] | key[3] | \ key[4] | key[5] | key[6] | key[7]) diff --git a/contrib/telnet/libtelnet/pk.c b/contrib/telnet/libtelnet/pk.c new file mode 100644 index 0000000..78e474f --- /dev/null +++ b/contrib/telnet/libtelnet/pk.c @@ -0,0 +1,266 @@ +/* public key routines */ +/* functions: + genkeys(char *public, char *secret) + common_key(char *secret, char *public, desData *deskey) + pk_encode(char *in, *out, DesData *deskey); + pk_decode(char *in, *out, DesData *deskey); + where + char public[HEXKEYBYTES + 1]; + char secret[HEXKEYBYTES + 1]; + */ + +#include <stdio.h> +#include <sys/time.h> +#include <string.h> +#include <fcntl.h> +#include <des.h> +#include "mp.h" +#include "pk.h" +#if defined(SOLARIS2) || defined(LINUX) +#include <stdlib.h> +#endif + +/* + * Choose top 128 bits of the common key to use as our idea key. + */ +static +extractideakey(ck, ideakey) + MINT *ck; + IdeaData *ideakey; +{ + MINT *a; + MINT *z; + short r; + int i; + short base = (1 << 8); + char *k; + + z = itom(0); + a = itom(0); + madd(ck, z, a); + for (i = 0; i < ((KEYSIZE - 128) / 8); i++) { + sdiv(a, base, a, &r); + } + k = (char *)ideakey; + for (i = 0; i < 16; i++) { + sdiv(a, base, a, &r); + *k++ = r; + } + mfree(z); + mfree(a); +} + +/* + * Choose middle 64 bits of the common key to use as our des key, possibly + * overwriting the lower order bits by setting parity. + */ +static +extractdeskey(ck, deskey) + MINT *ck; + DesData *deskey; +{ + MINT *a; + MINT *z; + short r; + int i; + short base = (1 << 8); + char *k; + + z = itom(0); + a = itom(0); + madd(ck, z, a); + for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { + sdiv(a, base, a, &r); + } + k = (char *)deskey; + for (i = 0; i < 8; i++) { + sdiv(a, base, a, &r); + *k++ = r; + } + mfree(z); + mfree(a); +} + +/* + * get common key from my secret key and his public key + */ +void common_key(char *xsecret, char *xpublic, IdeaData *ideakey, DesData *deskey) +{ + MINT *public; + MINT *secret; + MINT *common; + MINT *modulus = xtom(HEXMODULUS); + + public = xtom(xpublic); + secret = xtom(xsecret); + common = itom(0); + pow(public, secret, modulus, common); + extractdeskey(common, deskey); + extractideakey(common, ideakey); +#if DES_OSTHOLM + des_fixup_key_parity(deskey); +#else + des_set_odd_parity(deskey); +#endif + mfree(common); + mfree(secret); + mfree(public); + mfree(modulus); +} + + +/* + * Generate a seed + */ +void getseed(seed, seedsize) + char *seed; + int seedsize; +{ + int i,f; + int rseed; + struct timeval tv; + long devrand; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + rseed = tv.tv_sec + tv.tv_usec; +/* XXX What the hell is this?! */ + for (i = 0; i < 8; i++) { + rseed ^= (rseed << 8); + } + + f=open("/dev/random",O_NONBLOCK|O_RDONLY); + if (f>=0) + { + read(f,&devrand,sizeof(devrand)); + close(f); + } + srand48((long)rseed^devrand); + + for (i = 0; i < seedsize; i++) { + seed[i] = (lrand48() & 0xff); + } +} + + +/* + * Generate a random public/secret key pair + */ +void genkeys(public, secret) + char *public; + char *secret; +{ + int i; + +# define BASEBITS (8*sizeof(short) - 1) +# define BASE (1 << BASEBITS) + + MINT *pk = itom(0); + MINT *sk = itom(0); + MINT *tmp; + MINT *base = itom(BASE); + MINT *root = itom(PROOT); + MINT *modulus = xtom(HEXMODULUS); + short r; + unsigned short seed[KEYSIZE/BASEBITS + 1]; + char *xkey; + + getseed((char *)seed, sizeof(seed)); + for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { + r = seed[i] % BASE; + tmp = itom(r); + mult(sk, base, sk); + madd(sk, tmp, sk); + mfree(tmp); + } + tmp = itom(0); + mdiv(sk, modulus, tmp, sk); + mfree(tmp); + pow(root, sk, modulus, pk); + xkey = mtox(sk); + adjust(secret, xkey); + xkey = mtox(pk); + adjust(public, xkey); + mfree(sk); + mfree(base); + mfree(pk); + mfree(root); + mfree(modulus); +} + +/* + * Adjust the input key so that it is 0-filled on the left + */ +adjust(keyout, keyin) + char keyout[HEXKEYBYTES+1]; + char *keyin; +{ + char *p; + char *s; + + for (p = keyin; *p; p++) + ; + for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { + *s = *p; + } + while (s >= keyout) { + *s-- = '0'; + } +} + +static char hextab[17] = "0123456789ABCDEF"; + +/* given a DES key, cbc encrypt and translate input to terminated hex */ +void pk_encode(in, out, key) +char *in,*out; +DesData *key; +{ + char buf[256]; + DesData i; + des_key_schedule k; + int l,op,deslen; + + memset(&i,0,sizeof(i)); + memset(buf,0,sizeof(buf)); + deslen = ((strlen(in) + 7)/8)*8; + des_key_sched(key, k); + des_cbc_encrypt((des_cblock *)in,(des_cblock *)buf,deslen, + k,&i,DES_ENCRYPT); + for (l=0,op=0;l<deslen;l++) { + out[op++] = hextab[(buf[l] & 0xf0) >> 4]; + out[op++] = hextab[(buf[l] & 0x0f)]; + } + out[op] = '\0'; +} + +/* given a DES key, translate input from hex and decrypt */ +void pk_decode(in, out, key) +char *in,*out; +DesData *key; +{ + char buf[256]; + DesData i; + des_key_schedule k; + int l,n1,n2,op; + + memset(&i,0,sizeof(i)); + memset(buf,0,sizeof(buf)); + for (l=0,op=0;l<strlen(in)/2;l++,op+=2) { + if(in[op] == '0' && in[op+1] == '0') { + buf[l] = '\0'; + break; + } + if (in[op] > '9') + n1 = in[op] - 'A' + 10; + else + n1 = in[op] - '0'; + if (in[op+1] > '9') + n2 = in[op+1] - 'A' + 10; + else + n2 = in[op+1] - '0'; + buf[l] = n1*16 +n2; + } + des_key_sched(key, k); + des_cbc_encrypt((des_cblock *)buf,(des_cblock *)out,strlen(in)/2, + k,&i,DES_DECRYPT); + out[strlen(in)/2] = '\0'; +} diff --git a/contrib/telnet/libtelnet/pk.h b/contrib/telnet/libtelnet/pk.h new file mode 100644 index 0000000..b41bba5 --- /dev/null +++ b/contrib/telnet/libtelnet/pk.h @@ -0,0 +1,41 @@ +/* header for the des routines that we will use */ + +typedef unsigned char byte, DesData[ 8], IdeaData[16]; +#if 0 +typedef unsigned long word, DesKeys[32]; +#else +#define DesKeys des_key_schedule +#endif + +#define DES_DECRYPT 0 +#define DES_ENCRYPT 1 + +#if 0 +extern void des_fixup_key_parity(); /* (DesData *key) */ +extern int des_key_sched(); /* (DesData *key, DesKeys *m) */ +extern int des_ecb_encrypt(); /* (DesData *src, *dst, DesKeys *m, int mode) */ +extern int des_cbc_encrypt(); /* (char *src, *dst, int length, + DesKeys *m, DesData *init, int mode) */ +#endif + +/* public key routines */ +/* functions: + genkeys(char *public, char *secret) + common_key(char *secret, char *public, desData *deskey) + where + char public[HEXKEYBYTES + 1]; + char secret[HEXKEYBYTES + 1]; + */ + +#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" +#define HEXKEYBYTES 48 +#define KEYSIZE 192 +#define KEYBYTES 24 +#define PROOT 3 + +extern void genkeys(char *public, char *secret); +extern void common_key(char *secret, char *public, IdeaData *common, + DesData *deskey); +extern void pk_encode(char *in, char *out, DesData *deskey); +extern void pk_decode(char *in, char *out, DesData *deskey); + diff --git a/contrib/telnet/libtelnet/sra.c b/contrib/telnet/libtelnet/sra.c new file mode 100644 index 0000000..44a26f2 --- /dev/null +++ b/contrib/telnet/libtelnet/sra.c @@ -0,0 +1,478 @@ +#ifdef SRA +#include <sys/types.h> +#include <arpa/telnet.h> +#include <stdio.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#ifdef NO_STRING_H +#include <strings.h> +#else +#include <string.h> +#endif + +#include "auth.h" +#include "misc.h" +#include "encrypt.h" +#include "pk.h" + +char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1]; +char *user,*pass,*xuser,*xpass; +DesData ck; +IdeaData ik; + +extern int auth_debug_mode; +static sra_valid = 0; +static passwd_sent = 0; + +static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, + AUTHTYPE_SRA, }; + +#define SRA_KEY 0 +#define SRA_USER 1 +#define SRA_CONTINUE 2 +#define SRA_PASS 3 +#define SRA_ACCEPT 4 +#define SRA_REJECT 5 + +/* support routine to send out authentication message */ +static int Data(ap, type, d, c) +Authenticator *ap; +int type; +void *d; +int c; +{ + unsigned char *p = str_data + 4; + unsigned char *cd = (unsigned char *)d; + + if (c == -1) + c = strlen((char *)cd); + + if (auth_debug_mode) { + printf("%s:%d: [%d] (%d)", + str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", + str_data[3], + type, c); + printd(d, c); + printf("\r\n"); + } + *p++ = ap->type; + *p++ = ap->way; + *p++ = type; + while (c-- > 0) { + if ((*p++ = *cd++) == IAC) + *p++ = IAC; + } + *p++ = IAC; + *p++ = SE; + if (str_data[3] == TELQUAL_IS) + printsub('>', &str_data[2], p - (&str_data[2])); + return(net_write(str_data, p - str_data)); +} + +int sra_init(ap, server) +Authenticator *ap; +int server; +{ + if (server) + str_data[3] = TELQUAL_REPLY; + else + str_data[3] = TELQUAL_IS; + + user = (char *)malloc(256); + xuser = (char *)malloc(512); + pass = (char *)malloc(256); + xpass = (char *)malloc(512); + passwd_sent = 0; + + genkeys(pka,ska); + return(1); +} + +/* client received a go-ahead for sra */ +int sra_send(ap) +Authenticator *ap; +{ + /* send PKA */ + + if (auth_debug_mode) + printf("Sent PKA to server.\r\n" ); + printf("Trying SRA secure login:\r\n"); + if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { + if (auth_debug_mode) + printf("Not enough room for authentication data\r\n"); + return(0); + } + + return(1); +} + +/* server received an IS -- could be SRA KEY, USER, or PASS */ +void sra_is(ap, data, cnt) +Authenticator *ap; +unsigned char *data; +int cnt; +{ + int valid; + Session_Key skey; + + if (cnt-- < 1) + return; + switch (*data++) { + + case SRA_KEY: + if (cnt < HEXKEYBYTES) { + Data(ap, SRA_REJECT, (void *)0, 0); + auth_finished(ap, AUTH_USER); + if (auth_debug_mode) { + printf("SRA user rejected for bad PKB\r\n"); + } + return; + } + if (auth_debug_mode) + printf("Sent pka\r\n"); + if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { + if (auth_debug_mode) + printf("Not enough room\r\n"); + return; + } + memcpy(pkb,data,HEXKEYBYTES); + pkb[HEXKEYBYTES] = '\0'; + common_key(ska,pkb,&ik,&ck); + break; + + case SRA_USER: + /* decode KAB(u) */ + memcpy(xuser,data,cnt); + xuser[cnt] = '\0'; + pk_decode(xuser,user,&ck); + auth_encrypt_user(user); + Data(ap, SRA_CONTINUE, (void *)0, 0); + + break; + + case SRA_PASS: + /* decode KAB(P) */ + memcpy(xpass,data,cnt); + xpass[cnt] = '\0'; + pk_decode(xpass,pass,&ck); + + /* check user's password */ + valid = check_user(user,pass); + + if(valid) { + Data(ap, SRA_ACCEPT, (void *)0, 0); +#ifdef DES_ENCRYPTION + skey.data = ck; + skey.type = SK_DES; + skey.length = 8; + encrypt_session_key(&skey, 1); +#endif + + sra_valid = 1; + auth_finished(ap, AUTH_VALID); + if (auth_debug_mode) { + printf("SRA user accepted\r\n"); + } + } + else { + Data(ap, SRA_CONTINUE, (void *)0, 0); +/* + Data(ap, SRA_REJECT, (void *)0, 0); + sra_valid = 0; + auth_finished(ap, AUTH_REJECT); +*/ + if (auth_debug_mode) { + printf("SRA user failed\r\n"); + } + } + break; + + default: + if (auth_debug_mode) + printf("Unknown SRA option %d\r\n", data[-1]); + Data(ap, SRA_REJECT, 0, 0); + sra_valid = 0; + auth_finished(ap, AUTH_REJECT); + break; + } +} + +extern char *getpass(); + +/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */ +void sra_reply(ap, data, cnt) +Authenticator *ap; +unsigned char *data; +int cnt; +{ + extern char *telnet_gets(); + char uprompt[256],tuser[256]; + Session_Key skey; + int i; + + if (cnt-- < 1) + return; + switch (*data++) { + + case SRA_KEY: + /* calculate common key */ + if (cnt < HEXKEYBYTES) { + if (auth_debug_mode) { + printf("SRA user rejected for bad PKB\r\n"); + } + return; + } + memcpy(pkb,data,HEXKEYBYTES); + pkb[HEXKEYBYTES] = '\0'; + + common_key(ska,pkb,&ik,&ck); + + enc_user: + + /* encode user */ + memset(tuser,0,sizeof(tuser)); + sprintf(uprompt,"User (%s): ",UserNameRequested); + telnet_gets(uprompt,tuser,255,1); + if (tuser[0] == '\n' || tuser[0] == '\r' ) + strcpy(user,UserNameRequested); + else { + /* telnet_gets leaves the newline on */ + for(i=0;i<sizeof(tuser);i++) { + if (tuser[i] == '\n') { + tuser[i] = '\0'; + break; + } + } + strcpy(user,tuser); + } + pk_encode(user,xuser,&ck); + + /* send it off */ + if (auth_debug_mode) + printf("Sent KAB(U)\r\n"); + if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) { + if (auth_debug_mode) + printf("Not enough room\r\n"); + return; + } + break; + + case SRA_CONTINUE: + if (passwd_sent) { + passwd_sent = 0; + printf("[ SRA login failed ]\r\n"); + goto enc_user; + } + /* encode password */ + memset(pass,0,sizeof(pass)); + telnet_gets("Password: ",pass,255,0); + pk_encode(pass,xpass,&ck); + /* send it off */ + if (auth_debug_mode) + printf("Sent KAB(P)\r\n"); + if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) { + if (auth_debug_mode) + printf("Not enough room\r\n"); + return; + } + passwd_sent = 1; + break; + + case SRA_REJECT: + printf("[ SRA refuses authentication ]\r\n"); + printf("Trying plaintext login:\r\n"); + auth_finished(0,AUTH_REJECT); + return; + + case SRA_ACCEPT: + printf("[ SRA accepts you ]\r\n"); +#ifdef DES_ENCRYPTION + skey.data = ck; + skey.type = SK_DES; + skey.length = 8; + encrypt_session_key(&skey, 0); +#endif + + auth_finished(ap, AUTH_VALID); + return; + default: + if (auth_debug_mode) + printf("Unknown SRA option %d\r\n", data[-1]); + return; + } +} + +int sra_status(ap, name, level) +Authenticator *ap; +char *name; +int level; +{ + if (level < AUTH_USER) + return(level); + if (UserNameRequested && sra_valid) { + strcpy(name, UserNameRequested); + return(AUTH_VALID); + } else + return(AUTH_USER); +} + +#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} +#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} + +void sra_printsub(data, cnt, buf, buflen) +unsigned char *data, *buf; +int cnt, buflen; +{ + char lbuf[32]; + register int i; + + buf[buflen-1] = '\0'; /* make sure its NULL terminated */ + buflen -= 1; + + switch(data[3]) { + + case SRA_CONTINUE: + strncpy((char *)buf, " CONTINUE ", buflen); + goto common; + + case SRA_REJECT: /* Rejected (reason might follow) */ + strncpy((char *)buf, " REJECT ", buflen); + goto common; + + case SRA_ACCEPT: /* Accepted (name might follow) */ + strncpy((char *)buf, " ACCEPT ", buflen); + + common: + BUMP(buf, buflen); + if (cnt <= 4) + break; + ADDC(buf, buflen, '"'); + for (i = 4; i < cnt; i++) + ADDC(buf, buflen, data[i]); + ADDC(buf, buflen, '"'); + ADDC(buf, buflen, '\0'); + break; + + case SRA_KEY: /* Authentication data follows */ + strncpy((char *)buf, " KEY ", buflen); + goto common2; + + case SRA_USER: + strncpy((char *)buf, " USER ", buflen); + goto common2; + + case SRA_PASS: + strncpy((char *)buf, " PASS ", buflen); + goto common2; + + default: + sprintf(lbuf, " %d (unknown)", data[3]); + strncpy((char *)buf, lbuf, buflen); + common2: + BUMP(buf, buflen); + for (i = 4; i < cnt; i++) { + sprintf(lbuf, " %d", data[i]); + strncpy((char *)buf, lbuf, buflen); + BUMP(buf, buflen); + } + break; + } +} + +struct passwd *pw; + +/* + * Helper function for sgetpwnam(). + */ +char * +sgetsave(s) + char *s; +{ + char *new = malloc((unsigned) strlen(s) + 1); + + if (new == NULL) { + return(NULL); + } + (void) strcpy(new, s); + return (new); +} + +#include <pwd.h> +#include <syslog.h> +#ifdef USE_SHADOW +#include <shadow.h> +#endif + + +struct passwd * +sgetpwnam(name) + char *name; +{ + static struct passwd save; + register struct passwd *p; + char *sgetsave(); + + if ((p = getpwnam(name)) == NULL) + return (p); + if (save.pw_name) { + free(save.pw_name); + free(save.pw_passwd); + free(save.pw_gecos); + free(save.pw_dir); + free(save.pw_shell); + } + save = *p; + save.pw_name = sgetsave(p->pw_name); + save.pw_passwd = sgetsave(p->pw_passwd); + save.pw_gecos = sgetsave(p->pw_gecos); + save.pw_dir = sgetsave(p->pw_dir); + save.pw_shell = sgetsave(p->pw_shell); +#if 0 +syslog(LOG_WARNING,"%s\n",save.pw_name); +syslog(LOG_WARNING,"%s\n",save.pw_passwd); +syslog(LOG_WARNING,"%s\n",save.pw_gecos); +syslog(LOG_WARNING,"%s\n",save.pw_dir); +#endif +#ifdef USE_SHADOW + { + struct spwd *sp; + sp = getspnam(name); + free(save.pw_passwd); + save.pw_passwd = sgetsave(sp->sp_pwdp); + } +#endif + return (&save); +} + +char *crypt(); + +int check_user(name, pass) +char *name; +char *pass; +{ + register char *cp; + char *xpasswd, *salt; + + if (pw = sgetpwnam(name)) { + if (pw->pw_shell == NULL) { + pw = (struct passwd *) NULL; + return(0); + } + + salt = pw->pw_passwd; + xpasswd = crypt(pass, salt); + /* The strcmp does not catch null passwords! */ + if (pw == NULL || *pw->pw_passwd == '\0' || + strcmp(xpasswd, pw->pw_passwd)) { + pw = (struct passwd *) NULL; + return(0); + } + return(1); + } + return(0); +} + + +#endif + |