xref: /plan9-contrib/sys/src/libauth/auth_challenge.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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