Ver código fonte

openconnect: added upstream patch for dynamic IPs

That requires an update to ocserv as well to advertise them.
Nikos Mavrogiannopoulos 10 anos atrás
pai
commit
9ea507c3ab

+ 1
- 1
net/openconnect/Makefile Ver arquivo

@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
9 9
 
10 10
 PKG_NAME:=openconnect
11 11
 PKG_VERSION:=7.00
12
-PKG_RELEASE:=2
12
+PKG_RELEASE:=3
13 13
 
14 14
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
15 15
 PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/

+ 114
- 132
net/openconnect/patches/001-always-resolve-ips.patch Ver arquivo

@@ -1,161 +1,143 @@
1
+From 2f55fec323730a94ed49d401d93b913d85e43b65 Mon Sep 17 00:00:00 2001
2
+From: Nikos Mavrogiannopoulos <nmav@gnutls.org>
3
+Date: Mon, 1 Dec 2014 20:10:06 +0100
4
+Subject: [PATCH 1/2] Re-resolve when reconnecting CSTP and the X-CSTP-DynDNS
5
+ is set by the server
6
+
7
+That is, when reconnecting CSTP due to peer tearing the connection
8
+down attempt to re-resolve its IP. That handles the case where
9
+the server is using dynamic DNS and is advertising it.
10
+
11
+[dwmw2: refactored to simplify it somewhat]
12
+
13
+Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
14
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
15
+---
16
+ cstp.c                 |  3 +++
17
+ openconnect-internal.h |  1 +
18
+ ssl.c                  | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
19
+ 4 files changed, 52 insertions(+), 2 deletions(-)
20
+
1 21
 diff --git a/cstp.c b/cstp.c
2
-index b1235ef..f955b82 100644
22
+index 3b93538..55225f4 100644
3 23
 --- a/cstp.c
4 24
 +++ b/cstp.c
