Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Unified Diff: net/base/x509_certificate_mac.cc

Issue 2668005: Bring the handling of <keygen> and support for the application/x-x509-user-ce... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Whitespace/style Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/x509_certificate_mac.cc
===================================================================
--- net/base/x509_certificate_mac.cc (revision 49024)
+++ net/base/x509_certificate_mac.cc (working copy)
@@ -8,6 +8,8 @@
#include <Security/Security.h>
#include <time.h>
+#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/scoped_cftyperef.h"
#include "base/logging.h"
#include "base/pickle.h"
@@ -358,6 +360,80 @@
return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
}
+void AddCertificatesFromData(const char* data, size_t length,
+ SecExternalFormat format,
+ X509Certificate::OSCertHandles* output) {
+ // In order to use SecKeychainItemImport successfully, a destination
+ // keychain must be specified to receive the created objects. Further,
+ // the created objects remain valid only for as long as the keychain does.
+ // In order to match the handling on Windows/NSS, which has the handles
+ // valid for an arbitrary length of time, a temporary keychain is created,
+ // the certificates are imported into it, and then free-standing
+ // certificates are created from the DER representation of the original
+ // keychain item.
+ FilePath temp_file;
+ if (!file_util::CreateTemporaryFile(&temp_file))
+ return;
+
+ SecExternalFormat input_format = format;
+ scoped_cftyperef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data),
+ length, kCFAllocatorDefault);
+
+ scoped_cftyperef<SecKeychainRef> temp_keychain;
+ SecKeychainRef keychain = NULL;
+ OSStatus rv = SecKeychainCreate(temp_file.value().c_str(), 0, NULL, FALSE,
+ NULL, &keychain);
+ if (rv != noErr) {
+ DLOG(WARNING) << rv << " Unable to create temporary keychain at "
+ << temp_file.value();
+ return;
+ }
+
+ temp_keychain.reset(keychain);
+ keychain = NULL;
+
+ CFArrayRef items = NULL;
+ rv = SecKeychainItemImport(local_data, NULL, &input_format, NULL,
+ 0, NULL, NULL, temp_keychain, &items);
+ if (rv != noErr) {
+ scoped_cftyperef<CFArrayRef> scoped_items(items);
+ CFTypeID certTypeID = SecCertificateGetTypeID();
+
+ for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) {
+ SecKeychainItemRef item = CFArrayGetValueAtIndex(items, i);
+
+ // While inputFormat implies only certificates will be imported, if/when
+ // other formats (eg: PKCS#12) are supported, this may also include
+ // private keys or other items types, so filter appropriately.
+ if (CFGetTypeID(item) == certTypeID) {
+ // Create a freestanding SecCertificateRef from the keychain item.
+ // Unfortunately, this invokes a double-parse of the DER data, which
+ // is less than optimally efficient.
+ scoped_cftyperef<CFDataRef> scoped_cert_data =
+ SecCertificateCopyData(reinterpret_cast<SecCertificateRef>(item));
+ if (scoped_cert_data == NULL)
+ continue;
+
+ SecCertificateRef cert = SecCertificateCreateWithData(NULL,
+ scoped_cert_data);
+ if (cert == NULL)
+ continue;
+
+ output->push_back(cert);
+ }
+ } else {
+ DLOG(WARNING) << rv << " Unable to import items from data of length "
+ << length;
+ }
+
+ rv = SecKeychainDelete(temp_keychain);
+ if (rv != noErr) {
+ DLOG(WARNING) << rv << " Unable to remove temporary keychain at "
+ << temp_file.value();
+ }
+}
+
} // namespace
void X509Certificate::Initialize() {
@@ -387,7 +463,7 @@
if (!pickle.ReadData(pickle_iter, &data, &length))
return NULL;
- return CreateFromBytes(data, length);
+ return CreateFromBytes(data, length, X509Certificate::FORMAT_DER);
}
void X509Certificate::Persist(Pickle* pickle) {
@@ -647,7 +723,7 @@
// static
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
- const char* data, int length) {
+ const char* data, size_t length) {
CSSM_DATA cert_data;
cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
cert_data.Length = length;
@@ -664,6 +740,34 @@
}
// static
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
+ const char* data, size_t length, CertificateFormat format) {
+ OSCertHandles results;
+
+ switch (format) {
+ case FORMAT_DER:
+ {
+ OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
+ if (handle)
+ results.push_back(handle);
+ }
+ break;
+ case FORMAT_PKCS7:
+ AddCertificatesFromData(data, length, kSecFormatPKCS7, &results);
+ break;
+ case FORMAT_LEGACY_NETSCAPE:
+ AddCertificatesFromData(data, length, kSecFormatNetscapeCertSequence,
+ &results);
+ break;
+ default:
+ NOTREACHED() << "Certificate format " << format << " unimplemented";
+ break;
+ }
+
+ return results;
+}
+
+// static
X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
OSCertHandle handle) {
if (!handle)
@@ -763,7 +867,7 @@
}
// static
-bool X509Certificate::GetSSLClientCertificates (
+bool X509Certificate::GetSSLClientCertificates(
const std::string& server_domain,
const std::vector<Principal>& valid_issuers,
std::vector<scoped_refptr<X509Certificate> >* certs) {
@@ -775,7 +879,7 @@
SecIdentityRef identity = NULL;
if (SecIdentityCopyPreference(domain_str,
0,
- NULL, // validIssuers argument is ignored :(
+ NULL, // validIssuers argument is ignored :(
&identity) == noErr)
preferred_identity.reset(identity);
}
@@ -867,7 +971,7 @@
}
CFRelease(cert_chain);
}
-exit:
+ exit:
if (result)
LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
return chain.release();
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/base/x509_certificate_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698