Blame


1 6e527fbc 2005-02-13 devnull /*
2 d96dce4d 2007-09-14 rsc * p9cr - one-sided challenge/response authentication
3 6e527fbc 2005-02-13 devnull *
4 6e527fbc 2005-02-13 devnull * Protocol:
5 6e527fbc 2005-02-13 devnull *
6 6e527fbc 2005-02-13 devnull * C -> S: user
7 6e527fbc 2005-02-13 devnull * S -> C: challenge
8 6e527fbc 2005-02-13 devnull * C -> S: response
9 6e527fbc 2005-02-13 devnull * S -> C: ok or bad
10 6e527fbc 2005-02-13 devnull *
11 6e527fbc 2005-02-13 devnull * Note that this is the protocol between factotum and the local
12 6e527fbc 2005-02-13 devnull * program, not between the two factotums. The information
13 6e527fbc 2005-02-13 devnull * exchanged here is wrapped in other protocols by the local
14 6e527fbc 2005-02-13 devnull * programs.
15 6e527fbc 2005-02-13 devnull */
16 6e527fbc 2005-02-13 devnull
17 6e527fbc 2005-02-13 devnull #include "std.h"
18 6e527fbc 2005-02-13 devnull #include "dat.h"
19 6e527fbc 2005-02-13 devnull
20 d96dce4d 2007-09-14 rsc /* shared with auth dialing routines */
21 d96dce4d 2007-09-14 rsc typedef struct ServerState ServerState;
22 d96dce4d 2007-09-14 rsc struct ServerState
23 d96dce4d 2007-09-14 rsc {
24 d96dce4d 2007-09-14 rsc int asfd;
25 d96dce4d 2007-09-14 rsc Key *k;
26 d96dce4d 2007-09-14 rsc Ticketreq tr;
27 d96dce4d 2007-09-14 rsc Ticket t;
28 d96dce4d 2007-09-14 rsc char *dom;
29 d96dce4d 2007-09-14 rsc char *hostid;
30 d96dce4d 2007-09-14 rsc };
31 d96dce4d 2007-09-14 rsc
32 d96dce4d 2007-09-14 rsc enum
33 d96dce4d 2007-09-14 rsc {
34 d96dce4d 2007-09-14 rsc MAXCHAL = 64,
35 d96dce4d 2007-09-14 rsc MAXRESP = 64,
36 d96dce4d 2007-09-14 rsc };
37 d96dce4d 2007-09-14 rsc
38 d96dce4d 2007-09-14 rsc extern Proto p9cr, vnc;
39 d96dce4d 2007-09-14 rsc static int p9response(char*, uchar*, uchar*);
40 d96dce4d 2007-09-14 rsc // static int vncresponse(char*, uchar*, uchar*);
41 d96dce4d 2007-09-14 rsc static int p9crchal(ServerState *s, int, char*, uchar*, int);
42 d96dce4d 2007-09-14 rsc static int p9crresp(ServerState*, uchar*, int);
43 d96dce4d 2007-09-14 rsc
44 6e527fbc 2005-02-13 devnull static int
45 d96dce4d 2007-09-14 rsc p9crcheck(Key *k)
46 d96dce4d 2007-09-14 rsc {
47 d96dce4d 2007-09-14 rsc if(!strfindattr(k->attr, "user") || !strfindattr(k->privattr, "!password")){
48 d96dce4d 2007-09-14 rsc werrstr("need user and !password attributes");
49 d96dce4d 2007-09-14 rsc return -1;
50 d96dce4d 2007-09-14 rsc }
51 d96dce4d 2007-09-14 rsc return 0;
52 d96dce4d 2007-09-14 rsc }
53 d96dce4d 2007-09-14 rsc
54 d96dce4d 2007-09-14 rsc static int
55 6e527fbc 2005-02-13 devnull p9crclient(Conv *c)
56 6e527fbc 2005-02-13 devnull {
57 d96dce4d 2007-09-14 rsc char *pw, *res, *user;
58 d96dce4d 2007-09-14 rsc int astype, challen, resplen, ntry, ret;
59 6e527fbc 2005-02-13 devnull Attr *attr;
60 6e527fbc 2005-02-13 devnull Key *k;
61 d96dce4d 2007-09-14 rsc uchar chal[MAXCHAL+1], resp[MAXRESP];
62 d96dce4d 2007-09-14 rsc int (*response)(char*, uchar*, uchar*);
63 d96dce4d 2007-09-14 rsc
64 6e527fbc 2005-02-13 devnull k = nil;
65 6e527fbc 2005-02-13 devnull res = nil;
66 6e527fbc 2005-02-13 devnull ret = -1;
67 6e527fbc 2005-02-13 devnull attr = c->attr;
68 6e527fbc 2005-02-13 devnull
69 6e527fbc 2005-02-13 devnull if(c->proto == &p9cr){
70 6e527fbc 2005-02-13 devnull astype = AuthChal;
71 6e527fbc 2005-02-13 devnull challen = NETCHLEN;
72 d96dce4d 2007-09-14 rsc response = p9response;
73 d96dce4d 2007-09-14 rsc attr = _mkattr(AttrNameval, "proto", "p9sk1", _delattr(_copyattr(attr), "proto"));
74 6e527fbc 2005-02-13 devnull }else if(c->proto == &vnc){
75 d96dce4d 2007-09-14 rsc astype = AuthVNC;
76 6e527fbc 2005-02-13 devnull challen = MAXCHAL;
77 d96dce4d 2007-09-14 rsc // response = vncresponse;
78 523f3148 2007-11-05 rsc werrstr("no vnc");
79 523f3148 2007-11-05 rsc goto out;
80 6e527fbc 2005-02-13 devnull }else{
81 6e527fbc 2005-02-13 devnull werrstr("bad proto");
82 6e527fbc 2005-02-13 devnull goto out;
83 6e527fbc 2005-02-13 devnull }
84 6e527fbc 2005-02-13 devnull
85 6e527fbc 2005-02-13 devnull c->state = "find key";
86 6e527fbc 2005-02-13 devnull k = keyfetch(c, "%A %s", attr, c->proto->keyprompt);
87 6e527fbc 2005-02-13 devnull if(k == nil)
88 6e527fbc 2005-02-13 devnull goto out;
89 6e527fbc 2005-02-13 devnull
90 6e527fbc 2005-02-13 devnull for(ntry=1;; ntry++){
91 6e527fbc 2005-02-13 devnull if(c->attr != attr)
92 6e527fbc 2005-02-13 devnull freeattr(c->attr);
93 6e527fbc 2005-02-13 devnull c->attr = addattrs(copyattr(attr), k->attr);
94 d96dce4d 2007-09-14 rsc
95 6e527fbc 2005-02-13 devnull if((pw = strfindattr(k->privattr, "!password")) == nil){
96 6e527fbc 2005-02-13 devnull werrstr("key has no !password (cannot happen)");
97 6e527fbc 2005-02-13 devnull goto out;
98 6e527fbc 2005-02-13 devnull }
99 6e527fbc 2005-02-13 devnull if((user = strfindattr(k->attr, "user")) == nil){
100 6e527fbc 2005-02-13 devnull werrstr("key has no user (cannot happen)");
101 6e527fbc 2005-02-13 devnull goto out;
102 6e527fbc 2005-02-13 devnull }
103 6e527fbc 2005-02-13 devnull
104 6e527fbc 2005-02-13 devnull if(convprint(c, "%s", user) < 0)
105 6e527fbc 2005-02-13 devnull goto out;
106 6e527fbc 2005-02-13 devnull
107 d96dce4d 2007-09-14 rsc if(convread(c, chal, challen) < 0)
108 6e527fbc 2005-02-13 devnull goto out;
109 d96dce4d 2007-09-14 rsc chal[challen] = 0;
110 6e527fbc 2005-02-13 devnull
111 d96dce4d 2007-09-14 rsc if((resplen = (*response)(pw, chal, resp)) < 0)
112 6e527fbc 2005-02-13 devnull goto out;
113 6e527fbc 2005-02-13 devnull
114 d96dce4d 2007-09-14 rsc if(convwrite(c, resp, resplen) < 0)
115 6e527fbc 2005-02-13 devnull goto out;
116 6e527fbc 2005-02-13 devnull
117 6e527fbc 2005-02-13 devnull if(convreadm(c, &res) < 0)
118 6e527fbc 2005-02-13 devnull goto out;
119 6e527fbc 2005-02-13 devnull
120 6e527fbc 2005-02-13 devnull if(strcmp(res, "ok") == 0)
121 6e527fbc 2005-02-13 devnull break;
122 6e527fbc 2005-02-13 devnull
123 6e527fbc 2005-02-13 devnull if((k = keyreplace(c, k, "%s", res)) == nil){
124 6e527fbc 2005-02-13 devnull c->state = "auth failed";
125 6e527fbc 2005-02-13 devnull werrstr("%s", res);
126 6e527fbc 2005-02-13 devnull goto out;
127 6e527fbc 2005-02-13 devnull }
128 6e527fbc 2005-02-13 devnull }
129 6e527fbc 2005-02-13 devnull
130 6e527fbc 2005-02-13 devnull werrstr("succeeded");
131 6e527fbc 2005-02-13 devnull ret = 0;
132 6e527fbc 2005-02-13 devnull
133 6e527fbc 2005-02-13 devnull out:
134 6e527fbc 2005-02-13 devnull keyclose(k);
135 6e527fbc 2005-02-13 devnull if(c->attr != attr)
136 6e527fbc 2005-02-13 devnull freeattr(attr);
137 6e527fbc 2005-02-13 devnull return ret;
138 6e527fbc 2005-02-13 devnull }
139 6e527fbc 2005-02-13 devnull
140 6e527fbc 2005-02-13 devnull static int
141 6e527fbc 2005-02-13 devnull p9crserver(Conv *c)
142 6e527fbc 2005-02-13 devnull {
143 d96dce4d 2007-09-14 rsc uchar chal[MAXCHAL], *resp, *resp1;
144 d96dce4d 2007-09-14 rsc char *user;
145 d96dce4d 2007-09-14 rsc ServerState s;
146 d96dce4d 2007-09-14 rsc int astype, ret, challen, resplen;
147 6e527fbc 2005-02-13 devnull Attr *a;
148 6e527fbc 2005-02-13 devnull
149 6e527fbc 2005-02-13 devnull ret = -1;
150 6e527fbc 2005-02-13 devnull user = nil;
151 6e527fbc 2005-02-13 devnull resp = nil;
152 6e527fbc 2005-02-13 devnull memset(&s, 0, sizeof s);
153 6e527fbc 2005-02-13 devnull s.asfd = -1;
154 6e527fbc 2005-02-13 devnull
155 1757e76a 2005-02-13 devnull if(c->proto == &p9cr){
156 1757e76a 2005-02-13 devnull astype = AuthChal;
157 1757e76a 2005-02-13 devnull challen = NETCHLEN;
158 1757e76a 2005-02-13 devnull }else if(c->proto == &vnc){
159 d96dce4d 2007-09-14 rsc astype = AuthVNC;
160 1757e76a 2005-02-13 devnull challen = MAXCHAL;
161 1757e76a 2005-02-13 devnull }else{
162 6e527fbc 2005-02-13 devnull werrstr("bad proto");
163 6e527fbc 2005-02-13 devnull goto out;
164 6e527fbc 2005-02-13 devnull }
165 6e527fbc 2005-02-13 devnull
166 6e527fbc 2005-02-13 devnull c->state = "find key";
167 d96dce4d 2007-09-14 rsc if((s.k = plan9authkey(c->attr)) == nil)
168 6e527fbc 2005-02-13 devnull goto out;
169 6e527fbc 2005-02-13 devnull
170 d96dce4d 2007-09-14 rsc a = copyattr(s.k->attr);
171 6e527fbc 2005-02-13 devnull a = delattr(a, "proto");
172 6e527fbc 2005-02-13 devnull c->attr = addattrs(c->attr, a);
173 6e527fbc 2005-02-13 devnull freeattr(a);
174 6e527fbc 2005-02-13 devnull
175 6e527fbc 2005-02-13 devnull c->state = "authdial";
176 d96dce4d 2007-09-14 rsc s.hostid = strfindattr(s.k->attr, "user");
177 d96dce4d 2007-09-14 rsc s.dom = strfindattr(s.k->attr, "dom");
178 d96dce4d 2007-09-14 rsc if((s.asfd = xioauthdial(nil, s.dom)) < 0){
179 6e527fbc 2005-02-13 devnull werrstr("authdial %s: %r", s.dom);
180 6e527fbc 2005-02-13 devnull goto out;
181 6e527fbc 2005-02-13 devnull }
182 6e527fbc 2005-02-13 devnull
183 6e527fbc 2005-02-13 devnull for(;;){
184 6e527fbc 2005-02-13 devnull c->state = "read user";
185 6e527fbc 2005-02-13 devnull if(convreadm(c, &user) < 0)
186 6e527fbc 2005-02-13 devnull goto out;
187 6e527fbc 2005-02-13 devnull
188 d96dce4d 2007-09-14 rsc c->state = "authchal";
189 d96dce4d 2007-09-14 rsc if(p9crchal(&s, astype, user, chal, challen) < 0)
190 d96dce4d 2007-09-14 rsc goto out;
191 d96dce4d 2007-09-14 rsc
192 d96dce4d 2007-09-14 rsc c->state = "write challenge";
193 d96dce4d 2007-09-14 rsc if(convwrite(c, chal, challen) < 0)
194 d96dce4d 2007-09-14 rsc goto out;
195 d96dce4d 2007-09-14 rsc
196 6e527fbc 2005-02-13 devnull c->state = "read response";
197 d96dce4d 2007-09-14 rsc if((resplen = convreadm(c, (char**)(void*)&resp)) < 0)
198 6e527fbc 2005-02-13 devnull goto out;
199 d96dce4d 2007-09-14 rsc if(c->proto == &p9cr){
200 d96dce4d 2007-09-14 rsc if(resplen > NETCHLEN){
201 d96dce4d 2007-09-14 rsc convprint(c, "bad response too long");
202 d96dce4d 2007-09-14 rsc goto out;
203 d96dce4d 2007-09-14 rsc }
204 d96dce4d 2007-09-14 rsc resp1 = emalloc(NETCHLEN);
205 d96dce4d 2007-09-14 rsc memset(resp1, 0, NETCHLEN);
206 d96dce4d 2007-09-14 rsc memmove(resp1, resp, resplen);
207 d96dce4d 2007-09-14 rsc free(resp);
208 d96dce4d 2007-09-14 rsc resp = resp1;
209 d96dce4d 2007-09-14 rsc resplen = NETCHLEN;
210 d96dce4d 2007-09-14 rsc }
211 6e527fbc 2005-02-13 devnull
212 6e527fbc 2005-02-13 devnull c->state = "authwrite";
213 d96dce4d 2007-09-14 rsc switch(p9crresp(&s, resp, resplen)){
214 6e527fbc 2005-02-13 devnull case -1:
215 d96dce4d 2007-09-14 rsc fprint(2, "p9crresp: %r\n");
216 6e527fbc 2005-02-13 devnull goto out;
217 6e527fbc 2005-02-13 devnull case 0:
218 6e527fbc 2005-02-13 devnull c->state = "write status";
219 6e527fbc 2005-02-13 devnull if(convprint(c, "bad authentication failed") < 0)
220 6e527fbc 2005-02-13 devnull goto out;
221 6e527fbc 2005-02-13 devnull break;
222 6e527fbc 2005-02-13 devnull case 1:
223 6e527fbc 2005-02-13 devnull c->state = "write status";
224 6e527fbc 2005-02-13 devnull if(convprint(c, "ok") < 0)
225 6e527fbc 2005-02-13 devnull goto out;
226 6e527fbc 2005-02-13 devnull goto ok;
227 6e527fbc 2005-02-13 devnull }
228 6e527fbc 2005-02-13 devnull free(user);
229 6e527fbc 2005-02-13 devnull free(resp);
230 6e527fbc 2005-02-13 devnull user = nil;
231 6e527fbc 2005-02-13 devnull resp = nil;
232 6e527fbc 2005-02-13 devnull }
233 6e527fbc 2005-02-13 devnull
234 6e527fbc 2005-02-13 devnull ok:
235 6e527fbc 2005-02-13 devnull ret = 0;
236 6e527fbc 2005-02-13 devnull c->attr = addcap(c->attr, c->sysuser, &s.t);
237 6e527fbc 2005-02-13 devnull
238 6e527fbc 2005-02-13 devnull out:
239 6e527fbc 2005-02-13 devnull keyclose(s.k);
240 6e527fbc 2005-02-13 devnull free(user);
241 6e527fbc 2005-02-13 devnull free(resp);
242 1757e76a 2005-02-13 devnull xioclose(s.asfd);
243 6e527fbc 2005-02-13 devnull return ret;
244 6e527fbc 2005-02-13 devnull }
245 6e527fbc 2005-02-13 devnull
246 d96dce4d 2007-09-14 rsc static int
247 d96dce4d 2007-09-14 rsc p9crchal(ServerState *s, int astype, char *user, uchar *chal, int challen)
248 6e527fbc 2005-02-13 devnull {
249 d96dce4d 2007-09-14 rsc char trbuf[TICKREQLEN];
250 6e527fbc 2005-02-13 devnull Ticketreq tr;
251 d96dce4d 2007-09-14 rsc int n;
252 6e527fbc 2005-02-13 devnull
253 d96dce4d 2007-09-14 rsc memset(&tr, 0, sizeof tr);
254 6e527fbc 2005-02-13 devnull
255 d96dce4d 2007-09-14 rsc tr.type = astype;
256 6e527fbc 2005-02-13 devnull
257 d96dce4d 2007-09-14 rsc if(strlen(s->hostid) >= sizeof tr.hostid){
258 d96dce4d 2007-09-14 rsc werrstr("hostid too long");
259 d96dce4d 2007-09-14 rsc return -1;
260 d96dce4d 2007-09-14 rsc }
261 d96dce4d 2007-09-14 rsc strcpy(tr.hostid, s->hostid);
262 6e527fbc 2005-02-13 devnull
263 d96dce4d 2007-09-14 rsc if(strlen(s->dom) >= sizeof tr.authdom){
264 d96dce4d 2007-09-14 rsc werrstr("domain too long");
265 d96dce4d 2007-09-14 rsc return -1;
266 d96dce4d 2007-09-14 rsc }
267 d96dce4d 2007-09-14 rsc strcpy(tr.authdom, s->dom);
268 6e527fbc 2005-02-13 devnull
269 d96dce4d 2007-09-14 rsc if(strlen(user) >= sizeof tr.uid){
270 d96dce4d 2007-09-14 rsc werrstr("user name too long");
271 d96dce4d 2007-09-14 rsc return -1;
272 d96dce4d 2007-09-14 rsc }
273 d96dce4d 2007-09-14 rsc strcpy(tr.uid, user);
274 d96dce4d 2007-09-14 rsc convTR2M(&tr, trbuf);
275 6e527fbc 2005-02-13 devnull
276 d96dce4d 2007-09-14 rsc if(xiowrite(s->asfd, trbuf, TICKREQLEN) != TICKREQLEN)
277 d96dce4d 2007-09-14 rsc return -1;
278 6e527fbc 2005-02-13 devnull
279 d96dce4d 2007-09-14 rsc if((n=xioasrdresp(s->asfd, chal, challen)) <= 0)
280 d96dce4d 2007-09-14 rsc return -1;
281 d96dce4d 2007-09-14 rsc return n;
282 6e527fbc 2005-02-13 devnull }
283 6e527fbc 2005-02-13 devnull
284 6e527fbc 2005-02-13 devnull static int
285 d96dce4d 2007-09-14 rsc p9crresp(ServerState *s, uchar *resp, int resplen)
286 6e527fbc 2005-02-13 devnull {
287 d96dce4d 2007-09-14 rsc char tabuf[TICKETLEN+AUTHENTLEN];
288 d96dce4d 2007-09-14 rsc Authenticator a;
289 d96dce4d 2007-09-14 rsc Ticket t;
290 d96dce4d 2007-09-14 rsc Ticketreq tr;
291 6e527fbc 2005-02-13 devnull
292 d96dce4d 2007-09-14 rsc if(xiowrite(s->asfd, resp, resplen) != resplen)
293 d96dce4d 2007-09-14 rsc return -1;
294 6e527fbc 2005-02-13 devnull
295 d96dce4d 2007-09-14 rsc if(xioasrdresp(s->asfd, tabuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
296 d96dce4d 2007-09-14 rsc return 0;
297 6e527fbc 2005-02-13 devnull
298 d96dce4d 2007-09-14 rsc convM2T(tabuf, &t, s->k->priv);
299 d96dce4d 2007-09-14 rsc if(t.num != AuthTs
300 d96dce4d 2007-09-14 rsc || memcmp(t.chal, tr.chal, sizeof tr.chal) != 0){
301 d96dce4d 2007-09-14 rsc werrstr("key mismatch with auth server");
302 d96dce4d 2007-09-14 rsc return -1;
303 d96dce4d 2007-09-14 rsc }
304 6e527fbc 2005-02-13 devnull
305 d96dce4d 2007-09-14 rsc convM2A(tabuf+TICKETLEN, &a, t.key);
306 d96dce4d 2007-09-14 rsc if(a.num != AuthAc
307 d96dce4d 2007-09-14 rsc || memcmp(a.chal, tr.chal, sizeof a.chal) != 0
308 d96dce4d 2007-09-14 rsc || a.id != 0){
309 d96dce4d 2007-09-14 rsc werrstr("key2 mismatch with auth server");
310 d96dce4d 2007-09-14 rsc return -1;
311 6e527fbc 2005-02-13 devnull }
312 d96dce4d 2007-09-14 rsc
313 d96dce4d 2007-09-14 rsc s->t = t;
314 d96dce4d 2007-09-14 rsc return 1;
315 6e527fbc 2005-02-13 devnull }
316 6e527fbc 2005-02-13 devnull
317 6e527fbc 2005-02-13 devnull static int
318 d96dce4d 2007-09-14 rsc p9response(char *pw, uchar *chal, uchar *resp)
319 d96dce4d 2007-09-14 rsc {
320 6e527fbc 2005-02-13 devnull char key[DESKEYLEN];
321 6e527fbc 2005-02-13 devnull uchar buf[8];
322 d96dce4d 2007-09-14 rsc ulong x;
323 6e527fbc 2005-02-13 devnull
324 6e527fbc 2005-02-13 devnull passtokey(key, pw);
325 6e527fbc 2005-02-13 devnull memset(buf, 0, 8);
326 d96dce4d 2007-09-14 rsc snprint((char*)buf, sizeof buf, "%d", atoi((char*)chal));
327 d96dce4d 2007-09-14 rsc if(encrypt(key, buf, 8) < 0){
328 d96dce4d 2007-09-14 rsc werrstr("can't encrypt response");
329 6e527fbc 2005-02-13 devnull return -1;
330 6e527fbc 2005-02-13 devnull }
331 d96dce4d 2007-09-14 rsc x = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
332 d96dce4d 2007-09-14 rsc return snprint((char*)resp, MAXRESP, "%.8lux", x);
333 6e527fbc 2005-02-13 devnull }
334 6e527fbc 2005-02-13 devnull
335 d96dce4d 2007-09-14 rsc /*
336 6e527fbc 2005-02-13 devnull static int
337 d96dce4d 2007-09-14 rsc vncresponse(char *pw, uchar *chal, uchar *resp)
338 6e527fbc 2005-02-13 devnull {
339 6e527fbc 2005-02-13 devnull DESstate des;
340 d96dce4d 2007-09-14 rsc
341 d96dce4d 2007-09-14 rsc memmove(resp, chal, MAXCHAL);
342 d96dce4d 2007-09-14 rsc setupDESstate(&des, 0, nil); // XXX put key in for 0
343 d96dce4d 2007-09-14 rsc desECBencrypt(resp, MAXCHAL, &des);
344 d96dce4d 2007-09-14 rsc return MAXCHAL;
345 6e527fbc 2005-02-13 devnull }
346 d96dce4d 2007-09-14 rsc */
347 6e527fbc 2005-02-13 devnull
348 d96dce4d 2007-09-14 rsc static Role
349 d96dce4d 2007-09-14 rsc p9crroles[] =
350 6e527fbc 2005-02-13 devnull {
351 d96dce4d 2007-09-14 rsc "client", p9crclient,
352 d96dce4d 2007-09-14 rsc "server", p9crserver,
353 d96dce4d 2007-09-14 rsc 0
354 d96dce4d 2007-09-14 rsc };
355 6e527fbc 2005-02-13 devnull
356 d96dce4d 2007-09-14 rsc Proto p9cr = {
357 d96dce4d 2007-09-14 rsc "p9cr",
358 d96dce4d 2007-09-14 rsc p9crroles,
359 d96dce4d 2007-09-14 rsc "user? !password?",
360 d96dce4d 2007-09-14 rsc p9crcheck,
361 d96dce4d 2007-09-14 rsc nil
362 6e527fbc 2005-02-13 devnull };
363 6e527fbc 2005-02-13 devnull
364 50f5d1a7 2007-09-16 rsc /* still need to implement vnc key generator */
365 d96dce4d 2007-09-14 rsc Proto vnc = {
366 d96dce4d 2007-09-14 rsc "vnc",
367 d96dce4d 2007-09-14 rsc p9crroles,
368 d96dce4d 2007-09-14 rsc "user? !password?",
369 d96dce4d 2007-09-14 rsc p9crcheck,
370 d96dce4d 2007-09-14 rsc nil
371 6e527fbc 2005-02-13 devnull };