From ce6a4620c5441172d92242afcea11c2561e226e9 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 31 May 2012 22:03:08 +0100 Subject: [PATCH] Remove duplicate socket connect code from gnutls.c Signed-off-by: David Woodhouse --- gnutls.c | 213 +-------------------------------------------------------------- 1 file changed, 3 insertions(+), 210 deletions(-) diff --git a/gnutls.c b/gnutls.c index ac0d0c4..17b3e02 100644 --- a/gnutls.c +++ b/gnutls.c @@ -44,11 +44,6 @@ #include "openconnect-internal.h" -/* OSX < 1.6 doesn't have AI_NUMERICSERV */ -#ifndef AI_NUMERICSERV -#define AI_NUMERICSERV 0 -#endif - /* Helper functions for reading/writing lines over SSL. We could use cURL for the HTTP stuff, but it's overkill */ @@ -885,41 +880,6 @@ static int verify_peer(gnutls_session_t session) return err; } -static int cancellable_connect(struct openconnect_info *vpninfo, int sockfd, - const struct sockaddr *addr, socklen_t addrlen) -{ - struct sockaddr_storage peer; - socklen_t peerlen = sizeof(peer); - fd_set wr_set, rd_set; - int maxfd = sockfd; - - fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); - - if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS) - return -1; - - FD_ZERO(&wr_set); - FD_ZERO(&rd_set); - FD_SET(sockfd, &wr_set); - if (vpninfo->cancel_fd != -1) { - FD_SET(vpninfo->cancel_fd, &rd_set); - if (vpninfo->cancel_fd > sockfd) - maxfd = vpninfo->cancel_fd; - } - - /* Later we'll render this whole exercise non-pointless by - including a 'cancelfd' here too. */ - select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); - if (vpninfo->cancel_fd != -1 && FD_ISSET(vpninfo->cancel_fd, &rd_set)) { - vpn_progress(vpninfo, PRG_ERR, _("Socket connect cancelled\n")); - errno = EINTR; - return -1; - } - - /* Check whether connect() succeeded or failed by using - getpeername(). See http://cr.yp.to/docs/connect.html */ - return getpeername(sockfd, (void *)&peer, &peerlen); -} int openconnect_open_https(struct openconnect_info *vpninfo) { @@ -929,176 +889,9 @@ int openconnect_open_https(struct openconnect_info *vpninfo) if (vpninfo->https_sess) return 0; - if (!vpninfo->port) - vpninfo->port = 443; - - if (vpninfo->peer_addr) { -#ifdef SOCK_CLOEXEC - ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP); - if (ssl_sock < 0) -#endif - { - ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM, IPPROTO_IP); - if (ssl_sock < 0) - goto reconn_err; - fcntl(ssl_sock, F_SETFD, fcntl(ssl_sock, F_GETFD) | FD_CLOEXEC); - } - if (cancellable_connect(vpninfo, ssl_sock, vpninfo->peer_addr, vpninfo->peer_addrlen)) { - reconn_err: - if (vpninfo->proxy) { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to reconnect to proxy %s\n"), - vpninfo->proxy); - } else { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to reconnect to host %s\n"), - vpninfo->hostname); - } - return -EINVAL; - } - - } else { - struct addrinfo hints, *result, *rp; - char *hostname; - char port[6]; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; - hints.ai_protocol = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - /* The 'port' variable is a string because it's easier - this way than if we pass NULL to getaddrinfo() and - then try to fill in the numeric value into - different types of returned sockaddr_in{6,}. */ -#ifdef LIBPROXY_HDR - if (vpninfo->proxy_factory) { - char *url; - char **proxies; - int i = 0; - - free(vpninfo->proxy_type); - vpninfo->proxy_type = NULL; - free(vpninfo->proxy); - vpninfo->proxy = NULL; - - if (vpninfo->port == 443) - i = asprintf(&url, "https://%s/%s", vpninfo->hostname, - vpninfo->urlpath?:""); - else - i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname, - vpninfo->port, vpninfo->urlpath?:""); - if (i == -1) - return -ENOMEM; - - proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory, - url); - - i = 0; - while (proxies && proxies[i]) { - if (!vpninfo->proxy && - (!strncmp(proxies[i], "http://", 7) || - !strncmp(proxies[i], "socks://", 8) || - !strncmp(proxies[i], "socks5://", 9))) - internal_parse_url(proxies[i], &vpninfo->proxy_type, - &vpninfo->proxy, &vpninfo->proxy_port, - NULL, 0); - i++; - } - free(url); - free(proxies); - if (vpninfo->proxy) - vpn_progress(vpninfo, PRG_TRACE, - _("Proxy from libproxy: %s://%s:%d/\n"), - vpninfo->proxy_type, vpninfo->proxy, vpninfo->port); - } -#endif - if (vpninfo->proxy) { - hostname = vpninfo->proxy; - snprintf(port, 6, "%d", vpninfo->proxy_port); - } else { - hostname = vpninfo->hostname; - snprintf(port, 6, "%d", vpninfo->port); - } - - if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') { - /* Solaris has no strndup(). */ - int len = strlen(hostname) - 2; - char *new_hostname = malloc(len + 1); - if (!new_hostname) - return -ENOMEM; - memcpy(new_hostname, hostname + 1, len); - new_hostname[len] = 0; - - hostname = new_hostname; - hints.ai_flags |= AI_NUMERICHOST; - } - - err = getaddrinfo(hostname, port, &hints, &result); - if (hints.ai_flags & AI_NUMERICHOST) - free(hostname); - - if (err) { - vpn_progress(vpninfo, PRG_ERR, - _("getaddrinfo failed for host '%s': %s\n"), - hostname, gai_strerror(err)); - return -EINVAL; - } - - for (rp = result; rp ; rp = rp->ai_next) { - char host[80]; - - if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host, - sizeof(host), NULL, 0, NI_NUMERICHOST)) - vpn_progress(vpninfo, PRG_INFO, - _("Attempting to connect to %s%s%s:%s\n"), - rp->ai_family == AF_INET6?"[":"", - host, - rp->ai_family == AF_INET6?"]":"", - port); - - ssl_sock = socket(rp->ai_family, rp->ai_socktype, - rp->ai_protocol); - if (ssl_sock < 0) - continue; - if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) { - /* Store the peer address we actually used, so that DTLS can - use it again later */ - vpninfo->peer_addr = malloc(rp->ai_addrlen); - if (!vpninfo->peer_addr) { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to allocate sockaddr storage\n")); - close(ssl_sock); - return -ENOMEM; - } - vpninfo->peer_addrlen = rp->ai_addrlen; - memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen); - break; - } - close(ssl_sock); - ssl_sock = -1; - } - freeaddrinfo(result); - - if (ssl_sock < 0) { - vpn_progress(vpninfo, PRG_ERR, - _("Failed to connect to host %s\n"), - vpninfo->proxy?:vpninfo->hostname); - return -EINVAL; - } - } - - if (vpninfo->proxy) { - err = process_proxy(vpninfo, ssl_sock); - if (err) { - close(ssl_sock); - return err; - } - } + ssl_sock = connect_https_socket(vpninfo); + if (ssl_sock < 0) + return ssl_sock; if (!vpninfo->https_cred) { gnutls_certificate_allocate_credentials(&vpninfo->https_cred); -- 2.7.4