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

Unified Diff: net/base/cert_database_nss.cc

Issue 2668005: Bring the handling of <keygen> and support for the application/x-x509-user-ce... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Whitespace/style Created 10 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/cert_database_mac.cc ('k') | net/base/cert_database_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/cert_database_nss.cc
===================================================================
--- net/base/cert_database_nss.cc (revision 49024)
+++ net/base/cert_database_nss.cc (working copy)
@@ -4,22 +4,121 @@
#include "net/base/cert_database.h"
+#include <cert.h>
+#include <certdb.h>
#include <pk11pub.h>
#include <secmod.h>
#include <ssl.h>
#include <nssb64.h> // NSSBase64_EncodeItem()
#include <secder.h> // DER_Encode()
+#include <secerr.h>
#include <cryptohi.h> // SEC_DerSignData()
#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/nss_util.h"
+#include "base/crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"
namespace net {
+namespace {
+
+typedef scoped_ptr_malloc<CERTCertList,
+ base::NSSDestroyer<CERTCertList,
+ CERT_DestroyCertList> > ScopedCERTCertList;
+
+typedef scoped_ptr_malloc<CERTCertificateList,
+ base::NSSDestroyer<CERTCertificateList,
+ CERT_DestroyCertificateList> > ScopedCERTCertificateList;
+
+// From an arbitrary, unordered list of certificate, attempt to import every
+// certificate that:
+// 1) Is a CA
+// 2) Results in a valid certificate chain
+// It is adapted from the PSM logic located in
+// security/manager/ssl/src/nsNSSCertificateDB.cpp
+void ImportValidIntermediates(
+ const X509Certificate::OSCertHandles& intermediates) {
+ if (intermediates.empty())
+ return;
+
+ ScopedCERTCertList os_intermediates(CERT_NewCertList());
+ if (os_intermediates == NULL)
+ return;
+
+ for (X509Certificate::OSCertHandles::const_iterator it =
+ intermediates.begin(); it != intermediates.end(); ++it) {
+ // CERTCertList will free each certificate when it's destroyed, so we must
+ // duplicate each cert prior to adding to the list, as we do not own the
+ // intermediates (see x509_certificate.h)
+ CERTCertificate* cert = CERT_DupCertificate(
+ const_cast<CERTCertificate*>(*it));
+ if (cert)
+ CERT_AddCertToListTail(os_intermediates.get(), cert);
+ }
+
+ // Filter out any certificates which are not valid CA certificates
+ SECStatus rv = CERT_FilterCertListByUsage(os_intermediates.get(),
+ certUsageAnyCA,
+ PR_TRUE);
+ if (rv != SECSuccess)
+ return;
+
+ PRTime now = PR_Now();
+ size_t offset = 0;
+ for (CERTCertListNode* node = CERT_LIST_HEAD(os_intermediates);
+ !CERT_LIST_END(node, os_intermediates);
+ node = CERT_LIST_NEXT(node), ++offset) {
+ // Validate the certificate
+ SECStatus verify_result = CERT_VerifyCert(CERT_GetDefaultCertDB(),
+ node->cert, PR_TRUE,
+ certUsageVerifyCA, now, NULL,
+ NULL);
+ if (verify_result != SECSuccess) {
+ DLOG(WARNING) << "Unable to validate the intermediate at " << offset
+ << ". Skipping import of this certificate. Result was "
+ << verify_result;
+ continue;
+ }
+
+ // Attempt to construct a chain. The presumption here is that if
+ // construction of chain depends on other certificates that were part of
+ // |intermediates|, they will all be available in the same
+ // CERTCertDBHandle. This is true if they were created via
+ // X509Certificate::CreateFromBytes(), since under the hood that creates
+ // temporary objects in CERT_GetDefaultCertDB(), but that may not be true
+ // if they were obtained by other means.
+ //
+ // Note: If multiple CertDBs are ever supported, this chain building logic
+ // will need to be adjusted accordingly.
+ ScopedCERTCertificateList chain(
+ CERT_CertChainFromCert(node->cert, certUsageAnyCA, PR_FALSE));
+ if (chain == NULL) {
+ DLOG(WARNING) << "Unable to construct certificate chain for"
+ << "intermediate " << offset << ". Skipping import of "
+ << "this certificate.";
+ continue;
+ }
+
+ // CertChainFromCert returns an array of SECItems, but ImportCerts
+ // requires an array of SECItem pointers, so convert.
+ scoped_array<SECItem*> items(new SECItem*[chain->len]);
+ if (items == NULL)
+ continue;
+
+ for (int i = 0; i < chain->len; i++) {
+ items[i] = &chain->certs[i];
+ }
+ CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, chain->len,
+ items.get(), NULL, PR_TRUE, PR_TRUE, NULL);
+ }
+}
+
+} // namespace
+
CertDatabase::CertDatabase() {
base::EnsureNSSInit();
}
@@ -30,13 +129,12 @@
if (cert_obj->HasExpired())
return ERR_CERT_DATE_INVALID;
- // Check if the private key corresponding to the certificate exist
- // We shouldn't accept any random client certificate sent by a CA.
-
- // Note: The NSS source documentation wrongly suggests that this
- // also imports the certificate if the private key exists. This
- // doesn't seem to be the case.
-
+ // Check if the private key corresponding to the certificate exist. We
+ // shouldn't accept any random client certificate sent by a CA.
+ //
+ // Note: The NSS source documentation wrongly suggests that this also
+ // imports the certificate if the private key exists. This doesn't seem to
+ // be the case.
CERTCertificate* cert = cert_obj->os_cert_handle();
PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL);
if (!slot) {
@@ -78,6 +176,8 @@
return ERR_ADD_USER_CERT_FAILED;
}
PK11_FreeSlot(slot);
+
+ ImportValidIntermediates(cert_obj->GetIntermediateCertificates());
return OK;
}
« no previous file with comments | « net/base/cert_database_mac.cc ('k') | net/base/cert_database_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698