unable to use RSA SecureID on Unbuntu 14.04 LTS 64 bit
Mark Kolmar
mark at burningrome.com
Tue Jul 29 15:18:07 PDT 2014
Regarding the code changes: Do you recommend using stoken
0.8~20140721085000-1ppa1~trusty from the PPA? Offhand, it looks like
that is a package appropriate for Ubuntu 14.04 (64 bit?), and the source
can be downloaded at https://github.com/cernekee/stoken.
Or is this a good starting point? I have local copies of the source,
which I built and installed:
-------
$ stoken --version
stoken 0.6 - software token for Linux/UNIX systems
Copyright (C) 2014 Kevin Cernekee <cernekee at gmail.com>
...
$ openconnect --version
OpenConnect version v6.00
Using OpenSSL. Features present: TPM (OpenSSL ENGINE not present), RSA
software token, HOTP software token, TOTP software token, DTLS
------
Using stoken or stoken-gui will not work the way you suggest.
Authentication requires two passwords. The first password requested in
the Cisco AnyConnect GUI would be the tokencode, and is entered
manually. Under that, a second password is entered. As it is not
possible to specify the prefix or supply the first password directly
using openconnect, the VPN server does not accept the generated tokencode.
The example below works for the old VPN. I enter the password manually.
(VPN server happens to authenticate against AD/LDAP with no tokencode.)
$ sudo openconnect --no-cert-check -u User_Name https://vpn.company.com/
On the new VPN, the server requires the token code (with prefix) as a
first password, then a second password as in the case above. Without
being able to send the server a soft token it accepts, it isn't clear
whether openconnect would prompt for a second password or what the
response would be from the server. (It doesn't appear that AnyConnect
logs the raw server output to let me send an example of success there.)
Neither the token code nor the AD/LDAP password are sufficient, and both
fail the same way when using openconnect. Here is an example. I will
paste a dump of HTTP output at the end.
$ sudo openconnect --no-cert-check --no-xmlpost --token-mode=rsa
--os=win --user=User_Name https://newvpn.company.com/
[prompts to unlock token]
[server interaction]
Please enter your username and password.
Generating RSA token code
POST https://....
Server is rejecting the soft token; switching to manual entry
Login failed.
Please enter your username and password.
Username: User_Name
Password:
POST https://....
Server is rejecting the soft token; switching to manual entry
Login failed.
Please enter your username and password.
...
--Mark
Here is the raw HTTP.
$ sudo openconnect --dump-http-traffic --no-cert-check --no-xmlpost
--token-mode=rsa --os=win --user=User_Name https://vpn.company.com/
Enter credentials to unlock software token.
Password:
Soft token init was successful.
GET https://vpn.company.com/
Attempting to connect to server 99.99.99.99:443
SSL negotiation with vpn.company.com
Matched DNS altname 'vpn.company.com'
Connected to HTTPS on vpn.company.com
> GET / HTTP/1.1
> Host: vpn.company.com
> User-Agent: Open AnyConnect VPN Agent v6.00
> Accept: */*
> Accept-Encoding: identity
> X-Transcend-Version: 1
>
Got HTTP response: HTTP/1.0 302 Temporary moved
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Tue, 29 Jul 2014 22:08:21 GMT
Location: https://vpn.company.com/
HTTP body length: (0)
GET https://vpn.company.com/
Attempting to connect to server 99.99.99.99:443
SSL negotiation with vpn.company.com
Matched DNS altname 'vpn.company.com'
Connected to HTTPS on vpn.company.com
> GET / HTTP/1.1
> Host: vpn.company.com
> User-Agent: Open AnyConnect VPN Agent v6.00
> Accept: */*
> Accept-Encoding: identity
> X-Transcend-Version: 1
>
Got HTTP response: HTTP/1.0 302 Object Moved
Content-Type: text/html; charset=utf-8
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Tue, 29 Jul 2014 22:08:23 GMT
Location: /+webvpn+/index.html
Set-Cookie: tg=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
HTTP body length: (0)
GET https://vpn.company.com/+webvpn+/index.html
SSL negotiation with vpn.company.com
Matched DNS altname 'vpn.company.com'
Connected to HTTPS on vpn.company.com
> GET /+webvpn+/index.html HTTP/1.1
> Host: vpn.company.com
> User-Agent: Open AnyConnect VPN Agent v6.00
> Accept: */*
> Accept-Encoding: identity
> X-Transcend-Version: 1
>
Got HTTP response: HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/xml
Cache-Control: max-age=0
Set-Cookie: webvpn=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
Set-Cookie: webvpnc=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
Set-Cookie: webvpnlogin=1; secure
X-Transcend-Version: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <auth id="main">
< <title>SSL VPN Service</title>
< <ca status="disabled" href="/+CSCOCA+/login.html" />
<
<
<
< <banner></banner>
< <message>Please enter your username and password.</message>
<
<
< <form method="post" action="/+webvpn+/index.html">
<
< <input type="text" name="username" label="Username:" />
< <input type="password" name="password" label="Password:" />
<
<
<
<
< <input type="submit" name="Login" value="Login" />
< <input type="reset" name="Clear" value="Clear" />
<
<
< </form>
< </auth>
<
OK to generate INITIAL tokencode
Please enter your username and password.
Generating RSA token code
POST https://vpn.company.com/+webvpn+/index.html
> POST /+webvpn+/index.html HTTP/1.1
> Host: vpn.company.com
> User-Agent: Open AnyConnect VPN Agent v6.00
> Accept: */*
> Accept-Encoding: identity
> Cookie: webvpnlogin=1
> X-Transcend-Version: 1
> X-Pad: 00000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 38
>
> username=User%5FName&password=[*** 6-digit tokencode ***]
Got HTTP response: HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/xml
Cache-Control: max-age=0
Set-Cookie: webvpn=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
Set-Cookie: webvpnc=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
Set-Cookie: webvpnlogin=1; secure
X-Transcend-Version: 1
HTTP body chunked (-2)
< <?xml version="1.0" encoding="UTF-8"?>
< <auth id="main">
< <title>SSL VPN Service</title>
< <ca status="disabled" href="/+CSCOCA+/login.html" />
<
<
<
< <banner></banner>
< <message>Please enter your username and password.</message>
<
<
< <error id="15" param1="" param2="">Login failed.</error>
< <form method="post" action="/+webvpn+/index.html">
<
< <input type="text" name="username" label="Username:" />
< <input type="password" name="password" label="Password:" />
<
<
<
<
< <input type="submit" name="Login" value="Login" />
< <input type="reset" name="Clear" value="Clear" />
<
<
< </form>
< </auth>
<
Server is rejecting the soft token; switching to manual entry
Login failed.
Please enter your username and password.
Username:
On 7/29/2014 2:05 PM, Kevin Cernekee wrote:
> On Tue, Jul 29, 2014 at 7:35 AM, Mark Kolmar <mark at burningrome.com> wrote:
>> I wrote earlier about the need to use a prefix with the token generated from stoken to form a password. When we left off, the idea was to use --token-prefix or similar to allow the PIN/prefix to be specified on the command line, and/or a way to supply the entire first password (prefix+token, or arbitrary string for testing).
>>
>> Without this, it will not be possible to authenticate to the company's VPN under Linux. Therefore it would be necessary to purchase a full Windows license, etc., etc.
>
> As a temporary workaround can you run "stoken-gui --small" on your
> desktop, and copy/paste the tokencode into the password field when
> connecting?
>
>> This change is probably something I am capable of doing. Would someone be able to offer some hints about where to add code for the command line option and where the first password is formed? Meanwhile, I will see if I can't figure this out. Or is the enhancement already in progress, or maybe even ready to test?
>
> I added a new field in stoken_info to support this use case. Using
> the libstoken API v1.3+, you should be able to do something like:
>
> #define PASSCODE_PREFIX_LEN 16
>
> struct stoken_info *info = stoken_get_info(ctx);
> char pin[PASSCODE_PREFIX_LEN + 1] = { 0 };
> char tokencode[STOKEN_MAX_TOKENCODE + 1];
> char passcode[PASSCODE_PREFIX_LEN + STOKEN_MAX_TOKENCODE + 1];
>
> if (!info)
> return -EIO;
>
> if (stoken_pin_required(ctx)) {
> prompt("SecurID PIN (required): ", pin, PASSCODE_PREFIX_LEN);
> /* keep prompting until stoken_check_pin() == 0 */
> } else if (!info->uses_pin)
> prompt("SecurID PIN (optional): ", pin, PASSCODE_PREFIX_LEN);
> /* else: PIN was already fetched from ~/.stokenrc; do not prompt */
>
> if (securid_compute_tokencode(ctx, time(NULL), pin, tokencode))
> return -EIO;
>
> snprintf(passcode, sizeof(passcode), "%s%s",
> info->uses_pin ? "" : pin, tokencode);
>
>
> I did not find a good way of figuring out whether the token is PINless
> (no PIN at all, either prepended or incorporated into the tokencode
> computation). For this case the user will need to enter "" for the
> PIN, so the raw tokencode is sent as the passcode.
>
> BTW, if you're going to help update this code, there are a few other
> changes needed to support recent libstoken enhancements:
>
> 1) The stoken_pin_required() check should be moved after
> stoken_decrypt_seed() to support using the new "v3" seeds with
> --token-secret. On "v3" tokens, most of the metadata is encrypted
> with the password/devid (if any). Existing v1/v2 tokens are
> unaffected.
>
> 2) If --token-secret points to a file, read the file contents into
> token_str. This would allow sdtid (XML) tokens to be used directly;
> it may also be helpful in keeping token strings (basically keys) from
> showing up in "ps".
>
More information about the openconnect-devel
mailing list