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>