]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20110820
authorWietse Venema <wietse@porcupine.org>
Sat, 20 Aug 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:25 +0000 (06:37 +0000)
13 files changed:
postfix/HISTORY
postfix/README_FILES/MILTER_README
postfix/html/MILTER_README.html
postfix/html/smtpd.8.html
postfix/man/man8/smtpd.8
postfix/proto/MILTER_README.html
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls_bio_ops.c
postfix/src/tls/tls_client.c
postfix/src/tls/tls_server.c
postfix/src/tls/tls_stream.c
postfix/src/util/vstream.c

index ccdbaa2964730c54f3aae243daad58484d279040..41e3eeb0572de6245e591d7d5e3b2cb6ed62fda4 100644 (file)
@@ -16879,5 +16879,35 @@ Apologies for any names omitted.
 
        Workaround: report a {client_connections} Milter macro value
        of zero instead of garbage, when the remote SMTP client is
-       excluded from connection count limits. Problem reported by
-       Christian Roessner. File: smtpd/smtpd_state,c,
+       not subject to any smtpd_client_* limits. Problem reported
+       by Christian Roessner. Files: smtpd/smtpd_state.c,
+       proto/MILTER_README.html.
+
+20110817
+
+       Cleanup: avoid misleading error messages after future code
+       change. The tls_bio_ops(3) module now returns non-zero errno
+       values only when requests fail due to a system-call error.
+       File: tls/tls_bio_ops.c.
+
+       Cleanup: TLS handshake error messages. The SMTP client and
+       server now report STARTTLS network errors as "connection
+       timed out", "connection reset by peer", etc., instead of
+       reporting TLS error number 0.  Files: tls/tls_bio_ops.c,
+       tls/tls_server.c, tls/tls_client.c.
+
+20110818
+
+       Cleanup: VSTREAM-over-TLS error return values, for robustness
+       against future change.  For consistency with VSTREAM internal
+       interfaces, the tls_stream(3) read/write routines now return
+       -1 instead of unspecified negative OpenSSL results.  File:
+       tls/tls_stream.c.
+
+20110819
+
+       Cleanup: further TLS code cleanups, for robustness against
+       future change.  Unexpected TLS errors are no longer silently
+       treated as ordinary errors, and one corner-case error in TLS
+       timeout handling was fixed before it could cause trouble.
+       File: tls/tls_bio_ops.c.
index b31be4ecaa6c039fdfaab0dceebd57bae54ac40a..8e2a687592e7be13005719ea45c248cfd89faade 100644 (file)
@@ -347,8 +347,11 @@ Sendmail. See the workarounds section below for solutions.
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |{client_addr}       |Always                   |Client IP address         |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
-    |{client_connections}|CONNECT                  |Connection concurrency for|
-    |                    |                         |this client               |
+    |                    |                         |Connection concurrency for|
+    |                    |                         |this client (zero if the  |
+    |{client_connections}|CONNECT                  |client is excluded from   |
+    |                    |                         |all smtpd_client_*        |
+    |                    |                         |limits).                  |
     |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
     |                    |                         |Client hostname           |
     |                    |                         |When address -> name      |
index 63a61a70fc32668f1e579074ba3694a5df20d7ea..d0dc9e81abacbfc9b816b934b81b6397ec5c4600 100644 (file)
@@ -573,7 +573,8 @@ login method </td> </tr>
 address </td> </tr>
 
 <tr> <td> {client_connections} </td> <td> CONNECT </td> <td>
-Connection concurrency for this client </td> </tr>
+Connection concurrency for this client (zero if the client is
+excluded from all smtpd_client_* limits). </td> </tr>
 
 <tr> <td> {client_name} </td> <td> Always </td> <td> Client hostname
 <br> When address &rarr; name lookup or name &rarr; address
index 8bcd086971e715278c09ab84189ecd03c08f162d..fe412be529e8b8414b835b9152f941b73a4e9407 100644 (file)
@@ -47,16 +47,17 @@ SMTPD(8)                                                              SMTPD(8)
        <a href="http://tools.ietf.org/html/rfc1123">RFC 1123</a> (Host requirements)
        <a href="http://tools.ietf.org/html/rfc1652">RFC 1652</a> (8bit-MIME transport)
        <a href="http://tools.ietf.org/html/rfc1869">RFC 1869</a> (SMTP service extensions)
