Annotation of embedaddon/lighttpd/src/network_openssl.c, revision 1.1.1.3

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "network_backends.h"
                      4: 
1.1.1.3 ! misho       5: #if defined(USE_OPENSSL)
1.1       misho       6: 
                      7: #include "network.h"
                      8: #include "log.h"
                      9: 
1.1.1.3 ! misho      10: #include <unistd.h>
        !            11: #include <stdlib.h>
1.1       misho      12: 
                     13: #include <errno.h>
                     14: #include <string.h>
                     15: 
                     16: # include <openssl/ssl.h>
                     17: # include <openssl/err.h>
                     18: 
1.1.1.3 ! misho      19: static int load_next_chunk(server *srv, connection *con, chunkqueue *cq, off_t max_bytes, const char **data, size_t *data_len) {
        !            20:        chunk * const c = cq->first;
1.1       misho      21: 
1.1.1.3 ! misho      22: #define LOCAL_SEND_BUFSIZE (64 * 1024)
1.1       misho      23:        /* this is a 64k sendbuffer
                     24:         *
                     25:         * it has to stay at the same location all the time to satisfy the needs
                     26:         * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
                     27:         *
                     28:         * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
                     29:         * -> we expect a 64k block to 'leak' in valgrind
                     30:         * */
                     31:        static char *local_send_buffer = NULL;
                     32: 
1.1.1.3 ! misho      33:        force_assert(NULL != c);
1.1       misho      34: 
1.1.1.3 ! misho      35:        switch (c->type) {
        !            36:        case MEM_CHUNK:
        !            37:                {
        !            38:                        size_t have;
1.1       misho      39: 
1.1.1.3 ! misho      40:                        force_assert(c->offset >= 0 && c->offset <= (off_t)buffer_string_length(c->mem));
1.1       misho      41: 
1.1.1.3 ! misho      42:                        have = buffer_string_length(c->mem) - c->offset;
        !            43:                        if ((off_t) have > max_bytes) have = max_bytes;
1.1       misho      44: 
1.1.1.3 ! misho      45:                        *data = c->mem->ptr + c->offset;
        !            46:                        *data_len = have;
        !            47:                }
        !            48:                return 0;
1.1       misho      49: 
1.1.1.3 ! misho      50:        case FILE_CHUNK:
        !            51:                if (NULL == local_send_buffer) {
        !            52:                        local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
        !            53:                        force_assert(NULL != local_send_buffer);
        !            54:                }
1.1       misho      55: 
1.1.1.3 ! misho      56:                if (0 != network_open_file_chunk(srv, con, cq)) return -1;
1.1       misho      57: 
1.1.1.3 ! misho      58:                {
        !            59:                        off_t offset, toSend;
1.1       misho      60: 
1.1.1.3 ! misho      61:                        force_assert(c->offset >= 0 && c->offset <= c->file.length);
        !            62:                        offset = c->file.start + c->offset;
        !            63:                        toSend = c->file.length - c->offset;
1.1       misho      64: 
1.1.1.3 ! misho      65:                        if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
        !            66:                        if (toSend > max_bytes) toSend = max_bytes;
1.1       misho      67: 
1.1.1.3 ! misho      68:                        if (-1 == lseek(c->file.fd, offset, SEEK_SET)) {
        !            69:                                log_error_write(srv, __FILE__, __LINE__, "ss", "lseek: ", strerror(errno));
1.1       misho      70:                                return -1;
                     71:                        }
1.1.1.3 ! misho      72:                        if (-1 == (toSend = read(c->file.fd, local_send_buffer, toSend))) {
        !            73:                                log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
        !            74:                                return -1;
1.1       misho      75:                        }
                     76: 
1.1.1.3 ! misho      77:                        *data = local_send_buffer;
        !            78:                        *data_len = toSend;
        !            79:                }
        !            80:                return 0;
        !            81:        }
1.1       misho      82: 
1.1.1.3 ! misho      83:        return -1;
        !            84: }
1.1       misho      85: 
                     86: 
