Fix Android keystore support for older keystore_get.h
[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         char content[KEYSTORE_MESSAGE_SIZE];
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         /* Old versions of keystore_get.h will return the input length
618            instead of an error, in some circumstances. So check the
619            content actually changes, too. */
620         content[0] = 0;
621         len = keystore_get(p, strlen(p), content);
622         if (len < 0 || content[0] == 0) {
623                 vpn_progress(vpninfo, PRG_ERR,
624                              _("Failed to lead item '%s' from keystore\n"),
625                              p);
626                 return NULL;
627         }
628         if (!(b = BIO_new(BIO_s_mem())) || BIO_write(b, content, len) != len) {
629                 vpn_progress(vpninfo, PRG_ERR,
630                              _("Failed to create BIO for keystore item '%s'\n"),
631                                p);
632                 BIO_free(b);
633                 return NULL;
634         }
635         return b;
636 }
637 #endif
638
639 static int is_pem_password_error(struct openconnect_info *vpninfo)
640 {
641         unsigned long err = ERR_peek_error();
642
643         openconnect_report_ssl_errors(vpninfo);
644
645 #ifndef EVP_F_EVP_DECRYPTFINAL_EX
646 #define EVP_F_EVP_DECRYPTFINAL_EX EVP_F_EVP_DECRYPTFINAL
647 #endif
648         /* If the user fat-fingered the passphrase, try again */
649         if (ERR_GET_LIB(err) == ERR_LIB_EVP &&
650             ERR_GET_FUNC(err) == EVP_F_EVP_DECRYPTFINAL_EX &&
651             ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT) {
652                 vpn_progress(vpninfo, PRG_ERR,
653                              _("Loading private key failed (wrong passphrase?)\n"));
654                 ERR_clear_error();
655                 return 1;
656         }
657
658         vpn_progress(vpninfo, PRG_ERR,
659                      _("Loading private key failed (see above errors)\n"));
660         return 0;
661 }
662
663 static int load_certificate(struct openconnect_info *vpninfo)
664 {
665         if (!strncmp(vpninfo->sslkey, "pkcs11:", 7) ||
666             !strncmp(vpninfo->cert, "pkcs11:", 7)) {
667                 vpn_progress(vpninfo, PRG_ERR,
668                              _("This binary built without PKCS#11 support\n"));
669                 return -EINVAL;
670         }
671                      
672         vpn_progress(vpninfo, PRG_TRACE,
673                      _("Using certificate file %s\n"), vpninfo->cert);
674
675         if (strncmp(vpninfo->cert, "keystore:", 9) &&
676             (vpninfo->cert_type == CERT_TYPE_PKCS12 ||
677              vpninfo->cert_type == CERT_TYPE_UNKNOWN)) {
678                 FILE *f;
679                 PKCS12 *p12;
680
681                 f = fopen(vpninfo->cert, "r");
682                 if (!f) {
683                         vpn_progress(vpninfo, PRG_ERR,
684                                      _("Failed to open certificate file %s: %s\n"),
685                                      vpninfo->cert, strerror(errno));
686                         return -ENOENT;
687                 }
688                 p12 = d2i_PKCS12_fp(f, NULL);
689                 fclose(f);
690                 if (p12)
691                         return load_pkcs12_certificate(vpninfo, p12);
692
693                 /* Not PKCS#12 */
694                 if (vpninfo->cert_type == CERT_TYPE_PKCS12) {
695                         vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n"));
696                         openconnect_report_ssl_errors(vpninfo);
697                         return -EINVAL;
698                 }
699                 /* Clear error and fall through to see if it's a PEM file... */
700                 ERR_clear_error();
701         }
702
703         /* It's PEM or TPM now, and either way we need to load the plain cert: */
704 #ifdef ANDROID_KEYSTORE
705         if (!strncmp(vpninfo->cert, "keystore:", 9)) {
706                 BIO *b = BIO_from_keystore(vpninfo, vpninfo->cert);
707                 if (!b)
708                         return -EINVAL;
709                 vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, pem_pw_cb, vpninfo);
710                 BIO_free(b);
711                 if (!vpninfo->cert_x509) {
712                         vpn_progress(vpninfo, PRG_ERR,
713                                      _("Failed to load X509 certificate from keystore\n"));
714                         openconnect_report_ssl_errors(vpninfo);
715                         BIO_free(b);
716                         return -EINVAL;
717                 }
718                 if (!SSL_CTX_use_certificate(vpninfo->https_ctx, vpninfo->cert_x509)) {
719                         vpn_progress(vpninfo, PRG_ERR,
720                                      _("Failed to use X509 certificate from keystore\n"));
721                         openconnect_report_ssl_errors(vpninfo);
722                         X509_free(vpninfo->cert_x509);
723                         vpninfo->cert_x509 = NULL;
724                         return -EINVAL;
725                 }
726         } else
727 #endif /* ANDROID_KEYSTORE */
728         {
729                 if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx,
730                                                         vpninfo->cert)) {
731                         vpn_progress(vpninfo, PRG_ERR,
732                                      _("Loading certificate failed\n"));
733                         openconnect_report_ssl_errors(vpninfo);
734                         return -EINVAL;
735                 }
736
737                 /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */
738                 reload_pem_cert(vpninfo);
739         }
740
741 #ifdef ANDROID_KEYSTORE
742         if (!strncmp(vpninfo->sslkey, "keystore:", 9)) {
743                 EVP_PKEY *key;
744                 BIO *b;
745
746         again_android:
747                 b = BIO_from_keystore(vpninfo, vpninfo->sslkey);
748                 if (!b)
749                         return -EINVAL;
750                 key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, vpninfo);
751                 BIO_free(b);
752                 if (!key) {
753                         if (is_pem_password_error(vpninfo))
754                                 goto again_android;
755                         return -EINVAL;
756                 }
757                 if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) {
758                         vpn_progress(vpninfo, PRG_ERR,
759                                      _("Failed to use private key from keystore\n"));
760                         EVP_PKEY_free(key);
761                         X509_free(vpninfo->cert_x509);
762                         vpninfo->cert_x509 = NULL;
763                         return -EINVAL;
764                 }
765                 return 0;
766         }
767 #endif /* ANDROID */
768
769         if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
770                 FILE *f = fopen(vpninfo->sslkey, "r");
771                 char buf[256];
772
773                 if (!f) {
774                         vpn_progress(vpninfo, PRG_ERR,
775                                      _("Failed to open private key file %s: %s\n"),
776                                      vpninfo->cert, strerror(errno));
777                         return -ENOENT;
778                 }
779
780                 buf[255] = 0;
781                 while (fgets(buf, 255, f)) {
782                         if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) {
783                                 vpninfo->cert_type = CERT_TYPE_TPM;
784                                 break;
785                         } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") ||
786                                    !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") ||
787                                    !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) {
788                                 vpninfo->cert_type = CERT_TYPE_PEM;
789                                 break;
790                         }
791                 }
792                 fclose(f);
793                 if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) {
794                         vpn_progress(vpninfo, PRG_ERR,
795                                      _("Failed to identify private key type in '%s'\n"),
796                                      vpninfo->sslkey);
797                         return -EINVAL;
798                 }
799         }
800
801         if (vpninfo->cert_type == CERT_TYPE_TPM)
802                 return load_tpm_certificate(vpninfo);
803
804         /* Standard PEM certificate */
805         SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb);
806         SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo);
807  again:
808         if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey,
809                                             SSL_FILETYPE_PEM)) {
810                 if (is_pem_password_error(vpninfo))
811                         goto again;
812                 return -EINVAL;
813         }
814         return 0;
815 }
816
817 static int get_cert_fingerprint(struct openconnect_info *vpninfo,
818                                 OPENCONNECT_X509 *cert, const EVP_MD *type,
819                                 char *buf)
820 {
821         unsigned char md[EVP_MAX_MD_SIZE];
822         unsigned int i, n;
823
824         if (!X509_digest(cert, type, md, &n))
825                 return -ENOMEM;
826
827         for (i=0; i < n; i++)
828                 sprintf(&buf[i*2], "%02X", md[i]);
829
830         return 0;
831 }
832
833 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,
834                              OPENCONNECT_X509 *cert, char *buf)
835 {
836         return get_cert_fingerprint(vpninfo, cert, EVP_md5(), buf);
837 }
838
839 int openconnect_get_cert_sha1(struct openconnect_info *vpninfo,
840                               OPENCONNECT_X509 *cert, char *buf)
841 {
842         return get_cert_fingerprint(vpninfo, cert, EVP_sha1(), buf);
843 }
844
845 static int check_server_cert(struct openconnect_info *vpninfo, X509 *cert)
846 {
847         char fingerprint[EVP_MAX_MD_SIZE * 2 + 1];
848         int ret;
849
850         ret = openconnect_get_cert_sha1(vpninfo, cert, fingerprint);
851         if (ret)
852                 return ret;
853
854         if (strcasecmp(vpninfo->servercert, fingerprint)) {
855                 vpn_progress(vpninfo, PRG_ERR,
856                              _("Server SSL certificate didn't match: %s\n"), fingerprint);
857                 return -EINVAL;
858         }
859         return 0;
860 }
861
862 static int match_hostname_elem(const char *hostname, int helem_len,
863                                const char *match, int melem_len)
864 {
865         if (!helem_len && !melem_len)
866                 return 0;
867
868         if (!helem_len || !melem_len)
869                 return -1;
870
871
872         if (match[0] == '*') {
873                 int i;
874
875                 for (i = 1 ; i <= helem_len; i++) {
876                         if (!match_hostname_elem(hostname + i, helem_len - i,
877                                                  match + 1, melem_len - 1))
878                                 return 0;
879                 }
880                 return -1;
881         }
882
883         /* From the NetBSD (5.1) man page for ctype(3):
884            Values of type char or signed char must first be cast to unsigned char,
885            to ensure that the values are within the correct range.  The result
886            should then be cast to int to avoid warnings from some compilers.
887            We do indeed get warning "array subscript has type 'char'" without
888            the casts. Ick. */
889         if (toupper((int)(unsigned char)hostname[0]) ==
890             toupper((int)(unsigned char)match[0]))
891                 return match_hostname_elem(hostname + 1, helem_len - 1,
892                                            match + 1, melem_len - 1);
893
894         return -1;
895 }
896
897 static int match_hostname(const char *hostname, const char *match)
898 {
899         while (*match) {
900                 const char *h_dot, *m_dot;
901                 int helem_len, melem_len;
902
903                 h_dot = strchr(hostname, '.');
904                 m_dot = strchr(match, '.');
905                 
906                 if (h_dot && m_dot) {
907                         helem_len = h_dot - hostname + 1;
908                         melem_len = m_dot - match + 1;
909                 } else if (!h_dot && !m_dot) {
910                         helem_len = strlen(hostname);
911                         melem_len = strlen(match);
912                 } else
913                         return -1;
914
915
916                 if (match_hostname_elem(hostname, helem_len,
917                                         match, melem_len))
918                         return -1;
919
920                 hostname += helem_len;
921                 match += melem_len;
922         }
923         if (*hostname)
924                 return -1;
925
926         return 0;
927 }
928
929 /* cf. RFC2818 and RFC2459 */
930 static int match_cert_hostname(struct openconnect_info *vpninfo, X509 *peer_cert)
931 {
932         STACK_OF(GENERAL_NAME) *altnames;
933         X509_NAME *subjname;
934         ASN1_STRING *subjasn1;
935         char *subjstr = NULL;
936         int addrlen = 0;
937         int i, altdns = 0;
938         char addrbuf[sizeof(struct in6_addr)];
939         int ret;
940
941         /* Allow GEN_IP in the certificate only if we actually connected
942            by IP address rather than by name. */
943         if (inet_pton(AF_INET, vpninfo->hostname, addrbuf) > 0)
944                 addrlen = 4;
945         else if (inet_pton(AF_INET6, vpninfo->hostname, addrbuf) > 0)
946                 addrlen = 16;
947         else if (vpninfo->hostname[0] == '[' &&
948                  vpninfo->hostname[strlen(vpninfo->hostname)-1] == ']') {
949                 char *p = &vpninfo->hostname[strlen(vpninfo->hostname)-1];
950                 *p = 0;
951                 if (inet_pton(AF_INET6, vpninfo->hostname + 1, addrbuf) > 0)
952                         addrlen = 16;
953                 *p = ']';
954         }
955
956         altnames = X509_get_ext_d2i(peer_cert, NID_subject_alt_name,
957                                     NULL, NULL);
958         for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
959                 const GENERAL_NAME *this = sk_GENERAL_NAME_value(altnames, i);
960
961                 if (this->type == GEN_DNS) {
962                         char *str;
963
964                         int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
965                         if (len < 0)
966                                 continue;
967
968                         altdns = 1;
969
970                         /* We don't like names with embedded NUL */
971                         if (strlen(str) != len)
972                                 continue;
973
974                         if (!match_hostname(vpninfo->hostname, str)) {
975                                 vpn_progress(vpninfo, PRG_TRACE,
976                                              _("Matched DNS altname '%s'\n"),
977                                              str);
978                                 GENERAL_NAMES_free(altnames);
979                                 OPENSSL_free(str);
980                                 return 0;
981                         } else {
982                                 vpn_progress(vpninfo, PRG_TRACE,
983                                              _("No match for altname '%s'\n"),
984                                              str);
985                         }
986                         OPENSSL_free(str);
987                 } else if (this->type == GEN_IPADD && addrlen) {
988                         char host[80];
989                         int family;
990
991                         if (this->d.ip->length == 4) {
992                                 family = AF_INET;
993                         } else if (this->d.ip->length == 16) {
994                                 family = AF_INET6;
995                         } else {
996                                 vpn_progress(vpninfo, PRG_ERR,
997                                              _("Certificate has GEN_IPADD altname with bogus length %d\n"),
998                                              this->d.ip->length);
999                                 continue;
1000                         }
1001                         
1002                         /* We only do this for the debug messages */
1003                         inet_ntop(family, this->d.ip->data, host, sizeof(host));
1004
1005                         if (this->d.ip->length == addrlen &&
1006                             !memcmp(addrbuf, this->d.ip->data, addrlen)) {
1007                                 vpn_progress(vpninfo, PRG_TRACE,
1008                                              _("Matched %s address '%s'\n"),
1009                                              (family == AF_INET6)?"IPv6":"IPv4",
1010                                              host);
1011                                 GENERAL_NAMES_free(altnames);
1012                                 return 0;
1013                         } else {
1014                                 vpn_progress(vpninfo, PRG_TRACE,
1015                                              _("No match for %s address '%s'\n"),
1016                                              (family == AF_INET6)?"IPv6":"IPv4",
1017                                              host);
1018                         }
1019                 } else if (this->type == GEN_URI) {
1020                         char *str;
1021                         char *url_proto, *url_host, *url_path, *url_host2;
1022                         int url_port;
1023                         int len = ASN1_STRING_to_UTF8((void *)&str, this->d.ia5);
1024
1025                         if (len < 0)
1026                                 continue;
1027
1028                         /* We don't like names with embedded NUL */
1029                         if (strlen(str) != len)
1030                                 continue;
1031
1032                         if (internal_parse_url(str, &url_proto, &url_host, &url_port, &url_path, 0)) {
1033                                 OPENSSL_free(str);
1034                                 continue;
1035                         }
1036
1037                         if (!url_proto || strcasecmp(url_proto, "https"))
1038                                 goto no_uri_match;
1039
1040                         if (url_port != vpninfo->port)
1041                                 goto no_uri_match;
1042
1043                         /* Leave url_host as it was so that it can be freed */
1044                         url_host2 = url_host;
1045                         if (addrlen == 16 && vpninfo->hostname[0] != '[' &&
1046                             url_host[0] == '[' && url_host[strlen(url_host)-1] == ']') {
1047                                 /* Cope with https://[IPv6]/ when the hostname is bare IPv6 */
1048                                 url_host[strlen(url_host)-1] = 0;
1049                                 url_host2++;
1050                         }
1051
1052                         if (strcasecmp(vpninfo->hostname, url_host2))
1053                                 goto no_uri_match;
1054
1055                         if (url_path) {
1056                                 vpn_progress(vpninfo, PRG_TRACE,
1057                                              _("URI '%s' has non-empty path; ignoring\n"),
1058                                              str);
1059                                 goto no_uri_match_silent;
1060                         }
1061                         vpn_progress(vpninfo, PRG_TRACE,
1062                                      _("Matched URI '%s'\n"),
1063                                      str);
1064                         free(url_proto);
1065                         free(url_host);
1066                         free(url_path);
1067                         OPENSSL_free(str);
1068                         GENERAL_NAMES_free(altnames);
1069                         return 0;
1070
1071                 no_uri_match:
1072                         vpn_progress(vpninfo, PRG_TRACE,
1073                                      _("No match for URI '%s'\n"),
1074                                      str);
1075                 no_uri_match_silent:
1076                         free(url_proto);
1077                         free(url_host);
1078                         free(url_path);
1079                         OPENSSL_free(str);
1080                 }
1081         }
1082         GENERAL_NAMES_free(altnames);
1083
1084         /* According to RFC2818, we don't use the legacy subject name if
1085            there was an altname with DNS type. */
1086         if (altdns) {
1087                 vpn_progress(vpninfo, PRG_ERR,
1088                              _("No altname in peer cert matched '%s'\n"),
1089                              vpninfo->hostname);
1090                 return -EINVAL;
1091         }
1092
1093         subjname = X509_get_subject_name(peer_cert);
1094         if (!subjname) {
1095                 vpn_progress(vpninfo, PRG_ERR,
1096                              _("No subject name in peer cert!\n"));
1097                 return -EINVAL;
1098         }
1099
1100         /* Find the _last_ (most specific) commonName */
1101         i = -1;
1102         while (1) {
1103                 int j = X509_NAME_get_index_by_NID(subjname, NID_commonName, i);
1104                 if (j >= 0)
1105                         i = j;
1106                 else
1107                         break;
1108         }
1109
1110         subjasn1 = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subjname, i));
1111
1112         i = ASN1_STRING_to_UTF8((void *)&subjstr, subjasn1);
1113
1114         if (!subjstr || strlen(subjstr) != i) {
1115                 vpn_progress(vpninfo, PRG_ERR,
1116                              _("Failed to parse subject name in peer cert\n"));
1117                 return -EINVAL;
1118         }
1119         ret = 0;
1120
1121         if (match_hostname(vpninfo->hostname, subjstr)) {
1122                 vpn_progress(vpninfo, PRG_ERR,
1123                              _("Peer cert subject mismatch ('%s' != '%s')\n"),
1124                              subjstr, vpninfo->hostname);
1125                 ret = -EINVAL;
1126         } else {
1127                 vpn_progress(vpninfo, PRG_TRACE,
1128                              _("Matched peer certificate subject name '%s'\n"),
1129                              subjstr);
1130         }
1131
1132         OPENSSL_free(subjstr);                    
1133         return ret;
1134 }
1135
1136 static int verify_peer(struct openconnect_info *vpninfo, SSL *https_ssl)
1137 {
1138         X509 *peer_cert;
1139         int ret;
1140
1141         peer_cert = SSL_get_peer_certificate(https_ssl);
1142
1143         if (vpninfo->servercert) {
1144                 /* If given a cert fingerprint on the command line, that's
1145                    all we look for */
1146                 ret = check_server_cert(vpninfo, peer_cert);
1147         } else {
1148                 int vfy = SSL_get_verify_result(https_ssl);
1149                 const char *err_string = NULL;
1150
1151                 if (vfy != X509_V_OK)
1152                         err_string = X509_verify_cert_error_string(vfy);
1153                 else if (match_cert_hostname(vpninfo, peer_cert))
1154                         err_string = _("certificate does not match hostname");
1155
1156                 if (err_string) {
1157                         vpn_progress(vpninfo, PRG_INFO,
1158                                      _("Server certificate verify failed: %s\n"),
1159                                      err_string);
1160
1161                         if (vpninfo->validate_peer_cert)
1162                                 ret = vpninfo->validate_peer_cert(vpninfo->cbdata,
1163                                                                   peer_cert,
1164                                                                   err_string);
1165                         else
1166                                 ret = -EINVAL;
1167                 } else {
1168                         ret = 0;
1169                 }
1170         }
1171         X509_free(peer_cert);
1172
1173         return ret;
1174 }
1175
1176 static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo,
1177                                              SSL *ssl)
1178 {
1179         /* OpenSSL has problems with certificate chains -- if there are
1180            multiple certs with the same name, it doesn't necessarily
1181            choose the _right_ one. (RT#1942)
1182            Pick the right ones for ourselves and add them manually. */
1183         X509 *cert = SSL_get_certificate(ssl);
1184         X509 *cert2;
1185         X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx);
1186         X509_STORE_CTX ctx;
1187
1188         if (!cert || !store)
1189                 return;
1190
1191         /* If we already have 'supporting' certs, don't add them again */
1192         if (vpninfo->https_ctx->extra_certs)
1193                 return;
1194
1195         if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL))
1196                 return;
1197
1198         while (ctx.get_issuer(&cert2, &ctx, cert) == 1) {
1199                 char buf[200];
1200                 if (cert2 == cert)
1201                         break;
1202                 if (X509_check_issued(cert2, cert2) == X509_V_OK)
1203                         break;
1204                 cert = cert2;
1205                 X509_NAME_oneline(X509_get_subject_name(cert),
1206                                   buf, sizeof(buf));
1207                 vpn_progress(vpninfo, PRG_DEBUG,
1208                              _("Extra cert from cafile: '%s'\n"), buf);
1209                 SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert);
1210         }
1211         X509_STORE_CTX_cleanup(&ctx);
1212 }
1213
1214 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1215 static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg)
1216 {
1217         /* We've seen certificates in the wild which don't have the
1218            purpose fields filled in correctly */
1219         X509_VERIFY_PARAM_set_purpose(ctx->param, X509_PURPOSE_ANY);
1220         return X509_verify_cert(ctx);
1221 }
1222 #endif
1223
1224 static int check_certificate_expiry(struct openconnect_info *vpninfo)
1225 {
1226         ASN1_TIME *notAfter;
1227         const char *reason = NULL;
1228         time_t t;
1229         int i;
1230
1231         if (!vpninfo->cert_x509)
1232                 return 0;
1233
1234         t = time(NULL);
1235         notAfter = X509_get_notAfter(vpninfo->cert_x509);
1236         i = X509_cmp_time(notAfter, &t);
1237         if (!i) {
1238                 vpn_progress(vpninfo, PRG_ERR,
1239                              _("Error in client cert notAfter field\n"));
1240                 return -EINVAL;
1241         } else if (i < 0) {
1242                 reason = _("Client certificate has expired at");
1243         } else {
1244                 t += vpninfo->cert_expire_warning;
1245                 i = X509_cmp_time(notAfter, &t);
1246                 if (i < 0) {
1247                         reason = _("Client certificate expires soon at");
1248                 }
1249         }
1250         if (reason) {
1251                 BIO *bp = BIO_new(BIO_s_mem());
1252                 BUF_MEM *bm;
1253                 const char *expiry = _("<error>");
1254                 char zero = 0;
1255
1256                 if (bp) {
1257                         ASN1_TIME_print(bp, notAfter);
1258                         BIO_write(bp, &zero, 1);
1259                         BIO_get_mem_ptr(bp, &bm);
1260                         expiry = bm->data;
1261                 }
1262                 vpn_progress(vpninfo, PRG_ERR, "%s: %s\n", reason, expiry);
1263                 if (bp)
1264                         BIO_free(bp);
1265         }
1266         return 0;
1267 }
1268 int openconnect_open_https(struct openconnect_info *vpninfo)
1269 {
1270         method_const SSL_METHOD *ssl3_method;
1271         SSL *https_ssl;
1272         BIO *https_bio;
1273         int ssl_sock;
1274         int err;
1275
1276         if (vpninfo->https_ssl)
1277                 return 0;
1278
1279         if (vpninfo->peer_cert) {
1280                 X509_free(vpninfo->peer_cert);
1281                 vpninfo->peer_cert = NULL;
1282         }
1283
1284         ssl_sock = connect_https_socket(vpninfo);
1285         if (ssl_sock < 0)
1286                 return ssl_sock;
1287
1288         ssl3_method = TLSv1_client_method();
1289         if (!vpninfo->https_ctx) {
1290                 vpninfo->https_ctx = SSL_CTX_new(ssl3_method);
1291
1292                 /* Some servers (or their firewalls) really don't like seeing
1293                    extensions. */
1294 #ifdef SSL_OP_NO_TICKET
1295                 SSL_CTX_set_options (vpninfo->https_ctx, SSL_OP_NO_TICKET);
1296 #endif
1297
1298                 if (vpninfo->cert) {
1299                         err = load_certificate(vpninfo);
1300                         if (err) {
1301                                 vpn_progress(vpninfo, PRG_ERR,
1302                                              _("Loading certificate failed. Aborting.\n"));
1303                                 return err;
1304                         }
1305                         check_certificate_expiry(vpninfo);
1306                 }
1307
1308                 /* We just want to do:
1309                    SSL_CTX_set_purpose(vpninfo->https_ctx, X509_PURPOSE_ANY); 
1310                    ... but it doesn't work with OpenSSL < 0.9.8k because of 
1311                    problems with inheritance (fixed in v1.1.4.6 of
1312                    crypto/x509/x509_vpm.c) so we have to play silly buggers
1313                    instead. This trick doesn't work _either_ in < 0.9.7 but
1314                    I don't know of _any_ workaround which will, and can't
1315                    be bothered to find out either. */
1316 #if OPENSSL_VERSION_NUMBER >= 0x00908000
1317                 SSL_CTX_set_cert_verify_callback(vpninfo->https_ctx,
1318                                                  ssl_app_verify_callback, NULL);
1319 #endif
1320                 SSL_CTX_set_default_verify_paths(vpninfo->https_ctx);
1321
1322                 if (vpninfo->cafile) {
1323                         if (!SSL_CTX_load_verify_locations(vpninfo->https_ctx, vpninfo->cafile, NULL)) {
1324                                 vpn_progress(vpninfo, PRG_ERR,
1325                                              _("Failed to open CA file '%s'\n"),
1326                                              vpninfo->cafile);
1327                                 openconnect_report_ssl_errors(vpninfo);
1328                                 close(ssl_sock);
1329                                 return -EINVAL;
1330                         }
1331                 }
1332
1333         }
1334         https_ssl = SSL_new(vpninfo->https_ctx);
1335         workaround_openssl_certchain_bug(vpninfo, https_ssl);
1336
1337         https_bio = BIO_new_socket(ssl_sock, BIO_NOCLOSE);
1338         BIO_set_nbio(https_bio, 1);
1339         SSL_set_bio(https_ssl, https_bio, https_bio);
1340
1341         vpn_progress(vpninfo, PRG_INFO, _("SSL negotiation with %s\n"),
1342                      vpninfo->hostname);
1343
1344         while ((err = SSL_connect(https_ssl)) <= 0) {
1345                 fd_set wr_set, rd_set;
1346                 int maxfd = ssl_sock;
1347                 
1348                 FD_ZERO(&wr_set);
1349                 FD_ZERO(&rd_set);
1350
1351                 err = SSL_get_error(https_ssl, err);
1352                 if (err == SSL_ERROR_WANT_READ)
1353                         FD_SET(ssl_sock, &rd_set);
1354                 else if (err == SSL_ERROR_WANT_WRITE)
1355                         FD_SET(ssl_sock, &wr_set);
1356                 else {
1357                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection failure\n"));
1358                         openconnect_report_ssl_errors(vpninfo);
1359                         SSL_free(https_ssl);
1360                         close(ssl_sock);
1361                         return -EINVAL;
1362                 }
1363
1364                 if (vpninfo->cancel_fd != -1) {
1365                         FD_SET(vpninfo->cancel_fd, &rd_set);
1366                         if (vpninfo->cancel_fd > ssl_sock)
1367                                 maxfd = vpninfo->cancel_fd;
1368                 }
1369                 select(maxfd + 1, &rd_set, &wr_set, NULL, NULL);
1370                 if (vpninfo->cancel_fd != -1 &&
1371                     FD_ISSET(vpninfo->cancel_fd, &rd_set)) {
1372                         vpn_progress(vpninfo, PRG_ERR, _("SSL connection cancelled\n"));
1373                         SSL_free(https_ssl);
1374                         close(ssl_sock);
1375                         return -EINVAL;
1376                 }
1377         }
1378
1379         if (verify_peer(vpninfo, https_ssl)) {
1380                 SSL_free(https_ssl);
1381                 close(ssl_sock);
1382                 return -EINVAL;
1383         }
1384
1385         vpninfo->ssl_fd = ssl_sock;
1386         vpninfo->https_ssl = https_ssl;
1387
1388         /* Stash this now, because it might not be available later if the
1389            server has disconnected. */
1390         vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl);
1391
1392         vpn_progress(vpninfo, PRG_INFO, _("Connected to HTTPS on %s\n"),
1393                      vpninfo->hostname);
1394
1395         return 0;
1396 }
1397
1398 void openconnect_close_https(struct openconnect_info *vpninfo, int final)
1399 {
1400         if (vpninfo->peer_cert) {
1401                 X509_free(vpninfo->peer_cert);
1402                 vpninfo->peer_cert = NULL;
1403         }
1404         if (vpninfo->https_ssl) {
1405                 SSL_free(vpninfo->https_ssl);
1406                 vpninfo->https_ssl = NULL;
1407         }
1408         if (vpninfo->ssl_fd != -1) {
1409                 close(vpninfo->ssl_fd);
1410                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_rfds);
1411                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_wfds);
1412                 FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
1413                 vpninfo->ssl_fd = -1;
1414         }
1415         if (final) {
1416                 if (vpninfo->https_ctx) {
1417                         SSL_CTX_free(vpninfo->https_ctx);
1418                         vpninfo->https_ctx = NULL;
1419                 }
1420                 if (vpninfo->cert_x509) {
1421                         X509_free(vpninfo->cert_x509);
1422                         vpninfo->cert_x509 = NULL;
1423                 }
1424         }
1425 }
1426
1427 void openconnect_init_ssl(void)
1428 {
1429         SSL_library_init ();
1430         ERR_clear_error ();
1431         SSL_load_error_strings ();
1432         OpenSSL_add_all_algorithms ();
1433 }
1434
1435 char *openconnect_get_cert_details(struct openconnect_info *vpninfo,
1436                                    OPENCONNECT_X509 *cert)
1437 {
1438         BIO *bp = BIO_new(BIO_s_mem());
1439         BUF_MEM *certinfo;
1440         char zero = 0;
1441         char *ret;
1442
1443         X509_print_ex(bp, cert, 0, 0);
1444         BIO_write(bp, &zero, 1);
1445         BIO_get_mem_ptr(bp, &certinfo);
1446
1447         ret = strdup(certinfo->data);
1448         BIO_free(bp);
1449         return ret;
1450 }
1451
1452
1453 int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
1454                                char *buf)
1455 {
1456         buf[0] = 0;
1457
1458         if (!vpninfo->cert_x509)
1459                 return -EIO;
1460
1461         if (get_cert_md5_fingerprint(vpninfo, vpninfo->cert_x509, buf))
1462                 return -EIO;
1463
1464         return 0;
1465 }