diff options
author | mdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-21 04:22:12 +0000 |
---|---|---|
committer | mdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-21 04:22:12 +0000 |
commit | ba46566966dafa8ea80a56b3a23fa896a82b67f9 (patch) | |
tree | aba46c76702012bead5b7a92d6fd31c1b1ebc267 /net | |
parent | f94ff9d982e6132277160486be59e1e424d04f79 (diff) | |
download | chromium_src-ba46566966dafa8ea80a56b3a23fa896a82b67f9.zip chromium_src-ba46566966dafa8ea80a56b3a23fa896a82b67f9.tar.gz chromium_src-ba46566966dafa8ea80a56b3a23fa896a82b67f9.tar.bz2 |
Avoid using Pickle::WriteSize(), which writes an architecture-dependent amount
of data, in X.509 pickles. (The goal is to remove that method entirely.
Uses that never persist or send pickles over the network are [probably] safe,
but having the method around is waiting for accidental misuses.)
These pickles can be persisted on disk, so I've adjusted the code to be able to
read old 64-bit pickles on platforms that previously wrote such pickles. New
pickles will be written with 32-bit values on all platforms.
BUG=cros:27159
Review URL: http://codereview.chromium.org/9693013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127901 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/x509_certificate.cc | 52 | ||||
-rw-r--r-- | net/base/x509_certificate.h | 4 | ||||
-rw-r--r-- | net/http/http_response_info.cc | 5 |
3 files changed, 54 insertions, 7 deletions
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index ca8299e..b42bd87 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -332,14 +332,49 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, return NULL; OSCertHandles intermediates; - size_t num_intermediates = 0; - if (type == PICKLETYPE_CERTIFICATE_CHAIN) { - if (!pickle.ReadSize(pickle_iter, &num_intermediates)) { + uint32 num_intermediates = 0; + if (type != PICKLETYPE_SINGLE_CERTIFICATE) { + if (!pickle.ReadUInt32(pickle_iter, &num_intermediates)) { FreeOSCertHandle(cert_handle); return NULL; } - for (size_t i = 0; i < num_intermediates; ++i) { +#if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(__x86_64__) + // On 64-bit Linux (and any other 64-bit platforms), the intermediate count + // might really be a 64-bit field since we used to use Pickle::WriteSize(), + // which writes either 32 or 64 bits depending on the architecture. Since + // x86-64 is little-endian, if that happens, the next 32 bits will be all + // zeroes (the high bits) and the 32 bits we already read above are the + // correct value (we assume there are never more than 2^32 - 1 intermediate + // certificates in a chain; in practice, more than a dozen or so is + // basically unheard of). Since it's invalid for a certificate to start with + // 32 bits of zeroes, we check for that here and skip it if we find it. We + // save a copy of the pickle iterator to restore in case we don't get 32 + // bits of zeroes. Now we always write 32 bits, so after a while, these old + // cached pickles will all get replaced. + // TODO(mdm): remove this compatibility code in April 2013 or so. + if (type == PICKLETYPE_CERTIFICATE_CHAIN_OLD) { + PickleIterator saved_iter = *pickle_iter; + uint32 zero_check = 0; + if (!pickle.ReadUInt32(pickle_iter, &zero_check)) { + // This may not be an error. If there are no intermediates, and we're + // reading an old 32-bit pickle, and there's nothing else after this in + // the pickle, we should report success. Note that it is technically + // possible for us to skip over zeroes that should have occurred after + // an empty certificate list; to avoid this going forward, only do this + // backward-compatibility stuff for PICKLETYPE_CERTIFICATE_CHAIN_OLD + // which comes from the pickle version number in http_response_info.cc. + if (num_intermediates) { + FreeOSCertHandle(cert_handle); + return NULL; + } + } + if (zero_check) + *pickle_iter = saved_iter; + } +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && defined(__x86_64__) + + for (uint32 i = 0; i < num_intermediates; ++i) { OSCertHandle intermediate = ReadOSCertHandleFromPickle(pickle, pickle_iter); if (!intermediate) @@ -442,7 +477,14 @@ void X509Certificate::Persist(Pickle* pickle) { return; } - if (!pickle->WriteSize(intermediate_ca_certs_.size())) { + // This would be an absolutely insane number of intermediates. + if (intermediate_ca_certs_.size() >= 0xFFFFFFFF) { + NOTREACHED(); + return; + } + + if (!pickle->WriteUInt32( + static_cast<uint32>(intermediate_ca_certs_.size()))) { NOTREACHED(); return; } diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h index 5c07284..c22e940 100644 --- a/net/base/x509_certificate.h +++ b/net/base/x509_certificate.h @@ -130,6 +130,10 @@ class NET_EXPORT X509Certificate // When reading a certificate from a Pickle, the Pickle contains the // the certificate plus any certificates that were stored in // |intermediate_ca_certificates_| at the time it was serialized. + // The count of certificates is stored as either 32 or 64 bits. + PICKLETYPE_CERTIFICATE_CHAIN_OLD, + + // Same as PICKLETYPE_CERTIFICATE_CHAIN_OLD but with a 32-bit cert count. PICKLETYPE_CERTIFICATE_CHAIN, }; diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index 542bdb0..bacffc3 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc @@ -22,7 +22,7 @@ namespace net { // serialized HttpResponseInfo. enum { // The version of the response info used when persisting response info. - RESPONSE_INFO_VERSION = 2, + RESPONSE_INFO_VERSION = 3, // The minimum version supported for deserializing response info. RESPONSE_INFO_MINIMUM_VERSION = 1, @@ -150,7 +150,8 @@ bool HttpResponseInfo::InitFromPickle(const Pickle& pickle, if (flags & RESPONSE_INFO_HAS_CERT) { X509Certificate::PickleType type = (version == 1) ? X509Certificate::PICKLETYPE_SINGLE_CERTIFICATE : - X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN; + (version == 2) ? X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_OLD : + X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN; ssl_info.cert = X509Certificate::CreateFromPickle(pickle, &iter, type); if (!ssl_info.cert) return false; |