-       <a href="http://tools.ietf.org/html/rfc1870">RFC 1870</a> (Message Size Declaration)
+       <a href="http://tools.ietf.org/html/rfc1870">RFC 1870</a> (Message size declaration)
        <a href="http://tools.ietf.org/html/rfc1985">RFC 1985</a> (ETRN command)
-       <a href="http://tools.ietf.org/html/rfc2034">RFC 2034</a> (SMTP Enhanced Status Codes)
+       <a href="http://tools.ietf.org/html/rfc2034">RFC 2034</a> (SMTP enhanced status codes)
        <a href="http://tools.ietf.org/html/rfc2554">RFC 2554</a> (AUTH command)
        <a href="http://tools.ietf.org/html/rfc2821">RFC 2821</a> (SMTP protocol)
-       <a href="http://tools.ietf.org/html/rfc2920">RFC 2920</a> (SMTP Pipelining)
+       <a href="http://tools.ietf.org/html/rfc2920">RFC 2920</a> (SMTP pipelining)
        <a href="http://tools.ietf.org/html/rfc3207">RFC 3207</a> (STARTTLS command)
-       <a href="http://tools.ietf.org/html/rfc3461">RFC 3461</a> (SMTP DSN Extension)
-       <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced Status Codes)
-       <a href="http://tools.ietf.org/html/rfc3848">RFC 3848</a> (ESMTP Transmission Types)
+       <a href="http://tools.ietf.org/html/rfc3461">RFC 3461</a> (SMTP DSN extension)
+       <a href="http://tools.ietf.org/html/rfc3463">RFC 3463</a> (Enhanced status codes)
+       <a href="http://tools.ietf.org/html/rfc3848">RFC 3848</a> (ESMTP transmission types)
+       <a href="http://tools.ietf.org/html/rfc4409">RFC 4409</a> (Message submission)
        <a href="http://tools.ietf.org/html/rfc4954">RFC 4954</a> (AUTH command)
 
 <b>DIAGNOSTICS</b>
@@ -158,7 +159,7 @@ SMTPD(8)                                                              SMTPD(8)
        <b><a href="postconf.5.html#smtpd_per_record_deadline">smtpd_per_record_deadline</a> (normal: no, overload: yes)</b>
               Change  the  behavior  of  the  <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a>  time
               limit, from a time limit per read or  write  system
-              call,  to  a time limit to read or write a complete
+              call, to a time limit to send or receive a complete
               record (an SMTP command line, SMTP  response  line,
               SMTP  message  content  line,  or TLS protocol mes-
               sage).
@@ -857,7 +858,7 @@ SMTPD(8)                                                              SMTPD(8)
        <b><a href="postconf.5.html#smtpd_per_record_deadline">smtpd_per_record_deadline</a> (normal: no, overload: yes)</b>
               Change  the  behavior  of  the  <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a>  time
               limit,  from  a time limit per read or write system
-              call, to a time limit to read or write  a  complete
+              call, to a time limit to send or receive a complete
               record  (an  SMTP command line, SMTP response line,
               SMTP message content line,  or  TLS  protocol  mes-
               sage).
index c8355b7f15b8a70c78bebe0f91c140f90472840a..9150ec351c1ee71f7c0b97e368f2d6dc12f73b53 100644 (file)
@@ -50,16 +50,17 @@ RFC 821 (SMTP protocol)
 RFC 1123 (Host requirements)
 RFC 1652 (8bit-MIME transport)
 RFC 1869 (SMTP service extensions)
-RFC 1870 (Message Size Declaration)
+RFC 1870 (Message size declaration)
 RFC 1985 (ETRN command)
-RFC 2034 (SMTP Enhanced Status Codes)
+RFC 2034 (SMTP enhanced status codes)
 RFC 2554 (AUTH command)
 RFC 2821 (SMTP protocol)
-RFC 2920 (SMTP Pipelining)
+RFC 2920 (SMTP pipelining)
 RFC 3207 (STARTTLS command)
