uagen: Add OpenBSD architecture 'arm64'
[privoxy.git] / ssl_common.c
1 /*********************************************************************
2  *
3  * File        :  $Source: /cvsroot/ijbswa/current/ssl_common.c,v $
4  *
5  * Purpose     :  File with TLS/SSL extension. Contains methods for
6  *                creating, using and closing TLS/SSL connections that do
7  *                not depend on particular TLS/SSL library.
8  *
9  * Copyright   :  Written by and Copyright (c) 2017 Vaclav Svec. FIT CVUT.
10  *                Copyright (C) 2018-2021 by Fabian Keil <fk@fabiankeil.de>
11  *
12  *                This program is free software; you can redistribute it
13  *                and/or modify it under the terms of the GNU General
14  *                Public License as published by the Free Software
15  *                Foundation; either version 2 of the License, or (at
16  *                your option) any later version.
17  *
18  *                This program is distributed in the hope that it will
19  *                be useful, but WITHOUT ANY WARRANTY; without even the
20  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
21  *                PARTICULAR PURPOSE.  See the GNU General Public
22  *                License for more details.
23  *
24  *                The GNU General Public License should be included with
25  *                this file.  If not, you can view it at
26  *                http://www.gnu.org/copyleft/gpl.html
27  *                or write to the Free Software Foundation, Inc., 59
28  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
29  *
30  *********************************************************************/
31 #include <string.h>
32
33 #include <ctype.h>
34 #include <unistd.h>
35 #include "config.h"
36 #include "project.h"
37 #include "miscutil.h"
38 #include "errlog.h"
39 #include "ssl.h"
40 #include "ssl_common.h"
41
42 /*
43  * Macros for ssl_common.c
44  */
45 #define CERT_SERIAL_NUM_LENGTH           4                 /* Bytes of hash to be used for creating serial number of certificate. Min=2 and max=16 */
46
47 /*********************************************************************
48  *
49  * Function    :  client_use_ssl
50  *
51  * Description :  Tests if client in current client state structure
52  *                should use SSL connection or standard connection.
53  *
54  * Parameters  :
55  *          1  :  csp = Current client state (buffers, headers, etc...)
56  *
57  * Returns     :  If client should use TLS/SSL connection, 1 is returned.
58  *                Otherwise 0 is returned.
59  *
60  *********************************************************************/
61 extern int client_use_ssl(const struct client_state *csp)
62 {
63    return csp->http->client_ssl;
64 }
65
66
67 /*********************************************************************
68  *
69  * Function    :  server_use_ssl
70  *
71  * Description :  Tests if server in current client state structure
72  *                should use SSL connection or standard connection.
73  *
74  * Parameters  :
75  *          1  :  csp = Current client state (buffers, headers, etc...)
76  *
77  * Returns     :  If server should use TLS/SSL connection, 1 is returned.
78  *                Otherwise 0 is returned.
79  *
80  *********************************************************************/
81 extern int server_use_ssl(const struct client_state *csp)
82 {
83    return csp->http->server_ssl;
84 }
85
86
87 /*********************************************************************
88  *
89  * Function    :  ssl_send_data_delayed
90  *
91  * Description :  Sends the contents of buf (for n bytes) to given SSL
92  *                connection, optionally delaying the operation.
93  *
94  * Parameters  :
95  *          1  :  ssl_attr = SSL context to send data to
96  *          2  :  buf = Pointer to data to be sent
97  *          3  :  len = Length of data to be sent to the SSL context
98  *          4  :  delay = Delay in milliseconds.
99  *
100  * Returns     :  0 on success (entire buffer sent).
101  *                nonzero on error.
102  *
103  *********************************************************************/
104 extern int ssl_send_data_delayed(struct ssl_attr* ssl_attr,
105                                  const unsigned char *buf, size_t len,
106                                  unsigned int delay)
107 {
108    size_t i = 0;
109
110    if (delay == 0)
111    {
112       if (ssl_send_data(ssl_attr, buf, len) < 0)
113       {
114          return -1;
115       }
116       else
117       {
118          return 0;
119       }
120    }
121
122    while (i < len)
123    {
124       size_t write_length;
125       enum { MAX_WRITE_LENGTH = 10 };
126
127       if ((i + MAX_WRITE_LENGTH) > len)
128       {
129          write_length = len - i;
130       }
131       else
132       {
133          write_length = MAX_WRITE_LENGTH;
134       }
135
136       privoxy_millisleep(delay);
137
138       if (ssl_send_data(ssl_attr, buf + i, write_length) < 0)
139       {
140          return -1;
141       }
142       i += write_length;
143    }
144
145    return 0;
146
147 }
148
149
150 /*********************************************************************
151  *
152  * Function    :  ssl_flush_socket
153  *
154  * Description :  Send any pending "buffered" content with given
155  *                SSL connection. Alternative to function flush_socket.
156  *
157  * Parameters  :
158  *          1  :  ssl_attr = SSL context to send buffer to
159  *          2  :  iob = The I/O buffer to flush, usually csp->iob.
160  *
161  * Returns     :  On success, the number of bytes send are returned (zero
162  *                indicates nothing was sent).  On error, -1 is returned.
163  *
164  *********************************************************************/
165 extern long ssl_flush_socket(struct ssl_attr *ssl_attr, struct iob *iob)
166 {
167    /* Computing length of buffer part to send */
168    long len = iob->eod - iob->cur;
169
170    if (len <= 0)
171    {
172       return(0);
173    }
174
175    /* Sending data to given SSl context */
176    if (ssl_send_data(ssl_attr, (const unsigned char *)iob->cur, (size_t)len) < 0)
177    {
178       return -1;
179    }
180    iob->eod = iob->cur = iob->buf;
181    return(len);
182 }
183
184
185 /*********************************************************************
186  *
187  * Function    :  close_client_and_server_ssl_connections
188  *
189  * Description :  Checks if client or server should use secured
190  *                connection over SSL and if so, closes all of them.
191  *
192  * Parameters  :
193  *          1  :  csp = Current client state (buffers, headers, etc...)
194  *
195  * Returns     :  N/A
196  *
197  *********************************************************************/
198 extern void close_client_and_server_ssl_connections(struct client_state *csp)
199 {
200    if (client_use_ssl(csp) == 1)
201    {
202       close_client_ssl_connection(csp);
203    }
204    if (server_use_ssl(csp) == 1)
205    {
206       close_server_ssl_connection(csp);
207    }
208 }
209
210
211 /*********************************************************************
212  *
213  * Function    :  tunnel_established_successfully
214  *
215  * Description :  Check if parent proxy server response contains
216  *                information about successfully created connection with
217  *                destination server. (HTTP/... 2xx ...)
218  *
219  * Parameters  :
220  *          1  :  server_response = Buffer with parent proxy server response
221  *          2  :  response_len = Length of server_response
222  *
223  * Returns     :  1 => Connection created successfully
224  *                0 => Connection wasn't created successfully
225  *
226  *********************************************************************/
227 extern int tunnel_established_successfully(const char *server_response,
228    unsigned int response_len)
229 {
230    unsigned int pos = 0;
231
232    if (server_response == NULL)
233    {
234       return 0;
235    }
236
237    /* Tests if "HTTP/" string is at the begin of received response */
238    if (strncmp(server_response, "HTTP/", 5) != 0)
239    {
240       return 0;
241    }
242
243    for (pos = 0; pos < response_len; pos++)
244    {
245       if (server_response[pos] == ' ')
246       {
247          break;
248       }
249    }
250
251    /*
252     * response_len -3 because of buffer end, response structure and 200 code.
253     * There must be at least 3 chars after space.
254     * End of buffer: ... 2xx'\0'
255     *             pos = |
256     */
257    if (pos >= (response_len - 3))
258    {
259       return 0;
260    }
261
262    /* Test HTTP status code */
263    if (server_response[pos + 1] != '2')
264    {
265       return 0;
266    }
267
268    return 1;
269 }
270
271
272 /*********************************************************************
273  *
274  * Function    :  free_certificate_chain
275  *
276  * Description :  Frees certificates linked list. This linked list is
277  *                used to save information about certificates in
278  *                trusted chain.
279  *
280  * Parameters  :
281  *          1  :  csp = Current client state (buffers, headers, etc...)
282  *
283  * Returns     :  N/A
284  *
285  *********************************************************************/
286 extern void free_certificate_chain(struct client_state *csp)
287 {
288    struct certs_chain *cert = csp->server_certs_chain.next;
289
290    /* Cleaning buffers */
291    memset(csp->server_certs_chain.info_buf, 0,
292       sizeof(csp->server_certs_chain.info_buf));
293    freez(csp->server_certs_chain.file_buf);
294
295    csp->server_certs_chain.next = NULL;
296
297    /* Freeing memory in whole linked list */
298    while (cert != NULL)
299    {
300       struct certs_chain *cert_for_free = cert;
301       cert = cert->next;
302
303       /* Cleaning buffers */
304       memset(cert_for_free->info_buf, 0, sizeof(cert_for_free->info_buf));
305       freez(cert_for_free->file_buf);
306
307       freez(cert_for_free);
308    }
309 }
310
311
312 /*********************************************************************
313  *
314  * Function    :  ssl_send_certificate_error
315  *
316  * Description :  Sends info about invalid server certificate to client.
317  *                Sent message is including all trusted chain certificates,
318  *                that can be downloaded in web browser.
319  *
320  * Parameters  :
321  *          1  :  csp = Current client state (buffers, headers, etc...)
322  *
323  * Returns     :  N/A
324  *
325  *********************************************************************/
326 extern void ssl_send_certificate_error(struct client_state *csp)
327 {
328    struct ssl_attr *ssl_attr = &csp->ssl_client_attr;
329    size_t message_len = 0;
330    int ret = 0;
331    struct certs_chain *cert = NULL;
332    const size_t head_length = 63;
333
334    /* Header of message with certificate information */
335    const char message_begin[] =
336       "HTTP/1.1 403 Certificate validation failed\r\n"
337       "Content-Type: text/html\r\n"
338       "Connection: close\r\n\r\n"
339       "<!DOCTYPE html>\n"
340       "<html><head><title>Server certificate verification failed</title></head>\n"
341       "<body><h1>Server certificate verification failed</h1>\n"
342       "<p><a href=\"https://" CGI_SITE_2_HOST "/\">Privoxy</a> was unable "
343       "to securely connect to the destination server.</p>"
344       "<p>Reason: ";
345    const char message_end[] = "</body></html>\n";
346    char reason[INVALID_CERT_INFO_BUF_SIZE];
347    memset(reason, 0, sizeof(reason));
348
349    /* Get verification message from verification return code */
350    ssl_crt_verify_info(reason, sizeof(reason), csp);
351
352    /*
353     * Computing total length of message with all certificates inside
354     */
355    message_len = strlen(message_begin) + strlen(message_end)
356                  + strlen(reason) + strlen("</p>") + 1;
357
358    cert = &(csp->server_certs_chain);
359    while (cert->next != NULL)
360    {
361       size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1;
362
363       message_len += strlen(cert->info_buf) + strlen("<pre></pre>\n")
364                      +  base64_len + strlen("<a href=\"data:application"
365                         "/x-x509-ca-cert;base64,\">Download certificate</a>");
366       cert = cert->next;
367    }
368
369    /*
370     * Joining all blocks in one long message
371     */
372    char message[message_len];
373    memset(message, 0, message_len);
374
375    strlcpy(message, message_begin, message_len);
376    strlcat(message, reason       , message_len);
377    strlcat(message, "</p>"       , message_len);
378
379    cert = &(csp->server_certs_chain);
380    while (cert->next != NULL)
381    {
382       size_t olen = 0;
383       size_t base64_len = 4 * ((strlen(cert->file_buf) + 2) / 3) + 1; /* +1 for terminating null*/
384       char base64_buf[base64_len];
385       memset(base64_buf, 0, base64_len);
386
387       /* Encoding certificate into base64 code */
388       ret = ssl_base64_encode((unsigned char*)base64_buf,
389                base64_len, &olen, (const unsigned char*)cert->file_buf,
390                strlen(cert->file_buf));
391       if (ret != 0)
392       {
393          log_error(LOG_LEVEL_ERROR,
394             "Encoding to base64 failed, buffer is to small");
395       }
396
397       strlcat(message, "<pre>",        message_len);
398       strlcat(message, cert->info_buf, message_len);
399       strlcat(message, "</pre>\n",     message_len);
400
401       if (ret == 0)
402       {
403          strlcat(message, "<a href=\"data:application/x-x509-ca-cert;base64,",
404             message_len);
405          strlcat(message, base64_buf, message_len);
406          strlcat(message, "\">Download certificate</a>", message_len);
407       }
408
409       cert = cert->next;
410    }
411    strlcat(message, message_end, message_len);
412
413    if (0 == strcmpic(csp->http->gpc, "HEAD"))
414    {
415       /* Cut off body */
416       char *header_end = strstr(message, "\r\n\r\n");
417       if (header_end != NULL)
418       {
419          header_end[3] = '\0';
420       }
421    }
422
423    /*
424     * Sending final message to client
425     */
426    (void)ssl_send_data(ssl_attr, (const unsigned char *)message, strlen(message));
427
428    free_certificate_chain(csp);
429
430    log_error(LOG_LEVEL_CRUNCH, "Certificate error: %s: https://%s%s",
431       reason, csp->http->hostport, csp->http->path);
432    log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" 403 %lu",
433       csp->ip_addr_str, csp->http->gpc, csp->http->hostport, csp->http->path,
434       csp->http->version, message_len-head_length);
435
436 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
437    csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
438    csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
439 #endif
440 }
441
442
443 /*********************************************************************
444  *
445  * Function    :  file_exists
446  *
447  * Description :  Tests if file exists and is readable.
448  *
449  * Parameters  :
450  *          1  :  path = Path to tested file.
451  *
452  * Returns     :  1 => File exists and is readable.
453  *                0 => File doesn't exist or is not readable.
454  *
455  *********************************************************************/
456 extern int file_exists(const char *path)
457 {
458    FILE *f;
459    if ((f = fopen(path, "r")) != NULL)
460    {
461       fclose(f);
462       return 1;
463    }
464
465    return 0;
466 }
467
468
469 /*********************************************************************
470  *
471  * Function    :  make_certs_path
472  *
473  * Description : Creates path to file from three pieces. This function
474  *               takes parameters and puts them in one new mallocated
475  *               char * in correct order. Returned variable must be freed
476  *               by caller. This function is mainly used for creating
477  *               paths of certificates and keys files.
478  *
479  * Parameters  :
480  *          1  :  conf_dir  = Name/path of directory where is the file.
481  *                            '.' can be used for current directory.
482  *          2  :  file_name = Name of file in conf_dir without suffix.
483  *          3  :  suffix    = Suffix of given file_name.
484  *
485  * Returns     :  path => Path was built up successfully
486  *                NULL => Path can't be built up
487  *
488  *********************************************************************/
489 extern char *make_certs_path(const char *conf_dir, const char *file_name,
490    const char *suffix)
491 {
492    /* Test if all given parameters are valid */
493    if (conf_dir == NULL || *conf_dir == '\0' || file_name == NULL ||
494       *file_name == '\0' || suffix == NULL || *suffix == '\0')
495    {
496       log_error(LOG_LEVEL_ERROR,
497          "make_certs_path failed: bad input parameters");
498       return NULL;
499    }
500
501    char *path = NULL;
502    size_t path_size = strlen(conf_dir)
503       + strlen(file_name) + strlen(suffix) + 2;
504
505    /* Setting delimiter and editing path length */
506 #if defined(_WIN32)
507    char delim[] = "\\";
508    path_size += 1;
509 #else /* ifndef _WIN32 */
510    char delim[] = "/";
511 #endif /* ifndef _WIN32 */
512
513    /*
514     * Building up path from many parts
515     */
516 #if defined(unix)
517    if (*conf_dir != '/' && basedir && *basedir)
518    {
519       /*
520        * Replacing conf_dir with basedir. This new variable contains
521        * absolute path to cwd.
522        */
523       path_size += strlen(basedir) + 2;
524       path = zalloc_or_die(path_size);
525
526       strlcpy(path, basedir,   path_size);
527       strlcat(path, delim,     path_size);
528       strlcat(path, conf_dir,  path_size);
529       strlcat(path, delim,     path_size);
530       strlcat(path, file_name, path_size);
531       strlcat(path, suffix,    path_size);
532    }
533    else
534 #endif /* defined unix */
535    {
536       path = zalloc_or_die(path_size);
537
538       strlcpy(path, conf_dir,  path_size);
539       strlcat(path, delim,     path_size);
540       strlcat(path, file_name, path_size);
541       strlcat(path, suffix,    path_size);
542    }
543
544    return path;
545 }
546
547
548 /*********************************************************************
549  *
550  * Function    :  get_certificate_serial
551  *
552  * Description :  Computes serial number for new certificate from host
553  *                name hash. This hash must be already saved in csp
554  *                structure.
555  *
556  * Parameters  :
557  *          1  :  csp = Current client state (buffers, headers, etc...)
558  *
559  * Returns     :  Serial number for new certificate
560  *
561  *********************************************************************/
562 extern unsigned long get_certificate_serial(struct client_state *csp)
563 {
564    unsigned long exp    = 1;
565    unsigned long serial = 0;
566
567    int i = CERT_SERIAL_NUM_LENGTH;
568
569    for (; i >= 0; i--)
570    {
571       serial += exp * (unsigned)csp->http->hash_of_host[i];
572       exp *= 256;
573    }
574    return serial;
575 }
576
577
578 /*********************************************************************
579  *
580  * Function    :  generate_certificate_valid_date
581  *
582  * Description :  Turns a time_t into the format expected by mbedTLS.
583  *
584  * Parameters  :
585  *          1  :  time_spec = The timestamp to convert
586  *          2  :  buffer = The buffer to write the date to
587  *          3  :  buffer_size = The size of the buffer
588  *          4  :  fmt = format
589  *
590  * Returns     :   0 => The conversion worked
591  *                 1 => The conversion failed
592  *
593  *********************************************************************/
594 static int generate_certificate_valid_date(time_t time_spec, char *buffer,
595                                            size_t buffer_size, const char *fmt)
596 {
597    struct tm valid_date;
598    struct tm *timeptr;
599    size_t ret;
600
601    timeptr = privoxy_gmtime_r(&time_spec, &valid_date);
602    if (NULL == timeptr)
603    {
604       return 1;
605    }
606
607    ret = strftime(buffer, buffer_size, fmt, timeptr);
608    if (ret <= 0)
609    {
610       return 1;
611    }
612
613    return 0;
614
615 }
616
617
618 /*********************************************************************
619  *
620  * Function    :  get_certificate_valid_from_date
621  *
622  * Description :  Generates a "valid from" date in the format
623  *                expected by mbedTLS.
624  *
625  * Parameters  :
626  *          1  :  buffer = The buffer to write the date to
627  *          2  :  buffer_size = The size of the buffer
628  *          3  :  fmt = format
629  *
630  * Returns     :   0 => The generation worked
631  *                 1 => The generation failed
632  *
633  *********************************************************************/
634 extern int get_certificate_valid_from_date(char *buffer, size_t buffer_size, const char *fmt)
635 {
636    time_t time_spec;
637
638    time_spec = time(NULL);
639    /* 1 month in the past */
640    time_spec -= 30 * 24 * 60 * 60;
641
642    return generate_certificate_valid_date(time_spec, buffer, buffer_size, fmt);
643
644 }
645
646
647 /*********************************************************************
648  *
649  * Function    :  get_certificate_valid_to_date
650  *
651  * Description :  Generates a "valid to" date in the format
652  *                expected by mbedTLS.
653  *
654  * Parameters  :
655  *          1  :  buffer = The buffer to write the date to
656  *          2  :  buffer_size = The size of the buffer
657  *          3  :  fmt = format
658  *
659  * Returns     :   0 => The generation worked
660  *                 1 => The generation failed
661  *
662  *********************************************************************/
663 extern int get_certificate_valid_to_date(char *buffer, size_t buffer_size, const char *fmt)
664 {
665    time_t time_spec;
666
667    time_spec = time(NULL);
668    /* Three months in the future */
669    time_spec += 90 * 24 * 60 * 60;
670
671    return generate_certificate_valid_date(time_spec, buffer, buffer_size, fmt);
672
673 }
674
675
676 /*********************************************************************
677  *
678  * Function    :  host_is_ip_address
679  *
680  * Description :  Checks whether or not a host is specified by
681  *                IP address. Does not actually validate the
682  *                address.
683  *
684  * Parameters  :
685  *          1  :  host = The host name to check
686  *
687  * Returns     :   1 => Yes
688  *                 0 => No
689  *
690  *********************************************************************/
691 extern int host_is_ip_address(const char *host)
692 {
693    const char *p;
694
695    if (NULL != strstr(host, ":"))
696    {
697       /* Assume an IPv6 address. */
698       return 1;
699    }
700
701    for (p = host; *p; p++)
702    {
703       if ((*p != '.') && !privoxy_isdigit(*p))
704       {
705          /* Not a dot or digit so it can't be an IPv4 address. */
706          return 0;
707       }
708    }
709
710    /*
711     * Host only consists of dots and digits so
712     * assume that is an IPv4 address.
713     */
714    return 1;
715
716 }
717
718
719 /*********************************************************************
720  *
721  * Function    :  enforce_sane_certificate_state
722  *
723  * Description :  Makes sure the certificate state is sane.
724  *
725  * Parameters  :
726  *          1  :  certificate = Path to the potentionally existing certifcate.
727  *          2  :  key = Path to the potentionally existing key.
728  *
729  * Returns     :   -1 => Error
730  *                 0 => Certificate state is sane
731  *
732  *********************************************************************/
733 extern int enforce_sane_certificate_state(const char *certificate, const char *key)
734 {
735    const int certificate_exists = file_exists(certificate);
736    const int key_exists = file_exists(key);
737
738    if (!certificate_exists && key_exists)
739    {
740       log_error(LOG_LEVEL_ERROR,
741          "A website key already exists but there's no matching certificate. "
742          "Removing %s before creating a new key and certificate.", key);
743       if (unlink(key))
744       {
745          log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E", key);
746
747          return -1;
748       }
749    }
750    if (certificate_exists && !key_exists)
751    {
752       log_error(LOG_LEVEL_ERROR,
753          "A certificate exists but there's no matching key. "
754          "Removing %s before creating a new key and certificate.", certificate);
755       if (unlink(certificate))
756       {
757          log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E", certificate);
758
759          return -1;
760       }
761    }
762
763    return 0;
764
765 }