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