]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/bss_conn.c
Make BIO_do_connect() and friends handle multiple IP addresses
[thirdparty/openssl.git] / crypto / bio / bss_conn.c
CommitLineData
b1322259 1/*
33388b44 2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
d02b48c6 3 *
09abbca1 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
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
d02b48c6
RE
8 */
9
d02b48c6
RE
10#include <stdio.h>
11#include <errno.h>
d02b48c6 12
706457b7 13#include "bio_local.h"
b1f79e7c 14#include "internal/ktls.h"
b00b2124 15
417be660 16#ifndef OPENSSL_NO_SOCK
0f113f3e
MC
17
18typedef struct bio_connect_st {
19 int state;
417be660 20 int connect_family;
0f113f3e 21 char *param_hostname;
417be660
RL
22 char *param_service;
23 int connect_mode;
b1f79e7c
JB
24# ifndef OPENSSL_NO_KTLS
25 unsigned char record_type;
26# endif
417be660
RL
27
28 BIO_ADDRINFO *addr_first;
29 const BIO_ADDRINFO *addr_iter;
0f113f3e
MC
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 */
fce78bd4 39 BIO_info_cb *info_callback;
0f113f3e 40} BIO_CONNECT;
d02b48c6 41
0e1c0612
UM
42static int conn_write(BIO *h, const char *buf, int num);
43static int conn_read(BIO *h, char *buf, int size);
44static int conn_puts(BIO *h, const char *str);
45static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
d02b48c6
RE
46static int conn_new(BIO *h);
47static int conn_free(BIO *data);
fce78bd4 48static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
d02b48c6
RE
49
50static int conn_state(BIO *b, BIO_CONNECT *c);
51static void conn_close_socket(BIO *data);
0f113f3e 52BIO_CONNECT *BIO_CONNECT_new(void);
d02b48c6
RE
53void BIO_CONNECT_free(BIO_CONNECT *a);
54
417be660
RL
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
181f5185 61#define BIO_CONN_S_CONNECT_ERROR 7
417be660 62
04f6b0fd 63static const BIO_METHOD methods_connectp = {
0f113f3e
MC
64 BIO_TYPE_CONNECT,
65 "socket connect",
3befffa3
MC
66 /* TODO: Convert to new style write function */
67 bwrite_conv,
0f113f3e 68 conn_write,
d07aee2c
MC
69 /* TODO: Convert to new style read function */
70 bread_conv,
0f113f3e
MC
71 conn_read,
72 conn_puts,
b4ff6622 73 NULL, /* conn_gets, */
0f113f3e
MC
74 conn_ctrl,
75 conn_new,
76 conn_free,
77 conn_callback_ctrl,
78};
d02b48c6 79
6b691a5c 80static int conn_state(BIO *b, BIO_CONNECT *c)
0f113f3e
MC
81{
82 int ret = -1, i;
fce78bd4 83 BIO_info_cb *cb = NULL;
0f113f3e
MC
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:
417be660
RL
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);
0f113f3e
MC
96 goto exit_loop;
97 }
417be660
RL
98 c->state = BIO_CONN_S_GET_ADDR;
99 break;
0f113f3e 100
417be660
RL
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;
0f113f3e 127 }
417be660
RL
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;
0f113f3e 132 }
417be660
RL
133 if (c->addr_first == NULL) {
134 BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
0f113f3e
MC
135 goto exit_loop;
136 }
417be660 137 c->addr_iter = c->addr_first;
0f113f3e
MC
138 c->state = BIO_CONN_S_CREATE_SOCKET;
139 break;
140
141 case BIO_CONN_S_CREATE_SOCKET:
417be660
RL
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);
b13fdc48 145 if (ret == (int)INVALID_SOCKET) {
ff988500
RS
146 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
147 "calling socket(%s, %s)",
148 c->param_hostname, c->param_service);
0f113f3e
MC
149 BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
150 goto exit_loop;
151 }
152 b->num = ret;
0f113f3e 153 c->state = BIO_CONN_S_CONNECT;
0f113f3e
MC
154 break;
155
156 case BIO_CONN_S_CONNECT:
157 BIO_clear_retry_flags(b);
417be660
RL
158 ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
159 BIO_SOCK_KEEPALIVE | c->connect_mode);
0f113f3e 160 b->retry_reason = 0;
a043d0b9 161 if (ret == 0) {
0f113f3e
MC
162 if (BIO_sock_should_retry(ret)) {
163 BIO_set_retry_special(b);
164 c->state = BIO_CONN_S_BLOCKED_CONNECT;
165 b->retry_reason = BIO_RR_CONNECT;
417be660
RL
166 ERR_clear_error();
167 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
168 != NULL) {
169 /*
170 * if there are more addresses to try, do that first
171 */
172 BIO_closesocket(b->num);
173 c->state = BIO_CONN_S_CREATE_SOCKET;
174 ERR_clear_error();
175 break;
0f113f3e 176 } else {
ff988500
RS
177 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
178 "calling connect(%s, %s)",
179 c->param_hostname, c->param_service);
181f5185
RL
180 c->state = BIO_CONN_S_CONNECT_ERROR;
181 break;
0f113f3e
MC
182 }
183 goto exit_loop;
417be660 184 } else {
0f113f3e 185 c->state = BIO_CONN_S_OK;
417be660 186 }
0f113f3e
MC
187 break;
188
189 case BIO_CONN_S_BLOCKED_CONNECT:
190 i = BIO_sock_error(b->num);
dc18e4dd 191 if (i != 0) {
0f113f3e 192 BIO_clear_retry_flags(b);
dc18e4dd
DDO
193 if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) {
194 /*
195 * if there are more addresses to try, do that first
196 */
197 BIO_closesocket(b->num);
198 c->state = BIO_CONN_S_CREATE_SOCKET;
199 ERR_clear_error();
200 break;
201 }
ff988500
RS
202 ERR_raise_data(ERR_LIB_SYS, i,
203 "calling connect(%s, %s)",
204 c->param_hostname, c->param_service);
0f113f3e
MC
205 BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
206 ret = 0;
207 goto exit_loop;
208 } else
209 c->state = BIO_CONN_S_OK;
210 break;
211
181f5185
RL
212 case BIO_CONN_S_CONNECT_ERROR:
213 BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
214 ret = 0;
215 goto exit_loop;
216
0f113f3e
MC
217 case BIO_CONN_S_OK:
218 ret = 1;
219 goto exit_loop;
220 default:
221 /* abort(); */
222 goto exit_loop;
223 }
224
225 if (cb != NULL) {
75ebbd9a 226 if ((ret = cb((BIO *)b, c->state, ret)) == 0)
0f113f3e
MC
227 goto end;
228 }
229 }
230
231 /* Loop does not exit */
232 exit_loop:
233 if (cb != NULL)
234 ret = cb((BIO *)b, c->state, ret);
235 end:
26a7d938 236 return ret;
0f113f3e 237}
d02b48c6 238
6b691a5c 239BIO_CONNECT *BIO_CONNECT_new(void)
0f113f3e
MC
240{
241 BIO_CONNECT *ret;
242
f06080cb
F
243 if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
244 BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
26a7d938 245 return NULL;
f06080cb 246 }
0f113f3e 247 ret->state = BIO_CONN_S_BEFORE;
417be660 248 ret->connect_family = BIO_FAMILY_IPANY;
26a7d938 249 return ret;
0f113f3e 250}
d02b48c6 251
6b691a5c 252void BIO_CONNECT_free(BIO_CONNECT *a)
0f113f3e 253{
e6e9170d
RS
254 if (a == NULL)
255 return;
b548a1f1 256 OPENSSL_free(a->param_hostname);
417be660
RL
257 OPENSSL_free(a->param_service);
258 BIO_ADDRINFO_free(a->addr_first);
0f113f3e
MC
259 OPENSSL_free(a);
260}
d02b48c6 261
04f6b0fd 262const BIO_METHOD *BIO_s_connect(void)
0f113f3e 263{
26a7d938 264 return &methods_connectp;
0f113f3e 265}
d02b48c6 266
6b691a5c 267static int conn_new(BIO *bi)
0f113f3e
MC
268{
269 bi->init = 0;
b13fdc48 270 bi->num = (int)INVALID_SOCKET;
0f113f3e
MC
271 bi->flags = 0;
272 if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
26a7d938 273 return 0;
0f113f3e 274 else
208fb891 275 return 1;
0f113f3e 276}
d02b48c6 277
6b691a5c 278static void conn_close_socket(BIO *bio)
0f113f3e
MC
279{
280 BIO_CONNECT *c;
281
282 c = (BIO_CONNECT *)bio->ptr;
b13fdc48 283 if (bio->num != (int)INVALID_SOCKET) {
0f113f3e
MC
284 /* Only do a shutdown if things were established */
285 if (c->state == BIO_CONN_S_OK)
286 shutdown(bio->num, 2);
417be660 287 BIO_closesocket(bio->num);
b13fdc48 288 bio->num = (int)INVALID_SOCKET;
0f113f3e
MC
289 }
290}
d02b48c6 291
6b691a5c 292static int conn_free(BIO *a)
0f113f3e
MC
293{
294 BIO_CONNECT *data;
295
296 if (a == NULL)
26a7d938 297 return 0;
0f113f3e
MC
298 data = (BIO_CONNECT *)a->ptr;
299
300 if (a->shutdown) {
301 conn_close_socket(a);
302 BIO_CONNECT_free(data);
303 a->ptr = NULL;
304 a->flags = 0;
305 a->init = 0;
306 }
208fb891 307 return 1;
0f113f3e
MC
308}
309
6b691a5c 310static int conn_read(BIO *b, char *out, int outl)
0f113f3e
MC
311{
312 int ret = 0;
313 BIO_CONNECT *data;
314
315 data = (BIO_CONNECT *)b->ptr;
316 if (data->state != BIO_CONN_S_OK) {
317 ret = conn_state(b, data);
318 if (ret <= 0)
26a7d938 319 return ret;
0f113f3e
MC
320 }
321
322 if (out != NULL) {
323 clear_socket_error();
b1f79e7c
JB
324# ifndef OPENSSL_NO_KTLS
325 if (BIO_get_ktls_recv(b))
326 ret = ktls_read_record(b->num, out, outl);
327 else
328# endif
329 ret = readsocket(b->num, out, outl);
0f113f3e
MC
330 BIO_clear_retry_flags(b);
331 if (ret <= 0) {
332 if (BIO_sock_should_retry(ret))
333 BIO_set_retry_read(b);
6d53ad6b
MC
334 else if (ret == 0)
335 b->flags |= BIO_FLAGS_IN_EOF;
0f113f3e
MC
336 }
337 }
26a7d938 338 return ret;
0f113f3e 339}
d02b48c6 340
0e1c0612 341static int conn_write(BIO *b, const char *in, int inl)
0f113f3e
MC
342{
343 int ret;
344 BIO_CONNECT *data;
345
346 data = (BIO_CONNECT *)b->ptr;
347 if (data->state != BIO_CONN_S_OK) {
348 ret = conn_state(b, data);
349 if (ret <= 0)
26a7d938 350 return ret;
0f113f3e
MC
351 }
352
353 clear_socket_error();
b1f79e7c
JB
354# ifndef OPENSSL_NO_KTLS
355 if (BIO_should_ktls_ctrl_msg_flag(b)) {
356 ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl);
357 if (ret >= 0) {
358 ret = inl;
359 BIO_clear_ktls_ctrl_msg_flag(b);
360 }
361 } else
362# endif
363 ret = writesocket(b->num, in, inl);
0f113f3e
MC
364 BIO_clear_retry_flags(b);
365 if (ret <= 0) {
366 if (BIO_sock_should_retry(ret))
367 BIO_set_retry_write(b);
368 }
26a7d938 369 return ret;
0f113f3e 370}
d02b48c6 371
0e1c0612 372static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
0f113f3e
MC
373{
374 BIO *dbio;
375 int *ip;
4b72d5f8 376 const char **pptr = NULL;
0f113f3e
MC
377 long ret = 1;
378 BIO_CONNECT *data;
b1f79e7c
JB
379# ifndef OPENSSL_NO_KTLS
380# ifdef __FreeBSD__
381 struct tls_enable *crypto_info;
382# else
383 struct tls12_crypto_info_aes_gcm_128 *crypto_info;
384# endif
385# endif
0f113f3e
MC
386
387 data = (BIO_CONNECT *)b->ptr;
388
389 switch (cmd) {
390 case BIO_CTRL_RESET:
391 ret = 0;
392 data->state = BIO_CONN_S_BEFORE;
393 conn_close_socket(b);
417be660
RL
394 BIO_ADDRINFO_free(data->addr_first);
395 data->addr_first = NULL;
0f113f3e
MC
396 b->flags = 0;
397 break;
398 case BIO_C_DO_STATE_MACHINE:
399 /* use this one to start the connection */
400 if (data->state != BIO_CONN_S_OK)
401 ret = (long)conn_state(b, data);
402 else
403 ret = 1;
404 break;
405 case BIO_C_GET_CONNECT:
406 if (ptr != NULL) {
407 pptr = (const char **)ptr;
417be660
RL
408 if (num == 0) {
409 *pptr = data->param_hostname;
410 } else if (num == 1) {
411 *pptr = data->param_service;
412 } else if (num == 2) {
413 *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
414 } else if (num == 3) {
415 switch (BIO_ADDRINFO_family(data->addr_iter)) {
416# ifdef AF_INET6
417 case AF_INET6:
418 ret = BIO_FAMILY_IPV6;
419 break;
420# endif
421 case AF_INET:
422 ret = BIO_FAMILY_IPV4;
423 break;
424 case 0:
425 ret = data->connect_family;
426 break;
427 default:
428 ret = -1;
429 break;
4b72d5f8 430 }
417be660
RL
431 } else {
432 ret = 0;
4b72d5f8
RL
433 }
434 } else {
4b72d5f8 435 ret = 0;
0f113f3e
MC
436 }
437 break;
438 case BIO_C_SET_CONNECT:
439 if (ptr != NULL) {
440 b->init = 1;
441 if (num == 0) {
417be660
RL
442 char *hold_service = data->param_service;
443 /* We affect the hostname regardless. However, the input
444 * string might contain a host:service spec, so we must
445 * parse it, which might or might not affect the service
446 */
b548a1f1 447 OPENSSL_free(data->param_hostname);
417be660
RL
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);
0f113f3e 455 } else if (num == 1) {
417be660 456 OPENSSL_free(data->param_service);
3d484574 457 data->param_service = OPENSSL_strdup(ptr);
0f113f3e 458 } else if (num == 2) {
417be660
RL
459 const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
460 if (ret) {
461 data->param_hostname = BIO_ADDR_hostname_string(addr, 1);
462 data->param_service = BIO_ADDR_service_string(addr, 1);
463 BIO_ADDRINFO_free(data->addr_first);
464 data->addr_first = NULL;
465 data->addr_iter = NULL;
466 }
0f113f3e 467 } else if (num == 3) {
417be660
RL
468 data->connect_family = *(int *)ptr;
469 } else {
470 ret = 0;
0f113f3e
MC
471 }
472 }
473 break;
474 case BIO_C_SET_NBIO:
417be660
RL
475 if (num != 0)
476 data->connect_mode |= BIO_SOCK_NONBLOCK;
477 else
478 data->connect_mode &= ~BIO_SOCK_NONBLOCK;
479 break;
480 case BIO_C_SET_CONNECT_MODE:
481 data->connect_mode = (int)num;
0f113f3e
MC
482 break;
483 case BIO_C_GET_FD:
484 if (b->init) {
485 ip = (int *)ptr;
486 if (ip != NULL)
487 *ip = b->num;
488 ret = b->num;
489 } else
490 ret = -1;
491 break;
492 case BIO_CTRL_GET_CLOSE:
493 ret = b->shutdown;
494 break;
495 case BIO_CTRL_SET_CLOSE:
496 b->shutdown = (int)num;
497 break;
498 case BIO_CTRL_PENDING:
499 case BIO_CTRL_WPENDING:
500 ret = 0;
501 break;
502 case BIO_CTRL_FLUSH:
503 break;
504 case BIO_CTRL_DUP:
505 {
506 dbio = (BIO *)ptr;
0f113f3e
MC
507 if (data->param_hostname)
508 BIO_set_conn_hostname(dbio, data->param_hostname);
417be660
RL
509 if (data->param_service)
510 BIO_set_conn_port(dbio, data->param_service);
511 BIO_set_conn_ip_family(dbio, data->connect_family);
512 BIO_set_conn_mode(dbio, data->connect_mode);
0f113f3e
MC
513 /*
514 * FIXME: the cast of the function seems unlikely to be a good
515 * idea
516 */
fce78bd4 517 (void)BIO_set_info_callback(dbio, data->info_callback);
0f113f3e
MC
518 }
519 break;
520 case BIO_CTRL_SET_CALLBACK:
2722ff50 521 ret = 0; /* use callback ctrl */
0f113f3e
MC
522 break;
523 case BIO_CTRL_GET_CALLBACK:
524 {
fce78bd4 525 BIO_info_cb **fptr;
0f113f3e 526
fce78bd4 527 fptr = (BIO_info_cb **)ptr;
0f113f3e
MC
528 *fptr = data->info_callback;
529 }
530 break;
6d53ad6b
MC
531 case BIO_CTRL_EOF:
532 ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
533 break;
b1f79e7c
JB
534# ifndef OPENSSL_NO_KTLS
535 case BIO_CTRL_SET_KTLS:
536# ifdef __FreeBSD__
537 crypto_info = (struct tls_enable *)ptr;
538# else
539 crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr;
540# endif
541 ret = ktls_start(b->num, crypto_info, sizeof(*crypto_info), num);
542 if (ret)
543 BIO_set_ktls_flag(b, num);
544 break;
545 case BIO_CTRL_GET_KTLS_SEND:
546 return BIO_should_ktls_flag(b, 1);
547 case BIO_CTRL_GET_KTLS_RECV:
548 return BIO_should_ktls_flag(b, 0);
549 case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG:
550 BIO_set_ktls_ctrl_msg_flag(b);
551 data->record_type = num;
552 ret = 0;
553 break;
554 case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG:
555 BIO_clear_ktls_ctrl_msg_flag(b);
556 ret = 0;
557 break;
558# endif
0f113f3e
MC
559 default:
560 ret = 0;
561 break;
562 }
26a7d938 563 return ret;
0f113f3e 564}
d02b48c6 565
fce78bd4 566static long conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
0f113f3e
MC
567{
568 long ret = 1;
569 BIO_CONNECT *data;
570
571 data = (BIO_CONNECT *)b->ptr;
572
573 switch (cmd) {
574 case BIO_CTRL_SET_CALLBACK:
575 {
fce78bd4 576 data->info_callback = fp;
0f113f3e
MC
577 }
578 break;
579 default:
580 ret = 0;
581 break;
582 }
26a7d938 583 return ret;
0f113f3e 584}
d3442bc7 585
0e1c0612 586static int conn_puts(BIO *bp, const char *str)
0f113f3e
MC
587{
588 int n, ret;
d02b48c6 589
0f113f3e
MC
590 n = strlen(str);
591 ret = conn_write(bp, str, n);
26a7d938 592 return ret;
0f113f3e 593}
d02b48c6 594
c45a48c1 595BIO *BIO_new_connect(const char *str)
0f113f3e
MC
596{
597 BIO *ret;
598
599 ret = BIO_new(BIO_s_connect());
600 if (ret == NULL)
26a7d938 601 return NULL;
0f113f3e 602 if (BIO_set_conn_hostname(ret, str))
26a7d938 603 return ret;
ca3a82c3 604 BIO_free(ret);
26a7d938 605 return NULL;
0f113f3e 606}
d02b48c6
RE
607
608#endif