OpenSSL ssl_store_cert(): Remove pointless variable initialization
[privoxy.git] / openssl.c
1 /*********************************************************************
2  *
3  * File        :  $Source: /cvsroot/ijbswa/current/openssl.c,v $
4  *
5  * Purpose     :  File with TLS/SSL extension. Contains methods for
6  *                creating, using and closing TLS/SSL connections
7  *                using OpenSSL (or LibreSSL).
8  *
9  * Copyright   :  Written by and Copyright (c) 2020 Maxim Antonov <mantonov@gmail.com>
10  *                Copyright (C) 2017 Vaclav Svec. FIT CVUT.
11  *                Copyright (C) 2018-2020 by Fabian Keil <fk@fabiankeil.de>
12  *
13  *                This program is free software; you can redistribute it
14  *                and/or modify it under the terms of the GNU General
15  *                Public License as published by the Free Software
16  *                Foundation; either version 2 of the License, or (at
17  *                your option) any later version.
18  *
19  *                This program is distributed in the hope that it will
20  *                be useful, but WITHOUT ANY WARRANTY; without even the
21  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
22  *                PARTICULAR PURPOSE.  See the GNU General Public
23  *                License for more details.
24  *
25  *                The GNU General Public License should be included with
26  *                this file.  If not, you can view it at
27  *                http://www.gnu.org/copyleft/gpl.html
28  *                or write to the Free Software Foundation, Inc., 59
29  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  *
31  *********************************************************************/
32
33 #include <string.h>
34 #include <unistd.h>
35
36 #include <openssl/bn.h>
37 #include <openssl/opensslv.h>
38 #include <openssl/pem.h>
39 #include <openssl/md5.h>
40 #include <openssl/x509v3.h>
41
42 #include "config.h"
43 #include "project.h"
44 #include "miscutil.h"
45 #include "errlog.h"
46 #include "encode.h"
47 #include "jcc.h"
48 #include "ssl.h"
49 #include "ssl_common.h"
50
51 /*
52  * Macros for openssl.c
53  */
54 #define CERTIFICATE_BASIC_CONSTRAINTS            "CA:FALSE"
55 #define CERTIFICATE_SUBJECT_KEY                  "hash"
56 #define CERTIFICATE_AUTHORITY_KEY                "keyid:always"
57 #define CERTIFICATE_ALT_NAME_PREFIX              "DNS:"
58 #define CERTIFICATE_VERSION                      2
59 #define VALID_DATETIME_FMT                       "%y%m%d%H%M%SZ"
60 #define VALID_DATETIME_BUFLEN                    16
61
62 static int generate_host_certificate(struct client_state *csp);
63 static void free_client_ssl_structures(struct client_state *csp);
64 static void free_server_ssl_structures(struct client_state *csp);
65 static int ssl_store_cert(struct client_state *csp, X509 *crt);
66 static void log_ssl_errors(int debuglevel, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
67
68 static int ssl_inited = 0;
69
70 #if OPENSSL_VERSION_NUMBER < 0x10100000L
71 #define X509_set1_notBefore X509_set_notBefore
72 #define X509_set1_notAfter X509_set_notAfter
73 #define X509_get0_serialNumber X509_get_serialNumber
74 #define X509_get0_notBefore X509_get_notBefore
75 #define X509_get0_notAfter X509_get_notAfter
76 #endif
77
78 /*********************************************************************
79  *
80  * Function    :  openssl_init
81  *
82  * Description :  Initializes OpenSSL library once
83  *
84  * Parameters  :  N/A
85  *
86  * Returns     :  N/A
87  *
88  *********************************************************************/
89 static void openssl_init(void)
90 {
91    if (ssl_inited == 0)
92    {
93       privoxy_mutex_lock(&ssl_init_mutex);
94       if (ssl_inited == 0)
95       {
96 #if OPENSSL_VERSION_NUMBER < 0x10100000L
97          SSL_library_init();
98 #else
99          OPENSSL_init_ssl(0, NULL);
100 #endif
101          SSL_load_error_strings();
102          OpenSSL_add_ssl_algorithms();
103          ssl_inited = 1;
104       }
105       privoxy_mutex_unlock(&ssl_init_mutex);
106    }
107 }
108
109
110 /*********************************************************************
111  *
112  * Function    :  is_ssl_pending
113  *
114  * Description :  Tests if there are some waiting data on ssl connection.
115  *                Only considers data that has actually been received
116  *                locally and ignores data that is still on the fly
117  *                or has not yet been sent by the remote end.
118  *
119  * Parameters  :
120  *          1  :  ssl_attr = SSL context to test
121  *
122  * Returns     :   0 => No data are pending
123  *                >0 => Pending data length
124  *
125  *********************************************************************/
126 extern size_t is_ssl_pending(struct ssl_attr *ssl_attr)
127 {
128    BIO *bio = ssl_attr->openssl_attr.bio;
129    if (bio == NULL)
130    {
131       return 0;
132    }
133
134    return (size_t)BIO_pending(bio);
135 }
136
137
138 /*********************************************************************
139  *
140  * Function    :  ssl_send_data
141  *
142  * Description :  Sends the content of buf (for n bytes) to given SSL
143  *                connection context.
144  *
145  * Parameters  :
146  *          1  :  ssl_attr = SSL context to send data to
147  *          2  :  buf = Pointer to data to be sent
148  *          3  :  len = Length of data to be sent to the SSL context
149  *
150  * Returns     :  Length of sent data or negative value on error.
151  *
152  *********************************************************************/
153 extern int ssl_send_data(struct ssl_attr *ssl_attr, const unsigned char *buf, size_t len)
154 {
155    BIO *bio = ssl_attr->openssl_attr.bio;
156    SSL *ssl;
157    int ret = 0;
158    int pos = 0; /* Position of unsent part in buffer */
159    int fd = -1;
160
161    if (len == 0)
162    {
163       return 0;
164    }
165
166    if (BIO_get_ssl(bio, &ssl) == 1)
167    {
168       fd = SSL_get_fd(ssl);
169    }
170
171    while (pos < len)
172    {
173       int send_len = (int)len - pos;
174
175       log_error(LOG_LEVEL_WRITING, "TLS on socket %d: %N",
176          fd, send_len, buf+pos);
177
178       /*
179        * Sending one part of the buffer
180        */
181       while ((ret = BIO_write(bio,
182          (const unsigned char *)(buf + pos),
183          send_len)) <= 0)
184       {
185          if (!BIO_should_retry(bio))
186          {
187             log_ssl_errors(LOG_LEVEL_ERROR,
188                "Sending data on socket %d over TLS/SSL failed", fd);
189             return -1;
190          }
191       }
192       /* Adding count of sent bytes to position in buffer */
193       pos = pos + ret;
194    }
195
196    return (int)len;
197 }
198
199
200 /*********************************************************************
201  *
202  * Function    :  ssl_recv_data
203  *
204  * Description :  Receives data from given SSL context and puts
205  *                it into buffer.
206  *
207  * Parameters  :
208  *          1  :  ssl_attr = SSL context to receive data from
209  *          2  :  buf = Pointer to buffer where data will be written
210  *          3  :  max_length = Maximum number of bytes to read
211  *
212  * Returns     :  Number of bytes read, 0 for EOF, or -1
213  *                on error.
214  *
215  *********************************************************************/
216 extern int ssl_recv_data(struct ssl_attr *ssl_attr, unsigned char *buf, size_t max_length)
217 {
218    BIO *bio = ssl_attr->openssl_attr.bio;
219    SSL *ssl;
220    int ret = 0;
221    int fd = -1;
222
223    memset(buf, 0, max_length);
224
225    /*
226     * Receiving data from SSL context into buffer
227     */
228    do
229    {
230       ret = BIO_read(bio, buf, (int)max_length);
231    } while (ret <= 0 && BIO_should_retry(bio));
232
233    if (BIO_get_ssl(bio, &ssl) == 1)
234    {
235       fd = SSL_get_fd(ssl);
236    }
237
238    if (ret < 0)
239    {
240       log_ssl_errors(LOG_LEVEL_ERROR,
241          "Receiving data on socket %d over TLS/SSL failed", fd);
242
243       return -1;
244    }
245
246    log_error(LOG_LEVEL_RECEIVED, "TLS from socket %d: %N",
247       fd, ret, buf);
248
249    return ret;
250 }
251
252
253 /*********************************************************************
254  *
255  * Function    :  ssl_store_cert
256  *
257  * Description : This function is called once for each certificate in the
258  *               server's certificate trusted chain and prepares
259  *               information about the certificate. The information can
260  *               be used to inform the user about invalid certificates.
261  *
262  * Parameters  :
263  *          1  :  csp = Current client state (buffers, headers, etc...)
264  *          2  :  crt = certificate from trusted chain
265  *
266  * Returns     :  0 on success and negative value on error
267  *
268  *********************************************************************/
269 static int ssl_store_cert(struct client_state *csp, X509 *crt)
270 {
271    long len;
272    struct certs_chain  *last = &(csp->server_certs_chain);
273    int ret = 0;
274    BIO *bio = BIO_new(BIO_s_mem());
275    EVP_PKEY *pkey = NULL;
276    char *bio_mem_data = NULL;
277    char *encoded_text;
278    long l;
279    const ASN1_INTEGER *bs;
280 #if OPENSSL_VERSION_NUMBER > 0x10100000L
281    const X509_ALGOR *tsig_alg;
282 #endif
283    int loc;
284
285    if (!bio)
286    {
287       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new() failed");
288       return -1;
289    }
290
291    /*
292     * Searching for last item in certificates linked list
293     */
294    while (last->next != NULL)
295    {
296       last = last->next;
297    }
298
299    /*
300     * Preparing next item in linked list for next certificate
301     */
302    last->next = malloc_or_die(sizeof(struct certs_chain));
303    last->next->next = NULL;
304    memset(last->next->info_buf, 0, sizeof(last->next->info_buf));
305    memset(last->next->file_buf, 0, sizeof(last->next->file_buf));
306
307    /*
308     * Saving certificate file into buffer
309     */
310    if (!PEM_write_bio_X509(bio, crt))
311    {
312       log_ssl_errors(LOG_LEVEL_ERROR, "PEM_write_bio_X509() failed");
313       ret = -1;
314       goto exit;
315    }
316
317    len = BIO_get_mem_data(bio, &bio_mem_data);
318
319    if (len > (sizeof(last->file_buf) - 1))
320    {
321       log_error(LOG_LEVEL_ERROR,
322          "X509 PEM cert len %ld is larger than buffer len %lu",
323          len, sizeof(last->file_buf) - 1);
324       len = sizeof(last->file_buf) - 1;
325    }
326
327    strncpy(last->file_buf, bio_mem_data, (size_t)len);
328    BIO_free(bio);
329    bio = BIO_new(BIO_s_mem());
330    if (!bio)
331    {
332       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new() failed");
333       ret = -1;
334       goto exit;
335    }
336
337    /*
338     * Saving certificate information into buffer
339     */
340    l = X509_get_version(crt);
341    if (l >= 0 && l <= 2)
342    {
343       if (BIO_printf(bio, "cert. version     : %ld\n", l + 1) <= 0)
344       {
345          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for version failed");
346          ret = -1;
347          goto exit;
348       }
349    }
350    else
351    {
352       if (BIO_printf(bio, "cert. version     : Unknown (%ld)\n", l) <= 0)
353       {
354          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for version failed");
355          ret = -1;
356          goto exit;
357       }
358    }
359
360    if (BIO_puts(bio, "serial number     : ") <= 0)
361    {
362       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for serial failed");
363       ret = -1;
364       goto exit;
365    }
366    bs = X509_get0_serialNumber(crt);
367    if (bs->length <= (int)sizeof(long))
368    {
369       ERR_set_mark();
370       l = ASN1_INTEGER_get(bs);
371       ERR_pop_to_mark();
372    }
373    else
374    {
375       l = -1;
376    }
377    if (l != -1)
378    {
379       unsigned long ul;
380       const char *neg;
381       if (bs->type == V_ASN1_NEG_INTEGER)
382       {
383          ul = 0 - (unsigned long)l;
384          neg = "-";
385       }
386       else
387       {
388          ul = (unsigned long)l;
389          neg = "";
390       }
391       if (BIO_printf(bio, "%s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0)
392       {
393          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for serial failed");
394          ret = -1;
395          goto exit;
396       }
397    }
398    else
399    {
400       int i;
401       if (bs->type == V_ASN1_NEG_INTEGER)
402       {
403          if (BIO_puts(bio, " (Negative)") < 0)
404          {
405             log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for serial failed");
406             ret = -1;
407             goto exit;
408          }
409       }
410       for (i = 0; i < bs->length; i++)
411       {
412          if (BIO_printf(bio, "%02x%c", bs->data[i],
413                ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
414          {
415             log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for serial failed");
416             ret = -1;
417             goto exit;
418          }
419       }
420    }
421
422    if (BIO_puts(bio, "issuer name       : ") <= 0)
423    {
424       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for issuer failed");
425       ret = -1;
426       goto exit;
427    }
428    if (X509_NAME_print_ex(bio, X509_get_issuer_name(crt), 0, 0) < 0)
429    {
430       log_ssl_errors(LOG_LEVEL_ERROR, "X509_NAME_print_ex() for issuer failed");
431       ret = -1;
432       goto exit;
433    }
434
435    if (BIO_puts(bio, "\nsubject name      : ") <= 0)
436    {
437       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for subject failed");
438       ret = -1;
439       goto exit;
440    }
441    if (X509_NAME_print_ex(bio, X509_get_subject_name(crt), 0, 0) < 0) {
442       log_ssl_errors(LOG_LEVEL_ERROR, "X509_NAME_print_ex() for subject failed");
443       ret = -1;
444       goto exit;
445    }
446
447    if (BIO_puts(bio, "\nissued  on        : ") <= 0)
448    {
449       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for issued on failed");
450       ret = -1;
451       goto exit;
452    }
453    if (!ASN1_TIME_print(bio, X509_get0_notBefore(crt)))
454    {
455       log_ssl_errors(LOG_LEVEL_ERROR, "ASN1_TIME_print() for issued on failed");
456       ret = -1;
457       goto exit;
458    }
459
460    if (BIO_puts(bio, "\nexpires on        : ") <= 0)
461    {
462       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for expires on failed");
463       ret = -1;
464       goto exit;
465    }
466    if (!ASN1_TIME_print(bio, X509_get0_notAfter(crt)))
467    {
468       log_ssl_errors(LOG_LEVEL_ERROR, "ASN1_TIME_print() for expires on failed");
469       ret = -1;
470       goto exit;
471    }
472
473 #if OPENSSL_VERSION_NUMBER > 0x10100000L
474    if (BIO_puts(bio, "\nsigned using      : ") <= 0)
475    {
476       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_puts() for signed using failed");
477       ret = -1;
478       goto exit;
479    }
480    tsig_alg = X509_get0_tbs_sigalg(crt);
481    if (!i2a_ASN1_OBJECT(bio, tsig_alg->algorithm))
482    {
483       log_ssl_errors(LOG_LEVEL_ERROR, "i2a_ASN1_OBJECT() for signed using failed");
484       ret = -1;
485       goto exit;
486    }
487 #endif
488    pkey = X509_get_pubkey(crt);
489    if (!pkey)
490    {
491       log_ssl_errors(LOG_LEVEL_ERROR, "X509_get_pubkey() failed");
492       ret = -1;
493       goto exit;
494    }
495 #define BC              "18"
496    switch (EVP_PKEY_base_id(pkey))
497    {
498       case EVP_PKEY_RSA:
499          ret = BIO_printf(bio, "\n%-" BC "s: %d bits", "RSA key size", EVP_PKEY_bits(pkey));
500          break;
501       case EVP_PKEY_DSA:
502          ret = BIO_printf(bio, "\n%-" BC "s: %d bits", "DSA key size", EVP_PKEY_bits(pkey));
503          break;
504       default:
505          ret = BIO_printf(bio, "\n%-" BC "s: %d bits", "non-RSA/DSA key size", EVP_PKEY_bits(pkey));
506          break;
507    }
508    if (ret <= 0)
509    {
510       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for key size failed");
511       ret = -1;
512       goto exit;
513    }
514
515    loc = X509_get_ext_by_NID(crt, NID_basic_constraints, -1);
516    if (loc != -1)
517    {
518       X509_EXTENSION *ex = X509_get_ext(crt, loc);
519       if (BIO_puts(bio, "\nbasic constraints : ") <= 0)
520       {
521          log_ssl_errors(LOG_LEVEL_ERROR,
522             "BIO_printf() for basic constraints failed");
523          ret = -1;
524          goto exit;
525       }
526       if (!X509V3_EXT_print(bio, ex, 0, 0))
527       {
528          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex), ASN1_STRFLGS_RFC2253))
529          {
530             log_ssl_errors(LOG_LEVEL_ERROR,
531                "ASN1_STRING_print_ex() for basic constraints failed");
532             ret = -1;
533             goto exit;
534          }
535       }
536    }
537
538    loc = X509_get_ext_by_NID(crt, NID_subject_alt_name, -1);
539    if (loc != -1)
540    {
541       X509_EXTENSION *ex = X509_get_ext(crt, loc);
542       if (BIO_puts(bio, "\nsubject alt name  : ") <= 0)
543       {
544          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for alt name failed");
545          ret = -1;
546          goto exit;
547       }
548       if (!X509V3_EXT_print(bio, ex, 0, 0))
549       {
550          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex),
551                ASN1_STRFLGS_RFC2253))
552          {
553             log_ssl_errors(LOG_LEVEL_ERROR,
554                "ASN1_STRING_print_ex() for alt name failed");
555             ret = -1;
556             goto exit;
557          }
558       }
559    }
560
561    loc = X509_get_ext_by_NID(crt, NID_netscape_cert_type, -1);
562    if (loc != -1)
563    {
564       X509_EXTENSION *ex = X509_get_ext(crt, loc);
565       if (BIO_puts(bio, "\ncert. type        : ") <= 0)
566       {
567          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for cert type failed");
568          ret = -1;
569          goto exit;
570       }
571       if (!X509V3_EXT_print(bio, ex, 0, 0))
572       {
573          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex),
574                ASN1_STRFLGS_RFC2253))
575          {
576             log_ssl_errors(LOG_LEVEL_ERROR,
577                "ASN1_STRING_print_ex() for cert type failed");
578             ret = -1;
579             goto exit;
580          }
581       }
582    }
583
584    loc = X509_get_ext_by_NID(crt, NID_key_usage, -1);
585    if (loc != -1)
586    {
587       X509_EXTENSION *ex = X509_get_ext(crt, loc);
588       if (BIO_puts(bio, "\nkey usage         : ") <= 0)
589       {
590          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for key usage failed");
591          ret = -1;
592          goto exit;
593       }
594       if (!X509V3_EXT_print(bio, ex, 0, 0))
595       {
596          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex),
597                ASN1_STRFLGS_RFC2253))
598          {
599             log_ssl_errors(LOG_LEVEL_ERROR,
600                "ASN1_STRING_print_ex() for key usage failed");
601             ret = -1;
602             goto exit;
603          }
604       }
605    }
606
607    loc = X509_get_ext_by_NID(crt, NID_ext_key_usage, -1);
608    if (loc != -1) {
609       X509_EXTENSION *ex = X509_get_ext(crt, loc);
610       if (BIO_puts(bio, "\next key usage     : ") <= 0)
611       {
612          log_ssl_errors(LOG_LEVEL_ERROR,
613             "BIO_printf() for ext key usage failed");
614          ret = -1;
615          goto exit;
616       }
617       if (!X509V3_EXT_print(bio, ex, 0, 0))
618       {
619          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex),
620                ASN1_STRFLGS_RFC2253))
621          {
622             log_ssl_errors(LOG_LEVEL_ERROR,
623                "ASN1_STRING_print_ex() for ext key usage failed");
624             ret = -1;
625             goto exit;
626          }
627       }
628    }
629
630    loc = X509_get_ext_by_NID(crt, NID_certificate_policies, -1);
631    if (loc != -1)
632    {
633       X509_EXTENSION *ex = X509_get_ext(crt, loc);
634       if (BIO_puts(bio, "\ncertificate policies : ") <= 0)
635       {
636          log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for certificate policies failed");
637          ret = -1;
638          goto exit;
639       }
640       if (!X509V3_EXT_print(bio, ex, 0, 0))
641       {
642          if (!ASN1_STRING_print_ex(bio, X509_EXTENSION_get_data(ex),
643                ASN1_STRFLGS_RFC2253))
644          {
645             log_ssl_errors(LOG_LEVEL_ERROR,
646                "ASN1_STRING_print_ex() for certificate policies failed");
647             ret = -1;
648             goto exit;
649          }
650       }
651    }
652
653    /* make valgrind happy */
654    static const char zero = 0;
655    BIO_write(bio, &zero, 1);
656
657    len = BIO_get_mem_data(bio, &bio_mem_data);
658    if (len <= 0)
659    {
660       log_error(LOG_LEVEL_ERROR, "BIO_get_mem_data() returned %ld "
661          "while gathering certificate information", len);
662       ret = -1;
663       goto exit;
664    }
665    encoded_text = html_encode(bio_mem_data);
666    if (encoded_text == NULL)
667    {
668       log_error(LOG_LEVEL_ERROR,
669          "Failed to HTML-encode the certificate information");
670       ret = -1;
671       goto exit;
672    }
673
674    strlcpy(last->info_buf, encoded_text, sizeof(last->info_buf));
675    freez(encoded_text);
676    ret = 0;
677
678 exit:
679    if (bio)
680    {
681       BIO_free(bio);
682    }
683    if (pkey)
684    {
685       EVP_PKEY_free(pkey);
686    }
687    return ret;
688 }
689
690
691 /*********************************************************************
692  *
693  * Function    :  host_to_hash
694  *
695  * Description :  Creates MD5 hash from host name. Host name is loaded
696  *                from structure csp and saved again into it.
697  *
698  * Parameters  :
699  *          1  :  csp = Current client state (buffers, headers, etc...)
700  *
701  * Returns     : -1 => Error while creating hash
702  *                0 => Hash created successfully
703  *
704  *********************************************************************/
705 static int host_to_hash(struct client_state *csp)
706 {
707    int ret = 0;
708
709    memset(csp->http->hash_of_host, 0, sizeof(csp->http->hash_of_host));
710    MD5((unsigned char *)csp->http->host, strlen(csp->http->host),
711       csp->http->hash_of_host);
712
713    /* Converting hash into string with hex */
714    size_t i = 0;
715    for (; i < 16; i++)
716    {
717       if ((ret = sprintf((char *)csp->http->hash_of_host_hex + 2 * i, "%02x",
718          csp->http->hash_of_host[i])) < 0)
719       {
720          log_error(LOG_LEVEL_ERROR, "Sprintf return value: %d", ret);
721          return -1;
722       }
723    }
724
725    return 0;
726 }
727
728
729 /*********************************************************************
730  *
731  * Function    :  create_client_ssl_connection
732  *
733  * Description :  Creates TLS/SSL secured connection with client
734  *
735  * Parameters  :
736  *          1  :  csp = Current client state (buffers, headers, etc...)
737  *
738  * Returns     :  0 on success, negative value if connection wasn't created
739  *                successfully.
740  *
741  *********************************************************************/
742 extern int create_client_ssl_connection(struct client_state *csp)
743 {
744    struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
745    /* Paths to certificates file and key file */
746    char *key_file  = NULL;
747    char *cert_file = NULL;
748    int ret = 0;
749    SSL *ssl;
750
751    /*
752     * Initializing OpenSSL structures for TLS/SSL connection
753     */
754    openssl_init();
755
756    /*
757     * Preparing hash of host for creating certificates
758     */
759    ret = host_to_hash(csp);
760    if (ret != 0)
761    {
762       log_error(LOG_LEVEL_ERROR, "Generating hash of host failed: %d", ret);
763       ret = -1;
764       goto exit;
765    }
766
767    /*
768     * Preparing paths to certificates files and key file
769     */
770    cert_file = make_certs_path(csp->config->certificate_directory,
771       (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE);
772    key_file  = make_certs_path(csp->config->certificate_directory,
773       (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
774
775    if (cert_file == NULL || key_file == NULL)
776    {
777       ret = -1;
778       goto exit;
779    }
780
781    /*
782     * Generating certificate for requested host. Mutex to prevent
783     * certificate and key inconsistence must be locked.
784     */
785    privoxy_mutex_lock(&certificate_mutex);
786
787    ret = generate_host_certificate(csp);
788    if (ret < 0)
789    {
790       log_error(LOG_LEVEL_ERROR,
791          "generate_host_certificate failed: %d", ret);
792       privoxy_mutex_unlock(&certificate_mutex);
793       ret = -1;
794       goto exit;
795    }
796    privoxy_mutex_unlock(&certificate_mutex);
797
798    if (!(ssl_attr->openssl_attr.ctx = SSL_CTX_new(SSLv23_server_method())))
799    {
800       log_ssl_errors(LOG_LEVEL_ERROR, "Unable to create SSL context");
801       ret = -1;
802       goto exit;
803    }
804
805    /* Set the key and cert */
806    if (SSL_CTX_use_certificate_file(ssl_attr->openssl_attr.ctx,
807          cert_file, SSL_FILETYPE_PEM) != 1)
808    {
809       log_ssl_errors(LOG_LEVEL_ERROR,
810          "Loading webpage certificate %s failed", cert_file);
811       ret = -1;
812       goto exit;
813    }
814
815    if (SSL_CTX_use_PrivateKey_file(ssl_attr->openssl_attr.ctx,
816          key_file, SSL_FILETYPE_PEM) != 1)
817    {
818       log_ssl_errors(LOG_LEVEL_ERROR,
819          "Loading webpage certificate private key %s failed", key_file);
820       ret = -1;
821       goto exit;
822    }
823
824    SSL_CTX_set_options(ssl_attr->openssl_attr.ctx, SSL_OP_NO_SSLv3);
825
826    if (!(ssl_attr->openssl_attr.bio = BIO_new_ssl(ssl_attr->openssl_attr.ctx, 0)))
827    {
828       log_ssl_errors(LOG_LEVEL_ERROR, "Unable to create BIO structure");
829       ret = -1;
830       goto exit;
831    }
832
833    if (BIO_get_ssl(ssl_attr->openssl_attr.bio, &ssl) != 1)
834    {
835       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_get_ssl failed");
836       ret = -1;
837       goto exit;
838    }
839
840    if (!SSL_set_fd(ssl, csp->cfd))
841    {
842       log_ssl_errors(LOG_LEVEL_ERROR, "SSL_set_fd failed");
843       ret = -1;
844       goto exit;
845    }
846
847    if (csp->config->cipher_list != NULL)
848    {
849       if (!SSL_set_cipher_list(ssl, csp->config->cipher_list))
850       {
851          log_ssl_errors(LOG_LEVEL_ERROR,
852             "Setting the cipher list '%s' for the client connection failed",
853             csp->config->cipher_list);
854          ret = -1;
855          goto exit;
856       }
857    }
858
859    /*
860     *  Handshake with client
861     */
862    log_error(LOG_LEVEL_CONNECT,
863       "Performing the TLS/SSL handshake with client. Hash of host: %s",
864       csp->http->hash_of_host_hex);
865    if (BIO_do_handshake(ssl_attr->openssl_attr.bio) != 1)
866    {
867        log_ssl_errors(LOG_LEVEL_ERROR,
868           "The TLS/SSL handshake with the client failed");
869        ret = -1;
870        goto exit;
871    }
872
873    log_error(LOG_LEVEL_CONNECT, "Client successfully connected over %s (%s).",
874       SSL_get_version(ssl), SSL_get_cipher_name(ssl));
875
876    csp->ssl_with_client_is_opened = 1;
877    ret = 0;
878
879 exit:
880    /*
881     * Freeing allocated paths to files
882     */
883    freez(cert_file);
884    freez(key_file);
885
886    /* Freeing structures if connection wasn't created successfully */
887    if (ret < 0)
888    {
889       free_client_ssl_structures(csp);
890    }
891    return ret;
892 }
893
894
895 /*********************************************************************
896  *
897  * Function    :  close_client_ssl_connection
898  *
899  * Description :  Closes TLS/SSL connection with client. This function
900  *                checks if this connection is already created.
901  *
902  * Parameters  :
903  *          1  :  csp = Current client state (buffers, headers, etc...)
904  *
905  * Returns     :  N/A
906  *
907  *********************************************************************/
908 extern void close_client_ssl_connection(struct client_state *csp)
909 {
910    struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
911    SSL *ssl;
912
913    if (csp->ssl_with_client_is_opened == 0)
914    {
915       return;
916    }
917
918    /*
919     * Notifying the peer that the connection is being closed.
920     */
921    BIO_ssl_shutdown(ssl_attr->openssl_attr.bio);
922    if (BIO_get_ssl(ssl_attr->openssl_attr.bio, &ssl) != 1)
923    {
924       log_ssl_errors(LOG_LEVEL_ERROR,
925          "BIO_get_ssl() failed in close_client_ssl_connection()");
926    }
927    else
928    {
929       /*
930        * Pretend we received a shutdown alert so
931        * the BIO_free_all() call later on returns
932        * quickly.
933        */
934       SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
935    }
936    free_client_ssl_structures(csp);
937    csp->ssl_with_client_is_opened = 0;
938 }
939
940
941 /*********************************************************************
942  *
943  * Function    :  free_client_ssl_structures
944  *
945  * Description :  Frees structures used for SSL communication with
946  *                client.
947  *
948  * Parameters  :
949  *          1  :  csp = Current client state (buffers, headers, etc...)
950  *
951  * Returns     :  N/A
952  *
953  *********************************************************************/
954 static void free_client_ssl_structures(struct client_state *csp)
955 {
956    struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
957
958    if (ssl_attr->openssl_attr.bio)
959    {
960       BIO_free_all(ssl_attr->openssl_attr.bio);
961    }
962    if (ssl_attr->openssl_attr.ctx)
963    {
964       SSL_CTX_free(ssl_attr->openssl_attr.ctx);
965    }
966 }
967
968
969 /*********************************************************************
970  *
971  * Function    :  close_server_ssl_connection
972  *
973  * Description :  Closes TLS/SSL connection with server. This function
974  *                checks if this connection is already opened.
975  *
976  * Parameters  :
977  *          1  :  csp = Current client state (buffers, headers, etc...)
978  *
979  * Returns     :  N/A
980  *
981  *********************************************************************/
982 extern void close_server_ssl_connection(struct client_state *csp)
983 {
984    struct ssl_attr *ssl_attr = &csp->ssl_server_attr;
985    SSL *ssl;
986
987    if (csp->ssl_with_server_is_opened == 0)
988    {
989       return;
990    }
991
992    /*
993    * Notifying the peer that the connection is being closed.
994    */
995    BIO_ssl_shutdown(ssl_attr->openssl_attr.bio);
996    if (BIO_get_ssl(ssl_attr->openssl_attr.bio, &ssl) != 1)
997    {
998       log_ssl_errors(LOG_LEVEL_ERROR,
999          "BIO_get_ssl() failed in close_server_ssl_connection()");
1000    }
1001    else
1002    {
1003       /*
1004        * Pretend we received a shutdown alert so
1005        * the BIO_free_all() call later on returns
1006        * quickly.
1007        */
1008       SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
1009    }
1010    free_server_ssl_structures(csp);
1011    csp->ssl_with_server_is_opened = 0;
1012 }
1013
1014
1015 /*********************************************************************
1016  *
1017  * Function    :  create_server_ssl_connection
1018  *
1019  * Description :  Creates TLS/SSL secured connection with server.
1020  *
1021  * Parameters  :
1022  *          1  :  csp = Current client state (buffers, headers, etc...)
1023  *
1024  * Returns     :  0 on success, negative value if connection wasn't created
1025  *                successfully.
1026  *
1027  *********************************************************************/
1028 extern int create_server_ssl_connection(struct client_state *csp)
1029 {
1030    openssl_connection_attr *ssl_attrs = &csp->ssl_server_attr.openssl_attr;
1031    int ret = 0;
1032    char *trusted_cas_file = NULL;
1033    STACK_OF(X509) *chain;
1034    SSL *ssl;
1035
1036    csp->server_cert_verification_result = SSL_CERT_NOT_VERIFIED;
1037    csp->server_certs_chain.next = NULL;
1038
1039    /* Setting path to file with trusted CAs */
1040    trusted_cas_file = csp->config->trusted_cas_file;
1041
1042    ssl_attrs->ctx = SSL_CTX_new(SSLv23_method());
1043    if (!ssl_attrs->ctx)
1044    {
1045       log_ssl_errors(LOG_LEVEL_ERROR, "SSL context creation failed");
1046       ret = -1;
1047       goto exit;
1048    }
1049
1050    /*
1051     * Loading file with trusted CAs
1052     */
1053    if (!SSL_CTX_load_verify_locations(ssl_attrs->ctx, trusted_cas_file, NULL))
1054    {
1055       log_ssl_errors(LOG_LEVEL_ERROR, "Loading trusted CAs file %s failed",
1056          trusted_cas_file);
1057       ret = -1;
1058       goto exit;
1059    }
1060
1061    SSL_CTX_set_verify(ssl_attrs->ctx, SSL_VERIFY_NONE, NULL);
1062    SSL_CTX_set_options(ssl_attrs->ctx, SSL_OP_NO_SSLv3);
1063
1064    if (!(ssl_attrs->bio = BIO_new_ssl(ssl_attrs->ctx, 1)))
1065    {
1066       log_ssl_errors(LOG_LEVEL_ERROR, "Unable to create BIO structure");
1067       ret = -1;
1068       goto exit;
1069    }
1070
1071    if (BIO_get_ssl(ssl_attrs->bio, &ssl) != 1)
1072    {
1073       log_ssl_errors(LOG_LEVEL_ERROR, "BIO_get_ssl failed");
1074       ret = -1;
1075       goto exit;
1076    }
1077
1078    if (!SSL_set_fd(ssl, csp->server_connection.sfd))
1079    {
1080       log_ssl_errors(LOG_LEVEL_ERROR, "SSL_set_fd failed");
1081       ret = -1;
1082       goto exit;
1083    }
1084
1085    if (csp->config->cipher_list != NULL)
1086    {
1087       if (!SSL_set_cipher_list(ssl, csp->config->cipher_list))
1088       {
1089          log_ssl_errors(LOG_LEVEL_ERROR,
1090             "Setting the cipher list '%s' for the server connection failed",
1091             csp->config->cipher_list);
1092          ret = -1;
1093          goto exit;
1094       }
1095    }
1096
1097    /*
1098     * Set the hostname to check against the received server certificate
1099     */
1100 #if OPENSSL_VERSION_NUMBER > 0x10100000L
1101    if (!SSL_set1_host(ssl, csp->http->host))
1102    {
1103       log_ssl_errors(LOG_LEVEL_ERROR, "SSL_set1_host failed");
1104       ret = -1;
1105       goto exit;
1106    }
1107 #else
1108    if (host_is_ip_address(csp->http->host))
1109    {
1110       if (X509_VERIFY_PARAM_set1_ip_asc(ssl->param,  csp->http->host) != 1)
1111       {
1112          log_ssl_errors(LOG_LEVEL_ERROR,
1113             "X509_VERIFY_PARAM_set1_ip_asc() failed");
1114          ret = -1;
1115          goto exit;
1116       }
1117    }
1118    else
1119    {
1120       if (X509_VERIFY_PARAM_set1_host(ssl->param,  csp->http->host, 0) != 1)
1121       {
1122          log_ssl_errors(LOG_LEVEL_ERROR,
1123             "X509_VERIFY_PARAM_set1_host() failed");
1124          ret = -1;
1125          goto exit;
1126       }
1127    }
1128 #endif
1129    /* SNI extension */
1130    if (!SSL_set_tlsext_host_name(ssl, csp->http->host))
1131    {
1132       log_ssl_errors(LOG_LEVEL_ERROR, "SSL_set_tlsext_host_name failed");
1133       ret = -1;
1134       goto exit;
1135    }
1136
1137    /*
1138     * Handshake with server
1139     */
1140    log_error(LOG_LEVEL_CONNECT,
1141       "Performing the TLS/SSL handshake with the server");
1142
1143    if (BIO_do_handshake(ssl_attrs->bio) != 1)
1144    {
1145       log_ssl_errors(LOG_LEVEL_ERROR,
1146          "The TLS/SSL handshake with the server failed");
1147       ret = -1;
1148       goto exit;
1149    }
1150
1151    chain = SSL_get_peer_cert_chain(ssl);
1152    if (chain)
1153    {
1154       int i;
1155       for (i = 0; i < sk_X509_num(chain); i++)
1156       {
1157          if (ssl_store_cert(csp, sk_X509_value(chain, i)) != 0)
1158          {
1159             log_error(LOG_LEVEL_ERROR, "ssl_store_cert failed");
1160             ret = -1;
1161             goto exit;
1162          }
1163       }
1164    }
1165
1166    if (!csp->dont_verify_certificate)
1167    {
1168       long verify_result = SSL_get_verify_result(ssl);
1169       if (verify_result == X509_V_OK)
1170       {
1171          ret = 0;
1172          csp->server_cert_verification_result = SSL_CERT_VALID;
1173       }
1174       else
1175       {
1176          csp->server_cert_verification_result = verify_result;
1177          log_error(LOG_LEVEL_ERROR,
1178             "X509 certificate verification for %s failed: %s",
1179             csp->http->hostport, X509_verify_cert_error_string(verify_result));
1180          ret = -1;
1181          goto exit;
1182       }
1183    }
1184
1185    log_error(LOG_LEVEL_CONNECT, "Server successfully connected over %s (%s).",
1186      SSL_get_version(ssl), SSL_get_cipher_name(ssl));
1187
1188    /*
1189     * Server certificate chain is valid, so we can clean
1190     * chain, because we will not send it to client.
1191     */
1192    free_certificate_chain(csp);
1193
1194    csp->ssl_with_server_is_opened = 1;
1195 exit:
1196    /* Freeing structures if connection wasn't created successfully */
1197    if (ret < 0)
1198    {
1199       free_server_ssl_structures(csp);
1200    }
1201
1202    return ret;
1203 }
1204
1205
1206 /*********************************************************************
1207  *
1208  * Function    :  free_server_ssl_structures
1209  *
1210  * Description :  Frees structures used for SSL communication with server
1211  *
1212  * Parameters  :
1213  *          1  :  csp = Current client state (buffers, headers, etc...)
1214  *
1215  * Returns     :  N/A
1216  *
1217  *********************************************************************/
1218 static void free_server_ssl_structures(struct client_state *csp)
1219 {
1220    struct ssl_attr *ssl_attr = &csp->ssl_server_attr;
1221
1222    if (ssl_attr->openssl_attr.bio)
1223    {
1224       BIO_free_all(ssl_attr->openssl_attr.bio);
1225    }
1226    if (ssl_attr->openssl_attr.ctx)
1227    {
1228       SSL_CTX_free(ssl_attr->openssl_attr.ctx);
1229    }
1230 }
1231
1232
1233 /*********************************************************************
1234  *
1235  * Function    :  log_ssl_errors
1236  *
1237  * Description :  Log SSL errors
1238  *
1239  * Parameters  :
1240  *          1  :  debuglevel = Debug level
1241  *          2  :  desc = Error description
1242  *
1243  * Returns     :  N/A
1244  *
1245  *********************************************************************/
1246 static void log_ssl_errors(int debuglevel, const char* fmt, ...)
1247 {
1248    unsigned long err_code;
1249    char prefix[ERROR_BUF_SIZE];
1250    va_list args;
1251    va_start(args, fmt);
1252    vsnprintf(prefix, sizeof(prefix), fmt, args);
1253    int reported = 0;
1254
1255    while ((err_code = ERR_get_error()))
1256    {
1257       char err_buf[ERROR_BUF_SIZE];
1258       reported = 1;
1259       ERR_error_string_n(err_code, err_buf, sizeof(err_buf));
1260       log_error(debuglevel, "%s: %s", prefix, err_buf);
1261    }
1262    va_end(args);
1263    /*
1264     * In case if called by mistake and there were
1265     * no TLS/SSL errors let's report it to the log.
1266     */
1267    if (!reported)
1268    {
1269       log_error(debuglevel, "%s: no TLS/SSL errors detected", prefix);
1270    }
1271 }
1272
1273
1274 /*********************************************************************
1275  *
1276  * Function    :  ssl_base64_encode
1277  *
1278  * Description :  Encode a buffer into base64 format.
1279  *
1280  * Parameters  :
1281  *          1  :  dst = Destination buffer
1282  *          2  :  dlen = Destination buffer length
1283  *          3  :  olen = Number of bytes written
1284  *          4  :  src = Source buffer
1285  *          5  :  slen = Amount of data to be encoded
1286  *
1287  * Returns     :  0 on success, error code othervise
1288  *
1289  *********************************************************************/
1290 extern int ssl_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
1291                              const unsigned char *src, size_t slen)
1292 {
1293    *olen = 4 * ((slen/3) + ((slen%3) ? 1 : 0)) + 1;
1294    if (*olen > dlen)
1295    {
1296       return ENOBUFS;
1297    }
1298    *olen = (size_t)EVP_EncodeBlock(dst, src, (int)slen) + 1;
1299    return 0;
1300 }
1301
1302
1303 /*********************************************************************
1304  *
1305  * Function    :  close_file_stream
1306  *
1307  * Description :  Close file stream, report error on close error
1308  *
1309  * Parameters  :
1310  *          1  :  f = file stream to close
1311  *          2  :  path = path for error report
1312  *
1313  * Returns     :  N/A
1314  *
1315  *********************************************************************/
1316 static void close_file_stream(FILE *f, const char *path)
1317 {
1318    if (fclose(f) != 0)
1319    {
1320       log_error(LOG_LEVEL_ERROR,
1321          "Error closing file %s: %s", path, strerror(errno));
1322    }
1323 }
1324
1325
1326 /*********************************************************************
1327  *
1328  * Function    :  write_certificate
1329  *
1330  * Description :  Writes certificate into file.
1331  *
1332  * Parameters  :
1333  *          1  :  crt = certificate to write into file
1334  *          2  :  output_file = path to save certificate file
1335  *
1336  *                on error
1337  * Returns     :  1 on success success or negative value
1338  *
1339  *********************************************************************/
1340 static int write_certificate(X509 *crt, const char *output_file)
1341 {
1342    FILE *f = NULL;
1343    int ret = -1;
1344
1345    /*
1346     * Saving certificate into file
1347     */
1348    if ((f = fopen(output_file, "w")) == NULL)
1349    {
1350       log_error(LOG_LEVEL_ERROR, "Opening file %s to save certificate failed",
1351          output_file);
1352       return ret;
1353    }
1354
1355    ret = PEM_write_X509(f, crt);
1356    if (!ret)
1357    {
1358       log_ssl_errors(LOG_LEVEL_ERROR,
1359          "Writing certificate into file %s failed", output_file);
1360       ret = -1;
1361    }
1362
1363    close_file_stream(f, output_file);
1364
1365    return ret;
1366 }
1367
1368 /*********************************************************************
1369  *
1370  * Function    :  write_private_key
1371  *
1372  * Description :  Writes private key into file and copies saved
1373  *                content into given pointer to string. If function
1374  *                returns 0 for success, this copy must be freed by
1375  *                caller.
1376  *
1377  * Parameters  :
1378  *          1  :  key = key to write into file
1379  *          2  :  ret_buf = pointer to string with created key file content
1380  *          3  :  key_file_path = path where to save key file
1381  *
1382  * Returns     :  Length of written private key on success or negative value
1383  *                on error
1384  *
1385  *********************************************************************/
1386 static int write_private_key(EVP_PKEY *key, char **ret_buf,
1387                              const char *key_file_path)
1388 {
1389    size_t len = 0;                /* Length of created key    */
1390    FILE *f = NULL;                /* File to save certificate */
1391    int ret = 0;
1392    BIO *bio_mem = BIO_new(BIO_s_mem());
1393    char *bio_mem_data = 0;
1394
1395    if (bio_mem == NULL)
1396    {
1397       log_ssl_errors(LOG_LEVEL_ERROR, "write_private_key memory allocation failure");
1398       return -1;
1399    }
1400
1401    /*
1402     * Writing private key into PEM string
1403     */
1404    if (!PEM_write_bio_PrivateKey(bio_mem, key, NULL, NULL, 0, NULL, NULL))
1405    {
1406       log_ssl_errors(LOG_LEVEL_ERROR,
1407          "Writing private key into PEM string failed");
1408       ret = -1;
1409       goto exit;
1410    }
1411
1412    len = (size_t)BIO_get_mem_data(bio_mem, &bio_mem_data);
1413
1414    /* Initializing buffer for key file content */
1415    *ret_buf = zalloc_or_die(len + 1);
1416    (*ret_buf)[len] = 0;
1417
1418    strncpy(*ret_buf, bio_mem_data, len);
1419
1420    /*
1421     * Saving key into file
1422     */
1423    if ((f = fopen(key_file_path, "wb")) == NULL)
1424    {
1425       log_error(LOG_LEVEL_ERROR,
1426          "Opening file %s to save private key failed: %E",
1427          key_file_path);
1428       ret = -1;
1429       goto exit;
1430    }
1431
1432    if (fwrite(*ret_buf, 1, len, f) != len)
1433    {
1434       log_error(LOG_LEVEL_ERROR,
1435          "Writing private key into file %s failed",
1436          key_file_path);
1437       close_file_stream(f, key_file_path);
1438       ret = -1;
1439       goto exit;
1440    }
1441
1442    close_file_stream(f, key_file_path);
1443
1444 exit:
1445    BIO_free(bio_mem);
1446    if (ret < 0)
1447    {
1448       freez(*ret_buf);
1449       *ret_buf = NULL;
1450       return ret;
1451    }
1452    return (int)len;
1453 }
1454
1455
1456 /*********************************************************************
1457  *
1458  * Function    :  generate_key
1459  *
1460  * Description : Tests if private key for host saved in csp already
1461  *               exists.  If this file doesn't exists, a new key is
1462  *               generated and saved in a file. The generated key is also
1463  *               copied into given parameter key_buf, which must be then
1464  *               freed by caller. If file with key exists, key_buf
1465  *               contain NULL and no private key is generated.
1466  *
1467  * Parameters  :
1468  *          1  :  csp = Current client state (buffers, headers, etc...)
1469  *          2  :  key_buf = buffer to save new generated key
1470  *
1471  * Returns     :  -1 => Error while generating private key
1472  *                 0 => Key already exists
1473  *                >0 => Length of generated private key
1474  *
1475  *********************************************************************/
1476 static int generate_key(struct client_state *csp, char **key_buf)
1477 {
1478    int ret = 0;
1479    char* key_file_path;
1480    BIGNUM *exp;
1481    RSA *rsa;
1482    EVP_PKEY *key;
1483
1484    key_file_path = make_certs_path(csp->config->certificate_directory,
1485       (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
1486    if (key_file_path == NULL)
1487    {
1488       return -1;
1489    }
1490
1491    /*
1492     * Test if key already exists. If so, we don't have to create it again.
1493     */
1494    if (file_exists(key_file_path) == 1)
1495    {
1496       freez(key_file_path);
1497       return 0;
1498    }
1499
1500    exp = BN_new();
1501    rsa = RSA_new();
1502    key = EVP_PKEY_new();
1503    if (exp == NULL || rsa == NULL || key == NULL)
1504    {
1505       log_ssl_errors(LOG_LEVEL_ERROR, "RSA key memory allocation failure");
1506       ret = -1;
1507       goto exit;
1508    }
1509
1510    if (BN_set_word(exp, RSA_KEY_PUBLIC_EXPONENT) != 1)
1511    {
1512       log_ssl_errors(LOG_LEVEL_ERROR, "Setting RSA key exponent failed");
1513       ret = -1;
1514       goto exit;
1515    }
1516
1517    ret = RSA_generate_key_ex(rsa, RSA_KEYSIZE, exp, NULL);
1518    if (ret == 0)
1519    {
1520       log_ssl_errors(LOG_LEVEL_ERROR, "RSA key generation failure");
1521       ret = -1;
1522       goto exit;
1523    }
1524
1525    if (!EVP_PKEY_set1_RSA(key, rsa))
1526    {
1527       log_ssl_errors(LOG_LEVEL_ERROR,
1528          "Error assigning RSA key pair to PKEY structure");
1529       ret = -1;
1530       goto exit;
1531    }
1532
1533    /*
1534     * Exporting private key into file
1535     */
1536    if ((ret = write_private_key(key, key_buf, key_file_path)) < 0)
1537    {
1538       log_error(LOG_LEVEL_ERROR,
1539          "Writing private key into file %s failed", key_file_path);
1540       ret = -1;
1541       goto exit;
1542    }
1543
1544 exit:
1545    /*
1546     * Freeing used variables
1547     */
1548    if (exp)
1549    {
1550       BN_free(exp);
1551    }
1552    if (rsa)
1553    {
1554       RSA_free(rsa);
1555    }
1556    if (key)
1557    {
1558       EVP_PKEY_free(key);
1559    }
1560    freez(key_file_path);
1561
1562    return ret;
1563 }
1564
1565
1566 /*********************************************************************
1567  *
1568  * Function    :  ssl_certificate_load
1569  *
1570  * Description :  Loads certificate from file.
1571  *
1572  * Parameters  :
1573  *          1  :  cert_path = The certificate path to load
1574  *
1575  * Returns     :   NULL => error loading certificate,
1576  *                   pointer to certificate instance otherwise
1577  *
1578  *********************************************************************/
1579 static X509 *ssl_certificate_load(const char *cert_path)
1580 {
1581    X509 *cert = NULL;
1582    FILE *cert_f = NULL;
1583
1584    if (!(cert_f = fopen(cert_path, "r")))
1585    {
1586       log_error(LOG_LEVEL_ERROR,
1587          "Error opening certificate file %s: %s", cert_path, strerror(errno));
1588       return NULL;
1589    }
1590
1591    if (!(cert = PEM_read_X509(cert_f, NULL, NULL, NULL)))
1592    {
1593       log_ssl_errors(LOG_LEVEL_ERROR,
1594          "Error reading certificate file %s", cert_path);
1595    }
1596
1597    close_file_stream(cert_f, cert_path);
1598    return cert;
1599 }
1600
1601
1602 /*********************************************************************
1603  *
1604  * Function    :  ssl_certificate_is_invalid
1605  *
1606  * Description :  Checks whether or not a certificate is valid.
1607  *                Currently only checks that the certificate can be
1608  *                parsed and that the "valid to" date is in the future.
1609  *
1610  * Parameters  :
1611  *          1  :  cert_file = The certificate to check
1612  *
1613  * Returns     :   0 => The certificate is valid.
1614  *                 1 => The certificate is invalid
1615  *
1616  *********************************************************************/
1617 static int ssl_certificate_is_invalid(const char *cert_file)
1618 {
1619    int ret;
1620
1621    X509 *cert = NULL;
1622
1623    if (!(cert = ssl_certificate_load(cert_file)))
1624    {
1625       return 1;
1626    }
1627
1628    ret = X509_cmp_current_time(X509_get_notAfter(cert));
1629    if (ret == 0)
1630    {
1631       log_ssl_errors(LOG_LEVEL_ERROR,
1632          "Error checking certificate %s validity", cert_file);
1633       ret = -1;
1634    }
1635
1636    X509_free(cert);
1637
1638    return ret == -1 ? 1 : 0;
1639 }
1640
1641
1642 /*********************************************************************
1643  *
1644  * Function    :  set_x509_ext
1645  *
1646  * Description :  Sets the X509V3 extension data
1647  *
1648  * Parameters  :
1649  *          1  :  cert = The certificate to modify
1650  *          2  :  issuer = Issuer certificate
1651  *          3  :  nid = OpenSSL NID
1652  *          4  :  value = extension value
1653  *
1654  * Returns     :   0 => Error while setting extension data
1655  *                 1 => It worked
1656  *
1657  *********************************************************************/
1658 static int set_x509_ext(X509 *cert, X509 *issuer, int nid, char *value)
1659 {
1660    X509_EXTENSION *ext = NULL;
1661    X509V3_CTX ctx;
1662    int ret = 0;
1663
1664    X509V3_set_ctx(&ctx, issuer, cert, NULL, NULL, 0);
1665    ext = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
1666    if (!ext)
1667    {
1668       log_ssl_errors(LOG_LEVEL_ERROR, "X509V3_EXT_conf_nid failure");
1669       goto exit;
1670    }
1671
1672    if (!X509_add_ext(cert, ext, -1))
1673    {
1674       log_ssl_errors(LOG_LEVEL_ERROR, "X509_add_ext failure");
1675       goto exit;
1676    }
1677
1678    ret = 1;
1679 exit:
1680    if (ext)
1681    {
1682       X509_EXTENSION_free(ext);
1683    }
1684    return ret;
1685 }
1686
1687
1688 /*********************************************************************
1689  *
1690  * Function    :  set_subject_alternative_name
1691  *
1692  * Description :  Sets the Subject Alternative Name extension to a cert
1693  *
1694  * Parameters  :
1695  *          1  :  cert = The certificate to modify
1696  *          2  :  issuer = Issuer certificate
1697  *          3  :  hostname = The hostname to add
1698  *
1699  * Returns     :   0 => Error while creating certificate.
1700  *                 1 => It worked
1701  *
1702  *********************************************************************/
1703 static int set_subject_alternative_name(X509 *cert, X509 *issuer, const char *hostname)
1704 {
1705    size_t altname_len = strlen(hostname) + sizeof(CERTIFICATE_ALT_NAME_PREFIX);
1706    char alt_name_buf[altname_len];
1707
1708    snprintf(alt_name_buf, sizeof(alt_name_buf),
1709       CERTIFICATE_ALT_NAME_PREFIX"%s", hostname);
1710    return set_x509_ext(cert, issuer, NID_subject_alt_name, alt_name_buf);
1711 }
1712
1713
1714 /*********************************************************************
1715  *
1716  * Function    :  generate_host_certificate
1717  *
1718  * Description :  Creates certificate file in presetted directory.
1719  *                If certificate already exists, no other certificate
1720  *                will be created. Subject of certificate is named
1721  *                by csp->http->host from parameter. This function also
1722  *                triggers generating of private key for new certificate.
1723  *
1724  * Parameters  :
1725  *          1  :  csp = Current client state (buffers, headers, etc...)
1726  *
1727  * Returns     :  -1 => Error while creating certificate.
1728  *                 0 => Certificate already exists.
1729  *                 1 => Certificate created
1730  *
1731  *********************************************************************/
1732 static int generate_host_certificate(struct client_state *csp)
1733 {
1734    char *key_buf = NULL;    /* Buffer for created key */
1735    X509 *issuer_cert = NULL;
1736    X509 *cert = NULL;
1737    BIO *pk_bio = NULL;
1738    EVP_PKEY *loaded_subject_key = NULL;
1739    EVP_PKEY *loaded_issuer_key = NULL;
1740    X509_NAME *issuer_name;
1741    X509_NAME *subject_name = NULL;
1742    ASN1_TIME *asn_time = NULL;
1743    ASN1_INTEGER *serial = NULL;
1744    BIGNUM *serial_num = NULL;
1745
1746    int ret = 0;
1747    cert_options cert_opt;
1748    char cert_valid_from[VALID_DATETIME_BUFLEN];
1749    char cert_valid_to[VALID_DATETIME_BUFLEN];
1750
1751    /* Paths to keys and certificates needed to create certificate */
1752    cert_opt.issuer_key  = NULL;
1753    cert_opt.subject_key = NULL;
1754    cert_opt.issuer_crt  = NULL;
1755
1756    cert_opt.output_file = make_certs_path(csp->config->certificate_directory,
1757       (const char *)csp->http->hash_of_host_hex, CERT_FILE_TYPE);
1758    if (cert_opt.output_file == NULL)
1759    {
1760       return -1;
1761    }
1762
1763    cert_opt.subject_key = make_certs_path(csp->config->certificate_directory,
1764       (const char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
1765    if (cert_opt.subject_key == NULL)
1766    {
1767       freez(cert_opt.output_file);
1768       return -1;
1769    }
1770
1771    if (enforce_sane_certificate_state(cert_opt.output_file,
1772          cert_opt.subject_key))
1773    {
1774       freez(cert_opt.output_file);
1775       freez(cert_opt.subject_key);
1776
1777       return -1;
1778    }
1779
1780    if (file_exists(cert_opt.output_file) == 1)
1781    {
1782       /* The file exists, but is it valid? */
1783       if (ssl_certificate_is_invalid(cert_opt.output_file))
1784       {
1785          log_error(LOG_LEVEL_CONNECT,
1786             "Certificate %s is no longer valid. Removing it.",
1787             cert_opt.output_file);
1788          if (unlink(cert_opt.output_file))
1789          {
1790             log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E",
1791                cert_opt.output_file);
1792
1793             freez(cert_opt.output_file);
1794             freez(cert_opt.subject_key);
1795
1796             return -1;
1797          }
1798          if (unlink(cert_opt.subject_key))
1799          {
1800             log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E",
1801                cert_opt.subject_key);
1802
1803             freez(cert_opt.output_file);
1804             freez(cert_opt.subject_key);
1805
1806             return -1;
1807          }
1808       }
1809       else
1810       {
1811          freez(cert_opt.output_file);
1812          freez(cert_opt.subject_key);
1813
1814          return 0;
1815       }
1816    }
1817
1818    /*
1819     * Create key for requested host
1820     */
1821    int subject_key_len = generate_key(csp, &key_buf);
1822    if (subject_key_len < 0)
1823    {
1824       freez(cert_opt.output_file);
1825       freez(cert_opt.subject_key);
1826       log_error(LOG_LEVEL_ERROR, "Key generating failed");
1827       return -1;
1828    }
1829
1830    /*
1831     * Converting unsigned long serial number to char * serial number.
1832     * We must compute length of serial number in string + terminating null.
1833     */
1834    unsigned long certificate_serial = get_certificate_serial(csp);
1835    unsigned long certificate_serial_time = (unsigned long)time(NULL);
1836    int serial_num_size = snprintf(NULL, 0, "%lu%lu",
1837       certificate_serial_time, certificate_serial) + 1;
1838    if (serial_num_size <= 0)
1839    {
1840       serial_num_size = 1;
1841    }
1842
1843    char serial_num_text[serial_num_size];  /* Buffer for serial number */
1844    ret = snprintf(serial_num_text, (size_t)serial_num_size, "%lu%lu",
1845       certificate_serial_time, certificate_serial);
1846    if (ret < 0 || ret >= serial_num_size)
1847    {
1848       log_error(LOG_LEVEL_ERROR,
1849          "Converting certificate serial number into string failed");
1850       ret = -1;
1851       goto exit;
1852    }
1853
1854    /*
1855     * Preparing parameters for certificate
1856     */
1857    subject_name = X509_NAME_new();
1858    if (!subject_name)
1859    {
1860       log_ssl_errors(LOG_LEVEL_ERROR, "RSA key memory allocation failure");
1861       ret = -1;
1862       goto exit;
1863    }
1864
1865    if (!X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_COMMON_NAME_FCODE,
1866          MBSTRING_ASC, (void *)csp->http->host, -1, -1, 0))
1867    {
1868       log_ssl_errors(LOG_LEVEL_ERROR,
1869          "X509 subject name (code: %s, val: %s) error",
1870          CERT_PARAM_COMMON_NAME_FCODE, csp->http->host);
1871       ret = -1;
1872       goto exit;
1873    }
1874    if (!X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_ORGANIZATION_FCODE,
1875          MBSTRING_ASC, (void *)csp->http->host, -1, -1, 0))
1876    {
1877       log_ssl_errors(LOG_LEVEL_ERROR,
1878          "X509 subject name (code: %s, val: %s) error",
1879          CERT_PARAM_ORGANIZATION_FCODE, csp->http->host);
1880       ret = -1;
1881       goto exit;
1882    }
1883    if (!X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_ORG_UNIT_FCODE,
1884          MBSTRING_ASC, (void *)csp->http->host, -1, -1, 0))
1885    {
1886       log_ssl_errors(LOG_LEVEL_ERROR,
1887          "X509 subject name (code: %s, val: %s) error",
1888          CERT_PARAM_ORG_UNIT_FCODE, csp->http->host);
1889       ret = -1;
1890       goto exit;
1891    }
1892    if (!X509_NAME_add_entry_by_txt(subject_name, CERT_PARAM_COUNTRY_FCODE,
1893          MBSTRING_ASC, (void *)CERT_PARAM_COUNTRY_CODE, -1, -1, 0))
1894    {
1895       log_ssl_errors(LOG_LEVEL_ERROR,
1896          "X509 subject name (code: %s, val: %s) error",
1897          CERT_PARAM_COUNTRY_FCODE, csp->http->host);
1898       ret = -1;
1899       goto exit;
1900    }
1901
1902    cert_opt.issuer_crt = csp->config->ca_cert_file;
1903    cert_opt.issuer_key = csp->config->ca_key_file;
1904
1905    if (get_certificate_valid_from_date(cert_valid_from,
1906          sizeof(cert_valid_from), VALID_DATETIME_FMT)
1907     || get_certificate_valid_to_date(cert_valid_to,
1908          sizeof(cert_valid_to), VALID_DATETIME_FMT))
1909    {
1910       log_error(LOG_LEVEL_ERROR, "Generating one of the validity dates failed");
1911       ret = -1;
1912       goto exit;
1913    }
1914
1915    cert_opt.subject_pwd = CERT_SUBJECT_PASSWORD;
1916    cert_opt.issuer_pwd  = csp->config->ca_password;
1917    cert_opt.not_before  = cert_valid_from;
1918    cert_opt.not_after   = cert_valid_to;
1919    cert_opt.serial      = serial_num_text;
1920    cert_opt.max_pathlen = -1;
1921
1922    /*
1923     * Test if the private key was already created.
1924     * XXX: Can this still happen?
1925     */
1926    if (subject_key_len == 0)
1927    {
1928       log_error(LOG_LEVEL_ERROR, "Subject key was already created");
1929       ret = 0;
1930       goto exit;
1931    }
1932
1933    /*
1934     * Parse serial to MPI
1935     */
1936    serial_num = BN_new();
1937    if (!serial_num)
1938    {
1939       log_error(LOG_LEVEL_ERROR, "generate_host_certificate: memory error");
1940       ret = -1;
1941       goto exit;
1942    }
1943    if (!BN_dec2bn(&serial_num, cert_opt.serial))
1944    {
1945       log_ssl_errors(LOG_LEVEL_ERROR, "Failed to parse serial %s", cert_opt.serial);
1946       ret = -1;
1947       goto exit;
1948    }
1949
1950    if (!(serial = BN_to_ASN1_INTEGER(serial_num, NULL)))
1951    {
1952       log_ssl_errors(LOG_LEVEL_ERROR, "Failed to generate serial ASN1 representation");
1953       ret = -1;
1954       goto exit;
1955    }
1956
1957    /*
1958     * Loading certificates
1959     */
1960    if (!(issuer_cert = ssl_certificate_load(cert_opt.issuer_crt)))
1961    {
1962       log_error(LOG_LEVEL_ERROR, "Loading issuer certificate %s failed",
1963          cert_opt.issuer_crt);
1964       ret = -1;
1965       goto exit;
1966    }
1967
1968    issuer_name = X509_get_issuer_name(issuer_cert);
1969
1970    /*
1971     * Loading keys from file or from buffer
1972     */
1973    if (key_buf != NULL && subject_key_len > 0)
1974    {
1975       pk_bio = BIO_new_mem_buf(key_buf, subject_key_len);
1976    }
1977    else if (!(pk_bio = BIO_new_file(cert_opt.subject_key, "r")))
1978    {
1979       log_ssl_errors(LOG_LEVEL_ERROR,
1980          "Failure opening subject key %s BIO", cert_opt.subject_key);
1981       ret = -1;
1982       goto exit;
1983    }
1984
1985    loaded_subject_key = PEM_read_bio_PrivateKey(pk_bio, NULL, NULL,
1986       (void *)cert_opt.subject_pwd);
1987    if (!loaded_subject_key)
1988    {
1989       log_ssl_errors(LOG_LEVEL_ERROR, "Parsing subject key %s failed",
1990          cert_opt.subject_key);
1991       ret = -1;
1992       goto exit;
1993    }
1994
1995    if (!BIO_free(pk_bio))
1996    {
1997       log_ssl_errors(LOG_LEVEL_ERROR, "Error closing subject key BIO");
1998    }
1999
2000    if (!(pk_bio = BIO_new_file(cert_opt.issuer_key, "r")))
2001    {
2002       log_ssl_errors(LOG_LEVEL_ERROR, "Failure opening issuer key %s BIO",
2003          cert_opt.issuer_key);
2004       ret = -1;
2005       goto exit;
2006    }
2007
2008    loaded_issuer_key = PEM_read_bio_PrivateKey(pk_bio, NULL, NULL,
2009       (void *)cert_opt.issuer_pwd);
2010    if (!loaded_issuer_key)
2011    {
2012       log_ssl_errors(LOG_LEVEL_ERROR, "Parsing issuer key %s failed",
2013          cert_opt.subject_key);
2014       ret = -1;
2015       goto exit;
2016    }
2017
2018    cert = X509_new();
2019    if (!cert)
2020    {
2021       log_ssl_errors(LOG_LEVEL_ERROR, "Certificate allocation error");
2022       ret = -1;
2023       goto exit;
2024    }
2025
2026    if (!X509_set_version(cert, CERTIFICATE_VERSION))
2027    {
2028       log_ssl_errors(LOG_LEVEL_ERROR, "X509_set_version failed");
2029       ret = -1;
2030       goto exit;
2031    }
2032
2033    /*
2034     * Setting parameters of signed certificate
2035     */
2036    if (!X509_set_pubkey(cert, loaded_subject_key))
2037    {
2038       log_ssl_errors(LOG_LEVEL_ERROR,
2039          "Setting public key in signed certificate failed");
2040       ret = -1;
2041       goto exit;
2042    }
2043
2044    if (!X509_set_subject_name(cert, subject_name))
2045    {
2046       log_ssl_errors(LOG_LEVEL_ERROR,
2047          "Setting subject name in signed certificate failed");
2048       ret = -1;
2049       goto exit;
2050    }
2051
2052    if (!X509_set_issuer_name(cert, issuer_name))
2053    {
2054       log_ssl_errors(LOG_LEVEL_ERROR,
2055          "Setting issuer name in signed certificate failed");
2056       ret = -1;
2057       goto exit;
2058    }
2059
2060    if (!X509_set_serialNumber(cert, serial))
2061    {
2062       log_ssl_errors(LOG_LEVEL_ERROR,
2063          "Setting serial number in signed certificate failed");
2064       ret = -1;
2065       goto exit;
2066    }
2067
2068    asn_time = ASN1_TIME_new();
2069    if (!asn_time)
2070    {
2071       log_ssl_errors(LOG_LEVEL_ERROR, "ASN1 time memory allocation failure");
2072       ret = -1;
2073       goto exit;
2074    }
2075
2076    if (!ASN1_TIME_set_string(asn_time, cert_opt.not_after))
2077    {
2078       log_ssl_errors(LOG_LEVEL_ERROR, "ASN1 time [%s] encode error", cert_opt.not_after);
2079       ret = -1;
2080       goto exit;
2081    }
2082
2083    if (!X509_set1_notAfter(cert, asn_time))
2084    {
2085       log_ssl_errors(LOG_LEVEL_ERROR,
2086          "Setting valid not after in signed certificate failed");
2087       ret = -1;
2088       goto exit;
2089    }
2090
2091    if (!ASN1_TIME_set_string(asn_time, cert_opt.not_before))
2092    {
2093       log_ssl_errors(LOG_LEVEL_ERROR, "ASN1 time encode error");
2094       ret = -1;
2095       goto exit;
2096    }
2097
2098    if (!X509_set1_notBefore(cert, asn_time))
2099    {
2100       log_ssl_errors(LOG_LEVEL_ERROR,
2101          "Setting valid not before in signed certificate failed");
2102       ret = -1;
2103       goto exit;
2104    }
2105
2106    if (!set_x509_ext(cert, issuer_cert, NID_basic_constraints, CERTIFICATE_BASIC_CONSTRAINTS))
2107    {
2108       log_ssl_errors(LOG_LEVEL_ERROR, "Setting the basicConstraints extension "
2109          "in signed certificate failed");
2110       ret = -1;
2111       goto exit;
2112    }
2113
2114    if (!set_x509_ext(cert, issuer_cert, NID_subject_key_identifier, CERTIFICATE_SUBJECT_KEY))
2115    {
2116       log_ssl_errors(LOG_LEVEL_ERROR,
2117          "Setting the Subject Key Identifier extension failed");
2118       ret = -1;
2119       goto exit;
2120    }
2121
2122    if (!set_x509_ext(cert, issuer_cert, NID_authority_key_identifier, CERTIFICATE_AUTHORITY_KEY))
2123    {
2124       log_ssl_errors(LOG_LEVEL_ERROR,
2125          "Setting the Authority Key Identifier extension failed");
2126       ret = -1;
2127       goto exit;
2128    }
2129
2130    if (!host_is_ip_address(csp->http->host) &&
2131        !set_subject_alternative_name(cert, issuer_cert, csp->http->host))
2132    {
2133       log_ssl_errors(LOG_LEVEL_ERROR,
2134          "Setting the Subject Alt Name extension failed");
2135       ret = -1;
2136       goto exit;
2137    }
2138
2139    if (!X509_sign(cert, loaded_issuer_key, EVP_sha256()))
2140    {
2141       log_ssl_errors(LOG_LEVEL_ERROR, "Signing certificate failed");
2142       ret = -1;
2143       goto exit;
2144    }
2145
2146    /*
2147     * Writing certificate into file
2148     */
2149    if (write_certificate(cert, cert_opt.output_file) < 0)
2150    {
2151       log_error(LOG_LEVEL_ERROR, "Writing certificate into file failed");
2152       ret = -1;
2153       goto exit;
2154    }
2155
2156    ret = 1;
2157
2158 exit:
2159    /*
2160     * Freeing used structures
2161     */
2162    if (issuer_cert)
2163    {
2164       X509_free(issuer_cert);
2165    }
2166    if (cert)
2167    {
2168       X509_free(cert);
2169    }
2170    if (pk_bio && !BIO_free(pk_bio))
2171    {
2172       log_ssl_errors(LOG_LEVEL_ERROR, "Error closing pk BIO");
2173    }
2174    if (loaded_subject_key)
2175    {
2176       EVP_PKEY_free(loaded_subject_key);
2177    }
2178    if (loaded_issuer_key)
2179    {
2180       EVP_PKEY_free(loaded_issuer_key);
2181    }
2182    if (subject_name)
2183    {
2184       X509_NAME_free(subject_name);
2185    }
2186    if (asn_time)
2187    {
2188       ASN1_TIME_free(asn_time);
2189    }
2190    if (serial_num)
2191    {
2192       BN_free(serial_num);
2193    }
2194    if (serial)
2195    {
2196       ASN1_INTEGER_free(serial);
2197    }
2198    freez(cert_opt.subject_key);
2199    freez(cert_opt.output_file);
2200    freez(key_buf);
2201
2202    return ret;
2203 }
2204
2205
2206 /*********************************************************************
2207  *
2208  * Function    :  ssl_crt_verify_info
2209  *
2210  * Description :  Returns an informational string about the verification
2211  *                status of a certificate.
2212  *
2213  * Parameters  :
2214  *          1  :  buf = Buffer to write to
2215  *          2  :  size = Maximum size of buffer
2216  *          3  :  csp = client state
2217  *
2218  * Returns     :  N/A
2219  *
2220  *********************************************************************/
2221 extern void ssl_crt_verify_info(char *buf, size_t size, struct client_state *csp)
2222 {
2223    strncpy(buf, X509_verify_cert_error_string(csp->server_cert_verification_result), size);
2224    buf[size - 1] = 0;
2225 }
2226
2227
2228 #ifdef FEATURE_GRACEFUL_TERMINATION
2229 /*********************************************************************
2230  *
2231  * Function    :  ssl_release
2232  *
2233  * Description :  Release all SSL resources
2234  *
2235  * Parameters  :
2236  *
2237  * Returns     :  N/A
2238  *
2239  *********************************************************************/
2240 extern void ssl_release(void)
2241 {
2242    if (ssl_inited == 1)
2243    {
2244 #if OPENSSL_VERSION_NUMBER >= 0x1000200fL
2245 #ifndef LIBRESSL_VERSION_NUMBER
2246 #ifndef OPENSSL_NO_COMP
2247       SSL_COMP_free_compression_methods();
2248 #endif
2249 #endif
2250 #endif
2251       CONF_modules_free();
2252       CONF_modules_unload(1);
2253 #ifndef OPENSSL_NO_COMP
2254       COMP_zlib_cleanup();
2255 #endif
2256
2257       ERR_free_strings();
2258       EVP_cleanup();
2259
2260       CRYPTO_cleanup_all_ex_data();
2261    }
2262 }
2263 #endif /* def FEATURE_GRACEFUL_TERMINATION */