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)

Anthony Alba authored on 31/08/2021 23:26:08 • Daniel-Constantin Mierla committed on 06/09/2021 08:35:01
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>
... ...
@@ -648,39 +648,78 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
648 648
  */
649 649
 static int tls_engine_init()
650 650
 {
651
-	LM_DBG("With OpenSSL engine support\n");
652
-	if (strncmp(tls_engine_settings.engine.s, "NONE", 4)) {
653
-		int err = 0;
654
-		ENGINE_load_builtin_engines();
655
-		OPENSSL_load_builtin_modules();
656
-		if (strncmp(tls_engine_settings.engine_config.s, "NONE", 4)) {
657
-			err = CONF_modules_load_file(tls_engine_settings.engine_config.s, "kamailio", 0);
658
-			if (!err) {
659
-				LM_ERR("OpenSSL failed to load ENGINE configuration file: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
660
-				goto error;
661
-			}
662
-		}
663
-		ksr_tls_engine = ENGINE_by_id(tls_engine_settings.engine.s);
664
-		if (!ksr_tls_engine) {
665
-			LM_ERR("OpenSSL failed to obtain ENGINE: %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
651
+	char *err, *section, *engines_section, *engine_section;
652
+	char *engine_id;
653
+	int rc;
654
+	long errline;
655
+	CONF* config;
656
+	STACK_OF(CONF_VALUE) *stack;
657
+	CONF_VALUE *confval;
658
+	ENGINE *e;
659
+
660
+	LM_INFO("With OpenSSL engine support %*s\n", tls_engine_settings.engine_config.len, tls_engine_settings.engine_config.s);
661
+
662
+	/*
663
+	 * #2839: don't use CONF_modules_load_file():
664
+	 * We are in the child process and the global engine linked-list
665
+	 * is initialized in the parent.
666
+	 */
667
+	e  = ENGINE_by_id("dynamic");
668
+	if (!e) {
669
+		err = "Error loading dynamic engine";
670
+		goto error;
671
+	}
672
+	engine_id = tls_engine_settings.engine.s;
673
+
674
+	config = NCONF_new(NULL);
675
+	rc = NCONF_load(config, tls_engine_settings.engine_config.s, &errline);
676
+	if (!rc) {
677
+		err = "Error loading OpenSSL configuration file";
678
+		goto error;
679
+	}
680
+
681
+	section = NCONF_get_string(config, NULL, "kamailio");
682
+	engines_section = NCONF_get_string(config, section, "engines");
683
+	engine_section = NCONF_get_string(config, engines_section, engine_id);
684
+	stack = NCONF_get_section(config, engine_section);
685
+
686
+	if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", NCONF_get_string(config, engine_section, "dynamic_path"), 0)) {
687
+		err = "SO_PATH";
688
+		goto error;
689
+	}
690
+	if (!ENGINE_ctrl_cmd_string(e, "ID", engine_id, 0)) {
691
+		err = "ID";
692
+		goto error;
693
+	}
694
+	if (!ENGINE_ctrl_cmd(e, "LOAD", 1, NULL, NULL, 0)) {
695
+		err = "LOAD";
696
+		goto error;
697
+	}
698
+	while((confval = sk_CONF_VALUE_pop(stack))) {
699
+		if (strcmp(confval->name, "dynamic_path") == 0) continue;
700
+		LM_DBG("Configuring OpenSSL engine %s: %s(%s)\n", engine_id, confval->name, confval->value);
701
+		if (!ENGINE_ctrl_cmd_string(e, confval->name, confval->value, 0)) {
702
+			err = confval->name;
666 703
 			goto error;
667 704
 		}
668
-		err = ENGINE_init(ksr_tls_engine);
669
-		if (!err) {
670
-			LM_ERR("OpenSSL ENGINE_init() failed\n");
705
+	}
706
+
707
+	if (!ENGINE_init(e)) {
708
+		err = "ENGINE_init()";
709
+		goto error;
710
+	}
711
+	if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
712
+		rc = ENGINE_set_default_string(e, tls_engine_settings.engine_algorithms.s);
713
+		if (!rc) {
714
+			err = "OpenSSL ENGINE could not set algorithms";
671 715
 			goto error;
672 716
 		}
673
-		if (strncmp(tls_engine_settings.engine_algorithms.s, "NONE", 4)) {
674
-			err = ENGINE_set_default_string(ksr_tls_engine, tls_engine_settings.engine_algorithms.s);
675
-			if (!err) {
676
-				LM_ERR("OpenSSL ENGINE could not set algorithms\n");
677
-				goto error;
678
-			}
679
-		}
680
-		LM_INFO("OpenSSL engine %*s initialized\n", tls_engine_settings.engine.len, tls_engine_settings.engine.s);
681 717
 	}
718
+	ENGINE_free(e);
719
+	ksr_tls_engine = e;
682 720
 	return 0;
683 721
 error:
722
+	LM_ERR("TLS Engine: %s\n", err);
684 723
 	return -1;
685 724
 }
686 725