2 ** _ __ ___ ___ __| | ___ ___| | mod_ssl
3 ** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
4 ** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
5 ** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
11 /* ====================================================================
12 * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this
27 * software must display the following acknowledgment:
28 * "This product includes software developed by
29 * Ralf S. Engelschall <rse@engelschall.com> for use in the
30 * mod_ssl project (http://www.modssl.org/)."
32 * 4. The names "mod_ssl" must not be used to endorse or promote
33 * products derived from this software without prior written
34 * permission. For written permission, please contact
35 * rse@engelschall.com.
37 * 5. Products derived from this software may not be called "mod_ssl"
38 * nor may "mod_ssl" appear in their names without prior
39 * written permission of Ralf S. Engelschall.
41 * 6. Redistributions of any form whatsoever must retain the following
43 * "This product includes software developed by
44 * Ralf S. Engelschall <rse@engelschall.com> for use in the
45 * mod_ssl project (http://www.modssl.org/)."
47 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
48 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
51 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58 * OF THE POSSIBILITY OF SUCH DAMAGE.
59 * ====================================================================
61 /* ``MY HACK: This universe.
62 Just one little problem:
67 /* _________________________________________________________________
69 ** I/O Request Body Sucking and Re-Injection
70 ** _________________________________________________________________
73 #ifndef SSL_CONSERVATIVE
78 * 1. When the client sends a HTTP/HTTPS request, Apache's core code
79 * reads only the request line ("METHOD /path HTTP/x.y") and the
80 * attached MIME headers ("Foo: bar") up to the terminating line ("CR
81 * LF"). An attached request body (for instance the data of a POST
82 * method) is _NOT_ read. Instead it is read by mod_cgi's content
83 * handler and directly passed to the CGI script.
85 * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
86 * This is implemented by performing an SSL renegotiation of the
87 * re-configured parameters after the request is read, but before the
88 * response is sent. In more detail: the renegotiation happens after the
89 * request line and MIME headers were read, but _before_ the attached
90 * request body is read. The reason simply is that in the HTTP protocol
91 * usually there is no acknowledgment step between the headers and the
92 * body (there is the 100-continue feature and the chunking facility
93 * only), so Apache has no API hook for this step.
95 * 3. the problem now occurs when the client sends a POST request for
96 * URL /foo via HTTPS the server and the server has SSL parameters
97 * re-configured on a per-URL basis for /foo. Then mod_ssl has to
98 * perform an SSL renegotiation after the request was read and before
99 * the response is sent. But the problem is the pending POST body data
100 * in the receive buffer of SSL (which Apache still has not read - it's
101 * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
102 * the renegotiation the pending data leads to an I/O error.
106 * There are only two solutions: Either to simply state that POST
107 * requests to URLs with SSL re-configurations are not allowed, or to
108 * renegotiate really after the _complete_ request (i.e. including
109 * the POST body) was read. Obviously the latter would be preferred,
110 * but it cannot be done easily inside Apache, because as already
111 * mentioned, there is no API step between the body reading and the body
112 * processing. And even when we mod_ssl would hook directly into the
113 * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
114 * course. So the only general solution is to suck in the pending data
115 * of the request body from the OpenSSL BIO into the Apache BUFF. Then
116 * the renegotiation can be done and after this step Apache can proceed
117 * processing the request as before.
119 * Solution Implementation:
121 * We cannot simply suck in the data via an SSL_read-based loop because of
122 * HTTP chunking. Instead we _have_ to use the Apache API for this step which
123 * is aware of HTTP chunking. So the trick is to suck in the pending request
124 * data via the Apache API (which uses Apache's BUFF code and in the
125 * background mod_ssl's I/O glue code) and re-inject it later into the Apache
126 * BUFF code again. This way the data flows twice through the Apache BUFF, of
127 * course. But this way the solution doesn't depend on any Apache specifics
128 * and is fully transparent to Apache modules.
131 struct ssl_io_suck_st {
139 /* prepare request_rec structure for input sucking */
140 static void ssl_io_suck_start(request_rec *r)
142 struct ssl_io_suck_st *ss;
144 ss = ap_ctx_get(r->ctx, "ssl::io::suck");
146 ss = ap_palloc(r->pool, sizeof(struct ssl_io_suck_st));
147 ap_ctx_set(r->ctx, "ssl::io::suck", ss);
149 ss->bufptr = ap_palloc(r->pool, ss->buflen);
151 ss->pendptr = ss->bufptr;
157 /* record a sucked input chunk */
158 static void ssl_io_suck_record(request_rec *r, char *buf, int len)
160 struct ssl_io_suck_st *ss;
162 if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
164 if (((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) < len) {
165 /* "expand" buffer: actually we cannot really expand the buffer
166 here, because Apache's pool system doesn't support expanding chunks
167 of memory. Instead we have to either reuse processed data or
168 allocate a new chunk of memory in advance if we really need more
173 if (( (ss->pendptr - ss->bufptr)
174 + ((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) ) >= len) {
175 /* make memory available by reusing already processed data */
176 memmove(ss->bufptr, ss->pendptr, ss->pendlen);
177 ss->pendptr = ss->bufptr;
180 /* too bad, we have to allocate a new larger buffer */
181 newlen = (ss->buflen * 2) + len;
182 newptr = ap_palloc(r->pool, newlen);
185 memcpy(ss->bufptr, ss->pendptr, ss->pendlen);
186 ss->pendptr = ss->bufptr;
189 memcpy(ss->pendptr+ss->pendlen, buf, len);
194 /* finish request_rec after input sucking */
195 static void ssl_io_suck_end(request_rec *r)
197 struct ssl_io_suck_st *ss;
199 if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
202 r->read_body = REQUEST_NO_BODY;
206 ap_bsetflag(r->connection->client, B_CHUNK, 0);
210 void ssl_io_suck(request_rec *r, SSL *ssl)
219 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) {
220 if (ap_should_client_block(r)) {
222 /* read client request block through Apache API */
223 buflen = HUGE_STRING_LEN;
224 buf = ap_palloc(r->pool, buflen);
225 ap_hard_timeout("SSL I/O request body pre-sucking", r);
227 ssl_io_suck_start(r);
228 while ((len = ap_get_client_block(r, buf, buflen)) > 0) {
229 ssl_io_suck_record(r, buf, len);
235 /* suck trailing data (usually CR LF) which
236 is still in the Apache BUFF layer */
237 while (ap_bpeekc(r->connection->client) != EOF) {
238 c = ap_bgetc(r->connection->client);
239 ssl_io_suck_record(r, &c, 1);
243 ssl_log(r->server, SSL_LOG_TRACE,
244 "I/O: sucked %d bytes of input data from SSL/TLS I/O layer "
245 "for delayed injection into Apache I/O layer", sucked);
251 /* the SSL_read replacement routine which knows about the suck buffer */
252 static int ssl_io_suck_read(SSL *ssl, char *buf, int len)
255 struct ssl_io_suck_st *ss;
256 request_rec *r = NULL;
259 actx = (ap_ctx *)SSL_get_app_data2(ssl);
261 r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
265 ss = ap_ctx_get(r->ctx, "ssl::io::suck");
267 if (ss->active && ss->pendlen > 0) {
268 /* ok, there is pre-sucked data */
269 len = (ss->pendlen > len ? len : ss->pendlen);
270 memcpy(buf, ss->pendptr, len);
273 ssl_log(r->server, SSL_LOG_TRACE,
274 "I/O: injecting %d bytes of pre-sucked data "
275 "into Apache I/O layer", len);
281 rv = SSL_read(ssl, buf, len);
285 /* override SSL_read in the following code... */
286 #define SSL_read ssl_io_suck_read
288 #endif /* !SSL_CONSERVATIVE */
290 /* _________________________________________________________________
293 ** _________________________________________________________________
297 #include <sys/types.h>
301 static int ssl_io_hook_read(BUFF *fb, char *buf, int len);
302 static int ssl_io_hook_write(BUFF *fb, char *buf, int len);
304 static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt);
307 static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len);
308 static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len);
311 void ssl_io_register(void)
313 ap_hook_register("ap::buff::read", ssl_io_hook_read, AP_HOOK_NOCTX);
314 ap_hook_register("ap::buff::write", ssl_io_hook_write, AP_HOOK_NOCTX);
316 ap_hook_register("ap::buff::writev", ssl_io_hook_writev, AP_HOOK_NOCTX);
319 ap_hook_register("ap::buff::recvwithtimeout",
320 ssl_io_hook_recvwithtimeout, AP_HOOK_NOCTX);
321 ap_hook_register("ap::buff::sendwithtimeout",
322 ssl_io_hook_sendwithtimeout, AP_HOOK_NOCTX);
327 void ssl_io_unregister(void)
329 ap_hook_unregister("ap::buff::read", ssl_io_hook_read);
330 ap_hook_unregister("ap::buff::write", ssl_io_hook_write);
332 ap_hook_unregister("ap::buff::writev", ssl_io_hook_writev);
335 ap_hook_unregister("ap::buff::recvwithtimeout", ssl_io_hook_recvwithtimeout);
336 ap_hook_unregister("ap::buff::sendwithtimeout", ssl_io_hook_sendwithtimeout);
341 static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
347 if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
348 rc = SSL_read(ssl, buf, len);
350 * Simulate an EINTR in case OpenSSL wants to read more.
351 * (This is usually the case when the client forces an SSL
352 * renegotation which is handled implicitly by OpenSSL.)
354 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
359 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
360 c = (conn_rec *)SSL_get_app_data(ssl);
361 ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
362 "SSL error on reading data");
365 * read(2) returns only the generic error number -1
371 rc = read(fb->fd_in, buf, len);
375 static int ssl_io_hook_write(BUFF *fb, char *buf, int len)
381 if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
382 rc = SSL_write(ssl, buf, len);
384 * Simulate an EINTR in case OpenSSL wants to write more.
386 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
391 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
392 c = (conn_rec *)SSL_get_app_data(ssl);
393 ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
394 "SSL error on writing data");
397 * write(2) returns only the generic error number -1
403 rc = write(fb->fd, buf, len);
408 /* the prototype for our own SSL_writev() */
409 static int SSL_writev(SSL *, const struct iovec *, int);
411 static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt)
417 if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
418 rc = SSL_writev(ssl, iov, iovcnt);
420 * Simulate an EINTR in case OpenSSL wants to write more.
422 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
427 if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
428 c = (conn_rec *)SSL_get_app_data(ssl);
429 ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
430 "SSL error on writing data");
433 * writev(2) returns only the generic error number -1
439 rc = writev(fb->fd, iov, iovcnt);
446 /* these two functions are exported from buff.c under WIN32 */
447 API_EXPORT(int) sendwithtimeout(int sock, const char *buf, int len, int flags);
448 API_EXPORT(int) recvwithtimeout(int sock, char *buf, int len, int flags);
450 /* and the prototypes for our SSL_xxx variants */
451 static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len);
452 static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len);
454 static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len)
459 if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
460 rc = SSL_recvwithtimeout(fb, buf, len);
462 rc = recvwithtimeout(fb->fd, buf, len, 0);
466 static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len)
471 if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
472 rc = SSL_sendwithtimeout(fb, buf, len);
474 rc = sendwithtimeout(fb->fd, buf, len, 0);
480 /* _________________________________________________________________
482 ** Special Functions for OpenSSL
483 ** _________________________________________________________________
488 static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len)
493 int err = WSAEWOULDBLOCK;
499 ssl = ap_ctx_get(fb->ctx, "ssl");
501 if (!(tv.tv_sec = ap_check_alarm()))
502 return (SSL_write(ssl, (char*)buf, len));
504 rv = ioctlsocket(sock, FIONBIO, &iostate);
507 err = WSAGetLastError();
510 rv = SSL_write(ssl, (char*)buf, len);
512 if (BIO_sock_should_retry(rv)) {
516 FD_SET((unsigned int)sock, &fdset);
518 rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
519 if (rv == SOCKET_ERROR)
520 err = WSAGetLastError();
522 ioctlsocket(sock, FIONBIO, &iostate);
523 if(ap_check_alarm() < 0) {
524 WSASetLastError(EINTR); /* Simulate an alarm() */
525 return (SOCKET_ERROR);
529 rv = SSL_write(ssl, (char*)buf, len);
530 if (BIO_sock_should_retry(rv)) {
531 ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
532 "select claimed we could write, "
533 "but in fact we couldn't. "
534 "This is a bug in Windows.");
542 ioctlsocket(sock, FIONBIO, &iostate);
543 if (rv == SOCKET_ERROR)
544 WSASetLastError(err);
548 static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len)
553 int err = WSAEWOULDBLOCK;
555 int sock = fb->fd_in;
559 ssl = ap_ctx_get(fb->ctx, "ssl");
561 if (!(tv.tv_sec = ap_check_alarm()))
562 return (SSL_read(ssl, buf, len));
564 rv = ioctlsocket(sock, FIONBIO, &iostate);
567 rv = SSL_read(ssl, buf, len);
569 if (BIO_sock_should_retry(rv)) {
573 FD_SET((unsigned int)sock, &fdset);
575 rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
576 if (rv == SOCKET_ERROR)
577 err = WSAGetLastError();
579 ioctlsocket(sock, FIONBIO, &iostate);
581 WSASetLastError(WSAEWOULDBLOCK);
582 return (SOCKET_ERROR);
585 rv = SSL_read(ssl, buf, len);
586 if (rv == SOCKET_ERROR) {
587 if (BIO_sock_should_retry(rv)) {
588 ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
589 "select claimed we could read, "
590 "but in fact we couldn't. "
591 "This is a bug in Windows.");
596 err = WSAGetLastError();
603 ioctlsocket(sock, FIONBIO, &iostate);
604 if (rv == SOCKET_ERROR)
605 WSASetLastError(err);
612 * There is no SSL_writev() provided by OpenSSL. The reason is mainly because
613 * OpenSSL has to fragment the data itself again for the SSL record layer, so a
614 * writev() like interface makes not much sense. What we do is to emulate it
615 * to at least being able to use the write() like interface. But keep in mind
616 * that the network I/O performance is not write() like, of course.
619 static int SSL_writev(SSL *ssl, const struct iovec *iov, int iovcnt)
626 for (i = 0; i < iovcnt; i++) {
627 if ((n = SSL_write(ssl, iov[i].iov_base, iov[i].iov_len)) == -1) {
637 /* _________________________________________________________________
639 ** I/O Data Debugging
640 ** _________________________________________________________________
643 #define DUMP_WIDTH 16
645 static void ssl_io_data_dump(server_rec *srvr, const char *s, long len)
649 int i, j, rows, trunc;
653 for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--)
655 rows = (len / DUMP_WIDTH);
656 if ((rows * DUMP_WIDTH) < len)
658 ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
659 "+-------------------------------------------------------------------------+");
660 for(i = 0 ; i< rows; i++) {
661 ap_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH);
662 ap_cpystrn(buf, tmp, sizeof(buf));
663 for (j = 0; j < DUMP_WIDTH; j++) {
664 if (((i * DUMP_WIDTH) + j) >= len)
665 ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
667 ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
668 ap_snprintf(tmp, sizeof(tmp), "%02x%c", ch , j==7 ? '-' : ' ');
669 ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
672 ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
673 for (j = 0; j < DUMP_WIDTH; j++) {
674 if (((i * DUMP_WIDTH) + j) >= len)
675 ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
677 ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
678 ap_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.');
679 ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
682 ap_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));
683 ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID, "%s", buf);
686 ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
687 "| %04x - <SPACES/NULS>", len + trunc);
688 ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
689 "+-------------------------------------------------------------------------+");
693 long ssl_io_data_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long rc)
699 if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
701 if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
705 if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
706 || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
708 ssl_log(s, SSL_LOG_DEBUG,
709 "%s: %s %ld/%d bytes %s BIO#%08X [mem: %08lX] %s",
711 (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
712 rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
714 (argp != NULL ? "(BIO dump follows)" : "(Ops, no memory buffer?)"));
716 ssl_io_data_dump(s, argp, rc);
719 ssl_log(s, SSL_LOG_DEBUG,
720 "%s: I/O error, %d bytes expected to %s on BIO#%08X [mem: %08lX]",
721 SSL_LIBRARY_NAME, argi,
722 (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),