mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 23:19:28 +00:00
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.
This commit is contained in:
parent
9b9405865e
commit
ec1ce4584a
@ -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;
|
|||||||
*
|
*
|
||||||
* @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)
|
|||||||
#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) {
|
||||||
|
@ -517,28 +517,31 @@ static int _git_ssh_setup_conn(
|
|||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (t->owner->certificate_check_cb != NULL) {
|
if (t->owner->certificate_check_cb != NULL) {
|
||||||
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;
|
||||||
} else {
|
memcpy(&cert.hash, key, certlen);
|
||||||
cert.type = LIBSSH2_HOSTKEY_HASH_MD5;
|
} else {
|
||||||
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
cert.type = LIBSSH2_HOSTKEY_HASH_MD5;
|
||||||
if (key != NULL)
|
key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
|
||||||
memcpy(&cert.hash, key, 16);
|
certlen = 16;
|
||||||
}
|
if (key != NULL)
|
||||||
|
memcpy(&cert.hash, key, certlen);
|
||||||
|
}
|
||||||
|
|
||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
giterr_set(GITERR_SSH, "unable to get the host key");
|
giterr_set(GITERR_SSH, "unable to get the host key");
|
||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user