| From 3b4d16c8735951ccfb5e671db72d1a72ce91bb66 Mon Sep 17 00:00:00 2001 |
| From: Avery Pennarun <apenwarr@gmail.com> |
| Date: Fri, 18 Apr 2014 23:02:24 -0400 |
| Subject: [PATCH] tlsdate-helper: openssl: support connecting on IPv6-only |
| networks. |
| |
| openssl's BIO_s_connect methods support IPv4 only. Use BIO_s_fd instead |
| to connect using a file descriptor, and supply our own pre-connected socket |
| file descriptor. This allows us to support both IPv4 and IPv6 servers. |
| --- |
| src/tlsdate-helper.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- |
| 1 file changed, 44 insertions(+), 8 deletions(-) |
| |
| diff --git a/src/tlsdate-helper.c b/src/tlsdate-helper.c |
| index 6def865..5d458b8 100644 |
| --- a/src/tlsdate-helper.c |
| +++ b/src/tlsdate-helper.c |
| @@ -94,6 +94,10 @@ know: |
| #include "polarssl/entropy.h" |
| #include "polarssl/ctr_drbg.h" |
| #include "polarssl/ssl.h" |
| +#else |
| +#include <sys/types.h> |
| +#include <sys/socket.h> |
| +#include <netdb.h> |
| #endif |
| |
| static void |
| @@ -180,18 +184,53 @@ setup_proxy(BIO *ssl) |
| } |
| |
| static BIO * |
| -make_ssl_bio(SSL_CTX *ctx) |
| +make_ssl_bio(SSL_CTX *ctx, const char *host, const char *port) |
| { |
| BIO *con = NULL; |
| BIO *ssl = NULL; |
| + int err, sock = -1; |
| + struct addrinfo *ai = NULL, *cai = NULL; |
| + struct addrinfo hints = { |
| + .ai_flags = AI_ADDRCONFIG, |
| + .ai_family = AF_UNSPEC, |
| + .ai_socktype = SOCK_STREAM, |
| + }; |
| + err = getaddrinfo(host, port, &hints, &ai); |
| + if (err != 0 || !ai) { |
| + fprintf(stderr, "getaddrinfo(%s): %s\n", host, gai_strerror(err)); |
| + goto error; |
| + } |
| + |
| + for (cai = ai; cai; cai = cai->ai_next) { |
| + sock = socket(cai->ai_family, SOCK_STREAM, 0); |
| + if (sock < 0) { |
| + perror("socket"); |
| + continue; |
| + } |
| + |
| + if (connect(sock, cai->ai_addr, cai->ai_addrlen) != 0) { |
| + perror("connect"); |
| + close(sock); |
| + sock = -1; |
| + continue; |
| + } |
| + |
| + break; |
| + } |
| + if (ai) freeaddrinfo(ai); |
| + if (sock < 0) goto error; |
| |
| - if (!(con = BIO_new(BIO_s_connect()))) |
| - die("BIO_s_connect failed"); |
| + if (!(con = BIO_new_fd(sock, 1))) |
| + die("BIO_new_fd failed\n"); |
| if (!(ssl = BIO_new_ssl(ctx, 1))) |
| die("BIO_new_ssl failed"); |
| setup_proxy(ssl); |
| BIO_push(ssl, con); |
| return ssl; |
| + |
| +error: |
| + die("connection failed\n"); |
| + return NULL; |
| } |
| |
| |
| @@ -1185,7 +1224,8 @@ run_ssl (uint32_t *time_map, int time_is_an_illusion, int http) |
| } |
| } |
| |
| - if (NULL == (s_bio = make_ssl_bio(ctx))) |
| + verb("V: opening socket to %s:%s\n", host, port); |
| + if (NULL == (s_bio = make_ssl_bio(ctx, host, port))) |
| die ("SSL BIO setup failed"); |
| BIO_get_ssl(s_bio, &ssl); |
| if (NULL == ssl) |
| @@ -1203,10 +1243,6 @@ run_ssl (uint32_t *time_map, int time_is_an_illusion, int http) |
| } |
| |
| SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); |
| - verb("V: opening socket to %s:%s", host, port); |
| - if ( (1 != BIO_set_conn_hostname(s_bio, host)) || |
| - (1 != BIO_set_conn_port(s_bio, port)) ) |
| - die ("Failed to initialize connection to `%s:%s'", host, port); |
| |
| if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE)) |
| die ("BIO_new_fp returned error, possibly: %s", strerror(errno)); |
| -- |
| 2.6.0.rc2.230.g3dd15c0 |
| |