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
network_write_chunkqueue_openssl(server * srv,connection * con,SSL * ssl,chunkqueue * cq,off_t max_bytes)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");
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");
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
294