]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bio/bss_acpt.c
Update copyright year
[thirdparty/openssl.git] / crypto / bio / bss_acpt.c
1 /*
2 * Copyright 1995-2022 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 #define OPENSSL_SUPPRESS_DEPRECATED
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include "bio_local.h"
15
16 #ifndef OPENSSL_NO_SOCK
17
18 typedef struct bio_accept_st {
19 int state;
20 int accept_family;
21 int bind_mode; /* Socket mode for BIO_listen */
22 int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */
23 char *param_addr;
24 char *param_serv;
25
26 int accept_sock;
27
28 BIO_ADDRINFO *addr_first;
29 const BIO_ADDRINFO *addr_iter;
30 BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */
31 char *cache_accepting_name, *cache_accepting_serv;
32 BIO_ADDR cache_peer_addr;
33 char *cache_peer_name, *cache_peer_serv;
34
35 BIO *bio_chain;
36 } BIO_ACCEPT;
37
38 static int acpt_write(BIO *h, const char *buf, int num);
39 static int acpt_read(BIO *h, char *buf, int size);
40 static int acpt_puts(BIO *h, const char *str);
41 static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
42 static int acpt_new(BIO *h);
43 static int acpt_free(BIO *data);
44 static int acpt_state(BIO *b, BIO_ACCEPT *c);
45 static void acpt_close_socket(BIO *data);
46 static BIO_ACCEPT *BIO_ACCEPT_new(void);
47 static void BIO_ACCEPT_free(BIO_ACCEPT *a);
48
49 # define ACPT_S_BEFORE 1
50 # define ACPT_S_GET_ADDR 2
51 # define ACPT_S_CREATE_SOCKET 3
52 # define ACPT_S_LISTEN 4
53 # define ACPT_S_ACCEPT 5
54 # define ACPT_S_OK 6
55
56 static const BIO_METHOD methods_acceptp = {
57 BIO_TYPE_ACCEPT,
58 "socket accept",
59 bwrite_conv,
60 acpt_write,
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 ERR_raise(ERR_LIB_BIO, 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 ERR_raise_data(ERR_LIB_BIO,
160 BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED,
161 "hostname=%s, service=%s",
162 c->param_addr, 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 ERR_raise(ERR_LIB_BIO, 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 ERR_raise(ERR_LIB_BIO, 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 ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING);
215 goto exit_loop;
216 }
217 c->addr_iter = c->addr_first;
218 c->state = ACPT_S_CREATE_SOCKET;
219 break;
220
221 case ACPT_S_CREATE_SOCKET:
222 ERR_set_mark();
223 s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
224 BIO_ADDRINFO_socktype(c->addr_iter),
225 BIO_ADDRINFO_protocol(c->addr_iter), 0);
226 if (s == (int)INVALID_SOCKET) {
227 if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
228 /*
229 * if there are more addresses to try, do that first
230 */
231 ERR_pop_to_mark();
232 break;
233 }
234 ERR_clear_last_mark();
235 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
236 "calling socket(%s, %s)",
237 c->param_addr, c->param_serv);
238 ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
239 goto exit_loop;
240 }
241 c->accept_sock = s;
242 b->num = s;
243 c->state = ACPT_S_LISTEN;
244 s = -1;
245 break;
246
247 case ACPT_S_LISTEN:
248 {
249 if (!BIO_listen(c->accept_sock,
250 BIO_ADDRINFO_address(c->addr_iter),
251 c->bind_mode)) {
252 BIO_closesocket(c->accept_sock);
253 goto exit_loop;
254 }
255 }
256
257 {
258 union BIO_sock_info_u info;
259
260 info.addr = &c->cache_accepting_addr;
261 if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
262 &info)) {
263 BIO_closesocket(c->accept_sock);
264 goto exit_loop;
265 }
266 }
267
268 c->cache_accepting_name =
269 BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
270 c->cache_accepting_serv =
271 BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
272 c->state = ACPT_S_ACCEPT;
273 s = -1;
274 ret = 1;
275 goto end;
276
277 case ACPT_S_ACCEPT:
278 if (b->next_bio != NULL) {
279 c->state = ACPT_S_OK;
280 break;
281 }
282 BIO_clear_retry_flags(b);
283 b->retry_reason = 0;
284
285 OPENSSL_free(c->cache_peer_name);
286 c->cache_peer_name = NULL;
287 OPENSSL_free(c->cache_peer_serv);
288 c->cache_peer_serv = NULL;
289
290 s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
291 c->accepted_mode);
292
293 /* If the returned socket is invalid, this might still be
294 * retryable
295 */
296 if (s < 0) {
297 if (BIO_sock_should_retry(s)) {
298 BIO_set_retry_special(b);
299 b->retry_reason = BIO_RR_ACCEPT;
300 goto end;
301 }
302 }
303
304 /* If it wasn't retryable, we fail */
305 if (s < 0) {
306 ret = s;
307 goto exit_loop;
308 }
309
310 bio = BIO_new_socket(s, BIO_CLOSE);
311 if (bio == NULL)
312 goto exit_loop;
313
314 BIO_set_callback_ex(bio, BIO_get_callback_ex(b));
315 #ifndef OPENSSL_NO_DEPRECATED_3_0
316 BIO_set_callback(bio, BIO_get_callback(b));
317 #endif
318 BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
319 /*
320 * If the accept BIO has an bio_chain, we dup it and put the new
321 * socket at the end.
322 */
323 if (c->bio_chain != NULL) {
324 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
325 goto exit_loop;
326 if (!BIO_push(dbio, bio))
327 goto exit_loop;
328 bio = dbio;
329 }
330 if (BIO_push(b, bio) == NULL)
331 goto exit_loop;
332
333 c->cache_peer_name =
334 BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
335 c->cache_peer_serv =
336 BIO_ADDR_service_string(&c->cache_peer_addr, 1);
337 c->state = ACPT_S_OK;
338 bio = NULL;
339 ret = 1;
340 goto end;
341
342 case ACPT_S_OK:
343 if (b->next_bio == NULL) {
344 c->state = ACPT_S_ACCEPT;
345 break;
346 }
347 ret = 1;
348 goto end;
349
350 default:
351 ret = 0;
352 goto end;
353 }
354 }
355
356 exit_loop:
357 if (bio != NULL)
358 BIO_free(bio);
359 else if (s >= 0)
360 BIO_closesocket(s);
361 end:
362 return ret;
363 }
364
365 static int acpt_read(BIO *b, char *out, int outl)
366 {
367 int ret = 0;
368 BIO_ACCEPT *data;
369
370 BIO_clear_retry_flags(b);
371 data = (BIO_ACCEPT *)b->ptr;
372
373 while (b->next_bio == NULL) {
374 ret = acpt_state(b, data);
375 if (ret <= 0)
376 return ret;
377 }
378
379 ret = BIO_read(b->next_bio, out, outl);
380 BIO_copy_next_retry(b);
381 return ret;
382 }
383
384 static int acpt_write(BIO *b, const char *in, int inl)
385 {
386 int ret;
387 BIO_ACCEPT *data;
388
389 BIO_clear_retry_flags(b);
390 data = (BIO_ACCEPT *)b->ptr;
391
392 while (b->next_bio == NULL) {
393 ret = acpt_state(b, data);
394 if (ret <= 0)
395 return ret;
396 }
397
398 ret = BIO_write(b->next_bio, in, inl);
399 BIO_copy_next_retry(b);
400 return ret;
401 }
402
403 static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
404 {
405 int *ip;
406 long ret = 1;
407 BIO_ACCEPT *data;
408 char **pp;
409
410 data = (BIO_ACCEPT *)b->ptr;
411
412 switch (cmd) {
413 case BIO_CTRL_RESET:
414 ret = 0;
415 data->state = ACPT_S_BEFORE;
416 acpt_close_socket(b);
417 BIO_ADDRINFO_free(data->addr_first);
418 data->addr_first = NULL;
419 b->flags = 0;
420 break;
421 case BIO_C_DO_STATE_MACHINE:
422 /* use this one to start the connection */
423 ret = (long)acpt_state(b, data);
424 break;
425 case BIO_C_SET_ACCEPT:
426 if (ptr != NULL) {
427 if (num == 0) {
428 char *hold_serv = data->param_serv;
429 /* We affect the hostname regardless. However, the input
430 * string might contain a host:service spec, so we must
431 * parse it, which might or might not affect the service
432 */
433 OPENSSL_free(data->param_addr);
434 data->param_addr = NULL;
435 ret = BIO_parse_hostserv(ptr,
436 &data->param_addr,
437 &data->param_serv,
438 BIO_PARSE_PRIO_SERV);
439 if (hold_serv != data->param_serv)
440 OPENSSL_free(hold_serv);
441 b->init = 1;
442 } else if (num == 1) {
443 OPENSSL_free(data->param_serv);
444 if ((data->param_serv = OPENSSL_strdup(ptr)) == NULL)
445 ret = 0;
446 else
447 b->init = 1;
448 } else if (num == 2) {
449 data->bind_mode |= BIO_SOCK_NONBLOCK;
450 } else if (num == 3) {
451 BIO_free(data->bio_chain);
452 data->bio_chain = (BIO *)ptr;
453 } else if (num == 4) {
454 data->accept_family = *(int *)ptr;
455 } else if (num == 5) {
456 data->bind_mode |= BIO_SOCK_TFO;
457 }
458 } else {
459 if (num == 2) {
460 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
461 } else if (num == 5) {
462 data->bind_mode &= ~BIO_SOCK_TFO;
463 }
464 }
465 break;
466 case BIO_C_SET_NBIO:
467 if (num != 0)
468 data->accepted_mode |= BIO_SOCK_NONBLOCK;
469 else
470 data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
471 break;
472 case BIO_C_SET_FD:
473 b->num = *((int *)ptr);
474 data->accept_sock = b->num;
475 data->state = ACPT_S_ACCEPT;
476 b->shutdown = (int)num;
477 b->init = 1;
478 break;
479 case BIO_C_GET_FD:
480 if (b->init) {
481 ip = (int *)ptr;
482 if (ip != NULL)
483 *ip = data->accept_sock;
484 ret = data->accept_sock;
485 } else
486 ret = -1;
487 break;
488 case BIO_C_GET_ACCEPT:
489 if (b->init) {
490 if (num == 0 && ptr != NULL) {
491 pp = (char **)ptr;
492 *pp = data->cache_accepting_name;
493 } else if (num == 1 && ptr != NULL) {
494 pp = (char **)ptr;
495 *pp = data->cache_accepting_serv;
496 } else if (num == 2 && ptr != NULL) {
497 pp = (char **)ptr;
498 *pp = data->cache_peer_name;
499 } else if (num == 3 && ptr != NULL) {
500 pp = (char **)ptr;
501 *pp = data->cache_peer_serv;
502 } else if (num == 4) {
503 switch (BIO_ADDRINFO_family(data->addr_iter)) {
504 #ifdef AF_INET6
505 case AF_INET6:
506 ret = BIO_FAMILY_IPV6;
507 break;
508 #endif
509 case AF_INET:
510 ret = BIO_FAMILY_IPV4;
511 break;
512 case 0:
513 ret = data->accept_family;
514 break;
515 default:
516 ret = -1;
517 break;
518 }
519 } else
520 ret = -1;
521 } else
522 ret = -1;
523 break;
524 case BIO_CTRL_GET_CLOSE:
525 ret = b->shutdown;
526 break;
527 case BIO_CTRL_SET_CLOSE:
528 b->shutdown = (int)num;
529 break;
530 case BIO_CTRL_PENDING:
531 case BIO_CTRL_WPENDING:
532 ret = 0;
533 break;
534 case BIO_CTRL_FLUSH:
535 break;
536 case BIO_C_SET_BIND_MODE:
537 data->bind_mode = (int)num;
538 break;
539 case BIO_C_GET_BIND_MODE:
540 ret = (long)data->bind_mode;
541 break;
542 case BIO_CTRL_DUP:
543 break;
544 case BIO_CTRL_EOF:
545 if (b->next_bio == NULL)
546 ret = 0;
547 else
548 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
549 break;
550 default:
551 ret = 0;
552 break;
553 }
554 return ret;
555 }
556
557 static int acpt_puts(BIO *bp, const char *str)
558 {
559 int n, ret;
560
561 n = strlen(str);
562 ret = acpt_write(bp, str, n);
563 return ret;
564 }
565
566 BIO *BIO_new_accept(const char *str)
567 {
568 BIO *ret;
569
570 ret = BIO_new(BIO_s_accept());
571 if (ret == NULL)
572 return NULL;
573 if (BIO_set_accept_name(ret, str))
574 return ret;
575 BIO_free(ret);
576 return NULL;
577 }
578
579 #endif