diff options
Diffstat (limited to 'src/cmd/secstore')
-rw-r--r-- | src/cmd/secstore/SConn.c | 213 | ||||
-rw-r--r-- | src/cmd/secstore/SConn.h | 26 | ||||
-rw-r--r-- | src/cmd/secstore/aescbc.c | 156 | ||||
-rw-r--r-- | src/cmd/secstore/dirls.c | 87 | ||||
-rw-r--r-- | src/cmd/secstore/mkfile | 27 | ||||
-rw-r--r-- | src/cmd/secstore/pak.c | 344 | ||||
-rw-r--r-- | src/cmd/secstore/password.c | 136 | ||||
-rw-r--r-- | src/cmd/secstore/portdate | 9 | ||||
-rw-r--r-- | src/cmd/secstore/secacct.c | 35 | ||||
-rw-r--r-- | src/cmd/secstore/secchk.c | 28 | ||||
-rw-r--r-- | src/cmd/secstore/secstore.c | 585 | ||||
-rw-r--r-- | src/cmd/secstore/secstore.h | 31 | ||||
-rw-r--r-- | src/cmd/secstore/secstored.c | 420 | ||||
-rw-r--r-- | src/cmd/secstore/secureidcheck.c | 446 | ||||
-rw-r--r-- | src/cmd/secstore/secuser.c | 244 | ||||
-rw-r--r-- | src/cmd/secstore/util.c | 28 |
16 files changed, 0 insertions, 2815 deletions
diff --git a/src/cmd/secstore/SConn.c b/src/cmd/secstore/SConn.c deleted file mode 100644 index 7a8654ac..00000000 --- a/src/cmd/secstore/SConn.c +++ /dev/null @@ -1,213 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" - -extern int verbose; - -typedef struct ConnState { - uchar secret[SHA1dlen]; - ulong seqno; - RC4state rc4; -} ConnState; - -typedef struct SS{ - int fd; // file descriptor for read/write of encrypted data - int alg; // if nonzero, "alg sha rc4_128" - ConnState in, out; -} SS; - -static int -SC_secret(SConn *conn, uchar *sigma, int direction) -{ - SS *ss = (SS*)(conn->chan); - int nsigma = conn->secretlen; - - if(direction != 0){ - hmac_sha1(sigma, nsigma, (uchar*)"one", 3, ss->out.secret, nil); - hmac_sha1(sigma, nsigma, (uchar*)"two", 3, ss->in.secret, nil); - }else{ - hmac_sha1(sigma, nsigma, (uchar*)"two", 3, ss->out.secret, nil); - hmac_sha1(sigma, nsigma, (uchar*)"one", 3, ss->in.secret, nil); - } - setupRC4state(&ss->in.rc4, ss->in.secret, 16); // restrict to 128 bits - setupRC4state(&ss->out.rc4, ss->out.secret, 16); - ss->alg = 1; - return 0; -} - -static void -hash(uchar secret[SHA1dlen], uchar *data, int len, int seqno, uchar d[SHA1dlen]) -{ - DigestState sha; - uchar seq[4]; - - seq[0] = seqno>>24; - seq[1] = seqno>>16; - seq[2] = seqno>>8; - seq[3] = seqno; - memset(&sha, 0, sizeof sha); - sha1(secret, SHA1dlen, nil, &sha); - sha1(data, len, nil, &sha); - sha1(seq, 4, d, &sha); -} - -static int -verify(uchar secret[SHA1dlen], uchar *data, int len, int seqno, uchar d[SHA1dlen]) -{ - DigestState sha; - uchar seq[4]; - uchar digest[SHA1dlen]; - - seq[0] = seqno>>24; - seq[1] = seqno>>16; - seq[2] = seqno>>8; - seq[3] = seqno; - memset(&sha, 0, sizeof sha); - sha1(secret, SHA1dlen, nil, &sha); - sha1(data, len, nil, &sha); - sha1(seq, 4, digest, &sha); - return memcmp(d, digest, SHA1dlen); -} - -static int -SC_read(SConn *conn, uchar *buf, int n) -{ - SS *ss = (SS*)(conn->chan); - uchar count[2], digest[SHA1dlen]; - int len, nr; - - if(read(ss->fd, count, 2) != 2 || (count[0]&0x80) == 0){ - snprint((char*)buf,n,"!SC_read invalid count"); - return -1; - } - len = (count[0]&0x7f)<<8 | count[1]; // SSL-style count; no pad - if(ss->alg){ - len -= SHA1dlen; - if(len <= 0 || readn(ss->fd, digest, SHA1dlen) != SHA1dlen){ - snprint((char*)buf,n,"!SC_read missing sha1"); - return -1; - } - if(len > n || readn(ss->fd, buf, len) != len){ - snprint((char*)buf,n,"!SC_read missing data"); - return -1; - } - rc4(&ss->in.rc4, digest, SHA1dlen); - rc4(&ss->in.rc4, buf, len); - if(verify(ss->in.secret, buf, len, ss->in.seqno, digest) != 0){ - snprint((char*)buf,n,"!SC_read integrity check failed"); - return -1; - } - }else{ - if(len <= 0 || len > n){ - snprint((char*)buf,n,"!SC_read implausible record length"); - return -1; - } - if( (nr = readn(ss->fd, buf, len)) != len){ - snprint((char*)buf,n,"!SC_read expected %d bytes, but got %d", len, nr); - return -1; - } - } - ss->in.seqno++; - return len; -} - -static int -SC_write(SConn *conn, uchar *buf, int n) -{ - SS *ss = (SS*)(conn->chan); - uchar count[2], digest[SHA1dlen], enc[Maxmsg+1]; - int len; - - if(n <= 0 || n > Maxmsg+1){ - werrstr("!SC_write invalid n %d", n); - return -1; - } - len = n; - if(ss->alg) - len += SHA1dlen; - count[0] = 0x80 | len>>8; - count[1] = len; - if(write(ss->fd, count, 2) != 2){ - werrstr("!SC_write invalid count"); - return -1; - } - if(ss->alg){ - hash(ss->out.secret, buf, n, ss->out.seqno, digest); - rc4(&ss->out.rc4, digest, SHA1dlen); - memcpy(enc, buf, n); - rc4(&ss->out.rc4, enc, n); - if(write(ss->fd, digest, SHA1dlen) != SHA1dlen || - write(ss->fd, enc, n) != n){ - werrstr("!SC_write error on send"); - return -1; - } - }else{ - if(write(ss->fd, buf, n) != n){ - werrstr("!SC_write error on send"); - return -1; - } - } - ss->out.seqno++; - return n; -} - -static void -SC_free(SConn *conn) -{ - SS *ss = (SS*)(conn->chan); - - close(ss->fd); - free(ss); - free(conn); -} - -SConn* -newSConn(int fd) -{ - SS *ss; - SConn *conn; - - if(fd < 0) - return nil; - ss = (SS*)emalloc(sizeof(*ss)); - conn = (SConn*)emalloc(sizeof(*conn)); - ss->fd = fd; - ss->alg = 0; - conn->chan = (void*)ss; - conn->secretlen = SHA1dlen; - conn->free = SC_free; - conn->secret = SC_secret; - conn->read = SC_read; - conn->write = SC_write; - return conn; -} - -void -writerr(SConn *conn, char *s) -{ - char buf[Maxmsg]; - - snprint(buf, Maxmsg, "!%s", s); - conn->write(conn, (uchar*)buf, strlen(buf)); -} - -int -readstr(SConn *conn, char *s) -{ - int n; - - n = conn->read(conn, (uchar*)s, Maxmsg); - if(n >= 0){ - s[n] = 0; - if(s[0] == '!'){ - memmove(s, s+1, n); - n = -1; - } - }else{ - strcpy(s, "read error"); - } - return n; -} - diff --git a/src/cmd/secstore/SConn.h b/src/cmd/secstore/SConn.h deleted file mode 100644 index 9a428d83..00000000 --- a/src/cmd/secstore/SConn.h +++ /dev/null @@ -1,26 +0,0 @@ -// delimited, authenticated, encrypted connection -enum{ Maxmsg=4096 }; // messages > Maxmsg bytes are truncated -typedef struct SConn SConn; - -extern SConn* newSConn(int); // arg is open file descriptor -struct SConn{ - void *chan; - int secretlen; - int (*secret)(SConn*, uchar*, int);// - int (*read)(SConn*, uchar*, int); // <0 if error; errmess in buffer - int (*write)(SConn*, uchar*, int); - void (*free)(SConn*); // also closes file descriptor -}; -// secret(s,b,dir) sets secret for digest, encrypt, using the secretlen -// bytes in b to form keys for the two directions; -// set dir=0 in client, dir=1 in server - -// error convention: write !message in-band -extern void writerr(SConn*, char*); -extern int readstr(SConn*, char*); // call with buf of size Maxmsg+1 - // returns -1 upon error, with error message in buf - -extern void *emalloc(ulong); /* dies on failure; clears memory */ -extern void *erealloc(void *, ulong); -extern char *estrdup(char *); - diff --git a/src/cmd/secstore/aescbc.c b/src/cmd/secstore/aescbc.c deleted file mode 100644 index 56aeb00b..00000000 --- a/src/cmd/secstore/aescbc.c +++ /dev/null @@ -1,156 +0,0 @@ -/* encrypt file by writing - v2hdr, - 16byte initialization vector, - AES-CBC(key, random | file), - HMAC_SHA1(md5(key), AES-CBC(random | file)) -*/ -#include <u.h> -#include <libc.h> -#include <bio.h> -#include <mp.h> -#include <libsec.h> - -extern char* getpassm(char*); - -enum{ CHK = 16, BUF = 4096 }; - -uchar v2hdr[AESbsize+1] = "AES CBC SHA1 2\n"; -Biobuf bin; -Biobuf bout; - -void -safewrite(uchar *buf, int n) -{ - int i = Bwrite(&bout, buf, n); - - if(i == n) - return; - fprint(2, "write error\n"); - exits("write error"); -} - -void -saferead(uchar *buf, int n) -{ - int i = Bread(&bin, buf, n); - - if(i == n) - return; - fprint(2, "read error\n"); - exits("read error"); -} - -int -main(int argc, char **argv) -{ - int encrypt = 0; /* 0=decrypt, 1=encrypt */ - int n, nkey, pass_stdin = 0; - char *pass; - uchar key[AESmaxkey], key2[SHA1dlen]; - uchar buf[BUF+SHA1dlen]; /* assumption: CHK <= SHA1dlen */ - AESstate aes; - DigestState *dstate; - - ARGBEGIN{ - case 'e': - encrypt = 1; - break; - case 'i': - pass_stdin = 1; - break; - }ARGEND; - if(argc!=0){ - fprint(2,"usage: %s -d < cipher.aes > clear.txt\n", argv0); - fprint(2," or: %s -e < clear.txt > cipher.aes\n", argv0); - exits("usage"); - } - Binit(&bin, 0, OREAD); - Binit(&bout, 1, OWRITE); - - if(pass_stdin){ - n = readn(3, buf, (sizeof buf)-1); - if(n < 1) - exits("usage: echo password |[3=1] auth/aescbc -i ..."); - buf[n] = 0; - while(buf[n-1] == '\n') - buf[--n] = 0; - }else{ - pass = readcons("aescbc key", nil, 1); - n = strlen(pass); - if(n >= BUF) - exits("key too long"); - strcpy((char*)buf, pass); - memset(pass, 0, n); - free(pass); - } - if(n <= 0){ - fprint(2,"no key\n"); - exits("key"); - } - dstate = sha1((uchar*)"aescbc file", 11, nil, nil); - sha1(buf, n, key2, dstate); - memcpy(key, key2, 16); - nkey = 16; - md5(key, nkey, key2, 0); /* so even if HMAC_SHA1 is broken, encryption key is protected */ - - if(encrypt){ - safewrite(v2hdr, AESbsize); - genrandom(buf,2*AESbsize); /* CBC is semantically secure if IV is unpredictable. */ - setupAESstate(&aes, key, nkey, buf); /* use first AESbsize bytes as IV */ - aesCBCencrypt(buf+AESbsize, AESbsize, &aes); /* use second AESbsize bytes as initial plaintext */ - safewrite(buf, 2*AESbsize); - dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0); - while(1){ - n = Bread(&bin, buf, BUF); - if(n < 0){ - fprint(2,"read error\n"); - exits("read error"); - } - aesCBCencrypt(buf, n, &aes); - safewrite(buf, n); - dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate); - if(n < BUF) - break; /* EOF */ - } - hmac_sha1(0, 0, key2, MD5dlen, buf, dstate); - safewrite(buf, SHA1dlen); - }else{ /* decrypt */ - saferead(buf, AESbsize); - if(memcmp(buf, v2hdr, AESbsize) == 0){ - saferead(buf, 2*AESbsize); /* read IV and random initial plaintext */ - setupAESstate(&aes, key, nkey, buf); - dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0); - aesCBCdecrypt(buf+AESbsize, AESbsize, &aes); - saferead(buf, SHA1dlen); - while((n = Bread(&bin, buf+SHA1dlen, BUF)) > 0){ - dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate); - aesCBCdecrypt(buf, n, &aes); - safewrite(buf, n); - memmove(buf, buf+n, SHA1dlen); /* these bytes are not yet decrypted */ - } - hmac_sha1(0, 0, key2, MD5dlen, buf+SHA1dlen, dstate); - if(memcmp(buf, buf+SHA1dlen, SHA1dlen) != 0){ - fprint(2,"decrypted file failed to authenticate\n"); - exits("decrypted file failed to authenticate"); - } - }else{ /* compatibility with past mistake */ - // if file was encrypted with bad aescbc use this: - // memset(key, 0, AESmaxkey); - // else assume we're decrypting secstore files - setupAESstate(&aes, key, AESbsize, buf); - saferead(buf, CHK); - aesCBCdecrypt(buf, CHK, &aes); - while((n = Bread(&bin, buf+CHK, BUF)) > 0){ - aesCBCdecrypt(buf+CHK, n, &aes); - safewrite(buf, n); - memmove(buf, buf+n, CHK); - } - if(memcmp(buf, "XXXXXXXXXXXXXXXX", CHK) != 0){ - fprint(2,"decrypted file failed to authenticate\n"); - exits("decrypted file failed to authenticate"); - } - } - } - exits(""); - return 1; /* gcc */ -} diff --git a/src/cmd/secstore/dirls.c b/src/cmd/secstore/dirls.c deleted file mode 100644 index b4479413..00000000 --- a/src/cmd/secstore/dirls.c +++ /dev/null @@ -1,87 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" - -static long -ls(char *p, Dir **dirbuf) -{ - int fd; - long n; - Dir *db; - - if((db = dirstat(p)) == nil || - !(db->qid.type & QTDIR) || - (fd = open(p, OREAD)) < 0 ) - return -1; - free(db); - n = dirreadall(fd, dirbuf); - close(fd); - return n; -} - -static uchar* -sha1file(char *pfx, char *nm) -{ - int n, fd, len; - char *tmp; - uchar buf[8192]; - static uchar digest[SHA1dlen]; - DigestState *s; - - len = strlen(pfx)+1+strlen(nm)+1; - tmp = emalloc(len); - snprint(tmp, len, "%s/%s", pfx, nm); - if((fd = open(tmp, OREAD)) < 0){ - free(tmp); - return nil; - } - free(tmp); - s = nil; - while((n = read(fd, buf, sizeof buf)) > 0) - s = sha1(buf, n, nil, s); - close(fd); - sha1(nil, 0, digest, s); - return digest; -} - -static int -compare(Dir *a, Dir *b) -{ - return strcmp(a->name, b->name); -} - -/* list the (name mtime size sum) of regular, readable files in path */ -char * -dirls(char *path) -{ - char *list, *date, dig[30], buf[128]; - int m, nmwid, lenwid; - long i, n, ndir, len; - Dir *dirbuf; - - if(path==nil || (ndir = ls(path, &dirbuf)) < 0) - return nil; - - qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void *, const void *))compare); - for(nmwid=lenwid=i=0; i<ndir; i++){ - if((m = strlen(dirbuf[i].name)) > nmwid) - nmwid = m; - snprint(buf, sizeof(buf), "%ulld", dirbuf[i].length); - if((m = strlen(buf)) > lenwid) - lenwid = m; - } - for(list=nil, len=0, i=0; i<ndir; i++){ - date = ctime(dirbuf[i].mtime); - date[28] = 0; // trim newline - n = snprint(buf, sizeof buf, "%*ulld %s", lenwid, dirbuf[i].length, date+4); - n += enc64(dig, sizeof dig, sha1file(path, dirbuf[i].name), SHA1dlen); - n += nmwid+3+strlen(dirbuf[i].name); - list = erealloc(list, len+n+1); - len += snprint(list+len, n+1, "%-*s\t%s %s\n", nmwid, dirbuf[i].name, buf, dig); - } - free(dirbuf); - return list; -} - diff --git a/src/cmd/secstore/mkfile b/src/cmd/secstore/mkfile deleted file mode 100644 index 72986edd..00000000 --- a/src/cmd/secstore/mkfile +++ /dev/null @@ -1,27 +0,0 @@ -<$PLAN9/src/mkhdr - -BIN=$PLAN9/bin -#CFLAGS=-Fw -HFILES =\ - SConn.h\ - secstore.h\ - -OFILES =\ - pak.$O\ - password.$O\ - SConn.$O\ - util.$O\ - - -TARG=aescbc secstore secstored secuser - -<$PLAN9/src/mkmany - -$O.aescbc: aescbc.$O util.$O - $LD -o $target $prereq $LDFLAGS - -$O.secstored: secstored.$O dirls.$O secureidcheck.$O $OFILES - $LD -o $target $prereq - -$O.secuser: secuser.$O $OFILES - $LD -o $target $prereq diff --git a/src/cmd/secstore/pak.c b/src/cmd/secstore/pak.c deleted file mode 100644 index fb008e0f..00000000 --- a/src/cmd/secstore/pak.c +++ /dev/null @@ -1,344 +0,0 @@ -// PAK is an encrypted key exchange protocol designed by Philip MacKenzie et al. -// It is patented and use outside Plan 9 requires you get a license. -// (All other EKE protocols are patented as well, by Lucent or others.) -#include <u.h> -#include <libc.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" -#include "secstore.h" - -extern int verbose; - -char VERSION[] = "secstore"; -static char *feedback[] = {"alpha","bravo","charlie","delta","echo","foxtrot","golf","hotel"}; - -typedef struct PAKparams{ - mpint *q, *p, *r, *g; -} PAKparams; - -static PAKparams *pak; - -// from seed EB7B6E35F7CD37B511D96C67D6688CC4DD440E1E -static void -initPAKparams(void) -{ - if(pak) - return; - pak = (PAKparams*)emalloc(sizeof(*pak)); - pak->q = strtomp("E0F0EF284E10796C5A2A511E94748BA03C795C13", nil, 16, nil); - pak->p = strtomp("C41CFBE4D4846F67A3DF7DE9921A49D3B42DC33728427AB159CEC8CBB" - "DB12B5F0C244F1A734AEB9840804EA3C25036AD1B61AFF3ABBC247CD4B384224567A86" - "3A6F020E7EE9795554BCD08ABAD7321AF27E1E92E3DB1C6E7E94FAAE590AE9C48F96D9" - "3D178E809401ABE8A534A1EC44359733475A36A70C7B425125062B1142D", - nil, 16, nil); - pak->r = strtomp("DF310F4E54A5FEC5D86D3E14863921E834113E060F90052AD332B3241" - "CEF2497EFA0303D6344F7C819691A0F9C4A773815AF8EAECFB7EC1D98F039F17A32A7E" - "887D97251A927D093F44A55577F4D70444AEBD06B9B45695EC23962B175F266895C67D" - "21C4656848614D888A4", nil, 16, nil); - pak->g = strtomp("2F1C308DC46B9A44B52DF7DACCE1208CCEF72F69C743ADD4D23271734" - "44ED6E65E074694246E07F9FD4AE26E0FDDD9F54F813C40CB9BCD4338EA6F242AB94CD" - "410E676C290368A16B1A3594877437E516C53A6EEE5493A038A017E955E218E7819734" - "E3E2A6E0BAE08B14258F8C03CC1B30E0DDADFCF7CEDF0727684D3D255F1", - nil, 16, nil); -} - -// H = (sha(ver,C,sha(passphrase)))^r mod p, -// a hash function expensive to attack by brute force. -static void -longhash(char *ver, char *C, uchar *passwd, mpint *H) -{ - uchar *Cp; - int i, n, nver, nC; - uchar buf[140], key[1]; - - nver = strlen(ver); - nC = strlen(C); - n = nver + nC + SHA1dlen; - Cp = (uchar*)emalloc(n); - memmove(Cp, ver, nver); - memmove(Cp+nver, C, nC); - memmove(Cp+nver+nC, passwd, SHA1dlen); - for(i = 0; i < 7; i++){ - key[0] = 'A'+i; - hmac_sha1(Cp, n, key, sizeof key, buf+i*SHA1dlen, nil); - } - memset(Cp, 0, n); - free(Cp); - betomp(buf, sizeof buf, H); - mpmod(H, pak->p, H); - mpexp(H, pak->r, pak->p, H); -} - -// Hi = H^-1 mod p -char * -PAK_Hi(char *C, char *passphrase, mpint *H, mpint *Hi) -{ - uchar passhash[SHA1dlen]; - - sha1((uchar *)passphrase, strlen(passphrase), passhash, nil); - initPAKparams(); - longhash(VERSION, C, passhash, H); - mpinvert(H, pak->p, Hi); - return mptoa(Hi, 64, nil, 0); -} - -// another, faster, hash function for each party to -// confirm that the other has the right secrets. -static void -shorthash(char *mess, char *C, char *S, char *m, char *mu, char *sigma, char *Hi, uchar *digest) -{ - SHA1state *state; - - state = sha1((uchar*)mess, strlen(mess), 0, 0); - state = sha1((uchar*)C, strlen(C), 0, state); - state = sha1((uchar*)S, strlen(S), 0, state); - state = sha1((uchar*)m, strlen(m), 0, state); - state = sha1((uchar*)mu, strlen(mu), 0, state); - state = sha1((uchar*)sigma, strlen(sigma), 0, state); - state = sha1((uchar*)Hi, strlen(Hi), 0, state); - state = sha1((uchar*)mess, strlen(mess), 0, state); - state = sha1((uchar*)C, strlen(C), 0, state); - state = sha1((uchar*)S, strlen(S), 0, state); - state = sha1((uchar*)m, strlen(m), 0, state); - state = sha1((uchar*)mu, strlen(mu), 0, state); - state = sha1((uchar*)sigma, strlen(sigma), 0, state); - sha1((uchar*)Hi, strlen(Hi), digest, state); -} - -// On input, conn provides an open channel to the server; -// C is the name this client calls itself; -// pass is the user's passphrase -// On output, session secret has been set in conn -// (unless return code is negative, which means failure). -// If pS is not nil, it is set to the (alloc'd) name the server calls itself. -int -PAKclient(SConn *conn, char *C, char *pass, char **pS) -{ - char *mess, *mess2, *eol, *S, *hexmu, *ks, *hexm, *hexsigma = nil, *hexHi; - char kc[2*SHA1dlen+1]; - uchar digest[SHA1dlen]; - int rc = -1, n; - mpint *x, *m = mpnew(0), *mu = mpnew(0), *sigma = mpnew(0); - mpint *H = mpnew(0), *Hi = mpnew(0); - - hexHi = PAK_Hi(C, pass, H, Hi); - if(verbose) - fprint(2,"%s\n", feedback[H->p[0]&0x7]); // provide a clue to catch typos - - // random 1<=x<=q-1; send C, m=g**x H - x = mprand(240, genrandom, nil); - mpmod(x, pak->q, x); - if(mpcmp(x, mpzero) == 0) - mpassign(mpone, x); - mpexp(pak->g, x, pak->p, m); - mpmul(m, H, m); - mpmod(m, pak->p, m); - hexm = mptoa(m, 64, nil, 0); - mess = (char*)emalloc(2*Maxmsg+2); - mess2 = mess+Maxmsg+1; - snprint(mess, Maxmsg, "%s\tPAK\nC=%s\nm=%s\n", VERSION, C, hexm); - conn->write(conn, (uchar*)mess, strlen(mess)); - - // recv g**y, S, check hash1(g**xy) - if(readstr(conn, mess) < 0){ - fprint(2, "error: %s\n", mess); - writerr(conn, "couldn't read g**y"); - goto done; - } - eol = strchr(mess, '\n'); - if(strncmp("mu=", mess, 3) != 0 || !eol || strncmp("\nk=", eol, 3) != 0){ - writerr(conn, "verifier syntax error"); - goto done; - } - hexmu = mess+3; - *eol = 0; - ks = eol+3; - eol = strchr(ks, '\n'); - if(!eol || strncmp("\nS=", eol, 3) != 0){ - writerr(conn, "verifier syntax error for secstore 1.0"); - goto done; - } - *eol = 0; - S = eol+3; - eol = strchr(S, '\n'); - if(!eol){ - writerr(conn, "verifier syntax error for secstore 1.0"); - goto done; - } - *eol = 0; - if(pS) - *pS = estrdup(S); - strtomp(hexmu, nil, 64, mu); - mpexp(mu, x, pak->p, sigma); - hexsigma = mptoa(sigma, 64, nil, 0); - shorthash("server", C, S, hexm, hexmu, hexsigma, hexHi, digest); - enc64(kc, sizeof kc, digest, SHA1dlen); - if(strcmp(ks, kc) != 0){ - writerr(conn, "verifier didn't match"); - goto done; - } - - // send hash2(g**xy) - shorthash("client", C, S, hexm, hexmu, hexsigma, hexHi, digest); - enc64(kc, sizeof kc, digest, SHA1dlen); - snprint(mess2, Maxmsg, "k'=%s\n", kc); - conn->write(conn, (uchar*)mess2, strlen(mess2)); - - // set session key - shorthash("session", C, S, hexm, hexmu, hexsigma, hexHi, digest); - memset(hexsigma, 0, strlen(hexsigma)); - n = conn->secret(conn, digest, 0); - memset(digest, 0, SHA1dlen); - if(n < 0){ - writerr(conn, "can't set secret"); - goto done; - } - - rc = 0; -done: - mpfree(x); - mpfree(sigma); - mpfree(mu); - mpfree(m); - mpfree(Hi); - mpfree(H); - free(hexsigma); - free(hexHi); - free(hexm); - free(mess); - return rc; -} - -// On input, -// mess contains first message; -// name is name this server should call itself. -// On output, session secret has been set in conn; -// if pw!=nil, then *pw points to PW struct for authenticated user. -// returns -1 if error -int -PAKserver(SConn *conn, char *S, char *mess, PW **pwp) -{ - int rc = -1, n; - char mess2[Maxmsg+1], *eol; - char *C, ks[41], *kc, *hexm, *hexmu = nil, *hexsigma = nil, *hexHi = nil; - uchar digest[SHA1dlen]; - mpint *H = mpnew(0), *Hi = mpnew(0); - mpint *y = nil, *m = mpnew(0), *mu = mpnew(0), *sigma = mpnew(0); - PW *pw = nil; - - // secstore version and algorithm - snprint(mess2,Maxmsg,"%s\tPAK\n", VERSION); - n = strlen(mess2); - if(strncmp(mess,mess2,n) != 0){ - writerr(conn, "protocol should start with ver alg"); - return -1; - } - mess += n; - initPAKparams(); - - // parse first message into C, m - eol = strchr(mess, '\n'); - if(strncmp("C=", mess, 2) != 0 || !eol){ - fprint(2,"mess[1]=%s\n", mess); - writerr(conn, "PAK version mismatch"); - goto done; - } - C = mess+2; - *eol = 0; - hexm = eol+3; - eol = strchr(hexm, '\n'); - if(strncmp("m=", hexm-2, 2) != 0 || !eol){ - writerr(conn, "PAK version mismatch"); - goto done; - } - *eol = 0; - strtomp(hexm, nil, 64, m); - mpmod(m, pak->p, m); - - // lookup client - if((pw = getPW(C,0)) == nil) { - snprint(mess2, sizeof mess2, "%r"); - writerr(conn, mess2); - goto done; - } - if(mpcmp(m, mpzero) == 0) { - writerr(conn, "account exists"); - freePW(pw); - pw = nil; - goto done; - } - hexHi = mptoa(pw->Hi, 64, nil, 0); - - // random y, mu=g**y, sigma=g**xy - y = mprand(240, genrandom, nil); - mpmod(y, pak->q, y); - if(mpcmp(y, mpzero) == 0){ - mpassign(mpone, y); - } - mpexp(pak->g, y, pak->p, mu); - mpmul(m, pw->Hi, m); - mpmod(m, pak->p, m); - mpexp(m, y, pak->p, sigma); - - // send g**y, hash1(g**xy) - hexmu = mptoa(mu, 64, nil, 0); - hexsigma = mptoa(sigma, 64, nil, 0); - shorthash("server", C, S, hexm, hexmu, hexsigma, hexHi, digest); - enc64(ks, sizeof ks, digest, SHA1dlen); - snprint(mess2, sizeof mess2, "mu=%s\nk=%s\nS=%s\n", hexmu, ks, S); - conn->write(conn, (uchar*)mess2, strlen(mess2)); - - // recv hash2(g**xy) - if(readstr(conn, mess2) < 0){ - writerr(conn, "couldn't read verifier"); - goto done; - } - eol = strchr(mess2, '\n'); - if(strncmp("k'=", mess2, 3) != 0 || !eol){ - writerr(conn, "verifier syntax error"); - goto done; - } - kc = mess2+3; - *eol = 0; - shorthash("client", C, S, hexm, hexmu, hexsigma, hexHi, digest); - enc64(ks, sizeof ks, digest, SHA1dlen); - if(strcmp(ks, kc) != 0) { - rc = -2; - goto done; - } - - // set session key - shorthash("session", C, S, hexm, hexmu, hexsigma, hexHi, digest); - n = conn->secret(conn, digest, 1); - if(n < 0){ - writerr(conn, "can't set secret"); - goto done; - } - - rc = 0; -done: - if(rc<0 && pw){ - pw->failed++; - putPW(pw); - } - if(rc==0 && pw && pw->failed>0){ - pw->failed = 0; - putPW(pw); - } - if(pwp) - *pwp = pw; - else - freePW(pw); - free(hexsigma); - free(hexHi); - free(hexmu); - mpfree(y); - mpfree(sigma); - mpfree(mu); - mpfree(m); - mpfree(Hi); - mpfree(H); - return rc; -} - diff --git a/src/cmd/secstore/password.c b/src/cmd/secstore/password.c deleted file mode 100644 index aacadd9b..00000000 --- a/src/cmd/secstore/password.c +++ /dev/null @@ -1,136 +0,0 @@ -/* password.c */ -#include <u.h> -#include <libc.h> -#include <bio.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" -#include "secstore.h" - -static Biobuf* -openPW(char *id, int mode) -{ - Biobuf *b; - int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; - char *fn = emalloc(nfn); - - snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); - b = Bopen(fn, mode); - free(fn); - return b; -} - -static ulong -mtimePW(char *id) -{ - Dir *d; - int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; - char *fn = emalloc(nfn); - ulong mt; - - snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); - d = dirstat(fn); - free(fn); - mt = d->mtime; - free(d); - return mt; -} - -PW * -getPW(char *id, int dead_or_alive) -{ - uint now = time(0); - Biobuf *bin; - PW *pw; - char *f1, *f2; // fields 1, 2 = attribute, value - - if((bin = openPW(id, OREAD)) == 0){ - id = "FICTITIOUS"; - if((bin = openPW(id, OREAD)) == 0){ - werrstr("account does not exist"); - return nil; - } - } - pw = emalloc(sizeof(*pw)); - pw->id = estrdup(id); - pw->status |= Enabled; - while( (f1 = Brdline(bin, '\n')) != 0){ - f1[Blinelen(bin)-1] = 0; - for(f2 = f1; *f2 && (*f2!=' ') && (*f2!='\t'); f2++){} - if(*f2) - for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++){} - if(strcmp(f1, "exp") == 0){ - pw->expire = strtoul(f2, 0, 10); - }else if(strcmp(f1, "DISABLED") == 0){ - pw->status &= ~Enabled; - }else if(strcmp(f1, "STA") == 0){ - pw->status |= STA; - }else if(strcmp(f1, "failed") == 0){ - pw->failed = strtoul(f2, 0, 10); - }else if(strcmp(f1, "other") == 0){ - pw->other = estrdup(f2); - }else if(strcmp(f1, "PAK-Hi") == 0){ - pw->Hi = strtomp(f2, nil, 64, nil); - } - } - Bterm(bin); - if(dead_or_alive) - return pw; // return PW entry for editing, whether currently valid or not - if(pw->expire <= now){ - werrstr("account expired"); - freePW(pw); - return nil; - } - if((pw->status & Enabled) == 0){ - werrstr("account disabled"); - freePW(pw); - return nil; - } - if(pw->failed < 10) - return pw; // success - if(now < mtimePW(id)+300){ - werrstr("too many failures; try again in five minutes"); - freePW(pw); - return nil; - } - pw->failed = 0; - putPW(pw); // reset failed-login-counter after five minutes - return pw; -} - -int -putPW(PW *pw) -{ - Biobuf *bout; - char *hexHi; - - if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){ - werrstr("can't open PW file"); - return -1; - } - Bprint(bout, "exp %lud\n", pw->expire); - if(!(pw->status & Enabled)) - Bprint(bout, "DISABLED\n"); - if(pw->status & STA) - Bprint(bout, "STA\n"); - if(pw->failed) - Bprint(bout, "failed\t%d\n", pw->failed); - if(pw->other) - Bprint(bout,"other\t%s\n", pw->other); - hexHi = mptoa(pw->Hi, 64, nil, 0); - Bprint(bout, "PAK-Hi\t%s\n", hexHi); - free(hexHi); - return 0; -} - -void -freePW(PW *pw) -{ - if(pw == nil) - return; - free(pw->id); - free(pw->other); - mpfree(pw->Hi); - free(pw); -} - diff --git a/src/cmd/secstore/portdate b/src/cmd/secstore/portdate deleted file mode 100644 index 8d50496e..00000000 --- a/src/cmd/secstore/portdate +++ /dev/null @@ -1,9 +0,0 @@ -SConn.c 2004/1225 -SConn.h 2004/1225 -aescbc.c 2004/1225 -dirls.c 2004/1225 -pak.c 2004/1225 -password.c 2004/1225 -secstore.c 2004/1225 -secstore.h 2004/1225 -util.c 2004/1225 diff --git a/src/cmd/secstore/secacct.c b/src/cmd/secstore/secacct.c deleted file mode 100644 index 4390129a..00000000 --- a/src/cmd/secstore/secacct.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <ip.h> - -int verbose = 1; -static char testmess[] = "__secstore\tPAK\nC=%s\nm=0\n"; - -void -main(int argc, char **argv) -{ - int n, m, fd; - uchar buf[500]; - - if(argc != 2) - exits("usage: secacct userid"); - - n = snprint((char*)buf, sizeof buf, testmess, argv[1]); - hnputs(buf, 0x8000+n-2); - - fd = dial("tcp!ruble.cs.bell-labs.com!5356", 0, 0, 0); - if(fd < 0) - exits("cannot dial ruble"); - if(write(fd, buf, n) != n || readn(fd, buf, 2) != 2) - exits("cannot exchange first round"); - n = ((buf[0]&0x7f)<<8) + buf[1]; - if(n+1 > sizeof buf) - exits("implausibly large count"); - m = readn(fd, buf, n); - close(fd); - if(m != n) - fprint(2,"short read from secstore\n"); - buf[m] = 0; - print("%s\n", (char*)buf); - exits(0); -} diff --git a/src/cmd/secstore/secchk.c b/src/cmd/secstore/secchk.c deleted file mode 100644 index 59e26d51..00000000 --- a/src/cmd/secstore/secchk.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <bio.h> -#include <ndb.h> - -extern char* secureidcheck(char *user, char *response); -Ndb *db; - -void -main(int argc, char **argv) -{ - Ndb *db2; - - if(argc!=2){ - fprint(2,"usage %s pinsecurid\n", argv[0]); - exits("usage"); - } - db = ndbopen("/lib/ndb/auth"); - if(db == 0) - syslog(0, "secstore", "no /lib/ndb/auth"); - db2 = ndbopen(0); - if(db2 == 0) - syslog(0, "secstore", "no /lib/ndb/local"); - db = ndbcat(db, db2); - print("user=%s\n", getenv("user")); - print("%s\n", secureidcheck(getenv("user"), argv[1])); - exits(0); -} diff --git a/src/cmd/secstore/secstore.c b/src/cmd/secstore/secstore.c deleted file mode 100644 index 864aa88d..00000000 --- a/src/cmd/secstore/secstore.c +++ /dev/null @@ -1,585 +0,0 @@ -/* network login client */ -#include <u.h> -#include <libc.h> -#include <mp.h> -#include <libsec.h> -#include <authsrv.h> -#include "SConn.h" -#include "secstore.h" -enum{ CHK = 16, MAXFILES = 100 }; - -typedef struct AuthConn{ - SConn *conn; - char pass[64]; - int passlen; -} AuthConn; - -int verbose; -Nvrsafe nvr; -char *SECSTORE_DIR; - -void -usage(void) -{ - fprint(2, "usage: secstore [-cin] [-g getfile] [-p putfile] [-r rmfile] [-s tcp!server!5356] [-u user] [-v]\n"); - exits("usage"); -} - -static int -getfile(SConn *conn, char *gf, uchar **buf, ulong *buflen, uchar *key, int nkey) -{ - int fd = -1; - int i, n, nr, nw, len; - char s[Maxmsg+1]; - uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw, *bufw, *bufe; - AESstate aes; - DigestState *sha; - - if(strchr(gf, '/')){ - fprint(2, "simple filenames, not paths like %s\n", gf); - return -1; - } - memset(&aes, 0, sizeof aes); - - snprint(s, Maxmsg, "GET %s\n", gf); - conn->write(conn, (uchar*)s, strlen(s)); - - /* get file size */ - s[0] = '\0'; - bufw = bufe = nil; - if(readstr(conn, s) < 0){ - fprint(2, "remote: %s\n", s); - return -1; - } - len = atoi(s); - if(len == -1){ - fprint(2, "remote file %s does not exist\n", gf); - return -1; - }else if(len == -3){ - fprint(2, "implausible filesize for %s\n", gf); - return -1; - }else if(len < 0){ - fprint(2, "GET refused for %s\n", gf); - return -1; - } - if(buf != nil){ - *buflen = len - AESbsize - CHK; - *buf = bufw = emalloc(len); - bufe = bufw + len; - } - - /* directory listing */ - if(strcmp(gf,".")==0){ - if(buf != nil) - *buflen = len; - for(i=0; i < len; i += n){ - if((n = conn->read(conn, (uchar*)s, Maxmsg)) <= 0){ - fprint(2, "empty file chunk\n"); - return -1; - } - if(buf == nil) - write(1, s, n); - else - memmove((*buf)+i, s, n); - } - return 0; - } - - /* conn is already encrypted against wiretappers, - but gf is also encrypted against server breakin. */ - if(buf == nil && (fd =create(gf, OWRITE, 0600)) < 0){ - fprint(2, "can't open %s: %r\n", gf); - return -1; - } - - ibr = ibw = ib; - for(nr=0; nr < len;){ - if((n = conn->read(conn, ibw, Maxmsg)) <= 0){ - fprint(2, "empty file chunk n=%d nr=%d len=%d: %r\n", n, nr, len); - return -1; - } - nr += n; - ibw += n; - if(!aes.setup){ /* first time, read 16 byte IV */ - if(n < AESbsize){ - fprint(2, "no IV in file\n"); - return -1; - } - sha = sha1((uchar*)"aescbc file", 11, nil, nil); - sha1(key, nkey, skey, sha); - setupAESstate(&aes, skey, AESbsize, ibr); - memset(skey, 0, sizeof skey); - ibr += AESbsize; - n -= AESbsize; - } - aesCBCdecrypt(ibw-n, n, &aes); - n = ibw-ibr-CHK; - if(n > 0){ - if(buf == nil){ - nw = write(fd, ibr, n); - if(nw != n){ - fprint(2, "write error on %s", gf); - return -1; - } - }else{ - assert(bufw+n <= bufe); - memmove(bufw, ibr, n); - bufw += n; - } - ibr += n; - } - memmove(ib, ibr, ibw-ibr); - ibw = ib + (ibw-ibr); - ibr = ib; - } - if(buf == nil) - close(fd); - n = ibw-ibr; - if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){ - fprint(2,"decrypted file failed to authenticate!\n"); - return -1; - } - return 0; -} - -// This sends a file to the secstore disk that can, in an emergency, be -// decrypted by the program aescbc.c. -static int -putfile(SConn *conn, char *pf, uchar *buf, ulong len, uchar *key, int nkey) -{ - int i, n, fd, ivo, bufi, done; - char s[Maxmsg]; - uchar skey[SHA1dlen], b[CHK+Maxmsg], IV[AESbsize]; - AESstate aes; - DigestState *sha; - - /* create initialization vector */ - srand(time(0)); /* doesn't need to be unpredictable */ - for(i=0; i<AESbsize; i++) - IV[i] = 0xff & rand(); - sha = sha1((uchar*)"aescbc file", 11, nil, nil); - sha1(key, nkey, skey, sha); - setupAESstate(&aes, skey, AESbsize, IV); - memset(skey, 0, sizeof skey); - - snprint(s, Maxmsg, "PUT %s\n", pf); - conn->write(conn, (uchar*)s, strlen(s)); - - if(buf == nil){ - /* get file size */ - if((fd = open(pf, OREAD)) < 0){ - fprint(2, "can't open %s: %r\n", pf); - return -1; - } - len = seek(fd, 0, 2); - seek(fd, 0, 0); - } else { - fd = -1; - } - if(len > MAXFILESIZE){ - fprint(2, "implausible filesize %ld for %s\n", len, pf); - return -1; - } - - /* send file size */ - snprint(s, Maxmsg, "%ld", len+AESbsize+CHK); - conn->write(conn, (uchar*)s, strlen(s)); - - /* send IV and file+XXXXX in Maxmsg chunks */ - ivo = AESbsize; - bufi = 0; - memcpy(b, IV, ivo); - for(done = 0; !done; ){ - if(buf == nil){ - n = read(fd, b+ivo, Maxmsg-ivo); - if(n < 0){ - fprint(2, "read error on %s: %r\n", pf); - return -1; - } - }else{ - if((n = len - bufi) > Maxmsg-ivo) - n = Maxmsg-ivo; - memcpy(b+ivo, buf+bufi, n); - bufi += n; - } - n += ivo; - ivo = 0; - if(n < Maxmsg){ /* EOF on input; append XX... */ - memset(b+n, 'X', CHK); - n += CHK; // might push n>Maxmsg - done = 1; - } - aesCBCencrypt(b, n, &aes); - if(n > Maxmsg){ - assert(done==1); - conn->write(conn, b, Maxmsg); - n -= Maxmsg; - memmove(b, b+Maxmsg, n); - } - conn->write(conn, b, n); - } - - if(buf == nil) - close(fd); - fprint(2, "saved %ld bytes\n", len); - - return 0; -} - -static int -removefile(SConn *conn, char *rf) -{ - char buf[Maxmsg]; - - if(strchr(rf, '/')){ - fprint(2, "simple filenames, not paths like %s\n", rf); - return -1; - } - - snprint(buf, Maxmsg, "RM %s\n", rf); - conn->write(conn, (uchar*)buf, strlen(buf)); - - return 0; -} - -static int -cmd(AuthConn *c, char **gf, int *Gflag, char **pf, char **rf) -{ - ulong len; - int rv = -1; - uchar *memfile, *memcur, *memnext; - - while(*gf != nil){ - if(verbose) - fprint(2, "get %s\n", *gf); - if(getfile(c->conn, *gf, *Gflag ? &memfile : nil, &len, (uchar*)c->pass, c->passlen) < 0) - goto Out; - if(*Gflag){ - // write one line at a time, as required by /mnt/factotum/ctl - memcur = memfile; - while(len>0){ - memnext = (uchar*)strchr((char*)memcur, '\n'); - if(memnext){ - write(1, memcur, memnext-memcur+1); - len -= memnext-memcur+1; - memcur = memnext+1; - }else{ - write(1, memcur, len); - break; - } - } - free(memfile); - } - gf++; - Gflag++; - } - while(*pf != nil){ - if(verbose) - fprint(2, "put %s\n", *pf); - if(putfile(c->conn, *pf, nil, 0, (uchar*)c->pass, c->passlen) < 0) - goto Out; - pf++; - } - while(*rf != nil){ - if(verbose) - fprint(2, "rm %s\n", *rf); - if(removefile(c->conn, *rf) < 0) - goto Out; - rf++; - } - - c->conn->write(c->conn, (uchar*)"BYE", 3); - rv = 0; - -Out: - c->conn->free(c->conn); - return rv; -} - -static int -chpasswd(AuthConn *c, char *id) -{ - ulong len; - int rv = -1, newpasslen = 0; - mpint *H, *Hi; - uchar *memfile; - char *newpass, *passck; - char *list, *cur, *next, *hexHi; - char *f[8], prompt[128]; - - H = mpnew(0); - Hi = mpnew(0); - // changing our password is vulnerable to connection failure - for(;;){ - snprint(prompt, sizeof(prompt), "new password for %s: ", id); - newpass = readcons(prompt, nil, 1); - if(newpass == nil) - goto Out; - if(strlen(newpass) >= 7) - break; - else if(strlen(newpass) == 0){ - fprint(2, "!password change aborted\n"); - goto Out; - } - print("!password must be at least 7 characters\n"); - } - newpasslen = strlen(newpass); - snprint(prompt, sizeof(prompt), "retype password: "); - passck = readcons(prompt, nil, 1); - if(passck == nil){ - fprint(2, "readcons failed\n"); - goto Out; - } - if(strcmp(passck, newpass) != 0){ - fprint(2, "passwords didn't match\n"); - goto Out; - } - - c->conn->write(c->conn, (uchar*)"CHPASS", strlen("CHPASS")); - hexHi = PAK_Hi(id, newpass, H, Hi); - c->conn->write(c->conn, (uchar*)hexHi, strlen(hexHi)); - free(hexHi); - mpfree(H); - mpfree(Hi); - - if(getfile(c->conn, ".", (uchar **)(void*)&list, &len, nil, 0) < 0){ - fprint(2, "directory listing failed.\n"); - goto Out; - } - - /* Loop over files and reencrypt them; try to keep going after error */ - for(cur=list; (next=strchr(cur, '\n')) != nil; cur=next+1){ - *next = '\0'; - if(tokenize(cur, f, nelem(f))< 1) - break; - fprint(2, "reencrypting '%s'\n", f[0]); - if(getfile(c->conn, f[0], &memfile, &len, (uchar*)c->pass, c->passlen) < 0){ - fprint(2, "getfile of '%s' failed\n", f[0]); - continue; - } - if(putfile(c->conn, f[0], memfile, len, (uchar*)newpass, newpasslen) < 0) - fprint(2, "putfile of '%s' failed\n", f[0]); - free(memfile); - } - free(list); - c->conn->write(c->conn, (uchar*)"BYE", 3); - rv = 0; - -Out: - if(newpass != nil){ - memset(newpass, 0, newpasslen); - free(newpass); - } - c->conn->free(c->conn); - return rv; -} - -static AuthConn* -login(char *id, char *dest, int pass_stdin, int pass_nvram) -{ - AuthConn *c; - int fd, n, ntry = 0; - char *S, *PINSTA = nil, *nl, s[Maxmsg+1], *pass; - - if(dest == nil){ - fprint(2, "tried to login with nil dest\n"); - exits("nil dest"); - } - c = emalloc(sizeof(*c)); - if(pass_nvram){ - /* if(readnvram(&nvr, 0) < 0) */ - exits("readnvram: %r"); - strecpy(c->pass, c->pass+sizeof c->pass, nvr.config); - } - if(pass_stdin){ - n = readn(0, s, Maxmsg-2); // so len(PINSTA)<Maxmsg-3 - if(n < 1) - exits("no password on standard input"); - s[n] = 0; - nl = strchr(s, '\n'); - if(nl){ - *nl++ = 0; - PINSTA = estrdup(nl); - nl = strchr(PINSTA, '\n'); - if(nl) - *nl = 0; - } - strecpy(c->pass, c->pass+sizeof c->pass, s); - } - while(1){ - if(verbose) - fprint(2, "dialing %s\n", dest); - if((fd = dial(dest, nil, nil, nil)) < 0){ - fprint(2, "can't dial %s\n", dest); - free(c); - return nil; - } - if((c->conn = newSConn(fd)) == nil){ - free(c); - return nil; - } - ntry++; - if(!pass_stdin && !pass_nvram){ - pass = readcons("secstore password", nil, 1); - if(pass == nil) - pass = estrdup(""); - if(strlen(pass) >= sizeof c->pass){ - fprint(2, "password too long, skipping secstore login\n"); - exits("password too long"); - } - strcpy(c->pass, pass); - memset(pass, 0, strlen(pass)); - free(pass); - } - if(c->pass[0]==0){ - fprint(2, "null password, skipping secstore login\n"); - exits("no password"); - } - if(PAKclient(c->conn, id, c->pass, &S) >= 0) - break; - c->conn->free(c->conn); - if(pass_stdin) - exits("invalid password on standard input"); - if(pass_nvram) - exits("invalid password in nvram"); - // and let user try retyping the password - if(ntry==3) - fprint(2, "Enter an empty password to quit.\n"); - } - c->passlen = strlen(c->pass); - fprint(2, "server: %s\n", S); - free(S); - if(readstr(c->conn, s) < 0){ - c->conn->free(c->conn); - free(c); - return nil; - } - if(strcmp(s, "STA") == 0){ - long sn; - if(pass_stdin){ - if(PINSTA) - strncpy(s+3, PINSTA, (sizeof s)-3); - else - exits("missing PIN+SecureID on standard input"); - free(PINSTA); - }else{ - pass = readcons("STA PIN+SecureID", nil, 1); - if(pass == nil) - pass = estrdup(""); - strncpy(s+3, pass, (sizeof s)-4); - memset(pass, 0, strlen(pass)); - free(pass); - } - sn = strlen(s+3); - if(verbose) - fprint(2, "%ld\n", sn); - c->conn->write(c->conn, (uchar*)s, sn+3); - readstr(c->conn, s); - } - if(strcmp(s, "OK") != 0){ - fprint(2, "%s\n", s); - c->conn->free(c->conn); - free(c); - return nil; - } - return c; -} - -int -main(int argc, char **argv) -{ - int chpass = 0, pass_stdin = 0, pass_nvram = 0, rc; - int ngfile = 0, npfile = 0, nrfile = 0, Gflag[MAXFILES+1]; - char *gfile[MAXFILES], *pfile[MAXFILES], *rfile[MAXFILES]; - char *serve, *tcpserve, *user; - AuthConn *c; - - serve = "$auth"; - user = getuser(); - memset(Gflag, 0, sizeof Gflag); - fmtinstall('B', mpfmt); - fmtinstall('H', encodefmt); - - ARGBEGIN{ - case 'c': - chpass = 1; - break; - case 'G': - Gflag[ngfile]++; - /* fall through */ - case 'g': - if(ngfile >= MAXFILES) - exits("too many gfiles"); - gfile[ngfile++] = ARGF(); - if(gfile[ngfile-1] == nil) - usage(); - break; - case 'i': - pass_stdin = 1; - break; - case 'n': - pass_nvram = 1; - break; - case 'p': - if(npfile >= MAXFILES) - exits("too many pfiles"); - pfile[npfile++] = ARGF(); - if(pfile[npfile-1] == nil) - usage(); - break; - case 'r': - if(nrfile >= MAXFILES) - exits("too many rfiles"); - rfile[nrfile++] = ARGF(); - if(rfile[nrfile-1] == nil) - usage(); - break; - case 's': - serve = EARGF(usage()); - break; - case 'u': - user = EARGF(usage()); - break; - case 'v': - verbose++; - break; - default: - usage(); - break; - }ARGEND; - gfile[ngfile] = nil; - pfile[npfile] = nil; - rfile[nrfile] = nil; - - if(argc!=0 || user==nil) - usage(); - - if(chpass && (ngfile || npfile || nrfile)){ - fprint(2, "Get, put, and remove invalid with password change.\n"); - exits("usage"); - } - - rc = strlen(serve)+sizeof("tcp!!99990"); - tcpserve = emalloc(rc); - if(strchr(serve,'!')) - strcpy(tcpserve, serve); - else - snprint(tcpserve, rc, "tcp!%s!5356", serve); - c = login(user, tcpserve, pass_stdin, pass_nvram); - free(tcpserve); - if(c == nil){ - fprint(2, "secstore authentication failed\n"); - exits("secstore authentication failed"); - } - if(chpass) - rc = chpasswd(c, user); - else - rc = cmd(c, gfile, Gflag, pfile, rfile); - if(rc < 0){ - fprint(2, "secstore cmd failed\n"); - exits("secstore cmd failed"); - } - exits(""); - return 0; -} - diff --git a/src/cmd/secstore/secstore.h b/src/cmd/secstore/secstore.h deleted file mode 100644 index dbd2ec9c..00000000 --- a/src/cmd/secstore/secstore.h +++ /dev/null @@ -1,31 +0,0 @@ -enum{ MAXFILESIZE = 10*1024*1024 }; - -enum{// PW status bits - Enabled = (1<<0), - STA = (1<<1), // extra SecurID step -}; - -typedef struct PW { - char *id; // user id - ulong expire; // expiration time (epoch seconds) - ushort status; // Enabled, STA, ... - ushort failed; // number of failed login attempts - char *other; // other information, e.g. sponsor - mpint *Hi; // H(passphrase)^-1 mod p -} PW; - -PW *getPW(char *, int); -int putPW(PW *); -void freePW(PW *); - -// *client: SConn, client name, passphrase -// *server: SConn, (partial) 1st msg, PW entry -// *setpass: Username, hashed passphrase, PW entry -int PAKclient(SConn *, char *, char *, char **); -int PAKserver(SConn *, char *, char *, PW **); -char *PAK_Hi(char *, char *, mpint *, mpint *); - -#define LOG "secstore" - -extern char *SECSTORE_DIR; - diff --git a/src/cmd/secstore/secstored.c b/src/cmd/secstore/secstored.c deleted file mode 100644 index 58f7459a..00000000 --- a/src/cmd/secstore/secstored.c +++ /dev/null @@ -1,420 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <bio.h> -#include <ndb.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" -#include "secstore.h" - -char *SECSTORE_DIR; -char* secureidcheck(char *, char *); // from /sys/src/cmd/auth/ -extern char* dirls(char *path); - -int verbose; -Ndb *db; - -static void -usage(void) -{ - fprint(2, "usage: secstored [-R] [-S servername] [-s tcp!*!5356] [-v] [-x netmtpt]\n"); - exits("usage"); -} - -static int -getdir(SConn *conn, char *id) -{ - char *ls, *s; - uchar *msg; - int n, len; - - s = emalloc(Maxmsg); - snprint(s, Maxmsg, "%s/store/%s", SECSTORE_DIR, id); - - if((ls = dirls(s)) == nil) - len = 0; - else - len = strlen(ls); - - /* send file size */ - snprint(s, Maxmsg, "%d", len); - conn->write(conn, (uchar*)s, strlen(s)); - - /* send directory listing in Maxmsg chunks */ - n = Maxmsg; - msg = (uchar*)ls; - while(len > 0){ - if(len < Maxmsg) - n = len; - conn->write(conn, msg, n); - msg += n; - len -= n; - } - free(s); - free(ls); - return 0; -} - -char * -validatefile(char *f) -{ - char *nl; - - if(f==nil || *f==0) - return nil; - if(nl = strchr(f, '\n')) - *nl = 0; - if(strchr(f,'/') != nil || strcmp(f,"..")==0 || strlen(f) >= 300){ - syslog(0, LOG, "no slashes allowed: %s\n", f); - return nil; - } - return f; -} - -static int -getfile(SConn *conn, char *id, char *gf) -{ - int n, gd, len; - ulong mode; - char *s; - Dir *st; - - if(strcmp(gf,".")==0) - return getdir(conn, id); - - /* send file size */ - s = emalloc(Maxmsg); - snprint(s, Maxmsg, "%s/store/%s/%s", SECSTORE_DIR, id, gf); - gd = open(s, OREAD); - if(gd < 0){ - syslog(0, LOG, "can't open %s: %r\n", s); - free(s); - conn->write(conn, (uchar*)"-1", 2); - return -1; - } - st = dirfstat(gd); - if(st == nil){ - syslog(0, LOG, "can't stat %s: %r\n", s); - free(s); - conn->write(conn, (uchar*)"-1", 2); - return -1; - } - mode = st->mode; - len = st->length; - free(st); - if(mode & DMDIR) { - syslog(0, LOG, "%s should be a plain file, not a directory\n", s); - free(s); - conn->write(conn, (uchar*)"-1", 2); - return -1; - } - if(len < 0 || len > MAXFILESIZE){ - syslog(0, LOG, "implausible filesize %d for %s\n", len, gf); - free(s); - conn->write(conn, (uchar*)"-3", 2); - return -1; - } - snprint(s, Maxmsg, "%d", len); - conn->write(conn, (uchar*)s, strlen(s)); - - /* send file in Maxmsg chunks */ - while(len > 0){ - n = read(gd, s, Maxmsg); - if(n <= 0){ - syslog(0, LOG, "read error on %s: %r\n", gf); - free(s); - return -1; - } - conn->write(conn, (uchar*)s, n); - len -= n; - } - close(gd); - free(s); - return 0; -} - -static int -putfile(SConn *conn, char *id, char *pf) -{ - int n, nw, pd; - long len; - char s[Maxmsg+1]; - - /* get file size */ - n = readstr(conn, s); - if(n < 0){ - syslog(0, LOG, "remote: %s: %r\n", s); - return -1; - } - len = atoi(s); - if(len == -1){ - syslog(0, LOG, "remote file %s does not exist\n", pf); - return -1; - }else if(len < 0 || len > MAXFILESIZE){ - syslog(0, LOG, "implausible filesize %ld for %s\n", len, pf); - return -1; - } - - /* get file in Maxmsg chunks */ - if(strchr(pf,'/') != nil || strcmp(pf,"..")==0){ - syslog(0, LOG, "no slashes allowed: %s\n", pf); - return -1; - } - snprint(s, Maxmsg, "%s/store/%s/%s", SECSTORE_DIR, id, pf); - pd = create(s, OWRITE, 0660); - if(pd < 0){ - syslog(0, LOG, "can't open %s: %r\n", s); - return -1; - } - while(len > 0){ - n = conn->read(conn, (uchar*)s, Maxmsg); - if(n <= 0){ - syslog(0, LOG, "empty file chunk\n"); - return -1; - } - nw = write(pd, s, n); - if(nw != n){ - syslog(0, LOG, "write error on %s: %r", pf); - return -1; - } - len -= n; - } - close(pd); - return 0; - -} - -static int -removefile(SConn *conn, char *id, char *f) -{ - Dir *d; - char buf[Maxmsg]; - - snprint(buf, Maxmsg, "%s/store/%s/%s", SECSTORE_DIR, id, f); - - if((d = dirstat(buf)) == nil){ - snprint(buf, sizeof buf, "remove failed: %r"); - writerr(conn, buf); - return -1; - }else if(d->mode & DMDIR){ - snprint(buf, sizeof buf, "can't remove a directory"); - writerr(conn, buf); - free(d); - return -1; - } - - free(d); - if(remove(buf) < 0){ - snprint(buf, sizeof buf, "remove failed: %r"); - writerr(conn, buf); - return -1; - } - return 0; -} - -/* given line directory from accept, returns ipaddr!port */ -static char* -remoteIP(char *ldir) -{ - int fd, n; - char rp[100], ap[500]; - - snprint(rp, sizeof rp, "%s/remote", ldir); - fd = open(rp, OREAD); - if(fd < 0) - return strdup("?!?"); - n = read(fd, ap, sizeof ap); - if(n <= 0 || n == sizeof ap){ - fprint(2, "error %d reading %s: %r\n", n, rp); - return strdup("?!?"); - } - close(fd); - ap[n--] = 0; - if(ap[n] == '\n') - ap[n] = 0; - return strdup(ap); -} - -static int -dologin(int fd, char *S, int forceSTA) -{ - int i, n, rv; - char *file, *mess; - char msg[Maxmsg+1]; - PW *pw; - SConn *conn; - - pw = nil; - rv = -1; - - // collect the first message - if((conn = newSConn(fd)) == nil) - return -1; - if(readstr(conn, msg) < 0){ - fprint(2, "remote: %s: %r\n", msg); - writerr(conn, "can't read your first message"); - goto Out; - } - - // authenticate - if(PAKserver(conn, S, msg, &pw) < 0){ - if(pw != nil) - syslog(0, LOG, "secstore denied for %s", pw->id); - goto Out; - } - if((forceSTA || pw->status&STA) != 0){ - conn->write(conn, (uchar*)"STA", 3); - if(readstr(conn, msg) < 10 || strncmp(msg, "STA", 3) != 0){ - syslog(0, LOG, "no STA from %s", pw->id); - goto Out; - } - mess = secureidcheck(pw->id, msg+3); - if(mess != nil){ - syslog(0, LOG, "secureidcheck denied %s because %s", pw->id, mess); - goto Out; - } - } - conn->write(conn, (uchar*)"OK", 2); - syslog(0, LOG, "AUTH %s", pw->id); - - // perform operations as asked - while((n = readstr(conn, msg)) > 0){ - syslog(0, LOG, "[%s] %s", pw->id, msg); - - if(strncmp(msg, "GET ", 4) == 0){ - file = validatefile(msg+4); - if(file==nil || getfile(conn, pw->id, file) < 0) - goto Err; - - }else if(strncmp(msg, "PUT ", 4) == 0){ - file = validatefile(msg+4); - if(file==nil || putfile(conn, pw->id, file) < 0){ - syslog(0, LOG, "failed PUT %s/%s", pw->id, file); - goto Err; - } - - }else if(strncmp(msg, "RM ", 3) == 0){ - file = validatefile(msg+3); - if(file==nil || removefile(conn, pw->id, file) < 0){ - syslog(0, LOG, "failed RM %s/%s", pw->id, file); - goto Err; - } - - }else if(strncmp(msg, "CHPASS", 6) == 0){ - if(readstr(conn, msg) < 0){ - syslog(0, LOG, "protocol botch CHPASS for %s", pw->id); - writerr(conn, "protocol botch while setting PAK"); - goto Out; - } - pw->Hi = strtomp(msg, nil, 64, pw->Hi); - for(i=0; i < 4 && putPW(pw) < 0; i++) - syslog(0, LOG, "password change failed for %s (%d): %r", pw->id, i); - if(i==4) - goto Out; - - }else if(strncmp(msg, "BYE", 3) == 0){ - rv = 0; - break; - - }else{ - writerr(conn, "unrecognized operation"); - break; - } - - } - if(n <= 0) - syslog(0, LOG, "%s closed connection without saying goodbye\n", pw->id); - -Out: - freePW(pw); - conn->free(conn); - return rv; -Err: - writerr(conn, "operation failed"); - goto Out; -} - -void -main(int argc, char **argv) -{ - int afd, dfd, lcfd, forceSTA = 0; - char adir[40], ldir[40], *remote; - char *serve = "tcp!*!5356", *p, aserve[128]; - char *S = "secstore"; - char *dbpath; - Ndb *db2; - - S = sysname(); - SECSTORE_DIR = unsharp("#9/secstore"); -// setnetmtpt(net, sizeof(net), nil); - ARGBEGIN{ - case 'R': - forceSTA = 1; - break; - case 's': - serve = EARGF(usage()); - break; - case 'S': - S = EARGF(usage()); - break; - case 'x': - p = ARGF(); - if(p == nil) - usage(); - USED(p); - // setnetmtpt(net, sizeof(net), p); - break; - case 'v': - verbose++; - break; - default: - usage(); - }ARGEND; - - if(!verbose) - switch(rfork(RFNOTEG|RFPROC|RFFDG)) { - case -1: - sysfatal("fork: %r"); - case 0: - break; - default: - exits(0); - } - - snprint(aserve, sizeof aserve, "%s", serve); - afd = announce(aserve, adir); - if(afd < 0) - sysfatal("%s: %r\n", aserve); - syslog(0, LOG, "ANNOUNCE %s", aserve); - for(;;){ - if((lcfd = listen(adir, ldir)) < 0) - exits("can't listen"); - switch(fork()){ - case -1: - fprint(2, "secstore forking: %r\n"); - close(lcfd); - break; - case 0: - // "/lib/ndb/common.radius does not exist" if db set before fork - db = ndbopen(dbpath=unsharp("#9/ndb/auth")); - if(db == 0) - syslog(0, LOG, "no ndb/auth"); - db2 = ndbopen(0); - if(db2 == 0) - syslog(0, LOG, "no ndb/local"); - db = ndbcat(db, db2); - if((dfd = accept(lcfd, ldir)) < 0) - exits("can't accept"); - alarm(30*60*1000); // 30 min - remote = remoteIP(ldir); - syslog(0, LOG, "secstore from %s", remote); - free(remote); - dologin(dfd, S, forceSTA); - exits(nil); - default: - close(lcfd); - break; - } - } -} - diff --git a/src/cmd/secstore/secureidcheck.c b/src/cmd/secstore/secureidcheck.c deleted file mode 100644 index 95adb385..00000000 --- a/src/cmd/secstore/secureidcheck.c +++ /dev/null @@ -1,446 +0,0 @@ -/* RFC2138 */ -#include <u.h> -#include <libc.h> -#include <ip.h> -#include <ctype.h> -#include <mp.h> -#include <libsec.h> -#include <bio.h> -#include <ndb.h> -#define AUTHLOG "auth" - -enum{ R_AccessRequest=1, /* Packet code */ - R_AccessAccept=2, - R_AccessReject=3, - R_AccessChallenge=11, - R_UserName=1, - R_UserPassword=2, - R_NASIPAddress=4, - R_ReplyMessage=18, - R_State=24, - R_NASIdentifier=32 -}; - -typedef struct Secret{ - uchar *s; - int len; -} Secret; - -typedef struct Attribute{ - struct Attribute *next; - uchar type; - uchar len; // number of bytes in value - uchar val[256]; -} Attribute; - -typedef struct Packet{ - uchar code, ID; - uchar authenticator[16]; - Attribute first; -} Packet; - -// assumes pass is at most 16 chars -void -hide(Secret *shared, uchar *auth, Secret *pass, uchar *x) -{ - DigestState *M; - int i, n = pass->len; - - M = md5(shared->s, shared->len, nil, nil); - md5(auth, 16, x, M); - if(n > 16) - n = 16; - for(i = 0; i < n; i++) - x[i] ^= (pass->s)[i]; -} - -int -authcmp(Secret *shared, uchar *buf, int m, uchar *auth) -{ - DigestState *M; - uchar x[16]; - - M = md5(buf, 4, nil, nil); // Code+ID+Length - M = md5(auth, 16, nil, M); // RequestAuth - M = md5(buf+20, m-20, nil, M); // Attributes - md5(shared->s, shared->len, x, M); - return memcmp(x, buf+4, 16); -} - -Packet* -newRequest(uchar *auth) -{ - static uchar ID = 0; - Packet *p; - - p = (Packet*)malloc(sizeof(*p)); - if(p == nil) - return nil; - p->code = R_AccessRequest; - p->ID = ++ID; - memmove(p->authenticator, auth, 16); - p->first.next = nil; - p->first.type = 0; - return p; -} - -void -freePacket(Packet *p) -{ - Attribute *a, *x; - - if(!p) - return; - a = p->first.next; - while(a){ - x = a; - a = a->next; - free(x); - } - free(p); -} - -int -ding(void *v, char *msg) -{ - USED(v); -/* syslog(0, AUTHLOG, "ding %s", msg); */ - if(strstr(msg, "alarm")) - return 1; - return 0; -} - -Packet * -rpc(char *dest, Secret *shared, Packet *req) -{ - uchar buf[4096], buf2[4096], *b, *e; - Packet *resp; - Attribute *a; - int m, n, fd, try; - - // marshal request - e = buf + sizeof buf; - buf[0] = req->code; - buf[1] = req->ID; - memmove(buf+4, req->authenticator, 16); - b = buf+20; - for(a = &req->first; a; a = a->next){ - if(b + 2 + a->len > e) - return nil; - *b++ = a->type; - *b++ = 2 + a->len; - memmove(b, a->val, a->len); - b += a->len; - } - n = b-buf; - buf[2] = n>>8; - buf[3] = n; - - // send request, wait for reply - fd = dial(dest, 0, 0, 0); - if(fd < 0){ - syslog(0, AUTHLOG, "%s: rpc can't get udp channel", dest); - return nil; - } - atnotify(ding, 1); - m = -1; - for(try = 0; try < 2; try++){ - alarm(4000); - m = write(fd, buf, n); - if(m != n){ - syslog(0, AUTHLOG, "%s: rpc write err %d %d: %r", dest, m, n); - m = -1; - break; - } - m = read(fd, buf2, sizeof buf2); - alarm(0); - if(m < 0){ - syslog(0, AUTHLOG, "%s rpc read err %d: %r", dest, m); - break; // failure - } - if(m == 0 || buf2[1] != buf[1]){ // need matching ID - syslog(0, AUTHLOG, "%s unmatched reply %d", dest, m); - continue; - } - if(authcmp(shared, buf2, m, buf+4) == 0) - break; - syslog(0, AUTHLOG, "%s bad rpc chksum", dest); - } - close(fd); - if(m <= 0) - return nil; - - // unmarshal reply - b = buf2; - e = buf2+m; - resp = (Packet*)malloc(sizeof(*resp)); - if(resp == nil) - return nil; - resp->code = *b++; - resp->ID = *b++; - n = *b++; - n = (n<<8) | *b++; - if(m != n){ - syslog(0, AUTHLOG, "rpc got %d bytes, length said %d", m, n); - if(m > n) - e = buf2+n; - } - memmove(resp->authenticator, b, 16); - b += 16; - a = &resp->first; - a->type = 0; - while(1){ - if(b >= e){ - a->next = nil; - break; // exit loop - } - a->type = *b++; - a->len = (*b++) - 2; - if(b + a->len > e){ // corrupt packet - a->next = nil; - freePacket(resp); - return nil; - } - memmove(a->val, b, a->len); - b += a->len; - if(b < e){ // any more attributes? - a->next = (Attribute*)malloc(sizeof(*a)); - if(a->next == nil){ - free(req); - return nil; - } - a = a->next; - } - } - return resp; -} - -int -setAttribute(Packet *p, uchar type, uchar *s, int n) -{ - Attribute *a; - - a = &p->first; - if(a->type != 0){ - a = (Attribute*)malloc(sizeof(*a)); - if(a == nil) - return -1; - a->next = p->first.next; - p->first.next = a; - } - a->type = type; - a->len = n; - if(a->len > 253 ) // RFC2138, section 5 - a->len = 253; - memmove(a->val, s, a->len); - return 0; -} - -/* return a reply message attribute string */ -char* -replymsg(Packet *p) -{ - Attribute *a; - static char buf[255]; - - for(a = &p->first; a; a = a->next){ - if(a->type == R_ReplyMessage){ - if(a->len >= sizeof buf) - a->len = sizeof(buf)-1; - memmove(buf, a->val, a->len); - buf[a->len] = 0; - } - } - return buf; -} - -/* for convenience while debugging */ -char *replymess; -Attribute *stateattr; - -void -logPacket(Packet *p) -{ - Attribute *a; - char buf[255]; - char pbuf[4*1024]; - uchar *au = p->authenticator; - int i; - char *np, *e; - - e = pbuf + sizeof(pbuf); - - np = seprint(pbuf, e, "Packet ID=%d auth=%x %x %x... ", p->ID, au[0], au[1], au[2]); - switch(p->code){ - case R_AccessRequest: - np = seprint(np, e, "request\n"); - break; - case R_AccessAccept: - np = seprint(np, e, "accept\n"); - break; - case R_AccessReject: - np = seprint(np, e, "reject\n"); - break; - case R_AccessChallenge: - np = seprint(np, e, "challenge\n"); - break; - default: - np = seprint(np, e, "code=%d\n", p->code); - break; - } - replymess = "0000000"; - for(a = &p->first; a; a = a->next){ - if(a->len > 253 ) - a->len = 253; - memmove(buf, a->val, a->len); - np = seprint(np, e, " [%d]", a->type); - for(i = 0; i<a->len; i++) - if(isprint(a->val[i])) - np = seprint(np, e, "%c", a->val[i]); - else - np = seprint(np, e, "\\%o", a->val[i]); - np = seprint(np, e, "\n"); - buf[a->len] = 0; - if(a->type == R_ReplyMessage) - replymess = strdup(buf); - else if(a->type == R_State) - stateattr = a; - } - - syslog(0, AUTHLOG, "%s", pbuf); -} - -static uchar* -getipv4addr(void) -{ - Ipifc *nifc; - Iplifc *lifc; - static Ipifc *ifc; - - ifc = readipifc("/net", ifc, -1); - for(nifc = ifc; nifc; nifc = nifc->next) - for(lifc = nifc->lifc; lifc; lifc = lifc->next) - if(ipcmp(lifc->ip, IPnoaddr) != 0 && ipcmp(lifc->ip, v4prefix) != 0) - return lifc->ip; - return nil; -} - -extern Ndb *db; - -/* returns 0 on success, error message on failure */ -char* -secureidcheck(char *user, char *response) -{ - Packet *req = nil, *resp = nil; - ulong u[4]; - uchar x[16]; - char *radiussecret; - char ruser[ 64]; - char dest[3*IPaddrlen+20]; - Secret shared, pass; - char *rv = "authentication failed"; - Ndbs s; - Ndbtuple *t, *nt, *tt; - uchar *ip; - static Ndb *netdb; - - if(netdb == nil) - netdb = ndbopen(0); - - /* bad responses make them disable the fob, avoid silly checks */ - if(strlen(response) < 4 || strpbrk(response,"abcdefABCDEF") != nil) - goto out; - - /* get radius secret */ - radiussecret = ndbgetvalue(db, &s, "radius", "lra-radius", "secret", &t); - if(radiussecret == nil){ - syslog(0, AUTHLOG, "secureidcheck: nil radius secret: %r"); - goto out; - } - - /* translate user name if we have to */ - strcpy(ruser, user); - for(nt = t; nt; nt = nt->entry){ - if(strcmp(nt->attr, "uid") == 0 && strcmp(nt->val, user) == 0) - for(tt = nt->line; tt != nt; tt = tt->line) - if(strcmp(tt->attr, "rid") == 0){ - strcpy(ruser, tt->val); - break; - } - } - ndbfree(t); - - u[0] = fastrand(); - u[1] = fastrand(); - u[2] = fastrand(); - u[3] = fastrand(); - req = newRequest((uchar*)u); - if(req == nil) - goto out; - shared.s = (uchar*)radiussecret; - shared.len = strlen(radiussecret); - ip = getipv4addr(); - if(ip == nil){ - syslog(0, AUTHLOG, "no interfaces: %r\n"); - goto out; - } - if(setAttribute(req, R_NASIPAddress, ip + IPv4off, 4) < 0) - goto out; - - if(setAttribute(req, R_UserName, (uchar*)ruser, strlen(ruser)) < 0) - goto out; - pass.s = (uchar*)response; - pass.len = strlen(response); - hide(&shared, req->authenticator, &pass, x); - if(setAttribute(req, R_UserPassword, x, 16) < 0) - goto out; - - t = ndbsearch(netdb, &s, "sys", "lra-radius"); - if(t == nil){ - syslog(0, AUTHLOG, "secureidcheck: nil radius sys search: %r\n"); - goto out; - } - for(nt = t; nt; nt = nt->entry){ - if(strcmp(nt->attr, "ip") != 0) - continue; - - snprint(dest,sizeof dest,"udp!%s!oradius", nt->val); - resp = rpc(dest, &shared, req); - if(resp == nil){ - syslog(0, AUTHLOG, "%s nil response", dest); - continue; - } - if(resp->ID != req->ID){ - syslog(0, AUTHLOG, "%s mismatched ID req=%d resp=%d", - dest, req->ID, resp->ID); - freePacket(resp); - resp = nil; - continue; - } - - switch(resp->code){ - case R_AccessAccept: - syslog(0, AUTHLOG, "%s accepted ruser=%s", dest, ruser); - rv = nil; - break; - case R_AccessReject: - syslog(0, AUTHLOG, "%s rejected ruser=%s %s", dest, ruser, replymsg(resp)); - rv = "secureid failed"; - break; - case R_AccessChallenge: - syslog(0, AUTHLOG, "%s challenge ruser=%s %s", dest, ruser, replymsg(resp)); - rv = "secureid out of sync"; - break; - default: - syslog(0, AUTHLOG, "%s code=%d ruser=%s %s", dest, resp->code, ruser, replymsg(resp)); - break; - } - break; // we have a proper reply, no need to ask again - } - ndbfree(t); - free(radiussecret); -out: - freePacket(req); - freePacket(resp); - return rv; -} diff --git a/src/cmd/secstore/secuser.c b/src/cmd/secstore/secuser.c deleted file mode 100644 index 31ba184b..00000000 --- a/src/cmd/secstore/secuser.c +++ /dev/null @@ -1,244 +0,0 @@ -#include <u.h> -#include <libc.h> -#include <mp.h> -#include <libsec.h> -#include "SConn.h" -#include "secstore.h" - -int verbose; - -static void userinput(char *, int); -char *SECSTORE_DIR; - -static void -ensure_exists(char *f, ulong perm) -{ - int fd; - - if(access(f, AEXIST) >= 0) - return; - if(verbose) - fprint(2,"first time setup for secstore: create %s %lo\n", f, perm); - fd = create(f, OREAD, perm); - if(fd < 0){ - fprint(2, "unable to create %s\n", f); - exits("secstored directories"); - } - close(fd); -} - - -int -main(int argc, char **argv) -{ - int isnew; - char *id, buf[Maxmsg], home[Maxmsg], prompt[100], *hexHi; - char *pass, *passck; - long expsecs; - mpint *H = mpnew(0), *Hi = mpnew(0); - PW *pw; - Tm *tm; - - SECSTORE_DIR = unsharp("#9/secstore"); - - ARGBEGIN{ - case 'v': - verbose++; - break; - }ARGEND; - if(argc!=1){ - print("usage: secuser [-v] <user>\n"); - exits("usage"); - } - - ensure_exists(SECSTORE_DIR, DMDIR|0755L); - snprint(home, sizeof(home), "%s/who", SECSTORE_DIR); - ensure_exists(home, DMDIR|0755L); - snprint(home, sizeof(home), "%s/store", SECSTORE_DIR); - ensure_exists(home, DMDIR|0700L); - - id = argv[0]; - if(verbose) - fprint(2,"secuser %s\n", id); - if((pw = getPW(id,1)) == nil){ - isnew = 1; - print("new account (because %s/%s %r)\n", SECSTORE_DIR, id); - pw = emalloc(sizeof(*pw)); - pw->id = estrdup(id); - snprint(home, sizeof(home), "%s/store/%s", SECSTORE_DIR, id); - if(access(home, AEXIST) == 0){ - print("new user, but directory %s already exists\n", home); - exits(home); - } - }else{ - isnew = 0; - } - - /* get main password for id */ - for(;;){ - if(isnew) - snprint(prompt, sizeof(prompt), "%s password", id); - else - snprint(prompt, sizeof(prompt), "%s password [default = don't change]", id); - pass = readcons(prompt, nil, 1); - if(pass == nil){ - print("getpass failed\n"); - exits("getpass failed"); - } - if(verbose) - print("%ld characters\n", strlen(pass)); - if(pass[0] == '\0' && isnew == 0) - break; - if(strlen(pass) >= 7) - break; - print("password must be at least 7 characters\n"); - } - - if(pass[0] != '\0'){ - snprint(prompt, sizeof(prompt), "retype password"); - if(verbose) - print("confirming...\n"); - passck = readcons(prompt, nil, 1); - if(passck == nil){ - print("getpass failed\n"); - exits("getpass failed"); - } - if(strcmp(pass, passck) != 0){ - print("passwords didn't match\n"); - exits("no match"); - } - memset(passck, 0, strlen(passck)); - free(passck); - hexHi = PAK_Hi(id, pass, H, Hi); - memset(pass, 0, strlen(pass)); - free(pass); - free(hexHi); - mpfree(H); - pw->Hi = Hi; - } - - /* get expiration time (midnight of date specified) */ - if(isnew) - expsecs = time(0) + 365*24*60*60; - else - expsecs = pw->expire; - - for(;;){ - tm = localtime(expsecs); - print("expires [DDMMYYYY, default = %2.2d%2.2d%4.4d]: ", - tm->mday, tm->mon, tm->year+1900); - userinput(buf, sizeof(buf)); - if(strlen(buf) == 0) - break; - if(strlen(buf) != 8){ - print("!bad date format: %s\n", buf); - continue; - } - tm->mday = (buf[0]-'0')*10 + (buf[1]-'0'); - if(tm->mday > 31 || tm->mday < 1){ - print("!bad day of month: %d\n", tm->mday); - continue; - } - tm->mon = (buf[2]-'0')*10 + (buf[3]-'0') - 1; - if(tm->mon > 11 || tm->mday < 0){ - print("!bad month: %d\n", tm->mon + 1); - continue; - } - tm->year = atoi(buf+4) - 1900; - if(tm->year < 70){ - print("!bad year: %d\n", tm->year + 1900); - continue; - } - tm->sec = 59; - tm->min = 59; - tm->hour = 23; - tm->yday = 0; - expsecs = tm2sec(tm); - break; - } - pw->expire = expsecs; - - /* failed logins */ - if(pw->failed != 0 ) - print("clearing %d failed login attempts\n", pw->failed); - pw->failed = 0; - - /* status bits */ - if(isnew) - pw->status = Enabled; - for(;;){ - print("Enabled or Disabled [default %s]: ", - (pw->status & Enabled) ? "Enabled" : "Disabled" ); - userinput(buf, sizeof(buf)); - if(strlen(buf) == 0) - break; - if(buf[0]=='E' || buf[0]=='e'){ - pw->status |= Enabled; - break; - } - if(buf[0]=='D' || buf[0]=='d'){ - pw->status = pw->status & ~Enabled; - break; - } - } - for(;;){ - print("require STA? [default %s]: ", - (pw->status & STA) ? "yes" : "no" ); - userinput(buf, sizeof(buf)); - if(strlen(buf) == 0) - break; - if(buf[0]=='Y' || buf[0]=='y'){ - pw->status |= STA; - break; - } - if(buf[0]=='N' || buf[0]=='n'){ - pw->status = pw->status & ~STA; - break; - } - } - - /* free form field */ - if(isnew) - pw->other = nil; - print("comments [default = %s]: ", (pw->other == nil) ? "" : pw->other); - userinput(buf, 72); /* 72 comes from password.h */ - if(buf[0]) - if((pw->other = strdup(buf)) == nil) - sysfatal("strdup"); - - syslog(0, LOG, "CHANGELOGIN for '%s'", pw->id); - if(putPW(pw) < 0){ - print("error writing entry: %r\n"); - exits("can't write password file"); - }else{ - print("change written\n"); - if(isnew && create(home, OREAD, DMDIR | 0775L) < 0){ - print("unable to create %s: %r\n", home); - exits(home); - } - } - - exits(""); - return 1; /* keep other compilers happy */ -} - - -static void -userinput(char *buf, int blen) -{ - int n; - - while(1){ - n = read(0, buf, blen); - if(n<=0) - exits("read error"); - if(buf[n-1]=='\n'){ - buf[n-1] = '\0'; - return; - } - buf += n; blen -= n; - if(blen<=0) - exits("input too large"); - } -} - diff --git a/src/cmd/secstore/util.c b/src/cmd/secstore/util.c deleted file mode 100644 index ebbb12df..00000000 --- a/src/cmd/secstore/util.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <u.h> -#include <libc.h> - -void * -emalloc(ulong n) -{ - void *p = malloc(n); - if(p == nil) - sysfatal("emalloc"); - memset(p, 0, n); - return p; -} - -void * -erealloc(void *p, ulong n) -{ - if ((p = realloc(p, n)) == nil) - sysfatal("erealloc"); - return p; -} - -char * -estrdup(char *s) -{ - if ((s = strdup(s)) == nil) - sysfatal("estrdup"); - return s; -} |