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 |