1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

The authentication diagnostics in SSH2 should now be better.

Additionally, the ability to switch usernames if you mistype the
first one has been restored (although it didn't actually work
because OpenSSH didn't feel like playing; patch submitted :-).

[originally from svn r975]
This commit is contained in:
Simon Tatham 2001-03-03 13:53:44 +00:00
parent 146b5f5f6e
commit deccfaa3ef

181
ssh.c
View File

@ -348,6 +348,10 @@ static void c_write (char *buf, int len) {
from_backend(1, buf, len);
}
static void c_write_str (char *buf) {
c_write(buf, strlen(buf));
}
/*
* Collect incoming data in the incoming packet buffer.
* Decipher and verify the packet when it is completely read.
@ -1394,12 +1398,12 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
case CIPHER_DES: cipher_type = SSH_CIPHER_DES; break;
case CIPHER_3DES: cipher_type = SSH_CIPHER_3DES; break;
case CIPHER_AES:
c_write("AES not supported in SSH1, falling back to 3DES\r\n", 49);
c_write_str("AES not supported in SSH1, falling back to 3DES\r\n");
cipher_type = SSH_CIPHER_3DES;
break;
}
if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {
c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);
c_write_str("Selected cipher not supported, falling back to 3DES\r\n");
cipher_type = SSH_CIPHER_3DES;
}
switch (cipher_type) {
@ -1439,7 +1443,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
static int pos = 0;
static char c;
if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
c_write("login as: ", 10);
c_write_str("login as: ");
ssh_send_ok = 1;
while (pos >= 0) {
crWaitUntil(!ispkt);
@ -1450,13 +1454,13 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
break;
case 8: case 127:
if (pos > 0) {
c_write("\b \b", 3);
c_write_str("\b \b");
pos--;
}
break;
case 21: case 27:
while (pos > 0) {
c_write("\b \b", 3);
c_write_str("\b \b");
pos--;
}
break;
@ -1473,7 +1477,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
break;
}
}
c_write("\r\n", 2);
c_write_str("\r\n");
username[strcspn(username, "\n\r")] = '\0';
} else {
strncpy(username, cfg.username, 99);
@ -1488,7 +1492,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
if (flags & FLAG_INTERACTIVE &&
(!((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)))) {
strcat(userlog, "\r\n");
c_write(userlog, strlen(userlog));
c_write_str(userlog);
}
}
}
@ -1585,10 +1589,9 @@ static int do_ssh1_login(unsigned char *in, int inlen, int 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_str("Authenticated using RSA key \"");
c_write(commentp, commentlen);
c_write("\" from agent\r\n", 14);
c_write_str("\" from agent\r\n");
}
authed = TRUE;
} else
@ -1624,7 +1627,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int 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);
c_write_str("TIS authentication refused.\r\n");
} else {
int challengelen = ((pktin.body[0] << 24) |
(pktin.body[1] << 16) |
@ -1646,7 +1649,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt);
if (pktin.type != SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
logevent("CryptoCard authentication declined");
c_write("CryptoCard authentication refused.\r\n", 29);
c_write_str("CryptoCard authentication refused.\r\n");
} else {
int challengelen = ((pktin.body[0] << 24) |
(pktin.body[1] << 16) |
@ -1668,10 +1671,10 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
if (pwpkt_type == SSH1_CMSG_AUTH_RSA) {
char *comment = NULL;
if (flags & FLAG_VERBOSE)
c_write("Trying public key authentication.\r\n", 35);
c_write_str("Trying public key authentication.\r\n");
if (!rsakey_encrypted(cfg.keyfile, &comment)) {
if (flags & FLAG_VERBOSE)
c_write("No passphrase required.\r\n", 25);
c_write_str("No passphrase required.\r\n");
goto tryauth;
}
sprintf(prompt, "Passphrase for key \"%.100s\": ", comment);
@ -1691,7 +1694,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
crReturn(1);
}
} else {
c_write(prompt, strlen(prompt));
c_write_str(prompt);
pos = 0;
ssh_send_ok = 1;
while (pos >= 0) {
@ -1719,7 +1722,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
break;
}
}
c_write("\r\n", 2);
c_write_str("\r\n");
}
tryauth:
@ -1736,13 +1739,13 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
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);
c_write_str("Couldn't load public key from ");
c_write_str(cfg.keyfile);
c_write_str(".\r\n");
continue; /* go and try password */
}
if (i == -1) {
c_write("Wrong passphrase.\r\n", 19);
c_write_str("Wrong passphrase.\r\n");
tried_publickey = 0;
continue; /* try again */
}
@ -1755,7 +1758,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
crWaitUntil(ispkt);
if (pktin.type == SSH1_SMSG_FAILURE) {
c_write("Server refused our public key.\r\n", 32);
c_write_str("Server refused our public key.\r\n");
continue; /* go and try password */
}
if (pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
@ -1781,8 +1784,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("Failed to authenticate with our public key.\r\n",
45);
c_write_str("Failed to authenticate with our public key.\r\n");
continue; /* go and try password */
} else if (pktin.type != SSH1_SMSG_SUCCESS) {
bombout(("Bizarre response to RSA authentication response"));
@ -1798,7 +1800,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("Access denied\r\n", 15);
c_write_str("Access denied\r\n");
logevent("Authentication refused");
} else if (pktin.type == SSH1_MSG_DISCONNECT) {
logevent("Received disconnect request");
@ -1904,7 +1906,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
bombout(("Protocol confusion"));
crReturnV;
} else if (pktin.type == SSH1_SMSG_FAILURE) {
c_write("Server refused to allocate pty\r\n", 32);
c_write_str("Server refused to allocate pty\r\n");
ssh_editing = ssh_echoing = 1;
}
logevent("Allocated pty");
@ -1919,7 +1921,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
bombout(("Protocol confusion"));
crReturnV;
} else if (pktin.type == SSH1_SMSG_FAILURE) {
c_write("Server refused to compress\r\n", 32);
c_write_str("Server refused to compress\r\n");
}
logevent("Started compression");
ssh1_compressing = TRUE;
@ -2629,7 +2631,15 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
static enum {
AUTH_INVALID, AUTH_PUBLICKEY_AGENT, AUTH_PUBLICKEY_FILE, AUTH_PASSWORD
} method;
static enum {
AUTH_TYPE_NONE,
AUTH_TYPE_PUBLICKEY,
AUTH_TYPE_PUBLICKEY_OFFER_LOUD,
AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
AUTH_TYPE_PASSWORD
} type;
static int gotit, need_pw, can_pubkey, can_passwd, tried_pubkey_config;
static int we_are_in;
static char username[100];
static char pwprompt[200];
static char password[100];
@ -2649,14 +2659,39 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
}
/*
* Get a username.
* We repeat this whole loop, including the username prompt,
* until we manage a successful authentication. If the user
* types the wrong _password_, they are sent back to the
* beginning to try another username. (If they specify a
* username in the config, they are never asked, even if they
* do give a wrong password.)
*
* I think this best serves the needs of
*
* - the people who have no configuration, no keys, and just
* want to try repeated (username,password) pairs until they
* type both correctly
*
* - people who have keys and configuration but occasionally
* need to fall back to passwords
*
* - people with a key held in Pageant, who might not have
* logged in to a particular machine before; so they want to
* type a username, and then _either_ their key will be
* accepted, _or_ they will type a password. If they mistype
* the username they will want to be able to get back and
* retype it!
*/
{
static int pos = 0;
do {
static int pos;
static char c;
/*
* Get a username.
*/
pos = 0;
if ((flags & FLAG_INTERACTIVE) && !*cfg.username) {
c_write("login as: ", 10);
c_write_str("login as: ");
ssh_send_ok = 1;
while (pos >= 0) {
crWaitUntilV(!ispkt);
@ -2667,13 +2702,13 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
break;
case 8: case 127:
if (pos > 0) {
c_write("\b \b", 3);
c_write_str("\b \b");
pos--;
}
break;
case 21: case 27:
while (pos > 0) {
c_write("\b \b", 3);
c_write_str("\b \b");
pos--;
}
break;
@ -2690,7 +2725,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
break;
}
}
c_write("\r\n", 2);
c_write_str("\r\n");
username[strcspn(username, "\n\r")] = '\0';
} else {
char stuff[200];
@ -2698,8 +2733,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
username[99] = '\0';
if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
sprintf(stuff, "Using username \"%s\".\r\n", username);
c_write(stuff, strlen(stuff));
}
c_write_str(stuff);
}
}
@ -2713,8 +2747,11 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
ssh2_pkt_addstring("ssh-connection"); /* service requested */
ssh2_pkt_addstring("none"); /* method */
ssh2_pkt_send();
logevent("Attempting null authentication");
type = AUTH_TYPE_NONE;
gotit = FALSE;
we_are_in = FALSE;
tried_pubkey_config = FALSE;
while (1) {
/*
@ -2728,6 +2765,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
}
if (pktin.type == SSH2_MSG_USERAUTH_SUCCESS) {
logevent("Access granted");
we_are_in = TRUE;
break;
}
@ -2749,13 +2787,44 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
ssh2_pkt_getstring(&methods, &methlen);
if (!ssh2_pkt_getbool()) {
/*
* FIXME: these messages are often inappropriate.
* We have received an unequivocal Access
* Denied. This can translate to a variety of
* messages:
*
* - if we'd just tried "none" authentication,
* it's not worth printing anything at all
*
* - if we'd just tried a public key _offer_,
* the message should be "Server refused our
* key" (or no message at all if the key
* came from Pageant)
*
* - if we'd just tried anything else, the
* message really should be "Access denied".
*
* Additionally, if we'd just tried password
* authentication, we should break out of this
* whole loop so as to go back to the username
* prompt.
*/
c_write("Access denied\r\n", 15);
logevent("Access denied");
if (type == AUTH_TYPE_NONE) {
/* do nothing */
} else if (type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD ||
type == AUTH_TYPE_PUBLICKEY_OFFER_QUIET) {
if (type == AUTH_TYPE_PUBLICKEY_OFFER_LOUD)
c_write_str("Server refused our key\r\n");
logevent("Server refused public key");
} else {
c_write("Authentication partially successful\r\n", 37);
logevent("Authentication partially successful");
c_write_str("Access denied\r\n");
logevent("Access denied");
if (type == AUTH_TYPE_PASSWORD) {
we_are_in = FALSE;
break;
}
}
} else {
c_write_str("Further authentication required\r\n");
logevent("Further authentication required");
}
can_pubkey = in_commasep_string("publickey", methods, methlen);
@ -2794,6 +2863,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
crWaitUntilV(ispkt);
if (pktin.type != SSH2_MSG_USERAUTH_PK_OK) {
gotit = TRUE;
type = AUTH_TYPE_PUBLICKEY_OFFER_LOUD;
continue; /* key refused; give up on it */
}
@ -2808,6 +2878,9 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
} else {
need_pw = FALSE;
}
c_write_str("Authenticating with public key \"");
c_write_str(comment);
c_write_str("\"\r\n");
method = AUTH_PUBLICKEY_FILE;
}
}
@ -2835,7 +2908,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
static int pos = 0;
static char c;
c_write(pwprompt, strlen(pwprompt));
c_write_str(pwprompt);
ssh_send_ok = 1;
pos = 0;
@ -2864,7 +2937,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
break;
}
}
c_write("\r\n", 2);
c_write_str("\r\n");
}
}
@ -2875,24 +2948,21 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
struct ssh2_userkey *key;
key = ssh2_load_userkey(cfg.keyfile, password);
if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
if (key == SSH2_WRONG_PASSPHRASE) {
c_write("Wrong passphrase\r\n", 18);
c_write_str("Wrong passphrase\r\n");
tried_pubkey_config = FALSE;
/* Send a spurious AUTH_NONE to return to the top. */
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(username);
ssh2_pkt_addstring("ssh-connection"); /* service requested */
ssh2_pkt_addstring("none"); /* method */
ssh2_pkt_send();
} else if (key == NULL) {
c_write("Unable to load private key\r\n",28);
} else {
c_write_str("Unable to load private key\r\n");
tried_pubkey_config = TRUE;
}
/* Send a spurious AUTH_NONE to return to the top. */
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(username);
ssh2_pkt_addstring("ssh-connection"); /* service requested */
ssh2_pkt_addstring("none"); /* method */
ssh2_pkt_send();
type = AUTH_TYPE_NONE;
} else {
unsigned char *blob, *sigdata;
int blob_len, sigdata_len;
@ -2933,6 +3003,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
sfree(sigdata);
ssh2_pkt_send();
type = AUTH_TYPE_PUBLICKEY;
}
} else if (method == AUTH_PASSWORD) {
/*
@ -2975,8 +3046,9 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
ssh2_pkt_defer();
}
ssh2_pkt_defersend();
type = AUTH_TYPE_PASSWORD;
} else {
c_write("No supported authentication methods left to try!\r\n", 50);
c_write_str("No supported authentication methods left to try!\r\n");
logevent("No supported authentications offered. Disconnecting");
ssh2_pkt_init(SSH2_MSG_DISCONNECT);
ssh2_pkt_adduint32(SSH2_DISCONNECT_BY_APPLICATION);
@ -2987,6 +3059,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
crReturnV;
}
}
} while (!we_are_in);
/*
* Now we're authenticated for the connection protocol. The
@ -3102,7 +3175,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
bombout(("Server got confused by pty request"));
crReturnV;
}
c_write("Server refused to allocate pty\r\n", 32);
c_write_str("Server refused to allocate pty\r\n");
ssh_editing = ssh_echoing = 1;
} else {
logevent("Allocated pty");