]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.11-20130326
authorWietse Venema <wietse@porcupine.org>
Tue, 26 Mar 2013 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 6 Apr 2013 03:31:41 +0000 (23:31 -0400)
24 files changed:
postfix/HISTORY
postfix/html/smtpd.8.html
postfix/man/man8/smtpd.8
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtpd/smtpd.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_fprint.c [new file with mode: 0644]
postfix/src/tls/tls_level.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_server.c
postfix/src/tls/tls_verify.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/util/Makefile.in
postfix/src/util/iostuff.h
postfix/src/util/poll_fd.c [new file with mode: 0644]
postfix/src/util/read_wait.c [deleted file]
postfix/src/util/readable.c [deleted file]
postfix/src/util/sys_defs.h
postfix/src/util/writable.c [deleted file]
postfix/src/util/write_wait.c [deleted file]

index 9194cb2b603b242b4274fcb64b36a28561b393a7..91b190cf0863465c1ad0999bb2fc5091f5dcc612 100644 (file)
@@ -18332,7 +18332,7 @@ Apologies for any names omitted.
        src/dns/dns_strtype.c, src/dns/test_dns_lookup.c,
 
        Cleanup: the personality switch between "smtp" and "lmtp".
-       This streamlies the swicth in the SMTP/LMTP protocol, DNS
+       This streamlines the switch in the SMTP/LMTP protocol, DNS
        MX lookups, and configuration parameter names in error
        messages.  Viktor Dukhovni. Files: src/smtp/smtp.c,
        src/smtp/smtp.h, src/smtp/smtp_chat.c, src/smtp/smtp_connect.c,
@@ -18357,3 +18357,20 @@ Apologies for any names omitted.
 
        Portability: support for NetBSD 5.x, NetBSD 6.x and DragonFly
        BSD. Viktor Dukhovni. Files: makedefs, src/util/sys_defs.h.
+
+20130326
+
+       Cleanup: new module that consolidates all system-dependent
+       code to enforce read/write timeouts. This includes a final
+       workaround for MacOS X that uses poll() first, and select()
+       if that fails.  This makes their /dev/urandom workaround
+       unnecessary. Files: util/poll_fd.c, util/iostuff.h.  Removed:
+       util/readable.c, util/writable.c, util/read_wait.c,
+       util/write_wait.c.
+
+       Cleanup: refactor TLS digest functions, improved signature
+       for TLS session cache. Viktor Dukhovni. Files: src/smtp/smtp.c,
+       src/smtp/smtp_proto.c, src/smtpd/smtpd.c, src/tls/Makefile.in,
+       src/tls/tls.h, src/tls/tls_client.c, src/tls/tls_fprint.c,
+       src/tls/tls_level.c, src/tls/tls_misc.c, src/tls/tls_server.c,
+       src/tls/tls_verify.c, src/tlsproxy/tlsproxy.c.
index 1bde6223ce24d1ff2279800c63e1ed123b9b81b9..dc934bb9091698fed30550a8252689f17ad60156 100644 (file)
@@ -689,7 +689,9 @@ SMTPD(8)                                                              SMTPD(8)
 
        <b><a href="postconf.5.html#smtpd_log_access_permit_actions">smtpd_log_access_permit_actions</a> (empty)</b>
               Enable  logging  of  the  named "permit" actions in
-              SMTP server access lists.
+              SMTP server access  lists  (by  default,  the  SMTP
+              server  logs  "reject"  actions  but  not  "permit"
+              actions).
 
 <b>KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS</b>
        As of Postfix version 2.0, the SMTP  server  rejects  mail
index fc0f816559c8427eaa9dcb68e94290a065476f9f..d6c8bce001efcf3e26683a43b57d8433ab051992 100644 (file)
@@ -569,7 +569,8 @@ What remote SMTP clients are allowed to use the XCLIENT feature.
 Available in Postfix version 2.10 and later:
 .IP "\fBsmtpd_log_access_permit_actions (empty)\fR"
 Enable logging of the named "permit" actions in SMTP server
-access lists.
+access lists (by default, the SMTP server logs "reject" actions but
+not "permit" actions).
 .SH "KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS"
 .na
 .nf
index f519f386dcc33ea4fbaecbf38797938559153e39..fe4f14218119748f820ce028c15192b2c266db77 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20130325"
+#define MAIL_RELEASE_DATE      "20130326"
 #define MAIL_VERSION_NUMBER    "2.11"
 
 #ifdef SNAPSHOT
index 26e581c0d6aa9a494197622cec3ea57446c9f797..841910b0b949cea5185ce01ad4ff8550cbd8914a 100644 (file)
@@ -1110,7 +1110,7 @@ static void pre_init(char *unused_name, char **unused_argv)
                            eckey_file = var_smtp_tls_eckey_file,
                            CAfile = var_smtp_tls_CAfile,
                            CApath = var_smtp_tls_CApath,
-                           fpt_dgst = var_smtp_tls_fpt_dgst);
+                           mdalg = var_smtp_tls_fpt_dgst);
        smtp_tls_list_init();
 #else
        msg_warn("TLS has been selected, but TLS support is not compiled in");
index cd5299e65eb01f54c976bbe7ab2e3e7262713c62..aa3fe40806353d64fa7c7ee3f9068d8883ccf42d 100644 (file)
@@ -751,15 +751,6 @@ static int smtp_start_tls(SMTP_STATE *state)
     DONT_CACHE_THIS_SESSION;
 
     /*
-     * As of Postfix 2.5, tls_client_start() tries hard to always complete
-     * the TLS handshake. It records the verification and match status in the
-     * resulting TLScontext. It is now up to the application to abort the TLS
-     * connection if it chooses.
-     * 
-     * XXX When tls_client_start() fails then we don't know what state the SMTP
-     * connection is in, so we give up on this connection even if we are not
-     * required to use TLS.
-     * 
      * The following assumes sites that use TLS in a perverse configuration:
      * multiple hosts per hostname, or even multiple hosts per IP address.
      * All this without a shared TLS session cache, and they still want to
@@ -779,15 +770,28 @@ static int smtp_start_tls(SMTP_STATE *state)
      * ehlo response name to build a lookup key that works for split caches
      * (that announce distinct names) behind a load balancer.
      * 
-     * XXX: The TLS library may salt the serverid with further details of the
-     * protocol and cipher requirements.
+     * XXX: The TLS library will salt the serverid with further details of the
+     * protocol and cipher requirements including the server ehlo response.
+     * Deferring the helo to the digested suffix results in more predictable
+     * SSL session lookup key lengths.
+     */
+    serverid = vstring_alloc(10);
+    vstring_sprintf(serverid, "%s:%s:%u",
+                   state->service, session->addr, ntohs(session->port));
+
+    /*
+     * As of Postfix 2.5, tls_client_start() tries hard to always complete
+     * the TLS handshake. It records the verification and match status in the
+     * resulting TLScontext. It is now up to the application to abort the TLS
+     * connection if it chooses.
+     * 
+     * XXX When tls_client_start() fails then we don't know what state the SMTP
+     * connection is in, so we give up on this connection even if we are not
+     * required to use TLS.
      * 
      * Large parameter lists are error-prone, so we emulate a language feature
      * that C does not have natively: named parameter lists.
      */
-    serverid = vstring_alloc(10);
-    vstring_sprintf(serverid, "%s:%s:%u:%s", state->service, session->addr,
-                 ntohs(session->port), session->helo ? session->helo : "");
     session->tls_context =
        TLS_CLIENT_START(&tls_props,
                         ctx = smtp_tls_ctx,
@@ -798,12 +802,13 @@ static int smtp_start_tls(SMTP_STATE *state)
                         host = session->host,
                         namaddr = session->namaddrport,
                         serverid = vstring_str(serverid),
+                        helo = session->helo,
                         protocols = session->tls_protocols,
                         cipher_grade = session->tls_grade,
                         cipher_exclusions
                         = vstring_str(session->tls_exclusions),
                         matchargv = session->tls_matchargv,
-                        fpt_dgst = var_smtp_tls_fpt_dgst);
+                        mdalg = var_smtp_tls_fpt_dgst);
     vstring_free(serverid);
 
     if (session->tls_context == 0) {
@@ -851,7 +856,7 @@ static int smtp_start_tls(SMTP_STATE *state)
            return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
                                   SMTP_RESP_FAKE(&fake, "4.7.5"),
                                   "Server certificate not trusted"));
-    if (session->tls_level > TLS_LEV_ENCRYPT)
+    if (session->tls_level >= TLS_LEV_DANE)
        if (!TLS_CERT_IS_MATCHED(session->tls_context))
            return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
                                   SMTP_RESP_FAKE(&fake, "4.7.5"),
index 8cf16913184a9637ea6c0268104da7f949c2329a..b1bc22097cf480529a2b81623560de0e76e8c631 100644 (file)
 /*     Available in Postfix version 2.10 and later:
 /* .IP "\fBsmtpd_log_access_permit_actions (empty)\fR"
 /*     Enable logging of the named "permit" actions in SMTP server
-/*     access lists.
+/*     access lists (by default, the SMTP server logs "reject" actions but
+/*     not "permit" actions).
 /* KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS
 /* .ad
 /* .fi
@@ -4206,7 +4207,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
                         namaddr = state->namaddr,
                         cipher_grade = cipher_grade,
                         cipher_exclusions = STR(cipher_exclusions),
-                        fpt_dgst = var_smtpd_tls_fpt_dgst);
+                        mdalg = var_smtpd_tls_fpt_dgst);
 
 #endif                                         /* USE_TLSPROXY */
 
