| Index: net/base/x509_cert_types_win.cc
 | 
| diff --git a/net/base/x509_cert_types_win.cc b/net/base/x509_cert_types_win.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..0db63b1863e31b4f26711e9823d50b2bab853ae0
 | 
| --- /dev/null
 | 
| +++ b/net/base/x509_cert_types_win.cc
 | 
| @@ -0,0 +1,139 @@
 | 
| +// 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 <windows.h>
 | 
| +#include <wincrypt.h>
 | 
| +
 | 
| +#include "base/logging.h"
 | 
| +#include "base/memory/scoped_ptr.h"
 | 
| +#include "base/string_util.h"
 | 
| +#include "base/utf_string_conversions.h"
 | 
| +#include "crypto/capi_util.h"
 | 
| +
 | 
| +#pragma comment(lib, "crypt32.lib")
 | 
| +
 | 
| +namespace net {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +// 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 UTF-8 string, storing the result
 | 
| +// in |value|. Returns false if the string cannot be converted.
 | 
| +bool GetAttributeValue(PCERT_RDN_ATTR attribute,
 | 
| +                       std::string* value) {
 | 
| +  DWORD chars_needed = CertRDNValueToStrW(attribute->dwValueType,
 | 
| +                                          &attribute->Value, NULL, 0);
 | 
| +  if (chars_needed == 0)
 | 
| +    return false;
 | 
| +  if (chars_needed == 1) {
 | 
| +    // The value is actually an empty string (chars_needed includes a single
 | 
| +    // char for a NULL value). Don't bother converting - just clear the
 | 
| +    // string.
 | 
| +    value->clear();
 | 
| +    return true;
 | 
| +  }
 | 
| +  std::wstring wide_name;
 | 
| +  DWORD chars_written = CertRDNValueToStrW(
 | 
| +      attribute->dwValueType, &attribute->Value,
 | 
| +      WriteInto(&wide_name, chars_needed), chars_needed);
 | 
| +  if (chars_written <= 1)
 | 
| +    return false;
 | 
| +  wide_name.resize(chars_written - 1);
 | 
| +  *value = WideToUTF8(wide_name);
 | 
| +  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];
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
 | 
| +                                           size_t length) {
 | 
| +  DCHECK(ber_name_data);
 | 
| +
 | 
| +  CRYPT_DECODE_PARA decode_para;
 | 
| +  decode_para.cbSize = sizeof(decode_para);
 | 
| +  decode_para.pfnAlloc = crypto::CryptAlloc;
 | 
| +  decode_para.pfnFree = crypto::CryptFree;
 | 
| +  CERT_NAME_INFO* name_info = NULL;
 | 
| +  DWORD name_info_size = 0;
 | 
| +  BOOL rv;
 | 
| +  rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
 | 
| +                           X509_NAME,
 | 
| +                           reinterpret_cast<const BYTE*>(ber_name_data),
 | 
| +                           length,
 | 
| +                           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,
 | 
| +      &this->street_addresses,
 | 
| +      &this->organization_names,
 | 
| +      &this->organization_unit_names,
 | 
| +      &this->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, &this->common_name);
 | 
| +  SetSingle(locality_names, &this->locality_name);
 | 
| +  SetSingle(state_names, &this->state_or_province_name);
 | 
| +  SetSingle(country_names, &this->country_name);
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +}  // namespace net
 | 
| 
 |