~ubuntu-branches/debian/sid/postfix/sid

« back to all changes in this revision

Viewing changes to src/tls/tls_bio_ops.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2012-03-20 13:47:16 UTC
  • mfrom: (1.1.34) (39.1.16 trunk)
  • Revision ID: package-import@ubuntu.com-20120320134716-o62kosz3odzt1rh6
Tags: 2.9.1-2
Drop unnecessary openssl check, since sonames will save us.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
/*      int     timeout;
37
37
/*      TLS_SESS_STATE *context;
38
38
/* DESCRIPTION
39
 
/*      This module enforces timeouts on non-blocking I/O while
40
 
/*      performing TLS handshake or input/output operations.
 
39
/*      This module enforces VSTREAM-style timeouts on non-blocking
 
40
/*      I/O while performing TLS handshake or input/output operations.
41
41
/*
42
42
/*      The Postfix VSTREAM read/write routines invoke the
43
43
/*      tls_bio_read/write routines to send and receive plain-text
74
74
/* .IP TLScontext
75
75
/*      TLS session state.
76
76
/* DIAGNOSTICS
77
 
/*      The result value is -1 in case of a network read/write
78
 
/*      error, otherwise it is the result value of the TLS operation.
 
77
/*      A result value > 0 means successful completion.
 
78
/*
 
79
/*      A result value < 0 means that the requested operation did
 
80
/*      not complete due to TLS protocol failure, system call
 
81
/*      failure, or for any reason described under "in addition"
 
82
/*      below.
 
83
/*
 
84
/*      A result value of 0 from tls_bio_shutdown() means that the
 
85
/*      operation is in progress. A result value of 0 from other
 
86
/*      tls_bio_ops(3) operations means that the remote party either
 
87
/*      closed the network connection or that it sent a TLS shutdown
 
88
/*      request.
 
89
/*
 
90
/*      Upon return from the tls_bio_ops(3) routines the global
 
91
/*      errno value is non-zero when the requested operation did not
 
92
/*      complete due to system call failure.
 
93
/*
 
94
/*      In addition, the result value is set to -1, and the global
 
95
/*      errno value is set to ETIMEDOUT, when some network read/write
 
96
/*      operation did not complete within the time limit.
79
97
/* LICENSE
80
98
/* .ad
81
99
/* .fi
103
121
/* System library. */
104
122
 
105
123
#include <sys_defs.h>
 
124
#include <sys/time.h>
 
125
 
 
126
#ifndef timersub
 
127
/* res = a - b */
 
128
#define timersub(a, b, res) do { \
 