@@ -5148,7 +5149,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
                                    var_smtpd_tls_mand_proto :
                                    var_smtpd_tls_proto,
                                    ask_ccert = ask_client_cert,
-                                   fpt_dgst = var_smtpd_tls_fpt_dgst);
+                                   mdalg = var_smtpd_tls_fpt_dgst);
            else
                msg_warn("No server certs available. TLS won't be enabled");
 #endif                                         /* USE_TLSPROXY */
index 57096e1242a17b84c7adf27ba5b9f863b824daaa..f1565f3bb8ddfa05527839f6097b07dc0eef8617 100644 (file)
@@ -1,11 +1,11 @@
 SHELL  = /bin/sh
-SRCS   = tls_prng_dev.c tls_prng_egd.c tls_prng_file.c \
+SRCS   = tls_prng_dev.c tls_prng_egd.c tls_prng_file.c tls_fprint.c \
        tls_prng_exch.c tls_stream.c tls_bio_ops.c tls_misc.c tls_dh.c \
        tls_rsa.c tls_verify.c tls_certkey.c tls_session.c \
        tls_client.c tls_server.c tls_scache.c tls_mgr.c tls_seed.c \
        tls_level.c \
        tls_proxy_clnt.c tls_proxy_print.c tls_proxy_scan.c
-OBJS   = tls_prng_dev.o tls_prng_egd.o tls_prng_file.o \
+OBJS   = tls_prng_dev.o tls_prng_egd.o tls_prng_file.o tls_fprint.o \
        tls_prng_exch.o tls_stream.o tls_bio_ops.o tls_misc.o tls_dh.o \
        tls_rsa.o tls_verify.o tls_certkey.o tls_session.o \
        tls_client.o tls_server.o tls_scache.o tls_mgr.o tls_seed.o \
@@ -139,6 +139,19 @@ tls_dh.o: ../../include/vstream.h
 tls_dh.o: ../../include/vstring.h
 tls_dh.o: tls.h
 tls_dh.o: tls_dh.c
+tls_fprint.o: ../../include/argv.h
+tls_fprint.o: ../../include/mail_params.h
+tls_fprint.o: ../../include/msg.h
+tls_fprint.o: ../../include/mymalloc.h
+tls_fprint.o: ../../include/name_code.h
+tls_fprint.o: ../../include/name_mask.h
+tls_fprint.o: ../../include/stringops.h
+tls_fprint.o: ../../include/sys_defs.h
+tls_fprint.o: ../../include/vbuf.h
+tls_fprint.o: ../../include/vstream.h
+tls_fprint.o: ../../include/vstring.h
+tls_fprint.o: tls.h
+tls_fprint.o: tls_fprint.c
 tls_level.o: ../../include/argv.h
 tls_level.o: ../../include/name_code.h
 tls_level.o: ../../include/name_mask.h
@@ -320,7 +333,6 @@ 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/mail_params.h
 tls_verify.o: ../../include/msg.h
 tls_verify.o: ../../include/mymalloc.h
 tls_verify.o: ../../include/name_code.h
index 66972c509ffc255524e439616c82339c07cf55d2..3592f97bd2e61db07b75653e8ad599f73b3e14fe 100644 (file)
 #define TLS_LEV_NONE           0       /* plain-text only */
 #define TLS_LEV_MAY            1       /* wildcard */
 #define TLS_LEV_ENCRYPT                2       /* encrypted connection */
-#define TLS_LEV_FPRINT         3       /* "peer" CA-less verification */
-#define TLS_LEV_VERIFY         4       /* certificate verified */
-#define TLS_LEV_SECURE         5       /* "secure" verification */
+#define TLS_LEV_DANE           3       /* "peer" CA-less verification */
+#define TLS_LEV_FPRINT         4       /* "peer" CA-less verification */
+#define TLS_LEV_VERIFY         5       /* certificate verified */
+#define TLS_LEV_SECURE         6       /* "secure" verification */
 
 extern const NAME_CODE tls_level_table[];
 
@@ -97,8 +98,8 @@ typedef struct {
     int     log_mask;                  /* What to log */
     int     session_reused;            /* this session was reused */
     int     am_server;                 /* Are we an SSL server or client? */
+    const char *mdalg;                 /* default message digest algorithm */
     /* Built-in vs external SSL_accept/read/write/shutdown support. */
-    char   *fpt_dgst;                  /* Certificate fingerprint digest */
     VSTREAM *stream;                   /* Blocking-mode SMTP session */
 } TLS_SESS_STATE;
 
@@ -234,7 +235,7 @@ typedef struct {
     const char *eckey_file;
     const char *CAfile;
     const char *CApath;
-    const char *fpt_dgst;              /* Fingerprint digest algorithm */
+    const char *mdalg;                 /* default message digest algorithm */
 } TLS_CLIENT_INIT_PROPS;
 
 typedef struct {
@@ -246,11 +247,12 @@ typedef struct {
     const char *host;                  /* MX hostname */
     const char *namaddr;               /* nam[addr] for logging */
     const char *serverid;              /* Session cache key */
+    const char *helo;                  /* Server name from EHLO response */
     const char *protocols;             /* Enabled protocols */
     const char *cipher_grade;          /* Minimum cipher grade */
     const char *cipher_exclusions;     /* Ciphers to exclude */
     const ARGV *matchargv;             /* Cert match patterns */
-    const char *fpt_dgst;              /* Fingerprint digest algorithm */
+    const char *mdalg;                 /* default message digest algorithm */
 } TLS_CLIENT_START_PROPS;
 
 extern TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *);
@@ -267,11 +269,11 @@ extern TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *);
     ((props)->a12), ((props)->a13), (props)))
 
 #define TLS_CLIENT_START(props, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
-    a10, a11, a12, a13) \
+    a10, a11, a12, a13, a14) \
     tls_client_start((((props)->a1), ((props)->a2), ((props)->a3), \
     ((props)->a4), ((props)->a5), ((props)->a6), ((props)->a7), \
     ((props)->a8), ((props)->a9), ((props)->a10), ((props)->a11), \
-    ((props)->a12), ((props)->a13), (props)))
+    ((props)->a12), ((props)->a13), ((props)->a14), (props)))
 
  /*
   * tls_server.c
@@ -296,7 +298,7 @@ typedef struct {
     const char *dh1024_param_file;
     const char *dh512_param_file;
     int     ask_ccert;
-    const char *fpt_dgst;              /* Fingerprint digest algorithm */
+    const char *mdalg;                 /* default message digest algorithm */
 } TLS_SERVER_INIT_PROPS;
 
 typedef struct {
@@ -309,7 +311,7 @@ typedef struct {
     const char *namaddr;               /* Client nam[addr] for logging */
     const char *cipher_grade;
     const char *cipher_exclusions;
-    const char *fpt_dgst;              /* Fingerprint digest algorithm */
+    const char *mdalg;                 /* default message digest algorithm */
 } TLS_SERVER_START_PROPS;
 
 extern TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *);
@@ -397,9 +399,15 @@ extern RSA *tls_tmp_rsa_cb(SSL *, int, int);
 extern char *tls_peer_CN(X509 *, const TLS_SESS_STATE *);
 extern char *tls_issuer_CN(X509 *, const TLS_SESS_STATE *);
 extern const char *tls_dns_name(const GENERAL_NAME *, const TLS_SESS_STATE *);
+extern int tls_verify_certificate_callback(int, X509_STORE_CTX *);
+
+ /*
+  * tls_fprint.c
+  */
 extern char *tls_fingerprint(X509 *, const char *);
 extern char *tls_pkey_fprint(X509 *, const char *);
-extern int tls_verify_certificate_callback(int, X509_STORE_CTX *);
+extern char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *, long,
+                                        const char *);
 
  /*
   * tls_certkey.c
@@ -423,6 +431,7 @@ extern long tls_bug_bits(void);
 extern void tls_print_errors(void);
 extern void tls_info_callback(const SSL *, int, int);
 extern long tls_bio_dump_cb(BIO *, int, const char *, int, long, long);
+extern int tls_validate_digest(const char *);
 
  /*
   * tls_seed.c
index 2252b00fa8e72b1cce8ae0a249b8372b3f898ab8..19582ee6e85bfa7d5c71e919acd58d246054ae8e 100644 (file)
@@ -168,7 +168,7 @@ static SSL_SESSION *load_clnt_session(TLS_SESS_STATE *TLScontext)
      * Prepare the query.
      */
     if (TLScontext->log_mask & TLS_LOG_CACHE)
-       /* serverid already contains namaddrport information */
+       /* serverid contains transport:addr:port information */
        msg_info("looking for session %s in %s cache",
                 TLScontext->serverid, TLScontext->cache_type);
 
@@ -190,7 +190,7 @@ static SSL_SESSION *load_clnt_session(TLS_SESS_STATE *TLScontext)
        session = tls_session_activate(STR(session_data), LEN(session_data));
        if (session) {
            if (TLScontext->log_mask & TLS_LOG_CACHE)
-               /* serverid already contains namaddrport information */
+               /* serverid contains transport:addr:port information */
                msg_info("reloaded session %s from %s cache",
                         TLScontext->serverid, TLScontext->cache_type);
        }
