[exim-cvs] cvs commit: exim/exim-doc/doc-docbook spec.xfpt …

Top Page
Delete this message
Reply to this message
Author: Phil Pennock
Date:  
To: exim-cvs
Subject: [exim-cvs] cvs commit: exim/exim-doc/doc-docbook spec.xfpt exim/exim-doc/doc-txt ChangeLog NewStuff exim/exim-src/src functions.h globals.c globals.h readconf.c tls-openssl.c
pdp 2010/06/05 10:10:11 BST

  Modified files:
    exim-doc/doc-docbook spec.xfpt 
    exim-doc/doc-txt     ChangeLog NewStuff 
    exim-src/src         functions.h globals.c globals.h 
                         readconf.c tls-openssl.c 
  Log:
  Add an openssl_options main configuration option, to allow administrators to
  shoot themselves in each foot in turn.  The default value is chosen to avoid
  a change in behaviour, but since it is disabling a security countermeasure,
  I'd like to change the default to be "no options".  Fixes: #994


  Revision  Changes    Path
  1.75      +31 -0     exim/exim-doc/doc-docbook/spec.xfpt
  1.617     +2 -0      exim/exim-doc/doc-txt/ChangeLog
  1.166     +12 -0     exim/exim-doc/doc-txt/NewStuff
  1.48      +3 -0      exim/exim-src/src/functions.h
  1.87      +1 -0      exim/exim-src/src/globals.c
  1.68      +1 -0      exim/exim-src/src/globals.h
  1.40      +18 -0     exim/exim-src/src/readconf.c
  1.23      +213 -16   exim/exim-src/src/tls-openssl.c


  Index: spec.xfpt
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-docbook/spec.xfpt,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- spec.xfpt    29 May 2010 19:26:31 -0000    1.74
  +++ spec.xfpt    5 Jun 2010 09:10:08 -0000    1.75
  @@ -1,4 +1,4 @@
  -. $Cambridge: exim/exim-doc/doc-docbook/spec.xfpt,v 1.74 2010/05/29 19:26:31 nm4 Exp $
  +. $Cambridge: exim/exim-doc/doc-docbook/spec.xfpt,v 1.75 2010/06/05 09:10:08 pdp Exp $
   .
   . /////////////////////////////////////////////////////////////////////////////
   . This is the primary source of the Exim Manual. It is an xfpt document that is
  @@ -12392,6 +12392,7 @@
   .row &%gnutls_require_mac%&          "control GnuTLS MAC algorithms"
   .row &%gnutls_require_protocols%&    "control GnuTLS protocols"
   .row &%gnutls_compat_mode%&          "use GnuTLS compatibility mode"
  +.row &%openssl_options%&             "adjust OpenSSL compatibility options"
   .row &%tls_advertise_hosts%&         "advertise TLS to these hosts"
   .row &%tls_certificate%&             "location of server certificate"
   .row &%tls_crl%&                     "certificate revocation list"
  @@ -14003,6 +14004,36 @@
   transport driver.



+.option openssl_options main "string list" +dont_insert_empty_fragments
+.cindex "OpenSSL "compatibility options"
+This option allows an administrator to adjust the SSL options applied
+by OpenSSL to connections. It is given as a space-separated list of items,
+each one to be +added or -subtracted from the current value. The default
+value is one option which happens to have been set historically. You can
+remove all options with:
+.code
+openssl_options = -all
+.endd
+This option is only available if Exim is built against OpenSSL. The values
+available for this option vary according to the age of your OpenSSL install.
+The &"all"& value controls a subset of flags which are available, typically
+the bug workaround options. The &'SSL_CTX_set_options'& man page will
+list the values known on your system and Exim should support all the
+&"bug workaround"& options and many of the &"modifying"& options. The Exim
+names lose the leading &"SSL_OP_"& and are lower-cased.
+
+Note that adjusting the options can have severe impact upon the security of
+SSL as used by Exim. It is possible to disable safety checks and shoot
+yourself in the foot in various unpleasant ways. This option should not be
+adjusted lightly. An unrecognised item will be detected at by invoking Exim
+with the &%-bV%& flag.
+
+An example:
+.code
+openssl_options = -all +microsoft_big_sslv3_buffer
+.endd
+
+
.option oracle_servers main "string list" unset
.cindex "Oracle" "server list"
This option provides a list of Oracle servers and associated connection data,

  Index: ChangeLog
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
  retrieving revision 1.616
  retrieving revision 1.617
  diff -u -r1.616 -r1.617
  --- ChangeLog    3 Jun 2010 15:20:41 -0000    1.616
  +++ ChangeLog    5 Jun 2010 09:10:09 -0000    1.617
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.616 2010/06/03 15:20:41 jetmore Exp $
  +$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.617 2010/06/05 09:10:09 pdp Exp $


