blob: 43fe01d3bd893b6aeb1e629e214a6f68fdb2fde2 [file] [log] [blame]
William Lallemand03c331c2020-05-13 10:10:01 +02001/*
2 *
3 * Copyright (C) 2020 HAProxy Technologies, William Lallemand <wlallemand@haproxy.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <unistd.h>
20
21#include <sys/stat.h>
22#include <sys/types.h>
23
Willy Tarreau8d366972020-05-27 16:10:29 +020024#include <haproxy/base64.h>
Willy Tarreauf1d32c42020-06-04 21:07:02 +020025#include <haproxy/channel.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020026#include <haproxy/cli.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020027#include <haproxy/errors.h>
Willy Tarreau47d7f902020-06-04 14:25:47 +020028#include <haproxy/ssl_ckch.h>
Willy Tarreau209108d2020-06-04 20:30:20 +020029#include <haproxy/ssl_sock.h>
Willy Tarreaub2bd8652020-06-04 14:21:22 +020030#include <haproxy/ssl_utils.h>
Willy Tarreau5e539c92020-06-04 20:45:39 +020031#include <haproxy/stream_interface.h>
Willy Tarreau48fbcae2020-06-03 18:09:46 +020032#include <haproxy/tools.h>
William Lallemand03c331c2020-05-13 10:10:01 +020033
Willy Tarreau8d2b7772020-05-27 10:58:19 +020034#include <import/ebsttree.h>
William Lallemand03c331c2020-05-13 10:10:01 +020035
William Lallemandda8584c2020-05-14 10:14:37 +020036/* Uncommitted CKCH transaction */
37
38static struct {
39 struct ckch_store *new_ckchs;
40 struct ckch_store *old_ckchs;
41 char *path;
42} ckchs_transaction;
43
44
William Lallemand03c331c2020-05-13 10:10:01 +020045
46/******************** cert_key_and_chain functions *************************
47 * These are the functions that fills a cert_key_and_chain structure. For the
48 * functions filling a SSL_CTX from a cert_key_and_chain, see ssl_sock.c
49 */
50
51/*
52 * Try to parse Signed Certificate Timestamp List structure. This function
53 * makes only basic test if the data seems like SCTL. No signature validation
54 * is performed.
55 */
56static int ssl_sock_parse_sctl(struct buffer *sctl)
57{
58 int ret = 1;
59 int len, pos, sct_len;
60 unsigned char *data;
61
62 if (sctl->data < 2)
63 goto out;
64
65 data = (unsigned char *) sctl->area;
66 len = (data[0] << 8) | data[1];
67
68 if (len + 2 != sctl->data)
69 goto out;
70
71 data = data + 2;
72 pos = 0;
73 while (pos < len) {
74 if (len - pos < 2)
75 goto out;
76
77 sct_len = (data[pos] << 8) | data[pos + 1];
78 if (pos + sct_len + 2 > len)
79 goto out;
80
81 pos += sct_len + 2;
82 }
83
84 ret = 0;
85
86out:
87 return ret;
88}
89
90/* Try to load a sctl from a buffer <buf> if not NULL, or read the file <sctl_path>
91 * It fills the ckch->sctl buffer
92 * return 0 on success or != 0 on failure */
93int ssl_sock_load_sctl_from_file(const char *sctl_path, char *buf, struct cert_key_and_chain *ckch, char **err)
94{
95 int fd = -1;
96 int r = 0;
97 int ret = 1;
98 struct buffer tmp;
99 struct buffer *src;
100 struct buffer *sctl;
101
102 if (buf) {
103 tmp.area = buf;
104 tmp.data = strlen(buf);
105 tmp.size = tmp.data + 1;
106 src = &tmp;
107 } else {
108 fd = open(sctl_path, O_RDONLY);
109 if (fd == -1)
110 goto end;
111
112 trash.data = 0;
113 while (trash.data < trash.size) {
114 r = read(fd, trash.area + trash.data, trash.size - trash.data);
115 if (r < 0) {
116 if (errno == EINTR)
117 continue;
118 goto end;
119 }
120 else if (r == 0) {
121 break;
122 }
123 trash.data += r;
124 }
125 src = &trash;
126 }
127
128 ret = ssl_sock_parse_sctl(src);
129 if (ret)
130 goto end;
131
132 sctl = calloc(1, sizeof(*sctl));
133 if (!chunk_dup(sctl, src)) {
134 free(sctl);
135 sctl = NULL;
136 goto end;
137 }
138 /* no error, fill ckch with new context, old context must be free */
139 if (ckch->sctl) {
140 free(ckch->sctl->area);
141 ckch->sctl->area = NULL;
142 free(ckch->sctl);
143 }
144 ckch->sctl = sctl;
145 ret = 0;
146end:
147 if (fd != -1)
148 close(fd);
149
150 return ret;
151}
152
153#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
154/*
155 * This function load the OCSP Resonse in DER format contained in file at
156 * path 'ocsp_path' or base64 in a buffer <buf>
157 *
158 * Returns 0 on success, 1 in error case.
159 */
160int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, char *buf, struct cert_key_and_chain *ckch, char **err)
161{
162 int fd = -1;
163 int r = 0;
164 int ret = 1;
165 struct buffer *ocsp_response;
166 struct buffer *src = NULL;
167
168 if (buf) {
169 int i, j;
170 /* if it's from a buffer it will be base64 */
171
172 /* remove \r and \n from the payload */
173 for (i = 0, j = 0; buf[i]; i++) {
174 if (buf[i] == '\r' || buf[i] == '\n')
175 continue;
176 buf[j++] = buf[i];
177 }
178 buf[j] = 0;
179
180 ret = base64dec(buf, j, trash.area, trash.size);
181 if (ret < 0) {
182 memprintf(err, "Error reading OCSP response in base64 format");
183 goto end;
184 }
185 trash.data = ret;
186 src = &trash;
187 } else {
188 fd = open(ocsp_path, O_RDONLY);
189 if (fd == -1) {
190 memprintf(err, "Error opening OCSP response file");
191 goto end;
192 }
193
194 trash.data = 0;
195 while (trash.data < trash.size) {
196 r = read(fd, trash.area + trash.data, trash.size - trash.data);
197 if (r < 0) {
198 if (errno == EINTR)
199 continue;
200
201 memprintf(err, "Error reading OCSP response from file");
202 goto end;
203 }
204 else if (r == 0) {
205 break;
206 }
207 trash.data += r;
208 }
209 close(fd);
210 fd = -1;
211 src = &trash;
212 }
213
214 ocsp_response = calloc(1, sizeof(*ocsp_response));
215 if (!chunk_dup(ocsp_response, src)) {
216 free(ocsp_response);
217 ocsp_response = NULL;
218 goto end;
219 }
220 /* no error, fill ckch with new context, old context must be free */
221 if (ckch->ocsp_response) {
222 free(ckch->ocsp_response->area);
223 ckch->ocsp_response->area = NULL;
224 free(ckch->ocsp_response);
225 }
226 ckch->ocsp_response = ocsp_response;
227 ret = 0;
228end:
229 if (fd != -1)
230 close(fd);
231
232 return ret;
233}
234#endif
235
236/*
237 * Try to load in a ckch every files related to a ckch.
238 * (PEM, sctl, ocsp, issuer etc.)
239 *
240 * This function is only used to load files during the configuration parsing,
241 * it is not used with the CLI.
242 *
243 * This allows us to carry the contents of the file without having to read the
244 * file multiple times. The caller must call
245 * ssl_sock_free_cert_key_and_chain_contents.
246 *
247 * returns:
248 * 0 on Success
249 * 1 on SSL Failure
250 */
251int ssl_sock_load_files_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
252{
253 int ret = 1;
254
255 /* try to load the PEM */
256 if (ssl_sock_load_pem_into_ckch(path, NULL, ckch , err) != 0) {
257 goto end;
258 }
259
260 /* try to load an external private key if it wasn't in the PEM */
261 if ((ckch->key == NULL) && (global_ssl.extra_files & SSL_GF_KEY)) {
262 char fp[MAXPATHLEN+1];
263 struct stat st;
264
265 snprintf(fp, MAXPATHLEN+1, "%s.key", path);
266 if (stat(fp, &st) == 0) {
267 if (ssl_sock_load_key_into_ckch(fp, NULL, ckch, err)) {
268 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
269 err && *err ? *err : "", fp);
270 goto end;
271 }
272 }
273 }
274
275 if (ckch->key == NULL) {
276 memprintf(err, "%sNo Private Key found in '%s' or '%s.key'.\n", err && *err ? *err : "", path, path);
277 goto end;
278 }
279
280 if (!X509_check_private_key(ckch->cert, ckch->key)) {
281 memprintf(err, "%sinconsistencies between private key and certificate loaded '%s'.\n",
282 err && *err ? *err : "", path);
283 goto end;
284 }
285
286#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
287 /* try to load the sctl file */
288 if (global_ssl.extra_files & SSL_GF_SCTL) {
289 char fp[MAXPATHLEN+1];
290 struct stat st;
291
292 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
293 if (stat(fp, &st) == 0) {
294 if (ssl_sock_load_sctl_from_file(fp, NULL, ckch, err)) {
295 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
296 err && *err ? *err : "", fp);
297 ret = 1;
298 goto end;
299 }
300 }
301 }
302#endif
303
304 /* try to load an ocsp response file */
305 if (global_ssl.extra_files & SSL_GF_OCSP) {
306 char fp[MAXPATHLEN+1];
307 struct stat st;
308
309 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
310 if (stat(fp, &st) == 0) {
311 if (ssl_sock_load_ocsp_response_from_file(fp, NULL, ckch, err)) {
312 ret = 1;
313 goto end;
314 }
315 }
316 }
317
318#ifndef OPENSSL_IS_BORINGSSL /* Useless for BoringSSL */
319 if (ckch->ocsp_response && (global_ssl.extra_files & SSL_GF_OCSP_ISSUER)) {
320 /* if no issuer was found, try to load an issuer from the .issuer */
321 if (!ckch->ocsp_issuer) {
322 struct stat st;
323 char fp[MAXPATHLEN+1];
324
325 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
326 if (stat(fp, &st) == 0) {
327 if (ssl_sock_load_issuer_file_into_ckch(fp, NULL, ckch, err)) {
328 ret = 1;
329 goto end;
330 }
331
332 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
333 memprintf(err, "%s '%s' is not an issuer'.\n",
334 err && *err ? *err : "", fp);
335 ret = 1;
336 goto end;
337 }
338 }
339 }
340 }
341#endif
342
343 ret = 0;
344
345end:
346
347 ERR_clear_error();
348
349 /* Something went wrong in one of the reads */
350 if (ret != 0)
351 ssl_sock_free_cert_key_and_chain_contents(ckch);
352
353 return ret;
354}
355
356/*
357 * Try to load a private key file from a <path> or a buffer <buf>
358 *
359 * If it failed you should not attempt to use the ckch but free it.
360 *
361 * Return 0 on success or != 0 on failure
362 */
363int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
364{
365 BIO *in = NULL;
366 int ret = 1;
367 EVP_PKEY *key = NULL;
368
369 if (buf) {
370 /* reading from a buffer */
371 in = BIO_new_mem_buf(buf, -1);
372 if (in == NULL) {
373 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
374 goto end;
375 }
376
377 } else {
378 /* reading from a file */
379 in = BIO_new(BIO_s_file());
380 if (in == NULL)
381 goto end;
382
383 if (BIO_read_filename(in, path) <= 0)
384 goto end;
385 }
386
387 /* Read Private Key */
388 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
389 if (key == NULL) {
390 memprintf(err, "%sunable to load private key from file '%s'.\n",
391 err && *err ? *err : "", path);
392 goto end;
393 }
394
395 ret = 0;
396
397 SWAP(ckch->key, key);
398
399end:
400
401 ERR_clear_error();
402 if (in)
403 BIO_free(in);
404 if (key)
405 EVP_PKEY_free(key);
406
407 return ret;
408}
409
410/*
411 * Try to load a PEM file from a <path> or a buffer <buf>
412 * The PEM must contain at least a Certificate,
413 * It could contain a DH, a certificate chain and a PrivateKey.
414 *
415 * If it failed you should not attempt to use the ckch but free it.
416 *
417 * Return 0 on success or != 0 on failure
418 */
419int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch , char **err)
420{
421 BIO *in = NULL;
422 int ret = 1;
423 X509 *ca;
424 X509 *cert = NULL;
425 EVP_PKEY *key = NULL;
426 DH *dh = NULL;
427 STACK_OF(X509) *chain = NULL;
428
429 if (buf) {
430 /* reading from a buffer */
431 in = BIO_new_mem_buf(buf, -1);
432 if (in == NULL) {
433 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
434 goto end;
435 }
436
437 } else {
438 /* reading from a file */
439 in = BIO_new(BIO_s_file());
440 if (in == NULL) {
441 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
442 goto end;
443 }
444
445 if (BIO_read_filename(in, path) <= 0) {
446 memprintf(err, "%scannot open the file '%s'.\n",
447 err && *err ? *err : "", path);
448 goto end;
449 }
450 }
451
452 /* Read Private Key */
453 key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
454 /* no need to check for errors here, because the private key could be loaded later */
455
456#ifndef OPENSSL_NO_DH
457 /* Seek back to beginning of file */
458 if (BIO_reset(in) == -1) {
459 memprintf(err, "%san error occurred while reading the file '%s'.\n",
460 err && *err ? *err : "", path);
461 goto end;
462 }
463
464 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
465 /* no need to return an error there, dh is not mandatory */
466#endif
467
468 /* Seek back to beginning of file */
469 if (BIO_reset(in) == -1) {
470 memprintf(err, "%san error occurred while reading the file '%s'.\n",
471 err && *err ? *err : "", path);
472 goto end;
473 }
474
475 /* Read Certificate */
476 cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
477 if (cert == NULL) {
478 memprintf(err, "%sunable to load certificate from file '%s'.\n",
479 err && *err ? *err : "", path);
480 goto end;
481 }
482
483 /* Look for a Certificate Chain */
484 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
485 if (chain == NULL)
486 chain = sk_X509_new_null();
487 if (!sk_X509_push(chain, ca)) {
488 X509_free(ca);
489 goto end;
490 }
491 }
492
493 ret = ERR_get_error();
494 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
495 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
496 err && *err ? *err : "", path);
497 goto end;
498 }
499
500 /* once it loaded the PEM, it should remove everything else in the ckch */
501 if (ckch->ocsp_response) {
502 free(ckch->ocsp_response->area);
503 ckch->ocsp_response->area = NULL;
504 free(ckch->ocsp_response);
505 ckch->ocsp_response = NULL;
506 }
507
508 if (ckch->sctl) {
509 free(ckch->sctl->area);
510 ckch->sctl->area = NULL;
511 free(ckch->sctl);
512 ckch->sctl = NULL;
513 }
514
515 if (ckch->ocsp_issuer) {
516 X509_free(ckch->ocsp_issuer);
517 ckch->ocsp_issuer = NULL;
518 }
519
520 /* no error, fill ckch with new context, old context will be free at end: */
521 SWAP(ckch->key, key);
522 SWAP(ckch->dh, dh);
523 SWAP(ckch->cert, cert);
524 SWAP(ckch->chain, chain);
525
526 ret = 0;
527
528end:
529
530 ERR_clear_error();
531 if (in)
532 BIO_free(in);
533 if (key)
534 EVP_PKEY_free(key);
535 if (dh)
536 DH_free(dh);
537 if (cert)
538 X509_free(cert);
539 if (chain)
540 sk_X509_pop_free(chain, X509_free);
541
542 return ret;
543}
544
545/* Frees the contents of a cert_key_and_chain
546 */
547void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
548{
549 if (!ckch)
550 return;
551
552 /* Free the certificate and set pointer to NULL */
553 if (ckch->cert)
554 X509_free(ckch->cert);
555 ckch->cert = NULL;
556
557 /* Free the key and set pointer to NULL */
558 if (ckch->key)
559 EVP_PKEY_free(ckch->key);
560 ckch->key = NULL;
561
562 /* Free each certificate in the chain */
563 if (ckch->chain)
564 sk_X509_pop_free(ckch->chain, X509_free);
565 ckch->chain = NULL;
566
567 if (ckch->dh)
568 DH_free(ckch->dh);
569 ckch->dh = NULL;
570
571 if (ckch->sctl) {
572 free(ckch->sctl->area);
573 ckch->sctl->area = NULL;
574 free(ckch->sctl);
575 ckch->sctl = NULL;
576 }
577
578 if (ckch->ocsp_response) {
579 free(ckch->ocsp_response->area);
580 ckch->ocsp_response->area = NULL;
581 free(ckch->ocsp_response);
582 ckch->ocsp_response = NULL;
583 }
584
585 if (ckch->ocsp_issuer)
586 X509_free(ckch->ocsp_issuer);
587 ckch->ocsp_issuer = NULL;
588}
589
590/*
591 *
592 * This function copy a cert_key_and_chain in memory
593 *
594 * It's used to try to apply changes on a ckch before committing them, because
595 * most of the time it's not possible to revert those changes
596 *
597 * Return a the dst or NULL
598 */
599struct cert_key_and_chain *ssl_sock_copy_cert_key_and_chain(struct cert_key_and_chain *src,
600 struct cert_key_and_chain *dst)
601{
602 if (src->cert) {
603 dst->cert = src->cert;
604 X509_up_ref(src->cert);
605 }
606
607 if (src->key) {
608 dst->key = src->key;
609 EVP_PKEY_up_ref(src->key);
610 }
611
612 if (src->chain) {
613 dst->chain = X509_chain_up_ref(src->chain);
614 }
615
616 if (src->dh) {
617 DH_up_ref(src->dh);
618 dst->dh = src->dh;
619 }
620
621 if (src->sctl) {
622 struct buffer *sctl;
623
624 sctl = calloc(1, sizeof(*sctl));
625 if (!chunk_dup(sctl, src->sctl)) {
626 free(sctl);
627 sctl = NULL;
628 goto error;
629 }
630 dst->sctl = sctl;
631 }
632
633 if (src->ocsp_response) {
634 struct buffer *ocsp_response;
635
636 ocsp_response = calloc(1, sizeof(*ocsp_response));
637 if (!chunk_dup(ocsp_response, src->ocsp_response)) {
638 free(ocsp_response);
639 ocsp_response = NULL;
640 goto error;
641 }
642 dst->ocsp_response = ocsp_response;
643 }
644
645 if (src->ocsp_issuer) {
646 X509_up_ref(src->ocsp_issuer);
647 dst->ocsp_issuer = src->ocsp_issuer;
648 }
649
650 return dst;
651
652error:
653
654 /* free everything */
655 ssl_sock_free_cert_key_and_chain_contents(dst);
656
657 return NULL;
658}
659
660/*
661 * return 0 on success or != 0 on failure
662 */
663int ssl_sock_load_issuer_file_into_ckch(const char *path, char *buf, struct cert_key_and_chain *ckch, char **err)
664{
665 int ret = 1;
666 BIO *in = NULL;
667 X509 *issuer;
668
669 if (buf) {
670 /* reading from a buffer */
671 in = BIO_new_mem_buf(buf, -1);
672 if (in == NULL) {
673 memprintf(err, "%sCan't allocate memory\n", err && *err ? *err : "");
674 goto end;
675 }
676
677 } else {
678 /* reading from a file */
679 in = BIO_new(BIO_s_file());
680 if (in == NULL)
681 goto end;
682
683 if (BIO_read_filename(in, path) <= 0)
684 goto end;
685 }
686
687 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
688 if (!issuer) {
689 memprintf(err, "%s'%s' cannot be read or parsed'.\n",
690 err && *err ? *err : "", path);
691 goto end;
692 }
693 /* no error, fill ckch with new context, old context must be free */
694 if (ckch->ocsp_issuer)
695 X509_free(ckch->ocsp_issuer);
696 ckch->ocsp_issuer = issuer;
697 ret = 0;
698
699end:
700
701 ERR_clear_error();
702 if (in)
703 BIO_free(in);
704
705 return ret;
706}
707
708/******************** ckch_store functions ***********************************
709 * The ckch_store is a structure used to cache and index the SSL files used in
710 * configuration
711 */
712
713/*
714 * Free a ckch_store, its ckch, its instances and remove it from the ebtree
715 */
716void ckch_store_free(struct ckch_store *store)
717{
718 struct ckch_inst *inst, *inst_s;
719
720 if (!store)
721 return;
722
723#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200L
724 if (store->multi) {
725 int n;
726
727 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
728 ssl_sock_free_cert_key_and_chain_contents(&store->ckch[n]);
729 } else
730#endif
731 {
732 ssl_sock_free_cert_key_and_chain_contents(store->ckch);
733 }
734
735 free(store->ckch);
736 store->ckch = NULL;
737
738 list_for_each_entry_safe(inst, inst_s, &store->ckch_inst, by_ckchs) {
739 ckch_inst_free(inst);
740 }
741 ebmb_delete(&store->node);
742 free(store);
743}
744
745/*
746 * create and initialize a ckch_store
747 * <path> is the key name
748 * <nmemb> is the number of store->ckch objects to allocate
749 *
750 * Return a ckch_store or NULL upon failure.
751 */
752struct ckch_store *ckch_store_new(const char *filename, int nmemb)
753{
754 struct ckch_store *store;
755 int pathlen;
756
757 pathlen = strlen(filename);
758 store = calloc(1, sizeof(*store) + pathlen + 1);
759 if (!store)
760 return NULL;
761
762 if (nmemb > 1)
763 store->multi = 1;
764 else
765 store->multi = 0;
766
767 memcpy(store->path, filename, pathlen + 1);
768
769 LIST_INIT(&store->ckch_inst);
770 LIST_INIT(&store->crtlist_entry);
771
772 store->ckch = calloc(nmemb, sizeof(*store->ckch));
773 if (!store->ckch)
774 goto error;
775
776 return store;
777error:
778 ckch_store_free(store);
779 return NULL;
780}
781
782/* allocate and duplicate a ckch_store
783 * Return a new ckch_store or NULL */
784struct ckch_store *ckchs_dup(const struct ckch_store *src)
785{
786 struct ckch_store *dst;
787
788 dst = ckch_store_new(src->path, src->multi ? SSL_SOCK_NUM_KEYTYPES : 1);
789
790#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
791 if (src->multi) {
792 int n;
793
794 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
795 if (&src->ckch[n]) {
796 if (!ssl_sock_copy_cert_key_and_chain(&src->ckch[n], &dst->ckch[n]))
797 goto error;
798 }
799 }
800 } else
801#endif
802 {
803 if (!ssl_sock_copy_cert_key_and_chain(src->ckch, dst->ckch))
804 goto error;
805 }
806
807 return dst;
808
809error:
810 ckch_store_free(dst);
811
812 return NULL;
813}
814
815/*
816 * lookup a path into the ckchs tree.
817 */
818struct ckch_store *ckchs_lookup(char *path)
819{
820 struct ebmb_node *eb;
821
822 eb = ebst_lookup(&ckchs_tree, path);
823 if (!eb)
824 return NULL;
825
826 return ebmb_entry(eb, struct ckch_store, node);
827}
828
829/*
830 * This function allocate a ckch_store and populate it with certificates from files.
831 */
832struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
833{
834 struct ckch_store *ckchs;
835
836 ckchs = ckch_store_new(path, multi ? SSL_SOCK_NUM_KEYTYPES : 1);
837 if (!ckchs) {
838 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
839 goto end;
840 }
841 if (!multi) {
842
843 if (ssl_sock_load_files_into_ckch(path, ckchs->ckch, err) == 1)
844 goto end;
845
846 /* insert into the ckchs tree */
847 memcpy(ckchs->path, path, strlen(path) + 1);
848 ebst_insert(&ckchs_tree, &ckchs->node);
849 } else {
850 int found = 0;
851#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
852 char fp[MAXPATHLEN+1] = {0};
853 int n = 0;
854
855 /* Load all possible certs and keys */
856 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
857 struct stat buf;
858 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
859 if (stat(fp, &buf) == 0) {
860 if (ssl_sock_load_files_into_ckch(fp, &ckchs->ckch[n], err) == 1)
861 goto end;
862 found = 1;
863 ckchs->multi = 1;
864 }
865 }
866#endif
867
868 if (!found) {
869 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
870 goto end;
871 }
872 /* insert into the ckchs tree */
873 memcpy(ckchs->path, path, strlen(path) + 1);
874 ebst_insert(&ckchs_tree, &ckchs->node);
875 }
876 return ckchs;
877
878end:
879 ckch_store_free(ckchs);
880
881 return NULL;
882}
883
William Lallemandfa1d8b42020-05-13 15:46:10 +0200884
885/******************** ckch_inst functions ******************************/
886
887/* unlink a ckch_inst, free all SNIs, free the ckch_inst */
888/* The caller must use the lock of the bind_conf if used with inserted SNIs */
889void ckch_inst_free(struct ckch_inst *inst)
890{
891 struct sni_ctx *sni, *sni_s;
892
893 if (inst == NULL)
894 return;
895
896 list_for_each_entry_safe(sni, sni_s, &inst->sni_ctx, by_ckch_inst) {
897 SSL_CTX_free(sni->ctx);
898 LIST_DEL(&sni->by_ckch_inst);
899 ebmb_delete(&sni->name);
900 free(sni);
901 }
902 LIST_DEL(&inst->by_ckchs);
903 LIST_DEL(&inst->by_crtlist_entry);
904 free(inst);
905}
906
907/* Alloc and init a ckch_inst */
908struct ckch_inst *ckch_inst_new()
909{
910 struct ckch_inst *ckch_inst;
911
912 ckch_inst = calloc(1, sizeof *ckch_inst);
913 if (!ckch_inst)
914 return NULL;
915
916 LIST_INIT(&ckch_inst->sni_ctx);
917 LIST_INIT(&ckch_inst->by_ckchs);
918 LIST_INIT(&ckch_inst->by_crtlist_entry);
919
920 return ckch_inst;
921}
922
William Lallemandda8584c2020-05-14 10:14:37 +0200923/*************************** CLI commands ***********************/
924
925/* Type of SSL payloads that can be updated over the CLI */
926
927enum {
928 CERT_TYPE_PEM = 0,
929 CERT_TYPE_KEY,
930#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
931 CERT_TYPE_OCSP,
932#endif
933 CERT_TYPE_ISSUER,
934#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
935 CERT_TYPE_SCTL,
936#endif
937 CERT_TYPE_MAX,
938};
939
940struct {
941 const char *ext;
942 int type;
943 int (*load)(const char *path, char *payload, struct cert_key_and_chain *ckch, char **err);
944 /* add a parsing callback */
945} cert_exts[CERT_TYPE_MAX+1] = {
946 [CERT_TYPE_PEM] = { "", CERT_TYPE_PEM, &ssl_sock_load_pem_into_ckch }, /* default mode, no extensions */
947 [CERT_TYPE_KEY] = { "key", CERT_TYPE_KEY, &ssl_sock_load_key_into_ckch },
948#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
949 [CERT_TYPE_OCSP] = { "ocsp", CERT_TYPE_OCSP, &ssl_sock_load_ocsp_response_from_file },
950#endif
951#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
952 [CERT_TYPE_SCTL] = { "sctl", CERT_TYPE_SCTL, &ssl_sock_load_sctl_from_file },
953#endif
954 [CERT_TYPE_ISSUER] = { "issuer", CERT_TYPE_ISSUER, &ssl_sock_load_issuer_file_into_ckch },
955 [CERT_TYPE_MAX] = { NULL, CERT_TYPE_MAX, NULL },
956};
957
958
959/* release function of the `show ssl cert' command */
960static void cli_release_show_cert(struct appctx *appctx)
961{
962 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
963}
964
965/* IO handler of "show ssl cert <filename>" */
966static int cli_io_handler_show_cert(struct appctx *appctx)
967{
968 struct buffer *trash = alloc_trash_chunk();
969 struct ebmb_node *node;
970 struct stream_interface *si = appctx->owner;
971 struct ckch_store *ckchs;
972
973 if (trash == NULL)
974 return 1;
975
976 if (!appctx->ctx.ssl.old_ckchs) {
977 if (ckchs_transaction.old_ckchs) {
978 ckchs = ckchs_transaction.old_ckchs;
979 chunk_appendf(trash, "# transaction\n");
980 if (!ckchs->multi) {
981 chunk_appendf(trash, "*%s\n", ckchs->path);
982#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
983 } else {
984 int n;
985
986 chunk_appendf(trash, "*%s:", ckchs->path);
987 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
988 if (ckchs->ckch[n].cert)
989 chunk_appendf(trash, " %s.%s\n", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
990 }
991 chunk_appendf(trash, "\n");
992#endif
993 }
994 }
995 }
996
997 if (!appctx->ctx.cli.p0) {
998 chunk_appendf(trash, "# filename\n");
999 node = ebmb_first(&ckchs_tree);
1000 } else {
1001 node = &((struct ckch_store *)appctx->ctx.cli.p0)->node;
1002 }
1003 while (node) {
1004 ckchs = ebmb_entry(node, struct ckch_store, node);
1005 if (!ckchs->multi) {
1006 chunk_appendf(trash, "%s\n", ckchs->path);
1007#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
1008 } else {
1009 int n;
1010
1011 chunk_appendf(trash, "%s:", ckchs->path);
1012 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
1013 if (ckchs->ckch[n].cert)
1014 chunk_appendf(trash, " %s.%s", ckchs->path, SSL_SOCK_KEYTYPE_NAMES[n]);
1015 }
1016 chunk_appendf(trash, "\n");
1017#endif
1018 }
1019
1020 node = ebmb_next(node);
1021 if (ci_putchk(si_ic(si), trash) == -1) {
1022 si_rx_room_blk(si);
1023 goto yield;
1024 }
1025 }
1026
1027 appctx->ctx.cli.p0 = NULL;
1028 free_trash_chunk(trash);
1029 return 1;
1030yield:
1031
1032 free_trash_chunk(trash);
1033 appctx->ctx.cli.p0 = ckchs;
1034 return 0; /* should come back */
1035}
1036
1037/*
1038 * Extract and format the DNS SAN extensions and copy result into a chuink
1039 * Return 0;
1040 */
1041#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1042static int ssl_sock_get_san_oneline(X509 *cert, struct buffer *out)
1043{
1044 int i;
1045 char *str;
1046 STACK_OF(GENERAL_NAME) *names = NULL;
1047
1048 names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1049 if (names) {
1050 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
1051 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
1052 if (i > 0)
1053 chunk_appendf(out, ", ");
1054 if (name->type == GEN_DNS) {
1055 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
1056 chunk_appendf(out, "DNS:%s", str);
1057 OPENSSL_free(str);
1058 }
1059 }
1060 }
1061 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1062 }
1063 return 0;
1064}
1065#endif
1066
1067
1068
1069
1070/* IO handler of the details "show ssl cert <filename>" */
1071static int cli_io_handler_show_cert_detail(struct appctx *appctx)
1072{
1073 struct stream_interface *si = appctx->owner;
1074 struct ckch_store *ckchs = appctx->ctx.cli.p0;
1075 struct buffer *out = alloc_trash_chunk();
1076 struct buffer *tmp = alloc_trash_chunk();
1077 X509_NAME *name = NULL;
1078 STACK_OF(X509) *chain;
1079 unsigned int len = 0;
1080 int write = -1;
1081 BIO *bio = NULL;
1082 int i;
1083
1084 if (!tmp || !out)
1085 goto end_no_putchk;
1086
1087 if (!ckchs->multi) {
1088 chunk_appendf(out, "Filename: ");
1089 if (ckchs == ckchs_transaction.new_ckchs)
1090 chunk_appendf(out, "*");
1091 chunk_appendf(out, "%s\n", ckchs->path);
1092
1093 chunk_appendf(out, "Status: ");
1094 if (ckchs->ckch->cert == NULL)
1095 chunk_appendf(out, "Empty\n");
1096 else if (LIST_ISEMPTY(&ckchs->ckch_inst))
1097 chunk_appendf(out, "Unused\n");
1098 else
1099 chunk_appendf(out, "Used\n");
1100
1101 if (ckchs->ckch->cert == NULL)
1102 goto end;
1103
1104 chain = ckchs->ckch->chain;
1105 if (chain == NULL) {
1106 struct issuer_chain *issuer;
1107 issuer = ssl_get0_issuer_chain(ckchs->ckch->cert);
1108 if (issuer) {
1109 chain = issuer->chain;
1110 chunk_appendf(out, "Chain Filename: ");
1111 chunk_appendf(out, "%s\n", issuer->path);
1112 }
1113 }
1114 chunk_appendf(out, "Serial: ");
1115 if (ssl_sock_get_serial(ckchs->ckch->cert, tmp) == -1)
1116 goto end;
1117 dump_binary(out, tmp->area, tmp->data);
1118 chunk_appendf(out, "\n");
1119
1120 chunk_appendf(out, "notBefore: ");
1121 chunk_reset(tmp);
1122 if ((bio = BIO_new(BIO_s_mem())) == NULL)
1123 goto end;
1124 if (ASN1_TIME_print(bio, X509_getm_notBefore(ckchs->ckch->cert)) == 0)
1125 goto end;
1126 write = BIO_read(bio, tmp->area, tmp->size-1);
1127 tmp->area[write] = '\0';
1128 BIO_free(bio);
1129 bio = NULL;
1130 chunk_appendf(out, "%s\n", tmp->area);
1131
1132 chunk_appendf(out, "notAfter: ");
1133 chunk_reset(tmp);
1134 if ((bio = BIO_new(BIO_s_mem())) == NULL)
1135 goto end;
1136 if (ASN1_TIME_print(bio, X509_getm_notAfter(ckchs->ckch->cert)) == 0)
1137 goto end;
1138 if ((write = BIO_read(bio, tmp->area, tmp->size-1)) <= 0)
1139 goto end;
1140 tmp->area[write] = '\0';
1141 BIO_free(bio);
1142 bio = NULL;
1143 chunk_appendf(out, "%s\n", tmp->area);
1144
1145#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1146 chunk_appendf(out, "Subject Alternative Name: ");
1147 if (ssl_sock_get_san_oneline(ckchs->ckch->cert, out) == -1)
1148 goto end;
1149 *(out->area + out->data) = '\0';
1150 chunk_appendf(out, "\n");
1151#endif
1152 chunk_reset(tmp);
1153 chunk_appendf(out, "Algorithm: ");
1154 if (cert_get_pkey_algo(ckchs->ckch->cert, tmp) == 0)
1155 goto end;
1156 chunk_appendf(out, "%s\n", tmp->area);
1157
1158 chunk_reset(tmp);
1159 chunk_appendf(out, "SHA1 FingerPrint: ");
1160 if (X509_digest(ckchs->ckch->cert, EVP_sha1(), (unsigned char *) tmp->area, &len) == 0)
1161 goto end;
1162 tmp->data = len;
1163 dump_binary(out, tmp->area, tmp->data);
1164 chunk_appendf(out, "\n");
1165
1166 chunk_appendf(out, "Subject: ");
1167 if ((name = X509_get_subject_name(ckchs->ckch->cert)) == NULL)
1168 goto end;
1169 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
1170 goto end;
1171 *(tmp->area + tmp->data) = '\0';
1172 chunk_appendf(out, "%s\n", tmp->area);
1173
1174 chunk_appendf(out, "Issuer: ");
1175 if ((name = X509_get_issuer_name(ckchs->ckch->cert)) == NULL)
1176 goto end;
1177 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
1178 goto end;
1179 *(tmp->area + tmp->data) = '\0';
1180 chunk_appendf(out, "%s\n", tmp->area);
1181
1182 /* Displays subject of each certificate in the chain */
1183 for (i = 0; i < sk_X509_num(chain); i++) {
1184 X509 *ca = sk_X509_value(chain, i);
1185
1186 chunk_appendf(out, "Chain Subject: ");
1187 if ((name = X509_get_subject_name(ca)) == NULL)
1188 goto end;
1189 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
1190 goto end;
1191 *(tmp->area + tmp->data) = '\0';
1192 chunk_appendf(out, "%s\n", tmp->area);
1193
1194 chunk_appendf(out, "Chain Issuer: ");
1195 if ((name = X509_get_issuer_name(ca)) == NULL)
1196 goto end;
1197 if ((ssl_sock_get_dn_oneline(name, tmp)) == -1)
1198 goto end;
1199 *(tmp->area + tmp->data) = '\0';
1200 chunk_appendf(out, "%s\n", tmp->area);
1201 }
1202 }
1203
1204end:
1205 if (ci_putchk(si_ic(si), out) == -1) {
1206 si_rx_room_blk(si);
1207 goto yield;
1208 }
1209
1210end_no_putchk:
1211 if (bio)
1212 BIO_free(bio);
1213 free_trash_chunk(tmp);
1214 free_trash_chunk(out);
1215 return 1;
1216yield:
1217 free_trash_chunk(tmp);
1218 free_trash_chunk(out);
1219 return 0; /* should come back */
1220}
1221
1222/* parsing function for 'show ssl cert [certfile]' */
1223static int cli_parse_show_cert(char **args, char *payload, struct appctx *appctx, void *private)
1224{
1225 struct ckch_store *ckchs;
1226
1227 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
1228 return cli_err(appctx, "Can't allocate memory!\n");
1229
1230 /* The operations on the CKCH architecture are locked so we can
1231 * manipulate ckch_store and ckch_inst */
1232 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1233 return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
1234
1235 /* check if there is a certificate to lookup */
1236 if (*args[3]) {
1237 if (*args[3] == '*') {
1238 if (!ckchs_transaction.new_ckchs)
1239 goto error;
1240
1241 ckchs = ckchs_transaction.new_ckchs;
1242
1243 if (strcmp(args[3] + 1, ckchs->path))
1244 goto error;
1245
1246 } else {
1247 if ((ckchs = ckchs_lookup(args[3])) == NULL)
1248 goto error;
1249
1250 }
1251
1252 if (ckchs->multi)
1253 goto error;
1254
1255 appctx->ctx.cli.p0 = ckchs;
1256 /* use the IO handler that shows details */
1257 appctx->io_handler = cli_io_handler_show_cert_detail;
1258 }
1259
1260 return 0;
1261
1262error:
1263 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1264 return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
1265}
1266
1267/* release function of the `set ssl cert' command, free things and unlock the spinlock */
1268static void cli_release_commit_cert(struct appctx *appctx)
1269{
1270 struct ckch_store *new_ckchs;
1271
1272 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1273
1274 if (appctx->st2 != SETCERT_ST_FIN) {
1275 /* free every new sni_ctx and the new store, which are not in the trees so no spinlock there */
1276 new_ckchs = appctx->ctx.ssl.new_ckchs;
1277
1278 /* if the allocation failed, we need to free everything from the temporary list */
1279 ckch_store_free(new_ckchs);
1280 }
1281}
1282
1283/*
1284 * This function tries to create the new ckch_inst and their SNIs
1285 */
1286static int cli_io_handler_commit_cert(struct appctx *appctx)
1287{
1288 struct stream_interface *si = appctx->owner;
1289 int y = 0;
1290 char *err = NULL;
1291 int errcode = 0;
1292 struct ckch_store *old_ckchs, *new_ckchs = NULL;
1293 struct ckch_inst *ckchi, *ckchis;
1294 struct buffer *trash = alloc_trash_chunk();
1295 struct sni_ctx *sc0, *sc0s;
1296 struct crtlist_entry *entry;
1297
1298 if (trash == NULL)
1299 goto error;
1300
1301 if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
1302 goto error;
1303
1304 while (1) {
1305 switch (appctx->st2) {
1306 case SETCERT_ST_INIT:
1307 /* This state just print the update message */
1308 chunk_printf(trash, "Committing %s", ckchs_transaction.path);
1309 if (ci_putchk(si_ic(si), trash) == -1) {
1310 si_rx_room_blk(si);
1311 goto yield;
1312 }
1313 appctx->st2 = SETCERT_ST_GEN;
1314 /* fallthrough */
1315 case SETCERT_ST_GEN:
1316 /*
1317 * This state generates the ckch instances with their
1318 * sni_ctxs and SSL_CTX.
1319 *
1320 * Since the SSL_CTX generation can be CPU consumer, we
1321 * yield every 10 instances.
1322 */
1323
1324 old_ckchs = appctx->ctx.ssl.old_ckchs;
1325 new_ckchs = appctx->ctx.ssl.new_ckchs;
1326
1327 if (!new_ckchs)
1328 continue;
1329
1330 /* get the next ckchi to regenerate */
1331 ckchi = appctx->ctx.ssl.next_ckchi;
1332 /* we didn't start yet, set it to the first elem */
1333 if (ckchi == NULL)
1334 ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
1335
1336 /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
1337 list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
1338 struct ckch_inst *new_inst;
1339 char **sni_filter = NULL;
1340 int fcount = 0;
1341
1342 /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
1343 if (y >= 10) {
1344 /* save the next ckchi to compute */
1345 appctx->ctx.ssl.next_ckchi = ckchi;
1346 goto yield;
1347 }
1348
1349 if (ckchi->crtlist_entry) {
1350 sni_filter = ckchi->crtlist_entry->filters;
1351 fcount = ckchi->crtlist_entry->fcount;
1352 }
1353
1354 if (new_ckchs->multi)
1355 errcode |= ckch_inst_new_load_multi_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
1356 else
1357 errcode |= ckch_inst_new_load_store(new_ckchs->path, new_ckchs, ckchi->bind_conf, ckchi->ssl_conf, sni_filter, fcount, &new_inst, &err);
1358
1359 if (errcode & ERR_CODE)
1360 goto error;
1361
1362 /* if the previous ckchi was used as the default */
1363 if (ckchi->is_default)
1364 new_inst->is_default = 1;
1365
1366 /* we need to initialize the SSL_CTX generated */
1367 /* this iterate on the newly generated SNIs in the new instance to prepare their SSL_CTX */
1368 list_for_each_entry_safe(sc0, sc0s, &new_inst->sni_ctx, by_ckch_inst) {
1369 if (!sc0->order) { /* we initialized only the first SSL_CTX because it's the same in the other sni_ctx's */
1370 errcode |= ssl_sock_prepare_ctx(ckchi->bind_conf, ckchi->ssl_conf, sc0->ctx, &err);
1371 if (errcode & ERR_CODE)
1372 goto error;
1373 }
1374 }
1375
1376
1377 /* display one dot per new instance */
1378 chunk_appendf(trash, ".");
1379 /* link the new ckch_inst to the duplicate */
1380 LIST_ADDQ(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
1381 y++;
1382 }
1383 appctx->st2 = SETCERT_ST_INSERT;
1384 /* fallthrough */
1385 case SETCERT_ST_INSERT:
1386 /* The generation is finished, we can insert everything */
1387
1388 old_ckchs = appctx->ctx.ssl.old_ckchs;
1389 new_ckchs = appctx->ctx.ssl.new_ckchs;
1390
1391 if (!new_ckchs)
1392 continue;
1393
1394 /* get the list of crtlist_entry in the old store, and update the pointers to the store */
1395 LIST_SPLICE(&new_ckchs->crtlist_entry, &old_ckchs->crtlist_entry);
1396 list_for_each_entry(entry, &new_ckchs->crtlist_entry, by_ckch_store) {
1397 ebpt_delete(&entry->node);
1398 /* change the ptr and reinsert the node */
1399 entry->node.key = new_ckchs;
1400 ebpt_insert(&entry->crtlist->entries, &entry->node);
1401 }
1402
1403 /* First, we insert every new SNIs in the trees, also replace the default_ctx */
1404 list_for_each_entry_safe(ckchi, ckchis, &new_ckchs->ckch_inst, by_ckchs) {
1405 HA_RWLOCK_WRLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
1406 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
1407 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &ckchi->bind_conf->sni_lock);
1408 }
1409
1410 /* delete the old sni_ctx, the old ckch_insts and the ckch_store */
1411 list_for_each_entry_safe(ckchi, ckchis, &old_ckchs->ckch_inst, by_ckchs) {
1412 struct bind_conf __maybe_unused *bind_conf = ckchi->bind_conf;
1413
1414 HA_RWLOCK_WRLOCK(SNI_LOCK, &bind_conf->sni_lock);
1415 ckch_inst_free(ckchi);
1416 HA_RWLOCK_WRUNLOCK(SNI_LOCK, &bind_conf->sni_lock);
1417 }
1418
1419 /* Replace the old ckchs by the new one */
1420 ckch_store_free(old_ckchs);
1421 ebst_insert(&ckchs_tree, &new_ckchs->node);
1422 appctx->st2 = SETCERT_ST_FIN;
1423 /* fallthrough */
1424 case SETCERT_ST_FIN:
1425 /* we achieved the transaction, we can set everything to NULL */
1426 free(ckchs_transaction.path);
1427 ckchs_transaction.path = NULL;
1428 ckchs_transaction.new_ckchs = NULL;
1429 ckchs_transaction.old_ckchs = NULL;
1430 goto end;
1431 }
1432 }
1433end:
1434
1435 chunk_appendf(trash, "\n");
1436 if (errcode & ERR_WARN)
1437 chunk_appendf(trash, "%s", err);
1438 chunk_appendf(trash, "Success!\n");
1439 if (ci_putchk(si_ic(si), trash) == -1)
1440 si_rx_room_blk(si);
1441 free_trash_chunk(trash);
1442 /* success: call the release function and don't come back */
1443 return 1;
1444yield:
1445 /* store the state */
1446 if (ci_putchk(si_ic(si), trash) == -1)
1447 si_rx_room_blk(si);
1448 free_trash_chunk(trash);
1449 si_rx_endp_more(si); /* let's come back later */
1450 return 0; /* should come back */
1451
1452error:
1453 /* spin unlock and free are done in the release function */
1454 if (trash) {
1455 chunk_appendf(trash, "\n%sFailed!\n", err);
1456 if (ci_putchk(si_ic(si), trash) == -1)
1457 si_rx_room_blk(si);
1458 free_trash_chunk(trash);
1459 }
1460 /* error: call the release function and don't come back */
1461 return 1;
1462}
1463
1464/*
1465 * Parsing function of 'commit ssl cert'
1466 */
1467static int cli_parse_commit_cert(char **args, char *payload, struct appctx *appctx, void *private)
1468{
1469 char *err = NULL;
1470
1471 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1472 return 1;
1473
1474 if (!*args[3])
1475 return cli_err(appctx, "'commit ssl cert expects a filename\n");
1476
1477 /* The operations on the CKCH architecture are locked so we can
1478 * manipulate ckch_store and ckch_inst */
1479 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1480 return cli_err(appctx, "Can't commit the certificate!\nOperations on certificates are currently locked!\n");
1481
1482 if (!ckchs_transaction.path) {
1483 memprintf(&err, "No ongoing transaction! !\n");
1484 goto error;
1485 }
1486
1487 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
1488 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, args[3]);
1489 goto error;
1490 }
1491
1492#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
1493 if (ckchs_transaction.new_ckchs->multi) {
1494 int n;
1495
1496 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
1497 if (ckchs_transaction.new_ckchs->ckch[n].cert && !X509_check_private_key(ckchs_transaction.new_ckchs->ckch[n].cert, ckchs_transaction.new_ckchs->ckch[n].key)) {
1498 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
1499 goto error;
1500 }
1501 }
1502 } else
1503#endif
1504 {
1505 if (!X509_check_private_key(ckchs_transaction.new_ckchs->ckch->cert, ckchs_transaction.new_ckchs->ckch->key)) {
1506 memprintf(&err, "inconsistencies between private key and certificate loaded '%s'.\n", ckchs_transaction.path);
1507 goto error;
1508 }
1509 }
1510
1511 /* init the appctx structure */
1512 appctx->st2 = SETCERT_ST_INIT;
1513 appctx->ctx.ssl.next_ckchi = NULL;
1514 appctx->ctx.ssl.new_ckchs = ckchs_transaction.new_ckchs;
1515 appctx->ctx.ssl.old_ckchs = ckchs_transaction.old_ckchs;
1516
1517 /* we don't unlock there, it will be unlock after the IO handler, in the release handler */
1518 return 0;
1519
1520error:
1521
1522 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1523 err = memprintf(&err, "%sCan't commit %s!\n", err ? err : "", args[3]);
1524
1525 return cli_dynerr(appctx, err);
1526}
1527
1528
1529
1530
1531/*
1532 * Parsing function of `set ssl cert`, it updates or creates a temporary ckch.
1533 */
1534static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
1535{
1536 struct ckch_store *new_ckchs = NULL;
1537 struct ckch_store *old_ckchs = NULL;
1538 char *err = NULL;
1539 int i;
1540 int bundle = -1; /* TRUE if >= 0 (ckch index) */
1541 int errcode = 0;
1542 char *end;
1543 int type = CERT_TYPE_PEM;
1544 struct cert_key_and_chain *ckch;
1545 struct buffer *buf;
1546
1547 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1548 return 1;
1549
William Lallemandda8584c2020-05-14 10:14:37 +02001550 if (!*args[3] || !payload)
1551 return cli_err(appctx, "'set ssl cert expects a filename and a certificate as a payload\n");
1552
1553 /* The operations on the CKCH architecture are locked so we can
1554 * manipulate ckch_store and ckch_inst */
1555 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1556 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
1557
William Lallemande5ff4ad2020-06-08 09:40:37 +02001558 if ((buf = alloc_trash_chunk()) == NULL)
1559 return cli_err(appctx, "Can't allocate memory\n");
1560
William Lallemandda8584c2020-05-14 10:14:37 +02001561 if (!chunk_strcpy(buf, args[3])) {
1562 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
1563 errcode |= ERR_ALERT | ERR_FATAL;
1564 goto end;
1565 }
1566
1567 /* check which type of file we want to update */
1568 for (i = 0; cert_exts[i].type < CERT_TYPE_MAX; i++) {
1569 end = strrchr(buf->area, '.');
1570 if (end && *cert_exts[i].ext && (!strcmp(end + 1, cert_exts[i].ext))) {
1571 *end = '\0';
1572 type = cert_exts[i].type;
1573 break;
1574 }
1575 }
1576
1577 appctx->ctx.ssl.old_ckchs = NULL;
1578 appctx->ctx.ssl.new_ckchs = NULL;
1579
1580 /* if there is an ongoing transaction */
1581 if (ckchs_transaction.path) {
1582 /* if the ongoing transaction is a bundle, we need to find which part of the bundle need to be updated */
1583#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
1584 if (ckchs_transaction.new_ckchs->multi) {
1585 char *end;
1586 int j;
1587
1588 /* check if it was used in a bundle by removing the
1589 * .dsa/.rsa/.ecdsa at the end of the filename */
1590 end = strrchr(buf->area, '.');
1591 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
1592 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
1593 bundle = j; /* keep the type of certificate so we insert it at the right place */
1594 *end = '\0'; /* it's a bundle let's end the string*/
1595 break;
1596 }
1597 }
1598 if (bundle < 0) {
1599 memprintf(&err, "The ongoing transaction is the '%s' bundle. You need to specify which part of the bundle you want to update ('%s.{rsa,ecdsa,dsa}')\n", ckchs_transaction.path, buf->area);
1600 errcode |= ERR_ALERT | ERR_FATAL;
1601 goto end;
1602 }
1603 }
1604#endif
1605
1606 /* if there is an ongoing transaction, check if this is the same file */
1607 if (strcmp(ckchs_transaction.path, buf->area) != 0) {
1608 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to set '%s'\n", ckchs_transaction.path, buf->area);
1609 errcode |= ERR_ALERT | ERR_FATAL;
1610 goto end;
1611 }
1612
1613 appctx->ctx.ssl.old_ckchs = ckchs_transaction.new_ckchs;
1614
1615 } else {
1616 struct ckch_store *find_ckchs[2] = { NULL, NULL };
1617
1618 /* lookup for the certificate in the tree:
1619 * check if this is used as a bundle AND as a unique certificate */
1620 for (i = 0; i < 2; i++) {
1621
1622 if ((find_ckchs[i] = ckchs_lookup(buf->area)) != NULL) {
1623 /* only the bundle name is in the tree and you should
1624 * never update a bundle name, only a filename */
1625 if (bundle < 0 && find_ckchs[i]->multi) {
1626 /* we tried to look for a non-bundle and we found a bundle */
1627 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
1628 err ? err : "", args[3], args[3]);
1629 errcode |= ERR_ALERT | ERR_FATAL;
1630 goto end;
1631 }
1632 /* If we want a bundle but this is not a bundle
1633 * example: When you try to update <file>.rsa, but
1634 * <file> is a regular file */
1635 if (bundle >= 0 && find_ckchs[i]->multi == 0) {
1636 find_ckchs[i] = NULL;
1637 break;
1638 }
1639 }
1640#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
1641 {
1642 char *end;
1643 int j;
1644
1645 /* check if it was used in a bundle by removing the
1646 * .dsa/.rsa/.ecdsa at the end of the filename */
1647 end = strrchr(buf->area, '.');
1648 for (j = 0; end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
1649 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
1650 bundle = j; /* keep the type of certificate so we insert it at the right place */
1651 *end = '\0'; /* it's a bundle let's end the string*/
1652 break;
1653 }
1654 }
1655 if (bundle < 0) /* we didn't find a bundle extension */
1656 break;
1657 }
1658#else
1659 /* bundles are not supported here, so we don't need to lookup again */
1660 break;
1661#endif
1662 }
1663
1664 if (find_ckchs[0] && find_ckchs[1]) {
1665 memprintf(&err, "%sUpdating a certificate which is used in the HAProxy configuration as a bundle and as a unique certificate is not supported. ('%s' and '%s')\n",
1666 err ? err : "", find_ckchs[0]->path, find_ckchs[1]->path);
1667 errcode |= ERR_ALERT | ERR_FATAL;
1668 goto end;
1669 }
1670
1671 appctx->ctx.ssl.old_ckchs = find_ckchs[0] ? find_ckchs[0] : find_ckchs[1];
1672 }
1673
1674 if (!appctx->ctx.ssl.old_ckchs) {
1675 memprintf(&err, "%sCan't replace a certificate which is not referenced by the configuration!\n",
1676 err ? err : "");
1677 errcode |= ERR_ALERT | ERR_FATAL;
1678 goto end;
1679 }
1680
1681 if (!appctx->ctx.ssl.path) {
1682 /* this is a new transaction, set the path of the transaction */
1683 appctx->ctx.ssl.path = strdup(appctx->ctx.ssl.old_ckchs->path);
1684 if (!appctx->ctx.ssl.path) {
1685 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
1686 errcode |= ERR_ALERT | ERR_FATAL;
1687 goto end;
1688 }
1689 }
1690
1691 old_ckchs = appctx->ctx.ssl.old_ckchs;
1692
1693 /* duplicate the ckch store */
1694 new_ckchs = ckchs_dup(old_ckchs);
1695 if (!new_ckchs) {
1696 memprintf(&err, "%sCannot allocate memory!\n",
1697 err ? err : "");
1698 errcode |= ERR_ALERT | ERR_FATAL;
1699 goto end;
1700 }
1701
1702 if (!new_ckchs->multi)
1703 ckch = new_ckchs->ckch;
1704 else
1705 ckch = &new_ckchs->ckch[bundle];
1706
1707 /* appply the change on the duplicate */
1708 if (cert_exts[type].load(buf->area, payload, ckch, &err) != 0) {
1709 memprintf(&err, "%sCan't load the payload\n", err ? err : "");
1710 errcode |= ERR_ALERT | ERR_FATAL;
1711 goto end;
1712 }
1713
1714 appctx->ctx.ssl.new_ckchs = new_ckchs;
1715
1716 /* we succeed, we can save the ckchs in the transaction */
1717
1718 /* if there wasn't a transaction, update the old ckchs */
1719 if (!ckchs_transaction.old_ckchs) {
1720 ckchs_transaction.old_ckchs = appctx->ctx.ssl.old_ckchs;
1721 ckchs_transaction.path = appctx->ctx.ssl.path;
1722 err = memprintf(&err, "Transaction created for certificate %s!\n", ckchs_transaction.path);
1723 } else {
1724 err = memprintf(&err, "Transaction updated for certificate %s!\n", ckchs_transaction.path);
1725
1726 }
1727
1728 /* free the previous ckchs if there was a transaction */
1729 ckch_store_free(ckchs_transaction.new_ckchs);
1730
1731 ckchs_transaction.new_ckchs = appctx->ctx.ssl.new_ckchs;
1732
1733
1734 /* creates the SNI ctxs later in the IO handler */
1735
1736end:
1737 free_trash_chunk(buf);
1738
1739 if (errcode & ERR_CODE) {
1740
1741 ckch_store_free(appctx->ctx.ssl.new_ckchs);
1742 appctx->ctx.ssl.new_ckchs = NULL;
1743
1744 appctx->ctx.ssl.old_ckchs = NULL;
1745
1746 free(appctx->ctx.ssl.path);
1747 appctx->ctx.ssl.path = NULL;
1748
1749 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1750 return cli_dynerr(appctx, memprintf(&err, "%sCan't update %s!\n", err ? err : "", args[3]));
1751 } else {
1752
1753 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1754 return cli_dynmsg(appctx, LOG_NOTICE, err);
1755 }
1756 /* TODO: handle the ERR_WARN which are not handled because of the io_handler */
1757}
1758
1759/* parsing function of 'abort ssl cert' */
1760static int cli_parse_abort_cert(char **args, char *payload, struct appctx *appctx, void *private)
1761{
1762 char *err = NULL;
1763
1764 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1765 return 1;
1766
1767 if (!*args[3])
1768 return cli_err(appctx, "'abort ssl cert' expects a filename\n");
1769
1770 /* The operations on the CKCH architecture are locked so we can
1771 * manipulate ckch_store and ckch_inst */
1772 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1773 return cli_err(appctx, "Can't abort!\nOperations on certificates are currently locked!\n");
1774
1775 if (!ckchs_transaction.path) {
1776 memprintf(&err, "No ongoing transaction!\n");
1777 goto error;
1778 }
1779
1780 if (strcmp(ckchs_transaction.path, args[3]) != 0) {
1781 memprintf(&err, "The ongoing transaction is about '%s' but you are trying to abort a transaction for '%s'\n", ckchs_transaction.path, args[3]);
1782 goto error;
1783 }
1784
1785 /* Only free the ckchs there, because the SNI and instances were not generated yet */
1786 ckch_store_free(ckchs_transaction.new_ckchs);
1787 ckchs_transaction.new_ckchs = NULL;
1788 ckch_store_free(ckchs_transaction.old_ckchs);
1789 ckchs_transaction.old_ckchs = NULL;
1790 free(ckchs_transaction.path);
1791 ckchs_transaction.path = NULL;
1792
1793 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1794
1795 err = memprintf(&err, "Transaction aborted for certificate '%s'!\n", args[3]);
1796 return cli_dynmsg(appctx, LOG_NOTICE, err);
1797
1798error:
1799 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1800
1801 return cli_dynerr(appctx, err);
1802}
1803
1804/* parsing function of 'new ssl cert' */
1805static int cli_parse_new_cert(char **args, char *payload, struct appctx *appctx, void *private)
1806{
1807 struct ckch_store *store;
1808 char *err = NULL;
1809 char *path;
1810
1811 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1812 return 1;
1813
1814 if (!*args[3])
1815 return cli_err(appctx, "'new ssl cert' expects a filename\n");
1816
1817 path = args[3];
1818
1819 /* The operations on the CKCH architecture are locked so we can
1820 * manipulate ckch_store and ckch_inst */
1821 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1822 return cli_err(appctx, "Can't create a certificate!\nOperations on certificates are currently locked!\n");
1823
1824 store = ckchs_lookup(path);
1825 if (store != NULL) {
1826 memprintf(&err, "Certificate '%s' already exists!\n", path);
1827 store = NULL; /* we don't want to free it */
1828 goto error;
1829 }
1830 /* we won't support multi-certificate bundle here */
1831 store = ckch_store_new(path, 1);
1832 if (!store) {
1833 memprintf(&err, "unable to allocate memory.\n");
1834 goto error;
1835 }
1836
1837 /* insert into the ckchs tree */
1838 ebst_insert(&ckchs_tree, &store->node);
1839 memprintf(&err, "New empty certificate store '%s'!\n", args[3]);
1840
1841 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1842 return cli_dynmsg(appctx, LOG_NOTICE, err);
1843error:
1844 free(store);
1845 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1846 return cli_dynerr(appctx, err);
1847}
1848
1849/* parsing function of 'del ssl cert' */
1850static int cli_parse_del_cert(char **args, char *payload, struct appctx *appctx, void *private)
1851{
1852 struct ckch_store *store;
1853 char *err = NULL;
1854 char *filename;
1855
1856 if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
1857 return 1;
1858
1859 if (!*args[3])
1860 return cli_err(appctx, "'del ssl cert' expects a certificate name\n");
1861
1862 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
1863 return cli_err(appctx, "Can't delete the certificate!\nOperations on certificates are currently locked!\n");
1864
1865 filename = args[3];
1866
1867 store = ckchs_lookup(filename);
1868 if (store == NULL) {
1869 memprintf(&err, "certificate '%s' doesn't exist!\n", filename);
1870 goto error;
1871 }
1872 if (!LIST_ISEMPTY(&store->ckch_inst)) {
1873 memprintf(&err, "certificate '%s' in use, can't be deleted!\n", filename);
1874 goto error;
1875 }
1876
1877 ebmb_delete(&store->node);
1878 ckch_store_free(store);
1879
1880 memprintf(&err, "Certificate '%s' deleted!\n", filename);
1881
1882 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1883 return cli_dynmsg(appctx, LOG_NOTICE, err);
1884
1885error:
1886 memprintf(&err, "Can't remove the certificate: %s\n", err ? err : "");
1887 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
1888 return cli_dynerr(appctx, err);
1889}
1890
1891
1892/* register cli keywords */
1893static struct cli_kw_list cli_kws = {{ },{
1894 { { "new", "ssl", "cert", NULL }, "new ssl cert <certfile> : create a new certificate file to be used in a crt-list or a directory", cli_parse_new_cert, NULL, NULL },
1895 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL, NULL },
1896 { { "commit", "ssl", "cert", NULL }, "commit ssl cert <certfile> : commit a certificate file", cli_parse_commit_cert, cli_io_handler_commit_cert, cli_release_commit_cert },
1897 { { "abort", "ssl", "cert", NULL }, "abort ssl cert <certfile> : abort a transaction for a certificate file", cli_parse_abort_cert, NULL, NULL },
1898 { { "del", "ssl", "cert", NULL }, "del ssl cert <certfile> : delete an unused certificate file", cli_parse_del_cert, NULL, NULL },
1899 { { "show", "ssl", "cert", NULL }, "show ssl cert [<certfile>] : display the SSL certificates used in memory, or the details of a <certfile>", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
1900 { { NULL }, NULL, NULL, NULL }
1901}};
1902
1903INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
1904