Create BIO_read_ex() which handles size_t arguments
[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     acpt_write,
58     /* TODO: Convert to new style read function */
59     bread_conv,
60     acpt_read,
61     acpt_puts,
62     NULL,                       /* connect_gets, */
63     acpt_ctrl,
64     acpt_new,
65     acpt_free,
66     NULL,
67 };
68
69 const BIO_METHOD *BIO_s_accept(void)
70 {
71     return (&methods_acceptp);
72 }
73
74 static int acpt_new(BIO *bi)
75 {
76     BIO_ACCEPT *ba;
77
78     bi->init = 0;
79     bi->num = (int)INVALID_SOCKET;
80     bi->flags = 0;
81     if ((ba = BIO_ACCEPT_new()) == NULL)
82         return (0);
83     bi->ptr = (char *)ba;
84     ba->state = ACPT_S_BEFORE;
85     bi->shutdown = 1;
86     return (1);
87 }
88
89 static BIO_ACCEPT *BIO_ACCEPT_new(void)
90 {
91     BIO_ACCEPT *ret;
92
93     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
94         return (NULL);
95     ret->accept_family = BIO_FAMILY_IPANY;
96     ret->accept_sock = (int)INVALID_SOCKET;
97     return (ret);
98 }
99
100 static void BIO_ACCEPT_free(BIO_ACCEPT *a)
101 {
102     if (a == NULL)
103         return;
104
105     OPENSSL_free(a->param_addr);
106     OPENSSL_free(a->param_serv);
107     BIO_ADDRINFO_free(a->addr_first);
108     OPENSSL_free(a->cache_accepting_name);
109     OPENSSL_free(a->cache_accepting_serv);
110     OPENSSL_free(a->cache_peer_name);
111     OPENSSL_free(a->cache_peer_serv);
112     BIO_free(a->bio_chain);
113     OPENSSL_free(a);
114 }
115
116 static void acpt_close_socket(BIO *bio)
117 {
118     BIO_ACCEPT *c;
119
120     c = (BIO_ACCEPT *)bio->ptr;
121     if (c->accept_sock != (int)INVALID_SOCKET) {
122         shutdown(c->accept_sock, 2);
123         closesocket(c->accept_sock);
124         c->accept_sock = (int)INVALID_SOCKET;
125         bio->num = (int)INVALID_SOCKET;
126     }
127 }
128
129 static int acpt_free(BIO *a)
130 {
131     BIO_ACCEPT *data;
132
133     if (a == NULL)
134         return (0);
135     data = (BIO_ACCEPT *)a->ptr;
136
137     if (a->shutdown) {
138         acpt_close_socket(a);
139         BIO_ACCEPT_free(data);
140         a->ptr = NULL;
141         a->flags = 0;
142         a->init = 0;
143     }
144     return (1);
145 }
146
147 static int acpt_state(BIO *b, BIO_ACCEPT *c)
148 {
149     BIO *bio = NULL, *dbio;
150     int s = -1, ret = -1;
151
152     for (;;) {
153         switch (c->state) {
154         case ACPT_S_BEFORE:
155             if (c->param_addr == NULL && c->param_serv == NULL) {
156                 BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
157                 ERR_add_error_data(4,
158                                    "hostname=", c->param_addr,
159                                    " service=", c->param_serv);
160                 goto exit_loop;
161             }
162
163             /* Because we're starting a new bind, any cached name and serv
164              * are now obsolete and need to be cleaned out.
165              * QUESTION: should this be done in acpt_close_socket() instead?
166              */
167             OPENSSL_free(c->cache_accepting_name);
168             c->cache_accepting_name = NULL;
169             OPENSSL_free(c->cache_accepting_serv);
170             c->cache_accepting_serv = NULL;
171             OPENSSL_free(c->cache_peer_name);
172             c->cache_peer_name = NULL;
173             OPENSSL_free(c->cache_peer_serv);
174             c->cache_peer_serv = NULL;
175
176             c->state = ACPT_S_GET_ADDR;
177             break;
178
179         case ACPT_S_GET_ADDR:
180             {
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 #ifdef AF_INET6
189                         family = AF_INET6;
190                     } else {
191 #endif
192                         BIOerr(BIO_F_ACPT_STATE, 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                     BIOerr(BIO_F_ACPT_STATE, 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) == 0)
208                     goto exit_loop;
209             }
210             if (c->addr_first == NULL) {
211                 BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
212                 goto exit_loop;
213             }
214             /* We're currently not iterating, but set this as preparation
215              * for possible future development in that regard
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             ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
223                              BIO_ADDRINFO_socktype(c->addr_iter),
224                              BIO_ADDRINFO_protocol(c->addr_iter), 0);
225             if (ret == (int)INVALID_SOCKET) {
226                 SYSerr(SYS_F_SOCKET, get_last_socket_error());
227                 ERR_add_error_data(4,
228                                    "hostname=", c->param_addr,
229                                    " service=", c->param_serv);
230                 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
231                 goto exit_loop;
232             }
233             c->accept_sock = ret;
234             b->num = ret;
235             c->state = ACPT_S_LISTEN;
236             break;
237
238         case ACPT_S_LISTEN:
239             {
240                 if (!BIO_listen(c->accept_sock,
241                                 BIO_ADDRINFO_address(c->addr_iter),
242                                 c->bind_mode)) {
243                     BIO_closesocket(c->accept_sock);
244                     goto exit_loop;
245                 }
246             }
247
248             {
249                 union BIO_sock_info_u info;
250
251                 info.addr = &c->cache_accepting_addr;
252                 if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
253                                    &info)) {
254                     BIO_closesocket(c->accept_sock);
255                     goto exit_loop;
256                 }
257             }
258
259             c->cache_accepting_name =
260                 BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
261             c->cache_accepting_serv =
262                 BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
263             c->state = ACPT_S_ACCEPT;
264             s = -1;
265             ret = 1;
266             goto end;
267
268         case ACPT_S_ACCEPT:
269             if (b->next_bio != NULL) {
270                 c->state = ACPT_S_OK;
271                 break;
272             }
273             BIO_clear_retry_flags(b);
274             b->retry_reason = 0;
275
276             s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
277                               c->accepted_mode);
278
279             /* If the returned socket is invalid, this might still be
280              * retryable
281              */
282             if (s < 0) {
283                 if (BIO_sock_should_retry(s)) {
284                     BIO_set_retry_special(b);
285                     b->retry_reason = BIO_RR_ACCEPT;
286                     goto end;
287                 }
288             }
289
290             /* If it wasn't retryable, we fail */
291             if (s < 0) {
292                 ret = s;
293                 goto exit_loop;
294             }
295
296             bio = BIO_new_socket(s, BIO_CLOSE);
297             if (bio == NULL)
298                 goto exit_loop;
299
300             BIO_set_callback(bio, BIO_get_callback(b));
301             BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
302
303             /*
304              * If the accept BIO has an bio_chain, we dup it and put the new
305              * socket at the end.
306              */
307             if (c->bio_chain != NULL) {
308                 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
309                     goto exit_loop;
310                 if (!BIO_push(dbio, bio))
311                     goto exit_loop;
312                 bio = dbio;
313             }
314             if (BIO_push(b, bio) == NULL)
315                 goto exit_loop;
316
317             c->cache_peer_name =
318                 BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
319             c->cache_peer_serv =
320                 BIO_ADDR_service_string(&c->cache_peer_addr, 1);
321             c->state = ACPT_S_OK;
322             bio = NULL;
323             ret = 1;
324             goto end;
325
326         case ACPT_S_OK:
327             if (b->next_bio == NULL) {
328                 c->state = ACPT_S_ACCEPT;
329                 break;
330             }
331             ret = 1;
332             goto end;
333
334         default:
335             ret = 0;
336             goto end;
337         }
338     }
339
340   exit_loop:
341     if (bio != NULL)
342         BIO_free(bio);
343     else if (s >= 0)
344         BIO_closesocket(s);
345   end:
346     return ret;
347 }
348
349 static int acpt_read(BIO *b, char *out, int outl)
350 {
351     int ret = 0;
352     BIO_ACCEPT *data;
353
354     BIO_clear_retry_flags(b);
355     data = (BIO_ACCEPT *)b->ptr;
356
357     while (b->next_bio == NULL) {
358         ret = acpt_state(b, data);
359         if (ret <= 0)
360             return (ret);
361     }
362
363     ret = BIO_read(b->next_bio, out, outl);
364     BIO_copy_next_retry(b);
365     return (ret);
366 }
367
368 static int acpt_write(BIO *b, const char *in, int inl)
369 {
370     int ret;
371     BIO_ACCEPT *data;
372
373     BIO_clear_retry_flags(b);
374     data = (BIO_ACCEPT *)b->ptr;
375
376     while (b->next_bio == NULL) {
377         ret = acpt_state(b, data);
378         if (ret <= 0)
379             return (ret);
380     }
381
382     ret = BIO_write(b->next_bio, in, inl);
383     BIO_copy_next_retry(b);
384     return (ret);
385 }
386
387 static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
388 {
389     int *ip;
390     long ret = 1;
391     BIO_ACCEPT *data;
392     char **pp;
393
394     data = (BIO_ACCEPT *)b->ptr;
395
396     switch (cmd) {
397     case BIO_CTRL_RESET:
398         ret = 0;
399         data->state = ACPT_S_BEFORE;
400         acpt_close_socket(b);
401         BIO_ADDRINFO_free(data->addr_first);
402         data->addr_first = NULL;
403         b->flags = 0;
404         break;
405     case BIO_C_DO_STATE_MACHINE:
406         /* use this one to start the connection */
407         ret = (long)acpt_state(b, data);
408         break;
409     case BIO_C_SET_ACCEPT:
410         if (ptr != NULL) {
411             if (num == 0) {
412                 char *hold_serv = data->param_serv;
413                 /* We affect the hostname regardless.  However, the input
414                  * string might contain a host:service spec, so we must
415                  * parse it, which might or might not affect the service
416                  */
417                 OPENSSL_free(data->param_addr);
418                 data->param_addr = NULL;
419                 ret = BIO_parse_hostserv(ptr,
420                                          &data->param_addr,
421                                          &data->param_serv,
422                                          BIO_PARSE_PRIO_SERV);
423                 if (hold_serv != data->param_serv)
424                     OPENSSL_free(hold_serv);
425                 b->init = 1;
426             } else if (num == 1) {
427                 OPENSSL_free(data->param_serv);
428                 data->param_serv = BUF_strdup(ptr);
429                 b->init = 1;
430             } else if (num == 2) {
431                 data->bind_mode |= BIO_SOCK_NONBLOCK;
432             } else if (num == 3) {
433                 BIO_free(data->bio_chain);
434                 data->bio_chain = (BIO *)ptr;
435             } else if (num == 4) {
436                 data->accept_family = *(int *)ptr;
437             }
438         } else {
439             if (num == 2) {
440                 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
441             }
442         }
443         break;
444     case BIO_C_SET_NBIO:
445         if (num != 0)
446             data->accepted_mode |= BIO_SOCK_NONBLOCK;
447         else
448             data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
449         break;
450     case BIO_C_SET_FD:
451         b->init = 1;
452         b->num = *((int *)ptr);
453         data->accept_sock = b->num;
454         data->state = ACPT_S_ACCEPT;
455         b->shutdown = (int)num;
456         b->init = 1;
457         break;
458     case BIO_C_GET_FD:
459         if (b->init) {
460             ip = (int *)ptr;
461             if (ip != NULL)
462                 *ip = data->accept_sock;
463             ret = data->accept_sock;
464         } else
465             ret = -1;
466         break;
467     case BIO_C_GET_ACCEPT:
468         if (b->init) {
469             if (num == 0 && ptr != NULL) {
470                 pp = (char **)ptr;
471                 *pp = data->cache_accepting_name;
472             } else if (num == 1 && ptr != NULL) {
473                 pp = (char **)ptr;
474                 *pp = data->cache_accepting_serv;
475             } else if (num == 2 && ptr != NULL) {
476                 pp = (char **)ptr;
477                 *pp = data->cache_peer_name;
478             } else if (num == 3 && ptr != NULL) {
479                 pp = (char **)ptr;
480                 *pp = data->cache_peer_serv;
481             } else if (num == 4) {
482                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
483 #ifdef AF_INET6
484                 case AF_INET6:
485                     ret = BIO_FAMILY_IPV6;
486                     break;
487 #endif
488                 case AF_INET:
489                     ret = BIO_FAMILY_IPV4;
490                     break;
491                 case 0:
492                     ret = data->accept_family;
493                     break;
494                 default:
495                     ret = -1;
496                     break;
497                 }
498             } else
499                 ret = -1;
500         } else
501             ret = -1;
502         break;
503     case BIO_CTRL_GET_CLOSE:
504         ret = b->shutdown;
505         break;
506     case BIO_CTRL_SET_CLOSE:
507         b->shutdown = (int)num;
508         break;
509     case BIO_CTRL_PENDING:
510     case BIO_CTRL_WPENDING:
511         ret = 0;
512         break;
513     case BIO_CTRL_FLUSH:
514         break;
515     case BIO_C_SET_BIND_MODE:
516         data->bind_mode = (int)num;
517         break;
518     case BIO_C_GET_BIND_MODE:
519         ret = (long)data->bind_mode;
520         break;
521     case BIO_CTRL_DUP:
522 /*-     dbio=(BIO *)ptr;
523         if (data->param_port) EAY EAY
524                 BIO_set_port(dbio,data->param_port);
525         if (data->param_hostname)
526                 BIO_set_hostname(dbio,data->param_hostname);
527         BIO_set_nbio(dbio,data->nbio); */
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