1 /*
2 * Copyright 1995-2026 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
BIO_s_accept(void)71 const BIO_METHOD *BIO_s_accept(void)
72 {
73 return &methods_acceptp;
74 }
75
acpt_new(BIO * bi)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
BIO_ACCEPT_new(void)91 static BIO_ACCEPT *BIO_ACCEPT_new(void)
92 {
93 BIO_ACCEPT *ret;
94
95 if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
96 return NULL;
97 ret->accept_family = BIO_FAMILY_IPANY;
98 ret->accept_sock = (int)INVALID_SOCKET;
99 return ret;
100 }
101
BIO_ACCEPT_free(BIO_ACCEPT * a)102 static void BIO_ACCEPT_free(BIO_ACCEPT *a)
103 {
104 if (a == NULL)
105 return;
106 OPENSSL_free(a->param_addr);
107 OPENSSL_free(a->param_serv);
108 BIO_ADDRINFO_free(a->addr_first);
109 OPENSSL_free(a->cache_accepting_name);
110 OPENSSL_free(a->cache_accepting_serv);
111 OPENSSL_free(a->cache_peer_name);
112 OPENSSL_free(a->cache_peer_serv);
113 BIO_free(a->bio_chain);
114 OPENSSL_free(a);
115 }
116
acpt_close_socket(BIO * bio)117 static void acpt_close_socket(BIO *bio)
118 {
119 BIO_ACCEPT *c;
120
121 c = (BIO_ACCEPT *)bio->ptr;
122 if (c->accept_sock != (int)INVALID_SOCKET) {
123 shutdown(c->accept_sock, 2);
124 closesocket(c->accept_sock);
125 c->accept_sock = (int)INVALID_SOCKET;
126 bio->num = (int)INVALID_SOCKET;
127 }
128 }
129
acpt_free(BIO * a)130 static int acpt_free(BIO *a)
131 {
132 BIO_ACCEPT *data;
133
134 if (a == NULL)
135 return 0;
136 data = (BIO_ACCEPT *)a->ptr;
137
138 if (a->shutdown) {
139 acpt_close_socket(a);
140 BIO_ACCEPT_free(data);
141 a->ptr = NULL;
142 a->flags = 0;
143 a->init = 0;
144 }
145 return 1;
146 }
147
acpt_state(BIO * b,BIO_ACCEPT * c)148 static int acpt_state(BIO *b, BIO_ACCEPT *c)
149 {
150 BIO *bio = NULL, *dbio;
151 int s = -1, ret = -1;
152
153 for (;;) {
154 switch (c->state) {
155 case ACPT_S_BEFORE:
156 if (c->param_addr == NULL && c->param_serv == NULL) {
157 ERR_raise_data(ERR_LIB_BIO,
158 BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED,
159 "hostname=%s, service=%s",
160 c->param_addr, c->param_serv);
161 goto exit_loop;
162 }
163
164 /* Because we're starting a new bind, any cached name and serv
165 * are now obsolete and need to be cleaned out.
166 * QUESTION: should this be done in acpt_close_socket() instead?
167 */
168 OPENSSL_free(c->cache_accepting_name);
169 c->cache_accepting_name = NULL;
170 OPENSSL_free(c->cache_accepting_serv);
171 c->cache_accepting_serv = NULL;
172 OPENSSL_free(c->cache_peer_name);
173 c->cache_peer_name = NULL;
174 OPENSSL_free(c->cache_peer_serv);
175 c->cache_peer_serv = NULL;
176
177 c->state = ACPT_S_GET_ADDR;
178 break;
179
180 case ACPT_S_GET_ADDR: {
181 int family = AF_UNSPEC;
182 switch (c->accept_family) {
183 case BIO_FAMILY_IPV6:
184 if (1) { /* This is a trick we use to avoid bit rot.
185 * at least the "else" part will always be
186 * compiled.
187 */
188 #if OPENSSL_USE_IPV6
189 family = AF_INET6;
190 } else {
191 #endif
192 ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY);
193 goto exit_loop;
194 }
195 break;
196 case BIO_FAMILY_IPV4:
197 family = AF_INET;
198 break;
199 case BIO_FAMILY_IPANY:
200 family = AF_UNSPEC;
201 break;
202 default:
203 ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY);
204 goto exit_loop;
205 }
206 if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
207 family, SOCK_STREAM, &c->addr_first)
208 == 0)
209 goto exit_loop;
210 }
211 if (c->addr_first == NULL) {
212 ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING);
213 goto exit_loop;
214 }
215 c->addr_iter = c->addr_first;
216 c->state = ACPT_S_CREATE_SOCKET;
217 break;
218
219 case ACPT_S_CREATE_SOCKET:
220 ERR_set_mark();
221 s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
222 BIO_ADDRINFO_socktype(c->addr_iter),
223 BIO_ADDRINFO_protocol(c->addr_iter), 0);
224 if (s == (int)INVALID_SOCKET) {
225 if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
226 /*
227 * if there are more addresses to try, do that first
228 */
229 ERR_pop_to_mark();
230 break;
231 }
232 ERR_clear_last_mark();
233 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
234 "calling socket(%s, %s)",
235 c->param_addr, c->param_serv);
236 ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
237 goto exit_loop;
238 }
239 c->accept_sock = s;
240 b->num = s;
241 c->state = ACPT_S_LISTEN;
242 s = -1;
243 break;
244
245 case ACPT_S_LISTEN: {
246 if (!BIO_listen(c->accept_sock,
247 BIO_ADDRINFO_address(c->addr_iter),
248 c->bind_mode)) {
249 BIO_closesocket(c->accept_sock);
250 c->accept_sock = (int)INVALID_SOCKET;
251 b->num = (int)INVALID_SOCKET;
252 goto exit_loop;
253 }
254 }
255
256 {
257 union BIO_sock_info_u info;
258
259 info.addr = &c->cache_accepting_addr;
260 if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
261 &info)) {
262 BIO_closesocket(c->accept_sock);
263 c->accept_sock = (int)INVALID_SOCKET;
264 b->num = (int)INVALID_SOCKET;
265 goto exit_loop;
266 }
267 }
268
269 /* Free old values before assigning new ones to prevent memory leak */
270 OPENSSL_free(c->cache_accepting_name);
271 OPENSSL_free(c->cache_accepting_serv);
272 c->cache_accepting_name = BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
273 c->cache_accepting_serv = BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
274 c->state = ACPT_S_ACCEPT;
275 s = -1;
276 ret = 1;
277 goto end;
278
279 case ACPT_S_ACCEPT:
280 if (b->next_bio != NULL) {
281 c->state = ACPT_S_OK;
282 break;
283 }
284 BIO_clear_retry_flags(b);
285 b->retry_reason = 0;
286
287 OPENSSL_free(c->cache_peer_name);
288 c->cache_peer_name = NULL;
289 OPENSSL_free(c->cache_peer_serv);
290 c->cache_peer_serv = NULL;
291
292 s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
293 c->accepted_mode);
294
295 /* If the returned socket is invalid, this might still be
296 * retryable
297 */
298 if (s < 0) {
299 if (BIO_sock_should_retry(s)) {
300 BIO_set_retry_special(b);
301 b->retry_reason = BIO_RR_ACCEPT;
302 goto end;
303 }
304 }
305
306 /* If it wasn't retryable, we fail */
307 if (s < 0) {
308 ret = s;
309 goto exit_loop;
310 }
311
312 bio = BIO_new_socket(s, BIO_CLOSE);
313 if (bio == NULL)
314 goto exit_loop;
315
316 BIO_set_callback_ex(bio, BIO_get_callback_ex(b));
317 #ifndef OPENSSL_NO_DEPRECATED_3_0
318 BIO_set_callback(bio, BIO_get_callback(b));
319 #endif
320 BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
321 /*
322 * If the accept BIO has an bio_chain, we dup it and put the new
323 * socket at the end.
324 */
325 if (c->bio_chain != NULL) {
326 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
327 goto exit_loop;
328 if (!BIO_push(dbio, bio))
329 goto exit_loop;
330 bio = dbio;
331 }
332 if (BIO_push(b, bio) == NULL)
333 goto exit_loop;
334
335 c->cache_peer_name = BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
336 c->cache_peer_serv = 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
acpt_read(BIO * b,char * out,int outl)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
acpt_write(BIO * b,const char * in,int inl)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
acpt_ctrl(BIO * b,int cmd,long num,void * ptr)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 data->addr_iter = NULL;
420 b->flags = 0;
421 break;
422 case BIO_C_DO_STATE_MACHINE:
423 /* use this one to start the connection */
424 ret = (long)acpt_state(b, data);
425 break;
426 case BIO_C_SET_ACCEPT:
427 if (ptr != NULL) {
428 if (num == 0) {
429 char *hold_serv = data->param_serv;
430 /* We affect the hostname regardless. However, the input
431 * string might contain a host:service spec, so we must
432 * parse it, which might or might not affect the service
433 */
434 OPENSSL_free(data->param_addr);
435 data->param_addr = NULL;
436 ret = BIO_parse_hostserv(ptr,
437 &data->param_addr,
438 &data->param_serv,
439 BIO_PARSE_PRIO_SERV);
440 if (hold_serv != data->param_serv)
441 OPENSSL_free(hold_serv);
442 if (ret > 0)
443 b->init = 1;
444 } else if (num == 1) {
445 OPENSSL_free(data->param_serv);
446 if ((data->param_serv = OPENSSL_strdup(ptr)) == NULL)
447 ret = 0;
448 else
449 b->init = 1;
450 } else if (num == 2) {
451 data->bind_mode |= BIO_SOCK_NONBLOCK;
452 } else if (num == 3) {
453 BIO_free(data->bio_chain);
454 data->bio_chain = (BIO *)ptr;
455 } else if (num == 4) {
456 data->accept_family = *(int *)ptr;
457 } else if (num == 5) {
458 data->bind_mode |= BIO_SOCK_TFO;
459 }
460 } else {
461 if (num == 2) {
462 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
463 } else if (num == 5) {
464 data->bind_mode &= ~BIO_SOCK_TFO;
465 }
466 }
467 break;
468 case BIO_C_SET_NBIO:
469 if (num != 0)
470 data->accepted_mode |= BIO_SOCK_NONBLOCK;
471 else
472 data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
473 break;
474 case BIO_C_SET_FD:
475 b->num = *((int *)ptr);
476 data->accept_sock = b->num;
477 data->state = ACPT_S_ACCEPT;
478 b->shutdown = (int)num;
479 b->init = 1;
480 break;
481 case BIO_C_GET_FD:
482 if (b->init) {
483 ip = (int *)ptr;
484 if (ip != NULL)
485 *ip = data->accept_sock;
486 ret = data->accept_sock;
487 } else
488 ret = -1;
489 break;
490 case BIO_C_GET_ACCEPT:
491 if (b->init) {
492 if (num == 0 && ptr != NULL) {
493 pp = (char **)ptr;
494 *pp = data->cache_accepting_name;
495 } else if (num == 1 && ptr != NULL) {
496 pp = (char **)ptr;
497 *pp = data->cache_accepting_serv;
498 } else if (num == 2 && ptr != NULL) {
499 pp = (char **)ptr;
500 *pp = data->cache_peer_name;
501 } else if (num == 3 && ptr != NULL) {
502 pp = (char **)ptr;
503 *pp = data->cache_peer_serv;
504 } else if (num == 4) {
505 switch (BIO_ADDRINFO_family(data->addr_iter)) {
506 #if OPENSSL_USE_IPV6
507 case AF_INET6:
508 ret = BIO_FAMILY_IPV6;
509 break;
510 #endif
511 case AF_INET:
512 ret = BIO_FAMILY_IPV4;
513 break;
514 case 0:
515 ret = data->accept_family;
516 break;
517 default:
518 ret = -1;
519 break;
520 }
521 } else
522 ret = -1;
523 } else
524 ret = -1;
525 break;
526 case BIO_CTRL_GET_CLOSE:
527 ret = b->shutdown;
528 break;
529 case BIO_CTRL_SET_CLOSE:
530 b->shutdown = (int)num;
531 break;
532 case BIO_CTRL_PENDING:
533 case BIO_CTRL_WPENDING:
534 ret = 0;
535 break;
536 case BIO_CTRL_FLUSH:
537 break;
538 case BIO_C_SET_BIND_MODE:
539 data->bind_mode = (int)num;
540 break;
541 case BIO_C_GET_BIND_MODE:
542 ret = (long)data->bind_mode;
543 break;
544 case BIO_CTRL_DUP:
545 break;
546 case BIO_CTRL_EOF:
547 if (b->next_bio == NULL)
548 ret = 0;
549 else
550 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
551 break;
552 default:
553 ret = 0;
554 break;
555 }
556 return ret;
557 }
558
acpt_puts(BIO * bp,const char * str)559 static int acpt_puts(BIO *bp, const char *str)
560 {
561 int n, ret;
562
563 n = strlen(str);
564 ret = acpt_write(bp, str, n);
565 return ret;
566 }
567
BIO_new_accept(const char * str)568 BIO *BIO_new_accept(const char *str)
569 {
570 BIO *ret;
571
572 ret = BIO_new(BIO_s_accept());
573 if (ret == NULL)
574 return NULL;
575 if (BIO_set_accept_name(ret, str) > 0)
576 return ret;
577 BIO_free(ret);
578 return NULL;
579 }
580
581 #endif
582