[exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog NewSt…

Top Page
Delete this message
Reply to this message
Author: Philip Hazel
Date:  
To: exim-cvs
Subject: [exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog NewStuff OptionLists.txt exim/exim-src/src functions.h globals.c globals.h readconf.c smtp_in.c tls-gnu.c tls-openssl.c exim/exim-src/src/trans
ph10 2007/01/18 15:35:43 GMT

  Modified files:
    exim-doc/doc-txt     ChangeLog NewStuff OptionLists.txt 
    exim-src/src         functions.h globals.c globals.h 
                         readconf.c smtp_in.c tls-gnu.c 
                         tls-openssl.c 
    exim-src/src/transports smtp.c smtp.h 
    exim-test/confs      2011 
    exim-test/log        2011 
    exim-test/scripts/2000-GnuTLS 2011 
  Log:
  Add gnutls_require_{kx,mac,protocols}.


  Revision  Changes    Path
  1.455     +3 -0      exim/exim-doc/doc-txt/ChangeLog
  1.128     +69 -0     exim/exim-doc/doc-txt/NewStuff
  1.29      +7 -1      exim/exim-doc/doc-txt/OptionLists.txt
  1.34      +3 -2      exim/exim-src/src/functions.h
  1.63      +3 -0      exim/exim-src/src/globals.c
  1.44      +3 -0      exim/exim-src/src/globals.h
  1.27      +5 -0      exim/exim-src/src/readconf.c
  1.51      +5 -2      exim/exim-src/src/smtp_in.c
  1.18      +197 -74   exim/exim-src/src/tls-gnu.c
  1.10      +16 -2     exim/exim-src/src/tls-openssl.c
  1.31      +17 -1     exim/exim-src/src/transports/smtp.c
  1.11      +3 -0      exim/exim-src/src/transports/smtp.h
  1.2       +9 -2      exim/exim-test/confs/2011
  1.2       +41 -2     exim/exim-test/log/2011
  1.2       +29 -1     exim/exim-test/scripts/2000-GnuTLS/2011


  Index: ChangeLog
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
  retrieving revision 1.454
  retrieving revision 1.455
  diff -u -r1.454 -r1.455
  --- ChangeLog    17 Jan 2007 11:17:58 -0000    1.454
  +++ ChangeLog    18 Jan 2007 15:35:42 -0000    1.455
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.454 2007/01/17 11:17:58 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.455 2007/01/18 15:35:42 ph10 Exp $


Change log file for Exim from version 4.21
-------------------------------------------
@@ -25,6 +25,9 @@

   PH/03 Added additional dnslists conditions == and =& which are different from
         = and & when the dns lookup returns more than one IP address.
  +
  +PH/04 Added gnutls_require_{kx,mac,protocols} to give more control over the
  +      cipher suites used by GnuTLS. These options are ignored by OpenSSL.



Exim version 4.66

  Index: NewStuff
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/NewStuff,v
  retrieving revision 1.127
  retrieving revision 1.128
  diff -u -r1.127 -r1.128
  --- NewStuff    17 Jan 2007 11:17:58 -0000    1.127
  +++ NewStuff    18 Jan 2007 15:35:42 -0000    1.128
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.127 2007/01/17 11:17:58 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.128 2007/01/18 15:35:42 ph10 Exp $


New Features in Exim
--------------------
@@ -105,6 +105,75 @@

       When the DNS lookup yields only a single IP address, there is no difference
       between = and == and between & and =&.
  +
  + 3. Up till now, the only control over which cipher suites GnuTLS uses has been
  +    for the cipher algorithms. New options have been added to allow some of the
  +    other parameters to be varied. Here is complete documentation for the
  +    available features:
  +
  +    GnuTLS allows the caller to specify separate lists of permitted key
  +    exchange methods, main cipher algorithms, and MAC algorithms. These may be
  +    used in any combination to form a specific cipher suite. This is unlike
  +    OpenSSL, where complete cipher names can be passed to its control function.
  +    GnuTLS also allows a list of acceptable protocols to be supplied.
  +
  +    For compatibility with OpenSSL, the tls_require_ciphers option can be set
  +    to complete cipher suite names such as RSA_ARCFOUR_SHA, but for GnuTLS this
  +    option controls only the cipher algorithms. Exim searches each item in the
  +    list for the name of an available algorithm. For example, if the list
  +    contains RSA_AES_SHA, then AES is recognized, and the behaviour is exactly
  +    the same as if just AES were given.
  +
  +    There are additional options called gnutls_require_kx, gnutls_require_mac,
  +    and gnutls_require_protocols that can be used to restrict the key exchange
  +    methods, MAC algorithms, and protocols, respectively. These options are
  +    ignored if OpenSSL is in use.
  +
  +    All four options are available as global options, controlling how Exim
  +    behaves as a server, and also as options of the smtp transport, controlling
  +    how Exim behaves as a client. All the values are string expanded. After
  +    expansion, the values must be colon-separated lists, though the separator
  +    can be changed in the usual way.
  +
  +    Each of the four lists starts out with a default set of algorithms. If the
  +    first item in one of the "require" options does _not_ start with an
  +    exclamation mark, all the default items are deleted. In this case, only
  +    those that are explicitly specified can be used. If the first item in one
  +    of the "require" items _does_ start with an exclamation mark, the defaults
  +    are left on the list.
  +
  +    Then, any item that starts with an exclamation mark causes the relevant
  +    entry to be removed from the list, and any item that does not start with an
  +    exclamation mark causes a new entry to be added to the list. Unrecognized
  +    items in the list are ignored. Thus:
  +
  +      tls_require_ciphers = !ARCFOUR
  +
  +    allows all the defaults except ARCFOUR, whereas
  +
  +      tls_require_ciphers = AES : 3DES
  +
  +    allows only cipher suites that use AES or 3DES. For tls_require_ciphers
  +    the recognized names are AES_256, AES_128, AES (both of the preceding),
  +    3DES, ARCFOUR_128, ARCFOUR_40, and ARCFOUR (both of the preceding). The
  +    default list does not contain all of these; it just has AES_256, AES_128,
  +    3DES, and ARCFOUR_128.
  +
  +    For gnutls_require_kx, the recognized names are DHE_RSA, RSA (which
  +    includes DHE_RSA), DHE_DSS, and DHE (which includes both DHE_RSA and
  +    DHE_DSS). The default list contains RSA, DHE_DSS, DHE_RSA.
  +
  +    For gnutls_require_mac, the recognized names are SHA (synonym SHA1), and
  +    MD5. The default list contains SHA, MD5.
  +
  +    For gnutls_require_protocols, the recognized names are TLS1 and SSL3.
  +    The default list contains TLS1, SSL3.
  +
  +    In a server, the order of items in these lists is unimportant. The server
  +    will advertise the availability of all the relevant cipher suites. However,
  +    in a client, the order in the tls_require_ciphers list specifies a
  +    preference order for the cipher algorithms. The first one in the client's
  +    list that is also advertised by the server is tried first.



Version 4.66

  Index: OptionLists.txt
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/OptionLists.txt,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- OptionLists.txt    5 Dec 2006 11:35:28 -0000    1.28
  +++ OptionLists.txt    18 Jan 2007 15:35:42 -0000    1.29
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/OptionLists.txt,v 1.28 2006/12/05 11:35:28 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/OptionLists.txt,v 1.29 2007/01/18 15:35:42 ph10 Exp $


   LISTS OF EXIM OPTIONS
   ---------------------
  @@ -11,7 +11,7 @@
     4. Those that can appear in the build time configuration for the Exim monitor
        (Local/eximon.conf).


-This file was last updated for Exim release 4.64.
+This file was last updated for Exim release 4.67.


   1. RUN TIME OPTIONS
  @@ -231,6 +231,12 @@
   gecos_name                           string*         unset         main
   gecos_pattern                        string          unset         main
   gethostbyname                        boolean         false         smtp
  +gnutls_require_kx                    string*         unset         main              4.67
  +                                     string*         unset         smtp              4.67
  +gnutls_require_mac                   string*         unset         main              4.67
  +                                     string*         unset         smtp              4.67
  +gnutls_require_protocols             string*         unset         main              4.67
  +                                     string*         unset         smtp              4.67
   group                                string          +             routers           4.00
                                                        unset         transports        4.00 replaces local option in some transports
   header_line_maxsize                  integer         0 (unset)     main              4.14


  Index: functions.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/functions.h,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- functions.h    15 Jan 2007 15:59:22 -0000    1.33
  +++ functions.h    18 Jan 2007 15:35:42 -0000    1.34
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/functions.h,v 1.33 2007/01/15 15:59:22 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/functions.h,v 1.34 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -24,13 +24,14 @@


   #ifdef SUPPORT_TLS
   extern int     tls_client_start(int, host_item *, address_item *, uschar *,
  -                 uschar *, uschar *, uschar *, uschar *, uschar *, int);
  +                 uschar *, uschar *, uschar *, uschar *, uschar *, uschar *,
  +                 uschar *, uschar *, int);
   extern void    tls_close(BOOL);
   extern int     tls_feof(void);
   extern int     tls_ferror(void);
   extern int     tls_getc(void);
   extern int     tls_read(uschar *, size_t);
  -extern int     tls_server_start(uschar *);
  +extern int     tls_server_start(uschar *, uschar *, uschar *, uschar *);
   extern int     tls_ungetc(int);
   extern int     tls_write(const uschar *, size_t);
   #endif


  Index: globals.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/globals.c,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- globals.c    15 Jan 2007 15:59:22 -0000    1.62
  +++ globals.c    18 Jan 2007 15:35:42 -0000    1.63
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.c,v 1.62 2007/01/15 15:59:22 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.c,v 1.63 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -109,6 +109,9 @@
   uschar *tls_peerdn             = NULL;


   #ifdef SUPPORT_TLS
  +uschar *gnutls_require_mac     = NULL;
  +uschar *gnutls_require_kx      = NULL;
  +uschar *gnutls_require_proto   = 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.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- globals.h    15 Jan 2007 15:59:22 -0000    1.43
  +++ globals.h    18 Jan 2007 15:35:42 -0000    1.44
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.h,v 1.43 2007/01/15 15:59:22 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.h,v 1.44 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -71,6 +71,9 @@
   extern uschar *tls_peerdn;             /* DN from peer */


   #ifdef SUPPORT_TLS
  +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 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.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- readconf.c    8 Jan 2007 10:50:18 -0000    1.26
  +++ readconf.c    18 Jan 2007 15:35:42 -0000    1.27
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/readconf.c,v 1.26 2007/01/08 10:50:18 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/readconf.c,v 1.27 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -218,6 +218,11 @@
     { "freeze_tell",              opt_stringptr,   &freeze_tell },
     { "gecos_name",               opt_stringptr,   &gecos_name },
     { "gecos_pattern",            opt_stringptr,   &gecos_pattern },
  +#ifdef SUPPORT_TLS
  +  { "gnutls_require_kx",        opt_stringptr,   &gnutls_require_kx },
  +  { "gnutls_require_mac",       opt_stringptr,   &gnutls_require_mac },
  +  { "gnutls_require_protocols", opt_stringptr,   &gnutls_require_proto },
  +#endif
     { "header_line_maxsize",      opt_int,         &header_line_maxsize },
     { "header_maxsize",           opt_int,         &header_maxsize },
     { "headers_charset",          opt_stringptr,   &headers_charset },


  Index: smtp_in.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
  retrieving revision 1.50
  retrieving revision 1.51
  diff -u -r1.50 -r1.51
  --- smtp_in.c    15 Jan 2007 15:59:22 -0000    1.50
  +++ smtp_in.c    18 Jan 2007 15:35:42 -0000    1.51
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.50 2007/01/15 15:59:22 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.51 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -1540,7 +1540,9 @@
     smtps port for use with older style SSL MTAs. */


     #ifdef SUPPORT_TLS
  -  if (tls_on_connect && tls_server_start(tls_require_ciphers) != OK)
  +  if (tls_on_connect &&
  +      tls_server_start(tls_require_ciphers,
  +        gnutls_require_mac, gnutls_require_kx, gnutls_require_proto) != OK)
       return FALSE;
     #endif


  @@ -3593,7 +3595,8 @@
       We must allow for an extra EHLO command and an extra AUTH command after
       STARTTLS that don't add to the nonmail command count. */


  -    if ((rc = tls_server_start(tls_require_ciphers)) == OK)
  +    if ((rc = tls_server_start(tls_require_ciphers, gnutls_require_mac,
  +           gnutls_require_kx, gnutls_require_proto)) == OK)
         {
         if (!tls_remember_esmtp)
           helo_seen = esmtp = auth_advertised = pipelining_advertised = FALSE;


  Index: tls-gnu.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-gnu.c,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- tls-gnu.c    8 Jan 2007 10:50:18 -0000    1.17
  +++ tls-gnu.c    18 Jan 2007 15:35:42 -0000    1.18
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-gnu.c,v 1.17 2007/01/08 10:50:18 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-gnu.c,v 1.18 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -46,17 +46,24 @@
   static int  ssl_session_timeout = 200;
   static int  verify_requirement;


-/* Priorities for TLS algorithms to use. At present, only the cipher priority
-vector can be altered. */
+/* Priorities for TLS algorithms to use. In each case there's a default table,
+and space into which it can be copied and altered. */

-static const int protocol_priority[16] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
+static const int default_proto_priority[16] = {
+ GNUTLS_TLS1,
+ GNUTLS_SSL3,
+ 0 };
+
+static int proto_priority[16];

  -static const int kx_priority[16] = {
  +static const int default_kx_priority[16] = {
     GNUTLS_KX_RSA,
     GNUTLS_KX_DHE_DSS,
     GNUTLS_KX_DHE_RSA,
     0 };


  +static int kx_priority[16];
  +
   static int default_cipher_priority[16] = {
     GNUTLS_CIPHER_AES_256_CBC,
     GNUTLS_CIPHER_AES_128_CBC,
  @@ -66,21 +73,50 @@


static int cipher_priority[16];

  -static const int mac_priority[16] = {
  +static const int default_mac_priority[16] = {
     GNUTLS_MAC_SHA,
     GNUTLS_MAC_MD5,
     0 };


+static int mac_priority[16];
+
+/* These two are currently not changeable. */
+
static const int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
static const int cert_type_priority[16] = { GNUTLS_CRT_X509, 0 };

-/* Tables of cipher names and equivalent numbers */
+/* Tables of priority names and equivalent numbers */

   typedef struct pri_item {
     uschar *name;
     int *values;
   } pri_item;


  +
  +static int tls1_codes[] = { GNUTLS_TLS1, 0 };
  +static int ssl3_codes[] = { GNUTLS_SSL3, 0 };
  +
  +static pri_item proto_index[] = {
  +  { US"TLS1", tls1_codes },
  +  { US"SSL3", ssl3_codes }
  +};
  +
  +
  +static int kx_rsa_codes[]      = { GNUTLS_KX_RSA,
  +                                   GNUTLS_KX_DHE_RSA, 0 };
  +static int kx_dhe_codes[]      = { GNUTLS_KX_DHE_DSS,
  +                                   GNUTLS_KX_DHE_RSA, 0 };
  +static int kx_dhe_dss_codes[]  = { GNUTLS_KX_DHE_DSS, 0 };
  +static int kx_dhe_rsa_codes[]  = { GNUTLS_KX_DHE_RSA, 0 };
  +
  +static pri_item kx_index[] = {
  +  { US"DHE_DSS", kx_dhe_dss_codes },
  +  { US"DHE_RSA", kx_dhe_rsa_codes },
  +  { US"RSA", kx_rsa_codes },
  +  { US"DHE", kx_dhe_codes }
  +};
  +
  +
   static int arcfour_128_codes[] = { GNUTLS_CIPHER_ARCFOUR_128, 0 };
   static int arcfour_40_codes[]  = { GNUTLS_CIPHER_ARCFOUR_40, 0 };
   static int arcfour_codes[]     = { GNUTLS_CIPHER_ARCFOUR_128,
  @@ -102,6 +138,16 @@
   };



  +static int mac_sha_codes[]     = { GNUTLS_MAC_SHA, 0 };
  +static int mac_md5_codes[]     = { GNUTLS_MAC_MD5, 0 };
  +
  +static pri_item mac_index[] = {
  +  { US"SHA",  mac_sha_codes },
  +  { US"SHA1", mac_sha_codes },
  +  { US"MD5",  mac_md5_codes }
  +};
  +
  +


   /*************************************************
   *               Handle TLS error                 *
  @@ -512,7 +558,7 @@



   /*************************************************
  -*        Remove ciphers from priority list       *
  +*           Remove from a priority list          *
   *************************************************/


/* Cautiously written so that it will remove duplicates if present.
@@ -525,7 +571,7 @@
*/

   static void
  -remove_ciphers(int *list, int *remove_list)
  +remove_priority(int *list, int *remove_list)
   {
   for (; *remove_list != 0; remove_list++)
     {
  @@ -545,7 +591,7 @@



   /*************************************************
  -*        Add ciphers to priority list            *
  +*            Add to a priority list              *
   *************************************************/


/* Cautiously written to check the list size
@@ -559,7 +605,7 @@
*/

static BOOL
-add_ciphers(int *list, int list_max, int *add_list)
+add_priority(int *list, int list_max, int *add_list)
{
int next = 0;
while (list[next] != 0) next++;
@@ -575,6 +621,78 @@


   /*************************************************
  +*          Adjust a priority list                *
  +*************************************************/
  +
  +/* This function is called to adjust the lists of cipher algorithms, MAC
  +algorithms, key-exchange methods, and protocols.
  +
  +Arguments:
  +  plist       the appropriate priority list
  +  psize       the length of the list
  +  s           the configuation string
  +  index       the index of recognized strings
  +  isize       the length of the index
  +
  +
  +  which       text for an error message
  +
  +Returns:      FALSE if the table overflows, else TRUE
  +*/
  +
  +static BOOL
  +set_priority(int *plist, int psize, uschar *s, pri_item *index, int isize,
  +   uschar *which)
  +{
  +int sep = 0;
  +BOOL first = TRUE;
  +uschar *t;
  +
  +while ((t = string_nextinlist(&s, &sep, big_buffer, big_buffer_size)) != NULL)
  +  {
  +  int i;
  +  BOOL exclude = t[0] == '!';
  +  if (first && !exclude) plist[0] = 0;
  +  first = FALSE;
  +  for (i = 0; i < isize; i++)
  +    {
  +    uschar *ss = strstric(t, index[i].name, FALSE);
  +    if (ss != NULL)
  +      {
  +      uschar *endss = ss + Ustrlen(index[i].name);
  +      if ((ss == t || !isalnum(ss[-1])) && !isalnum(*endss))
  +        {
  +        if (exclude)
  +          remove_priority(plist, index[i].values);
  +        else
  +          {
  +          if (!add_priority(plist, psize, index[i].values))
  +            {
  +            log_write(0, LOG_MAIN|LOG_PANIC, "GnuTLS init failed: %s "
  +              "priority table overflow", which);
  +            return FALSE;
  +            }
  +          }
  +        }
  +      }
  +    }
  +  }
  +
  +DEBUG(D_tls)
  +  {
  +  int *ptr = plist;
  +  debug_printf("adjusted %s priorities:", which);
  +  while (*ptr != 0) debug_printf(" %d", *ptr++);
  +  debug_printf("\n");
  +  }
  +
  +return TRUE;
  +}
  +
  +
  +
  +
  +/*************************************************
   *        Initialize a single GNUTLS session      *
   *************************************************/


@@ -591,78 +709,60 @@

   Arguments:
     side         one of GNUTLS_SERVER, GNUTLS_CLIENT
  -  expciphers   expanded ciphers list
  +  expciphers   expanded ciphers list or NULL
  +  expmac       expanded MAC list or NULL
  +  expkx        expanded key-exchange list or NULL
  +  expproto     expanded protocol list or NULL


Returns: a gnutls_session, or NULL if there is a problem
*/

static gnutls_session
-tls_session_init(int side, uschar *expciphers)
+tls_session_init(int side, uschar *expciphers, uschar *expmac, uschar *expkx,
+ uschar *expproto)
{
gnutls_session session;

gnutls_init(&session, side);

-/* Handle the list of permitted ciphers */
+/* Initialize the lists of permitted protocols, key-exchange methods, ciphers,
+and MACs. */

memcpy(cipher_priority, default_cipher_priority, sizeof(cipher_priority));
+memcpy(mac_priority, default_mac_priority, sizeof(mac_priority));
+memcpy(kx_priority, default_kx_priority, sizeof(kx_priority));
+memcpy(proto_priority, default_proto_priority, sizeof(proto_priority));
+
+/* The names OpenSSL uses in tls_require_ciphers are of the form DES-CBC3-SHA,
+using hyphen separators. GnuTLS uses underscore separators. So that I can use
+either form for tls_require_ciphers in my tests, and also for general
+convenience, we turn hyphens into underscores before scanning the list. */

   if (expciphers != NULL)
     {
  -  int sep = 0;
  -  BOOL first = TRUE;
  -  uschar *cipher;
  -
  -  /* The names OpenSSL uses are of the form DES-CBC3-SHA, using hyphen
  -  separators. GnuTLS uses underscore separators. So that I can use either form
  -  in my tests, and also for general convenience, we turn hyphens into
  -  underscores before scanning the list. */
  -
     uschar *s = expciphers;
     while (*s != 0) { if (*s == '-') *s = '_'; s++; }
  +  }


  -  while ((cipher = string_nextinlist(&expciphers, &sep, big_buffer,
  -             big_buffer_size)) != NULL)
  -    {
  -    int i;
  -    BOOL exclude = cipher[0] == '!';
  -    if (first && !exclude) cipher_priority[0] = 0;
  -    first = FALSE;
  -
  -    for (i = 0; i < sizeof(cipher_index)/sizeof(pri_item); i++)
  -      {
  -      uschar *ss = strstric(cipher, cipher_index[i].name, FALSE);
  -      if (ss != NULL)
  -        {
  -        uschar *endss = ss + Ustrlen(cipher_index[i].name);
  -        if ((ss == cipher || !isalnum(ss[-1])) && !isalnum(*endss))
  -          {
  -          if (exclude)
  -            remove_ciphers(cipher_priority, cipher_index[i].values);
  -          else
  -            {
  -            if (!add_ciphers(cipher_priority,
  -                             sizeof(cipher_priority)/sizeof(pri_item),
  -                             cipher_index[i].values))
  -              {
  -              log_write(0, LOG_MAIN|LOG_PANIC, "GnuTLS init failed: cipher "
  -                "priority table overflow");
  -              gnutls_deinit(session);
  -              return NULL;
  -              }
  -            }
  -          }
  -        }
  -      }
  -    }
  -
  -  DEBUG(D_tls)
  -    {
  -    int *ptr = cipher_priority;
  -    debug_printf("adjusted cipher priorities:");
  -    while (*ptr != 0) debug_printf(" %d", *ptr++);
  -    debug_printf("\n");
  -    }
  +if ((expciphers != NULL &&
  +      !set_priority(cipher_priority, sizeof(cipher_priority)/sizeof(int),
  +        expciphers, cipher_index, sizeof(cipher_index)/sizeof(pri_item),
  +        US"cipher")) ||
  +    (expmac != NULL &&
  +      !set_priority(mac_priority, sizeof(mac_priority)/sizeof(int),
  +        expmac, mac_index, sizeof(mac_index)/sizeof(pri_item),
  +        US"MAC")) ||
  +    (expkx != NULL &&
  +      !set_priority(kx_priority, sizeof(kx_priority)/sizeof(int),
  +        expkx, kx_index, sizeof(kx_index)/sizeof(pri_item),
  +        US"key-exchange")) ||
  +    (expproto != NULL &&
  +      !set_priority(proto_priority, sizeof(proto_priority)/sizeof(int),
  +        expproto, proto_index, sizeof(proto_index)/sizeof(pri_item),
  +        US"protocol")))
  +  {
  +  gnutls_deinit(session);
  +  return NULL;
     }


/* Define the various priorities */
@@ -670,7 +770,7 @@
gnutls_cipher_set_priority(session, cipher_priority);
gnutls_compression_set_priority(session, comp_priority);
gnutls_kx_set_priority(session, kx_priority);
-gnutls_protocol_set_priority(session, protocol_priority);
+gnutls_protocol_set_priority(session, proto_priority);
gnutls_mac_set_priority(session, mac_priority);

gnutls_cred_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
@@ -739,7 +839,10 @@
a TLS session.

   Arguments:
  -  require_ciphers  list of allowed ciphers
  +  require_ciphers  list of allowed ciphers or NULL
  +  require_mac      list of allowed MACs or NULL
  +  require_kx       list of allowed key_exchange methods or NULL
  +  require_proto    list of allowed protocols or NULL


   Returns:           OK on success
                      DEFER for errors before the start of the negotiation
  @@ -748,11 +851,15 @@
   */


int
-tls_server_start(uschar *require_ciphers)
+tls_server_start(uschar *require_ciphers, uschar *require_mac,
+ uschar *require_kx, uschar *require_proto)
{
int rc;
uschar *error;
uschar *expciphers = NULL;
+uschar *expmac = NULL;
+uschar *expkx = NULL;
+uschar *expproto = NULL;

/* Check for previous activation */

  @@ -774,7 +881,10 @@
     tls_crl);
   if (rc != OK) return rc;


  -if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
  +if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
  +    !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
  +    !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
  +    !expand_check(require_proto, US"gnutls_require_proto", &expproto))
     return FAIL;


/* If this is a host for which certificate verification is mandatory or
@@ -790,7 +900,8 @@

/* Prepare for new connection */

  -tls_session = tls_session_init(GNUTLS_SERVER, expciphers);
  +tls_session = tls_session_init(GNUTLS_SERVER, expciphers, expmac, expkx,
  +  expproto);
   if (tls_session == NULL)
     return tls_error(US"tls_session_init", NULL, GNUTLS_E_MEMORY_ERROR);


  @@ -883,13 +994,16 @@
   Arguments:
     fd                the fd of the connection
     host              connected host (for messages)
  -  addr
  +  addr              the first address (not used)
     dhparam           DH parameter file
     certificate       certificate file
     privatekey        private key file
     verify_certs      file for certificate verify
     verify_crl        CRL for verify
  -  require_ciphers   list of allowed ciphers
  +  require_ciphers   list of allowed ciphers or NULL
  +  require_mac       list of allowed MACs or NULL
  +  require_kx        list of allowed key_exchange methods or NULL
  +  require_proto     list of allowed protocols or NULL
     timeout           startup timeout


   Returns:            OK/DEFER/FAIL (because using common functions),
  @@ -899,10 +1013,14 @@
   int
   tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
     uschar *certificate, uschar *privatekey, uschar *verify_certs,
  -  uschar *verify_crl, uschar *require_ciphers, int timeout)
  +  uschar *verify_crl, uschar *require_ciphers, uschar *require_mac,
  +  uschar *require_kx, uschar *require_proto, int timeout)
   {
   const gnutls_datum *server_certs;
   uschar *expciphers = NULL;
  +uschar *expmac = NULL;
  +uschar *expkx = NULL;
  +uschar *expproto = NULL;
   uschar *error;
   unsigned int server_certs_size;
   int rc;
  @@ -914,10 +1032,15 @@
   rc = tls_init(host, certificate, privatekey, verify_certs, verify_crl);
   if (rc != OK) return rc;


  -if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers))
  +if (!expand_check(require_ciphers, US"tls_require_ciphers", &expciphers) ||
  +    !expand_check(require_mac, US"gnutls_require_mac", &expmac) ||
  +    !expand_check(require_kx, US"gnutls_require_kx", &expkx) ||
  +    !expand_check(require_proto, US"gnutls_require_proto", &expproto))
     return FAIL;


  -tls_session = tls_session_init(GNUTLS_CLIENT, expciphers);
  +tls_session = tls_session_init(GNUTLS_CLIENT, expciphers, expmac, expkx,
  +  expproto);
  +
   if (tls_session == NULL)
     return tls_error(US "tls_session_init", host, GNUTLS_E_MEMORY_ERROR);



  Index: tls-openssl.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/tls-openssl.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- tls-openssl.c    8 Jan 2007 10:50:18 -0000    1.9
  +++ tls-openssl.c    18 Jan 2007 15:35:42 -0000    1.10
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.9 2007/01/08 10:50:18 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/tls-openssl.c,v 1.10 2007/01/18 15:35:42 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -598,6 +598,11 @@


   Arguments:
     require_ciphers   allowed ciphers
  +  ------------------------------------------------------
  +  require_mac      list of allowed MACs                 ) Not used
  +  require_kx       list of allowed key_exchange methods )   for
  +  require_proto    list of allowed protocols            ) OpenSSL
  +  ------------------------------------------------------


   Returns:            OK on success
                       DEFER for errors before the start of the negotiation
  @@ -606,7 +611,8 @@
   */


   int
  -tls_server_start(uschar *require_ciphers)
  +tls_server_start(uschar *require_ciphers, uschar *require_mac,
  +  uschar *require_kx, uschar *require_proto)
   {
   int rc;
   uschar *expciphers;
  @@ -746,12 +752,19 @@
   Argument:
     fd               the fd of the connection
     host             connected host (for messages)
  +  addr             the first address
     dhparam          DH parameter file
     certificate      certificate file
     privatekey       private key file
     verify_certs     file for certificate verify
     crl              file containing CRL
     require_ciphers  list of allowed ciphers
  +  ------------------------------------------------------
  +  require_mac      list of allowed MACs                 ) Not used
  +  require_kx       list of allowed key_exchange methods )   for
  +  require_proto    list of allowed protocols            ) OpenSSL
  +  ------------------------------------------------------
  +  timeout          startup timeout


   Returns:           OK on success
                      FAIL otherwise - note that tls_error() will not give DEFER
  @@ -761,7 +774,8 @@
   int
   tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam,
     uschar *certificate, uschar *privatekey, uschar *verify_certs, uschar *crl,
  -  uschar *require_ciphers, int timeout)
  +  uschar *require_ciphers, uschar *require_mac, uschar *require_kx,
  +  uschar *require_proto, int timeout)
   {
   static uschar txt[256];
   uschar *expciphers;


  Index: smtp.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/transports/smtp.c,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- smtp.c    8 Jan 2007 10:50:20 -0000    1.30
  +++ smtp.c    18 Jan 2007 15:35:43 -0000    1.31
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.30 2007/01/08 10:50:20 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/transports/smtp.c,v 1.31 2007/01/18 15:35:43 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -63,6 +63,14 @@
         (void *)offsetof(smtp_transport_options_block, final_timeout) },
     { "gethostbyname",        opt_bool,
         (void *)offsetof(smtp_transport_options_block, gethostbyname) },
  +  #ifdef SUPPORT_TLS
  +  { "gnutls_require_kx",    opt_stringptr,
  +      (void *)offsetof(smtp_transport_options_block, gnutls_require_kx) },
  +  { "gnutls_require_mac",   opt_stringptr,
  +      (void *)offsetof(smtp_transport_options_block, gnutls_require_mac) },
  +  { "gnutls_require_protocols", opt_stringptr,
  +      (void *)offsetof(smtp_transport_options_block, gnutls_require_proto) },
  +  #endif
     { "helo_data",            opt_stringptr,
         (void *)offsetof(smtp_transport_options_block, helo_data) },
     { "hosts",                opt_stringptr,
  @@ -178,6 +186,9 @@
     NULL,                /* tls_crl */
     NULL,                /* tls_privatekey */
     NULL,                /* tls_require_ciphers */
  +  NULL,                /* gnutls_require_kx */
  +  NULL,                /* gnutls_require_mac */
  +  NULL,                /* gnutls_require_proto */
     NULL,                /* tls_verify_certificates */
     TRUE                 /* tls_tempfail_tryclear */
     #endif
  @@ -1053,13 +1064,18 @@


     else
       {
  -    int rc = tls_client_start(inblock.sock, host, addrlist,
  +    int rc = tls_client_start(inblock.sock,
  +      host,
  +      addrlist,
         NULL,                    /* No DH param */
         ob->tls_certificate,
         ob->tls_privatekey,
         ob->tls_verify_certificates,
         ob->tls_crl,
         ob->tls_require_ciphers,
  +      ob->gnutls_require_mac,
  +      ob->gnutls_require_kx,
  +      ob->gnutls_require_proto,
         ob->command_timeout);


       /* TLS negotiation failed; give an error. From outside, this function may


  Index: smtp.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/transports/smtp.h,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- smtp.h    8 Jan 2007 10:50:20 -0000    1.10
  +++ smtp.h    18 Jan 2007 15:35:43 -0000    1.11
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.10 2007/01/08 10:50:20 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/transports/smtp.h,v 1.11 2007/01/18 15:35:43 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -50,6 +50,9 @@
     uschar *tls_crl;
     uschar *tls_privatekey;
     uschar *tls_require_ciphers;
  +  uschar *gnutls_require_kx;
  +  uschar *gnutls_require_mac;
  +  uschar *gnutls_require_proto;
     uschar *tls_verify_certificates;
     BOOL    tls_tempfail_tryclear;
     #endif


  Index: 2011
  ===================================================================
  RCS file: /home/cvs/exim/exim-test/confs/2011,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- 2011    7 Feb 2006 10:34:26 -0000    1.1
  +++ 2011    18 Jan 2007 15:35:43 -0000    1.2
  @@ -1,6 +1,10 @@
   # Exim test configuration 2011


SERVER =
+CREQCIP =
+CREQMAC =
+SREQCIP =
+SREQMAC =

exim_path = EXIM_PATH
host_lookup_order = bydns
@@ -28,6 +32,9 @@
tls_verify_hosts = *
tls_verify_certificates = ${if eq {SERVER}{server}{DIR/aux-fixed/cert2}fail}

+SREQCIP
+SREQMAC
+

# ----- Routers -----

  @@ -52,7 +59,7 @@
     port = PORT_D
     tls_certificate = DIR/aux-fixed/cert2
     tls_privatekey = DIR/aux-fixed/cert2
  -  tls_require_ciphers = IDEA-CBC-MD5 \
  -    ${if eq{$host_address}{127.0.0.1}{:DES-CBC3-SHA:RSA_ARCFOUR_SHA}}
  +  CREQCIP
  +  CREQMAC


# End

  Index: 2011
  ===================================================================
  RCS file: /home/cvs/exim/exim-test/log/2011,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- 2011    7 Feb 2006 10:34:46 -0000    1.1
  +++ 2011    18 Jan 2007 15:35:43 -0000    1.2
  @@ -1,11 +1,50 @@
   1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@??? U=CALLER P=local S=sss
   1999-03-02 09:44:33 Start queue run: pid=pppp -qf
   1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] (gnutls_handshake): No supported cipher suites have been found.
  -1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@??? R=client T=send_to_server H=127.0.0.1 [127.0.0.1] X=TLS-1.0:RSA_ARCFOUR_SHA1:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS error on connection to 127.0.0.1 [127.0.0.1] (gnutls_handshake): No supported cipher suites have been found.
  +1999-03-02 09:44:33 10HmaX-0005vi-00 TLS session failure: delivering unencrypted to 127.0.0.1 [127.0.0.1] (not in hosts_require_tls)
  +1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@??? R=client T=send_to_server H=127.0.0.1 [127.0.0.1]
   1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
   1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_ARCFOUR_SHA1:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmaZ-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmbA-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmbB-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmbC-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmbD-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=SSL 3.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf
  +1999-03-02 09:44:33 Start queue run: pid=pppp -qf
  +1999-03-02 09:44:33 10HmbE-0005vi-00 => userx@??? R=client T=send_to_server H=ip4.ip4.ip4.ip4 [ip4.ip4.ip4.ip4] X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel"
  +1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
  +1999-03-02 09:44:33 End queue run: pid=pppp -qf


******** SERVER ********
1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
1999-03-02 09:44:33 TLS error on connection from the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] (gnutls_handshake): A TLS packet with unexpected length was received.
-1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtps X=TLS-1.0:RSA_ARCFOUR_SHA1:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 TLS error on connection from localhost (myhost.test.ex) [127.0.0.1] (gnutls_handshake): A TLS packet with unexpected length was received.
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@??? H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_ARCFOUR_SHA1:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=SSL 3.0:RSA_AES_256_CBC_SHA1:32 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@??? H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS-1.0:RSA_ARCFOUR_MD5:16 DN="C=UK,L=Cambridge,O=University of Cambridge,OU=Computing Service,CN=Philip Hazel" S=sss id=E10HmaX-0005vi-00@???

  Index: 2011
  ===================================================================
  RCS file: /home/cvs/exim/exim-test/scripts/2000-GnuTLS/2011,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- 2011    7 Feb 2006 10:54:47 -0000    1.1
  +++ 2011    18 Jan 2007 15:35:43 -0000    1.2
  @@ -1,9 +1,37 @@
  -# TLS client: require_ciphers
  +# TLS client & server: (gnu)tls_require_xxx
   gnutls
  +# Start up the server
   exim -DSERVER=server -bd -oX PORT_D
   ****
  +# This puts a message on the queue (queue_only is set).
   exim userx@???
   Testing
  +****
  +# This will fail to deliver encrypted because there are no acceptable 
  +# ciphers, so it will deliver in clear.
  +exim -qf -DCREQCIP=tls_require_ciphers=IDEA-CBC-MD5
  +****
  +# This delivers the message to the server, where it will remain
  +# on the queue because queue_only is set.
  +exim -qf -DCREQCIP=tls_require_ciphers=IDEA-CBC-MD5:DES-CBC3-SHA:RSA_ARCFOUR_SHA
  +****
  +# So we can deliver it again and again, with different parameters.
  +exim -qf -DCREQMAC=gnutls_require_mac=MD5
  +****
  +exim -qf -DCREQMAC=gnutls_require_mac=!SHA1
  +****
  +exim -qf -DCREQMAC=gnutls_require_mac=MD5:SHA
  +****
  +exim -qf -DCREQMAC=gnutls_require_kx=!DHE
  +****
  +exim -qf -DCREQMAC=gnutls_require_protocols=SSL3
  +****
  +# Restart the server with a cipher restriction
  +killdaemon
  +exim -DSERVER=server \
  +     -DSREQCIP=tls_require_ciphers=ARCFOUR \
  +     -DSREQMAC=gnutls_require_mac=MD5 \
  +     -bd -oX PORT_D
   ****
   exim -qf
   ****