-RFC 3461 (SMTP DSN Extension)
-RFC 3463 (Enhanced Status Codes)
-RFC 3848 (ESMTP Transmission Types)
+RFC 3461 (SMTP DSN extension)
+RFC 3463 (Enhanced status codes)
+RFC 3848 (ESMTP transmission types)
+RFC 4409 (Message submission)
 RFC 4954 (AUTH command)
 .SH DIAGNOSTICS
 .ad
index 3c8d95418d6ea270c7302978b1e314712e57e5ad..ba30ad050e830243f8948e2d93a3e4e0fc8c179f 100644 (file)
@@ -573,7 +573,8 @@ login method </td> </tr>
 address </td> </tr>
 
 <tr> <td> {client_connections} </td> <td> CONNECT </td> <td>
-Connection concurrency for this client </td> </tr>
+Connection concurrency for this client (zero if the client is
+excluded from all smtpd_client_* limits). </td> </tr>
 
 <tr> <td> {client_name} </td> <td> Always </td> <td> Client hostname
 <br> When address &rarr; name lookup or name &rarr; address
index fc1b0e90ca4176dcc2e18e6dfd111824f738b7bd..013b14363aa29a9339fe423bb7ebaad6b8b6f7ff 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      "20110814"
+#define MAIL_RELEASE_DATE      "20110820"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index f813884b563db0f72dd1fdbe7c40e1753f617b3c..6bc2a68bb5b0fbfef7f35402ae1b391ca5841423 100644 (file)
 /*     RFC 1123 (Host requirements)
 /*     RFC 1652 (8bit-MIME transport)
 /*     RFC 1869 (SMTP service extensions)
-/*     RFC 1870 (Message Size Declaration)
+/*     RFC 1870 (Message size declaration)
 /*     RFC 1985 (ETRN command)
-/*     RFC 2034 (SMTP Enhanced Status Codes)
+/*     RFC 2034 (SMTP enhanced status codes)
 /*     RFC 2554 (AUTH command)
 /*     RFC 2821 (SMTP protocol)
-/*     RFC 2920 (SMTP Pipelining)
+/*     RFC 2920 (SMTP pipelining)
 /*     RFC 3207 (STARTTLS command)
-/*     RFC 3461 (SMTP DSN Extension)
-/*     RFC 3463 (Enhanced Status Codes)
-/*     RFC 3848 (ESMTP Transmission Types)
+/*     RFC 3461 (SMTP DSN extension)
+/*     RFC 3463 (Enhanced status codes)
+/*     RFC 3848 (ESMTP transmission types)
+/*     RFC 4409 (Message submission)
 /*     RFC 4954 (AUTH command)
 /* DIAGNOSTICS
 /*     Problems and transactions are logged to \fBsyslogd\fR(8).
 /*     Available in Postfix version 2.9 and later:
 /* .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
 /*     Change the behavior of the smtpd_timeout time limit, from a
-/*     time limit per read or write system call, to a time limit to read
-/*     or write a complete record (an SMTP command line, SMTP response
+/*     time limit per read or write system call, to a time limit to send
+/*     or receive a complete record (an SMTP command line, SMTP response
 /*     line, SMTP message content line, or TLS protocol message).
 /* ADDRESS REWRITING CONTROLS
 /* .ad
 /*     Available in Postfix version 2.9 and later:
 /* .IP "\fBsmtpd_per_record_deadline (normal: no, overload: yes)\fR"
 /*     Change the behavior of the smtpd_timeout time limit, from a
-/*     time limit per read or write system call, to a time limit to read
-/*     or write a complete record (an SMTP command line, SMTP response
+/*     time limit per read or write system call, to a time limit to send
+/*     or receive a complete record (an SMTP command line, SMTP response
 /*     line, SMTP message content line, or TLS protocol message).
 /* TARPIT CONTROLS
 /* .ad
index e6a1dc3f6a188986fe7d1540321d6fdf3525a3f2..4d1bf1a41c6c9b539dce58337f7947455ac87684 100644 (file)
@@ -36,8 +36,8 @@
 /*     int     timeout;
 /*     TLS_SESS_STATE *context;
 /* DESCRIPTION
-/*     This module enforces timeouts on non-blocking I/O while
-/*     performing TLS handshake or input/output operations.
+/*     This module enforces VSTREAM-style timeouts on non-blocking
+/*     I/O while performing TLS handshake or input/output operations.
 /*
 /*     The Postfix VSTREAM read/write routines invoke the
 /*     tls_bio_read/write routines to send and receive plain-text
 /* .IP TLScontext
 /*     TLS session state.
 /* DIAGNOSTICS
-/*     The result value is -1 in case of a network read/write
-/*     error, otherwise it is the result value of the TLS operation.
+/*     A result value > 0 means successful completion.
+/*
+/*     A result value < 0 means that the requested operation did
+/*     not complete due to TLS protocol failure, system call
+/*     failure, or for any reason described under "in addition"
+/*     below.
+/*
+/*     A result value of 0 from tls_bio_shutdown() means that the
+/*     operation is in progress. A result value of 0 from other
+/*     tls_bio_ops(3) operations means that the remote party either
+/*     closed the network connection or that it sent a TLS shutdown
+/*     request.
+/*
+/*     Upon return from the tls_bio_ops(3) routines the global
+/*     errno value is non-zero when the requested operation did not
+/*     complete due to system call failure.
+/*
+/*     In addition, the result value is set to -1, and the global
+/*     errno value is set to ETIMEDOUT, when some network read/write
+/*     operation did not complete within the time limit.
 /* LICENSE
 /* .ad
 /* .fi
@@ -140,8 +158,6 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
     const char *myname = "tls_bio";
     int     status;
     int     err;
-    int     retval = 0;
-    int     done;
     int     enable_deadline;
     struct timeval time_limit;         /* initial time limit */
     struct timeval time_left;          /* amount of time left */
