Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <fcall.h>
5
#include <thread.h>
6
#include <9p.h>
7
 
8
typedef struct Afid Afid;
9
 
10
struct Afid
11
{
12
	AuthRpc *rpc;
13
	char *uname;
14
	char *aname;
15
	int authok;
16
	int afd;
17
};
18
 
19
static uvlong authgen = 1ULL<<63;
20
 
21
void
22
auth9p(Req *r)
23
{
24
	char *spec;
25
	Afid *afid;
26
 
27
	afid = emalloc9p(sizeof(Afid));
28
	afid->afd = open("/mnt/factotum/rpc", ORDWR);
29
	if(afid->afd < 0)
30
		goto error;
31
 
32
	if((afid->rpc = auth_allocrpc(afid->afd)) == nil)
33
		goto error;
34
 
35
	if(r->ifcall.uname[0] == 0)
36
		goto error;
37
	afid->uname = estrdup9p(r->ifcall.uname);
38
	afid->aname = estrdup9p(r->ifcall.aname);
39
 
40
	spec = r->srv->keyspec;
41
	if(spec == nil)
42
		spec = "proto=p9any role=server";
43
 
44
	if(auth_rpc(afid->rpc, "start", spec, strlen(spec)) != ARok)
45
		goto error;
46
 
47
	r->afid->qid.type = QTAUTH;
48
	r->afid->qid.path = ++authgen;
49
	r->afid->qid.vers = 0;
50
	r->afid->omode = ORDWR;
51
	r->ofcall.qid = r->afid->qid;
52
	r->afid->aux = afid;
53
	respond(r, nil);
54
	return;
55
 
56
error:
57
	if(afid->rpc)
58
		auth_freerpc(afid->rpc);
59
	if(afid->uname)
60
		free(afid->uname);
61
	if(afid->aname)
62
		free(afid->aname);
63
	if(afid->afd >= 0)
64
		close(afid->afd);
65
	free(afid);
66
	responderror(r);
67
}
68
 
69
static int
70
_authread(Afid *afid, void *data, int count)
71
{
72
	AuthInfo *ai;
73
 
74
	switch(auth_rpc(afid->rpc, "read", nil, 0)){
75
	case ARdone:
76
		ai = auth_getinfo(afid->rpc);
77
		if(ai == nil)
78
			return -1;
79
		auth_freeAI(ai);
80
		if(chatty9p)
81
			fprint(2, "authenticate %s/%s: ok\n", afid->uname, afid->aname);
82
		afid->authok = 1;
83
		return 0;
84
 
85
	case ARok:
86
		if(count < afid->rpc->narg){
87
			werrstr("authread count too small");
88
			return -1;
89
		}
90
		count = afid->rpc->narg;
91
		memmove(data, afid->rpc->arg, count);
92
		return count;
93
 
94
	case ARphase:
95
	default:
96
		werrstr("authrpc botch");
97
		return -1;
98
	}
99
}
100
 
101
void
102
authread(Req *r)
103
{
104
	int n;
105
	Afid *afid;
106
	Fid *fid;
107
 
108
	fid = r->fid;
109
	afid = fid->aux;
110
	if(afid == nil || r->fid->qid.type != QTAUTH){
111
		respond(r, "not an auth fid");
112
		return;
113
	}
114
	n = _authread(afid, r->ofcall.data, r->ifcall.count);
115
	if(n < 0){
116
		responderror(r);
117
		return;
118
	}
119
	r->ofcall.count = n;
120
	respond(r, nil);
121
}
122
 
123
void
124
authwrite(Req *r)
125
{
126
	Afid *afid;
127
	Fid *fid;
128
 
129
	fid = r->fid;
130
	afid = fid->aux;
131
	if(afid == nil || r->fid->qid.type != QTAUTH){
132
		respond(r, "not an auth fid");
133
		return;
134
	}
135
	if(auth_rpc(afid->rpc, "write", r->ifcall.data, r->ifcall.count) != ARok){
136
		responderror(r);
137
		return;
138
	}
139
	r->ofcall.count = r->ifcall.count;
140
	respond(r, nil);
141
}
142
 
143
void
144
authdestroy(Fid *fid)
145
{
146
	Afid *afid;
147
 
148
	if((fid->qid.type & QTAUTH) && (afid = fid->aux) != nil){
149
		if(afid->rpc)
150
			auth_freerpc(afid->rpc);
151
		close(afid->afd);
152
		free(afid->uname);
153
		free(afid->aname);
154
		free(afid);
155
		fid->aux = nil;
156
	}
157
}
158
 
159
int
160
authattach(Req *r)
161
{
162
	Afid *afid;
163
	char buf[ERRMAX];
164
 
165
	if(r->afid == nil){
166
		respond(r, "not authenticated");
167
		return -1;
168
	}
169
 
170
	afid = r->afid->aux;
171
	if((r->afid->qid.type&QTAUTH) == 0 || afid == nil){
172
		respond(r, "not an auth fid");
173
		return -1;
174
	}
175
 
176
	if(!afid->authok){
177
		if(_authread(afid, buf, 0) < 0){
178
			responderror(r);
179
			return -1;
180
		}
181
	}
182
 
183
	if(strcmp(afid->uname, r->ifcall.uname) != 0){
184
		snprint(buf, sizeof buf, "auth uname mismatch: %s vs %s", 
185
			afid->uname, r->ifcall.uname);
186
		respond(r, buf);
187
		return -1;
188
	}
189
 
190
	if(strcmp(afid->aname, r->ifcall.aname) != 0){
191
		snprint(buf, sizeof buf, "auth aname mismatch: %s vs %s", 
192
			afid->aname, r->ifcall.aname);
193
		respond(r, buf);
194
		return -1;
195
	}
196
	return 0;
197
}
198