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

1.1       misho       1: #include "network_backends.h"
                      2: 
                      3: #ifdef USE_OPENSSL
                      4: 
                      5: #include "network.h"
                      6: #include "fdevent.h"
                      7: #include "log.h"
                      8: #include "stat_cache.h"
                      9: 
                     10: #include <sys/types.h>
                     11: #include <sys/socket.h>
                     12: #include <sys/stat.h>
                     13: #include <sys/time.h>
                     14: #include <sys/resource.h>
                     15: 
                     16: #include <netinet/in.h>
                     17: #include <netinet/tcp.h>
                     18: 
                     19: #include <errno.h>
                     20: #include <fcntl.h>
                     21: #include <unistd.h>
                     22: #include <netdb.h>
                     23: #include <string.h>
                     24: #include <stdlib.h>
                     25: #include <assert.h>
                     26: 
                     27: # include <openssl/ssl.h>
                     28: # include <openssl/err.h>
                     29: 
                     30: int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq, off_t max_bytes) {
                     31:        int ssl_r;
                     32:        chunk *c;
                     33: 
                     34:        /* this is a 64k sendbuffer
                     35:         *
                     36:         * it has to stay at the same location all the time to satisfy the needs
                     37:         * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
                     38:         *
                     39:         * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
                     40:         * -> we expect a 64k block to 'leak' in valgrind
                     41:         *
                     42:         *
                     43:         * In reality we would like to use mmap() but we don't have a guarantee that
                     44:         * we get the same mmap() address for each call. On openbsd the mmap() address
                     45:         * even randomized.
                     46:         *   That means either we keep the mmap() open or we do a read() into a
                     47:         * constant buffer
                     48:         * */
                     49: #define LOCAL_SEND_BUFSIZE (64 * 1024)
                     50:        static char *local_send_buffer = NULL;
                     51: 
                     52:        /* the remote side closed the connection before without shutdown request
                     53:         * - IE
                     54:         * - wget
                     55:         * if keep-alive is disabled */
                     56: 
                     57:        if (con->keep_alive == 0) {
                     58:                SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
                     59:        }
                     60: 
                     61:        for(c = cq->first; (max_bytes > 0) && (NULL != c); c = c->next) {
                     62:                int chunk_finished = 0;
                     63: 
                     64:                switch(c->type) {
                     65:                case MEM_CHUNK: {
                     66:                        char * offset;
                     67:                        off_t toSend;
                     68:                        ssize_t r;
                     69: 
                     70:                        if (c->mem->used == 0 || c->mem->used == 1) {
                     71:                                chunk_finished = 1;
                     72:                                break;
                     73:                        }
                     74: 
                     75:                        offset = c->mem->ptr + c->offset;
                     76:                        toSend = c->mem->used - 1 - c->offset;
                     77:                        if (toSend > max_bytes) toSend = max_bytes;
                     78: 
                     79:                        /**
                     80:                         * SSL_write man-page
                     81:                         *
                     82:                         * WARNING
                     83:                         *        When an SSL_write() operation has to be repeated because of
                     84:                         *        SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
                     85:                         *        repeated with the same arguments.
                     86:                         *
                     87:                         */
                     88: 
                     89:                        ERR_clear_error();
                     90:                        r = SSL_write(ssl, offset, toSend);
                     91: 
                     92:                        if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
                     93:                                log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
                     94:                                return -1;
                     95:                        }
                     96: 
                     97:                        if (r <= 0) {
                     98:                                unsigned long err;
                     99: 
                    100:                                switch ((ssl_r = SSL_get_error(ssl, r))) {
                    101:                                case SSL_ERROR_WANT_WRITE:
                    102:                                        break;
                    103:                                case SSL_ERROR_SYSCALL:
                    104:                                        /* perhaps we have error waiting in our error-queue */
                    105:                                        if (0 != (err = ERR_get_error())) {
                    106:                                                do {
                    107:                                                        log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
                    108:                                                                        ssl_r, r,
                    109:                                                                        ERR_error_string(err, NULL));
                    110:                                                } while((err = ERR_get_error()));
                    111:                                        } else if (r == -1) {
                    112:                                                /* no, but we have errno */
                    113:                                                switch(errno) {
                    114:                                                case EPIPE:
                    115:                                                case ECONNRESET:
                    116:                                                        return -2;
                    117:                                                default:
                    118:                                                        log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
                    119:                                                                        ssl_r, r, errno,
                    120:                                                                        strerror(errno));
                    121:                                                        break;
                    122:                                                }
                    123:                                        } else {
                    124:                                                /* neither error-queue nor errno ? */
                    125:                                                log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
                    126:                                                                ssl_r, r, errno,
                    127:                                                                strerror(errno));
                    128:                                        }
                    129: 
                    130:                                        return  -1;
                    131:                                case SSL_ERROR_ZERO_RETURN:
                    132:                                        /* clean shutdown on the remote side */
                    133: 
                    134:                                        if (r == 0) return -2;
                    135: 
                    136:                                        /* fall through */
                    137:                                default:
                    138:                                        while((err = ERR_get_error())) {
                    139:                                                log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
                    140:                                                                ssl_r, r,
                    141:                                                                ERR_error_string(err, NULL));
                    142:                                        }
                    143: 
                    144:                                        return  -1;
                    145:                                }
                    146:                        } else {
                    147:                                c->offset += r;
                    148:                                cq->bytes_out += r;
                    149:                                max_bytes -= r;
                    150:                        }
                    151: 
                    152:                        if (c->offset == (off_t)c->mem->used - 1) {
                    153:                                chunk_finished = 1;
                    154:                        }
                    155: 
                    156:                        break;
                    157:                }
                    158:                case FILE_CHUNK: {
                    159:                        char *s;
                    160:                        ssize_t r;
                    161:                        stat_cache_entry *sce = NULL;
                    162:                        int ifd;
                    163:                        int write_wait = 0;
                    164: 
                    165:                        if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
                    166:                                log_error_write(srv, __FILE__, __LINE__, "sb",
                    167:                                                strerror(errno), c->file.name);
                    168:                                return -1;
                    169:                        }
                    170: 
                    171:                        if (NULL == local_send_buffer) {
                    172:                                local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
                    173:                                assert(local_send_buffer);
                    174:                        }
                    175: 
                    176:                        do {
                    177:                                off_t offset = c->file.start + c->offset;
                    178:                                off_t toSend = c->file.length - c->offset;
                    179:                                if (toSend > max_bytes) toSend = max_bytes;
                    180: 
                    181:                                if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
                    182: 
                    183:                                if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
                    184:                                        log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
                    185: 
                    186:                                        return -1;
                    187:                                }
                    188: 
                    189: 
                    190:                                lseek(ifd, offset, SEEK_SET);
                    191:                                if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) {
                    192:                                        close(ifd);
                    193:                                        log_error_write(srv, __FILE__, __LINE__, "ss", "read failed:", strerror(errno));
                    194:                                        return -1;
                    195:                                }
                    196: 
                    197:                                s = local_send_buffer;
                    198: 
                    199:                                close(ifd);
                    200: 
                    201:                                ERR_clear_error();
                    202:                                r = SSL_write(ssl, s, toSend);
                    203: 
                    204:                                if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
                    205:                                        log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
                    206:                                        return -1;
                    207:                                }
                    208: 
                    209:                                if (r <= 0) {
                    210:                                        unsigned long err;
                    211: 
                    212:                                        switch ((ssl_r = SSL_get_error(ssl, r))) {
                    213:                                        case SSL_ERROR_WANT_WRITE:
                    214:                                                write_wait = 1;
                    215:                                                break;
                    216:                                        case SSL_ERROR_SYSCALL:
                    217:                                                /* perhaps we have error waiting in our error-queue */
                    218:                                                if (0 != (err = ERR_get_error())) {
                    219:                                                        do {
                    220:                                                                log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
                    221:                                                                                ssl_r, r,
                    222:                                                                                ERR_error_string(err, NULL));
                    223:                                                        } while((err = ERR_get_error()));
                    224:                                                } else if (r == -1) {
                    225:                                                        /* no, but we have errno */
                    226:                                                        switch(errno) {
                    227:                                                        case EPIPE:
                    228:                                                        case ECONNRESET:
                    229:                                                                return -2;
                    230:                                                        default:
                    231:                                                                log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
                    232:                                                                                ssl_r, r, errno,
                    233:                                                                                strerror(errno));
                    234:                                                                break;
                    235:                                                        }
                    236:                                                } else {
                    237:                                                        /* neither error-queue nor errno ? */
                    238:                                                        log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
                    239:                                                                        ssl_r, r, errno,
                    240:                                                                        strerror(errno));
                    241:                                                }
                    242: 
                    243:                                                return  -1;
                    244:                                        case SSL_ERROR_ZERO_RETURN:
                    245:                                                /* clean shutdown on the remote side */
                    246: 
                    247:                                                if (r == 0)  return -2;
                    248: 
                    249:                                                /* fall thourgh */
                    250:                                        default:
                    251:                                                while((err = ERR_get_error())) {
                    252:                                                        log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
                    253:                                                                        ssl_r, r,
                    254:                                                                        ERR_error_string(err, NULL));
                    255:                                                }
                    256: 
                    257:                                                return -1;
                    258:                                        }
                    259:                                } else {
                    260:                                        c->offset += r;
                    261:                                        cq->bytes_out += r;
                    262:                                        max_bytes -= r;
                    263:                                }
                    264: 
                    265:                                if (c->offset == c->file.length) {
                    266:                                        chunk_finished = 1;
                    267:                                }
                    268:                        } while (!chunk_finished && !write_wait && max_bytes > 0);
                    269: 
                    270:                        break;
                    271:                }
                    272:                default:
                    273:                        log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
                    274: 
                    275:                        return -1;
                    276:                }
                    277: 
                    278:                if (!chunk_finished) {
                    279:                        /* not finished yet */
                    280: 
                    281:                        break;
                    282:                }
                    283:        }
                    284: 
                    285:        return 0;
                    286: }
                    287: #endif
                    288: 
                    289: #if 0
                    290: network_openssl_init(void) {
                    291:        p->write_ssl = network_openssl_write_chunkset;
                    292: }
                    293: #endif

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