@@ -149,23 +165,38 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
     struct timeval time_now;           /* time after SSL_mumble() call */
     struct timeval time_elapsed;       /* total elapsed time */
 
+    /*
+     * Compensation for interface mis-match: With VSTREAMs, timeout <= 0
+     * means wait forever; with the read/write_wait() calls below, we need
+     * to specify timeout < 0 instead.
+     * 
+     * Safety: no time limit means no deadline.
+     */
+    if (timeout <= 0) {
+       timeout = -1;
+       enable_deadline = 0;
+    }
+
     /*
      * Deadline management is simpler than with VSTREAMs, because we don't
      * need to decrement a per-stream time limit. We just work within the
      * budget that is available for this tls_bio() call.
      */
-    enable_deadline = vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE);
-    if (enable_deadline) {
-       time_limit.tv_sec = timeout;
-       time_limit.tv_usec = 0;
-       GETTIMEOFDAY(&time_entry);
+    else {
+       enable_deadline =
+           vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE);
+       if (enable_deadline) {
+           time_limit.tv_sec = timeout;
+           time_limit.tv_usec = 0;
+           GETTIMEOFDAY(&time_entry);
+       }
     }
 
     /*
      * If necessary, retry the SSL handshake or read/write operation after
      * handling any pending network I/O.
      */