@@ -230,7 +230,7 @@ static int new_client_session_cb(SSL *ssl, SSL_SESSION *session)
                  myname);
 
     if (TLScontext->log_mask & TLS_LOG_CACHE)
-       /* serverid already contains namaddrport information */
+       /* serverid contains transport:addr:port information */
        msg_info("save session %s to %s cache",
                 TLScontext->serverid, TLScontext->cache_type);
 
@@ -278,7 +278,7 @@ static void uncache_session(SSL_CTX *ctx, TLS_SESS_STATE *TLScontext)
        return;
 
     if (TLScontext->log_mask & TLS_LOG_CACHE)
-       /* serverid already contains namaddrport information */
+       /* serverid contains transport:addr:port information */
        msg_info("remove session %s from client cache", TLScontext->serverid);
 
     tls_mgr_delete(TLScontext->cache_type, TLScontext->serverid);
@@ -292,8 +292,6 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
     int     cachable;
     SSL_CTX *client_ctx;
     TLS_APPL_STATE *app_ctx;
-    const EVP_MD *md_alg;
-    unsigned int md_len;
     int     log_mask;
 
     /*
@@ -339,18 +337,8 @@ TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
      * If the administrator specifies an unsupported digest algorithm, fail
      * now, rather than in the middle of a TLS handshake.
      */
-    if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) {
-       msg_warn("Digest algorithm \"%s\" not found: disabling TLS support",
-                props->fpt_dgst);
-       return (0);
-    }
-
-    /*
-     * Sanity check: Newer shared libraries may use larger digests.
-     */
-    if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
-       msg_warn("Digest algorithm \"%s\" output size %u too large:"
-                " disabling TLS support", props->fpt_dgst, md_len);
+    if (!tls_validate_digest(props->mdalg)) {
+       msg_warn("disabling TLS support");
        return (0);
     }
 
@@ -732,8 +720,8 @@ static void verify_extract_print(TLS_SESS_STATE *TLScontext, X509 *peercert,
     char  **cpp;
 
     /* Non-null by contract */
-    TLScontext->peer_fingerprint = tls_fingerprint(peercert, props->fpt_dgst);
-    TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->fpt_dgst);
+    TLScontext->peer_fingerprint = tls_fingerprint(peercert, props->mdalg);
+    TLScontext->peer_pkey_fprint = tls_pkey_fprint(peercert, props->mdalg);
 
     /*
      * Compare the fingerprint against each acceptable value, ignoring
@@ -765,7 +753,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     X509   *peercert;
     TLS_SESS_STATE *TLScontext;
     TLS_APPL_STATE *app_ctx = props->ctx;
-    VSTRING *myserverid;
+    char   *myserverid;
     int     log_mask = app_ctx->log_mask;
 
     /*
@@ -781,19 +769,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     /*
      * First make sure we have valid protocol and cipher parameters
      * 
-     * The cipherlist will be applied to the global SSL context, where it can be
-     * repeatedly reset if necessary, but the protocol restrictions will be
-     * is applied to the SSL connection, because protocol restrictions in the
-     * global context cannot be cleared.
-     */
-
-    /*
-     * OpenSSL will ignore cached sessions that use the wrong protocol. So we
-     * do not need to filter out cached sessions with the "wrong" protocol,
-     * rather OpenSSL will simply negotiate a new session.
-     * 
-     * Still, we salt the session lookup key with the protocol list, so that
-     * sessions found in the cache are always acceptable.
+     * Per-session protocol restrictions must be applied to the SSL connection,
+     * as restrictions in the global context cannot be cleared.
      */
     protomask = tls_protocol_mask(props->protocols);
     if (protomask == TLS_PROTOCOL_INVALID) {
@@ -802,35 +779,39 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
                 props->namaddr, props->protocols);
        return (0);
     }
-    myserverid = vstring_alloc(100);
-    vstring_sprintf_append(myserverid, "%s&p=%d", props->serverid, protomask);
 
     /*
      * Per session cipher selection for sessions with mandatory encryption
      * 
-     * By the time a TLS client is negotiating ciphers it has already offered to
-     * re-use a session, it is too late to renege on the offer. So we must
-     * not attempt to re-use sessions whose ciphers are too weak. We salt the
-     * session lookup key with the cipher list, so that sessions found in the
-     * cache are always acceptable.
+     * The cipherlist is applied to the global SSL context, since it is likely
+     * to stay the same between connections, so we make use of a 1-element
+     * cache to return the same result for identical inputs.
      */
     cipher_list = tls_set_ciphers(app_ctx, "TLS", props->cipher_grade,
                                  props->cipher_exclusions);
     if (cipher_list == 0) {
        msg_warn("%s: %s: aborting TLS session",
                 props->namaddr, vstring_str(app_ctx->why));
-       vstring_free(myserverid);
        return (0);
     }
     if (log_mask & TLS_LOG_VERBOSE)
        msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list);
-    vstring_sprintf_append(myserverid, "&c=%s", cipher_list);
 
     /*
-     * Finally, salt the session key with the OpenSSL library version,
-     * (run-time, rather than compile-time, just in case that matters).
+     * OpenSSL will ignore cached sessions that use the wrong protocol. So we
+     * do not need to filter out cached sessions with the "wrong" protocol,
+     * rather OpenSSL will simply negotiate a new session.
+     * 
+     * We salt the session lookup key with the protocol list, so that sessions
+     * found in the cache are plausibly acceptable.
+     * 
+     * By the time a TLS client is negotiating ciphers it has already offered to
+     * re-use a session, it is too late to renege on the offer. So we must
+     * not attempt to re-use sessions whose ciphers are too weak. We salt the
+     * session lookup key with the cipher list, so that sessions found in the
+     * cache are always acceptable.
      */
