Friday, November 15, 2013

cisco VPN with openconnect and Belgian EID

This is a quick howto to get the Belgian EID working with openconnect and connect to a cisco VPN. This will probably work for other pki cards too, but I can ofcourse only test with my EID.
The steps below are done on a Fedora 18 box. Fedora 18 comes out of the box with the software for cardreaders and cards. So I will not address this here. Find the relevant info for your distro if opensc / pcsc is missing.
If you have the right software you will be able to check for your reader with:
# opensc-tool --info
opensc 0.12.2 [gcc  4.7.1 20120720 (Red Hat 4.7.1-5)]
Enabled features: zlib readline openssl pcsc(libpcsclite.so.1)
# opensc-tool --list-readers
Detected readers (pcsc)
Nr.  Card  Features  Name
0    Yes             Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
It's a Dell with built-in smartcard reader.
If you insert a card the reader should detect it and you can ask for the name of the card:
# opensc-tool --name
Using reader with a card: Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00
Belpic cards
Openconnect uses pkcs. So in order that pkcs11 can use the cardreader, it should be linked to opensc. This isn't out of the box (yet). So configure that pkcs11 loads the opensc module by creating the following file:
# cat /etc/pkcs11/modules/opensc.module
module: opensc-pkcs11.so
Now you can test your EID card with p11tool. If all works well, it will ask for your pin and displays the certs.
# p11tool --list-certs --login
Token 'BELPIC (Basic PIN)' with URL 'pkcs11:model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29' requires user PIN
Enter PIN: 
Object 0:
    URL: pkcs11:library-description=Smart%20card%20PKCS%2311%20API;library-manufacturer=OpenSC%20%28www.opensc-project.org%29;model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29;id=%02;object=Authentication;object-type=cert
    Type: X.509 Certificate
    Label: Authentication
    ID: 02

Object 1:
    URL: pkcs11:library-description=Smart%20card%20PKCS%2311%20API;library-manufacturer=OpenSC%20%28www.opensc-project.org%29;model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29;id=%03;object=Signature;object-type=cert
    Type: X.509 Certificate
    Label: Signature
    ID: 03

Object 2:
    URL: pkcs11:library-description=Smart%20card%20PKCS%2311%20API;library-manufacturer=OpenSC%20%28www.opensc-project.org%29;model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29;id=%04;object=CA;object-type=cert
    Type: X.509 Certificate
    Label: CA
    ID: 04

Object 3:
    URL: pkcs11:library-description=Smart%20card%20PKCS%2311%20API;library-manufacturer=OpenSC%20%28www.opensc-project.org%29;model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29;id=%06;object=Root;object-type=cert                                                            
    Type: X.509 Certificate
    Label: Root
    ID: 06
To make the connection to cisco we need the Authentication and the CA for the chain. The current version doesn't pick up the CA automatically from the card. This will be fixed in future version of gnutls (current git or 3.2.7 when it's released; thxs to Nikos Mavrogiannopoulos). In order to include the CA (when it's not done automatically), you can export the CA to a file. Remember to copy the right string from the --list-certs output. Here we see that the CA is id=04 and object-type=cert. Copy the URL from token= till the end and put 'pkcs11:' in front of it:
# p11tool --export 'pkcs11:token=BELPIC%20%28Basic%20PIN%29;id=%04;object=CA;object-type=cert' --login --outfile myca.crt
Token 'BELPIC (Basic PIN)' with URL 'pkcs11:model=PKCS%2315;manufacturer=%28unknown%29;serial=123456789ABCDEF;token=BELPIC%20%28Basic%20PIN%29' requires user PIN
Enter PIN: 
# head -1 myca.crt
-----BEGIN CERTIFICATE-----
The file should start with a line as shown above.
So we have the CA (myca.crt) and the Authentication (id=02). Now you can make the connection with following command:
# openconnect -v --cafile myca.crt -c 'pkcs11:token=BELPIC%20%28Basic%20PIN%29;id=%02' https://vpn.example.com
Attempting to connect to server a.b.c.d:443
Using PKCS#11 certificate pkcs11:token=BELPIC%20%28Basic%20PIN%29;id=%02;object-type=cert;pin-source=openconnect%3a0x1582910
PIN required for BELPIC (Basic PIN)
Enter PIN:
Using PKCS#11 key pkcs11:token=BELPIC%20%28Basic%20PIN%29;id=%02;object-type=private;pin-source=openconnect%3a0x1582910
Using client certificate 'Christof Haerens (Authentication)'
Adding supporting CA 'Citizen CA'
SSL negotiation with vpn.example.com
Connected to HTTPS on vpn.example.com
GET https://vpn.example.com/
Got HTTP response: HTTP/1.0 302 Object Moved
Content-Type: text/html
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Connection: Close
Date: Thu, 07 Nov 2013 22:14:24 GMT
Location: /+webvpn+/index.html
Set-Cookie: tg=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; secure
HTTP body length:  (0)
SSL negotiation with vpn.example.com
Connected to HTTPS on vpn.example.com
GET https://vpn.example.com/+webvpn+/index.html
Got HTTP response: HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/xml
Cache-Control: max-age=0
Set-Cookie: ***********
Set-Cookie: ***********
Set-Cookie: ***********
X-Transcend-Version: 1
HTTP body chunked (-2)
TCP_INFO rcv mss 1380, snd mss 1380, adv mss 1460, pmtu 1500
Got CONNECT response: HTTP/1.1 200 OK 

An important part in the output is the line Adding supporting CA 'Citizen CA'. This shows that our CA is loaded.

Many thanks go to David Woodhouse of infradead, who was kind enough to help me debugging on parts where I was stuck.