5
-@@ -570,7 +570,10 @@ int openconnect_make_cstp_connection(struct openconnect_info *vpninfo)
6
- 	return ret;
7
- }
8
- 
9
--static int cstp_reconnect(struct openconnect_info *vpninfo)
10
-+/* When dead peer is set, this function will re-attempt resolving
11
-+ * the peer in case its IP changed.
12
-+ */
13
-+static int cstp_reconnect(struct openconnect_info *vpninfo, unsigned dead_peer)
14
- {
15
- 	int ret;
16
- 	int timeout;
17
-@@ -591,6 +594,16 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
18
- 	timeout = vpninfo->reconnect_timeout;
19
- 	interval = vpninfo->reconnect_interval;
20
- 
21
-+	/* handle cases with dynamic DNS by forcing a new resolve.
22
-+	 * The original IP is saved to retry as fallback if resolving
23
-+	 * fails.
24
-+	 */
25
-+	if (dead_peer && vpninfo->first_peer_addr == NULL) {
26
-+		vpninfo->first_peer_addr = vpninfo->peer_addr;
27
-+		vpninfo->first_peer_addrlen = vpninfo->peer_addrlen;
28
-+		vpninfo->peer_addr = NULL;
29
-+	}
30
-+
31
- 	while ((ret = openconnect_make_cstp_connection(vpninfo))) {
32
- 		if (timeout <= 0)
33
- 			return ret;
34
-@@ -611,6 +624,11 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
35
- 		interval += vpninfo->reconnect_interval;
36
- 		if (interval > RECONNECT_INTERVAL_MAX)
37
- 			interval = RECONNECT_INTERVAL_MAX;
38
-+
39
-+		if (dead_peer && vpninfo->first_peer_addr != NULL) {
40
-+			free(vpninfo->peer_addr);
41
-+			vpninfo->peer_addr = NULL;
42
-+		}
43
- 	}
44
- 	script_config_tun(vpninfo, "reconnect");
45
- 	return 0;
46
-@@ -903,8 +921,15 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
47
- 		/* Not that this will ever happen; we don't even process
48
- 		   the setting when we're asked for it. */
49
- 		vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
50
--		if (vpninfo->ssl_times.rekey_method == REKEY_TUNNEL)
51
--			goto do_reconnect;
52
-+		if (vpninfo->ssl_times.rekey_method == REKEY_TUNNEL) {
53
-+			ret = cstp_reconnect(vpninfo, 0);
54
-+			if (ret) {
55
-+				vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
56
-+				vpninfo->quit_reason = "CSTP reconnect failed";
57
-+				return ret;
58
-+			}
59
-+			goto do_dtls_reconnect;
60
-+		}
61
- 		else if (vpninfo->ssl_times.rekey_method == REKEY_SSL) {
62
- 			ret = cstp_handshake(vpninfo, 0);
63
- 			if (ret) {
64
-@@ -922,7 +947,7 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
65
- 		vpn_progress(vpninfo, PRG_ERR,
66
- 			     _("CSTP Dead Peer Detection detected dead peer!\n"));
67
- 	do_reconnect:
68
--		ret = cstp_reconnect(vpninfo);
69
-+		ret = cstp_reconnect(vpninfo, 1);
70
- 		if (ret) {
71
- 			vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
72
- 			vpninfo->quit_reason = "CSTP reconnect failed";
73
-diff --git a/library.c b/library.c
74
-index f5d3dc9..7c8d5ec 100644
75
---- a/library.c
76
-+++ b/library.c
77
-@@ -178,6 +178,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
78
- 		CloseHandle(vpninfo->dtls_event);
79
- #endif
80
- 	free(vpninfo->peer_addr);
81
-+	free(vpninfo->first_peer_addr);
82
- 	free_optlist(vpninfo->csd_env);
83
- 	free_optlist(vpninfo->script_env);
84
- 	free_optlist(vpninfo->cookies);
85
-@@ -291,6 +292,8 @@ int openconnect_set_hostname(struct openconnect_info *vpninfo,
86
- 	vpninfo->unique_hostname = NULL;
87
- 	free(vpninfo->peer_addr);
88
- 	vpninfo->peer_addr = NULL;
89
-+	free(vpninfo->first_peer_addr);
90
-+	vpninfo->first_peer_addr = NULL;
91
- 
92
- 	return 0;
93
- }
25
+@@ -378,6 +378,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
26
+ 			int cstpmtu = atol(colon);
27
+ 			if (cstpmtu > mtu)
28
+ 				mtu = cstpmtu;
29
++		} else if (!strcmp(buf + 7, "DynDNS")) {
30
++			if (!strcmp(colon, "true"))
31
++				vpninfo->is_dyndns = 1;
32
+ 		} else if (!strcmp(buf + 7, "Address-IP6")) {
33
+ 			vpninfo->ip_info.netmask6 = new_option->value;
34
+ 		} else if (!strcmp(buf + 7, "Address")) {
94 35
 diff --git a/openconnect-internal.h b/openconnect-internal.h
95
-index 1bc79e5..cafbb3c 100644
36
+index 1bc79e5..db6c2ba 100644
96 37
 --- a/openconnect-internal.h
97 38
 +++ b/openconnect-internal.h
98
-@@ -424,6 +424,9 @@ struct openconnect_info {
99
- 	struct sockaddr *peer_addr;
100
- 	struct sockaddr *dtls_addr;
101
- 
102
-+	struct sockaddr *first_peer_addr;
103
-+	socklen_t first_peer_addrlen;
104
-+
39
+@@ -427,6 +427,7 @@ struct openconnect_info {
105 40
  	int dtls_local_port;
106 41
  
107 42
  	int deflate;
43
++	int is_dyndns; /* Attempt to redo DNS lookup on each CSTP reconnect */
44
+ 	char *useragent;
45
+ 
46
+ 	const char *quit_reason;
108 47
 diff --git a/ssl.c b/ssl.c
109
-index b50652d..e341871 100644
48
+index b50652d..d47a819 100644
110 49
 --- a/ssl.c
111 50
 +++ b/ssl.c
112
-@@ -110,6 +110,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
51
+@@ -106,6 +106,23 @@ unsigned string_is_hostname(const char *str)
52
+ 	return 1;
53
+ }
54
+ 
55
++static int match_sockaddr(struct sockaddr *a, struct sockaddr *b)
56
++{
57
++	if (a->sa_family == AF_INET) {
58
++		struct sockaddr_in *a4 = (void *)a;
59
++		struct sockaddr_in *b4 = (void *)b;
60
++
61
++		return (a4->sin_addr.s_addr == b4->sin_addr.s_addr) &&
62
++			(a4->sin_port == b4->sin_port);
63
++	} else if (a->sa_family == AF_INET6) {
64
++		struct sockaddr_in6 *a6 = (void *)a;
65
++		struct sockaddr_in6 *b6 = (void *)b;
66
++		return !memcmp(&a6->sin6_addr, &b6->sin6_addr, sizeof(a6->sin6_addr) &&
67
++			       a6->sin6_port == b6->sin6_port);
68
++	} else
69
++		return 0;
70
++}
71
++
72
+ int connect_https_socket(struct openconnect_info *vpninfo)
113 73
  {
114 74
  	int ssl_sock = -1;
115
- 	int err;
116
-+	unsigned retry_old_ip = 0;
117
- 
75
+@@ -114,7 +131,11 @@ int connect_https_socket(struct openconnect_info *vpninfo)
118 76
  	if (!vpninfo->port)
119 77
  		vpninfo->port = 443;
120
-@@ -230,6 +231,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
78
+ 
79
+-	if (vpninfo->peer_addr) {
80
++	/* If we're talking to a server which told us it has dynamic DNS, don't
81
++	   just re-use its previous IP address. If we're talking to a proxy, we
82
++	   can use *its* previous IP address. We expect it'll re-do the DNS
83
++	   lookup for the server anyway. */
84
++	if (vpninfo->peer_addr && (!vpninfo->is_dyndns || vpninfo->proxy)) {
85
+ 	reconnect:
86
+ #ifdef SOCK_CLOEXEC
87
+ 		ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
88
+@@ -230,6 +251,13 @@ int connect_https_socket(struct openconnect_info *vpninfo)
121 89
  			if (hints.ai_flags & AI_NUMERICHOST)
122 90
  				free(hostname);
123 91
  			ssl_sock = -EINVAL;
124
-+			if (vpninfo->first_peer_addr != NULL)
125
-+				retry_old_ip = 1;
92
++			/* If we were just retrying for dynamic DNS, reconnct using
93
++			   the previously-known IP address */
94
++			if (vpninfo->peer_addr) {
95
++				vpn_progress(vpninfo, PRG_ERR,
96
++					     _("Reconnecting to DynDNS server using previously cached IP address\n"));
97
++				goto reconnect;
98
++			}
126 99
  			goto out;
127 100
  		}
128 101
  		if (hints.ai_flags & AI_NUMERICHOST)
129
-@@ -291,7 +294,10 @@ int connect_https_socket(struct openconnect_info *vpninfo)
102
+@@ -257,6 +285,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
103
+ 			if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
104
+ 				/* Store the peer address we actually used, so that DTLS can
105
+ 				   use it again later */
106
++				free(vpninfo->peer_addr);
107
++				vpninfo->peer_addrlen = 0;
108
+ 				vpninfo->peer_addr = malloc(rp->ai_addrlen);
109
+ 				if (!vpninfo->peer_addr) {
110
+ 					vpn_progress(vpninfo, PRG_ERR,
111
+@@ -288,6 +318,17 @@ int connect_https_socket(struct openconnect_info *vpninfo)
112
+ 			}
113
+ 			closesocket(ssl_sock);
114
+ 			ssl_sock = -1;
115
++
116
++			/* If we're in DynDNS mode but this *was* the cached IP address,
117
++			 * don't bother falling back to it if it didn't work. */
118
++			if (vpninfo->peer_addr && vpninfo->peer_addrlen == rp->ai_addrlen &&
119
++			    match_sockaddr(vpninfo->peer_addr, rp->ai_addr)) {
120
++				vpn_progress(vpninfo, PRG_TRACE,
121
++					     _("Forgetting non-functional previous peer address\n"));
122
++				free(vpninfo->peer_addr);
123
++				vpninfo->peer_addr = 0;
124
++				vpninfo->peer_addrlen = 0;
125
++			}
130 126
  		}
131 127
  		freeaddrinfo(result);
132 128
  
133
-+
134
- 		if (ssl_sock < 0) {
135
-+			if (vpninfo->first_peer_addr != NULL)
136
-+				retry_old_ip = 1;
137
- 			vpn_progress(vpninfo, PRG_ERR,
129
+@@ -296,6 +337,11 @@ int connect_https_socket(struct openconnect_info *vpninfo)
138 130
  				     _("Failed to connect to host %s\n"),
139 131
  				     vpninfo->proxy?:vpninfo->hostname);
140
-@@ -314,6 +320,21 @@ int connect_https_socket(struct openconnect_info *vpninfo)
132
+ 			ssl_sock = -EINVAL;
133
++			if (vpninfo->peer_addr) {
134
++				vpn_progress(vpninfo, PRG_ERR,
135
++					     _("Reconnecting to DynDNS server using previously cached IP address\n"));
136
++				goto reconnect;
137
++			}
138
+ 			goto out;
141 139
  		}
142 140
  	}
143
-  out:
144
-+	if (retry_old_ip != 0 && vpninfo->first_peer_addr != NULL) {
145
-+		vpn_progress(vpninfo, PRG_ERR,
146
-+			     _("Retrying connection to host %s with original IP\n"),
147
-+				     vpninfo->proxy?:vpninfo->hostname);
148
-+
149
-+		retry_old_ip = 0;
150
-+		if (vpninfo->first_peer_addrlen > vpninfo->peer_addrlen || vpninfo->peer_addr == NULL)
151
-+			realloc_inplace(vpninfo->peer_addr, vpninfo->first_peer_addrlen);
152
-+
153
-+		if (vpninfo->peer_addr != NULL) {
154
-+			memcpy(vpninfo->peer_addr, vpninfo->first_peer_addr, vpninfo->first_peer_addrlen);
155
-+			goto reconnect;
156
-+		}
157
-+	}
158
-+
159
- 	/* If proxy processing returned -EAGAIN to reconnect before attempting
160
- 	   further auth, and we failed to reconnect, we have to clean up here. */
161
- 	cleanup_proxy_auth(vpninfo);
141
+-- 
142
+2.1.3
143
+