diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2014-09-16 03:22:09 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2014-09-16 17:02:33 +0200 |
commit | 1e0aa105faff1bd6987665506037f299b8e0e1cb (patch) | |
tree | 0e2597dda7b4b0dfc8bf1050f2abd2479b973fdc | |
parent | 286369a81fc2e1d77a7a134d5c140f023af1298b (diff) | |
download | libgit2-1e0aa105faff1bd6987665506037f299b8e0e1cb.tar.gz |
ssh: expose both hashes
The user may have the data hashed as MD5 or SHA-1, so we should provide
both types for consumption.
-rw-r--r-- | include/git2/transport.h | 25 | ||||
-rw-r--r-- | src/transports/ssh.c | 18 | ||||
-rw-r--r-- | tests/online/clone.c | 17 |
3 files changed, 38 insertions, 22 deletions
diff --git a/include/git2/transport.h b/include/git2/transport.h index 6c568be65..39df479c7 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -24,11 +24,11 @@ GIT_BEGIN_DECL * Type of SSH host fingerprint */ typedef enum { - /** MD5, 16 bytes */ - GIT_CERT_SSH_MD5, - /** SHA-1, 20 bytes */ - GIT_CERT_SSH_SHA1, -} git_cert_ssh_type ; + /** MD5 is available */ + GIT_CERT_SSH_MD5 = (1 << 0), + /** SHA-1 is available */ + GIT_CERT_SSH_SHA1 = (1 << 1), +} git_cert_ssh_t; /** * Hostkey information taken from libssh2 @@ -43,12 +43,19 @@ typedef struct { * A hostkey type from libssh2, either * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1` */ - git_cert_ssh_type type; + git_cert_ssh_t type; + + /** + * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will + * have the MD5 hash of the hostkey. + */ + unsigned char hash_md5[16]; + /** - * Hostkey hash. If the type is MD5, only the first 16 bytes - * will be set. + * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will + * have the SHA-1 hash of the hostkey. */ - unsigned char hash[20]; + unsigned char hash_sha1[20]; } git_cert_hostkey; /** diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 717565327..15a45ca86 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -487,17 +487,17 @@ static int _git_ssh_setup_conn( key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); if (key != NULL) { - cert.type = GIT_CERT_SSH_SHA1; - memcpy(&cert.hash, key, 20); - } else { - key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); - if (key != NULL) { - cert.type = GIT_CERT_SSH_MD5; - memcpy(&cert.hash, key, 16); - } + cert.type |= GIT_CERT_SSH_SHA1; + memcpy(&cert.hash_sha1, key, 20); } - if (key == NULL) { + key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); + if (key != NULL) { + cert.type |= GIT_CERT_SSH_MD5; + memcpy(&cert.hash_md5, key, 16); + } + + if (cert.type == 0) { giterr_set(GITERR_SSH, "unable to get the host key"); return -1; } diff --git a/tests/online/clone.c b/tests/online/clone.c index 0dd746a75..42682e8d8 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -488,13 +488,22 @@ int ssh_certificate_check(git_cert *cert, int valid, void *payload) cl_git_pass(git_oid_fromstrp(&expected, expected_str)); cl_assert_equal_i(GIT_CERT_HOSTKEY_LIBSSH2, cert->cert_type); - key = (git_cert_hostkey *) cert; - git_oid_fromraw(&actual, key->hash); - cl_assert_equal_i(GIT_CERT_SSH_SHA1, key->type); + /* + * We need to figure out how long our input was to check for + * the type. Here we abuse the fact that both hashes fit into + * our git_oid type. + */ + if (strlen(expected_str) == 32 && key->type & GIT_CERT_SSH_MD5) { + memcpy(&actual.id, key->hash_md5, 16); + } else if (strlen(expected_str) == 40 && key->type & GIT_CERT_SSH_SHA1) { + memcpy(&actual, key->hash_sha1, 20); + } else { + cl_fail("Cannot find a usable SSH hash"); + } - cl_assert(git_oid_equal(&expected, &actual)); + cl_assert(!memcmp(&expected, &actual, 20)); return GIT_EUSER; } |