1 | /* |
2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include <stdio.h> |
11 | #include <errno.h> |
12 | #include "bio_local.h" |
13 | |
14 | #ifndef OPENSSL_NO_SOCK |
15 | |
16 | typedef struct bio_accept_st { |
17 | int state; |
18 | int accept_family; |
19 | int bind_mode; /* Socket mode for BIO_listen */ |
20 | int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */ |
21 | char *param_addr; |
22 | char *param_serv; |
23 | |
24 | int accept_sock; |
25 | |
26 | BIO_ADDRINFO *addr_first; |
27 | const BIO_ADDRINFO *addr_iter; |
28 | BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */ |
29 | char *cache_accepting_name, *cache_accepting_serv; |
30 | BIO_ADDR cache_peer_addr; |
31 | char *cache_peer_name, *cache_peer_serv; |
32 | |
33 | BIO *bio_chain; |
34 | } BIO_ACCEPT; |
35 | |
36 | static int acpt_write(BIO *h, const char *buf, int num); |
37 | static int acpt_read(BIO *h, char *buf, int size); |
38 | static int acpt_puts(BIO *h, const char *str); |
39 | static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2); |
40 | static int acpt_new(BIO *h); |
41 | static int acpt_free(BIO *data); |
42 | static int acpt_state(BIO *b, BIO_ACCEPT *c); |
43 | static void acpt_close_socket(BIO *data); |
44 | static BIO_ACCEPT *BIO_ACCEPT_new(void); |
45 | static void BIO_ACCEPT_free(BIO_ACCEPT *a); |
46 | |
47 | # define ACPT_S_BEFORE 1 |
48 | # define ACPT_S_GET_ADDR 2 |
49 | # define ACPT_S_CREATE_SOCKET 3 |
50 | # define ACPT_S_LISTEN 4 |
51 | # define ACPT_S_ACCEPT 5 |
52 | # define ACPT_S_OK 6 |
53 | |
54 | static const BIO_METHOD methods_acceptp = { |
55 | BIO_TYPE_ACCEPT, |
56 | "socket accept" , |
57 | /* TODO: Convert to new style write function */ |
58 | bwrite_conv, |
59 | acpt_write, |
60 | /* TODO: Convert to new style read function */ |
61 | bread_conv, |
62 | acpt_read, |
63 | acpt_puts, |
64 | NULL, /* connect_gets, */ |
65 | acpt_ctrl, |
66 | acpt_new, |
67 | acpt_free, |
68 | NULL, /* connect_callback_ctrl */ |
69 | }; |
70 | |
71 | const BIO_METHOD *BIO_s_accept(void) |
72 | { |
73 | return &methods_acceptp; |
74 | } |
75 | |
76 | static int acpt_new(BIO *bi) |
77 | { |
78 | BIO_ACCEPT *ba; |
79 | |
80 | bi->init = 0; |
81 | bi->num = (int)INVALID_SOCKET; |
82 | bi->flags = 0; |
83 | if ((ba = BIO_ACCEPT_new()) == NULL) |
84 | return 0; |
85 | bi->ptr = (char *)ba; |
86 | ba->state = ACPT_S_BEFORE; |
87 | bi->shutdown = 1; |
88 | return 1; |
89 | } |
90 | |
91 | static BIO_ACCEPT *BIO_ACCEPT_new(void) |
92 | { |
93 | BIO_ACCEPT *ret; |
94 | |
95 | if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { |
96 | BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE); |
97 | return NULL; |
98 | } |
99 | ret->accept_family = BIO_FAMILY_IPANY; |
100 | ret->accept_sock = (int)INVALID_SOCKET; |
101 | return ret; |
102 | } |
103 | |
104 | static void BIO_ACCEPT_free(BIO_ACCEPT *a) |
105 | { |
106 | if (a == NULL) |
107 | return; |
108 | OPENSSL_free(a->param_addr); |
109 | OPENSSL_free(a->param_serv); |
110 | BIO_ADDRINFO_free(a->addr_first); |
111 | OPENSSL_free(a->cache_accepting_name); |
112 | OPENSSL_free(a->cache_accepting_serv); |
113 | OPENSSL_free(a->cache_peer_name); |
114 | OPENSSL_free(a->cache_peer_serv); |
115 | BIO_free(a->bio_chain); |
116 | OPENSSL_free(a); |
117 | } |
118 | |
119 | static void acpt_close_socket(BIO *bio) |
120 | { |
121 | BIO_ACCEPT *c; |
122 | |
123 | c = (BIO_ACCEPT *)bio->ptr; |
124 | if (c->accept_sock != (int)INVALID_SOCKET) { |
125 | shutdown(c->accept_sock, 2); |
126 | closesocket(c->accept_sock); |
127 | c->accept_sock = (int)INVALID_SOCKET; |
128 | bio->num = (int)INVALID_SOCKET; |
129 | } |
130 | } |
131 | |
132 | static int acpt_free(BIO *a) |
133 | { |
134 | BIO_ACCEPT *data; |
135 | |
136 | if (a == NULL) |
137 | return 0; |
138 | data = (BIO_ACCEPT *)a->ptr; |
139 | |
140 | if (a->shutdown) { |
141 | acpt_close_socket(a); |
142 | BIO_ACCEPT_free(data); |
143 | a->ptr = NULL; |
144 | a->flags = 0; |
145 | a->init = 0; |
146 | } |
147 | return 1; |
148 | } |
149 | |
150 | static int acpt_state(BIO *b, BIO_ACCEPT *c) |
151 | { |
152 | BIO *bio = NULL, *dbio; |
153 | int s = -1, ret = -1; |
154 | |
155 | for (;;) { |
156 | switch (c->state) { |
157 | case ACPT_S_BEFORE: |
158 | if (c->param_addr == NULL && c->param_serv == NULL) { |
159 | BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); |
160 | ERR_add_error_data(4, |
161 | "hostname=" , c->param_addr, |
162 | " service=" , c->param_serv); |
163 | goto exit_loop; |
164 | } |
165 | |
166 | /* Because we're starting a new bind, any cached name and serv |
167 | * are now obsolete and need to be cleaned out. |
168 | * QUESTION: should this be done in acpt_close_socket() instead? |
169 | */ |
170 | OPENSSL_free(c->cache_accepting_name); |
171 | c->cache_accepting_name = NULL; |
172 | OPENSSL_free(c->cache_accepting_serv); |
173 | c->cache_accepting_serv = NULL; |
174 | OPENSSL_free(c->cache_peer_name); |
175 | c->cache_peer_name = NULL; |
176 | OPENSSL_free(c->cache_peer_serv); |
177 | c->cache_peer_serv = NULL; |
178 | |
179 | c->state = ACPT_S_GET_ADDR; |
180 | break; |
181 | |
182 | case ACPT_S_GET_ADDR: |
183 | { |
184 | int family = AF_UNSPEC; |
185 | switch (c->accept_family) { |
186 | case BIO_FAMILY_IPV6: |
187 | if (1) { /* This is a trick we use to avoid bit rot. |
188 | * at least the "else" part will always be |
189 | * compiled. |
190 | */ |
191 | #ifdef AF_INET6 |
192 | family = AF_INET6; |
193 | } else { |
194 | #endif |
195 | BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); |
196 | goto exit_loop; |
197 | } |
198 | break; |
199 | case BIO_FAMILY_IPV4: |
200 | family = AF_INET; |
201 | break; |
202 | case BIO_FAMILY_IPANY: |
203 | family = AF_UNSPEC; |
204 | break; |
205 | default: |
206 | BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); |
207 | goto exit_loop; |
208 | } |
209 | if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, |
210 | family, SOCK_STREAM, &c->addr_first) == 0) |
211 | goto exit_loop; |
212 | } |
213 | if (c->addr_first == NULL) { |
214 | BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); |
215 | goto exit_loop; |
216 | } |
217 | /* We're currently not iterating, but set this as preparation |
218 | * for possible future development in that regard |
219 | */ |
220 | c->addr_iter = c->addr_first; |
221 | c->state = ACPT_S_CREATE_SOCKET; |
222 | break; |
223 | |
224 | case ACPT_S_CREATE_SOCKET: |
225 | ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), |
226 | BIO_ADDRINFO_socktype(c->addr_iter), |
227 | BIO_ADDRINFO_protocol(c->addr_iter), 0); |
228 | if (ret == (int)INVALID_SOCKET) { |
229 | ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), |
230 | "calling socket(%s, %s)" , |
231 | c->param_addr, c->param_serv); |
232 | BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); |
233 | goto exit_loop; |
234 | } |
235 | c->accept_sock = ret; |
236 | b->num = ret; |
237 | c->state = ACPT_S_LISTEN; |
238 | break; |
239 | |
240 | case ACPT_S_LISTEN: |
241 | { |
242 | if (!BIO_listen(c->accept_sock, |
243 | BIO_ADDRINFO_address(c->addr_iter), |
244 | c->bind_mode)) { |
245 | BIO_closesocket(c->accept_sock); |
246 | goto exit_loop; |
247 | } |
248 | } |
249 | |
250 | { |
251 | union BIO_sock_info_u info; |
252 | |
253 | info.addr = &c->cache_accepting_addr; |
254 | if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS, |
255 | &info)) { |
256 | BIO_closesocket(c->accept_sock); |
257 | goto exit_loop; |
258 | } |
259 | } |
260 | |
261 | c->cache_accepting_name = |
262 | BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1); |
263 | c->cache_accepting_serv = |
264 | BIO_ADDR_service_string(&c->cache_accepting_addr, 1); |
265 | c->state = ACPT_S_ACCEPT; |
266 | s = -1; |
267 | ret = 1; |
268 | goto end; |
269 | |
270 | case ACPT_S_ACCEPT: |
271 | if (b->next_bio != NULL) { |
272 | c->state = ACPT_S_OK; |
273 | break; |
274 | } |
275 | BIO_clear_retry_flags(b); |
276 | b->retry_reason = 0; |
277 | |
278 | OPENSSL_free(c->cache_peer_name); |
279 | c->cache_peer_name = NULL; |
280 | OPENSSL_free(c->cache_peer_serv); |
281 | c->cache_peer_serv = NULL; |
282 | |
283 | s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr, |
284 | c->accepted_mode); |
285 | |
286 | /* If the returned socket is invalid, this might still be |
287 | * retryable |
288 | */ |
289 | if (s < 0) { |
290 | if (BIO_sock_should_retry(s)) { |
291 | BIO_set_retry_special(b); |
292 | b->retry_reason = BIO_RR_ACCEPT; |
293 | goto end; |
294 | } |
295 | } |
296 | |
297 | /* If it wasn't retryable, we fail */ |
298 | if (s < 0) { |
299 | ret = s; |
300 | goto exit_loop; |
301 | } |
302 | |
303 | bio = BIO_new_socket(s, BIO_CLOSE); |
304 | if (bio == NULL) |
305 | goto exit_loop; |
306 | |
307 | BIO_set_callback(bio, BIO_get_callback(b)); |
308 | BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); |
309 | |
310 | /* |
311 | * If the accept BIO has an bio_chain, we dup it and put the new |
312 | * socket at the end. |
313 | */ |
314 | if (c->bio_chain != NULL) { |
315 | if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL) |
316 | goto exit_loop; |
317 | if (!BIO_push(dbio, bio)) |
318 | goto exit_loop; |
319 | bio = dbio; |
320 | } |
321 | if (BIO_push(b, bio) == NULL) |
322 | goto exit_loop; |
323 | |
324 | c->cache_peer_name = |
325 | BIO_ADDR_hostname_string(&c->cache_peer_addr, 1); |
326 | c->cache_peer_serv = |
327 | BIO_ADDR_service_string(&c->cache_peer_addr, 1); |
328 | c->state = ACPT_S_OK; |
329 | bio = NULL; |
330 | ret = 1; |
331 | goto end; |
332 | |
333 | case ACPT_S_OK: |
334 | if (b->next_bio == NULL) { |
335 | c->state = ACPT_S_ACCEPT; |
336 | break; |
337 | } |
338 | ret = 1; |
339 | goto end; |
340 | |
341 | default: |
342 | ret = 0; |
343 | goto end; |
344 | } |
345 | } |
346 | |
347 | exit_loop: |
348 | if (bio != NULL) |
349 | BIO_free(bio); |
350 | else if (s >= 0) |
351 | BIO_closesocket(s); |
352 | end: |
353 | return ret; |
354 | } |
355 | |
356 | static int acpt_read(BIO *b, char *out, int outl) |
357 | { |
358 | int ret = 0; |
359 | BIO_ACCEPT *data; |
360 | |
361 | BIO_clear_retry_flags(b); |
362 | data = (BIO_ACCEPT *)b->ptr; |
363 | |
364 | while (b->next_bio == NULL) { |
365 | ret = acpt_state(b, data); |
366 | if (ret <= 0) |
367 | return ret; |
368 | } |
369 | |
370 | ret = BIO_read(b->next_bio, out, outl); |
371 | BIO_copy_next_retry(b); |
372 | return ret; |
373 | } |
374 | |
375 | static int acpt_write(BIO *b, const char *in, int inl) |
376 | { |
377 | int ret; |
378 | BIO_ACCEPT *data; |
379 | |
380 | BIO_clear_retry_flags(b); |
381 | data = (BIO_ACCEPT *)b->ptr; |
382 | |
383 | while (b->next_bio == NULL) { |
384 | ret = acpt_state(b, data); |
385 | if (ret <= 0) |
386 | return ret; |
387 | } |
388 | |
389 | ret = BIO_write(b->next_bio, in, inl); |
390 | BIO_copy_next_retry(b); |
391 | return ret; |
392 | } |
393 | |
394 | static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) |
395 | { |
396 | int *ip; |
397 | long ret = 1; |
398 | BIO_ACCEPT *data; |
399 | char **pp; |
400 | |
401 | data = (BIO_ACCEPT *)b->ptr; |
402 | |
403 | switch (cmd) { |
404 | case BIO_CTRL_RESET: |
405 | ret = 0; |
406 | data->state = ACPT_S_BEFORE; |
407 | acpt_close_socket(b); |
408 | BIO_ADDRINFO_free(data->addr_first); |
409 | data->addr_first = NULL; |
410 | b->flags = 0; |
411 | break; |
412 | case BIO_C_DO_STATE_MACHINE: |
413 | /* use this one to start the connection */ |
414 | ret = (long)acpt_state(b, data); |
415 | break; |
416 | case BIO_C_SET_ACCEPT: |
417 | if (ptr != NULL) { |
418 | if (num == 0) { |
419 | char *hold_serv = data->param_serv; |
420 | /* We affect the hostname regardless. However, the input |
421 | * string might contain a host:service spec, so we must |
422 | * parse it, which might or might not affect the service |
423 | */ |
424 | OPENSSL_free(data->param_addr); |
425 | data->param_addr = NULL; |
426 | ret = BIO_parse_hostserv(ptr, |
427 | &data->param_addr, |
428 | &data->param_serv, |
429 | BIO_PARSE_PRIO_SERV); |
430 | if (hold_serv != data->param_serv) |
431 | OPENSSL_free(hold_serv); |
432 | b->init = 1; |
433 | } else if (num == 1) { |
434 | OPENSSL_free(data->param_serv); |
435 | data->param_serv = OPENSSL_strdup(ptr); |
436 | b->init = 1; |
437 | } else if (num == 2) { |
438 | data->bind_mode |= BIO_SOCK_NONBLOCK; |
439 | } else if (num == 3) { |
440 | BIO_free(data->bio_chain); |
441 | data->bio_chain = (BIO *)ptr; |
442 | } else if (num == 4) { |
443 | data->accept_family = *(int *)ptr; |
444 | } |
445 | } else { |
446 | if (num == 2) { |
447 | data->bind_mode &= ~BIO_SOCK_NONBLOCK; |
448 | } |
449 | } |
450 | break; |
451 | case BIO_C_SET_NBIO: |
452 | if (num != 0) |
453 | data->accepted_mode |= BIO_SOCK_NONBLOCK; |
454 | else |
455 | data->accepted_mode &= ~BIO_SOCK_NONBLOCK; |
456 | break; |
457 | case BIO_C_SET_FD: |
458 | b->num = *((int *)ptr); |
459 | data->accept_sock = b->num; |
460 | data->state = ACPT_S_ACCEPT; |
461 | b->shutdown = (int)num; |
462 | b->init = 1; |
463 | break; |
464 | case BIO_C_GET_FD: |
465 | if (b->init) { |
466 | ip = (int *)ptr; |
467 | if (ip != NULL) |
468 | *ip = data->accept_sock; |
469 | ret = data->accept_sock; |
470 | } else |
471 | ret = -1; |
472 | break; |
473 | case BIO_C_GET_ACCEPT: |
474 | if (b->init) { |
475 | if (num == 0 && ptr != NULL) { |
476 | pp = (char **)ptr; |
477 | *pp = data->cache_accepting_name; |
478 | } else if (num == 1 && ptr != NULL) { |
479 | pp = (char **)ptr; |
480 | *pp = data->cache_accepting_serv; |
481 | } else if (num == 2 && ptr != NULL) { |
482 | pp = (char **)ptr; |
483 | *pp = data->cache_peer_name; |
484 | } else if (num == 3 && ptr != NULL) { |
485 | pp = (char **)ptr; |
486 | *pp = data->cache_peer_serv; |
487 | } else if (num == 4) { |
488 | switch (BIO_ADDRINFO_family(data->addr_iter)) { |
489 | #ifdef AF_INET6 |
490 | case AF_INET6: |
491 | ret = BIO_FAMILY_IPV6; |
492 | break; |
493 | #endif |
494 | case AF_INET: |
495 | ret = BIO_FAMILY_IPV4; |
496 | break; |
497 | case 0: |
498 | ret = data->accept_family; |
499 | break; |
500 | default: |
501 | ret = -1; |
502 | break; |
503 | } |
504 | } else |
505 | ret = -1; |
506 | } else |
507 | ret = -1; |
508 | break; |
509 | case BIO_CTRL_GET_CLOSE: |
510 | ret = b->shutdown; |
511 | break; |
512 | case BIO_CTRL_SET_CLOSE: |
513 | b->shutdown = (int)num; |
514 | break; |
515 | case BIO_CTRL_PENDING: |
516 | case BIO_CTRL_WPENDING: |
517 | ret = 0; |
518 | break; |
519 | case BIO_CTRL_FLUSH: |
520 | break; |
521 | case BIO_C_SET_BIND_MODE: |
522 | data->bind_mode = (int)num; |
523 | break; |
524 | case BIO_C_GET_BIND_MODE: |
525 | ret = (long)data->bind_mode; |
526 | break; |
527 | case BIO_CTRL_DUP: |
528 | break; |
529 | |
530 | default: |
531 | ret = 0; |
532 | break; |
533 | } |
534 | return ret; |
535 | } |
536 | |
537 | static int acpt_puts(BIO *bp, const char *str) |
538 | { |
539 | int n, ret; |
540 | |
541 | n = strlen(str); |
542 | ret = acpt_write(bp, str, n); |
543 | return ret; |
544 | } |
545 | |
546 | BIO *BIO_new_accept(const char *str) |
547 | { |
548 | BIO *ret; |
549 | |
550 | ret = BIO_new(BIO_s_accept()); |
551 | if (ret == NULL) |
552 | return NULL; |
553 | if (BIO_set_accept_name(ret, str)) |
554 | return ret; |
555 | BIO_free(ret); |
556 | return NULL; |
557 | } |
558 | |
559 | #endif |
560 | |