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)

Anthony Alba authored on 31/08/2021 23:26:08 • Daniel-Constantin Mierla committed on 17/09/2021 07:08:22
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>
... ...
@@ -601,39 +601,78 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
601 601
  */
602 602
 static int tls_engine_init()
603 603
 {
604
-	LM_DBG("With OpenSSL engine support\n");
605
-	if (strncmp(tls_engine_settings.engine.s, "NONE", 4)) {
606
-		int err = 0;
607
-		ENGINE_load_builtin_engines();
608
-		OPENSSL_load_builtin_modules();
609
-		if (strncmp(tls_engine_settings.engine_config.s, "NONE", 4)) {
610
-			err = CONF_modules_load_file(tls_engine_settings.engine_config.s, "kamailio", 0);
611
-			if (!err) {
612
-				LM_ERR("OpenSSL failed to load ENGINE configuration file: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
613
-				goto error;
614
-			}
615
-		}
616
-		ksr_tls_engine = ENGINE_by_id(tls_engine_settings.engine.s);
617
-		if (!ksr_tls_engine) {
618
-			LM_ERR("OpenSSL failed to obtain ENGINE: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
604
+	char *err, *section, *engines_section, *engine_section;
605
+	char *engine_id;
606
+	int rc;
607
+	long errline;
608
+	CONF* config;
609
+	STACK_OF(CONF_VALUE) *stack;
610
+	CONF_VALUE *confval;
611
+	ENGINE *e;
612
+
613
+	LM_INFO("With OpenSSL engine support %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
614
+
615
+	/*
616
+	 * #2839: don't use CONF_modules_load_file():
617
+	 * We are in the child process and the global engine linked-list
618
+	 * is initialized in the parent.
619
+	 */
620
+	e  = ENGINE_by_id("dynamic");
621
+	if (!e) {
622
+		err = "Error loading dynamic engine";
623
+		goto error;
624
+	}
625
+	engine_id = tls_engine_settings.engine.s;
626
+
627
+	config = NCONF_new(NULL);
628
+	rc = NCONF_load(config, tls_engine_settings.engine_config.s, &errline);
629
+	if (!rc) {
630
+		err = "Error loading OpenSSL configuration file";
631
+		goto error;
632
+	}
633
+
634
+	section = NCONF_get_string(config, NULL, "kamailio");
635
+	engines_section = NCONF_get_string(config, section, "engines");
636
+	engine_section = NCONF_get_string(config, engines_section, engine_id);
637
+	stack = NCONF_get_section(config, engine_section);
638
+
639
+	if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", NCONF_get_string(config, engine_section, "dynamic_path"), 0)) {
640
+		err = "SO_PATH";
641
+		goto error;
642
+	}
643
+	if (!ENGINE_ctrl_cmd_string(e, "ID", engine_id, 0)) {
644
+		err = "ID";
645
+		goto error;
646
+	}
647
+	if (!ENGINE_ctrl_cmd(e, "LOAD", 1, NULL, NULL, 0)) {
648
+		err = "LOAD";
649
+		goto error;
650
+	}
651
+	while((confval = sk_CONF_VALUE_pop(stack))) {
652
+		if (strcmp(confval->name, "dynamic_path") == 0) continue;
653
+		LM_DBG("Configuring OpenSSL engine %s: %s(%s)\n", engine_id, confval->name, confval->value);
654
+		if (!ENGINE_ctrl_cmd_string(e, confval->name, confval->value, 0)) {
655
+			err = confval->name;
619 656
 			goto error;
620 657
 		}
621
-		err = ENGINE_init(ksr_tls_engine);
622
-		if (!err) {
623
-			LM_ERR("OpenSSL ENGINE_init() failed\n");
658
+	}
659
+
660
+	if (!ENGINE_init(e)) {
661
+		err = "ENGINE_init()";
662
+		goto error;
663
+	}
664
+	if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
665
+		rc = ENGINE_set_default_string(e, tls_engine_settings.engine_algorithms.s);
666
+		if (!rc) {
667
+			err = "OpenSSL ENGINE could not set algorithms";
624 668
 			goto error;
625 669
 		}
626
-		if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
627
-			err = ENGINE_set_default_string(ksr_tls_engine, tls_engine_settings.engine_algorithms.s);
628
-			if (!err) {
629
-				LM_ERR("OpenSSL ENGINE could not set algorithms\n");
630
-				goto error;
631
-			}
632
-		}
633
-		LM_INFO("OpenSSL engine %*s initialized\n", tls_engine_settings.engine.len, tls_engine_settings.engine.s);
634 670
 	}
671
+	ENGINE_free(e);
672
+	ksr_tls_engine = e;
635 673
 	return 0;
636 674
 error:
675
+	LM_ERR("TLS Engine: %s\n", err);
637 676
 	return -1;
638 677
 }
639 678