SSH: fix CURLOPT_SSH_HOST_PUBLIC_KEY_MD5

When a 32 digit hex key is given as a hostkey md5 checksum, the code
would still run it against the knownhost check and not properly
acknowledge that the md5 should then be the sole guide for.

The verbose output now includes the evaluated MD5 hostkey checksum.

Some related source code comments were also updated.

Bug: http://curl.haxx.se/bug/view.cgi?id=3451592
Reported by: Reza Arbab
This commit is contained in:
Daniel Stenberg
2011-12-05 22:20:48 +01:00
parent c50dbf670f
commit 347f951c39

View File

@@ -644,10 +644,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct SSHPROTO *sftp_scp = data->state.proto.ssh; struct SSHPROTO *sftp_scp = data->state.proto.ssh;
struct ssh_conn *sshc = &conn->proto.sshc; struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET]; curl_socket_t sock = conn->sock[FIRSTSOCKET];
#ifdef CURL_LIBSSH2_DEBUG
const char *fingerprint; const char *fingerprint;
#endif /* CURL_LIBSSH2_DEBUG */ char md5buffer[33];
const char *host_public_key_md5;
char *new_readdir_line; char *new_readdir_line;
int rc = LIBSSH2_ERROR_NONE, i; int rc = LIBSSH2_ERROR_NONE, i;
int err; int err;
@@ -685,48 +683,40 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* fall-through */ /* fall-through */
case SSH_HOSTKEY: case SSH_HOSTKEY:
#ifdef CURL_LIBSSH2_DEBUG
/* /*
* Before we authenticate we should check the hostkey's fingerprint * Before we authenticate we should check the hostkey's fingerprint
* against our known hosts. How that is handled (reading from file, * against our known hosts. How that is handled (reading from file,
* whatever) is up to us. As for know not much is implemented, besides * whatever) is up to us.
* showing how to get the fingerprint.
*/ */
fingerprint = libssh2_hostkey_hash(sshc->ssh_session, fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
LIBSSH2_HOSTKEY_HASH_MD5); LIBSSH2_HOSTKEY_HASH_MD5);
/* The fingerprint points to static storage (!), don't free() it. */ /* The fingerprint points to static storage (!), don't free() it. */
infof(data, "Fingerprint: "); for(i = 0; i < 16; i++)
for(rc = 0; rc < 16; rc++) snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
infof(data, "%02X ", (unsigned char) fingerprint[rc]); infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
infof(data, "\n");
#endif /* CURL_LIBSSH2_DEBUG */
/* Before we authenticate we check the hostkey's MD5 fingerprint /* Before we authenticate we check the hostkey's MD5 fingerprint
* against a known fingerprint, if available. This implementation pulls * against a known fingerprint, if available.
* it from the curl option.
*/ */
if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] && if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) { strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) {
char buf[33]; if(!strequal(md5buffer,
host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
LIBSSH2_HOSTKEY_HASH_MD5);
for(i = 0; i < 16; i++)
snprintf(&buf[i*2], 3, "%02x",
(unsigned char) host_public_key_md5[i]);
if(!strequal(buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5])) {
failf(data, failf(data,
"Denied establishing ssh session: mismatch md5 fingerprint. " "Denied establishing ssh session: mismatch md5 fingerprint. "
"Remote %s is not equal to %s", "Remote %s is not equal to %s",
buf, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]); md5buffer, data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]);
state(conn, SSH_SESSION_FREE); state(conn, SSH_SESSION_FREE);
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION; result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
break;
} }
else
infof(data, "MD5 checksum match!\n");
/* as we already matched, we skip the check for known hosts */
} }
else
result = ssh_knownhost(conn);
result = ssh_knownhost(conn);
if(!result) if(!result)
state(conn, SSH_AUTHLIST); state(conn, SSH_AUTHLIST);
break; break;