Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: net/base/ssl_client_socket_win.cc

Issue 14915: Move certificate verification off the IO thread.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/ssl_client_socket_win.h ('k') | net/base/x509_certificate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/ssl_client_socket_win.h" 5 #include "net/base/ssl_client_socket_win.h"
6 6
7 #include <schnlsp.h> 7 #include <schnlsp.h>
8 8
9 #include "base/lock.h" 9 #include "base/lock.h"
10 #include "base/singleton.h" 10 #include "base/singleton.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "net/base/connection_type_histograms.h" 12 #include "net/base/connection_type_histograms.h"
13 #include "net/base/net_errors.h" 13 #include "net/base/net_errors.h"
14 #include "net/base/scoped_cert_chain_context.h"
15 #include "net/base/ssl_info.h" 14 #include "net/base/ssl_info.h"
16 15
17 #pragma comment(lib, "secur32.lib") 16 #pragma comment(lib, "secur32.lib")
18 17
19 namespace net { 18 namespace net {
20 19
21 //----------------------------------------------------------------------------- 20 //-----------------------------------------------------------------------------
22 21
23 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx 22 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx
24 // for the other error codes we may need to map. 23 // for the other error codes we may need to map.
(...skipping 28 matching lines...) Expand all
53 case SEC_E_INVALID_HANDLE: 52 case SEC_E_INVALID_HANDLE:
54 return ERR_UNEXPECTED; 53 return ERR_UNEXPECTED;
55 case SEC_E_OK: 54 case SEC_E_OK:
56 return OK; 55 return OK;
57 default: 56 default:
58 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 57 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
59 return ERR_FAILED; 58 return ERR_FAILED;
60 } 59 }
61 } 60 }
62 61
63 // Map a network error code to the equivalent certificate status flag. If
64 // the error code is not a certificate error, it is mapped to 0.
65 static int MapNetErrorToCertStatus(int error) {
66 switch (error) {
67 case ERR_CERT_COMMON_NAME_INVALID:
68 return CERT_STATUS_COMMON_NAME_INVALID;
69 case ERR_CERT_DATE_INVALID:
70 return CERT_STATUS_DATE_INVALID;
71 case ERR_CERT_AUTHORITY_INVALID:
72 return CERT_STATUS_AUTHORITY_INVALID;
73 case ERR_CERT_NO_REVOCATION_MECHANISM:
74 return CERT_STATUS_NO_REVOCATION_MECHANISM;
75 case ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
76 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
77 case ERR_CERT_REVOKED:
78 return CERT_STATUS_REVOKED;
79 case ERR_CERT_CONTAINS_ERRORS:
80 NOTREACHED();
81 // Falls through.
82 case ERR_CERT_INVALID:
83 return CERT_STATUS_INVALID;
84 default:
85 return 0;
86 }
87 }
88
89 static int MapCertStatusToNetError(int cert_status) {
90 // A certificate may have multiple errors. We report the most
91 // serious error.
92
93 // Unrecoverable errors
94 if (cert_status & CERT_STATUS_INVALID)
95 return ERR_CERT_INVALID;
96 if (cert_status & CERT_STATUS_REVOKED)
97 return ERR_CERT_REVOKED;
98
99 // Recoverable errors
100 if (cert_status & CERT_STATUS_AUTHORITY_INVALID)
101 return ERR_CERT_AUTHORITY_INVALID;
102 if (cert_status & CERT_STATUS_COMMON_NAME_INVALID)
103 return ERR_CERT_COMMON_NAME_INVALID;
104 if (cert_status & CERT_STATUS_DATE_INVALID)
105 return ERR_CERT_DATE_INVALID;
106
107 // Unknown status. Give it the benefit of the doubt.
108 if (cert_status & CERT_STATUS_UNABLE_TO_CHECK_REVOCATION)
109 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
110 if (cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM)
111 return ERR_CERT_NO_REVOCATION_MECHANISM;
112
113 NOTREACHED();
114 return ERR_UNEXPECTED;
115 }
116
117 // Map the errors in the chain_context->TrustStatus.dwErrorStatus returned by
118 // CertGetCertificateChain to our certificate status flags.
119 static int MapCertChainErrorStatusToCertStatus(DWORD error_status) {
120 int cert_status = 0;
121
122 // CERT_TRUST_IS_NOT_TIME_NESTED means a subject certificate's time validity
123 // does not nest correctly within its issuer's time validity.
124 const DWORD kDateInvalidErrors = CERT_TRUST_IS_NOT_TIME_VALID |
125 CERT_TRUST_IS_NOT_TIME_NESTED |
126 CERT_TRUST_CTL_IS_NOT_TIME_VALID;
127 if (error_status & kDateInvalidErrors)
128 cert_status |= CERT_STATUS_DATE_INVALID;
129
130 const DWORD kAuthorityInvalidErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
131 CERT_TRUST_IS_EXPLICIT_DISTRUST |
132 CERT_TRUST_IS_PARTIAL_CHAIN;
133 if (error_status & kAuthorityInvalidErrors)
134 cert_status |= CERT_STATUS_AUTHORITY_INVALID;
135
136 if ((error_status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) &&
137 !(error_status & CERT_TRUST_IS_OFFLINE_REVOCATION))
138 cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
139
140 if (error_status & CERT_TRUST_IS_OFFLINE_REVOCATION)
141 cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
142
143 if (error_status & CERT_TRUST_IS_REVOKED)
144 cert_status |= CERT_STATUS_REVOKED;
145
146 const DWORD kWrongUsageErrors = CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
147 CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
148 if (error_status & kWrongUsageErrors) {
149 // TODO(wtc): Handle these errors.
150 // cert_status = |= CERT_STATUS_WRONG_USAGE;
151 }
152
153 // The rest of the errors.
154 const DWORD kCertInvalidErrors =
155 CERT_TRUST_IS_NOT_SIGNATURE_VALID |
156 CERT_TRUST_IS_CYCLIC |
157 CERT_TRUST_INVALID_EXTENSION |
158 CERT_TRUST_INVALID_POLICY_CONSTRAINTS |
159 CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
160 CERT_TRUST_INVALID_NAME_CONSTRAINTS |
161 CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
162 CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
163 CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT |
164 CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT |
165 CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT |
166 CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY |
167 CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT;
168 if (error_status & kCertInvalidErrors)
169 cert_status |= CERT_STATUS_INVALID;
170
171 return cert_status;
172 }
173
174 //----------------------------------------------------------------------------- 62 //-----------------------------------------------------------------------------
175 63
176 // A bitmask consisting of these bit flags encodes which versions of the SSL 64 // A bitmask consisting of these bit flags encodes which versions of the SSL
177 // protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled. 65 // protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled.
178 enum { 66 enum {
179 SSL2 = 1 << 0, 67 SSL2 = 1 << 0,
180 SSL3 = 1 << 1, 68 SSL3 = 1 << 1,
181 TLS1 = 1 << 2, 69 TLS1 = 1 << 2,
182 SSL_VERSION_MASKS = 1 << 3 // The number of SSL version bitmasks. 70 SSL_VERSION_MASKS = 1 << 3 // The number of SSL version bitmasks.
183 }; 71 };
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 #pragma warning(suppress: 4355) 209 #pragma warning(suppress: 4355)
322 : io_callback_(this, &SSLClientSocketWin::OnIOComplete), 210 : io_callback_(this, &SSLClientSocketWin::OnIOComplete),
323 transport_(transport_socket), 211 transport_(transport_socket),
324 hostname_(hostname), 212 hostname_(hostname),
325 ssl_config_(ssl_config), 213 ssl_config_(ssl_config),
326 user_callback_(NULL), 214 user_callback_(NULL),
327 user_buf_(NULL), 215 user_buf_(NULL),
328 user_buf_len_(0), 216 user_buf_len_(0),
329 next_state_(STATE_NONE), 217 next_state_(STATE_NONE),
330 server_cert_(NULL), 218 server_cert_(NULL),
331 server_cert_status_(0),
332 creds_(NULL), 219 creds_(NULL),
333 payload_send_buffer_len_(0), 220 payload_send_buffer_len_(0),
334 bytes_sent_(0), 221 bytes_sent_(0),
335 decrypted_ptr_(NULL), 222 decrypted_ptr_(NULL),
336 bytes_decrypted_(0), 223 bytes_decrypted_(0),
337 received_ptr_(NULL), 224 received_ptr_(NULL),
338 bytes_received_(0), 225 bytes_received_(0),
339 completed_handshake_(false), 226 completed_handshake_(false),
340 complete_handshake_on_write_complete_(false), 227 complete_handshake_on_write_complete_(false),
341 ignore_ok_result_(false), 228 ignore_ok_result_(false),
(...skipping 23 matching lines...) Expand all
365 SecPkgContext_ConnectionInfo connection_info; 252 SecPkgContext_ConnectionInfo connection_info;
366 status = QueryContextAttributes(&ctxt_, 253 status = QueryContextAttributes(&ctxt_,
367 SECPKG_ATTR_CONNECTION_INFO, 254 SECPKG_ATTR_CONNECTION_INFO,
368 &connection_info); 255 &connection_info);
369 if (status == SEC_E_OK) { 256 if (status == SEC_E_OK) {
370 // TODO(wtc): compute the overall security strength, taking into account 257 // TODO(wtc): compute the overall security strength, taking into account
371 // dwExchStrength and dwHashStrength. dwExchStrength needs to be 258 // dwExchStrength and dwHashStrength. dwExchStrength needs to be
372 // normalized. 259 // normalized.
373 ssl_info->security_bits = connection_info.dwCipherStrength; 260 ssl_info->security_bits = connection_info.dwCipherStrength;
374 } 261 }
375 ssl_info->cert_status = server_cert_status_; 262 ssl_info->cert_status = server_cert_verify_result_.cert_status;
376 } 263 }
377 264
378 int SSLClientSocketWin::Connect(CompletionCallback* callback) { 265 int SSLClientSocketWin::Connect(CompletionCallback* callback) {
379 DCHECK(transport_.get()); 266 DCHECK(transport_.get());
380 DCHECK(next_state_ == STATE_NONE); 267 DCHECK(next_state_ == STATE_NONE);
381 DCHECK(!user_callback_); 268 DCHECK(!user_callback_);
382 269
383 int ssl_version_mask = 0; 270 int ssl_version_mask = 0;
384 if (ssl_config_.ssl2_enabled) 271 if (ssl_config_.ssl2_enabled)
385 ssl_version_mask |= SSL2; 272 ssl_version_mask |= SSL2;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 break; 414 break;
528 case STATE_HANDSHAKE_READ_COMPLETE: 415 case STATE_HANDSHAKE_READ_COMPLETE:
529 rv = DoHandshakeReadComplete(rv); 416 rv = DoHandshakeReadComplete(rv);
530 break; 417 break;
531 case STATE_HANDSHAKE_WRITE: 418 case STATE_HANDSHAKE_WRITE:
532 rv = DoHandshakeWrite(); 419 rv = DoHandshakeWrite();
533 break; 420 break;
534 case STATE_HANDSHAKE_WRITE_COMPLETE: 421 case STATE_HANDSHAKE_WRITE_COMPLETE:
535 rv = DoHandshakeWriteComplete(rv); 422 rv = DoHandshakeWriteComplete(rv);
536 break; 423 break;
424 case STATE_VERIFY_CERT:
425 rv = DoVerifyCert();
426 break;
427 case STATE_VERIFY_CERT_COMPLETE:
428 rv = DoVerifyCertComplete(rv);
429 break;
537 case STATE_PAYLOAD_READ: 430 case STATE_PAYLOAD_READ:
538 rv = DoPayloadRead(); 431 rv = DoPayloadRead();
539 break; 432 break;
540 case STATE_PAYLOAD_READ_COMPLETE: 433 case STATE_PAYLOAD_READ_COMPLETE:
541 rv = DoPayloadReadComplete(rv); 434 rv = DoPayloadReadComplete(rv);
542 break; 435 break;
543 case STATE_PAYLOAD_ENCRYPT: 436 case STATE_PAYLOAD_ENCRYPT:
544 rv = DoPayloadEncrypt(); 437 rv = DoPayloadEncrypt();
545 break; 438 break;
546 case STATE_PAYLOAD_WRITE: 439 case STATE_PAYLOAD_WRITE:
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 return DidCompleteHandshake(); 685 return DidCompleteHandshake();
793 next_state_ = STATE_HANDSHAKE_READ; 686 next_state_ = STATE_HANDSHAKE_READ;
794 } else { 687 } else {
795 // Send the remaining bytes. 688 // Send the remaining bytes.
796 next_state_ = STATE_HANDSHAKE_WRITE; 689 next_state_ = STATE_HANDSHAKE_WRITE;
797 } 690 }
798 691
799 return OK; 692 return OK;
800 } 693 }
801 694
695 // Set server_cert_status_ and return OK or a network error.
696 int SSLClientSocketWin::DoVerifyCert() {
697 next_state_ = STATE_VERIFY_CERT_COMPLETE;
698
699 DCHECK(server_cert_);
700
701 PCCERT_CONTEXT dup_cert = CertDuplicateCertificateContext(server_cert_);
702 scoped_refptr<X509Certificate> cert =
703 X509Certificate::CreateFromHandle(dup_cert,
704 X509Certificate::SOURCE_FROM_NETWORK);
705 return verifier_.Verify(cert, hostname_, ssl_config_.rev_checking_enabled,
706 &server_cert_verify_result_, &io_callback_);
707 }
708
709 int SSLClientSocketWin::DoVerifyCertComplete(int result) {
710 LogConnectionTypeMetrics();
711 return result;
712 }
713
802 int SSLClientSocketWin::DoPayloadRead() { 714 int SSLClientSocketWin::DoPayloadRead() {
803 next_state_ = STATE_PAYLOAD_READ_COMPLETE; 715 next_state_ = STATE_PAYLOAD_READ_COMPLETE;
804 716
805 DCHECK(recv_buffer_.get()); 717 DCHECK(recv_buffer_.get());
806 718
807 char* buf = recv_buffer_.get() + bytes_received_; 719 char* buf = recv_buffer_.get() + bytes_received_;
808 int buf_len = kRecvBufferSize - bytes_received_; 720 int buf_len = kRecvBufferSize - bytes_received_;
809 721
810 if (buf_len <= 0) { 722 if (buf_len <= 0) {
811 NOTREACHED() << "Receive buffer is too small!"; 723 NOTREACHED() << "Receive buffer is too small!";
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 } 925 }
1014 DCHECK(!server_cert_); 926 DCHECK(!server_cert_);
1015 status = QueryContextAttributes( 927 status = QueryContextAttributes(
1016 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_); 928 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_);
1017 if (status != SEC_E_OK) { 929 if (status != SEC_E_OK) {
1018 DLOG(ERROR) << "QueryContextAttributes failed: " << status; 930 DLOG(ERROR) << "QueryContextAttributes failed: " << status;
1019 return MapSecurityError(status); 931 return MapSecurityError(status);
1020 } 932 }
1021 933
1022 completed_handshake_ = true; 934 completed_handshake_ = true;
1023 return VerifyServerCert(); 935 next_state_ = STATE_VERIFY_CERT;
936 return OK;
1024 } 937 }
1025 938
1026 // static 939 void SSLClientSocketWin::LogConnectionTypeMetrics() const {
1027 void SSLClientSocketWin::LogConnectionTypeMetrics(
1028 PCCERT_CHAIN_CONTEXT chain_context) {
1029 UpdateConnectionTypeHistograms(CONNECTION_SSL); 940 UpdateConnectionTypeHistograms(CONNECTION_SSL);
1030 941 if (server_cert_verify_result_.has_md5)
1031 PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
1032 int num_elements = first_chain->cElement;
1033 PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
1034 bool has_md5 = false;
1035 bool has_md2 = false;
1036 bool has_md4 = false;
1037 bool has_md5_ca = false;
1038 bool has_md2_ca = false;
1039
1040 // Each chain starts with the end entity certificate (i = 0) and ends with
1041 // the root CA certificate (i = num_elements - 1). Do not inspect the
1042 // signature algorithm of the root CA certificate because the signature on
1043 // the trust anchor is not important.
1044 for (int i = 0; i < num_elements - 1; ++i) {
1045 PCCERT_CONTEXT cert = element[i]->pCertContext;
1046 const char* algorithm = cert->pCertInfo->SignatureAlgorithm.pszObjId;
1047 if (strcmp(algorithm, szOID_RSA_MD5RSA) == 0) {
1048 // md5WithRSAEncryption: 1.2.840.113549.1.1.4
1049 has_md5 = true;
1050 if (i != 0)
1051 has_md5_ca = true;
1052 } else if (strcmp(algorithm, szOID_RSA_MD2RSA) == 0) {
1053 // md2WithRSAEncryption: 1.2.840.113549.1.1.2
1054 has_md2 = true;
1055 if (i != 0)
1056 has_md2_ca = true;
1057 } else if (strcmp(algorithm, szOID_RSA_MD4RSA) == 0) {
1058 // md4WithRSAEncryption: 1.2.840.113549.1.1.3
1059 has_md4 = true;
1060 }
1061 }
1062
1063 if (has_md5)
1064 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); 942 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
1065 if (has_md2) 943 if (server_cert_verify_result_.has_md2)
1066 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); 944 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
1067 if (has_md4) 945 if (server_cert_verify_result_.has_md4)
1068 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); 946 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
1069 if (has_md5_ca) 947 if (server_cert_verify_result_.has_md5_ca)
1070 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); 948 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
1071 if (has_md2_ca) 949 if (server_cert_verify_result_.has_md2_ca)
1072 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); 950 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
1073 } 951 }
1074 952
1075 // Set server_cert_status_ and return OK or a network error.
1076 int SSLClientSocketWin::VerifyServerCert() {
1077 DCHECK(server_cert_);
1078 server_cert_status_ = 0;
1079
1080 // Build and validate certificate chain.
1081
1082 CERT_CHAIN_PARA chain_para;
1083 memset(&chain_para, 0, sizeof(chain_para));
1084 chain_para.cbSize = sizeof(chain_para);
1085 // TODO(wtc): consider requesting the usage szOID_PKIX_KP_SERVER_AUTH
1086 // or szOID_SERVER_GATED_CRYPTO or szOID_SGC_NETSCAPE
1087 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
1088 chain_para.RequestedUsage.Usage.cUsageIdentifier = 0;
1089 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR*
1090 // We can set CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS to get more chains.
1091 DWORD flags = CERT_CHAIN_CACHE_END_CERT;
1092 if (ssl_config_.rev_checking_enabled) {
1093 server_cert_status_ |= CERT_STATUS_REV_CHECKING_ENABLED;
1094 flags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1095 } else {
1096 flags |= CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
1097 }
1098 PCCERT_CHAIN_CONTEXT chain_context;
1099 if (!CertGetCertificateChain(
1100 NULL, // default chain engine, HCCE_CURRENT_USER
1101 server_cert_,
1102 NULL, // current system time
1103 server_cert_->hCertStore, // search this store
1104 &chain_para,
1105 flags,
1106 NULL, // reserved
1107 &chain_context)) {
1108 return MapSecurityError(GetLastError());
1109 }
1110 ScopedCertChainContext scoped_chain_context(chain_context);
1111
1112 LogConnectionTypeMetrics(chain_context);
1113
1114 server_cert_status_ |= MapCertChainErrorStatusToCertStatus(
1115 chain_context->TrustStatus.dwErrorStatus);
1116
1117 std::wstring wstr_hostname = ASCIIToWide(hostname_);
1118
1119 SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para;
1120 memset(&extra_policy_para, 0, sizeof(extra_policy_para));
1121 extra_policy_para.cbSize = sizeof(extra_policy_para);
1122 extra_policy_para.dwAuthType = AUTHTYPE_SERVER;
1123 extra_policy_para.fdwChecks = 0;
1124 extra_policy_para.pwszServerName =
1125 const_cast<wchar_t*>(wstr_hostname.c_str());
1126
1127 CERT_CHAIN_POLICY_PARA policy_para;
1128 memset(&policy_para, 0, sizeof(policy_para));
1129 policy_para.cbSize = sizeof(policy_para);
1130 policy_para.dwFlags = 0;
1131 policy_para.pvExtraPolicyPara = &extra_policy_para;
1132
1133 CERT_CHAIN_POLICY_STATUS policy_status;
1134 memset(&policy_status, 0, sizeof(policy_status));
1135 policy_status.cbSize = sizeof(policy_status);
1136
1137 if (!CertVerifyCertificateChainPolicy(
1138 CERT_CHAIN_POLICY_SSL,
1139 chain_context,
1140 &policy_para,
1141 &policy_status)) {
1142 return MapSecurityError(GetLastError());
1143 }
1144
1145 if (policy_status.dwError) {
1146 server_cert_status_ |= MapNetErrorToCertStatus(
1147 MapSecurityError(policy_status.dwError));
1148
1149 // CertVerifyCertificateChainPolicy reports only one error (in
1150 // policy_status.dwError) if the certificate has multiple errors.
1151 // CertGetCertificateChain doesn't report certificate name mismatch, so
1152 // CertVerifyCertificateChainPolicy is the only function that can report
1153 // certificate name mismatch.
1154 //
1155 // To prevent a potential certificate name mismatch from being hidden by
1156 // some other certificate error, if we get any other certificate error,
1157 // we call CertVerifyCertificateChainPolicy again, ignoring all other
1158 // certificate errors. Both extra_policy_para.fdwChecks and
1159 // policy_para.dwFlags allow us to ignore certificate errors, so we set
1160 // them both.
1161 if (policy_status.dwError != CERT_E_CN_NO_MATCH) {
1162 const DWORD extra_ignore_flags =
1163 0x00000080 | // SECURITY_FLAG_IGNORE_REVOCATION
1164 0x00000100 | // SECURITY_FLAG_IGNORE_UNKNOWN_CA
1165 0x00002000 | // SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
1166 0x00000200; // SECURITY_FLAG_IGNORE_WRONG_USAGE
1167 extra_policy_para.fdwChecks = extra_ignore_flags;
1168 const DWORD ignore_flags =
1169 CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS |
1170 CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG |
1171 CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG |
1172 CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG |
1173 CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG |
1174 CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG |
1175 CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS |
1176 CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
1177 CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
1178 CERT_CHAIN_POLICY_IGNORE_NOT_SUPPORTED_CRITICAL_EXT_FLAG |
1179 CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG;
1180 policy_para.dwFlags = ignore_flags;
1181 if (!CertVerifyCertificateChainPolicy(
1182 CERT_CHAIN_POLICY_SSL,
1183 chain_context,
1184 &policy_para,
1185 &policy_status)) {
1186 return MapSecurityError(GetLastError());
1187 }
1188 if (policy_status.dwError) {
1189 server_cert_status_ |= MapNetErrorToCertStatus(
1190 MapSecurityError(policy_status.dwError));
1191 }
1192 }
1193 }
1194
1195 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
1196 // compatible with WinHTTP, which doesn't report this error (bug 3004).
1197 server_cert_status_ &= ~CERT_STATUS_NO_REVOCATION_MECHANISM;
1198
1199 if (IsCertStatusError(server_cert_status_))
1200 return MapCertStatusToNetError(server_cert_status_);
1201 return OK;
1202 }
1203
1204 } // namespace net 953 } // namespace net
1205 954
OLDNEW
« no previous file with comments | « net/base/ssl_client_socket_win.h ('k') | net/base/x509_certificate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698