Signed-off-by: Daniel Lenski <[email protected]>
---
 auth-globalprotect.c  |  29 +++++---
 gpst.c                | 158 +++++++++++++++++++++++++++++++++++++++++++
 hipreport.sh          | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++
 www/Makefile.am       |   2 +-
 www/features.xml      |   2 +-
 www/globalprotect.xml |   7 ++
 www/hip.xml           |  89 ++++++++++++++++++++++++
 7 files changed, 459 insertions(+), 10 deletions(-)
 create mode 100755 hipreport.sh
 create mode 100644 www/hip.xml

diff --git a/auth-globalprotect.c b/auth-globalprotect.c
index 1e7c854..8e27cfb 100644
--- a/auth-globalprotect.c
+++ b/auth-globalprotect.c
@@ -83,7 +83,8 @@ static struct oc_auth_form *auth_form(struct openconnect_info 
*vpninfo,
  */
 struct gp_login_arg {
        const char *opt;
-       unsigned save:1;
+       unsigned save_cookie:1;
+       unsigned save_token:1;
        unsigned show:1;
        unsigned warn_missing:1;
        unsigned err_missing:1;
@@ -91,13 +92,13 @@ struct gp_login_arg {
 };
 static const struct gp_login_arg gp_login_args[] = {
        { .opt="unknown-arg0", .show=1 },
-       { .opt="authcookie", .save=1, .err_missing=1 },
+       { .opt="authcookie", .save_cookie=1, .err_missing=1 },
        { .opt="persistent-cookie", .warn_missing=1 },  /* 40 hex digits; 
persists across sessions */
-       { .opt="portal", .save=1, .warn_missing=1 },
-       { .opt="user", .save=1, .err_missing=1 },
+       { .opt="portal", .save_cookie=1, .save_token=1, .warn_missing=1 },
+       { .opt="user", .save_cookie=1, .save_token=1, .err_missing=1 },
        { .opt="authentication-source", .show=1 },      /* LDAP-auth, 
AUTH-RADIUS_RSA_OTP, etc. */
        { .opt="configuration", .warn_missing=1 },      /* usually vsys1 
(sometimes vsys2, etc.) */
-       { .opt="domain", .save=1, .warn_missing=1 },
+       { .opt="domain", .save_cookie=1, .save_token=1, .warn_missing=1 },
        { .opt="unknown-arg8", .show=1 },
        { .opt="unknown-arg9", .show=1 },
        { .opt="unknown-arg10", .show=1 },
@@ -105,15 +106,17 @@ static const struct gp_login_arg gp_login_args[] = {
        { .opt="connection-type", .err_missing=1, .check="tunnel" },
        { .opt="password-expiration-days", .show=1 },   /* days until password 
expires, if not -1 */
        { .opt="clientVer", .err_missing=1, .check="4100" },
-       { .opt="preferred-ip", .save=1 },
+       { .opt="preferred-ip", .save_cookie=1 },
        { .opt=NULL },
 };
 
 static int parse_login_xml(struct openconnect_info *vpninfo, xmlNode *xml_node)
 {
-       struct oc_text_buf *cookie = buf_alloc();
+       struct oc_text_buf *cookie = buf_alloc(), *token = buf_alloc();
        char *value = NULL;
        const struct gp_login_arg *arg;
+       unsigned char md5[16];
+       int i;
 
        if (!xmlnode_is_named(xml_node, "jnlp"))
                goto err_out;
@@ -154,20 +157,30 @@ static int parse_login_xml(struct openconnect_info 
*vpninfo, xmlNode *xml_node)
                                     arg->opt, value);
                }
 
-               if (value && arg->save)
+               if (value && arg->save_cookie)
                        append_opt(cookie, arg->opt, value);
+               if (value && arg->save_token)
+                       append_opt(token, arg->opt, value);
                free(value);
                value = NULL;
        }
 
        vpninfo->cookie = cookie->data;
        cookie->data = NULL;
+
+       openconnect_md5(md5, token->data, token->pos);
+       vpninfo->csd_token = malloc(MD5_SIZE * 2 + 1);
+       for (i=0; i < MD5_SIZE; i++)
+               sprintf(&vpninfo->csd_token[i*2], "%02x", md5[i]);
+
        buf_free(cookie);
+       buf_free(token);
        return 0;
 
 err_out:
        free(value);
        buf_free(cookie);
+       buf_free(token);
        return -EINVAL;
 }
 