1.1.1.3 ! misho      87: int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes) {
        !            88:        /* the remote side closed the connection before without shutdown request
        !            89:         * - IE
        !            90:         * - wget
        !            91:         * if keep-alive is disabled */
1.1       misho      92: 
1.1.1.3 ! misho      93:        if (con->keep_alive == 0) {
        !            94:                SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
        !            95:        }
1.1       misho      96: 
1.1.1.3 ! misho      97:        chunkqueue_remove_finished_chunks(cq);
1.1       misho      98: 
1.1.1.3 ! misho      99:        while (max_bytes > 0 && NULL != cq->first) {
        !           100:                const char *data;
        !           101:                size_t data_len;
        !           102:                int r;
        !           103: 
        !           104:                if (0 != load_next_chunk(srv, con, cq, max_bytes, &data, &data_len)) return -1;
        !           105: 
        !           106:                /**
        !           107:                 * SSL_write man-page
        !           108:                 *
        !           109:                 * WARNING
        !           110:                 *        When an SSL_write() operation has to be repeated because of
        !           111:                 *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
        !           112:                 *        repeated with the same arguments.
        !           113:                 */
1.1       misho     114: 
1.1.1.3 ! misho     115:                ERR_clear_error();
        !           116:                r = SSL_write(ssl, data, data_len);
1.1       misho     117: 
1.1.1.3 ! misho     118:                if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
        !           119:                        log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
        !           120:                        return -1;
        !           121:                }
1.1       misho     122: 
1.1.1.3 ! misho     123:                if (r <= 0) {
        !           124:                        int ssl_r;
        !           125:                        unsigned long err;
        !           126: 
        !           127:                        switch ((ssl_r = SSL_get_error(ssl, r))) {
        !           128:                        case SSL_ERROR_WANT_READ:
        !           129:                                con->is_readable = -1;
        !           130:                                return 0; /* try again later */
        !           131:                        case SSL_ERROR_WANT_WRITE:
        !           132:                                con->is_writable = -1;
        !           133:                                return 0; /* try again later */
        !           134:                        case SSL_ERROR_SYSCALL:
        !           135:                                /* perhaps we have error waiting in our error-queue */
        !           136:                                if (0 != (err = ERR_get_error())) {
        !           137:                                        do {
        !           138:                                                log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
        !           139:                                                                ssl_r, r,
        !           140:                                                                ERR_error_string(err, NULL));
        !           141:                                        } while((err = ERR_get_error()));
        !           142:                                } else if (r == -1) {
        !           143:                                        /* no, but we have errno */
        !           144:                                        switch(errno) {
        !           145:                                        case EPIPE:
        !           146:                                        case ECONNRESET:
        !           147:                                                return -2;
1.1       misho     148:                                        default:
1.1.1.3 ! misho     149:                                                log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
        !           150:                                                                ssl_r, r, errno,
        !           151:                                                                strerror(errno));
        !           152:                                                break;
1.1       misho     153:                                        }
                    154:                                } else {
1.1.1.3 ! misho     155:                                        /* neither error-queue nor errno ? */
        !           156:                                        log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
        !           157:                                                        ssl_r, r, errno,
        !           158:                                                        strerror(errno));
1.1       misho     159:                                }
1.1.1.3 ! misho     160:                                break;
1.1       misho     161: 
1.1.1.3 ! misho     162:                        case SSL_ERROR_ZERO_RETURN:
        !           163:                                /* clean shutdown on the remote side */
1.1       misho     164: 
1.1.1.3 ! misho     165:                                if (r == 0) return -2;
1.1       misho     166: 
1.1.1.3 ! misho     167:                                /* fall through */
        !           168:                        default:
        !           169:                                while((err = ERR_get_error())) {
        !           170:                                        log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
        !           171:                                                        ssl_r, r,
        !           172:                                                        ERR_error_string(err, NULL));
        !           173:                                }
        !           174:                                break;
        !           175:                        }
1.1       misho     176:                        return -1;
                    177:                }
                    178: 
1.1.1.3 ! misho     179:                chunkqueue_mark_written(cq, r);
        !           180:                max_bytes -= r;
1.1       misho     181: 
1.1.1.3 ! misho     182:                if ((size_t) r < data_len) break; /* try again later */
1.1       misho     183:        }
                    184: 
                    185:        return 0;
                    186: }
1.1.1.3 ! misho     187: #endif /* USE_OPENSSL */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>