-    vstring_sprintf_append(myserverid, "&l=%ld", (long) SSLeay());
+    myserverid = tls_serverid_digest(props, protomask, cipher_list);
 
     /*
      * Allocate a new TLScontext for the new connection and get an SSL
@@ -843,8 +824,9 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     TLScontext = tls_alloc_sess_context(log_mask, props->namaddr);
     TLScontext->cache_type = app_ctx->cache_type;
 
-    TLScontext->serverid = vstring_export(myserverid);
+    TLScontext->serverid = myserverid;
     TLScontext->stream = props->stream;
+    TLScontext->mdalg = props->mdalg;
 
     if ((TLScontext->con = SSL_new(app_ctx->ssl_ctx)) == NULL) {
        msg_warn("Could not allocate 'TLScontext->con' with SSL_new()");
diff --git a/postfix/src/tls/tls_fprint.c b/postfix/src/tls/tls_fprint.c
new file mode 100644 (file)
index 0000000..f7c10ea
--- /dev/null
@@ -0,0 +1,250 @@
+/*++
+/* NAME
+/*     tls_fprint 3
+/* SUMMARY
+/*     Digests fingerprints and all that.
+/* SYNOPSIS
+/*     #include <tls.h>
+/*
+/*     char    *tls_serverid_digest(props, protomask, ciphers);
+/*     const TLS_CLIENT_START_PROPS *props;
+/*     long    protomask;
+/*     const char *ciphers;
+/*
+/*     char    *tls_fingerprint(peercert, mdalg)
+/*     X509    *peercert;
+/*     const char *mdalg;
+/*
+/*     char    *tls_pkey_fprint(peercert, mdalg)
+/*     X509    *peercert;
+/*     const char *mdalg;
+/* DESCRIPTION
+/*     tls_fingerprint() returns a fingerprint of the the given
+/*     certificate using the requested message digest. Panics if the
+/*     (previously verified) digest algorithm is not found. The return
+/*     value is dynamically allocated with mymalloc(), and the caller
+/*     must eventually free it with myfree().
+/*
+/*     tls_pkey_fprint() returns a public-key fingerprint; in all
+/*     other respects the function behaves as tls_fingerprint().
+/*     The var_tls_bc_pkey_fprint variable enables an incorrect
+/*     algorithm that was used in Postfix versions 2.9.[0-5].
+/*
+/*     tls_serverid_digest() suffixes props->serverid computed by the SMTP
+/*     client with a digest of additional parameters needed to ensure
+/*     that re-used sessions are more likely to be reused and will satisfy
+/*     all protocol and security requirements. The caller should pass
+/*     the result to myfree().
+/*
+/*     Arguments:
+/* .IP peercert
+/*     Server or client X.509 certificate.
+/* .IP mdalg
+/*     Name of a message digest algorithm suitable for computing secure
+/*     (1st pre-image resistant) message digests of certificates. For now,
+/*     md5, sha1, or member of SHA-2 family if supported by OpenSSL.
+/* .IP props
+/*     The client start properties for the session, which include the
+/*     initial serverid from the SMTP client.
+/* .IP protomask
+/*     The mask of protocol exclusions.
+/* .IP ciphers
+/*     The SSL client cipherlist.
+/* LICENSE
+/* .ad
+/* .fi
+/*     This software is free. You can do with it whatever you want.
+/*     The original author kindly requests that you acknowledge
+/*     the use of his software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*
+/*     Viktor Dukhovni
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <ctype.h>
+
+#ifdef USE_TLS
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* TLS library. */
+
+#define TLS_INTERNAL
+#include <tls.h>
+
+/* Application-specific. */
+
+static const char hexcodes[] = "0123456789ABCDEF";
+
+#define chknonzero(ret)        (ok &= ((ret) ? 1 : 0))
+#define digestpl(p, l) chknonzero(EVP_DigestUpdate(mdctx, (char *)(p), (l)))
+#define digestptr(p) digestpl((p), sizeof(*(p)))
+#define digeststr(s) digestpl((s), strlen(s)+1)
+
+/* tls_serverid_digest - suffix props->serverid with parameter digest */
+
+char   *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask,
+                                   const char *ciphers)
+{
+    EVP_MD_CTX *mdctx;
+    const EVP_MD *md;
+    const char *mdalg;
+    unsigned char md_buf[EVP_MAX_MD_SIZE];
+    unsigned int md_len;
+    int     ok = 1;
+    int     i;
+    long    sslversion;
+    VSTRING *result;
+
+    /*
+     * Try to use sha256: our serverid choice should be strong enough to
+     * resist 2nd-preimage attacks with a difficulty comparable to that of
+     * DANE TLSA digests.  Failing that, we compute serverid digests with the
+     * default digest, but DANE requires sha256 and sha512, so if we must
+     * fall back to our default digest, DANE support won't be available.  We
+     * panic if the fallback algorithm is not available, as it was verified
+     * available in tls_client_init() and must not simply vanish.
+     */
+    if ((md = EVP_get_digestbyname(mdalg = "sha256")) == 0
+       && (md = EVP_get_digestbyname(mdalg = props->mdalg)) == 0)
+       msg_panic("digest algorithm \"%s\" not found", mdalg);
+
+    /* Salt the session lookup key with the OpenSSL runtime version. */
+    sslversion = SSLeay();
+
+    mdctx = EVP_MD_CTX_create();
+    chknonzero(EVP_DigestInit_ex(mdctx, md, NULL));
+    digeststr(props->helo ? props->helo : "");
+    digestptr(&sslversion);
+    digestptr(&protomask);
+    digeststr(ciphers);
+    chknonzero(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
+    EVP_MD_CTX_destroy(mdctx);
+    if (!ok)
+       msg_fatal("error computing %s message digest", mdalg);
+
+    /* Check for OpenSSL contract violation */
+    if (md_len > EVP_MAX_MD_SIZE)
+       msg_panic("unexpectedly large %s digest size: %u", mdalg, md_len);
+
+    /* Append the digest to the serverid */
+    result = vstring_alloc(strlen(props->serverid) + 1 + 2 * md_len);
+    vstring_strcpy(result, props->serverid);
+    VSTRING_ADDCH(result, ':');
+    for (i = 0; i < md_len; i++) {
+       VSTRING_ADDCH(result, hexcodes[(md_buf[i] & 0xf0) >> 4U]);
+       VSTRING_ADDCH(result, hexcodes[(md_buf[i] & 0x0f)]);
+    }
+    VSTRING_TERMINATE(result);
+    return (vstring_export(result));
+}
+
+/* tls_fprint - compute and encode digest of DER-encoded object */
+
+static char *tls_fprint(const char *buf, int len, const char *mdalg)
+{
+    EVP_MD_CTX *mdctx;
+    const EVP_MD *md;
+    unsigned char md_buf[EVP_MAX_MD_SIZE];
+    unsigned int md_len;
+    int     i;
+    int     ok = 1;
+    char   *result = 0;
+
+    /* Previously available in "init" routine. */
+    if ((md = EVP_get_digestbyname(mdalg)) == 0)
+       msg_panic("digest algorithm \"%s\" not found", mdalg);
+
+    mdctx = EVP_MD_CTX_create();
+    chknonzero(EVP_DigestInit_ex(mdctx, md, NULL));
+    digestpl(buf, len);
+    chknonzero(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
+    EVP_MD_CTX_destroy(mdctx);
+    if (!ok)
+       msg_fatal("error computing %s message digest", mdalg);
+
+    /* Check for OpenSSL contract violation */
+    if (md_len > EVP_MAX_MD_SIZE || md_len >= INT_MAX / 3)
+       msg_panic("unexpectedly large %s digest size: %u", mdalg, md_len);
+
+    result = mymalloc(md_len * 3);
+    for (i = 0; i < md_len; i++) {
+       result[i * 3] = hexcodes[(md_buf[i] & 0xf0) >> 4U];
+       result[(i * 3) + 1] = hexcodes[(md_buf[i] & 0x0f)];
+       result[(i * 3) + 2] = (i + 1 != md_len) ? ':' : '\0';
+    }
+    return (result);
+}
+
+/* tls_fingerprint - extract certificate fingerprint */
+
+char   *tls_fingerprint(X509 *peercert, const char *mdalg)
+{
+    int     len;
+    char   *buf;
+    char   *buf2;
+    char   *result;
+
+    len = i2d_X509(peercert, NULL);
+    buf2 = buf = mymalloc(len);
+    i2d_X509(peercert, (unsigned char **) &buf2);
+    if (buf2 - buf != len)
+       msg_panic("i2d_X509 invalid result length");
+
+    result = tls_fprint(buf, len, mdalg);
+    myfree(buf);
+
+    return (result);
+}
+
+/* tls_pkey_fprint - extract public key fingerprint from certificate */
+
+char   *tls_pkey_fprint(X509 *peercert, const char *mdalg)
+{
+    if (var_tls_bc_pkey_fprint) {
+       const char *myname = "tls_pkey_fprint";
+       ASN1_BIT_STRING *key;
+       char   *result;
+
+       key = X509_get0_pubkey_bitstr(peercert);
+       if (key == 0)
+           msg_fatal("%s: error extracting legacy public-key fingerprint: %m",
+                     myname);
+
+       result = tls_fprint((char *) key->data, key->length, mdalg);
+       return (result);
+    } else {
+       int     len;
+       char   *buf;
+       char   *buf2;
+       char   *result;
+
+       len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL);
+       buf2 = buf = mymalloc(len);
+       i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), (unsigned char **) &buf2);
+       if (buf2 - buf != len)
+           msg_panic("i2d_X509_PUBKEY invalid result length");
+
+       result = tls_fprint(buf, len, mdalg);
+       myfree(buf);
+       return (result);
+    }
+}
+
+#endif
index 32063200ef9fb27592b6fd911e71a78846d8be47..d87ec0cd9b8cf3fd849dddb6c9217c331c9c9056 100644 (file)
@@ -66,6 +66,9 @@ const NAME_CODE tls_level_table[] = {
     "none", TLS_LEV_NONE,
     "may", TLS_LEV_MAY,
     "encrypt", TLS_LEV_ENCRYPT,
+#if 0                                  /* Not yet */
+    "dane", TLS_LEV_DANE,
+#endif
     "fingerprint", TLS_LEV_FPRINT,
     "verify", TLS_LEV_VERIFY,
     "secure", TLS_LEV_SECURE,
index d09bb3225dc0708e8901a6b8f35c58bece75977c..c09e7f1899ade7acfda11b0fbd8304b91b3f3145 100644 (file)
@@ -72,6 +72,9 @@
 /*     int     tls_log_mask(log_param, log_level)
 /*     const char *log_param;
 /*     const char *log_level;
+/*
+/*     int     tls_validate_digest(dgst)
+/*     const char *dgst;
 /* DESCRIPTION
 /*     This module implements routines that support the TLS client
 /*     and server internals.
 /*     tls_log_mask() converts a TLS log_level value from string
 /*     to mask.  The main.cf parameter name is passed along for
 /*     diagnostics.
+/*
+/*     tls_validate_digest() returns non-zero if the named digest
+/*     is usable and zero otherwise.
 /* LICENSE
 /* .ad
 /* .fi
@@ -740,7 +746,7 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr)
     TLScontext->cipher_name = 0;
     TLScontext->log_mask = log_mask;
     TLScontext->namaddr = lowercase(mystrdup(namaddr));
-    TLScontext->fpt_dgst = 0;
+    TLScontext->mdalg = 0;                     /* Alias for props->mdalg */
 
     return (TLScontext);
 }
@@ -771,8 +777,6 @@ void    tls_free_context(TLS_SESS_STATE *TLScontext)
        myfree(TLScontext->peer_fingerprint);
     if (TLScontext->peer_pkey_fprint)
        myfree(TLScontext->peer_pkey_fprint);
-    if (TLScontext->fpt_dgst)
-       myfree(TLScontext->fpt_dgst);
 
     myfree((char *) TLScontext);
 }
@@ -1054,6 +1058,31 @@ long    tls_bio_dump_cb(BIO *bio, int cmd, const char *argp, int argi,
     return (ret);
 }
 
+int     tls_validate_digest(const char *dgst)
+{
+    const EVP_MD *md_alg;
+    unsigned int md_len;
+
+    /*
+     * If the administrator specifies an unsupported digest algorithm, fail
+     * now, rather than in the middle of a TLS handshake.
+     */
+    if ((md_alg = EVP_get_digestbyname(dgst)) == 0) {
+       msg_warn("Digest algorithm \"%s\" not found", dgst);
+       return (0);
+    }
+
+    /*
+     * Sanity check: Newer shared libraries may use larger digests.
+     */
+    if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
+       msg_warn("Digest algorithm \"%s\" output size %u too large",
+                dgst, md_len);
+       return (0);
+    }
+    return (1);
+}
+
 #else
 
  /*
index f0ebf669c5046a2fbe299ca562f4ea4c8cb3b654..c1bf8174041c2ca51cfd42952942ca68d4275e72 100644 (file)
@@ -286,8 +286,6 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
     int     cachable;
     int     protomask;
     TLS_APPL_STATE *app_ctx;
-    const EVP_MD *md_alg;
-    unsigned int md_len;
     int     log_mask;
 
     /*
@@ -344,18 +342,8 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
      * If the administrator specifies an unsupported digest algorithm, fail
      * now, rather than in the middle of a TLS handshake.
      */
