]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3.7-RC3 v2.3.7-RC3
authorWietse Venema <wietse@porcupine.org>
Mon, 29 Jan 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 10 Feb 2018 20:57:20 +0000 (15:57 -0500)
17 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/src/global/mail_version.h
postfix/src/global/mime_state.c
postfix/src/global/record.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_session.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_exp.ref
postfix/src/tls/Makefile.in
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_server.c
postfix/src/util/match_list.c

index 86d18924c44ffde4e21bd1272055edb5ca96ed0d..dd38a02776fcca93fea35426ace3f2c7676263dc 100644 (file)
 -TXSASL_SERVER
 -TXSASL_SERVER_IMPL
 -TXSASL_SERVER_IMPL_INFO
+-Tcipher_probe
 -Tregex_t
 -Tregmatch_t
 -Tsasl_conn_t
index f0d473879b6237eff91d076b7f9ff71563b999b5..4aee528f324c6893935345d5d3ec4990b500d671 100644 (file)
@@ -12927,8 +12927,16 @@ Apologies for any names omitted.
        Duchovni.  Files: smtpd/smtpd_check.c.
 
        Workaround: don't insert header/body blank line separator
-       in malformed attachments, to avoid breaking digital signatures.
-       Switch from header to body state, for robust MIME parsing.
-       People concerned about MIME evasion can use a MIME normalizer
-       to corrupt their user's legitimate email.  File:
-       global/mime_state.c.
+       into malformed MIME attachments, to avoid breaking digital
+       signatures.  File: global/mime_state.c.
+
+20070118
+
+       Bugfix: match lists didn't implement ![ipv6address].  Problem
+       reported by Paulo Pacheco. File: util/match_list.c.
+
+200070129
+
+       Workaround: OpenSSL falsely concludes that AES256 support
+       is present when only AES128 is available.  Code by Victor
+       Duchovni.  File: tls/tls_misc.c.
index 1815464788366ca7da4234ee8d254ebd4e16d09b..887cc48beaf41b15fe8cf587f0d256263f184da5 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20070113"
-#define MAIL_VERSION_NUMBER    "2.3.7-RC2"
+#define MAIL_RELEASE_DATE      "20070129"
+#define MAIL_VERSION_NUMBER    "2.3.7-RC3"
 
 #ifdef SNAPSHOT
 # define MAIL_VERSION_DATE     "-" MAIL_RELEASE_DATE
index b81fc1f9072bd7a46ee0bedb96d84469c2ac271f..4b4bf69f99c2fd54c66cdc1b2c46a61007db1ede 100644 (file)
@@ -499,6 +499,7 @@ MIME_STATE *mime_state_alloc(int flags,
 
     /* Volatile members. */
     state->err_flags = 0;
+    state->body_offset = 0;                    /* XXX */
     SET_MIME_STATE(state, MIME_STATE_PRIMARY,
                   MIME_CTYPE_TEXT, MIME_STYPE_PLAIN,
                   MIME_ENC_7BIT, MIME_ENC_7BIT);
@@ -938,6 +939,15 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
         * messages. Otherwise, treat such headers as part of the "body". Set
         * the proper encoding information for the multipart prolog.
         * 
+        * XXX We parse headers inside message/* content even when the encoding
+        * is invalid (encoding != domain). With base64 we won't recognize
+        * any headers, and with quoted-printable we won't recognize MIME
+        * boundary strings, but the MIME processor will still resynchronize
+        * when it runs into the higher-level boundary string at the end of
+        * the message/* content. Although we will treat some headers as body
+        * text, we will still do a better job than if we were treating the
+        * entire message/* content as body text.
+        * 
         * XXX This changes state to MIME_STATE_NESTED and then outputs a body
         * line, so that the body offset is not properly reset.
         * 
@@ -973,13 +983,14 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
             * separator, nor does the Milter protocol pass it on to Milter
             * applications.
             * 
-            * XXX We don't insert a blank line separator with attachments, as
-            * this breaks digital signatures. Postfix shall not do a worse
-            * mail delivery job than crappy MTAs that can't even parse MIME.
-            * But we switch to the body state anyway.
+            * XXX We don't insert a blank line separator into attachments, to
+            * avoid breaking digital signatures. Postfix shall not do a
+            * worse mail delivery job than MTAs that can't even parse MIME.
+            * We switch to body state anyway, to avoid treating body text as
+            * header text, and mis-interpreting or truncating it. The code
+            * below for initial From_ lines is for educational purposes.
             * 
-            * People who worry about MIME evasion can use a MIME normalizer,
-            * and knowlingly corrupt legitimate email for their users.
+            * Sites concerned about MIME evasion can use a MIME normalizer.
             * Postfix has a different mission.
             */
            else {
@@ -989,9 +1000,25 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
                       state->curr_state == MIME_STATE_PRIMARY ? "primary" :
                         state->curr_state == MIME_STATE_NESTED ? "nested" :
                             "other");
-               if (state->curr_state == MIME_STATE_PRIMARY)
+               switch (state->curr_state) {
+               case MIME_STATE_PRIMARY:
                    BODY_OUT(state, REC_TYPE_NORM, "", 0);
-               SET_CURR_STATE(state, MIME_STATE_BODY);
+                   SET_CURR_STATE(state, MIME_STATE_BODY);
+                   break;
+#if 0
+               case MIME_STATE_NESTED:
+                   if (state->body_offset <= 1
+                       && rec_type == REC_TYPE_NORM
+                       && len > 7
+                       && (strncmp(text + (*text == '>'), "From ", 5) == 0
+                           || strncmp(text, "=46rom ", 7) == 0))
+                       break;
+                   /* FALLTHROUGH */
+#endif
+               default:
+                   SET_CURR_STATE(state, MIME_STATE_BODY);
+                   break;
+               }
            }
        }
 
