]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssl/crypto/bio/bss_conn.c
Merge OpenSSL 1.1.1h.
[FreeBSD/FreeBSD.git] / crypto / openssl / crypto / bio / bss_conn.c
1 /*
2  * Copyright 1995-2020 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
13 #include "bio_local.h"
14
15 #ifndef OPENSSL_NO_SOCK
16
17 typedef struct bio_connect_st {
18     int state;
19     int connect_family;
20     char *param_hostname;
21     char *param_service;
22     int connect_mode;
23
24     BIO_ADDRINFO *addr_first;
25     const BIO_ADDRINFO *addr_iter;
26     /*
27      * int socket; this will be kept in bio->num so that it is compatible
28      * with the bss_sock bio
29      */
30     /*
31      * called when the connection is initially made callback(BIO,state,ret);
32      * The callback should return 'ret'.  state is for compatibility with the
33      * ssl info_callback
34      */
35     BIO_info_cb *info_callback;
36 } BIO_CONNECT;
37
38 static int conn_write(BIO *h, const char *buf, int num);
39 static int conn_read(BIO *h, char *buf, int size);
40 static int conn_puts(BIO *h, const char *str);
41 static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
42 static int conn_new(BIO *h);
43 static int conn_free(BIO *data);
44 static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
45
46 static int conn_state(BIO *b, BIO_CONNECT *c);
47 static void conn_close_socket(BIO *data);
48 BIO_CONNECT *BIO_CONNECT_new(void);
49 void BIO_CONNECT_free(BIO_CONNECT *a);
50
51 #define BIO_CONN_S_BEFORE                1
52 #define BIO_CONN_S_GET_ADDR              2
53 #define BIO_CONN_S_CREATE_SOCKET         3
54 #define BIO_CONN_S_CONNECT               4
55 #define BIO_CONN_S_OK                    5
56 #define BIO_CONN_S_BLOCKED_CONNECT       6
57 #define BIO_CONN_S_CONNECT_ERROR         7
58
59 static const BIO_METHOD methods_connectp = {
60     BIO_TYPE_CONNECT,
61     "socket connect",
62     /* TODO: Convert to new style write function */
63     bwrite_conv,
64     conn_write,
65     /* TODO: Convert to new style read function */
66     bread_conv,
67     conn_read,
68     conn_puts,
69     NULL,                       /* conn_gets, */
70     conn_ctrl,
71     conn_new,
72     conn_free,
73     conn_callback_ctrl,
74 };
75
76 static int conn_state(BIO *b, BIO_CONNECT *c)
77 {
78     int ret = -1, i;
79     BIO_info_cb *cb = NULL;
80
81     if (c->info_callback != NULL)
82         cb = c->info_callback;
83
84     for (;;) {
85         switch (c->state) {
86         case BIO_CONN_S_BEFORE:
87             if (c->param_hostname == NULL && c->param_service == NULL) {
88                 BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED);
89                 ERR_add_error_data(4,
90                                    "hostname=", c->param_hostname,
91                                    " service=", c->param_service);
92                 goto exit_loop;
93             }
94             c->state = BIO_CONN_S_GET_ADDR;
95             break;
96
97         case BIO_CONN_S_GET_ADDR:
98             {
99                 int family = AF_UNSPEC;
100                 switch (c->connect_family) {
101                 case BIO_FAMILY_IPV6:
102                     if (1) { /* This is a trick we use to avoid bit rot.
103                               * at least the "else" part will always be
104                               * compiled.
105                               */
106 #ifdef AF_INET6
107                         family = AF_INET6;
108                     } else {
109 #endif
110                         BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
111                         goto exit_loop;
112                     }
113                     break;
114                 case BIO_FAMILY_IPV4:
115                     family = AF_INET;
116                     break;
117                 case BIO_FAMILY_IPANY:
118                     family = AF_UNSPEC;
119                     break;
120                 default:
121                     BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
122                     goto exit_loop;
123                 }
124                 if (BIO_lookup(c->param_hostname, c->param_service,
125                                BIO_LOOKUP_CLIENT,
126                                family, SOCK_STREAM, &c->addr_first) == 0)
127                     goto exit_loop;
128             }
129             if (c->addr_first == NULL) {
130                 BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
131                 goto exit_loop;
132             }
133             c->addr_iter = c->addr_first;
134             c->state = BIO_CONN_S_CREATE_SOCKET;
135             break;
136
137         case BIO_CONN_S_CREATE_SOCKET:
138             ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
139                              BIO_ADDRINFO_socktype(c->addr_iter),
140                              BIO_ADDRINFO_protocol(c->addr_iter), 0);
141             if (ret == (int)INVALID_SOCKET) {
142                 SYSerr(SYS_F_SOCKET, get_last_socket_error());
143                 ERR_add_error_data(4,
144                                    "hostname=", c->param_hostname,
145                                    " service=", c->param_service);
146                 BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
147                 goto exit_loop;
148             }
149             b->num = ret;
150             c->state = BIO_CONN_S_CONNECT;
151             break;
152
153         case BIO_CONN_S_CONNECT:
154             BIO_clear_retry_flags(b);
155             ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
156                               BIO_SOCK_KEEPALIVE | c->connect_mode);
157             b->retry_reason = 0;
158             if (ret == 0) {
159                 if (BIO_sock_should_retry(ret)) {
160                     BIO_set_retry_special(b);
161                     c->state = BIO_CONN_S_BLOCKED_CONNECT;
162                     b->retry_reason = BIO_RR_CONNECT;
163                     ERR_clear_error();
164                 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
165                            != NULL) {
166                     /*
167                      * if there are more addresses to try, do that first
168                      */
169                     BIO_closesocket(b->num);
170                     c->state = BIO_CONN_S_CREATE_SOCKET;
171                     ERR_clear_error();
172                     break;
173                 } else {
174                     SYSerr(SYS_F_CONNECT, get_last_socket_error());
175                     ERR_add_error_data(4,
176                                        "hostname=", c->param_hostname,
177                                        " service=", c->param_service);
178                     c->state = BIO_CONN_S_CONNECT_ERROR;
179                     break;
180                 }
181                 goto exit_loop;
182             } else {
183                 c->state = BIO_CONN_S_OK;
184             }
185             break;
186
187         case BIO_CONN_S_BLOCKED_CONNECT:
188             i = BIO_sock_error(b->num);
189             if (i != 0) {
190                 BIO_clear_retry_flags(b);
191                 if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
192                     /*
193                      * if there are more addresses to try, do that first
194                      */
195                     BIO_closesocket(b->num);
196                     c->state = BIO_CONN_S_CREATE_SOCKET;
197                     ERR_clear_error();
198                     break;
199                 }
200                 SYSerr(SYS_F_CONNECT, i);
201                 ERR_add_error_data(4,
202                                    "hostname=", c->param_hostname,
203                                    " service=", c->param_service);
204                 BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
205                 ret = 0;
206                 goto exit_loop;
207             } else
208                 c->state = BIO_CONN_S_OK;
209             break;
210
211         case BIO_CONN_S_CONNECT_ERROR:
212             BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
213             ret = 0;
214             goto exit_loop;
215
216         case BIO_CONN_S_OK:
217             ret = 1;
218             goto exit_loop;
219         default:
220             /* abort(); */
221             goto exit_loop;
222         }
223
224         if (cb != NULL) {
225             if ((ret = cb((BIO *)b, c->state, ret)) == 0)
226                 goto end;
227         }
228     }
229
230     /* Loop does not exit */
231  exit_loop:
232     if (cb != NULL)
233         ret = cb((BIO *)b, c->state, ret);
234  end:
235     return ret;
236 }
237
238 BIO_CONNECT *BIO_CONNECT_new(void)
239 {
240     BIO_CONNECT *ret;
241
242     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
243         BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
244         return NULL;
245     }
246     ret->state = BIO_CONN_S_BEFORE;
247     ret->connect_family = BIO_FAMILY_IPANY;
248     return ret;
249 }
250
251 void BIO_CONNECT_free(BIO_CONNECT *a)
252 {
253     if (a == NULL)
254         return;
255     OPENSSL_free(a->param_hostname);
256     OPENSSL_free(a->param_service);
257     BIO_ADDRINFO_free(a->addr_first);
258     OPENSSL_free(a);
259 }
260
261 const BIO_METHOD *BIO_s_connect(void)
262 {
263     return &methods_connectp;
264 }
265
266 static int conn_new(BIO *bi)
267 {
268     bi->init = 0;
269     bi->num = (int)INVALID_SOCKET;
270     bi->flags = 0;
271     if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
272         return 0;
273     else
274         return 1;
275 }
276
277 static void conn_close_socket(BIO *bio)
278 {
279     BIO_CONNECT *c;
280
281     c = (BIO_CONNECT *)bio->ptr;
282     if (bio->num != (int)INVALID_SOCKET) {
283         /* Only do a shutdown if things were established */
284         if (c->state == BIO_CONN_S_OK)
285             shutdown(bio->num, 2);
286         BIO_closesocket(bio->num);
287         bio->num = (int)INVALID_SOCKET;
288     }
289 }
290
291 static int conn_free(BIO *a)
292 {
293     BIO_CONNECT *data;
294
295     if (a == NULL)
296         return 0;
297     data = (BIO_CONNECT *)a->ptr;
298
299     if (a->shutdown) {
300         conn_close_socket(a);
301         BIO_CONNECT_free(data);
302         a->ptr = NULL;
303         a->flags = 0;
304         a->init = 0;
305     }
306     return 1;
307 }
308
309 static int conn_read(BIO *b, char *out, int outl)
310 {
311     int ret = 0;
312     BIO_CONNECT *data;
313
314     data = (BIO_CONNECT *)b->ptr;
315     if (data->state != BIO_CONN_S_OK) {
316         ret = conn_state(b, data);
317         if (ret <= 0)
318             return ret;
319     }
320
321     if (out != NULL) {
322         clear_socket_error();
323         ret = readsocket(b->num, out, outl);
324         BIO_clear_retry_flags(b);
325         if (ret <= 0) {
326             if (BIO_sock_should_retry(ret))
327                 BIO_set_retry_read(b);
328             else if (ret == 0)
329                 b->flags |= BIO_FLAGS_IN_EOF;
330         }
331     }
332     return ret;
333 }
334
335 static int conn_write(BIO *b, const char *in, int inl)
336 {
337     int ret;
338     BIO_CONNECT *data;
339
340     data = (BIO_CONNECT *)b->ptr;
341     if (data->state != BIO_CONN_S_OK) {
342         ret = conn_state(b, data);
343         if (ret <= 0)
344             return ret;
345     }
346
347     clear_socket_error();
348     ret = writesocket(b->num, in, inl);
349     BIO_clear_retry_flags(b);
350     if (ret <= 0) {
351         if (BIO_sock_should_retry(ret))
352             BIO_set_retry_write(b);
353     }
354     return ret;
355 }
356
357 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
358 {
359     BIO *dbio;
360     int *ip;
361     const char **pptr = NULL;
362     long ret = 1;
363     BIO_CONNECT *data;
364
365     data = (BIO_CONNECT *)b->ptr;
366
367     switch (cmd) {
368     case BIO_CTRL_RESET:
369         ret = 0;
370         data->state = BIO_CONN_S_BEFORE;
371         conn_close_socket(b);
372         BIO_ADDRINFO_free(data->addr_first);
373         data->addr_first = NULL;
374         b->flags = 0;
375         break;
376     case BIO_C_DO_STATE_MACHINE:
377         /* use this one to start the connection */
378         if (data->state != BIO_CONN_S_OK)
379             ret = (long)conn_state(b, data);
380         else
381             ret = 1;
382         break;
383     case BIO_C_GET_CONNECT:
384         if (ptr != NULL) {
385             pptr = (const char **)ptr;
386             if (num == 0) {
387                 *pptr = data->param_hostname;
388             } else if (num == 1) {
389                 *pptr = data->param_service;
390             } else if (num == 2) {
391                 *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
392             } else if (num == 3) {
393                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
394 # ifdef AF_INET6
395                 case AF_INET6:
396                     ret = BIO_FAMILY_IPV6;
397                     break;
398 # endif
399                 case AF_INET:
400                     ret = BIO_FAMILY_IPV4;
401                     break;
402                 case 0:
403                     ret = data->connect_family;
404                     break;
405                 default:
406                     ret = -1;
407                     break;
408                 }
409             } else {
410                 ret = 0;
411             }
412         } else {
413             ret = 0;
414         }
415         break;
416     case BIO_C_SET_CONNECT:
417         if (ptr != NULL) {
418             b->init = 1;
419             if (num == 0) { /* BIO_set_conn_hostname */
420                 char *hold_service = data->param_service;
421                 /* We affect the hostname regardless.  However, the input
422                  * string might contain a host:service spec, so we must
423                  * parse it, which might or might not affect the service
424                  */
425
426                 OPENSSL_free(data->param_hostname);
427                 data->param_hostname = NULL;
428                 ret = BIO_parse_hostserv(ptr,
429                                          &data->param_hostname,
430                                          &data->param_service,
431                                          BIO_PARSE_PRIO_HOST);
432                 if (hold_service != data->param_service)
433                     OPENSSL_free(hold_service);
434             } else if (num == 1) { /* BIO_set_conn_port */
435                 OPENSSL_free(data->param_service);
436                 if ((data->param_service = OPENSSL_strdup(ptr)) == NULL)
437                     ret = 0;
438             } else if (num == 2) { /* BIO_set_conn_address */
439                 const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
440                 char *host = BIO_ADDR_hostname_string(addr, 1);
441                 char *service = BIO_ADDR_service_string(addr, 1);
442
443                 ret = host != NULL && service != NULL;
444                 if (ret) {
445                     OPENSSL_free(data->param_hostname);
446                     data->param_hostname = host;
447                     OPENSSL_free(data->param_service);
448                     data->param_service = service;
449                     BIO_ADDRINFO_free(data->addr_first);
450                     data->addr_first = NULL;
451                     data->addr_iter = NULL;
452                 } else {
453                     OPENSSL_free(host);
454                     OPENSSL_free(service);
455                 }
456             } else if (num == 3) { /* BIO_set_conn_ip_family */
457                 data->connect_family = *(int *)ptr;
458             } else {
459                 ret = 0;
460             }
461         }
462         break;
463     case BIO_C_SET_NBIO:
464         if (num != 0)
465             data->connect_mode |= BIO_SOCK_NONBLOCK;
466         else
467             data->connect_mode &= ~BIO_SOCK_NONBLOCK;
468         break;
469     case BIO_C_SET_CONNECT_MODE:
470         data->connect_mode = (int)num;
471         break;
472     case BIO_C_GET_FD:
473         if (b->init) {
474             ip = (int *)ptr;
475             if (ip != NULL)
476                 *ip = b->num;
477             ret = b->num;
478         } else
479             ret = -1;
480         break;
481     case BIO_CTRL_GET_CLOSE:
482         ret = b->shutdown;
483         break;
484     case BIO_CTRL_SET_CLOSE:
485         b->shutdown = (int)num;
486         break;
487     case BIO_CTRL_PENDING:
488     case BIO_CTRL_WPENDING:
489         ret = 0;
490         break;
491     case BIO_CTRL_FLUSH:
492         break;
493     case BIO_CTRL_DUP:
494         {
495             dbio = (BIO *)ptr;
496             if (data->param_hostname)
497                 BIO_set_conn_hostname(dbio, data->param_hostname);
498             if (data->param_service)
499                 BIO_set_conn_port(dbio, data->param_service);
500             BIO_set_conn_ip_family(dbio, data->connect_family);
501             BIO_set_conn_mode(dbio, data->connect_mode);
502             /*
503              * FIXME: the cast of the function seems unlikely to be a good
504              * idea
505              */
506             (void)BIO_set_info_callback(dbio, data->info_callback);
507         }
508         break;
509     case BIO_CTRL_SET_CALLBACK:
510         ret = 0; /* use callback ctrl */
511         break;
512     case BIO_CTRL_GET_CALLBACK:
513         {
514             BIO_info_cb **fptr;
515
516             fptr = (BIO_info_cb **)ptr;
517             *fptr = data->info_callback;
518         }
519         break;
520     case BIO_CTRL_EOF:
521         ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
522         break;
523     default:
524         ret = 0;
525         break;
526     }
527     return ret;
528 }
529
530 static long conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
531 {
532     long ret = 1;
533     BIO_CONNECT *data;
534
535     data = (BIO_CONNECT *)b->ptr;
536
537     switch (cmd) {
538     case BIO_CTRL_SET_CALLBACK:
539         {
540             data->info_callback = fp;
541         }
542         break;
543     default:
544         ret = 0;
545         break;
546     }
547     return ret;
548 }
549
550 static int conn_puts(BIO *bp, const char *str)
551 {
552     int n, ret;
553
554     n = strlen(str);
555     ret = conn_write(bp, str, n);
556     return ret;
557 }
558
559 BIO *BIO_new_connect(const char *str)
560 {
561     BIO *ret;
562
563     ret = BIO_new(BIO_s_connect());
564     if (ret == NULL)
565         return NULL;
566     if (BIO_set_conn_hostname(ret, str))
567         return ret;
568     BIO_free(ret);
569     return NULL;
570 }
571
572 #endif