-    if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) {
-       msg_warn("Digest algorithm \"%s\" not found: disabling TLS support",
-                props->fpt_dgst);
-       return (0);
-    }
-
-    /*
-     * Sanity check: Newer shared libraries may use larger digests.
-     */
-    if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
-       msg_warn("Digest algorithm \"%s\" output size %u too large:"
-                " disabling TLS support", props->fpt_dgst, md_len);
+    if (!tls_validate_digest(props->mdalg)) {
+       msg_warn("disabling TLS support");
        return (0);
     }
 
@@ -643,9 +631,8 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
 
     TLScontext->serverid = mystrdup(props->serverid);
     TLScontext->am_server = 1;
-
-    TLScontext->fpt_dgst = mystrdup(props->fpt_dgst);
     TLScontext->stream = props->stream;
+    TLScontext->mdalg = props->mdalg;
 
     ERR_clear_error();
     if ((TLScontext->con = (SSL *) SSL_new(app_ctx->ssl_ctx)) == 0) {
@@ -777,10 +764,8 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
        }
        TLScontext->peer_CN = tls_peer_CN(peer, TLScontext);
        TLScontext->issuer_CN = tls_issuer_CN(peer, TLScontext);
-       TLScontext->peer_fingerprint =
-           tls_fingerprint(peer, TLScontext->fpt_dgst);
-       TLScontext->peer_pkey_fprint =
-           tls_pkey_fprint(peer, TLScontext->fpt_dgst);
+       TLScontext->peer_fingerprint = tls_fingerprint(peer, TLScontext->mdalg);
+       TLScontext->peer_pkey_fprint = tls_pkey_fprint(peer, TLScontext->mdalg);
 
        if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_PEERCERT)) {
            msg_info("%s: subject_CN=%s, issuer=%s, fingerprint=%s"
@@ -795,6 +780,7 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
        TLScontext->peer_CN = mystrdup("");
        TLScontext->issuer_CN = mystrdup("");
        TLScontext->peer_fingerprint = mystrdup("");
+       TLScontext->peer_pkey_fprint = mystrdup("");
     }
 
     /*
index 9d909fe635f8aa3e8a5c569656f070422bdd1919..50dddc8cff5e67de749177391ce9709baead698e 100644 (file)
 /*     const GENERAL_NAME *gn;
 /*     TLS_SESS_STATE *TLScontext;
 /*
-/*     char *tls_fingerprint(peercert, dgst)
-/*     X509   *peercert;
-/*     const char *dgst;
-/*
-/*     char *tls_pkey_fprint(peercert, dgst)
-/*     X509   *peercert;
-/*     const char *dgst;
 /*
 /*     int     tls_verify_certificate_callback(ok, ctx)
 /*     int     ok;
 /*     are found, a null string is returned instead. Further sanity
 /*     checks may be added if the need arises.
 /*
-/*     tls_fingerprint() returns a fingerprint of the the given
-/*     certificate using the requested message digest. Panics if the
-/*     (previously verified) digest algorithm is not found. The return
-/*     value is dynamically allocated with mymalloc(), and the caller
-/*     must eventually free it with myfree().
-/*
-/*     tls_pkey_fprint() returns a public-key fingerprint; in all
-/*     other respects the function behaves as tls_fingerprint().
-/*     The var_tls_bc_pkey_fprint variable enables an incorrect
-/*     algorithm that was used in Postfix versions 2.9.[0-5].
-/*
 /*     tls_verify_callback() is called several times (directly or
 /*     indirectly) from crypto/x509/x509_vfy.c. It is called as
 /*     a final check, and if it returns "0", the handshake is
 /*     to be decoded and checked for validity.
 /* .IP peercert
 /*     Server or client X.509 certificate.
-/* .IP dgst
-/*     Name of a message digest algorithm suitable for computing secure
-/*     (1st pre-image resistant) message digests of certificates. For now,
-/*     md5, sha1, or member of SHA-2 family if supported by OpenSSL.
 /* .IP TLScontext
 /*     Server or client context for warning messages.
 /* DIAGNOSTICS
 #include <mymalloc.h>
 #include <stringops.h>
 
-/* Global library. */
-
-#include <mail_params.h>
-
 /* TLS library. */
 
 #define TLS_INTERNAL
 #include <tls.h>
 
-/* Application-specific. */
-
-static const char hexcodes[] = "0123456789ABCDEF";
-
 /* tls_verify_certificate_callback - verify peer certificate info */
 
 int     tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
@@ -503,96 +473,4 @@ char   *tls_issuer_CN(X509 *peer, const TLS_SESS_STATE *TLScontext)
     return (cn ? cn : mystrdup(""));
 }
 
-/* tls_fprint - compute and encode digest of DER-encoded object */
-
-static char *tls_fprint(const char *buf, int len, const char *dgst)
-{
-    const char *myname = "tls_fprint";
-    EVP_MD_CTX *mdctx;
-    const EVP_MD *md_alg;
-    unsigned char md_buf[EVP_MAX_MD_SIZE];
-    unsigned int md_len;
-    int     i;
-    char   *result = 0;
-
-    /* Previously available in "init" routine. */
-    if ((md_alg = EVP_get_digestbyname(dgst)) == 0)
-       msg_panic("%s: digest algorithm \"%s\" not found", myname, dgst);
-
-    mdctx = EVP_MD_CTX_create();
-    if (EVP_DigestInit_ex(mdctx, md_alg, NULL) == 0
-       || EVP_DigestUpdate(mdctx, buf, len) == 0
-       || EVP_DigestFinal_ex(mdctx, md_buf, &md_len) == 0)
-       msg_fatal("%s: error computing %s message digest", myname, dgst);
-    EVP_MD_CTX_destroy(mdctx);
-
-    /* Check for OpenSSL contract violation */
-    if (md_len > EVP_MAX_MD_SIZE || md_len >= INT_MAX / 3)
-       msg_panic("%s: unexpectedly large %s digest size: %u",
-                 myname, dgst, md_len);
-
-    result = mymalloc(md_len * 3);
-    for (i = 0; i < md_len; i++) {
-       result[i * 3] = hexcodes[(md_buf[i] & 0xf0) >> 4U];
-       result[(i * 3) + 1] = hexcodes[(md_buf[i] & 0x0f)];
-       result[(i * 3) + 2] = (i + 1 != md_len) ? ':' : '\0';
-    }
-    return (result);
-}
-
-/* tls_fingerprint - extract certificate fingerprint */
-
-char   *tls_fingerprint(X509 *peercert, const char *dgst)
-{
-    int     len;
-    char   *buf;
-    char   *buf2;
-    char   *result;
-
-    len = i2d_X509(peercert, NULL);
-    buf2 = buf = mymalloc(len);
-    i2d_X509(peercert, (unsigned char **) &buf2);
-    if (buf2 - buf != len)
-       msg_panic("i2d_X509 invalid result length");
-
-    result = tls_fprint(buf, len, dgst);
-    myfree(buf);
-
-    return (result);
-}
-
-/* tls_pkey_fprint - extract public key fingerprint from certificate */
-
-char   *tls_pkey_fprint(X509 *peercert, const char *dgst)
-{
-    if (var_tls_bc_pkey_fprint) {
-       const char *myname = "tls_pkey_fprint";
-       ASN1_BIT_STRING *key;
-       char   *result;
-
-       key = X509_get0_pubkey_bitstr(peercert);
-       if (key == 0)
-           msg_fatal("%s: error extracting legacy public-key fingerprint: %m",
-                     myname);
-
-       result = tls_fprint((char *) key->data, key->length, dgst);
-       return (result);
-    } else {
-       int     len;
-       char   *buf;
-       char   *buf2;
-       char   *result;
-
-       len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL);
-       buf2 = buf = mymalloc(len);
-       i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), (unsigned char **) &buf2);
-       if (buf2 - buf != len)
-           msg_panic("i2d_X509_PUBKEY invalid result length");
-
-       result = tls_fprint(buf, len, dgst);
-       myfree(buf);
-       return (result);
-    }
-}
-
 #endif
index 78d15a8f0fee3ea2cccedc21bdc8bfe20c9549a2..e2e1d348fdfb5234c9070215398b4e4482ba7f92 100644 (file)
@@ -698,7 +698,7 @@ static void tlsp_start_tls(TLSP_STATE *state)
                         namaddr = state->remote_endpt,
                         cipher_grade = cipher_grade,
                         cipher_exclusions = STR(cipher_exclusions),
-                        fpt_dgst = var_tlsp_tls_fpt_dgst);
+                        mdalg = var_tlsp_tls_fpt_dgst);
 
     if (state->tls_context == 0) {
        tlsp_state_free(state);
@@ -993,7 +993,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
                            var_tlsp_tls_mand_proto :
                            var_tlsp_tls_proto,
                            ask_ccert = ask_client_cert,
-                           fpt_dgst = var_tlsp_tls_fpt_dgst);
+                           mdalg = var_tlsp_tls_fpt_dgst);
     else
        msg_warn("No server certs available. TLS can't be enabled");
 
