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