Change log file for Exim from version 4.21
-------------------------------------------
@@ -14,6 +14,8 @@

JJ/01 Added DISABLE_DKIM and comment to src/EDITME

+PP/03 Bugzilla 994: added openssl_options main configuration option.
+
Exim version 4.72
-----------------


  Index: NewStuff
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/NewStuff,v
  retrieving revision 1.165
  retrieving revision 1.166
  diff -u -r1.165 -r1.166
  --- NewStuff    3 Jun 2010 15:20:41 -0000    1.165
  +++ NewStuff    5 Jun 2010 09:10:09 -0000    1.166
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.165 2010/06/03 15:20:41 jetmore Exp $
  +$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.166 2010/06/05 09:10:09 pdp Exp $


New Features in Exim
--------------------
@@ -9,6 +9,18 @@
the documentation is updated, this file is reduced to a short list.


  +Version 4.73
  +------------
  +
  + 1. A new main configuration option, "openssl_options", is available if Exim
  +    is built with SSL support provided by OpenSSL.  The option allows
  +    administrators to specify OpenSSL options to be used on connections;
  +    typically this is to set bug compatibility features which the OpenSSL
  +    developers have not enabled by default.  There may be security
  +    consequences for certain options, so these should not be changed
  +    frivolously.
  +
  +
   Version 4.72
   ------------



  Index: functions.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/functions.h,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- functions.h    16 Nov 2009 19:50:37 -0000    1.47
  +++ functions.h    5 Jun 2010 09:10:10 -0000    1.48
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/functions.h,v 1.47 2009/11/16 19:50:37 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/functions.h,v 1.48 2010/06/05 09:10:10 pdp Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -36,6 +36,9 @@
   extern int     tls_ungetc(int);
   extern int     tls_write(const uschar *, size_t);
   extern void    tls_version_report(FILE *);
  +#ifndef USE_GNUTLS
  +extern BOOL    tls_openssl_options_parse(uschar *, long *);
  +#endif
   #endif




  Index: globals.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/globals.c,v
  retrieving revision 1.86
  retrieving revision 1.87
  diff -u -r1.86 -r1.87
  --- globals.c    16 Nov 2009 19:50:37 -0000    1.86
  +++ globals.c    5 Jun 2010 09:10:10 -0000    1.87
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.c,v 1.86 2009/11/16 19:50:37 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.c,v 1.87 2010/06/05 09:10:10 pdp Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -115,6 +115,7 @@
   uschar *gnutls_require_mac     = NULL;
   uschar *gnutls_require_kx      = NULL;
   uschar *gnutls_require_proto   = NULL;
  +uschar *openssl_options        = NULL;
   const pcre *regex_STARTTLS     = NULL;
   uschar *tls_advertise_hosts    = NULL;    /* This is deliberate */
   uschar *tls_certificate        = NULL;


  Index: globals.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/globals.h,v
  retrieving revision 1.67
  retrieving revision 1.68
  diff -u -r1.67 -r1.68
  --- globals.h    16 Nov 2009 19:50:37 -0000    1.67
  +++ globals.h    5 Jun 2010 09:10:10 -0000    1.68
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.h,v 1.67 2009/11/16 19:50:37 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.h,v 1.68 2010/06/05 09:10:10 pdp Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -75,6 +75,7 @@
   extern uschar *gnutls_require_mac;     /* So some can be avoided */
   extern uschar *gnutls_require_kx;      /* So some can be avoided */
   extern uschar *gnutls_require_proto;   /* So some can be avoided */
  +extern uschar *openssl_options;        /* OpenSSL compatibility options */
   extern const pcre *regex_STARTTLS;     /* For recognizing STARTTLS settings */
   extern uschar *tls_advertise_hosts;    /* host for which TLS is advertised */
   extern uschar *tls_certificate;        /* Certificate file */


  Index: readconf.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/readconf.c,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- readconf.c    16 Nov 2009 19:50:37 -0000    1.39
  +++ readconf.c    5 Jun 2010 09:10:10 -0000    1.40
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/readconf.c,v 1.39 2009/11/16 19:50:37 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/readconf.c,v 1.40 2010/06/05 09:10:10 pdp Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -291,6 +291,9 @@
     { "mysql_servers",            opt_stringptr,   &mysql_servers },
   #endif
     { "never_users",              opt_uidlist,     &never_users },
  +#ifdef SUPPORT_TLS
  +  { "openssl_options",          opt_stringptr,   &openssl_options },
  +#endif
   #ifdef LOOKUP_ORACLE
     { "oracle_servers",           opt_stringptr,   &oracle_servers },
   #endif
  @@ -2748,6 +2751,7 @@
   readconf_main(void)
   {
   int sep = 0;
  +long dummy_l;
   struct stat statbuf;
   uschar *s, *filename;
   uschar *list = config_main_filelist;
  @@ -3156,6 +3160,20 @@
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
       "tls_%sverify_hosts is set, but tls_verify_certificates is not set",
       (tls_verify_hosts != NULL)? "" : "try_");
  +
  +/* If openssl_options is set, validate it */
  +if (openssl_options != NULL)
  +  {
  +# ifdef USE_GNUTLS
  +  log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
  +    "openssl_options is set but we're using GnuTLS\n");
  +# else
  +  long dummy;
  +  if (!(tls_openssl_options_parse(openssl_options, &dummy)))
  +    log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
  +      "openssl_options parse error: %s\n", openssl_options);
  +# endif
  +  }
   #endif
   }



  Index: tls-openssl.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-openssl.c,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- tls-openssl.c    16 Nov 2009 19:50:37 -0000    1.22
  +++ tls-openssl.c    5 Jun 2010 09:10:10 -0000    1.23
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.22 2009/11/16 19:50:37 nm4 Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.23 2010/06/05 09:10:10 pdp Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -302,11 +302,14 @@
   tls_init(host_item *host, uschar *dhparam, uschar *certificate,
     uschar *privatekey, address_item *addr)
   {
  +long init_options;
  +BOOL okay;
  +
   SSL_load_error_strings();          /* basic set up */
   OpenSSL_add_ssl_algorithms();


#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-/* SHA256 is becoming ever moar popular. This makes sure it gets added to the
+/* SHA256 is becoming ever more popular. This makes sure it gets added to the
list of available digests. */
EVP_add_digest(EVP_sha256());
#endif
@@ -346,21 +349,28 @@

SSL_CTX_set_info_callback(ctx, (void (*)())info_callback);

  -/* The following patch was supplied by Robert Roselius */
  -
  -#if OPENSSL_VERSION_NUMBER > 0x00906040L
  -/* Enable client-bug workaround.
  -   Versions of OpenSSL as of 0.9.6d include a "CBC countermeasure" feature,
  -   which causes problems with some clients (such as the Certicom SSL Plus
  -   library used by Eudora).  This option, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS,
  -   disables the coutermeasure allowing Eudora to connect.
  -   Some poppers and MTAs use SSL_OP_ALL, which enables all such bug
  -   workarounds. */
  -/* XXX (Silently?) ignore failure here? XXX*/
  -
  -if (!(SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)))
  -  return tls_error(US"SSL_CTX_set_option", host, NULL);
  -#endif
  +/* Apply administrator-supplied work-arounds.
  +Historically we applied just one requested option,
  +SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, but when bug 994 requested a second, we
  +moved to an administrator-controlled list of options to specify and
  +grandfathered in the first one as the default value for "openssl_options".
  +
  +No OpenSSL version number checks: the options we accept depend upon the
  +availability of the option value macros from OpenSSL.  */
  +
  +okay = tls_openssl_options_parse(openssl_options, &init_options);
  +if (!okay)
  +  return tls_error("openssl_options parsing failed", host, NULL);
  +
  +if (init_options)
  +  {
  +  DEBUG(D_tls) debug_printf("setting SSL CTX options: %#lx\n", init_options);
  +  if (!(SSL_CTX_set_options(ctx, init_options)))
  +    return tls_error(string_sprintf(
  +          "SSL_CTX_set_option(%#lx)", init_options), host, NULL);
  +  }
  +else
  +  DEBUG(D_tls) debug_printf("no SSL CTX options to set\n");