index 14216c62b3681d35df3ac375035572955468a19b..7be09a31141bd9cf7fa5045e32194a504c21a5c9 100644 (file)
@@ -18,7 +18,7 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \
        neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \
        peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \
-       read_wait.c readable.c readlline.c ring.c safe_getenv.c safe_open.c \
+       readlline.c ring.c safe_getenv.c safe_open.c \
        sane_accept.c sane_connect.c sane_link.c sane_rename.c \
        sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \
        sigdelay.c skipblanks.c sock_addr.c spawn_command.c split_at.c \
@@ -28,14 +28,15 @@ SRCS        = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        translit.c trimblanks.c unescape.c unix_connect.c unix_listen.c \
        unix_recv_fd.c unix_send_fd.c unix_trigger.c unsafe.c uppercase.c \
        username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
-       vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
-       write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
+       vstream_popen.c vstring.c vstring_vstream.c watchdog.c \
+       write_buf.c sane_basename.c format_tv.c allspace.c \
        allascii.c load_file.c killme_after.c vstream_tweak.c \
        pass_trigger.c edit_file.c inet_windowsize.c \
        unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
        ip_match.c nbbio.c base32_code.c dict_test.c \
        dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c \
-       dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c
+       dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c \
+       poll_fd.c
 OBJS   = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
        attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -55,7 +56,7 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
        neuter.o non_blocking.o nvtable.o open_as.o open_limit.o open_lock.o \
        peekfd.o percentm.o posix_signals.o printable.o rand_sleep.o \
-       read_wait.o readable.o readlline.o ring.o safe_getenv.o safe_open.o \
+       readlline.o ring.o safe_getenv.o safe_open.o \
        sane_accept.o sane_connect.o sane_link.o sane_rename.o \
        sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \
        sigdelay.o skipblanks.o sock_addr.o spawn_command.o split_at.o \
@@ -65,14 +66,15 @@ OBJS        = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        translit.o trimblanks.o unescape.o unix_connect.o unix_listen.o \
        unix_recv_fd.o unix_send_fd.o unix_trigger.o unsafe.o uppercase.o \
        username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
-       vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
-       write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
+       vstream_popen.o vstring.o vstring_vstream.o watchdog.o \
+       write_buf.o sane_basename.o format_tv.o allspace.o \
        allascii.o load_file.o killme_after.o vstream_tweak.o \
        pass_trigger.o edit_file.o inet_windowsize.o \
        unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
        ip_match.o nbbio.o base32_code.o dict_test.o \
        dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o \
-       dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o
+       dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o \
+       poll_fd.o
 HDRS   = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
        dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
@@ -1644,6 +1646,10 @@ percentm.o: percentm.h
 percentm.o: sys_defs.h
 percentm.o: vbuf.h
 percentm.o: vstring.h
+poll_fd.o: iostuff.h
+poll_fd.o: msg.h
+poll_fd.o: poll_fd.c
+poll_fd.o: sys_defs.h
 posix_signals.o: posix_signals.c
 posix_signals.o: posix_signals.h
 posix_signals.o: sys_defs.h
@@ -1657,14 +1663,6 @@ rand_sleep.o: msg.h
 rand_sleep.o: myrand.h
 rand_sleep.o: rand_sleep.c
 rand_sleep.o: sys_defs.h
-read_wait.o: iostuff.h
-read_wait.o: msg.h
-read_wait.o: read_wait.c
-read_wait.o: sys_defs.h
-readable.o: iostuff.h
-readable.o: msg.h
-readable.o: readable.c
-readable.o: sys_defs.h
 readlline.o: msg.h
 readlline.o: readlline.c
 readlline.o: readlline.h
@@ -1981,15 +1979,7 @@ watchdog.o: posix_signals.h
 watchdog.o: sys_defs.h
 watchdog.o: watchdog.c
 watchdog.o: watchdog.h
-writable.o: iostuff.h
-writable.o: msg.h
-writable.o: sys_defs.h
-writable.o: writable.c
 write_buf.o: iostuff.h
 write_buf.o: msg.h
 write_buf.o: sys_defs.h
 write_buf.o: write_buf.c
-write_wait.o: iostuff.h
-write_wait.o: msg.h
-write_wait.o: sys_defs.h
-write_wait.o: write_wait.c
index 8a2704a96d87f7a7a6ed09a142b733ca87966a58..da3fa3a38777c2436c058e4caf2f55404a02b986 100644 (file)
 extern int non_blocking(int, int);
 extern int close_on_exec(int, int);
 extern int open_limit(int);
-extern int readable(int);
-extern int writable(int);
+extern int poll_fd(int, int, int, int);
 extern off_t get_file_limit(void);
 extern void set_file_limit(off_t);
 extern ssize_t peekfd(int);
-extern int read_wait(int, int);
-extern int write_wait(int, int);
 extern ssize_t write_buf(int, const char *, ssize_t, int);
 extern ssize_t timed_read(int, void *, size_t, int, void *);
 extern ssize_t timed_write(int, void *, size_t, int, void *);
@@ -36,9 +33,18 @@ extern int unix_send_fd(int, int);
 extern ssize_t dummy_read(int, void *, size_t, int, void *);
 extern ssize_t dummy_write(int, void *, size_t, int, void *);
 
+#define readable(fd)           poll_fd((fd), POLL_FD_READ, 0, 1)
+#define writable(fd)           poll_fd((fd), POLL_FD_WRITE, 0, 1)
+
+#define read_wait(fd, time_limit) poll_fd((fd), POLL_FD_READ, (time_limit), 0)
+#define write_wait(fd, time_limit) poll_fd((fd), POLL_FD_WRITE, (time_limit), 0)
+
 extern int inet_windowsize;
 extern void set_inet_windowsize(int, int);
 
+#define POLL_FD_READ   0
+#define POLL_FD_WRITE  1
+
 #define BLOCKING       0
 #define NON_BLOCKING   1
 
