Annotation of embedaddon/lighttpd/src/network_openssl.c, revision 1.1.1.2
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);
1.1.1.2 ! misho 173: force_assert(local_send_buffer);
1.1 misho 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:
1.1.1.2 ! misho 190: if (-1 == lseek(ifd, offset, SEEK_SET)) {
! 191: log_error_write(srv, __FILE__, __LINE__, "ss", "lseek failed:", strerror(errno));
1.1 misho 192: close(ifd);
1.1.1.2 ! misho 193: return -1;
! 194: }
! 195: if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) {
1.1 misho 196: log_error_write(srv, __FILE__, __LINE__, "ss", "read failed:", strerror(errno));
1.1.1.2 ! misho 197: close(ifd);
1.1 misho 198: return -1;
199: }
200:
201: s = local_send_buffer;
202:
203: close(ifd);
204:
205: ERR_clear_error();
206: r = SSL_write(ssl, s, toSend);
207:
208: if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) {
209: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client, killing connection");
210: return -1;
211: }
212:
213: if (r <= 0) {
214: unsigned long err;
215:
216: switch ((ssl_r = SSL_get_error(ssl, r))) {
217: case SSL_ERROR_WANT_WRITE:
218: write_wait = 1;
219: break;
220: case SSL_ERROR_SYSCALL:
221: /* perhaps we have error waiting in our error-queue */
222: if (0 != (err = ERR_get_error())) {
223: do {
224: log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
225: ssl_r, r,
226: ERR_error_string(err, NULL));
227: } while((err = ERR_get_error()));
228: } else if (r == -1) {
229: /* no, but we have errno */
230: switch(errno) {
231: case EPIPE:
232: case ECONNRESET:
233: return -2;
234: default:
235: log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
236: ssl_r, r, errno,
237: strerror(errno));
238: break;
239: }
240: } else {
241: /* neither error-queue nor errno ? */
242: log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
243: ssl_r, r, errno,
244: strerror(errno));
245: }
246:
247: return -1;
248: case SSL_ERROR_ZERO_RETURN:
249: /* clean shutdown on the remote side */
250:
251: if (r == 0) return -2;
252:
253: /* fall thourgh */
254: default:
255: while((err = ERR_get_error())) {
256: log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
257: ssl_r, r,
258: ERR_error_string(err, NULL));
259: }
260:
261: return -1;
262: }
263: } else {
264: c->offset += r;
265: cq->bytes_out += r;
266: max_bytes -= r;
267: }
268:
269: if (c->offset == c->file.length) {
270: chunk_finished = 1;
271: }
272: } while (!chunk_finished && !write_wait && max_bytes > 0);
273:
274: break;
275: }
276: default:
277: log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
278:
279: return -1;
280: }
281:
282: if (!chunk_finished) {
283: /* not finished yet */
284:
285: break;
286: }
287: }
288:
289: return 0;
290: }
291: #endif
292:
293: #if 0
294: network_openssl_init(void) {
295: p->write_ssl = network_openssl_write_chunkset;
296: }
297: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>