#include <9pm/u.h> #include <9pm/libc.h> #include <9pm/auth.h> #include "authlocal.h" Chalstate* auth_challenge(char *fmt, ...) { char buf[256]; va_list arg; Chalstate *c; quotefmtinstall(); /* just in case */ va_start(arg, fmt); doprint(buf, buf+sizeof buf, fmt, arg); va_end(arg); c = mallocz(sizeof(*c), 1); if(c == nil) return nil; if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ auth_freechal(c); return nil; } c->rpc = _auth_allocrpc(c->afd); if(c->rpc == nil){ auth_freechal(c); return nil; } if(_auth_rpc(c->rpc, "start", buf, strlen(buf)) != ARok){ auth_freechal(c); return nil; } if(_auth_rpc(c->rpc, "read", nil, 0) != ARok){ auth_freechal(c); return nil; } if(c->rpc->narg > sizeof(c->chal)-1){ werrstr("buffer too small for challenge"); auth_freechal(c); return nil; } memmove(c->chal, c->rpc->arg, c->rpc->narg); c->nchal = c->rpc->narg; 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); }