1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <auth.h>
4*9a747e4fSDavid du Colombier #include <authsrv.h>
5*9a747e4fSDavid du Colombier #include "authlocal.h"
6*9a747e4fSDavid du Colombier
7*9a747e4fSDavid du Colombier Chalstate*
auth_challenge(char * fmt,...)8*9a747e4fSDavid du Colombier auth_challenge(char *fmt, ...)
9*9a747e4fSDavid du Colombier {
10*9a747e4fSDavid du Colombier char *p;
11*9a747e4fSDavid du Colombier va_list arg;
12*9a747e4fSDavid du Colombier Chalstate *c;
13*9a747e4fSDavid du Colombier
14*9a747e4fSDavid du Colombier quotefmtinstall(); /* just in case */
15*9a747e4fSDavid du Colombier va_start(arg, fmt);
16*9a747e4fSDavid du Colombier p = vsmprint(fmt, arg);
17*9a747e4fSDavid du Colombier va_end(arg);
18*9a747e4fSDavid du Colombier if(p == nil)
19*9a747e4fSDavid du Colombier return nil;
20*9a747e4fSDavid du Colombier
21*9a747e4fSDavid du Colombier c = mallocz(sizeof(*c), 1);
22*9a747e4fSDavid du Colombier if(c == nil){
23*9a747e4fSDavid du Colombier free(p);
24*9a747e4fSDavid du Colombier return nil;
25*9a747e4fSDavid du Colombier }
26*9a747e4fSDavid du Colombier
27*9a747e4fSDavid du Colombier if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
28*9a747e4fSDavid du Colombier Error:
29*9a747e4fSDavid du Colombier auth_freechal(c);
30*9a747e4fSDavid du Colombier free(p);
31*9a747e4fSDavid du Colombier return nil;
32*9a747e4fSDavid du Colombier }
33*9a747e4fSDavid du Colombier
34*9a747e4fSDavid du Colombier if((c->rpc=auth_allocrpc(c->afd)) == nil
35*9a747e4fSDavid du Colombier || auth_rpc(c->rpc, "start", p, strlen(p)) != ARok
36*9a747e4fSDavid du Colombier || auth_rpc(c->rpc, "read", nil, 0) != ARok)
37*9a747e4fSDavid du Colombier goto Error;
38*9a747e4fSDavid du Colombier
39*9a747e4fSDavid du Colombier if(c->rpc->narg > sizeof(c->chal)-1){
40*9a747e4fSDavid du Colombier werrstr("buffer too small for challenge");
41*9a747e4fSDavid du Colombier goto Error;
42*9a747e4fSDavid du Colombier }
43*9a747e4fSDavid du Colombier memmove(c->chal, c->rpc->arg, c->rpc->narg);
44*9a747e4fSDavid du Colombier c->nchal = c->rpc->narg;
45*9a747e4fSDavid du Colombier free(p);
46*9a747e4fSDavid du Colombier return c;
47*9a747e4fSDavid du Colombier }
48*9a747e4fSDavid du Colombier
49*9a747e4fSDavid du Colombier AuthInfo*
auth_response(Chalstate * c)50*9a747e4fSDavid du Colombier auth_response(Chalstate *c)
51*9a747e4fSDavid du Colombier {
52*9a747e4fSDavid du Colombier int ret;
53*9a747e4fSDavid du Colombier AuthInfo *ai;
54*9a747e4fSDavid du Colombier
55*9a747e4fSDavid du Colombier ai = nil;
56*9a747e4fSDavid du Colombier if(c->afd < 0){
57*9a747e4fSDavid du Colombier werrstr("auth_response: connection not open");
58*9a747e4fSDavid du Colombier return nil;
59*9a747e4fSDavid du Colombier }
60*9a747e4fSDavid du Colombier if(c->resp == nil){
61*9a747e4fSDavid du Colombier werrstr("auth_response: nil response");
62*9a747e4fSDavid du Colombier return nil;
63*9a747e4fSDavid du Colombier }
64*9a747e4fSDavid du Colombier if(c->nresp == 0){
65*9a747e4fSDavid du Colombier werrstr("auth_response: unspecified response length");
66*9a747e4fSDavid du Colombier return nil;
67*9a747e4fSDavid du Colombier }
68*9a747e4fSDavid du Colombier
69*9a747e4fSDavid du Colombier if(c->user){
70*9a747e4fSDavid du Colombier if(auth_rpc(c->rpc, "write", c->user, strlen(c->user)) != ARok){
71*9a747e4fSDavid du Colombier /*
72*9a747e4fSDavid du Colombier * if this fails we're out of phase with factotum.
73*9a747e4fSDavid du Colombier * give up.
74*9a747e4fSDavid du Colombier */
75*9a747e4fSDavid du Colombier goto Out;
76*9a747e4fSDavid du Colombier }
77*9a747e4fSDavid du Colombier }
78*9a747e4fSDavid du Colombier
79*9a747e4fSDavid du Colombier if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){
80*9a747e4fSDavid du Colombier /*
81*9a747e4fSDavid du Colombier * don't close the connection -- maybe we'll try again.
82*9a747e4fSDavid du Colombier */
83*9a747e4fSDavid du Colombier return nil;
84*9a747e4fSDavid du Colombier }
85*9a747e4fSDavid du Colombier
86*9a747e4fSDavid du Colombier switch(ret = auth_rpc(c->rpc, "read", nil, 0)){
87*9a747e4fSDavid du Colombier case ARok:
88*9a747e4fSDavid du Colombier default:
89*9a747e4fSDavid du Colombier werrstr("factotum protocol botch %d %s", ret, c->rpc->ibuf);
90*9a747e4fSDavid du Colombier break;
91*9a747e4fSDavid du Colombier case ARdone:
92*9a747e4fSDavid du Colombier ai = auth_getinfo(c->rpc);
93*9a747e4fSDavid du Colombier break;
94*9a747e4fSDavid du Colombier }
95*9a747e4fSDavid du Colombier
96*9a747e4fSDavid du Colombier Out:
97*9a747e4fSDavid du Colombier close(c->afd);
98*9a747e4fSDavid du Colombier auth_freerpc(c->rpc);
99*9a747e4fSDavid du Colombier c->afd = -1;
100*9a747e4fSDavid du Colombier c->rpc = nil;
101*9a747e4fSDavid du Colombier return ai;
102*9a747e4fSDavid du Colombier }
103*9a747e4fSDavid du Colombier
104*9a747e4fSDavid du Colombier void
auth_freechal(Chalstate * c)105*9a747e4fSDavid du Colombier auth_freechal(Chalstate *c)
106*9a747e4fSDavid du Colombier {
107*9a747e4fSDavid du Colombier if(c == nil)
108*9a747e4fSDavid du Colombier return;
109*9a747e4fSDavid du Colombier
110*9a747e4fSDavid du Colombier if(c->afd >= 0)
111*9a747e4fSDavid du Colombier close(c->afd);
112*9a747e4fSDavid du Colombier if(c->rpc != nil)
113*9a747e4fSDavid du Colombier auth_freerpc(c->rpc);
114*9a747e4fSDavid du Colombier
115*9a747e4fSDavid du Colombier memset(c, 0xBB, sizeof(*c));
116*9a747e4fSDavid du Colombier free(c);
117*9a747e4fSDavid du Colombier }
118