/* Initialize with DH parameters if supplied */

  @@ -702,6 +712,9 @@
   if (rc <= 0)
     {
     tls_error(US"SSL_accept", NULL, sigalrm_seen ? US"timed out" : NULL);
  +  if (ERR_get_error() == 0)
  +    log_write(0, LOG_MAIN,
  +        "  => client disconnected cleanly (rejected our certificate?)\n");
     return FAIL;
     }


@@ -1123,4 +1136,188 @@
return r % max;
}

  +
  +
  +
  +/*************************************************
  +*        OpenSSL option parse                    *
  +*************************************************/
  +
  +/* Parse one option for tls_openssl_options_parse below
  +
  +Arguments:
  +  name    one option name
  +  value   place to store a value for it
  +Returns   success or failure in parsing
  +*/
  +
  +struct exim_openssl_option {
  +  uschar *name;
  +  long    value;
  +};
  +/* We could use a macro to expand, but we need the ifdef and not all the
  +options document which version they were introduced in.  Policylet: include
  +all options unless explicitly for DTLS, let the administrator choose which
  +to apply.
  +
  +This list is current as of:
  +  ==>  0.9.8n  <==  */
  +static struct exim_openssl_option exim_openssl_options[] = {
  +/* KEEP SORTED ALPHABETICALLY! */
  +#ifdef SSL_OP_ALL
  +  { "all", SSL_OP_ALL },
  +#endif
  +#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
  +  { "allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION },
  +#endif
  +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
  +  { "cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE },
  +#endif
  +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
  +  { "dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS },
  +#endif
  +#ifdef SSL_OP_EPHEMERAL_RSA
  +  { "ephemeral_rsa", SSL_OP_EPHEMERAL_RSA },
  +#endif
  +#ifdef SSL_OP_LEGACY_SERVER_CONNECT
  +  { "legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT },
  +#endif
  +#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
  +  { "microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER },
  +#endif
  +#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
  +  { "microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG },
  +#endif
  +#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
  +  { "msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING },
  +#endif
  +#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
  +  { "netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG },
  +#endif
  +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
  +  { "netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG },
  +#endif
  +#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
  +  { "no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION },
  +#endif
  +#ifdef SSL_OP_SINGLE_DH_USE
  +  { "single_dh_use", SSL_OP_SINGLE_DH_USE },
  +#endif
  +#ifdef SSL_OP_SINGLE_ECDH_USE
  +  { "single_ecdh_use", SSL_OP_SINGLE_ECDH_USE },
  +#endif
  +#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
  +  { "ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG },
  +#endif
  +#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
  +  { "sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG },
  +#endif
  +#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
  +  { "tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG },
  +#endif
  +#ifdef SSL_OP_TLS_D5_BUG
  +  { "tls_d5_bug", SSL_OP_TLS_D5_BUG },
  +#endif
  +#ifdef SSL_OP_TLS_ROLLBACK_BUG
  +  { "tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG },
  +#endif
  +};
  +static int exim_openssl_options_size =
  +  sizeof(exim_openssl_options)/sizeof(struct exim_openssl_option);
  +
  +static BOOL
  +tls_openssl_one_option_parse(uschar *name, long *value)
  +{
  +int first = 0;
  +int last = exim_openssl_options_size;
  +while (last > first)
  +  {
  +  int middle = (first + last)/2;
  +  int c = Ustrcmp(name, exim_openssl_options[middle].name);
  +  if (c == 0)
  +    {
  +    *value = exim_openssl_options[middle].value;
  +    return TRUE;
  +    }
  +  else if (c > 0)
  +    first = middle + 1;
  +  else
  +    last = middle;
  +  }
  +return FALSE;
  +}
  +
  +
  +
  +
  +/*************************************************
  +*        OpenSSL option parsing logic            *
  +*************************************************/
  +
  +/* OpenSSL has a number of compatibility options which an administrator might
  +reasonably wish to set.  Interpret a list similarly to decode_bits(), so that
  +we look like log_selector.
  +
  +Arguments:
  +  option_spec  the administrator-supplied string of options
  +  results      ptr to long storage for the options bitmap
  +Returns        success or failure
  +*/
  +
  +BOOL
  +tls_openssl_options_parse(uschar *option_spec, long *results)
  +{
  +long result, item;
  +uschar *s, *end;
  +uschar keep_c;
  +BOOL adding, item_parsed;
  +
  +/* We grandfather in as default the one option which we used to set always. */
  +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
  +result = SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
  +#else
  +result = 0L;
  +#endif
  +
  +if (option_spec == NULL)
  +  {
  +  *results = result;
  +  return TRUE;
  +  }
  +
  +for (s=option_spec; *s != '\0'; /**/)
  +  {
  +  while (isspace(*s)) ++s;
  +  if (*s == '\0')
  +    break;
  +  if (*s != '+' && *s != '-')
  +    {
  +    DEBUG(D_tls) debug_printf("malformed openssl option setting: "
  +        "+ or - expected but found \"%s\"", s);
  +    return FALSE;
  +    }
  +  adding = *s++ == '+';
  +  for (end = s; (*end != '\0') && !isspace(*end); ++end) /**/ ;
  +  keep_c = *end;
  +  *end = '\0';
  +  item_parsed = tls_openssl_one_option_parse(s, &item);
  +  if (!item_parsed)
  +    {
  +    DEBUG(D_tls) debug_printf("openssl option setting unrecognised: \"%s\"", s);
  +    return FALSE;
  +    }
  +  DEBUG(D_tls) debug_printf("openssl option, %s from %lx: %lx (%s)\n",
  +      adding ? "adding" : "removing", result, item, s);
  +  if (adding)
  +    result |= item;
  +  else
  +    result &= ~item;
  +  *end = keep_c;
  +  s = end;
  +  }
  +
  +*results = result;
  +return TRUE;
  +}
  +
   /* End of tls-openssl.c */