-    for (done = 0; done == 0; /* void */ ) {
+    for (;;) {
        if (hsfunc)
            status = hsfunc(TLScontext->con);
        else if (rfunc)
@@ -212,6 +243,27 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
 #endif
 
        /*
+        * Correspondence between SSL_ERROR_* error codes and tls_bio_(read,
+        * write, accept, connect, shutdown) return values (for brevity:
+        * retval).
+        * 
+        * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write)
+        * this is the number of plaintext bytes sent or received. With
+        * SSL_(accept, connect, shutdown) this means that the operation was
+        * completed successfully.
+        * 
+        * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force
+        * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded.
+        * 
+        * All other SSL_ERROR_* cases correspond with retval <= 0. With
+        * SSL_(read, write, accept, connect) retval == 0 means that the
+        * remote party either closed the network connection or that it
+        * requested TLS shutdown; with SSL_shutdown() retval == 0 means that
+        * our own shutdown request is in progress. With all operations
+        * retval < 0 means that there was an error. In the latter case,
+        * SSL_ERROR_SYSCALL means that error details are returned via the
+        * errno value.
+        * 
         * Find out if we must retry the operation and/or if there is pending
         * network I/O.
         * 
@@ -220,10 +272,6 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
         * anomaly here and repeat the call.
         */
        switch (err) {
-       case SSL_ERROR_NONE:                    /* success */
-           retval = status;
-           done = 1;
-           break;
        case SSL_ERROR_WANT_WRITE:
        case SSL_ERROR_WANT_READ:
            if (enable_deadline) {
@@ -245,6 +293,16 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
            }
            break;
 
+           /*
+            * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP)
+            * etc. Historically, Postfix silently treated these as ordinary
+            * I/O errors so we don't really know how common they are. For
+            * now, we just log a warning.
+            */
+       default:
+           msg_warn("%s: unexpected SSL_ERROR code %d", myname, err);
+           /* FALLTHROUGH */
+
            /*
             * With tls_timed_read() and tls_timed_write() the caller is the
             * VSTREAM library module which is unaware of TLS, so we log the
@@ -257,13 +315,14 @@ int     tls_bio(int fd, int timeout, TLS_SESS_STATE *TLScontext,
            if (rfunc || wfunc)
                tls_print_errors();
            /* FALLTHROUGH */
-       default:
-           retval = status;
-           done = 1;
-           break;
+       case SSL_ERROR_ZERO_RETURN:
+       case SSL_ERROR_NONE:
+           errno = 0;                          /* avoid bogus warnings */
+           /* FALLTHROUGH */
+       case SSL_ERROR_SYSCALL:
+           return (status);
        }
     }
-    return (retval);
 }
 
 #endif
