+ send_packet(SSH1_CMSG_SESSION_KEY,
+ PKT_CHAR, cipher_type,
+ PKT_DATA, cookie, 8,
+ PKT_CHAR, (len*8) >> 8, PKT_CHAR, (len*8) & 0xFF,
+ PKT_DATA, rsabuf, len,
+ PKT_INT, 0,
+ PKT_END);
+
+ logevent("Trying to enable encryption...");
+
+ free(rsabuf);
+
+ cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
+ cipher_type == SSH_CIPHER_DES ? &ssh_des :
+ &ssh_3des;
+ cipher->sesskey(session_key);
+
+ crWaitUntil(ispkt);
+
+ if (pktin.type != SSH1_SMSG_SUCCESS) {
+ bombout(("Encryption not successfully enabled"));
+ crReturn(0);
+ }
+
+ logevent("Successfully started encryption");
+
+ fflush(stdout);
+ {
+ static int pos = 0;
+ static char c;
+ if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
+ c_write("login as: ", 10);
+ ssh_send_ok = 1;
+ while (pos >= 0) {
+ crWaitUntil(!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 <= '~') ||
+ ((unsigned char)c >= 160)) && 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';
+ if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
+ sprintf(stuff, "Sent username \"%s\".\r\n", username);
+ c_write(stuff, strlen(stuff));
+ }
+ }
+
+ send_packet(SSH1_CMSG_USER, PKT_STR, username, PKT_END);
+ {
+ char userlog[20+sizeof(username)];
+ sprintf(userlog, "Sent username \"%s\"", username);
+ logevent(userlog);
+ }
+ }
+
+ crWaitUntil(ispkt);
+
+ tried_publickey = 0;
+
+ while (pktin.type == SSH1_SMSG_FAILURE) {
+ static char password[100];
+ static char prompt[200];
+ static int pos;
+ static char c;
+ static int pwpkt_type;
+ /*
+ * Show password prompt, having first obtained it via a TIS
+ * or CryptoCard exchange if we're doing TIS or CryptoCard
+ * authentication.
+ */
+ pwpkt_type = SSH1_CMSG_AUTH_PASSWORD;
+ if (agent_exists()) {
+ /*
+ * Attempt RSA authentication using Pageant.
+ */
+ static unsigned char request[5], *response, *p;
+ static int responselen;
+ static int i, nkeys;
+ static int authed = FALSE;
+ void *r;
+
+ logevent("Pageant is running. Requesting keys.");
+
+ /* Request the keys held by the agent. */
+ PUT_32BIT(request, 1);
+ request[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
+ agent_query(request, 5, &r, &responselen);
+ response = (unsigned char *)r;
+ if (response) {
+ p = response + 5;
+ nkeys = GET_32BIT(p); p += 4;
+ { char buf[64]; sprintf(buf, "Pageant has %d keys", nkeys);
+ logevent(buf); }
+ for (i = 0; i < nkeys; i++) {
+ static struct RSAKey key;
+ static Bignum challenge;
+ static char *commentp;
+ static int commentlen;
+
+ { char buf[64]; sprintf(buf, "Trying Pageant key #%d", i);
+ logevent(buf); }
+ p += 4;
+ p += ssh1_read_bignum(p, &key.exponent);
+ p += ssh1_read_bignum(p, &key.modulus);
+ commentlen = GET_32BIT(p); p += 4;
+ commentp = p; p += commentlen;
+ send_packet(SSH1_CMSG_AUTH_RSA,
+ PKT_BIGNUM, key.modulus, PKT_END);
+ crWaitUntil(ispkt);
+ if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
+ logevent("Key refused");
+ continue;
+ }
+ logevent("Received RSA challenge");
+ ssh1_read_bignum(pktin.body, &challenge);
+ {
+ char *agentreq, *q, *ret;
+ int len, retlen;
+ len = 1 + 4; /* message type, bit count */
+ len += ssh1_bignum_length(key.exponent);
+ len += ssh1_bignum_length(key.modulus);
+ len += ssh1_bignum_length(challenge);
+ len += 16; /* session id */
+ len += 4; /* response format */
+ agentreq = malloc(4 + len);
+ PUT_32BIT(agentreq, len);
+ q = agentreq + 4;
+ *q++ = SSH_AGENTC_RSA_CHALLENGE;
+ PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus));
+ q += 4;
+ q += ssh1_write_bignum(q, key.exponent);
+ q += ssh1_write_bignum(q, key.modulus);
+ q += ssh1_write_bignum(q, challenge);
+ memcpy(q, session_id, 16); q += 16;
+ PUT_32BIT(q, 1); /* response format */
+ agent_query(agentreq, len+4, &ret, &retlen);
+ free(agentreq);
+ if (ret) {
+ if (ret[4] == SSH_AGENT_RSA_RESPONSE) {
+ logevent("Sending Pageant's response");
+ send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
+ PKT_DATA, ret+5, 16, PKT_END);
+ free(ret);
+ crWaitUntil(ispkt);
+ if (pktin.type == SSH1_SMSG_SUCCESS) {
+ logevent("Pageant's response accepted");
+ if (flags & FLAG_VERBOSE) {
+ c_write("Authenticated using RSA key \"",
+ 29);
+ c_write(commentp, commentlen);
+ c_write("\" from agent\r\n", 14);
+ }
+ authed = TRUE;
+ } else
+ logevent("Pageant's response not accepted");
+ } else {
+ logevent("Pageant failed to answer challenge");
+ free(ret);
+ }
+ } else {
+ logevent("No reply received from Pageant");
+ }
+ }
+ freebn(key.exponent);
+ freebn(key.modulus);
+ freebn(challenge);
+ if (authed)
+ break;
+ }
+ }
+ if (authed)
+ break;
+ }
+ if (*cfg.keyfile && !tried_publickey)
+ pwpkt_type = SSH1_CMSG_AUTH_RSA;
+
+ if (pktin.type == SSH1_SMSG_FAILURE &&
+ cfg.try_tis_auth &&
+ (supported_auths_mask & (1<<SSH1_AUTH_TIS))) {
+ pwpkt_type = SSH1_CMSG_AUTH_TIS_RESPONSE;
+ logevent("Requested TIS authentication");
+ send_packet(SSH1_CMSG_AUTH_TIS, PKT_END);
+ crWaitUntil(ispkt);
+ if (pktin.type != SSH1_SMSG_AUTH_TIS_CHALLENGE) {
+ logevent("TIS authentication declined");
+ if (flags & FLAG_INTERACTIVE)
+ c_write("TIS authentication refused.\r\n", 29);
+ } else {
+ int challengelen = ((pktin.body[0] << 24) |
+ (pktin.body[1] << 16) |
+ (pktin.body[2] << 8) |
+ (pktin.body[3]));
+ logevent("Received TIS challenge");
+ if (challengelen > sizeof(prompt)-1)
+ challengelen = sizeof(prompt)-1; /* prevent overrun */
+ memcpy(prompt, pktin.body+4, challengelen);
+ prompt[challengelen] = '\0';
+ }
+ }
+ if (pktin.type == SSH1_SMSG_FAILURE &&
+ cfg.try_tis_auth &&
+ (supported_auths_mask & (1<<SSH1_AUTH_CCARD))) {
+ pwpkt_type = SSH1_CMSG_AUTH_CCARD_RESPONSE;
+ logevent("Requested CryptoCard authentication");
+ send_packet(SSH1_CMSG_AUTH_CCARD, PKT_END);
+ crWaitUntil(ispkt);
+ if (pktin.type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
+ logevent("CryptoCard authentication declined");
+ c_write("CryptoCard authentication refused.\r\n", 29);
+ } else {
+ int challengelen = ((pktin.body[0] << 24) |
+ (pktin.body[1] << 16) |
+ (pktin.body[2] << 8) |
+ (pktin.body[3]));
+ logevent("Received CryptoCard challenge");
+ if (challengelen > sizeof(prompt)-1)
+ challengelen = sizeof(prompt)-1; /* prevent overrun */
+ memcpy(prompt, pktin.body+4, challengelen);
+ strncpy(prompt + challengelen, "\r\nResponse : ",
+ sizeof(prompt)-challengelen);
+ prompt[sizeof(prompt)-1] = '\0';
+ }
+ }
+ if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD) {
+ sprintf(prompt, "%.90s@%.90s's password: ",
+ username, savedhost);
+ }
+ if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
+ char *comment = NULL;
+ if (flags & FLAG_VERBOSE)
+ c_write("Trying public key authentication.\r\n", 35);
+ if (!rsakey_encrypted(cfg.keyfile, &comment)) {
+ if (flags & FLAG_VERBOSE)
+ c_write("No passphrase required.\r\n", 25);
+ goto tryauth;
+ }
+ sprintf(prompt, "Passphrase for key \"%.100s\": ", comment);
+ free(comment);
+ }
+
+ if (ssh_get_password) {
+ if (!ssh_get_password(prompt, password, sizeof(password))) {
+ /*
+ * get_password failed to get a password (for
+ * example because one was supplied on the command
+ * line which has already failed to work).
+ * Terminate.
+ */
+ logevent("No more passwords to try");
+ ssh_state = SSH_STATE_CLOSED;
+ crReturn(1);
+ }
+ } else {
+ c_write(prompt, strlen(prompt));
+ pos = 0;
+ ssh_send_ok = 1;
+ while (pos >= 0) {
+ crWaitUntil(!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 <= '~') ||
+ ((unsigned char)c >= 160)) && pos < sizeof(password))
+ password[pos++] = c;
+ break;
+ }
+ }
+ c_write("\r\n", 2);
+ }
+
+ tryauth:
+ if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
+ /*
+ * Try public key authentication with the specified
+ * key file.
+ */
+ static struct RSAKey pubkey;
+ static Bignum challenge, response;
+ static int i;
+ static unsigned char buffer[32];
+
+ tried_publickey = 1;
+ i = loadrsakey(cfg.keyfile, &pubkey, password);
+ if (i == 0) {
+ c_write("Couldn't load public key from ", 30);
+ c_write(cfg.keyfile, strlen(cfg.keyfile));
+ c_write(".\r\n", 3);
+ continue; /* go and try password */
+ }
+ if (i == -1) {
+ c_write("Wrong passphrase.\r\n", 19);
+ tried_publickey = 0;
+ continue; /* try again */
+ }
+
+ /*
+ * Send a public key attempt.
+ */
+ send_packet(SSH1_CMSG_AUTH_RSA,
+ PKT_BIGNUM, pubkey.modulus, PKT_END);
+
+ crWaitUntil(ispkt);
+ if (pktin.type == SSH1_SMSG_FAILURE) {
+ c_write("Server refused our public key.\r\n", 32);
+ continue; /* go and try password */
+ }
+ if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
+ bombout(("Bizarre response to offer of public key"));
+ crReturn(0);
+ }
+ ssh1_read_bignum(pktin.body, &challenge);
+ response = rsadecrypt(challenge, &pubkey);
+ freebn(pubkey.private_exponent); /* burn the evidence */
+
+ for (i = 0; i < 32; i += 2) {
+ buffer[i] = response[16-i/2] >> 8;
+ buffer[i+1] = response[16-i/2] & 0xFF;
+ }
+
+ MD5Init(&md5c);
+ MD5Update(&md5c, buffer, 32);
+ MD5Update(&md5c, session_id, 16);
+ MD5Final(buffer, &md5c);
+
+ send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
+ PKT_DATA, buffer, 16, PKT_END);
+
+ crWaitUntil(ispkt);
+ if (pktin.type == SSH1_SMSG_FAILURE) {
+ if (flags & FLAG_VERBOSE)
+ c_write("Failed to authenticate with our public key.\r\n",
+ 45);
+ continue; /* go and try password */
+ } else if (pktin.type != SSH1_SMSG_SUCCESS) {
+ bombout(("Bizarre response to RSA authentication response"));
+ crReturn(0);
+ }
+
+ break; /* we're through! */
+ } else {
+ send_packet(pwpkt_type, PKT_STR, password, PKT_END);
+ }
+ logevent("Sent password");
+ memset(password, 0, strlen(password));
+ crWaitUntil(ispkt);
+ if (pktin.type == SSH1_SMSG_FAILURE) {
+ if (flags & FLAG_VERBOSE)
+ c_write("Access denied\r\n", 15);
+ logevent("Authentication refused");
+ } else if (pktin.type == SSH1_MSG_DISCONNECT) {
+ logevent("Received disconnect request");
+ ssh_state = SSH_STATE_CLOSED;
+ crReturn(1);
+ } else if (pktin.type != SSH1_SMSG_SUCCESS) {
+ bombout(("Strange packet received, type %d", pktin.type));
+ crReturn(0);
+ }
+ }
+
+ logevent("Authentication successful");
+
+ crFinish(1);
+}
+
+static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {