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

Unified Diff: net/base/x509_certificate_mac.cc

Issue 2963: Bring X.509 cert handling (at least preliminarily) to the Mac. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 3 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
Index: net/base/x509_certificate_mac.cc
===================================================================
--- net/base/x509_certificate_mac.cc (revision 2361)
+++ net/base/x509_certificate_mac.cc (working copy)
@@ -4,6 +4,7 @@
#include "net/base/x509_certificate.h"
+#include <CommonCrypto/CommonDigest.h>
#include <map>
#include "base/histogram.h"
@@ -15,7 +16,11 @@
#include "net/base/cert_status_flags.h"
#include "net/base/ev_root_ca_metadata.h"
-#pragma comment(lib, "crypt32.lib")
+// NOTE: This Mac implementation is almost entirely untested. TODO(avi): test
+// it to make sure it does what the docs imply it does.
+// NOTE: This implementation doesn't keep track of dates. Calling code is
+// expected to use SecTrustEvaluate(x509cert.os_cert_handle()) and look at the
+// result there.
namespace net {
@@ -24,7 +29,7 @@
// Returns true if this cert fingerprint is the null (all zero) fingerprint.
// We use this as a bogus fingerprint value.
bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) {
- for (int i = 0; i < arraysize(fingerprint.data); ++i) {
+ for (size_t i = 0; i < arraysize(fingerprint.data); ++i) {
if (fingerprint.data[i] != 0)
return false;
}
@@ -33,161 +38,130 @@
// Calculates the SHA-1 fingerprint of the certificate. Returns an empty
// (all zero) fingerprint on failure.
-X509Certificate::Fingerprint CalculateFingerprint(PCCERT_CONTEXT cert) {
- DCHECK(NULL != cert->pbCertEncoded);
- DCHECK(0 != cert->cbCertEncoded);
-
- BOOL rv;
+X509Certificate::Fingerprint CalculateFingerprint(
+ X509Certificate::OSCertHandle cert) {
+ // The Windows code uses CryptHashCertificate, a function specially designed
wtc 2008/09/18 20:37:55 I believe CryptHashCertificate is just a convenien
Avi (use Gerrit) 2008/09/18 20:48:17 Nice, thanks.
+ // to hash certificates. I'm not sure what the difference between using it and
+ // just hashing the data is. WINE's implementation just hashes the data, and
+ // so we'll do that.
+
X509Certificate::Fingerprint sha1;
- DWORD sha1_size = sizeof(sha1.data);
- rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
- cert->cbCertEncoded, sha1.data, &sha1_size);
- DCHECK(rv && sha1_size == sizeof(sha1.data));
- if (!rv)
- memset(sha1.data, 0, sizeof(sha1.data));
+ memset(sha1.data, 0, sizeof(sha1.data));
+
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert, &cert_data);
+ if (status)
+ return sha1;
+
+ DCHECK(NULL != cert_data.Data);
+ DCHECK(0 != cert_data.Length);
+
+ CC_SHA1(cert_data.Data, cert_data.Length, sha1.data);
+
return sha1;
}
-// Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
-// WINAPI calling convention.
-void* WINAPI MyCryptAlloc(size_t size) {
- return malloc(size);
+inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
wtc 2008/09/18 20:37:55 I'm a little surprised that the Security Framework
Avi (use Gerrit) 2008/09/18 20:48:17 Me too, but I looked...
+ return oid1->Length == oid2->Length &&
+ (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
}
-void WINAPI MyCryptFree(void* p) {
- free(p);
-}
+void ParsePrincipal(const CSSM_X509_NAME* name,
+ X509Certificate::Principal* principal) {
+ std::vector<std::string> common_names, locality_names, state_names,
+ country_names;
-// Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
-// structure and stores it in *output.
-void GetCertSubjectAltName(PCCERT_CONTEXT cert,
- scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) {
- PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
- cert->pCertInfo->cExtension,
- cert->pCertInfo->rgExtension);
- if (!extension)
- return;
+ // TODO(jcampan): add business_category and serial_number.
+ const CSSM_OID* kOIDs[8] = { &CSSMOID_CommonName,
Amanda Walker 2008/09/18 16:14:43 suggest using [] instead of [8] so that we don't n
+ &CSSMOID_LocalityName,
+ &CSSMOID_StateProvinceName,
+ &CSSMOID_CountryName,
+ &CSSMOID_StreetAddress,
+ &CSSMOID_OrganizationName,
+ &CSSMOID_OrganizationalUnitName,
+ &CSSMOID_DNQualifier }; // This should be "DC"
wtc 2008/09/18 20:37:55 "DN" most likely stands for Distinguished Name, so
+ // but is undoubtedly
+ // wrong. Find the right
+ // OID.
Amanda Walker 2008/09/18 16:14:43 Add TODO
- CRYPT_DECODE_PARA decode_para;
- decode_para.cbSize = sizeof(decode_para);
- decode_para.pfnAlloc = MyCryptAlloc;
- decode_para.pfnFree = MyCryptFree;
- CERT_ALT_NAME_INFO* alt_name_info = NULL;
- DWORD alt_name_info_size = 0;
- BOOL rv;
- rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- szOID_SUBJECT_ALT_NAME2,
- extension->Value.pbData,
- extension->Value.cbData,
- CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
- &decode_para,
- &alt_name_info,
- &alt_name_info_size);
- if (rv)
- output->reset(alt_name_info);
-}
+ std::vector<std::string>* values[8] = {
Amanda Walker 2008/09/18 16:14:43 suggest using [] instead of [8] so that we don't n
+ &common_names, &locality_names,
+ &state_names, &country_names,
+ &(principal->street_addresses),
+ &(principal->organization_names),
+ &(principal->organization_unit_names),
+ &(principal->domain_components) };
+ DCHECK(arraysize(kOIDs) == arraysize(values));
-///////////////////////////////////////////////////////////////////////////
-//
-// Functions used by X509Certificate::IsEV
-//
-///////////////////////////////////////////////////////////////////////////
+ for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
+ CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
+ for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
+ CSSM_X509_TYPE_VALUE_PAIR pair_struct =
+ rdn_struct.AttributeTypeAndValue[pair];
+ for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
+ if (CSSMOIDEqual(&pair_struct.type, kOIDs[oid])) {
+ std::string value =
+ std::string(reinterpret_cast<std::string::value_type*>
+ (pair_struct.value.Data),
+ pair_struct.value.Length);
+ values[oid]->push_back(value);
+ break;
+ }
+ }
+ }
+ }
-// Constructs a certificate chain starting from the end certificate
-// 'cert_context', matching any of the certificate policies.
-//
-// Returns the certificate chain context on success, or NULL on failure.
-// The caller is responsible for freeing the certificate chain context with
-// CertFreeCertificateChain.
-PCCERT_CHAIN_CONTEXT ConstructCertChain(
- PCCERT_CONTEXT cert_context,
- const char* const* policies,
- int num_policies) {
- CERT_CHAIN_PARA chain_para;
- memset(&chain_para, 0, sizeof(chain_para));
- chain_para.cbSize = sizeof(chain_para);
- chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
- chain_para.RequestedUsage.Usage.cUsageIdentifier = 0;
- chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR*
- chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_OR;
- chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = num_policies;
- chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
- const_cast<char**>(policies);
- PCCERT_CHAIN_CONTEXT chain_context;
- if (!CertGetCertificateChain(
- NULL, // default chain engine, HCCE_CURRENT_USER
- cert_context,
- NULL, // current system time
- cert_context->hCertStore, // search this store
- &chain_para,
- CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT |
- CERT_CHAIN_CACHE_END_CERT,
- NULL, // reserved
- &chain_context)) {
- return NULL;
+ // We don't expect to have more than one CN, L, S, and C.
+ std::vector<std::string>* single_value_lists[4] = {
+ &common_names, &locality_names, &state_names, &country_names };
+ std::string* single_values[4] = {
+ &principal->common_name, &principal->locality_name,
+ &principal->state_or_province_name, &principal->country_name };
+ for (size_t i = 0; i < arraysize(single_value_lists); ++i) {
+ DCHECK(single_value_lists[i]->size() <= 1);
+ if (single_value_lists[i]->size() > 0)
+ *(single_values[i]) = (*(single_value_lists[i]))[0];
}
- return chain_context;
}
-// Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
-// structure and stores it in *output.
-void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
- scoped_ptr_malloc<CERT_POLICIES_INFO>* output) {
- PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES,
- cert->pCertInfo->cExtension,
- cert->pCertInfo->rgExtension);
- if (!extension)
+void GetCertFieldsForOID(X509Certificate::OSCertHandle cert_handle,
wtc 2008/09/18 20:37:55 Use "Field", singular. You're returning only one
Avi (use Gerrit) 2008/09/18 20:48:17 The break is a mistake on my part, copied from the
+ CSSM_OID oid,
+ std::vector<std::string>* result) {
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
+ if (status)
return;
-
- CRYPT_DECODE_PARA decode_para;
- decode_para.cbSize = sizeof(decode_para);
- decode_para.pfnAlloc = MyCryptAlloc;
- decode_para.pfnFree = MyCryptFree;
- CERT_POLICIES_INFO* policies_info = NULL;
- DWORD policies_info_size = 0;
- BOOL rv;
- rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- szOID_CERT_POLICIES,
- extension->Value.pbData,
- extension->Value.cbData,
- CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
- &decode_para,
- &policies_info,
- &policies_info_size);
- if (rv)
- output->reset(policies_info);
-}
-
-// Returns true if the policy is in the array of CERT_POLICY_INFO in
-// the CERT_POLICIES_INFO structure.
-bool ContainsPolicy(const CERT_POLICIES_INFO* policies_info,
- const char* policy) {
- int num_policies = policies_info->cPolicyInfo;
- for (int i = 0; i < num_policies; i++) {
- if (!strcmp(policies_info->rgPolicyInfo[i].pszPolicyIdentifier, policy))
- return true;
+
+ CSSM_CL_HANDLE clHandle;
wtc 2008/09/18 20:37:55 clHandle doesn't follow the naming convention in t
+ status = SecCertificateGetCLHandle(cert_handle, &clHandle);
+ if (status)
+ return;
+
+ uint32 numOfFields;
wtc 2008/09/18 20:37:55 numOfFields doesn't follow the naming convention i
+ CSSM_FIELD_PTR fields;
+ status = CSSM_CL_CertGetAllFields(clHandle, &cert_data, &numOfFields,
+ &fields);
+ if (status)
+ return;
+
+ for (size_t field = 0; field < numOfFields; ++field) {
+ if (CSSMOIDEqual(&fields[field].FieldOid, &oid)) {
+ std::string value =
+ std::string(reinterpret_cast<std::string::value_type*>
+ (fields[field].FieldValue.Data),
+ fields[field].FieldValue.Length);
+ result->push_back(value);
+ break;
+ }
}
- return false;
}
-// This class wraps the CertFreeCertificateChain function in a class that can
-// be passed as a template argument to scoped_ptr_malloc.
-class ScopedPtrMallocFreeCertChain {
- public:
- void operator()(const CERT_CHAIN_CONTEXT* x) const {
- CertFreeCertificateChain(x);
- }
-};
-
-typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT,
- ScopedPtrMallocFreeCertChain> ScopedCertChainContext;
-
} // namespace
bool X509Certificate::FingerprintLessThan::operator()(
const Fingerprint& lhs,
const Fingerprint& rhs) const {
- for (int i = 0; i < sizeof(lhs.data); ++i) {
+ for (size_t i = 0; i < sizeof(lhs.data); ++i) {
if (lhs.data[i] < rhs.data[i])
return true;
if (lhs.data[i] > rhs.data[i])
@@ -256,7 +230,7 @@
// Obtain an instance of X509Certificate::Cache via GetInstance().
Cache() { }
- friend DefaultSingletonTraits<X509Certificate::Cache>;
+ friend class DefaultSingletonTraits<X509Certificate::Cache>;
// You must acquire this lock before using any private data of this object.
// You must not block while holding this lock.
@@ -265,35 +239,20 @@
// The certificate cache. You must acquire |lock_| before using |cache_|.
CertMap cache_;
- DISALLOW_EVIL_CONSTRUCTORS(X509Certificate::Cache);
+ DISALLOW_COPY_AND_ASSIGN(Cache);
};
void X509Certificate::Initialize() {
- std::wstring subject_info;
- std::wstring issuer_info;
- DWORD name_size;
- name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
- &cert_handle_->pCertInfo->Subject,
- CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- NULL, 0);
- name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
- &cert_handle_->pCertInfo->Subject,
- CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- WriteInto(&subject_info, name_size), name_size);
- name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
- &cert_handle_->pCertInfo->Issuer,
- CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- NULL, 0);
- name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
- &cert_handle_->pCertInfo->Issuer,
- CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- WriteInto(&issuer_info, name_size), name_size);
- ParsePrincipal(WideToUTF8(subject_info), &subject_);
- ParsePrincipal(WideToUTF8(issuer_info), &issuer_);
-
- valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
- valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
-
+ const CSSM_X509_NAME* name;
+ OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
+ if (!status) {
+ ParsePrincipal(name, &subject_);
+ }
+ status = SecCertificateGetIssuer(cert_handle_, &name);
+ if (!status) {
+ ParsePrincipal(name, &issuer_);
+ }
+
fingerprint_ = CalculateFingerprint(cert_handle_);
// Store the certificate in the cache in case we need it later.
@@ -310,7 +269,7 @@
if (cert) {
// We've found a certificate with the same fingerprint in our cache. We own
// the |cert_handle|, which makes it our job to free it.
- CertFreeCertificateContext(cert_handle);
+ CFRelease(cert_handle);
DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
return cert;
}
@@ -325,13 +284,16 @@
int length;
if (!pickle.ReadData(pickle_iter, &data, &length))
return NULL;
+ CSSM_DATA cert_data;
+ cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
+ cert_data.Length = length;
OSCertHandle cert_handle = NULL;
- if (!CertAddSerializedElementToStore(
- NULL, // the cert won't be persisted in any cert store
- reinterpret_cast<const BYTE*>(data), length,
- CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
- NULL, reinterpret_cast<const void **>(&cert_handle)))
+ OSStatus status = SecCertificateCreateFromData(&cert_data,
+ CSSM_CERT_X_509v3,
+ CSSM_CERT_ENCODING_BER,
+ &cert_handle);
+ if (status)
return NULL;
return CreateFromHandle(cert_handle);
@@ -343,60 +305,40 @@
}
X509Certificate::X509Certificate(std::string subject, std::string issuer,
- Time start_date, Time expiration_date)
+ Time, Time)
: subject_(subject),
issuer_(issuer),
- valid_start_(start_date),
- valid_expiry_(expiration_date),
cert_handle_(NULL) {
memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
}
void X509Certificate::Persist(Pickle* pickle) {
- DWORD length;
- if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
- NULL, &length)) {
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
+ if (status) {
NOTREACHED();
return;
}
- BYTE* data = reinterpret_cast<BYTE*>(pickle->BeginWriteData(length));
- if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
- data, &length)) {
- NOTREACHED();
- length = 0;
- }
- pickle->TrimWriteData(length);
+
+ pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), cert_data.Length);
}
X509Certificate::~X509Certificate() {
// We might not be in the cache, but it is safe to remove ourselves anyway.
X509Certificate::Cache::GetInstance()->Remove(this);
if (cert_handle_)
- CertFreeCertificateContext(cert_handle_);
+ CFRelease(cert_handle_);
}
void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
dns_names->clear();
- scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info;
- GetCertSubjectAltName(cert_handle_, &alt_name_info);
- CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
- if (alt_name) {
- int num_entries = alt_name->cAltEntry;
- for (int i = 0; i < num_entries; i++) {
- // dNSName is an ASN.1 IA5String representing a string of ASCII
- // characters, so we can use WideToASCII here.
- if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
- dns_names->push_back(WideToASCII(alt_name->rgAltEntry[i].pwszDNSName));
- }
- }
+
+ GetCertFieldsForOID(cert_handle_, CSSMOID_SubjectAltName, dns_names);
wtc 2008/09/18 20:37:55 Add a TODO comment to note that we still need to p
Avi (use Gerrit) 2008/09/18 20:48:17 OK; this is me coding not quite sure what needs to
+
if (dns_names->empty())
dns_names->push_back(subject_.common_name);
}
-
-bool X509Certificate::HasExpired() const {
- return Time::Now() > valid_expiry();
-}
-
+
// Returns true if the certificate is an extended-validation certificate.
//
// The certificate has already been verified by the HTTP library. cert_status
@@ -406,112 +348,11 @@
// Certificate Guidelines Version 1.0 at
// http://cabforum.org/EV_Certificate_Guidelines.pdf.
bool X509Certificate::IsEV(int cert_status) const {
- if (net::IsCertStatusError(cert_status) ||
- (cert_status & net::CERT_STATUS_REV_CHECKING_ENABLED) == 0)
- return false;
-
- net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance();
-
- PCCERT_CHAIN_CONTEXT chain_context = ConstructCertChain(cert_handle_,
- metadata->GetPolicyOIDs(), metadata->NumPolicyOIDs());
- if (!chain_context)
- return false;
- ScopedCertChainContext scoped_chain_context(chain_context);
-
- DCHECK(chain_context->cChain != 0);
- // If the cert doesn't match any of the policies, the
- // CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
- // chain_context->TrustStatus.dwErrorStatus is set.
- DWORD error_status = chain_context->TrustStatus.dwErrorStatus;
- DWORD info_status = chain_context->TrustStatus.dwInfoStatus;
- if (!chain_context->cChain || error_status != CERT_TRUST_NO_ERROR)
- return false;
-
- // Check the end certificate simple chain (chain_context->rgpChain[0]).
- // If the end certificate's certificatePolicies extension contains the
- // EV policy OID of the root CA, return true.
- PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
- int num_elements = chain_context->rgpChain[0]->cElement;
- if (num_elements < 2)
- return false;
-
- // Look up the EV policy OID of the root CA.
- PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
- X509Certificate::Fingerprint fingerprint = CalculateFingerprint(root_cert);
- std::string ev_policy_oid;
- if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid))
- return false;
- DCHECK(!ev_policy_oid.empty());
-
- // Get the certificatePolicies extension of the end certificate.
- PCCERT_CONTEXT end_cert = element[0]->pCertContext;
- scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
- GetCertPoliciesInfo(end_cert, &policies_info);
- if (!policies_info.get())
- return false;
-
- return ContainsPolicy(policies_info.get(), ev_policy_oid.c_str());
+ // TODO(avi): implement this
+ NOTIMPLEMENTED();
+ return false;
}
-// static
-void X509Certificate::ParsePrincipal(const std::string& description,
- Principal* principal) {
- // The description of the principal is a string with each LDAP value on
- // a separate line.
- const std::string kDelimiters("\r\n");
-
- std::vector<std::string> common_names, locality_names, state_names,
- country_names, street_addresses;
-
- // TODO(jcampan): add business_category and serial_number.
- const std::string kPrefixes[8] = { std::string("CN="),
- std::string("L="),
- std::string("S="),
- std::string("C="),
- std::string("STREET="),
- std::string("O="),
- std::string("OU="),
- std::string("DC=") };
-
- std::vector<std::string>* values[8] = {
- &common_names, &locality_names,
- &state_names, &country_names,
- &(principal->street_addresses),
- &(principal->organization_names),
- &(principal->organization_unit_names),
- &(principal->domain_components) };
- DCHECK(arraysize(kPrefixes) == arraysize(values));
-
- StringTokenizer str_tok(description, kDelimiters);
- while (str_tok.GetNext()) {
- std::string entry = str_tok.token();
- for (int i = 0; i < arraysize(kPrefixes); i++) {
- if (!entry.compare(0, kPrefixes[i].length(), kPrefixes[i])) {
- std::string value = entry.substr(kPrefixes[i].length());
- // Remove enclosing double-quotes if any.
- if (value.size() >= 2 &&
- value[0] == '"' && value[value.size() - 1] == '"')
- value = value.substr(1, value.size() - 2);
- values[i]->push_back(value);
- break;
- }
- }
- }
-
- // We don't expect to have more than one CN, L, S, and C.
- std::vector<std::string>* single_value_lists[4] = {
- &common_names, &locality_names, &state_names, &country_names };
- std::string* single_values[4] = {
- &principal->common_name, &principal->locality_name,
- &principal->state_or_province_name, &principal->country_name };
- for (int i = 0; i < arraysize(single_value_lists); ++i) {
- int length = static_cast<int>(single_value_lists[i]->size());
- DCHECK(single_value_lists[i]->size() <= 1);
- if (single_value_lists[i]->size() > 0)
- *(single_values[i]) = (*(single_value_lists[i]))[0];
- }
-}
-
X509Certificate::Policy::Judgment X509Certificate::Policy::Check(
Amanda Walker 2008/09/18 16:14:43 If X509Certificate::Policy has no platform depende
X509Certificate* cert) const {
// It shouldn't matter which set we check first, but we check denied first

Powered by Google App Engine
This is Rietveld 408576698