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