diff --git a/gpst.c b/gpst.c
index a4ec789..1262612 100644
--- a/gpst.c
+++ b/gpst.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <stdarg.h>
 #ifdef HAVE_LZ4
 #include <lz4.h>
@@ -631,6 +632,150 @@ static int gpst_connect(struct openconnect_info *vpninfo)
        return ret;
 }
 
+static int parse_hip_report_check(struct openconnect_info *vpninfo, xmlNode 
*xml_node)
+{
+       char *s;
+       int result = -EINVAL;
+
+       if (!xml_node || !xmlnode_is_named(xml_node, "response"))
+               goto out;
+
+       for (xml_node = xml_node->children; xml_node; xml_node=xml_node->next) {
+               if (!xmlnode_get_text(xml_node, "hip-report-needed", &s)) {
+                       if (!strcmp(s, "no"))
+                               result = 0;
+                       else if (!strcmp(s, "yes"))
+                               result = -EAGAIN;
+                       else
+                               result = -EINVAL;
+                       free(s);
+                       goto out;
+               }
+       }
+
+out:
+       return result;
+}
+
+/* check if HIP report is needed (to ssl-vpn/hipreportcheck.esp) or submit HIP 
report contents (to ssl-vpn/hipreport.esp) */
+static int check_or_submit_hip_report(struct openconnect_info *vpninfo, const 
char *report)
+{
+       int result;
+
+       struct oc_text_buf *request_body = buf_alloc();
+       const char *request_body_type = "application/x-www-form-urlencoded";
+       const char *method = "POST";
+       char *xml_buf=NULL, *orig_path;
+
+       buf_truncate(request_body);
+
+       /* cookie gives us these fields: authcookie, portal, user, domain, and 
(maybe the unnecessary) preferred-ip */
+       buf_truncate(request_body);
+       buf_append(request_body, "%s", vpninfo->cookie);
+       append_opt(request_body, "computer", vpninfo->localname);
+       append_opt(request_body, "client-ip", vpninfo->ip_info.addr);
+       append_opt(request_body, "client-role", "global-protect-full");
+       if (report) {
+               buf_ensure_space(request_body, strlen(report)*5);
+               append_opt(request_body, "report", report);
+       } else
+               append_opt(request_body, "md5", vpninfo->csd_token);
+
+       orig_path = vpninfo->urlpath;
+       vpninfo->urlpath = strdup(report ? "ssl-vpn/hipreport.esp" : 
"ssl-vpn/hipreportcheck.esp");
+       result = do_https_request(vpninfo, method, request_body_type, 
request_body,
+                                 &xml_buf, 0);
+       free(vpninfo->urlpath);
+       vpninfo->urlpath = orig_path;
+
+       result = gpst_xml_or_error(vpninfo, result, xml_buf, report ? NULL : 
parse_hip_report_check, NULL, NULL);
+
+       buf_free(request_body);
+       free(xml_buf);
+       return result;
+}
+
+static int run_hip_script(struct openconnect_info *vpninfo)
+{
+#if defined(_WIN32) || defined(__native_client__)
+       vpn_progress(vpninfo, PRG_ERR,
+                    _("Error: Running the 'HIP Report' script on this platform 
is not yet implemented.\n"));
+       return -EPERM;
+#else
+       int pipefd[2];
+       int ret;
+       pid_t child;
+
+       if (!vpninfo->csd_wrapper) {
+               vpn_progress(vpninfo, PRG_ERR,
+                            _("WARNING: Server asked us to submit HIP report 
with md5sum %s.\n"
+                              "VPN connectivity may be disabled or limited 
without HIP report submission.\n"
+                              "You need to provide a --csd-wrapper argument 
with the HIP report submission script.\n"),
+                            vpninfo->csd_token);
+               /* XXX: Many GlobalProtect VPNs work fine despite allegedly 
requiring HIP report submission */
+               return 0;
+       }
+
+       if (pipe(pipefd) == -1)
+               goto out;
+       child = fork();
+       if (child == -1) {
+               goto out;
+       } else if (child > 0) {
+               /* in parent: read report from child */
+               struct oc_text_buf *report_buf = buf_alloc();
+               char b[256];
+               int i, status;
+               close(pipefd[1]);
+
+               buf_truncate(report_buf);
+               while ((i = read(pipefd[0], b, sizeof(b))) > 0)
+                       buf_append_bytes(report_buf, b, i);
+
+               waitpid(child, &status, 0);
+               if (status != 0) {
+                       vpn_progress(vpninfo, PRG_ERR,
+                                                _("HIP script returned 
non-zero status: %d\n"), status);
+                       ret = -EINVAL;
+               } else {
+                       ret = check_or_submit_hip_report(vpninfo, 
report_buf->data);
+                       if (ret < 0)
+                               vpn_progress(vpninfo, PRG_ERR, _("HIP report 
submission failed.\n"));
+                       else {
+                               vpn_progress(vpninfo, PRG_INFO, _("HIP report 
submitted successfully.\n"));
+                               ret = 0;
+                       }
+               }
+               buf_free(report_buf);
+               return ret;
+       } else {
+               /* in child: run HIP script */
+               char *hip_argv[32];
+               int i = 0;
+               close(pipefd[0]);
+               dup2(pipefd[1], 1);
+
+               hip_argv[i++] = openconnect_utf8_to_legacy(vpninfo, 
vpninfo->csd_wrapper);
+               hip_argv[i++] = (char *)"--cookie";
+               hip_argv[i++] = vpninfo->cookie;
+               hip_argv[i++] = (char *)"--computer";
+               hip_argv[i++] = vpninfo->localname;
+               hip_argv[i++] = (char *)"--client-ip";
+               hip_argv[i++] = (char *)vpninfo->ip_info.addr;
+               hip_argv[i++] = (char *)"--md5";
+               hip_argv[i++] = vpninfo->csd_token;
+               hip_argv[i++] = NULL;
+               execv(hip_argv[0], hip_argv);
+
+       out:
+               vpn_progress(vpninfo, PRG_ERR,
+                                _("Failed to exec HIP script %s\n"), 
hip_argv[0]);
+               exit(1);
+       }
+
+#endif /* !_WIN32 && !__native_client__ */
+}
+
 int gpst_setup(struct openconnect_info *vpninfo)
 {
        int ret;
@@ -640,6 +785,18 @@ int gpst_setup(struct openconnect_info *vpninfo)
        if (ret)
                return ret;
 
+       /* Check HIP */
+       ret = check_or_submit_hip_report(vpninfo, NULL);
+       if (ret == -EAGAIN) {
+               vpn_progress(vpninfo, PRG_DEBUG,
+                                        _("Gateway says HIP report submission 
is needed.\n"));
+               ret = run_hip_script(vpninfo);
+               if (ret != 0)
+                       goto out;
+       } else if (ret == 0)
+               vpn_progress(vpninfo, PRG_DEBUG,
+                                        _("Gateway says no HIP report 
submission is needed.\n"));
+
        /* We do NOT actually start the HTTPS tunnel yet if we want to
         * use ESP, because the ESP tunnel won't work if the HTTPS tunnel
         * is connected! >:-(
@@ -647,6 +804,7 @@ int gpst_setup(struct openconnect_info *vpninfo)
        if (vpninfo->dtls_state == DTLS_DISABLED || vpninfo->dtls_state == 
DTLS_NOSECRET)
                ret = gpst_connect(vpninfo);
 
+out:
        return ret;
 }
 
diff --git a/hipreport.sh b/hipreport.sh
new file mode 100755
index 0000000..afc3067
--- /dev/null
+++ b/hipreport.sh
@@ -0,0 +1,182 @@
+#!/bin/sh
+
+# Read required variables from command line:
+#
+#   --cookie: a URL-encoded string, as output by openconnect
+#             --authenticate --protocol=gp, which includes parameters
+#             --from the /ssl-vpn/login.esp response
+#
+#   --computer: local hostname, which can be overriden with
+#               --openconnect local-hostname=HOSTNAME
+#
+#   --client-ip: IPv4 address allocated by the GlobalProtect VPN for
+#                this client (included in /ssl-vpn/getconfig.esp
+#                response)
+#
+#   --md5: The md5 digest to encode into this HIP report. I'm not sure
+#          exactly what this is the md5 digest *of*, but all that
+#          really matters is that the value in the HIP report
+#          submission should match the value in the HIP report check.
+
+COOKIE=
+COMPUTER=
+IP=
+MD5=
+
+while [ "$1" ]; do
+    if [ "$1" = "--cookie" ];    then shift; COOKIE="$1"; fi
+    if [ "$1" = "--computer" ];  then shift; COMPUTER="$1"; fi
+    if [ "$1" = "--client-ip" ]; then shift; IP="$1"; fi
+    if [ "$1" = "--md5" ];       then shift; MD5="$1"; fi
+    shift
+done
+
+if [ -z "$COOKIE" -o -z "$COMPUTER" -o -z "$IP" -o -z "$MD5" ]; then
+    echo "Parameters --cookie, --computer, --client-ip, and --md5 are 
required" >&2
+    exit 1;
+fi
+
+# Extract username and domain from cookie
+USER=$(echo "$COOKIE" | sed -rn 's/(.+&|^)user=([^&]+)(&.+|$)/\2/p')
+DOMAIN=$(echo "$COOKIE" | sed -rn 's/(.+&|^)domain=([^&]+)(&.+|$)/\2/p')
+
+# Timestamp in the format expected by GlobalProtect server
+NOW=$(date +'%m/%d/%Y %H:%M:%S')
+
+# This value may need to be extracted from the official HIP report, if a 
made-up value is not accepted.
+HOSTID="deadbeef-dead-beef-dead-beefdeadbeef"
+
+cat <<EOF
+<hip-report name="hip-report">
+       <md5-sum>$MD5</md5-sum>
+       <user-name>$USER</user-name>
+       <domain>$DOMAIN</domain>
+       <host-name>$COMPUTER</host-name>
+       <host-id>$HOSTID</host-id>
+       <ip-address>$IP</ip-address>
+       <ipv6-address></ipv6-address>
+       <generate-time>$NOW</generate-time>
+       <categories>
+               <entry name="host-info">
+                       <client-version>4.0.2-19</client-version>
+                       <os>Microsoft Windows 10 Pro , 64-bit</os>
+                       <os-vendor>Microsoft</os-vendor>
+                       <domain>$DOMAIN.internal</domain>
+                       <host-name>$COMPUTER</host-name>
+                       <host-id>$HOSTID</host-id>
+                       <network-interface>
+                               <entry 
name="{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}">
+                                       <description>PANGP Virtual Ethernet 
Adapter #2</description>
+                                       
<mac-address>01-02-03-00-00-01</mac-address>
+                                       <ip-address>
+                                               <entry name="$IP"/>
+                                       </ip-address>
+                                       <ipv6-address>
+                                               <entry 
name="dead::beef:dead:beef:dead"/>
+                                       </ipv6-address>
+                               </entry>
+                       </network-interface>
+               </entry>
+               <entry name="antivirus">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="McAfee VirusScan 
Enterprise" version="8.8.0.1804" defver="8682.0" prodType="1" 
engver="5900.7806" osType="1" vendor="McAfee, Inc." dateday="12" 
dateyear="2017" datemon="10">
+                                               </Prod>
+                                               
<real-time-protection>yes</real-time-protection>
+                                               <last-full-scan-time>10/11/2017 
15:23:41</last-full-scan-time>
+                                       </ProductInfo>
+                               </entry>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Windows Defender" 
version="4.11.15063.332" defver="1.245.683.0" prodType="1" engver="1.1.13804.0" 
osType="1" vendor="Microsoft Corp." dateday="8" dateyear="2017" datemon="6">
+                                               </Prod>
+                                               
<real-time-protection>no</real-time-protection>
+                                               
<last-full-scan-time>n/a</last-full-scan-time>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+               </entry>
+               <entry name="anti-spyware">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="McAfee VirusScan 
Enterprise" version="8.8.0.1804" defver="8682.0" prodType="2" 
engver="5900.7806" osType="1" vendor="McAfee, Inc." dateday="12" 
dateyear="2017" datemon="10">
+                                               </Prod>
+                                               
<real-time-protection>yes</real-time-protection>
+                                               <last-full-scan-time>10/11/2017 
15:23:41</last-full-scan-time>
+                                       </ProductInfo>
+                               </entry>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Windows Defender" 
version="4.11.15063.332" defver="1.245.683.0" prodType="2" engver="1.1.13804.0" 
osType="1" vendor="Microsoft Corp." dateday="8" dateyear="2017" datemon="6">
+                                               </Prod>
+                                               
<real-time-protection>no</real-time-protection>
+                                               
<last-full-scan-time>n/a</last-full-scan-time>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+               </entry>
+               <entry name="disk-backup">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Windows Backup and 
Restore" version="10.0.15063.0" vendor="Microsoft Corp.">
+                                               </Prod>
+                                               
<last-backup-time>n/a</last-backup-time>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+               </entry>
+               <entry name="disk-encryption">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Windows Drive 
Encryption" version="10.0.15063.0" vendor="Microsoft Corp.">
+                                               </Prod>
+                                               <drives>
+                                                       <entry>
+                                                               
<drive-name>C:</drive-name>
+                                                               
<enc-state>full</enc-state>
+                                                       </entry>
+                                               </drives>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+               </entry>
+               <entry name="firewall">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Microsoft Windows 
Firewall" version="10.0" vendor="Microsoft Corp.">
+                                               </Prod>
+                                               <is-enabled>yes</is-enabled>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+               </entry>
+               <entry name="patch-management">
+                       <list>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="McAfee ePolicy 
Orchestrator Agent" version="5.0.5.658" vendor="McAfee, Inc.">
+                                               </Prod>
+                                               <is-enabled>yes</is-enabled>
+                                       </ProductInfo>
+                               </entry>
+                               <entry>
+                                       <ProductInfo>
+                                               <Prod name="Microsoft Windows 
Update Agent" version="10.0.15063.0" vendor="Microsoft Corp.">
+                                               </Prod>
+                                               <is-enabled>yes</is-enabled>
+                                       </ProductInfo>
+                               </entry>
+                       </list>
+                       <missing-patches/>
+               </entry>
+               <entry name="data-loss-prevention">
+                       <list/>
+               </entry>
+       </categories>
+</hip-report>
+EOF
diff --git a/www/Makefile.am b/www/Makefile.am
index f791a00..a6de6ac 100644
--- a/www/Makefile.am
+++ b/www/Makefile.am
@@ -3,7 +3,7 @@
 SUBDIRS = styles inc images
 CONV   = "$(srcdir)/html.py"
 
-FTR_PAGES = csd.html charset.html token.html pkcs11.html tpm.html 
features.html gui.html nonroot.html
+FTR_PAGES = csd.html charset.html token.html pkcs11.html tpm.html 
features.html gui.html nonroot.html hip.html
 START_PAGES = building.html connecting.html manual.html vpnc-script.html 
 INDEX_PAGES = changelog.html download.html index.html packages.html 
platforms.html
 PROTO_PAGES = anyconnect.html juniper.html globalprotect.html
diff --git a/www/features.xml b/www/features.xml
index 92457dc..cbe9144 100644
--- a/www/features.xml
+++ b/www/features.xml
@@ -24,7 +24,7 @@
   <li>Automatic update of VPN server list / configuration.</li>
   <li>Roaming support, allowing reconnection when the local IP address 
changes.</li>
   <li>Run without root privileges <i>(see <a 
href="nonroot.html">here</a>)</i>.</li>
-  <li>"Cisco Secure Desktop" support <i>(see <a 
href="csd.html">here</a>)</i>.</li>
+  <li>Support for "Cisco Secure Desktop" <i>(see <a 
href="csd.html">here</a>)</i> and "GlobalProtect HIP report" <i>(see <a 
href="hip.html">here</a>)</i>.</li>
   <li>Graphical connection tools for various environments <i>(see <a 
href="gui.html">here</a>)</i>.</li>
 </ul>
 
diff --git a/www/globalprotect.xml b/www/globalprotect.xml
index ee45819..655db9a 100644
--- a/www/globalprotect.xml
+++ b/www/globalprotect.xml
@@ -16,15 +16,22 @@
 href="https://tools.ietf.org/html/rfc3948";>ESP</a>, with routing and
 configuration information distributed in XML format.</p>
 
+<h3>Authentication</h3>
+
 <p>To authenticate, you connect to the secure web server (<tt>POST
 /ssl-vpn/login.esp</tt>), provide a username, password, and (optionally) a
 certificate, and receive an authcookie.  The username, authcookie, and a
 couple other bits of information obtained at login are combined into the
 OpenConnect cookie.</p>
 
+<h3>Tunnel configuration</h3>
+
 <p>To connect to the secure tunnel, the cookie is used to read routing and
 tunnel configuration information (<tt>POST /ssl-vpn/getconfig.esp</tt>).</p>
 
+<p>Next, a <a href="hip.html">HIP report</a> (security scanner report) is
+generated by the client and submitted to the server, if required.</p>
+
 <p>Finally, either an HTTPS-based or ESP-based tunnel is setup:</p>
 
 <ol>
diff --git a/www/hip.xml b/www/hip.xml
new file mode 100644
index 0000000..0009c32
--- /dev/null
+++ b/www/hip.xml
@@ -0,0 +1,89 @@
+<PAGE>
+       <INCLUDE file="inc/header.tmpl" />
+
+       <VAR match="VAR_SEL_FEATURES" replace="selected" />
+       <VAR match="VAR_SEL_FEATURE_CSD" replace="selected" />
+       <PARSE file="menu1.xml" />
+       <PARSE file="menu2-features.xml" />
+
+       <INCLUDE file="inc/content.tmpl" />
+
+<h1>PAN GlobalProtect HIP</h1>
+
+<p>The HIP ('Host Integrity Protection') mechanism is a security
+scanner for the <a href="globalprotect.html">PAN GlobalProtect</a>
+VPNs, in the same vein as <a href="csd.html">Cisco's CSD</a> and <a
+href="juniper.html">Juniper's Host Checker (tncc.jar)</a>.</p>
+
+<h2>How it works</h2>
+
+<p>It is somewhat <i>less</i> intrusive than CSD or TNCC, because it
+does not appear to work by downloading a trojan binary from the VPN
+server. Instead, it runs a HIP report generator (built-in as part of
+the official GlobalProtect VPN client software), which generates an
+"HIP report" XML file.</p>
+
+<p>HIP flow used in the official clients:</p>
+<ol>
+  <li>Client authenticates and fetches the tunnel configuration from the 
GlobalProtect gateway.</li>
+  <li>Client runs HIP report generator and computes MD5 digest of report.</li>
+  <li>Client checks whether a HIP report is required 
(<code>/ssl-vpn/hipreportcheck.esp</code>), including its MD5 digest and 
gateway-assigned IP address in the report.</li>
+  <li>Gateway responds whether or not a HIP report is required (normally, it 
doesn't require a new one if a report with the same MD5 digest and same IP 
address have been submitted recently).</li>
+  <li>Client uploads the complete HIP report to 
(<code>/ssl-vpn/hipreport.esp</code>).</li>
+  <li>Server confirms acceptance of HIP report with a success message.</li>
+</ol>
+
+<p>If all goes well, the client should have the expected level of
+access to resources on the network after these steps are
+complete. However, two things can go wrong:</p>
+
+<ul>
+  <li>Many GlobalProtect servers report that they require HIP reports
+  (#3 above), but don't actually enforce this requirement. (For this
+  reason, OpenConnect does not currently fail if a HIP report is
+  required but no HIP report script is provided.)</li>
+  <li>Many GlobalProtect servers will claim that the HIP report was
+  accepted successfully (#6 above) but silently fail to enable the
+  expected network access, presumably because some aspect of the
+  HIP report contents were not approved.</li>
+</ul>
+
+<h2>HIP support in openconnect</h2>
+
+<p>OpenConnect supports HIP report generation and submission by passing the 
<code>--csd-wrapper=SCRIPT</code> argument with a shell script to generate a 
HIP report in the format expected by the
+server. This shell script must output the HIP report to standard output and 
exit successfully (status code 0). The HIP script is called with the following 
command-line arguments:</p>
+
+<pre>
+   --cookie: a URL-encoded string, as output by openconnect
+             --authenticate --protocol=gp, which includes parameters
+             --from the /ssl-vpn/login.esp response
+
+   --computer: local hostname, which can be overriden with
+               --openconnect local-hostname=HOSTNAME
+
+   --client-ip: IPv4 address allocated by the GlobalProtect VPN for
+                this client (included in /ssl-vpn/getconfig.esp
+                response)
+
+   --md5: The md5 digest to encode into this HIP report. All that
+          really matters is that the value in the HIP report
+          submission should match the value in the HIP report check.
+</pre>
+
+<h2>Generating/spoofing a HIP report</h2>
+
+<p>An example <code>hipreport.sh</code> script is included in the
+openconnect distribution.</p>
+
+<p>Depending on how picky your GlobalProtect
+VPN is, it may be necessary to spoof or alter some of the parameters
+of the HIP report to match the output of one of the official
+clients. In order to capture the contents of the official Windows
+client's HIP reports, enable the highest logging level for the "PanGPS
+Service", and then sift through the giant <code>PanGPS.log</code> file
+(which should be in the same directory as the executables, normally
+<code>c:\Program Files\PaloAlto Networks\GlobalProtect</code>) to find
+the HIP report submission.</p>
+
+<INCLUDE file="inc/footer.tmpl" />
+</PAGE>
-- 
2.7.4


_______________________________________________
openconnect-devel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/openconnect-devel

Reply via email to