39
39
#include "schannel.h"
40
40
#include "schannel_int.h"
41
41
42
- #ifdef HAS_MANUAL_VERIFY_API
43
-
44
42
#include "vtls.h"
45
43
#include "vtls_int.h"
46
44
#include "sendf.h"
56
54
57
55
#define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend)
58
56
57
+
58
+ #ifdef HAS_MANUAL_VERIFY_API
59
+
59
60
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
60
61
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
61
62
#define END_CERT "\n-----END CERTIFICATE-----"
@@ -330,6 +331,8 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store,
330
331
return result ;
331
332
}
332
333
334
+ #endif /* HAS_MANUAL_VERIFY_API */
335
+
333
336
/*
334
337
* Returns the number of characters necessary to populate all the host_names.
335
338
* If host_names is not NULL, populate it with all the host names. Each string
@@ -353,10 +356,10 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
353
356
LPTSTR current_pos = NULL ;
354
357
DWORD i ;
355
358
359
+ #ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
356
360
/* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
357
361
if (curlx_verify_windows_version (6 , 2 , 0 , PLATFORM_WINNT ,
358
362
VERSION_GREATER_THAN_EQUAL )) {
359
- #ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
360
363
/* CertGetNameString will provide the 8-bit character string without
361
364
* any decoding */
362
365
DWORD name_flags =
@@ -368,8 +371,8 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
368
371
host_names ,
369
372
length );
370
373
return actual_length ;
371
- #endif
372
374
}
375
+ #endif
373
376
374
377
compute_content = host_names != NULL && length != 0 ;
375
378
@@ -457,17 +460,34 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
457
460
return actual_length ;
458
461
}
459
462
460
- static CURLcode verify_host ( struct Curl_easy * data ,
461
- CERT_CONTEXT * pCertContextServer ,
462
- const char * conn_hostname )
463
+ /* Verify the server's hostname */
464
+ CURLcode Curl_verify_host ( struct Curl_cfilter * cf ,
465
+ struct Curl_easy * data )
463
466
{
467
+ struct ssl_connect_data * connssl = cf -> ctx ;
468
+ SECURITY_STATUS sspi_status ;
464
469
CURLcode result = CURLE_PEER_FAILED_VERIFICATION ;
470
+ CERT_CONTEXT * pCertContextServer = NULL ;
465
471
TCHAR * cert_hostname_buff = NULL ;
466
472
size_t cert_hostname_buff_index = 0 ;
473
+ const char * conn_hostname = connssl -> hostname ;
467
474
size_t hostlen = strlen (conn_hostname );
468
475
DWORD len = 0 ;
469
476
DWORD actual_len = 0 ;
470
477
478
+ sspi_status =
479
+ s_pSecFn -> QueryContextAttributes (& BACKEND -> ctxt -> ctxt_handle ,
480
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT ,
481
+ & pCertContextServer );
482
+
483
+ if ((sspi_status != SEC_E_OK ) || !pCertContextServer ) {
484
+ char buffer [STRERROR_LEN ];
485
+ failf (data , "schannel: Failed to read remote certificate context: %s" ,
486
+ Curl_sspi_strerror (sspi_status , buffer , sizeof (buffer )));
487
+ result = CURLE_PEER_FAILED_VERIFICATION ;
488
+ goto cleanup ;
489
+ }
490
+
471
491
/* Determine the size of the string needed for the cert hostname */
472
492
len = cert_get_name_string (data , pCertContextServer , NULL , 0 );
473
493
if (len == 0 ) {
@@ -498,10 +518,9 @@ static CURLcode verify_host(struct Curl_easy *data,
498
518
goto cleanup ;
499
519
}
500
520
501
- /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output
502
- * will contain all DNS names, where each name is null-terminated
503
- * and the last DNS name is double null-terminated. Due to this
504
- * encoding, use the length of the buffer to iterate over all names.
521
+ /* cert_hostname_buff contains all DNS names, where each name is
522
+ * null-terminated and the last DNS name is double null-terminated. Due to
523
+ * this encoding, use the length of the buffer to iterate over all names.
505
524
*/
506
525
result = CURLE_PEER_FAILED_VERIFICATION ;
507
526
while (cert_hostname_buff_index < len &&
@@ -560,9 +579,15 @@ static CURLcode verify_host(struct Curl_easy *data,
560
579
cleanup :
561
580
Curl_safefree (cert_hostname_buff );
562
581
582
+ if (pCertContextServer )
583
+ CertFreeCertificateContext (pCertContextServer );
584
+
563
585
return result ;
564
586
}
565
587
588
+
589
+ #ifdef HAS_MANUAL_VERIFY_API
590
+ /* Verify the server's certificate and hostname */
566
591
CURLcode Curl_verify_certificate (struct Curl_cfilter * cf ,
567
592
struct Curl_easy * data )
568
593
{
@@ -721,7 +746,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
721
746
722
747
if (result == CURLE_OK ) {
723
748
if (conn_config -> verifyhost ) {
724
- result = verify_host ( data , pCertContextServer , connssl -> hostname );
749
+ result = Curl_verify_host ( cf , data );
725
750
}
726
751
}
727
752
0 commit comments