summaryrefslogtreecommitdiff
path: root/sys/src/cmd/unix/drawterm/libauth
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/unix/drawterm/libauth
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/unix/drawterm/libauth')
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/Makefile22
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/attr.c174
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_attr.c13
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_challenge.c117
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c75
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_proxy.c213
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_respond.c73
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_rpc.c116
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c50
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/authlocal.h1
-rwxr-xr-xsys/src/cmd/unix/drawterm/libauth/httpauth.c51
11 files changed, 905 insertions, 0 deletions
diff --git a/sys/src/cmd/unix/drawterm/libauth/Makefile b/sys/src/cmd/unix/drawterm/libauth/Makefile
new file mode 100755
index 000000000..39b1ec9e4
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/libauth/Makefile
@@ -0,0 +1,22 @@
+ROOT=..
+include ../Make.config
+
+LIB=libauth.a
+OFILES=\
+ attr.$O\
+ auth_attr.$O\
+ auth_challenge.$O\
+ auth_getuserpasswd.$O\
+ auth_proxy.$O\
+ auth_respond.$O\
+ auth_rpc.$O\
+ auth_userpasswd.$O\
+
+default: $(LIB)
+$(LIB): $(OFILES)
+ $(AR) r $(LIB) $(OFILES)
+ $(RANLIB) $(LIB)
+
+%.$O: %.c
+ $(CC) $(CFLAGS) $*.c
+
diff --git a/sys/src/cmd/unix/drawterm/libauth/attr.c b/sys/src/cmd/unix/drawterm/libauth/attr.c
new file mode 100755
index 000000000..fcfa35f6a
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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/sys/src/cmd/unix/drawterm/libauth/auth_attr.c b/sys/src/cmd/unix/drawterm/libauth/auth_attr.c
new file mode 100755
index 000000000..8842590a9
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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/sys/src/cmd/unix/drawterm/libauth/auth_challenge.c b/sys/src/cmd/unix/drawterm/libauth/auth_challenge.c
new file mode 100755
index 000000000..298f5f1b2
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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/sys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c b/sys/src/cmd/unix/drawterm/libauth/auth_getuserpasswd.c
new file mode 100755
index 000000000..186488f52
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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 == 0)
+ 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/sys/src/cmd/unix/drawterm/libauth/auth_proxy.c b/sys/src/cmd/unix/drawterm/libauth/auth_proxy.c
new file mode 100755
index 000000000..b6b24df14
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/libauth/auth_proxy.c
@@ -0,0 +1,213 @@
+#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;
+ a = 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 == 0)
+ 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/sys/src/cmd/unix/drawterm/libauth/auth_respond.c b/sys/src/cmd/unix/drawterm/libauth/auth_respond.c
new file mode 100755
index 000000000..5c6d177f3
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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 == 0)
+ 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/sys/src/cmd/unix/drawterm/libauth/auth_rpc.c b/sys/src/cmd/unix/drawterm/libauth/auth_rpc.c
new file mode 100755
index 000000000..4333a7381
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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/sys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c b/sys/src/cmd/unix/drawterm/libauth/auth_userpasswd.c
new file mode 100755
index 000000000..34a38c26a
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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/sys/src/cmd/unix/drawterm/libauth/authlocal.h b/sys/src/cmd/unix/drawterm/libauth/authlocal.h
new file mode 100755
index 000000000..2c52bf8b6
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/libauth/authlocal.h
@@ -0,0 +1 @@
+extern AuthInfo* _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params);
diff --git a/sys/src/cmd/unix/drawterm/libauth/httpauth.c b/sys/src/cmd/unix/drawterm/libauth/httpauth.c
new file mode 100755
index 000000000..9d1b0d26f
--- /dev/null
+++ b/sys/src/cmd/unix/drawterm/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;
+}