summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2014-10-03 12:15:09 -0400
committerNick Mathewson <nickm@torproject.org>2014-10-03 12:15:09 -0400
commitd1fa0163e571913b8e4972c5c8a2d46798f46156 (patch)
treeece5b4ede52f43d47cfd8e8196a44102ee43661f
parent0c3b3650aa831183c76b044466e89eaee36d5684 (diff)
downloadtor-d1fa0163e571913b8e4972c5c8a2d46798f46156.tar.gz
tor-d1fa0163e571913b8e4972c5c8a2d46798f46156.zip
Run correctly on OpenBSD systems without SSL_METHOD.get_cipher_by_char
Also, make sure we will compile correctly on systems where they finally rip it out. Fixes issue #13325. Caused by this openbsd commit: ​http://marc.info/?l=openbsd-cvs&m=140768179627976&w=2 Reported by Fredzupy.
-rw-r--r--changes/bug133254
-rw-r--r--configure.ac4
-rw-r--r--src/common/tortls.c48
3 files changed, 46 insertions, 10 deletions
diff --git a/changes/bug13325 b/changes/bug13325
new file mode 100644
index 0000000000..b1da4d0bd5
--- /dev/null
+++ b/changes/bug13325
@@ -0,0 +1,4 @@
+ o Compilation fixes:
+ - Build and run correctly on systems like OpenBSD-current that
+ have patched OpenSSL to remove get_cipher_by_char and/or its
+ implementations. Fixes issue 13325.
diff --git a/configure.ac b/configure.ac
index 3456013320..35484748ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -524,6 +524,10 @@ else
fi
AC_SUBST(TOR_OPENSSL_LIBS)
+AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
+[#include <openssl/ssl.h>
+])
+
dnl ------------------------------------------------------
dnl Where do you live, zlib? And how do we call you?
diff --git a/src/common/tortls.c b/src/common/tortls.c
index c13b12fd40..9d45eb00f7 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -1478,6 +1478,43 @@ static uint16_t v2_cipher_list[] = {
/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */
static int v2_cipher_list_pruned = 0;
+/** Return 0 if <b>m</b> does not support the cipher with ID <b>cipher</b>;
+ * return 1 if it does support it, or if we have no way to tell. */
+static int
+find_cipher_by_id(const SSL_METHOD *m, uint16_t cipher)
+{
+ const SSL_CIPHER *c;
+#ifdef HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR
+ if (m && m->get_cipher_by_char) {
+ unsigned char cipherid[3];
+ set_uint16(cipherid, htons(cipher));
+ cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
+ * with a two-byte 'cipherid', it may look for a v2
+ * cipher with the appropriate 3 bytes. */
+ c = m->get_cipher_by_char(cipherid);
+ if (c)
+ tor_assert((c->id & 0xffff) == cipher);
+ return c != NULL;
+ } else
+#endif
+ if (m && m->get_cipher && m->num_ciphers) {
+ /* It would seem that some of the "let's-clean-up-openssl" forks have
+ * removed the get_cipher_by_char function. Okay, so now you get a
+ * quadratic search.
+ */
+ int i;
+ for (i = 0; i < m->num_ciphers(); ++i) {
+ c = m->get_cipher(i);
+ if (c && (c->id & 0xffff) == cipher) {
+ return 1;
+ }
+ }
+ return 0;
+ } else {
+ return 1; /* No way to search */
+ }
+}
+
/** Remove from v2_cipher_list every cipher that we don't support, so that
* comparing v2_cipher_list to a client's cipher list will give a sensible
* result. */
@@ -1489,16 +1526,7 @@ prune_v2_cipher_list(void)
inp = outp = v2_cipher_list;
while (*inp) {
- unsigned char cipherid[3];
- const SSL_CIPHER *cipher;
- /* Is there no better way to do this? */
- set_uint16(cipherid, htons(*inp));
- cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting
- * with a two-byte 'cipherid', it may look for a v2
- * cipher with the appropriate 3 bytes. */
- cipher = m->get_cipher_by_char(cipherid);
- if (cipher) {
- tor_assert((cipher->id & 0xffff) == *inp);
+ if (find_cipher_by_id(m, *inp)) {
*outp++ = *inp++;
} else {
inp++;