if (i < lenof(ciphers)-1)
if (i < lenof(ciphers))
static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt){    static int i, len;    static char *str;    static Bignum e, f, K;    static const struct ssh_cipher *cscipher_tobe = NULL;    static const struct ssh_cipher *sccipher_tobe = NULL;    static const struct ssh_mac *csmac_tobe = NULL;    static const struct ssh_mac *scmac_tobe = NULL;    static const struct ssh_compress *cscomp_tobe = NULL;    static const struct ssh_compress *sccomp_tobe = NULL;    static char *hostkeydata, *sigdata, *keystr, *fingerprint;    static int hostkeylen, siglen;    static unsigned char exchange_hash[20];    static unsigned char keyspace[40];    static const struct ssh_cipher *preferred_cipher;    crBegin;    random_init();    /*     * Set up the preferred cipher.     */    if (cfg.cipher == CIPHER_BLOWFISH) {        preferred_cipher = &ssh_blowfish_ssh2;    } else if (cfg.cipher == CIPHER_DES) {        logevent("Single DES not supported in SSH2; using 3DES");        preferred_cipher = &ssh_3des_ssh2;    } else if (cfg.cipher == CIPHER_3DES) {        preferred_cipher = &ssh_3des_ssh2;    } else {        /* Shouldn't happen, but we do want to initialise to _something_. */        preferred_cipher = &ssh_3des_ssh2;    }    begin_key_exchange:    /*     * Construct and send our key exchange packet.     */    ssh2_pkt_init(SSH2_MSG_KEXINIT);    for (i = 0; i < 16; i++)        ssh2_pkt_addbyte((unsigned char)random_byte());    /* List key exchange algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(kex_algs); i++) {        ssh2_pkt_addstring_str(kex_algs[i]->name);        if (i < lenof(kex_algs)-1)            ssh2_pkt_addstring_str(",");    }    /* List server host key algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(hostkey_algs); i++) {        ssh2_pkt_addstring_str(hostkey_algs[i]->name);        if (i < lenof(hostkey_algs)-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server encryption algorithms. */    ssh2_pkt_addstring_start();    for (i = -1; i < lenof(ciphers); i++) {        const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i];        ssh2_pkt_addstring_str(c->name);        if (i < lenof(ciphers)-1)            ssh2_pkt_addstring_str(",");    }    /* List server->client encryption algorithms. */    ssh2_pkt_addstring_start();    for (i = -1; i < lenof(ciphers); i++) {        const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i];        ssh2_pkt_addstring_str(c->name);        if (i < lenof(ciphers)-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server MAC algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(macs); i++) {        ssh2_pkt_addstring_str(macs[i]->name);        if (i < lenof(macs)-1)            ssh2_pkt_addstring_str(",");    }    /* List server->client MAC algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(macs); i++) {        ssh2_pkt_addstring_str(macs[i]->name);        if (i < lenof(macs)-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server compression algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(compressions); i++) {        ssh2_pkt_addstring_str(compressions[i]->name);        if (i < lenof(compressions)-1)            ssh2_pkt_addstring_str(",");    }    /* List server->client compression algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(compressions); i++) {        ssh2_pkt_addstring_str(compressions[i]->name);        if (i < lenof(compressions)-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server languages. Empty list. */    ssh2_pkt_addstring_start();    /* List server->client languages. Empty list. */    ssh2_pkt_addstring_start();    /* First KEX packet does _not_ follow, because we're not that brave. */    ssh2_pkt_addbool(FALSE);    /* Reserved. */    ssh2_pkt_adduint32(0);    sha_string(&exhash, pktout.data+5, pktout.length-5);    ssh2_pkt_send();    if (!ispkt) crWaitUntil(ispkt);    sha_string(&exhash, pktin.data+5, pktin.length-5);    /*     * Now examine the other side's KEXINIT to see what we're up     * to.     */    if (pktin.type != SSH2_MSG_KEXINIT) {        bombout(("expected key exchange packet from server"));        crReturn(0);    }    kex = NULL; hostkey = NULL; cscipher_tobe = NULL; sccipher_tobe = NULL;    csmac_tobe = NULL; scmac_tobe = NULL; cscomp_tobe = NULL; sccomp_tobe = NULL;    pktin.savedpos += 16;              /* skip garbage cookie */    ssh2_pkt_getstring(&str, &len);    /* key exchange algorithms */    for (i = 0; i < lenof(kex_algs); i++) {        if (in_commasep_string(kex_algs[i]->name, str, len)) {            kex = kex_algs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* host key algorithms */    for (i = 0; i < lenof(hostkey_algs); i++) {        if (in_commasep_string(hostkey_algs[i]->name, str, len)) {            hostkey = hostkey_algs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* client->server cipher */    for (i = -1; i < lenof(ciphers); i++) {        const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i];        if (in_commasep_string(c->name, str, len)) {            cscipher_tobe = ciphers[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* server->client cipher */    for (i = -1; i < lenof(ciphers); i++) {        const struct ssh_cipher *c = i<0 ? preferred_cipher : ciphers[i];        if (in_commasep_string(c->name, str, len)) {            sccipher_tobe = ciphers[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* client->server mac */    for (i = 0; i < lenof(macs); i++) {        if (in_commasep_string(macs[i]->name, str, len)) {            csmac_tobe = macs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* server->client mac */    for (i = 0; i < lenof(macs); i++) {        if (in_commasep_string(macs[i]->name, str, len)) {            scmac_tobe = macs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* client->server compression */    for (i = 0; i < lenof(compressions); i++) {        if (in_commasep_string(compressions[i]->name, str, len)) {            cscomp_tobe = compressions[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* server->client compression */    for (i = 0; i < lenof(compressions); i++) {        if (in_commasep_string(compressions[i]->name, str, len)) {            sccomp_tobe = compressions[i];            break;        }    }    /*     * Currently we only support Diffie-Hellman and DSS, so let's     * bomb out if those aren't selected.     */    if (kex != &ssh_diffiehellman || hostkey != &ssh_dss) {        bombout(("internal fault: chaos in SSH 2 transport layer"));        crReturn(0);    }    /*     * Now we begin the fun. Generate and send e for Diffie-Hellman.     */    e = dh_create_e();    ssh2_pkt_init(SSH2_MSG_KEXDH_INIT);    ssh2_pkt_addmp(e);    ssh2_pkt_send();    crWaitUntil(ispkt);    if (pktin.type != SSH2_MSG_KEXDH_REPLY) {        bombout(("expected key exchange packet from server"));        crReturn(0);    }    ssh2_pkt_getstring(&hostkeydata, &hostkeylen);    f = ssh2_pkt_getmp();    ssh2_pkt_getstring(&sigdata, &siglen);    K = dh_find_K(f);    sha_string(&exhash, hostkeydata, hostkeylen);    sha_mpint(&exhash, e);    sha_mpint(&exhash, f);    sha_mpint(&exhash, K);    SHA_Final(&exhash, exchange_hash);#if 0    debug(("Exchange hash is:\r\n"));    for (i = 0; i < 20; i++)        debug((" %02x", exchange_hash[i]));    debug(("\r\n"));#endif    hostkey->setkey(hostkeydata, hostkeylen);    if (!hostkey->verifysig(sigdata, siglen, exchange_hash, 20)) {        bombout(("Server failed host key check"));        crReturn(0);    }    /*     * Expect SSH2_MSG_NEWKEYS from server.     */    crWaitUntil(ispkt);    if (pktin.type != SSH2_MSG_NEWKEYS) {        bombout(("expected new-keys packet from server"));        crReturn(0);    }    /*     * Authenticate remote host: verify host key. (We've already     * checked the signature of the exchange hash.)     */    keystr = hostkey->fmtkey();    fingerprint = hostkey->fingerprint();    verify_ssh_host_key(savedhost, savedport, hostkey->keytype,                        keystr, fingerprint);    logevent("Host key fingerprint is:");    logevent(fingerprint);    free(fingerprint);    free(keystr);    /*     * Send SSH2_MSG_NEWKEYS.     */    ssh2_pkt_init(SSH2_MSG_NEWKEYS);    ssh2_pkt_send();    /*     * Create and initialise session keys.     */    cscipher = cscipher_tobe;    sccipher = sccipher_tobe;    csmac = csmac_tobe;    scmac = scmac_tobe;    cscomp = cscomp_tobe;    sccomp = sccomp_tobe;    /*     * Set IVs after keys.     */    ssh2_mkkey(K, exchange_hash, 'C', keyspace); cscipher->setcskey(keyspace);    ssh2_mkkey(K, exchange_hash, 'D', keyspace); cscipher->setsckey(keyspace);    ssh2_mkkey(K, exchange_hash, 'A', keyspace); cscipher->setcsiv(keyspace);    ssh2_mkkey(K, exchange_hash, 'B', keyspace); sccipher->setsciv(keyspace);    ssh2_mkkey(K, exchange_hash, 'E', keyspace); csmac->setcskey(keyspace);    ssh2_mkkey(K, exchange_hash, 'F', keyspace); scmac->setsckey(keyspace);    /*     * Now we're encrypting. Begin returning 1 to the protocol main     * function so that other things can run on top of the     * transport. If we ever see a KEXINIT, we must go back to the     * start.     */    do {        crReturn(1);    } while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT));    goto begin_key_exchange;    crFinish(1);}