index 3ef7ca7b5c287ae22eb98eb8c6b26d37aac0f044..96233f4263164c588d8983d87e9607233ffcfd43 100644 (file)
@@ -77,8 +77,8 @@
 /*     and REC_FLAG_DEFAULT for normal use.
 /*
 /*     rec_get() is a wrapper around rec_get_raw() that always
-/*     enables the REC_FLAG_FOLLOW_PTR and REC_FLAG_SKIP_DTXT
-/*     features.
+/*     enables the REC_FLAG_FOLLOW_PTR, REC_FLAG_SKIP_DTXT
+/*     and REC_FLAG_SEEK_END features.
 /*
 /*     rec_put() stores the specified record and returns the record
 /*     type, or REC_TYPE_ERROR in case of problems.
index dad89aae9ed4cfc715b3af0dac583faf0baebd08..8f6a00f140028b0ddce9664ec131cb37dbc22338 100644 (file)
@@ -210,6 +210,7 @@ smtp_chat.o: ../../include/dsn.h
 smtp_chat.o: ../../include/dsn_buf.h
 smtp_chat.o: ../../include/dsn_util.h
 smtp_chat.o: ../../include/htable.h
+smtp_chat.o: ../../include/int_filt.h
 smtp_chat.o: ../../include/line_wrap.h
 smtp_chat.o: ../../include/mail_addr.h
 smtp_chat.o: ../../include/mail_error.h
index 5c5d634706ec0ce48e1bfdcc783c03aaee79ba23..1f8dab64c1ccd656f72171e2c3840e887c6d5f83 100644 (file)
@@ -716,6 +716,7 @@ int     smtp_ext_prop_mask;
   * OpenSSL client state.
   */
 SSL_CTX *smtp_tls_ctx;
+int     smtp_tls_mand_level;
 
 #endif
 
@@ -879,6 +880,18 @@ static void pre_init(char *unused_name, char **unused_argv)
        props.CAfile = var_smtp_tls_CAfile;
        props.CApath = var_smtp_tls_CApath;
 
+       /*
+        * If the administrator set an invalid grade, use "medium" instead.
+        * The TLS library requires a valid setting.
+        */
+       smtp_tls_mand_level = tls_cipher_level(var_smtp_tls_mand_ciph);
+       if (smtp_tls_mand_level == TLS_CIPHER_NONE) {
+           smtp_tls_mand_level = TLS_CIPHER_MEDIUM;
+           msg_warn("invalid '%s' value '%s', using 'medium'",
+                    strcmp(var_procname, "smtp") == 0 ?
+                    VAR_SMTP_TLS_MAND_CIPH : VAR_LMTP_TLS_MAND_CIPH,
+                    var_smtp_tls_mand_ciph);
+       }
        smtp_tls_ctx = tls_client_init(&props);
        smtp_tls_list_init();
 #else
