mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 15:10:02 +00:00
SecureTransport: allow overriding a bad certificate
Do not automatically fail on a bad certificate, but let the caller decide. This means we don't need our switch on errors anymore but can return a string representation from the security framework.
This commit is contained in:
parent
24e53d2fba
commit
b7e1c81d1b
@ -17,17 +17,19 @@
|
|||||||
|
|
||||||
int stransport_error(OSStatus ret)
|
int stransport_error(OSStatus ret)
|
||||||
{
|
{
|
||||||
switch (ret) {
|
CFStringRef message;
|
||||||
case noErr:
|
|
||||||
|
if (ret == noErr) {
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
return 0;
|
return 0;
|
||||||
case errSSLXCertChainInvalid:
|
|
||||||
case errSSLBadCert:
|
|
||||||
return GIT_ECERTIFICATE;
|
|
||||||
default:
|
|
||||||
giterr_set(GITERR_NET, "SecureTransport error %d", ret);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message = SecCopyErrorMessageString(ret, NULL);
|
||||||
|
GITERR_CHECK_ALLOC(message);
|
||||||
|
|
||||||
|
giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
|
||||||
|
CFRelease(message);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -42,15 +44,43 @@ int stransport_connect(git_stream *stream)
|
|||||||
{
|
{
|
||||||
stransport_stream *st = (stransport_stream *) stream;
|
stransport_stream *st = (stransport_stream *) stream;
|
||||||
int error;
|
int error;
|
||||||
|
SecTrustRef trust = NULL;
|
||||||
|
SecTrustResultType sec_res;
|
||||||
OSStatus ret;
|
OSStatus ret;
|
||||||
|
|
||||||
if ((error = git_stream_connect(st->io)) < 0)
|
if ((error = git_stream_connect(st->io)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ((ret = SSLHandshake(st->ctx)) != noErr)
|
ret = SSLHandshake(st->ctx);
|
||||||
return stransport_error(ret);
|
if (ret != errSSLServerAuthCompleted) {
|
||||||
|
giterr_set(GITERR_SSL, "unexpected return value from ssl handshake %d", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
CFRelease(trust);
|
||||||
|
|
||||||
|
if (sec_res == kSecTrustResultInvalid || sec_res == kSecTrustResultOtherError) {
|
||||||
|
giterr_set(GITERR_SSL, "internal security trust error");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sec_res == kSecTrustResultDeny || sec_res == kSecTrustResultRecoverableTrustFailure ||
|
||||||
|
sec_res == kSecTrustResultFatalTrustFailure)
|
||||||
|
return GIT_ECERTIFICATE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
if (trust)
|
||||||
|
CFRelease(trust);
|
||||||
|
|
||||||
|
return stransport_error(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int stransport_certificate(git_cert **out, git_stream *stream)
|
int stransport_certificate(git_cert **out, git_stream *stream)
|
||||||
@ -58,15 +88,11 @@ int stransport_certificate(git_cert **out, git_stream *stream)
|
|||||||
stransport_stream *st = (stransport_stream *) stream;
|
stransport_stream *st = (stransport_stream *) stream;
|
||||||
SecTrustRef trust = NULL;
|
SecTrustRef trust = NULL;
|
||||||
SecCertificateRef sec_cert;
|
SecCertificateRef sec_cert;
|
||||||
SecTrustResultType sec_res;
|
|
||||||
OSStatus ret;
|
OSStatus ret;
|
||||||
|
|
||||||
if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
|
if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
|
||||||
return stransport_error(ret);
|
return stransport_error(ret);
|
||||||
|
|
||||||
if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
|
|
||||||
return stransport_error(ret);
|
|
||||||
|
|
||||||
sec_cert = SecTrustGetCertificateAtIndex(trust, 0);
|
sec_cert = SecTrustGetCertificateAtIndex(trust, 0);
|
||||||
st->der_data = SecCertificateCopyData(sec_cert);
|
st->der_data = SecCertificateCopyData(sec_cert);
|
||||||
CFRelease(trust);
|
CFRelease(trust);
|
||||||
@ -198,6 +224,7 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
|
|||||||
|
|
||||||
if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr ||
|
if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr ||
|
||||||
(ret = SSLSetConnection(st->ctx, st->io)) != noErr ||
|
(ret = SSLSetConnection(st->ctx, st->io)) != noErr ||
|
||||||
|
(ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr ||
|
||||||
(ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
|
(ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
|
||||||
git_stream_free((git_stream *)st);
|
git_stream_free((git_stream *)st);
|
||||||
return stransport_error(ret);
|
return stransport_error(ret);
|
||||||
|
Loading…
Reference in New Issue
Block a user