summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/SConscript3
-rw-r--r--net/base/x509_certificate.h23
-rw-r--r--net/base/x509_certificate_mac.cc390
-rw-r--r--net/base/x509_certificate_win.cc (renamed from net/base/x509_certificate.cc)0
-rw-r--r--net/build/net.vcproj2
-rw-r--r--net/net.xcodeproj/project.pbxproj6
-rw-r--r--webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj4
7 files changed, 422 insertions, 6 deletions
diff --git a/net/SConscript b/net/SConscript
index 8348602..fe95094 100644
--- a/net/SConscript
+++ b/net/SConscript
@@ -92,7 +92,7 @@ if env['PLATFORM'] == 'win32':
'base/upload_data_stream.cc',
'base/wininet_util.cc',
'base/winsock_init.cc',
- 'base/x509_certificate.cc',
+ 'base/x509_certificate_win.cc',
'http/http_network_layer.cc',
'http/http_network_transaction.cc',
'http/http_transaction_winhttp.cc',
@@ -126,6 +126,7 @@ if env['PLATFORM'] == 'win32':
if env['PLATFORM'] == 'darwin':
input_files.extend([
'base/platform_mime_util_mac.mm',
+ 'base/x509_certificate_mac.cc',
])
if env['PLATFORM'] == 'posix':
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index 4411322..645454e 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -15,6 +15,8 @@
#if defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>
+#elif defined(OS_MACOSX)
+#include <Security/Security.h>
#endif
class Pickle;
@@ -44,6 +46,8 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
#if defined(OS_WIN)
typedef PCCERT_CONTEXT OSCertHandle;
+#elif defined(OS_MACOSX)
+ typedef SecCertificateRef OSCertHandle;
#else
// TODO(ericroman): not implemented
typedef void* OSCertHandle;
@@ -102,12 +106,14 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
};
// Create an X509Certificate from a handle to the certificate object
- // in the underlying crypto library.
+ // in the underlying crypto library. This is a transfer of ownership;
+ // X509Certificate will properly dispose of |cert_handle| for you.
static X509Certificate* CreateFromHandle(OSCertHandle cert_handle);
// Create an X509Certificate from the representation stored in the given
// pickle. The data for this object is found relative to the given
// pickle_iter, which should be passed to the pickle's various Read* methods.
+ // Returns NULL on failure.
static X509Certificate* CreateFromPickle(const Pickle& pickle,
void** pickle_iter);
@@ -127,6 +133,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// The issuer of the certificate.
const Principal& issuer() const { return issuer_; }
+#if defined(OS_WIN)
// Time period during which the certificate is valid. More precisely, this
// certificate is invalid before the |valid_start| date and invalid after
// the |valid_expiry| date.
@@ -134,6 +141,12 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// lacks either date), the date will be null (i.e., is_null() will be true).
const Time& valid_start() const { return valid_start_; }
const Time& valid_expiry() const { return valid_expiry_; }
+#elif defined(OS_MACOSX)
+ // These are used only for some UI, where HasExpired is used to disambiguate a
+ // time error on the certificate as a "too old" or "too young" error. On the
+ // Mac you get different codes for those. There's no easy way of pulling dates
+ // out of the cert short of CSSM, so these remain unimplemented for now.
+#endif
// The fingerprint of this certificate.
const Fingerprint& fingerprint() const { return fingerprint_; }
@@ -144,9 +157,11 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// Otherwise, it gets the common name in the subject field.
void GetDNSNames(std::vector<std::string>* dns_names) const;
+#if defined(OS_WIN)
// Convenience method that returns whether this certificate has expired as of
// now.
bool HasExpired() const;
+#endif
// Returns true if the certificate is an extended-validation (EV)
// certificate.
@@ -168,10 +183,12 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// Common object initialization code. Called by the constructors only.
void Initialize();
+#if defined(OS_WIN)
// Helper function to parse a principal from a WinInet description of that
// principal.
static void ParsePrincipal(const std::string& description,
Principal* principal);
+#endif
// The subject of the certificate.
Principal subject_;
@@ -179,11 +196,13 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// The issuer of the certificate.
Principal issuer_;
+#if defined(OS_WIN)
// This certificate is not valid before |valid_start_|
Time valid_start_;
// This certificate is not valid after |valid_expiry_|
Time valid_expiry_;
+#endif
// The fingerprint of this certificate.
Fingerprint fingerprint_;
@@ -191,7 +210,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// A handle to the certificate object in the underlying crypto library.
OSCertHandle cert_handle_;
- DISALLOW_EVIL_CONSTRUCTORS(X509Certificate);
+ DISALLOW_COPY_AND_ASSIGN(X509Certificate);
};
} // namespace net
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
new file mode 100644
index 0000000..a65bec1
--- /dev/null
+++ b/net/base/x509_certificate_mac.cc
@@ -0,0 +1,390 @@
+// Copyright (c) 2006-2008 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_certificate.h"
+
+#include <CommonCrypto/CommonDigest.h>
+#include <map>
+
+#include "base/histogram.h"
+#include "base/lock.h"
+#include "base/pickle.h"
+#include "base/singleton.h"
+#include "base/string_tokenizer.h"
+#include "base/string_util.h"
+#include "net/base/cert_status_flags.h"
+#include "net/base/ev_root_ca_metadata.h"
+
+// 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 {
+
+namespace {
+
+// 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 (size_t i = 0; i < arraysize(fingerprint.data); ++i) {
+ if (fingerprint.data[i] != 0)
+ return false;
+ }
+ return true;
+}
+
+// Calculates the SHA-1 fingerprint of the certificate. Returns an empty
+// (all zero) fingerprint on failure.
+X509Certificate::Fingerprint CalculateFingerprint(
+ X509Certificate::OSCertHandle cert) {
+ // The Windows code uses CryptHashCertificate, a function specially designed
+ // 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;
+ 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;
+}
+
+inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
+ return oid1->Length == oid2->Length &&
+ (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
+}
+
+void ParsePrincipal(const CSSM_X509_NAME* name,
+ X509Certificate::Principal* principal) {
+ std::vector<std::string> common_names, locality_names, state_names,
+ country_names;
+
+ // TODO(jcampan): add business_category and serial_number.
+ const CSSM_OID* kOIDs[] = { &CSSMOID_CommonName,
+ &CSSMOID_LocalityName,
+ &CSSMOID_StateProvinceName,
+ &CSSMOID_CountryName,
+ &CSSMOID_StreetAddress,
+ &CSSMOID_OrganizationName,
+ &CSSMOID_OrganizationalUnitName,
+ &CSSMOID_DNQualifier }; // This should be "DC"
+ // but is undoubtedly
+ // wrong. TODO(avi):
+ // Find the right OID.
+
+ 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 (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;
+ }
+ }
+ }
+ }
+
+ // 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];
+ }
+}
+
+void GetCertFieldsForOID(X509Certificate::OSCertHandle cert_handle,
+ CSSM_OID oid,
+ std::vector<std::string>* result) {
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
+ if (status)
+ return;
+
+ CSSM_CL_HANDLE clHandle;
+ status = SecCertificateGetCLHandle(cert_handle, &clHandle);
+ if (status)
+ return;
+
+ uint32 numOfFields;
+ 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;
+ }
+ }
+}
+
+} // namespace
+
+bool X509Certificate::FingerprintLessThan::operator()(
+ const Fingerprint& lhs,
+ const Fingerprint& rhs) const {
+ 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])
+ return false;
+ }
+ return false;
+}
+
+bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
+ X509Certificate* rhs) const {
+ if (lhs == rhs)
+ return false;
+
+ X509Certificate::FingerprintLessThan fingerprint_functor;
+ return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
+}
+
+// A thread-safe cache for X509Certificate objects.
+//
+// The cache does not hold a reference to the certificate objects. The objects
+// must |Remove| themselves from the cache upon destruction (or else the cache
+// will be holding dead pointers to the objects).
+class X509Certificate::Cache {
+ public:
+ // Get the singleton object for the cache.
+ static X509Certificate::Cache* GetInstance() {
+ return Singleton<X509Certificate::Cache>::get();
+ }
+
+ // Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache
+ // must not already contain a certificate with the same fingerprint.
+ void Insert(X509Certificate* cert) {
+ AutoLock lock(lock_);
+
+ DCHECK(!IsNullFingerprint(cert->fingerprint())) <<
+ "Only insert certs with real fingerprints.";
+ DCHECK(cache_.find(cert->fingerprint()) == cache_.end());
+ cache_[cert->fingerprint()] = cert;
+ };
+
+ // Remove |cert| from the cache. The cache does not assume that |cert| is
+ // already in the cache.
+ void Remove(X509Certificate* cert) {
+ AutoLock lock(lock_);
+
+ CertMap::iterator pos(cache_.find(cert->fingerprint()));
+ if (pos == cache_.end())
+ return; // It is not an error to remove a cert that is not in the cache.
+ cache_.erase(pos);
+ };
+
+ // Find a certificate in the cache with the given fingerprint. If one does
+ // not exist, this method returns NULL.
+ X509Certificate* Find(const Fingerprint& fingerprint) {
+ AutoLock lock(lock_);
+
+ CertMap::iterator pos(cache_.find(fingerprint));
+ if (pos == cache_.end())
+ return NULL;
+
+ return pos->second;
+ };
+
+ private:
+ typedef std::map<Fingerprint, X509Certificate*, FingerprintLessThan> CertMap;
+
+ // Obtain an instance of X509Certificate::Cache via GetInstance().
+ 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.
+ Lock lock_;
+
+ // The certificate cache. You must acquire |lock_| before using |cache_|.
+ CertMap cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(Cache);
+};
+
+void X509Certificate::Initialize() {
+ 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.
+ X509Certificate::Cache::GetInstance()->Insert(this);
+}
+
+// static
+X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) {
+ DCHECK(cert_handle);
+
+ // Check if we already have this certificate in memory.
+ X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance();
+ X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle));
+ 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.
+ CFRelease(cert_handle);
+ DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
+ return cert;
+ }
+ // Otherwise, allocate a new object.
+ return new X509Certificate(cert_handle);
+}
+
+// static
+X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
+ void** pickle_iter) {
+ const char* data;
+ 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;
+ OSStatus status = SecCertificateCreateFromData(&cert_data,
+ CSSM_CERT_X_509v3,
+ CSSM_CERT_ENCODING_BER,
+ &cert_handle);
+ if (status)
+ return NULL;
+
+ return CreateFromHandle(cert_handle);
+}
+
+X509Certificate::X509Certificate(OSCertHandle cert_handle)
+ : cert_handle_(cert_handle) {
+ Initialize();
+}
+
+X509Certificate::X509Certificate(std::string subject, std::string issuer,
+ Time, Time)
+ : subject_(subject),
+ issuer_(issuer),
+ cert_handle_(NULL) {
+ memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
+}
+
+void X509Certificate::Persist(Pickle* pickle) {
+ CSSM_DATA cert_data;
+ OSStatus status = SecCertificateGetData(cert_handle_, &cert_data);
+ if (status) {
+ NOTREACHED();
+ return;
+ }
+
+ 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_)
+ CFRelease(cert_handle_);
+}
+
+void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
+ dns_names->clear();
+
+ GetCertFieldsForOID(cert_handle_, CSSMOID_SubjectAltName, dns_names);
+
+ if (dns_names->empty())
+ dns_names->push_back(subject_.common_name);
+}
+
+// Returns true if the certificate is an extended-validation certificate.
+//
+// The certificate has already been verified by the HTTP library. cert_status
+// represents the result of that verification. This function performs
+// additional checks of the certificatePolicies extensions of the certificates
+// in the certificate chain according to Section 7 (pp. 11-12) of the EV
+// Certificate Guidelines Version 1.0 at
+// http://cabforum.org/EV_Certificate_Guidelines.pdf.
+bool X509Certificate::IsEV(int cert_status) const {
+ // TODO(avi): implement this
+ NOTIMPLEMENTED();
+ return false;
+}
+
+X509Certificate::Policy::Judgment X509Certificate::Policy::Check(
+ X509Certificate* cert) const {
+ // It shouldn't matter which set we check first, but we check denied first
+ // in case something strange has happened.
+
+ if (denied_.find(cert->fingerprint()) != denied_.end()) {
+ // DCHECK that the order didn't matter.
+ DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end());
+ return DENIED;
+ }
+
+ if (allowed_.find(cert->fingerprint()) != allowed_.end()) {
+ // DCHECK that the order didn't matter.
+ DCHECK(denied_.find(cert->fingerprint()) == denied_.end());
+ return ALLOWED;
+ }
+
+ // We don't have a policy for this cert.
+ return UNKNOWN;
+}
+
+void X509Certificate::Policy::Allow(X509Certificate* cert) {
+ // Put the cert in the allowed set and (maybe) remove it from the denied set.
+ denied_.erase(cert->fingerprint());
+ allowed_.insert(cert->fingerprint());
+}
+
+void X509Certificate::Policy::Deny(X509Certificate* cert) {
+ // Put the cert in the denied set and (maybe) remove it from the allowed set.
+ allowed_.erase(cert->fingerprint());
+ denied_.insert(cert->fingerprint());
+}
+
+} // namespace net
+
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate_win.cc
index ab3fe64..ab3fe64 100644
--- a/net/base/x509_certificate.cc
+++ b/net/base/x509_certificate_win.cc
diff --git a/net/build/net.vcproj b/net/build/net.vcproj
index 069db63..d4e779b 100644
--- a/net/build/net.vcproj
+++ b/net/build/net.vcproj
@@ -477,7 +477,7 @@
>
</File>
<File
- RelativePath="..\base\x509_certificate.cc"
+ RelativePath="..\base\x509_certificate_win.cc"
>
</File>
<File
diff --git a/net/net.xcodeproj/project.pbxproj b/net/net.xcodeproj/project.pbxproj
index 89a3146..9402388 100644
--- a/net/net.xcodeproj/project.pbxproj
+++ b/net/net.xcodeproj/project.pbxproj
@@ -123,6 +123,7 @@
821F23CA0E5E106B003C7E38 /* url_request_job.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED33980E5A198600A747DB /* url_request_job.cc */; };
821F23CC0E5E106D003C7E38 /* url_request_simple_job.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED339C0E5A198600A747DB /* url_request_simple_job.cc */; };
825C2FCC0E5C968B00FDEAB7 /* ev_root_ca_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32BE0E5A181C00A747DB /* ev_root_ca_metadata.cc */; };
+ 827E139D0E81611D00183614 /* x509_certificate_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32800E5A181C00A747DB /* x509_certificate_mac.cc */; };
82ECB3090E5B651D00A913E3 /* mime_sniffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32AD0E5A181C00A747DB /* mime_sniffer.cc */; };
B5F622260E805FC40076681A /* url_request_job_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED33A30E5A198600A747DB /* url_request_job_manager.cc */; };
BAA46E3B0E5CE99A00E77460 /* net_util_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED329F0E5A181C00A747DB /* net_util_unittest.cc */; };
@@ -389,7 +390,7 @@
7BED327D0E5A181C00A747DB /* address_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = address_list.h; sourceTree = "<group>"; };
7BED327E0E5A181C00A747DB /* address_list.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = address_list.cc; sourceTree = "<group>"; };
7BED327F0E5A181C00A747DB /* x509_certificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509_certificate.h; sourceTree = "<group>"; };
- 7BED32800E5A181C00A747DB /* x509_certificate.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x509_certificate.cc; sourceTree = "<group>"; };
+ 7BED32800E5A181C00A747DB /* x509_certificate_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x509_certificate_mac.cc; sourceTree = "<group>"; };
7BED32860E5A181C00A747DB /* upload_data_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = upload_data_stream.h; sourceTree = "<group>"; };
7BED32870E5A181C00A747DB /* upload_data_stream.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = upload_data_stream.cc; sourceTree = "<group>"; };
7BED32880E5A181C00A747DB /* upload_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = upload_data.h; sourceTree = "<group>"; };
@@ -835,7 +836,7 @@
7BED32880E5A181C00A747DB /* upload_data.h */,
7BED32870E5A181C00A747DB /* upload_data_stream.cc */,
7BED32860E5A181C00A747DB /* upload_data_stream.h */,
- 7BED32800E5A181C00A747DB /* x509_certificate.cc */,
+ 7BED32800E5A181C00A747DB /* x509_certificate_mac.cc */,
7BED327F0E5A181C00A747DB /* x509_certificate.h */,
);
path = base;
@@ -1282,6 +1283,7 @@
7B8504540E5B2E9600730B43 /* url_request_job_tracker.cc in Sources */,
821F23CC0E5E106D003C7E38 /* url_request_simple_job.cc in Sources */,
821F20A50E5CD414003C7E38 /* url_request_view_cache_job.cc in Sources */,
+ 827E139D0E81611D00183614 /* x509_certificate_mac.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
index f23c6d3..a966573 100644
--- a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
+++ b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 82F372150E82AE0500DF5AFE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82F372140E82AE0500DF5AFE /* Security.framework */; };
82F399480E7EE4D500785E15 /* libWebKitSystemInterfaceLeopard.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 82F399470E7EE4D500785E15 /* libWebKitSystemInterfaceLeopard.a */; };
82F399B70E7EF75800785E15 /* libbase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B8205260E770291008F45CF /* libbase.a */; };
82F399B80E7EF75A00785E15 /* libbase_gfx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B8205280E770291008F45CF /* libbase_gfx.a */; };
@@ -527,6 +528,7 @@
829E35270DC0C95300819EBF /* icu.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = icu.xcodeproj; path = third_party/icu38/icu.xcodeproj; sourceTree = "<group>"; };
829E35590DC0D37B00819EBF /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = "<group>"; };
829E355C0DC0D47400819EBF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = "<group>"; };
+ 82F372140E82AE0500DF5AFE /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
82F399470E7EE4D500785E15 /* libWebKitSystemInterfaceLeopard.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libWebKitSystemInterfaceLeopard.a; path = temp/libWebKitSystemInterfaceLeopard.a; sourceTree = "<group>"; };
82F39A1C0E7EF85C00785E15 /* gtest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = gtest.xcodeproj; path = testing/gtest.xcodeproj; sourceTree = "<group>"; };
82F39CFF0E7EF95A00785E15 /* modp_b64.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = modp_b64.xcodeproj; path = third_party/modp_b64/modp_b64.xcodeproj; sourceTree = "<group>"; };
@@ -600,6 +602,7 @@
82F39D400E7EFD9300785E15 /* libxml.a in Frameworks */,
82F39CF40E7EF90F00785E15 /* libzlib.a in Frameworks */,
E456292D0E26B4FE005E4685 /* QuartzCore.framework in Frameworks */,
+ 82F372150E82AE0500DF5AFE /* Security.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -648,6 +651,7 @@
13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
29B97325FDCFA39411CA2CEA /* Foundation.framework */,
829E355C0DC0D47400819EBF /* QuartzCore.framework */,
+ 82F372140E82AE0500DF5AFE /* Security.framework */,
);
name = Frameworks;
sourceTree = SDKROOT;