index af397d711d12c21429cbb6fac3e31d5c1d61fa30..98989805c430f4579ffe50a04a43ab4a6917c1bf 100644 (file)
@@ -168,6 +168,7 @@ extern int smtp_ext_prop_mask;              /* address externsion propagation */
 #ifdef USE_TLS
 
 extern SSL_CTX *smtp_tls_ctx;          /* client-side TLS engine */
+extern int smtp_tls_mand_level;                /* TLS_CIPHER_EXPORT, ... */
 
 #endif
 
index abb32789b713e782805837d4d1c66f3f51addbbe..d042840e505471be596d3c111934e9f1a7c540e0 100644 (file)
@@ -355,7 +355,7 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp)
     case TLS_LEV_ENCRYPT:
        also_exclude = "eNULL";
        if (cipher_level == TLS_CIPHER_NONE)
-           cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph);
+           cipher_level = smtp_tls_mand_level;
        mand_exclude = var_smtp_tls_mand_excl;
        break;
 
@@ -363,22 +363,14 @@ static void set_cipherlist(SMTP_SESSION *session, int cipher_level, int lmtp)
     case TLS_LEV_SECURE:
        also_exclude = "aNULL";
        if (cipher_level == TLS_CIPHER_NONE)
-           cipher_level = tls_cipher_level(var_smtp_tls_mand_ciph);
+           cipher_level = smtp_tls_mand_level;
        mand_exclude = var_smtp_tls_mand_excl;
        break;
     }
 
-    cipherlist = tls_cipher_list(cipher_level, exclude, mand_exclude,
-                                also_exclude, TLS_END_EXCLUDE);
-    if (cipherlist == 0) {
-       msg_warn("unknown '%s' value '%s' ignored, using 'medium'",
-                lmtp ? VAR_LMTP_TLS_MAND_CIPH : VAR_SMTP_TLS_MAND_CIPH,
-                var_smtp_tls_mand_ciph);
-       cipherlist = tls_cipher_list(TLS_CIPHER_MEDIUM, exclude, mand_exclude,
-                                    also_exclude, TLS_END_EXCLUDE);
-       if (cipherlist == 0)
-           msg_panic("NULL medium cipherlist");
-    }
+    cipherlist = tls_cipher_list(cipher_level, TLS_CIPH_EXCL_LIST,
+                                exclude, mand_exclude, also_exclude,
+                                TLS_CIPH_EXCL_END);
     session->tls_cipherlist = mystrdup(cipherlist);
 }
 
