Tag version 4.00
[platform/upstream/openconnect.git] / openssl.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 <errno.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <ctype.h>
30
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
33 #include <openssl/engine.h>
34 #include <openssl/evp.h>
35 #include <openssl/rand.h>
36 #include <openssl/pkcs12.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/x509.h>
39 #include <openssl/bio.h>
40
41 #include "openconnect-internal.h"
42
43 int openconnect_sha1(unsigned char *result, void *data, int len)
44 {
45         EVP_MD_CTX c;
46
47         EVP_MD_CTX_init(&c);
48         EVP_Digest(data, len, result, NULL, EVP_sha1(), NULL);
49         EVP_MD_CTX_cleanup(&c);
50
51         return 0;
52 }
53
54 int openconnect_get_cert_DER(struct openconnect_info *vpninfo,
55                              OPENCONNECT_X509 *cert, unsigned char **buf)
56 {
57         BIO *bp = BIO_new(BIO_s_mem());
58         BUF_MEM *certinfo;
59         size_t l;
60
61         if (!i2d_X509_bio(bp, cert)) {
62                 BIO_free(bp);
63                 return -EIO;
64         }
65
66         BIO_get_mem_ptr(bp, &certinfo);
67         l = certinfo->length;
68         *buf = malloc(l);
69         if (!*buf) {
70                 BIO_free(bp);
71                 return -ENOMEM;
72         }
73         memcpy(*buf, certinfo->data, l);
74         BIO_free(bp);
75         return l;
76 }
77
78 int openconnect_random(void *bytes, int len)
79 {
80         if (RAND_bytes(bytes, len) != 1)
81                 return -EIO;
82         return 0;
83 }
84
85 /* Helper functions for reading/writing lines over SSL.
86    We could use cURL for the HTTP stuff, but it's overkill */
87
88 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len)
89 {
90         size_t orig_len = len;
91
92         while (len) {
93                 int done = SSL_write(vpninfo->https_ssl, buf, len);
94
95                 if (done > 0)
96                         len -= done;
97                 else {
98                         int err = SSL_get_error(vpninfo->https_ssl, done);
99                         fd_set wr_set, rd_set;
100                         int maxfd = vpninfo->ssl_fd;
101
102                         FD_ZERO(&wr_set);
103                         FD_ZERO(&rd_set);
104                         
105                         if (err == SSL_ERROR_WANT_READ)
106                                 FD_SET(vpninfo->ssl_fd, &rd_set);
107                         else if (err == SSL_ERROR_WANT_WRITE)
108                                 FD_SET(vpninfo->ssl_fd, &wr_set);
109                         else {
110                                 vpn_progress(vpninfo, PRG_ERR, _("Failed to write to SSL socket"));
111                                 openconnect_report_ssl_errors(vpninfo);
112                                 return -EIO;
113                         }
114                         if (vpninfo->cancel_fd != -1) {
115                                 FD_SET(vpninfo->cancel_fd, &rd_set);
116                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
117                                         maxfd = vpninfo->cancel_fd;
118                         }
119                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
120                         if (vpninfo->cancel_fd != -1 &&
121                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
122                                 vpn_progress(vpninfo, PRG_ERR, _("SSL write cancelled\n"));
123                                 return -EINTR;
124                         }
125                 }
126         }
127         return orig_len;
128 }
129
130 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len)
131 {
132         int done;
133
134         while ((done = SSL_read(vpninfo->https_ssl, buf, len)) == -1) {
135                 int err = SSL_get_error(vpninfo->https_ssl, done);
136                 fd_set wr_set, rd_set;
137                 int maxfd = vpninfo->ssl_fd;
138
139                 FD_ZERO(&wr_set);
140                 FD_ZERO(&rd_set);
141                         
142                 if (err == SSL_ERROR_WANT_READ)
143                         FD_SET(vpninfo->ssl_fd, &rd_set);
144                 else if (err == SSL_ERROR_WANT_WRITE)
145                         FD_SET(vpninfo->ssl_fd, &wr_set);
146                 else {
147                         vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket"));
148                         openconnect_report_ssl_errors(vpninfo);
149                         return -EIO;
150                 }
151                 if (vpninfo->cancel_fd != -1) {
152                         FD_SET(vpninfo->cancel_fd, &rd_set);
153                         if (vpninfo->cancel_fd > vpninfo->ssl_fd)
154                                 maxfd = vpninfo->cancel_fd;
155                 }
156                 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
157                 if (vpninfo->cancel_fd != -1 &&
158                     FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
159                         vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
160                         return -EINTR;
161                 }
162         }
163         return done;
164 }
165
166 int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
167 {
168         int i = 0;
169         int ret;
170
171         if (len < 2)
172                 return -EINVAL;
173
174         while (1) {
175                 ret = SSL_read(vpninfo->https_ssl, buf + i, 1);
176                 if (ret == 1) {
177                         if (buf[i] == '\n') {
178                                 buf[i] = 0;
179                                 if (i && buf[i-1] == '\r') {
180                                         buf[i-1] = 0;
181                                         i--;
182                                 }
183                                 return i;
184                         }
185                         i++;
186
187                         if (i >= len - 1) {
188                                 buf[i] = 0;
189                                 return i;
190                         }
191                 } else {
192                         fd_set rd_set, wr_set;
193                         int maxfd = vpninfo->ssl_fd;
194                         
195                         FD_ZERO(&rd_set);
196                         FD_ZERO(&wr_set);
197                         
198                         ret = SSL_get_error(vpninfo->https_ssl, ret);
199                         if (ret == SSL_ERROR_WANT_READ)
200                                 FD_SET(vpninfo->ssl_fd, &rd_set);
201                         else if (ret == SSL_ERROR_WANT_WRITE)
202                                 FD_SET(vpninfo->ssl_fd, &wr_set);
203                         else {
204                                 vpn_progress(vpninfo, PRG_ERR, _("Failed to read from SSL socket\n"));
205                                 openconnect_report_ssl_errors(vpninfo);
206                                 ret = -EIO;
207                                 break;
208                         }
209                         if (vpninfo->cancel_fd != -1) {
210                                 FD_SET(vpninfo->cancel_fd, &rd_set);
211                                 if (vpninfo->cancel_fd > vpninfo->ssl_fd)
212                                         maxfd = vpninfo->cancel_fd;
213                         }
214                         select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
215                         if (vpninfo->cancel_fd != -1 &&
216                             FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
217                                 vpn_progress(vpninfo, PRG_ERR, _("SSL read cancelled\n"));
218                                 ret = -EINTR;
219                                 break;
220                         }
221                 }
222         }
223         buf[i] = 0;
224         return i ?: ret;
225 }
226
227
228 /* UI handling. All this just to handle the PIN callback from the TPM ENGINE,
229    and turn it into a call to our ->process_auth_form function */
230
231 struct ui_data {
232         struct openconnect_info *vpninfo;
233         struct oc_form_opt **last_opt;
234         struct oc_auth_form form;
235 };
236
237 struct ui_form_opt {
238         struct oc_form_opt opt;
239         UI_STRING *uis;
240 };
241
242  /* Ick. But there is no way to pass this sanely through OpenSSL */
243 static struct openconnect_info *ui_vpninfo;
244
245 static int ui_open(UI *ui)
246 {
247         struct openconnect_info *vpninfo = ui_vpninfo; /* Ick */
248         struct ui_data *ui_data;
249
250         if (!vpninfo || !vpninfo->process_auth_form)
251                 return 0;
252         
253         ui_data = malloc(sizeof(*ui_data));
254         if (!ui_data)
255                 return 0;
256
257         memset(ui_data, 0, sizeof(*ui_data));
258         ui_data->last_opt = &ui_data->form.opts;
259         ui_data->vpninfo = vpninfo;
260         ui_data->form.auth_id = (char *)"openssl_ui";
261         UI_add_user_data(ui, ui_data);
262
263         return 1;
264 }
265
266 static int ui_write(UI *ui, UI_STRING *uis)
267 {
268         struct ui_data *ui_data = UI_get0_user_data(ui);
269         struct ui_form_opt *opt;
270
271         switch(UI_get_string_type(uis)) {
272         case UIT_ERROR:
273                 ui_data->form.error = (char *)UI_get0_output_string(uis);
274                 break;
275         case UIT_INFO:
276                 ui_data->form.message = (char *)UI_get0_output_string(uis);
277                 break;
278         case UIT_PROMPT:
279                 opt = malloc(sizeof(*opt));
280                 if (!opt)
281                         return 1;
282                 memset(opt, 0, sizeof(*opt));
283                 opt->uis = uis;
284                 opt->opt.label = opt->opt.name = (char *)UI_get0_output_string(uis);
285                 if (UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO)
286                         opt->opt.type = OC_FORM_OPT_TEXT;
287                 else
288                         opt->opt.type = OC_FORM_OPT_PASSWORD;
289                 *(ui_data->last_opt) = &opt->opt;
290                 ui_data->last_opt = &opt->opt.next;
291                 break;
292
293         default:
294                 fprintf(stderr, "Unhandled SSL UI request type %d\n",
295                         UI_get_string_type(uis));
296                 return 0;
297         }
298         return 1;
299 }
300
301 static int ui_flush(UI *ui)
302 {
303         struct ui_data *ui_data = UI_get0_user_data(ui);
304         struct openconnect_info *vpninfo = ui_data->vpninfo;
305         struct ui_form_opt *opt;
306         int ret;
307
308         ret = vpninfo->process_auth_form(vpninfo->cbdata, &ui_data->form);
309         if (ret)
310                 return 0;
311
312         for (opt = (struct ui_form_opt *)ui_data->form.opts; opt;
313              opt = (struct ui_form_opt *)opt->opt.next) {
314                 if (opt->opt.value && opt->uis)
315                         UI_set_result(ui, opt->uis, opt->opt.value);
316         }
317         return 1;
318 }
319
320 static int ui_close(UI *ui)
321 {
322         struct ui_data *ui_data = UI_get0_user_data(ui);
323         struct ui_form_opt *opt, *next_opt;
324
325         opt = (struct ui_form_opt *)ui_data->form.opts;
326         while (opt) {
327                 next_opt = (struct ui_form_opt *)opt->opt.next;
328                 if (opt->opt.value)
329                         free(opt->opt.value);
330                 free(opt);
331                 opt = next_opt;
332         }
333         free(ui_data);
334         UI_add_user_data(ui, NULL);
335
336         return 1;
337 }
338
339 static UI_METHOD *create_openssl_ui(struct openconnect_info *vpninfo)
340 {
341         UI_METHOD *ui_method = UI_create_method((char *)"AnyConnect VPN UI");
342
343         /* There is a race condition here because of the use of the
344            static ui_vpninfo pointer. This sucks, but it's OpenSSL's
345            fault and in practice it's *never* going to hurt us.
346
347            This UI is only used for loading certificates from a TPM; for
348            PKCS#12 and PEM files we hook the passphrase request differently.
349            The ui_vpninfo variable is set here, and is used from ui_open()
350            when the TPM ENGINE decides it needs to ask the user for a PIN.
351
352            The race condition exists because theoretically, there
353            could be more than one thread using libopenconnect and
354            trying to authenticate to a VPN server, within the *same*
355            process. And if *both* are using certificates from the TPM,
356            and *both* manage to be within that short window of time
357            between setting ui_vpninfo and invoking ui_open() to fetch
358            the PIN, then one connection's ->process_auth_form() could
359            get a PIN request for the *other* connection. 
360
361            However, the only thing that ever does run libopenconnect more
362            than once from the same process is KDE's NetworkManager support,
363            and NetworkManager doesn't *support* having more than one VPN
364            connected anyway, so first that would have to be fixed and then
365            you'd have to connect to two VPNs simultaneously by clicking
366            'connect' on both at *exactly* the same time and then getting
367            *really* unlucky.
368
369            Oh, and the KDE support won't be using OpenSSL anyway because of
370            licensing conflicts... so although this sucks, I'm not going to
371            lose sleep over it.
372         */
373         ui_vpninfo = vpninfo;
374
375         /* Set up a UI method of our own for password/passphrase requests */
376         UI_method_set_opener(ui_method, ui_open);
377         UI_method_set_writer(ui_method, ui_write);
378         UI_method_set_flusher(ui_method, ui_flush);
379         UI_method_set_closer(ui_method, ui_close);
380
381         return ui_method;
382 }
383
384 static int pem_pw_cb(char *buf, int len, int w, void *v)
385 {
386         struct openconnect_info *vpninfo = v;
387         char *pass = NULL;
388         int plen;
389
390         if (vpninfo->cert_password) {
391                 pass = vpninfo->cert_password;
392                 vpninfo->cert_password = NULL;
393         } else if (request_passphrase(vpninfo, "openconnect_pem",
394                                       &pass, _("Enter PEM pass phrase:")))
395                 return -1;
396
397         plen = strlen(pass);
398
399         if (len <= plen) {
400                 vpn_progress(vpninfo, PRG_ERR,
401                              _("PEM password too long (%d >= %d)\n"),
402                              plen, len);
403                 free(pass);
404                 return -1;
405         }
406
407         memcpy(buf, pass, plen+1);
408         free(pass);
409         return plen;
410 }
411
412 static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12)
413 {
414         EVP_PKEY *pkey = NULL;
415         X509 *cert = NULL;
416         STACK_OF(X509) *ca;
417         int ret = 0;
418         char *pass;
419
420         pass = vpninfo->cert_password;
421         vpninfo->cert_password = NULL;
422  retrypass:
423         /* We do this every time round the loop, to work around a bug in
424            OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed
425            when PKCS12_parse() returns an error, but *ca is left pointing
426            to the freed memory. */
427         ca = NULL;
428         if (!pass && request_passphrase(vpninfo, "openconnect_pkcs12", &pass,
429                                         _("Enter PKCS#12 pass phrase:")) < 0) {
430                 PKCS12_free(p12);
431                 return -EINVAL;
432         }
433         if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) {
434                 unsigned long err = ERR_peek_error();
435
436                 openconnect_report_ssl_errors(vpninfo);
437
438                 if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&
439                     ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE &&
440                     ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {
441                         vpn_progress(vpninfo, PRG_ERR,
442                                      _("Parse PKCS#12 failed (wrong passphrase?)\n"));
443                         free(pass);
444                         pass = NULL;
445                         goto retrypass;
446                 }
447
448                 vpn_progress(vpninfo, PRG_ERR,
449                              _("Parse PKCS#12 failed (see above errors)\n"));
450                 PKCS12_free(p12);
451                 free(pass);
452                 return -EINVAL;
453         }
454         free(pass);
455         if (cert) {
456                 char buf[200];
457                 vpninfo->cert_x509 = cert;
458                 SSL_CTX_use_certificate(vpninfo->https_ctx, cert);
459                 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
460                 vpn_progress(vpninfo, PRG_INFO,
461                              _("Using client certificate '%s'\n"), buf);
462         } else {
463                 vpn_progress(vpninfo, PRG_ERR,
464                              _("PKCS#12 contained no certificate!"));
465                 ret = -EINVAL;
466         }
467
468         if (pkey) {
469                 SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey);
470                 EVP_PKEY_free(pkey);
471         } else {
472                 vpn_progress(vpninfo, PRG_ERR,
473                              _("PKCS#12 contained no private key!"));
474                 ret = -EINVAL;
475         }
476
477         /* Only include supporting certificates which are actually necessary */
478         if (ca) {
479                 int i;
480         next:
481                 for (i = 0; i < sk_X509_num(ca); i++) {
482                         X509 *cert2 = sk_X509_value(ca, i);
483                         if (X509_check_issued(cert2, cert) == X509_V_OK) {
484                                 char buf[200];
485
486                                 if (cert2 == cert)
487                                         break;
488                                 if (X509_check_issued(cert2, cert2) == X509_V_OK)
489                                         break;
490
491                                 X509_NAME_oneline(X509_get_subject_name(cert2),
492                                                   buf, sizeof(buf));
493                                 vpn_progress(vpninfo, PRG_DEBUG,
494                                              _("Extra cert from PKCS#12: '%s'\n"), buf);
495                                 CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509);
496                                 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2);
497                                 cert = cert2;
498                                 goto next;
499                         }
500                 }
501                 sk_X509_pop_free(ca, X509_free);
502         }
503
504         PKCS12_free(p12);
505         return ret;
506 }
507
508 #ifdef HAVE_ENGINE
509 static int load_tpm_certificate(struct openconnect_info *vpninfo)
510 {
511         ENGINE *e;
512         EVP_PKEY *key;
513         UI_METHOD *meth = NULL;
514         int ret = 0;
515
516         ENGINE_load_builtin_engines();
517
518         e = ENGINE_by_id("tpm");
519         if (!e) {
520                 vpn_progress(vpninfo, PRG_ERR, _("Can't load TPM engine.\n"));
521                 openconnect_report_ssl_errors(vpninfo);
522                 return -EINVAL;
523         }
524         if (!ENGINE_init(e) || !ENGINE_set_default_RSA(e) ||
525             !ENGINE_set_default_RAND(e)) {
526                 vpn_progress(vpninfo, PRG_ERR, _("Failed to init TPM engine\n"));
527                 openconnect_report_ssl_errors(vpninfo);
528                 ENGINE_free(e);
529                 return -EINVAL;
530         }
531
532         if (vpninfo->cert_password) {
533                 if (!ENGINE_ctrl_cmd(e, "PIN", strlen(vpninfo->cert_password),
534                                      vpninfo->cert_password, NULL, 0)) {
535                         vpn_progress(vpninfo, PRG_ERR,
536                                      _("Failed to set TPM SRK password\n"));
537                         openconnect_report_ssl_errors(vpninfo);
538                 }
539                 vpninfo->cert_password = NULL;
540                 free(vpninfo->cert_password);
541         } else {
542                 /* Provide our own UI method to handle the PIN callback. */
543                 meth = create_openssl_ui(vpninfo);
544         }
545         key = ENGINE_load_private_key(e, vpninfo->sslkey, meth, NULL);
546         if (meth)
547                 UI_destroy_method(meth);
548         if (!key) {
549                 vpn_progress(vpninfo, PRG_ERR,
550                              _("Failed to load TPM private key\n"));
551                 openconnect_report_ssl_errors(vpninfo);
552                 ret = -EINVAL;
553                 goto out;
554         }
555         if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
556                 vpn_progress(vpninfo, PRG_ERR, _("Add key from TPM failed\n"));
557                 openconnect_report_ssl_errors(vpninfo);
558                 ret = -EINVAL;
559         }
560         EVP_PKEY_free(key);
561  out:
562         ENGINE_finish(e);
563         ENGINE_free(e);
564         return ret;
565 }
566 #else
567 static int load_tpm_certificate(struct openconnect_info *vpninfo)
568 {
569         vpn_progress(vpninfo, PRG_ERR,
570                      _("This version of OpenConnect was built without TPM support\n"));
571         return -EINVAL;
572 }
573 #endif
574
575 static int reload_pem_cert(struct openconnect_info *vpninfo)
576 {
577         BIO *b = BIO_new(BIO_s_file_internal());
578         char buf[200];
579
580         if (!b)
581                 return -ENOMEM;
582
583         if (BIO_read_filename(b, vpninfo->cert) <= 0) {
584         err:
585                 BIO_free(b);
586                 vpn_progress(vpninfo, PRG_ERR,
587                              _("Failed to reload X509 cert for expiry check\n"));
588                 openconnect_report_ssl_errors(vpninfo);
589                 return -EIO;
590         }
591         vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL);
592         BIO_free(b);
593         if (!vpninfo->cert_x509)
594                 goto err;
595
596         X509_NAME_oneline(X509_get_subject_name(vpninfo->cert_x509), buf, sizeof(buf));
597         vpn_progress(vpninfo, PRG_INFO,
598                              _("Using client certificate '%s'\n"), buf);
599
600         return 0;
601 }
602
603 #ifdef ANDROID_KEYSTORE
604 static BIO *BIO_from_keystore(struct openconnect_info *vpninfo, const char *item)
605 {
606         unsigned char *content;
607         BIO *b;
608         int len;
609         const char *p = item + 9;
610
611         /* Skip first two slashes if the user has given it as
612            keystore://foo ... */
613         if (*p == '/')
614                 p++;
615         if (*p == '/')
616                 p++;
617
618         len = keystore_fetch(p, &content);
619         if (len < 0) {
620                 vpn_progress(vpninfo, PRG_ERR,
621                              _("Failed to load item '%s' from keystore: %s\n"),
622                              p, keystore_strerror(len));
623                 return NULL;
624         }
625         if (!(b = BIO_new(BIO_s_mem())) || BIO_write(b, content, len) != len) {
626                 vpn_progress(vpninfo, PRG_ERR,
627                              _("Failed to create BIO for keystore item '%s'\n"),
628                                p);
629                 free(content);
630                 BIO_free(b);
631                 return NULL;
632         }
633         free(content);
634         return b;
635 }
636 #endif
637
638 static int is_pem_password_error(struct openconnect_info *vpninfo)
639 {
640         unsigned long err = ERR_peek_error();
641
642         openconnect_report_ssl_errors(vpninfo);
643
644 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
645 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
646 #endif
647         /* If the user fat-fingered the passphrase, try again */
648         if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
649             ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
650             ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
651                 vpn_progress(vpninfo, PRG_ERR,
652                              _("Loading private key failed (wrong passphrase?)\n"));
653                 ERR_clear_error();
654                 return 1;
655         }
656
657         vpn_progress(vpninfo, PRG_ERR,
658                      _("Loading private key failed (see above errors)\n"));
659         return 0;
660 }
661
662 static int load_certificate(struct openconnect_info *vpninfo)
663 {
664         if (!strncmp(vpninfo->sslkey, "pkcs11:", 7) ||
665             !strncmp(vpninfo->cert, "pkcs11:", 7)) {
666                 vpn_progress(vpninfo, PRG_ERR,
667                              _("This binary built without PKCS#11 support\n"));
668                 return -EINVAL;
669         }
670                      
671         vpn_progress(vpninfo, PRG_TRACE,
672                      _("Using certificate file %s\n"), vpninfo->cert);
673
674         if (strncmp(vpninfo->cert, "keystore:", 9) &&
675             (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
676              vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
677                 FILE *f;
678                 PKCS12 *p12;
679
680                 f = fopen(vpninfo->cert, "r");
681                 if (!f) {
682                         vpn_progress(vpninfo, PRG_ERR,
683                                      _("Failed to open certificate file %s: %s\n"),
684                                      vpninfo->cert, strerror(errno));
685                         return -ENOENT;
686                 }
687                 p12 = d2i_PKCS12_fp(f, NULL);
688                 fclose(f);
689                 if (p12)
690                         return load_pkcs12_certificate(vpninfo, p12);
691
692                 /* Not PKCS#12 */
693                 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
694                         vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
695                         openconnect_report_ssl_errors(vpninfo);
696                         return -EINVAL;
697                 }
698                 /* Clear error and fall through to see if it's a PEM file... */
699                 ERR_clear_error();
700         }
701
702         /* It's PEM or TPM now, and either way we need to load the plain cert: */
703 #ifdef ANDROID_KEYSTORE
704         if (!strncmp(vpninfo->cert, "keystore:", 9)) {
705                 BIO *b = BIO_from_keystore(vpninfo, vpninfo->cert);
706                 if (!b)
707                         return -EINVAL;
708                 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, pem_pw_cb, vpninfo);
709                 BIO_free(b);
710                 if (!vpninfo->cert_x509) {
711                         vpn_progress(vpninfo, PRG_ERR,
712                                      _("Failed to load X509 certificate from keystore\n"));
713                         openconnect_report_ssl_errors(vpninfo);
714                         return -EINVAL;
715                 }
716                 if (!SSL_CTX_use_certificate(vpninfo->https_ctx, vpninfo->cert_x509)) {
717                         vpn_progress(vpninfo, PRG_ERR,
718                                      _("Failed to use X509 certificate from keystore\n"));
719                         openconnect_report_ssl_errors(vpninfo);
720                         X509_free(vpninfo->cert_x509);
721                         vpninfo->cert_x509 = NULL;
722                         return -EINVAL;
723                 }
724         } else
725 #endif /* ANDROID_KEYSTORE */
726         {
727                 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
728                                                         vpninfo->cert)) {
729                         vpn_progress(vpninfo, PRG_ERR,
730                                      _("Loading certificate failed\n"));
731                         openconnect_report_ssl_errors(vpninfo);
732                         return -EINVAL;
733                 }
734
735                 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
736                 reload_pem_cert(vpninfo);
737         }
738
739 #ifdef ANDROID_KEYSTORE
740         if (!strncmp(vpninfo->sslkey, "keystore:", 9)) {
741                 EVP_PKEY *key;
742                 BIO *b;
743
744         again_android:
745                 b = BIO_from_keystore(vpninfo, vpninfo->sslkey);
746                 if (!b)
747                         return -EINVAL;
748                 key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, vpninfo);
749                 BIO_free(b);
750                 if (!key) {
751                         if (is_pem_password_error(vpninfo))
752                                 goto again_android;
753                         return -EINVAL;
754                 }
755                 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
756                         vpn_progress(vpninfo, PRG_ERR,
757                                      _("Failed to use private key from keystore\n"));
758                         EVP_PKEY_free(key);
759                         X509_free(vpninfo->cert_x509);
760                         vpninfo->cert_x509 = NULL;
761                         return -EINVAL;
762                 }
763                 return 0;
764         }
765 #endif /* ANDROID */
766
767         if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
768                 FILE *f = fopen(vpninfo->sslkey, "r");
769                 char buf[256];
770
771                 if (!f) {
772                         vpn_progress(vpninfo, PRG_ERR,
773                                      _("Failed to open private key file %s: %s\n"),
774                                      vpninfo->cert, strerror(errno));
775                         return -ENOENT;
776                 }
777
778                 buf[255] = 0;
779                 while (fgets(buf, 255, f)) {
780                         if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
781                                 vpninfo->cert_type = CERT_TYPE_TPM;
782                                 break;
783                         } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
784                                    !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
785                                    !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
786                                 vpninfo->cert_type = CERT_TYPE_PEM;
787                                 break;
788                         }
789                 }
790                 fclose(f);
791                 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
792                         vpn_progress(vpninfo, PRG_ERR,
793                                      _("Failed to identify private key type in '%s'\n"),
794                                      vpninfo->sslkey);
795                         return -EINVAL;
796                 }
797         }
798
799         if (vpninfo->cert_type == CERT_TYPE_TPM)
800                 return load_tpm_certificate(vpninfo);
801
802         /* Standard PEM certificate */
803         SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
804         SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
805  again:
806         if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
807                                             SSL_FILETYPE_PEM)) {
808                 if (is_pem_password_error(vpninfo))
809                         goto again;
810                 return -EINVAL;
811         }
812         return 0;
813 }
814
815 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
816                                 OPENCONNECT_X509 *cert, const EVP_MD *type,
817                                 char *buf)
818 {
819         unsigned char md[EVP_MAX_MD_SIZE];
820         unsigned int i, n;
821
822         if (!X509_digest(cert, type, md, &n))
823                 return -ENOMEM;
824
825         for (i=0; i < n; i++)
826                 sprintf(&buf[i*2], "%02X", md[i]);
827
828         return 0;
829 }
830
831 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
832                              OPENCONNECT_X509 *cert, char *buf)
833 {
834         return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
835 }
836
837 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
838                               OPENCONNECT_X509 *cert, char *buf)
839 {
840         return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
841 }
842
843 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
844 {
845         char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
846         int ret;
847
848         ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
849         if (ret)
850                 return ret;
851
852         if (strcasecmp(vpninfo->servercert, fingerprint)) {
853                 vpn_progress(vpninfo, PRG_ERR,
854                              _("Server SSL certificate didn't match: %s\n"), fingerprint);
855                 return -EINVAL;
856         }
857         return 0;
858 }
859
860 static int match_hostname_elem(const char *hostname, int helem_len,
861                                const char *match, int melem_len)
862 {
863         if (!helem_len && !melem_len)
864                 return 0;
865
866         if (!helem_len || !melem_len)
867                 return -1;
868
869
870         if (match[0] == '*') {
871                 int i;
872
873                 for (i = 1 ; i <= helem_len; i++) {
874                         if (!match_hostname_elem(hostname + i, helem_len - i,
875                                                  match + 1, melem_len - 1))
876                                 return 0;
877                 }
878                 return -1;
879         }
880
881         /* From the NetBSD (5.1) man page for ctype(3):
882            Values of type char or signed char must first be cast to unsigned char,
883            to ensure that the values are within the correct range.  The result
884            should then be cast to int to avoid warnings from some compilers.
885            We do indeed get warning "array subscript has type 'char'" without
886            the casts. Ick. */
887         if (toupper((int)(unsigned char)hostname[0]) ==
888             toupper((int)(unsigned char)match[0]))
889                 return match_hostname_elem(hostname + 1, helem_len - 1,
890                                            match + 1, melem_len - 1);
891
892         return -1;
893 }
894
895 static int match_hostname(const char *hostname, const char *match)
896 {
897         while (*match) {
898                 const char *h_dot, *m_dot;
899                 int helem_len, melem_len;
900
901                 h_dot = strchr(hostname, '.');
902                 m_dot = strchr(match, '.');
903                 
904                 if (h_dot && m_dot) {
905                         helem_len = h_dot - hostname + 1;
906                         melem_len = m_dot - match + 1;
907                 } else if (!h_dot && !m_dot) {
908                         helem_len = strlen(hostname);
909                         melem_len = strlen(match);
910                 } else
911                         return -1;
912
913
914                 if (match_hostname_elem(hostname, helem_len,
915                                         match, melem_len))
916                         return -1;
917
918                 hostname += helem_len;
919                 match += melem_len;
920         }
921         if (*hostname)
922                 return -1;
923
924         return 0;
925 }
926
927 /* cf. RFC2818 and RFC2459 */
928 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
929 {
930         STACK_OF(GENERAL_NAME) *altnames;
931         X509_NAME *subjname;
932         ASN1_STRING *subjasn1;
933         char *subjstr = NULL;
934         int addrlen = 0;
935         int i, altdns = 0;
936         char addrbuf[sizeof(struct in6_addr)];
937         int ret;
938
939         /* Allow GEN_IP in the certificate only if we actually connected
940            by IP address rather than by name. */
941         if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
942                 addrlen = 4;
943         else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
944                 addrlen = 16;
945         else if (vpninfo->hostname[0] == '[' &&
946                  vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
947                 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
948                 *p = 0;
949                 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
950                         addrlen = 16;
951                 *p = ']';
952         }
953
954         altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
955                                     NULL, NULL);
956         for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
957                 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
958
959                 if (this->type == GEN_DNS) {
960                         char *str;
961
962                         int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
963                         if (len < 0)
964                                 continue;
965
966                         altdns = 1;
967
968                         /* We don't like names with embedded NUL */
969                         if (strlen(str) != len)
970                                 continue;
971
972                         if (!match_hostname(vpninfo->hostname, str)) {
973                                 vpn_progress(vpninfo, PRG_TRACE,
974                                              _("Matched DNS altname '%s'\n"),
975                                              str);
976                                 GENERAL_NAMES_free(altnames);
977                                 OPENSSL_free(str);
978                                 return 0;
979                         } else {
980                                 vpn_progress(vpninfo, PRG_TRACE,
981                                              _("No match for altname '%s'\n"),
982                                              str);
983                         }
984                         OPENSSL_free(str);
985                 } else if (this->type == GEN_IPADD && addrlen) {
986                         char host[80];
987                         int family;
988
989                         if (this->d.ip->length == 4) {
990                                 family = AF_INET;
991                         } else if (this->d.ip->length == 16) {
992                                 family = AF_INET6;
993                         } else {
994                                 vpn_progress(vpninfo, PRG_ERR,
995                                              _("Certificate has GEN_IPADD altname with bogus length %d\n"),
996                                              this->d.ip->length);
997                                 continue;
998                         }
999                         
1000                         /* We only do this for the debug messages */
1001                         inet_ntop(family, this->d.ip->data, host, sizeof(host));
1002
1003                         if (this->d.ip->length == addrlen &&
1004                             !memcmp(addrbuf, this->d.ip->data, addrlen)) {
1005                                 vpn_progress(vpninfo, PRG_TRACE,
1006                                              _("Matched %s address '%s'\n"),
1007                                              (family == AF_INET6)?"IPv6":"IPv4",
1008                                              host);
1009                                 GENERAL_NAMES_free(altnames);
1010                                 return 0;
1011                         } else {
1012                                 vpn_progress(vpninfo, PRG_TRACE,
1013                                              _("No match for %s address '%s'\n"),
1014                                              (family == AF_INET6)?"IPv6":"IPv4",
1015                                              host);
1016                         }
1017                 } else if (this->type == GEN_URI) {
1018                         char *str;
1019                         char *url_proto, *url_host, *url_path, *url_host2;
1020                         int url_port;
1021                         int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
1022
1023                         if (len < 0)
1024                                 continue;
1025
1026                         /* We don't like names with embedded NUL */
1027                         if (strlen(str) != len)
1028                                 continue;
1029
1030                         if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
1031                                 OPENSSL_free(str);
1032                                 continue;
1033                         }
1034
1035                         if (!url_proto || strcasecmp(url_proto, "https"))
1036                                 goto no_uri_match;
1037
1038                         if (url_port != vpninfo->port)
1039                                 goto no_uri_match;
1040
1041                         /* Leave url_host as it was so that it can be freed */
1042                         url_host2 = url_host;
1043                         if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
1044                             url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
1045                                 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
1046                                 url_host[strlen(url_host)-1] = 0;
1047                                 url_host2++;
1048                         }
1049
1050                         if (strcasecmp(vpninfo->hostname, url_host2))
1051                                 goto no_uri_match;
1052
1053                         if (url_path) {
1054                                 vpn_progress(vpninfo, PRG_TRACE,
1055                                              _("URI '%s' has non-empty path; ignoring\n"),
1056                                              str);
1057                                 goto no_uri_match_silent;
1058                         }
1059                         vpn_progress(vpninfo, PRG_TRACE,
1060                                      _("Matched URI '%s'\n"),
1061                                      str);
1062                         free(url_proto);
1063                         free(url_host);
1064                         free(url_path);
1065                         OPENSSL_free(str);
1066                         GENERAL_NAMES_free(altnames);
1067                         return 0;
1068
1069                 no_uri_match:
1070                         vpn_progress(vpninfo, PRG_TRACE,
1071                                      _("No match for URI '%s'\n"),
1072                                      str);
1073                 no_uri_match_silent:
1074                         free(url_proto);
1075                         free(url_host);
1076                         free(url_path);
1077                         OPENSSL_free(str);
1078                 }
1079         }
1080         GENERAL_NAMES_free(altnames);
1081
1082         /* According to RFC2818, we don't use the legacy subject name if
1083            there was an altname with DNS type. */
1084         if (altdns) {
1085                 vpn_progress(vpninfo, PRG_ERR,
1086                              _("No altname in peer cert matched '%s'\n"),
1087                              vpninfo->hostname);
1088                 return -EINVAL;
1089         }
1090
1091         subjname = X509_get_subject_name(peer_cert);
1092         if (!subjname) {
1093                 vpn_progress(vpninfo, PRG_ERR,
1094                              _("No subject name in peer cert!\n"));
1095                 return -EINVAL;
1096         }
1097
1098         /* Find the _last_ (most specific) commonName */
1099         i = -1;
1100         while (1) {
1101                 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
1102                 if (j >= 0)
1103                         i = j;
1104                 else
1105                         break;
1106         }
1107
1108         subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1109
1110         i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1111
1112         if (!subjstr || strlen(subjstr) != i) {
1113                 vpn_progress(vpninfo, PRG_ERR,
1114                              _("Failed to parse subject name in peer cert\n"));
1115                 return -EINVAL;
1116         }
1117         ret = 0;
1118
1119         if (match_hostname(vpninfo->hostname, subjstr)) {
1120                 vpn_progress(vpninfo, PRG_ERR,
1121                              _("Peer cert subject mismatch ('%s' != '%s')\n"),
1122                              subjstr, vpninfo->hostname);
1123                 ret = -EINVAL;
1124         } else {
1125                 vpn_progress(vpninfo, PRG_TRACE,
1126                              _("Matched peer certificate subject name '%s'\n"),
1127                              subjstr);
1128         }
1129
1130         OPENSSL_free(subjstr);                    
1131         return ret;
1132 }
1133
1134 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1135 {
1136         X509 *peer_cert;
1137         int ret;
1138
1139         peer_cert = SSL_get_peer_certificate(https_ssl);
1140
1141         if (vpninfo->servercert) {
1142                 /* If given a cert fingerprint on the command line, that's
1143                    all we look for */
1144                 ret = check_server_cert(vpninfo, peer_cert);
1145         } else {
1146                 int vfy = SSL_get_verify_result(https_ssl);
1147                 const char *err_string = NULL;
1148
1149                 if (vfy != X509_V_OK)
1150                         err_string = X509_verify_cert_error_string(vfy);
1151                 else if (match_cert_hostname(vpninfo, peer_cert))
1152                         err_string = _("certificate does not match hostname");
1153
1154                 if (err_string) {
1155                         vpn_progress(vpninfo, PRG_INFO,
1156                                      _("Server certificate verify failed: %s\n"),
1157                                      err_string);
1158
1159                         if (vpninfo->validate_peer_cert)
1160                                 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1161                                                                   peer_cert,
1162                                                                   err_string);
1163                         else
1164                                 ret = -EINVAL;
1165                 } else {
1166                         ret = 0;
1167                 }
1168         }
1169         X509_free(peer_cert);
1170
1171         return ret;
1172 }
1173
1174 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1175                                              SSL *ssl)
1176 {
1177         /* OpenSSL has problems with certificate chains -- if there are
1178            multiple certs with the same name, it doesn't necessarily
1179            choose the _right_ one. (RT#1942)
1180            Pick the right ones for ourselves and add them manually. */
1181         X509 *cert = SSL_get_certificate(ssl);
1182         X509 *cert2;
1183         X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1184         X509_STORE_CTX ctx;
1185
1186         if (!cert || !store)
1187                 return;
1188
1189         /* If we already have 'supporting' certs, don't add them again */
1190         if (vpninfo->https_ctx->extra_certs)
1191                 return;
1192
1193         if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1194                 return;
1195
1196         while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1197                 char buf[200];
1198                 if (cert2 == cert)
1199                         break;
1200                 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1201                         break;
1202                 cert = cert2;
1203                 X509_NAME_oneline(X509_get_subject_name(cert),
1204                                   buf, sizeof(buf));
1205                 vpn_progress(vpninfo, PRG_DEBUG,
1206                              _("Extra cert from cafile: '%s'\n"), buf);
1207                 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1208         }
1209         X509_STORE_CTX_cleanup(&ctx);
1210 }
1211
1212 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1213 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1214 {
1215         /* We've seen certificates in the wild which don't have the
1216            purpose fields filled in correctly */
1217         X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1218         return X509_verify_cert(ctx);
1219 }
1220 #endif
1221
1222 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1223 {
1224         ASN1_TIME *notAfter;
1225         const char *reason = NULL;
1226         time_t t;
1227         int i;
1228
1229         if (!vpninfo->cert_x509)
1230                 return 0;
1231
1232         t = time(NULL);
1233         notAfter = X509_get_notAfter(vpninfo->cert_x509);
1234         i = X509_cmp_time(notAfter, &t);
1235         if (!i) {
1236                 vpn_progress(vpninfo, PRG_ERR,
1237                              _("Error in client cert notAfter field\n"));
1238                 return -EINVAL;
1239         } else if (i < 0) {
1240                 reason = _("Client certificate has expired at");
1241         } else {
1242                 t += vpninfo->cert_expire_warning;
1243                 i = X509_cmp_time(notAfter, &t);
1244                 if (i < 0) {
1245                         reason = _("Client certificate expires soon at");
1246                 }
1247         }
1248         if (reason) {
1249                 BIO *bp = BIO_new(BIO_s_mem());
1250                 BUF_MEM *bm;
1251                 const char *expiry = _("<error>");
1252                 char zero = 0;
1253
1254                 if (bp) {
1255                         ASN1_TIME_print(bp, notAfter);
1256                         BIO_write(bp, &zero, 1);
1257                         BIO_get_mem_ptr(bp, &bm);
1258                         expiry = bm->data;
1259                 }
1260                 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1261                 if (bp)
1262                         BIO_free(bp);
1263         }
1264         return 0;
1265 }
1266 int openconnect_open_https(struct openconnect_info *vpninfo)
1267 {
1268         method_const SSL_METHOD *ssl3_method;
1269         SSL *https_ssl;
1270         BIO *https_bio;
1271         int ssl_sock;
1272         int err;
1273
1274         if (vpninfo->https_ssl)
1275                 return 0;
1276
1277         if (vpninfo->peer_cert) {
1278                 X509_free(vpninfo->peer_cert);
1279                 vpninfo->peer_cert = NULL;
1280         }
1281
1282         ssl_sock = connect_https_socket(vpninfo);
1283         if (ssl_sock < 0)
1284                 return ssl_sock;
1285
1286         ssl3_method = TLSv1_client_method();
1287         if (!vpninfo->https_ctx) {
1288                 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1289
1290                 /* Some servers (or their firewalls) really don't like seeing
1291                    extensions. */
1292 #ifdef SSL_OP_NO_TICKET
1293                 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1294 #endif
1295
1296                 if (vpninfo->cert) {
1297                         err = load_certificate(vpninfo);
1298                         if (err) {
1299                                 vpn_progress(vpninfo, PRG_ERR,
1300                                              _("Loading certificate failed. Aborting.\n"));
1301                                 return err;
1302                         }
1303                         check_certificate_expiry(vpninfo);
1304                 }
1305
1306                 /* We just want to do:
1307                    SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY); 
1308                    ... but it doesn't work with OpenSSL < 0.9.8k because of 
1309                    problems with inheritance (fixed in v1.1.4.6 of
1310                    crypto/x509/x509_vpm.c) so we have to play silly buggers
1311                    instead. This trick doesn't work _either_ in < 0.9.7 but
1312                    I don't know of _any_ workaround which will, and can't
1313                    be bothered to find out either. */
1314 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1315                 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1316                                                  ssl_app_verify_callback, NULL);
1317 #endif
1318                 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1319
1320 #ifdef ANDROID_KEYSTORE
1321                 if (vpninfo->cafile && !strncmp(vpninfo->cafile, "keystore:", 9)) {
1322                         STACK_OF(X509_INFO) *stack;
1323                         X509_STORE *store;
1324                         X509_INFO *info;
1325                         BIO *b = BIO_from_keystore(vpninfo, vpninfo->cafile);
1326
1327                         if (!b) {
1328                                 close(ssl_sock);
1329                                 return -EINVAL;
1330                         }
1331
1332                         stack = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
1333                         BIO_free(b);
1334
1335                         if (!stack) {
1336                                 vpn_progress(vpninfo, PRG_ERR,
1337                                              _("Failed to read certs from CA file '%s'\n"),
1338                                              vpninfo->cafile);
1339                                 openconnect_report_ssl_errors(vpninfo);
1340                                 close(ssl_sock);
1341                                 return -ENOENT;
1342                         }
1343
1344                         store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1345
1346                         while ((info = sk_X509_INFO_pop(stack))) {
1347                                 if (info->x509)
1348                                         X509_STORE_add_cert(store, info->x509);
1349                                 if (info->crl)
1350                                         X509_STORE_add_crl(store, info->crl);
1351                                 X509_INFO_free(info);
1352                         }
1353                         sk_X509_INFO_free(stack);
1354                 } else
1355 #endif
1356                 if (vpninfo->cafile) {
1357                         if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1358                                 vpn_progress(vpninfo, PRG_ERR,
1359                                              _("Failed to open CA file '%s'\n"),
1360                                              vpninfo->cafile);
1361                                 openconnect_report_ssl_errors(vpninfo);
1362                                 close(ssl_sock);
1363                                 return -EINVAL;
1364                         }
1365                 }
1366
1367         }
1368         https_ssl = SSL_new(vpninfo->https_ctx);
1369         workaround_openssl_certchain_bug(vpninfo, https_ssl);
1370
1371         https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1372         BIO_set_nbio(https_bio, 1);
1373         SSL_set_bio(https_ssl, https_bio, https_bio);
1374
1375         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1376                      vpninfo->hostname);
1377
1378         while ((err = SSL_connect(https_ssl)) <= 0) {
1379                 fd_set wr_set, rd_set;
1380                 int maxfd = ssl_sock;
1381                 
1382                 FD_ZERO(&wr_set);
1383                 FD_ZERO(&rd_set);
1384
1385                 err = SSL_get_error(https_ssl, err);
1386                 if (err == SSL_ERROR_WANT_READ)
1387                         FD_SET(ssl_sock, &rd_set);
1388                 else if (err == SSL_ERROR_WANT_WRITE)
1389                         FD_SET(ssl_sock, &wr_set);
1390                 else {
1391                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1392                         openconnect_report_ssl_errors(vpninfo);
1393                         SSL_free(https_ssl);
1394                         close(ssl_sock);
1395                         return -EINVAL;
1396                 }
1397
1398                 if (vpninfo->cancel_fd != -1) {
1399                         FD_SET(vpninfo->cancel_fd, &rd_set);
1400                         if (vpninfo->cancel_fd > ssl_sock)
1401                                 maxfd = vpninfo->cancel_fd;
1402                 }
1403                 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1404                 if (vpninfo->cancel_fd != -1 &&
1405                     FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1406                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1407                         SSL_free(https_ssl);
1408                         close(ssl_sock);
1409                         return -EINVAL;
1410                 }
1411         }
1412
1413         if (verify_peer(vpninfo, https_ssl)) {
1414                 SSL_free(https_ssl);
1415                 close(ssl_sock);
1416                 return -EINVAL;
1417         }
1418
1419         vpninfo->ssl_fd = ssl_sock;
1420         vpninfo->https_ssl = https_ssl;
1421
1422         /* Stash this now, because it might not be available later if the
1423            server has disconnected. */
1424         vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1425
1426         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1427                      vpninfo->hostname);
1428
1429         return 0;
1430 }
1431
1432 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1433 {
1434         if (vpninfo->peer_cert) {
1435                 X509_free(vpninfo->peer_cert);
1436                 vpninfo->peer_cert = NULL;
1437         }
1438         if (vpninfo->https_ssl) {
1439                 SSL_free(vpninfo->https_ssl);
1440                 vpninfo->https_ssl = NULL;
1441         }
1442         if (vpninfo->ssl_fd != -1) {
1443                 close(vpninfo->ssl_fd);
1444                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1445                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1446                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1447                 vpninfo->ssl_fd = -1;
1448         }
1449         if (final) {
1450                 if (vpninfo->https_ctx) {
1451                         SSL_CTX_free(vpninfo->https_ctx);
1452                         vpninfo->https_ctx = NULL;
1453                 }
1454                 if (vpninfo->cert_x509) {
1455                         X509_free(vpninfo->cert_x509);
1456                         vpninfo->cert_x509 = NULL;
1457                 }
1458         }
1459 }
1460
1461 void openconnect_init_ssl(void)
1462 {
1463         SSL_library_init ();
1464         ERR_clear_error ();
1465         SSL_load_error_strings ();
1466         OpenSSL_add_all_algorithms ();
1467 }
1468
1469 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1470                                    OPENCONNECT_X509 *cert)
1471 {
1472         BIO *bp = BIO_new(BIO_s_mem());
1473         BUF_MEM *certinfo;
1474         char zero = 0;
1475         char *ret;
1476
1477         X509_print_ex(bp, cert, 0, 0);
1478         BIO_write(bp, &zero, 1);
1479         BIO_get_mem_ptr(bp, &certinfo);
1480
1481         ret = strdup(certinfo->data);
1482         BIO_free(bp);
1483         return ret;
1484 }
1485
1486
1487 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1488                                char *buf)
1489 {
1490         buf[0] = 0;
1491
1492         if (!vpninfo->cert_x509)
1493                 return -EIO;
1494
1495         if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))
1496                 return -EIO;
1497
1498         return 0;
1499 }