Merge pull request #5704 from lhchavez/ssh-raw-certificate Also add the raw hostkey to `git_cert_hostkey`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
diff --git a/include/git2/cert.h b/include/git2/cert.h
index e8cd2d1..07ae8c9 100644
--- a/include/git2/cert.h
+++ b/include/git2/cert.h
@@ -80,8 +80,19 @@ typedef enum {
GIT_CERT_SSH_SHA1 = (1 << 1),
/** SHA-256 is available */
GIT_CERT_SSH_SHA256 = (1 << 2),
+ /** Raw hostkey is available */
+ GIT_CERT_SSH_RAW = (1 << 3),
} git_cert_ssh_t;
+typedef enum {
+ /** The raw key is of an unknown type. */
+ GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0,
+ /** The raw key is an RSA key. */
+ GIT_CERT_SSH_RAW_TYPE_RSA = 1,
+ /** The raw key is a DSS key. */
+ GIT_CERT_SSH_RAW_TYPE_DSS = 2,
+} git_cert_ssh_raw_type_t;
+
/**
* Hostkey information taken from libssh2
*/
@@ -89,28 +100,45 @@ typedef struct {
git_cert parent; /**< The parent cert */
/**
- * A hostkey type from libssh2, either
- * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1`
+ * A bitmask containing the available fields.
*/
git_cert_ssh_t type;
/**
- * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will
+ * 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 type has `GIT_CERT_SSH_SHA1` set, this will
+ * Hostkey hash. If `type` has `GIT_CERT_SSH_SHA1` set, this will
* have the SHA-1 hash of the hostkey.
*/
unsigned char hash_sha1[20];
/**
- * Hostkey hash. If type has `GIT_CERT_SSH_SHA256` set, this will
+ * Hostkey hash. If `type` has `GIT_CERT_SSH_SHA256` set, this will
* have the SHA-256 hash of the hostkey.
*/
unsigned char hash_sha256[32];
+
+ /**
+ * Raw hostkey type. If `type` has `GIT_CERT_SSH_RAW` set, this will
+ * have the type of the raw hostkey.
+ */
+ git_cert_ssh_raw_type_t raw_type;
+
+ /**
+ * Pointer to the raw hostkey. If `type` has `GIT_CERT_SSH_RAW` set,
+ * this will have the raw contents of the hostkey.
+ */
+ const char *hostkey;
+
+ /**
+ * Raw hostkey length. If `type` has `GIT_CERT_SSH_RAW` set, this will
+ * have the length of the raw contents of the hostkey.
+ */
+ size_t hostkey_len;
} git_cert_hostkey;
/**
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index b7efd5c..c33c08a 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -563,9 +563,28 @@ post_extract:
if (t->owner->certificate_check_cb != NULL) {
git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
const char *key;
+ size_t cert_len;
+ int cert_type;
cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;
+ key = libssh2_session_hostkey(session, &cert_len, &cert_type);
+ if (key != NULL) {
+ cert.type |= GIT_CERT_SSH_RAW;
+ cert.hostkey = key;
+ cert.hostkey_len = cert_len;
+ switch (cert_type) {
+ case LIBSSH2_HOSTKEY_TYPE_RSA:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_RSA;
+ break;
+ case LIBSSH2_HOSTKEY_TYPE_DSS:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_DSS;
+ break;
+ default:
+ cert.raw_type = GIT_CERT_SSH_RAW_TYPE_UNKNOWN;
+ }
+ }
+
#ifdef LIBSSH2_HOSTKEY_HASH_SHA256
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256);
if (key != NULL) {