5 send_ssh_smsg_public_key(Conn *c)
10 m = allocmsg(c, SSH_SMSG_PUBLIC_KEY, 2048);
11 putbytes(m, c->cookie, COOKIELEN);
12 putRSApub(m, c->serverkey);
13 putRSApub(m, c->hostkey);
16 for(i=0; i<c->nokcipher; i++)
17 c->ciphermask |= 1<<c->okcipher[i]->id;
18 putlong(m, c->ciphermask);
19 for(i=0; i<c->nokauthsrv; i++)
20 c->authmask |= 1<<c->okauthsrv[i]->id;
21 putlong(m, c->authmask);
27 rpcdecrypt(AuthRpc *rpc, mpint *b)
32 p = mptoa(b, 16, nil, 0);
33 if(auth_rpc(rpc, "write", p, strlen(p)) != ARok)
34 sysfatal("factotum rsa write: %r");
36 if(auth_rpc(rpc, "read", nil, 0) != ARok)
37 sysfatal("factotum rsa read: %r");
38 a = strtomp(rpc->arg, nil, 16, nil);
44 recv_ssh_cmsg_session_key(Conn *c, AuthRpc *rpc)
46 int i, id, n, serverkeylen, hostkeylen;
50 RSApriv *ksmall, *kbig;
52 m = recvmsg(c, SSH_CMSG_SESSION_KEY);
55 for(i=0; i<c->nokcipher; i++)
56 if(c->okcipher[i]->id == id)
57 c->cipher = c->okcipher[i];
59 sysfatal("invalid cipher selected");
61 if(memcmp(getbytes(m, COOKIELEN), c->cookie, COOKIELEN) != 0)
62 sysfatal("bad cookie");
64 serverkeylen = mpsignif(c->serverkey->n);
65 hostkeylen = mpsignif(c->hostkey->n);
67 if(serverkeylen+128 <= hostkeylen){
68 ksmall = c->serverpriv;
70 }else if(hostkeylen+128 <= serverkeylen){
74 sysfatal("server session and host keys do not differ by at least 128 bits");
78 debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b);
80 a = rsadecrypt(kbig, b, nil);
84 b = rpcdecrypt(rpc, b);
89 debug(DBG_CRYPTO, "encrypted with ksmall is %B\n", b);
91 a = rsadecrypt(ksmall, b, nil);
95 b = rpcdecrypt(rpc, b);
100 debug(DBG_CRYPTO, "munged is %B\n", b);
102 n = (mpsignif(b)+7)/8;
104 sysfatal("client sent short session key");
106 buf = emalloc(SESSKEYLEN);
107 mptoberjust(b, buf, SESSKEYLEN);
110 for(i=0; i<SESSIDLEN; i++)
111 buf[i] ^= c->sessid[i];
113 memmove(c->sesskey, buf, SESSKEYLEN);
115 debug(DBG_CRYPTO, "unmunged is %.*H\n", SESSKEYLEN, buf);
117 c->flags = getlong(m);
122 responselogin(char *user, char *resp)
127 if((c = auth_challenge("proto=p9cr user=%q role=server", user)) == nil){
128 sshlog("auth_challenge failed for %s", user);
132 c->nresp = strlen(resp);
133 ai = auth_response(c);
139 authusername(Conn *c)
145 * hack for sam users: 'name numbers' gets tried as securid login.
147 if(p = strchr(c->user, ' ')){
149 if((ai=responselogin(c->user, p)) != nil)
152 sshlog("bad response: %s", c->user);
165 m = recvmsg(c, SSH_CMSG_USER);
167 c->user = emalloc(strlen(user)+1);
168 strcpy(c->user, user);
171 ai = authusername(c);
174 * clumsy: if the client aborted the auth_tis early
175 * we don't send a new failure. we check this by
176 * looking at c->unget, which is only used in that
181 sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
184 for(i=0; i<c->nokauthsrv; i++)
185 if(c->okauthsrv[i]->firstmsg == m->type){
186 ai = (*c->okauthsrv[i]->fn)(c, m);
192 sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
194 if(noworld(ai->cuid))
195 ns = "/lib/namespace.noworld";
198 if(auth_chuid(ai, ns) < 0){
199 sshlog("auth_chuid to %s: %r", ai->cuid);
200 sysfatal("auth_chuid: %r");
202 sshlog("logged in as %s", ai->cuid);
207 sshserverhandshake(Conn *c)
218 * BUG: should use `attr' to get the key attributes
219 * after the read, but that's not implemented yet.
221 if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil)
222 sysfatal("open /mnt/factotum/ctl: %r");
223 while((p = Brdline(b, '\n')) != nil){
224 p[Blinelen(b)-1] = '\0';
225 if(strstr(p, " proto=rsa ") && strstr(p, " service=sshserve "))
229 sysfatal("no sshserve keys found in /mnt/factotum/ctl");
232 key = emalloc(sizeof(*key));
233 if((p = _strfindattr(a, "n")) == nil)
234 sysfatal("no n in sshserve key");
235 if((key->n = strtomp(p, &p, 16, nil)) == nil || *p != 0)
236 sysfatal("bad n in sshserve key");
237 if((p = _strfindattr(a, "ek")) == nil)
238 sysfatal("no ek in sshserve key");
239 if((key->ek = strtomp(p, &p, 16, nil)) == nil || *p != 0)
240 sysfatal("bad ek in sshserve key");
243 if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
244 sysfatal("open /mnt/factotum/rpc: %r");
245 if((rpc = auth_allocrpc(afd)) == nil)
246 sysfatal("auth_allocrpc: %r");
247 p = "proto=rsa role=client service=sshserve";
248 if(auth_rpc(rpc, "start", p, strlen(p)) != ARok)
249 sysfatal("auth_rpc start %s: %r", p);
250 if(auth_rpc(rpc, "read", nil, 0) != ARok)
251 sysfatal("auth_rpc read: %r");
252 m = strtomp(rpc->arg, nil, 16, nil);
253 if(mpcmp(m, key->n) != 0)
254 sysfatal("key in /mnt/factotum/ctl does not match rpc key");
259 fprint(c->fd[0], "SSH-1.5-Plan9\n");
261 /* receive id string */
262 if(readstrnl(c->fd[0], buf, sizeof buf) < 0)
263 sysfatal("reading server version: %r");
265 /* id string is "SSH-m.n-comment". We need m=1, n>=5. */
266 if(strncmp(buf, "SSH-", 4) != 0
267 || strtol(buf+4, &p, 10) != 1
269 || strtol(p+1, &p, 10) < 5
271 sysfatal("protocol mismatch; got %s, need SSH-1.x for x>=5", buf);
273 for(i=0; i<COOKIELEN; i++)
274 c->cookie[i] = fastrand();
276 send_ssh_smsg_public_key(c);
277 recv_ssh_cmsg_session_key(c, rpc);
281 c->cstate = (*c->cipher->init)(c, 1); /* turns on encryption */
282 sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));