[core] avoid spurious trace and error abort
[lighttpd.git] / src / network_openssl.c
blob4cf2cc48bfea5da1a16755305f3d0a1e9b3064c0
1 #include "first.h"
3 #include "network_backends.h"
5 #if defined(USE_OPENSSL)
7 #include "network.h"
8 #include "log.h"
10 #include <unistd.h>
11 #include <stdlib.h>
13 #include <errno.h>
14 #include <string.h>
16 # include <openssl/ssl.h>
17 # include <openssl/err.h>
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;
22 #define LOCAL_SEND_BUFSIZE (64 * 1024)
23 /* this is a 64k sendbuffer
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
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;
33 force_assert(NULL != c);
35 switch (c->type) {
36 case MEM_CHUNK:
38 size_t have;
40 force_assert(c->offset >= 0 && c->offset <= (off_t)buffer_string_length(c->mem));
42 have = buffer_string_length(c->mem) - c->offset;
43 if ((off_t) have > max_bytes) have = max_bytes;
45 *data = c->mem->ptr + c->offset;
46 *data_len = have;
48 return 0;
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);
56 if (0 != network_open_file_chunk(srv, con, cq)) return -1;
59 off_t offset, toSend;
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;
65 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
66 if (toSend > max_bytes) toSend = max_bytes;
68 if (-1 == lseek(c->file.fd, offset, SEEK_SET)) {
69 log_error_write(srv, __FILE__, __LINE__, "ss", "lseek: ", strerror(errno));
70 return -1;
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;
77 *data = local_send_buffer;
78 *data_len = toSend;
80 return 0;
83 return -1;
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 */
93 if (con->keep_alive == 0) {
94 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
97 chunkqueue_remove_finished_chunks(cq);
99 while (max_bytes > 0 && NULL != cq->first) {
100 const char *data;
101 size_t data_len;
102 int r;
104 if (0 != load_next_chunk(srv, con, cq, max_bytes, &data, &data_len)) return -1;
107 * SSL_write man-page
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.
115 ERR_clear_error();
116 r = SSL_write(ssl, data, data_len);
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;
123 if (r <= 0) {
124 int ssl_r;
125 unsigned long err;
127 switch ((ssl_r = SSL_get_error(ssl, r))) {
128 case SSL_ERROR_WANT_WRITE:
129 return 0; /* try again later */
130 case SSL_ERROR_SYSCALL:
131 /* perhaps we have error waiting in our error-queue */
132 if (0 != (err = ERR_get_error())) {
133 do {
134 log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
135 ssl_r, r,
136 ERR_error_string(err, NULL));
137 } while((err = ERR_get_error()));
138 } else if (r == -1) {
139 /* no, but we have errno */
140 switch(errno) {
141 case EPIPE:
142 case ECONNRESET:
143 return -2;
144 default:
145 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
146 ssl_r, r, errno,
147 strerror(errno));
148 break;
150 } else {
151 /* neither error-queue nor errno ? */
152 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
153 ssl_r, r, errno,
154 strerror(errno));
156 break;
158 case SSL_ERROR_ZERO_RETURN:
159 /* clean shutdown on the remote side */
161 if (r == 0) return -2;
163 /* fall through */
164 default:
165 while((err = ERR_get_error())) {
166 log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
167 ssl_r, r,
168 ERR_error_string(err, NULL));
170 break;
172 return -1;
175 chunkqueue_mark_written(cq, r);
176 max_bytes -= r;
178 if ((size_t) r < data_len) break; /* try again later */
181 return 0;
183 #endif /* USE_OPENSSL */