winhttp: bring together request sending We need to call WinHttpSendRequest() in three different places. Unify all in a single function to have a single place for the certificate check.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index e6bd1c9..14afce2 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -212,6 +212,10 @@ static int certificate_check(winhttp_stream *s, int valid)
PCERT_CONTEXT cert_ctx;
DWORD cert_ctx_size = sizeof(cert_ctx);
+ /* If there is no override, we should fail if WinHTTP doesn't think it's fine */
+ if (t->owner->certificate_check_cb == NULL && !valid)
+ return GIT_ECERTIFICATE;
+
if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl)
return 0;
@@ -411,8 +415,6 @@ static int winhttp_stream_connect(winhttp_stream *s)
goto on_error;
}
- /* set up the certificate failure callback */
-
/* We've done everything up to calling WinHttpSendRequest. */
error = 0;
@@ -556,6 +558,38 @@ on_error:
return error;
}
+static int send_request(winhttp_stream *s, size_t len, int ignore_length)
+{
+ int request_failed = 0, cert_valid = 1, error = 0;
+
+ if (ignore_length) {
+ if (!WinHttpSendRequest(s->request,
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ WINHTTP_NO_REQUEST_DATA, 0,
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
+ request_failed = 1;
+ }
+ } else {
+ if (!WinHttpSendRequest(s->request,
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+ WINHTTP_NO_REQUEST_DATA, 0,
+ len, 0)) {
+ request_failed = 1;
+ }
+ }
+
+ if (request_failed && GetLastError() == ERROR_WINHTTP_SECURE_FAILURE)
+ cert_valid = 0;
+
+ giterr_clear();
+ if ((error = certificate_check(s, cert_valid)) < 0) {
+ if (!giterr_last())
+ giterr_set(GITERR_OS, "failed to send request");
+ }
+
+ return error;
+}
+
static int winhttp_stream_read(
git_smart_subtransport_stream *stream,
char *buffer,
@@ -583,22 +617,16 @@ replay:
DWORD status_code, status_code_length, content_type_length, bytes_written;
char expected_content_type_8[MAX_CONTENT_TYPE_LEN];
wchar_t expected_content_type[MAX_CONTENT_TYPE_LEN], content_type[MAX_CONTENT_TYPE_LEN];
+ int request_failed = 0, cert_valid = 1;
if (!s->sent_request) {
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- s->post_body_len, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+
+ if ((error = send_request(s, s->post_body_len, 0)) < 0)
+ return error;
s->sent_request = 1;
}
- if ((error = certificate_check(s, 1)) < 0)
- return error;
-
if (s->chunked) {
assert(s->verb == post_verb);
@@ -859,19 +887,11 @@ static int winhttp_stream_write_single(
return -1;
}
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- (DWORD)len, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+ if ((error = send_request(s, len, 0)) < 0)
+ return error;
s->sent_request = 1;
- if ((error = certificate_check(s, 1)) < 0)
- return error;
-
if (!WinHttpWriteData(s->request,
(LPCVOID)buffer,
(DWORD)len,
@@ -1005,20 +1025,12 @@ static int winhttp_stream_write_chunked(
return -1;
}
- if (!WinHttpSendRequest(s->request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
- giterr_set(GITERR_OS, "Failed to send request");
- return -1;
- }
+ if ((error = send_request(s, 0, 1)) < 0)
+ return error;
s->sent_request = 1;
}
- if ((error = certificate_check(s, 1)) < 0)
- return error;
-
if (len > CACHED_POST_BODY_BUF_SIZE) {
/* Flush, if necessary */
if (s->chunk_buffer_len > 0) {