Address some code-analysis issues.
[openssl.git] / crypto / bio / bss_acpt.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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_lcl.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,
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         return NULL;
97     ret->accept_family = BIO_FAMILY_IPANY;
98     ret->accept_sock = (int)INVALID_SOCKET;
99     return ret;
100 }
101
102 static void BIO_ACCEPT_free(BIO_ACCEPT *a)
103 {
104     if (a == NULL)
105         return;
106
107     OPENSSL_free(a->param_addr);
108     OPENSSL_free(a->param_serv);
109     BIO_ADDRINFO_free(a->addr_first);
110     OPENSSL_free(a->cache_accepting_name);
111     OPENSSL_free(a->cache_accepting_serv);
112     OPENSSL_free(a->cache_peer_name);
113     OPENSSL_free(a->cache_peer_serv);
114     BIO_free(a->bio_chain);
115     OPENSSL_free(a);
116 }
117
118 static void acpt_close_socket(BIO *bio)
119 {
120     BIO_ACCEPT *c;
121
122     c = (BIO_ACCEPT *)bio->ptr;
123     if (c->accept_sock != (int)INVALID_SOCKET) {
124         shutdown(c->accept_sock, 2);
125         closesocket(c->accept_sock);
126         c->accept_sock = (int)INVALID_SOCKET;
127         bio->num = (int)INVALID_SOCKET;
128     }
129 }
130
131 static int acpt_free(BIO *a)
132 {
133     BIO_ACCEPT *data;
134
135     if (a == NULL)
136         return 0;
137     data = (BIO_ACCEPT *)a->ptr;
138
139     if (a->shutdown) {
140         acpt_close_socket(a);
141         BIO_ACCEPT_free(data);
142         a->ptr = NULL;
143         a->flags = 0;
144         a->init = 0;
145     }
146     return 1;
147 }
148
149 static int acpt_state(BIO *b, BIO_ACCEPT *c)
150 {
151     BIO *bio = NULL, *dbio;
152     int s = -1, ret = -1;
153
154     for (;;) {
155         switch (c->state) {
156         case ACPT_S_BEFORE:
157             if (c->param_addr == NULL && c->param_serv == NULL) {
158                 BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
159                 ERR_add_error_data(4,
160                                    "hostname=", c->param_addr,
161                                    " service=", c->param_serv);
162                 goto exit_loop;
163             }
164
165             /* Because we're starting a new bind, any cached name and serv
166              * are now obsolete and need to be cleaned out.
167              * QUESTION: should this be done in acpt_close_socket() instead?
168              */
169             OPENSSL_free(c->cache_accepting_name);
170             c->cache_accepting_name = NULL;
171             OPENSSL_free(c->cache_accepting_serv);
172             c->cache_accepting_serv = NULL;
173             OPENSSL_free(c->cache_peer_name);
174             c->cache_peer_name = NULL;
175             OPENSSL_free(c->cache_peer_serv);
176             c->cache_peer_serv = NULL;
177
178             c->state = ACPT_S_GET_ADDR;
179             break;
180
181         case ACPT_S_GET_ADDR:
182             {
183                 int family = AF_UNSPEC;
184                 switch (c->accept_family) {
185                 case BIO_FAMILY_IPV6:
186                     if (1) { /* This is a trick we use to avoid bit rot.
187                               * at least the "else" part will always be
188                               * compiled.
189                               */
190 #ifdef AF_INET6
191                         family = AF_INET6;
192                     } else {
193 #endif
194                         BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
195                         goto exit_loop;
196                     }
197                     break;
198                 case BIO_FAMILY_IPV4:
199                     family = AF_INET;
200                     break;
201                 case BIO_FAMILY_IPANY:
202                     family = AF_UNSPEC;
203                     break;
204                 default:
205                     BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
206                     goto exit_loop;
207                 }
208                 if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
209                                family, SOCK_STREAM, &c->addr_first) == 0)
210                     goto exit_loop;
211             }
212             if (c->addr_first == NULL) {
213                 BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
214                 goto exit_loop;
215             }
216             /* We're currently not iterating, but set this as preparation
217              * for possible future development in that regard
218              */
219             c->addr_iter = c->addr_first;
220             c->state = ACPT_S_CREATE_SOCKET;
221             break;
222
223         case ACPT_S_CREATE_SOCKET:
224             ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
225                              BIO_ADDRINFO_socktype(c->addr_iter),
226                              BIO_ADDRINFO_protocol(c->addr_iter), 0);
227             if (ret == (int)INVALID_SOCKET) {
228                 SYSerr(SYS_F_SOCKET, get_last_socket_error());
229                 ERR_add_error_data(4,
230                                    "hostname=", c->param_addr,
231                                    " service=", 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             s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
279                               c->accepted_mode);
280
281             /* If the returned socket is invalid, this might still be
282              * retryable
283              */
284             if (s < 0) {
285                 if (BIO_sock_should_retry(s)) {
286                     BIO_set_retry_special(b);
287                     b->retry_reason = BIO_RR_ACCEPT;
288                     goto end;
289                 }
290             }
291
292             /* If it wasn't retryable, we fail */
293             if (s < 0) {
294                 ret = s;
295                 goto exit_loop;
296             }
297
298             bio = BIO_new_socket(s, BIO_CLOSE);
299             if (bio == NULL)
300                 goto exit_loop;
301
302             BIO_set_callback(bio, BIO_get_callback(b));
303             BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
304
305             /*
306              * If the accept BIO has an bio_chain, we dup it and put the new
307              * socket at the end.
308              */
309             if (c->bio_chain != NULL) {
310                 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
311                     goto exit_loop;
312                 if (!BIO_push(dbio, bio))
313                     goto exit_loop;
314                 bio = dbio;
315             }
316             if (BIO_push(b, bio) == NULL)
317                 goto exit_loop;
318
319             c->cache_peer_name =
320                 BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
321             c->cache_peer_serv =
322                 BIO_ADDR_service_string(&c->cache_peer_addr, 1);
323             c->state = ACPT_S_OK;
324             bio = NULL;
325             ret = 1;
326             goto end;
327
328         case ACPT_S_OK:
329             if (b->next_bio == NULL) {
330                 c->state = ACPT_S_ACCEPT;
331                 break;
332             }
333             ret = 1;
334             goto end;
335
336         default:
337             ret = 0;
338             goto end;
339         }
340     }
341
342   exit_loop:
343     if (bio != NULL)
344         BIO_free(bio);
345     else if (s >= 0)
346         BIO_closesocket(s);
347   end:
348     return ret;
349 }
350
351 static int acpt_read(BIO *b, char *out, int outl)
352 {
353     int ret = 0;
354     BIO_ACCEPT *data;
355
356     BIO_clear_retry_flags(b);
357     data = (BIO_ACCEPT *)b->ptr;
358
359     while (b->next_bio == NULL) {
360         ret = acpt_state(b, data);
361         if (ret <= 0)
362             return ret;
363     }
364
365     ret = BIO_read(b->next_bio, out, outl);
366     BIO_copy_next_retry(b);
367     return ret;
368 }
369
370 static int acpt_write(BIO *b, const char *in, int inl)
371 {
372     int ret;
373     BIO_ACCEPT *data;
374
375     BIO_clear_retry_flags(b);
376     data = (BIO_ACCEPT *)b->ptr;
377
378     while (b->next_bio == NULL) {
379         ret = acpt_state(b, data);
380         if (ret <= 0)
381             return ret;
382     }
383
384     ret = BIO_write(b->next_bio, in, inl);
385     BIO_copy_next_retry(b);
386     return ret;
387 }
388
389 static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
390 {
391     int *ip;
392     long ret = 1;
393     BIO_ACCEPT *data;
394     char **pp;
395
396     data = (BIO_ACCEPT *)b->ptr;
397
398     switch (cmd) {
399     case BIO_CTRL_RESET:
400         ret = 0;
401         data->state = ACPT_S_BEFORE;
402         acpt_close_socket(b);
403         BIO_ADDRINFO_free(data->addr_first);
404         data->addr_first = NULL;
405         b->flags = 0;
406         break;
407     case BIO_C_DO_STATE_MACHINE:
408         /* use this one to start the connection */
409         ret = (long)acpt_state(b, data);
410         break;
411     case BIO_C_SET_ACCEPT:
412         if (ptr != NULL) {
413             if (num == 0) {
414                 char *hold_serv = data->param_serv;
415                 /* We affect the hostname regardless.  However, the input
416                  * string might contain a host:service spec, so we must
417                  * parse it, which might or might not affect the service
418                  */
419                 OPENSSL_free(data->param_addr);
420                 data->param_addr = NULL;
421                 ret = BIO_parse_hostserv(ptr,
422                                          &data->param_addr,
423                                          &data->param_serv,
424                                          BIO_PARSE_PRIO_SERV);
425                 if (hold_serv != data->param_serv)
426                     OPENSSL_free(hold_serv);
427                 b->init = 1;
428             } else if (num == 1) {
429                 OPENSSL_free(data->param_serv);
430                 data->param_serv = BUF_strdup(ptr);
431                 b->init = 1;
432             } else if (num == 2) {
433                 data->bind_mode |= BIO_SOCK_NONBLOCK;
434             } else if (num == 3) {
435                 BIO_free(data->bio_chain);
436                 data->bio_chain = (BIO *)ptr;
437             } else if (num == 4) {
438                 data->accept_family = *(int *)ptr;
439             }
440         } else {
441             if (num == 2) {
442                 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
443             }
444         }
445         break;
446     case BIO_C_SET_NBIO:
447         if (num != 0)
448             data->accepted_mode |= BIO_SOCK_NONBLOCK;
449         else
450             data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
451         break;
452     case BIO_C_SET_FD:
453         b->num = *((int *)ptr);
454         data->accept_sock = b->num;
455         data->state = ACPT_S_ACCEPT;
456         b->shutdown = (int)num;
457         b->init = 1;
458         break;
459     case BIO_C_GET_FD:
460         if (b->init) {
461             ip = (int *)ptr;
462             if (ip != NULL)
463                 *ip = data->accept_sock;
464             ret = data->accept_sock;
465         } else
466             ret = -1;
467         break;
468     case BIO_C_GET_ACCEPT:
469         if (b->init) {
470             if (num == 0 && ptr != NULL) {
471                 pp = (char **)ptr;
472                 *pp = data->cache_accepting_name;
473             } else if (num == 1 && ptr != NULL) {
474                 pp = (char **)ptr;
475                 *pp = data->cache_accepting_serv;
476             } else if (num == 2 && ptr != NULL) {
477                 pp = (char **)ptr;
478                 *pp = data->cache_peer_name;
479             } else if (num == 3 && ptr != NULL) {
480                 pp = (char **)ptr;
481                 *pp = data->cache_peer_serv;
482             } else if (num == 4) {
483                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
484 #ifdef AF_INET6
485                 case AF_INET6:
486                     ret = BIO_FAMILY_IPV6;
487                     break;
488 #endif
489                 case AF_INET:
490                     ret = BIO_FAMILY_IPV4;
491                     break;
492                 case 0:
493                     ret = data->accept_family;
494                     break;
495                 default:
496                     ret = -1;
497                     break;
498                 }
499             } else
500                 ret = -1;
501         } else
502             ret = -1;
503         break;
504     case BIO_CTRL_GET_CLOSE:
505         ret = b->shutdown;
506         break;
507     case BIO_CTRL_SET_CLOSE:
508         b->shutdown = (int)num;
509         break;
510     case BIO_CTRL_PENDING:
511     case BIO_CTRL_WPENDING:
512         ret = 0;
513         break;
514     case BIO_CTRL_FLUSH:
515         break;
516     case BIO_C_SET_BIND_MODE:
517         data->bind_mode = (int)num;
518         break;
519     case BIO_C_GET_BIND_MODE:
520         ret = (long)data->bind_mode;
521         break;
522     case BIO_CTRL_DUP:
523         break;
524
525     default:
526         ret = 0;
527         break;
528     }
529     return ret;
530 }
531
532 static int acpt_puts(BIO *bp, const char *str)
533 {
534     int n, ret;
535
536     n = strlen(str);
537     ret = acpt_write(bp, str, n);
538     return ret;
539 }
540
541 BIO *BIO_new_accept(const char *str)
542 {
543     BIO *ret;
544
545     ret = BIO_new(BIO_s_accept());
546     if (ret == NULL)
547         return NULL;
548     if (BIO_set_accept_name(ret, str))
549         return ret;
550     BIO_free(ret);
551     return NULL;
552 }
553
554 #endif