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