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