cipher_type == SSH_CIPHER_DES ? &ssh_des :
static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {    int i, j, len;    unsigned char session_id[16];    unsigned char *rsabuf, *keystr1, *keystr2;    unsigned char cookie[8];    struct RSAKey servkey, hostkey;    struct MD5Context md5c;    unsigned long supported_ciphers_mask;    int cipher_type;    extern struct ssh_cipher ssh_3des;    extern struct ssh_cipher ssh_blowfish;    crBegin;    random_init();    while (!ispkt)	crReturnV;    if (pktin.type != 2)	fatalbox("Public key packet not received");    memcpy(cookie, pktin.body, 8);    MD5Init(&md5c);    i = makekey(pktin.body+8, &servkey, &keystr1);    j = makekey(pktin.body+8+i, &hostkey, &keystr2);    supported_ciphers_mask = (pktin.body[12+i+j] << 24) |                             (pktin.body[13+i+j] << 16) |                             (pktin.body[14+i+j] << 8) |                             (pktin.body[15+i+j]);    MD5Update(&md5c, keystr2, hostkey.bytes);    MD5Update(&md5c, keystr1, servkey.bytes);    MD5Update(&md5c, pktin.body, 8);    MD5Final(session_id, &md5c);    for (i=0; i<32; i++)	session_key[i] = random_byte();    len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);    rsabuf = malloc(len);    if (!rsabuf)	fatalbox("Out of memory");    verify_ssh_host_key(savedhost, &hostkey);    for (i=0; i<32; i++) {	rsabuf[i] = session_key[i];	if (i < 16)	    rsabuf[i] ^= session_id[i];    }    if (hostkey.bytes > servkey.bytes) {	rsaencrypt(rsabuf, 32, &servkey);	rsaencrypt(rsabuf, servkey.bytes, &hostkey);    } else {	rsaencrypt(rsabuf, 32, &hostkey);	rsaencrypt(rsabuf, hostkey.bytes, &servkey);    }    cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :                  SSH_CIPHER_3DES;    if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {	c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);	cipher_type = SSH_CIPHER_3DES;    }    s_wrpkt_start(3, len+15);    pktout.body[0] = cipher_type;    memcpy(pktout.body+1, cookie, 8);    pktout.body[9] = (len*8) >> 8;    pktout.body[10] = (len*8) & 0xFF;    memcpy(pktout.body+11, rsabuf, len);    pktout.body[len+11] = pktout.body[len+12] = 0;   /* protocol flags */    pktout.body[len+13] = pktout.body[len+14] = 0;    s_wrpkt();    free(rsabuf);    cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish :             &ssh_3des;    cipher->sesskey(session_key);    do { crReturnV; } while (!ispkt);    if (pktin.type != 14)	fatalbox("Encryption not successfully enabled");    fflush(stdout);    {	static char username[100];	static int pos = 0;	static char c;	if (!*cfg.username) {	    c_write("login as: ", 10);	    while (pos >= 0) {		do { crReturnV; } while (ispkt);		while (inlen--) switch (c = *in++) {		  case 10: case 13:		    username[pos] = 0;		    pos = -1;		    break;		  case 8: case 127:		    if (pos > 0) {			c_write("\b \b", 3);			pos--;		    }		    break;		  case 21: case 27:		    while (pos > 0) {			c_write("\b \b", 3);			pos--;		    }		    break;		  case 3: case 4:		    random_save_seed();		    exit(0);		    break;		  default:		    if (c >= ' ' && c <= '~' && pos < 40) {			username[pos++] = c;			c_write(&c, 1);		    }		    break;		}	    }	    c_write("\r\n", 2);	    username[strcspn(username, "\n\r")] = '\0';	} else {	    char stuff[200];	    strncpy(username, cfg.username, 99);	    username[99] = '\0';	    sprintf(stuff, "Sent username \"%s\".\r\n", username);	    c_write(stuff, strlen(stuff));	}	s_wrpkt_start(4, 4+strlen(username));	pktout.body[0] = pktout.body[1] = pktout.body[2] = 0;	pktout.body[3] = strlen(username);	memcpy(pktout.body+4, username, strlen(username));	s_wrpkt();    }    do { crReturnV; } while (!ispkt);    while (pktin.type == 15) {	static char password[100];	static int pos;	static char c;	c_write("password: ", 10);	pos = 0;	while (pos >= 0) {	    do { crReturnV; } while (ispkt);	    while (inlen--) switch (c = *in++) {	      case 10: case 13:		password[pos] = 0;		pos = -1;		break;	      case 8: case 127:		if (pos > 0)		    pos--;		break;	      case 21: case 27:		pos = 0;		break;	      case 3: case 4:		random_save_seed();		exit(0);		break;	      default:		if (c >= ' ' && c <= '~' && pos < 40)		    password[pos++] = c;		break;	    }	}	c_write("\r\n", 2);	s_wrpkt_start(9, 4+strlen(password));	pktout.body[0] = pktout.body[1] = pktout.body[2] = 0;	pktout.body[3] = strlen(password);	memcpy(pktout.body+4, password, strlen(password));	s_wrpkt();	memset(password, 0, strlen(password));	do { crReturnV; } while (!ispkt);	if (pktin.type == 15) {	    c_write("Access denied\r\n", 15);	} else if (pktin.type != 14) {	    fatalbox("Strange packet received, type %d", pktin.type);	}    }    if (!cfg.nopty) {        i = strlen(cfg.termtype);        s_wrpkt_start(10, i+5*4+1);        pktout.body[0] = (i >> 24) & 0xFF;        pktout.body[1] = (i >> 16) & 0xFF;        pktout.body[2] = (i >> 8) & 0xFF;        pktout.body[3] = i & 0xFF;        memcpy(pktout.body+4, cfg.termtype, i);        i += 4;        pktout.body[i++] = (rows >> 24) & 0xFF;        pktout.body[i++] = (rows >> 16) & 0xFF;        pktout.body[i++] = (rows >> 8) & 0xFF;        pktout.body[i++] = rows & 0xFF;        pktout.body[i++] = (cols >> 24) & 0xFF;        pktout.body[i++] = (cols >> 16) & 0xFF;        pktout.body[i++] = (cols >> 8) & 0xFF;        pktout.body[i++] = cols & 0xFF;        memset(pktout.body+i, 0, 9);       /* 0 pixwidth, 0 pixheight, 0.b endofopt */        s_wrpkt();        ssh_state = SSH_STATE_INTERMED;        do { crReturnV; } while (!ispkt);        if (pktin.type != 14 && pktin.type != 15) {            fatalbox("Protocol confusion");        } else if (pktin.type == 15) {            c_write("Server refused to allocate pty\r\n", 32);        }    }    s_wrpkt_start(12, 0);    s_wrpkt();    ssh_state = SSH_STATE_SESSION;    if (size_needed)	ssh_size();    while (1) {	crReturnV;	if (ispkt) {	    if (pktin.type == 17 || pktin.type == 18) {		long len = 0;		for (i = 0; i < 4; i++)		    len = (len << 8) + pktin.body[i];		c_write(pktin.body+4, len);	    } else if (pktin.type == 1) {		/* SSH_MSG_DISCONNECT */                ssh_state = SSH_STATE_CLOSED;	    } else if (pktin.type == 14) {		/* SSH_MSG_SUCCESS: may be from EXEC_SHELL on some servers */	    } else if (pktin.type == 15) {		/* SSH_MSG_FAILURE: may be from EXEC_SHELL on some servers		 * if no pty is available or in other odd cases. Ignore */	    } else if (pktin.type == 20) {		/* EXITSTATUS */		s_wrpkt_start(33, 0);		s_wrpkt();	    } else {		fatalbox("Strange packet received: type %d", pktin.type);	    }	} else {	    s_wrpkt_start(16, 4+inlen);	    pktout.body[0] = (inlen >> 24) & 0xFF;	    pktout.body[1] = (inlen >> 16) & 0xFF;	    pktout.body[2] = (inlen >> 8) & 0xFF;	    pktout.body[3] = inlen & 0xFF;	    memcpy(pktout.body+4, in, inlen);	    s_wrpkt();	}    }    crFinishV;}