Blame


1 2277c5d7 2004-03-21 devnull #include "std.h"
2 2277c5d7 2004-03-21 devnull #include "dat.h"
3 2277c5d7 2004-03-21 devnull
4 2277c5d7 2004-03-21 devnull /*
5 2277c5d7 2004-03-21 devnull * p9any - protocol negotiator
6 2277c5d7 2004-03-21 devnull *
7 2277c5d7 2004-03-21 devnull * Protocol:
8 2277c5d7 2004-03-21 devnull * S->C: v.2 proto@dom proto@dom proto@dom... NUL
9 2277c5d7 2004-03-21 devnull * C->S: proto dom NUL
10 2277c5d7 2004-03-21 devnull * [negotiated proto continues]
11 2277c5d7 2004-03-21 devnull */
12 2277c5d7 2004-03-21 devnull
13 2277c5d7 2004-03-21 devnull static Proto* okproto[] =
14 2277c5d7 2004-03-21 devnull {
15 2277c5d7 2004-03-21 devnull &p9sk1,
16 2277c5d7 2004-03-21 devnull nil,
17 2277c5d7 2004-03-21 devnull };
18 2277c5d7 2004-03-21 devnull
19 2277c5d7 2004-03-21 devnull static int
20 2277c5d7 2004-03-21 devnull rolecall(Role *r, char *name, Conv *c)
21 2277c5d7 2004-03-21 devnull {
22 2277c5d7 2004-03-21 devnull for(; r->name; r++)
23 2277c5d7 2004-03-21 devnull if(strcmp(r->name, name) == 0)
24 2277c5d7 2004-03-21 devnull return (*r->fn)(c);
25 2277c5d7 2004-03-21 devnull werrstr("unknown role");
26 2277c5d7 2004-03-21 devnull return -1;
27 2277c5d7 2004-03-21 devnull }
28 2277c5d7 2004-03-21 devnull
29 2277c5d7 2004-03-21 devnull static int
30 2277c5d7 2004-03-21 devnull hasnul(void *v, int n)
31 2277c5d7 2004-03-21 devnull {
32 2277c5d7 2004-03-21 devnull char *c;
33 2277c5d7 2004-03-21 devnull
34 2277c5d7 2004-03-21 devnull c = v;
35 2277c5d7 2004-03-21 devnull if(n > 0 && c[n-1] == '\0')
36 2277c5d7 2004-03-21 devnull return n;
37 2277c5d7 2004-03-21 devnull else
38 2277c5d7 2004-03-21 devnull return n+1;
39 2277c5d7 2004-03-21 devnull }
40 2277c5d7 2004-03-21 devnull
41 2277c5d7 2004-03-21 devnull static int
42 2277c5d7 2004-03-21 devnull p9anyserver(Conv *c)
43 2277c5d7 2004-03-21 devnull {
44 2277c5d7 2004-03-21 devnull char *s, *dom;
45 2277c5d7 2004-03-21 devnull int i, j, n, m, ret;
46 2277c5d7 2004-03-21 devnull char *tok[3];
47 2277c5d7 2004-03-21 devnull Attr *attr;
48 2277c5d7 2004-03-21 devnull Key *k;
49 2277c5d7 2004-03-21 devnull
50 2277c5d7 2004-03-21 devnull ret = -1;
51 2277c5d7 2004-03-21 devnull s = estrdup("v.2");
52 2277c5d7 2004-03-21 devnull n = 0;
53 2277c5d7 2004-03-21 devnull attr = delattr(copyattr(c->attr), "proto");
54 2277c5d7 2004-03-21 devnull
55 2277c5d7 2004-03-21 devnull for(i=0; i<ring.nkey; i++){
56 2277c5d7 2004-03-21 devnull k = ring.key[i];
57 2277c5d7 2004-03-21 devnull for(j=0; okproto[j]; j++)
58 2277c5d7 2004-03-21 devnull if(k->proto == okproto[j]
59 2277c5d7 2004-03-21 devnull && (dom = strfindattr(k->attr, "dom")) != nil
60 2277c5d7 2004-03-21 devnull && matchattr(attr, k->attr, k->privattr)){
61 2277c5d7 2004-03-21 devnull s = estrappend(s, " %s@%s", k->proto->name, dom);
62 2277c5d7 2004-03-21 devnull n++;
63 2277c5d7 2004-03-21 devnull }
64 2277c5d7 2004-03-21 devnull }
65 2277c5d7 2004-03-21 devnull
66 2277c5d7 2004-03-21 devnull if(n == 0){
67 2277c5d7 2004-03-21 devnull werrstr("no valid keys");
68 2277c5d7 2004-03-21 devnull goto out;
69 2277c5d7 2004-03-21 devnull }
70 2277c5d7 2004-03-21 devnull
71 2277c5d7 2004-03-21 devnull c->state = "write offer";
72 2277c5d7 2004-03-21 devnull if(convwrite(c, s, strlen(s)+1) < 0)
73 2277c5d7 2004-03-21 devnull goto out;
74 2277c5d7 2004-03-21 devnull free(s);
75 2277c5d7 2004-03-21 devnull s = nil;
76 2277c5d7 2004-03-21 devnull
77 2277c5d7 2004-03-21 devnull c->state = "read choice";
78 2277c5d7 2004-03-21 devnull if(convreadfn(c, hasnul, &s) < 0)
79 2277c5d7 2004-03-21 devnull goto out;
80 2277c5d7 2004-03-21 devnull
81 2277c5d7 2004-03-21 devnull m = tokenize(s, tok, nelem(tok));
82 2277c5d7 2004-03-21 devnull if(m != 2){
83 2277c5d7 2004-03-21 devnull werrstr("bad protocol message");
84 2277c5d7 2004-03-21 devnull goto out;
85 2277c5d7 2004-03-21 devnull }
86 2277c5d7 2004-03-21 devnull
87 2277c5d7 2004-03-21 devnull for(i=0; okproto[i]; i++)
88 2277c5d7 2004-03-21 devnull if(strcmp(okproto[i]->name, tok[0]) == 0)
89 2277c5d7 2004-03-21 devnull break;
90 2277c5d7 2004-03-21 devnull if(!okproto[i]){
91 2277c5d7 2004-03-21 devnull werrstr("bad chosen protocol %q", tok[0]);
92 2277c5d7 2004-03-21 devnull goto out;
93 2277c5d7 2004-03-21 devnull }
94 2277c5d7 2004-03-21 devnull
95 2277c5d7 2004-03-21 devnull c->state = "write ok";
96 2277c5d7 2004-03-21 devnull if(convwrite(c, "OK\0", 3) < 0)
97 2277c5d7 2004-03-21 devnull goto out;
98 2277c5d7 2004-03-21 devnull
99 2277c5d7 2004-03-21 devnull c->state = "start choice";
100 2277c5d7 2004-03-21 devnull attr = addattr(attr, "proto=%q dom=%q", tok[0], tok[1]);
101 2277c5d7 2004-03-21 devnull free(c->attr);
102 2277c5d7 2004-03-21 devnull c->attr = attr;
103 2277c5d7 2004-03-21 devnull attr = nil;
104 2277c5d7 2004-03-21 devnull c->proto = okproto[i];
105 2277c5d7 2004-03-21 devnull
106 2277c5d7 2004-03-21 devnull if(rolecall(c->proto->roles, "server", c) < 0){
107 2277c5d7 2004-03-21 devnull werrstr("%s: %r", tok[0]);
108 2277c5d7 2004-03-21 devnull goto out;
109 2277c5d7 2004-03-21 devnull }
110 2277c5d7 2004-03-21 devnull
111 2277c5d7 2004-03-21 devnull ret = 0;
112 2277c5d7 2004-03-21 devnull
113 2277c5d7 2004-03-21 devnull out:
114 2277c5d7 2004-03-21 devnull free(s);
115 2277c5d7 2004-03-21 devnull freeattr(attr);
116 2277c5d7 2004-03-21 devnull return ret;
117 2277c5d7 2004-03-21 devnull }
118 2277c5d7 2004-03-21 devnull
119 2277c5d7 2004-03-21 devnull static int
120 2277c5d7 2004-03-21 devnull p9anyclient(Conv *c)
121 2277c5d7 2004-03-21 devnull {
122 2277c5d7 2004-03-21 devnull char *s, **f, *tok[20], ok[3], *q, *user, *dom;
123 2277c5d7 2004-03-21 devnull int i, n, ret, version;
124 2277c5d7 2004-03-21 devnull Key *k;
125 2277c5d7 2004-03-21 devnull Attr *attr;
126 2277c5d7 2004-03-21 devnull Proto *p;
127 2277c5d7 2004-03-21 devnull
128 2277c5d7 2004-03-21 devnull ret = -1;
129 2277c5d7 2004-03-21 devnull s = nil;
130 2277c5d7 2004-03-21 devnull k = nil;
131 2277c5d7 2004-03-21 devnull
132 2277c5d7 2004-03-21 devnull user = strfindattr(c->attr, "user");
133 2277c5d7 2004-03-21 devnull dom = strfindattr(c->attr, "dom");
134 2277c5d7 2004-03-21 devnull
135 2277c5d7 2004-03-21 devnull /*
136 2277c5d7 2004-03-21 devnull * if the user is the factotum owner, any key will do.
137 2277c5d7 2004-03-21 devnull * if not, then if we have a speakfor key,
138 2277c5d7 2004-03-21 devnull * we will only vouch for the user's local identity.
139 2277c5d7 2004-03-21 devnull *
140 2277c5d7 2004-03-21 devnull * this logic is duplicated in p9sk1.c
141 2277c5d7 2004-03-21 devnull */
142 2277c5d7 2004-03-21 devnull attr = delattr(copyattr(c->attr), "role");
143 2277c5d7 2004-03-21 devnull attr = delattr(attr, "proto");
144 2277c5d7 2004-03-21 devnull if(strcmp(c->sysuser, owner) == 0)
145 2277c5d7 2004-03-21 devnull attr = addattr(attr, "role=client");
146 2277c5d7 2004-03-21 devnull else if(user==nil || strcmp(c->sysuser, user)==0){
147 2277c5d7 2004-03-21 devnull attr = delattr(attr, "user");
148 2277c5d7 2004-03-21 devnull attr = addattr(attr, "role=speakfor");
149 2277c5d7 2004-03-21 devnull }else{
150 2277c5d7 2004-03-21 devnull werrstr("will not authenticate for %q as %q", c->sysuser, user);
151 2277c5d7 2004-03-21 devnull goto out;
152 2277c5d7 2004-03-21 devnull }
153 2277c5d7 2004-03-21 devnull
154 2277c5d7 2004-03-21 devnull c->state = "read offer";
155 2277c5d7 2004-03-21 devnull if(convreadfn(c, hasnul, &s) < 0)
156 2277c5d7 2004-03-21 devnull goto out;
157 2277c5d7 2004-03-21 devnull
158 2277c5d7 2004-03-21 devnull c->state = "look for keys";
159 2277c5d7 2004-03-21 devnull n = tokenize(s, tok, nelem(tok));
160 2277c5d7 2004-03-21 devnull f = tok;
161 2277c5d7 2004-03-21 devnull version = 1;
162 2277c5d7 2004-03-21 devnull if(n > 0 && memcmp(f[0], "v.", 2) == 0){
163 2277c5d7 2004-03-21 devnull version = atoi(f[0]+2);
164 2277c5d7 2004-03-21 devnull if(version != 2){
165 2277c5d7 2004-03-21 devnull werrstr("unknown p9any version: %s", f[0]);
166 2277c5d7 2004-03-21 devnull goto out;
167 2277c5d7 2004-03-21 devnull }
168 2277c5d7 2004-03-21 devnull f++;
169 2277c5d7 2004-03-21 devnull n--;
170 2277c5d7 2004-03-21 devnull }
171 2277c5d7 2004-03-21 devnull
172 2277c5d7 2004-03-21 devnull /* look for keys that don't need confirmation */
173 2277c5d7 2004-03-21 devnull for(i=0; i<n; i++){
174 2277c5d7 2004-03-21 devnull if((q = strchr(f[i], '@')) == nil)
175 2277c5d7 2004-03-21 devnull continue;
176 2277c5d7 2004-03-21 devnull if(dom && strcmp(q+1, dom) != 0)
177 2277c5d7 2004-03-21 devnull continue;
178 2277c5d7 2004-03-21 devnull *q++ = '\0';
179 2277c5d7 2004-03-21 devnull if((k = keylookup("%A proto=%q dom=%q", attr, f[i], q))
180 2277c5d7 2004-03-21 devnull && strfindattr(k->attr, "confirm") == nil)
181 2277c5d7 2004-03-21 devnull goto found;
182 2277c5d7 2004-03-21 devnull *--q = '@';
183 2277c5d7 2004-03-21 devnull }
184 2277c5d7 2004-03-21 devnull
185 2277c5d7 2004-03-21 devnull /* look for any keys at all */
186 2277c5d7 2004-03-21 devnull for(i=0; i<n; i++){
187 2277c5d7 2004-03-21 devnull if((q = strchr(f[i], '@')) == nil)
188 2277c5d7 2004-03-21 devnull continue;
189 2277c5d7 2004-03-21 devnull if(dom && strcmp(q+1, dom) != 0)
190 2277c5d7 2004-03-21 devnull continue;
191 2277c5d7 2004-03-21 devnull *q++ = '\0';
192 2277c5d7 2004-03-21 devnull if(k = keyfetch(c, "%A proto=%q dom=%q", attr, f[i], q))
193 2277c5d7 2004-03-21 devnull goto found;
194 2277c5d7 2004-03-21 devnull *--q = '@';
195 2277c5d7 2004-03-21 devnull }
196 2277c5d7 2004-03-21 devnull
197 2277c5d7 2004-03-21 devnull /* ask for new keys */
198 2277c5d7 2004-03-21 devnull c->state = "ask for keys";
199 2277c5d7 2004-03-21 devnull for(i=0; i<n; i++){
200 2277c5d7 2004-03-21 devnull if((q = strchr(f[i], '@')) == nil)
201 2277c5d7 2004-03-21 devnull continue;
202 2277c5d7 2004-03-21 devnull if(dom && strcmp(q+1, dom) != 0)
203 2277c5d7 2004-03-21 devnull continue;
204 2277c5d7 2004-03-21 devnull *q++ = '\0';
205 2277c5d7 2004-03-21 devnull p = protolookup(f[i]);
206 2277c5d7 2004-03-21 devnull if(p == nil || p->keyprompt == nil){
207 2277c5d7 2004-03-21 devnull *--q = '@';
208 2277c5d7 2004-03-21 devnull continue;
209 2277c5d7 2004-03-21 devnull }
210 2277c5d7 2004-03-21 devnull if(k = keyfetch(c, "%A proto=%q dom=%q %s", attr, f[i], q, p->keyprompt))
211 2277c5d7 2004-03-21 devnull goto found;
212 2277c5d7 2004-03-21 devnull *--q = '@';
213 2277c5d7 2004-03-21 devnull }
214 2277c5d7 2004-03-21 devnull
215 2277c5d7 2004-03-21 devnull /* nothing worked */
216 2277c5d7 2004-03-21 devnull werrstr("unable to find common key");
217 2277c5d7 2004-03-21 devnull goto out;
218 2277c5d7 2004-03-21 devnull
219 2277c5d7 2004-03-21 devnull found:
220 2277c5d7 2004-03-21 devnull /* f[i] is the chosen protocol, q the chosen domain */
221 2277c5d7 2004-03-21 devnull attr = addattr(attr, "proto=%q dom=%q", f[i], q);
222 2277c5d7 2004-03-21 devnull c->state = "write choice";
223 2277c5d7 2004-03-21 devnull /* have a key: go for it */
224 2277c5d7 2004-03-21 devnull if(convprint(c, "%q %q", f[i], q) < 0
225 2277c5d7 2004-03-21 devnull || convwrite(c, "\0", 1) < 0)
226 2277c5d7 2004-03-21 devnull goto out;
227 2277c5d7 2004-03-21 devnull
228 2277c5d7 2004-03-21 devnull if(version == 2){
229 2277c5d7 2004-03-21 devnull c->state = "read ok";
230 2277c5d7 2004-03-21 devnull if(convread(c, ok, 3) < 0 || memcmp(ok, "OK\0", 3) != 0)
231 2277c5d7 2004-03-21 devnull goto out;
232 2277c5d7 2004-03-21 devnull }
233 2277c5d7 2004-03-21 devnull
234 2277c5d7 2004-03-21 devnull c->state = "start choice";
235 2277c5d7 2004-03-21 devnull c->proto = protolookup(f[i]);
236 2277c5d7 2004-03-21 devnull freeattr(c->attr);
237 2277c5d7 2004-03-21 devnull c->attr = attr;
238 2277c5d7 2004-03-21 devnull attr = nil;
239 2277c5d7 2004-03-21 devnull
240 2277c5d7 2004-03-21 devnull if(rolecall(c->proto->roles, "client", c) < 0){
241 2277c5d7 2004-03-21 devnull werrstr("%s: %r", c->proto->name);
242 2277c5d7 2004-03-21 devnull goto out;
243 2277c5d7 2004-03-21 devnull }
244 2277c5d7 2004-03-21 devnull
245 2277c5d7 2004-03-21 devnull ret = 0;
246 2277c5d7 2004-03-21 devnull
247 2277c5d7 2004-03-21 devnull out:
248 2277c5d7 2004-03-21 devnull keyclose(k);
249 2277c5d7 2004-03-21 devnull freeattr(attr);
250 2277c5d7 2004-03-21 devnull free(s);
251 2277c5d7 2004-03-21 devnull return ret;
252 2277c5d7 2004-03-21 devnull }
253 2277c5d7 2004-03-21 devnull
254 2277c5d7 2004-03-21 devnull static Role
255 2277c5d7 2004-03-21 devnull p9anyroles[] =
256 2277c5d7 2004-03-21 devnull {
257 2277c5d7 2004-03-21 devnull "client", p9anyclient,
258 2277c5d7 2004-03-21 devnull "server", p9anyserver,
259 2277c5d7 2004-03-21 devnull 0
260 2277c5d7 2004-03-21 devnull };
261 2277c5d7 2004-03-21 devnull
262 2277c5d7 2004-03-21 devnull Proto p9any = {
263 2277c5d7 2004-03-21 devnull .name= "p9any",
264 2277c5d7 2004-03-21 devnull .roles= p9anyroles,
265 2277c5d7 2004-03-21 devnull };
266 2277c5d7 2004-03-21 devnull