Commit a2e6e0ea by Edward Thomson

transport: allow cred/cert callbacks to return GIT_PASSTHROUGH

Allow credential and certificate checking callbacks to return
GIT_PASSTHROUGH, indicating that they do not want to act.
Introduce this to support in both the http and ssh callbacks.
Additionally, enable the same mechanism for certificate validation.

This is most useful to disambiguate any meaning in the publicly exposed
credential and certificate functions (`git_transport_smart_credentials`
and `git_transport_smart_certificate_check`) but it may be more
generally useful for callers to be able to defer back to libgit2.
parent 8ee10098
...@@ -52,7 +52,7 @@ typedef enum { ...@@ -52,7 +52,7 @@ typedef enum {
GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */ GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */
GIT_EMERGECONFLICT = -24, /**< A merge conflict exists and cannot continue */ GIT_EMERGECONFLICT = -24, /**< A merge conflict exists and cannot continue */
GIT_PASSTHROUGH = -30, /**< Internal only */ GIT_PASSTHROUGH = -30, /**< A user-configured callback refused to act */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */ GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
GIT_RETRY = -32, /**< Internal only */ GIT_RETRY = -32, /**< Internal only */
GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */ GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
......
...@@ -330,6 +330,9 @@ typedef struct { ...@@ -330,6 +330,9 @@ typedef struct {
* this certificate is valid * this certificate is valid
* @param host Hostname of the host libgit2 connected to * @param host Hostname of the host libgit2 connected to
* @param payload Payload provided by the caller * @param payload Payload provided by the caller
* @return 0 to proceed with the connection, < 0 to fail the connection
* or > 0 to indicate that the callback refused to act and that
* the existing validity determination should be honored
*/ */
typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload); typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, const char *host, void *payload);
......
...@@ -367,6 +367,7 @@ static int on_headers_complete(http_parser *parser) ...@@ -367,6 +367,7 @@ static int on_headers_complete(http_parser *parser)
allowed_auth_types, allowed_auth_types,
t->owner->cred_acquire_payload); t->owner->cred_acquire_payload);
/* treat GIT_PASSTHROUGH as if callback isn't set */
if (error == GIT_PASSTHROUGH) { if (error == GIT_PASSTHROUGH) {
no_callback = 1; no_callback = 1;
} else if (error < 0) { } else if (error < 0) {
...@@ -635,6 +636,9 @@ static int http_connect(http_subtransport *t) ...@@ -635,6 +636,9 @@ static int http_connect(http_subtransport *t)
giterr_clear(); giterr_clear();
error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload); error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
if (error == GIT_PASSTHROUGH)
error = is_valid ? 0 : GIT_ECERTIFICATE;
if (error < 0) { if (error < 0) {
if (!giterr_last()) if (!giterr_last())
giterr_set(GITERR_NET, "user cancelled certificate check"); giterr_set(GITERR_NET, "user cancelled certificate check");
......
...@@ -447,11 +447,11 @@ static int request_creds(git_cred **out, ssh_subtransport *t, const char *user, ...@@ -447,11 +447,11 @@ static int request_creds(git_cred **out, ssh_subtransport *t, const char *user,
error = t->owner->cred_acquire_cb(&cred, t->owner->url, user, auth_methods, error = t->owner->cred_acquire_cb(&cred, t->owner->url, user, auth_methods,
t->owner->cred_acquire_payload); t->owner->cred_acquire_payload);
if (error == GIT_PASSTHROUGH) if (error == GIT_PASSTHROUGH) {
no_callback = 1; no_callback = 1;
else if (error < 0) } else if (error < 0) {
return error; return error;
else if (!cred) { } else if (!cred) {
giterr_set(GITERR_SSH, "callback failed to initialize SSH credentials"); giterr_set(GITERR_SSH, "callback failed to initialize SSH credentials");
return -1; return -1;
} }
...@@ -584,7 +584,8 @@ post_extract: ...@@ -584,7 +584,8 @@ post_extract:
cert_ptr = &cert; cert_ptr = &cert;
error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload); error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload);
if (error < 0) {
if (error < 0 && error != GIT_PASSTHROUGH) {
if (!giterr_last()) if (!giterr_last())
giterr_set(GITERR_NET, "user cancelled hostkey check"); giterr_set(GITERR_NET, "user cancelled hostkey check");
......
...@@ -228,7 +228,7 @@ static int fallback_cred_acquire_cb( ...@@ -228,7 +228,7 @@ static int fallback_cred_acquire_cb(
} }
hCoInitResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); hCoInitResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hCoInitResult) || hCoInitResult == RPC_E_CHANGED_MODE) { if (SUCCEEDED(hCoInitResult) || hCoInitResult == RPC_E_CHANGED_MODE) {
IInternetSecurityManager* pISM; IInternetSecurityManager* pISM;
...@@ -295,6 +295,9 @@ static int certificate_check(winhttp_stream *s, int valid) ...@@ -295,6 +295,9 @@ static int certificate_check(winhttp_stream *s, int valid)
error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->connection_data.host, t->owner->message_cb_payload); error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->connection_data.host, t->owner->message_cb_payload);
CertFreeCertificateContext(cert_ctx); CertFreeCertificateContext(cert_ctx);
if (error == GIT_PASSTHROUGH)
error = valid ? 0 : GIT_ECERTIFICATE;
if (error < 0 && !giterr_last()) if (error < 0 && !giterr_last())
giterr_set(GITERR_NET, "user cancelled certificate check"); giterr_set(GITERR_NET, "user cancelled certificate check");
......
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