winhttp: support optional client cert

parent 55975171
...@@ -864,42 +864,68 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked) ...@@ -864,42 +864,68 @@ static int do_send_request(winhttp_stream *s, size_t len, bool chunked)
static int send_request(winhttp_stream *s, size_t len, bool chunked) static int send_request(winhttp_stream *s, size_t len, bool chunked)
{ {
int request_failed = 0, cert_valid = 1, error = 0; int request_failed = 1, cert_valid, client_cert_requested, error, attempts = 0;
DWORD ignore_flags; DWORD ignore_flags, send_request_error;
git_error_clear(); git_error_clear();
if ((error = do_send_request(s, len, chunked)) < 0) {
if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
git_error_set(GIT_ERROR_OS, "failed to send request");
return -1;
}
request_failed = 1; while (request_failed && attempts++ < 3) {
cert_valid = 0; request_failed = 0;
} cert_valid = 1;
client_cert_requested = 0;
if ((error = do_send_request(s, len, chunked)) < 0) {
send_request_error = GetLastError();
request_failed = 1;
switch (send_request_error) {
case ERROR_WINHTTP_SECURE_FAILURE: {
cert_valid = 0;
break;
}
case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED: {
client_cert_requested = 1;
break;
}
default: {
git_error_set(GIT_ERROR_OS, "failed to send request");
return -1;
}
}
}
git_error_clear(); if (!request_failed || send_request_error == ERROR_WINHTTP_SECURE_FAILURE) {
if ((error = certificate_check(s, cert_valid)) < 0) { git_error_clear();
if (!git_error_last()) if ((error = certificate_check(s, cert_valid)) < 0) {
git_error_set(GIT_ERROR_OS, "user cancelled certificate check"); if (!git_error_last())
git_error_set(GIT_ERROR_OS, "user cancelled certificate check");
return error; return error;
} }
}
/* if neither the request nor the certificate check returned errors, we're done */ /* if neither the request nor the certificate check returned errors, we're done */
if (!request_failed) if (!request_failed)
return 0; return 0;
ignore_flags = no_check_cert_flags; if (!cert_valid) {
ignore_flags = no_check_cert_flags;
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
git_error_set(GIT_ERROR_OS, "failed to set security options");
return -1;
}
}
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) { if (client_cert_requested) {
git_error_set(GIT_ERROR_OS, "failed to set security options"); /*
return -1; * Client certificates are not supported, explicitly tell the server that
* (it's possible a client certificate was requested but is not required)
*/
if (!WinHttpSetOption(s->request, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0)) {
git_error_set(GIT_ERROR_OS, "failed to set client cert context");
return -1;
}
}
} }
if ((error = do_send_request(s, len, chunked)) < 0)
git_error_set(GIT_ERROR_OS, "failed to send request with unchecked certificate");
return error; return error;
} }
......
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