index 16f71294bfc7eb9ff4099cf6b6a899ce15358b92..9fa60e9efb996ebd730874c4a83598feccb6d416 100644 (file)
@@ -4226,6 +4226,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
        if (use_tls) {
 #ifdef USE_TLS
            tls_server_props props;
+           ARGV   *cipher_exclusions;
            int     havecert;
            int     oknocert;
            int     wantcert;
@@ -4271,32 +4272,44 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
            if (!enforce_tls && var_smtpd_tls_req_ccert)
                msg_warn("Can't require client certs unless TLS is required");
 
-           props.cipherlist =
-               tls_cipher_list(enforce_tls ?
-                               tls_cipher_level(var_smtpd_tls_mand_ciph) :
-                               TLS_CIPHER_EXPORT,
-                               var_smtpd_tls_excl_ciph,
-                               havecert ? "" : "aRSA aDSS",
-                               wantcert ? "aNULL" : "",
-                               enforce_tls ? var_smtpd_tls_mand_excl :
-                               TLS_END_EXCLUDE,
-                               TLS_END_EXCLUDE);
-
-           if (props.cipherlist == 0) {
-               msg_warn("unknown '%s' value '%s' ignored, using 'export'",
-                        VAR_SMTPD_TLS_MAND_CIPH, var_smtpd_tls_mand_ciph);
-               props.cipherlist =
-                   tls_cipher_list(TLS_CIPHER_EXPORT,
-                                   var_smtpd_tls_excl_ciph,
-                                   havecert ? "" : "aRSA aDSS",
-                                   wantcert ? "aNULL" : "",
-                                   enforce_tls ? var_smtpd_tls_mand_excl :
-                                   TLS_END_EXCLUDE,
-                                   TLS_END_EXCLUDE);
-           }
-           if (havecert || oknocert)
+           if (havecert || oknocert) {
+               cipher_exclusions = argv_alloc(3);
+               argv_add(cipher_exclusions, var_smtpd_tls_excl_ciph, ARGV_END);
+               if (wantcert)
+                   argv_add(cipher_exclusions, "aNULL", ARGV_END);
+
+               /*
+                * Detect problem configurations early, a certificate-less
+                * handshake can't use ciphers that need server certificates,
+                * so we want to fail now while setting up the cipherlist,
+                * not later. Also this detects any conflict between wantcert
+                * and !havecert.
+                */
+               if (!havecert)
+                   argv_add(cipher_exclusions, "aRSA", "aDSS", ARGV_END);
+               if (enforce_tls) {
+                   argv_add(cipher_exclusions,
+                            var_smtpd_tls_mand_excl, ARGV_END);
+
+                   /*
+                    * If the administrator set an invalid grade, use
+                    * "medium" instead. The TLS library requires a valid
+                    * setting.
+                    */
+                   props.cipher_level =
+                       tls_cipher_level(var_smtpd_tls_mand_ciph);
+                   if (props.cipher_level == TLS_CIPHER_NONE) {
+                       props.cipher_level = TLS_CIPHER_MEDIUM;
+                       msg_warn("invalid '%s' value '%s', using 'medium'",
+                                VAR_SMTPD_TLS_MAND_CIPH,
+                                var_smtpd_tls_mand_ciph);
+                   }
+               } else
+                   props.cipher_level = TLS_CIPHER_EXPORT;
+               props.cipher_exclusions = cipher_exclusions->argv;
                smtpd_tls_ctx = tls_server_init(&props);
-           else if (enforce_tls)
+               argv_free(cipher_exclusions);
+           } else if (enforce_tls)
                msg_fatal("No server certs available. TLS can't be enabled");
            else
                msg_warn("No server certs available. TLS won't be enabled");
index 75b6c84f388a341aa4aed66fa4127b2fbda82565..c04381ba8b5089f5cae821741474f725115fb4a4 100644 (file)
@@ -107,8 +107,8 @@ OK
 >>> mail sname@sdomain
 OK
 >>> rcpt rname@rdomain
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
-554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
+554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
 >>> #
 >>> # Check MX access
 >>> #
index 8b8d254bf2853460d4b30a197800a3ee9b381d2c..f0bc15572650cef565046827ec15a729cd5ded5d 100644 (file)
@@ -89,6 +89,7 @@ depend: $(MAKES)
        @$(EXPORT) make -f Makefile.in Makefile 1>&2
 
 # do not edit below this line - it is generated by 'make depend'
+tls_bio_ops.o: ../../include/argv.h
 tls_bio_ops.o: ../../include/iostuff.h
 tls_bio_ops.o: ../../include/msg.h
 tls_bio_ops.o: ../../include/name_code.h
@@ -99,6 +100,7 @@ tls_bio_ops.o: ../../include/vstream.h
 tls_bio_ops.o: ../../include/vstring.h
 tls_bio_ops.o: tls.h
 tls_bio_ops.o: tls_bio_ops.c
+tls_certkey.o: ../../include/argv.h
 tls_certkey.o: ../../include/msg.h
 tls_certkey.o: ../../include/name_code.h
 tls_certkey.o: ../../include/name_mask.h
@@ -122,6 +124,7 @@ tls_client.o: ../../include/vstring.h
 tls_client.o: tls.h
 tls_client.o: tls_client.c
 tls_client.o: tls_mgr.h
+tls_dh.o: ../../include/argv.h
 tls_dh.o: ../../include/msg.h
 tls_dh.o: ../../include/name_code.h
 tls_dh.o: ../../include/name_mask.h
@@ -131,6 +134,7 @@ tls_dh.o: ../../include/vstream.h
 tls_dh.o: ../../include/vstring.h
 tls_dh.o: tls.h
 tls_dh.o: tls_dh.c
+tls_level.o: ../../include/argv.h
 tls_level.o: ../../include/name_code.h
 tls_level.o: ../../include/name_mask.h
 tls_level.o: ../../include/sys_defs.h
@@ -151,6 +155,7 @@ tls_mgr.o: ../../include/vstream.h
 tls_mgr.o: ../../include/vstring.h
 tls_mgr.o: tls_mgr.c
 tls_mgr.o: tls_mgr.h
+tls_misc.o: ../../include/argv.h
 tls_misc.o: ../../include/msg.h
 tls_misc.o: ../../include/mymalloc.h
 tls_misc.o: ../../include/name_code.h
@@ -190,6 +195,7 @@ tls_prng_file.o: ../../include/mymalloc.h
 tls_prng_file.o: ../../include/sys_defs.h
 tls_prng_file.o: tls_prng.h
 tls_prng_file.o: tls_prng_file.c
+tls_rsa.o: ../../include/argv.h
 tls_rsa.o: ../../include/name_code.h
 tls_rsa.o: ../../include/name_mask.h
 tls_rsa.o: ../../include/sys_defs.h
@@ -211,6 +217,7 @@ tls_scache.o: ../../include/vstream.h
 tls_scache.o: ../../include/vstring.h
 tls_scache.o: tls_scache.c
 tls_scache.o: tls_scache.h
+tls_seed.o: ../../include/argv.h
 tls_seed.o: ../../include/msg.h
 tls_seed.o: ../../include/name_code.h
 tls_seed.o: ../../include/name_mask.h
@@ -237,6 +244,7 @@ tls_server.o: ../../include/vstring.h
 tls_server.o: tls.h
 tls_server.o: tls_mgr.h
 tls_server.o: tls_server.c
+tls_session.o: ../../include/argv.h
 tls_session.o: ../../include/msg.h
 tls_session.o: ../../include/mymalloc.h
 tls_session.o: ../../include/name_code.h
@@ -247,6 +255,7 @@ tls_session.o: ../../include/vstream.h
 tls_session.o: ../../include/vstring.h
 tls_session.o: tls.h
 tls_session.o: tls_session.c
+tls_stream.o: ../../include/argv.h
 tls_stream.o: ../../include/iostuff.h
 tls_stream.o: ../../include/msg.h
 tls_stream.o: ../../include/name_code.h
@@ -257,6 +266,7 @@ tls_stream.o: ../../include/vstream.h
 tls_stream.o: ../../include/vstring.h
 tls_stream.o: tls.h
 tls_stream.o: tls_stream.c
+tls_verify.o: ../../include/argv.h
 tls_verify.o: ../../include/msg.h
 tls_verify.o: ../../include/mymalloc.h
 tls_verify.o: ../../include/name_code.h
index f1370232703ffd56621b6386ab6e538387c7574e..ef679971255493710ea718cfd0f0e3325fc750c8 100644 (file)
@@ -56,6 +56,7 @@ extern NAME_CODE tls_level_table[];
 #include <vstream.h>
 #include <name_mask.h>
 #include <name_code.h>
+#include <argv.h>
 
 #define TLS_BIO_BUFSIZE        8192
 
@@ -128,8 +129,10 @@ extern NAME_CODE tls_cipher_level_table[];
 #define tls_cipher_level(str) \
     name_code(tls_cipher_level_table, NAME_CODE_FLAG_NONE, (str))
 
-#define TLS_END_EXCLUDE ((char *)0)
-extern const char *tls_cipher_list(int,...);
+#define TLS_CIPH_EXCL_ARRAY    1
+#define TLS_CIPH_EXCL_LIST     2
+#define TLS_CIPH_EXCL_END      ((char *) 0)
+extern const char *tls_cipher_list(int, int,...);
 
  /*
   * tls_client.c
@@ -181,7 +184,8 @@ typedef struct {
     const char *dkey_file;
     const char *CAfile;
     const char *CApath;
-    const char *cipherlist;
+    int     cipher_level;              /* TLS_CIPHER_EXPORT, ... */
+    char  **cipher_exclusions;
     int     protocols;                 /* protocols, 0 => all */
     const char *dh1024_param_file;
     const char *dh512_param_file;
index 0680ee0cd14bdd5f034560456dbb03caa810f96c..6ecac330b6df4d5e096330893af4c3202cdc6bd4 100644 (file)
@@ -718,13 +718,12 @@ TLScontext_t *tls_client_start(const tls_client_start_props *props)
      * the caller to salt the session lookup key with the cipher list, so
      * that sessions found in the cache are always acceptable.
      */
-    if (props->cipherlist != 0)
-       if (SSL_set_cipher_list(TLScontext->con, props->cipherlist) == 0) {
-           msg_warn("Could not set cipherlist: %s", props->cipherlist);
-           tls_print_errors();
-           tls_free_context(TLScontext);
-           return (0);
-       }
+    if (SSL_set_cipher_list(TLScontext->con, props->cipherlist) == 0) {
+       msg_warn("Could not set cipherlist: %s", props->cipherlist);
+       tls_print_errors();
+       tls_free_context(TLScontext);
+       return (0);
+    }
 
     /*
      * Try to load an existing session from the TLS session cache.
index f8738981946fae268facfa17a3bfe351b3d571f6..e0a1d832baee3ce0cab4d0e298ea379a1c82d08f 100644 (file)
@@ -18,8 +18,9 @@
 /*
 /*     long    tls_bug_bits()
 /*
-/*     const char *tls_cipher_list(cipher_level, ...)
+/*     const char *tls_cipher_list(cipher_level, options, ...)
 /*     int     cipher_level;
+/*     int     options;
 /*
 /*     void    tls_print_errors()
 /*
 /*     tls_cipher_list() generates a cipher list from the specified
 /*     grade, minus any ciphers specified via a null-terminated
 /*     list of string-valued exclusions. The result is overwritten
-/*     upon each call.
+/*     upon each call. The options argument specifies how exceptions
+/*     are specified: TLS_CIPH_EXCL_ARRAY (null-terminated character
+/*     pointer array) or TLS_CIPH_EXCL_LIST (variadic parameter
+/*     list terminated with TLS_CIPH_EXCL_END).
 /*
 /*     tls_print_errors() queries the OpenSSL error stack,
 /*     logs the error messages, and clears the error stack.
@@ -151,6 +155,41 @@ NAME_CODE tls_cipher_level_table[] = {
     0, TLS_CIPHER_NONE,
 };
 
+typedef struct {
+    char   *algorithm;
+    char   *exclusion;
+} cipher_probe;
+
+static cipher_probe cipher_probe_list[] = {
+
+    /*
+     * Check for missing AES256, OpenSSL only checks for AES128, and then
+     * enables both, because they only have one "is AES" boolean flag in the
+     * cipher property mask. The implementation cannot distinguish between
+     * AES128 and AES256. When some O/S distributions play games with
+     * libcrypto and exclude just the AES256 ciphers, they break the OpenSSL
+     * cipherlist construction code, with clients and servers potentially
+     * negotiating unimplemented ciphers.
+     * 
+     * This problem is peculiar to AES, which is not a single cipher, but a
+     * family of related ciphers. The other OpenSSL symmetric ciphers are
+     * atomic, either implemented or not. We expect that future ciphers will
+     * either also be atomic, or will have one property bit per family member
+     * and will be filtered accurately by OpenSSL.
+     * 
+     * If all else fails, this table can be expanded :-(
+     * 
+     * XXX: the probe for AES256 is enclosed in #ifdef. OpenSSL 0.9.6 and and
+     * earlier don't have AES 256, this requires 0.9.7 or later. We recommend
+     * against use of 0.9.6, it has open issues solved in 0.9.7l and 0.9.8d,
+     * but we are not yet prepared to drop support for 0.9.6.
+     */
+#ifdef SN_aes_256_cbc
+    SN_aes_256_cbc, SSL_TXT_AES "+HIGH",
+#endif
+    0, 0,
+};
+
  /*
   * Parsed OpenSSL version number.
   */
