xref: /openssl/crypto/bio/bss_acpt.c (revision 836bb089)
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 
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         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 
BIO_ACCEPT_free(BIO_ACCEPT * a)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 
acpt_close_socket(BIO * bio)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 
acpt_free(BIO * a)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 
acpt_state(BIO * b,BIO_ACCEPT * c)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 #if OPENSSL_USE_IPV6
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 
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         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 #if OPENSSL_USE_IPV6
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 
acpt_puts(BIO * bp,const char * str)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 
BIO_new_accept(const char * str)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
580