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

Side by Side Diff: net/socket/ssl_client_socket_nss.cc

Issue 11184027: net: add DANE support for DNSSEC stapled certificates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Syncing with trunk in order to land. Created 8 years, 1 month 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/dnssec_chain_verifier.cc ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
6 // from AuthCertificateCallback() in 6 // from AuthCertificateCallback() in
7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
8 8
9 /* ***** BEGIN LICENSE BLOCK ***** 9 /* ***** BEGIN LICENSE BLOCK *****
10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 DNSVR_SUCCESS, // the cert is immediately acceptable. 272 DNSVR_SUCCESS, // the cert is immediately acceptable.
273 DNSVR_FAILURE, // the cert is unconditionally rejected. 273 DNSVR_FAILURE, // the cert is unconditionally rejected.
274 DNSVR_CONTINUE, // perform CA validation as usual. 274 DNSVR_CONTINUE, // perform CA validation as usual.
275 }; 275 };
276 276
277 // VerifyCAARecords processes DNSSEC validated RRDATA for a number of DNS CAA 277 // VerifyCAARecords processes DNSSEC validated RRDATA for a number of DNS CAA
278 // records and checks them against the given chain. 278 // records and checks them against the given chain.
279 // server_cert_nss: the server's leaf certificate. 279 // server_cert_nss: the server's leaf certificate.
280 // rrdatas: the CAA records for the current domain. 280 // rrdatas: the CAA records for the current domain.
281 // port: the TCP port number that we connected to. 281 // port: the TCP port number that we connected to.
282 // TODO(agl): remove once DANE support has been released.
282 DNSValidationResult VerifyCAARecords( 283 DNSValidationResult VerifyCAARecords(
283 CERTCertificate* server_cert_nss, 284 CERTCertificate* server_cert_nss,
284 const std::vector<base::StringPiece>& rrdatas, 285 const std::vector<base::StringPiece>& rrdatas,
285 uint16 port) { 286 uint16 port) {
286 DnsCAARecord::Policy policy; 287 DnsCAARecord::Policy policy;
287 const DnsCAARecord::ParseResult r = DnsCAARecord::Parse(rrdatas, &policy); 288 const DnsCAARecord::ParseResult r = DnsCAARecord::Parse(rrdatas, &policy);
288 if (r == DnsCAARecord::SYNTAX_ERROR || r == DnsCAARecord::UNKNOWN_CRITICAL) 289 if (r == DnsCAARecord::SYNTAX_ERROR || r == DnsCAARecord::UNKNOWN_CRITICAL)
289 return DNSVR_FAILURE; 290 return DNSVR_FAILURE;
290 if (r == DnsCAARecord::DISCARD) 291 if (r == DnsCAARecord::DISCARD)
291 return DNSVR_CONTINUE; 292 return DNSVR_CONTINUE;
(...skipping 25 matching lines...) Expand all
317 return DNSVR_SUCCESS; 318 return DNSVR_SUCCESS;
318 } 319 }
319 } 320 }
320 } 321 }
321 322
322 // If a CAA record was found, but nothing matched, then we reject the 323 // If a CAA record was found, but nothing matched, then we reject the
323 // certificate. 324 // certificate.
324 return DNSVR_FAILURE; 325 return DNSVR_FAILURE;
325 } 326 }
326 327
328 // VerifyTLSARecords processes DNSSEC validated RRDATA for a number of DNS TLSA
329 // records and checks them against the given chain.
330 // server_cert_nss: the server's leaf certificate.
331 // rrdatas: the TLSA records for the current domain.
332 DNSValidationResult VerifyTLSARecords(
333 CERTCertificate* server_cert_nss,
334 const std::vector<base::StringPiece>& rrdatas) {
335 std::vector<DnsTLSARecord::Match> matches;
336 DnsTLSARecord::Parse(rrdatas, &matches);
337
338 for (std::vector<DnsTLSARecord::Match>::const_iterator
339 i = matches.begin(); i != matches.end(); ++i) {
340 SECItem matched_data;
341 switch (i->target) {
342 case DnsTLSARecord::Match::CERTIFICATE:
343 matched_data = server_cert_nss->derCert;
344 break;
345 case DnsTLSARecord::Match::SUBJECT_PUBLIC_KEY_INFO:
346 matched_data = server_cert_nss->derPublicKey;
347 break;
348 default:
349 continue;
350 }
351
352 uint8 calculated_hash[HASH_LENGTH_MAX];
353 SECItem processed_data;
354 if (i->algorithm == HASH_AlgNULL) {
355 processed_data = matched_data;
356 } else {
357 SECStatus rv = HASH_HashBuf(
358 static_cast<HASH_HashType>(i->algorithm),
359 calculated_hash,
360 matched_data.data,
361 matched_data.len);
362 if (rv != SECSuccess)
363 continue;
364 processed_data.data = calculated_hash;
365 processed_data.len = i->data.size();
366 }
367
368 if (processed_data.len == i->data.size() &&
369 memcmp(processed_data.data, i->data.data(), i->data.size()) == 0) {
370 return DNSVR_SUCCESS;
371 }
372 }
373
374 // No TLSA records matched so we reject the certificate.
375 return DNSVR_FAILURE;
376 }
377
327 // CheckDNSSECChain tries to validate a DNSSEC chain embedded in 378 // CheckDNSSECChain tries to validate a DNSSEC chain embedded in
328 // |server_cert_nss|. It returns true iff a chain is found that proves the 379 // |server_cert_nss|. It returns true iff a chain is found that proves the
329 // value of a CAA record that contains a valid public key fingerprint. 380 // value of a CAA record that contains a valid public key fingerprint.
330 // |port| contains the TCP port number that we connected to as CAA records can 381 // |port| contains the TCP port number that we connected to as CAA records can
331 // be specific to a given port. 382 // be specific to a given port.
332 DNSValidationResult CheckDNSSECChain( 383 DNSValidationResult CheckDNSSECChain(
333 const std::string& hostname, 384 const std::string& hostname,
334 CERTCertificate* server_cert_nss, 385 CERTCertificate* server_cert_nss,
335 uint16 port) { 386 uint16 port) {
336 if (!server_cert_nss) 387 if (!server_cert_nss)
(...skipping 20 matching lines...) Expand all
357 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag); 408 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
358 dnssec_chain_tag_valid = true; 409 dnssec_chain_tag_valid = true;
359 } 410 }
360 411
361 SECItem dnssec_embedded_chain; 412 SECItem dnssec_embedded_chain;
362 SECStatus rv = CERT_FindCertExtension(server_cert_nss, 413 SECStatus rv = CERT_FindCertExtension(server_cert_nss,
363 dnssec_chain_tag, &dnssec_embedded_chain); 414 dnssec_chain_tag, &dnssec_embedded_chain);
364 if (rv != SECSuccess) 415 if (rv != SECSuccess)
365 return DNSVR_CONTINUE; 416 return DNSVR_CONTINUE;
366 417
367 base::StringPiece chain( 418 std::string chain(
368 reinterpret_cast<char*>(dnssec_embedded_chain.data), 419 reinterpret_cast<char*>(dnssec_embedded_chain.data),
369 dnssec_embedded_chain.len); 420 dnssec_embedded_chain.len);
421 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
370 std::string dns_hostname; 422 std::string dns_hostname;
371 if (!DNSDomainFromDot(hostname, &dns_hostname)) 423 if (!DNSDomainFromDot(hostname, &dns_hostname))
372 return DNSVR_CONTINUE; 424 return DNSVR_CONTINUE;
425
373 DNSSECChainVerifier verifier(dns_hostname, chain); 426 DNSSECChainVerifier verifier(dns_hostname, chain);
374 DNSSECChainVerifier::Error err = verifier.Verify(); 427 DNSSECChainVerifier::Error err = verifier.Verify();
428 bool is_tlsa = false;
429 if (err == DNSSECChainVerifier::BAD_TARGET) {
430 // We might have failed because this is a DANE chain, not a CAA chain.
431 // DANE stores records in a subdomain of the name that includes the port
432 // and protocol, i.e. _443._tcp.www.example.com. We have to construct
433 // such a name for |hostname|.
434 const std::string port_str = base::UintToString(port);
435 char port_label_len = 1 + static_cast<char>(port_str.size());
436 const std::string tlsa_domain =
437 std::string(&port_label_len, 1) + "_" + port_str +
438 "\x04_tcp" +
439 dns_hostname;
440
441 verifier = DNSSECChainVerifier(tlsa_domain, chain);
442 err = verifier.Verify();
443 is_tlsa = true;
444 }
445
375 if (err != DNSSECChainVerifier::OK) { 446 if (err != DNSSECChainVerifier::OK) {
376 LOG(ERROR) << "DNSSEC chain verification failed: " << err; 447 LOG(ERROR) << "DNSSEC chain verification failed: " << err;
377 return DNSVR_CONTINUE; 448 return DNSVR_CONTINUE;
378 } 449 }
379 450
451 if (is_tlsa) {
452 if (verifier.rrtype() != kDNS_TLSA)
453 return DNSVR_CONTINUE;
454
455 return VerifyTLSARecords(server_cert_nss, verifier.rrdatas());
456 }
457
380 if (verifier.rrtype() != kDNS_CAA) 458 if (verifier.rrtype() != kDNS_CAA)
381 return DNSVR_CONTINUE; 459 return DNSVR_CONTINUE;
382 460
383 DNSValidationResult r = VerifyCAARecords( 461 return VerifyCAARecords(server_cert_nss, verifier.rrdatas(), port);
384 server_cert_nss, verifier.rrdatas(), port);
385 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
386
387 return r;
388 } 462 }
389 463
390 void DestroyCertificates(CERTCertificate** certs, size_t len) { 464 void DestroyCertificates(CERTCertificate** certs, size_t len) {
391 for (size_t i = 0; i < len; i++) 465 for (size_t i = 0; i < len; i++)
392 CERT_DestroyCertificate(certs[i]); 466 CERT_DestroyCertificate(certs[i]);
393 } 467 }
394 468
395 // Helper functions to make it possible to log events from within the 469 // Helper functions to make it possible to log events from within the
396 // SSLClientSocketNSS::Core. 470 // SSLClientSocketNSS::Core.
397 void AddLogEvent(BoundNetLog* net_log, NetLog::EventType event_type) { 471 void AddLogEvent(BoundNetLog* net_log, NetLog::EventType event_type) {
(...skipping 3166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3564 EnsureThreadIdAssigned(); 3638 EnsureThreadIdAssigned();
3565 base::AutoLock auto_lock(lock_); 3639 base::AutoLock auto_lock(lock_);
3566 return valid_thread_id_ == base::PlatformThread::CurrentId(); 3640 return valid_thread_id_ == base::PlatformThread::CurrentId();
3567 } 3641 }
3568 3642
3569 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { 3643 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
3570 return server_bound_cert_service_; 3644 return server_bound_cert_service_;
3571 } 3645 }
3572 3646
3573 } // namespace net 3647 } // namespace net
OLDNEW
« no previous file with comments | « net/base/dnssec_chain_verifier.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698