| 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
|
| index 14d5eee26b188bb7bb3e64504b1807f09d4756c6..c672863200a23e4b7376b9bc054bd2ef4a8caec2 100644
|
| --- a/net/base/x509_cert_types_mac.cc
|
| +++ b/net/base/x509_cert_types_mac.cc
|
| @@ -14,7 +14,9 @@
|
|
|
| namespace net {
|
|
|
| -static const CSSM_OID* kOIDs[] = {
|
| +namespace {
|
| +
|
| +const CSSM_OID* kOIDs[] = {
|
| &CSSMOID_CommonName,
|
| &CSSMOID_LocalityName,
|
| &CSSMOID_StateProvinceName,
|
| @@ -25,65 +27,6 @@ static const CSSM_OID* kOIDs[] = {
|
| &CSSMOID_DNQualifier // This should be "DC" but is undoubtedly wrong.
|
| }; // TODO(avi): Find the right OID.
|
|
|
| -// Converts raw CSSM_DATA to a std::string. (Char encoding is unaltered.)
|
| -static std::string DataToString(CSSM_DATA data);
|
| -
|
| -// Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8.
|
| -static std::string Latin1DataToUTF8String(CSSM_DATA data);
|
| -
|
| -// 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!
|
| -static bool UTF16BigEndianToUTF8(char16* chars, size_t length,
|
| - std::string* 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!
|
| -static bool UTF32BigEndianToUTF8(char32* chars, size_t length,
|
| - std::string* out_string);
|
| -
|
| -// Adds a type+value pair to the appropriate vector from a C array.
|
| -// The array is keyed by the matching OIDs from kOIDS[].
|
| - static void AddTypeValuePair(const CSSM_OID type,
|
| - const std::string& value,
|
| - std::vector<std::string>* values[]);
|
| -
|
| -// Stores the first string of the vector, if any, to *single_value.
|
| -static void SetSingle(const std::vector<std::string> &values,
|
| - std::string* single_value);
|
| -
|
| -
|
| -void CertPrincipal::Parse(const CSSM_X509_NAME* name) {
|
| - 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 (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];
|
| - AddTypeValuePair(pair_struct.type,
|
| - DataToString(pair_struct.value),
|
| - values);
|
| - }
|
| - }
|
| -
|
| - 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);
|
| -}
|
| -
|
| -
|
| // 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:
|
| @@ -108,7 +51,7 @@ struct KeyValuePair {
|
| };
|
| };
|
|
|
| -static const SecAsn1Template kStringValueTemplate[] = {
|
| +const SecAsn1Template kStringValueTemplate[] = {
|
| { SEC_ASN1_CHOICE, offsetof(KeyValuePair, value_type), },
|
| { SEC_ASN1_PRINTABLE_STRING,
|
| offsetof(KeyValuePair, value), 0, KeyValuePair::kTypePrintableString },
|
| @@ -125,7 +68,7 @@ static const SecAsn1Template kStringValueTemplate[] = {
|
| { 0, }
|
| };
|
|
|
| -static const SecAsn1Template kKeyValuePairTemplate[] = {
|
| +const SecAsn1Template kKeyValuePairTemplate[] = {
|
| { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KeyValuePair) },
|
| { SEC_ASN1_OBJECT_ID, offsetof(KeyValuePair, key), },
|
| { SEC_ASN1_INLINE, 0, &kStringValueTemplate, },
|
| @@ -136,8 +79,8 @@ struct KeyValuePairs {
|
| KeyValuePair* pairs;
|
| };
|
|
|
| -static const SecAsn1Template kKeyValuePairSetTemplate[] = {
|
| - { SEC_ASN1_SET_OF, offsetof(KeyValuePairs,pairs),
|
| +const SecAsn1Template kKeyValuePairSetTemplate[] = {
|
| + { SEC_ASN1_SET_OF, offsetof(KeyValuePairs, pairs),
|
| kKeyValuePairTemplate, sizeof(KeyValuePairs) }
|
| };
|
|
|
| @@ -145,11 +88,99 @@ struct X509Name {
|
| KeyValuePairs** pairs_list;
|
| };
|
|
|
| -static const SecAsn1Template kNameTemplate[] = {
|
| - { SEC_ASN1_SEQUENCE_OF, offsetof(X509Name,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) {
|
| + 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.size() > 0)
|
| + *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);
|
| @@ -182,7 +213,7 @@ bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
|
| };
|
| DCHECK(arraysize(kOIDs) == arraysize(values));
|
|
|
| - for (int rdn=0; name[rdn].pairs_list; ++rdn) {
|
| + for (int rdn = 0; name[rdn].pairs_list; ++rdn) {
|
| KeyValuePair *pair;
|
| for (int pair_index = 0;
|
| NULL != (pair = name[rdn].pairs_list[0][pair_index].pairs);
|
| @@ -235,59 +266,46 @@ bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
|
| return true;
|
| }
|
|
|
| +void CertPrincipal::Parse(const CSSM_X509_NAME* name) {
|
| + std::vector<std::string> common_names, locality_names, state_names,
|
| + country_names;
|
|
|
| -// SUBROUTINES:
|
| -
|
| -static std::string DataToString(CSSM_DATA data) {
|
| - return std::string(
|
| - reinterpret_cast<std::string::value_type*>(data.Data),
|
| - data.Length);
|
| -}
|
| -
|
| -static std::string Latin1DataToUTF8String(CSSM_DATA data) {
|
| - string16 utf16;
|
| - if (!CodepageToUTF16(DataToString(data), base::kCodepageLatin1,
|
| - base::OnStringConversionError::FAIL, &utf16))
|
| - return "";
|
| - return UTF16ToUTF8(utf16);
|
| -}
|
| -
|
| -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);
|
| -}
|
| -
|
| -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
|
| -}
|
| + 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));
|
|
|
| - static 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;
|
| + 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];
|
| + AddTypeValuePair(pair_struct.type,
|
| + DataToString(pair_struct.value),
|
| + values);
|
| }
|
| }
|
| +
|
| + 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);
|
| }
|
|
|
| -static 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.size() > 0)
|
| - *single_value = values[0];
|
| +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
|
|
|