Browse code

tls: fix OpenSSL engine in child processes

tls_init.c calls OPENSSL_init_ssl(); this initializes the
global engine linked-list and this cannot be reset in the child.

To avoid linked-list corruption we manually instantiate
the engine object required for loading private keys instead of
relying on CONF_modules_load_file().

Updates to doc/.

Addresses #2839

(cherry picked from commit 238ef139bfbe145fb93e5c4b0730de58040d2265)
(cherry picked from commit ad5af6d3acd648e6bd57b923083cc26d3a3d0f57)
(cherry picked from commit a564c8d2e88b58948f2e1ea01008ec89e3c7d225)

Anthony Alba authored on 31/08/2021 23:26:08 • Henning Westerholt committed on 22/10/2021 12:10:11
Showing 2 changed files
... ...
@@ -22,17 +22,17 @@
22 22
 		</para>
23 23
 		<para>
24 24
 		<programlisting>
25
-AWS CloudHSM Example
25
+Thales Luna Example
26 26
 --------------------
27 27
 
28 28
 ...
29
-# Example for AWS CloudHSM (SafeNet Luna)
29
+# Example for Thales Luna
30 30
 modparam("tls", "engine", "gem")
31
-modparam("tls", "engine_config", "/usr/local/etc/kamailio/luna.conf")
32
-modparam("tls", "engine_algorithms", "ALL)
31
+modparam("tls", "engine_config", "/usr/local/etc/kamailio/thales.cnf")
32
+modparam("tls", "engine_algorithms", "EC")
33 33
 ...
34 34
 
35
-/usr/local/etc/kamailio/luna.cnf is a OpenSSL config format file used to
35
+/usr/local/etc/kamailio/thales.cnf is a OpenSSL config format file used to
36 36
 bootstrap the engine, e.g., pass the PIN.
37 37
 
38 38
 ...
... ...
@@ -43,11 +43,12 @@ kamailio = openssl_init
43 43
 engines = engine_section
44 44
 
45 45
 [ engine_section ]
46
-# gem is the name of the SafeNet Luna OpenSSL engine
46
+# gem is the name of the Thales Luna OpenSSL engine
47 47
 gem = gem_section
48 48
 
49 49
 [ gem_section ]
50
-# from SafeNet documentation
50
+# from Thales documentation
51
+dynamic_path = /usr/lib64/engines-1.1/gem.so
51 52
 ENGINE_INIT = 0:20:21:password=1234-ABCD-5678-EFGH
52 53
 ...
53 54
 
... ...
@@ -23,7 +23,7 @@
23 23
  * Module: @ref tls
24 24
  */
25 25
 
26
-
26
+#include <stdlib.h>
27 27
 #include <sys/types.h>
28 28
 #include <sys/socket.h>
29 29
 #include <arpa/inet.h>
... ...
@@ -590,39 +590,78 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
590 590
  */
591 591
 static int tls_engine_init()
592 592
 {
593
-	LM_DBG("With OpenSSL engine support\n");
594
-	if (strncmp(tls_engine_settings.engine.s, "NONE", 4)) {
595
-		int err = 0;
596
-		ENGINE_load_builtin_engines();
597
-		OPENSSL_load_builtin_modules();
598
-		if (strncmp(tls_engine_settings.engine_config.s, "NONE", 4)) {
599
-			err = CONF_modules_load_file(tls_engine_settings.engine_config.s, "kamailio", 0);
600
-			if (!err) {
601
-				LM_ERR("OpenSSL failed to load ENGINE configuration file: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
602
-				goto error;
603
-			}
604
-		}
605
-		ksr_tls_engine = ENGINE_by_id(tls_engine_settings.engine.s);
606
-		if (!ksr_tls_engine) {
607
-			LM_ERR("OpenSSL failed to obtain ENGINE: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
593
+	char *err, *section, *engines_section, *engine_section;
594
+	char *engine_id;
595
+	int rc;
596
+	long errline;
597
+	CONF* config;
598
+	STACK_OF(CONF_VALUE) *stack;
599
+	CONF_VALUE *confval;
600
+	ENGINE *e;
601
+
602
+	LM_INFO("With OpenSSL engine support %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
603
+
604
+	/*
605
+	 * #2839: don't use CONF_modules_load_file():
606
+	 * We are in the child process and the global engine linked-list
607
+	 * is initialized in the parent.
608
+	 */
609
+	e  = ENGINE_by_id("dynamic");
610
+	if (!e) {
611
+		err = "Error loading dynamic engine";
612
+		goto error;
613
+	}
614
+	engine_id = tls_engine_settings.engine.s;
615
+
616
+	config = NCONF_new(NULL);
617
+	rc = NCONF_load(config, tls_engine_settings.engine_config.s, &errline);
618
+	if (!rc) {
619
+		err = "Error loading OpenSSL configuration file";
620
+		goto error;
621
+	}
622
+
623
+	section = NCONF_get_string(config, NULL, "kamailio");
624
+	engines_section = NCONF_get_string(config, section, "engines");
625
+	engine_section = NCONF_get_string(config, engines_section, engine_id);
626
+	stack = NCONF_get_section(config, engine_section);
627
+
628
+	if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", NCONF_get_string(config, engine_section, "dynamic_path"), 0)) {
629
+		err = "SO_PATH";
630
+		goto error;
631
+	}
632
+	if (!ENGINE_ctrl_cmd_string(e, "ID", engine_id, 0)) {
633
+		err = "ID";
634
+		goto error;
635
+	}
636
+	if (!ENGINE_ctrl_cmd(e, "LOAD", 1, NULL, NULL, 0)) {
637
+		err = "LOAD";
638
+		goto error;
639
+	}
640
+	while((confval = sk_CONF_VALUE_pop(stack))) {
641
+		if (strcmp(confval->name, "dynamic_path") == 0) continue;
642
+		LM_DBG("Configuring OpenSSL engine %s: %s(%s)\n", engine_id, confval->name, confval->value);
643
+		if (!ENGINE_ctrl_cmd_string(e, confval->name, confval->value, 0)) {
644
+			err = confval->name;
608 645
 			goto error;
609 646
 		}
610
-		err = ENGINE_init(ksr_tls_engine);
611
-		if (!err) {
612
-			LM_ERR("OpenSSL ENGINE_init() failed\n");
647
+	}
648
+
649
+	if (!ENGINE_init(e)) {
650
+		err = "ENGINE_init()";
651
+		goto error;
652
+	}
653
+	if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
654
+		rc = ENGINE_set_default_string(e, tls_engine_settings.engine_algorithms.s);
655
+		if (!rc) {
656
+			err = "OpenSSL ENGINE could not set algorithms";
613 657
 			goto error;
614 658
 		}
615
-		if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
616
-			err = ENGINE_set_default_string(ksr_tls_engine, tls_engine_settings.engine_algorithms.s);
617
-			if (!err) {
618
-				LM_ERR("OpenSSL ENGINE could not set algorithms\n");
619
-				goto error;
620
-			}
621
-		}
622
-		LM_INFO("OpenSSL engine %*s initialized\n", tls_engine_settings.engine.len, tls_engine_settings.engine.s);
623 659
 	}
660
+	ENGINE_free(e);
661
+	ksr_tls_engine = e;
624 662
 	return 0;
625 663
 error:
664
+	LM_ERR("TLS Engine: %s\n", err);
626 665
 	return -1;
627 666
 }
628 667