mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-10-31 07:41:33 +00:00 
			
		
		
		
	winhttp: credential check on successful connect
On successful connection, still ask the user whether they accept the server's certificate, indicating that WinHTTP would let it though.
This commit is contained in:
		
							parent
							
								
									23ca0ad5eb
								
							
						
					
					
						commit
						08545d366b
					
				| @ -16,6 +16,8 @@ | ||||
| #include "remote.h" | ||||
| #include "repository.h" | ||||
| 
 | ||||
| #include <wincrypt.h> | ||||
| #pragma comment(lib, "crypt32") | ||||
| #include <winhttp.h> | ||||
| #pragma comment(lib, "winhttp") | ||||
| 
 | ||||
| @ -203,6 +205,31 @@ static int fallback_cred_acquire_cb( | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static int certificate_check(winhttp_stream *s, int valid) | ||||
| { | ||||
| 	int error; | ||||
| 	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); | ||||
| 	PCERT_CONTEXT cert_ctx; | ||||
| 	DWORD cert_ctx_size = sizeof(cert_ctx); | ||||
| 
 | ||||
| 	if (t->owner->certificate_check_cb == NULL) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	if (!WinHttpQueryOption(s->request, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert_ctx, &cert_ctx_size)) { | ||||
| 		giterr_set(GITERR_OS, "failed to get server certificate"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	giterr_clear(); | ||||
| 	error = t->owner->certificate_check_cb(GIT_CERT_X509, cert_ctx->pbCertEncoded, cert_ctx->cbCertEncoded, valid, t->owner->cred_acquire_payload); | ||||
| 	CertFreeCertificateContext(cert_ctx); | ||||
| 
 | ||||
| 	if (error < 0 && !giterr_last()) | ||||
| 		giterr_set(GITERR_NET, "user cancelled certificate check"); | ||||
| 
 | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static int winhttp_stream_connect(winhttp_stream *s) | ||||
| { | ||||
| 	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); | ||||
| @ -384,6 +411,8 @@ 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; | ||||
| @ -537,6 +566,7 @@ static int winhttp_stream_read( | ||||
| 	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); | ||||
| 	DWORD dw_bytes_read; | ||||
| 	char replay_count = 0; | ||||
| 	int error; | ||||
| 
 | ||||
| replay: | ||||
| 	/* Enforce a reasonable cap on the number of replays */ | ||||
| @ -566,6 +596,9 @@ replay: | ||||
| 			s->sent_request = 1; | ||||
| 		} | ||||
| 
 | ||||
| 		if ((error = certificate_check(s, 1)) < 0) | ||||
| 			return error; | ||||
| 
 | ||||
| 		if (s->chunked) { | ||||
| 			assert(s->verb == post_verb); | ||||
| 
 | ||||
| @ -815,6 +848,7 @@ static int winhttp_stream_write_single( | ||||
| 	winhttp_stream *s = (winhttp_stream *)stream; | ||||
| 	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); | ||||
| 	DWORD bytes_written; | ||||
| 	int error; | ||||
| 
 | ||||
| 	if (!s->request && winhttp_stream_connect(s) < 0) | ||||
| 		return -1; | ||||
| @ -835,6 +869,9 @@ static int winhttp_stream_write_single( | ||||
| 
 | ||||
| 	s->sent_request = 1; | ||||
| 
 | ||||
| 	if ((error = certificate_check(s, 1)) < 0) | ||||
| 		return error; | ||||
| 
 | ||||
| 	if (!WinHttpWriteData(s->request, | ||||
| 			(LPCVOID)buffer, | ||||
| 			(DWORD)len, | ||||
| @ -954,6 +991,7 @@ static int winhttp_stream_write_chunked( | ||||
| { | ||||
| 	winhttp_stream *s = (winhttp_stream *)stream; | ||||
| 	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); | ||||
| 	int error; | ||||
| 
 | ||||
| 	if (!s->request && winhttp_stream_connect(s) < 0) | ||||
| 		return -1; | ||||
| @ -978,6 +1016,9 @@ static int winhttp_stream_write_chunked( | ||||
| 		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) { | ||||
|  | ||||
| @ -485,11 +485,13 @@ void test_online_clone__certificate_invalid(void) | ||||
| { | ||||
| 	g_options.remote_callbacks.certificate_check = fail_certificate_check; | ||||
| 
 | ||||
| 	cl_git_fail_with(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options), | ||||
| 	cl_git_fail_with(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options), | ||||
| 		GIT_ECERTIFICATE); | ||||
| 
 | ||||
| #ifdef GIT_SSH | ||||
| 	cl_git_fail_with(git_clone(&g_repo, "ssh://github.com/libgit2/TestGitRepository", "./foo", &g_options), | ||||
| 		GIT_ECERTIFICATE); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static int succeed_certificate_check(git_cert_t type, void *data, size_t len, int valid, void *payload) | ||||
| @ -507,5 +509,5 @@ void test_online_clone__certificate_valid(void) | ||||
| { | ||||
| 	g_options.remote_callbacks.certificate_check = succeed_certificate_check; | ||||
| 
 | ||||
| 	cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options)); | ||||
| 	cl_git_pass(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options)); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carlos Martín Nieto
						Carlos Martín Nieto