| Index: net/base/x509_certificate_win.cc
|
| diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
|
| index 12acdaf363ecf77baa4c5ed218832fa6a67269ad..c04ff4d0284e1d6c05ab488dfc0d8da0a7404d3a 100644
|
| --- a/net/base/x509_certificate_win.cc
|
| +++ b/net/base/x509_certificate_win.cc
|
| @@ -408,70 +408,6 @@ void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
|
| output->reset(policies_info);
|
| }
|
|
|
| -// Helper function to parse a principal from a WinInet description of that
|
| -// principal.
|
| -void ParsePrincipal(const std::string& description,
|
| - CertPrincipal* 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;
|
| -
|
| - // TODO(jcampan): add business_category and serial_number.
|
| - const std::string kPrefixes[] = { 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[] = {
|
| - &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. If there is more
|
| - // than one entry for CN, L, S, and C, we will use the first entry. Although
|
| - // RFC 2818 Section 3.1 says the "most specific" CN should be used, that term
|
| - // has been removed in draft-saintandre-tls-server-id-check, which requires
|
| - // that the Subject field contains only one CN. So it is fine for us to just
|
| - // use the first CN.
|
| - 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());
|
| - if (!single_value_lists[i]->empty())
|
| - *(single_values[i]) = (*(single_value_lists[i]))[0];
|
| - }
|
| -}
|
| -
|
| void AddCertsFromStore(HCERTSTORE store,
|
| X509Certificate::OSCertHandles* results) {
|
| PCCERT_CONTEXT cert = NULL;
|
| @@ -546,35 +482,119 @@ void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain,
|
| }
|
| }
|
|
|
| +// A list of OIDs to decode. Any OID not on this list will be ignored for
|
| +// purposes of parsing.
|
| +const char* kOIDs[] = {
|
| + szOID_COMMON_NAME,
|
| + szOID_LOCALITY_NAME,
|
| + szOID_STATE_OR_PROVINCE_NAME,
|
| + szOID_COUNTRY_NAME,
|
| + szOID_STREET_ADDRESS,
|
| + szOID_ORGANIZATION_NAME,
|
| + szOID_ORGANIZATIONAL_UNIT_NAME,
|
| + szOID_DOMAIN_COMPONENT
|
| +};
|
| +
|
| +// Converts the value for |attribute| to an ASCII string, storing the result
|
| +// in |value|. Returns false if the string cannot be converted.
|
| +bool GetAttributeValue(PCERT_RDN_ATTR attribute,
|
| + std::string* value) {
|
| + DWORD bytes_needed = CertRDNValueToStrA(attribute->dwValueType,
|
| + &attribute->Value, NULL, 0);
|
| + if (bytes_needed == 0)
|
| + return false;
|
| + if (bytes_needed == 1) {
|
| + // The value is actually an empty string (bytes_needed includes a single
|
| + // byte for a NULL value). Don't bother converting - just clear the
|
| + // string.
|
| + value->clear();
|
| + return true;
|
| + }
|
| + DWORD bytes_written = CertRDNValueToStrA(
|
| + attribute->dwValueType, &attribute->Value,
|
| + WriteInto(value, bytes_needed), bytes_needed);
|
| + if (bytes_written <= 1)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +// Adds a type+value pair to the appropriate vector from a C array.
|
| +// The array is keyed by the matching OIDs from kOIDS[].
|
| +bool AddTypeValuePair(PCERT_RDN_ATTR attribute,
|
| + std::vector<std::string>* values[]) {
|
| + for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
|
| + if (strcmp(attribute->pszObjId, kOIDs[oid]) == 0) {
|
| + std::string value;
|
| + if (!GetAttributeValue(attribute, &value))
|
| + return false;
|
| + values[oid]->push_back(value);
|
| + break;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// 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 ParsePrincipal(CERT_NAME_BLOB* name, CertPrincipal* principal) {
|
| + CRYPT_DECODE_PARA decode_para;
|
| + decode_para.cbSize = sizeof(decode_para);
|
| + decode_para.pfnAlloc = MyCryptAlloc;
|
| + decode_para.pfnFree = MyCryptFree;
|
| + CERT_NAME_INFO* name_info = NULL;
|
| + DWORD name_info_size = 0;
|
| + BOOL rv;
|
| + rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
| + X509_NAME, name->pbData, name->cbData,
|
| + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
|
| + &decode_para,
|
| + &name_info, &name_info_size);
|
| + if (!rv)
|
| + return false;
|
| + scoped_ptr_malloc<CERT_NAME_INFO> scoped_name_info(name_info);
|
| +
|
| + 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,
|
| + &(principal->street_addresses),
|
| + &(principal->organization_names),
|
| + &(principal->organization_unit_names),
|
| + &(principal->domain_components)
|
| + };
|
| + DCHECK(arraysize(kOIDs) == arraysize(values));
|
| +
|
| + for (DWORD cur_rdn = 0; cur_rdn < name_info->cRDN; ++cur_rdn) {
|
| + PCERT_RDN rdn = &name_info->rgRDN[cur_rdn];
|
| + for (DWORD cur_ava = 0; cur_ava < rdn->cRDNAttr; ++cur_ava) {
|
| + PCERT_RDN_ATTR ava = &rdn->rgRDNAttr[cur_ava];
|
| + if (!AddTypeValuePair(ava, values))
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + SetSingle(common_names, &principal->common_name);
|
| + SetSingle(locality_names, &principal->locality_name);
|
| + SetSingle(state_names, &principal->state_or_province_name);
|
| + SetSingle(country_names, &principal->country_name);
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| void X509Certificate::Initialize() {
|
| - std::wstring subject_info;
|
| - std::wstring issuer_info;
|
| - DWORD name_size;
|
| DCHECK(cert_handle_);
|
| - name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
|
| - &cert_handle_->pCertInfo->Subject,
|
| - CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
|
| - NULL, 0);
|
| - if (name_size > 1) {
|
| - 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);
|
| - if (name_size > 1) {
|
| - 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_);
|
| + ParsePrincipal(&cert_handle_->pCertInfo->Subject, &subject_);
|
| + ParsePrincipal(&cert_handle_->pCertInfo->Issuer, &issuer_);
|
|
|
| valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore);
|
| valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
|
|
|