and there is, of course, a typo. if needed i'll send the entire thing again. let me know. @@ -1506,7 +1506,7 @@ int main(int argc, char **argv) - sudo -E openconnect .... */ - if (!strcmp(config_arg, "linux-64") || !strcmp(os, "mac-intel")) { + if (!strcmp(config_arg, "linux-64") || !strcmp(config_arg, "mac-intel")) { vpn_progress(vpninfo, PRG_INFO, _("providing device info\n")); On Sat, Sep 8, 2018 at 2:58 PM <rschmied at janus.inka.de> wrote: > > [ ok, sending plain text without wrapping long lines seems to be harder > than it should be. sorry for the additional list submission] > > I've included a patch that provides better compatibility with CSD on > ASA head ends. E.g. it allows to specify the version string that is > presented to the ASA. Previous to this patch, OC presents it's own > version e.g. 0.7.8 but that could cause rejection on the head end if > it looks for a matching AC version string. > > It also contains a change that allows to even control more of the > client system data that is passed in the XML during authentication. > This part is entirely optional but might help to provide better > compatibility going forward. > > The patch works for me... especially the version-string seems to be > important in some environments to allow a successful connection, the > XML changes using the mobile_info struct might be seen as experimental > / optional. > > > > Thanks, > -ralph > > > > Signed-off-by: Ralph Schmieder <ralph.schmieder at gmail.com> > --- > auth.c | 12 ++++++-- > cstp.c | 2 +- > env.sh | 60 ++++++++++++++++++++++++++++++++++++++ > http.c | 10 +++++++ > library.c | 5 +++- > main.c | 65 +++++++++++++++++++++++++++++++++++++++++- > openconnect-internal.h | 3 ++ > openconnect.8.in | 23 +++++++++++++++ > openconnect.h | 3 +- > 9 files changed, 177 insertions(+), 6 deletions(-) > create mode 100644 env.sh > > diff --git a/auth.c b/auth.c > index 5883988..1236f3f 100644 > --- a/auth.c > +++ b/auth.c > @@ -705,7 +705,7 @@ static xmlDocPtr xmlpost_new_query(struct openconnect_info *vpninfo, const char > xmlNodePtr *rootp) > { > xmlDocPtr doc; > - xmlNodePtr root, node; > + xmlNodePtr root, node, child; > > doc = xmlNewDoc(XCAST("1.0")); > if (!doc) > @@ -720,7 +720,7 @@ static xmlDocPtr xmlpost_new_query(struct openconnect_info *vpninfo, const char > goto bad; > xmlDocSetRootElement(doc, root); > > - node = xmlNewTextChild(root, NULL, XCAST("version"), XCAST(openconnect_version_str)); > + node = xmlNewTextChild(root, NULL, XCAST("version"), XCAST(vpninfo->version_string)); > if (!node) > goto bad; > if (!xmlNewProp(node, XCAST("who"), XCAST("vpn"))) > @@ -734,6 +734,14 @@ static xmlDocPtr xmlpost_new_query(struct openconnect_info *vpninfo, const char > !xmlNewProp(node, XCAST("device-type"), XCAST(vpninfo->mobile_device_type)) || > !xmlNewProp(node, XCAST("unique-id"), XCAST(vpninfo->mobile_device_uniqueid))) > goto bad; > + if (vpninfo->mobile_mac_address) { > + node = xmlNewTextChild(root, NULL, XCAST("mac-address-list"), NULL); > + if (!node) > + goto bad; > + child = xmlNewTextChild(node, NULL, XCAST("mac-address"), XCAST(vpninfo->mobile_mac_address)); > + if (!child) > + goto bad; > + } > } > > return doc; > diff --git a/cstp.c b/cstp.c > index 68c3d51..625c414 100644 > --- a/cstp.c > +++ b/cstp.c > @@ -179,7 +179,7 @@ static void append_mobile_headers(struct openconnect_info *vpninfo, struct oc_te > { > if (vpninfo->mobile_platform_version) { > buf_append(buf, "X-AnyConnect-Identifier-ClientVersion: %s\r\n", > - openconnect_version_str); > + vpninfo->version_string); > buf_append(buf, "X-AnyConnect-Identifier-Platform: %s\r\n", > vpninfo->platname); > buf_append(buf, "X-AnyConnect-Identifier-PlatformVersion: %s\r\n", > diff --git a/env.sh b/env.sh > new file mode 100644 > index 0000000..17faea0 > --- /dev/null > +++ b/env.sh > @@ -0,0 +1,60 @@ > +# > +# This is entirely optional to provide better compatibility as > +# this information may show in the ASA head-end output or can > +# be used for CSD evaluation (e.g. if the wrong information is > +# presented, the head-end may deny the connection). > +# > +# Source this script (provide password for 'sudo dmidecode') > +# provide -E to sudo when launching openconnect to make sure > +# the environment is preserved: > +# > +# The script obviously relies on some Linux tools to provide > +# actual information. However, the variables could also be > +# statically provided when pretending to be something else. > +# > +# Example: > +# > +# OC_DEVICE_TYPE="VMware, Inc. VMware Virtual Platform" > +# OC_PLATFORM_VERSION="Linux 4.10.0-42-generic #46~16.04.1-Ubuntu SMP Mon Dec 4 15:57:59 UTC 2017 x86_64" > +# OC_UNIQUE_ID="A1C043E19F166410ABC2C2BDC8C376DA4F7F03513FBE1DCB3A066F22C65C12B6" > +# OC_MAC_ADDRESS="00-0c-29-0c-0e-57" > +# > +# - source env.sh > +# - sudo -E openconnect .... > +# > +#set -x > + > +# get system information from DMI > +DMI=$(sudo dmidecode | grep -A8 'System Information') > + > +# extract stuff we're interested in > +MANUFACTURER=$(echo "$DMI" | grep 'Manufacturer' | cut -d: -f2) > +PRODUCT=$(echo "$DMI" | grep 'Product Name' | cut -d: -f2) > +SERIAL=$(echo "$DMI" | grep 'Serial Number' | cut -d: -f2) > +UUID=$(echo "$DMI" | grep 'UUID' | cut -d: -f2) > + > +# synthesize / acquire device information > +OC_DEVICE_TYPE="${MANUFACTURER## } ${PRODUCT## }" > +OC_PLATFORM_VERSION=$(uname -srvp) > +OC_UNIQUE_ID=$(echo $UUID$SERIAL | openssl sha256 | sed 's/^.* //' | tr [[:lower:]] [[:upper:]]) > + > +# get the device that has the default route > +GW_DEV=$(ip route | sed -nr '/^default/s/.* dev ([[:alnum:]]+) .*$/\1/p') > + > +# does it exist and is it different from tun? > +# (if tunnel is running it potentially has the default route) > +# if not, set it to all-zeroes > +if [[ -n ${GW_DEV} && ! "${GW_DEV}" =~ ^tun[0-9]+$ ]]; then > + OC_MAC_ADDRESS=$(ip link show dev ${GW_DEV} | \ > + sed -nr '2s/^.*ether (([0-9a-f]{2}(:?)){6}) .*$/\1/p' | \ > + tr ':' '-') > +else > + OC_MAC_ADDRESS="00-00-00-00-00-00" > +fi > + > +# export the information used by OpenConnect > +export OC_DEVICE_TYPE > +export OC_PLATFORM_VERSION > +export OC_UNIQUE_ID > +export OC_MAC_ADDRESS > + > diff --git a/http.c b/http.c > index 7ff3bf7..397141c 100644 > --- a/http.c > +++ b/http.c > @@ -1001,6 +1001,16 @@ char *openconnect_create_useragent(const char *base) > return uagent; > } > > +char *openconnect_create_version_string(void) > +{ > + char *version; > + > + if (asprintf(&version, "%s", openconnect_version_str) < 0) > + return NULL; > + > + return version; > +} > + > static int proxy_gets(struct openconnect_info *vpninfo, char *buf, size_t len) > { > int i = 0; > diff --git a/library.c b/library.c > index 3d13499..b26d938 100644 > --- a/library.c > +++ b/library.c > @@ -78,6 +78,7 @@ struct openconnect_info *openconnect_vpninfo_new(const char *useragent, > vpninfo->max_qlen = 10; > vpninfo->localname = strdup("localhost"); > vpninfo->useragent = openconnect_create_useragent(useragent); > + vpninfo->version_string = openconnect_create_version_string(); > vpninfo->validate_peer_cert = validate_peer_cert; > vpninfo->write_new_config = write_new_config; > vpninfo->process_auth_form = process_auth_form; > @@ -276,11 +277,13 @@ int openconnect_set_reported_os(struct openconnect_info *vpninfo, > int openconnect_set_mobile_info(struct openconnect_info *vpninfo, > const char *mobile_platform_version, > const char *mobile_device_type, > - const char *mobile_device_uniqueid) > + const char *mobile_device_uniqueid, > + const char *mobile_mac_address) > { > STRDUP(vpninfo->mobile_platform_version, mobile_platform_version); > STRDUP(vpninfo->mobile_device_type, mobile_device_type); > STRDUP(vpninfo->mobile_device_uniqueid, mobile_device_uniqueid); > + STRDUP(vpninfo->mobile_mac_address, mobile_mac_address); > > return 0; > } > diff --git a/main.c b/main.c > index 379cf5d..1a95d49 100644 > --- a/main.c > +++ b/main.c > @@ -188,6 +188,7 @@ enum { > OPT_LOCAL_HOSTNAME, > OPT_PROTOCOL, > OPT_PASSTOS, > + OPT_VERSION, > }; > > #ifdef __sun__ > @@ -253,6 +254,7 @@ static const struct option long_options[] = { > OPTION("resolve", 1, OPT_RESOLVE), > OPTION("key-password-from-fsid", 0, OPT_KEY_PASSWORD_FROM_FSID), > OPTION("useragent", 1, OPT_USERAGENT), > + OPTION("version-string", 1, OPT_VERSION), > OPTION("local-hostname", 1, OPT_LOCAL_HOSTNAME), > OPTION("disable-ipv6", 0, OPT_DISABLE_IPV6), > OPTION("no-proxy", 0, OPT_NO_PROXY), > @@ -875,6 +877,8 @@ static void usage(void) > printf(" --useragent=STRING %s\n", _("HTTP header User-Agent: field")); > printf(" --local-hostname=STRING %s\n", _("Local hostname to advertise to server")); > printf(" --os=STRING %s\n", _("OS type (linux,linux-64,win,...) to report")); > + printf(" --version-string=STRING %s\n", _("reported version string during authentication")); > + printf(" (%s %s)\n", _("default:"), openconnect_version_str); > > #ifndef _WIN32 > printf("\n%s:\n", _("Trojan binary (CSD) execution")); > @@ -1416,6 +1420,10 @@ int main(int argc, char **argv) > free(vpninfo->useragent); > vpninfo->useragent = dup_config_arg(); > break; > + case OPT_VERSION: > + free(vpninfo->version_string); > + vpninfo->version_string = dup_config_arg(); > + break; > case OPT_LOCAL_HOSTNAME: > openconnect_set_localname(vpninfo, config_arg); > break; > @@ -1454,7 +1462,62 @@ int main(int argc, char **argv) > openconnect_set_mobile_info(vpninfo, > xstrdup("1.0"), > dup_config_arg(), > - xstrdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")); > + xstrdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), > + NULL); > + } > + > + /* This is ONLY applied for linux-64 and mac-intel, but could be used for > + other platforms, too. > + > + Read env variables for device information provided during authentication > + this includes: > + > + - device type (from 'dmidecode'), e.g. 'VMware, Inc. VMware Virtual Platform' > + - platform version (from 'uname -srvp'), e.g. > + 'Linux 3.19.0-61-generic #69~14.04.1-Ubuntu SMP Thu Jun 9 09:09:13 UTC 2016 x86_64' > + - uuid (some 32 byte hex value) > + - MAC address list (use first MAC address from interface which has default gateway) > + > + Sample output in <device-id> and <mac-address> elements: > + (shortened and line-wrapped for readability) > + > + <?xml version="1.0" encoding="UTF-8"?> > + <config-auth client="vpn" type="auth-reply"> > + <version who="vpn">v7.07-lalala</version> > + <device-id device-type="VMware, Inc. VMware Virtual Platform" > + platform-version="Linux 3.19.0-61-generic #69~14.04.1-Ubuntu > + SMP Thu Jun 9 09:09:13 UTC 2016 x86_64" > + unique-id="AB92EE073BD690CA94A89E2...984701EEB1CC7C4C9666D5"> > + linux-64 > + </device-id> > + <mac-address-list> > + <mac-address>00-0c-29-1a-ee-36</mac-address> > + </mac-address-list> > + [...] > + </config-auth> > + > + This is entirely optional to provide better compatibility as this information may show > + in the ASA head-end output or can be used for CSD evaluation. > + > + sample script provided (env.sh), source script (provide password for 'sudo dmidecode') > + provide -E to sudo to make sure environment is preserved > + > + - source env.sh > + - sudo -E openconnect .... > + */ > + > + if (!strcmp(config_arg, "linux-64") || !strcmp(os, "mac-intel")) { > + vpn_progress(vpninfo, PRG_INFO, _("providing device info\n")); > + vpn_progress(vpninfo, PRG_INFO, _("OC_PLATFORM_VERSION [%s]\n"), getenv("OC_PLATFORM_VERSION")); > + vpn_progress(vpninfo, PRG_INFO, _("OC_DEVICE_TYPE [%s]\n"), getenv("OC_DEVICE_TYPE")); > + vpn_progress(vpninfo, PRG_INFO, _("OC_UNIQUE_ID [%s]\n"), getenv("OC_UNIQUE_ID")); > + vpn_progress(vpninfo, PRG_INFO, _("OC_MAC_ADDRESS [%s]\n"), getenv("OC_MAC_ADDRESS")); > + > + openconnect_set_mobile_info(vpninfo, > + xstrdup(getenv("OC_PLATFORM_VERSION")), > + xstrdup(getenv("OC_DEVICE_TYPE")), > + xstrdup(getenv("OC_UNIQUE_ID")), > + xstrdup(getenv("OC_MAC_ADDRESS"))); > } > break; > case OPT_PASSTOS: > diff --git a/openconnect-internal.h b/openconnect-internal.h > index 729d301..766f76e 100644 > --- a/openconnect-internal.h > +++ b/openconnect-internal.h > @@ -389,6 +389,7 @@ struct openconnect_info { > char *mobile_platform_version; > char *mobile_device_type; > char *mobile_device_uniqueid; > + char *mobile_mac_address; > char *csd_token; > char *csd_ticket; > char *csd_stuburl; > @@ -640,6 +641,7 @@ struct openconnect_info { > > int is_dyndns; /* Attempt to redo DNS lookup on each CSTP reconnect */ > char *useragent; > + char *version_string; /* userdefined openconnect_version_str */ > > const char *quit_reason; > > @@ -1044,6 +1046,7 @@ void buf_append_xmlescaped(struct oc_text_buf *buf, const char *str); > int buf_error(struct oc_text_buf *buf); > int buf_free(struct oc_text_buf *buf); > char *openconnect_create_useragent(const char *base); > +char *openconnect_create_version_string(void); > int process_proxy(struct openconnect_info *vpninfo, int ssl_sock); > int internal_parse_url(const char *url, char **res_proto, char **res_host, > int *res_port, char **res_path, int default_port); > diff --git a/openconnect.8.in b/openconnect.8.in > index 1951183..1b19495 100644 > --- a/openconnect.8.in > +++ b/openconnect.8.in > @@ -64,6 +64,7 @@ openconnect \- Multi-protocol VPN client, for Cisco AnyConnect VPNs and others > .OP \-\-resolve host:ip > .OP \-\-servercert sha1 > .OP \-\-useragent string > +.OP \-\-version\-string string > .OP \-\-local-hostname string > .OP \-\-os string > .B [https://]\fIserver\fB[:\fIport\fB][/\fIgroup\fB] > @@ -504,6 +505,12 @@ Use > as 'User\-Agent:' field value in HTTP header. > (e.g. \-\-useragent 'Cisco AnyConnect VPN Agent for Windows 2.2.0133') > .TP > +.B \-\-version\-string=STRING > +Use > +.I STRING > +as the software version reported to the head end. > +(e.g. \-\-version\-string '2.2.0133') > +.TP > .B \-\-local-hostname=STRING > Use > .I STRING > @@ -523,6 +530,22 @@ 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. > +.SH ENVIRONMENT > +When the following environment variables are present, their information is > +sent during authentication to the head-end. This is entirely optional and > +may provide better compatibility when CSD is in use. > +.TP > +.B OC_DEVICE_TYPE > +the device type of the client, e.g. "VMware, Inc. VMware Virtual Platform" > +.TP > +.B OC_PLATFORM_VERSION > +the exact version of the client's operating system, e.g. "Linux 4.10.0-42-generic #46~16.04.1-Ubuntu SMP Mon Dec 4 15:57:59 UTC 2017 x86_64" > +.TP > +.B OC_UNIQUE_ID > +a unique 64 hex char long ID string representing the client, e.g. "A1C043E19F166410[...]DA4FCB3A066F22C65C12B6" > +.TP > +.B OC_MAC_ADDRESS > +a MAC address identifying the client, e.g. "00-0c-29-0c-0e-57" > .SH SIGNALS > In the data phase of the connection, the following signals are handled: > .TP > diff --git a/openconnect.h b/openconnect.h > index 74a5124..43a4984 100644 > --- a/openconnect.h > +++ b/openconnect.h > @@ -509,7 +509,8 @@ int openconnect_set_reported_os(struct openconnect_info *, const char *os); > int openconnect_set_mobile_info(struct openconnect_info *vpninfo, > const char *mobile_platform_version, > const char *mobile_device_type, > - const char *mobile_device_uniqueid); > + const char *mobile_device_uniqueid, > + const char *mobile_mac_address); > int openconnect_set_client_cert(struct openconnect_info *, const char *cert, > const char *sslkey); > const char *openconnect_get_ifname(struct openconnect_info *); > -- > 2.18.0 > > > _______________________________________________ > openconnect-devel mailing list > openconnect-devel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/openconnect-devel -- Ralph Schmieder Holtzstr. 2 76135 Karlsruhe Germany ralph.schmieder at gmail.com