resetting manifest requested domain to floor
[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\n"),
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 0
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                 /* We only use the first 8 bytes of the salt for this */
617                 err = gnutls_hash(hash, salt->data, 8);
618                 if (err)
619                         goto hash_err;
620
621                 gnutls_hash_deinit(hash, md5);
622
623                 if (key->size - count <= sizeof(md5)) {
624                         memcpy(&key->data[count], md5, key->size - count);
625                         break;
626                 }
627
628                 memcpy(&key->data[count], md5, sizeof(md5));
629                 count += sizeof(md5);
630         }
631
632         return 0;
633 }
634
635 static int import_openssl_pem(struct openconnect_info *vpninfo,
636                               gnutls_x509_privkey_t key,
637                               char type, char *pem_header, size_t pem_size)
638 {
639         gnutls_cipher_hd_t handle;
640         gnutls_cipher_algorithm_t cipher;
641         gnutls_datum_t constructed_pem;
642         gnutls_datum_t b64_data;
643         gnutls_datum_t salt, enc_key;
644         unsigned char *key_data;
645         const char *begin;
646         char *pass, *p;
647         char *pem_start = pem_header;
648         int ret, err, i;
649
650         if (type == 'E')
651                 begin = "EC PRIVATE KEY";
652         else if (type == 'R')
653                 begin = "RSA PRIVATE KEY";
654         else if (type == 'D')
655                  begin = "DSA PRIVATE KEY";
656         else
657                 return -EINVAL;
658
659         while (*pem_header == '\r' || *pem_header == '\n')
660                 pem_header++;
661
662         if (strncmp(pem_header, "DEK-Info: ", 10)) {
663                 vpn_progress(vpninfo, PRG_ERR,
664                              _("Missing DEK-Info: header from OpenSSL encrypted key\n"));
665                 return -EIO;
666         }
667         pem_header += 10;
668         p = strchr(pem_header, ',');
669         if (!p) {
670                 vpn_progress(vpninfo, PRG_ERR,
671                              _("Cannot determine PEM encryption type\n"));
672                 return -EINVAL;
673         }
674
675         *p = 0;
676         cipher = gnutls_cipher_get_id(pem_header);
677         /* GnuTLS calls this '3DES-CBC' but all other names match */
678         if (cipher == GNUTLS_CIPHER_UNKNOWN &&
679             !strcmp(pem_header, "DES-EDE3-CBC"))
680                 cipher = GNUTLS_CIPHER_3DES_CBC;
681
682         if (cipher == GNUTLS_CIPHER_UNKNOWN) {
683                 vpn_progress(vpninfo, PRG_ERR,
684                              _("Unsupported PEM encryption type: %s\n"),
685                              pem_header);
686                 return -EINVAL;
687         }
688         pem_header = p + 1;
689
690         /* No supported algorithms have an IV larger than this, and dynamically
691            allocating it would be painful. */
692         salt.size = 64;
693         salt.data = malloc(salt.size);
694         if (!salt.data)
695                 return -ENOMEM;
696         for (i = 0; i < salt.size * 2; i++) {
697                 unsigned char x;
698                 char *c = &pem_header[i];
699
700                 if (*c >= '0' && *c <= '9')
701                         x = (*c) - '0';
702                 else if (*c >= 'A' && *c <= 'F')
703                         x = (*c) - 'A' + 10;
704                 else if ((*c == '\r' || *c == '\n') && i >= 16 && !(i % 16)) {
705                         salt.size = i / 2;
706                         break;
707                 } else {
708                         vpn_progress(vpninfo, PRG_ERR,
709                                      _("Invalid salt in encrypted PEM file\n"));
710                         ret = -EINVAL;
711                         goto out_salt;
712                 }
713                 if (i & 1)
714                         salt.data[i/2] |= x;
715                 else
716                         salt.data[i/2] = x << 4;
717         }
718
719         pem_header += salt.size * 2;
720         if (*pem_header != '\r' && *pem_header != '\n') {
721                 vpn_progress(vpninfo, PRG_ERR,
722                              _("Invalid salt in encrypted PEM file\n"));
723                 ret = -EINVAL;
724                 goto out_salt;
725         }
726         while (*pem_header == '\n' || *pem_header == '\r')
727                 pem_header++;
728
729         /* pem_header should now point to the start of the base64 content.
730            Put a -----BEGIN banner in place before it, so that we can use
731            gnutls_pem_base64_decode_alloc(). The banner has to match the
732            -----END banner, so make sure we get it right... */
733         pem_header -= 6;
734         memcpy(pem_header, "-----\n", 6);
735         pem_header -= strlen(begin);
736         memcpy(pem_header, begin, strlen(begin));
737         pem_header -= 11;
738         memcpy(pem_header, "-----BEGIN ", 11);
739
740         constructed_pem.data = (void *)pem_header;
741         constructed_pem.size = pem_size - (pem_header - pem_start);
742
743         err = gnutls_pem_base64_decode_alloc(begin, &constructed_pem, &b64_data);
744         if (err) {
745                 vpn_progress(vpninfo, PRG_ERR,
746                              _("Error base64-decoding encrypted PEM file: %s\n"),
747                              gnutls_strerror(err));
748                 ret = -EINVAL;
749                 goto out_salt;
750         }
751         if (b64_data.size < 16) {
752                 /* Just to be sure our parsing is OK */
753                 vpn_progress(vpninfo, PRG_ERR,
754                              _("Encrypted PEM file too short\n"));
755                 ret = -EINVAL;
756                 goto out_b64;
757         }
758
759         ret = -ENOMEM;
760         enc_key.size = gnutls_cipher_get_key_size(cipher);
761         enc_key.data = malloc(enc_key.size);
762         if (!enc_key.data)
763                 goto out_b64;
764
765         key_data = malloc(b64_data.size);
766         if (!key_data)
767                 goto out_enc_key;
768
769         pass = vpninfo->cert_password;
770         vpninfo->cert_password = NULL;
771
772         while (1) {
773                 memcpy(key_data, b64_data.data, b64_data.size);
774
775                 ret = openssl_hash_password(vpninfo, pass, &enc_key, &salt);
776                 if (ret)
777                         goto out;
778
779                 err = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
780                 if (err) {
781                         vpn_progress(vpninfo, PRG_ERR,
782                                      _("Failed to initialise cipher for decrypting PEM file: %s\n"),
783                                      gnutls_strerror(err));
784                         gnutls_cipher_deinit(handle);
785                         ret = -EIO;
786                         goto out;
787                 }
788
789                 err = gnutls_cipher_decrypt(handle, key_data, b64_data.size);
790                 gnutls_cipher_deinit(handle);
791                 if (err) {
792                         vpn_progress(vpninfo, PRG_ERR,
793                                      _("Failed to decrypt PEM key: %s\n"),
794                                      gnutls_strerror(err));
795                         ret = -EIO;
796                         goto out;
797                 }
798
799                 /* We have to strip any padding for GnuTLS to accept it.
800                    So a bit more ASN.1 parsing for us.
801                    FIXME: Consolidate with similar code in gnutls_tpm.c */
802                 if (key_data[0] == 0x30) {
803                         gnutls_datum_t key_datum;
804                         int blocksize = gnutls_cipher_get_block_size(cipher);
805                         int keylen = key_data[1];
806                         int ofs = 2;
807
808                         if (keylen & 0x80) {
809                                 int lenlen = keylen & 0x7f;
810                                 keylen = 0;
811
812                                 if (lenlen > 3)
813                                         goto fail;
814
815                                 while (lenlen) {
816                                         keylen <<= 8;
817                                         keylen |= key_data[ofs++];
818                                         lenlen--;
819                                 }
820                         }
821                         keylen += ofs;
822
823                         /* If there appears to be more padding than required, fail */
824                         if (b64_data.size - keylen >= blocksize)
825                                 goto fail;
826
827                         /* If the padding bytes aren't all equal to the amount of padding, fail */
828                         ofs = keylen;
829                         while (ofs < b64_data.size) {
830                                 if (key_data[ofs] != b64_data.size - keylen)
831                                         goto fail;
832                                 ofs++;
833                         }
834
835                         key_datum.data = key_data;
836                         key_datum.size = keylen;
837                         err = gnutls_x509_privkey_import(key, &key_datum, GNUTLS_X509_FMT_DER);
838                         if (!err) {
839                                 ret = 0;
840                                 goto out;
841                         }
842                 }
843  fail:
844                 if (pass) {
845                         vpn_progress(vpninfo, PRG_ERR,  _("Decrypting PEM key failed\n"));
846                         free(pass);
847                 }
848                 err = request_passphrase(vpninfo, "openconnect_pem",
849                                          &pass, _("Enter PEM pass phrase:"));
850                 if (err) {
851                         ret = -EINVAL;
852                         goto out;
853                 }
854         }
855  out:
856         free(key_data);
857         free(pass);
858  out_enc_key:
859         free(enc_key.data);
860  out_b64:
861         free(b64_data.data);
862  out_salt:
863         free(salt.data);
864         return ret;
865 }
866
867 static int load_certificate(struct openconnect_info *vpninfo)
868 {
869         gnutls_datum_t fdata;
870         gnutls_x509_privkey_t key = NULL;
871 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
872         gnutls_privkey_t pkey = NULL;
873         gnutls_datum_t pkey_sig = {NULL, 0};
874         void *dummy_hash_data = &load_certificate;
875 #endif
876 #ifdef HAVE_P11KIT
877         char *cert_url = (char *)vpninfo->cert;
878         char *key_url = (char *)vpninfo->sslkey;
879         gnutls_pkcs11_privkey_t p11key = NULL;
880 #endif
881         char *pem_header;
882         gnutls_x509_crl_t crl = NULL;
883         gnutls_x509_crt_t last_cert, cert = NULL;
884         gnutls_x509_crt_t *extra_certs = NULL, *supporting_certs = NULL;
885         unsigned int nr_supporting_certs = 0, nr_extra_certs = 0;
886         unsigned int certs_to_free = 0; /* How many of supporting_certs */
887         int err; /* GnuTLS error */
888         int ret;
889         int i;
890         int cert_is_p11 = 0, key_is_p11 = 0;
891         unsigned char key_id[20];
892         size_t key_id_size = sizeof(key_id);
893         char name[80];
894
895         fdata.data = NULL;
896
897         key_is_p11 = !strncmp(vpninfo->sslkey, "pkcs11:", 7);
898         cert_is_p11 = !strncmp(vpninfo->cert, "pkcs11:", 7);
899
900 #ifndef HAVE_P11KIT
901         if (key_is_p11 || cert_is_p11) {
902                 vpn_progress(vpninfo, PRG_ERR,
903                              _("This binary built without PKCS#11 support\n"));
904                 return -EINVAL;
905         }
906 #else
907         /* Install PIN handler if either certificate or key are coming from PKCS#11 */
908         if (key_is_p11 || cert_is_p11) {
909                 CK_OBJECT_CLASS class;
910                 CK_ATTRIBUTE attr;
911                 char pin_source[40];
912                 P11KitUri *uri;
913
914                 sprintf(pin_source, "openconnect:%p", vpninfo);
915                 p11_kit_pin_register_callback(pin_source, pin_callback, vpninfo, NULL);
916
917                 uri = p11_kit_uri_new();
918
919                 attr.type = CKA_CLASS;
920                 attr.pValue = &class;
921                 attr.ulValueLen = sizeof(class);
922
923                 /* Add appropriate pin-source and object-type attributes to
924                    both certificate and key URLs, unless they already exist. */
925                 if (cert_is_p11 &&
926                     !p11_kit_uri_parse(cert_url, P11_KIT_URI_FOR_ANY, uri)) {
927                         if (!p11_kit_uri_get_pin_source(uri))
928                                 p11_kit_uri_set_pin_source(uri, pin_source);
929                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
930                                 class = CKO_CERTIFICATE;
931                                 p11_kit_uri_set_attribute(uri, &attr);
932                         }
933                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_ANY, &cert_url);
934                 }
935
936                 if (key_is_p11 &&
937                     !p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_ANY, uri)) {
938                         if (!p11_kit_uri_get_pin_source(uri))
939                                 p11_kit_uri_set_pin_source(uri, pin_source);
940                         if (!p11_kit_uri_get_attribute(uri, CKA_CLASS)) {
941                                 class = CKO_PRIVATE_KEY;
942                                 p11_kit_uri_set_attribute(uri, &attr);
943                         }
944                         p11_kit_uri_format(uri, P11_KIT_URI_FOR_ANY, &key_url);
945                 }
946
947                 p11_kit_uri_free(uri);
948         }
949
950         /* Load certificate(s) first... */
951         if (cert_is_p11) {
952                 vpn_progress(vpninfo, PRG_TRACE,
953                              _("Using PKCS#11 certificate %s\n"), cert_url);
954
955                 err = gnutls_x509_crt_init(&cert);
956                 if (err) {
957                         ret = -ENOMEM;
958                         goto out;
959                 }
960                 err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url, 0);
961                 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
962                         err = gnutls_x509_crt_import_pkcs11_url(cert, cert_url,
963                                                                 GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
964                 if (err) {
965                         vpn_progress(vpninfo, PRG_ERR,
966                                      _("Error loading certificate from PKCS#11: %s\n"),
967                                      gnutls_strerror(err));
968                         ret = -EIO;
969                         goto out;
970                 }
971                 goto got_certs;
972         }
973 #endif /* HAVE_P11KIT */
974
975         /* OK, not a PKCS#11 certificate so it must be coming from a file... */
976         vpn_progress(vpninfo, PRG_TRACE,
977                      _("Using certificate file %s\n"), vpninfo->cert);
978
979         /* Load file contents */
980         ret = load_datum(vpninfo, &fdata, vpninfo->cert);
981         if (ret)
982                 return ret;
983
984         /* Is it PKCS#12? */
985         if (!key_is_p11 && (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
986                             vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
987                 /* PKCS#12 should actually contain certificates *and* private key */
988                 ret = load_pkcs12_certificate(vpninfo, &fdata, &key,
989                                               &supporting_certs, &nr_supporting_certs,
990                                               &extra_certs, &nr_extra_certs,
991                                               &crl);
992                 if (ret < 0)
993                         goto out;
994                 else if (!ret) {
995                         if (nr_supporting_certs) {
996                                 cert = supporting_certs[0];
997                                 goto got_key;
998                         }
999                         vpn_progress(vpninfo, PRG_ERR,
1000                                      _("PKCS#11 file contained no certificate\n"));
1001                         ret = -EINVAL;
1002                         goto out;
1003                 }
1004
1005                 /* It returned NOT_PKCS12.
1006                    Fall through to try PEM formats. */
1007         }
1008
1009         /* We need to know how many there are in *advance*; it won't just allocate
1010            the array for us :( */
1011         nr_extra_certs = count_x509_certificates(&fdata);
1012         if (!nr_extra_certs)
1013                 nr_extra_certs = 1; /* wtf? Oh well, we'll fail later... */
1014
1015         extra_certs = calloc(nr_extra_certs, sizeof(cert));
1016         if (!extra_certs) {
1017                 nr_extra_certs = 0;
1018                 ret = -ENOMEM;
1019                 goto out;
1020         }
1021         err = gnutls_x509_crt_list_import(extra_certs, &nr_extra_certs, &fdata,
1022                                           GNUTLS_X509_FMT_PEM, 0);
1023         if (err <= 0) {
1024                 const char *reason;
1025                 if (!err || err == GNUTLS_E_NO_CERTIFICATE_FOUND)
1026                         reason = _("No certificate found in file");
1027                 else
1028                         reason = gnutls_strerror(err);
1029
1030                 vpn_progress(vpninfo, PRG_ERR,
1031                              _("Loading certificate failed: %s\n"),
1032                              reason);
1033                 ret = -EINVAL;
1034                 goto out;
1035         }
1036         nr_extra_certs = err;
1037         err = 0;
1038
1039         goto got_certs;
1040  got_certs:
1041         /* Now we have either a single certificate in 'cert', or an array of
1042            them in extra_certs[]. Next we look for the private key ... */
1043 #if defined (HAVE_P11KIT)
1044         if (key_is_p11) {
1045                 vpn_progress(vpninfo, PRG_TRACE,
1046                              _("Using PKCS#11 key %s\n"), key_url);
1047
1048                 err = gnutls_pkcs11_privkey_init(&p11key);
1049                 if (err) {
1050                         vpn_progress(vpninfo, PRG_ERR,
1051                                      _("Error initialising PKCS#11 key structure: %s\n"),
1052                                      gnutls_strerror(err));
1053                         ret = -EIO;
1054                         goto out;
1055                 }
1056
1057                 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
1058
1059                 /* Annoyingly, some tokens don't even admit the *existence* of
1060                    the key until they're logged in. And thus a search doesn't
1061                    work unless it specifies the *token* too. But if the URI for
1062                    key and cert are the same, and the cert was found, then we
1063                    can work out what token the *cert* was found in and try that
1064                    before we give up... */
1065                 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE &&
1066                     vpninfo->cert == vpninfo->sslkey) {
1067                         gnutls_pkcs11_obj_t crt;
1068                         P11KitUri *uri;
1069                         CK_TOKEN_INFO *token;
1070                         char buf[33];
1071                         size_t s;
1072
1073                         if (gnutls_pkcs11_obj_init(&crt))
1074                                 goto key_err;
1075                         if (gnutls_pkcs11_obj_import_url(crt, cert_url, 0))
1076                                 goto key_err_obj;
1077                         uri = p11_kit_uri_new();
1078                         if (!uri)
1079                                 goto key_err_obj;
1080                         if (p11_kit_uri_parse(key_url, P11_KIT_URI_FOR_ANY, uri))
1081                                 goto key_err_uri;
1082                         token = p11_kit_uri_get_token_info(uri);
1083                         if (!token)
1084                                 goto key_err_uri;
1085
1086                         if (!token->label[0]) {
1087                                 s = sizeof(token->label) + 1;
1088                                 if (!gnutls_pkcs11_obj_get_info(crt, GNUTLS_PKCS11_OBJ_TOKEN_LABEL,
1089                                                                 buf, &s)) {
1090                                         s--;
1091                                         memcpy(token->label, buf, s);
1092                                         memset(token->label + s, ' ',
1093                                                sizeof(token->label) - s);
1094                                 }
1095                         }
1096                         if (!token->manufacturerID[0]) {
1097                                 s = sizeof(token->manufacturerID) + 1;
1098                                 if (!gnutls_pkcs11_obj_get_info(crt, GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER,
1099                                                                 buf, &s)) {
1100                                         s--;
1101                                         memcpy(token->manufacturerID, buf, s);
1102                                         memset(token->manufacturerID + s, ' ',
1103                                                sizeof(token->manufacturerID) - s);
1104                                 }
1105                         }
1106                         if (!token->model[0]) {
1107                                 s = sizeof(token->model) + 1;
1108                                 if (!gnutls_pkcs11_obj_get_info(crt, GNUTLS_PKCS11_OBJ_TOKEN_MODEL,
1109                                                                 buf, &s)) {
1110                                             s--;
1111                                             memcpy(token->model, buf, s);
1112                                             memset(token->model + s, ' ',
1113                                                    sizeof(token->model) - s);
1114                                 }
1115                         }
1116                         if (!token->serialNumber[0]) {
1117                                 s = sizeof(token->serialNumber) + 1;
1118                                 if (!gnutls_pkcs11_obj_get_info(crt, GNUTLS_PKCS11_OBJ_TOKEN_SERIAL,
1119                                                                 buf, &s)) {
1120                                         s--;
1121                                         memcpy(token->serialNumber, buf, s);
1122                                         memset(token->serialNumber + s, ' ',
1123                                                sizeof(token->serialNumber) - s);
1124                                 }
1125
1126                         }
1127
1128                         free(key_url);
1129                         key_url = NULL;
1130                         if (!p11_kit_uri_format(uri, P11_KIT_URI_FOR_ANY, &key_url))
1131                                 err = gnutls_pkcs11_privkey_import_url(p11key, key_url, 0);
1132                 key_err_uri:
1133                         p11_kit_uri_free(uri);
1134                 key_err_obj:
1135                         gnutls_pkcs11_obj_deinit(crt);
1136                 key_err:
1137                         ;
1138                 }
1139                 if (err) {
1140                         vpn_progress(vpninfo, PRG_ERR,
1141                                      _("Error importing PKCS#11 URL %s: %s\n"),
1142                                      key_url, gnutls_strerror(err));
1143                         gnutls_pkcs11_privkey_deinit(p11key);
1144                         ret = -EIO;
1145                         goto out;
1146                 }
1147
1148                 err = gnutls_privkey_init(&pkey);
1149                 if (err) {
1150                         vpn_progress(vpninfo, PRG_ERR,
1151                                      _("Error initialising private key structure: %s\n"),
1152                                      gnutls_strerror(err));
1153                         gnutls_pkcs11_privkey_deinit(p11key);
1154                         ret = -EIO;
1155                         goto out;
1156                 }
1157
1158                 err = gnutls_privkey_import_pkcs11(pkey, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
1159                 if (err) {
1160                         vpn_progress(vpninfo, PRG_ERR,
1161                                      _("Error importing PKCS#11 key into private key structure: %s\n"),
1162                                      gnutls_strerror(err));
1163                         gnutls_pkcs11_privkey_deinit(p11key);
1164                         ret = -EIO;
1165                         goto out;
1166                 }
1167 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1168                 /* This can be set now and doesn't need to be separately freed.
1169                    It goes with the pkey. This is a PITA; it would be better
1170                    if there was a way to get the p11key *back* from a privkey
1171                    that we *know* is based on one. In fact, since this is only
1172                    for GnuTLS 2.12 and we *know* the gnutls_privkey_st won't
1173                    ever change there, so we *could* do something evil... but
1174                    we won't :) */
1175                 vpninfo->my_p11key = p11key;
1176 #endif /* !SET_KEY */
1177                 goto match_cert;
1178         }
1179 #endif /* HAVE_P11KIT */
1180
1181         /* OK, not a PKCS#11 key so it must be coming from a file... load the
1182            file into memory, unless it's the same as the cert file and we
1183            already loaded that. */
1184         if (!fdata.data || vpninfo->sslkey != vpninfo->cert) {
1185                 gnutls_free(fdata.data);
1186                 fdata.data = NULL;
1187
1188                 vpn_progress(vpninfo, PRG_TRACE,
1189                              _("Using private key file %s\n"), vpninfo->sslkey);
1190
1191                 ret = load_datum(vpninfo, &fdata, vpninfo->sslkey);
1192                 if (ret)
1193                         goto out;
1194         }
1195
1196         /* Is it a PEM file with a TPM key blob? */
1197         if (vpninfo->cert_type == CERT_TYPE_TPM ||
1198             (vpninfo->cert_type == CERT_TYPE_UNKNOWN &&
1199              strstr((char *)fdata.data, "-----BEGIN TSS KEY BLOB-----"))) {
1200 #ifndef HAVE_TROUSERS
1201                 vpn_progress(vpninfo, PRG_ERR,
1202                              _("This version of OpenConnect was built without TPM support\n"));
1203                 return -EINVAL;
1204 #else
1205                 ret = load_tpm_key(vpninfo, &fdata, &pkey, &pkey_sig);
1206                 if (ret)
1207                         goto out;
1208
1209                 goto match_cert;
1210 #endif
1211         }
1212
1213         /* OK, try other PEM files... */
1214         gnutls_x509_privkey_init(&key);
1215         if ((pem_header = strstr((char *)fdata.data, "-----BEGIN RSA PRIVATE KEY-----")) ||
1216             (pem_header = strstr((char *)fdata.data, "-----BEGIN DSA PRIVATE KEY-----")) ||
1217             (pem_header = strstr((char *)fdata.data, "-----BEGIN EC PRIVATE KEY-----"))) {
1218                 /* PKCS#1 files, including OpenSSL's odd encrypted version */
1219                 char type = pem_header[11];
1220                 char *p = strchr(pem_header, '\n');
1221                 if (!p) {
1222                         vpn_progress(vpninfo, PRG_ERR,
1223                                      _("Failed to interpret PEM file\n"));
1224                         ret = -EINVAL;
1225                         goto out;
1226                 }
1227                 while (*p == '\n' || *p == '\r')
1228                         p++;
1229
1230                 if (!strncmp(p, "Proc-Type: 4,ENCRYPTED", 22)) {
1231                         p += 22;
1232                         while (*p == '\n' || *p == '\r')
1233                                 p++;
1234                         ret = import_openssl_pem(vpninfo, key, type, p,
1235                                                  fdata.size - (p - (char *)fdata.data));
1236                         if (ret)
1237                                 goto out;
1238                 } else {
1239                         err = gnutls_x509_privkey_import(key, &fdata, GNUTLS_X509_FMT_PEM);
1240                         if (err) {
1241                                 vpn_progress(vpninfo, PRG_ERR,
1242                                              _("Failed to load PKCS#1 private key: %s\n"),
1243                                              gnutls_strerror(err));
1244                                 ret = -EINVAL;
1245                                 goto out;
1246                         }
1247                 }
1248         } else if (strstr((char *)fdata.data, "-----BEGIN PRIVATE KEY-----")) {
1249                 /* Unencrypted PKCS#8 */
1250                 err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
1251                                                        GNUTLS_X509_FMT_PEM,
1252                                                        NULL, GNUTLS_PKCS_PLAIN);
1253                 if (err) {
1254                         vpn_progress(vpninfo, PRG_ERR,
1255                                              _("Failed to load private key as PKCS#8: %s\n"),
1256                                              gnutls_strerror(err));
1257                         ret = -EINVAL;
1258                         goto out;
1259                 }
1260         } else if (strstr((char *)fdata.data, "-----BEGIN ENCRYPTED PRIVATE KEY-----")) {
1261                 /* Encrypted PKCS#8 */
1262                 char *pass = vpninfo->cert_password;
1263
1264                 while ((err = gnutls_x509_privkey_import_pkcs8(key, &fdata,
1265                                                                GNUTLS_X509_FMT_PEM,
1266                                                                pass?:"", 0))) {
1267                         if (err != GNUTLS_E_DECRYPTION_FAILED) {
1268                                 vpn_progress(vpninfo, PRG_ERR,
1269                                              _("Failed to load private key as PKCS#8: %s\n"),
1270                                              gnutls_strerror(err));
1271                                 ret = -EINVAL;
1272                                 goto out;
1273                         }
1274                         vpninfo->cert_password = NULL;
1275                         if (pass) {
1276                                 vpn_progress(vpninfo, PRG_ERR,
1277                                              _("Failed to decrypt PKCS#8 certificate file\n"));
1278                                 free(pass);
1279                         }
1280                         err = request_passphrase(vpninfo, "openconnect_pem",
1281                                                  &pass, _("Enter PEM pass phrase:"));
1282                         if (err) {
1283                                 ret = -EINVAL;
1284                                 goto out;
1285                         }
1286                 }
1287                 free(pass);
1288                 vpninfo->cert_password = NULL;
1289         } else {
1290                 vpn_progress(vpninfo, PRG_ERR,
1291                              _("Failed to determine type of private key %s\n"),
1292                              vpninfo->sslkey);
1293                 ret = -EINVAL;
1294                 goto out;
1295         }
1296
1297         /* Now attempt to make sure we use the *correct* certificate, to match
1298            the key. Since we have a software key, we can easily query it and
1299            compare its key_id with each certificate till we find a match. */
1300         err = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
1301         if (err) {
1302                 vpn_progress(vpninfo, PRG_ERR,
1303                              _("Failed to get key ID: %s\n"),
1304                              gnutls_strerror(err));
1305                 ret = -EINVAL;
1306                 goto out;
1307         }
1308         /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
1309         for (i = 0; i < (extra_certs?nr_extra_certs:1); i++) {
1310                 unsigned char cert_id[20];
1311                 size_t cert_id_size = sizeof(cert_id);
1312
1313                 err = gnutls_x509_crt_get_key_id(extra_certs?extra_certs[i]:cert, 0, cert_id, &cert_id_size);
1314                 if (err)
1315                         continue;
1316
1317                 if (cert_id_size == key_id_size && !memcmp(cert_id, key_id, key_id_size)) {
1318                         if (extra_certs) {
1319                                 cert = extra_certs[i];
1320                                 extra_certs[i] = NULL;
1321                         }
1322                         goto got_key;
1323                 }
1324         }
1325         /* There's no pkey (there's an x509 key), so even if p11-kit or trousers is
1326            enabled we'll fall straight through the bit at match_cert: below, and go
1327            directly to the bit where it prints the 'no match found' error and exits. */
1328
1329 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1330  match_cert:
1331         /* If we have a privkey from PKCS#11 or TPM, we can't do the simple comparison
1332            of key ID that we do for software keys to find which certificate is a
1333            match. So sign some dummy data and then check the signature against each
1334            of the available certificates until we find the right one. */
1335         if (pkey) {
1336                 /* The TPM code may have already signed it, to test authorisation. We
1337                    only sign here for PKCS#11 keys, in which case fdata might be
1338                    empty too so point it at dummy data. */
1339                 if (!pkey_sig.data) {
1340                         if (!fdata.data) {
1341                                 fdata.data = dummy_hash_data;
1342                                 fdata.size = 20;
1343                         }
1344
1345                         err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig);
1346                         if (err) {
1347                                 vpn_progress(vpninfo, PRG_ERR,
1348                                              _("Error signing test data with private key: %s\n"),
1349                                              gnutls_strerror(err));
1350                                 ret = -EINVAL;
1351                                 goto out;
1352                         }
1353                 }
1354
1355                 /* If extra_certs[] is NULL, we have one candidate in 'cert' to check. */
1356                 for (i=0; i < (extra_certs?nr_extra_certs:1); i++) {
1357                         gnutls_pubkey_t pubkey;
1358
1359                         gnutls_pubkey_init(&pubkey);
1360                         err = gnutls_pubkey_import_x509(pubkey, extra_certs?extra_certs[i]:cert, 0);
1361                         if (err) {
1362                                 vpn_progress(vpninfo, PRG_ERR,
1363                                              _("Error validating signature against certificate: %s\n"),
1364                                              gnutls_strerror(err));
1365                                 /* We'll probably fail shortly if we don't find it. */
1366                                 gnutls_pubkey_deinit(pubkey);
1367                                 continue;
1368                         }
1369                         err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig);
1370                         gnutls_pubkey_deinit(pubkey);
1371
1372                         if (err >= 0) {
1373                                 if (extra_certs) {
1374                                         cert = extra_certs[i];
1375                                         extra_certs[i] = NULL;
1376                                 }
1377                                 gnutls_free(pkey_sig.data);
1378                                 goto got_key;
1379                         }
1380                 }
1381                 gnutls_free(pkey_sig.data);
1382         }
1383 #endif /* P11KIT || TROUSERS */
1384
1385         /* We shouldn't reach this. It means that we didn't find *any* matching cert */
1386         vpn_progress(vpninfo, PRG_ERR,
1387                      _("No SSL certificate found to match private key\n"));
1388         ret = -EINVAL;
1389         goto out;
1390
1391         /********************************************************************/
1392  got_key:
1393         /* Now we have a key in either 'key' or 'pkey', a matching cert in 'cert',
1394            and potentially a list of other certs in 'extra_certs[]'. If we loaded
1395            a PKCS#12 file we may have a trust chain in 'supporting_certs[]' too. */
1396         check_certificate_expiry(vpninfo, cert);
1397         get_cert_name(cert, name, sizeof(name));
1398         vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"),
1399                      name);
1400
1401         if (crl) {
1402                 err = gnutls_certificate_set_x509_crl(vpninfo->https_cred, &crl, 1);
1403                 if (err) {
1404                         vpn_progress(vpninfo, PRG_ERR,
1405                                      _("Setting certificate recovation list failed: %s\n"),
1406                                      gnutls_strerror(err));
1407                         ret = -EINVAL;
1408                         goto out;
1409                 }
1410         }
1411
1412         /* OpenSSL has problems with certificate chains — if there are
1413            multiple certs with the same name, it doesn't necessarily
1414            choose the _right_ one. (RT#1942)
1415            Pick the right ones for ourselves and add them manually. */
1416
1417         if (nr_supporting_certs) {
1418                 /* We already got a bunch of certs from PKCS#12 file. Remember
1419                    how many need to be freed when we're done, since we'll
1420                    expand the supporting_certs array with more from the cafile
1421                    and extra_certs[] array if we can, and those extra certs
1422                    must not be freed (twice). */
1423                 last_cert = supporting_certs[nr_supporting_certs-1];
1424                 certs_to_free = nr_supporting_certs;
1425         } else {
1426                 last_cert = cert;
1427                 certs_to_free = nr_supporting_certs = 1;
1428         }
1429         while (1) {
1430                 gnutls_x509_crt_t issuer;
1431
1432                 for (i = 0; i < nr_extra_certs; i++) {
1433                         if (extra_certs[i] &&
1434                             gnutls_x509_crt_check_issuer(last_cert, extra_certs[i]) &&
1435                             !check_issuer_sanity(last_cert, extra_certs[i]))
1436                                 break;
1437                 }
1438
1439                 if (i < nr_extra_certs) {
1440                         /* We found the next cert in the chain in extra_certs[] */
1441                         issuer = extra_certs[i];
1442                 } else {
1443                         /* Look for it in the system trust cafile too. */
1444                         err = gnutls_certificate_get_issuer(vpninfo->https_cred,
1445                                                             last_cert, &issuer, 0);
1446                         if (err)
1447                                 break;
1448
1449                         /* The check_issuer_sanity() function works fine as a workaround where
1450                            it was used above, but when gnutls_certificate_get_issuer() returns
1451                            a bogus cert, there's nothing we can do to fix it up. We don't get
1452                            to iterate over all the available certs like we can over our own
1453                            list. */
1454                         if (check_issuer_sanity(last_cert, issuer)) {
1455                                 /* Hm, is there a bug reference for this? Or just the git commit
1456                                    reference (c1ef7efb in master, 5196786c in gnutls_3_0_x-2)? */
1457                                 vpn_progress(vpninfo, PRG_ERR,
1458                                              _("WARNING: GnuTLS returned incorrect issuer certs; authentication may fail!\n"));
1459                                 break;
1460                         }
1461                 }
1462
1463                 if (issuer == last_cert) {
1464                         /* Don't actually include the root CA. If they don't already trust it,
1465                            then handing it to them isn't going to help. But don't omit the
1466                            original certificate if it's self-signed. */
1467                         if (nr_supporting_certs > 1)
1468                                 nr_supporting_certs--;
1469                         break;
1470                 }
1471
1472                 /* OK, we found a new cert to add to our chain. */
1473                 supporting_certs = gnutls_realloc(supporting_certs,
1474                                                   sizeof(cert) * ++nr_supporting_certs);
1475                 if (!supporting_certs) {
1476                         vpn_progress(vpninfo, PRG_ERR,
1477                                      _("Failed to allocate memory for supporting certificates\n"));
1478                         /* The world is probably about to end, but try without them anyway */
1479                         certs_to_free = 0;
1480                         ret = -ENOMEM;
1481                         goto out;
1482                 }
1483
1484                 /* First time we actually allocated an array? Copy the first cert into it */
1485                 if (nr_supporting_certs == 2)
1486                         supporting_certs[0] = cert;
1487
1488                 /* Append the new one */
1489                 supporting_certs[nr_supporting_certs-1] = issuer;
1490                 last_cert = issuer;
1491         }
1492         for (i = 1; i < nr_supporting_certs; i++) {
1493                 get_cert_name(supporting_certs[i], name, sizeof(name));
1494
1495                 vpn_progress(vpninfo, PRG_DEBUG,
1496                              _("Adding supporting CA '%s'\n"), name);
1497         }
1498
1499         /* OK, now we've checked the cert expiry and warned the user if it's
1500            going to expire soon, and we've built up as much of a trust chain
1501            in supporting_certs[] as we can find, to help the server work around
1502            OpenSSL RT#1942. Set up the GnuTLS credentials with the appropriate
1503            key and certs. GnuTLS makes us do this differently for X509 privkeys
1504            vs. TPM/PKCS#11 "generic" privkeys, and the latter is particularly
1505            'fun' for GnuTLS 2.12... */
1506 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1507         if (pkey) {
1508                 err = assign_privkey(vpninfo, pkey,
1509                                      supporting_certs ? supporting_certs : &cert,
1510                                      nr_supporting_certs,
1511                                      extra_certs, nr_extra_certs);
1512                 if (!err) {
1513                         pkey = NULL; /* we gave it away, and potentially also some
1514                                         of extra_certs[] may have been zeroed. */
1515                 }
1516         } else
1517 #endif /* P11KIT || TROUSERS */
1518                 err = gnutls_certificate_set_x509_key(vpninfo->https_cred,
1519                                                       supporting_certs ? supporting_certs : &cert,
1520                                                       nr_supporting_certs, key);
1521
1522         if (err) {
1523                 vpn_progress(vpninfo, PRG_ERR,
1524                              _("Setting certificate failed: %s\n"),
1525                              gnutls_strerror(err));
1526                 ret = -EIO;
1527         } else
1528                 ret = 0;
1529  out:
1530         if (crl)
1531                 gnutls_x509_crl_deinit(crl);
1532         if (key)
1533                 gnutls_x509_privkey_deinit(key);
1534         if (supporting_certs) {
1535                 for (i = 0; i < certs_to_free; i++) {
1536                         if (supporting_certs[i])
1537                                 gnutls_x509_crt_deinit(supporting_certs[i]);
1538                 }
1539                 gnutls_free(supporting_certs);
1540         } else if (cert) {
1541                 /* Not if supporting_certs. It's supporting_certs[0] then and
1542                    was already freed. */
1543                 gnutls_x509_crt_deinit(cert);
1544         }
1545         for (i = 0; i < nr_extra_certs; i++) {
1546                 if (extra_certs[i])
1547                         gnutls_x509_crt_deinit(extra_certs[i]);
1548         }
1549         gnutls_free(extra_certs);
1550
1551 #if defined (HAVE_P11KIT) || defined (HAVE_TROUSERS)
1552         if (pkey && pkey != OPENCONNECT_TPM_PKEY)
1553                 gnutls_privkey_deinit(pkey);
1554         /* If we support arbitrary privkeys, we might have abused fdata.data
1555            just to point to something to hash. Don't free it in that case! */
1556         if (fdata.data != dummy_hash_data)
1557 #endif
1558                 gnutls_free(fdata.data);
1559
1560 #ifdef HAVE_P11KIT
1561         if (cert_url != vpninfo->cert)
1562                 free(cert_url);
1563         if (key_url != vpninfo->sslkey)
1564                 free(key_url);
1565 #endif
1566         return ret;
1567 }
1568
1569 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
1570                                 gnutls_x509_crt_t cert,
1571                                 gnutls_digest_algorithm_t algo,
1572                                 char *buf)
1573 {
1574         unsigned char md[256];
1575         size_t md_size = sizeof(md);
1576         unsigned int i;
1577
1578         if (gnutls_x509_crt_get_fingerprint(cert, algo, md, &md_size))
1579                 return -EIO;
1580
1581         for (i=0; i < md_size; i++)
1582                 sprintf(&buf[i*2], "%02X", md[i]);
1583
1584         return 0;
1585 }
1586
1587 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
1588                              OPENCONNECT_X509 *cert, char *buf)
1589 {
1590         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_MD5, buf);
1591 }
1592
1593 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
1594                               OPENCONNECT_X509 *cert, char *buf)
1595 {
1596         return get_cert_fingerprint(vpninfo, cert, GNUTLS_DIG_SHA1, buf);
1597 }
1598
1599 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1600                                    OPENCONNECT_X509 *cert)
1601 {
1602         gnutls_datum_t buf;
1603         char *ret;
1604
1605         if (gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &buf))
1606                 return NULL;
1607         
1608         /* Just in case gnutls_free() isn't free(), we can't steal it. */
1609         ret = strdup((char *)buf.data);
1610         gnutls_free(buf.data);
1611         
1612         return ret;
1613 }
1614
1615 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
1616                              OPENCONNECT_X509 *cert, unsigned char **buf)
1617 {
1618         size_t l = 0;
1619         unsigned char *ret = NULL;
1620
1621         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l) != 
1622             GNUTLS_E_SHORT_MEMORY_BUFFER)
1623                 return -EIO;
1624
1625         ret = malloc(l);
1626         if (!ret)
1627                 return -ENOMEM;
1628
1629         if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, ret, &l)) {
1630                 free(ret);
1631                 return -EIO;
1632         }
1633         *buf = ret;
1634         return l;
1635 }
1636
1637 static int verify_peer(gnutls_session_t session)
1638 {
1639         struct openconnect_info *vpninfo = gnutls_session_get_ptr(session);
1640         const gnutls_datum_t *cert_list;
1641         gnutls_x509_crt_t cert;
1642         unsigned int status, cert_list_size;
1643         const char *reason = NULL;
1644         int err;
1645
1646         if (vpninfo->peer_cert) {
1647                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1648                 vpninfo->peer_cert = NULL;
1649         }
1650
1651         cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
1652         if (!cert_list) {
1653                 vpn_progress(vpninfo, PRG_ERR, _("Server presented no certificate\n"));
1654                 return GNUTLS_E_CERTIFICATE_ERROR;
1655         }
1656
1657         if (vpninfo->servercert) {
1658                 unsigned char sha1bin[SHA1_SIZE];
1659                 char fingerprint[(SHA1_SIZE * 2) + 1];
1660                 int i;
1661                 
1662                 err = openconnect_sha1(sha1bin, cert_list[0].data, cert_list[0].size);
1663                 if (err) {
1664                         vpn_progress(vpninfo, PRG_ERR,
1665                                      _("Could not calculate SHA1 of server's certificate\n"));
1666                         return GNUTLS_E_CERTIFICATE_ERROR;
1667                 }
1668                 for (i=0; i < SHA1_SIZE; i++)
1669                         sprintf(&fingerprint[i*2], "%02X", sha1bin[i]);
1670
1671                 if (strcasecmp(vpninfo->servercert, fingerprint)) {
1672                         vpn_progress(vpninfo, PRG_ERR,
1673                                      _("Server SSL certificate didn't match: %s\n"), fingerprint);
1674                         return GNUTLS_E_CERTIFICATE_ERROR;
1675                 }
1676                 return 0;
1677         }
1678
1679         err = gnutls_certificate_verify_peers2 (session, &status);
1680         if (err) {
1681                 vpn_progress(vpninfo, PRG_ERR, _("Error checking server cert status\n"));
1682                 return GNUTLS_E_CERTIFICATE_ERROR;
1683         }
1684
1685         if (status & GNUTLS_CERT_REVOKED)
1686                 reason = _("certificate revoked");
1687         else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1688                 reason = _("signer not found");
1689         else if (status & GNUTLS_CERT_SIGNER_NOT_CA)
1690                 reason = _("signer not a CA certificate");
1691         else if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1692                 reason = _("insecure algorithm");
1693         else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1694                 reason = _("certificate not yet activated");
1695         else if (status & GNUTLS_CERT_EXPIRED)
1696                 reason = _("certificate expired");
1697         else if (status & GNUTLS_CERT_INVALID)
1698                 /* If this is set and no other reason, it apparently means
1699                    that signature verification failed. Not entirely sure
1700                    why we don't just set a bit for that too. */
1701                 reason = _("signature verification failed");
1702
1703         err = gnutls_x509_crt_init(&cert);
1704         if (err) {
1705                 vpn_progress(vpninfo, PRG_ERR, _("Error initialising X509 cert structure\n"));
1706                 return GNUTLS_E_CERTIFICATE_ERROR;
1707         }
1708
1709         err = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
1710         if (err) {
1711                 vpn_progress(vpninfo, PRG_ERR, _("Error importing server's cert\n"));
1712                 gnutls_x509_crt_deinit(cert);
1713                 return GNUTLS_E_CERTIFICATE_ERROR;
1714         }
1715
1716         if (!reason && !gnutls_x509_crt_check_hostname(cert, vpninfo->hostname))
1717                 reason = _("certificate does not match hostname");
1718
1719         if (reason) {
1720                 vpn_progress(vpninfo, PRG_INFO, "Server certificate verify failed: %s\n",
1721                              reason);
1722                 if (vpninfo->validate_peer_cert)
1723                         err = vpninfo->validate_peer_cert(vpninfo->cbdata,
1724                                                           cert,
1725                                                           reason) ? GNUTLS_E_CERTIFICATE_ERROR : 0;
1726                 else
1727                         err = GNUTLS_E_CERTIFICATE_ERROR;
1728         }
1729
1730         vpninfo->peer_cert = cert;
1731
1732         return err;
1733 }
1734
1735
1736 int openconnect_open_https(struct openconnect_info *vpninfo)
1737 {
1738         int ssl_sock = -1;
1739         int err;
1740
1741         if (vpninfo->https_sess)
1742                 return 0;
1743
1744         ssl_sock = connect_https_socket(vpninfo);
1745         if (ssl_sock < 0)
1746                 return ssl_sock;
1747
1748         if (!vpninfo->https_cred) {
1749                 gnutls_certificate_allocate_credentials(&vpninfo->https_cred);
1750 #ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
1751                 gnutls_certificate_set_x509_system_trust(vpninfo->https_cred);
1752 #else
1753                 gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1754                                                        DEFAULT_SYSTEM_CAFILE,
1755                                                        GNUTLS_X509_FMT_PEM);
1756 #endif
1757                 gnutls_certificate_set_verify_function (vpninfo->https_cred,
1758                                                         verify_peer);
1759
1760 #ifdef ANDROID_KEYSTORE
1761                 if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {
1762                         gnutls_datum_t datum;
1763                         unsigned int nr_certs;
1764
1765                         err = load_datum(vpninfo, &datum, vpninfo->cafile);
1766                         if (err < 0)
1767                                 return err;
1768
1769                         /* For GnuTLS 3.x We should use gnutls_x509_crt_list_import2() */
1770                         nr_certs = count_x509_certificates(&datum);
1771                         if (nr_certs) {
1772                                 gnutls_x509_crt *certs;
1773                                 int i;
1774
1775                                 certs = calloc(nr_certs, sizeof(*certs));
1776                                 if (!certs) {
1777                                         vpn_progress(vpninfo, PRG_ERR,
1778                                                      _("Failed to allocate memory for cafile certs\n"));
1779                                         gnutls_free(datum.data);
1780                                         close(ssl_sock);
1781                                         return -ENOMEM;
1782                                 }
1783                                 err = gnutls_x509_crt_list_import(certs, &nr_certs, &datum,
1784                                                                   GNUTLS_X509_FMT_PEM, 0);
1785                                 gnutls_free(datum.data);
1786                                 if (err >= 0) {
1787                                         nr_certs = err;
1788                                         err = gnutls_certificate_set_x509_trust(vpninfo->https_cred,
1789                                                                                 certs, nr_certs);
1790                                 }
1791                                 for (i = 0; i < nr_certs; i++)
1792                                         gnutls_x509_crt_deinit(certs[i]);
1793                                 free(certs);
1794                                 if (err < 0) {
1795                                         /* From crt_list_import or set_x509_trust */
1796                                         vpn_progress(vpninfo, PRG_ERR,
1797                                                      _("Failed to read certs from cafile: %s\n"),
1798                                                      gnutls_strerror(err));
1799                                         close(ssl_sock);
1800                                         return -EINVAL;
1801                                 }
1802                         }
1803                 } else
1804 #endif
1805                 if (vpninfo->cafile) {
1806                         err = gnutls_certificate_set_x509_trust_file(vpninfo->https_cred,
1807                                                                      vpninfo->cafile,
1808                                                                      GNUTLS_X509_FMT_PEM);
1809                         if (err < 0) {
1810                                 vpn_progress(vpninfo, PRG_ERR,
1811                                              _("Failed to open CA file '%s': %s\n"),
1812                                              vpninfo->cafile, gnutls_strerror(err));
1813                                 close(ssl_sock);
1814                                 return -EINVAL;
1815                         }
1816                 }
1817
1818                 if (vpninfo->cert) {
1819                         err = load_certificate(vpninfo);
1820                         if (err) {
1821                                 vpn_progress(vpninfo, PRG_ERR,
1822                                              _("Loading certificate failed. Aborting.\n"));
1823                                 close(ssl_sock);
1824                                 return err;
1825                         }
1826                 }
1827         }
1828         gnutls_init (&vpninfo->https_sess, GNUTLS_CLIENT);
1829         gnutls_session_set_ptr (vpninfo->https_sess, (void *) vpninfo);
1830 #if defined(HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY)
1831         if (vpninfo->my_pkey == OPENCONNECT_TPM_PKEY)
1832                 gnutls_sign_callback_set(vpninfo->https_sess, gtls2_tpm_sign_cb, vpninfo);
1833 #endif
1834
1835         err = gnutls_priority_set_direct (vpninfo->https_sess,
1836                                           "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:"
1837 #if GNUTLS_VERSION_MAJOR >= 3
1838                                           "-CURVE-ALL:"
1839 #endif
1840                                           "%COMPAT:%DISABLE_SAFE_RENEGOTIATION:%LATEST_RECORD_VERSION",
1841                                           NULL);
1842         if (err) {
1843                 vpn_progress(vpninfo, PRG_ERR,
1844                              _("Failed to set TLS priority string: %s\n"),
1845                              gnutls_strerror(err));
1846                 gnutls_deinit(vpninfo->https_sess);
1847                 vpninfo->https_sess = NULL;
1848                 close(ssl_sock);
1849                 return -EIO;
1850         }
1851
1852         gnutls_record_disable_padding (vpninfo->https_sess);
1853         gnutls_credentials_set (vpninfo->https_sess, GNUTLS_CRD_CERTIFICATE, vpninfo->https_cred);
1854         gnutls_transport_set_ptr(vpninfo->https_sess, /* really? */(gnutls_transport_ptr_t)(long) ssl_sock);
1855
1856         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1857                      vpninfo->hostname);
1858
1859         while ((err = gnutls_handshake (vpninfo->https_sess))) {
1860                 if (err == GNUTLS_E_AGAIN) {
1861                         fd_set rd_set, wr_set;
1862                         int maxfd = ssl_sock;
1863
1864                         FD_ZERO(&rd_set);
1865                         FD_ZERO(&wr_set);
1866
1867                         if (gnutls_record_get_direction(vpninfo->https_sess))
1868                                 FD_SET(ssl_sock, &wr_set);
1869                         else
1870                                 FD_SET(ssl_sock, &rd_set);
1871
1872                         if (vpninfo->cancel_fd != -1) {
1873                                 FD_SET(vpninfo->cancel_fd, &rd_set);
1874                                 if (vpninfo->cancel_fd > ssl_sock)
1875                                         maxfd = vpninfo->cancel_fd;
1876                         }
1877                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1878                         if (vpninfo->cancel_fd != -1 &&
1879                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1880                                 vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1881                                 gnutls_deinit(vpninfo->https_sess);
1882                                 vpninfo->https_sess = NULL;
1883                                 close(ssl_sock);
1884                                 return -EINTR;
1885                         }
1886                 } else if (err == GNUTLS_E_INTERRUPTED || gnutls_error_is_fatal(err)) {
1887                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure: %s\n"),
1888                                                          gnutls_strerror(err));
1889                         gnutls_deinit(vpninfo->https_sess);
1890                         vpninfo->https_sess = NULL;
1891                         close(ssl_sock);
1892                         return -EIO;
1893                 } else {
1894                         /* non-fatal error or warning. Ignore it and continue */
1895                         vpn_progress(vpninfo, PRG_TRACE,
1896                                      _("GnuTLS non-fatal return during handshake: %s\n"),
1897                                      gnutls_strerror(err));
1898                 }
1899         }
1900
1901         vpninfo->ssl_fd = ssl_sock;
1902
1903         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1904                      vpninfo->hostname);
1905
1906         return 0;
1907 }
1908
1909 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1910 {
1911         if (vpninfo->peer_cert) {
1912                 gnutls_x509_crt_deinit(vpninfo->peer_cert);
1913                 vpninfo->peer_cert = NULL;
1914         }
1915         if (vpninfo->https_sess) {
1916                 gnutls_deinit(vpninfo->https_sess);
1917                 vpninfo->https_sess = NULL;
1918         }
1919         if (vpninfo->ssl_fd != -1) {
1920                 close(vpninfo->ssl_fd);
1921                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1922                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1923                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1924                 vpninfo->ssl_fd = -1;
1925         }
1926         if (final && vpninfo->https_cred) {
1927                 gnutls_certificate_free_credentials(vpninfo->https_cred);
1928                 vpninfo->https_cred = NULL;
1929 #ifdef HAVE_P11KIT
1930                 if ((vpninfo->cert && !strncmp(vpninfo->cert, "pkcs11:", 7)) ||
1931                     (vpninfo->sslkey && !strncmp(vpninfo->sslkey, "pkcs11:", 7))) {
1932                         char pin_source[40];
1933
1934                         sprintf(pin_source, "openconnect:%p", vpninfo);
1935                         p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
1936
1937                         while (vpninfo->pin_cache) {
1938                                 struct pin_cache *cache = vpninfo->pin_cache;
1939
1940                                 free(cache->token);
1941                                 memset(cache->pin, 0x5a, strlen(cache->pin));
1942                                 free(cache->pin);
1943                                 vpninfo->pin_cache = cache->next;
1944                                 free(cache);
1945                         }
1946                 }
1947 #endif
1948 #ifdef HAVE_TROUSERS
1949                 if (vpninfo->tpm_key_policy) {
1950                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
1951                         vpninfo->tpm_key = 0;
1952                 }
1953                 if (vpninfo->tpm_key) {
1954                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
1955                         vpninfo->tpm_key = 0;
1956                 }
1957                 if (vpninfo->srk_policy) {
1958                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
1959                         vpninfo->srk_policy = 0;
1960                 }
1961                 if (vpninfo->srk) {
1962                         Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
1963                         vpninfo->srk = 0;
1964                 }
1965                 if (vpninfo->tpm_context) {
1966                         Tspi_Context_Close(vpninfo->tpm_context);
1967                         vpninfo->tpm_context = 0;
1968                 }
1969 #endif
1970 #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY
1971                 if (vpninfo->my_pkey && vpninfo->my_pkey != OPENCONNECT_TPM_PKEY) {
1972                         gnutls_privkey_deinit(vpninfo->my_pkey);
1973                         vpninfo->my_pkey = NULL;
1974                         /* my_p11key went with it */
1975                 }
1976                 if (vpninfo->my_certs) {
1977                         int i;
1978                         for (i = 0; i < vpninfo->nr_my_certs; i++)
1979                                 gnutls_x509_crt_deinit(vpninfo->my_certs[i]);
1980                         free(vpninfo->my_certs);
1981                         vpninfo->my_certs = NULL;
1982                 }
1983 #endif
1984         }
1985 }
1986
1987 void openconnect_init_ssl(void)
1988 {
1989         gnutls_global_init();
1990 }
1991
1992 int openconnect_sha1(unsigned char *result, void *data, int datalen)
1993 {
1994         gnutls_datum_t d;
1995         size_t shalen = SHA1_SIZE;
1996
1997         d.data = data;
1998         d.size = datalen;
1999         if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, result, &shalen))
2000                 return -1;
2001
2002         return 0;
2003 }
2004
2005 int openconnect_random(void *bytes, int len)
2006 {
2007         if (gnutls_rnd(GNUTLS_RND_RANDOM, bytes, len))
2008                 return -EIO;
2009         return 0;
2010 }
2011
2012 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
2013                                char *buf)
2014 {
2015         const gnutls_datum_t *d;
2016         size_t md5len = 16;
2017
2018         buf[0] = 0;
2019
2020         d = gnutls_certificate_get_ours(vpninfo->https_sess);
2021         if (!d)
2022                 return -EIO;
2023
2024         if (gnutls_fingerprint(GNUTLS_DIG_MD5, d, buf, &md5len))
2025                 return -EIO;
2026
2027         return 0;
2028 }
2029
2030 #ifdef HAVE_P11KIT
2031 static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
2032                         const char *pin_description,
2033                         P11KitPinFlags flags,
2034                         void *_vpninfo)
2035 {
2036         struct openconnect_info *vpninfo = _vpninfo;
2037         struct pin_cache **cache = &vpninfo->pin_cache;
2038         struct oc_auth_form f;
2039         struct oc_form_opt o;
2040         char message[1024];
2041         char *uri;
2042         P11KitPin *pin;
2043         int ret;
2044
2045         if (!vpninfo || !vpninfo->process_auth_form)
2046                 return NULL;
2047
2048         if (p11_kit_uri_format(pin_uri, P11_KIT_URI_FOR_TOKEN, &uri))
2049                 return NULL;
2050
2051         while (*cache) {
2052                 if (!strcmp(uri, (*cache)->token)) {
2053                         free(uri);
2054                         uri = NULL;
2055                         if ((*cache)->pin) {
2056                                 if ((flags & P11_KIT_PIN_FLAGS_RETRY) != P11_KIT_PIN_FLAGS_RETRY)
2057                                         return p11_kit_pin_new_for_string((*cache)->pin);
2058                                 memset((*cache)->pin, 0x5a, strlen((*cache)->pin));
2059                                 free((*cache)->pin);
2060                                 (*cache)->pin = NULL;
2061                         }
2062                         break;
2063                 }
2064                 cache = &(*cache)->next;
2065         }
2066         if (!*cache) {
2067                 *cache = calloc(1, sizeof(struct pin_cache));
2068                 if (!*cache) {
2069                         free(uri);
2070                         return NULL;
2071                 }
2072                 (*cache)->token = uri;
2073         }
2074
2075         memset(&f, 0, sizeof(f));
2076         f.auth_id = (char *)"pkcs11_pin";
2077         f.opts = &o;
2078
2079         message[sizeof(message)-1] = 0;
2080         snprintf(message, sizeof(message) - 1, _("PIN required for %s"), pin_description);
2081         f.message = message;
2082
2083         /*
2084          * In p11-kit <= 0.12, these flags are *odd*.
2085          * RETRY is 0xa, FINAL_TRY is 0x14 and MANY_TRIES is 0x28.
2086          * So don't treat it like a sane bitmask. Fixed in
2087          * http://cgit.freedesktop.org/p11-glue/p11-kit/commit/?id=59774b11
2088          */
2089         if ((flags & P11_KIT_PIN_FLAGS_RETRY) == P11_KIT_PIN_FLAGS_RETRY)
2090                 f.error = (char *)_("Wrong PIN");
2091
2092         if ((flags & P11_KIT_PIN_FLAGS_FINAL_TRY) == P11_KIT_PIN_FLAGS_FINAL_TRY)
2093                 f.banner = (char *)_("This is the final try before locking!");
2094         else if ((flags & P11_KIT_PIN_FLAGS_MANY_TRIES) == P11_KIT_PIN_FLAGS_MANY_TRIES)
2095                 f.banner = (char *)_("Only a few tries left before locking!");
2096
2097         o.next = NULL;
2098         o.type = OC_FORM_OPT_PASSWORD;
2099         o.name = (char *)"pkcs11_pin";
2100         o.label = (char *)_("Enter PIN:");
2101         o.value = NULL;
2102
2103         ret = vpninfo->process_auth_form(vpninfo->cbdata, &f);
2104         if (ret || !o.value)
2105                 return NULL;
2106
2107         pin = p11_kit_pin_new_for_string(o.value);
2108         (*cache)->pin = o.value;
2109
2110         return pin;
2111 }
2112 #endif