Tag version 4.00
[platform/upstream/openconnect.git] / gnutls.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2012 Intel Corporation.
5  *
6  * Author: David Woodhouse <dwmw2@infradead.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to:
19  *
20  *   Free Software Foundation, Inc.
21  *   51 Franklin Street, Fifth Floor,
22  *   Boston, MA 02110-1301 USA
23  */
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <errno.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39
40 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
41 /* Shut up about gnutls_sign_callback_set() being deprecated. We only use it
42    in the GnuTLS 2.12 case, and there just isn't another way of doing it. */
43 #define GNUTLS_INTERNAL_BUILD 1
44 #endif
45
46 #include <gnutls/gnutls.h>
47 #include <gnutls/x509.h>
48 #include <gnutls/crypto.h>
49 #include <gnutls/pkcs12.h>
50 #include <gnutls/abstract.h>
51
52 #ifdef HAVE_TROUSERS
53 #include <trousers/tss.h>
54 #include <trousers/trousers.h>
55 #endif
56 #ifdef HAVE_P11KIT
57 #include <p11-kit/p11-kit.h>
58 #include <p11-kit/pkcs11.h>
59 #include <p11-kit/pin.h>
60
61 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
62                                const char *pin_description,
63                                P11KitPinFlags flags,
64                                void *_vpninfo);
65 #endif
66
67 #include "gnutls.h"
68 #include "openconnect-internal.h"
69
70 /* Helper functions for reading/writing lines over SSL.
71    We could use cURL for the HTTP stuff, but it's overkill */
72
73 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
74 {
75         size_t orig_len = len;
76
77         while (len) {
78                 int done = gnutls_record_send(vpninfo->https_sess, buf, len);
79                 if (done > 0)
80                         len -= done;
81                 else if (done != GNUTLS_E_AGAIN) {
82                         vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket: %s"),
83                                      gnutls_strerror(done));
84                         return -EIO;
85                 } else {
86                         fd_set wr_set, rd_set;
87                         int maxfd = vpninfo->ssl_fd;
88
89                         FD_ZERO(&wr_set);
90                         FD_ZERO(&rd_set);
91                         
92                         if (gnutls_record_get_direction(vpninfo->https_sess))
93                                 FD_SET(vpninfo->ssl_fd, &wr_set);
94                         else
95                                 FD_SET(vpninfo->ssl_fd, &rd_set);
96
97                         if (vpninfo->cancel_fd != -1) {
98                                 FD_SET(vpninfo->cancel_fd, &rd_set);
99                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
100                                         maxfd = vpninfo->cancel_fd;
101                         }
102                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
103                         if (vpninfo->cancel_fd != -1 &&
104                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
105                                 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
106                                 return -EINTR;
107                         }
108                 }
109         }
110         return orig_len;
111 }
112
113 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
114 {
115         int done;
116
117         while ((done = gnutls_record_recv(vpninfo->https_sess, buf, len)) < 0) {
118                 fd_set wr_set, rd_set;
119                 int maxfd = vpninfo->ssl_fd;
120
121                 if (done != GNUTLS_E_AGAIN) {
122                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s"),
123                                      gnutls_strerror(done));
124                         return -EIO;
125                 } else {
126                         FD_ZERO(&wr_set);
127                         FD_ZERO(&rd_set);
128                         
129                         if (gnutls_record_get_direction(vpninfo->https_sess))
130                                 FD_SET(vpninfo->ssl_fd, &wr_set);
131                         else
132                                 FD_SET(vpninfo->ssl_fd, &rd_set);
133
134                         if (vpninfo->cancel_fd != -1) {
135                                 FD_SET(vpninfo->cancel_fd, &rd_set);
136                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
137                                         maxfd = vpninfo->cancel_fd;
138                         }
139                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
140                         if (vpninfo->cancel_fd != -1 &&
141                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
142                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
143                                 return -EINTR;
144                         }
145                 }
146         }
147         return done;
148 }
149
150 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
151 {
152         int i = 0;
153         int ret;
154
155         if (len < 2)
156                 return -EINVAL;
157
158         while (1) {
159                 ret = gnutls_record_recv(vpninfo->https_sess, buf + i, 1);
160                 if (ret == 1) {
161                         if (buf[i] == '\n') {
162                                 buf[i] = 0;
163                                 if (i && buf[i-1] == '\r') {
164                                         buf[i-1] = 0;
165                                         i--;
166                                 }
167                                 return i;
168                         }
169                         i++;
170
171                         if (i >= len - 1) {
172                                 buf[i] = 0;
173                                 return i;
174                         }
175                 } else if (ret != GNUTLS_E_AGAIN) {
176                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket: %s\n"),
177                                      gnutls_strerror(ret));
178                         ret = -EIO;
179                         break;
180                 } else {
181                         fd_set rd_set, wr_set;
182                         int maxfd = vpninfo->ssl_fd;
183                         
184                         FD_ZERO(&rd_set);
185                         FD_ZERO(&wr_set);
186                         
187                         if (gnutls_record_get_direction(vpninfo->https_sess))
188                                 FD_SET(vpninfo->ssl_fd, &wr_set);
189                         else
190                                 FD_SET(vpninfo->ssl_fd, &rd_set);
191
192                         if (vpninfo->cancel_fd != -1) {
193                                 FD_SET(vpninfo->cancel_fd, &rd_set);
194                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
195                                         maxfd = vpninfo->cancel_fd;
196                         }
197                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
198                         if (vpninfo->cancel_fd != -1 &&
199                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
200                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
201                                 ret = -EINTR;
202                                 break;
203                         }
204                 }
205         }
206         buf[i] = 0;
207         return i ?: ret;
208 }
209
210 static int check_certificate_expiry(struct openconnect_info *vpninfo, gnutls_x509_crt_t cert)
211 {
212         const char *reason = NULL;
213         time_t expires = gnutls_x509_crt_get_expiration_time(cert);
214         time_t now = time(NULL);
215
216         if (expires == -1) {
217                 vpn_progress(vpninfo, PRG_ERR,
218                              _("Could not extract expiration time of certificate\n"));
219                 return -EINVAL;
220         }
221
222         if (expires < now)
223                 reason = _("Client certificate has expired at");
224         else if (expires < now + vpninfo->cert_expire_warning)
225                 reason = _("Client certificate expires soon at");
226
227         if (reason) {
228                 struct tm tm;
229                 char buf[80];
230
231                 gmtime_r(&expires, &tm);
232                 strftime(buf, 80, "%a, %d %b %Y %T %Z", &tm);
233
234                 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, buf);
235         }
236         return 0;
237 }
238
239 /* For systems that don't support O_CLOEXEC, just don't bother.
240    It's not open for long anyway. */
241 #ifndef O_CLOEXEC
242 #define O_CLOEXEC
243 #endif
244
245 static int load_datum(struct openconnect_info *vpninfo,
246                       gnutls_datum_t *datum, const char *fname)
247 {
248         struct stat st;
249         int fd, err;
250 #ifdef ANDROID_KEYSTORE
251         if (!strncmp(fname, "keystore:", 9)) {
252                 int len;
253                 const char *p = fname + 9;
254
255                 /* Skip first two slashes if the user has given it as
256                    keystore://foo ... */
257                 if (*p == '/')
258                         p++;
259                 if (*p == '/')
260                         p++;
261                 len = keystore_fetch(p, &datum->data);
262                 if (len <= 0) {
263                         vpn_progress(vpninfo, PRG_ERR,
264                                      _("Failed to load item '%s' from keystore: %s\n"),
265                                      p, keystore_strerror(len));
266                         return -EINVAL;
267                 }
268                 datum->size = len;
269                 return 0;
270         }
271 #endif
272
273         fd = open(fname, O_RDONLY|O_CLOEXEC);
274         if (fd == -1) {
275                 err = errno;
276                 vpn_progress(vpninfo, PRG_ERR,
277                              _("Failed to open key/certificate file %s: %s\n"),
278                              fname, strerror(err));
279                 return -ENOENT;
280         }
281         if (fstat(fd, &st)) {
282                 err = errno;
283                 vpn_progress(vpninfo, PRG_ERR,
284                              _("Failed to stat key/certificate file %s: %s\n"),
285                              fname, strerror(err));
286                 close(fd);
287                 return -EIO;
288         }
289         datum->size = st.st_size;
290         datum->data = gnutls_malloc(st.st_size + 1);
291         if (!datum->data) {
292                 vpn_progress(vpninfo, PRG_ERR,
293                              _("Failed to allocate certificate buffer\n"));
294                 close(fd);
295                 return -ENOMEM;
296         }
297         errno = EAGAIN;
298         if (read(fd, datum->data, datum->size) != datum->size) {
299                 err = errno;
300                 vpn_progress(vpninfo, PRG_ERR,
301                              _("Failed to read certificate into memory: %s\n"),
302                              strerror(err));
303                 close(fd);
304                 gnutls_free(datum->data);
305                 return -EIO;
306         }
307         datum->data[st.st_size] = 0;
308         close(fd);
309         return 0;
310 }
311
312 /* A non-zero, non-error return to make load_certificate() continue and
313    interpreting the file as other types */
314 #define NOT_PKCS12      1
315
316 static int load_pkcs12_certificate(struct openconnect_info *vpninfo,
317                                    gnutls_datum_t *datum,
318                                    gnutls_x509_privkey_t *key,
319                                    gnutls_x509_crt_t **chain,
320                                    unsigned int *chain_len,
321                                    gnutls_x509_crt_t **extra_certs,
322                                    unsigned int *extra_certs_len,
323                                    gnutls_x509_crl_t *crl)
324 {
325         gnutls_pkcs12_t p12;
326         char *pass;
327         int err;
328
329         err = gnutls_pkcs12_init(&p12);
330         if (err) {
331                 vpn_progress(vpninfo, PRG_ERR,
332                              _("Failed to setup PKCS#12 data structure: %s\n"),
333                              gnutls_strerror(err));
334                 return -EIO;
335         }
336
337         err = gnutls_pkcs12_import(p12, datum, GNUTLS_X509_FMT_DER, 0);
338         if (err) {
339                 gnutls_pkcs12_deinit(p12);
340                 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN)
341                         return NOT_PKCS12;
342                 vpn_progress(vpninfo, PRG_ERR,
343                              _("Failed to import PKCS#12 file: %s\n"),
344                              gnutls_strerror(err));
345                 return -EINVAL;
346         }
347
348         pass = vpninfo->cert_password;
349         while ((err = gnutls_pkcs12_verify_mac(p12, pass)) == GNUTLS_E_MAC_VERIFY_FAILED) {
350                 if (pass)
351                         vpn_progress(vpninfo, PRG_ERR,
352                                      _("Failed to decrypt PKCS#12 certificate file\n"));
353                 free(pass);
354                 vpninfo->cert_password = NULL;
355                 err = request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
356                                          _("Enter PKCS#12 pass phrase:"));
357                 if (err) {
358                         gnutls_pkcs12_deinit(p12);
359                         return -EINVAL;
360                 }
361         }
362         /* If it wasn't GNUTLS_E_MAC_VERIFY_FAILED, then the problem wasn't just a
363            bad password. Give up. */
364         if (err) {
365                 int level = PRG_ERR;
366                 int ret = -EINVAL;
367
368                 gnutls_pkcs12_deinit(p12);
369
370                 /* If the first attempt, and we didn't know for sure it was PKCS#12
371                    anyway, bail out and try loading it as something different. */
372                 if (pass == vpninfo->cert_password &&
373                     vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
374                         /* Make it non-fatal... */
375                         level = PRG_TRACE;
376                         ret = NOT_PKCS12;
377                 }
378
379                 vpn_progress(vpninfo, level,
380                              _("Failed to process PKCS#12 file: %s\n"),
381                                gnutls_strerror(err));
382                 return ret;
383         }
384         err = gnutls_pkcs12_simple_parse(p12, pass, key, chain, chain_len,
385                                          extra_certs, extra_certs_len, crl, 0);
386         free(pass);
387         vpninfo->cert_password = NULL;
388
389         gnutls_pkcs12_deinit(p12);
390         if (err) {
391                 vpn_progress(vpninfo, PRG_ERR,
392                              _("Failed to load PKCS#12 certificate: %s\n"),
393                              gnutls_strerror(err));
394                 return -EINVAL;
395         }
396         return 0;
397 }
398
399 /* Older versions of GnuTLS didn't actually bother to check this, so we'll
400    do it for them. */
401 static int check_issuer_sanity(gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer)
402 {
403 #if GNUTLS_VERSION_NUMBER > 0x300014
404         return 0;
405 #else
406         unsigned char id1[512], id2[512];
407         size_t id1_size = 512, id2_size = 512;
408         int err;
409
410         err = gnutls_x509_crt_get_authority_key_id(cert, id1, &id1_size, NULL);
411         if (err)
412                 return 0;
413
414         err = gnutls_x509_crt_get_subject_key_id(issuer, id2, &id2_size, NULL);
415         if (err)
416                 return 0;
417         if (id1_size == id2_size && !memcmp(id1, id2, id1_size))
418                 return 0;
419
420         /* EEP! */
421         return -EIO;
422 #endif
423 }
424
425 static int count_x509_certificates(gnutls_datum_t *datum)
426 {
427         int count = 0;
428         char *p = (char *)datum->data;
429
430         while (p) {
431                 p = strstr(p, "-----BEGIN ");
432                 if (!p)
433                         break;
434                 p += 11;
435                 if (!strncmp(p, "CERTIFICATE", 11) ||
436                     !strncmp(p, "X509 CERTIFICATE", 16))
437                     count++;
438         }
439         return count;
440 }
441
442 static int get_cert_name(gnutls_x509_crt_t cert, char *name, size_t namelen)
443 {
444         if (gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
445                                           0, 0, name, &namelen) &&
446             gnutls_x509_crt_get_dn(cert, name, &namelen)) {
447                 name[namelen-1] = 0;
448                 snprintf(name, namelen-1, "<unknown>");
449                 return -EINVAL;
450         }
451         return 0;
452 }
453
454 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
455 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
456 /* For GnuTLS 2.12 even if we *have* a privkey (as we do for PKCS#11), we
457    can't register it. So we have to use the cert_callback function. This
458    just hands out the certificate chain we prepared in load_certificate().
459    If we have a pkey then return that too; otherwise leave the key NULL —
460    we'll also have registered a sign_callback for the session, which will
461    handle that. */
462 static int gtls_cert_cb(gnutls_session_t sess, const gnutls_datum_t *req_ca_dn,
463                         int nreqs, const gnutls_pk_algorithm_t *pk_algos,
464                         int pk_algos_length, gnutls_retr2_st *st) {
465
466         struct openconnect_info *vpninfo = gnutls_session_get_ptr(sess);
467         int algo = GNUTLS_PK_RSA; /* TPM */
468         int i;
469
470 #ifdef HAVE_P11KIT
471         if (vpninfo->my_p11key) {
472                 st->key_type = GNUTLS_PRIVKEY_PKCS11;
473                 st->key.pkcs11 = vpninfo->my_p11key;
474                 algo = gnutls_pkcs11_privkey_get_pk_algorithm(vpninfo->my_p11key, NULL);
475         };
476 #endif
477         for (i = 0; i < pk_algos_length; i++) {
478                 if (algo == pk_algos[i])
479                         break;
480         }
481         if (i == pk_algos_length)
482                 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
483
484         st->cert_type = GNUTLS_CRT_X509;
485         st->cert.x509 = vpninfo->my_certs;
486         st->ncerts = vpninfo->nr_my_certs;
487         st->deinit_all = 0;
488
489         return 0;
490 }
491
492 /* For GnuTLS 2.12, this has to set the cert_callback to the function
493    above, which will return the pkey and certs on demand. Or in the
494    case of TPM we can't make a suitable pkey, so we have to set a
495    sign_callback too (which is done in openconnect_open_https() since
496    it has to be done on the *session*). */
497 static int assign_privkey(struct openconnect_info *vpninfo,
498                           gnutls_privkey_t pkey,
499                           gnutls_x509_crt_t *certs,
500                           unsigned int nr_certs,
501                           gnutls_x509_crt_t *extra_certs,
502                           unsigned int nr_extra_certs)
503 {
504         int i;
505
506         vpninfo->my_certs = gnutls_calloc(nr_certs, sizeof(*certs));
507         if (!vpninfo->my_certs)
508                 return GNUTLS_E_MEMORY_ERROR;
509
510         memcpy(vpninfo->my_certs, certs, nr_certs * sizeof(*certs));
511         vpninfo->nr_my_certs = nr_certs;
512
513         /* We are *keeping* the certs, unlike in GnuTLS 3 where our caller
514            can free them after gnutls_certificate_set_key() has been called.
515            So first wipe the 'certs' array (which is either '&cert' or
516            'supporting_certs' in load_certificate())... */
517         memset(certs, 0, nr_certs * sizeof(*certs));
518
519         /* ... and then also zero out the entries in extra_certs[] that
520            correspond to the certs that we're stealing.
521            We know certs[0] was already stolen by the load_certificate()
522            function so we might as well start at certs[1]. */
523         for (i = 1; i < nr_certs; i++) {
524                 int j;
525                 for (j = 0; j < nr_extra_certs; j++) {
526                         if (vpninfo->my_certs[i] == extra_certs[j]) {
527                                 extra_certs[j] = NULL;
528                                 break;
529                         }
530                 }
531         }
532
533         gnutls_certificate_set_retrieve_function(vpninfo->https_cred,
534                                                  gtls_cert_cb);
535         vpninfo->my_pkey = pkey;
536
537         return 0;
538 }
539 #else /* !SET_KEY */
540
541 /* For GnuTLS 3+ this is saner than the GnuTLS 2.12 version. But still we
542    have to convert the array of X509 certificates to gnutls_pcert_st for
543    ourselves. There's no function that takes a gnutls_privkey_t as the key
544    and gnutls_x509_crt_t certificates. */
545 static int assign_privkey(struct openconnect_info *vpninfo,
546                           gnutls_privkey_t pkey,
547                           gnutls_x509_crt_t *certs,
548                           unsigned int nr_certs,
549                           gnutls_x509_crt_t *extra_certs,
550                           unsigned int nr_extra_certs)
551 {
552         gnutls_pcert_st *pcerts = calloc(nr_certs, sizeof(*pcerts));
553         int i, err;
554
555         if (!pcerts)
556                 return GNUTLS_E_MEMORY_ERROR;
557
558         for (i=0 ; i < nr_certs; i++) {
559                 err = gnutls_pcert_import_x509(pcerts + i, certs[i], 0);
560                 if (err) {
561                         vpn_progress(vpninfo, PRG_ERR,
562                                      _("Importing X509 certificate failed: %s\n"),
563                                      gnutls_strerror(err));
564                         goto free_pcerts;
565                 }
566         }
567
568         err = gnutls_certificate_set_key(vpninfo->https_cred, NULL, 0,
569                                          pcerts, nr_certs, pkey);
570         if (err) {
571                 vpn_progress(vpninfo, PRG_ERR,
572                              _("Setting PKCS#11 certificate failed: %s\n"),
573                              gnutls_strerror(err));
574         free_pcerts:
575                 for (i=0 ; i < nr_certs; i++)
576                         gnutls_pcert_deinit(pcerts + i);
577                 free (pcerts);
578         }
579         return err;
580 }
581 #endif /* !SET_KEY */
582 #endif /* (P11KIT || TROUSERS) */
583
584 static int openssl_hash_password(struct openconnect_info *vpninfo, char *pass,
585                                  gnutls_datum_t *key, gnutls_datum_t *salt)
586 {
587         unsigned char md5[16];
588         gnutls_hash_hd_t hash;
589         int count = 0;
590         int err;
591
592         while (count < key->size) {
593                 err = gnutls_hash_init(&hash, GNUTLS_DIG_MD5);
594                 if (err) {
595                         vpn_progress(vpninfo, PRG_ERR,
596                                      _("Could not initialise MD5 hash: %s\n"),
597                                      gnutls_strerror(err));
598                         return -EIO;
599                 }
600                 if (count) {
601                         err = gnutls_hash(hash, md5, sizeof(md5));
602                         if (err) {
603                         hash_err:
604                                 gnutls_hash_deinit(hash, NULL);
605                                 vpn_progress(vpninfo, PRG_ERR,
606                                              _("MD5 hash error: %s\n"),
607                                              gnutls_strerror(err));
608                                 return -EIO;
609                         }
610                 }
611                 if (pass) {
612                         err = gnutls_hash(hash, pass, strlen(pass));
613                         if (err)
614                                 goto hash_err;
615                 }
616                 err = gnutls_hash(hash, salt->data, salt->size);
617                 if (err)
618                         goto hash_err;
619
620                 gnutls_hash_deinit(hash, md5);
621
622                 if (key->size - count <= sizeof(md5)) {
623                         memcpy(&key->data[count], md5, key->size - count);
624                         break;
625                 }
626
627                 memcpy(&key->data[count], md5, sizeof(md5));
628                 count += sizeof(md5);
629         }
630
631         return 0;
632 }
633
634 static int import_openssl_pem(struct openconnect_info *vpninfo,
635                               gnutls_x509_privkey_t key,
636                               char type, char *pem_header, size_t pem_size)
637 {
638         gnutls_cipher_hd_t handle;
639         gnutls_cipher_algorithm_t cipher;
640         gnutls_datum_t constructed_pem;
641         gnutls_datum_t b64_data;
642         gnutls_datum_t salt, enc_key;
643         unsigned char *key_data;
644         const char *begin;
645         char *pass;
646         char *pem_start = pem_header;
647         int ret, err, i, iv_size;
648
649         if (type == 'E')
650                 begin = "EC PRIVATE KEY";
651         else if (type == 'R')
652                 begin = "RSA PRIVATE KEY";
653         else if (type == 'D')
654                  begin = "DSA PRIVATE KEY";
655         else
656                 return -EINVAL;
657
658         while (*pem_header == '\r' || *pem_header == '\n')
659                 pem_header++;
660
661         if (strncmp(pem_header, "DEK-Info: ", 10)) {
662                 vpn_progress(vpninfo, PRG_ERR,
663                              _("Missing DEK-Info: header from OpenSSL encrypted key\n"));
664                 return -EIO;
665         }
666         pem_header += 10;
667         if (!strncmp(pem_header, "DES-EDE3-CBC,", 13)) {
668                 pem_header += 13;
669                 cipher = GNUTLS_CIPHER_3DES_CBC;
670                 /* Pfft. _gnutls_cipher_get_iv_size() is internal */
671                 iv_size = 8;
672         } else {
673                 char *p = pem_header;
674
675                 while (*p) {
676                         if (*p == ',' || *p == '\r' || *p == '\n' || p == pem_header+20) {
677                                 *p = 0;
678                                 break;
679                         }
680                         p++;
681                 }
682                 vpn_progress(vpninfo, PRG_ERR,
683                              _("Unsupported PEM encryption type: %s\n"),
684                              pem_header);
685                 return -EINVAL;
686         }
687         salt.size = iv_size;
688         salt.data = malloc(salt.size);
689         if (!salt.data)
690                 return -ENOMEM;
691         for (i = 0; i < salt.size * 2; i++) {
692                 unsigned char x;
693                 char *c = &pem_header[i];
694
695                 if (*c >= '0' && *c <= '9')
696                         x = (*c) - '0';
697                 else if (*c >= 'A' && *c <= 'F')
698                         x = (*c) - 'A' + 10;
699                 else {
700                         vpn_progress(vpninfo, PRG_ERR,
701                                      _("Invalid salt in encrypted PEM file\n"));
702                         ret = -EINVAL;
703                         goto out_salt;
704                 }
705                 if (i & 1)
706                         salt.data[i/2] |= x;
707                 else
708                         salt.data[i/2] = x << 4;
709         }
710
711         pem_header += salt.size * 2;
712         if (*pem_header != '\r' && *pem_header != '\n') {
713                 vpn_progress(vpninfo, PRG_ERR,
714                              _("Invalid encrypted PEM file\n"));
715                 ret = -EINVAL;
716                 goto out_salt;
717         }
718         while (*pem_header == '\n' || *pem_header == '\r')
719                 pem_header++;
720
721         /* pem_header should now point to the start of the base64 content.
722            Put a -----BEGIN banner in place before it, so that we can use
723            gnutls_pem_base64_decode_alloc(). The banner has to match the
724            -----END banner, so make sure we get it right... */
725         pem_header -= 6;
726         memcpy(pem_header, "-----\n", 6);
727         pem_header -= strlen(begin);
728         memcpy(pem_header, begin, strlen(begin));
729         pem_header -= 11;
730         memcpy(pem_header, "-----BEGIN ", 11);
731
732         constructed_pem.data = (void *)pem_header;
733         constructed_pem.size = pem_size - (pem_header - pem_start);
734
735         err = gnutls_pem_base64_decode_alloc(begin, &constructed_pem, &b64_data);
736         if (err) {
737                 vpn_progress(vpninfo, PRG_ERR,
738                              _("Error base64-decoding encrypted PEM file: %s\n"),
739                              gnutls_strerror(err));
740                 ret = -EINVAL;
741                 goto out_salt;
742         }
743         if (b64_data.size < 16) {
744                 /* Just to be sure our parsing is OK */
745                 vpn_progress(vpninfo, PRG_ERR,
746                              _("Encrypted PEM file too short\n"));
747                 ret = -EINVAL;
748                 goto out_b64;
749         }
750
751         ret = -ENOMEM;
752         enc_key.size = gnutls_cipher_get_key_size(cipher);
753         enc_key.data = malloc(enc_key.size);
754         if (!enc_key.data)
755                 goto out_b64;
756
757         key_data = malloc(b64_data.size);
758         if (!key_data)
759                 goto out_enc_key;
760
761         pass = vpninfo->cert_password;
762         vpninfo->cert_password = NULL;
763
764         while (1) {
765                 memcpy(key_data, b64_data.data, b64_data.size);
766
767                 ret = openssl_hash_password(vpninfo, pass, &enc_key, &salt);
768                 if (ret)
769                         goto out;
770
771                 err = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
772                 if (err) {
773                         vpn_progress(vpninfo, PRG_ERR,
774                                      _("Failed to initialise cipher for decrypting PEM file: %s\n"),
775                                      gnutls_strerror(err));
776                         gnutls_cipher_deinit(handle);
777                         ret = -EIO;
778                         goto out;
779                 }
780
781                 err = gnutls_cipher_decrypt(handle, key_data, b64_data.size);
782                 gnutls_cipher_deinit(handle);
783                 if (err) {
784                         vpn_progress(vpninfo, PRG_ERR,
785                                      _("Failed to decrypt PEM key: %s\n"),
786                                      gnutls_strerror(err));
787                         ret = -EIO;
788                         goto out;
789                 }
790
791                 /* We have to strip any padding for GnuTLS to accept it.
792                    So a bit more ASN.1 parsing for us.
793                    FIXME: Consolidate with similar code in gnutls_tpm.c */
794                 if (key_data[0] == 0x30) {
795                         gnutls_datum_t key_datum;
796                         int blocksize = gnutls_cipher_get_block_size(cipher);
797                         int keylen = key_data[1];
798                         int ofs = 2;
799
800                         if (keylen & 0x80) {
801                                 int lenlen = keylen & 0x7f;
802                                 keylen = 0;
803
804                                 if (lenlen > 3)
805                                         goto fail;
806
807                                 while (lenlen) {
808                                         keylen <<= 8;
809                                         keylen |= key_data[ofs++];
810                                         lenlen--;
811                                 }
812                         }
813                         keylen += ofs;
814
815                         /* If there appears to be more padding than required, fail */
816                         if (b64_data.size - keylen >= blocksize)
817                                 goto fail;
818
819                         /* If the padding bytes aren't all equal to the amount of padding, fail */
820                         ofs = keylen;
821                         while (ofs < b64_data.size) {
822                                 if (key_data[ofs] != b64_data.size - keylen)
823                                         goto fail;
824                                 ofs++;
825                         }
826
827                         key_datum.data = key_data;
828                         key_datum.size = keylen;
829                         err = gnutls_x509_privkey_import(key, &key_datum, GNUTLS_X509_FMT_DER);
830                         if (!err) {
831                                 ret = 0;
832                                 goto out;
833                         }
834                 }
835  fail:
836                 if (pass) {
837                         vpn_progress(vpninfo, PRG_ERR,  _("Decrypting PEM key failed\n"));
838                         free(pass);
839                 }
840                 err = request_passphrase(vpninfo, "openconnect_pem",
841                                          &pass, _("Enter PEM pass phrase:"));
842                 if (err) {
843                         ret = -EINVAL;
844                         goto out;
845                 }
846         }
847  out:
848         free(key_data);
849         free(pass);
850  out_enc_key:
851         free(enc_key.data);
852  out_b64:
853         free(b64_data.data);
854  out_salt:
855         free(salt.data);
856         return ret;
857 }
858
859 static int load_certificate(struct openconnect_info *vpninfo)
860 {
861         gnutls_datum_t fdata;
862         gnutls_x509_privkey_t key = NULL;
863 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
864         gnutls_privkey_t pkey = NULL;
865         gnutls_datum_t pkey_sig = {NULL, 0};
866         void *dummy_hash_data = &load_certificate;
867 #endif
868 #ifdef HAVE_P11KIT
869         char *cert_url = (char *)vpninfo->cert;
870         char *key_url = (char *)vpninfo->sslkey;
871         gnutls_pkcs11_privkey_t p11key = NULL;
872 #endif
873         char *pem_header;
874         gnutls_x509_crl_t crl = NULL;
875         gnutls_x509_crt_t last_cert, cert = NULL;
876         gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
877         unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
878         unsigned int certs_to_free = 0; /* How many of supporting_certs */
879         int err; /* GnuTLS error */
880         int ret;
881         int i;
882         int cert_is_p11 = 0, key_is_p11 = 0;
883         unsigned char key_id[20];
884         size_t key_id_size = sizeof(key_id);
885         char name[80];
886
887         fdata.data = NULL;
888
889         key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
890         cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
891
892 #ifndef HAVE_P11KIT
893         if (key_is_p11 || cert_is_p11) {
894                 vpn_progress(vpninfo, PRG_ERR,
895                              _("This binary built without PKCS#11 support\n"));
896                 return -EINVAL;
897         }
898 #else
899         /* Install PIN handler if either certificate or key are coming from PKCS#11 */
900         if (key_is_p11 || cert_is_p11) {
901                 CK_OBJECT_CLASS class;
902                 CK_ATTRIBUTE attr;
903                 char pin_source[40];
904                 P11KitUri *uri;
905
906                 sprintf(pin_source, "openconnect:%p", vpninfo);
907                 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
908
909                 uri = p11_kit_uri_new();
910
911                 attr.type = CKA_CLASS;
912                 attr.pValue = &class;
913                 attr.ulValueLen = sizeof(class);
914
915                 /* Add appropriate pin-source and object-type attributes to
916                    both certificate and key URLs, unless they already exist. */
917                 if (cert_is_p11 &&
918                     !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_OBJECT, uri)) {
919                         if (!p11_kit_uri_get_pin_source(uri))
920                                 p11_kit_uri_set_pin_source(uri, pin_source);
921                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
922                                 class = CKO_CERTIFICATE;
923                                 p11_kit_uri_set_attribute(uri, &attr);
924                         }
925                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &cert_url);
926                 }
927
928                 if (key_is_p11 &&
929                     !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_OBJECT, uri)) {
930                         if (!p11_kit_uri_get_pin_source(uri))
931                                 p11_kit_uri_set_pin_source(uri, pin_source);
932                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
933                                 class = CKO_PRIVATE_KEY;
934                                 p11_kit_uri_set_attribute(uri, &attr);
935                         }
936                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_OBJECT, &key_url);
937                 }
938
939                 p11_kit_uri_free(uri);
940         }
941
942         /* Load certificate(s) first... */
943         if (cert_is_p11) {
944                 vpn_progress(vpninfo, PRG_TRACE,
945                              _("Using PKCS#11 certificate %s\n"), cert_url);
946
947                 err = gnutls_x509_crt_init(&cert);
948                 if (err) {
949                         ret = -ENOMEM;
950                         goto out;
951                 }
952                 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
953                 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
954                         err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
955                                                                 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
956                 if (err) {
957                         vpn_progress(vpninfo, PRG_ERR,
958                                      _("Error loading certificate from PKCS#11: %s\n"),
959                                      gnutls_strerror(err));
960                         ret = -EIO;
961                         goto out;
962                 }
963                 goto got_certs;
964         }
965 #endif /* HAVE_P11KIT */
966
967         /* OK, not a PKCS#11 certificate so it must be coming from a file... */
968         vpn_progress(vpninfo, PRG_TRACE,
969                      _("Using certificate file %s\n"), vpninfo->cert);
970
971         /* Load file contents */
972         ret = load_datum(vpninfo, &fdata, vpninfo->cert);
973         if (ret)
974                 return ret;
975
976         /* Is it PKCS#12? */
977         if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
978                             vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
979                 /* PKCS#12 should actually contain certificates *and* private key */
980                 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
981                                               &supporting_certs, &nr_supporting_certs,
982                                               &extra_certs, &nr_extra_certs,
983                                               &crl);
984                 if (ret < 0)
985                         goto out;
986                 else if (!ret) {
987                         if (nr_supporting_certs) {
988                                 cert = supporting_certs[0];
989                                 goto got_key;
990                         }
991                         vpn_progress(vpninfo, PRG_ERR,
992                                      _("PKCS#11 file contained no certificate\n"));
993                         ret = -EINVAL;
994                         goto out;
995                 }
996
997                 /* It returned NOT_PKCS12.
998                    Fall through to try PEM formats. */
999         }
1000
1001         /* We need to know how many there are in *advance*; it won't just allocate
1002            the array for us :( */
1003         nr_extra_certs = count_x509_certificates(&fdata);
1004         if (!nr_extra_certs)
1005                 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
1006
1007         extra_certs = calloc(nr_extra_certs, sizeof(cert));
1008         if (!extra_certs) {
1009                 nr_extra_certs = 0;
1010                 ret = -ENOMEM;
1011                 goto out;
1012         }
1013         err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
1014                                           GNUTLS_X509_FMT_PEM, 0);
1015         if (err <= 0) {
1016                 const char *reason;
1017                 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
1018                         reason = _("No certificate found in file");
1019                 else
1020                         reason = gnutls_strerror(err);
1021
1022                 vpn_progress(vpninfo, PRG_ERR,
1023                              _("Loading certificate failed: %s\n"),
1024                              reason);
1025                 ret = -EINVAL;
1026                 goto out;
1027         }
1028         nr_extra_certs = err;
1029         err = 0;
1030
1031         goto got_certs;
1032  got_certs:
1033         /* Now we have either a single certificate in 'cert', or an array of
1034            them in extra_certs[]. Next we look for the private key ... */
1035 #if defined (HAVE_P11KIT)
1036         if (key_is_p11) {
1037                 vpn_progress(vpninfo, PRG_TRACE,
1038                              _("Using PKCS#11 key %s\n"), key_url);
1039
1040                 err = gnutls_pkcs11_privkey_init(&p11key);
1041                 if (err) {
1042                         vpn_progress(vpninfo, PRG_ERR,
1043                                      _("Error initialising PKCS#11 key structure: %s\n"),
1044                                      gnutls_strerror(err));
1045                         ret = -EIO;
1046                         goto out;
1047                 }
1048
1049                 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
1050                 if (err) {
1051                         vpn_progress(vpninfo, PRG_ERR,
1052                                      _("Error importing PKCS#11 URL %s: %s\n"),
1053                                      key_url, gnutls_strerror(err));
1054                         gnutls_pkcs11_privkey_deinit(p11key);
1055                         ret = -EIO;
1056                         goto out;
1057                 }
1058
1059                 err = gnutls_privkey_init(&pkey);
1060                 if (err) {
1061                         vpn_progress(vpninfo, PRG_ERR,
1062                                      _("Error initialising private key structure: %s\n"),
1063                                      gnutls_strerror(err));
1064                         gnutls_pkcs11_privkey_deinit(p11key);
1065                         ret = -EIO;
1066                         goto out;
1067                 }
1068
1069                 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
1070                 if (err) {
1071                         vpn_progress(vpninfo, PRG_ERR,
1072                                      _("Error importing PKCS#11 key into private key structure: %s\n"),
1073                                      gnutls_strerror(err));
1074                         gnutls_pkcs11_privkey_deinit(p11key);
1075                         ret = -EIO;
1076                         goto out;
1077                 }
1078 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1079                 /* This can be set now and doesn't need to be separately freed.
1080                    It goes with the pkey. This is a PITA; it would be better
1081                    if there was a way to get the p11key *back* from a privkey
1082                    that we *know* is based on one. In fact, since this is only
1083                    for GnuTLS 2.12 and we *know* the gnutls_privkey_st won't
1084                    ever change there, so we *could* do something evil... but
1085                    we won't :) */
1086                 vpninfo->my_p11key = p11key;
1087 #endif /* !SET_KEY */
1088                 goto match_cert;
1089         }
1090 #endif /* HAVE_P11KIT */
1091
1092         /* OK, not a PKCS#11 key so it must be coming from a file... load the
1093            file into memory, unless it's the same as the cert file and we
1094            already loaded that. */
1095         if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
1096                 gnutls_free(fdata.data);
1097                 fdata.data = NULL;
1098
1099                 vpn_progress(vpninfo, PRG_TRACE,
1100                              _("Using private key file %s\n"), vpninfo->sslkey);
1101
1102                 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
1103                 if (ret)
1104                         goto out;
1105         }
1106
1107         /* Is it a PEM file with a TPM key blob? */
1108         if (vpninfo->cert_type == CERT_TYPE_TPM ||
1109             (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
1110              strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
1111 #ifndef HAVE_TROUSERS
1112                 vpn_progress(vpninfo, PRG_ERR,
1113                              _("This version of OpenConnect was built without TPM support\n"));
1114                 return -EINVAL;
1115 #else
1116                 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
1117                 if (ret)
1118                         goto out;
1119
1120                 goto match_cert;
1121 #endif
1122         }
1123
1124         /* OK, try other PEM files... */
1125         gnutls_x509_privkey_init(&key);
1126         if ((pem_header = strstr((char *)fdata.data, "-----BEGIN RSA PRIVATE KEY-----")) ||
1127             (pem_header = strstr((char *)fdata.data, "-----BEGIN DSA PRIVATE KEY-----")) ||
1128             (pem_header = strstr((char *)fdata.data, "-----BEGIN EC PRIVATE KEY-----"))) {
1129                 /* PKCS#1 files, including OpenSSL's odd encrypted version */
1130                 char type = pem_header[11];
1131                 char *p = strchr(pem_header, '\n');
1132                 if (!p) {
1133                         vpn_progress(vpninfo, PRG_ERR,
1134                                      _("Failed to interpret PEM file\n"));
1135                         ret = -EINVAL;
1136                         goto out;
1137                 }
1138                 while (*p == '\n' || *p == '\r')
1139                         p++;
1140
1141                 if (!strncmp(p, "Proc-Type: 4,ENCRYPTED", 22)) {
1142                         p += 22;
1143                         while (*p == '\n' || *p == '\r')
1144                                 p++;
1145                         ret = import_openssl_pem(vpninfo, key, type, p,
1146                                                  fdata.size - (p - (char *)fdata.data));
1147                         if (ret)
1148                                 goto out;
1149                 } else {
1150                         err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
1151                         if (err) {
1152                                 vpn_progress(vpninfo, PRG_ERR,
1153                                              _("Failed to load PKCS#1 private key: %s\n"),
1154                                              gnutls_strerror(err));
1155                                 ret = -EINVAL;
1156                                 goto out;
1157                         }
1158                 }
1159         } else if (strstr((char *)fdata.data, "-----BEGIN ENCRYPTED PRIVATE KEY-----") ||
1160                    strstr((char *)fdata.data, "-----BEGIN PRIVATE KEY-----")) {
1161                 /* PKCS#8 */
1162                 char *pass = vpninfo->cert_password;
1163
1164                 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
1165                                                                GNUTLS_X509_FMT_PEM,
1166                                                                pass, pass?0:GNUTLS_PKCS_PLAIN))) {
1167                         if (err != GNUTLS_E_DECRYPTION_FAILED) {
1168                                 vpn_progress(vpninfo, PRG_ERR,
1169                                              _("Failed to load private key as PKCS#8: %s\n"),
1170                                              gnutls_strerror(err));
1171                                 ret = -EINVAL;
1172                                 goto out;
1173                         }
1174                         vpninfo->cert_password = NULL;
1175                         if (pass) {
1176                                 vpn_progress(vpninfo, PRG_ERR,
1177                                              _("Failed to decrypt PKCS#8 certificate file\n"));
1178                                 free(pass);
1179                         }
1180                         err = request_passphrase(vpninfo, "openconnect_pem",
1181                                                  &pass, _("Enter PEM pass phrase:"));
1182                         if (err) {
1183                                 ret = -EINVAL;
1184                                 goto out;
1185                         }
1186                 }
1187                 free(pass);
1188                 vpninfo->cert_password = NULL;
1189         } else {
1190                 vpn_progress(vpninfo, PRG_ERR,
1191                              _("Failed to determine type of private key %s\n"),
1192                              vpninfo->sslkey);
1193                 ret = -EINVAL;
1194                 goto out;
1195         }
1196
1197         /* Now attempt to make sure we use the *correct* certificate, to match
1198            the key. Since we have a software key, we can easily query it and
1199            compare its key_id with each certificate till we find a match. */
1200         err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
1201         if (err) {
1202                 vpn_progress(vpninfo, PRG_ERR,
1203                              _("Failed to get key ID: %s\n"),
1204                              gnutls_strerror(err));
1205                 ret = -EINVAL;
1206                 goto out;
1207         }
1208         /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
1209         for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
1210                 unsigned char cert_id[20];
1211                 size_t cert_id_size = sizeof(cert_id);
1212
1213                 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
1214                 if (err)
1215                         continue;
1216
1217                 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
1218                         if (extra_certs) {
1219                                 cert = extra_certs[i];
1220                                 extra_certs[i] = NULL;
1221                         }
1222                         goto got_key;
1223                 }
1224         }
1225         /* There's no pkey (there's an x509 key), so even if p11-kit or trousers is
1226            enabled we'll fall straight through the bit at match_cert: below, and go
1227            directly to the bit where it prints the 'no match found' error and exits. */
1228
1229 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1230  match_cert:
1231         /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
1232            of key ID that we do for software keys to find which certificate is a
1233            match. So sign some dummy data and then check the signature against each
1234            of the available certificates until we find the right one. */
1235         if (pkey) {
1236                 /* The TPM code may have already signed it, to test authorisation. We
1237                    only sign here for PKCS#11 keys, in which case fdata might be
1238                    empty too so point it at dummy data. */
1239                 if (!pkey_sig.data) {
1240                         if (!fdata.data) {
1241                                 fdata.data = dummy_hash_data;
1242                                 fdata.size = 20;
1243                         }
1244
1245                         err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
1246                         if (err) {
1247                                 vpn_progress(vpninfo, PRG_ERR,
1248                                              _("Error signing test data with private key: %s\n"),
1249                                              gnutls_strerror(err));
1250                                 ret = -EINVAL;
1251                                 goto out;
1252                         }
1253                 }
1254
1255                 /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
1256                 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
1257                         gnutls_pubkey_t pubkey;
1258
1259                         gnutls_pubkey_init(&pubkey);
1260                         err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
1261                         if (err) {
1262                                 vpn_progress(vpninfo, PRG_ERR,
1263                                              _("Error validating signature against certificate: %s\n"),
1264                                              gnutls_strerror(err));
1265                                 /* We'll probably fail shortly if we don't find it. */
1266                                 gnutls_pubkey_deinit(pubkey);
1267                                 continue;
1268                         }
1269                         err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
1270                         gnutls_pubkey_deinit(pubkey);
1271
1272                         if (err >= 0) {
1273                                 if (extra_certs) {
1274                                         cert = extra_certs[i];
1275                                         extra_certs[i] = NULL;
1276                                 }
1277                                 gnutls_free(pkey_sig.data);
1278                                 goto got_key;
1279                         }
1280                 }
1281                 gnutls_free(pkey_sig.data);
1282         }
1283 #endif /* P11KIT || TROUSERS */
1284
1285         /* We shouldn't reach this. It means that we didn't find *any* matching cert */
1286         vpn_progress(vpninfo, PRG_ERR,
1287                      _("No SSL certificate found to match private key\n"));
1288         ret = -EINVAL;
1289         goto out;
1290
1291         /********************************************************************/
1292  got_key:
1293         /* Now we have a key in either 'key' or 'pkey', a matching cert in 'cert',
1294            and potentially a list of other certs in 'extra_certs[]'. If we loaded
1295            a PKCS#12 file we may have a trust chain in 'supporting_certs[]' too. */
1296         check_certificate_expiry(vpninfo, cert);
1297         get_cert_name(cert, name, sizeof(name));
1298         vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
1299                      name);
1300
1301         if (crl) {
1302                 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
1303                 if (err) {
1304                         vpn_progress(vpninfo, PRG_ERR,
1305                                      _("Setting certificate recovation list failed: %s\n"),
1306                                      gnutls_strerror(err));
1307                         ret = -EINVAL;
1308                         goto out;
1309                 }
1310         }
1311
1312         /* OpenSSL has problems with certificate chains — if there are
1313            multiple certs with the same name, it doesn't necessarily
1314            choose the _right_ one. (RT#1942)
1315            Pick the right ones for ourselves and add them manually. */
1316
1317         if (nr_supporting_certs) {
1318                 /* We already got a bunch of certs from PKCS#12 file. Remember
1319                    how many need to be freed when we're done, since we'll
1320                    expand the supporting_certs array with more from the cafile
1321                    and extra_certs[] array if we can, and those extra certs
1322                    must not be freed (twice). */
1323                 last_cert = supporting_certs[nr_supporting_certs-1];
1324                 certs_to_free = nr_supporting_certs;
1325         } else {
1326                 last_cert = cert;
1327                 certs_to_free = nr_supporting_certs = 1;
1328         }
1329         while (1) {
1330                 gnutls_x509_crt_t issuer;
1331
1332                 for (i = 0; i < nr_extra_certs; i++) {
1333                         if (extra_certs[i] &&
1334                             gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1335                             !check_issuer_sanity(last_cert, extra_certs[i]))
1336                                 break;
1337                 }
1338
1339                 if (i < nr_extra_certs) {
1340                         /* We found the next cert in the chain in extra_certs[] */
1341                         issuer = extra_certs[i];
1342                 } else {
1343                         /* Look for it in the system trust cafile too. */
1344                         err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1345                                                             last_cert, &issuer, 0);
1346                         if (err)
1347                                 break;
1348
1349                         /* The check_issuer_sanity() function works fine as a workaround where
1350                            it was used above, but when gnutls_certificate_get_issuer() returns
1351                            a bogus cert, there's nothing we can do to fix it up. We don't get
1352                            to iterate over all the available certs like we can over our own
1353                            list. */
1354                         if (check_issuer_sanity(last_cert, issuer)) {
1355                                 /* Hm, is there a bug reference for this? Or just the git commit
1356                                    reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1357                                 vpn_progress(vpninfo, PRG_ERR,
1358                                              _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1359                                 break;
1360                         }
1361                 }
1362
1363                 if (issuer == last_cert) {
1364                         /* Don't actually include the root CA. If they don't already trust it,
1365                            then handing it to them isn't going to help. But don't omit the
1366                            original certificate if it's self-signed. */
1367                         if (nr_supporting_certs > 1)
1368                                 nr_supporting_certs--;
1369                         break;
1370                 }
1371
1372                 /* OK, we found a new cert to add to our chain. */
1373                 supporting_certs = gnutls_realloc(supporting_certs,
1374                                                   sizeof(cert) * ++nr_supporting_certs);
1375                 if (!supporting_certs) {
1376                         vpn_progress(vpninfo, PRG_ERR,
1377                                      _("Failed to allocate memory for supporting certificates\n"));
1378                         /* The world is probably about to end, but try without them anyway */
1379                         certs_to_free = 0;
1380                         ret = -ENOMEM;
1381                         goto out;
1382                 }
1383
1384                 /* First time we actually allocated an array? Copy the first cert into it */
1385                 if (nr_supporting_certs == 2)
1386                         supporting_certs[0] = cert;
1387
1388                 /* Append the new one */
1389                 supporting_certs[nr_supporting_certs-1] = issuer;
1390                 last_cert = issuer;
1391         }
1392         for (i = 1; i < nr_supporting_certs; i++) {
1393                 get_cert_name(supporting_certs[i], name, sizeof(name));
1394
1395                 vpn_progress(vpninfo, PRG_DEBUG,
1396                              _("Adding supporting CA '%s'\n"), name);
1397         }
1398
1399         /* OK, now we've checked the cert expiry and warned the user if it's
1400            going to expire soon, and we've built up as much of a trust chain
1401            in supporting_certs[] as we can find, to help the server work around
1402            OpenSSL RT#1942. Set up the GnuTLS credentials with the appropriate
1403            key and certs. GnuTLS makes us do this differently for X509 privkeys
1404            vs. TPM/PKCS#11 "generic" privkeys, and the latter is particularly
1405            'fun' for GnuTLS 2.12... */
1406 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1407         if (pkey) {
1408                 err = assign_privkey(vpninfo, pkey,
1409                                      supporting_certs ? supporting_certs : &cert,
1410                                      nr_supporting_certs,
1411                                      extra_certs, nr_extra_certs);
1412                 if (!err) {
1413                         pkey = NULL; /* we gave it away, and potentially also some
1414                                         of extra_certs[] may have been zeroed. */
1415                 }
1416         } else
1417 #endif /* P11KIT || TROUSERS */
1418                 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1419                                                       supporting_certs ? supporting_certs : &cert,
1420                                                       nr_supporting_certs, key);
1421
1422         if (err) {
1423                 vpn_progress(vpninfo, PRG_ERR,
1424                              _("Setting certificate failed: %s\n"),
1425                              gnutls_strerror(err));
1426                 ret = -EIO;
1427         } else
1428                 ret = 0;
1429  out:
1430         if (crl)
1431                 gnutls_x509_crl_deinit(crl);
1432         if (key)
1433                 gnutls_x509_privkey_deinit(key);
1434         if (supporting_certs) {
1435                 for (i = 0; i < certs_to_free; i++) {
1436                         if (supporting_certs[i])
1437                                 gnutls_x509_crt_deinit(supporting_certs[i]);
1438                 }
1439                 gnutls_free(supporting_certs);
1440         } else if (cert) {
1441                 /* Not if supporting_certs. It's supporting_certs[0] then and
1442                    was already freed. */
1443                 gnutls_x509_crt_deinit(cert);
1444         }
1445         for (i = 0; i < nr_extra_certs; i++) {
1446                 if (extra_certs[i])
1447                         gnutls_x509_crt_deinit(extra_certs[i]);
1448         }
1449         gnutls_free(extra_certs);
1450
1451 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1452         if (pkey && pkey != OPENCONNECT_TPM_PKEY)
1453                 gnutls_privkey_deinit(pkey);
1454         /* If we support arbitrary privkeys, we might have abused fdata.data
1455            just to point to something to hash. Don't free it in that case! */
1456         if (fdata.data != dummy_hash_data)
1457 #endif
1458                 gnutls_free(fdata.data);
1459
1460 #ifdef HAVE_P11KIT
1461         if (cert_url != vpninfo->cert)
1462                 free(cert_url);
1463         if (key_url != vpninfo->sslkey)
1464                 free(key_url);
1465 #endif
1466         return ret;
1467 }
1468
1469 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1470                                 gnutls_x509_crt_t cert,
1471                                 gnutls_digest_algorithm_t algo,
1472                                 char *buf)
1473 {
1474         unsigned char md[256];
1475         size_t md_size = sizeof(md);
1476         unsigned int i;
1477
1478         if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1479                 return -EIO;
1480
1481         for (i=0; i < md_size; i++)
1482                 sprintf(&buf[i*2], "%02X", md[i]);
1483
1484         return 0;
1485 }
1486
1487 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1488                              OPENCONNECT_X509 *cert, char *buf)
1489 {
1490         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1491 }
1492
1493 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1494                               OPENCONNECT_X509 *cert, char *buf)
1495 {
1496         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1497 }
1498
1499 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1500                                    OPENCONNECT_X509 *cert)
1501 {
1502         gnutls_datum_t buf;
1503         char *ret;
1504
1505         if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1506                 return NULL;
1507         
1508         /* Just in case gnutls_free() isn't free(), we can't steal it. */
1509         ret = strdup((char *)buf.data);
1510         gnutls_free(buf.data);
1511         
1512         return ret;
1513 }
1514
1515 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1516                              OPENCONNECT_X509 *cert, unsigned char **buf)
1517 {
1518         size_t l = 0;
1519         unsigned char *ret = NULL;
1520
1521         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) != 
1522             GNUTLS_E_SHORT_MEMORY_BUFFER)
1523                 return -EIO;
1524
1525         ret = malloc(l);
1526         if (!ret)
1527                 return -ENOMEM;
1528
1529         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1530                 free(ret);
1531                 return -EIO;
1532         }
1533         *buf = ret;
1534         return l;
1535 }
1536
1537 static int verify_peer(gnutls_session_t session)
1538 {
1539         struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1540         const gnutls_datum_t *cert_list;
1541         gnutls_x509_crt_t cert;
1542         unsigned int status, cert_list_size;
1543         const char *reason = NULL;
1544         int err;
1545
1546         if (vpninfo->peer_cert) {
1547                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1548                 vpninfo->peer_cert = NULL;
1549         }
1550
1551         cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1552         if (!cert_list) {
1553                 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1554                 return GNUTLS_E_CERTIFICATE_ERROR;
1555         }
1556
1557         if (vpninfo->servercert) {
1558                 unsigned char sha1bin[SHA1_SIZE];
1559                 char fingerprint[(SHA1_SIZE * 2) + 1];
1560                 int i;
1561                 
1562                 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1563                 if (err) {
1564                         vpn_progress(vpninfo, PRG_ERR,
1565                                      _("Could not calculate SHA1 of server's certificate\n"));
1566                         return GNUTLS_E_CERTIFICATE_ERROR;
1567                 }
1568                 for (i=0; i < SHA1_SIZE; i++)
1569                         sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1570
1571                 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1572                         vpn_progress(vpninfo, PRG_ERR,
1573                                      _("Server SSL certificate didn't match: %s\n"), fingerprint);
1574                         return GNUTLS_E_CERTIFICATE_ERROR;
1575                 }
1576                 return 0;
1577         }
1578
1579         err = gnutls_certificate_verify_peers2 (session, &status);
1580         if (err) {
1581                 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1582                 return GNUTLS_E_CERTIFICATE_ERROR;
1583         }
1584
1585         if (status & GNUTLS_CERT_REVOKED)
1586                 reason = _("certificate revoked");
1587         else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1588                 reason = _("signer not found");
1589         else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1590                 reason = _("signer not a CA certificate");
1591         else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1592                 reason = _("insecure algorithm");
1593         else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1594                 reason = _("certificate not yet activated");
1595         else if (status & GNUTLS_CERT_EXPIRED)
1596                 reason = _("certificate expired");
1597         else if (status & GNUTLS_CERT_INVALID)
1598                 /* If this is set and no other reason, it apparently means
1599                    that signature verification failed. Not entirely sure
1600                    why we don't just set a bit for that too. */
1601                 reason = _("signature verification failed");
1602
1603         err = gnutls_x509_crt_init(&cert);
1604         if (err) {
1605                 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1606                 return GNUTLS_E_CERTIFICATE_ERROR;
1607         }
1608
1609         err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1610         if (err) {
1611                 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1612                 gnutls_x509_crt_deinit(cert);
1613                 return GNUTLS_E_CERTIFICATE_ERROR;
1614         }
1615
1616         if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1617                 reason = _("certificate does not match hostname");
1618
1619         if (reason) {
1620                 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1621                              reason);
1622                 if (vpninfo->validate_peer_cert)
1623                         err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1624                                                           cert,
1625                                                           reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1626                 else
1627                         err = GNUTLS_E_CERTIFICATE_ERROR;
1628         }
1629
1630         vpninfo->peer_cert = cert;
1631
1632         return err;
1633 }
1634
1635
1636 int openconnect_open_https(struct openconnect_info *vpninfo)
1637 {
1638         int ssl_sock = -1;
1639         int err;
1640
1641         if (vpninfo->https_sess)
1642                 return 0;
1643
1644         ssl_sock = connect_https_socket(vpninfo);
1645         if (ssl_sock < 0)
1646                 return ssl_sock;
1647
1648         if (!vpninfo->https_cred) {
1649                 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1650 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1651                 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1652 #else
1653                 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1654                                                        "/etc/pki/tls/certs/ca-bundle.crt",
1655                                                        GNUTLS_X509_FMT_PEM);
1656 #endif
1657                 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1658                                                         verify_peer);
1659
1660 #ifdef ANDROID_KEYSTORE
1661                 if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {
1662                         gnutls_datum_t datum;
1663                         unsigned int nr_certs;
1664
1665                         err = load_datum(vpninfo, &datum, vpninfo->cafile);
1666                         if (err < 0)
1667                                 return err;
1668
1669                         /* For GnuTLS 3.x We should use gnutls_x509_crt_list_import2() */
1670                         nr_certs = count_x509_certificates(&datum);
1671                         if (nr_certs) {
1672                                 gnutls_x509_crt *certs;
1673                                 int i;
1674
1675                                 certs = calloc(nr_certs, sizeof(*certs));
1676                                 if (!certs) {
1677                                         vpn_progress(vpninfo, PRG_ERR,
1678                                                      _("Failed to allocate memory for cafile certs\n"));
1679                                         gnutls_free(datum.data);
1680                                         close(ssl_sock);
1681                                         return -ENOMEM;
1682                                 }
1683                                 err = gnutls_x509_crt_list_import(certs, &nr_certs, &datum,
1684                                                                   GNUTLS_X509_FMT_PEM, 0);
1685                                 gnutls_free(datum.data);
1686                                 if (err >= 0) {
1687                                         nr_certs = err;
1688                                         err = gnutls_certificate_set_x509_trust(vpninfo->https_cred,
1689                                                                                 certs, nr_certs);
1690                                 }
1691                                 for (i = 0; i < nr_certs; i++)
1692                                         gnutls_x509_crt_deinit(certs[i]);
1693                                 free(certs);
1694                                 if (err < 0) {
1695                                         /* From crt_list_import or set_x509_trust */
1696                                         vpn_progress(vpninfo, PRG_ERR,
1697                                                      _("Failed to read certs from cafile: %s\n"),
1698                                                      gnutls_strerror(err));
1699                                         close(ssl_sock);
1700                                         return -EINVAL;
1701                                 }
1702                         }
1703                 } else
1704 #endif
1705                 if (vpninfo->cafile) {
1706                         err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1707                                                                      vpninfo->cafile,
1708                                                                      GNUTLS_X509_FMT_PEM);
1709                         if (err < 0) {
1710                                 vpn_progress(vpninfo, PRG_ERR,
1711                                              _("Failed to open CA file '%s': %s\n"),
1712                                              vpninfo->cafile, gnutls_strerror(err));
1713                                 close(ssl_sock);
1714                                 return -EINVAL;
1715                         }
1716                 }
1717
1718                 if (vpninfo->cert) {
1719                         err = load_certificate(vpninfo);
1720                         if (err) {
1721                                 vpn_progress(vpninfo, PRG_ERR,
1722                                              _("Loading certificate failed. Aborting.\n"));
1723                                 close(ssl_sock);
1724                                 return err;
1725                         }
1726                 }
1727         }
1728         gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1729         gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1730 #if defined(HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1731         if (vpninfo->my_pkey == OPENCONNECT_TPM_PKEY)
1732                 gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo);
1733 #endif
1734         err = gnutls_priority_set_direct (vpninfo->https_sess, "NONE:+VERS-TLS1.0:+SHA1:+AES-128-CBC:+RSA:+COMP-NULL:%COMPAT:%DISABLE_SAFE_RENEGOTIATION", NULL);
1735         if (err) {
1736                 vpn_progress(vpninfo, PRG_ERR,
1737                              _("Failed to set TLS priority string: %s\n"),
1738                              gnutls_strerror(err));
1739                 return -EIO;
1740         }
1741
1742         gnutls_record_disable_padding (vpninfo->https_sess);
1743         gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1744         gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1745
1746         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1747                      vpninfo->hostname);
1748
1749         while ((err = gnutls_handshake (vpninfo->https_sess))) {
1750                 if (err == GNUTLS_E_AGAIN) {
1751                         fd_set rd_set, wr_set;
1752                         int maxfd = ssl_sock;
1753
1754                         FD_ZERO(&rd_set);
1755                         FD_ZERO(&wr_set);
1756
1757                         if (gnutls_record_get_direction(vpninfo->https_sess))
1758                                 FD_SET(ssl_sock, &wr_set);
1759                         else
1760                                 FD_SET(ssl_sock, &rd_set);
1761
1762                         if (vpninfo->cancel_fd != -1) {
1763                                 FD_SET(vpninfo->cancel_fd, &rd_set);
1764                                 if (vpninfo->cancel_fd > ssl_sock)
1765                                         maxfd = vpninfo->cancel_fd;
1766                         }
1767                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1768                         if (vpninfo->cancel_fd != -1 &&
1769                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1770                                 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1771                                 gnutls_deinit(vpninfo->https_sess);
1772                                 vpninfo->https_sess = NULL;
1773                                 close(ssl_sock);
1774                                 return -EINTR;
1775                         }
1776                 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1777                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1778                                                          gnutls_strerror(err));
1779                         gnutls_deinit(vpninfo->https_sess);
1780                         vpninfo->https_sess = NULL;
1781                         close(ssl_sock);
1782                         return -EIO;
1783                 } else {
1784                         /* non-fatal error or warning. Ignore it and continue */
1785                         vpn_progress(vpninfo, PRG_TRACE,
1786                                      _("GnuTLS non-fatal return during handshake: %s\n"),
1787                                      gnutls_strerror(err));
1788                 }
1789         }
1790
1791         vpninfo->ssl_fd = ssl_sock;
1792
1793         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1794                      vpninfo->hostname);
1795
1796         return 0;
1797 }
1798
1799 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1800 {
1801         if (vpninfo->peer_cert) {
1802                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1803                 vpninfo->peer_cert = NULL;
1804         }
1805         if (vpninfo->https_sess) {
1806                 gnutls_deinit(vpninfo->https_sess);
1807                 vpninfo->https_sess = NULL;
1808         }
1809         if (vpninfo->ssl_fd != -1) {
1810                 close(vpninfo->ssl_fd);
1811                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1812                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1813                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1814                 vpninfo->ssl_fd = -1;
1815         }
1816         if (final && vpninfo->https_cred) {
1817                 gnutls_certificate_free_credentials(vpninfo->https_cred);
1818                 vpninfo->https_cred = NULL;
1819 #ifdef HAVE_P11KIT
1820                 if ((vpninfo->cert && !strncmp(vpninfo->cert, "pkcs11:", 7)) ||
1821                     (vpninfo->sslkey && !strncmp(vpninfo->sslkey, "pkcs11:", 7))) {
1822                         char pin_source[40];
1823
1824                         sprintf(pin_source, "openconnect:%p", vpninfo);
1825                         p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1826
1827                         while (vpninfo->pin_cache) {
1828                                 struct pin_cache *cache = vpninfo->pin_cache;
1829
1830                                 free(cache->token);
1831                                 memset(cache->pin, 0x5a, strlen(cache->pin));
1832                                 free(cache->pin);
1833                                 vpninfo->pin_cache = cache->next;
1834                                 free(cache);
1835                         }
1836                 }
1837 #endif
1838 #ifdef HAVE_TROUSERS
1839                 if (vpninfo->tpm_key_policy) {
1840                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
1841                         vpninfo->tpm_key = 0;
1842                 }
1843                 if (vpninfo->tpm_key) {
1844                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1845                         vpninfo->tpm_key = 0;
1846                 }
1847                 if (vpninfo->srk_policy) {
1848                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1849                         vpninfo->srk_policy = 0;
1850                 }
1851                 if (vpninfo->srk) {
1852                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1853                         vpninfo->srk = 0;
1854                 }
1855                 if (vpninfo->tpm_context) {
1856                         Tspi_Context_Close(vpninfo->tpm_context);
1857                         vpninfo->tpm_context = 0;
1858                 }
1859 #endif
1860 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1861                 if (vpninfo->my_pkey && vpninfo->my_pkey != OPENCONNECT_TPM_PKEY) {
1862                         gnutls_privkey_deinit(vpninfo->my_pkey);
1863                         vpninfo->my_pkey = NULL;
1864                         /* my_p11key went with it */
1865                 }
1866                 if (vpninfo->my_certs) {
1867                         int i;
1868                         for (i = 0; i < vpninfo->nr_my_certs; i++)
1869                                 gnutls_x509_crt_deinit(vpninfo->my_certs[i]);
1870                         free(vpninfo->my_certs);
1871                         vpninfo->my_certs = NULL;
1872                 }
1873 #endif
1874         }
1875 }
1876
1877 void openconnect_init_ssl(void)
1878 {
1879         gnutls_global_init();
1880 }
1881
1882 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1883 {
1884         gnutls_datum_t d;
1885         size_t shalen = SHA1_SIZE;
1886
1887         d.data = data;
1888         d.size = datalen;
1889         if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
1890                 return -1;
1891
1892         return 0;
1893 }
1894
1895 int openconnect_random(void *bytes, int len)
1896 {
1897         if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
1898                 return -EIO;
1899         return 0;
1900 }
1901
1902 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1903                                char *buf)
1904 {
1905         const gnutls_datum_t *d;
1906         size_t md5len = 16;
1907
1908         buf[0] = 0;
1909
1910         d = gnutls_certificate_get_ours(vpninfo->https_sess);
1911         if (!d)
1912                 return -EIO;
1913
1914         if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
1915                 return -EIO;
1916
1917         return 0;
1918 }
1919
1920 #ifdef HAVE_P11KIT
1921 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
1922                         const char *pin_description,
1923                         P11KitPinFlags flags,
1924                         void *_vpninfo)
1925 {
1926         struct openconnect_info *vpninfo = _vpninfo;
1927         struct pin_cache **cache = &vpninfo->pin_cache;
1928         struct oc_auth_form f;
1929         struct oc_form_opt o;
1930         char message[1024];
1931         char *uri;
1932         P11KitPin *pin;
1933         int ret;
1934
1935         if (!vpninfo || !vpninfo->process_auth_form)
1936                 return NULL;
1937
1938         if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
1939                 return NULL;
1940         
1941         while (*cache) {
1942                 if (!strcmp(uri, (*cache)->token)) {
1943                         free(uri);
1944                         uri = NULL;
1945                         if ((*cache)->pin) {
1946                                 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
1947                                         return p11_kit_pin_new_for_string((*cache)->pin);
1948                                 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
1949                                 free((*cache)->pin);
1950                                 (*cache)->pin = NULL;
1951                         }
1952                         break;
1953                 }
1954         }
1955         if (!*cache) {
1956                 *cache = calloc(1, sizeof(struct pin_cache));
1957                 if (!*cache) {
1958                         free(uri);
1959                         return NULL;
1960                 }
1961                 (*cache)->token = uri;
1962         }
1963
1964         memset(&f, 0, sizeof(f));
1965         f.auth_id = (char *)"pkcs11_pin";
1966         f.opts = &o;
1967
1968         message[sizeof(message)-1] = 0;
1969         snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
1970         f.message = message;
1971         
1972         /* 
1973          * In p11-kit <= 0.12, these flags are *odd*.
1974          * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
1975          * So don't treat it like a sane bitmask. Fixed in
1976          * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
1977          */
1978         if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
1979                 f.error = (char *)_("Wrong PIN");
1980
1981         if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
1982                 f.banner = (char *)_("This is the final try before locking!");
1983         else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
1984                 f.banner = (char *)_("Only a few tries left before locking!");
1985
1986         o.next = NULL;
1987         o.type = OC_FORM_OPT_PASSWORD;
1988         o.name = (char *)"pkcs11_pin";
1989         o.label = (char *)_("Enter PIN:");
1990         o.value = NULL;
1991
1992         ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
1993         if (ret || !o.value)
1994                 return NULL;
1995
1996         pin = p11_kit_pin_new_for_string(o.value);
1997         (*cache)->pin = o.value;
1998
1999         return pin;
2000 }
2001 #endif