commit 0f8ec41b0ae522b73085fa1662461e6351ba7e54 from: rsc date: Sun Feb 13 05:58:45 2005 UTC moving to auth commit - 7637c81af02c49ef508b946dfdec39f757a658d4 commit + 0f8ec41b0ae522b73085fa1662461e6351ba7e54 blob - 7aed917f52a27e4f384673158244d293cfba9f4d (mode 644) blob + /dev/null --- src/cmd/factotum/BUGS +++ /dev/null @@ -1 +0,0 @@ -key, delkey, wipe should be in ctl not rpc. blob - f555c39484e63dff1bf88b6119d649d7544763b6 (mode 644) blob + /dev/null --- src/cmd/factotum/apop.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * APOP, CRAM - MD5 challenge/response authentication - * - * The client does not authenticate the server, hence no CAI. - * - * Protocol: - * - * S -> C: random@domain - * C -> S: hex-response - * S -> C: ok - * - * Note that this is the protocol between factotum and the local - * program, not between the two factotums. The information - * exchanged here is wrapped in the APOP protocol by the local - * programs. - * - * If S sends "bad [msg]" instead of "ok", that is a hint that the key is bad. - * The protocol goes back to "C -> S: user". - */ - -#include "std.h" -#include "dat.h" - -static int -apopcheck(Key *k) -{ - if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){ - werrstr("need user and !password attributes"); - return -1; - } - return 0; -} - -static int -apopclient(Conv *c) -{ - char *chal, *pw, *res; - int astype, nchal, npw, ntry, ret; - uchar resp[MD5dlen]; - Attr *attr; - DigestState *ds; - Key *k; - - chal = nil; - k = nil; - res = nil; - ret = -1; - attr = c->attr; - - if(c->proto == &apop) - astype = AuthApop; - else if(c->proto == &cram) - astype = AuthCram; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - k = keyfetch(c, "%A %s", attr, c->proto->keyprompt); - if(k == nil) - goto out; - - c->state = "read challenge"; - if((nchal = convreadm(c, &chal)) < 0) - goto out; - - for(ntry=1;; ntry++){ - if(c->attr != attr) - freeattr(c->attr); - c->attr = addattrs(copyattr(attr), k->attr); - if((pw = strfindattr(k->privattr, "!password")) == nil){ - werrstr("key has no password (cannot happen?)"); - goto out; - } - npw = strlen(pw); - - switch(astype){ - case AuthApop: - ds = md5((uchar*)chal, nchal, nil, nil); - md5((uchar*)pw, npw, resp, ds); - break; - case AuthCram: - hmac_md5((uchar*)chal, nchal, (uchar*)pw, npw, resp, nil); - break; - } - - /* C->S: APOP user hex-response\n */ - if(ntry == 1) - c->state = "write user"; - else{ - sprint(c->statebuf, "write user (auth attempt #%d)", ntry); - c->state = c->statebuf; - } - if(convprint(c, "%s", strfindattr(k->attr, "user")) < 0) - goto out; - - c->state = "write response"; - if(convprint(c, "%.*H", sizeof resp, resp) < 0) - goto out; - - c->state = "read result"; - if(convreadm(c, &res) < 0) - goto out; - - if(strcmp(res, "ok") == 0) - break; - - if(strncmp(res, "bad ", 4) != 0){ - werrstr("bad result: %s", res); - goto out; - } - - c->state = "replace key"; - if((k = keyreplace(c, k, "%s", res+4)) == nil){ - c->state = "auth failed"; - werrstr("%s", res+4); - goto out; - } - free(res); - res = nil; - } - - werrstr("succeeded"); - ret = 0; - -out: - keyclose(k); - free(chal); - if(c->attr != attr) - freeattr(attr); - return ret; -} - -/* shared with auth dialing routines */ -typedef struct ServerState ServerState; -struct ServerState -{ - int asfd; - Key *k; - Ticketreq tr; - Ticket t; - char *dom; - char *hostid; -}; - -enum -{ - APOPCHALLEN = 128, -}; - -static int apopchal(ServerState*, int, char[APOPCHALLEN]); -static int apopresp(ServerState*, char*, char*); - -static int -apopserver(Conv *c) -{ - char chal[APOPCHALLEN], *user, *resp; - ServerState s; - int astype, ret; - Attr *a; - - ret = -1; - user = nil; - resp = nil; - memset(&s, 0, sizeof s); - s.asfd = -1; - - if(c->proto == &apop) - astype = AuthApop; - else if(c->proto == &cram) - astype = AuthCram; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - if((s.k = plan9authkey(c->attr)) == nil) - goto out; - - a = copyattr(s.k->attr); - a = delattr(a, "proto"); - c->attr = addattrs(c->attr, a); - freeattr(a); - - c->state = "authdial"; - s.hostid = strfindattr(s.k->attr, "user"); - s.dom = strfindattr(s.k->attr, "dom"); - if((s.asfd = xioauthdial(nil, s.dom)) < 0){ - werrstr("authdial %s: %r", s.dom); - goto out; - } - - c->state = "authchal"; - if(apopchal(&s, astype, chal) < 0) - goto out; - - c->state = "write challenge"; - if(convprint(c, "%s", chal) < 0) - goto out; - - for(;;){ - c->state = "read user"; - if(convreadm(c, &user) < 0) - goto out; - - c->state = "read response"; - if(convreadm(c, &resp) < 0) - goto out; - - c->state = "authwrite"; - switch(apopresp(&s, user, resp)){ - case -1: - goto out; - case 0: - c->state = "write status"; - if(convprint(c, "bad authentication failed") < 0) - goto out; - break; - case 1: - c->state = "write status"; - if(convprint(c, "ok") < 0) - goto out; - goto ok; - } - free(user); - free(resp); - user = nil; - resp = nil; - } - -ok: - ret = 0; - c->attr = addcap(c->attr, c->sysuser, &s.t); - -out: - keyclose(s.k); - free(user); - free(resp); -// xioclose(s.asfd); - return ret; -} - -static int -apopchal(ServerState *s, int astype, char chal[APOPCHALLEN]) -{ - char trbuf[TICKREQLEN]; - Ticketreq tr; - - memset(&tr, 0, sizeof tr); - - tr.type = astype; - - if(strlen(s->hostid) >= sizeof tr.hostid){ - werrstr("hostid too long"); - return -1; - } - strcpy(tr.hostid, s->hostid); - - if(strlen(s->dom) >= sizeof tr.authdom){ - werrstr("domain too long"); - return -1; - } - strcpy(tr.authdom, s->dom); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - if(xioasrdresp(s->asfd, chal, APOPCHALLEN) <= 5) - return -1; - - s->tr = tr; - return 0; -} - -static int -apopresp(ServerState *s, char *user, char *resp) -{ - char tabuf[TICKETLEN+AUTHENTLEN]; - char trbuf[TICKREQLEN]; - int len; - Authenticator a; - Ticket t; - Ticketreq tr; - - tr = s->tr; - if(memrandom(tr.chal, CHALLEN) < 0) - return -1; - - if(strlen(user) >= sizeof tr.uid){ - werrstr("uid too long"); - return -1; - } - strcpy(tr.uid, user); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - len = strlen(resp); - if(xiowrite(s->asfd, resp, len) != len) - return -1; - - if(xioasrdresp(s->asfd, tabuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) - return 0; - - convM2T(tabuf, &t, s->k->priv); - if(t.num != AuthTs - || memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ - werrstr("key mismatch with auth server"); - return -1; - } - - convM2A(tabuf+TICKETLEN, &a, t.key); - if(a.num != AuthAc - || memcmp(a.chal, tr.chal, sizeof a.chal) != 0 - || a.id != 0){ - werrstr("key2 mismatch with auth server"); - return -1; - } - - s->t = t; - return 1; -} - -static Role -apoproles[] = -{ - "client", apopclient, - "server", apopserver, - 0 -}; - -Proto apop = { -.name= "apop", -.roles= apoproles, -.checkkey= apopcheck, -.keyprompt= "user? !password?", -}; - -Proto cram = { -.name= "cram", -.roles= apoproles, -.checkkey= apopcheck, -.keyprompt= "user? !password?", -}; blob - b92e96a02a284f92a80b874fd22f6baadb087fc6 (mode 644) blob + /dev/null --- src/cmd/factotum/attr.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "std.h" -#include "dat.h" - -Attr* -addattr(Attr *a, char *fmt, ...) -{ - char buf[1024]; - va_list arg; - Attr *b; - - va_start(arg, fmt); - vseprint(buf, buf+sizeof buf, fmt, arg); - va_end(arg); - b = _parseattr(buf); - a = addattrs(a, b); - setmalloctag(a, getcallerpc(&a)); - _freeattr(b); - return a; -} - -/* - * add attributes in list b to list a. If any attributes are in - * both lists, replace those in a by those in b. - */ -Attr* -addattrs(Attr *a, Attr *b) -{ - int found; - Attr **l, *aa; - - for(; b; b=b->next){ - switch(b->type){ - case AttrNameval: - for(l=&a; *l; ){ - if(strcmp((*l)->name, b->name) != 0){ - l=&(*l)->next; - continue; - } - aa = *l; - *l = aa->next; - aa->next = nil; - freeattr(aa); - } - *l = mkattr(AttrNameval, b->name, b->val, nil); - break; - case AttrQuery: - found = 0; - for(l=&a; *l; l=&(*l)->next) - if((*l)->type==AttrNameval && strcmp((*l)->name, b->name) == 0) - found++; - if(!found) - *l = mkattr(AttrQuery, b->name, b->val, nil); - break; - } - } - return a; -} - -void -setmalloctaghere(void *v) -{ - setmalloctag(v, getcallerpc(&v)); -} - -Attr* -sortattr(Attr *a) -{ - int i; - Attr *anext, *a0, *a1, **l; - - if(a == nil || a->next == nil) - return a; - - /* cut list in halves */ - a0 = nil; - a1 = nil; - i = 0; - for(; a; a=anext){ - anext = a->next; - if(i++%2){ - a->next = a0; - a0 = a; - }else{ - a->next = a1; - a1 = a; - } - } - - /* sort */ - a0 = sortattr(a0); - a1 = sortattr(a1); - - /* merge */ - l = &a; - while(a0 || a1){ - if(a1==nil){ - anext = a0; - a0 = a0->next; - }else if(a0==nil){ - anext = a1; - a1 = a1->next; - }else if(strcmp(a0->name, a1->name) < 0){ - anext = a0; - a0 = a0->next; - }else{ - anext = a1; - a1 = a1->next; - } - *l = anext; - l = &(*l)->next; - } - *l = nil; - return a; -} - -int -attrnamefmt(Fmt *fmt) -{ - char *b, buf[1024], *ebuf; - Attr *a; - - ebuf = buf+sizeof buf; - b = buf; - strcpy(buf, " "); - for(a=va_arg(fmt->args, Attr*); a; a=a->next){ - if(a->name == nil) - continue; - b = seprint(b, ebuf, " %q?", a->name); - } - return fmtstrcpy(fmt, buf+1); -} - -/* -static int -hasqueries(Attr *a) -{ - for(; a; a=a->next) - if(a->type == AttrQuery) - return 1; - return 0; -} -*/ - -char *ignored[] = { - "role", - "disabled", -}; - -static int -ignoreattr(char *s) -{ - int i; - - for(i=0; inext, name)) - if(strcmp(a->val, val) == 0) - return 1; - for(a=_findattr(a1, name); a; a=_findattr(a->next, name)) - if(strcmp(a->val, val) == 0) - return 1; - return 0; -} - -int -matchattr(Attr *pat, Attr *a0, Attr *a1) -{ - int type; - - for(; pat; pat=pat->next){ - type = pat->type; - if(ignoreattr(pat->name)) - type = AttrDefault; - switch(type){ - case AttrQuery: /* name=something be present */ - if(!hasname(a0, a1, pat->name)) - return 0; - break; - case AttrNameval: /* name=val must be present */ - if(!hasnameval(a0, a1, pat->name, pat->val)) - return 0; - break; - case AttrDefault: /* name=val must be present if name=anything is present */ - if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val)) - return 0; - break; - } - } - return 1; -} - -Attr* -parseattrfmtv(char *fmt, va_list arg) -{ - char *s; - Attr *a; - - s = vsmprint(fmt, arg); - if(s == nil) - sysfatal("vsmprint: out of memory"); - a = parseattr(s); - free(s); - return a; -} - -Attr* -parseattrfmt(char *fmt, ...) -{ - va_list arg; - Attr *a; - - va_start(arg, fmt); - a = parseattrfmtv(fmt, arg); - va_end(arg); - return a; -} blob - debf8d0ec9de804352725313b3d654e2960f5173 (mode 644) blob + /dev/null --- src/cmd/factotum/chap.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * CHAP, MSCHAP - * - * The client does not authenticate the server, hence no CAI - * - * Protocol: - * - * S -> C: random 8-byte challenge - * C -> S: user in UTF-8 - * C -> S: Chapreply or MSchapreply structure - * S -> C: ok or 'bad why' - * - * The chap protocol requires the client to give it id=%d, the id of - * the PPP message containing the challenge, which is used - * as part of the response. Because the client protocol is message-id - * specific, there is no point in looping to try multiple keys. - * - * The MS chap protocol actually uses two different hashes, an - * older insecure one called the LM (Lan Manager) hash, and a newer - * more secure one called the NT hash. By default we send back only - * the NT hash, because the LM hash can help an eavesdropper run - * a brute force attack. If the key has an lm attribute, then we send only the - * LM hash. - */ - -#include "std.h" -#include "dat.h" - -enum { - ChapChallen = 8, - - MShashlen = 16, - MSchallen = 8, - MSresplen = 24, -}; - -static int -chapcheck(Key *k) -{ - if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){ - werrstr("need user and !password attributes"); - return -1; - } - return 0; -} - -static void -nthash(uchar hash[MShashlen], char *passwd) -{ - uchar buf[512]; - int i; - - for(i=0; *passwd && i= 'a' && buf[i] <= 'z') - buf[i] += 'A' - 'a'; - - memset(hash, 0, 16); - memcpy(hash, stdtext, 8); - memcpy(hash+8, stdtext, 8); - - desencrypt(hash, buf); - desencrypt(hash+8, buf+7); -} - -static void -mschalresp(uchar resp[MSresplen], uchar hash[MShashlen], uchar chal[MSchallen]) -{ - int i; - uchar buf[21]; - - memset(buf, 0, sizeof(buf)); - memcpy(buf, hash, MShashlen); - - for(i=0; i<3; i++) { - memmove(resp+i*MSchallen, chal, MSchallen); - desencrypt(resp+i*MSchallen, buf+i*7); - } -} - -static int -chapclient(Conv *c) -{ - int id, astype, nchal, npw, ret; - uchar *chal; - char *s, *pw, *user, *res; - Attr *attr; - Key *k; - Chapreply cr; - MSchapreply mscr; - DigestState *ds; - - ret = -1; - chal = nil; - k = nil; - attr = c->attr; - - if(c->proto == &chap){ - astype = AuthChap; - s = strfindattr(attr, "id"); - if(s == nil || *s == 0){ - werrstr("need id=n attr in start message"); - goto out; - } - id = strtol(s, &s, 10); - if(*s != 0 || id < 0 || id >= 256){ - werrstr("bad id=n attr in start message"); - goto out; - } - cr.id = id; - }else if(c->proto == &mschap) - astype = AuthMSchap; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - k = keyfetch(c, "%A %s", attr, c->proto->keyprompt); - if(k == nil) - goto out; - - c->attr = addattrs(copyattr(attr), k->attr); - - c->state = "read challenge"; - if((nchal = convreadm(c, (char**)(void*)&chal)) < 0) - goto out; - if(astype == AuthMSchap && nchal != MSchallen) - c->state = "write user"; - if((user = strfindattr(k->attr, "user")) == nil){ - werrstr("key has no user (cannot happen?)"); - goto out; - } - if(convprint(c, "%s", user) < 0) - goto out; - - c->state = "write response"; - if((pw = strfindattr(k->privattr, "!password")) == nil){ - werrstr("key has no password (cannot happen?)"); - goto out; - } - npw = strlen(pw); - - if(astype == AuthChap){ - ds = md5(&cr.id, 1, 0, 0); - md5((uchar*)pw, npw, 0, ds); - md5(chal, nchal, (uchar*)cr.resp, ds); - if(convwrite(c, &cr, sizeof cr) < 0) - goto out; - }else{ - uchar hash[MShashlen]; - - memset(&mscr, 0, sizeof mscr); - if(strfindattr(k->attr, "lm")){ - lmhash(hash, pw); - mschalresp((uchar*)mscr.LMresp, hash, chal); - }else{ - nthash(hash, pw); - mschalresp((uchar*)mscr.NTresp, hash, chal); - } - if(convwrite(c, &mscr, sizeof mscr) < 0) - goto out; - } - - c->state = "read result"; - if(convreadm(c, &res) < 0) - goto out; - if(strcmp(res, "ok") == 0){ - ret = 0; - werrstr("succeeded"); - goto out; - } - if(strncmp(res, "bad ", 4) != 0){ - werrstr("bad result: %s", res); - goto out; - } - - c->state = "replace key"; - keyevict(c, k, "%s", res+4); - werrstr("%s", res+4); - -out: - free(res); - keyclose(k); - free(chal); - if(c->attr != attr) - freeattr(attr); - return ret; -} - -/* shared with auth dialing routines */ -typedef struct ServerState ServerState; -struct ServerState -{ - int asfd; - Key *k; - Ticketreq tr; - Ticket t; - char *dom; - char *hostid; -}; - -static int chapchal(ServerState*, int, char[ChapChallen]); -static int chapresp(ServerState*, char*, char*); - -static int -chapserver(Conv *c) -{ - char chal[ChapChallen], *user, *resp; - ServerState s; - int astype, ret; - Attr *a; - - ret = -1; - user = nil; - resp = nil; - memset(&s, 0, sizeof s); - s.asfd = -1; - - if(c->proto == &chap) - astype = AuthChap; - else if(c->proto == &mschap) - astype = AuthMSchap; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - if((s.k = plan9authkey(c->attr)) == nil) - goto out; - - a = copyattr(s.k->attr); - a = delattr(a, "proto"); - c->attr = addattrs(c->attr, a); - freeattr(a); - - c->state = "authdial"; - s.hostid = strfindattr(s.k->attr, "user"); - s.dom = strfindattr(s.k->attr, "dom"); - if((s.asfd = xioauthdial(nil, s.dom)) < 0){ - werrstr("authdial %s: %r", s.dom); - goto out; - } - - c->state = "authchal"; - if(chapchal(&s, astype, chal) < 0) - goto out; - - c->state = "write challenge"; - if(convprint(c, "%s", chal) < 0) - goto out; - - c->state = "read user"; - if(convreadm(c, &user) < 0) - goto out; - - c->state = "read response"; - if(convreadm(c, &resp) < 0) - goto out; - - c->state = "authwrite"; - switch(chapresp(&s, user, resp)){ - default: - fprint(2, "factotum: bad result from chapresp\n"); - goto out; - case -1: - goto out; - case 0: - c->state = "write status"; - if(convprint(c, "bad authentication failed") < 0) - goto out; - goto out; - - case 1: - c->state = "write status"; - if(convprint(c, "ok") < 0) - goto out; - goto ok; - } - -ok: - ret = 0; - c->attr = addcap(c->attr, c->sysuser, &s.t); - -out: - keyclose(s.k); - free(user); - free(resp); -// xioclose(s.asfd); - return ret; -} - -static int -chapchal(ServerState *s, int astype, char chal[ChapChallen]) -{ - char trbuf[TICKREQLEN]; - Ticketreq tr; - - memset(&tr, 0, sizeof tr); - - tr.type = astype; - - if(strlen(s->hostid) >= sizeof tr.hostid){ - werrstr("hostid too long"); - return -1; - } - strcpy(tr.hostid, s->hostid); - - if(strlen(s->dom) >= sizeof tr.authdom){ - werrstr("domain too long"); - return -1; - } - strcpy(tr.authdom, s->dom); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - if(xioasrdresp(s->asfd, chal, ChapChallen) <= 5) - return -1; - - s->tr = tr; - return 0; -} - -static int -chapresp(ServerState *s, char *user, char *resp) -{ - char tabuf[TICKETLEN+AUTHENTLEN]; - char trbuf[TICKREQLEN]; - int len; - Authenticator a; - Ticket t; - Ticketreq tr; - - tr = s->tr; - if(memrandom(tr.chal, CHALLEN) < 0) - return -1; - - if(strlen(user) >= sizeof tr.uid){ - werrstr("uid too long"); - return -1; - } - strcpy(tr.uid, user); - - convTR2M(&tr, trbuf); - if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return -1; - - len = strlen(resp); - if(xiowrite(s->asfd, resp, len) != len) - return -1; - - if(xioasrdresp(s->asfd, tabuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) - return 0; - - convM2T(tabuf, &t, s->k->priv); - if(t.num != AuthTs - || memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){ - werrstr("key mismatch with auth server"); - return -1; - } - - convM2A(tabuf+TICKETLEN, &a, t.key); - if(a.num != AuthAc - || memcmp(a.chal, tr.chal, sizeof a.chal) != 0 - || a.id != 0){ - werrstr("key2 mismatch with auth server"); - return -1; - } - - s->t = t; - return 1; -} - -static Role -chaproles[] = -{ - "client", chapclient, - "server", chapserver, - 0 -}; - -Proto chap = { -.name= "chap", -.roles= chaproles, -.checkkey= chapcheck, -.keyprompt= "user? !password?", -}; - -Proto mschap = { -.name= "mschap", -.roles= chaproles, -.checkkey= chapcheck, -.keyprompt= "user? !password?", -}; - blob - 8f49245043b90a6fed49bd1f90336db5d1ac1b16 (mode 644) blob + /dev/null --- src/cmd/factotum/confirm.c +++ /dev/null @@ -1,139 +0,0 @@ -#include "std.h" -#include "dat.h" - -Logbuf confbuf; - -void -confirmread(Req *r) -{ - lbread(&confbuf, r); -} - -void -confirmflush(Req *r) -{ - lbflush(&confbuf, r); -} - -int -confirmwrite(char *s) -{ - char *t, *ans; - int allow; - ulong tag; - Attr *a; - Conv *c; - - a = _parseattr(s); - if(a == nil){ - werrstr("bad attr"); - return -1; - } - if((t = _strfindattr(a, "tag")) == nil){ - werrstr("no tag"); - return -1; - } - tag = strtoul(t, 0, 0); - if((ans = _strfindattr(a, "answer")) == nil){ - werrstr("no answer"); - return -1; - } - if(strcmp(ans, "yes") == 0) - allow = 1; - else if(strcmp(ans, "no") == 0) - allow = 0; - else{ - werrstr("bad answer"); - return -1; - } - for(c=conv; c; c=c->next){ - if(tag == c->tag){ - nbsendul(c->keywait, allow); - break; - } - } - if(c == nil){ - werrstr("tag not found"); - return -1; - } - return 0; -} - -int -confirmkey(Conv *c, Key *k) -{ - if(*confirminuse == 0) - return -1; - - lbappend(&confbuf, "confirm tag=%lud %A %N", c->tag, k->attr, k->privattr); - c->state = "keyconfirm"; - return recvul(c->keywait); -} - -Logbuf needkeybuf; - -void -needkeyread(Req *r) -{ - lbread(&needkeybuf, r); -} - -void -needkeyflush(Req *r) -{ - lbflush(&needkeybuf, r); -} - -int -needkeywrite(char *s) -{ - char *t; - ulong tag; - Attr *a; - Conv *c; - - a = _parseattr(s); - if(a == nil){ - werrstr("empty write"); - return -1; - } - if((t = _strfindattr(a, "tag")) == nil){ - werrstr("no tag"); - freeattr(a); - return -1; - } - tag = strtoul(t, 0, 0); - for(c=conv; c; c=c->next) - if(c->tag == tag){ - nbsendul(c->keywait, 0); - break; - } - if(c == nil){ - werrstr("tag not found"); - freeattr(a); - return -1; - } - freeattr(a); - return 0; -} - -int -needkey(Conv *c, Attr *a) -{ - if(c == nil || *needkeyinuse == 0) - return -1; - - lbappend(&needkeybuf, "needkey tag=%lud %A", c->tag, a); - return nbrecvul(c->keywait); -} - -int -badkey(Conv *c, Key *k, char *msg, Attr *a) -{ - if(c == nil || *needkeyinuse == 0) - return -1; - - lbappend(&needkeybuf, "badkey tag=%lud %A %N\n%s\n%A", - c->tag, k->attr, k->privattr, msg, a); - return nbrecvul(c->keywait); -} blob - 862993f9a5d0ba879789de766123e5c1bda715e9 (mode 644) blob + /dev/null --- src/cmd/factotum/conv.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "std.h" -#include "dat.h" - -Conv *conv; - -ulong taggen = 1; - -Conv* -convalloc(char *sysuser) -{ - Conv *c; - - c = mallocz(sizeof(Conv), 1); - if(c == nil) - return nil; - c->ref = 1; - c->tag = taggen++; - c->next = conv; - c->sysuser = estrdup(sysuser); - c->state = "nascent"; - c->rpcwait = chancreate(sizeof(void*), 0); - c->keywait = chancreate(sizeof(void*), 0); - strcpy(c->err, "protocol has not started"); - conv = c; - convreset(c); - return c; -} - -void -convreset(Conv *c) -{ - if(c->ref != 1){ - c->hangup = 1; - nbsendp(c->rpcwait, 0); - while(c->ref > 1) - yield(); - c->hangup = 0; - } - c->state = "nascent"; - c->err[0] = '\0'; - freeattr(c->attr); - c->attr = nil; - c->proto = nil; - c->rpc.op = 0; - c->active = 0; - c->done = 0; - c->hangup = 0; -} - -void -convhangup(Conv *c) -{ - c->hangup = 1; - c->rpc.op = 0; - (*c->kickreply)(c); - nbsendp(c->rpcwait, 0); -} - -void -convclose(Conv *c) -{ - Conv *p; - - if(c == nil) - return; - - if(--c->ref > 0) - return; - - if(c == conv){ - conv = c->next; - goto free; - } - for(p=conv; p && p->next!=c; p=p->next) - ; - if(p == nil){ - print("cannot find conv in list\n"); - return; - } - p->next = c->next; - -free: - c->next = nil; - free(c); -} - -static Rpc* -convgetrpc(Conv *c, int want) -{ - for(;;){ - if(c->hangup){ - werrstr("hangup"); - return nil; - } - if(c->rpc.op == RpcUnknown){ - recvp(c->rpcwait); - if(c->hangup){ - werrstr("hangup"); - return nil; - } - if(c->rpc.op == RpcUnknown) - continue; - } - if(want < 0 || c->rpc.op == want) - return &c->rpc; - rpcrespond(c, "phase in state '%s' want '%s'", c->state, rpcname[want]); - } - return nil; /* not reached */ -} - -/* read until the done function tells us that's enough */ -int -convreadfn(Conv *c, int (*done)(void*, int), char **ps) -{ - int n; - Rpc *r; - char *s; - - for(;;){ - r = convgetrpc(c, RpcWrite); - if(r == nil) - return -1; - n = (*done)(r->data, r->count); - if(n == r->count) - break; - rpcrespond(c, "toosmall %d", n); - } - - s = emalloc(r->count+1); - memmove(s, r->data, r->count); - s[r->count] = 0; - *ps = s; - rpcrespond(c, "ok"); - return r->count; -} - -/* - * read until we get a non-zero write. assumes remote side - * knows something about the protocol (is not auth_proxy). - * the remote side typically won't bother with the zero-length - * write to find out the length -- the loop is there only so the - * test program can call auth_proxy on both sides of a pipe - * to play a conversation. - */ -int -convreadm(Conv *c, char **ps) -{ - char *s; - Rpc *r; - - for(;;){ - r = convgetrpc(c, RpcWrite); - if(r == nil) - return -1; - if(r->count > 0) - break; - rpcrespond(c, "toosmall %d", AuthRpcMax); - } - s = emalloc(r->count+1); - memmove(s, r->data, r->count); - s[r->count] = 0; - *ps = s; - rpcrespond(c, "ok"); - return r->count; -} - -/* read exactly count bytes */ -int -convread(Conv *c, void *data, int count) -{ - Rpc *r; - - for(;;){ - r = convgetrpc(c, RpcWrite); - if(r == nil) - return -1; - if(r->count == count) - break; - if(r->count < count) - rpcrespond(c, "toosmall %d", count); - else - rpcrespond(c, "error too much data; want %d got %d", count, r->count); - } - memmove(data, r->data, count); - rpcrespond(c, "ok"); - return 0; -} - -/* write exactly count bytes */ -int -convwrite(Conv *c, void *data, int count) -{ - Rpc *r; - - for(;;){ - r = convgetrpc(c, RpcRead); - if(r == nil) - return -1; - break; - } - rpcrespondn(c, "ok", data, count); - return 0; -} - -/* print to the conversation */ -int -convprint(Conv *c, char *fmt, ...) -{ - char *s; - va_list arg; - int ret; - - va_start(arg, fmt); - s = vsmprint(fmt, arg); - va_end(arg); - if(s == nil) - return -1; - ret = convwrite(c, s, strlen(s)); - free(s); - return ret; -} - -/* ask for a key */ -int -convneedkey(Conv *c, Attr *a) -{ - /* - * Piggyback key requests in the usual RPC channel. - * Wait for the next RPC and then send a key request - * in response. The keys get added out-of-band (via the - * ctl file), so assume the key has been added when the - * next request comes in. - */ - if(convgetrpc(c, -1) == nil) - return -1; - rpcrespond(c, "needkey %A", a); - if(convgetrpc(c, -1) == nil) - return -1; - return 0; -} - -/* ask for a replacement for a bad key*/ -int -convbadkey(Conv *c, Key *k, char *msg, Attr *a) -{ - if(convgetrpc(c, -1) == nil) - return -1; - rpcrespond(c, "badkey %A %N\n%s\n%A", - k->attr, k->privattr, msg, a); - if(convgetrpc(c, -1) == nil) - return -1; - return 0; -} - blob - da8280ada929d6305234c49dc6c57fadea6876e7 (mode 644) blob + /dev/null --- src/cmd/factotum/cpu.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * cpu.c - Make a connection to a cpu server - * - * Invoked by listen as 'cpu -R | -N service net netdir' - * by users as 'cpu [-h system] [-c cmd args ...]' - */ - -#include -#include -#include -#include -#include -#include - -#define Maxfdata 8192 - -void remoteside(int); -void fatal(int, char*, ...); -void lclnoteproc(int); -void rmtnoteproc(void); -void catcher(void*, char*); -void usage(void); -void writestr(int, char*, char*, int); -int readstr(int, char*, int); -char *rexcall(int*, char*, char*); -int setamalg(char*); - -int notechan; -char system[32]; -int cflag; -int hflag; -int dbg; -char *user; - -char *srvname = "ncpu"; -char *exportfs = "/bin/exportfs"; -char *ealgs = "rc4_256 sha1"; - -/* message size for exportfs; may be larger so we can do big graphics in CPU window */ -int msgsize = 8192+IOHDRSZ; - -/* authentication mechanisms */ -static int netkeyauth(int); -static int netkeysrvauth(int, char*); -static int p9auth(int); -static int srvp9auth(int, char*); -static int noauth(int); -static int srvnoauth(int, char*); - -typedef struct AuthMethod AuthMethod; -struct AuthMethod { - char *name; /* name of method */ - int (*cf)(int); /* client side authentication */ - int (*sf)(int, char*); /* server side authentication */ -} authmethod[] = -{ - { "p9", p9auth, srvp9auth,}, - { "netkey", netkeyauth, netkeysrvauth,}, -// { "none", noauth, srvnoauth,}, - { nil, nil} -}; -AuthMethod *am = authmethod; /* default is p9 */ - -char *p9authproto = "p9any"; - -int setam(char*); - -void -usage(void) -{ - fprint(2, "usage: cpu [-h system] [-a authmethod] [-e 'crypt hash'] [-c cmd args ...]\n"); - exits("usage"); -} -int fdd; - -void -main(int argc, char **argv) -{ - char dat[128], buf[128], cmd[128], *p, *err; - int fd, ms, kms, data; - - /* see if we should use a larger message size */ - fd = open("/dev/draw", OREAD); - if(fd > 0){ - ms = iounit(fd); - if(ms != 0 && ms < ms+IOHDRSZ) - msgsize = ms+IOHDRSZ; - close(fd); - } - kms = kiounit(); - if(msgsize > kms-IOHDRSZ-100) /* 100 for network packets, etc. */ - msgsize = kms-IOHDRSZ-100; - - user = getuser(); - if(user == nil) - fatal(1, "can't read user name"); - ARGBEGIN{ - case 'a': - p = EARGF(usage()); - if(setam(p) < 0) - fatal(0, "unknown auth method %s", p); - break; - case 'e': - ealgs = EARGF(usage()); - if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) - ealgs = nil; - break; - case 'd': - dbg++; - break; - case 'f': - /* ignored but accepted for compatibility */ - break; - case 'O': - p9authproto = "p9sk2"; - remoteside(1); /* From listen */ - break; - case 'R': /* From listen */ - remoteside(0); - break; - case 'h': - hflag++; - p = EARGF(usage()); - strcpy(system, p); - break; - case 'c': - cflag++; - cmd[0] = '!'; - cmd[1] = '\0'; - while(p = ARGF()) { - strcat(cmd, " "); - strcat(cmd, p); - } - break; - case 'o': - p9authproto = "p9sk2"; - srvname = "cpu"; - break; - case 'u': - user = EARGF(usage()); - break; - default: - usage(); - }ARGEND; - - - if(argc != 0) - usage(); - - if(hflag == 0) { - p = getenv("cpu"); - if(p == 0) - fatal(0, "set $cpu"); - strcpy(system, p); - } - - if(err = rexcall(&data, system, srvname)) - fatal(1, "%s: %s", err, system); - - /* Tell the remote side the command to execute and where our working directory is */ - if(cflag) - writestr(data, cmd, "command", 0); - if(getwd(dat, sizeof(dat)) == 0) - writestr(data, "NO", "dir", 0); - else - writestr(data, dat, "dir", 0); - - /* start up a process to pass along notes */ - lclnoteproc(data); - - /* - * Wait for the other end to execute and start our file service - * of /mnt/term - */ - if(readstr(data, buf, sizeof(buf)) < 0) - fatal(1, "waiting for FS"); - if(strncmp("FS", buf, 2) != 0) { - print("remote cpu: %s", buf); - exits(buf); - } - - /* Begin serving the gnot namespace */ - close(0); - dup(data, 0); - close(data); - sprint(buf, "%d", msgsize); - if(dbg) - execl(exportfs, exportfs, "-dm", buf, 0); - else - execl(exportfs, exportfs, "-m", buf, 0); - fatal(1, "starting exportfs"); -} - -void -fatal(int syserr, char *fmt, ...) -{ - char buf[ERRMAX]; - va_list arg; - - va_start(arg, fmt); - doprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - if(syserr) - fprint(2, "cpu: %s: %r\n", buf); - else - fprint(2, "cpu: %s\n", buf); - exits(buf); -} - -char *negstr = "negotiating authentication method"; - -char bug[256]; - -int -old9p(int fd) -{ - int p[2]; - - if(pipe(p) < 0) - fatal(1, "pipe"); - - switch(rfork(RFPROC|RFFDG|RFNAMEG)) { - case -1: - fatal(1, "rfork srvold9p"); - case 0: - if(fd != 1){ - dup(fd, 1); - close(fd); - } - if(p[0] != 0){ - dup(p[0], 0); - close(p[0]); - } - close(p[1]); - if(0){ - fd = open("/sys/log/cpu", OWRITE); - if(fd != 2){ - dup(fd, 2); - close(fd); - } - execl("/bin/srvold9p", "srvold9p", "-ds", 0); - } else - execl("/bin/srvold9p", "srvold9p", "-s", 0); - fatal(1, "exec srvold9p"); - default: - close(fd); - close(p[0]); - } - return p[1]; -} - -/* Invoked with stdin, stdout and stderr connected to the network connection */ -void -remoteside(int old) -{ - char user[128], home[128], buf[128], xdir[128], cmd[128]; - int i, n, fd, badchdir, gotcmd; - - fd = 0; - - /* negotiate authentication mechanism */ - n = readstr(fd, cmd, sizeof(cmd)); - if(n < 0) - fatal(1, "authenticating"); - if(setamalg(cmd) < 0){ - writestr(fd, "unsupported auth method", nil, 0); - fatal(1, "bad auth method %s", cmd); - } else - writestr(fd, "", "", 1); - - fd = (*am->sf)(fd, user); - if(fd < 0) - fatal(1, "srvauth"); - - /* Set environment values for the user */ - putenv("user", user); - sprint(home, "/usr/%s", user); - putenv("home", home); - - /* Now collect invoking cpu's current directory or possibly a command */ - gotcmd = 0; - if(readstr(fd, xdir, sizeof(xdir)) < 0) - fatal(1, "dir/cmd"); - if(xdir[0] == '!') { - strcpy(cmd, &xdir[1]); - gotcmd = 1; - if(readstr(fd, xdir, sizeof(xdir)) < 0) - fatal(1, "dir"); - } - - /* Establish the new process at the current working directory of the - * gnot */ - badchdir = 0; - if(strcmp(xdir, "NO") == 0) - chdir(home); - else if(chdir(xdir) < 0) { - badchdir = 1; - chdir(home); - } - - /* Start the gnot serving its namespace */ - writestr(fd, "FS", "FS", 0); - writestr(fd, "/", "exportfs dir", 0); - - n = read(fd, buf, sizeof(buf)); - if(n != 2 || buf[0] != 'O' || buf[1] != 'K') - exits("remote tree"); - - if(old) - fd = old9p(fd); - - /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */ - strcpy(buf, VERSION9P); - if(fversion(fd, 64*1024, buf, sizeof buf) < 0) - exits("fversion failed"); - if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") < 0) - exits("mount failed"); - - close(fd); - - /* the remote noteproc uses the mount so it must follow it */ - rmtnoteproc(); - - for(i = 0; i < 3; i++) - close(i); - - if(open("/mnt/term/dev/cons", OREAD) != 0) - exits("open stdin"); - if(open("/mnt/term/dev/cons", OWRITE) != 1) - exits("open stdout"); - dup(1, 2); - - if(badchdir) - print("cpu: failed to chdir to '%s'\n", xdir); - - if(gotcmd) - execl("/bin/rc", "rc", "-lc", cmd, 0); - else - execl("/bin/rc", "rc", "-li", 0); - fatal(1, "exec shell"); -} - -char* -rexcall(int *fd, char *host, char *service) -{ - char *na; - char dir[128]; - char err[ERRMAX]; - char msg[128]; - int n; - - na = netmkaddr(host, 0, service); - if((*fd = dial(na, 0, dir, 0)) < 0) - return "can't dial"; - - /* negotiate authentication mechanism */ - if(ealgs != nil) - snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); - else - snprint(msg, sizeof(msg), "%s", am->name); - writestr(*fd, msg, negstr, 0); - n = readstr(*fd, err, sizeof err); - if(n < 0) - return negstr; - if(*err){ - werrstr(err); - return negstr; - } - - /* authenticate */ - *fd = (*am->cf)(*fd); - if(*fd < 0) - return "can't authenticate"; - return 0; -} - -void -writestr(int fd, char *str, char *thing, int ignore) -{ - int l, n; - - l = strlen(str); - n = write(fd, str, l+1); - if(!ignore && n < 0) - fatal(1, "writing network: %s", thing); -} - -int -readstr(int fd, char *str, int len) -{ - int n; - - while(len) { - n = read(fd, str, 1); - if(n < 0) - return -1; - if(*str == '\0') - return 0; - str++; - len--; - } - return -1; -} - -static int -readln(char *buf, int n) -{ - char *p = buf; - - n--; - while(n > 0){ - if(read(0, p, 1) != 1) - break; - if(*p == '\n' || *p == '\r'){ - *p = 0; - return p-buf; - } - p++; - } - *p = 0; - return p-buf; -} - -/* - * user level challenge/response - */ -static int -netkeyauth(int fd) -{ - char chall[32]; - char resp[32]; - - strcpy(chall, getuser()); - print("user[%s]: ", chall); - if(readln(resp, sizeof(resp)) < 0) - return -1; - if(*resp != 0) - strcpy(chall, resp); - writestr(fd, chall, "challenge/response", 1); - - for(;;){ - if(readstr(fd, chall, sizeof chall) < 0) - break; - if(*chall == 0) - return fd; - print("challenge: %s\nresponse: ", chall); - if(readln(resp, sizeof(resp)) < 0) - break; - writestr(fd, resp, "challenge/response", 1); - } - return -1; -} - -static int -netkeysrvauth(int fd, char *user) -{ - char response[32]; - Chalstate *ch; - int tries; - AuthInfo *ai; - - if(readstr(fd, user, 32) < 0) - return -1; - - ai = nil; - ch = nil; - for(tries = 0; tries < 10; tries++){ - if((ch = auth_challenge("p9cr", user, nil)) == nil) - return -1; - writestr(fd, ch->chal, "challenge", 1); - if(readstr(fd, response, sizeof response) < 0) - return -1; - ch->resp = response; - ch->nresp = strlen(response); - if((ai = auth_response(ch)) != nil) - break; - } - auth_freechal(ch); - if(ai == nil) - return -1; - writestr(fd, "", "challenge", 1); - if(auth_chuid(ai, 0) < 0) - fatal(1, "newns"); - auth_freeAI(ai); - return fd; -} - -static void -mksecret(char *t, uchar *f) -{ - sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", - f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); -} - -/* - * plan9 authentication followed by rc4 encryption - */ -static int -p9auth(int fd) -{ - uchar key[16]; - uchar digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - AuthInfo *ai; - - ai = auth_proxy(fd, auth_getkey, "proto=%q user=%q role=client", p9authproto, user); - if(ai == nil) - return -1; - memmove(key+4, ai->secret, ai->nsecret); - if(ealgs == nil) - return fd; - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i] = rand(); - if(write(fd, key, 4) != 4) - return -1; - if(readn(fd, key+12, 4) != 4) - return -1; - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - /* set up encryption */ - i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); - if(i < 0) - werrstr("can't establish ssl connection: %r"); - return i; -} - -static int -noauth(int fd) -{ - ealgs = nil; - return fd; -} - -static int -srvnoauth(int fd, char *user) -{ - strcpy(user, getuser()); - ealgs = nil; - return fd; -} - -void -loghex(uchar *p, int n) -{ - char buf[100]; - int i; - - for(i = 0; i < n; i++) - sprint(buf+2*i, "%2.2ux", p[i]); - syslog(0, "cpu", buf); -} - -static int -srvp9auth(int fd, char *user) -{ - uchar key[16]; - uchar digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - AuthInfo *ai; - - ai = auth_proxy(0, nil, "proto=%q role=server", p9authproto); - if(ai == nil) - return -1; - if(auth_chuid(ai, nil) < 0) - return -1; - strcpy(user, ai->cuid); - memmove(key+4, ai->secret, ai->nsecret); - - if(ealgs == nil) - return fd; - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i+12] = rand(); - if(readn(fd, key, 4) != 4) - return -1; - if(write(fd, key+12, 4) != 4) - return -1; - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - /* set up encryption */ - i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil); - if(i < 0) - werrstr("can't establish ssl connection: %r"); - return i; -} - -/* - * set authentication mechanism - */ -int -setam(char *name) -{ - for(am = authmethod; am->name != nil; am++) - if(strcmp(am->name, name) == 0) - return 0; - am = authmethod; - return -1; -} - -/* - * set authentication mechanism and encryption/hash algs - */ -int -setamalg(char *s) -{ - ealgs = strchr(s, ' '); - if(ealgs != nil) - *ealgs++ = 0; - return setam(s); -} - -char *rmtnotefile = "/mnt/term/dev/cpunote"; - -/* - * loop reading /mnt/term/dev/note looking for notes. - * The child returns to start the shell. - */ -void -rmtnoteproc(void) -{ - int n, fd, pid, notepid; - char buf[256]; - - /* new proc returns to start shell */ - pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM); - switch(pid){ - case -1: - syslog(0, "cpu", "cpu -R: can't start noteproc: %r"); - return; - case 0: - return; - } - - /* new proc reads notes from other side and posts them to shell */ - switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){ - case -1: - syslog(0, "cpu", "cpu -R: can't start wait proc: %r"); - _exits(0); - case 0: - fd = open(rmtnotefile, OREAD); - if(fd < 0){ - syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile); - _exits(0); - } - - for(;;){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0){ - postnote(PNGROUP, pid, "hangup"); - _exits(0); - } - buf[n] = 0; - postnote(PNGROUP, pid, buf); - } - break; - } - - /* original proc waits for shell proc to die and kills note proc */ - for(;;){ - n = waitpid(); - if(n < 0 || n == pid) - break; - } - postnote(PNPROC, notepid, "kill"); - _exits(0); -} - -enum -{ - Qdir, - Qcpunote, - - Nfid = 32, -}; - -struct { - char *name; - Qid qid; - ulong perm; -} fstab[] = -{ - [Qdir] { ".", {Qdir, 0, QTDIR}, DMDIR|0555 }, - [Qcpunote] { "cpunote", {Qcpunote, 0}, 0444 }, -}; - -typedef struct Note Note; -struct Note -{ - Note *next; - char msg[ERRMAX]; -}; - -typedef struct Request Request; -struct Request -{ - Request *next; - Fcall f; -}; - -typedef struct Fid Fid; -struct Fid -{ - int fid; - int file; -}; -Fid fids[Nfid]; - -struct { - Lock; - Note *nfirst, *nlast; - Request *rfirst, *rlast; -} nfs; - -int -fsreply(int fd, Fcall *f) -{ - uchar buf[IOHDRSZ+Maxfdata]; - int n; - - if(dbg) - fprint(2, "<-%F\n", f); - n = convS2M(f, buf, sizeof buf); - if(n > 0){ - if(write(fd, buf, n) != n){ - close(fd); - return -1; - } - } - return 0; -} - -/* match a note read request with a note, reply to the request */ -int -kick(int fd) -{ - Request *rp; - Note *np; - int rv; - - for(;;){ - lock(&nfs); - rp = nfs.rfirst; - np = nfs.nfirst; - if(rp == nil || np == nil){ - unlock(&nfs); - break; - } - nfs.rfirst = rp->next; - nfs.nfirst = np->next; - unlock(&nfs); - - rp->f.type = Rread; - rp->f.count = strlen(np->msg); - rp->f.data = np->msg; - rv = fsreply(fd, &rp->f); - free(rp); - free(np); - if(rv < 0) - return -1; - } - return 0; -} - -void -flushreq(int tag) -{ - Request **l, *rp; - - lock(&nfs); - for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){ - rp = *l; - if(rp->f.tag == tag){ - *l = rp->next; - unlock(&nfs); - free(rp); - return; - } - } - unlock(&nfs); -} - -Fid* -getfid(int fid) -{ - int i, freefid; - - freefid = -1; - for(i = 0; i < Nfid; i++){ - if(freefid < 0 && fids[i].file < 0) - freefid = i; - if(fids[i].fid == fid) - return &fids[i]; - } - if(freefid >= 0){ - fids[freefid].fid = fid; - return &fids[freefid]; - } - return nil; -} - -int -fsstat(int fd, Fid *fid, Fcall *f) -{ - Dir d; - uchar statbuf[256]; - - memset(&d, 0, sizeof(d)); - d.name = fstab[fid->file].name; - d.uid = user; - d.gid = user; - d.muid = user; - d.qid = fstab[fid->file].qid; - d.mode = fstab[fid->file].perm; - d.atime = d.mtime = time(0); - f->stat = statbuf; - f->nstat = convD2M(&d, statbuf, sizeof statbuf); - return fsreply(fd, f); -} - -int -fsread(int fd, Fid *fid, Fcall *f) -{ - Dir d; - uchar buf[256]; - Request *rp; - - switch(fid->file){ - default: - return -1; - case Qdir: - if(f->offset == 0 && f->count >0){ - memset(&d, 0, sizeof(d)); - d.name = fstab[Qcpunote].name; - d.uid = user; - d.gid = user; - d.muid = user; - d.qid = fstab[Qcpunote].qid; - d.mode = fstab[Qcpunote].perm; - d.atime = d.mtime = time(0); - f->count = convD2M(&d, buf, sizeof buf); - f->data = (char*)buf; - } else - f->count = 0; - return fsreply(fd, f); - case Qcpunote: - rp = mallocz(sizeof(*rp), 1); - if(rp == nil) - return -1; - rp->f = *f; - lock(&nfs); - if(nfs.rfirst == nil) - nfs.rfirst = rp; - else - nfs.rlast->next = rp; - nfs.rlast = rp; - unlock(&nfs); - return kick(fd);; - } -} - -char Eperm[] = "permission denied"; -char Enofile[] = "out of files"; -char Enotdir[] = "not a directory"; - -void -notefs(int fd) -{ - uchar buf[IOHDRSZ+Maxfdata]; - int i, j, n; - char err[ERRMAX]; - Fcall f; - Fid *fid, *nfid; - int doreply; - - rfork(RFNOTEG); - fmtinstall('F', fcallconv); - - for(n = 0; n < Nfid; n++) - fids[n].file = -1; - - for(;;){ - n = read9pmsg(fd, buf, sizeof(buf)); - if(n <= 0){ - if(dbg) - fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n); - break; - } - if(convM2S(buf, n, &f) < 0) - break; - if(dbg) - fprint(2, "->%F\n", &f); - doreply = 1; - fid = getfid(f.fid); - if(fid == nil){ -nofids: - f.type = Rerror; - f.ename = Enofile; - fsreply(fd, &f); - continue; - } - switch(f.type++){ - default: - f.type = Rerror; - f.ename = "unknown type"; - break; - case Tflush: - flushreq(f.oldtag); - break; - case Tversion: - if(f.msize > IOHDRSZ+Maxfdata) - f.msize = IOHDRSZ+Maxfdata; - break; - case Tauth: - f.type = Rerror; - f.ename = "cpu: authentication not required"; - break; - case Tattach: - f.qid = fstab[Qdir].qid; - fid->file = Qdir; - break; - case Twalk: - nfid = nil; - if(f.newfid != f.fid){ - nfid = getfid(f.newfid); - if(nfid == nil) - goto nofids; - nfid->file = fid->file; - fid = nfid; - } - - f.ename = nil; - for(i=0; i MAXWELEM){ - f.type = Rerror; - f.ename = "too many name elements"; - break; - } - if(fid->file != Qdir){ - f.type = Rerror; - f.ename = Enotdir; - break; - } - if(strcmp(f.wname[i], "cpunote") == 0){ - fid->file = Qcpunote; - f.wqid[i] = fstab[Qcpunote].qid; - continue; - } - f.type = Rerror; - f.ename = err; - strcpy(err, "cpu: file \""); - for(j=0; j<=i; j++){ - if(strlen(err)+1+strlen(f.wname[j])+32 > sizeof err) - break; - if(j != 0) - strcat(err, "/"); - strcat(err, f.wname[j]); - } - strcat(err, "\" does not exist"); - break; - } - if(nfid != nil && (f.ename != nil || i < f.nwname)) - nfid ->file = -1; - if(f.type != Rerror) - f.nwqid = i; - break; - case Topen: - if(f.mode != OREAD){ - f.type = Rerror; - f.ename = Eperm; - } - f.qid = fstab[fid->file].qid; - break; - case Tcreate: - f.type = Rerror; - f.ename = Eperm; - break; - case Tread: - if(fsread(fd, fid, &f) < 0) - goto err; - doreply = 0; - break; - case Twrite: - f.type = Rerror; - f.ename = Eperm; - break; - case Tclunk: - fid->file = -1; - break; - case Tremove: - f.type = Rerror; - f.ename = Eperm; - break; - case Tstat: - if(fsstat(fd, fid, &f) < 0) - goto err; - doreply = 0; - break; - case Twstat: - f.type = Rerror; - f.ename = Eperm; - break; - } - if(doreply) - if(fsreply(fd, &f) < 0) - break; - } -err: - if(dbg) - fprint(2, "notefs exiting: %r\n"); - close(fd); -} - -char notebuf[ERRMAX]; - -void -catcher(void*, char *text) -{ - int n; - - n = strlen(text); - if(n >= sizeof(notebuf)) - n = sizeof(notebuf)-1; - memmove(notebuf, text, n); - notebuf[n] = '\0'; - noted(NCONT); -} - -/* - * mount in /dev a note file for the remote side to read. - */ -void -lclnoteproc(int netfd) -{ - int exportfspid; - Waitmsg *w; - Note *np; - int pfd[2]; - - if(pipe(pfd) < 0){ - fprint(2, "cpu: can't start note proc: pipe: %r\n"); - return; - } - - /* new proc mounts and returns to start exportfs */ - switch(exportfspid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){ - case -1: - fprint(2, "cpu: can't start note proc: rfork: %r\n"); - return; - case 0: - close(pfd[0]); - if(mount(pfd[1], -1, "/dev", MBEFORE, "") < 0) - fprint(2, "cpu: can't mount note proc: %r\n"); - close(pfd[1]); - return; - } - - close(netfd); - close(pfd[1]); - - /* new proc listens for note file system rpc's */ - switch(rfork(RFPROC|RFNAMEG|RFMEM)){ - case -1: - fprint(2, "cpu: can't start note proc: rfork1: %r\n"); - _exits(0); - case 0: - notefs(pfd[0]); - _exits(0); - } - - /* original proc waits for notes */ - notify(catcher); - w = nil; - for(;;) { - *notebuf = 0; - free(w); - w = wait(); - if(w == nil) { - if(*notebuf == 0) - break; - np = mallocz(sizeof(Note), 1); - if(np != nil){ - strcpy(np->msg, notebuf); - lock(&nfs); - if(nfs.nfirst == nil) - nfs.nfirst = np; - else - nfs.nlast->next = np; - nfs.nlast = np; - unlock(&nfs); - kick(pfd[0]); - } - unlock(&nfs); - } else if(w->pid == exportfspid) - break; - } - - if(w == nil) - exits(nil); - exits(w->msg); -} blob - df44b97da1a66add949dfc0478761c60fa4a2895 (mode 644) blob + /dev/null --- src/cmd/factotum/ctl.c +++ /dev/null @@ -1,158 +0,0 @@ -#include "std.h" -#include "dat.h" - -/* - * key attr=val... - add a key - * the attr=val pairs are protocol-specific. - * for example, both of these are valid: - * key p9sk1 gre cs.bell-labs.com mysecret - * key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex - * delkey ... - delete a key - * if given, the attr=val pairs are used to narrow the search - * [maybe should require a password?] - * - * debug - toggle debugging - */ - -static char *msg[] = { - "key", - "delkey", - "debug", -}; - -static int -classify(char *s) -{ - int i; - - for(i=0; i/mnt/factotum/ctl" - * and writes that (incorrectly) contain multiple key lines. - */ - if(p = strchr(a, '\n')){ - if(p[1] != '\0'){ - werrstr("multiline write not allowed"); - return -1; - } - *p = '\0'; - } - - if((p = strchr(a, ' ')) == nil) - p = ""; - else - *p++ = '\0'; - switch(classify(a)){ - default: - werrstr("unknown verb"); - return -1; - case 0: /* key */ - attr = parseattr(p); - /* separate out proto= attributes */ - lprotos = &protos; - for(l=&attr; (*l); ){ - if(strcmp((*l)->name, "proto") == 0){ - *lprotos = *l; - lprotos = &(*l)->next; - *l = (*l)->next; - }else - l = &(*l)->next; - } - *lprotos = nil; - if(protos == nil){ - werrstr("key without protos"); - freeattr(attr); - return -1; - } - - /* separate out private attributes */ - lpriv = &priv; - for(l=&attr; (*l); ){ - if((*l)->name[0] == '!'){ - *lpriv = *l; - lpriv = &(*l)->next; - *l = (*l)->next; - }else - l = &(*l)->next; - } - *lpriv = nil; - - /* add keys */ - ret = 0; - for(pa=protos; pa; pa=pa->next){ - if((proto = protolookup(pa->val)) == nil){ - werrstr("unknown proto %s", pa->val); - ret = -1; - continue; - } - if(proto->checkkey == nil){ - werrstr("proto %s does not accept keys", proto->name); - ret = -1; - continue; - } - k = emalloc(sizeof(Key)); - k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr)); - k->privattr = copyattr(priv); - k->ref = 1; - k->proto = proto; - if((*proto->checkkey)(k) < 0){ - ret = -1; - keyclose(k); - continue; - } - keyadd(k); - keyclose(k); - } - freeattr(attr); - freeattr(priv); - freeattr(protos); - return ret; - case 1: /* delkey */ - nmatch = 0; - attr = parseattr(p); - for(pa=attr; pa; pa=pa->next){ - if(pa->type != AttrQuery && pa->name[0]=='!'){ - werrstr("only !private? patterns are allowed for private fields"); - freeattr(attr); - return -1; - } - } - for(i=0; iattr, ring.key[i]->privattr)){ - nmatch++; - keyclose(ring.key[i]); - ring.nkey--; - memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0])); - }else - i++; - } - freeattr(attr); - if(nmatch == 0){ - werrstr("found no keys to delete"); - return -1; - } - return 0; - case 2: /* debug */ - debug ^= 1; - return 0; - } -} blob - 1d4a3da242d7ba506e2506aa9ee9ec64af4be86f (mode 644) blob + /dev/null --- src/cmd/factotum/dat.h +++ /dev/null @@ -1,227 +0,0 @@ -enum -{ - MaxRpc = 2048, /* max size of any protocol message */ - - /* keep in sync with rpc.c:/rpcname */ - RpcUnknown = 0, /* Rpc.op */ - RpcAuthinfo, - RpcAttr, - RpcRead, - RpcStart, - RpcWrite, - - /* thread stack size */ - STACK = 8192, -}; - -typedef struct Conv Conv; -typedef struct Key Key; -typedef struct Logbuf Logbuf; -typedef struct Proto Proto; -typedef struct Ring Ring; -typedef struct Role Role; -typedef struct Rpc Rpc; - -struct Rpc -{ - int op; - void *data; - int count; -}; - -struct Conv -{ - int ref; /* ref count */ - int hangup; /* flag: please hang up */ - int active; /* flag: there is an active thread */ - int done; /* flag: conversation finished successfully */ - ulong tag; /* identifying tag */ - Conv *next; /* in linked list */ - char *sysuser; /* system name for user speaking to us */ - char *state; /* for debugging */ - char statebuf[128]; /* for formatted states */ - char err[ERRMAX]; /* last error */ - - Attr *attr; /* current attributes */ - Proto *proto; /* protocol */ - - Channel *rpcwait; /* wait here for an rpc */ - Rpc rpc; /* current rpc. op==RpcUnknown means none */ - char rpcbuf[MaxRpc]; /* buffer for rpc */ - char reply[MaxRpc]; /* buffer for response */ - int nreply; /* count of response */ - void (*kickreply)(Conv*); /* call to send response */ - Req *req; /* 9P call to read response */ - - Channel *keywait; /* wait here for key confirmation */ - -}; - -struct Key -{ - int ref; /* ref count */ - ulong tag; /* identifying tag: sequence number */ - Attr *attr; /* public attributes */ - Attr *privattr; /* private attributes, like !password */ - Proto *proto; /* protocol owner of key */ - void *priv; /* protocol-specific storage */ -}; - -struct Logbuf -{ - Req *wait; - Req **waitlast; - int rp; - int wp; - char *msg[128]; -}; - -struct Ring -{ - Key **key; - int nkey; -}; - -struct Proto -{ - char *name; /* name of protocol */ - Role *roles; /* list of roles and service functions */ - char *keyprompt; /* required attributes for key proto=name */ - int (*checkkey)(Key*); /* initialize k->priv or reject key */ - void (*closekey)(Key*); /* free k->priv */ -}; - -struct Role -{ - char *name; /* name of role */ - int (*fn)(Conv*); /* service function */ -}; - -extern char *authaddr; /* plan9.c */ -extern int *confirminuse; /* fs.c */ -extern Conv* conv; /* conv.c */ -extern int debug; /* main.c */ -extern char *factname; /* main.c */ -extern Srv fs; /* fs.c */ -extern int *needkeyinuse; /* fs.c */ -extern char *owner; /* main.c */ -extern Proto *prototab[]; /* main.c */ -extern Ring ring; /* key.c */ -extern char *rpcname[]; /* rpc.c */ - -extern char Easproto[]; /* err.c */ - -extern Proto apop; /* apop.c */ -extern Proto chap; /* chap.c */ -extern Proto cram; /* cram.c */ -extern Proto mschap; /* mschap.c */ -extern Proto p9any; /* p9any.c */ -extern Proto p9sk1; /* p9sk1.c */ -extern Proto p9sk2; /* p9sk2.c */ - -/* provided by lib9p */ -#define emalloc emalloc9p -#define erealloc erealloc9p -#define estrdup estrdup9p - -/* hidden in libauth */ -#define attrfmt _attrfmt -#define copyattr _copyattr -#define delattr _delattr -#define findattr _findattr -#define freeattr _freeattr -#define mkattr _mkattr -#define parseattr _parseattr -#define strfindattr _strfindattr - -extern Attr* addattr(Attr*, char*, ...); -/* #pragma varargck argpos addattr 2 */ -extern Attr* addattrs(Attr*, Attr*); -extern Attr* sortattr(Attr*); -extern int attrnamefmt(Fmt*); -/* #pragma varargck type "N" Attr* */ -extern int matchattr(Attr*, Attr*, Attr*); -extern Attr* parseattrfmt(char*, ...); -/* #pragma varargck argpos parseattrfmt 1 */ -extern Attr* parseattrfmtv(char*, va_list); - -extern void confirmflush(Req*); -extern void confirmread(Req*); -extern int confirmwrite(char*); -extern int needkey(Conv*, Attr*); -extern int badkey(Conv*, Key*, char*, Attr*); -extern int confirmkey(Conv*, Key*); - -extern Conv* convalloc(char*); -extern void convclose(Conv*); -extern void convhangup(Conv*); -extern int convneedkey(Conv*, Attr*); -extern int convbadkey(Conv*, Key*, char*, Attr*); -extern int convread(Conv*, void*, int); -extern int convreadm(Conv*, char**); -extern int convprint(Conv*, char*, ...); -/* #pragma varargck argpos convprint 2 */ -extern int convreadfn(Conv*, int(*)(void*, int), char**); -extern void convreset(Conv*); -extern int convwrite(Conv*, void*, int); - -extern int ctlwrite(char*); - -extern char* estrappend(char*, char*, ...); -/* #pragma varargck argpos estrappend 2 */ -extern int hexparse(char*, uchar*, int); - -extern void keyadd(Key*); -extern Key* keylookup(char*, ...); -/* #pragma varargck argpos keylookup 1 */ -extern Key* keyfetch(Conv*, char*, ...); -/* #pragma varargck argpos keyfetch 2 */ -extern void keyclose(Key*); -extern void keyevict(Conv*, Key*, char*, ...); -/* #pragma varargck argpos keyevict 3 */ -extern Key* keyreplace(Conv*, Key*, char*, ...); -/* #pragma varargck argpos keyreplace 3 */ - -extern void lbkick(Logbuf*); -extern void lbappend(Logbuf*, char*, ...); -extern void lbvappend(Logbuf*, char*, va_list); -/* #pragma varargck argpos lbappend 2 */ -extern void lbread(Logbuf*, Req*); -extern void lbflush(Logbuf*, Req*); -extern void flog(char*, ...); -/* #pragma varargck argpos flog 1 */ - -extern void logflush(Req*); -extern void logread(Req*); -extern void logwrite(Req*); - -extern void needkeyread(Req*); -extern void needkeyflush(Req*); -extern int needkeywrite(char*); -extern int needkeyqueue(void); - -extern Attr* addcap(Attr*, char*, Ticket*); -extern Key* plan9authkey(Attr*); -extern int _authdial(char*, char*); - -extern int memrandom(void*, int); - -extern Proto* protolookup(char*); - -extern int rpcwrite(Conv*, void*, int); -extern void rpcrespond(Conv*, char*, ...); -/* #pragma varargck argpos rpcrespond 2 */ -extern void rpcrespondn(Conv*, char*, void*, int); -extern void rpcexec(Conv*); - -extern int xioauthdial(char*, char*); -extern void xioclose(int); -extern int xiodial(char*, char*, char*, int*); -extern int xiowrite(int, void*, int); -extern int xioasrdresp(int, void*, int); -extern int xioasgetticket(int, char*, char*); - -extern int extrafactotumdir; - -int havesecstore(void); -int secstorefetch(void); blob - 47d2a4e17aeb1754c31a134722adbf4f85e074f6 (mode 644) blob + /dev/null --- src/cmd/factotum/fs.acid +++ /dev/null @@ -1,1686 +0,0 @@ -sizeof_1_ = 8; -aggr _1_ -{ - 'D' 0 lo; - 'D' 4 hi; -}; - -defn -_1_(addr) { - complex _1_ addr; - print(" lo ", addr.lo, "\n"); - print(" hi ", addr.hi, "\n"); -}; - -sizeofFPdbleword = 8; -aggr FPdbleword -{ - 'F' 0 x; - { - 'D' 0 lo; - 'D' 4 hi; - }; -}; - -defn -FPdbleword(addr) { - complex FPdbleword addr; - print(" x ", addr.x, "\n"); - print("_1_ {\n"); - _1_(addr+0); - print("}\n"); -}; - -UTFmax = 3; -Runesync = 128; -Runeself = 128; -Runeerror = 128; -sizeofFconv = 24; -aggr Fconv -{ - 'X' 0 out; - 'X' 4 eout; - 'D' 8 f1; - 'D' 12 f2; - 'D' 16 f3; - 'D' 20 chr; -}; - -defn -Fconv(addr) { - complex Fconv addr; - print(" out ", addr.out\X, "\n"); - print(" eout ", addr.eout\X, "\n"); - print(" f1 ", addr.f1, "\n"); - print(" f2 ", addr.f2, "\n"); - print(" f3 ", addr.f3, "\n"); - print(" chr ", addr.chr, "\n"); -}; - -sizeofTm = 40; -aggr Tm -{ - 'D' 0 sec; - 'D' 4 min; - 'D' 8 hour; - 'D' 12 mday; - 'D' 16 mon; - 'D' 20 year; - 'D' 24 wday; - 'D' 28 yday; - 'a' 32 zone; - 'D' 36 tzoff; -}; - -defn -Tm(addr) { - complex Tm addr; - print(" sec ", addr.sec, "\n"); - print(" min ", addr.min, "\n"); - print(" hour ", addr.hour, "\n"); - print(" mday ", addr.mday, "\n"); - print(" mon ", addr.mon, "\n"); - print(" year ", addr.year, "\n"); - print(" wday ", addr.wday, "\n"); - print(" yday ", addr.yday, "\n"); - print(" zone ", addr.zone, "\n"); - print(" tzoff ", addr.tzoff, "\n"); -}; - -PNPROC = 1; -PNGROUP = 2; -sizeofLock = 4; -aggr Lock -{ - 'D' 0 val; -}; - -defn -Lock(addr) { - complex Lock addr; - print(" val ", addr.val, "\n"); -}; - -sizeofQLp = 12; -aggr QLp -{ - 'D' 0 inuse; - 'A' QLp 4 next; - 'C' 8 state; -}; - -defn -QLp(addr) { - complex QLp addr; - print(" inuse ", addr.inuse, "\n"); - print(" next ", addr.next\X, "\n"); - print(" state ", addr.state, "\n"); -}; - -sizeofQLock = 16; -aggr QLock -{ - Lock 0 lock; - 'D' 4 locked; - 'A' QLp 8 $head; - 'A' QLp 12 $tail; -}; - -defn -QLock(addr) { - complex QLock addr; - print("Lock lock {\n"); - Lock(addr.lock); - print("}\n"); - print(" locked ", addr.locked, "\n"); - print(" $head ", addr.$head\X, "\n"); - print(" $tail ", addr.$tail\X, "\n"); -}; - -sizeofRWLock = 20; -aggr RWLock -{ - Lock 0 lock; - 'D' 4 readers; - 'D' 8 writer; - 'A' QLp 12 $head; - 'A' QLp 16 $tail; -}; - -defn -RWLock(addr) { - complex RWLock addr; - print("Lock lock {\n"); - Lock(addr.lock); - print("}\n"); - print(" readers ", addr.readers, "\n"); - print(" writer ", addr.writer, "\n"); - print(" $head ", addr.$head\X, "\n"); - print(" $tail ", addr.$tail\X, "\n"); -}; - -RFNAMEG = 1; -RFENVG = 2; -RFFDG = 4; -RFNOTEG = 8; -RFPROC = 16; -RFMEM = 32; -RFNOWAIT = 64; -RFCNAMEG = 1024; -RFCENVG = 2048; -RFCFDG = 4096; -RFREND = 8192; -RFNOMNT = 16384; -sizeofQid = 16; -aggr Qid -{ - 'W' 0 path; - 'U' 8 vers; - 'b' 12 type; -}; - -defn -Qid(addr) { - complex Qid addr; - print(" path ", addr.path, "\n"); - print(" vers ", addr.vers, "\n"); - print(" type ", addr.type, "\n"); -}; - -sizeofDir = 60; -aggr Dir -{ - 'u' 0 type; - 'U' 4 dev; - Qid 8 qid; - 'U' 24 mode; - 'U' 28 atime; - 'U' 32 mtime; - 'V' 36 length; - 'X' 44 name; - 'X' 48 uid; - 'X' 52 gid; - 'X' 56 muid; -}; - -defn -Dir(addr) { - complex Dir addr; - print(" type ", addr.type, "\n"); - print(" dev ", addr.dev, "\n"); - print("Qid qid {\n"); - Qid(addr.qid); - print("}\n"); - print(" mode ", addr.mode, "\n"); - print(" atime ", addr.atime, "\n"); - print(" mtime ", addr.mtime, "\n"); - print(" length ", addr.length, "\n"); - print(" name ", addr.name\X, "\n"); - print(" uid ", addr.uid\X, "\n"); - print(" gid ", addr.gid\X, "\n"); - print(" muid ", addr.muid\X, "\n"); -}; - -sizeofWaitmsg = 20; -aggr Waitmsg -{ - 'D' 0 pid; - 'a' 4 time; - 'X' 16 msg; -}; - -defn -Waitmsg(addr) { - complex Waitmsg addr; - print(" pid ", addr.pid, "\n"); - print(" time ", addr.time, "\n"); - print(" msg ", addr.msg\X, "\n"); -}; - -sizeofIOchunk = 8; -aggr IOchunk -{ - 'X' 0 addr; - 'U' 4 len; -}; - -defn -IOchunk(addr) { - complex IOchunk addr; - print(" addr ", addr.addr\X, "\n"); - print(" len ", addr.len, "\n"); -}; - -MAXCHLEN = 256; -MAXNAMELEN = 256; -MD5LEN = 16; -ARok = 0; -ARdone = 1; -ARerror = 2; -ARneedkey = 3; -ARbadkey = 4; -ARwritenext = 5; -ARtoosmall = 6; -ARtoobig = 7; -ARrpcfailure = 8; -ARphase = 9; -AuthRpcMax = 4096; -sizeofAuthRpc = 8208; -aggr AuthRpc -{ - 'D' 0 afd; - 'X' 4 verb; - 'a' 8 ibuf; - 'a' 4104 obuf; - 'X' 8200 arg; - 'U' 8204 narg; -}; - -defn -AuthRpc(addr) { - complex AuthRpc addr; - print(" afd ", addr.afd, "\n"); - print(" verb ", addr.verb\X, "\n"); - print(" ibuf ", addr.ibuf, "\n"); - print(" obuf ", addr.obuf, "\n"); - print(" arg ", addr.arg\X, "\n"); - print(" narg ", addr.narg, "\n"); -}; - -sizeofAuthInfo = 20; -aggr AuthInfo -{ - 'X' 0 cuid; - 'X' 4 suid; - 'X' 8 cap; - 'D' 12 nsecret; - 'X' 16 secret; -}; - -defn -AuthInfo(addr) { - complex AuthInfo addr; - print(" cuid ", addr.cuid\X, "\n"); - print(" suid ", addr.suid\X, "\n"); - print(" cap ", addr.cap\X, "\n"); - print(" nsecret ", addr.nsecret, "\n"); - print(" secret ", addr.secret\X, "\n"); -}; - -sizeofChalstate = 540; -aggr Chalstate -{ - 'X' 0 user; - 'a' 4 chal; - 'D' 260 nchal; - 'X' 264 resp; - 'D' 268 nresp; - 'D' 272 afd; - 'A' AuthRpc 276 rpc; - 'a' 280 userbuf; - 'D' 536 userinchal; -}; - -defn -Chalstate(addr) { - complex Chalstate addr; - print(" user ", addr.user\X, "\n"); - print(" chal ", addr.chal, "\n"); - print(" nchal ", addr.nchal, "\n"); - print(" resp ", addr.resp\X, "\n"); - print(" nresp ", addr.nresp, "\n"); - print(" afd ", addr.afd, "\n"); - print(" rpc ", addr.rpc\X, "\n"); - print(" userbuf ", addr.userbuf, "\n"); - print(" userinchal ", addr.userinchal, "\n"); -}; - -sizeofChapreply = 20; -aggr Chapreply -{ - 'b' 0 id; - 'a' 1 resp; -}; - -defn -Chapreply(addr) { - complex Chapreply addr; - print(" id ", addr.id, "\n"); - print(" resp ", addr.resp, "\n"); -}; - -sizeofMSchapreply = 48; -aggr MSchapreply -{ - 'a' 0 LMresp; - 'a' 24 NTresp; -}; - -defn -MSchapreply(addr) { - complex MSchapreply addr; - print(" LMresp ", addr.LMresp, "\n"); - print(" NTresp ", addr.NTresp, "\n"); -}; - -sizeofUserPasswd = 8; -aggr UserPasswd -{ - 'X' 0 user; - 'X' 4 passwd; -}; - -defn -UserPasswd(addr) { - complex UserPasswd addr; - print(" user ", addr.user\X, "\n"); - print(" passwd ", addr.passwd\X, "\n"); -}; - -ANAMELEN = 28; -AERRLEN = 64; -DOMLEN = 48; -DESKEYLEN = 7; -CHALLEN = 8; -NETCHLEN = 16; -CONFIGLEN = 14; -SECRETLEN = 32; -KEYDBOFF = 8; -OKEYDBLEN = 41; -KEYDBLEN = 73; -OMD5LEN = 16; -AuthTreq = 1; -AuthChal = 2; -AuthPass = 3; -AuthOK = 4; -AuthErr = 5; -AuthMod = 6; -AuthApop = 7; -AuthOKvar = 9; -AuthChap = 10; -AuthMSchap = 11; -AuthCram = 12; -AuthHttp = 13; -AuthVNC = 14; -AuthTs = 64; -AuthTc = 65; -AuthAs = 66; -AuthAc = 67; -AuthTp = 68; -AuthHr = 69; -sizeofTicketreq = 144; -aggr Ticketreq -{ - 'C' 0 type; - 'a' 1 authid; - 'a' 29 authdom; - 'a' 77 chal; - 'a' 85 hostid; - 'a' 113 uid; -}; - -defn -Ticketreq(addr) { - complex Ticketreq addr; - print(" type ", addr.type, "\n"); - print(" authid ", addr.authid, "\n"); - print(" authdom ", addr.authdom, "\n"); - print(" chal ", addr.chal, "\n"); - print(" hostid ", addr.hostid, "\n"); - print(" uid ", addr.uid, "\n"); -}; - -sizeofTicket = 72; -aggr Ticket -{ - 'C' 0 num; - 'a' 1 chal; - 'a' 9 cuid; - 'a' 37 suid; - 'a' 65 key; -}; - -defn -Ticket(addr) { - complex Ticket addr; - print(" num ", addr.num, "\n"); - print(" chal ", addr.chal, "\n"); - print(" cuid ", addr.cuid, "\n"); - print(" suid ", addr.suid, "\n"); - print(" key ", addr.key, "\n"); -}; - -sizeofAuthenticator = 16; -aggr Authenticator -{ - 'C' 0 num; - 'a' 1 chal; - 'U' 12 id; -}; - -defn -Authenticator(addr) { - complex Authenticator addr; - print(" num ", addr.num, "\n"); - print(" chal ", addr.chal, "\n"); - print(" id ", addr.id, "\n"); -}; - -sizeofPasswordreq = 92; -aggr Passwordreq -{ - 'C' 0 num; - 'a' 1 old; - 'a' 29 new; - 'C' 57 changesecret; - 'a' 58 secret; -}; - -defn -Passwordreq(addr) { - complex Passwordreq addr; - print(" num ", addr.num, "\n"); - print(" old ", addr.old, "\n"); - print(" new ", addr.new, "\n"); - print(" changesecret ", addr.changesecret, "\n"); - print(" secret ", addr.secret, "\n"); -}; - -sizeofOChapreply = 48; -aggr OChapreply -{ - 'b' 0 id; - 'a' 1 uid; - 'a' 29 resp; -}; - -defn -OChapreply(addr) { - complex OChapreply addr; - print(" id ", addr.id, "\n"); - print(" uid ", addr.uid, "\n"); - print(" resp ", addr.resp, "\n"); -}; - -sizeofOMSchapreply = 76; -aggr OMSchapreply -{ - 'a' 0 uid; - 'a' 28 LMresp; - 'a' 52 NTresp; -}; - -defn -OMSchapreply(addr) { - complex OMSchapreply addr; - print(" uid ", addr.uid, "\n"); - print(" LMresp ", addr.LMresp, "\n"); - print(" NTresp ", addr.NTresp, "\n"); -}; - -NVwrite = 1; -NVwriteonerr = 2; -sizeofNvrsafe = 112; -aggr Nvrsafe -{ - 'a' 0 machkey; - 'b' 7 machsum; - 'a' 8 authkey; - 'b' 15 authsum; - 'a' 16 config; - 'b' 30 configsum; - 'a' 31 authid; - 'b' 59 authidsum; - 'a' 60 authdom; - 'b' 108 authdomsum; -}; - -defn -Nvrsafe(addr) { - complex Nvrsafe addr; - print(" machkey ", addr.machkey, "\n"); - print(" machsum ", addr.machsum, "\n"); - print(" authkey ", addr.authkey, "\n"); - print(" authsum ", addr.authsum, "\n"); - print(" config ", addr.config, "\n"); - print(" configsum ", addr.configsum, "\n"); - print(" authid ", addr.authid, "\n"); - print(" authidsum ", addr.authidsum, "\n"); - print(" authdom ", addr.authdom, "\n"); - print(" authdomsum ", addr.authdomsum, "\n"); -}; - -AESbsize = 16; -AESmaxkey = 32; -AESmaxrounds = 14; -sizeofAESstate = 540; -aggr AESstate -{ - 'U' 0 setup; - 'D' 4 rounds; - 'D' 8 keybytes; - 'a' 12 key; - 'a' 44 ekey; - 'a' 284 dkey; - 'a' 524 ivec; -}; - -defn -AESstate(addr) { - complex AESstate addr; - print(" setup ", addr.setup, "\n"); - print(" rounds ", addr.rounds, "\n"); - print(" keybytes ", addr.keybytes, "\n"); - print(" key ", addr.key, "\n"); - print(" ekey ", addr.ekey, "\n"); - print(" dkey ", addr.dkey, "\n"); - print(" ivec ", addr.ivec, "\n"); -}; - -BFbsize = 8; -BFrounds = 16; -sizeofBFstate = 4236; -aggr BFstate -{ - 'U' 0 setup; - 'a' 4 key; - 'a' 60 ivec; - 'a' 68 pbox; - 'a' 140 sbox; -}; - -defn -BFstate(addr) { - complex BFstate addr; - print(" setup ", addr.setup, "\n"); - print(" key ", addr.key, "\n"); - print(" ivec ", addr.ivec, "\n"); - print(" pbox ", addr.pbox, "\n"); - print(" sbox ", addr.sbox, "\n"); -}; - -DESbsize = 8; -sizeofDESstate = 148; -aggr DESstate -{ - 'U' 0 setup; - 'a' 4 key; - 'a' 12 expanded; - 'a' 140 ivec; -}; - -defn -DESstate(addr) { - complex DESstate addr; - print(" setup ", addr.setup, "\n"); - print(" key ", addr.key, "\n"); - print(" expanded ", addr.expanded, "\n"); - print(" ivec ", addr.ivec, "\n"); -}; - -DES3E = 0; -DES3D = 1; -DES3EEE = 0; -DES3EDE = 2; -DES3DED = 5; -DES3DDD = 7; -sizeofDES3state = 420; -aggr DES3state -{ - 'U' 0 setup; - 'a' 4 key; - 'a' 28 expanded; - 'a' 412 ivec; -}; - -defn -DES3state(addr) { - complex DES3state addr; - print(" setup ", addr.setup, "\n"); - print(" key ", addr.key, "\n"); - print(" expanded ", addr.expanded, "\n"); - print(" ivec ", addr.ivec, "\n"); -}; - -SHA1dlen = 20; -MD4dlen = 16; -MD5dlen = 16; -sizeofDigestState = 160; -aggr DigestState -{ - 'U' 0 len; - 'a' 4 state; - 'a' 24 buf; - 'D' 152 blen; - 'C' 156 malloced; - 'C' 157 seeded; -}; - -defn -DigestState(addr) { - complex DigestState addr; - print(" len ", addr.len, "\n"); - print(" state ", addr.state, "\n"); - print(" buf ", addr.buf, "\n"); - print(" blen ", addr.blen, "\n"); - print(" malloced ", addr.malloced, "\n"); - print(" seeded ", addr.seeded, "\n"); -}; - -sizeofRC4state = 260; -aggr RC4state -{ - 'a' 0 state; - 'b' 256 x; - 'b' 257 y; -}; - -defn -RC4state(addr) { - complex RC4state addr; - print(" state ", addr.state, "\n"); - print(" x ", addr.x, "\n"); - print(" y ", addr.y, "\n"); -}; - -sizeofRSApub = 8; -aggr RSApub -{ - 'X' 0 n; - 'X' 4 ek; -}; - -defn -RSApub(addr) { - complex RSApub addr; - print(" n ", addr.n\X, "\n"); - print(" ek ", addr.ek\X, "\n"); -}; - -sizeofRSApriv = 32; -aggr RSApriv -{ - RSApub 0 pub; - 'X' 8 dk; - 'X' 12 p; - 'X' 16 q; - 'X' 20 kp; - 'X' 24 kq; - 'X' 28 c2; -}; - -defn -RSApriv(addr) { - complex RSApriv addr; - print("RSApub pub {\n"); - RSApub(addr.pub); - print("}\n"); - print(" dk ", addr.dk\X, "\n"); - print(" p ", addr.p\X, "\n"); - print(" q ", addr.q\X, "\n"); - print(" kp ", addr.kp\X, "\n"); - print(" kq ", addr.kq\X, "\n"); - print(" c2 ", addr.c2\X, "\n"); -}; - -sizeofEGpub = 12; -aggr EGpub -{ - 'X' 0 p; - 'X' 4 alpha; - 'X' 8 key; -}; - -defn -EGpub(addr) { - complex EGpub addr; - print(" p ", addr.p\X, "\n"); - print(" alpha ", addr.alpha\X, "\n"); - print(" key ", addr.key\X, "\n"); -}; - -sizeofEGpriv = 16; -aggr EGpriv -{ - EGpub 0 pub; - 'X' 12 secret; -}; - -defn -EGpriv(addr) { - complex EGpriv addr; - print("EGpub pub {\n"); - EGpub(addr.pub); - print("}\n"); - print(" secret ", addr.secret\X, "\n"); -}; - -sizeofEGsig = 8; -aggr EGsig -{ - 'X' 0 r; - 'X' 4 s; -}; - -defn -EGsig(addr) { - complex EGsig addr; - print(" r ", addr.r\X, "\n"); - print(" s ", addr.s\X, "\n"); -}; - -sizeofString = 20; -aggr String -{ - { - 'D' 0 val; - }; - 'X' 4 base; - 'X' 8 end; - 'X' 12 ptr; - 'd' 16 ref; - 'b' 18 fixed; -}; - -defn -String(addr) { - complex String addr; - print("Lock {\n"); - Lock(addr+0); - print("}\n"); - print(" base ", addr.base\X, "\n"); - print(" end ", addr.end\X, "\n"); - print(" ptr ", addr.ptr\X, "\n"); - print(" ref ", addr.ref, "\n"); - print(" fixed ", addr.fixed, "\n"); -}; - -sizeofChannel = 156; -aggr Channel -{ - 'D' 0 s; - 'U' 4 f; - 'U' 8 n; - 'D' 12 e; - 'D' 16 freed; - 'U' 20 qused; - 'a' 24 qentry; - 'a' 152 v; -}; - -defn -Channel(addr) { - complex Channel addr; - print(" s ", addr.s, "\n"); - print(" f ", addr.f, "\n"); - print(" n ", addr.n, "\n"); - print(" e ", addr.e, "\n"); - print(" freed ", addr.freed, "\n"); - print(" qused ", addr.qused, "\n"); - print(" qentry ", addr.qentry, "\n"); - print(" v ", addr.v, "\n"); -}; - -sizeofAlt = 20; -aggr Alt -{ - 'A' Channel 0 c; - 'X' 4 v; - 'D' 8 op; - 'A' Channel 12 tag; - 'U' 16 q; -}; - -defn -Alt(addr) { - complex Alt addr; - print(" c ", addr.c\X, "\n"); - print(" v ", addr.v\X, "\n"); - print(" op ", addr.op, "\n"); - print(" tag ", addr.tag\X, "\n"); - print(" q ", addr.q, "\n"); -}; - -sizeofRef = 4; -aggr Ref -{ - 'D' 0 ref; -}; - -defn -Ref(addr) { - complex Ref addr; - print(" ref ", addr.ref, "\n"); -}; - -sizeof_2_ = 8; -aggr _2_ -{ - 'U' 0 msize; - 'X' 4 version; -}; - -defn -_2_(addr) { - complex _2_ addr; - print(" msize ", addr.msize, "\n"); - print(" version ", addr.version\X, "\n"); -}; - -sizeof_3_ = 4; -aggr _3_ -{ - 'u' 0 oldtag; -}; - -defn -_3_(addr) { - complex _3_ addr; - print(" oldtag ", addr.oldtag, "\n"); -}; - -sizeof_4_ = 4; -aggr _4_ -{ - 'X' 0 ename; -}; - -defn -_4_(addr) { - complex _4_ addr; - print(" ename ", addr.ename\X, "\n"); -}; - -sizeof_5_ = 20; -aggr _5_ -{ - Qid 0 qid; - 'U' 16 iounit; -}; - -defn -_5_(addr) { - complex _5_ addr; - print("Qid qid {\n"); - Qid(addr.qid); - print("}\n"); - print(" iounit ", addr.iounit, "\n"); -}; - -sizeof_6_ = 16; -aggr _6_ -{ - Qid 0 aqid; -}; - -defn -_6_(addr) { - complex _6_ addr; - print("Qid aqid {\n"); - Qid(addr.aqid); - print("}\n"); -}; - -sizeof_7_ = 12; -aggr _7_ -{ - 'U' 0 afid; - 'X' 4 uname; - 'X' 8 aname; -}; - -defn -_7_(addr) { - complex _7_ addr; - print(" afid ", addr.afid, "\n"); - print(" uname ", addr.uname\X, "\n"); - print(" aname ", addr.aname\X, "\n"); -}; - -sizeof_8_ = 12; -aggr _8_ -{ - 'U' 0 perm; - 'X' 4 name; - 'b' 8 mode; -}; - -defn -_8_(addr) { - complex _8_ addr; - print(" perm ", addr.perm, "\n"); - print(" name ", addr.name\X, "\n"); - print(" mode ", addr.mode, "\n"); -}; - -sizeof_9_ = 72; -aggr _9_ -{ - 'U' 0 newfid; - 'u' 4 nwname; - 'a' 8 wname; -}; - -defn -_9_(addr) { - complex _9_ addr; - print(" newfid ", addr.newfid, "\n"); - print(" nwname ", addr.nwname, "\n"); - print(" wname ", addr.wname, "\n"); -}; - -sizeof_10_ = 260; -aggr _10_ -{ - 'u' 0 nwqid; - 'a' 4 wqid; -}; - -defn -_10_(addr) { - complex _10_ addr; - print(" nwqid ", addr.nwqid, "\n"); - print(" wqid ", addr.wqid, "\n"); -}; - -sizeof_11_ = 16; -aggr _11_ -{ - 'V' 0 offset; - 'U' 8 count; - 'X' 12 data; -}; - -defn -_11_(addr) { - complex _11_ addr; - print(" offset ", addr.offset, "\n"); - print(" count ", addr.count, "\n"); - print(" data ", addr.data\X, "\n"); -}; - -sizeof_12_ = 8; -aggr _12_ -{ - 'u' 0 nstat; - 'X' 4 stat; -}; - -defn -_12_(addr) { - complex _12_ addr; - print(" nstat ", addr.nstat, "\n"); - print(" stat ", addr.stat\X, "\n"); -}; - -sizeof_13_ = 260; -aggr _13_ -{ - { - 'U' 0 msize; - 'X' 4 version; - }; - { - 'u' 0 oldtag; - }; - { - 'X' 0 ename; - }; - { - Qid 0 qid; - 'U' 16 iounit; - }; - { - Qid 0 aqid; - }; - { - 'U' 0 afid; - 'X' 4 uname; - 'X' 8 aname; - }; - { - 'U' 0 perm; - 'X' 4 name; - 'b' 8 mode; - }; - { - 'U' 0 newfid; - 'u' 4 nwname; - 'a' 8 wname; - }; - { - 'u' 0 nwqid; - 'a' 4 wqid; - }; - { - 'V' 0 offset; - 'U' 8 count; - 'X' 12 data; - }; - { - 'u' 0 nstat; - 'X' 4 stat; - }; -}; - -defn -_13_(addr) { - complex _13_ addr; - print("_2_ {\n"); - _2_(addr+0); - print("}\n"); - print("_3_ {\n"); - _3_(addr+0); - print("}\n"); - print("_4_ {\n"); - _4_(addr+0); - print("}\n"); - print("_5_ {\n"); - _5_(addr+0); - print("}\n"); - print("_6_ {\n"); - _6_(addr+0); - print("}\n"); - print("_7_ {\n"); - _7_(addr+0); - print("}\n"); - print("_8_ {\n"); - _8_(addr+0); - print("}\n"); - print("_9_ {\n"); - _9_(addr+0); - print("}\n"); - print("_10_ {\n"); - _10_(addr+0); - print("}\n"); - print("_11_ {\n"); - _11_(addr+0); - print("}\n"); - print("_12_ {\n"); - _12_(addr+0); - print("}\n"); -}; - -sizeofFcall = 272; -aggr Fcall -{ - 'b' 0 type; - 'U' 4 fid; - 'u' 8 tag; - { - { - 'U' 12 msize; - 'X' 16 version; - }; - { - 'u' 12 oldtag; - }; - { - 'X' 12 ename; - }; - { - Qid 12 qid; - 'U' 28 iounit; - }; - { - Qid 12 aqid; - }; - { - 'U' 12 afid; - 'X' 16 uname; - 'X' 20 aname; - }; - { - 'U' 12 perm; - 'X' 16 name; - 'b' 20 mode; - }; - { - 'U' 12 newfid; - 'u' 16 nwname; - 'a' 20 wname; - }; - { - 'u' 12 nwqid; - 'a' 16 wqid; - }; - { - 'V' 12 offset; - 'U' 20 count; - 'X' 24 data; - }; - { - 'u' 12 nstat; - 'X' 16 stat; - }; - }; -}; - -defn -Fcall(addr) { - complex Fcall addr; - print(" type ", addr.type, "\n"); - print(" fid ", addr.fid, "\n"); - print(" tag ", addr.tag, "\n"); - print("_13_ {\n"); - _13_(addr+12); - print("}\n"); -}; - -Tversion = 100; -Rversion = 101; -Tauth = 102; -Rauth = 103; -Tattach = 104; -Rattach = 105; -Terror = 106; -Rerror = 107; -Tflush = 108; -Rflush = 109; -Twalk = 110; -Rwalk = 111; -Topen = 112; -Ropen = 113; -Tcreate = 114; -Rcreate = 115; -Tread = 116; -Rread = 117; -Twrite = 118; -Rwrite = 119; -Tclunk = 120; -Rclunk = 121; -Tremove = 122; -Rremove = 123; -Tstat = 124; -Rstat = 125; -Twstat = 126; -Rwstat = 127; -Tmax = 128; -sizeofFid = 60; -aggr Fid -{ - 'U' 0 fid; - 'C' 4 omode; - 'X' 8 file; - 'X' 12 uid; - Qid 16 qid; - 'X' 32 aux; - 'X' 36 rdir; - Ref 40 ref; - 'X' 44 pool; - 'V' 48 diroffset; - 'D' 56 dirindex; -}; - -defn -Fid(addr) { - complex Fid addr; - print(" fid ", addr.fid, "\n"); - print(" omode ", addr.omode, "\n"); - print(" file ", addr.file\X, "\n"); - print(" uid ", addr.uid\X, "\n"); - print("Qid qid {\n"); - Qid(addr.qid); - print("}\n"); - print(" aux ", addr.aux\X, "\n"); - print(" rdir ", addr.rdir\X, "\n"); - print("Ref ref {\n"); - Ref(addr.ref); - print("}\n"); - print(" pool ", addr.pool\X, "\n"); - print(" diroffset ", addr.diroffset, "\n"); - print(" dirindex ", addr.dirindex, "\n"); -}; - -sizeofReq = 656; -aggr Req -{ - 'U' 0 tag; - 'X' 4 aux; - Fcall 8 ifcall; - Fcall 280 ofcall; - Dir 552 d; - 'A' Req 612 oldreq; - 'A' Fid 616 fid; - 'A' Fid 620 afid; - 'A' Fid 624 newfid; - 'X' 628 srv; - Ref 632 ref; - 'X' 636 pool; - 'X' 640 buf; - 'b' 644 type; - 'b' 645 responded; - 'X' 648 error; - 'X' 652 rbuf; -}; - -defn -Req(addr) { - complex Req addr; - print(" tag ", addr.tag, "\n"); - print(" aux ", addr.aux\X, "\n"); - print("Fcall ifcall {\n"); - Fcall(addr.ifcall); - print("}\n"); - print("Fcall ofcall {\n"); - Fcall(addr.ofcall); - print("}\n"); - print("Dir d {\n"); - Dir(addr.d); - print("}\n"); - print(" oldreq ", addr.oldreq\X, "\n"); - print(" fid ", addr.fid\X, "\n"); - print(" afid ", addr.afid\X, "\n"); - print(" newfid ", addr.newfid\X, "\n"); - print(" srv ", addr.srv\X, "\n"); - print("Ref ref {\n"); - Ref(addr.ref); - print("}\n"); - print(" pool ", addr.pool\X, "\n"); - print(" buf ", addr.buf\X, "\n"); - print(" type ", addr.type, "\n"); - print(" responded ", addr.responded, "\n"); - print(" error ", addr.error\X, "\n"); - print(" rbuf ", addr.rbuf\X, "\n"); -}; - -sizeofFidpool = 12; -aggr Fidpool -{ - 'X' 0 map; - 'X' 4 destroy; - 'X' 8 srv; -}; - -defn -Fidpool(addr) { - complex Fidpool addr; - print(" map ", addr.map\X, "\n"); - print(" destroy ", addr.destroy\X, "\n"); - print(" srv ", addr.srv\X, "\n"); -}; - -sizeofReqpool = 12; -aggr Reqpool -{ - 'X' 0 map; - 'X' 4 destroy; - 'X' 8 srv; -}; - -defn -Reqpool(addr) { - complex Reqpool addr; - print(" map ", addr.map\X, "\n"); - print(" destroy ", addr.destroy\X, "\n"); - print(" srv ", addr.srv\X, "\n"); -}; - -sizeofFile = 108; -aggr File -{ - { - 'D' 0 ref; - }; - { - 'u' 4 type; - 'U' 8 dev; - Qid 12 qid; - 'U' 28 mode; - 'U' 32 atime; - 'U' 36 mtime; - 'V' 40 length; - 'X' 48 name; - 'X' 52 uid; - 'X' 56 gid; - 'X' 60 muid; - }; - 'A' File 64 parent; - 'X' 68 aux; - { - Lock 72 lock; - 'D' 76 readers; - 'D' 80 writer; - 'A' QLp 84 $head; - 'A' QLp 88 $tail; - }; - 'X' 92 filelist; - 'X' 96 tree; - 'D' 100 nchild; - 'D' 104 allocd; -}; - -defn -File(addr) { - complex File addr; - print("Ref {\n"); - Ref(addr+0); - print("}\n"); - print("Dir {\n"); - Dir(addr+4); - print("}\n"); - print(" parent ", addr.parent\X, "\n"); - print(" aux ", addr.aux\X, "\n"); - print("RWLock {\n"); - RWLock(addr+72); - print("}\n"); - print(" filelist ", addr.filelist\X, "\n"); - print(" tree ", addr.tree\X, "\n"); - print(" nchild ", addr.nchild, "\n"); - print(" allocd ", addr.allocd, "\n"); -}; - -sizeofTree = 20; -aggr Tree -{ - 'A' File 0 root; - 'X' 4 destroy; - Lock 8 genlock; - 'U' 12 qidgen; - 'U' 16 dirqidgen; -}; - -defn -Tree(addr) { - complex Tree addr; - print(" root ", addr.root\X, "\n"); - print(" destroy ", addr.destroy\X, "\n"); - print("Lock genlock {\n"); - Lock(addr.genlock); - print("}\n"); - print(" qidgen ", addr.qidgen, "\n"); - print(" dirqidgen ", addr.dirqidgen, "\n"); -}; - -sizeofSrv = 136; -aggr Srv -{ - 'A' Tree 0 tree; - 'X' 4 destroyfid; - 'X' 8 destroyreq; - 'X' 12 end; - 'X' 16 aux; - 'X' 20 attach; - 'X' 24 auth; - 'X' 28 open; - 'X' 32 create; - 'X' 36 read; - 'X' 40 write; - 'X' 44 remove; - 'X' 48 flush; - 'X' 52 stat; - 'X' 56 wstat; - 'X' 60 walk; - 'X' 64 clone; - 'X' 68 walk1; - 'D' 72 infd; - 'D' 76 outfd; - 'D' 80 nopipe; - 'A' Fidpool 84 fpool; - 'A' Reqpool 88 rpool; - 'U' 92 msize; - 'X' 96 rbuf; - QLock 100 rlock; - 'X' 116 wbuf; - QLock 120 wlock; -}; - -defn -Srv(addr) { - complex Srv addr; - print(" tree ", addr.tree\X, "\n"); - print(" destroyfid ", addr.destroyfid\X, "\n"); - print(" destroyreq ", addr.destroyreq\X, "\n"); - print(" end ", addr.end\X, "\n"); - print(" aux ", addr.aux\X, "\n"); - print(" attach ", addr.attach\X, "\n"); - print(" auth ", addr.auth\X, "\n"); - print(" open ", addr.open\X, "\n"); - print(" create ", addr.create\X, "\n"); - print(" read ", addr.read\X, "\n"); - print(" write ", addr.write\X, "\n"); - print(" remove ", addr.remove\X, "\n"); - print(" flush ", addr.flush\X, "\n"); - print(" stat ", addr.stat\X, "\n"); - print(" wstat ", addr.wstat\X, "\n"); - print(" walk ", addr.walk\X, "\n"); - print(" clone ", addr.clone\X, "\n"); - print(" walk1 ", addr.walk1\X, "\n"); - print(" infd ", addr.infd, "\n"); - print(" outfd ", addr.outfd, "\n"); - print(" nopipe ", addr.nopipe, "\n"); - print(" fpool ", addr.fpool\X, "\n"); - print(" rpool ", addr.rpool\X, "\n"); - print(" msize ", addr.msize, "\n"); - print(" rbuf ", addr.rbuf\X, "\n"); - print("QLock rlock {\n"); - QLock(addr.rlock); - print("}\n"); - print(" wbuf ", addr.wbuf\X, "\n"); - print("QLock wlock {\n"); - QLock(addr.wlock); - print("}\n"); -}; - -OMASK = 3; -Maxname = 128; -Maxrpc = 4096; -Notstarted = -3; -Broken = -2; -Established = -1; -RpcFailure = 0; -RpcNeedkey = 1; -RpcOk = 2; -RpcErrstr = 3; -RpcToosmall = 4; -RpcPhase = 5; -sizeofAttr = 12; -aggr Attr -{ - 'A' Attr 0 next; - 'A' String 4 name; - 'A' String 8 val; -}; - -defn -Attr(addr) { - complex Attr addr; - print(" next ", addr.next\X, "\n"); - print(" name ", addr.name\X, "\n"); - print(" val ", addr.val\X, "\n"); -}; - -sizeof_14_ = 4120; -aggr _14_ -{ - 'X' 0 arg; - 'a' 4 buf; - 'X' 4100 verb; - 'D' 4104 iverb; - 'D' 4108 narg; - 'D' 4112 nbuf; - 'D' 4116 nwant; -}; - -defn -_14_(addr) { - complex _14_ addr; - print(" arg ", addr.arg\X, "\n"); - print(" buf ", addr.buf, "\n"); - print(" verb ", addr.verb\X, "\n"); - print(" iverb ", addr.iverb, "\n"); - print(" narg ", addr.narg, "\n"); - print(" nbuf ", addr.nbuf, "\n"); - print(" nwant ", addr.nwant, "\n"); -}; - -sizeofFsstate = 4700; -aggr Fsstate -{ - 'X' 0 sysuser; - 'D' 4 listoff; - _14_ 8 rpc; - 'a' 4128 err; - 'a' 4256 keyinfo; - 'X' 4640 phasename; - 'D' 4644 isclient; - 'D' 4648 haveai; - 'D' 4652 maxphase; - 'D' 4656 phase; - 'D' 4660 started; - 'A' Attr 4664 attr; - AuthInfo 4668 ai; - 'X' 4688 proto; - 'X' 4692 ps; - 'X' 4696 ring; -}; - -defn -Fsstate(addr) { - complex Fsstate addr; - print(" sysuser ", addr.sysuser\X, "\n"); - print(" listoff ", addr.listoff, "\n"); - print("_14_ rpc {\n"); - _14_(addr.rpc); - print("}\n"); - print(" err ", addr.err, "\n"); - print(" keyinfo ", addr.keyinfo, "\n"); - print(" phasename ", addr.phasename\X, "\n"); - print(" isclient ", addr.isclient, "\n"); - print(" haveai ", addr.haveai, "\n"); - print(" maxphase ", addr.maxphase, "\n"); - print(" phase ", addr.phase, "\n"); - print(" started ", addr.started, "\n"); - print(" attr ", addr.attr\X, "\n"); - print("AuthInfo ai {\n"); - AuthInfo(addr.ai); - print("}\n"); - print(" proto ", addr.proto\X, "\n"); - print(" ps ", addr.ps\X, "\n"); - print(" ring ", addr.ring\X, "\n"); -}; - -sizeofKey = 20; -aggr Key -{ - 'D' 0 ref; - 'A' Attr 4 attr; - 'A' Attr 8 privattr; - 'X' 12 proto; - 'X' 16 priv; -}; - -defn -Key(addr) { - complex Key addr; - print(" ref ", addr.ref, "\n"); - print(" attr ", addr.attr\X, "\n"); - print(" privattr ", addr.privattr\X, "\n"); - print(" proto ", addr.proto\X, "\n"); - print(" priv ", addr.priv\X, "\n"); -}; - -sizeofKeyring = 8; -aggr Keyring -{ - 'A' Key 0 key; - 'D' 4 nkey; -}; - -defn -Keyring(addr) { - complex Keyring addr; - print(" key ", addr.key\X, "\n"); - print(" nkey ", addr.nkey, "\n"); -}; - -sizeofLogbuf = 520; -aggr Logbuf -{ - 'D' 0 rp; - 'D' 4 wp; - 'a' 8 msg; -}; - -defn -Logbuf(addr) { - complex Logbuf addr; - print(" rp ", addr.rp, "\n"); - print(" wp ", addr.wp, "\n"); - print(" msg ", addr.msg, "\n"); -}; - -sizeofProto = 28; -aggr Proto -{ - 'X' 0 name; - 'X' 4 init; - 'X' 8 addkey; - 'X' 12 closekey; - 'X' 16 write; - 'X' 20 read; - 'X' 24 close; -}; - -defn -Proto(addr) { - complex Proto addr; - print(" name ", addr.name\X, "\n"); - print(" init ", addr.init\X, "\n"); - print(" addkey ", addr.addkey\X, "\n"); - print(" closekey ", addr.closekey\X, "\n"); - print(" write ", addr.write\X, "\n"); - print(" read ", addr.read\X, "\n"); - print(" close ", addr.close\X, "\n"); -}; - -complex Keyring ring; -complex Logbuf logbuf; -complex Proto apop; -complex Proto cram; -complex Proto p9any; -complex Proto p9sk1; -complex Proto p9sk2; -complex Keyring ring; -complex Srv fs; -complex Proto main:p; -Qroot = 0; -Qfactotum = 1; -Qrpc = 2; -Qkeylist = 3; -Qprotolist = 4; -Qconfirm = 5; -Qlog = 6; -Qctl = 7; -complex Qid mkqid:q; -complex Req fsattach:r; -sizeof_15_ = 12; -aggr _15_ -{ - 'X' 0 name; - 'D' 4 qidpath; - 'U' 8 perm; -}; - -defn -_15_(addr) { - complex _15_ addr; - print(" name ", addr.name\X, "\n"); - print(" qidpath ", addr.qidpath, "\n"); - print(" perm ", addr.perm, "\n"); -}; - -complex Dir fillstat:dir; -complex Dir fsdirgen:dir; -complex Fid fswalk1:fid; -complex Qid fswalk1:qid; -complex Req fsstat:r; -complex Req fsopen:r; -complex Fsstate fsopen:fss; -complex Fid fsdestroyfid:fid; -complex Req readlist:r; -complex Key keylist:k; -complex Req fsread:r; -complex Fsstate fsread:s; -complex Req fswrite:r; -complex Srv fs; blob - f9ad785be85abca7d31c939827ad8b9617240f97 (mode 644) blob + /dev/null --- src/cmd/factotum/fs.c +++ /dev/null @@ -1,531 +0,0 @@ -#include "std.h" -#include "dat.h" - -enum -{ - Qroot, - Qfactotum, - Qrpc, - Qkeylist, - Qprotolist, - Qconfirm, - Qlog, - Qctl, - Qneedkey, - Qconv, -}; - -static int qtop; - -Qid -mkqid(int type, int path) -{ - Qid q; - - q.type = type; - q.path = path; - q.vers = 0; - return q; -} - -static struct -{ - char *name; - int qidpath; - ulong perm; -} dirtab[] = { - /* positions of confirm and needkey known below */ - "confirm", Qconfirm, 0600|DMEXCL, - "needkey", Qneedkey, 0600|DMEXCL, - "ctl", Qctl, 0600, - "rpc", Qrpc, 0666, - "proto", Qprotolist, 0444, - "log", Qlog, 0600|DMEXCL, - "conv", Qconv, 0400, -}; - -static void -fillstat(Dir *dir, char *name, int type, int path, ulong perm) -{ - dir->name = estrdup(name); - dir->uid = estrdup(owner); - dir->gid = estrdup(owner); - dir->mode = perm; - dir->length = 0; - dir->qid = mkqid(type, path); - dir->atime = time(0); - dir->mtime = time(0); - dir->muid = estrdup(""); -} - -static int -rootdirgen(int n, Dir *dir, void *v) -{ - USED(v); - - if(n > 0) - return -1; - - fillstat(dir, factname, QTDIR, Qfactotum, DMDIR|0555); - return 0; -} - -static int -fsdirgen(int n, Dir *dir, void *v) -{ - USED(v); - - if(n >= nelem(dirtab)) - return -1; - fillstat(dir, dirtab[n].name, 0, dirtab[n].qidpath, dirtab[n].perm); - return 0; -} - -static char* -fswalk1(Fid *fid, char *name, Qid *qid) -{ - int i; - - switch((int)fid->qid.path){ - default: - return "fswalk1: cannot happen"; - case Qroot: - if(strcmp(name, factname) == 0){ - *qid = mkqid(QTDIR, Qfactotum); - fid->qid = *qid; - return nil; - } - if(strcmp(name, "..") == 0){ - *qid = fid->qid; - return nil; - } - return "not found"; - case Qfactotum: - for(i=0; iqid = *qid; - return nil; - } - if(strcmp(name, "..") == 0){ - *qid = mkqid(QTDIR, qtop); - fid->qid = *qid; - return nil; - } - return "not found"; - } -} - -static void -fsstat(Req *r) -{ - int i, path; - - path = r->fid->qid.path; - switch(path){ - case Qroot: - fillstat(&r->d, "/", QTDIR, Qroot, 0555|DMDIR); - break; - case Qfactotum: - fillstat(&r->d, "factotum", QTDIR, Qfactotum, 0555|DMDIR); - break; - default: - for(i=0; id, dirtab[i].name, 0, dirtab[i].qidpath, dirtab[i].perm); - goto Break2; - } - respond(r, "file not found"); - break; - } - Break2: - respond(r, nil); -} - -static int -readlist(int off, int (*gen)(int, char*, uint), Req *r) -{ - char *a, *ea; - int n; - - a = r->ofcall.data; - ea = a+r->ifcall.count; - for(;;){ - n = (*gen)(off, a, ea-a); - if(n == 0){ - r->ofcall.count = a - (char*)r->ofcall.data; - return off; - } - a += n; - off++; - } - return -1; /* not reached */ -} - -static int -keylist(int i, char *a, uint nn) -{ - int n; - char buf[512]; - Key *k; - - if(i >= ring.nkey) - return 0; - - k = ring.key[i]; - k->attr = sortattr(k->attr); - n = snprint(buf, sizeof buf, "key %A %N\n", k->attr, k->privattr); - if(n >= sizeof(buf)-5) - strcpy(buf+sizeof(buf)-5, "...\n"); - n = strlen(buf); - if(n > nn) - return 0; - memmove(a, buf, n); - return n; -} - -static int -protolist(int i, char *a, uint n) -{ - if(prototab[i] == nil) - return 0; - if(strlen(prototab[i]->name)+1 > n) - return 0; - n = strlen(prototab[i]->name)+1; - memmove(a, prototab[i]->name, n-1); - a[n-1] = '\n'; - return n; -} - -/* BUG this is O(n^2) to fill in the list */ -static int -convlist(int i, char *a, uint nn) -{ - Conv *c; - char buf[512]; - int n; - - for(c=conv; c && i-- > 0; c=c->next) - ; - - if(c == nil) - return 0; - - if(c->state) - n = snprint(buf, sizeof buf, "conv state=%q %A\n", c->state, c->attr); - else - n = snprint(buf, sizeof buf, "conv state=closed err=%q\n", c->err); - - if(n >= sizeof(buf)-5) - strcpy(buf+sizeof(buf)-5, "...\n"); - n = strlen(buf); - if(n > nn) - return 0; - memmove(a, buf, n); - return n; -} - -static void -fskickreply(Conv *c) -{ - Req *r; - - if(c->hangup){ - if(c->req){ - respond(c->req, "hangup"); - c->req = nil; - } - return; - } - - if(!c->req || !c->nreply) - return; - - r = c->req; - r->ofcall.count = c->nreply; - r->ofcall.data = c->reply; - if(r->ofcall.count > r->ifcall.count) - r->ofcall.count = r->ifcall.count; - respond(r, nil); - c->req = nil; - c->nreply = 0; -} - -/* - * Some of the file system work happens in the fs proc, but - * fsopen, fsread, fswrite, fsdestroyfid, and fsflush happen in - * the main proc so that they can access the various shared - * data structures without worrying about locking. - */ -static int inuse[nelem(dirtab)]; -int *confirminuse = &inuse[0]; -int *needkeyinuse = &inuse[1]; -static void -fsopen(Req *r) -{ - int i, *inusep, perm; - static int need[4] = { 4, 2, 6, 1 }; - Conv *c; - - inusep = nil; - perm = 5; /* directory */ - for(i=0; ifid->qid.path){ - if(dirtab[i].perm & DMEXCL) - inusep = &inuse[i]; - if(strcmp(r->fid->uid, owner) == 0) - perm = dirtab[i].perm>>6; - else - perm = dirtab[i].perm; - break; - } - - if((r->ifcall.mode&~(OMASK|OTRUNC)) - || (need[r->ifcall.mode&3] & ~perm)){ - respond(r, "permission denied"); - return; - } - - if(inusep){ - if(*inusep){ - respond(r, "file in use"); - return; - } - *inusep = 1; - } - - if(r->fid->qid.path == Qrpc){ - if((c = convalloc(r->fid->uid)) == nil){ - char e[ERRMAX]; - - rerrstr(e, sizeof e); - respond(r, e); - return; - } - c->kickreply = fskickreply; - r->fid->aux = c; - } - - respond(r, nil); -} - -static void -fsread(Req *r) -{ - Conv *c; - - switch((int)r->fid->qid.path){ - default: - respond(r, "fsread: cannot happen"); - break; - case Qroot: - dirread9p(r, rootdirgen, nil); - respond(r, nil); - break; - case Qfactotum: - dirread9p(r, fsdirgen, nil); - respond(r, nil); - break; - case Qrpc: - c = r->fid->aux; - if(c->rpc.op == RpcUnknown){ - respond(r, "no rpc pending"); - break; - } - if(c->req){ - respond(r, "read already pending"); - break; - } - c->req = r; - if(c->nreply) - (*c->kickreply)(c); - else - rpcexec(c); - break; - case Qconfirm: - confirmread(r); - break; - case Qlog: - logread(r); - break; - case Qctl: - r->fid->aux = (void*)readlist((int)r->fid->aux, keylist, r); - respond(r, nil); - break; - case Qneedkey: - needkeyread(r); - break; - case Qprotolist: - r->fid->aux = (void*)readlist((int)r->fid->aux, protolist, r); - respond(r, nil); - break; - case Qconv: - r->fid->aux = (void*)readlist((int)r->fid->aux, convlist, r); - respond(r, nil); - break; - } -} - -static void -fswrite(Req *r) -{ - int ret; - char err[ERRMAX], *s; - int (*strfn)(char*); - - switch((int)r->fid->qid.path){ - default: - respond(r, "fswrite: cannot happen"); - break; - case Qrpc: - if(rpcwrite(r->fid->aux, r->ifcall.data, r->ifcall.count) < 0){ - rerrstr(err, sizeof err); - respond(r, err); - }else{ - r->ofcall.count = r->ifcall.count; - respond(r, nil); - } - break; - case Qneedkey: - strfn = needkeywrite; - goto string; - case Qctl: - strfn = ctlwrite; - goto string; - case Qconfirm: - strfn = confirmwrite; - string: - s = emalloc(r->ifcall.count+1); - memmove(s, r->ifcall.data, r->ifcall.count); - s[r->ifcall.count] = '\0'; - ret = (*strfn)(s); - free(s); - if(ret < 0){ - rerrstr(err, sizeof err); - respond(r, err); - }else{ - r->ofcall.count = r->ifcall.count; - respond(r, nil); - } - break; - } -} - -static void -fsflush(Req *r) -{ - confirmflush(r); - logflush(r); -} - -static void -fsdestroyfid(Fid *fid) -{ - if(fid->qid.path == Qrpc && fid->aux){ - convhangup(fid->aux); - convclose(fid->aux); - } -} - -static Channel *creq; -static Channel *cfid, *cfidr; - -static void -fsreqthread(void *v) -{ - Req *r; - - USED(v); - - while((r = recvp(creq)) != nil){ - switch(r->ifcall.type){ - default: - respond(r, "bug in fsreqthread"); - break; - case Topen: - fsopen(r); - break; - case Tread: - fsread(r); - break; - case Twrite: - fswrite(r); - break; - case Tflush: - fsflush(r); - break; - } - } -} - -static void -fsclunkthread(void *v) -{ - Fid *f; - - USED(v); - - while((f = recvp(cfid)) != nil){ - fsdestroyfid(f); - sendp(cfidr, 0); - } -} - -static void -fsproc(void *v) -{ - USED(v); - - threadcreate(fsreqthread, nil, STACK); - threadcreate(fsclunkthread, nil, STACK); - threadexits(nil); -} - -static void -fsattach(Req *r) -{ - r->fid->qid = mkqid(QTDIR, qtop); - r->ofcall.qid = r->fid->qid; - respond(r, nil); -} - -static void -fssend(Req *r) -{ - sendp(creq, r); -} - -static void -fssendclunk(Fid *f) -{ - sendp(cfid, f); - recvp(cfidr); -} - -void -fsstart(Srv *s) -{ - USED(s); - - if(extrafactotumdir) - qtop = Qroot; - else - qtop = Qfactotum; - creq = chancreate(sizeof(Req*), 0); - cfid = chancreate(sizeof(Fid*), 0); - cfidr = chancreate(sizeof(Fid*), 0); - proccreate(fsproc, nil, STACK); -} - -Srv fs = { -.attach= fsattach, -.walk1= fswalk1, -.open= fssend, -.read= fssend, -.write= fssend, -.stat= fsstat, -.flush= fssend, -.destroyfid= fssendclunk, -.start= fsstart, -}; - blob - 7293e54b63e77381e187e4e86d8db5cd28f9d9bd (mode 755) blob + /dev/null --- src/cmd/factotum/guide +++ /dev/null @@ -1,3 +0,0 @@ -kill 8.out|rc -unmount /srv/factotum /mnt -8.out blob - 72f245d0e3d52b86bc84284a3eb4b088057173fb (mode 644) blob + /dev/null --- src/cmd/factotum/guide2 +++ /dev/null @@ -1,6 +0,0 @@ -kill 8.out|rc -unmount /mnt/factotum -8.out -m /mnt/factotum -cat /mnt/factotum/log & -unmount /factotum -bind 8.out /factotum blob - 9023fed509e1bcd4e560efb778f077c322f35cdd (mode 644) blob + /dev/null --- src/cmd/factotum/key.c +++ /dev/null @@ -1,190 +0,0 @@ -#include "std.h" -#include "dat.h" - -Ring ring; - -Key* -keylookup(char *fmt, ...) -{ - int i; - Attr *a; - Key *k; - va_list arg; - - va_start(arg, fmt); - a = parseattrfmtv(fmt, arg); - va_end(arg); - - for(i=0; iattr, k->privattr)){ - k->ref++; - freeattr(a); - return k; - } - } - freeattr(a); - werrstr("no key found"); - return nil; -} - -Key* -keyfetch(Conv *c, char *fmt, ...) -{ - int i, tag; - Attr *a; - Key *k; - va_list arg; - - va_start(arg, fmt); - a = parseattrfmtv(fmt, arg); - va_end(arg); - - tag = 0; - - for(i=0; itag) - tag = k->tag; - if(matchattr(a, k->attr, k->privattr)){ - k->ref++; - if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){ - k->ref--; - continue; - } - freeattr(a); - return k; - } - } - - if(needkey(c, a) < 0) - convneedkey(c, a); - - for(i=0; itag <= tag) - continue; - if(matchattr(a, k->attr, k->privattr)){ - k->ref++; - if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){ - k->ref--; - continue; - } - freeattr(a); - return k; - } - } - freeattr(a); - werrstr("no key found"); - return nil; -} - -static int taggen; - -void -keyadd(Key *k) -{ - int i; - - k->ref++; - k->tag = ++taggen; - for(i=0; iattr, ring.key[i]->attr, nil) - && matchattr(ring.key[i]->attr, k->attr, nil)){ - keyclose(ring.key[i]); - ring.key[i] = k; - return; - } - } - - ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0])); - ring.key[ring.nkey++] = k; -} - -void -keyclose(Key *k) -{ - if(k == nil) - return; - - if(--k->ref > 0) - return; - - if(k->proto->closekey) - (*k->proto->closekey)(k); - - freeattr(k->attr); - freeattr(k->privattr); - free(k); -} - -Key* -keyreplace(Conv *c, Key *k, char *fmt, ...) -{ - Key *kk; - char *msg; - Attr *a, *b, *bp; - va_list arg; - - va_start(arg, fmt); - msg = vsmprint(fmt, arg); - if(msg == nil) - sysfatal("out of memory"); - va_end(arg); - - /* replace prompted values with prompts */ - a = copyattr(k->attr); - bp = parseattr(k->proto->keyprompt); - for(b=bp; b; b=b->next){ - a = delattr(a, b->name); - a = addattr(a, "%q?", b->name); - } - freeattr(bp); - - if(badkey(c, k, msg, a) < 0) - convbadkey(c, k, msg, a); - kk = keylookup("%A", a); - freeattr(a); - keyclose(k); - if(kk == k){ - keyclose(kk); - werrstr("%s", msg); - return nil; - } - - if(strfindattr(kk->attr, "confirm")){ - if(confirmkey(c, kk) != 1){ - werrstr("key use not confirmed"); - keyclose(kk); - return nil; - } - } - return kk; -} - -void -keyevict(Conv *c, Key *k, char *fmt, ...) -{ - char *msg; - Attr *a, *b, *bp; - va_list arg; - - va_start(arg, fmt); - msg = vsmprint(fmt, arg); - if(msg == nil) - sysfatal("out of memory"); - va_end(arg); - - /* replace prompted values with prompts */ - a = copyattr(k->attr); - bp = parseattr(k->proto->keyprompt); - for(b=bp; b; b=b->next){ - a = delattr(a, b->name); - a = addattr(a, "%q?", b->name); - } - freeattr(bp); - - if(badkey(c, k, msg, nil) < 0) - convbadkey(c, k, msg, nil); - keyclose(k); -} blob - 6c2d69ddbf6a5d152737ebbb1ef680f8a42eab2f (mode 644) blob + /dev/null --- src/cmd/factotum/log.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "std.h" -#include "dat.h" - -void -lbkick(Logbuf *lb) -{ - char *s; - int n; - Req *r; - - while(lb->wait && lb->rp != lb->wp){ - r = lb->wait; - lb->wait = r->aux; - if(lb->wait == nil) - lb->waitlast = &lb->wait; - r->aux = nil; - if(r->ifcall.count < 5){ - respond(r, "factotum: read request count too short"); - continue; - } - s = lb->msg[lb->rp]; - lb->msg[lb->rp] = nil; - if(++lb->rp == nelem(lb->msg)) - lb->rp = 0; - n = r->ifcall.count; - if(n < strlen(s)+1+1){ - memmove(r->ofcall.data, s, n-5); - n -= 5; - r->ofcall.data[n] = '\0'; - /* look for first byte of UTF-8 sequence by skipping continuation bytes */ - while(n>0 && (r->ofcall.data[--n]&0xC0)==0x80) - ; - strcpy(r->ofcall.data+n, "...\n"); - }else{ - strcpy(r->ofcall.data, s); - strcat(r->ofcall.data, "\n"); - } - r->ofcall.count = strlen(r->ofcall.data); - free(s); - respond(r, nil); - } -} - -void -lbread(Logbuf *lb, Req *r) -{ - if(lb->waitlast == nil) - lb->waitlast = &lb->wait; - *(lb->waitlast) = r; - lb->waitlast = (Req**)&r->aux; - r->aux = nil; - lbkick(lb); -} - -void -lbflush(Logbuf *lb, Req *r) -{ - Req **l; - - for(l=&lb->wait; *l; l=(Req**)&(*l)->aux){ - if(*l == r){ - *l = r->aux; - r->aux = nil; - if(*l == nil) - lb->waitlast = l; - closereq(r); - break; - } - } -} - -void -lbappend(Logbuf *lb, char *fmt, ...) -{ - va_list arg; - - va_start(arg, fmt); - lbvappend(lb, fmt, arg); - va_end(arg); -} - -void -lbvappend(Logbuf *lb, char *fmt, va_list arg) -{ - char *s; - - s = smprint(fmt, arg); - if(s == nil) - sysfatal("out of memory"); - if(lb->msg[lb->wp]) - free(lb->msg[lb->wp]); - lb->msg[lb->wp] = s; - if(++lb->wp == nelem(lb->msg)) - lb->wp = 0; - lbkick(lb); -} - -Logbuf logbuf; - -void -logread(Req *r) -{ - lbread(&logbuf, r); -} - -void -logflush(Req *r) -{ - lbflush(&logbuf, r); -} - -void -flog(char *fmt, ...) -{ - va_list arg; - - va_start(arg, fmt); - lbvappend(&logbuf, fmt, arg); - va_end(arg); -} - blob - dbcfa5fe67bd96986dd86fc1798e426e79f09b67 (mode 644) blob + /dev/null --- src/cmd/factotum/main.c +++ /dev/null @@ -1,185 +0,0 @@ -#include "std.h" -#include "dat.h" -#include <9pclient.h> - -int extrafactotumdir; -int debug; -int trysecstore = 1; -char *factname = "factotum"; -char *service = "factotum"; -char *owner; -char *authaddr; -void gflag(char*); - -void -usage(void) -{ - fprint(2, "usage: factotum [-Dd] [-a authaddr] [-m mtpt] [-s service]\n"); - fprint(2, " or factotum -g keypattern\n"); - fprint(2, " or factotum -g 'badkeyattr\\nmsg\\nkeypattern'\n"); - threadexitsall("usage"); -} - -void -threadmain(int argc, char *argv[]) -{ - char *mtpt; - char err[ERRMAX]; - -// mtpt = "/mnt"; - mtpt = nil; - owner = getuser(); - quotefmtinstall(); - fmtinstall('A', attrfmt); - fmtinstall('H', encodefmt); - fmtinstall('N', attrnamefmt); - - if(argc == 3 && strcmp(argv[1], "-g") == 0){ - gflag(argv[2]); - threadexitsall(nil); - } - - ARGBEGIN{ - default: - usage(); - case 'D': - chatty9p++; - break; - case 'a': - authaddr = EARGF(usage()); - break; - case 'g': - usage(); - case 'm': - mtpt = EARGF(usage()); - break; - case 's': - service = EARGF(usage()); - break; - case 'n': - trysecstore = 0; - break; - case 'x': - extrafactotumdir = 1; - break; - }ARGEND - - if(argc != 0) - usage(); - - if(trysecstore && havesecstore()){ - while(secstorefetch() < 0){ - rerrstr(err, sizeof err); - if(strcmp(err, "cancel") == 0) - break; - fprint(2, "secstorefetch: %r\n"); - fprint(2, "Enter an empty password to quit.\n"); - } - } - - threadpostmountsrv(&fs, service, mtpt, MBEFORE); - threadexits(nil); -} - -/* - * prompt user for a key. don't care about memory leaks, runs standalone - */ -static Attr* -promptforkey(int fd, char *params) -{ - char *v; - Attr *a, *attr; - char *def; - - attr = _parseattr(params); - fprint(fd, "!adding key:"); - for(a=attr; a; a=a->next) - if(a->type != AttrQuery && a->name[0] != '!') - fprint(fd, " %q=%q", a->name, a->val); - fprint(fd, "\n"); - - for(a=attr; a; a=a->next){ - v = a->name; - if(a->type != AttrQuery || v[0]=='!') - continue; - def = nil; - if(strcmp(v, "user") == 0) - def = getuser(); - a->val = readcons(v, def, 0); - if(a->val == nil) - sysfatal("user terminated key input"); - a->type = AttrNameval; - } - for(a=attr; a; a=a->next){ - v = a->name; - if(a->type != AttrQuery || v[0]!='!') - continue; - def = nil; - if(strcmp(v+1, "user") == 0) - def = getuser(); - a->val = readcons(v+1, def, 1); - if(a->val == nil) - sysfatal("user terminated key input"); - a->type = AttrNameval; - } - fprint(fd, "!\n"); - close(fd); - return attr; -} - -/* - * send a key to the mounted factotum - */ -static int -sendkey(Attr *attr) -{ - int rv; - char buf[1024]; - CFid *fid; - - fid = nsopen("factotum", nil, "ctl", OWRITE); - if(fid == nil) - sysfatal("opening factotum/ctl: %r"); - snprint(buf, sizeof buf, "key %A\n", attr); - rv = fswrite(fid, buf, strlen(buf)); - fsclose(fid); - return rv; -} - -static void -askuser(int fd, char *params) -{ - Attr *attr; - - attr = promptforkey(fd, params); - if(attr == nil) - sysfatal("no key supplied"); - if(sendkey(attr) < 0) - sysfatal("sending key to factotum: %r"); -} - -void -gflag(char *s) -{ - char *f[4]; - int nf; - int fd; - - if((fd = open("/dev/tty", ORDWR)) < 0) - sysfatal("open /dev/tty: %r"); - - nf = getfields(s, f, nelem(f), 0, "\n"); - if(nf == 1){ /* needkey or old badkey */ - fprint(fd, "\n"); - askuser(fd, s); - threadexitsall(nil); - } - if(nf == 3){ /* new badkey */ - fprint(fd, "\n"); - fprint(fd, "!replace: %s\n", f[0]); - fprint(fd, "!because: %s\n", f[1]); - askuser(fd, f[2]); - threadexitsall(nil); - } - usage(); -} blob - 1d48e6a4950c021a827d0cea68fca704f4efa975 (mode 644) blob + /dev/null --- src/cmd/factotum/mkfile +++ /dev/null @@ -1,33 +0,0 @@ -<$PLAN9/src/mkhdr - -TARG=factotum -PROTO=\ - apop.$O\ - chap.$O\ - p9any.$O\ - p9sk1.$O\ - -OFILES=\ - $PROTO\ - attr.$O\ - confirm.$O\ - conv.$O\ - ctl.$O\ - fs.$O\ - key.$O\ - log.$O\ - main.$O\ - plan9.$O\ - proto.$O\ - rpc.$O\ - util.$O\ - xio.$O\ - secstore.$O\ - -HFILES=dat.h - -<$PLAN9/src/mkone - -$O.test: test.$O - $LD -o $target $prereq - blob - 0006cad1833979af04d9ef5ff78e594510a881a2 (mode 644) blob + /dev/null --- src/cmd/factotum/p9any.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "std.h" -#include "dat.h" - -/* - * p9any - protocol negotiator - * - * Protocol: - * S->C: v.2 proto@dom proto@dom proto@dom... NUL - * C->S: proto dom NUL - * [negotiated proto continues] - */ - -static Proto* okproto[] = -{ - &p9sk1, - nil, -}; - -static int -rolecall(Role *r, char *name, Conv *c) -{ - for(; r->name; r++) - if(strcmp(r->name, name) == 0) - return (*r->fn)(c); - werrstr("unknown role"); - return -1; -} - -static int -hasnul(void *v, int n) -{ - char *c; - - c = v; - if(n > 0 && c[n-1] == '\0') - return n; - else - return AuthRpcMax; -} - -static int -p9anyserver(Conv *c) -{ - char *s, *dom; - int i, j, n, m, ret; - char *tok[3]; - Attr *attr; - Key *k; - - ret = -1; - s = estrdup("v.2"); - n = 0; - attr = delattr(copyattr(c->attr), "proto"); - - for(i=0; iproto == okproto[j] - && (dom = strfindattr(k->attr, "dom")) != nil - && matchattr(attr, k->attr, k->privattr)){ - s = estrappend(s, " %s@%s", k->proto->name, dom); - n++; - } - } - - if(n == 0){ - werrstr("no valid keys"); - goto out; - } - - c->state = "write offer"; - if(convwrite(c, s, strlen(s)+1) < 0) - goto out; - free(s); - s = nil; - - c->state = "read choice"; - if(convreadfn(c, hasnul, &s) < 0) - goto out; - - m = tokenize(s, tok, nelem(tok)); - if(m != 2){ - werrstr("bad protocol message"); - goto out; - } - - for(i=0; okproto[i]; i++) - if(strcmp(okproto[i]->name, tok[0]) == 0) - break; - if(!okproto[i]){ - werrstr("bad chosen protocol %q", tok[0]); - goto out; - } - - c->state = "write ok"; - if(convwrite(c, "OK\0", 3) < 0) - goto out; - - c->state = "start choice"; - attr = addattr(attr, "proto=%q dom=%q", tok[0], tok[1]); - free(c->attr); - c->attr = attr; - attr = nil; - c->proto = okproto[i]; - - if(rolecall(c->proto->roles, "server", c) < 0){ - werrstr("%s: %r", tok[0]); - goto out; - } - - ret = 0; - -out: - free(s); - freeattr(attr); - return ret; -} - -static int -p9anyclient(Conv *c) -{ - char *s, **f, *tok[20], ok[3], *q, *user, *dom, *choice; - int i, n, ret, version; - Key *k; - Attr *attr; - Proto *p; - - ret = -1; - s = nil; - k = nil; - - user = strfindattr(c->attr, "user"); - dom = strfindattr(c->attr, "dom"); - - /* - * if the user is the factotum owner, any key will do. - * if not, then if we have a speakfor key, - * we will only vouch for the user's local identity. - * - * this logic is duplicated in p9sk1.c - */ - attr = delattr(copyattr(c->attr), "role"); - attr = delattr(attr, "proto"); - if(strcmp(c->sysuser, owner) == 0) - attr = addattr(attr, "role=client"); - else if(user==nil || strcmp(c->sysuser, user)==0){ - attr = delattr(attr, "user"); - attr = addattr(attr, "role=speakfor"); - }else{ - werrstr("will not authenticate for %q as %q", c->sysuser, user); - goto out; - } - - c->state = "read offer"; - if(convreadfn(c, hasnul, &s) < 0) - goto out; - - c->state = "look for keys"; - n = tokenize(s, tok, nelem(tok)); - f = tok; - version = 1; - if(n > 0 && memcmp(f[0], "v.", 2) == 0){ - version = atoi(f[0]+2); - if(version != 2){ - werrstr("unknown p9any version: %s", f[0]); - goto out; - } - f++; - n--; - } - - /* look for keys that don't need confirmation */ - for(i=0; iattr, "confirm") == nil) - goto found; - *--q = '@'; - } - - /* look for any keys at all */ - for(i=0; istate = "ask for keys"; - for(i=0; ikeyprompt == nil){ - *--q = '@'; - continue; - } - if(k = keyfetch(c, "%A proto=%q dom=%q %s", attr, f[i], q, p->keyprompt)) - goto found; - *--q = '@'; - } - - /* nothing worked */ - werrstr("unable to find common key"); - goto out; - -found: - /* f[i] is the chosen protocol, q the chosen domain */ - attr = addattr(attr, "proto=%q dom=%q", f[i], q); - c->state = "write choice"; - - /* have a key: go for it */ - choice = estrappend(nil, "%q %q", f[i], q); - if(convwrite(c, choice, strlen(choice)+1) < 0){ - free(choice); - goto out; - } - free(choice); - - if(version == 2){ - c->state = "read ok"; - if(convread(c, ok, 3) < 0 || memcmp(ok, "OK\0", 3) != 0) - goto out; - } - - c->state = "start choice"; - c->proto = protolookup(f[i]); - freeattr(c->attr); - c->attr = attr; - attr = nil; - - if(rolecall(c->proto->roles, "client", c) < 0){ - werrstr("%s: %r", c->proto->name); - goto out; - } - - ret = 0; - -out: - keyclose(k); - freeattr(attr); - free(s); - return ret; -} - -static Role -p9anyroles[] = -{ - "client", p9anyclient, - "server", p9anyserver, - 0 -}; - -Proto p9any = { -.name= "p9any", -.roles= p9anyroles, -}; - blob - 7f53e44782057f8f4aa67ba923ab8530b8490e38 (mode 644) blob + /dev/null --- src/cmd/factotum/p9cr.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * p9cr, vnc - one-sided challenge/response authentication - * - * Protocol: - * - * C -> S: user - * S -> C: challenge - * C -> S: response - * S -> C: ok or bad - * - * Note that this is the protocol between factotum and the local - * program, not between the two factotums. The information - * exchanged here is wrapped in other protocols by the local - * programs. - */ - -#include "std.h" -#include "dat.h" - -static int -p9crcheck(Key *k) -{ - if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){ - werrstr("need user and !password attributes"); - return -1; - } - return 0; -} - -static int -p9crclient(Conv *c) -{ - char *chal, *pw, *res, *user; - int astype, nchal, npw, ntry, ret; - uchar resp[MD5dlen]; - Attr *attr; - DigestState *ds; - Key *k; - - chal = nil; - k = nil; - res = nil; - ret = -1; - attr = c->attr; - - if(c->proto == &p9cr){ - astype = AuthChal; - challen = NETCHLEN; - }else if(c->proto == &vnc){ - astype = AuthVnc; - challen = MAXCHAL; - }else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - k = keyfetch(c, "%A %s", attr, c->proto->keyprompt); - if(k == nil) - goto out; - - for(ntry=1;; ntry++){ - if(c->attr != attr) - freeattr(c->attr); - c->attr = addattrs(copyattr(attr), k->attr); - if((pw = strfindattr(k->privattr, "!password")) == nil){ - werrstr("key has no !password (cannot happen)"); - goto out; - } - npw = strlen(pw); - - if((user = strfindattr(k->attr, "user")) == nil){ - werrstr("key has no user (cannot happen)"); - goto out; - } - - if(convprint(c, "%s", user) < 0) - goto out; - - if(convreadm(c, &chal) < 0) - goto out; - - if((nresp = (*response)(chal, resp)) < 0) - goto out; - - if(convwrite(c, resp, nresp) < 0) - goto out; - - if(convreadm(c, &res) < 0) - goto out; - - if(strcmp(res, "ok") == 0) - break; - - if((k = keyreplace(c, k, "%s", res)) == nil){ - c->state = "auth failed"; - werrstr("%s", res); - goto out; - } - } - - werrstr("succeeded"); - ret = 0; - -out: - keyclose(k); - free(chal); - if(c->attr != attr) - freeattr(attr); - return ret; -} - -static int -p9crserver(Conv *c) -{ - char chal[APOPCHALLEN], *user, *resp; - ServerState s; - int astype, ret; - Attr *a; - - ret = -1; - user = nil; - resp = nil; - memset(&s, 0, sizeof s); - s.asfd = -1; - - if(c->proto == &apop) - astype = AuthApop; - else if(c->proto == &cram) - astype = AuthCram; - else{ - werrstr("bad proto"); - goto out; - } - - c->state = "find key"; - if((s.k = plan9authkey(c->attr)) == nil) - goto out; - - a = copyattr(s.k->attr); - a = delattr(a, "proto"); - c->attr = addattrs(c->attr, a); - freeattr(a); - - c->state = "authdial"; - s.hostid = strfindattr(s.k->attr, "user"); - s.dom = strfindattr(s.k->attr, "dom"); - if((s.asfd = xioauthdial(nil, s.dom)) < 0){ - werrstr("authdial %s: %r", s.dom); - goto out; - } - - c->state = "authchal"; - if(p9crchal(&s, astype, chal) < 0) - goto out; - - c->state = "write challenge"; - if(convprint(c, "%s", chal) < 0) - goto out; - - for(;;){ - c->state = "read user"; - if(convreadm(c, &user) < 0) - goto out; - - c->state = "read response"; - if(convreadm(c, &resp) < 0) - goto out; - - c->state = "authwrite"; - switch(apopresp(&s, user, resp)){ - case -1: - goto out; - case 0: - c->state = "write status"; - if(convprint(c, "bad authentication failed") < 0) - goto out; - break; - case 1: - c->state = "write status"; - if(convprint(c, "ok") < 0) - goto out; - goto ok; - } - free(user); - free(resp); - user = nil; - resp = nil; - } - -ok: - ret = 0; - c->attr = addcap(c->attr, c->sysuser, &s.t); - -out: - keyclose(s.k); - free(user); - free(resp); -// xioclose(s.asfd); - return ret; -} - -enum -{ - MAXCHAL = 64, -}; - -typedef struct State State; -struct State -{ - Key *key; - int astype; - int asfd; - Ticket t; - Ticketreq tr; - char chal[MAXCHAL]; - int challen; - char resp[MAXCHAL]; - int resplen; -}; - -enum -{ - CNeedChal, - CHaveResp, - - SHaveChal, - SNeedResp, - - Maxphase, -}; - -static char *phasenames[Maxphase] = -{ -[CNeedChal] "CNeedChal", -[CHaveResp] "CHaveResp", - -[SHaveChal] "SHaveChal", -[SNeedResp] "SNeedResp", -}; - -static void -p9crclose(Fsstate *fss) -{ - State *s; - - s = fss->ps; - if(s->asfd >= 0){ - close(s->asfd); - s->asfd = -1; - } - free(s); -} - -static int getchal(State*, Fsstate*); - -static int -p9crinit(Proto *p, Fsstate *fss) -{ - int iscli, ret; - char *user; - State *s; - Attr *attr; - - if((iscli = isclient(_str_findattr(fss->attr, "role"))) < 0) - return failure(fss, nil); - - s = emalloc(sizeof(*s)); - s->asfd = -1; - if(p == &p9cr){ - s->astype = AuthChal; - s->challen = NETCHLEN; - }else if(p == &vnc){ - s->astype = AuthVNC; - s->challen = Maxchal; - }else - abort(); - - if(iscli){ - fss->phase = CNeedChal; - if(p == &p9cr) - attr = setattr(_copyattr(fss->attr), "proto=p9sk1"); - else - attr = nil; - ret = findkey(&s->key, fss, Kuser, 0, attr ? attr : fss->attr, - "role=client %s", p->keyprompt); - _freeattr(attr); - if(ret != RpcOk){ - free(s); - return ret; - } - fss->ps = s; - }else{ - if((ret = findp9authkey(&s->key, fss)) != RpcOk){ - free(s); - return ret; - } - if((user = _str_findattr(fss->attr, "user")) == nil){ - free(s); - return failure(fss, "no user name specified in start msg"); - } - if(strlen(user) >= sizeof s->tr.uid){ - free(s); - return failure(fss, "user name too long"); - } - fss->ps = s; - strcpy(s->tr.uid, user); - ret = getchal(s, fss); - if(ret != RpcOk){ - p9crclose(fss); /* frees s */ - fss->ps = nil; - } - } - fss->phasename = phasenames; - fss->maxphase = Maxphase; - return ret; -} - -static int -p9crread(Fsstate *fss, void *va, uint *n) -{ - int m; - State *s; - - s = fss->ps; - switch(fss->phase){ - default: - return phaseerror(fss, "read"); - - case CHaveResp: - if(s->resplen < *n) - *n = s->resplen; - memmove(va, s->resp, *n); - fss->phase = Established; - return RpcOk; - - case SHaveChal: - if(s->astype == AuthChal) - m = strlen(s->chal); /* ascii string */ - else - m = s->challen; /* fixed length binary */ - if(m > *n) - return toosmall(fss, m); - *n = m; - memmove(va, s->chal, m); - fss->phase = SNeedResp; - return RpcOk; - } -} - -static int -p9response(Fsstate *fss, State *s) -{ - char key[DESKEYLEN]; - uchar buf[8]; - ulong chal; - char *pw; - - pw = _str_findattr(s->key->privattr, "!password"); - if(pw == nil) - return failure(fss, "vncresponse cannot happen"); - passtokey(key, pw); - memset(buf, 0, 8); - sprint((char*)buf, "%d", atoi(s->chal)); - if(encrypt(key, buf, 8) < 0) - return failure(fss, "can't encrypt response"); - chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; - s->resplen = snprint(s->resp, sizeof s->resp, "%.8lux", chal); - return RpcOk; -} - -static uchar tab[256]; - -/* VNC reverses the bits of each byte before using as a des key */ -static void -mktab(void) -{ - int i, j, k; - static int once; - - if(once) - return; - once = 1; - - for(i=0; i<256; i++) { - j=i; - tab[i] = 0; - for(k=0; k<8; k++) { - tab[i] = (tab[i]<<1) | (j&1); - j >>= 1; - } - } -} - -static int -vncaddkey(Key *k) -{ - uchar *p; - char *s; - - k->priv = emalloc(8+1); - if(s = _str_findattr(k->privattr, "!password")){ - mktab(); - memset(k->priv, 0, 8+1); - strncpy((char*)k->priv, s, 8); - for(p=k->priv; *p; p++) - *p = tab[*p]; - }else{ - werrstr("no key data"); - return -1; - } - return replacekey(k); -} - -static void -vncclosekey(Key *k) -{ - free(k->priv); -} - -static int -vncresponse(Fsstate*, State *s) -{ - DESstate des; - - memmove(s->resp, s->chal, sizeof s->chal); - setupDESstate(&des, s->key->priv, nil); - desECBencrypt((uchar*)s->resp, s->challen, &des); - s->resplen = s->challen; - return RpcOk; -} - -static int -p9crwrite(Fsstate *fss, void *va, uint n) -{ - char tbuf[TICKETLEN+AUTHENTLEN]; - State *s; - char *data = va; - Authenticator a; - char resp[Maxchal]; - int ret; - - s = fss->ps; - switch(fss->phase){ - default: - return phaseerror(fss, "write"); - - case CNeedChal: - if(n >= sizeof(s->chal)) - return failure(fss, Ebadarg); - memset(s->chal, 0, sizeof s->chal); - memmove(s->chal, data, n); - s->challen = n; - - if(s->astype == AuthChal) - ret = p9response(fss, s); - else - ret = vncresponse(fss, s); - if(ret != RpcOk) - return ret; - fss->phase = CHaveResp; - return RpcOk; - - case SNeedResp: - /* send response to auth server and get ticket */ - if(n > sizeof(resp)) - return failure(fss, Ebadarg); - memset(resp, 0, sizeof resp); - memmove(resp, data, n); - if(write(s->asfd, resp, s->challen) != s->challen) - return failure(fss, Easproto); - - /* get ticket plus authenticator from auth server */ - if(_asrdresp(s->asfd, tbuf, TICKETLEN+AUTHENTLEN) < 0) - return failure(fss, nil); - - /* check ticket */ - convM2T(tbuf, &s->t, s->key->priv); - if(s->t.num != AuthTs - || memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0) - return failure(fss, Easproto); - convM2A(tbuf+TICKETLEN, &a, s->t.key); - if(a.num != AuthAc - || memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0 - || a.id != 0) - return failure(fss, Easproto); - - fss->haveai = 1; - fss->ai.cuid = s->t.cuid; - fss->ai.suid = s->t.suid; - fss->ai.nsecret = 0; - fss->ai.secret = nil; - fss->phase = Established; - return RpcOk; - } -} - -static int -getchal(State *s, Fsstate *fss) -{ - char trbuf[TICKREQLEN]; - int n; - - safecpy(s->tr.hostid, _str_findattr(s->key->attr, "user"), sizeof(s->tr.hostid)); - safecpy(s->tr.authdom, _str_findattr(s->key->attr, "dom"), sizeof(s->tr.authdom)); - s->tr.type = s->astype; - convTR2M(&s->tr, trbuf); - - /* get challenge from auth server */ - s->asfd = _authdial(nil, _str_findattr(s->key->attr, "dom")); - if(s->asfd < 0) - return failure(fss, Easproto); - if(write(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN) - return failure(fss, Easproto); - n = _asrdresp(s->asfd, s->chal, s->challen); - if(n <= 0){ - if(n == 0) - werrstr("_asrdresp short read"); - return failure(fss, nil); - } - s->challen = n; - fss->phase = SHaveChal; - return RpcOk; -} - -Proto p9cr = -{ -.name= "p9cr", -.init= p9crinit, -.write= p9crwrite, -.read= p9crread, -.close= p9crclose, -.keyprompt= "user? !password?", -}; - -Proto vnc = -{ -.name= "vnc", -.init= p9crinit, -.write= p9crwrite, -.read= p9crread, -.close= p9crclose, -.keyprompt= "!password?", -.addkey= vncaddkey, -}; blob - 2828e708c879be1d6abcec0c76cc1e047606ef95 (mode 644) blob + /dev/null --- src/cmd/factotum/p9sk1.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * p9sk1, p9sk2 - Plan 9 secret (private) key authentication. - * p9sk2 is an incomplete flawed variant of p9sk1. - * - * Client protocol: - * write challenge[challen] (p9sk1 only) - * read tickreq[tickreqlen] - * write ticket[ticketlen] - * read authenticator[authentlen] - * - * Server protocol: - * read challenge[challen] (p9sk1 only) - * write tickreq[tickreqlen] - * read ticket[ticketlen] - * write authenticator[authentlen] - */ - -#include "std.h" -#include "dat.h" - -static int gettickets(Ticketreq*, char*, Key*); - -#define max(a, b) ((a) > (b) ? (a) : (b)) -enum -{ - MAXAUTH = max(TICKREQLEN, TICKETLEN+max(TICKETLEN, AUTHENTLEN)) -}; - -static int -p9skclient(Conv *c) -{ - char *user; - char cchal[CHALLEN]; - uchar secret[8]; - char buf[MAXAUTH]; - int speakfor, ret; - Attr *a; - Authenticator au; - Key *k; - Ticket t; - Ticketreq tr; - - ret = -1; - a = nil; - k = nil; - - /* p9sk1: send client challenge */ - if(c->proto == &p9sk1){ - c->state = "write challenge"; - memrandom(cchal, CHALLEN); - if(convwrite(c, cchal, CHALLEN) < 0) - goto out; - } - - /* read ticket request */ - c->state = "read tickreq"; - if(convread(c, buf, TICKREQLEN) < 0) - goto out; - convM2TR(buf, &tr); - - /* p9sk2: use server challenge as client challenge */ - if(c->proto == &p9sk2) - memmove(cchal, tr.chal, CHALLEN); - - /* - * find a key. - * - * if the user is the factotum owner, any key will do. - * if not, then if we have a speakfor key, - * we will only vouch for the user's local identity. - * - * this logic is duplicated in p9any.c - */ - user = strfindattr(c->attr, "user"); - a = delattr(copyattr(c->attr), "role"); - a = addattr(a, "proto=p9sk1"); - - if(strcmp(c->sysuser, owner) == 0){ - speakfor = 0; - a = addattr(a, "proto=p9sk1 user? dom=%q", tr.authdom); - }else if(user==nil || strcmp(c->sysuser, user)==0){ - speakfor = 1; - a = delattr(a, "user"); - a = addattr(a, "proto=p9sk1 user? dom=%q role=speakfor", tr.authdom); - }else{ - werrstr("will not authenticate for %q as %q", c->sysuser, user); - goto out; - } - - for(;;){ - c->state = "find key"; - k = keyfetch(c, "%A", a); - if(k == nil) - goto out; - - /* relay ticket request to auth server, get tickets */ - strcpy(tr.hostid, strfindattr(k->attr, "user")); - if(speakfor) - strcpy(tr.uid, c->sysuser); - else - strcpy(tr.uid, tr.hostid); - - c->state = "get tickets"; - if(gettickets(&tr, buf, k) < 0) - goto out; - - convM2T(buf, &t, k->priv); - if(t.num == AuthTc) - break; - - /* we don't agree with the auth server about the key; try again */ - c->state = "replace key"; - if((k = keyreplace(c, k, "key mismatch with auth server")) == nil){ - werrstr("key mismatch with auth server"); - goto out; - } - } - - /* send second ticket and authenticator to server */ - c->state = "write ticket+auth"; - memmove(buf, buf+TICKETLEN, TICKETLEN); - au.num = AuthAc; - memmove(au.chal, tr.chal, CHALLEN); - au.id = 0; - convA2M(&au, buf+TICKETLEN, t.key); - if(convwrite(c, buf, TICKETLEN+AUTHENTLEN) < 0) - goto out; - - /* read authenticator from server */ - c->state = "read auth"; - if(convread(c, buf, AUTHENTLEN) < 0) - goto out; - convM2A(buf, &au, t.key); - if(au.num != AuthAs || memcmp(au.chal, cchal, CHALLEN) != 0 || au.id != 0){ - werrstr("server lies through his teeth"); - goto out; - } - - /* success */ - c->attr = addcap(c->attr, c->sysuser, &t); - des56to64((uchar*)t.key, secret); - c->attr = addattr(c->attr, "secret=%.8H", secret); - ret = 0; - -out: - freeattr(a); - keyclose(k); - return ret; -} - -static int -p9skserver(Conv *c) -{ - char cchal[CHALLEN], buf[MAXAUTH]; - uchar secret[8]; - int ret; - Attr *a; - Authenticator au; - Key *k; - Ticketreq tr; - Ticket t; - - ret = -1; - - a = addattr(copyattr(c->attr), "user? dom?"); - a = addattr(a, "user? dom? proto=p9sk1"); - if((k = keyfetch(c, "%A", a)) == nil) - goto out; - - /* p9sk1: read client challenge */ - if(c->proto == &p9sk1){ - if(convread(c, cchal, CHALLEN) < 0) - goto out; - } - - /* send ticket request */ - memset(&tr, 0, sizeof tr); - tr.type = AuthTreq; - strcpy(tr.authid, strfindattr(k->attr, "user")); - strcpy(tr.authdom, strfindattr(k->attr, "dom")); - memrandom(tr.chal, sizeof tr.chal); - convTR2M(&tr, buf); - if(convwrite(c, buf, TICKREQLEN) < 0) - goto out; - - /* p9sk2: use server challenge as client challenge */ - if(c->proto == &p9sk2) - memmove(cchal, tr.chal, sizeof tr.chal); - - /* read ticket+authenticator */ - if(convread(c, buf, TICKETLEN+AUTHENTLEN) < 0) - goto out; - - convM2T(buf, &t, k->priv); - if(t.num != AuthTs || memcmp(t.chal, tr.chal, CHALLEN) != 0){ - /* BUG badkey */ - werrstr("key mismatch with auth server"); - goto out; - } - - convM2A(buf+TICKETLEN, &au, t.key); - if(au.num != AuthAc || memcmp(au.chal, tr.chal, CHALLEN) != 0 || au.id != 0){ - werrstr("client lies through his teeth"); - goto out; - } - - /* send authenticator */ - au.num = AuthAs; - memmove(au.chal, cchal, CHALLEN); - convA2M(&au, buf, t.key); - if(convwrite(c, buf, AUTHENTLEN) < 0) - goto out; - - /* success */ - c->attr = addcap(c->attr, c->sysuser, &t); - des56to64((uchar*)t.key, secret); - c->attr = addattr(c->attr, "secret=%.8H", secret); - ret = 0; - -out: - freeattr(a); - keyclose(k); - return ret; -} - -int -_asgetticket(int fd, char *trbuf, char *tbuf) -{ - if(write(fd, trbuf, TICKREQLEN) < 0){ - close(fd); - return -1; - } - return _asrdresp(fd, tbuf, 2*TICKETLEN); -} -static int -getastickets(Ticketreq *tr, char *buf) -{ - int asfd; - int ret; - - if((asfd = xioauthdial(nil, tr->authdom)) < 0) - return -1; - convTR2M(tr, buf); - ret = xioasgetticket(asfd, buf, buf); - xioclose(asfd); - return ret; -} - -static int -mktickets(Ticketreq *tr, char *buf, Key *k) -{ - Ticket t; - - if(strcmp(tr->authid, tr->hostid) != 0) - return -1; - - memset(&t, 0, sizeof t); - memmove(t.chal, tr->chal, CHALLEN); - strcpy(t.cuid, tr->uid); - strcpy(t.suid, tr->uid); - memrandom(t.key, DESKEYLEN); - t.num = AuthTc; - convT2M(&t, buf, k->priv); - t.num = AuthTs; - convT2M(&t, buf+TICKETLEN, k->priv); - return 0; -} - -static int -gettickets(Ticketreq *tr, char *buf, Key *k) -{ - if(getastickets(tr, buf) == 0) - return 0; - if(mktickets(tr, buf, k) == 0) - return 0; - werrstr("gettickets: %r"); - return -1; -} - -static int -p9sk1check(Key *k) -{ - char *user, *dom, *pass; - Ticketreq tr; - - user = strfindattr(k->attr, "user"); - dom = strfindattr(k->attr, "dom"); - if(user==nil || dom==nil){ - werrstr("need user and dom attributes"); - return -1; - } - if(strlen(user) >= sizeof tr.authid){ - werrstr("user name too long"); - return -1; - } - if(strlen(dom) >= sizeof tr.authdom){ - werrstr("auth dom name too long"); - return -1; - } - - k->priv = emalloc(DESKEYLEN); - if(pass = strfindattr(k->privattr, "!password")) - passtokey(k->priv, pass); - else if(pass = strfindattr(k->privattr, "!hex")){ - if(hexparse(pass, k->priv, 7) < 0){ - werrstr("malformed !hex key data"); - return -1; - } - }else{ - werrstr("need !password or !hex attribute"); - return -1; - } - - return 0; -} - -static void -p9sk1close(Key *k) -{ - free(k->priv); - k->priv = nil; -} - -static Role -p9sk1roles[] = -{ - "client", p9skclient, - "server", p9skserver, - 0 -}; - -static Role -p9sk2roles[] = -{ - "client", p9skclient, - "server", p9skserver, - 0 -}; - -Proto p9sk1 = { -.name= "p9sk1", -.roles= p9sk1roles, -.checkkey= p9sk1check, -.closekey= p9sk1close, -.keyprompt= "user? dom? !password?", -}; - -Proto p9sk2 = { -.name= "p9sk2", -.roles= p9sk2roles, -}; - blob - b3d4cb6ad2c87b9b7755d314e63f41bebde4c72a (mode 644) blob + /dev/null --- src/cmd/factotum/pass.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This is just a repository for a password. - * We don't want to encourage this, there's - * no server side. - */ - -#include "dat.h" - -typedef struct State State; -struct State -{ - Key *key; -}; - -enum -{ - HavePass, - Maxphase, -}; - -static char *phasenames[Maxphase] = -{ -[HavePass] "HavePass", -}; - -static int -passinit(Proto *p, Fsstate *fss) -{ - int ask; - Key *k; - State *s; - - k = findkey(fss, Kuser, &ask, 0, fss->attr, "%s", p->keyprompt); - if(k == nil){ - if(ask) - return RpcNeedkey; - return failure(fss, nil); - } - setattrs(fss->attr, k->attr); - s = emalloc(sizeof(*s)); - s->key = k; - fss->ps = s; - return RpcOk; -} - -static void -passclose(Fsstate *fss) -{ - State *s; - - s = fss->ps; - if(s->key) - closekey(s->key); - free(s); -} - -static int -passread(Fsstate *fss, void *va, uint *n) -{ - int m; - char buf[500]; - char *pass, *user; - State *s; - - s = fss->ps; - switch(fss->phase){ - default: - return phaseerror(fss, "read"); - - case HavePass: - user = strfindattr(s->key->attr, "user"); - pass = strfindattr(s->key->privattr, "!password"); - if(user==nil || pass==nil) - return failure(fss, "passread cannot happen"); - snprint(buf, sizeof buf, "%q %q", user, pass); - m = strlen(buf); - if(m > *n) - return toosmall(fss, m); - *n = m; - memmove(va, buf, m); - return RpcOk; - } -} - -static int -passwrite(Fsstate *fss, void*, uint) -{ - return phaseerror(fss, "write"); -} - -Proto pass = -{ -.name= "pass", -.init= passinit, -.write= passwrite, -.read= passread, -.close= passclose, -.addkey= replacekey, -.keyprompt= "user? !password?", -}; blob - 0b6bb601731289951ac250f8f4c7ff466c78f065 (mode 644) blob + /dev/null --- src/cmd/factotum/plan9.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "std.h" -#include "dat.h" -#include - -int -memrandom(void *p, int n) -{ - uchar *cp; - - for(cp = (uchar*)p; n > 0; n--) - *cp++ = fastrand(); - return 0; -} - -Attr* -addcap(Attr *a, char *from, Ticket *t) -{ - return addattr(a, "cuid=%q suid=%q cap=''", t->cuid, t->suid); -} - -int -_authdial(char *net, char *authdom) -{ - return authdial(net, authdom); -} - -Key* -plan9authkey(Attr *a) -{ - char *dom; - Key *k; - - /* - * The only important part of a is dom. - * We don't care, for example, about user name. - */ - dom = strfindattr(a, "dom"); - if(dom) - k = keylookup("proto=p9sk1 role=server user? dom=%q", dom); - else - k = keylookup("proto=p9sk1 role=server user? dom?"); - if(k == nil) - werrstr("could not find plan 9 auth key dom %q", dom); - return k; -} blob - e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 (mode 644) blob + /dev/null blob - 64bb2e3411fe666d9858d2dd3e9cf2acccb4fe2a (mode 644) blob + /dev/null --- src/cmd/factotum/proto.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "std.h" -#include "dat.h" - -Proto *prototab[] = { - &apop, - &cram, - &p9any, - &p9sk1, - &p9sk2, - nil, -}; - -Proto* -protolookup(char *name) -{ - int i; - - for(i=0; prototab[i]; i++) - if(strcmp(prototab[i]->name, name) == 0) - return prototab[i]; - return nil; -} blob - e9c163aa4eff3753961142f1b20fd319388158fc (mode 644) blob + /dev/null --- src/cmd/factotum/rpc.c +++ /dev/null @@ -1,315 +0,0 @@ -#include "std.h" -#include "dat.h" - -/* - * Factotum RPC - * - * Must be paired write/read cycles on /mnt/factotum/rpc. - * The format of a request is verb, single space, data. - * Data format is verb-dependent; in particular, it can be binary. - * The format of a response is the same. The write only sets up - * the RPC. The read tries to execute it. If the /mnt/factotum/key - * file is open, we ask for new keys using that instead of returning - * an error in the RPC. This means the read blocks. - * Textual arguments are parsed with tokenize, so rc-style quoting - * rules apply. - * - * Only authentication protocol messages go here. Configuration - * is still via ctl (below). - * - * Request RPCs are: - * start attrs - initializes protocol for authentication, can fail. - * returns "ok read" or "ok write" on success. - * read - execute protocol read - * write - execute protocol write - * authinfo - if the protocol is finished, return the AI if any - * attr - return protocol information - * Return values are: - * error message - an error happened. - * ok [data] - success, possible data is request dependent. - * needkey attrs - request aborted, get me this key and try again - * badkey attrs - request aborted, this key might be bad - * done [haveai] - authentication is done [haveai: you can get an ai with authinfo] - */ - -char *rpcname[] = -{ - "unknown", - "authinfo", - "attr", - "read", - "start", - "write", -}; - -static int -classify(char *s) -{ - int i; - - for(i=1; i= MaxRpc){ - werrstr("rpc too large"); - return -1; - } - - /* cancel any current rpc */ - c->rpc.op = RpcUnknown; - c->nreply = 0; - - /* parse new rpc */ - memmove(c->rpcbuf, data, count); - c->rpcbuf[count] = 0; - if(p = (uchar*)strchr((char*)c->rpcbuf, ' ')){ - *p++ = '\0'; - c->rpc.data = p; - c->rpc.count = count - (p - (uchar*)c->rpcbuf); - }else{ - c->rpc.data = ""; - c->rpc.count = 0; - } - op = classify(c->rpcbuf); - if(op == RpcUnknown){ - werrstr("bad rpc verb: %s", c->rpcbuf); - return -1; - } - - c->rpc.op = op; - return 0; -} - -void -convthread(void *v) -{ - Conv *c; - Attr *a; - char *role, *proto; - Proto *p; - Role *r; - - c = v; - a = parseattr(c->rpc.data); - if(a == nil){ - werrstr("empty attr"); - goto out; - } - c->attr = a; - proto = strfindattr(a, "proto"); - role = strfindattr(a, "role"); - - if(proto == nil){ - werrstr("no proto in attrs"); - goto out; - } - if(role == nil){ - werrstr("no role in attrs"); - goto out; - } - - p = protolookup(proto); - if(p == nil){ - werrstr("unknown proto %s", proto); - goto out; - } - - c->proto = p; - for(r=p->roles; r->name; r++){ - if(strcmp(r->name, role) != 0) - continue; - rpcrespond(c, "ok"); - c->active = 1; - if((*r->fn)(c) == 0){ - c->done = 1; - werrstr("protocol finished"); - }else - werrstr("%s %s %s: %r", p->name, r->name, c->state); - goto out; - } - werrstr("unknown role"); - -out: - c->active = 0; - c->state = 0; - rerrstr(c->err, sizeof c->err); - rpcrespond(c, "error %r"); - convclose(c); -} - -static uchar* convAI2M(uchar *p, int n, char *cuid, char *suid, char *cap, char *hex); - -void -rpcexec(Conv *c) -{ - uchar *p; - - switch(c->rpc.op){ - case RpcRead: - if(c->rpc.count > 0){ - rpcrespond(c, "error read takes no parameters"); - break; - } - /* fall through */ - default: - if(!c->active){ - if(c->done) - rpcrespond(c, "done"); - else - rpcrespond(c, "error %s", c->err); - break; - } - nbsendp(c->rpcwait, 0); - break; - case RpcUnknown: - break; - case RpcAuthinfo: - /* deprecated */ - if(c->active) - rpcrespond(c, "error conversation still active"); - else if(!c->done) - rpcrespond(c, "error conversation not successful"); - else{ - /* make up an auth info using the attr */ - p = convAI2M((uchar*)c->reply+3, sizeof c->reply-3, - strfindattr(c->attr, "cuid"), - strfindattr(c->attr, "suid"), - strfindattr(c->attr, "cap"), - strfindattr(c->attr, "secret")); - if(p == nil) - rpcrespond(c, "error %r"); - else - rpcrespondn(c, "ok", c->reply+3, p-(uchar*)(c->reply+3)); - } - break; - case RpcAttr: - rpcrespond(c, "ok %A", c->attr); - break; - case RpcStart: - convreset(c); - c->ref++; - threadcreate(convthread, c, STACK); - break; - } -} - -void -rpcrespond(Conv *c, char *fmt, ...) -{ - va_list arg; - - if(c->hangup) - return; - - if(fmt == nil) - fmt = ""; - - va_start(arg, fmt); - c->nreply = vsnprint(c->reply, sizeof c->reply, fmt, arg); - va_end(arg); - (*c->kickreply)(c); - c->rpc.op = RpcUnknown; -} - -void -rpcrespondn(Conv *c, char *verb, void *data, int count) -{ - char *p; - - if(c->hangup) - return; - - if(strlen(verb)+1+count > sizeof c->reply){ - print("RPC response too large; caller %#lux", getcallerpc(&c)); - return; - } - - strcpy(c->reply, verb); - p = c->reply + strlen(c->reply); - *p++ = ' '; - memmove(p, data, count); - c->nreply = count + (p - c->reply); - (*c->kickreply)(c); - c->rpc.op = RpcUnknown; -} - -/* deprecated */ -static uchar* -pstring(uchar *p, uchar *e, char *s) -{ - uint n; - - if(p == nil) - return nil; - if(s == nil) - s = ""; - n = strlen(s); - if(p+n+BIT16SZ >= e) - return nil; - PBIT16(p, n); - p += BIT16SZ; - memmove(p, s, n); - p += n; - return p; -} - -static uchar* -pcarray(uchar *p, uchar *e, uchar *s, uint n) -{ - if(p == nil) - return nil; - if(s == nil){ - if(n > 0) - sysfatal("pcarray"); - s = (uchar*)""; - } - if(p+n+BIT16SZ >= e) - return nil; - PBIT16(p, n); - p += BIT16SZ; - memmove(p, s, n); - p += n; - return p; -} - -static uchar* -convAI2M(uchar *p, int n, char *cuid, char *suid, char *cap, char *hex) -{ - uchar *e = p+n; - uchar *secret; - int nsecret; - - if(cuid == nil) - cuid = ""; - if(suid == nil) - suid = ""; - if(cap == nil) - cap = ""; - if(hex == nil) - hex = ""; - nsecret = strlen(hex)/2; - secret = emalloc(nsecret); - if(hexparse(hex, secret, nsecret) < 0){ - werrstr("hexparse %s failed", hex); /* can't happen */ - free(secret); - return nil; - } - p = pstring(p, e, cuid); - p = pstring(p, e, suid); - p = pstring(p, e, cap); - p = pcarray(p, e, secret, nsecret); - free(secret); - if(p == nil) - werrstr("authinfo too big"); - return p; -} - blob - d82d7862a48e8b2692d1e0572a10e3e30f067594 (mode 644) blob + /dev/null --- src/cmd/factotum/secstore.c +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Various files from /sys/src/cmd/auth/secstore, just enough - * to download a file at boot time. - */ - -#include "std.h" -#include "dat.h" -#include - -enum{ CHK = 16}; -enum{ MAXFILESIZE = 10*1024*1024 }; - -enum{// PW status bits - Enabled = (1<<0), - STA = (1<<1), // extra SecurID step -}; - -static char testmess[] = "__secstore\tPAK\nC=%s\nm=0\n"; -char *secstore; - -int -secdial(void) -{ - char *p; - - p = secstore; - if(p == nil) /* else use the authserver */ - p = getenv("secstore"); - if(p == nil) - p = getenv("auth"); - if(p == nil) - p = "secstore"; - - return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0); -} - - -int -havesecstore(void) -{ - int m, n, fd; - uchar buf[500]; - - n = snprint((char*)buf, sizeof buf, testmess, owner); - hnputs(buf, 0x8000+n-2); - - fd = secdial(); - if(fd < 0) - return 0; - if(write(fd, buf, n) != n || readn(fd, buf, 2) != 2){ - close(fd); - return 0; - } - n = ((buf[0]&0x7f)<<8) + buf[1]; - if(n+1 > sizeof buf){ - werrstr("implausibly large count %d", n); - close(fd); - return 0; - } - m = readn(fd, buf, n); - close(fd); - if(m != n){ - if(m >= 0) - werrstr("short read from secstore"); - return 0; - } - buf[n] = 0; - if(strcmp((char*)buf, "!account expired") == 0){ - werrstr("account expired"); - return 0; - } - return strcmp((char*)buf, "!account exists") == 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 -#define readstr secstore_readstr -static void writerr(SConn*, char*); -static int readstr(SConn*, char*); // call with buf of size Maxmsg+1 - // returns -1 upon error, with error message in buf - -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){ - werrstr("!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){ - werrstr("!SC_read missing sha1"); - return -1; - } - if(len > n || readn(ss->fd, buf, len) != len){ - werrstr("!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){ - werrstr("!SC_read integrity check failed"); - return -1; - } - }else{ - if(len <= 0 || len > n){ - werrstr("!SC_read implausible record length"); - return -1; - } - if( (nr = readn(ss->fd, buf, len)) != len){ - werrstr("!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; -} - -static void -writerr(SConn *conn, char *s) -{ - char buf[Maxmsg]; - - snprint(buf, Maxmsg, "!%s", s); - conn->write(conn, (uchar*)buf, strlen(buf)); -} - -static 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; -} - -static int -getfile(SConn *conn, uchar *key, int nkey) -{ - char *buf; - int nbuf, n, nr, len; - char s[Maxmsg+1], *gf, *p, *q; - uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw; - AESstate aes; - DigestState *sha; - - gf = "factotum"; - 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'; - if(readstr(conn, s) < 0){ - werrstr("secstore: %r"); - return -1; - } - if((len = atoi(s)) < 0){ - werrstr("secstore: remote file %s does not exist", gf); - return -1; - }else if(len > MAXFILESIZE){//assert - werrstr("secstore: implausible file size %d for %s", len, gf); - return -1; - } - - ibr = ibw = ib; - buf = nil; - nbuf = 0; - for(nr=0; nr < len;){ - if((n = conn->read(conn, ibw, Maxmsg)) <= 0){ - werrstr("secstore: empty file chunk n=%d nr=%d len=%d: %r", n, nr, len); - return -1; - } - nr += n; - ibw += n; - if(!aes.setup){ /* first time, read 16 byte IV */ - if(n < 16){ - werrstr("secstore: no IV in file"); - 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){ - buf = erealloc(buf, nbuf+n+1); - memmove(buf+nbuf, ibr, n); - nbuf += n; - ibr += n; - } - memmove(ib, ibr, ibw-ibr); - ibw = ib + (ibw-ibr); - ibr = ib; - } - n = ibw-ibr; - if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){ - werrstr("secstore: decrypted file failed to authenticate!"); - free(buf); - return -1; - } - if(nbuf == 0){ - werrstr("secstore got empty file"); - return -1; - } - buf[nbuf] = '\0'; - p = buf; - n = 0; - while(p){ - if(q = strchr(p, '\n')) - *q++ = '\0'; - n++; - if(ctlwrite(p) < 0) - fprint(2, "secstore(%s) line %d: %r\n", gf, n); - p = q; - } - free(buf); - return 0; -} - -static char VERSION[] = "secstore"; - -typedef struct PAKparams{ - mpint *q, *p, *r, *g; -} PAKparams; - -static PAKparams *pak; - -// This group was generated by the seed EB7B6E35F7CD37B511D96C67D6688CC4DD440E1E. -static void -initPAKparams(void) -{ - if(pak) - return; - pak = (PAKparams*)emalloc(sizeof(*pak)); - pak->q = strtomp("E0F0EF284E10796C5A2A511E94748BA03C795C13", nil, 16, nil); - pak->p = strtomp("C41CFBE4D4846F67A3DF7DE9921A49D3B42DC33728427AB159CEC8CBBD" - "B12B5F0C244F1A734AEB9840804EA3C25036AD1B61AFF3ABBC247CD4B384224567A86" - "3A6F020E7EE9795554BCD08ABAD7321AF27E1E92E3DB1C6E7E94FAAE590AE9C48F96D9" - "3D178E809401ABE8A534A1EC44359733475A36A70C7B425125062B1142D", nil, 16, nil); - pak->r = strtomp("DF310F4E54A5FEC5D86D3E14863921E834113E060F90052AD332B3241CEF" - "2497EFA0303D6344F7C819691A0F9C4A773815AF8EAECFB7EC1D98F039F17A32A7E887" - "D97251A927D093F44A55577F4D70444AEBD06B9B45695EC23962B175F266895C67D21" - "C4656848614D888A4", nil, 16, nil); - pak->g = strtomp("2F1C308DC46B9A44B52DF7DACCE1208CCEF72F69C743ADD4D2327173444" - "ED6E65E074694246E07F9FD4AE26E0FDDD9F54F813C40CB9BCD4338EA6F242AB94CD41" - "0E676C290368A16B1A3594877437E516C53A6EEE5493A038A017E955E218E7819734E3E" - "2A6E0BAE08B14258F8C03CC1B30E0DDADFCF7CEDF0727684D3D255F1", 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 -static 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. -static 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); - - // random 1<=x<=q-1; send C, m=g**x H - x = mprand(164, 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){//assert - 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; -} - -int -secstorefetch(void) -{ - int rv = -1, fd; - char s[Maxmsg+1]; - SConn *conn; - char *pass, *sta; - - sta = nil; - conn = nil; - pass = readcons("secstore password", nil, 1); - if(pass==nil || strlen(pass)==0){ - werrstr("cancel"); - goto Out; - } - if((fd = secdial()) < 0) - goto Out; - if((conn = newSConn(fd)) == nil) - goto Out; - if(PAKclient(conn, owner, pass, nil) < 0){ - werrstr("password mistyped?"); - goto Out; - } - if(readstr(conn, s) < 0) - goto Out; - if(strcmp(s, "STA") == 0){ - sta = readcons("STA PIN+SecureID", nil, 1); - if(sta==nil || strlen(sta)==0){ - werrstr("cancel"); - goto Out; - } - if(strlen(sta) >= sizeof s - 3){ - werrstr("STA response too long"); - goto Out; - } - strcpy(s+3, sta); - conn->write(conn, (uchar*)s, strlen(s)); - readstr(conn, s); - } - if(strcmp(s, "OK") !=0){ - werrstr("%s", s); - goto Out; - } - if(getfile(conn, (uchar*)pass, strlen(pass)) < 0) - goto Out; - conn->write(conn, (uchar*)"BYE", 3); - rv = 0; - -Out: - if(conn) - conn->free(conn); - if(pass) - free(pass); - if(sta) - free(sta); - return rv; -} - blob - 4c88bfe655f0f4a62326110184f1a3ff1a1c95a6 (mode 644) blob + /dev/null --- src/cmd/factotum/ssh.c +++ /dev/null @@ -1,135 +0,0 @@ -#include "dat.h" -#include -#include - -typedef struct Sshrsastate Sshrsastate; - -enum { - CReadpub, - CWritechal, - CReadresp, -}; -struct State -{ - RSApriv *priv; - Key *k; - mpint *resp; - int phase; -}; - -static RSApriv* -readrsapriv(char *s) -{ - RSApriv *priv; - - priv = rsaprivalloc(); - - strtoul(s, &s, 10); - if((priv->pub.ek=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->dk=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->pub.n=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->p=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->q=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->kp=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->kq=strtomp(s, &s, 16, nil)) == nil) - goto Error; - if((priv->c2=strtomp(s, &s, 16, nil)) == nil) - goto Error; - - return priv; - -Error: - rsaprivfree(priv); - return nil; -} - -int -sshinit(Fsstate *fss, -sshrsaopen(Key *k, char*, int client) -{ - Sshrsastate *s; - - fmtinstall('B', mpconv); - assert(client); - s = emalloc(sizeof *s); - s->priv = readrsapriv(s_to_c(k->data)); - s->k = k; - if(s->priv == nil){ - agentlog("error parsing ssh key %s", k->file); - free(s); - return nil; - } - return s; -} - -int -sshrsaread(void *va, void *buf, int n) -{ - Sshrsastate *s; - - s = va; - switch(s->phase){ - case Readpub: - s->phase = Done; - return snprint(buf, n, "%B", s->priv->pub.n); - case Readresp: - s->phase = Done; - return snprint(buf, n, "%B", s->resp); - default: - return 0; - } -} - -int -sshrsawrite(void *va, void *vbuf, int n) -{ - mpint *m; - char *buf; - Sshrsastate *s; - - s = va; - if((s->k->flags&Fconfirmuse) && confirm("ssh use") < 0) - return -1; - - buf = emalloc(n+1); - memmove(buf, vbuf, n); - buf[n] = '\0'; - m = strtomp(buf, nil, 16, nil); - free(buf); - if(m == nil){ - werrstr("bad bignum"); - return -1; - } - - agentlog("ssh use"); - m = rsadecrypt(s->priv, m, m); - s->resp = m; - s->phase = Readresp; - return n; -} - -void -sshrsaclose(void *v) -{ - Sshrsastate *s; - - s = v; - rsaprivfree(s->priv); - mpfree(s->resp); - free(s); -} - -Proto sshrsa = { -.name= "ssh-rsa", -.perm= 0666, -.open= sshrsaopen, -.read= sshrsaread, -.write= sshrsawrite, -.close= sshrsaclose, -}; blob - 7227c85566a54cece660b3900a723ec8ab3a92cc (mode 644) blob + /dev/null --- src/cmd/factotum/sshrsa.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SSH RSA authentication. - * - * Client protocol: - * read public key - * if you don't like it, read another, repeat - * write challenge - * read response - * all numbers are hexadecimal biginits parsable with strtomp. - */ - -#include "dat.h" - -enum { - CHavePub, - CHaveResp, - - Maxphase, -}; - -static char *phasenames[] = { -[CHavePub] "CHavePub", -[CHaveResp] "CHaveResp", -}; - -struct State -{ - RSApriv *priv; - mpint *resp; - int off; - Key *key; -}; - -static RSApriv* -readrsapriv(Key *k) -{ - char *a; - RSApriv *priv; - - priv = rsaprivalloc(); - - if((a=strfindattr(k->attr, "ek"))==nil || (priv->pub.ek=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->attr, "n"))==nil || (priv->pub.n=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!p"))==nil || (priv->p=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!q"))==nil || (priv->q=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!kp"))==nil || (priv->kp=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!kq"))==nil || (priv->kq=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!c2"))==nil || (priv->c2=strtomp(a, nil, 16, nil))==nil) - goto Error; - if((a=strfindattr(k->privattr, "!dk"))==nil || (priv->dk=strtomp(a, nil, 16, nil))==nil) - goto Error; - return priv; - -Error: - rsaprivfree(priv); - return nil; -} - -static int -sshrsainit(Proto*, Fsstate *fss) -{ - int iscli; - State *s; - - if((iscli = isclient(strfindattr(fss->attr, "role"))) < 0) - return failure(fss, nil); - if(iscli==0) - return failure(fss, "sshrsa server unimplemented"); - - s = emalloc(sizeof *s); - fss->phasename = phasenames; - fss->maxphase = Maxphase; - fss->phase = CHavePub; - fss->ps = s; - return RpcOk; -} - -static int -sshrsaread(Fsstate *fss, void *va, uint *n) -{ - RSApriv *priv; - State *s; - - s = fss->ps; - switch(fss->phase){ - default: - return phaseerror(fss, "read"); - case CHavePub: - if(s->key){ - closekey(s->key); - s->key = nil; - } - if((s->key = findkey(fss, Kuser, nil, s->off, fss->attr, nil)) == nil) - return failure(fss, nil); - s->off++; - priv = s->key->priv; - *n = snprint(va, *n, "%B", priv->pub.n); - return RpcOk; - case CHaveResp: - *n = snprint(va, *n, "%B", s->resp); - fss->phase = Established; - return RpcOk; - } -} - -static int -sshrsawrite(Fsstate *fss, void *va, uint) -{ - mpint *m; - State *s; - - s = fss->ps; - switch(fss->phase){ - default: - return phaseerror(fss, "write"); - case CHavePub: - if(s->key == nil) - return failure(fss, "no current key"); - m = strtomp(va, nil, 16, nil); - m = rsadecrypt(s->key->priv, m, m); - s->resp = m; - fss->phase = CHaveResp; - return RpcOk; - } -} - -static void -sshrsaclose(Fsstate *fss) -{ - State *s; - - s = fss->ps; - if(s->key) - closekey(s->key); - if(s->resp) - mpfree(s->resp); - free(s); -} - -static int -sshrsaaddkey(Key *k) -{ - fmtinstall('B', mpconv); - - if((k->priv = readrsapriv(k)) == nil){ - werrstr("malformed key data"); - return -1; - } - return replacekey(k); -} - -static void -sshrsaclosekey(Key *k) -{ - rsaprivfree(k->priv); -} - -Proto sshrsa = { -.name= "sshrsa", -.init= sshrsainit, -.write= sshrsawrite, -.read= sshrsaread, -.close= sshrsaclose, -.addkey= sshrsaaddkey, -.closekey= sshrsaclosekey, -}; blob - 814664e0fb482cf11e5da201fb5f5c63d6b5b17a (mode 644) blob + /dev/null --- src/cmd/factotum/std.h +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include <9p.h> - blob - b41048980556fe7a81615ffbf1af9b703d5757b0 (mode 644) blob + /dev/null --- src/cmd/factotum/test.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include -#include - -typedef struct Test Test; - -struct Test -{ - char *name; - int (*server)(Test*, AuthRpc*, int); - int (*client)(Test*, int); -}; - -int -ai2status(AuthInfo *ai) -{ - if(ai == nil) - return -1; - auth_freeAI(ai); - return 0; -} - -int -proxyserver(Test *t, AuthRpc *rpc, int fd) -{ - char buf[1024]; - - sprint(buf, "proto=%q role=server", t->name); - return ai2status(fauth_proxy(fd, rpc, nil, buf)); -} - -int -proxyclient(Test *t, int fd) -{ - return ai2status(auth_proxy(fd, auth_getkey, "proto=%q role=client", t->name)); -} - -Test test[] = -{ - "apop", proxyserver, proxyclient, - "cram", proxyserver, proxyclient, - "p9sk1", proxyserver, proxyclient, - "p9sk2", proxyserver, proxyclient, - "p9any", proxyserver, proxyclient, -}; - -void -usage(void) -{ - fprint(2, "usage: test [name]...\n"); - exits("usage"); -} - -void -runtest(AuthRpc *srpc, Test *t) -{ - int p[2], bad; - Waitmsg *w; - - if(pipe(p) < 0) - sysfatal("pipe: %r"); - - print("%s...", t->name); - - switch(fork()){ - case -1: - sysfatal("fork: %r"); - - case 0: - close(p[0]); - if((*t->server)(t, srpc, p[1]) < 0){ - print("\n\tserver: %r"); - _exits("oops"); - } - close(p[1]); - _exits(nil); - default: - close(p[1]); - if((*t->client)(t, p[0]) < 0){ - print("\n\tclient: %r"); - bad = 1; - } - close(p[0]); - break; - } - w = wait(); - if(w->msg[0]) - bad = 1; - print("\n"); -} - -void -main(int argc, char **argv) -{ - int i, j; - int afd; - AuthRpc *srpc; - - ARGBEGIN{ - default: - usage(); - }ARGEND - - quotefmtinstall(); - afd = open("/n/kremvax/factotum/rpc", ORDWR); - if(afd < 0) - sysfatal("open /n/kremvax/factotum/rpc: %r"); - srpc = auth_allocrpc(afd); - if(srpc == nil) - sysfatal("auth_allocrpc: %r"); - - if(argc == 0) - for(i=0; i[2]/dev/null -auth/aescbc -d < /usr/rsc/lib/factotum.aes >/n/sid/all -read -m /n/sid/all >/n/kremvax/factotum/ctl -read -m /n/sid/all >/mnt/factotum/ctl -unmount /n/sid - blob - accddddde1c0aa943d3437aa04dad9a03e7658ad (mode 644) blob + /dev/null --- src/cmd/factotum/util.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "std.h" -#include "dat.h" - -static int -unhex(char c) -{ - if('0' <= c && c <= '9') - return c-'0'; - if('a' <= c && c <= 'f') - return c-'a'+10; - if('A' <= c && c <= 'F') - return c-'A'+10; - abort(); - return -1; -} - -int -hexparse(char *hex, uchar *dat, int ndat) -{ - int i, n; - - n = strlen(hex); - if(n%2) - return -1; - n /= 2; - if(n > ndat) - return -1; - if(hex[strspn(hex, "0123456789abcdefABCDEF")] != '\0') - return -1; - for(i=0; i -#include -#include - -void -f(void*) -{ -} - -void -main(void) -{ - f(auth_challenge); - f(auth_response); -} blob - 2e6b141b0cae8629e25e8d5bb0bb35b907400ca3 (mode 644) blob + /dev/null --- src/cmd/factotum/xio.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "std.h" -#include "dat.h" - -static Ioproc *cache[5]; -static int ncache; - -static Ioproc* -xioproc(void) -{ - Ioproc *c; - int i; - - for(i=0; i -#include -#include -#include -#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; -} - blob - 9a428d833b1ac5aa6b7e8be04252bf562fc5a9fc (mode 644) blob + /dev/null --- 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 *); - blob - 56aeb00b531f69c7715634f77242d43cb3ba6740 (mode 644) blob + /dev/null --- 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 -#include -#include -#include -#include - -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 */ -} blob - b4479413a8a00ba426432bf72f0ae9b5000eb8f1 (mode 644) blob + /dev/null --- src/cmd/secstore/dirls.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#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 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 -#include -#include -#include -#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; -} - blob - aacadd9b184dd688aaebfe8296426a75d7893001 (mode 644) blob + /dev/null --- src/cmd/secstore/password.c +++ /dev/null @@ -1,136 +0,0 @@ -/* password.c */ -#include -#include -#include -#include -#include -#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); -} - blob - 8d50496e37164560e61fe1703fbc71212ce90555 (mode 644) blob + /dev/null --- 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 blob - 4390129a1bd5beab28c664d673985630f9dcbf44 (mode 644) blob + /dev/null --- src/cmd/secstore/secacct.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include - -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); -} blob - 59e26d512ae6dfda4aec0a121c6ae5a7ad5ce2db (mode 644) blob + /dev/null --- src/cmd/secstore/secchk.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include - -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); -} blob - 864aa88d373b8467e7e1ba060d36a6a86b99ba4f (mode 644) blob + /dev/null --- src/cmd/secstore/secstore.c +++ /dev/null @@ -1,585 +0,0 @@ -/* network login client */ -#include -#include -#include -#include -#include -#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; iwrite(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)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; -} - blob - dbd2ec9cfeec4dd3aad3a57c5fd9a602ce10168c (mode 644) blob + /dev/null --- 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; - blob - 58f7459aec7b6f1783fda5734c1693cffecde193 (mode 644) blob + /dev/null --- src/cmd/secstore/secstored.c +++ /dev/null @@ -1,420 +0,0 @@ -#include -#include -#include -#include -#include -#include -#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; - } - } -} - blob - 95adb38541c9a7a656957ae28cabd7e2ecefb149 (mode 644) blob + /dev/null --- src/cmd/secstore/secureidcheck.c +++ /dev/null @@ -1,446 +0,0 @@ -/* RFC2138 */ -#include -#include -#include -#include -#include -#include -#include -#include -#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; ilen; 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; -} blob - 31ba184bb5d680aa3f18d666e44481814ce7cbd6 (mode 644) blob + /dev/null --- src/cmd/secstore/secuser.c +++ /dev/null @@ -1,244 +0,0 @@ -#include -#include -#include -#include -#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] \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"); - } -} - blob - ebbb12df8745f412311704ab7ad1fcecc0be741e (mode 644) blob + /dev/null --- src/cmd/secstore/util.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -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; -}