From: simon Date: Mon, 25 Sep 2000 10:14:53 +0000 (+0000) Subject: Rationalise ordering of authentication operations. Still some work to do, X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/commitdiff_plain/a52f067e0510f49ff0473878280521bd11cd3c78 Rationalise ordering of authentication operations. Still some work to do, but at least pscp no longer hangs when prompting for a passphrase git-svn-id: svn://svn.tartarus.org/sgt/putty@621 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/pageant.c b/pageant.c index 7133c8d5..978751a8 100644 --- a/pageant.c +++ b/pageant.c @@ -127,7 +127,8 @@ void add_keyfile(char *filename) { int ret; int attempts; - needs_pass = rsakey_encrypted(filename); + /* FIXME: we can acquire comment here and use it in dialog */ + needs_pass = rsakey_encrypted(filename, NULL); attempts = 0; key = malloc(sizeof(*key)); do { diff --git a/ssh.c b/ssh.c index 97c6839b..4068aa72 100644 --- a/ssh.c +++ b/ssh.c @@ -1273,6 +1273,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) while (pktin.type == SSH1_SMSG_FAILURE) { static char password[100]; + static char prompt[200]; static int pos; static char c; static int pwpkt_type; @@ -1385,10 +1386,71 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) if (*cfg.keyfile && !tried_publickey) pwpkt_type = SSH1_CMSG_AUTH_RSA; - if (pwpkt_type == SSH1_CMSG_AUTH_PASSWORD && - !(flags & FLAG_INTERACTIVE)) { - char prompt[200]; - sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost); + if (pktin.type == SSH1_SMSG_FAILURE && + cfg.try_tis_auth && + (supported_auths_mask & (1< 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< 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: ", + cfg.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 (!(flags & FLAG_INTERACTIVE)) { if (!ssh_get_password(prompt, password, sizeof(password))) { /* * get_password failed to get a password (for @@ -1401,59 +1463,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) crReturn(1); } } else { - - if (pktin.type == SSH1_SMSG_FAILURE && - cfg.try_tis_auth && - (supported_auths_mask & (1<= 0) { @@ -1482,8 +1492,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) } } c_write("\r\n", 2); - - } + } tryauth: if (pwpkt_type == SSH1_CMSG_AUTH_RSA) { @@ -1518,8 +1527,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) crWaitUntil(ispkt); if (pktin.type == SSH1_SMSG_FAILURE) { - if (flags & FLAG_VERBOSE) - c_write("Server refused our public key.\r\n", 32); + c_write("Server refused our public key.\r\n", 32); continue; /* go and try password */ } if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) { diff --git a/ssh.h b/ssh.h index a2b64012..058c5247 100644 --- a/ssh.h +++ b/ssh.h @@ -156,7 +156,7 @@ Bignum dh_create_e(void); Bignum dh_find_K(Bignum f); int loadrsakey(char *filename, struct RSAKey *key, char *passphrase); -int rsakey_encrypted(char *filename); +int rsakey_encrypted(char *filename, char **comment); void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len); diff --git a/sshbn.c b/sshbn.c index adb88243..dbf223d6 100644 --- a/sshbn.c +++ b/sshbn.c @@ -324,6 +324,9 @@ int ssh1_read_bignum(unsigned char *data, Bignum *result) { b = (w+7)/8; /* bits -> bytes */ w = (w+15)/16; /* bits -> words */ + if (!result) /* just return length */ + return b + 2; + bn = newbn(w); for (i=1; i<=w; i++) diff --git a/sshpubk.c b/sshpubk.c index 3e4de1fc..fb5b7cc6 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -1,17 +1,17 @@ /* - * Read SSH public keys from files. - * - * First implementation: only supports unencrypted SSH 1.1 format - * RSA keys. Encryption, and SSH 2 DSS keys, to be supported later. + * Generic SSH public-key handling operations. In particular, + * reading of SSH public-key files, and also the generic `sign' + * operation for ssh2 (which checks the type of the key and + * dispatches to the appropriate key-type specific function). */ #include +#include -#include /* FIXME */ #include /* FIXME */ #include /* FIXME */ -#include "putty.h" /* FIXME */ +#include "putty.h" #include "ssh.h" #define GET_32BIT(cp) \ @@ -21,33 +21,40 @@ ((unsigned long)(unsigned char)(cp)[3])) #define rsa_signature "SSH PRIVATE KEY FILE FORMAT 1.1\n" +#define dss_signature "-----BEGIN DSA PRIVATE KEY-----\n" -int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) { - FILE *fp; +#define BASE64_TOINT(x) ( (x)-'A'<26 ? (x)-'A'+0 :\ + (x)-'a'<26 ? (x)-'a'+26 :\ + (x)-'0'<10 ? (x)-'0'+52 :\ + (x)=='+' ? 62 : \ + (x)=='/' ? 63 : 0 ) + +static int loadrsakey_main(FILE *fp, struct RSAKey *key, + char **commentptr, char *passphrase) { unsigned char buf[16384]; unsigned char keybuf[16]; int len; int i, j, ciphertype; int ret = 0; struct MD5Context md5c; + char *comment; - fp = fopen(filename, "rb"); - if (!fp) - goto end; - - /* Slurp the whole file into a buffer. */ + /* Slurp the whole file (minus the header) into a buffer. */ len = fread(buf, 1, sizeof(buf), fp); fclose(fp); if (len < 0 || len == sizeof(buf)) goto end; /* file too big or not read */ - if (len < sizeof(rsa_signature) || - memcmp(buf, rsa_signature, sizeof(rsa_signature)) != 0) - goto end; /* failure to have sig at front */ + i = 0; - i = sizeof(rsa_signature); + /* + * A zero byte. (The signature includes a terminating NUL.) + */ + if (len-i < 1 || buf[i] != 0) + goto end; + i++; - /* Next, one byte giving encryption type, and one reserved uint32. */ + /* One byte giving encryption type, and one reserved uint32. */ if (len-i < 1) goto end; ciphertype = buf[i]; @@ -69,12 +76,19 @@ int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) { j = GET_32BIT(buf+i); i += 4; if (len-i < j) goto end; - key->comment = malloc(j+1); - if (key->comment) { - memcpy(key->comment, buf+i, j); - key->comment[j] = '\0'; + comment = malloc(j+1); + if (comment) { + memcpy(comment, buf+i, j); + comment[j] = '\0'; } i += j; + if (commentptr) + *commentptr = comment; + if (key) + key->comment = comment; + if (!key) { + return ciphertype != 0; + } /* * Decrypt remainder of buffer. @@ -108,24 +122,49 @@ int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) { return ret; } -/* - * See whether an RSA key is encrypted. - */ -int rsakey_encrypted(char *filename) { +int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) { FILE *fp; - unsigned char buf[1+sizeof(rsa_signature)]; - int len; + unsigned char buf[64]; fp = fopen(filename, "rb"); if (!fp) return 0; /* doesn't even exist */ - /* Slurp the whole file into a buffer. */ - len = fread(buf, 1, sizeof(buf), fp); + /* + * Read the first line of the file and see if it's a v1 private + * key file. + */ + if (fgets(buf, sizeof(buf), fp) && + !strcmp(buf, rsa_signature)) { + return loadrsakey_main(fp, key, NULL, passphrase); + } + + /* + * Otherwise, we have nothing. Return empty-handed. + */ fclose(fp); - if (len < sizeof(buf)) - return 0; /* not even valid */ - if (buf[sizeof(buf)-1]) - return 1; /* encrypted */ return 0; } + +/* + * See whether an RSA key is encrypted. Return its comment field as + * well. + */ +int rsakey_encrypted(char *filename, char **comment) { + FILE *fp; + unsigned char buf[64]; + + fp = fopen(filename, "rb"); + if (!fp) + return 0; /* doesn't even exist */ + + /* + * Read the first line of the file and see if it's a v1 private + * key file. + */ + if (fgets(buf, sizeof(buf), fp) && + !strcmp(buf, rsa_signature)) { + return loadrsakey_main(fp, NULL, comment, NULL); + } + return 0; /* wasn't the right kind of file */ +} diff --git a/sshrsa.c b/sshrsa.c index e44dce80..324fbd1d 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -43,9 +43,12 @@ int makekey(unsigned char *data, struct RSAKey *result, unsigned char *p = data; int i; - result->bits = 0; - for (i=0; i<4; i++) - result->bits = (result->bits << 8) + *p++; + if (result) { + result->bits = 0; + for (i=0; i<4; i++) + result->bits = (result->bits << 8) + *p++; + } else + p += 4; /* * order=0 means exponent then modulus (the keys sent by the @@ -54,12 +57,13 @@ int makekey(unsigned char *data, struct RSAKey *result, */ if (order == 0) - p += ssh1_read_bignum(p, &result->exponent); - result->bytes = (((p[0] << 8) + p[1]) + 7) / 8; + p += ssh1_read_bignum(p, result ? &result->exponent : NULL); + if (result) + result->bytes = (((p[0] << 8) + p[1]) + 7) / 8; if (keystr) *keystr = p+2; - p += ssh1_read_bignum(p, &result->modulus); + p += ssh1_read_bignum(p, result ? &result->modulus : NULL); if (order == 1) - p += ssh1_read_bignum(p, &result->exponent); + p += ssh1_read_bignum(p, result ? &result->exponent : NULL); return p - data; }