index 795ba7d70ed032d09a74196f5ae14c269b1ff08a..750fb5a83386996ba626ac6845affe79810e2e32 100644 (file)
@@ -900,8 +900,15 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     sts = tls_bio_connect(vstream_fileno(props->stream), props->timeout,
                          TLScontext);
     if (sts <= 0) {
-       msg_info("SSL_connect error to %s: %d", props->namaddr, sts);
-       tls_print_errors();
+       if (ERR_peek_error() != 0) {
+           msg_info("SSL_connect error to %s: %d", props->namaddr, sts);
+           tls_print_errors();
+       } else if (errno != 0) {
+           msg_info("SSL_connect error to %s: %m", props->namaddr);
+       } else {
+           msg_info("SSL_connect error to %s: lost connection",
+                    props->namaddr);
+       }
        uncache_session(app_ctx->ssl_ctx, TLScontext);
        tls_free_context(TLScontext);
        return (0);
index f764a5a393140ad19357fb02c9f8dc4f2c029a56..19b0fb2aecba6a9bf2fd551fc8d4380ff1c9cad6 100644 (file)
@@ -704,8 +704,15 @@ TLS_SESS_STATE *tls_server_start(const TLS_SERVER_START_PROPS *props)
     sts = tls_bio_accept(vstream_fileno(props->stream), props->timeout,
                         TLScontext);
     if (sts <= 0) {
-       msg_info("SSL_accept error from %s: %d", props->namaddr, sts);
-       tls_print_errors();
+       if (ERR_peek_error() != 0) {
+           msg_info("SSL_accept error from %s: %d", props->namaddr, sts);
+           tls_print_errors();
+       } else if (errno != 0) {
+           msg_info("SSL_accept error from %s: %m", props->namaddr);
+       } else {
+           msg_info("SSL_accept error from %s: lost connection",
+                    props->namaddr);
+       }
        tls_free_context(TLScontext);
        return (0);
     }
index ca73a11366048c7d20a83774ad73d9fb5cca5c27..73def41b9a667adb261686924d032e5f65d4135b 100644 (file)
 /*     tls_stream_stop() replaces the VSTREAM read/write routines
 /*     by dummies that have no side effects, and deletes the
 /*     VSTREAM's reference to the TLS context.
+/* DIAGNOSTICS
+/*     The tls_stream(3) read/write routines return the non-zero
+/*     number of plaintext bytes read/written if successful; -1
+/*     after TLS protocol failure, system-call failure, or for any
+/*     reason described under "in addition" below; and zero when
+/*     the remote party closed the connection or sent a TLS shutdown
+/*     request.
+/*
+/*     Upon return from the tls_stream(3) read/write routines the
+/*     global errno value is non-zero when the requested operation
+/*     did not complete due to system call failure.
+/*
+/*     In addition, the result value is set to -1, and the global
+/*     errno value is set to ETIMEDOUT, when a network read/write
+/*     request did not complete within the time limit.
 /* SEE ALSO
 /*     dummy_read(3), placebo read routine
 /*     dummy_write(3), placebo write routine
 #define TLS_INTERNAL
 #include <tls.h>
 
+ /*
+  * Interface mis-match compensation. The OpenSSL read/write routines return
+  * unspecified negative values when an operation fails, while the vstream(3)
+  * plaintext timed_read/write() functions follow the convention of UNIX
+  * system calls, and return -1 upon error. The macro below makes OpenSSL
+  * read/write results consistent with the UNIX system-call convention.
+  */
+#define NORMALIZED_VSTREAM_RETURN(retval) ((retval) < 0 ? -1 : (retval))
+
 /* tls_timed_read - read content from stream, then TLS decapsulate */
 
 static ssize_t tls_timed_read(int fd, void *buf, size_t len, int timeout,
@@ -82,7 +106,7 @@ static ssize_t tls_timed_read(int fd, void *buf, size_t len, int timeout,
     if (ret > 0 && TLScontext->log_level >= 4)
        msg_info("Read %ld chars: %.*s",
                 (long) ret, (int) (ret > 40 ? 40 : ret), (char *) buf);
-    return (ret);
+    return (NORMALIZED_VSTREAM_RETURN(ret));
 }
 
 /* tls_timed_write - TLS encapsulate content, then write to stream */
@@ -91,6 +115,7 @@ static ssize_t tls_timed_write(int fd, void *buf, size_t len, int timeout,
                                       void *context)
 {
     const char *myname = "tls_timed_write";
+    ssize_t ret;
     TLS_SESS_STATE *TLScontext;
 
     TLScontext = (TLS_SESS_STATE *) context;
@@ -100,7 +125,8 @@ static ssize_t tls_timed_write(int fd, void *buf, size_t len, int timeout,
     if (TLScontext->log_level >= 4)
        msg_info("Write %ld chars: %.*s",
                 (long) len, (int) (len > 40 ? 40 : len), (char *) buf);
-    return (tls_bio_write(fd, buf, len, timeout, TLScontext));
+    ret = tls_bio_write(fd, buf, len, timeout, TLScontext);
+    return (NORMALIZED_VSTREAM_RETURN(ret));
 }
 
 /* tls_stream_start - start VSTREAM over TLS */
index fdb1b2101162bcd677c4a2a8e5238b2d909ea3ee..5da2f15989821cd891209fa1882a23497d2f6c8e 100644 (file)
 /* .IP "VSTREAM_CTL_READ_FN (ssize_t (*)(int, void *, size_t, int, void *))"
 /*     The argument specifies an alternative for the timed_read(3) function,
 /*     for example, a read function that performs decryption.
+/*     This function receives as arguments a file descriptor, buffer pointer,
+/*     buffer length, timeout value, and the VSTREAM's context value.
+/*     A timeout value <= 0 disables the time limit.
+/*     This function should return the positive number of bytes transferred,
+/*     0 upon EOF, and -1 upon error with errno set appropriately.
 /* .IP "VSTREAM_CTL_WRITE_FN (ssize_t (*)(int, void *, size_t, int, void *))"
 /*     The argument specifies an alternative for the timed_write(3) function,
 /*     for example, a write function that performs encryption.
+/*     This function receives as arguments a file descriptor, buffer pointer,
+/*     buffer length, timeout value, and the VSTREAM's context value.
+/*     A timeout value <= 0 disables the time limit.
+/*     This function should return the positive number of bytes transferred,
+/*     and -1 upon error with errno set appropriately. Instead of -1 it may
+/*     also return 0, e.g., upon remote party-initiated protocol shutdown.
 /* .IP "VSTREAM_CTL_CONTEXT (char *)"
 /*     The argument specifies application context that is passed on to
 /*     the application-specified read/write routines. No copy is made.