[PATCH 2/2] add --request-ip option to explicitly request a specific IPv4 addresses
Daniel Lenski
dlenski at gmail.com
Wed Dec 20 22:56:59 PST 2017
This behavior is supported by AnyConnect (CONNECT with X-CSTP-Address header)
and by GlobalProtect (POST /ssl-vpn/getconfig.esp with preferred-ip form field).
Currently, this option is only a request. OpenConnect will print an error
message, but will not abort, if the server assigns a different IPv4 address.
I did not implement the corresponding behavior for IPv6 because I do not
have a way to test it right now.
Signed-off-by: Daniel Lenski <dlenski at gmail.com>
---
auth-globalprotect.c | 2 ++
cstp.c | 23 +++++++++++++++++------
gpst.c | 19 ++++++++++++++-----
main.c | 6 ++++++
openconnect.8.in | 6 ++++++
5 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/auth-globalprotect.c b/auth-globalprotect.c
index 1449d8c..dd3cb0d 100644
--- a/auth-globalprotect.c
+++ b/auth-globalprotect.c
@@ -295,6 +295,8 @@ static int gpst_login(struct openconnect_info *vpninfo, int portal)
buf_append(request_body, "jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:");
append_opt(request_body, "server", vpninfo->hostname);
append_opt(request_body, "computer", vpninfo->localname);
+ if (vpninfo->ip_info.addr)
+ append_opt(request_body, "preferred-ip", vpninfo->ip_info.addr);
if (form->auth_id && form->auth_id[0]!='_')
append_opt(request_body, "inputStr", form->auth_id);
append_form_opts(vpninfo, form, request_body);
diff --git a/cstp.c b/cstp.c
index a22c66e..3c35d05 100644
--- a/cstp.c
+++ b/cstp.c
@@ -262,7 +262,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
buf_append(reqbuf, "X-CSTP-MTU: %d\r\n", mtu);
buf_append(reqbuf, "X-CSTP-Address-Type: %s\r\n",
vpninfo->disable_ipv6 ? "IPv4" : "IPv6,IPv4");
- /* Explicitly request the same IPv4 address on reconnect */
+ /* Explicitly request the same IPv4 address on reconnect (or on
+ * initial connection if specified with the --request-ip option)
+ */
if (old_addr)
buf_append(reqbuf, "X-CSTP-Address: %s\r\n", old_addr);
if (!vpninfo->disable_ipv6)
@@ -580,11 +582,20 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
mtu);
}
if (old_addr) {
- if (strcmp(old_addr, vpninfo->ip_info.addr)) {
- vpn_progress(vpninfo, PRG_ERR,
- _("Reconnect gave different Legacy IP address (%s != %s)\n"),
- vpninfo->ip_info.addr, old_addr);
- return -EINVAL;
+ /* XXX: if --request-ip option is used, we'll have old_addr!=NULL even on the
+ first connection attempt, but if old_netmask is also non-NULL then we know
+ it's a reconnect. */
+ if (vpninfo->ip_info.addr==NULL || strcmp(old_addr, vpninfo->ip_info.addr)) {
+ if (!old_netmask)
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Legacy IP address %s was requested, but server provided %s\n"),
+ old_addr, vpninfo->ip_info.addr);
+ else {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Reconnect gave different Legacy IP address (%s != %s)\n"),
+ vpninfo->ip_info.addr, old_addr);
+ return -EINVAL;
+ }
}
}
if (old_netmask) {
diff --git a/gpst.c b/gpst.c
index 9b8b3c6..3665261 100644
--- a/gpst.c
+++ b/gpst.c
@@ -532,12 +532,21 @@ static int gpst_get_config(struct openconnect_info *vpninfo)
goto out;
}
if (old_addr) {
+ /* XXX: if --request-ip option is used, we'll have old_addr!=NULL even on the
+ first connection attempt, but if old_netmask is also non-NULL then we know
+ it's a reconnect. */
if (strcmp(old_addr, vpninfo->ip_info.addr)) {
- vpn_progress(vpninfo, PRG_ERR,
- _("Reconnect gave different Legacy IP address (%s != %s)\n"),
- vpninfo->ip_info.addr, old_addr);
- result = -EINVAL;
- goto out;
+ if (!old_netmask)
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Legacy IP address %s was requested, but server provided %s\n"),
+ old_addr, vpninfo->ip_info.addr);
+ else {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Reconnect gave different Legacy IP address (%s != %s)\n"),
+ vpninfo->ip_info.addr, old_addr);
+ result = -EINVAL;
+ goto out;
+ }
}
}
if (old_netmask) {
diff --git a/main.c b/main.c
index 815c220..b2fb10a 100644
--- a/main.c
+++ b/main.c
@@ -188,6 +188,7 @@ enum {
OPT_LOCAL_HOSTNAME,
OPT_PROTOCOL,
OPT_PASSTOS,
+ OPT_REQUEST_IP,
};
#ifdef __sun__
@@ -269,6 +270,7 @@ static const struct option long_options[] = {
OPTION("dump-http-traffic", 0, OPT_DUMP_HTTP),
OPTION("no-system-trust", 0, OPT_NO_SYSTEM_TRUST),
OPTION("protocol", 1, OPT_PROTOCOL),
+ OPTION("request-ip", 1, OPT_REQUEST_IP),
#ifdef OPENCONNECT_GNUTLS
OPTION("gnutls-debug", 1, OPT_GNUTLS_DEBUG),
#endif
@@ -860,6 +862,7 @@ static void usage(void)
printf(" --resolve=HOST:IP %s\n", _("Use IP when connecting to HOST"));
printf(" --os=STRING %s\n", _("OS type (linux,linux-64,win,...) to report"));
printf(" --dtls-local-port=PORT %s\n", _("Set local port for DTLS datagrams"));
+ printf(" --request-ip=IP %s\n", _("Request a specific IPv4 address"));
print_supported_protocols_usage();
printf("\n");
@@ -1270,6 +1273,9 @@ int main(int argc, char **argv)
case OPT_AUTHGROUP:
authgroup = keep_config_arg();
break;
+ case OPT_REQUEST_IP:
+ vpninfo->ip_info.addr = keep_config_arg();
+ break;
case 'C':
vpninfo->cookie = dup_config_arg();
break;
diff --git a/openconnect.8.in b/openconnect.8.in
index 9f46b30..65b26f3 100644
--- a/openconnect.8.in
+++ b/openconnect.8.in
@@ -66,6 +66,7 @@ openconnect \- Multi-protocol VPN client, for Cisco AnyConnect VPNs and others
.OP \-\-useragent string
.OP \-\-local-hostname string
.OP \-\-os string
+.OP \-\-request-ip ip
.B [https://]\fIserver\fB[:\fIport\fB][/\fIgroup\fB]
.YS
@@ -523,6 +524,11 @@ applied to the VPN session. If the gateway requires CSD, it will also cause
the corresponding CSD trojan binary to be downloaded, so you may need to use
.B \-\-csd\-wrapper
if this code is not executable on the local machine.
+.TP
+.B \-\-request-ip=IP
+Request a specific IPv4 address from the gateway. Currently, OpenConnect
+will print a warning but will not abort if the gateway provides a different
+IPv4 address.
.SH SIGNALS
In the data phase of the connection, the following signals are handled:
.TP
--
2.7.4
More information about the openconnect-devel
mailing list