diff --git a/postfix/src/util/poll_fd.c b/postfix/src/util/poll_fd.c
new file mode 100644 (file)
index 0000000..d7f84a2
--- /dev/null
@@ -0,0 +1,268 @@
+/*++
+/* NAME
+/*     poll_fd 3
+/* SUMMARY
+/*     wait until file descriptor becomes readable or writable
+/* SYNOPSIS
+/*     #include <iostuff.h>
+/*
+/*     int     readable(fd)
+/*     int     fd;
+/*
+/*     int     writable(fd)
+/*     int     fd;
+/*
+/*     int     read_wait(fd, timeout)
+/*     int     fd;
+/*     int     timeout
+/*
+/*     int     write_wait(fd, timeout)
+/*     int     fd;
+/*     int     timeout
+/*
+/*     int     poll_fd(fd, request, time_limit, success_val)
+/*     int     fd;
+/*     int     request;
+/*     int     time_limit;
+/*     int     success_val;
+/* DESCRIPTION
+/*     The functions in this module are macros that provide a
+/*     convenient interface to poll_fd().
+/*
+/*     readable() asks the kernel if the specified file descriptor
+/*     is readable, i.e. a read operation would not block.
+/*
+/*     writable() asks the kernel if the specified file descriptor
+/*     is writable, i.e. a write operation would not block.
+/*
+/*     read_wait() waits until the specified file descriptor becomes
+/*     readable, or until the time limit is reached.
+/*
+/*     write_wait() waits until the specified file descriptor
+/*     becomes writable, or until the time limit is reached.
+/*
+/*     poll_fd() waits until the specified file descriptor becomes
+/*     readable or writable, or until the time limit is reached.
+/*
+/*     Arguments:
+/* .IP fd
+/*     File descriptor. With implementations based on select(), a
+/*     best effort is made to handle descriptors >=FD_SETSIZE.
+/* .IP request
+/*     POLL_FD_READ (wait until readable) or POLL_FD_WRITE (wait
+/*     until writable).
+/* .IP time_limit
+/*     A positive value specifies a time limit in seconds. A zero
+/*     value effects a poll (return immediately).  A negative value
+/*     means wait until the requested POLL_FD_READ or POLL_FD_WRITE
+/*     condition becomes true.
+/* .IP success_val
+/*     Result value when the requested POLL_FD_READ or POLL_FD_WRITE
+/*     condition is true.
+/* DIAGNOSTICS
+/*     Panic: interface violation. All system call errors are fatal
+/*     unless specified otherwise.
+/*
+/*     readable() and writable() return 1 when the requested
+/*     condition is true, zero when it is false. They never return
+/*     an error indication.
+/*
+/*     read_wait() and write_wait() return zero when successful,
+/*     -1 with errno set to ETIMEDOUT when the time limit was
+/*     reached.
+/*
+/*     poll_fd() returns -1 with errno set to ETIMEDOUT when the
+/*     time limit was reached, success_val if the requested
+/*     POLL_FD_READ or POLL_FD_WRITE condition is true, and returns
+/*     zero otherwise.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef USE_SYSV_POLL
+#include <poll.h>
+#endif
+
+#ifdef USE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <iostuff.h>
+
+ /*
+  * Use select() only.
+  */
+#ifdef USE_BSD_SELECT
+#define poll_fd_bsd    poll_fd
+#undef USE_SYSV_POLL
+#undef USE_SYSV_POLL_WITH_SELECT
+#endif
+
+ /*
+  * Use poll() only.
+  */
+#ifdef USE_SYSV_POLL
+#define poll_fd_sysv   poll_fd
+#undef USE_SYSV_POLL_WITH_SELECT
+#endif
+
+ /*
+  * Use poll() with fall-back to select(). MacOSX needs this for devices.
+  */
+#ifdef USE_SYSV_POLL_WITH_SELECT
+#define poll_fd_sysv   poll_fd
+#define USE_SYSV_POLL
+#define USE_BSD_SELECT
+int     poll_fd_bsd(int, int, int, int);
+
+#endif
+
+ /*
+  * Sanity check.
+  */
+#if !defined(USE_BSD_SELECT) && !defined(USE_SYSV_POLL)
+#error "specify USE_BSD_SELECT, USE_SYSV_POLL or USE_SYSV_POLL_WITH_SELECT"
+#endif
+
+#ifdef USE_BSD_SELECT
+
+/* poll_fd_bsd - block with time_limit until file descriptor is ready */
+
+int     poll_fd_bsd(int fd, int request, int time_limit, int success_val)
+{
+    fd_set  req_fds;
+    fd_set *read_fds;
+    fd_set *write_fds;
+    fd_set  except_fds;
+    struct timeval tv;
+    struct timeval *tp;
+    int     temp_fd = -1;
+
+    /*
+     * Sanity checks.
+     */
+    if (FD_SETSIZE <= fd) {
+       if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE)
+           msg_fatal("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
+       fd = temp_fd;
+    }
+
+    /*
+     * Use select() so we do not depend on alarm() and on signal() handlers.
+     * Restart the select when interrupted by some signal. Some select()
+     * implementations reduce the time to wait when interrupted, which is
+     * exactly what we want.
+     */
+    FD_ZERO(&req_fds);
+    FD_SET(fd, &req_fds);
+    except_fds = req_fds;
+    if (request == POLL_FD_READ) {
+       read_fds = &req_fds;
+       write_fds = 0;
+    } else if (request == POLL_FD_WRITE) {
+       read_fds = 0;
+       write_fds = &req_fds;
+    } else {
+       msg_panic("poll_fd: bad request %d", request);
+    }
+
+    if (time_limit >= 0) {
+       tv.tv_usec = 0;
+       tv.tv_sec = time_limit;
+       tp = &tv;
+    } else {
+       tp = 0;
+    }
+
+    for (;;) {
+       switch (select(fd + 1, read_fds, write_fds, &except_fds, tp)) {
+       case -1:
+           if (errno != EINTR)
+               msg_fatal("select: %m");
+           continue;
+       case 0:
+           if (temp_fd != -1)
+               (void) close(temp_fd);
+           if (time_limit == 0) {
+               return (0);
+           } else {
+               errno = ETIMEDOUT;
+               return (-1);
+           }
+       default:
+           if (temp_fd != -1)
+               (void) close(temp_fd);
+           return (success_val);
+       }
+    }
+}
+
+#endif
+
+#ifdef USE_SYSV_POLL
+
+/* poll_fd_sysv - block with time_limit until file descriptor is ready */
+
+int     poll_fd_sysv(int fd, int request, int time_limit, int success_val)
+{
+    struct pollfd pollfd;
+
+    /*
+     * System-V poll() is optimal for polling a few descriptors.
+     */
+#define WAIT_FOR_EVENT (-1)
+
+    pollfd.fd = fd;
+    if (request == POLL_FD_READ)
+       pollfd.events = POLLIN;
+    else if (request == POLL_FD_WRITE)
+       pollfd.events = POLLOUT;
+    else
+       msg_panic("poll_fd: bad request %d", request);
+
+    for (;;) {
+       switch (poll(&pollfd, 1, time_limit < 0 ?
+                    WAIT_FOR_EVENT : time_limit * 1000)) {
+       case -1:
+           if (errno != EINTR)
+#ifdef USE_SYSV_POLL_WITH_SELECT
+               return (poll_fd_bsd(fd, request, time_limit, success_val));
+#else
+               msg_fatal("poll: %m");
+#endif
+           continue;
+       case 0:
+           if (time_limit == 0) {
+               return (0);
+           } else {
+               errno = ETIMEDOUT;
+               return (-1);
+           }
+       default:
+           if (pollfd.revents & POLLNVAL)
+               msg_fatal("poll: %m");
+           return (success_val);
+       }
+    }
+}
+
+#endif
diff --git a/postfix/src/util/read_wait.c b/postfix/src/util/read_wait.c
deleted file mode 100644 (file)
index 096b38a..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*++
-/* NAME
-/*     read_wait 3
-/* SUMMARY
-/*     wait until descriptor becomes readable
-/* SYNOPSIS
-/*     #include <iostuff.h>
-/*
-/*     int     read_wait(fd, timeout)
-/*     int     fd;
-/*     int     timeout;
-/* DESCRIPTION
-/*     read_wait() blocks the current process until the specified file
-/*     descriptor becomes readable, or until the deadline is exceeded.
-/*
-/*     Arguments:
-/* .IP fd
-/*     File descriptor. With implementations based on select(),
-/*     a best effort is made to handle descriptors >=FD_SETSIZE.
-/* .IP timeout
-/*     If positive, deadline in seconds. A zero value effects a poll.
-/*     A negative value means wait until something happens.
-/* DIAGNOSTICS
-/*     Panic: interface violation. All system call errors are fatal.
-/*
-/*     A zero result means success.  When the specified deadline is
-/*     exceeded, read_wait() returns -1 and sets errno to ETIMEDOUT.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#ifdef USE_SYSV_POLL
-#include <poll.h>
-#endif
-
-#ifdef USE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* read_wait - block with timeout until file descriptor is readable */
-
-int     read_wait(int fd, int timeout)
-{
-#if defined(NO_SYSV_POLL)
-    fd_set  read_fds;
-    fd_set  except_fds;
-    struct timeval tv;
-    struct timeval *tp;
-    int     temp_fd = -1;
-
-    /*
-     * Sanity checks.
-     */
-    if (FD_SETSIZE <= fd) {
-       if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE)
-           msg_fatal("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
-       fd = temp_fd;
-    }
-
-    /*
-     * Use select() so we do not depend on alarm() and on signal() handlers.
-     * Restart the select when interrupted by some signal. Some select()
-     * implementations reduce the time to wait when interrupted, which is
-     * exactly what we want.
-     */
-    FD_ZERO(&read_fds);
-    FD_SET(fd, &read_fds);
-    FD_ZERO(&except_fds);
-    FD_SET(fd, &except_fds);
-    if (timeout >= 0) {
-       tv.tv_usec = 0;
-       tv.tv_sec = timeout;
-       tp = &tv;
-    } else {
-       tp = 0;
-    }
-
-    for (;;) {
-       switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, tp)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("select: %m");
-           continue;
-       case 0:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           errno = ETIMEDOUT;
-           return (-1);
-       default:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (0);
-       }
-    }
-#elif defined(USE_SYSV_POLL)
-
-    /*
-     * System-V poll() is optimal for polling a few descriptors.
-     */
-    struct pollfd pollfd;
-
-#define WAIT_FOR_EVENT (-1)
-
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    for (;;) {
-       switch (poll(&pollfd, 1, timeout < 0 ?
-                    WAIT_FOR_EVENT : timeout * 1000)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("poll: %m");
-           continue;
-       case 0:
-           errno = ETIMEDOUT;
-           return (-1);
-       default:
-           if (pollfd.revents & POLLNVAL)
-               msg_fatal("poll: %m");
-           return (0);
-       }
-    }
-#else
-#error "define USE_SYSV_POLL or NO_SYSV_POLL"
-#endif
-}
diff --git a/postfix/src/util/readable.c b/postfix/src/util/readable.c
deleted file mode 100644 (file)
index 00756cc..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*++
-/* NAME
-/*     readable 3
-/* SUMMARY
-/*     test if descriptor is readable
-/* SYNOPSIS
-/*     #include <iostuff.h>
-/*
-/*     int     readable(fd)
-/*     int     fd;
-/* DESCRIPTION
-/*     readable() asks the kernel if the specified file descriptor
-/*     is readable, i.e. a read operation would not block.
-/*
-/*     Arguments:
-/* .IP fd
-/*     File descriptor. With implementations based on select(),
-/*     a best effort is made to handle descriptors >=FD_SETSIZE.
-/* DIAGNOSTICS
-/*     All system call errors are fatal.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#ifdef USE_SYSV_POLL
-#include <poll.h>
-#endif
-
-#ifdef USE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* readable - see if file descriptor is readable */
-
-int     readable(int fd)
-{
-#if defined(NO_SYSV_POLL)
-    struct timeval tv;
-    fd_set  read_fds;
-    fd_set  except_fds;
-    int     temp_fd = -1;
-
-    /*
-     * Sanity checks.
-     */
-    if (fd >= FD_SETSIZE) {
-       if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE)
-           msg_fatal("fd %d does not fit in FD_SETSIZE", fd);
-       fd = temp_fd;
-    }
-
-    /*
-     * Initialize.
-     */
-    FD_ZERO(&read_fds);
-    FD_SET(fd, &read_fds);
-    FD_ZERO(&except_fds);
-    FD_SET(fd, &except_fds);
-    tv.tv_sec = 0;
-    tv.tv_usec = 0;
-
-    /*
-     * Loop until we have an authoritative answer.
-     */
-    for (;;) {
-       switch (select(fd + 1, &read_fds, (fd_set *) 0, &except_fds, &tv)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("select: %m");
-           continue;
-       default:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (FD_ISSET(fd, &read_fds));
-       case 0:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (0);
-       }
-    }
-#elif defined(USE_SYSV_POLL)
-
-    /*
-     * System-V poll() is optimal for polling a few descriptors.
-     */
-    struct pollfd pollfd;
-
-#define DONT_WAIT_FOR_EVENT    0
-
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    for (;;) {
-       switch (poll(&pollfd, 1, DONT_WAIT_FOR_EVENT)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("poll: %m");
-           continue;
-       case 0:
-           return (0);
-       default:
-           if (pollfd.revents & POLLNVAL)
-               msg_fatal("poll: %m");
-           return (1);
-       }
-    }
-#else
-#error "define USE_SYSV_POLL or NO_SYSV_POLL"
-#endif
-}
index a32c351be4cbf64ab39e3e2e70ca47f92b5d1751..60d6b7f603ddc3a9184af95d84691b310f712d26 100644 (file)
 #define SOCKOPT_SIZE   socklen_t
 #ifndef NO_KQUEUE
 # define EVENTS_STYLE  EVENTS_STYLE_KQUEUE
