summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authormdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 04:22:12 +0000
committermdm@chromium.org <mdm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-21 04:22:12 +0000
commitba46566966dafa8ea80a56b3a23fa896a82b67f9 (patch)
treeaba46c76702012bead5b7a92d6fd31c1b1ebc267 /net
parentf94ff9d982e6132277160486be59e1e424d04f79 (diff)
downloadchromium_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.cc52
-rw-r--r--net/base/x509_certificate.h4
-rw-r--r--net/http/http_response_info.cc5
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;