diff options
author | rsc <devnull@localhost> | 2004-06-17 03:27:35 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-06-17 03:27:35 +0000 |
commit | be8b315d1522fa1c109a49435c1638bafd838b91 (patch) | |
tree | 4d8e2a0799ab463160b0a80feb0a008940d11230 /src/libauth | |
parent | d9c8a7c5366aea63aa45b4afc6a75d133192786d (diff) | |
download | plan9port-be8b315d1522fa1c109a49435c1638bafd838b91.tar.gz plan9port-be8b315d1522fa1c109a49435c1638bafd838b91.tar.bz2 plan9port-be8b315d1522fa1c109a49435c1638bafd838b91.zip |
basically none of these build
Diffstat (limited to 'src/libauth')
-rw-r--r-- | src/libauth/amount.c | 22 | ||||
-rw-r--r-- | src/libauth/amount_getkey.c | 5 | ||||
-rw-r--r-- | src/libauth/attr.c | 174 | ||||
-rw-r--r-- | src/libauth/auth_attr.c | 13 | ||||
-rw-r--r-- | src/libauth/auth_challenge.c | 117 | ||||
-rw-r--r-- | src/libauth/auth_chuid.c | 38 | ||||
-rw-r--r-- | src/libauth/auth_getkey.c | 51 | ||||
-rw-r--r-- | src/libauth/auth_getuserpasswd.c | 75 | ||||
-rw-r--r-- | src/libauth/auth_proxy.c | 212 | ||||
-rw-r--r-- | src/libauth/auth_respond.c | 73 | ||||
-rw-r--r-- | src/libauth/auth_rpc.c | 116 | ||||
-rw-r--r-- | src/libauth/auth_userpasswd.c | 50 | ||||
-rw-r--r-- | src/libauth/auth_wep.c | 50 | ||||
-rw-r--r-- | src/libauth/authlocal.h | 1 | ||||
-rw-r--r-- | src/libauth/httpauth.c | 51 | ||||
-rw-r--r-- | src/libauth/login.c | 17 | ||||
-rw-r--r-- | src/libauth/mkfile | 27 | ||||
-rw-r--r-- | src/libauth/newns.c | 322 | ||||
-rw-r--r-- | src/libauth/noworld.c | 45 |
19 files changed, 1459 insertions, 0 deletions
diff --git a/src/libauth/amount.c b/src/libauth/amount.c new file mode 100644 index 00000000..6565e373 --- /dev/null +++ b/src/libauth/amount.c @@ -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; +} diff --git a/src/libauth/amount_getkey.c b/src/libauth/amount_getkey.c new file mode 100644 index 00000000..019fad2a --- /dev/null +++ b/src/libauth/amount_getkey.c @@ -0,0 +1,5 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> + +int (*amount_getkey)(char*) = auth_getkey; diff --git a/src/libauth/attr.c b/src/libauth/attr.c new file mode 100644 index 00000000..5f35750b --- /dev/null +++ b/src/libauth/attr.c @@ -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; +} + diff --git a/src/libauth/auth_attr.c b/src/libauth/auth_attr.c new file mode 100644 index 00000000..8842590a --- /dev/null +++ b/src/libauth/auth_attr.c @@ -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); +} diff --git a/src/libauth/auth_challenge.c b/src/libauth/auth_challenge.c new file mode 100644 index 00000000..298f5f1b --- /dev/null +++ b/src/libauth/auth_challenge.c @@ -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); +} diff --git a/src/libauth/auth_chuid.c b/src/libauth/auth_chuid.c new file mode 100644 index 00000000..1bfbfff9 --- /dev/null +++ b/src/libauth/auth_chuid.c @@ -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); +} diff --git a/src/libauth/auth_getkey.c b/src/libauth/auth_getkey.c new file mode 100644 index 00000000..0ae28b1e --- /dev/null +++ b/src/libauth/auth_getkey.c @@ -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; +} diff --git a/src/libauth/auth_getuserpasswd.c b/src/libauth/auth_getuserpasswd.c new file mode 100644 index 00000000..4d66dcec --- /dev/null +++ b/src/libauth/auth_getuserpasswd.c @@ -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; +} diff --git a/src/libauth/auth_proxy.c b/src/libauth/auth_proxy.c new file mode 100644 index 00000000..186031eb --- /dev/null +++ b/src/libauth/auth_proxy.c @@ -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; +} + diff --git a/src/libauth/auth_respond.c b/src/libauth/auth_respond.c new file mode 100644 index 00000000..910f06b2 --- /dev/null +++ b/src/libauth/auth_respond.c @@ -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; +} diff --git a/src/libauth/auth_rpc.c b/src/libauth/auth_rpc.c new file mode 100644 index 00000000..4333a738 --- /dev/null +++ b/src/libauth/auth_rpc.c @@ -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; +} diff --git a/src/libauth/auth_userpasswd.c b/src/libauth/auth_userpasswd.c new file mode 100644 index 00000000..34a38c26 --- /dev/null +++ b/src/libauth/auth_userpasswd.c @@ -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; +} diff --git a/src/libauth/auth_wep.c b/src/libauth/auth_wep.c new file mode 100644 index 00000000..afde46b9 --- /dev/null +++ b/src/libauth/auth_wep.c @@ -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; +} diff --git a/src/libauth/authlocal.h b/src/libauth/authlocal.h new file mode 100644 index 00000000..2c52bf8b --- /dev/null +++ b/src/libauth/authlocal.h @@ -0,0 +1 @@ +extern AuthInfo* _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params); diff --git a/src/libauth/httpauth.c b/src/libauth/httpauth.c new file mode 100644 index 00000000..9d1b0d26 --- /dev/null +++ b/src/libauth/httpauth.c @@ -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; +} diff --git a/src/libauth/login.c b/src/libauth/login.c new file mode 100644 index 00000000..8bbc7b10 --- /dev/null +++ b/src/libauth/login.c @@ -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; +} diff --git a/src/libauth/mkfile b/src/libauth/mkfile new file mode 100644 index 00000000..647835bc --- /dev/null +++ b/src/libauth/mkfile @@ -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 diff --git a/src/libauth/newns.c b/src/libauth/newns.c new file mode 100644 index 00000000..66f51d37 --- /dev/null +++ b/src/libauth/newns.c @@ -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; +} diff --git a/src/libauth/noworld.c b/src/libauth/noworld.c new file mode 100644 index 00000000..c61b1463 --- /dev/null +++ b/src/libauth/noworld.c @@ -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; +} |