-# define NO_SYSV_POLL
+# define USE_SYSV_POLL_WITH_SELECT
 #endif
 #ifndef NO_POSIX_GETPW_R
 # define HAVE_POSIX_GETPW_R
@@ -1374,16 +1374,15 @@ extern int inet_pton(int, const char *, void *);
 #if !defined(EVENTS_STYLE)
 #define EVENTS_STYLE   EVENTS_STYLE_SELECT
 #endif
+#if !defined(USE_SYSV_POLL) && !defined(USE_SYSV_POLL_WITH_SELECT)
+#define USE_BSD_SELECT
+#endif
 
 #define EVENTS_STYLE_SELECT    1       /* Traditional BSD select */
 #define EVENTS_STYLE_KQUEUE    2       /* FreeBSD kqueue */
 #define EVENTS_STYLE_DEVPOLL   3       /* Solaris /dev/poll */
 #define EVENTS_STYLE_EPOLL     4       /* Linux epoll */
 
-#if !defined(USE_SYSV_POLL) && !defined(NO_SYSV_POLL) && (EVENTS_STYLE != EVENTS_STYLE_SELECT)
-#error "need USE_SYSV_POLL or NO_SYSV_POLL with EVENTS_STYLE != EVENTS_STYLE_SELECT"
-#endif
-
  /*
   * The Postfix 2.9 post-install workaround assumes that the inet_protocols
   * default value is "ipv4" when Postfix is compiled without IPv6 support.
diff --git a/postfix/src/util/writable.c b/postfix/src/util/writable.c
deleted file mode 100644 (file)
index a388dcb..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*++
-/* NAME
-/*     writable 3
-/* SUMMARY
-/*     test if descriptor is writable
-/* SYNOPSIS
-/*     #include <iostuff.h>
-/*
-/*     int     writable(fd)
-/*     int     fd;
-/* DESCRIPTION
-/*     writable() asks the kernel if the specified file descriptor
-/*     is writable, i.e. a write operation would not block.
-/*
-/*     Arguments:
-/* .IP fd
-/*     File descriptor. With implementations based on select(),
-/*     a best effort is made to handle descriptors >=FD_SETSIZE.
-/* DIAGNOSTICS
-/*     All system call errors are fatal.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#ifdef USE_SYSV_POLL
-#include <poll.h>
-#endif
-
-#ifdef USE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* writable - see if file descriptor is writable */
-
-int     writable(int fd)
-{
-#if defined(NO_SYSV_POLL)
-    struct timeval tv;
-    fd_set  write_fds;
-    fd_set  except_fds;
-    int     temp_fd = -1;
-
-    /*
-     * Sanity checks.
-     */
-    if (fd >= FD_SETSIZE) {
-       if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE)
-           msg_fatal("fd %d does not fit in FD_SETSIZE", fd);
-       fd = temp_fd;
-    }
-
-    /*
-     * Initialize.
-     */
-    FD_ZERO(&write_fds);
-    FD_SET(fd, &write_fds);
-    FD_ZERO(&except_fds);
-    FD_SET(fd, &except_fds);
-    tv.tv_sec = 0;
-    tv.tv_usec = 0;
-
-    /*
-     * Loop until we have an authoritative answer.
-     */
-    for (;;) {
-       switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, &tv)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("select: %m");
-           continue;
-       default:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (FD_ISSET(fd, &write_fds));
-       case 0:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (0);
-       }
-    }
-#elif defined(USE_SYSV_POLL)
-
-    /*
-     * System-V poll() is optimal for polling a few descriptors.
-     */
-    struct pollfd pollfd;
-
-#define DONT_WAIT_FOR_EVENT    0
-
-    pollfd.fd = fd;
-    pollfd.events = POLLOUT;
-    for (;;) {
-       switch (poll(&pollfd, 1, DONT_WAIT_FOR_EVENT)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("poll: %m");
-           continue;
-       case 0:
-           return (0);
-       default:
-           if (pollfd.revents & POLLNVAL)
-               msg_fatal("poll: %m");
-           return (1);
-       }
-    }
-#else
-#error "define USE_SYSV_POLL or NO_SYSV_POLL"
-#endif
-}
diff --git a/postfix/src/util/write_wait.c b/postfix/src/util/write_wait.c
deleted file mode 100644 (file)
index cf6dde1..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*++
-/* NAME
-/*     write_wait 3
-/* SUMMARY
-/*     wait until descriptor becomes writable
-/* SYNOPSIS
-/*     #include <iostuff.h>
-/*
-/*     int     write_wait(fd, timeout)
-/*     int     fd;
-/*     int     timeout;
-/* DESCRIPTION
-/*     write_wait() blocks the current process until the specified file
-/*     descriptor becomes writable, or until the deadline is exceeded.
-/*
-/*     Arguments:
-/* .IP fd
-/*     File descriptor. With implementations based on select(),
-/*     a best effort is made to handle descriptors >=FD_SETSIZE.
-/* .IP timeout
-/*     If positive, deadline in seconds. A zero value effects a poll.
-/*     A negative value means wait until something happens.
-/* DIAGNOSTICS
-/*     Panic: interface violation. All system call errors are fatal.
-/*
-/*     A zero result means success.  When the specified deadline is
-/*     exceeded, write_wait() returns -1 and sets errno to ETIMEDOUT.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#ifdef USE_SYSV_POLL
-#include <poll.h>
-#endif
-
-#ifdef USE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/* Utility library. */
-
-#include <msg.h>
-#include <iostuff.h>
-
-/* write_wait - block with timeout until file descriptor is writable */
-
-int     write_wait(int fd, int timeout)
-{
-#if defined(NO_SYSV_POLL)
-    fd_set  write_fds;
-    fd_set  except_fds;
-    struct timeval tv;
-    struct timeval *tp;
-    int     temp_fd = -1;
-
-    /*
-     * Sanity checks.
-     */
-    if (FD_SETSIZE <= fd) {
-       if ((temp_fd = dup(fd)) < 0 || temp_fd >= FD_SETSIZE)
-           msg_fatal("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
-       fd = temp_fd;
-    }
-
-    /*
-     * Guard the write() with select() so we do not depend on alarm() and on
-     * signal() handlers. Restart the select when interrupted by some signal.
-     * Some select() implementations may reduce the time to wait when
-     * interrupted, which is exactly what we want.
-     */
-    FD_ZERO(&write_fds);
-    FD_SET(fd, &write_fds);
-    FD_ZERO(&except_fds);
-    FD_SET(fd, &except_fds);
-    if (timeout >= 0) {
-       tv.tv_usec = 0;
-       tv.tv_sec = timeout;
-       tp = &tv;
-    } else {
-       tp = 0;
-    }
-
-    for (;;) {
-       switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, tp)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("select: %m");
-           continue;
-       case 0:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           errno = ETIMEDOUT;
-           return (-1);
-       default:
-           if (temp_fd != -1)
-               (void) close(temp_fd);
-           return (0);
-       }
-    }
-#elif defined(USE_SYSV_POLL)
-
-    /*
-     * System-V poll() is optimal for polling a few descriptors.
-     */
-    struct pollfd pollfd;
-
-#define WAIT_FOR_EVENT (-1)
-
-    pollfd.fd = fd;
-    pollfd.events = POLLOUT;
-    for (;;) {
-       switch (poll(&pollfd, 1, timeout < 0 ?
-                    WAIT_FOR_EVENT : timeout * 1000)) {
-       case -1:
-           if (errno != EINTR)
-               msg_fatal("poll: %m");
-           continue;
-       case 0:
-           errno = ETIMEDOUT;
-           return (-1);
-       default:
-           if (pollfd.revents & POLLNVAL)
-               msg_fatal("poll: %m");
-           return (0);
-       }
-    }
-#else
-#error "define USE_SYSV_POLL or NO_SYSV_POLL"
-#endif
-}