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