| Index: net/base/x509_cert_types_mac.cc
|
| diff --git a/net/base/x509_cert_types_mac.cc b/net/base/x509_cert_types_mac.cc
|
| deleted file mode 100644
|
| index a3eec5eab045ab5861c5adccf3c5adc1be73ad64..0000000000000000000000000000000000000000
|
| --- a/net/base/x509_cert_types_mac.cc
|
| +++ /dev/null
|
| @@ -1,290 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/base/x509_cert_types.h"
|
| -
|
| -#include <CoreServices/CoreServices.h>
|
| -#include <Security/Security.h>
|
| -#include <Security/SecAsn1Coder.h>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/i18n/icu_string_conversions.h"
|
| -#include "base/mac/mac_logging.h"
|
| -#include "base/utf_string_conversions.h"
|
| -
|
| -namespace net {
|
| -
|
| -namespace {
|
| -
|
| -// The BER encoding of 0.9.2342.19200300.100.1.25.
|
| -// On 10.6 and later this is available as CSSMOID_DomainComponent, which is an
|
| -// external symbol from Security.framework. However, it appears that Apple's
|
| -// implementation improperly encoded this on 10.6+, and even still is
|
| -// unavailable on 10.5, so simply including the raw BER here.
|
| -//
|
| -// Note: CSSM is allowed to store CSSM_OIDs in any arbitrary format desired,
|
| -// as long as the symbols are properly exposed. The fact that Apple's
|
| -// implementation stores it in BER is an internal implementation detail
|
| -// observed by studying libsecurity_cssm.
|
| -const uint8 kDomainComponentData[] = {
|
| - 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19
|
| -};
|
| -
|
| -const CSSM_OID kDomainComponentOID = {
|
| - arraysize(kDomainComponentData),
|
| - const_cast<uint8*>(kDomainComponentData)
|
| -};
|
| -
|
| -const CSSM_OID* kOIDs[] = {
|
| - &CSSMOID_CommonName,
|
| - &CSSMOID_LocalityName,
|
| - &CSSMOID_StateProvinceName,
|
| - &CSSMOID_CountryName,
|
| - &CSSMOID_StreetAddress,
|
| - &CSSMOID_OrganizationName,
|
| - &CSSMOID_OrganizationalUnitName,
|
| - &kDomainComponentOID,
|
| -};
|
| -
|
| -// The following structs and templates work with Apple's very arcane and under-
|
| -// documented SecAsn1Parser API, which is apparently the same as NSS's ASN.1
|
| -// decoder:
|
| -// http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn1.html
|
| -
|
| -// These are used to parse the contents of a raw
|
| -// BER DistinguishedName structure.
|
| -
|
| -const SecAsn1Template kStringValueTemplate[] = {
|
| - { SEC_ASN1_CHOICE, offsetof(CSSM_X509_TYPE_VALUE_PAIR, valueType), },
|
| - { SEC_ASN1_PRINTABLE_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_PRINTABLE_STRING },
|
| - { SEC_ASN1_IA5_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_IA5_STRING },
|
| - { SEC_ASN1_T61_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_T61_STRING },
|
| - { SEC_ASN1_UTF8_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_PKIX_UTF8_STRING },
|
| - { SEC_ASN1_BMP_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_PKIX_BMP_STRING },
|
| - { SEC_ASN1_UNIVERSAL_STRING,
|
| - offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
|
| - BER_TAG_PKIX_UNIVERSAL_STRING },
|
| - { 0, }
|
| -};
|
| -
|
| -const SecAsn1Template kKeyValuePairTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CSSM_X509_TYPE_VALUE_PAIR) },
|
| - { SEC_ASN1_OBJECT_ID, offsetof(CSSM_X509_TYPE_VALUE_PAIR, type), },
|
| - { SEC_ASN1_INLINE, 0, &kStringValueTemplate, },
|
| - { 0, }
|
| -};
|
| -
|
| -struct KeyValuePairs {
|
| - CSSM_X509_TYPE_VALUE_PAIR* pairs;
|
| -};
|
| -
|
| -const SecAsn1Template kKeyValuePairSetTemplate[] = {
|
| - { SEC_ASN1_SET_OF, offsetof(KeyValuePairs, pairs),
|
| - kKeyValuePairTemplate, sizeof(KeyValuePairs) }
|
| -};
|
| -
|
| -struct X509Name {
|
| - KeyValuePairs** pairs_list;
|
| -};
|
| -
|
| -const SecAsn1Template kNameTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE_OF, offsetof(X509Name, pairs_list),
|
| - kKeyValuePairSetTemplate, sizeof(X509Name) }
|
| -};
|
| -
|
| -// Converts raw CSSM_DATA to a std::string. (Char encoding is unaltered.)
|
| -std::string DataToString(CSSM_DATA data) {
|
| - return std::string(
|
| - reinterpret_cast<std::string::value_type*>(data.Data),
|
| - data.Length);
|
| -}
|
| -
|
| -// Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8.
|
| -std::string Latin1DataToUTF8String(CSSM_DATA data) {
|
| - base::string16 utf16;
|
| - if (!CodepageToUTF16(DataToString(data), base::kCodepageLatin1,
|
| - base::OnStringConversionError::FAIL, &utf16))
|
| - return "";
|
| - return UTF16ToUTF8(utf16);
|
| -}
|
| -
|
| -// Converts big-endian UTF-16 to UTF-8 in a std::string.
|
| -// Note: The byte-order flipping is done in place on the input buffer!
|
| -bool UTF16BigEndianToUTF8(char16* chars, size_t length,
|
| - std::string* out_string) {
|
| - for (size_t i = 0; i < length; i++)
|
| - chars[i] = EndianU16_BtoN(chars[i]);
|
| - return UTF16ToUTF8(chars, length, out_string);
|
| -}
|
| -
|
| -// Converts big-endian UTF-32 to UTF-8 in a std::string.
|
| -// Note: The byte-order flipping is done in place on the input buffer!
|
| -bool UTF32BigEndianToUTF8(char32* chars, size_t length,
|
| - std::string* out_string) {
|
| - for (size_t i = 0; i < length; ++i)
|
| - chars[i] = EndianS32_BtoN(chars[i]);
|
| -#if defined(WCHAR_T_IS_UTF32)
|
| - return WideToUTF8(reinterpret_cast<const wchar_t*>(chars),
|
| - length, out_string);
|
| -#else
|
| -#error This code doesn't handle 16-bit wchar_t.
|
| -#endif
|
| -}
|
| -
|
| -// Adds a type+value pair to the appropriate vector from a C array.
|
| -// The array is keyed by the matching OIDs from kOIDS[].
|
| -void AddTypeValuePair(const CSSM_OID type,
|
| - const std::string& value,
|
| - std::vector<std::string>* values[]) {
|
| - for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
|
| - if (CSSMOIDEqual(&type, kOIDs[oid])) {
|
| - values[oid]->push_back(value);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -// Stores the first string of the vector, if any, to *single_value.
|
| -void SetSingle(const std::vector<std::string>& values,
|
| - std::string* single_value) {
|
| - // We don't expect to have more than one CN, L, S, and C.
|
| - LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values";
|
| - if (!values.empty())
|
| - *single_value = values[0];
|
| -}
|
| -
|
| -bool match(const std::string& str, const std::string& against) {
|
| - // TODO(snej): Use the full matching rules specified in RFC 5280 sec. 7.1
|
| - // including trimming and case-folding: <http://www.ietf.org/rfc/rfc5280.txt>.
|
| - return against == str;
|
| -}
|
| -
|
| -bool match(const std::vector<std::string>& rdn1,
|
| - const std::vector<std::string>& rdn2) {
|
| - // "Two relative distinguished names RDN1 and RDN2 match if they have the
|
| - // same number of naming attributes and for each naming attribute in RDN1
|
| - // there is a matching naming attribute in RDN2." --RFC 5280 sec. 7.1.
|
| - if (rdn1.size() != rdn2.size())
|
| - return false;
|
| - for (unsigned i1 = 0; i1 < rdn1.size(); ++i1) {
|
| - unsigned i2;
|
| - for (i2 = 0; i2 < rdn2.size(); ++i2) {
|
| - if (match(rdn1[i1], rdn2[i2]))
|
| - break;
|
| - }
|
| - if (i2 == rdn2.size())
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
|
| - size_t length) {
|
| - DCHECK(ber_name_data);
|
| -
|
| - // First parse the BER |name_data| into the above structs.
|
| - SecAsn1CoderRef coder = NULL;
|
| - SecAsn1CoderCreate(&coder);
|
| - DCHECK(coder);
|
| - X509Name* name = NULL;
|
| - OSStatus err = SecAsn1Decode(coder, ber_name_data, length, kNameTemplate,
|
| - &name);
|
| - if (err) {
|
| - OSSTATUS_LOG(ERROR, err) << "SecAsn1Decode";
|
| - SecAsn1CoderRelease(coder);
|
| - return false;
|
| - }
|
| -
|
| - // Now scan the structs and add the values to my string vectors.
|
| - // I don't store multiple common/locality/state/country names, so use
|
| - // temporary vectors for those.
|
| - std::vector<std::string> common_names, locality_names, state_names,
|
| - country_names;
|
| - std::vector<std::string>* values[] = {
|
| - &common_names, &locality_names,
|
| - &state_names, &country_names,
|
| - &this->street_addresses,
|
| - &this->organization_names,
|
| - &this->organization_unit_names,
|
| - &this->domain_components
|
| - };
|
| - DCHECK(arraysize(kOIDs) == arraysize(values));
|
| -
|
| - for (int rdn = 0; name[rdn].pairs_list; ++rdn) {
|
| - CSSM_X509_TYPE_VALUE_PAIR* pair;
|
| - for (int pair_index = 0;
|
| - NULL != (pair = name[rdn].pairs_list[0][pair_index].pairs);
|
| - ++pair_index) {
|
| - switch (pair->valueType) {
|
| - case BER_TAG_IA5_STRING: // ASCII (that means 7-bit!)
|
| - case BER_TAG_PRINTABLE_STRING: // a subset of ASCII
|
| - case BER_TAG_PKIX_UTF8_STRING: // UTF-8
|
| - AddTypeValuePair(pair->type, DataToString(pair->value), values);
|
| - break;
|
| - case BER_TAG_T61_STRING: // T61, pretend it's Latin-1
|
| - AddTypeValuePair(pair->type,
|
| - Latin1DataToUTF8String(pair->value),
|
| - values);
|
| - break;
|
| - case BER_TAG_PKIX_BMP_STRING: { // UTF-16, big-endian
|
| - std::string value;
|
| - UTF16BigEndianToUTF8(reinterpret_cast<char16*>(pair->value.Data),
|
| - pair->value.Length / sizeof(char16),
|
| - &value);
|
| - AddTypeValuePair(pair->type, value, values);
|
| - break;
|
| - }
|
| - case BER_TAG_PKIX_UNIVERSAL_STRING: { // UTF-32, big-endian
|
| - std::string value;
|
| - UTF32BigEndianToUTF8(reinterpret_cast<char32*>(pair->value.Data),
|
| - pair->value.Length / sizeof(char32),
|
| - &value);
|
| - AddTypeValuePair(pair->type, value, values);
|
| - break;
|
| - }
|
| - default:
|
| - DCHECK_EQ(pair->valueType, BER_TAG_UNKNOWN);
|
| - // We don't know what data type this is, but we'll store it as a blob.
|
| - // Displaying the string may not work, but at least it can be compared
|
| - // byte-for-byte by a Matches() call.
|
| - AddTypeValuePair(pair->type, DataToString(pair->value), values);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - SetSingle(common_names, &this->common_name);
|
| - SetSingle(locality_names, &this->locality_name);
|
| - SetSingle(state_names, &this->state_or_province_name);
|
| - SetSingle(country_names, &this->country_name);
|
| -
|
| - // Releasing |coder| frees all the memory pointed to via |name|.
|
| - SecAsn1CoderRelease(coder);
|
| - return true;
|
| -}
|
| -
|
| -bool CertPrincipal::Matches(const CertPrincipal& against) const {
|
| - return match(common_name, against.common_name) &&
|
| - match(locality_name, against.locality_name) &&
|
| - match(state_or_province_name, against.state_or_province_name) &&
|
| - match(country_name, against.country_name) &&
|
| - match(street_addresses, against.street_addresses) &&
|
| - match(organization_names, against.organization_names) &&
|
| - match(organization_unit_names, against.organization_unit_names) &&
|
| - match(domain_components, against.domain_components);
|
| -}
|
| -
|
| -} // namespace net
|
|
|