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