debug(DBG_CRYPTO, "session key is %.*H\n", SESSKEYLEN, c->sesskey);
memmove(buf, c->sesskey, SESSKEYLEN);
for(i = 0; i < SESSIDLEN; i++)
buf[i] ^= c->sessid[i];
debug(DBG_CRYPTO, "munged session key is %.*H\n", SESSKEYLEN, buf);
b = rsaencryptbuf(ksmall, buf, SESSKEYLEN);
n = (mpsignif(ksmall->n)+7) / 8;
mptoberjust(b, buf, n);
mpfree(b);
debug(DBG_CRYPTO, "encrypted with ksmall is %.*H\n", n, buf);
b = rsaencryptbuf(kbig, buf, n);
putmpint(m, b);
debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b);
mpfree(b);
memset(buf, 0, buflen);
free(buf);
putlong(m, c->flags);
sendmsg(m);
}
static int
authuser(Conn *c)
{
int i;
Msg *m;
m = allocmsg(c, SSH_CMSG_USER, 4+strlen(c->user));
putstring(m, c->user);
sendmsg(m);
m = recvmsg(c, 0);
switch(m->type){
case SSH_SMSG_SUCCESS:
free(m);
return 0;
case SSH_SMSG_FAILURE:
free(m);
break;
default:
badmsg(m, 0);
}
debug(DBG_CRYPTO, "checking key %B %B\n", c->hostkey->n, c->hostkey->ek);
switch(findkey("/sys/lib/ssh/keyring", c->aliases, c->hostkey)){
default:
abort();
case KeyOk:
return;
case KeyWrong:
fprint(2, "server presented public key different than expected\n");
fprint(2, "(expected key in /sys/lib/ssh/keyring). will not continue.\n");
error("bad server key");
case NoKey:
case NoKeyFile:
break;
}
home = getenv("home");
if(home == nil){
fprint(2, "server %s not on keyring; will not continue.\n", c->host);
error("bad server key");
}
keyfile = smprint("%s/lib/keyring", home);
if(keyfile == nil)
error("out of memory");
switch(findkey(keyfile, c->aliases, c->hostkey)){
default:
abort();
case KeyOk:
return;
case KeyWrong:
fprint(2, "server %s presented public key different than expected\n", c->host);
fprint(2, "(expected key in %s). will not continue.\n", keyfile);
fprint(2, "this could be a man-in-the-middle attack.\n");
switch(ask(c, "eri", "replace key in keyfile (r), continue without replacing key (c), or exit (e) [e]")){
case 'e':
error("bad key");
case 'r':
if(replacekey(keyfile, c->aliases, c->hostkey) < 0)
error("replacekey: %r");
break;
case 'c':
break;
}
return;
case NoKey:
case NoKeyFile:
fprint(2, "server %s not on keyring.\n", c->host);
switch(ask(c, "eac", "add key to keyfile (a), continue without adding key (c), or exit (e) [e]")){
case 'e':
error("bad key");
case 'a':
if(appendkey(keyfile, c->aliases, c->hostkey) < 0)
error("appendkey: %r");
break;
case 'c':
break;
}
return;
}
}
static int
intgetenv(char *name, int def)
{
char *s;
int n, val;
val = def;
if((s = getenv(name))!=nil){
if((n=atoi(s)) > 0)
val = n;
free(s);
}
return val;
}
/*
* clumsy hack -- rather than open the font and fetch
* the real character width and height, we assume that
* LINES and COLS are initially correct and use them to
* derive cwidth, cheight. this is definitely a mistake,
* but i don't care. if you do, fix it.
*/
int
readgeom(int *nrow, int *ncol, int *width, int *height)
{
int ret;
static int first=1;
static int fd = -1;
static int cwidth, cheight;
char buf[64];
int n;
/*
* In each option line, the first byte is the option number
* and the second is either a boolean bit or actually an
* ASCII code.
*/
static uchar ptyopt[] =
{
0x01, 0x7F, /* interrupt = DEL */
0x02, 0x11, /* quit = ^Q */
0x03, 0x08, /* backspace = ^H */
0x04, 0x15, /* line kill = ^U */
0x05, 0x04, /* EOF = ^D */
0x20, 0x00, /* don't strip high bit */
0x48, 0x01, /* give us CRs */