129
        (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
 
130
        (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
 
131
        if ((res)->tv_usec < 0) { \
 
132
                (res)->tv_sec--; \
 
133
                (res)->tv_usec += 1000000; \
 
134
        } \
 
135
    } while (0)
 
136
#endif
106
137
 
107
138
#ifdef USE_TLS
108
139
 
127
158
    const char *myname = "tls_bio";
128
159
    int     status;
129
160
    int     err;
130
 
    int     retval = 0;
131
 
    int     done;
 
161
    int     enable_deadline;
 
162
    struct timeval time_left;           /* amount of time left */
 
163
    struct timeval time_deadline;       /* time of deadline */
 
164
    struct timeval time_now;            /* time after SSL_mumble() call */
 
165
 
 
166
    /*
 
167
     * Compensation for interface mis-match: With VSTREAMs, timeout <= 0
 
168
     * means wait forever; with the read/write_wait() calls below, we need to
 
169
     * specify timeout < 0 instead.
 
170
     * 
 
171
     * Safety: no time limit means no deadline.
 
172
     */
 
173
    if (timeout <= 0) {
 
174
        timeout = -1;
 
175
        enable_deadline = 0;
 
176
    }
 
177
 
 
178
    /*
 
179
     * Deadline management is simpler than with VSTREAMs, because we don't
 
180
     * need to decrement a per-stream time limit. We just work within the
 
181
     * budget that is available for this tls_bio() call.
 
182
     */
 
183
    else {
 
184
        enable_deadline =
 
185
            vstream_fstat(TLScontext->stream, VSTREAM_FLAG_DEADLINE);
 
186
        if (enable_deadline) {
 
187
            GETTIMEOFDAY(&time_deadline);
 
188
            time_deadline.tv_sec += timeout;
 
189
        }
 
190
    }
132
191
 
133
192
    /*
134
193
     * If necessary, retry the SSL handshake or read/write operation after
135
194
     * handling any pending network I/O.
136
195
     */
137
 
    for (done = 0; done == 0; /* void */ ) {
 
196
    for (;;) {
138
197
        if (hsfunc)
139
198
            status = hsfunc(TLScontext->con);
140
199
        else if (rfunc)
181
240
#endif
182
241
 
183
242
        /*
 
243
         * Correspondence between SSL_ERROR_* error codes and tls_bio_(read,
 
244
         * write, accept, connect, shutdown) return values (for brevity:
 
245
         * retval).
 
246
         * 
 
247
         * SSL_ERROR_NONE corresponds with retval > 0. With SSL_(read, write)
 
248
         * this is the number of plaintext bytes sent or received. With
 
249
         * SSL_(accept, connect, shutdown) this means that the operation was
 
250
         * completed successfully.
 
251
         * 
 
252
         * SSL_ERROR_WANT_(WRITE, READ) start a new loop iteration, or force
 
253
         * (retval = -1, errno = ETIMEDOUT) when the time limit is exceeded.
 
254
         * 
 
255
         * All other SSL_ERROR_* cases correspond with retval <= 0. With
 
256
         * SSL_(read, write, accept, connect) retval == 0 means that the
 
257
         * remote party either closed the network connection or that it
 
258
         * requested TLS shutdown; with SSL_shutdown() retval == 0 means that
 
259
         * our own shutdown request is in progress. With all operations
 
260
         * retval < 0 means that there was an error. In the latter case,
 
261
         * SSL_ERROR_SYSCALL means that error details are returned via the
 
262
         * errno value.
 
263
         * 
184
264
         * Find out if we must retry the operation and/or if there is pending
185
265
         * network I/O.
186
266
         * 
189
269
         * anomaly here and repeat the call.
190
270
         */
191
271
        switch (err) {
192
 
        case SSL_ERROR_NONE:                    /* success */
193
 
            retval = status;
194
 
            done = 1;
195
 
            break;
196
272
        case SSL_ERROR_WANT_WRITE:
197
 
            if (write_wait(fd, timeout) < 0)
198
 
                return (-1);                    /* timeout error */
199
 
            break;
200
273
        case SSL_ERROR_WANT_READ:
201
 
            if (read_wait(fd, timeout) < 0)
202
 
                return (-1);                    /* timeout error */
 
274
            if (enable_deadline) {
 
275
                GETTIMEOFDAY(&time_now);
 
276
                timersub(&time_deadline, &time_now, &time_left);
 
277
                timeout = time_left.tv_sec + (time_left.tv_usec > 0);
 
278
                if (timeout <= 0) {
 
279
                    errno = ETIMEDOUT;
 
280
                    return (-1);
 
281
                }
 
282
            }
 
283
            if (err == SSL_ERROR_WANT_WRITE) {
 
284
                if (write_wait(fd, timeout) < 0)
 
285
                    return (-1);                /* timeout error */
 
286
            } else {
 
287
                if (read_wait(fd, timeout) < 0)
 
288
                    return (-1);                /* timeout error */
 
289
            }
203
290
            break;
204
291
 
205
292
            /*
 
293
             * Unhandled cases: SSL_ERROR_WANT_(ACCEPT, CONNECT, X509_LOOKUP)
 
294
             * etc. Historically, Postfix silently treated these as ordinary
 
295
             * I/O errors so we don't really know how common they are. For
 
296
             * now, we just log a warning.
 
297
             */
 
298
        default:
 
299
            msg_warn("%s: unexpected SSL_ERROR code %d", myname, err);
 
300
            /* FALLTHROUGH */
 
301
 
 
302
            /*
206
303
             * With tls_timed_read() and tls_timed_write() the caller is the
207
304
             * VSTREAM library module which is unaware of TLS, so we log the
208
305
             * TLS error stack here. In a better world, each VSTREAM I/O
214
311
            if (rfunc || wfunc)
215
312
                tls_print_errors();
216
313
            /* FALLTHROUGH */
217
 
        default:
218
 
            retval = status;
219
 
            done = 1;
220
 
            break;
 
314
        case SSL_ERROR_ZERO_RETURN:
 
315
        case SSL_ERROR_NONE:
 
316
            errno = 0;                          /* avoid bogus warnings */
 
317
            /* FALLTHROUGH */
 
318
        case SSL_ERROR_SYSCALL:
 
319
            return (status);
221
320
        }
222
321
    }
223
 
    return (retval);
224
322
}
225
323
 
226
324
#endif