Commit ec1ce458 by Carlos Martín Nieto

http: send the DER-encoded cert to the callback

Instead of the parsed data, we can ask OpenSSL to give us the
DER-encoded version of the certificate, which the user can then parse
and validate.
parent 9b940586
...@@ -26,10 +26,9 @@ GIT_BEGIN_DECL ...@@ -26,10 +26,9 @@ GIT_BEGIN_DECL
typedef enum git_cert_t { typedef enum git_cert_t {
/** /**
* The `data` argument to the callback will be a pointer to * The `data` argument to the callback will be a pointer to
* OpenSSL's `X509` structure. * the DER-encoded data.
*/ */
GIT_CERT_X509_OPENSSL, GIT_CERT_X509,
GIT_CERT_X509_WINHTTP,
/** /**
* The `data` argument to the callback will be a pointer to a * The `data` argument to the callback will be a pointer to a
* `git_cert_hostkey` structure. * `git_cert_hostkey` structure.
......
...@@ -261,9 +261,10 @@ typedef enum git_cert_t git_cert_t; ...@@ -261,9 +261,10 @@ typedef enum git_cert_t git_cert_t;
* *
* @param type The type of certificate or host info, SSH or X.509 * @param type The type of certificate or host info, SSH or X.509
* @param data The data for the certificate or host info * @param data The data for the certificate or host info
* @param len The size of the certificate or host info
* @param payload Payload provided by the caller * @param payload Payload provided by the caller
*/ */
typedef int (*git_transport_certificate_check_cb)(git_cert_t type, void *data, void *payload); typedef int (*git_transport_certificate_check_cb)(git_cert_t type, void *data, size_t len, void *payload);
/** /**
* Opaque structure representing a submodule. * Opaque structure representing a submodule.
......
...@@ -555,9 +555,32 @@ static int http_connect(http_subtransport *t) ...@@ -555,9 +555,32 @@ static int http_connect(http_subtransport *t)
#ifdef GIT_SSL #ifdef GIT_SSL
if (error == GIT_ECERTIFICATE && t->owner->certificate_check_cb != NULL) { if (error == GIT_ECERTIFICATE && t->owner->certificate_check_cb != NULL) {
X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl); X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl);
int allow; int allow, len;
unsigned char *guard, *encoded_cert;
/* Retrieve the length of the certificate first */
len = i2d_X509(cert, NULL);
if (len < 0) {
giterr_set(GITERR_NET, "failed to retrieve certificate information");
return -1;
}
encoded_cert = git__malloc(len);
GITERR_CHECK_ALLOC(encoded_cert);
/* i2d_X509 makes 'copy' point to just after the data */
guard = encoded_cert;
len = i2d_X509(cert, &guard);
if (len < 0) {
git__free(encoded_cert);
giterr_set(GITERR_NET, "failed to retrieve certificate information");
return -1;
}
allow = t->owner->certificate_check_cb(GIT_CERT_X509, encoded_cert, len, t->owner->message_cb_payload);
git__free(encoded_cert);
allow = t->owner->certificate_check_cb(GIT_CERT_X509_OPENSSL, cert, t->owner->message_cb_payload);
if (allow < 0) { if (allow < 0) {
error = allow; error = allow;
} else if (!allow) { } else if (!allow) {
......
...@@ -521,16 +521,19 @@ static int _git_ssh_setup_conn( ...@@ -521,16 +521,19 @@ static int _git_ssh_setup_conn(
git_cert_hostkey cert; git_cert_hostkey cert;
const char *key; const char *key;
int allow; int allow;
size_t certlen;
cert.type = LIBSSH2_HOSTKEY_HASH_SHA1; cert.type = LIBSSH2_HOSTKEY_HASH_SHA1;
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
if (key != NULL) { if (key != NULL) {
memcpy(&cert.hash, key, 20); certlen = 20;
memcpy(&cert.hash, key, certlen);
} else { } else {
cert.type = LIBSSH2_HOSTKEY_HASH_MD5; cert.type = LIBSSH2_HOSTKEY_HASH_MD5;
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
certlen = 16;
if (key != NULL) if (key != NULL)
memcpy(&cert.hash, key, 16); memcpy(&cert.hash, key, certlen);
} }
if (key == NULL) { if (key == NULL) {
...@@ -538,7 +541,7 @@ static int _git_ssh_setup_conn( ...@@ -538,7 +541,7 @@ static int _git_ssh_setup_conn(
return -1; return -1;
} }
allow = t->owner->certificate_check_cb(GIT_CERT_HOSTKEY_LIBSSH2, &cert, t->owner->message_cb_payload); allow = t->owner->certificate_check_cb(GIT_CERT_HOSTKEY_LIBSSH2, &cert, certlen, t->owner->message_cb_payload);
if (allow < 0) { if (allow < 0) {
error = allow; error = allow;
goto on_error; goto on_error;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment