Discussion:
help with upgraded Cisco AnyConnect VPN
Ray Lambert
2018-10-03 22:32:16 UTC
Permalink
Hi,

I've been using OC successfully for months to connect to my organization's VPN.
However, they recently upgraded to a newer appliance (both Cisco AnyConnect) and
I'm having difficulty getting OC to work on the new one.  I'm hoping someone may
be able to help me figure this out.

I'm running on a fully up-to-date Manjaro system and connecting with a PIV card
(there has been no other change except the VPN itself since this was last
working).  (Please LMK if any other details are helpful.)

The new VPN requires CSD (the old one did not).  I've tried two different
third-party 'wrapper' implementations with partial success on one and (I think)
full success on the other.

The first one attempts an "honest" CSD by downloading the trojan and running it.
The wrapper seems to work but the 'cscan' program fails with the error
"drbg_instantiate failed" on stdout.  It also logs an error: "Opswat returned
error: -23 ... Failed to create OPSWAT plugin, error 1".  I wasn't able to find
any help with this error so I tried a different wrapper.

The second wrapper implements a "phony" hostscan response.  This seems to work.
I get the following response (as per curl, after POSTing the phony response):

    <?xml version="1.0" encoding="ISO-8859-1"?>
<hostscan><status>TOKEN_SUCCESS</status></hostscan>

I assume that means CSD verification was successful.  (Please tell me if it is
not.)

However, after this I still ultimately get a "Failed to obtain WebVPN cookie"
error.  I do not see anything in the output suggesting an error that I can try
to run down; hence, this inquiry.  The (sanitized) OC output that follows the
CSD verification is pasted below.  I'm happy to post the entire OC output log if
this is useful.

I would greatly appreciate any help with this.  I guess I'm mostly hoping that
someone familiar with the response formats can glean something from mine that
might lead to a solution.  (Unfortunately, my organization is not very helpful;
although they don't block Linux clients they also won't help with them, so I'm
on my own with this and my access is now completely cut-off.)

Thanks!

~ray

-------------------------------------------------------------------
GET https://$HOSTDOMAIN/+CSCOE+/sdesktop/wait.html
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
GET /+CSCOE+/sdesktop/wait.html HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Cookie: sdesktop=7BB2F2B628647A515AED4378
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
Got HTTP response: HTTP/1.1 302 Moved Temporarily
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Wed, 03 Oct 2018 19:53:26 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
Location: /
Set-Cookie: sdesktop=7BB2F2B628647A515AED4378; path=/; secure
HTTP body chunked (-2)
< <html>x</html>
POST https://$HOSTDOMAIN/piv
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Cookie: sdesktop=7BB2F2B628647A515AED4378
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 00000000000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 215
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="init"><version \
who="vpn">v7.08</version><device-id>linux-64</device-id> \
<group-access>https://$HOSTDOMAIN/piv</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Wed, 03 Oct 2018 19:53:28 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>PIV</tunnel-group>
< <config-hash>1530112511655</config-hash>
< </opaque>
< <auth id="main">
< <authentication-complete></authentication-complete>
< </auth>
< <host-scan>
< <host-scan-ticket>0C04BFF94F81F6C079004043</host-scan-ticket>
< <host-scan-token>2EF981F2731310FD606A9954</host-scan-token>
< <host-scan-base-uri>/CACHE</host-scan-base-uri>
< <host-scan-wait-uri>/+CSCOE+/sdesktop/wait.html</host-scan-wait-uri>
< </host-scan>
< </config-auth>
Failed to obtain WebVPN cookie
David Woodhouse
2018-10-03 22:54:33 UTC
Permalink
Post by Ray Lambert
However, after this I still ultimately get a "Failed to obtain WebVPN cookie"
error. I do not see anything in the output suggesting an error that I can try
to run down; hence, this inquiry. The (sanitized) OC output that follows the
CSD verification is pasted below. I'm happy to post the entire OC output log if
this is useful.
I don't see it trying the CSD wrapper at all there.

Can you show the command line, and add '-vv' to it too? Perhaps also
add a 'set -x' to the csd_wrapper script you're using, so we definitely
see what it's doing too.
Ray Lambert
2018-10-03 23:58:55 UTC
Permalink
Post by David Woodhouse
I don't see it trying the CSD wrapper at all there.
Can you show the command line, and add '-vv' to it too? Perhaps also
add a 'set -x' to the csd_wrapper script you're using, so we definitely
see what it's doing too.
Hi David,

Thanks for the response and sorry if I wasn't clear.  I had only posted the
last half of the log, after the wrapper script (because I thought that part
was successful and it was fairly long).

I re-ran it with -vv and 'set -x' and I'm now posting the full output (below)
and command.  Note that my wrapper script outputs a start/end message that
starts with "===" so I can see clearly where it runs.

~ray

---------------------------------------------------------------------------------------

$ sudo openconnect \
        -vv \
        --user="$ADDOM/$USERNAME" \
        --certificate="$PIVCERT" \
        --pid-file="$PIDFILE" \
        --csd-user=$ME \
        --csd-wrapper="$CSDWRAPPER" \
        --dump-http-traffic \
        $HOSTDOMAIN/piv
[sudo] password for ray:
POST https://$HOSTDOMAIN/piv
Attempting to connect to server XXX.XXX.XX.X:443
Connected to XXX.XXX.XX.X:443
Using PKCS#11 certificate
pkcs11:token=FIRSTNAME%20O%20LASTNAME;id=%00%02;type=cert
Trying PKCS#11 key URL
pkcs11:token=FIRSTNAME%20O%20LASTNAME;id=%00%02;type=private
PIN required for FIRSTNAME M LASTNAME
Enter PIN:
Using PKCS#11 key pkcs11:token=FIRSTNAME%20O%20LASTNAME;id=%00%02;type=private
Using client certificate 'FIRSTNAME M LASTNAME'
Adding supporting CA '$MYORG'
Adding supporting CA 'Symantec SSP Intermediate CA - G4'
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
Post by David Woodhouse
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 00000000000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 215
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="init"><version
who="vpn">v7.08</version><device-id>linux-64</device-id><group-access>https://$HOSTDOMAIN/piv</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Wed, 03 Oct 2018 23:44:23 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <client-cert-request></client-cert-request>
< </config-auth>
POST https://$HOSTDOMAIN/piv
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
Post by David Woodhouse
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 00000000000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 215
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="init"><version
who="vpn">v7.08</version><device-id>linux-64</device-id><group-access>https://$HOSTDOMAIN/piv</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Wed, 03 Oct 2018 23:44:25 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>PIV</tunnel-group>
< <config-hash>1530112511655</config-hash>
< </opaque>
< <auth id="main">
< <authentication-complete></authentication-complete>
< </auth>
< <host-scan>
< <host-scan-ticket>260F964C1481B67F19F23B9E</host-scan-ticket>
< <host-scan-token>0EF135D975E118204E8B8B23</host-scan-token>
< <host-scan-base-uri>/CACHE</host-scan-base-uri>
< <host-scan-wait-uri>/+CSCOE+/sdesktop/wait.html</host-scan-wait-uri>
< </host-scan>
< </config-auth>
XML POST enabled
GET https://$HOSTDOMAIN/+CSCOE+/sdesktop/wait.html
Post by David Woodhouse
GET /+CSCOE+/sdesktop/wait.html HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Cookie: sdesktop=0EF135D975E118204E8B8B23
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
+ echo '=== csd-wrapper.sh is running...'
=== csd-wrapper.sh is running...
+ CSD_HOSTNAME=$HOSTDOMAIN
+ host=https://$HOSTDOMAIN
+ token=0EF135D975E118204E8B8B23
+ echo '[token=0EF135D975E118204E8B8B23]'
[token=0EF135D975E118204E8B8B23]
+ echo '[sending...]'
[sending...]
+ run_curl --data-ascii @-
'https://$HOSTDOMAIN/+CSCOE+/sdesktop/scan.xml?reusebrowser=1'
+ /usr/bin/curl --insecure --user-agent 'Open AnyConnect VPN Agent v7.08'
--header 'X-Transcend-Version: 1' --header 'X-Aggregate-Auth: 1' --header
'X-AnyConnect-Platform: linux-64' --cookie sdesktop=0EF135D975E118204E8B8B23
--data-ascii @- 'https://$HOSTDOMAIN/+CSCOE+/sdesktop/scan.xml?reusebrowser=1'
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Wed, 03 Oct 2018 23:44:25 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
HTTP body chunked (-2)
<
< <html>
< <head>
< <meta http-equiv="refresh" content="1">
< <title>Installation</title>
< <link href="/+CSCOU+/portal.css" rel="stylesheet" type="text/css">
< <link href="/+CSCOE+/logon_custom.css" rel="stylesheet" type="text/css">
< </head>
< <body style="background-color:#ffffff; overflow:auto;">
< <table style="width:100%;height: 100%" cellspacing=0 cellpadding=0>
< <tr>
< <td style="border-bottom:1px solid #aaaaaa" colspan=2>
< <table style="width:100%" border="0" cellpadding="0" cellspacing="0"
class="cuesHeaderBg">
< <tr>
< <td colspan="2" class="cuesHeaderAccent"></td>
< </tr>
<    <tr>
<       <td class="install-title" style="height:40px; padding: 8px;
font-size:larger;font-weight:bold">
<           <img src="/+CSCOU+/csco_logo.gif" align="absmiddle" alt="Logo" 
title="Logo">
<           &nbsp;&nbsp;Secure Desktop
<       </td>
<    </tr>
< </tr>
< </table>
< </td>
< </tr>
<
< <td id=form_panel align=middle>
< <div id=keepout_margin>
< <table id=form_table cellspacing=0 cellpadding=0 border=0 width=300>
<
<     <tr>
<     <td colspan=2 id="logon" align="middle" valign="top">
<     <table id="form_title"  width=100% cellspacing=0  border="0">
<     <tr height=20>
<     <td id="form_title_text" colspan=2 align="middle" nowrap>
<         Secure Desktop
<     </td>
<     </tr>
<     </table>
<     </td>
< </tr>
< <tr><td colspan=2 align=middle>
< <table border=0>
< <tr>
< <td colspan=2><div style="margin-top:10;margin-bottom:10;">
< Processing, please wait...
< </div>
< </td>
< </tr>
< <tr><td><center><img src="/+CSCOU+/progress.gif"
alt="Loading..."></center></tr></td>
< <tr>
< <td align=middle colspan=2 height=40>
< </td>
< </tr>
< </table>
< </div>
< </td>
< </table>
< </div>
< </td>
< </body>
< </html>
Refreshing +CSCOE+/sdesktop/wait.html after 1 second...
<?xml version="1.0" encoding="ISO-8859-1"?>
<hostscan><status>TOKEN_SUCCESS</status></hostscan>
+ echo '[sent]'
[sent]
+ echo '=== csd-wrapper.sh is exiting'
=== csd-wrapper.sh is exiting
+ exit 0
GET https://$HOSTDOMAIN/+CSCOE+/sdesktop/wait.html
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
Post by David Woodhouse
GET /+CSCOE+/sdesktop/wait.html HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Cookie: sdesktop=0EF135D975E118204E8B8B23
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
Got HTTP response: HTTP/1.1 302 Moved Temporarily
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Wed, 03 Oct 2018 23:44:28 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
Location: /
Set-Cookie: sdesktop=0EF135D975E118204E8B8B23; path=/; secure
HTTP body chunked (-2)
< <html>x</html>
POST https://$HOSTDOMAIN/piv
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
Post by David Woodhouse
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08
Cookie: sdesktop=0EF135D975E118204E8B8B23
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 00000000000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 215
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="init"><version
who="vpn">v7.08</version><device-id>linux-64</device-id><group-access>https://$HOSTDOMAIN/piv</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Wed, 03 Oct 2018 23:44:30 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>PIV</tunnel-group>
< <config-hash>1530112511655</config-hash>
< </opaque>
< <auth id="main">
< <authentication-complete></authentication-complete>
< </auth>
< <host-scan>
< <host-scan-ticket>60AC20764B72C71146C5CB38</host-scan-ticket>
< <host-scan-token>65853B9B04C273AA7F365695</host-scan-token>
< <host-scan-base-uri>/CACHE</host-scan-base-uri>
< <host-scan-wait-uri>/+CSCOE+/sdesktop/wait.html</host-scan-wait-uri>
< </host-scan>
< </config-auth>
Failed to obtain WebVPN cookie
David Woodhouse
2018-10-04 15:23:05 UTC
Permalink
Post by Ray Lambert
Hi David,
Thanks for the response and sorry if I wasn't clear. I had only posted the
last half of the log, after the wrapper script (because I thought that part
was successful and it was fairly long).
I re-ran it with -vv and 'set -x' and I'm now posting the full output (below)
and command. Note that my wrapper script outputs a start/end message that
starts with "===" so I can see clearly where it runs.
Ah, I suspect the issue here is that the "form" at the end isn't
actually asking for anything. So we fail to parse it (or at least fail
to send any kind of response).

We should send back the hostscan token even if there's no username or
password or anything else.
Ray Lambert
2018-10-04 16:42:26 UTC
Permalink
Can you think of any kind of (short-term) workaround?

I don't know the code at all but I'd be happy to try a fix (can you point me
in the right direction?).

Thanks again!
Post by David Woodhouse
Post by Ray Lambert
Hi David,
Thanks for the response and sorry if I wasn't clear. I had only posted the
last half of the log, after the wrapper script (because I thought that part
was successful and it was fairly long).
I re-ran it with -vv and 'set -x' and I'm now posting the full output (below)
and command. Note that my wrapper script outputs a start/end message that
starts with "===" so I can see clearly where it runs.
Ah, I suspect the issue here is that the "form" at the end isn't
actually asking for anything. So we fail to parse it (or at least fail
to send any kind of response).
We should send back the hostscan token even if there's no username or
password or anything else.
Ray Lambert
2018-10-04 18:50:31 UTC
Permalink
Post by David Woodhouse
Ah, I suspect the issue here is that the "form" at the end isn't
actually asking for anything. So we fail to parse it (or at least fail
to send any kind of response).
We should send back the hostscan token even if there's no username or
password or anything else.
David,

Is the <authentication-complete> tag the key to this, by any chance?  I'm
just guessing (I don't know the protocol) but I don't see it being handled in
the code.

I tried adding some code to handle it but I'm not really sure what to do with
it; my first attempt failed (i.e. exiting handle_auth_form() with
OC_FORM_RESULT_OK if the tag has been seen).

Thanks,

~ray
David Woodhouse
2018-10-05 12:45:34 UTC
Permalink
Post by Ray Lambert
Post by David Woodhouse
Ah, I suspect the issue here is that the "form" at the end isn't
actually asking for anything. So we fail to parse it (or at least fail
to send any kind of response).
We should send back the hostscan token even if there's no username or
password or anything else.
David,
Is the <authentication-complete> tag the key to this, by any chance? I'm
just guessing (I don't know the protocol) but I don't see it being handled in
the code.
I tried adding some code to handle it but I'm not really sure what to do with
it; my first attempt failed (i.e. exiting handle_auth_form() with
OC_FORM_RESULT_OK if the tag has been seen).
Yeah, that won't work because it won't post anything back. Try
something like this...

diff --git a/auth.c b/auth.c
index 799a031..2c76b4d 100644
--- a/auth.c
+++ b/auth.c
@@ -648,6 +648,8 @@ static int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_for
vpn_progress(vpninfo, PRG_INFO, "%s\n", form->message);
if (form->error)
vpn_progress(vpninfo, PRG_ERR, "%s\n", form->error);
+ if (vpninfo->csd_token && vpninfo->csd_ticket)
+ goto justpost;
return -EPERM;
}

@@ -662,7 +664,7 @@ static int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_for
vpninfo->token_bypassed = 1;
return ret;
}
-
+ justpost:
ret = vpninfo->xmlpost ?
xmlpost_append_form_opts(vpninfo, form, request_body) :
append_form_opts(vpninfo, form, request_body);
David Woodhouse
2018-10-05 12:58:02 UTC
Permalink
Post by David Woodhouse
Post by Ray Lambert
Post by David Woodhouse
Ah, I suspect the issue here is that the "form" at the end isn't
actually asking for anything. So we fail to parse it (or at least fail
to send any kind of response).
We should send back the hostscan token even if there's no username or
password or anything else.
David,
Is the <authentication-complete> tag the key to this, by any chance? I'm
just guessing (I don't know the protocol) but I don't see it being handled in
the code.
I tried adding some code to handle it but I'm not really sure what to do with
it; my first attempt failed (i.e. exiting handle_auth_form() with
OC_FORM_RESULT_OK if the tag has been seen).
Yeah, that won't work because it won't post anything back. Try
something like this...
Or this slightly (but only slightly) nicer variant:

diff --git a/auth.c b/auth.c
index 799a031..fe26316 100644
--- a/auth.c
+++ b/auth.c
@@ -417,6 +417,12 @@ static int parse_auth_node(struct openconnect_info *vpninfo, xmlNode *xml_node,
} else if (!vpninfo->csd_scriptname && xmlnode_is_named(xml_node, "csd")) {
xmlnode_get_prop(xml_node, "token", &vpninfo->csd_token);
xmlnode_get_prop(xml_node, "ticket", &vpninfo->csd_ticket);
+ } else if (xmlnode_is_named(xml_node, "authentication-complete")) {
+ /* Ick. Since struct oc_auth_form is public there's no
+ * simple way to add a flag to it. So let's abuse the
+ * auth_id string instead. */
+ free(form->auth_id);
+ form->auth_id = strdup("openconnect_authentication_complete");
}
/* For Windows, vpninfo->csd_xmltag will be "csd" and there are *two* <csd>
nodes; one with token/ticket and one with the URLs. Process them both
@@ -648,6 +654,8 @@ static int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_for
vpn_progress(vpninfo, PRG_INFO, "%s\n", form->message);
if (form->error)
vpn_progress(vpninfo, PRG_ERR, "%s\n", form->error);
+ if (!strcmp(form->auth_id, "openconnect_authentication_complete"))
+ goto justpost;
return -EPERM;
}

@@ -662,7 +670,7 @@ static int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_for
vpninfo->token_bypassed = 1;
return ret;
}
-
+ justpost:
ret = vpninfo->xmlpost ?
xmlpost_append_form_opts(vpninfo, form, request_body) :
append_form_opts(vpninfo, form, request_body);
Ray Lambert
2018-10-05 17:57:41 UTC
Permalink
Thanks for the patch.
Login denied.  Your system does not meet the minumium security requirement
to access the XXXXX Network.  If you  need assistance please contact the
helpdesk.
Your client certificate will be used for authentication
And it then prompts for a group, username etc.

I'm still getting the same response as before to the hostscan
("TOKEN_SUCCESS").  Did that response look good to you (I've never seen a
good one so I can't judge)?  I'm guessing either hostscan did not actually
work or we're missing something in the later requests.
/* Ick. Since struct oc_auth_form is public there's no
* simple way to add a flag to it. So let's abuse the
* auth_id string instead. */
I had added an int flag to openconnect_info.  Is that less or more "ick"?  ;)

Here's the latest output (beginning at the hostscan response). The messages
enclosed in "[[...]]" are trace logging that I added to follow the flow.  You
can see where the patch is kicking in.

< HTTP/1.1 200 OK
< Content-Type: text/xml
< Transfer-Encoding: chunked
< Cache-Control: no-cache
< Pragma: no-cache
< Connection: Close
< Date: Fri, 05 Oct 2018 17:24:53 GMT
< X-Frame-Options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000; preload;
<
<?xml version="1.0" encoding="ISO-8859-1"?>
<hostscan><status>TOKEN_SUCCESS</status></hostscan>
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
[sent]
=== csd-wrapper.sh is exiting
GET https://$HOSTDOMAIN/+CSCOE+/sdesktop/wait.html
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
GET /+CSCOE+/sdesktop/wait.html HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08-unknown
Cookie: sdesktop=61FFDE3E463B3EF9149711C0
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
Got HTTP response: HTTP/1.1 302 Moved Temporarily
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Fri, 05 Oct 2018 17:24:56 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
Location: /
Set-Cookie: sdesktop=61FFDE3E463B3EF9149711C0; path=/; secure
HTTP body chunked (-2)
< <html>x</html>
POST https://$HOSTDOMAIN/piv
SSL negotiation with $HOSTDOMAIN
Connected to HTTPS on $HOSTDOMAIN
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08-unknown
Cookie: sdesktop=61FFDE3E463B3EF9149711C0
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 223
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="init"><version
who="vpn">v7.08-unknown</version><device-id>linux-64</device-id><group-access>https://$HOSTDOMAIN/piv</group-access></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Fri, 05 Oct 2018 17:24:58 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>PIV</tunnel-group>
< <config-hash>1530112511655</config-hash>
< </opaque>
< <auth id="main">
< <authentication-complete></authentication-complete>
< </auth>
< <host-scan>
< <host-scan-ticket>51EA98974F3777162A90D431</host-scan-ticket>
< <host-scan-token>1FCD58D80D21FBBB2117A04A</host-scan-token>
< <host-scan-base-uri>/CACHE</host-scan-base-uri>
< <host-scan-wait-uri>/+CSCOE+/sdesktop/wait.html</host-scan-wait-uri>
< </host-scan>
< </config-auth>
[[set openconnect_authentication_complete]]
[[entering auth form loop]]
[[handle_auth_form jumping to justpost for openconnect_authentication_complete]]
[[sending request]]
POST https://$HOSTDOMAIN/piv
POST /piv HTTP/1.1
Host: $HOSTDOMAIN
User-Agent: Open AnyConnect VPN Agent v7.08-unknown
Cookie: sdesktop=61FFDE3E463B3EF9149711C0
Accept: */*
Accept-Encoding: identity
X-Transcend-Version: 1
X-Aggregate-Auth: 1
X-AnyConnect-Platform: linux-64
X-Support-HTTP-Auth: true
X-Pad: 0000000000000000000000000000000000000000000
Content-Type: application/x-www-form-urlencoded
Content-Length: 341
<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="auth-reply"><version
who="vpn">v7.08-unknown</version><device-id>linux-64</device-id><opaque
is-for="sg">
<tunnel-group>PIV</tunnel-group>
<config-hash>1530112511655</config-hash>
</opaque><auth/><host-scan-token>61FFDE3E463B3EF9149711C0</host-scan-token></config-auth>
Got HTTP response: HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Cache-Control: no-cache
Pragma: no-cache
Connection: Keep-Alive
Date: Fri, 05 Oct 2018 17:24:58 GMT
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; preload;
X-Aggregate-Auth: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
< <opaque is-for="sg">
< <tunnel-group>PIV</tunnel-group>
< <group-alias>PIV</group-alias>
< <config-hash>1530112511655</config-hash>
< </opaque>
< <auth id="main">
< <title>Login</title>
< <message>Your client certificate will be used for authentication</message>
< <banner></banner>
< <error id="9" param1="Your system does not meet the minumium security
requirement to access the XXXX Network.  If you need assistance please
contact the helpdesk." param2="">Login denied.  %s</error>
< <form>
< <select name="group_list" label="GROUP:">
< <option>ANYCONNECT</option>
< <option>AnyConnect</option>
< <option>GPUpdate</option>
< <option selected="true">PIV</option>
< <option>PIV-Access</option>
< <option>VDI</option>
< <option>XXXX_Secure_Tunnel</option>
< <option>client</option>
< <option>gfe</option>
< <option>piv</option>
< <option>piv-exempt</option>
< <option>ts</option>
< </select>
< </form>
< </auth>
< <host-scan>
< <host-scan-ticket>6BFE52EE3FECD86921726AF0</host-scan-ticket>
< <host-scan-token>1E3627335BABEEA20A6D826D</host-scan-token>
< <host-scan-base-uri>/CACHE</host-scan-base-uri>
< <host-scan-wait-uri>/+CSCOE+/sdesktop/wait.html</host-scan-wait-uri>
< </host-scan>
< </config-auth>
[[repeating auth form loop]]
Login denied.  Your system does not meet the minumium security requirement to
access the XXXX Network.  If you  need assistance please contact the helpdesk.
Your client certificate will be used for authentication
GROUP:
[ANYCONNECT|AnyConnect|GPUpdate|PIV|PIV-Access|VDI|XXXX_Secure_Tunnel|client|gfe|piv|piv-exempt|ts]:
^Cfgets (stdin): Interrupted system call
David Woodhouse
2018-10-05 18:22:31 UTC
Permalink
Post by Ray Lambert
Thanks for the patch.
Login denied.  Your system does not meet the minumium security requirement
to access the XXXXX Network.  If you  need assistance please contact the
helpdesk.
Your client certificate will be used for authentication
And it then prompts for a group, username etc.
I'm still getting the same response as before to the hostscan
("TOKEN_SUCCESS").  Did that response look good to you (I've never seen a
good one so I can't judge)?  I'm guessing either hostscan did not actually
work or we're missing something in the later requests.
OK so the patch works. You see TOKEN_SUCCESS when you post a resposer
regardless of whether it's acceptable or not. You have more work to do, to
work out what the real hostscan would be asking for and what the correct
answers are.
--
dwmw2
Ray Lambert
2018-10-05 19:00:59 UTC
Permalink
Post by David Woodhouse
OK so the patch works. You see TOKEN_SUCCESS when you post a resposer
regardless of whether it's acceptable or not. You have more work to do, to
work out what the real hostscan would be asking for and what the correct
answers are.
Okay, thanks for confirming.

Do you have any pointers on figuring out what hostscan wants to see?  I don't
have access to a working one that I peek at.

Would you like me to do anything with the patch?

Thanks again,

~ray
Daniel Lenski
2018-10-09 21:38:29 UTC
Permalink
Post by Ray Lambert
Post by David Woodhouse
OK so the patch works. You see TOKEN_SUCCESS when you post a resposer
regardless of whether it's acceptable or not. You have more work to do, to
work out what the real hostscan would be asking for and what the correct
answers are.
Okay, thanks for confirming.
Do you have any pointers on figuring out what hostscan wants to see? I don't
have access to a working one that I peek at.
Corey Gilks wrote a tool that tries to figure out what your VPN's
hostscan wants to receive: https://github.com/Gilks/hostscan-bypass

You might want to see this thread from August:
http://lists.infradead.org/pipermail/openconnect-devel/2018-August/005024.html

"In some cases hostscan can be looking for the existence of specific
registry keys or software. Without the correct values the connection
may be rejected. On the other hand, failure to provide the correct
values may result in a successful connection but could result in being
placed in a restricted vlan. It really comes down to how the
administrators configured hostscan. If you find yourself in a scenario
where the static CSD files (such as the one you linked) are not
allowing you to connect then you will need to MITM the correct values
from an AnyConnect client.
That's where hostscan-bypass comes in handy!"
Ray Lambert
2018-10-09 23:54:51 UTC
Permalink
Hi Daniel,

Thanks for the response.  I had seen these things except for the wrapper
script from David Woodhouse (linked to on the list).  I tried that one but I
was unsurprised when it did not work (you'll see why...).

hostscan-bypass did not work for me.  It appears to be creating a MITM attack
and capturing the hostscan response.  The code appears to be scraping lines
from the response that have "endpoint" in them and inserting those into a
boilerplate script.  Importantly, it does not modify the lines, which implies
they must constitute a correct response to being with.  My guess is that this
tool is only useful if you have another machine (Windows likely) that already
works (I don't).  I do have an AC Linux client but it is an old one and I
think it is not compatible with my org's new VPN.  I can't use it anyway
because Cisco's client does not have *any* support for PIV cards (one might
think they could at least accept a PK11 URI like OC does, but, well... Cisco).

I do have my org's data.xml and I've been trying to guess how to build a
valid response from it.  I think I am probably very close but it's hard to
know what I'm missing because I don't know what it's looking for.  To make
matters worse, my org's vpn appears to use a newer version of hostscan with a
different response format. Most examples I've found online use the old
response format (which uses terms like "av" and "fw").  The new one uses "am"
(anti-malware) and "pfw" (personal firewall).  The changes are described
(high-level) in a Cisco migration document:

https://www.cisco.com/c/en/us/td/docs/security/asa/migration/guide/HostscanMigration43x-46x.html

(Look for "Endpoint Attribute Definitions" about halfway down.)

This doc contains some examples of the responses they want. There appears to
be added fields relative to the older format.  As you probably know, the
backend validates the response using a Lua script which can theoretically
contain almost anything the administrator wants to include.  (If I could get
that script this would be easy... :|  )

I think I need to start a dialog with my IT dept next (I've been waiting for
my manager to return to the office).  However, I'm not very hopeful about
that because past experiences have demonstrated that they barely know
anything about the stuff they're using (I hope that's not typical but I fear
it is).  I might be able to get help from Cisco through them (but that's a
whole other can of worms...  :|

Anyway, thanks again!

~ray
Post by Daniel Lenski
Post by Ray Lambert
Post by David Woodhouse
OK so the patch works. You see TOKEN_SUCCESS when you post a resposer
regardless of whether it's acceptable or not. You have more work to do, to
work out what the real hostscan would be asking for and what the correct
answers are.
Okay, thanks for confirming.
Do you have any pointers on figuring out what hostscan wants to see? I don't
have access to a working one that I peek at.
Corey Gilks wrote a tool that tries to figure out what your VPN's
hostscan wants to receive: https://github.com/Gilks/hostscan-bypass
http://lists.infradead.org/pipermail/openconnect-devel/2018-August/005024.html
"In some cases hostscan can be looking for the existence of specific
registry keys or software. Without the correct values the connection
may be rejected. On the other hand, failure to provide the correct
values may result in a successful connection but could result in being
placed in a restricted vlan. It really comes down to how the
administrators configured hostscan. If you find yourself in a scenario
where the static CSD files (such as the one you linked) are not
allowing you to connect then you will need to MITM the correct values
from an AnyConnect client.
That's where hostscan-bypass comes in handy!"
Loading...