@@ -164,15 +203,19 @@ typedef struct {
 
 /* tls_cipher_list - Cipherlist for given grade, less exclusions */
 
-const char *tls_cipher_list(int cipher_level,...)
+const char *tls_cipher_list(int cipher_level, int options,...)
 {
     const char *myname = "tls_cipher_list";
     static VSTRING *buf;
+    static ARGV *exclude_unavailable;
+    cipher_probe *probe;
+    int     i;
     va_list ap;
     const char *exclude;
     char   *tok;
     char   *save;
     char   *cp;
+    char  **ex_array = 0;
 
     buf = buf ? buf : vstring_alloc(10);
     VSTRING_RESET(buf);
@@ -193,17 +236,30 @@ const char *tls_cipher_list(int cipher_level,...)
     case TLS_CIPHER_NULL:
        vstring_strcpy(buf, var_tls_null_clist);
        break;
-    case TLS_CIPHER_NONE:
-       return 0;
     default:
        msg_panic("%s: invalid cipher grade: %d", myname, cipher_level);
     }
-
     if (VSTRING_LEN(buf) == 0)
        msg_panic("%s: empty cipherlist", myname);
 
-    va_start(ap, cipher_level);
-    while ((exclude = va_arg(ap, char *)) != 0) {
+    /*
+     * Exclude ciphers that clueless distributions leave out of libcrypto.
+     */
+    if (exclude_unavailable == 0) {
+       exclude_unavailable = argv_alloc(1);
+       for (probe = cipher_probe_list; probe->algorithm; ++probe)
+           if (!EVP_get_cipherbyname(probe->algorithm))
+               argv_add(exclude_unavailable, probe->exclusion, (char *) 0);
+    }
+    for (i = 0; i < exclude_unavailable->argc; ++i)
+       vstring_sprintf_append(buf, ":!%s", exclude_unavailable->argv[i]);
+
+    va_start(ap, options);
+    if (options == TLS_CIPH_EXCL_ARRAY)
+       ex_array = va_arg(ap, char **);
+    else if (options != TLS_CIPH_EXCL_LIST)
+       msg_panic("%s: bad argument list option: %d", myname, options);
+    while ((exclude = ex_array ? *ex_array++ : va_arg(ap, char *)) != 0) {
        if (*exclude == '\0')
            continue;
        save = cp = mystrdup(exclude);
index 3c6dac341a458b4766574c342bcb7d45c9be31de..720cbcfcdd2bdc6e55b0ffe6b93ca8cdf89d6e98 100644 (file)
@@ -249,6 +249,7 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
     int     verify_flags = SSL_VERIFY_NONE;
     SSL_CTX *server_ctx;
     int     cachable;
+    const char *cipher_list;
 
     /* See skeleton at OpenSSL apps/s_server.c. */
 
@@ -328,12 +329,14 @@ SSL_CTX *tls_server_init(const tls_server_props *props)
     /*
      * Override the default cipher list with our own list.
      */
-    if (*props->cipherlist != 0)
-       if (SSL_CTX_set_cipher_list(server_ctx, props->cipherlist) == 0) {
-           tls_print_errors();
-           SSL_CTX_free(server_ctx);           /* 200411 */
-           return (0);
-       }
+    cipher_list = tls_cipher_list(props->cipher_level, TLS_CIPH_EXCL_ARRAY,
+                                 props->cipher_exclusions);
+    if (SSL_CTX_set_cipher_list(server_ctx, cipher_list) == 0) {
+       tls_print_errors();
+       msg_warn("Invalid cipherlist: %s", cipher_list);
+       SSL_CTX_free(server_ctx);               /* 200411 */
+       return (0);
+    }
 
     /*
      * Load the CA public key certificates for both the server cert and for
index efeebd939229c0273ce7fdf5af27dcc59042acbd..1dfa2fcf527646efd88e3d528de21ba1e4bcd8c3 100644 (file)
@@ -96,7 +96,7 @@ struct MATCH_LIST {
 };
 
 #define MATCH_DICTIONARY(pattern) \
-    ((pattern)[0] != '[' && strchr((pattern), ':') != 0)
+    ((pattern + strspn(pattern, "!"))[0] != '[' && strchr((pattern), ':') != 0)
 
 /* match_list_parse - parse buffer, destroy buffer */