tbasically none of these build - 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 be8b315d1522fa1c109a49435c1638bafd838b91
 (DIR) parent d9c8a7c5366aea63aa45b4afc6a75d133192786d
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 17 Jun 2004 03:27:35 +0000
       
       basically none of these build
       
       Diffstat:
         A src/libauth/amount.c                |      22 ++++++++++++++++++++++
         A src/libauth/amount_getkey.c         |       5 +++++
         A src/libauth/attr.c                  |     174 +++++++++++++++++++++++++++++++
         A src/libauth/auth_attr.c             |      13 +++++++++++++
         A src/libauth/auth_challenge.c        |     117 +++++++++++++++++++++++++++++++
         A src/libauth/auth_chuid.c            |      38 +++++++++++++++++++++++++++++++
         A src/libauth/auth_getkey.c           |      51 +++++++++++++++++++++++++++++++
         A src/libauth/auth_getuserpasswd.c    |      75 +++++++++++++++++++++++++++++++
         A src/libauth/auth_proxy.c            |     212 ++++++++++++++++++++++++++++++
         A src/libauth/auth_respond.c          |      73 +++++++++++++++++++++++++++++++
         A src/libauth/auth_rpc.c              |     116 ++++++++++++++++++++++++++++++
         A src/libauth/auth_userpasswd.c       |      50 +++++++++++++++++++++++++++++++
         A src/libauth/auth_wep.c              |      50 +++++++++++++++++++++++++++++++
         A src/libauth/authlocal.h             |       1 +
         A src/libauth/httpauth.c              |      51 +++++++++++++++++++++++++++++++
         A src/libauth/login.c                 |      17 +++++++++++++++++
         A src/libauth/mkfile                  |      27 +++++++++++++++++++++++++++
         A src/libauth/newns.c                 |     322 +++++++++++++++++++++++++++++++
         A src/libauth/noworld.c               |      45 +++++++++++++++++++++++++++++++
       
       19 files changed, 1459 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/libauth/amount.c b/src/libauth/amount.c
       t@@ -0,0 +1,22 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include "authlocal.h"
       +
       +int
       +amount(int fd, char *mntpt, int flags, char *aname)
       +{
       +        int rv, afd;
       +        AuthInfo *ai;
       +
       +        afd = fauth(fd, aname);
       +        if(afd >= 0){
       +                ai = auth_proxy(afd, amount_getkey, "proto=p9any role=client");
       +                if(ai != nil)
       +                        auth_freeAI(ai);
       +        }
       +        rv = mount(fd, afd, mntpt, flags, aname);
       +        if(afd >= 0)
       +                close(afd);
       +        return rv;
       +}
 (DIR) diff --git a/src/libauth/amount_getkey.c b/src/libauth/amount_getkey.c
       t@@ -0,0 +1,5 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +int (*amount_getkey)(char*) = auth_getkey;
 (DIR) diff --git a/src/libauth/attr.c b/src/libauth/attr.c
       t@@ -0,0 +1,174 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +int
       +_attrfmt(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;
       +                switch(a->type){
       +                case AttrQuery:
       +                        b = seprint(b, ebuf, " %q?", a->name);
       +                        break;
       +                case AttrNameval:
       +                        b = seprint(b, ebuf, " %q=%q", a->name, a->val);
       +                        break;
       +                case AttrDefault:
       +                        b = seprint(b, ebuf, " %q:=%q", a->name, a->val);
       +                        break;
       +                }
       +        }
       +        return fmtstrcpy(fmt, buf+1);
       +}
       +
       +Attr*
       +_copyattr(Attr *a)
       +{
       +        Attr **la, *na;
       +
       +        na = nil;
       +        la = &na;
       +        for(; a; a=a->next){
       +                *la = _mkattr(a->type, a->name, a->val, nil);
       +                setmalloctag(*la, getcallerpc(&a));
       +                la = &(*la)->next;
       +        }
       +        *la = nil;
       +        return na;
       +}
       +
       +Attr*
       +_delattr(Attr *a, char *name)
       +{
       +        Attr *fa;
       +        Attr **la;
       +
       +        for(la=&a; *la; ){
       +                if(strcmp((*la)->name, name) == 0){
       +                        fa = *la;
       +                        *la = (*la)->next;
       +                        fa->next = nil;
       +                        _freeattr(fa);
       +                }else
       +                        la=&(*la)->next;
       +        }
       +        return a;
       +}
       +
       +Attr*
       +_findattr(Attr *a, char *n)
       +{
       +        for(; a; a=a->next)
       +                if(strcmp(a->name, n) == 0 && a->type != AttrQuery)
       +                        return a;
       +        return nil;
       +}
       +
       +void
       +_freeattr(Attr *a)
       +{
       +        Attr *anext;
       +
       +        for(; a; a=anext){
       +                anext = a->next;
       +                free(a->name);
       +                free(a->val);
       +                a->name = (void*)~0;
       +                a->val = (void*)~0;
       +                a->next = (void*)~0;
       +                free(a);
       +        }
       +}
       +
       +Attr*
       +_mkattr(int type, char *name, char *val, Attr *next)
       +{
       +        Attr *a;
       +
       +        a = malloc(sizeof(*a));
       +        if(a==nil)
       +                sysfatal("_mkattr malloc: %r");
       +        a->type = type;
       +        a->name = strdup(name);
       +        a->val = strdup(val);
       +        if(a->name==nil || a->val==nil)
       +                sysfatal("_mkattr malloc: %r");
       +        a->next = next;
       +        setmalloctag(a, getcallerpc(&type));
       +        return a;
       +}
       +
       +static Attr*
       +cleanattr(Attr *a)
       +{
       +        Attr *fa;
       +        Attr **la;
       +
       +        for(la=&a; *la; ){
       +                if((*la)->type==AttrQuery && _findattr(a, (*la)->name)){
       +                        fa = *la;
       +                        *la = (*la)->next;
       +                        fa->next = nil;
       +                        _freeattr(fa);
       +                }else
       +                        la=&(*la)->next;
       +        }
       +        return a;
       +}
       +
       +Attr*
       +_parseattr(char *s)
       +{
       +        char *p, *t, *tok[256];
       +        int i, ntok, type;
       +        Attr *a;
       +
       +        s = strdup(s);
       +        if(s == nil)
       +                sysfatal("_parseattr strdup: %r");
       +
       +        ntok = tokenize(s, tok, nelem(tok));
       +        a = nil;
       +        for(i=ntok-1; i>=0; i--){
       +                t = tok[i];
       +                if(p = strchr(t, '=')){
       +                        *p++ = '\0';
       +                //        if(p-2 >= t && p[-2] == ':'){
       +                //                p[-2] = '\0';
       +                //                type = AttrDefault;
       +                //        }else
       +                                type = AttrNameval;
       +                        a = _mkattr(type, t, p, a);
       +                        setmalloctag(a, getcallerpc(&s));
       +                }
       +                else if(t[strlen(t)-1] == '?'){
       +                        t[strlen(t)-1] = '\0';
       +                        a = _mkattr(AttrQuery, t, "", a);
       +                        setmalloctag(a, getcallerpc(&s));
       +                }else{
       +                        /* really a syntax error, but better to provide some indication */
       +                        a = _mkattr(AttrNameval, t, "", a);
       +                        setmalloctag(a, getcallerpc(&s));
       +                }
       +        }
       +        free(s);
       +        return cleanattr(a);
       +}
       +
       +char*
       +_strfindattr(Attr *a, char *n)
       +{
       +        a = _findattr(a, n);
       +        if(a == nil)
       +                return nil;
       +        return a->val;
       +}
       +
 (DIR) diff --git a/src/libauth/auth_attr.c b/src/libauth/auth_attr.c
       t@@ -0,0 +1,13 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +#include "authlocal.h"
       +
       +Attr*
       +auth_attr(AuthRpc *rpc)
       +{
       +        if(auth_rpc(rpc, "attr", nil, 0) != ARok)
       +                return nil;
       +        return _parseattr(rpc->arg);
       +}
 (DIR) diff --git a/src/libauth/auth_challenge.c b/src/libauth/auth_challenge.c
       t@@ -0,0 +1,117 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +#include "authlocal.h"
       +
       +Chalstate*
       +auth_challenge(char *fmt, ...)
       +{
       +        char *p;
       +        va_list arg;
       +        Chalstate *c;
       +
       +        quotefmtinstall();        /* just in case */
       +        va_start(arg, fmt);
       +        p = vsmprint(fmt, arg);
       +        va_end(arg);
       +        if(p == nil)
       +                return nil;
       +
       +        c = mallocz(sizeof(*c), 1);
       +        if(c == nil){
       +                free(p);
       +                return nil;
       +        }
       +
       +        if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
       +        Error:
       +                auth_freechal(c);
       +                free(p);
       +                return nil;
       +        }
       +
       +        if((c->rpc=auth_allocrpc(c->afd)) == nil
       +        || auth_rpc(c->rpc, "start", p, strlen(p)) != ARok
       +        || auth_rpc(c->rpc, "read", nil, 0) != ARok)
       +                goto Error;
       +
       +        if(c->rpc->narg > sizeof(c->chal)-1){
       +                werrstr("buffer too small for challenge");
       +                goto Error;
       +        }
       +        memmove(c->chal, c->rpc->arg, c->rpc->narg);
       +        c->nchal = c->rpc->narg;
       +        free(p);
       +        return c;
       +}
       +
       +AuthInfo*
       +auth_response(Chalstate *c)
       +{
       +        int ret;
       +        AuthInfo *ai;
       +
       +        ai = nil;
       +        if(c->afd < 0){
       +                werrstr("auth_response: connection not open");
       +                return nil;
       +        }
       +        if(c->resp == nil){
       +                werrstr("auth_response: nil response");
       +                return nil;
       +        }
       +        if(c->nresp == 0){
       +                werrstr("auth_response: unspecified response length");
       +                return nil;
       +        }
       +
       +        if(c->user){
       +                if(auth_rpc(c->rpc, "write", c->user, strlen(c->user)) != ARok){
       +                        /*
       +                         * if this fails we're out of phase with factotum.
       +                         * give up.
       +                         */
       +                        goto Out;
       +                }
       +        }
       +
       +        if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){
       +                /*
       +                 * don't close the connection -- maybe we'll try again.
       +                 */
       +                return nil;
       +        }
       +
       +        switch(ret = auth_rpc(c->rpc, "read", nil, 0)){
       +        case ARok:
       +        default:
       +                werrstr("factotum protocol botch %d %s", ret, c->rpc->ibuf);
       +                break;
       +        case ARdone:
       +                ai = auth_getinfo(c->rpc);
       +                break;
       +        }
       +
       +Out:
       +        close(c->afd);
       +        auth_freerpc(c->rpc);
       +        c->afd = -1;
       +        c->rpc = nil;
       +        return ai;
       +}
       +
       +void
       +auth_freechal(Chalstate *c)
       +{
       +        if(c == nil)
       +                return;
       +
       +        if(c->afd >= 0)
       +                close(c->afd);
       +        if(c->rpc != nil)
       +                auth_freerpc(c->rpc);
       +
       +        memset(c, 0xBB, sizeof(*c));
       +        free(c);
       +}
 (DIR) diff --git a/src/libauth/auth_chuid.c b/src/libauth/auth_chuid.c
       t@@ -0,0 +1,38 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +/*
       + *  become the authenticated user
       + */
       +int
       +auth_chuid(AuthInfo *ai, char *ns)
       +{
       +        int rv, fd;
       +
       +        if(ai == nil || ai->cap == nil){
       +                werrstr("no capability");
       +                return -1;
       +        }
       +
       +        /* change uid */
       +        fd = open("#¤/capuse", OWRITE);
       +        if(fd < 0){
       +                werrstr("opening #¤/capuse: %r");
       +                return -1;
       +        }
       +        rv = write(fd, ai->cap, strlen(ai->cap));
       +        close(fd);
       +        if(rv < 0){
       +                werrstr("writing %s to #¤/capuse: %r", ai->cap);
       +                return -1;
       +        }
       +
       +        /* get a link to factotum as new user */
       +        fd = open("/srv/factotum", ORDWR);
       +        if(fd >= 0)
       +                mount(fd, -1, "/mnt", MREPL, "");
       +
       +        /* set up new namespace */
       +        return newns(ai->cuid, ns);
       +}
 (DIR) diff --git a/src/libauth/auth_getkey.c b/src/libauth/auth_getkey.c
       t@@ -0,0 +1,51 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +int
       +auth_getkey(char *params)
       +{
       +        char *name;
       +        Dir *d;
       +        int pid;
       +        Waitmsg *w;
       +
       +        /* start /factotum to query for a key */
       +        name = "/factotum";
       +        d = dirstat(name);
       +        if(d == nil){
       +                name = "/boot/factotum";
       +                d = dirstat(name);
       +        }
       +        if(d == nil){
       +                werrstr("auth_getkey: no /factotum or /boot/factotum: didn't get key %s", params);
       +                return -1;
       +        }
       +if(0)        if(d->type != '/'){
       +                werrstr("auth_getkey: /factotum may be bad: didn't get key %s", params);
       +                return -1;
       +        }
       +        switch(pid = fork()){
       +        case -1:
       +                werrstr("can't fork for %s: %r", name);
       +                return -1;
       +        case 0:
       +                execl(name, "getkey", "-g", params, nil);
       +                exits(0);
       +        default:
       +                for(;;){
       +                        w = wait();
       +                        if(w == nil)
       +                                break;
       +                        if(w->pid == pid){
       +                                if(w->msg[0] != '\0'){
       +                                        free(w);
       +                                        return -1;
       +                                }
       +                                free(w);
       +                                return 0;
       +                        }
       +                }
       +        }
       +        return 0;
       +}
 (DIR) diff --git a/src/libauth/auth_getuserpasswd.c b/src/libauth/auth_getuserpasswd.c
       t@@ -0,0 +1,75 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include "authlocal.h"
       +
       +enum {
       +        ARgiveup = 100,
       +};
       +
       +static int
       +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
       +{
       +        int ret;
       +
       +        for(;;){
       +                if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
       +                        return ret;
       +                if(getkey == nil)
       +                        return ARgiveup;        /* don't know how */
       +                if((*getkey)(rpc->arg) < 0)
       +                        return ARgiveup;        /* user punted */
       +        }
       +}
       +
       +UserPasswd*
       +auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...)
       +{
       +        AuthRpc *rpc;
       +        char *f[3], *p, *params;
       +        int fd;
       +        va_list arg;
       +        UserPasswd *up;
       +
       +        up = nil;
       +        rpc = nil;
       +        params = nil;
       +
       +        fd = open("/mnt/factotum/rpc", ORDWR);
       +        if(fd < 0)
       +                goto out;
       +        rpc = auth_allocrpc(fd);
       +        if(rpc == nil)
       +                goto out;
       +        quotefmtinstall();        /* just in case */
       +        va_start(arg, fmt);
       +        params = vsmprint(fmt, arg);
       +        va_end(arg);
       +        if(params == nil)
       +                goto out;
       +
       +        if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok
       +        || dorpc(rpc, "read", nil, 0, getkey) != ARok)
       +                goto out;
       +
       +        rpc->arg[rpc->narg] = '\0';
       +        if(tokenize(rpc->arg, f, 2) != 2){
       +                werrstr("bad answer from factotum");
       +                goto out;
       +        }
       +        up = malloc(sizeof(*up)+rpc->narg+1);
       +        if(up == nil)
       +                goto out;
       +        p = (char*)&up[1];
       +        strcpy(p, f[0]);
       +        up->user = p;
       +        p += strlen(p)+1;
       +        strcpy(p, f[1]);
       +        up->passwd = p;
       +
       +out:
       +        free(params);
       +        auth_freerpc(rpc);
       +        close(fd);
       +        return up;
       +}
 (DIR) diff --git a/src/libauth/auth_proxy.c b/src/libauth/auth_proxy.c
       t@@ -0,0 +1,212 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <fcall.h>
       +#include <auth.h>
       +#include "authlocal.h"
       +
       +enum { 
       +        ARgiveup = 100,
       +};
       +
       +static uchar*
       +gstring(uchar *p, uchar *ep, char **s)
       +{
       +        uint n;
       +
       +        if(p == nil)
       +                return nil;
       +        if(p+BIT16SZ > ep)
       +                return nil;
       +        n = GBIT16(p);
       +        p += BIT16SZ;
       +        if(p+n > ep)
       +                return nil;
       +        *s = malloc(n+1);
       +        memmove((*s), p, n);
       +        (*s)[n] = '\0';
       +        p += n;
       +        return p;
       +}
       +
       +static uchar*
       +gcarray(uchar *p, uchar *ep, uchar **s, int *np)
       +{
       +        uint n;
       +
       +        if(p == nil)
       +                return nil;
       +        if(p+BIT16SZ > ep)
       +                return nil;
       +        n = GBIT16(p);
       +        p += BIT16SZ;
       +        if(p+n > ep)
       +                return nil;
       +        *s = malloc(n);
       +        if(*s == nil)
       +                return nil;
       +        memmove((*s), p, n);
       +        *np = n;
       +        p += n;
       +        return p;
       +}
       +
       +void
       +auth_freeAI(AuthInfo *ai)
       +{
       +        if(ai == nil)
       +                return;
       +        free(ai->cuid);
       +        free(ai->suid);
       +        free(ai->cap);
       +        free(ai->secret);
       +        free(ai);
       +}
       +
       +static uchar*
       +convM2AI(uchar *p, int n, AuthInfo **aip)
       +{
       +        uchar *e = p+n;
       +        AuthInfo *ai;
       +
       +        ai = mallocz(sizeof(*ai), 1);
       +        if(ai == nil)
       +                return nil;
       +
       +        p = gstring(p, e, &ai->cuid);
       +        p = gstring(p, e, &ai->suid);
       +        p = gstring(p, e, &ai->cap);
       +        p = gcarray(p, e, &ai->secret, &ai->nsecret);
       +        if(p == nil)
       +                auth_freeAI(ai);
       +        else
       +                *aip = ai;
       +        return p;
       +}
       +
       +AuthInfo*
       +auth_getinfo(AuthRpc *rpc)
       +{
       +        AuthInfo *a;
       +
       +        if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
       +                return nil;
       +        if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
       +                werrstr("bad auth info from factotum");
       +                return nil;
       +        }
       +        return a;
       +}
       +
       +static int
       +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
       +{
       +        int ret;
       +
       +        for(;;){
       +                if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
       +                        return ret;
       +                if(getkey == nil)
       +                        return ARgiveup;        /* don't know how */
       +                if((*getkey)(rpc->arg) < 0)
       +                        return ARgiveup;        /* user punted */
       +        }
       +}
       +
       +/*
       + *  this just proxies what the factotum tells it to.
       + */
       +AuthInfo*
       +fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params)
       +{
       +        char *buf;
       +        int m, n, ret;
       +        AuthInfo *a;
       +        char oerr[ERRMAX];
       +
       +        rerrstr(oerr, sizeof oerr);
       +        werrstr("UNKNOWN AUTH ERROR");
       +
       +        if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
       +                werrstr("fauth_proxy start: %r");
       +                return nil;
       +        }
       +
       +        buf = malloc(AuthRpcMax);
       +        if(buf == nil)
       +                return nil;
       +        for(;;){
       +                switch(dorpc(rpc, "read", nil, 0, getkey)){
       +                case ARdone:
       +                        free(buf);
       +                        a = auth_getinfo(rpc);
       +                        errstr(oerr, sizeof oerr);        /* no error, restore whatever was there */
       +                        return a;
       +                case ARok:
       +                        if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
       +                                werrstr("auth_proxy write fd: %r");
       +                                goto Error;
       +                        }
       +                        break;
       +                case ARphase:
       +                        n = 0;
       +                        memset(buf, 0, AuthRpcMax);
       +                        while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
       +                                if(atoi(rpc->arg) > AuthRpcMax)
       +                                        break;
       +                                m = read(fd, buf+n, atoi(rpc->arg)-n);
       +                                if(m <= 0){
       +                                        if(m == 0)
       +                                                werrstr("auth_proxy short read: %s", buf);
       +                                        goto Error;
       +                                }
       +                                n += m;
       +                        }
       +                        if(ret != ARok){
       +                                werrstr("auth_proxy rpc write: %s: %r", buf);
       +                                goto Error;
       +                        }
       +                        break;
       +                default:
       +                        werrstr("auth_proxy rpc: %r");
       +                        goto Error;
       +                }
       +        }
       +Error:
       +        free(buf);
       +        return nil;
       +}
       +
       +AuthInfo*
       +auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...)
       +{
       +        int afd;
       +        char *p;
       +        va_list arg;
       +        AuthInfo *ai;
       +        AuthRpc *rpc;
       +
       +        quotefmtinstall();        /* just in case */
       +        va_start(arg, fmt);
       +        p = vsmprint(fmt, arg);
       +        va_end(arg);
       +
       +        afd = open("/mnt/factotum/rpc", ORDWR);
       +        if(afd < 0){
       +                werrstr("opening /mnt/factotum/rpc: %r");
       +                free(p);
       +                return nil;
       +        }
       +
       +        rpc = auth_allocrpc(afd);
       +        if(rpc == nil){
       +                free(p);
       +                return nil;
       +        }
       +
       +        ai = fauth_proxy(fd, rpc, getkey, p);
       +        free(p);
       +        auth_freerpc(rpc);
       +        close(afd);
       +        return ai;
       +}
       +
 (DIR) diff --git a/src/libauth/auth_respond.c b/src/libauth/auth_respond.c
       t@@ -0,0 +1,73 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +#include "authlocal.h"
       +
       +enum {
       +        ARgiveup = 100,
       +};
       +
       +static int
       +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
       +{
       +        int ret;
       +
       +        for(;;){
       +                if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
       +                        return ret;
       +                if(getkey == nil)
       +                        return ARgiveup;        /* don't know how */
       +                if((*getkey)(rpc->arg) < 0)
       +                        return ARgiveup;        /* user punted */
       +        }
       +}
       +
       +int
       +auth_respond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...)
       +{
       +        char *p, *s;
       +        va_list arg;
       +        int afd;
       +        AuthRpc *rpc;
       +        Attr *a;
       +
       +        if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
       +                return -1;
       +        
       +        if((rpc = auth_allocrpc(afd)) == nil){
       +                close(afd);
       +                return -1;
       +        }
       +
       +        quotefmtinstall();        /* just in case */
       +        va_start(arg, fmt);
       +        p = vsmprint(fmt, arg);
       +        va_end(arg);
       +
       +        if(p==nil
       +        || dorpc(rpc, "start", p, strlen(p), getkey) != ARok
       +        || dorpc(rpc, "write", chal, nchal, getkey) != ARok
       +        || dorpc(rpc, "read", nil, 0, getkey) != ARok){
       +                free(p);
       +                close(afd);
       +                auth_freerpc(rpc);
       +                return -1;
       +        }
       +        free(p);
       +
       +        if(rpc->narg < nresp)
       +                nresp = rpc->narg;
       +        memmove(resp, rpc->arg, nresp);
       +
       +        if((a = auth_attr(rpc)) != nil
       +        && (s = _strfindattr(a, "user")) != nil && strlen(s) < nuser)
       +                strcpy(user, s);
       +        else if(nuser > 0)
       +                user[0] = '\0';
       +
       +        _freeattr(a);
       +        close(afd);
       +        auth_freerpc(rpc);
       +        return nresp;        
       +}
 (DIR) diff --git a/src/libauth/auth_rpc.c b/src/libauth/auth_rpc.c
       t@@ -0,0 +1,116 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include "authlocal.h"
       +
       +static struct {
       +        char *verb;
       +        int val;
       +} tab[] = {
       +        "ok",                        ARok,
       +        "done",                ARdone,
       +        "error",                ARerror,
       +        "needkey",        ARneedkey,
       +        "badkey",                ARbadkey,
       +        "phase",                ARphase,
       +        "toosmall",        ARtoosmall,
       +        "error",                ARerror,
       +};
       +
       +static int
       +classify(char *buf, uint n, AuthRpc *rpc)
       +{
       +        int i, len;
       +
       +        for(i=0; i<nelem(tab); i++){
       +                len = strlen(tab[i].verb);
       +                if(n >= len && memcmp(buf, tab[i].verb, len) == 0 && (n==len || buf[len]==' ')){
       +                        if(n==len){
       +                                rpc->narg = 0;
       +                                rpc->arg = "";
       +                        }else{
       +                                rpc->narg = n - (len+1);
       +                                rpc->arg = (char*)buf+len+1;
       +                        }
       +                        return tab[i].val;
       +                }
       +        }
       +        werrstr("malformed rpc response: %s", buf);
       +        return ARrpcfailure;
       +}
       +
       +AuthRpc*
       +auth_allocrpc(int afd)
       +{
       +        AuthRpc *rpc;
       +
       +        rpc = mallocz(sizeof(*rpc), 1);
       +        if(rpc == nil)
       +                return nil;
       +        rpc->afd = afd;
       +        return rpc;
       +}
       +
       +void
       +auth_freerpc(AuthRpc *rpc)
       +{
       +        free(rpc);
       +}
       +
       +uint
       +auth_rpc(AuthRpc *rpc, char *verb, void *a, int na)
       +{
       +        int l, n, type;
       +        char *f[4];
       +
       +        l = strlen(verb);
       +        if(na+l+1 > AuthRpcMax){
       +                werrstr("rpc too big");
       +                return ARtoobig;
       +        }
       +
       +        memmove(rpc->obuf, verb, l);
       +        rpc->obuf[l] = ' ';
       +        memmove(rpc->obuf+l+1, a, na);
       +        if((n=write(rpc->afd, rpc->obuf, l+1+na)) != l+1+na){
       +                if(n >= 0)
       +                        werrstr("auth_rpc short write");
       +                return ARrpcfailure;
       +        }
       +
       +        if((n=read(rpc->afd, rpc->ibuf, AuthRpcMax)) < 0)
       +                return ARrpcfailure;
       +        rpc->ibuf[n] = '\0';
       +
       +        /*
       +         * Set error string for good default behavior.
       +         */
       +        switch(type = classify(rpc->ibuf, n, rpc)){
       +        default:
       +                werrstr("unknown rpc type %d (bug in auth_rpc.c)", type);
       +                break;
       +        case ARok:
       +                break;
       +        case ARrpcfailure:
       +                break;
       +        case ARerror:
       +                if(rpc->narg == 0)
       +                        werrstr("unspecified rpc error");
       +                else
       +                        werrstr("%s", rpc->arg);
       +                break;
       +        case ARneedkey:
       +                werrstr("needkey %s", rpc->arg);
       +                break;
       +        case ARbadkey:
       +                if(getfields(rpc->arg, f, nelem(f), 0, "\n") < 2)
       +                        werrstr("badkey %s", rpc->arg);
       +                else
       +                        werrstr("badkey %s", f[1]);
       +                break;
       +        case ARphase:
       +                werrstr("phase error %s", rpc->arg);
       +                break;
       +        }
       +        return type;
       +}
 (DIR) diff --git a/src/libauth/auth_userpasswd.c b/src/libauth/auth_userpasswd.c
       t@@ -0,0 +1,50 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +#include "authlocal.h"
       +
       +/*
       + * compute the proper response.  We encrypt the ascii of
       + * challenge number, with trailing binary zero fill.
       + * This process was derived empirically.
       + * this was copied from inet's guard.
       + */
       +static void
       +netresp(char *key, long chal, char *answer)
       +{
       +        uchar buf[8];
       +
       +        memset(buf, 0, 8);
       +        sprint((char *)buf, "%lud", chal);
       +        if(encrypt(key, buf, 8) < 0)
       +                abort();
       +        chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
       +        sprint(answer, "%.8lux", chal);
       +}
       +
       +AuthInfo*
       +auth_userpasswd(char *user, char *passwd)
       +{
       +        char key[DESKEYLEN], resp[16];
       +        AuthInfo *ai;
       +        Chalstate *ch;
       +
       +        /*
       +         * Probably we should have a factotum protocol
       +         * to check a raw password.  For now, we use
       +         * p9cr, which is simplest to speak.
       +         */
       +        if((ch = auth_challenge("user=%q proto=p9cr role=server", user)) == nil)
       +                return nil;
       +
       +        passtokey(key, passwd);
       +        netresp(key, atol(ch->chal), resp);
       +        memset(key, 0, sizeof key);
       +
       +        ch->resp = resp;
       +        ch->nresp = strlen(resp);
       +        ai = auth_response(ch);
       +        auth_freechal(ch);
       +        return ai;
       +}
 (DIR) diff --git a/src/libauth/auth_wep.c b/src/libauth/auth_wep.c
       t@@ -0,0 +1,50 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include "authlocal.h"
       +
       +/*
       + *  make factotum add wep keys to an 802.11 device
       + */
       +int
       +auth_wep(char *dev, char *fmt, ...)
       +{
       +        AuthRpc *rpc;
       +        char *params, *p;
       +        int fd;
       +        va_list arg;
       +        int rv;
       +
       +        rv = -1;
       +
       +        if(dev == nil){
       +                werrstr("no device specified");
       +                return rv;
       +        }
       +
       +        fd = open("/mnt/factotum/rpc", ORDWR);
       +        if(fd < 0)
       +                return rv;
       +
       +        rpc = auth_allocrpc(fd);
       +        if(rpc != nil){
       +                quotefmtinstall();        /* just in case */
       +                va_start(arg, fmt);
       +                params = vsmprint(fmt, arg);
       +                va_end(arg);
       +                if(params != nil){
       +                        p = smprint("proto=wep %s", params);
       +                        if(p != nil){
       +                                if(auth_rpc(rpc, "start", p, strlen(p)) == ARok
       +                                && auth_rpc(rpc, "write", dev, strlen(dev)) == ARok)
       +                                        rv = 0;
       +                                free(p);
       +                        }
       +                        free(params);
       +                }
       +                auth_freerpc(rpc);
       +        }
       +        close(fd);
       +                
       +        return rv;
       +}
 (DIR) diff --git a/src/libauth/authlocal.h b/src/libauth/authlocal.h
       t@@ -0,0 +1 @@
       +extern AuthInfo*        _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params);
 (DIR) diff --git a/src/libauth/httpauth.c b/src/libauth/httpauth.c
       t@@ -0,0 +1,51 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +
       +/* deprecated.
       +        This is the mechanism that put entries in /sys/lib/httpd.rewrite
       +        and passwords on the authserver in /sys/lib/httppasswords, which
       +        was awkward to administer.  Instead, use local .httplogin files,
       +        which are implemented in sys/src/cmd/ip/httpd/authorize.c */
       +
       +int
       +httpauth(char *name, char *password)
       +{
       +        int afd;
       +        Ticketreq tr;
       +        Ticket        t;
       +        char key[DESKEYLEN];
       +        char buf[512];
       +
       +        afd = authdial(nil, nil);
       +        if(afd < 0)
       +                return -1;
       +
       +        /* send ticket request to AS */
       +        memset(&tr, 0, sizeof(tr));
       +        strcpy(tr.uid, name);
       +        tr.type = AuthHttp;
       +        convTR2M(&tr, buf);
       +        if(write(afd, buf, TICKREQLEN) != TICKREQLEN){
       +                close(afd);
       +                return -1;
       +        }
       +        if(_asrdresp(afd, buf, TICKETLEN) < 0){
       +                close(afd);
       +                return -1;
       +        }
       +        close(afd);
       +
       +        /*
       +         *  use password and try to decrypt the
       +         *  ticket.  If it doesn't work we've got a bad password,
       +         *  give up.
       +         */
       +        passtokey(key, password);
       +        convM2T(buf, &t, key);
       +        if(t.num != AuthHr || strcmp(t.cuid, tr.uid))
       +                return -1;
       +
       +        return 0;
       +}
 (DIR) diff --git a/src/libauth/login.c b/src/libauth/login.c
       t@@ -0,0 +1,17 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <auth.h>
       +
       +int
       +login(char *user, char *password, char *namespace)
       +{
       +        int rv;
       +        AuthInfo *ai;
       +
       +        if((ai = auth_userpasswd(user, password)) == nil)
       +                return -1;
       +
       +        rv = auth_chuid(ai, namespace);
       +        auth_freeAI(ai);
       +        return rv;
       +}
 (DIR) diff --git a/src/libauth/mkfile b/src/libauth/mkfile
       t@@ -0,0 +1,27 @@
       +PLAN9=../..
       +<$PLAN9/src/mkhdr
       +
       +LIB=libauth.a
       +OFILES=\
       +#        amount.$O\
       +#        amount_getkey.$O\
       +        attr.$O\
       +#        auth_attr.$O\
       +#        auth_challenge.$O\
       +#        auth_chuid.$O\
       +#        auth_getkey.$O\
       +#        auth_getuserpasswd.$O\
       +#        auth_proxy.$O\
       +#        auth_respond.$O\
       +#        auth_rpc.$O\
       +#        auth_userpasswd.$O\
       +#        auth_wep.$O\
       +#        login.$O\
       +#        newns.$O\
       +#        noworld.$O\
       +
       +HFILES=\
       +        $PLAN9/include/auth.h\
       +        authlocal.h\
       +
       +<$PLAN9/src/mksyslib
 (DIR) diff --git a/src/libauth/newns.c b/src/libauth/newns.c
       t@@ -0,0 +1,322 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <bio.h>
       +#include <auth.h>
       +#include <authsrv.h>
       +#include "authlocal.h"
       +
       +enum
       +{
       +        NARG        = 15,                /* max number of arguments */
       +        MAXARG        = 10*ANAMELEN,        /* max length of an argument */
       +};
       +
       +static int        setenv(char*, char*);
       +static char        *expandarg(char*, char*);
       +static int        splitargs(char*, char*[], char*, int);
       +static int        nsfile(Biobuf *, AuthRpc *);
       +static int        nsop(int, char*[], AuthRpc*);
       +static int        callexport(char*, char*);
       +static int        catch(void*, char*);
       +
       +static int
       +buildns(int newns, char *user, char *file)
       +{
       +        Biobuf *b;
       +        char home[4*ANAMELEN];
       +        int afd;
       +        AuthRpc *rpc;
       +        int cdroot;
       +        char *path;
       +
       +        rpc = nil;
       +        /* try for factotum now because later is impossible */
       +        afd = open("/mnt/factotum/rpc", ORDWR);
       +        if(afd >= 0){
       +                rpc = auth_allocrpc(afd);
       +                if(rpc == nil){
       +                        close(afd);
       +                        afd = -1;
       +                }
       +        }
       +        if(file == nil){
       +                if(!newns){
       +                        werrstr("no namespace file specified");
       +                        return -1;
       +                }
       +                file = "/lib/namespace";
       +        }
       +        b = Bopen(file, OREAD);
       +        if(b == 0){
       +                werrstr("can't open %s: %r", file);
       +                close(afd);
       +                auth_freerpc(rpc);
       +                return -1;
       +        }
       +        if(newns){
       +                rfork(RFENVG|RFCNAMEG);
       +                setenv("user", user);
       +                snprint(home, 2*ANAMELEN, "/usr/%s", user);
       +                setenv("home", home);
       +        }
       +        cdroot = nsfile(b, rpc);
       +        Bterm(b);
       +        if(rpc){
       +                close(rpc->afd);
       +                auth_freerpc(rpc);
       +        }
       +
       +        /* make sure we managed to cd into the new name space */
       +        if(newns && !cdroot){
       +                path = malloc(1024);
       +                if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
       +                        chdir("/");
       +                if(path != nil)
       +                        free(path);
       +        }
       +
       +        return 0;
       +}
       +
       +static int
       +nsfile(Biobuf *b, AuthRpc *rpc)
       +{
       +        int argc;
       +        char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
       +        int cdroot = 0;
       +
       +        atnotify(catch, 1);
       +        while(cmd = Brdline(b, '\n')){
       +                cmd[Blinelen(b)-1] = '\0';
       +                while(*cmd==' ' || *cmd=='\t')
       +                        cmd++;
       +                if(*cmd == '#')
       +                        continue;
       +                argc = splitargs(cmd, argv, argbuf, NARG);
       +                if(argc)
       +                        cdroot |= nsop(argc, argv, rpc);
       +        }
       +        atnotify(catch, 0);
       +        return cdroot;
       +}
       +
       +int
       +newns(char *user, char *file)
       +{
       +        return buildns(1, user, file);
       +}
       +
       +int
       +addns(char *user, char *file)
       +{
       +        return buildns(0, user, file);
       +}
       +
       +static int
       +famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
       +{
       +        int afd;
       +        AuthInfo *ai;
       +
       +        afd = fauth(fd, aname);
       +        if(afd >= 0){
       +                ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
       +                if(ai != nil)
       +                        auth_freeAI(ai);
       +        }
       +        return mount(fd, afd, mntpt, flags, aname);
       +}
       +
       +static int
       +nsop(int argc, char *argv[], AuthRpc *rpc)
       +{
       +        char *argv0;
       +        ulong flags;
       +        int fd;
       +        Biobuf *b;
       +        int cdroot = 0;
       +
       +        flags = 0;
       +        argv0 = 0;
       +        ARGBEGIN{
       +        case 'a':
       +                flags |= MAFTER;
       +                break;
       +        case 'b':
       +                flags |= MBEFORE;
       +                break;
       +        case 'c':
       +                flags |= MCREATE;
       +                break;
       +        case 'C':
       +                flags |= MCACHE;
       +                break;
       +        }ARGEND
       +
       +        if(!(flags & (MAFTER|MBEFORE)))
       +                flags |= MREPL;
       +
       +        if(strcmp(argv0, ".") == 0 && argc == 1){
       +                b = Bopen(argv[0], OREAD);
       +                if(b == nil)
       +                        return 0;
       +                cdroot |= nsfile(b, rpc);
       +                Bterm(b);
       +        } else if(strcmp(argv0, "clear") == 0 && argc == 0)
       +                rfork(RFCNAMEG);
       +        else if(strcmp(argv0, "bind") == 0 && argc == 2)
       +                bind(argv[0], argv[1], flags);
       +        else if(strcmp(argv0, "unmount") == 0){
       +                if(argc == 1)
       +                        unmount(nil, argv[0]);
       +                else if(argc == 2)
       +                        unmount(argv[0], argv[1]);
       +        } else if(strcmp(argv0, "mount") == 0){
       +                fd = open(argv[0], ORDWR);
       +                if(argc == 2)
       +                        famount(fd, rpc, argv[1], flags, "");
       +                else if(argc == 3)
       +                        famount(fd, rpc, argv[1], flags, argv[2]);
       +                close(fd);
       +        } else if(strcmp(argv0, "import") == 0){
       +                fd = callexport(argv[0], argv[1]);
       +                if(argc == 2)
       +                        famount(fd, rpc, argv[1], flags, "");
       +                else if(argc == 3)
       +                        famount(fd, rpc, argv[2], flags, "");
       +                close(fd);
       +        } else if(strcmp(argv0, "cd") == 0 && argc == 1)
       +                if(chdir(argv[0]) == 0 && *argv[0] == '/')
       +                        cdroot = 1;
       +        return cdroot;
       +}
       +
       +static char *wocp = "sys: write on closed pipe";
       +
       +static int
       +catch(void *x, char *m)
       +{
       +        USED(x);
       +        return strncmp(m, wocp, strlen(wocp)) == 0;
       +}
       +
       +static int
       +callexport(char *sys, char *tree)
       +{
       +        char *na, buf[3];
       +        int fd;
       +        AuthInfo *ai;
       +
       +        na = netmkaddr(sys, 0, "exportfs");
       +        if((fd = dial(na, 0, 0, 0)) < 0)
       +                return -1;
       +        if((ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client")) == nil
       +        || write(fd, tree, strlen(tree)) < 0
       +        || read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
       +                close(fd);
       +                auth_freeAI(ai);
       +                return -1;
       +        }
       +        auth_freeAI(ai);
       +        return fd;
       +}
       +
       +static int
       +splitargs(char *p, char *argv[], char *argbuf, int nargv)
       +{
       +        char *q;
       +        int i, n;
       +
       +        n = gettokens(p, argv, nargv, " \t'\r");
       +        if(n == nargv)
       +                return 0;
       +        for(i = 0; i < n; i++){
       +                q = argv[i];
       +                argv[i] = argbuf;
       +                argbuf = expandarg(q, argbuf);
       +                if(!argbuf)
       +                        return 0;
       +        }
       +        return n;
       +}
       +
       +/*
       + * copy the arg into the buffer,
       + * expanding any environment variables.
       + * environment variables are assumed to be
       + * names (ie. < ANAMELEN long)
       + * the entire argument is expanded to be at
       + * most MAXARG long and null terminated
       + * the address of the byte after the terminating null is returned
       + * any problems cause a 0 return;
       + */
       +static char *
       +expandarg(char *arg, char *buf)
       +{
       +        char env[3+ANAMELEN], *p, *q, *x;
       +        int fd, n, len;
       +
       +        n = 0;
       +        while(p = utfrune(arg, L'$')){
       +                len = p - arg;
       +                if(n + len + ANAMELEN >= MAXARG-1)
       +                        return 0;
       +                memmove(&buf[n], arg, len);
       +                n += len;
       +                p++;
       +                arg = utfrune(p, L'\0');
       +                q = utfrune(p, L'/');
       +                if(q && q < arg)
       +                        arg = q;
       +                q = utfrune(p, L'.');
       +                if(q && q < arg)
       +                        arg = q;
       +                q = utfrune(p, L'$');
       +                if(q && q < arg)
       +                        arg = q;
       +                len = arg - p;
       +                if(len >= ANAMELEN)
       +                        continue;
       +                strcpy(env, "#e/");
       +                strncpy(env+3, p, len);
       +                env[3+len] = '\0';
       +                fd = open(env, OREAD);
       +                if(fd >= 0){
       +                        len = read(fd, &buf[n], ANAMELEN - 1);
       +                        /* some singleton environment variables have trailing NULs */
       +                        /* lists separate entries with NULs; we arbitrarily take the first element */
       +                        if(len > 0){
       +                                x = memchr(&buf[n], 0, len);
       +                                if(x != nil)
       +                                        len = x - &buf[n];
       +                                n += len;
       +                        }
       +                        close(fd);
       +                }
       +        }
       +        len = strlen(arg);
       +        if(n + len >= MAXARG - 1)
       +                return 0;
       +        strcpy(&buf[n], arg);
       +        return &buf[n+len+1];
       +}
       +
       +static int
       +setenv(char *name, char *val)
       +{
       +        int f;
       +        char ename[ANAMELEN+6];
       +        long s;
       +
       +        sprint(ename, "#e/%s", name);
       +        f = create(ename, OWRITE, 0664);
       +        if(f < 0)
       +                return -1;
       +        s = strlen(val);
       +        if(write(f, val, s) != s){
       +                close(f);
       +                return -1;
       +        }
       +        close(f);
       +        return 0;
       +}
 (DIR) diff --git a/src/libauth/noworld.c b/src/libauth/noworld.c
       t@@ -0,0 +1,45 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <bio.h>
       +#include <auth.h>
       +
       +/*
       + *  see if user is in the group noworld, i.e., has all file
       + *  priviledges masked with 770, and all directories with
       + *  771, before checking access rights
       + */
       +int
       +noworld(char *user)
       +{
       +        Biobuf *b;
       +        char *p;
       +        int n;
       +
       +        b = Bopen("/adm/users", OREAD);
       +        if(b == nil)
       +                return 0;
       +        while((p = Brdline(b, '\n')) != nil){
       +                p[Blinelen(b)-1] = 0;
       +                p = strchr(p, ':');
       +                if(p == nil)
       +                        continue;
       +                if(strncmp(p, ":noworld:", 9) == 0){
       +                        p += 9;
       +                        break;
       +                }
       +        }
       +        n = strlen(user);
       +        while(p != nil && *p != 0){
       +                p = strstr(p, user);
       +                if(p == nil)
       +                        break;
       +                if(*(p-1) == ':' || *(p-1) == ',')
       +                if(*(p+n) == ':' || *(p+n) == ',' || *(p+n) == 0){
       +                        Bterm(b);
       +                        return 1;
       +                }
       +                p++;
       +        }
       +        Bterm(b);
       +        return 0;
       +}