From 9213ed3b753fdd3bddf51d0fe5bbb246c2e061df Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Wed, 10 Jul 2024 14:42:23 -0400 Subject: [PATCH 1/5] Add myself to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 784bab3ee7d..f4e852357e5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -75,4 +75,5 @@ Tim Clem Tim Harder Torsten Bögershausen Trent Mick +Venus Xeon-Blonde Vicent Marti From 848f8d6803a593fb3b86ff3e825f8919b66f34e3 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Wed, 10 Jul 2024 15:24:08 -0400 Subject: [PATCH 2/5] Add more robust error handling to `SecureTransport` errors that occur on macos. --- src/libgit2/streams/stransport.c | 45 +++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/libgit2/streams/stransport.c b/src/libgit2/streams/stransport.c index 7a3585e246b..97fe0dace44 100644 --- a/src/libgit2/streams/stransport.c +++ b/src/libgit2/streams/stransport.c @@ -20,6 +20,9 @@ static int stransport_error(OSStatus ret) { CFStringRef message; + char * message_c_str; + /* Use a boolean to track if we allocate a buffer for message_c_str that we need to free later. */ + bool must_free = false; if (ret == noErr || ret == errSSLClosedGraceful) { git_error_clear(); @@ -30,11 +33,51 @@ static int stransport_error(OSStatus ret) message = SecCopyErrorMessageString(ret, NULL); GIT_ERROR_CHECK_ALLOC(message); - git_error_set(GIT_ERROR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8)); + /* Attempt to cheaply convert the CoreFoundations string ref to a C-style null terminated string. */ + message_c_str = (char *) CFStringGetCStringPtr(message, kCFStringEncodingUTF8); + + /* + CFStringGetCStringPtr can return null in some instances, where the message conversion is not cheap. + In these cases, it's more valuable to print the actual error message than to be cheap/efficient. + Call the (more expensive) + */ + if (message_c_str == NULL) { + /* + Before we allocate a buffer, get the size of the buffer we need to allocate (in bytes). + CFStringGetLength gives us the number of UTF-16 code-pairs (16 bit characters) in the string. + Multiply by 2 (since 2 8-bit bytes make a 16 bit char). Add one for the null terminator. + */ + long buffer_size = CFStringGetLength(message) * 2 + 1; + + /* Allocate the buffer. */ + message_c_str = malloc((size_t) buffer_size); + + /* + Convert the string into a C string using the buffer. + This returns a bool, which we check using this block. + If getting the CString failed (unlikely) we return early. + */ + if (!CFStringGetCString(message, message_c_str, buffer_size, kCFStringEncodingUTF8)) { + git_error_set(GIT_ERROR_NET, "CFStringGetCString error while handling a SecureTransport error"); + free(message_c_str); + CFRelease(message); + return -1; + } + } + + git_error_set(GIT_ERROR_NET, "SecureTransport error: %s", message_c_str); + + /* If we decided earlier that we would have to free the buffer allocation, do that. */ + if (must_free) { + free(message_c_str); + } + CFRelease(message); #else git_error_set(GIT_ERROR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret); GIT_UNUSED(message); + GIT_UNUSED(message_c_str); + GIT_UNUSED(must_free); #endif return -1; From c9f0178aac372079f74f09a6e78aafb732a3a762 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Wed, 10 Jul 2024 21:10:04 -0400 Subject: [PATCH 3/5] Fix missing boolean assignment --- src/libgit2/streams/stransport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libgit2/streams/stransport.c b/src/libgit2/streams/stransport.c index 97fe0dace44..b30cb8f3c1f 100644 --- a/src/libgit2/streams/stransport.c +++ b/src/libgit2/streams/stransport.c @@ -41,7 +41,7 @@ static int stransport_error(OSStatus ret) In these cases, it's more valuable to print the actual error message than to be cheap/efficient. Call the (more expensive) */ - if (message_c_str == NULL) { + if (( must_free = (message_c_str == NULL) )) { /* Before we allocate a buffer, get the size of the buffer we need to allocate (in bytes). CFStringGetLength gives us the number of UTF-16 code-pairs (16 bit characters) in the string. From 0db62c889c161d64e53a87562f5e6c3972f69db3 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Fri, 12 Jul 2024 16:28:06 -0400 Subject: [PATCH 4/5] Use `git__malloc` and `git__free` over `malloc` and `free` --- src/libgit2/streams/stransport.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libgit2/streams/stransport.c b/src/libgit2/streams/stransport.c index b30cb8f3c1f..7c06fd574ea 100644 --- a/src/libgit2/streams/stransport.c +++ b/src/libgit2/streams/stransport.c @@ -15,6 +15,8 @@ #include "git2/transport.h" +#include "../util/alloc.h" + #include "streams/socket.h" static int stransport_error(OSStatus ret) @@ -50,7 +52,8 @@ static int stransport_error(OSStatus ret) long buffer_size = CFStringGetLength(message) * 2 + 1; /* Allocate the buffer. */ - message_c_str = malloc((size_t) buffer_size); + message_c_str = git__malloc((size_t) buffer_size); + GIT_ERROR_CHECK_ALLOC(message_c_str); /* Convert the string into a C string using the buffer. @@ -59,7 +62,7 @@ static int stransport_error(OSStatus ret) */ if (!CFStringGetCString(message, message_c_str, buffer_size, kCFStringEncodingUTF8)) { git_error_set(GIT_ERROR_NET, "CFStringGetCString error while handling a SecureTransport error"); - free(message_c_str); + git__free(message_c_str); CFRelease(message); return -1; } @@ -69,7 +72,7 @@ static int stransport_error(OSStatus ret) /* If we decided earlier that we would have to free the buffer allocation, do that. */ if (must_free) { - free(message_c_str); + git__free(message_c_str); } CFRelease(message); From c77c598c606d0b30da9d563251aad5f353591d99 Mon Sep 17 00:00:00 2001 From: Venus Xeon-Blonde Date: Fri, 12 Jul 2024 17:46:28 -0400 Subject: [PATCH 5/5] Add tracing info to specific SecureTransport error caused by `SSLRead` returning -9806. --- src/libgit2/streams/stransport.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libgit2/streams/stransport.c b/src/libgit2/streams/stransport.c index 7c06fd574ea..9f45110ddd3 100644 --- a/src/libgit2/streams/stransport.c +++ b/src/libgit2/streams/stransport.c @@ -16,6 +16,7 @@ #include "git2/transport.h" #include "../util/alloc.h" +#include "../trace.h" #include "streams/socket.h" @@ -282,6 +283,18 @@ static ssize_t stransport_read(git_stream *stream, void *data, size_t len) OSStatus ret; if ((ret = SSLRead(st->ctx, data, len, &processed)) != noErr) { + /* + This specific SecureTransport error is not well described by SecCopyErrorMessageString, + so we should at least log something to the user here so that they might see this if + they're running into the same error I am and they have tracing enabled. + */ + if (ret == -9806) { + git_trace(GIT_TRACE_FATAL, "SecureTransport error: SSLRead error: SSLRead returned -9806 (connection closed via error)."); + git_trace(GIT_TRACE_FATAL, "This means that the remote terminated the SSL connection due to an error."); + git_trace(GIT_TRACE_FATAL, "This is *possibly* similar to https://stackoverflow.com/questions/26461966/osx-10-10-curl-post-to-https-url-gives-sslread-error"); + git_trace(GIT_TRACE_FATAL, "You may find some valuable information running `security error -9806` (on macOS)."); + } + if (st->error == GIT_TIMEOUT) return GIT_TIMEOUT;