Browse code

tls: update DH initialization for OpenSSL 1.1.x

For OpenSSL 3.x, this will fix a deprecation warning.

SPChan authored on 22/11/2021 14:55:30 • Daniel-Constantin Mierla committed on 23/11/2021 19:02:37
Showing 1 changed files
... ...
@@ -89,6 +89,10 @@ static void setup_ecdh(SSL_CTX *ctx)
89 89
 
90 90
 #ifndef OPENSSL_NO_DH
91 91
 
92
+/*
93
+ * not needed for OpenSSL 1.1.0+ and LibreSSL
94
+ */
95
+#if !defined(SSL_CTX_set_dh_auto)
92 96
 static unsigned char dh3072_p[] = {
93 97
    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
94 98
    0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
... ...
@@ -126,9 +130,15 @@ static unsigned char dh3072_p[] = {
126 130
 };
127 131
 
128 132
 static unsigned char dh3072_g[] = { 0x02 };
133
+#endif
129 134
 
130 135
 static void setup_dh(SSL_CTX *ctx)
131 136
 {
137
+/*
138
+ * not needed for OpenSSL 1.1.0+ and LibreSSL
139
+ * DH_new() is deprecated in OpenSSL 3
140
+ */
141
+#if !defined(SSL_CTX_set_dh_auto)
132 142
 	DH *dh;
133 143
 	BIGNUM *p;
134 144
 	BIGNUM *g;
... ...
@@ -146,19 +156,17 @@ static void setup_dh(SSL_CTX *ctx)
146 156
 		return;
147 157
 	}
148 158
 
149
-#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
150
-	/* libssl >= v1.1.0 */
151
-	DH_set0_pqg(dh, p, NULL, g);
152
-#else
153 159
 	dh->p = p;
154 160
 	dh->g = g;
155
-#endif
156 161
 
157 162
 
158 163
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
159 164
    SSL_CTX_set_tmp_dh(ctx, dh);
160 165
 
161 166
    DH_free(dh);
167
+#else
168
+   SSL_CTX_set_dh_auto(ctx, 1);
169
+#endif
162 170
 }
163 171
 #endif
164 172
 
Browse code

tls: fix wrong macro used to detect OpenSSL 1.1.0+

SPChan authored on 22/11/2021 13:59:12 • Daniel-Constantin Mierla committed on 22/11/2021 18:22:23
Showing 1 changed files
... ...
@@ -62,7 +62,7 @@ extern EVP_PKEY * tls_engine_private_key(const char* key_id);
62 62
  * prime256v1 by default.  This is Apache mod_ssl's initialization
63 63
  * policy, so we should be safe. OpenSSL 1.1 has it enabled by default.
64 64
  */
65
-#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
65
+#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER < 0x10100000L
66 66
 static void setup_ecdh(SSL_CTX *ctx)
67 67
 {
68 68
 #if !defined(SSL_CTX_set_ecdh_auto)
... ...
@@ -701,7 +701,7 @@ static int set_cipher_list(tls_domain_t* d)
701 701
 					tls_domain_str(d), cipher_list);
702 702
 			return -1;
703 703
 		}
704
-#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
704
+#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER < 0x10100000L
705 705
                 setup_ecdh(d->ctx[i]);
706 706
 #endif
707 707
 #ifndef OPENSSL_NO_DH
Browse code

tls: declare variable based on SSL_CTX_set_ecdh_auto

- fix unused variable warning introduced in previous commit

Daniel-Constantin Mierla authored on 30/04/2021 06:53:47
Showing 1 changed files
... ...
@@ -65,7 +65,9 @@ extern EVP_PKEY * tls_engine_private_key(const char* key_id);
65 65
 #if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
66 66
 static void setup_ecdh(SSL_CTX *ctx)
67 67
 {
68
+#if !defined(SSL_CTX_set_ecdh_auto)
68 69
    EC_KEY *ecdh;
70
+#endif
69 71
 
70 72
 #if OPENSSL_VERSION_NUMBER < 0x010100000L
71 73
    if (SSLeay() < 0x1000005fL) {
Browse code

[tls] Don't use OpenSSL<1.0.2 fallback on 1.1+

Address GH #2716. Also see https://bugs.python.org/issue29697.

SPChan authored on 27/04/2021 16:51:22 • Daniel-Constantin Mierla committed on 29/04/2021 06:32:13
Showing 1 changed files
... ...
@@ -57,8 +57,12 @@ extern EVP_PKEY * tls_engine_private_key(const char* key_id);
57 57
  * ECDHE is enabled only on OpenSSL 1.0.0e and later.
58 58
  * See http://www.openssl.org/news/secadv_20110906.txt
59 59
  * for details.
60
+ * Also, copied from _ssl.c of Python for correct initialization.
61
+ * Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use
62
+ * prime256v1 by default.  This is Apache mod_ssl's initialization
63
+ * policy, so we should be safe. OpenSSL 1.1 has it enabled by default.
60 64
  */
61
-#ifndef OPENSSL_NO_ECDH
65
+#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
62 66
 static void setup_ecdh(SSL_CTX *ctx)
63 67
 {
64 68
    EC_KEY *ecdh;
... ...
@@ -69,11 +73,15 @@ static void setup_ecdh(SSL_CTX *ctx)
69 73
    }
70 74
 #endif
71 75
 
76
+#if defined(SSL_CTX_set_ecdh_auto)
77
+   SSL_CTX_set_ecdh_auto(ctx, 1);
78
+#else
72 79
    ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
73 80
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
74 81
    SSL_CTX_set_tmp_ecdh(ctx, ecdh);
75 82
 
76 83
    EC_KEY_free(ecdh);
84
+#endif
77 85
 }
78 86
 #endif
79 87
 
... ...
@@ -691,7 +699,7 @@ static int set_cipher_list(tls_domain_t* d)
691 699
 					tls_domain_str(d), cipher_list);
692 700
 			return -1;
693 701
 		}
694
-#ifndef OPENSSL_NO_ECDH
702
+#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1)
695 703
                 setup_ecdh(d->ctx[i]);
696 704
 #endif
697 705
 #ifndef OPENSSL_NO_DH
Browse code

tls: test the pointer to CA file path when setting the client property

Daniel-Constantin Mierla authored on 23/03/2021 11:53:38
Showing 1 changed files
... ...
@@ -580,9 +580,9 @@ static int load_ca_list(tls_domain_t* d)
580 580
 		DBG("%s: No CA list configured\n", tls_domain_str(d));
581 581
 		return 0;
582 582
 	}
583
-	if (d->ca_file.len>0 && fix_shm_pathname(&d->ca_file) < 0)
583
+	if (d->ca_file.s && d->ca_file.len>0 && fix_shm_pathname(&d->ca_file) < 0)
584 584
 		return -1;
585
-	if (d->ca_path.len>0 && fix_shm_pathname(&d->ca_path) < 0)
585
+	if (d->ca_path.s && d->ca_path.len>0 && fix_shm_pathname(&d->ca_path) < 0)
586 586
 		return -1;
587 587
 	procs_no=get_max_procs();
588 588
 	for(i = 0; i < procs_no; i++) {
... ...
@@ -594,7 +594,7 @@ static int load_ca_list(tls_domain_t* d)
594 594
 			TLS_ERR("load_ca_list:");
595 595
 			return -1;
596 596
 		}
597
-		if(d->ca_file.len>0) {
597
+		if(d->ca_file.s && d->ca_file.len>0) {
598 598
 			SSL_CTX_set_client_CA_list(d->ctx[i],
599 599
 					SSL_load_client_CA_file(d->ca_file.s));
600 600
 			if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
Browse code

tls: log file name if failure to set the client CA list

Daniel-Constantin Mierla authored on 23/03/2021 11:29:19
Showing 1 changed files
... ...
@@ -598,7 +598,10 @@ static int load_ca_list(tls_domain_t* d)
598 598
 			SSL_CTX_set_client_CA_list(d->ctx[i],
599 599
 					SSL_load_client_CA_file(d->ca_file.s));
600 600
 			if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
601
-				ERR("%s: Error while setting client CA list\n", tls_domain_str(d));
601
+				ERR("%s: Error while setting client CA list file [%.*s/%d]\n",
602
+						tls_domain_str(d), (d->ca_file.s)?d->ca_file.len:0,
603
+						(d->ca_file.s)?d->ca_file.s:"",
604
+						d->ca_file.len);
602 605
 				TLS_ERR("load_ca_list:");
603 606
 				return -1;
604 607
 			}
Browse code

tls: added ca_path config option

- used to provide path to directory with CA files in pem format, to be
given as parameter to SSL_CTX_load_verify_locations()
- GH #2682

Daniel-Constantin Mierla authored on 23/03/2021 07:54:20
Showing 1 changed files
... ...
@@ -192,7 +192,7 @@ void tls_free_domain(tls_domain_t* d)
192 192
 {
193 193
 	int i;
194 194
 	int procs_no;
195
-	
195
+
196 196
 	if (!d) return;
197 197
 	if (d->ctx) {
198 198
 		procs_no=get_max_procs();
... ...
@@ -204,6 +204,7 @@ void tls_free_domain(tls_domain_t* d)
204 204
 
205 205
 	if (d->cipher_list.s) shm_free(d->cipher_list.s);
206 206
 	if (d->ca_file.s) shm_free(d->ca_file.s);
207
+	if (d->ca_path.s) shm_free(d->ca_path.s);
207 208
 	if (d->crl_file.s) shm_free(d->crl_file.s);
208 209
 	if (d->pkey_file.s) shm_free(d->pkey_file.s);
209 210
 	if (d->cert_file.s) shm_free(d->cert_file.s);
... ...
@@ -327,6 +328,13 @@ static int ksr_tls_fill_missing(tls_domain_t* d, tls_domain_t* parent)
327 328
 	}
328 329
 	LOG(L_INFO, "%s: ca_list='%s'\n", tls_domain_str(d), d->ca_file.s);
329 330
 
331
+	if (!d->ca_path.s){
332
+		if (shm_asciiz_dup(&d->ca_path.s, parent->ca_path.s) < 0)
333
+			return -1;
334
+		d->ca_path.len = parent->ca_path.len;
335
+	}
336
+	LOG(L_INFO, "%s: ca_path='%s'\n", tls_domain_str(d), d->ca_path.s);
337
+
330 338
 	if (!d->crl_file.s) {
331 339
 		if (shm_asciiz_dup(&d->crl_file.s, parent->crl_file.s) < 0)
332 340
 			return -1;
... ...
@@ -568,26 +576,32 @@ static int load_ca_list(tls_domain_t* d)
568 576
 	int i;
569 577
 	int procs_no;
570 578
 
571
-	if (!d->ca_file.s || !d->ca_file.len) {
579
+	if ((!d->ca_file.s || !d->ca_file.len) && (!d->ca_path.s || !d->ca_path.len)) {
572 580
 		DBG("%s: No CA list configured\n", tls_domain_str(d));
573 581
 		return 0;
574 582
 	}
575
-	if (fix_shm_pathname(&d->ca_file) < 0)
583
+	if (d->ca_file.len>0 && fix_shm_pathname(&d->ca_file) < 0)
584
+		return -1;
585
+	if (d->ca_path.len>0 && fix_shm_pathname(&d->ca_path) < 0)
576 586
 		return -1;
577 587
 	procs_no=get_max_procs();
578 588
 	for(i = 0; i < procs_no; i++) {
579
-		if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s, 0) != 1) {
580
-			ERR("%s: Unable to load CA list '%s'\n", tls_domain_str(d),
581
-					d->ca_file.s);
589
+		if (SSL_CTX_load_verify_locations(d->ctx[i], d->ca_file.s,
590
+					d->ca_path.s) != 1) {
591
+			ERR("%s: Unable to load CA list file '%s' dir '%s'\n",
592
+					tls_domain_str(d), (d->ca_file.s)?d->ca_file.s:"",
593
+					(d->ca_path.s)?d->ca_path.s:"");
582 594
 			TLS_ERR("load_ca_list:");
583 595
 			return -1;
584 596
 		}
585
-		SSL_CTX_set_client_CA_list(d->ctx[i],
586
-				SSL_load_client_CA_file(d->ca_file.s));
587
-		if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
588
-			ERR("%s: Error while setting client CA list\n", tls_domain_str(d));
589
-			TLS_ERR("load_ca_list:");
590
-			return -1;
597
+		if(d->ca_file.len>0) {
598
+			SSL_CTX_set_client_CA_list(d->ctx[i],
599
+					SSL_load_client_CA_file(d->ca_file.s));
600
+			if (SSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
601
+				ERR("%s: Error while setting client CA list\n", tls_domain_str(d));
602
+				TLS_ERR("load_ca_list:");
603
+				return -1;
604
+			}
591 605
 		}
592 606
 	}
593 607
 	return 0;
Browse code

Revert "Revert "tls: added define condition on version functions""

This reverts commit bffd78f14921f67735a64caea2fb130393daa2bc.

Daniel-Constantin Mierla authored on 18/09/2020 12:12:17
Showing 1 changed files
... ...
@@ -63,9 +63,11 @@ static void setup_ecdh(SSL_CTX *ctx)
63 63
 {
64 64
    EC_KEY *ecdh;
65 65
 
66
-   if (OpenSSL_version_num() < 0x1000005fL) {
66
+#if OPENSSL_VERSION_NUMBER < 0x010100000L
67
+   if (SSLeay() < 0x1000005fL) {
67 68
       return;
68 69
    }
70
+#endif
69 71
 
70 72
    ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
71 73
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
Browse code

Revert "Revert "tls: support compilation without deprecated OpenSSL APIs""

This reverts commit 0a2fc0371430f19f868dc17f3a361e412ceb376f.

Daniel-Constantin Mierla authored on 18/09/2020 12:11:52
Showing 1 changed files
... ...
@@ -27,6 +27,8 @@
27 27
 #include <stdlib.h>
28 28
 #include <openssl/ssl.h>
29 29
 #include <openssl/opensslv.h>
30
+#include <openssl/bn.h>
31
+#include <openssl/dh.h>
30 32
 
31 33
 #ifndef OPENSSL_NO_ENGINE
32 34
 #include <openssl/engine.h>
... ...
@@ -61,7 +63,7 @@ static void setup_ecdh(SSL_CTX *ctx)
61 63
 {
62 64
    EC_KEY *ecdh;
63 65
 
64
-   if (SSLeay() < 0x1000005fL) {
66
+   if (OpenSSL_version_num() < 0x1000005fL) {
65 67
       return;
66 68
    }
67 69
 
Browse code

Revert "tls: support compilation without deprecated OpenSSL APIs"

This reverts commit 234b02236b3ad13cdaf5624d11c727ad7d804747.

Victor Seva authored on 02/09/2020 12:27:26
Showing 1 changed files
... ...
@@ -27,8 +27,6 @@
27 27
 #include <stdlib.h>
28 28
 #include <openssl/ssl.h>
29 29
 #include <openssl/opensslv.h>
30
-#include <openssl/bn.h>
31
-#include <openssl/dh.h>
32 30
 
33 31
 #ifndef OPENSSL_NO_ENGINE
34 32
 #include <openssl/engine.h>
... ...
@@ -63,7 +61,7 @@ static void setup_ecdh(SSL_CTX *ctx)
63 61
 {
64 62
    EC_KEY *ecdh;
65 63
 
66
-   if (OpenSSL_version_num() < 0x1000005fL) {
64
+   if (SSLeay() < 0x1000005fL) {
67 65
       return;
68 66
    }
69 67
 
Browse code

Revert "tls: added define condition on version functions"

This reverts commit 99c6a68dea60ca745dfdfa33085bb6acbcee846a.

Victor Seva authored on 02/09/2020 12:27:24
Showing 1 changed files
... ...
@@ -63,11 +63,9 @@ static void setup_ecdh(SSL_CTX *ctx)
63 63
 {
64 64
    EC_KEY *ecdh;
65 65
 
66
-#if OPENSSL_VERSION_NUMBER < 0x010100000L
67
-   if (SSLeay() < 0x1000005fL) {
66
+   if (OpenSSL_version_num() < 0x1000005fL) {
68 67
       return;
69 68
    }
70
-#endif
71 69
 
72 70
    ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
73 71
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
Browse code

tls: added define condition on version functions

- libssl 1.1 variants are not in 1.0
- following the changes by 234b02236b3ad13cdaf5624d11c727ad7d804747

Daniel-Constantin Mierla authored on 13/08/2020 05:19:28
Showing 1 changed files
... ...
@@ -63,9 +63,11 @@ static void setup_ecdh(SSL_CTX *ctx)
63 63
 {
64 64
    EC_KEY *ecdh;
65 65
 
66
-   if (OpenSSL_version_num() < 0x1000005fL) {
66
+#if OPENSSL_VERSION_NUMBER < 0x010100000L
67
+   if (SSLeay() < 0x1000005fL) {
67 68
       return;
68 69
    }
70
+#endif
69 71
 
70 72
    ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
71 73
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
Browse code

tls: support compilation without deprecated OpenSSL APIs

- GH #2428

Rosen Penev authored on 12/08/2020 14:37:13 • Daniel-Constantin Mierla committed on 12/08/2020 14:37:13
Showing 1 changed files
... ...
@@ -27,6 +27,8 @@
27 27
 #include <stdlib.h>
28 28
 #include <openssl/ssl.h>
29 29
 #include <openssl/opensslv.h>
30
+#include <openssl/bn.h>
31
+#include <openssl/dh.h>
30 32
 
31 33
 #ifndef OPENSSL_NO_ENGINE
32 34
 #include <openssl/engine.h>
... ...
@@ -61,7 +63,7 @@ static void setup_ecdh(SSL_CTX *ctx)
61 63
 {
62 64
    EC_KEY *ecdh;
63 65
 
64
-   if (SSLeay() < 0x1000005fL) {
66
+   if (OpenSSL_version_num() < 0x1000005fL) {
65 67
       return;
66 68
    }
67 69
 
Browse code

tls: better log messages when failing to create ssl ctx

Daniel-Constantin Mierla authored on 26/05/2020 13:05:15
Showing 1 changed files
... ...
@@ -1036,7 +1036,11 @@ static int ksr_tls_fix_domain(tls_domain_t* d, tls_domain_t* def)
1036 1036
 			d->ctx[i] = SSL_CTX_new((SSL_METHOD*)ssl_methods[d->method - 1]);
1037 1037
 		}
1038 1038
 		if (d->ctx[i] == NULL) {
1039
-			ERR("%s: Cannot create SSL context\n", tls_domain_str(d));
1039
+			unsigned long e = 0;
1040
+			e = ERR_peek_last_error();
1041
+			ERR("%s: Cannot create SSL context [%d] (%lu: %s / %s)\n",
1042
+					tls_domain_str(d), i, e, ERR_error_string(e, NULL),
1043
+					ERR_reason_error_string(e));
1040 1044
 			return -1;
1041 1045
 		}
1042 1046
 		if(d->method>TLS_USE_TLSvRANGE) {
... ...
@@ -1046,7 +1050,11 @@ static int ksr_tls_fix_domain(tls_domain_t* d, tls_domain_t* def)
1046 1050
 		/* libssl >= 1.1.0 */
1047 1051
 		d->ctx[i] = SSL_CTX_new(sr_tls_methods[d->method - 1].TLSMethod);
1048 1052
 		if (d->ctx[i] == NULL) {
1049
-			ERR("%s: Cannot create SSL context\n", tls_domain_str(d));
1053
+			unsigned long e = 0;
1054
+			e = ERR_peek_last_error();
1055
+			ERR("%s: Cannot create SSL context [%d] (%lu: %s / %s)\n",
1056
+					tls_domain_str(d), i, e, ERR_error_string(e, NULL),
1057
+					ERR_reason_error_string(e));
1050 1058
 			return -1;
1051 1059
 		}
1052 1060
 		if(d->method>TLS_USE_TLSvRANGE) {
Browse code

tls: proper match of config profile by server id

Daniel-Constantin Mierla authored on 21/01/2020 16:20:19
Showing 1 changed files
... ...
@@ -1543,7 +1543,7 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1543 1543
 				p->server_id.len, ZSW(p->server_id.s),
1544 1544
 				srvid->len, ZSW(srvid->s));
1545 1545
 			if(p->server_id.s && p->server_id.len==srvid->len
1546
-					&& strncasecmp(p->server_name.s, srvid->s, srvid->len)==0) {
1546
+					&& strncasecmp(p->server_id.s, srvid->s, srvid->len)==0) {
1547 1547
 				LM_DBG("TLS config found by server id\n");
1548 1548
 				return p;
1549 1549
 			}
Browse code

tls: init EVP_PKEY pointer when loading engine key

Daniel-Constantin Mierla authored on 10/12/2019 11:46:34
Showing 1 changed files
... ...
@@ -1194,7 +1194,7 @@ EVP_PKEY* tls_lookup_private_key(SSL_CTX* ctx)
1194 1194
 static int load_engine_private_key(tls_domain_t* d)
1195 1195
 {
1196 1196
 	int idx, ret_pwd, i;
1197
-	EVP_PKEY *pkey;
1197
+	EVP_PKEY *pkey = 0;
1198 1198
 	int procs_no;
1199 1199
 	char ctx_str[64];
1200 1200
 
Browse code

tls: add verify_client support (#2166)

* tls: add verify_client support

* tls: fix error in forward-port

* tls: docbook update

Armen Babikyan authored on 09/12/2019 20:02:53 • Daniel-Constantin Mierla committed on 09/12/2019 20:02:53
Showing 1 changed files
... ...
@@ -49,6 +49,7 @@ extern EVP_PKEY * tls_engine_private_key(const char* key_id);
49 49
 #include "tls_init.h"
50 50
 #include "tls_domain.h"
51 51
 #include "tls_cfg.h"
52
+#include "tls_verify.h"
52 53
 
53 54
 /*
54 55
  * ECDHE is enabled only on OpenSSL 1.0.0e and later.
... ...
@@ -174,6 +175,7 @@ tls_domain_t* tls_new_domain(int type, struct ip_addr *ip, unsigned short port)
174 175
 	d->verify_cert = -1;
175 176
 	d->verify_depth = -1;
176 177
 	d->require_cert = -1;
178
+	d->verify_client = -1;
177 179
 	return d;
178 180
 }
179 181
 
... ...
@@ -353,6 +355,9 @@ static int ksr_tls_fill_missing(tls_domain_t* d, tls_domain_t* parent)
353 355
 	if (d->verify_depth == -1) d->verify_depth = parent->verify_depth;
354 356
 	LOG(L_INFO, "%s: verify_depth=%d\n", tls_domain_str(d), d->verify_depth);
355 357
 
358
+	if (d->verify_client == -1) d->verify_client = parent->verify_client;
359
+	LOG(L_INFO, "%s: verify_client=%d\n", tls_domain_str(d), d->verify_client);
360
+
356 361
 	return 0;
357 362
 }
358 363
 
... ...
@@ -686,12 +691,12 @@ static int set_verification(tls_domain_t* d)
686 691
 	int verify_mode, i;
687 692
 	int procs_no;
688 693
 
689
-	if (d->require_cert) {
694
+	if (d->require_cert || d->verify_client == TLS_VERIFY_CLIENT_ON) {
690 695
 		verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
691 696
 		LOG(L_INFO, "%s: %s MUST present valid certificate\n", 
692 697
 			tls_domain_str(d), d->type & TLS_DOMAIN_SRV ? "Client" : "Server");
693 698
 	} else {
694
-		if (d->verify_cert) {
699
+		if (d->verify_cert || d->verify_client >= TLS_VERIFY_CLIENT_OPTIONAL) {
695 700
 			verify_mode = SSL_VERIFY_PEER;
696 701
 			if (d->type & TLS_DOMAIN_SRV) {
697 702
 				LOG(L_INFO, "%s: IF client provides certificate then it"
... ...
@@ -711,12 +716,17 @@ static int set_verification(tls_domain_t* d)
711 716
 			}
712 717
 		}
713 718
 	}
714
-	
719
+
715 720
 	procs_no=get_max_procs();
716 721
 	for(i = 0; i < procs_no; i++) {
717
-		SSL_CTX_set_verify(d->ctx[i], verify_mode, 0);
722
+		if (d->verify_client >= TLS_VERIFY_CLIENT_OPTIONAL_NO_CA) {
723
+			/* Note that actual verification result is available in $tls_peer_verified */
724
+			SSL_CTX_set_verify(d->ctx[i], verify_mode, verify_callback_unconditional_success);
725
+		} else {
726
+			SSL_CTX_set_verify(d->ctx[i], verify_mode, 0);
727
+		}
718 728
 		SSL_CTX_set_verify_depth(d->ctx[i], d->verify_depth);
719
-		
729
+
720 730
 	}
721 731
 	return 0;
722 732
 }
Browse code

tls: proper dot position for matching subdomains

- reported by GH #2049

Daniel-Constantin Mierla authored on 29/08/2019 16:51:17
Showing 1 changed files
... ...
@@ -1563,7 +1563,7 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1563 1563
 				if ((p->server_name_mode==KSR_TLS_SNM_INCDOM
1564 1564
 							|| p->server_name_mode==KSR_TLS_SNM_SUBDOM)
1565 1565
 						&& (p->server_name.len<sname->len)) {
1566
-					dotpos = sname->len - p->server_name.len;
1566
+					dotpos = sname->len - p->server_name.len - 1;
1567 1567
 					if(sname->s[dotpos] == '.'
1568 1568
 							&& strncasecmp(p->server_name.s,
1569 1569
 									sname->s + dotpos + 1,
Browse code

tls: register SNI callback for server default profile

- make SNI work for other profile when the default one does not have
server_name
- GH #1938

Daniel-Constantin Mierla authored on 20/05/2019 08:56:08
Showing 1 changed files
... ...
@@ -1061,17 +1061,20 @@ static int ksr_tls_fix_domain(tls_domain_t* d, tls_domain_t* def)
1061 1061
 		* check server domains for server_name extension and register
1062 1062
 		* callback function
1063 1063
 		*/
1064
-		if ((d->type & TLS_DOMAIN_SRV) && d->server_name.len>0) {
1064
+		if ((d->type & TLS_DOMAIN_SRV)
1065
+				&& (d->server_name.len>0 || (d->type & TLS_DOMAIN_DEF))) {
1065 1066
 			if (!SSL_CTX_set_tlsext_servername_callback(d->ctx[i], tls_server_name_cb)) {
1066 1067
 				LM_ERR("register server_name callback handler for socket "
1067 1068
 					"[%s:%d], server_name='%s' failed for proc %d\n",
1068
-					ip_addr2a(&d->ip), d->port, d->server_name.s, i);
1069
+					ip_addr2a(&d->ip), d->port,
1070
+					(d->server_name.s)?d->server_name.s:"<default>", i);
1069 1071
 				return -1;
1070 1072
 			}
1071 1073
 			if (!SSL_CTX_set_tlsext_servername_arg(d->ctx[i], d)) {
1072 1074
 				LM_ERR("register server_name callback handler data for socket "
1073 1075
 					"[%s:%d], server_name='%s' failed for proc %d\n",
1074
-					ip_addr2a(&d->ip), d->port, d->server_name.s, i);
1076
+					ip_addr2a(&d->ip), d->port,
1077
+					(d->server_name.s)?d->server_name.s:"<default>", i);
1075 1078
 				return -1;
1076 1079
 			}
1077 1080
 		}
... ...
@@ -1079,10 +1082,11 @@ static int ksr_tls_fix_domain(tls_domain_t* d, tls_domain_t* def)
1079 1082
 	}
1080 1083
 
1081 1084
 #ifndef OPENSSL_NO_TLSEXT
1082
-	if ((d->type & TLS_DOMAIN_SRV) && d->server_name.len>0) {
1085
+	if ((d->type & TLS_DOMAIN_SRV)
1086
+			&& (d->server_name.len>0 || (d->type & TLS_DOMAIN_DEF))) {
1083 1087
 		LM_NOTICE("registered server_name callback handler for socket "
1084 1088
 			"[%s:%d], server_name='%s' ...\n", ip_addr2a(&d->ip), d->port,
1085
-			d->server_name.s);
1089
+			(d->server_name.s)?d->server_name.s:"<default>");
1086 1090
 	}
1087 1091
 #endif
1088 1092
 
Browse code

tls: check tls domain cfg duplication after parsing all attributes

- allows definition of domain profiles with same address but different
server_name (SNI)

Daniel-Constantin Mierla authored on 06/09/2018 08:03:21
Showing 1 changed files
... ...
@@ -272,6 +272,12 @@ char* tls_domain_str(tls_domain_t* d)
272 272
 	p = strcat(p, d->type & TLS_DOMAIN_SRV ? "TLSs<" : "TLSc<");
273 273
 	if (d->type & TLS_DOMAIN_DEF) {
274 274
 		p = strcat(p, "default>");
275
+	} else if (d->type & TLS_DOMAIN_ANY) {
276
+		p = strcat(p, "any:");
277
+		if(d->server_name.s && d->server_name.len>0) {
278
+			p = strncat(p, d->server_name.s, d->server_name.len);
279
+		}
280
+		p = strcat(p, ">");
275 281
 	} else {
276 282
 		p = strcat(p, ip_addr2a(&d->ip));
277 283
 		p = strcat(p, ":");
... ...
@@ -291,7 +297,7 @@ char* tls_domain_str(tls_domain_t* d)
291 297
  * @param parent parent domain
292 298
  * @return 0 on success, -1 on error
293 299
  */
294
-static int fill_missing(tls_domain_t* d, tls_domain_t* parent)
300
+static int ksr_tls_fill_missing(tls_domain_t* d, tls_domain_t* parent)
295 301
 {
296 302
 	if (d->method == TLS_METHOD_UNSPEC) d->method = parent->method;
297 303
 	LOG(L_INFO, "%s: tls_method=%d\n", tls_domain_str(d), d->method);
... ...
@@ -983,12 +989,20 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
983 989
  * @param d initialized TLS domain
984 990
  * @param def default TLS domains
985 991
  */
986
-static int fix_domain(tls_domain_t* d, tls_domain_t* def)
992
+static int ksr_tls_fix_domain(tls_domain_t* d, tls_domain_t* def)
987 993
 {
988 994
 	int i;
989 995
 	int procs_no;
990 996
 
991
-	if (fill_missing(d, def) < 0) return -1;
997
+	if (ksr_tls_fill_missing(d, def) < 0) return -1;
998
+
999
+	if(d->type & TLS_DOMAIN_ANY) {
1000
+		if(d->server_name.s==NULL || d->server_name.len<0) {
1001
+			LM_ERR("%s: tls domain for any address but no server name\n",
1002
+					tls_domain_str(d));
1003
+			return -1;
1004
+		}
1005
+	}
992 1006
 
993 1007
 	procs_no=get_max_procs();
994 1008
 	d->ctx = (SSL_CTX**)shm_malloc(sizeof(SSL_CTX*) * procs_no);
... ...
@@ -1354,18 +1368,18 @@ int tls_fix_domains_cfg(tls_domains_cfg_t* cfg, tls_domain_t* srv_defaults,
1354 1368
 											0, 0);
1355 1369
 	}
1356 1370
 
1357
-	if (fix_domain(cfg->srv_default, srv_defaults) < 0) return -1;
1358
-	if (fix_domain(cfg->cli_default, cli_defaults) < 0) return -1;
1371
+	if (ksr_tls_fix_domain(cfg->srv_default, srv_defaults) < 0) return -1;
1372
+	if (ksr_tls_fix_domain(cfg->cli_default, cli_defaults) < 0) return -1;
1359 1373
 
1360 1374
 	d = cfg->srv_list;
1361 1375
 	while (d) {
1362
-		if (fix_domain(d, srv_defaults) < 0) return -1;
1376
+		if (ksr_tls_fix_domain(d, srv_defaults) < 0) return -1;
1363 1377
 		d = d->next;
1364 1378
 	}
1365 1379
 
1366 1380
 	d = cfg->cli_list;
1367 1381
 	while (d) {
1368
-		if (fix_domain(d, cli_defaults) < 0) return -1;
1382
+		if (ksr_tls_fix_domain(d, cli_defaults) < 0) return -1;
1369 1383
 		d = d->next;
1370 1384
 	}
1371 1385
 
... ...
@@ -1571,18 +1585,27 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1571 1585
 
1572 1586
 
1573 1587
 /**
1574
- * @brief Check whether configuration domain exists
1588
+ * @brief Check whether configuration domain is duplicated
1575 1589
  * @param cfg configuration set
1576 1590
  * @param d checked domain
1577
- * @return 1 if domain exists, 0 if its not exists
1591
+ * @return 1 if domain is duplicated, 0 if it's not
1578 1592
  */
1579
-static int domain_exists(tls_domains_cfg_t* cfg, tls_domain_t* d)
1593
+int ksr_tls_domain_duplicated(tls_domains_cfg_t* cfg, tls_domain_t* d)
1580 1594
 {
1581 1595
 	tls_domain_t *p;
1582 1596
 
1583 1597
 	if (d->type & TLS_DOMAIN_DEF) {
1584
-		if (d->type & TLS_DOMAIN_SRV) return cfg->srv_default != NULL;
1585
-		else return cfg->cli_default != NULL;
1598
+		if (d->type & TLS_DOMAIN_SRV) {
1599
+			if(cfg->srv_default==d) {
1600
+				return 0;
1601
+			}
1602
+			return cfg->srv_default != NULL;
1603
+		} else {
1604
+			if(cfg->cli_default==d) {
1605
+				return 0;
1606
+			}
1607
+			return cfg->cli_default != NULL;
1608
+		}
1586 1609
 	} else {
1587 1610
 		if (d->type & TLS_DOMAIN_SRV) p = cfg->srv_list;
1588 1611
 		else p = cfg->cli_list;
... ...
@@ -1594,17 +1617,19 @@ static int domain_exists(tls_domains_cfg_t* cfg, tls_domain_t* d)
1594 1617
 			LM_WARN("duplicate definition for a tls profile (same address)"
1595 1618
 					" and no server name provided\n");
1596 1619
 			return 1;
1620
+		} else {
1621
+			return 0;
1597 1622
 		}
1598
-	} else {
1599
-		return 0;
1600 1623
 	}
1601 1624
 
1602 1625
 	while (p) {
1603
-		if ((p->port == d->port) && ip_addr_cmp(&p->ip, &d->ip)) {
1604
-			if(d->server_name.len==0 || p->server_name.len==0) {
1605
-				LM_WARN("duplicate definition for a tls profile (same address)"
1606
-						" and no server name provided\n");
1607
-				return 1;
1626
+		if(p!=d) {
1627
+			if ((p->port == d->port) && ip_addr_cmp(&p->ip, &d->ip)) {
1628
+				if(d->server_name.len==0 || p->server_name.len==0) {
1629
+					LM_WARN("duplicate definition for a tls profile (same address)"
1630
+							" and no server name provided\n");
1631
+					return 1;
1632
+				}
1608 1633
 			}
1609 1634
 		}
1610 1635
 		p = p->next;
... ...
@@ -1627,9 +1652,6 @@ int tls_add_domain(tls_domains_cfg_t* cfg, tls_domain_t* d)
1627 1652
 		return -1;
1628 1653
 	}
1629 1654
 
1630
-	     /* Make sure the domain does not exist */
1631
-	if (domain_exists(cfg, d)) return 1;
1632
-
1633 1655
 	if (d->type & TLS_DOMAIN_DEF) {
1634 1656
 		if (d->type & TLS_DOMAIN_CLI) {
1635 1657
 			cfg->cli_default = d;
Browse code

tls: added server_name_mode attribute for tls domain profiles

- define how to match server_name (SNI):
* 0 - match only the domain
* 1 - match the domain and subdomains
* 2 - match only the subdomains

Daniel-Constantin Mierla authored on 05/09/2018 12:59:37
Showing 1 changed files
... ...
@@ -1498,6 +1498,7 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1498 1498
 		struct ip_addr* ip, unsigned short port, str *sname, str *srvid)
1499 1499
 {
1500 1500
 	tls_domain_t *p;
1501
+	int dotpos;
1501 1502
 
1502 1503
 	if (type & TLS_DOMAIN_DEF) {
1503 1504
 		if (type & TLS_DOMAIN_SRV) return cfg->srv_default;
... ...
@@ -1521,22 +1522,41 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1521 1522
 
1522 1523
 		}
1523 1524
 		if(sname) {
1524
-			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s] -- %d\n",
1525
+			LM_DBG("comparing addr: l[%s:%d]  r[%s:%d] -- sni: l[%.*s] r[%.*s] %d"
1526
+				" -- type: %d\n",
1525 1527
 				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
1526 1528
 				p->server_name.len, ZSW(p->server_name.s),
1527
-				sname->len, ZSW(sname->s), p->type);
1529
+				sname->len, ZSW(sname->s), p->server_name_mode, p->type);
1528 1530
 		}
1529 1531
 		if ((p->type & TLS_DOMAIN_ANY)
1530 1532
 				|| ((p->port==0 || p->port == port)
1531 1533
 						&& ip_addr_cmp(&p->ip, ip))) {
1532
-			if(sname && sname->len>0) {
1533
-				if(p->server_name.s && p->server_name.len==sname->len
1534
-					&& strncasecmp(p->server_name.s, sname->s, sname->len)==0) {
1535
-					LM_DBG("socket+server_name based TLS server domain found\n");
1536
-					return p;
1534
+			if(sname && sname->s && sname->len>0
1535
+						&& p->server_name.s && p->server_name.len>0) {
1536
+				if (p->server_name_mode!=KSR_TLS_SNM_SUBDOM) {
1537
+					/* match sni domain */
1538
+					if(p->server_name.len==sname->len
1539
+								&& strncasecmp(p->server_name.s, sname->s,
1540
+									sname->len)==0) {
1541
+						LM_DBG("socket+server_name based TLS server domain found\n");
1542
+						return p;
1543
+					}
1544
+				}
1545
+				if ((p->server_name_mode==KSR_TLS_SNM_INCDOM
1546
+							|| p->server_name_mode==KSR_TLS_SNM_SUBDOM)
1547
+						&& (p->server_name.len<sname->len)) {
1548
+					dotpos = sname->len - p->server_name.len;
1549
+					if(sname->s[dotpos] == '.'
1550
+							&& strncasecmp(p->server_name.s,
1551
+									sname->s + dotpos + 1,
1552
+									p->server_name.len)==0) {
1553
+						LM_DBG("socket+server_name based TLS server sub-domain found\n");
1554
+						return p;
1555
+					}
1537 1556
 				}
1538 1557
 			} else {
1539 1558
 				if (!(p->type & TLS_DOMAIN_ANY)) {
1559
+					LM_DBG("socket based TLS server domain found\n");
1540 1560
 					return p;
1541 1561
 				}
1542 1562
 			}
Browse code

tls: allow defining a tls profile (domain) for any address

- token 'any' or 'all' can be used instead of the address
[server:any] or [client:any]
- useful when the IP address/port to listen on is not known upfront or
many addresses are used to listen on
- such profiles can be defined many times and must have server_name attribute
(for SNI)

Daniel-Constantin Mierla authored on 05/09/2018 11:01:19
Showing 1 changed files
... ...
@@ -1521,12 +1521,14 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1521 1521
 
1522 1522
 		}
1523 1523
 		if(sname) {
1524
-			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s]\n",
1524
+			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s] -- %d\n",
1525 1525
 				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
1526 1526
 				p->server_name.len, ZSW(p->server_name.s),
1527
-				sname->len, ZSW(sname->s));
1527
+				sname->len, ZSW(sname->s), p->type);
1528 1528
 		}
1529
-		if ((p->port==0 || p->port == port) && ip_addr_cmp(&p->ip, ip)) {
1529
+		if ((p->type & TLS_DOMAIN_ANY)
1530
+				|| ((p->port==0 || p->port == port)
1531
+						&& ip_addr_cmp(&p->ip, ip))) {
1530 1532
 			if(sname && sname->len>0) {
1531 1533
 				if(p->server_name.s && p->server_name.len==sname->len
1532 1534
 					&& strncasecmp(p->server_name.s, sname->s, sname->len)==0) {
... ...
@@ -1534,13 +1536,15 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1534 1536
 					return p;
1535 1537
 				}
1536 1538
 			} else {
1537
-				return p;
1539
+				if (!(p->type & TLS_DOMAIN_ANY)) {
1540
+					return p;
1541
+				}
1538 1542
 			}
1539 1543
 		}
1540 1544
 		p = p->next;
1541 1545
 	}
1542 1546
 
1543
-	     /* No matching domain found, return default */
1547
+	/* No matching domain found, return default */
1544 1548
 	if (type & TLS_DOMAIN_SRV) return cfg->srv_default;
1545 1549
 	else return cfg->cli_default;
1546 1550
 }
... ...
@@ -1564,10 +1568,21 @@ static int domain_exists(tls_domains_cfg_t* cfg, tls_domain_t* d)
1564 1568
 		else p = cfg->cli_list;
1565 1569
 	}
1566 1570
 
1571
+	if(d->type & TLS_DOMAIN_ANY) {
1572
+		/* any address, it must have server_name for SNI */
1573
+		if(d->server_name.len==0) {
1574
+			LM_WARN("duplicate definition for a tls profile (same address)"
1575
+					" and no server name provided\n");
1576
+			return 1;
1577
+		}
1578
+	} else {
1579
+		return 0;
1580
+	}
1581
+
1567 1582
 	while (p) {
1568 1583
 		if ((p->port == d->port) && ip_addr_cmp(&p->ip, &d->ip)) {
1569
-			if(p->server_name.len==0) {
1570
-				LM_WARN("another tls domain with same address was defined"
1584
+			if(d->server_name.len==0 || p->server_name.len==0) {
1585
+				LM_WARN("duplicate definition for a tls profile (same address)"
1571 1586
 						" and no server name provided\n");
1572 1587
 				return 1;
1573 1588
 			}
Browse code

tls: add support for OpenSSL engine and private keys in HSM

- add support for OpenSSL engine and loading private keys from HSM
- for when kamailio is a TLS edge proxy and needs to use HSM
- currently we initialize the engine in worker processes as PKCS#11
libraries are not guaranteed to be fork() safe

- new config params
- engine: name the OpenSSL engine
- engine_config: an OpenSSL config format file used to bootstrap engines
- engine_algorithms: list of algorithms to delegate to the engine

- tested with Gemalto SafeNet Luna (AWS CloudHSM) with RSA and EC private keys
TLSv1.2 and PFS cipher suites

AntonyA authored on 15/03/2018 13:41:29
Showing 1 changed files
... ...
@@ -27,6 +27,13 @@
27 27
 #include <stdlib.h>
28 28
 #include <openssl/ssl.h>
29 29
 #include <openssl/opensslv.h>
30
+
31
+#ifndef OPENSSL_NO_ENGINE
32
+#include <openssl/engine.h>
33
+#include "tls_map.h"
34
+extern EVP_PKEY * tls_engine_private_key(const char* key_id);
35
+#endif
36
+
30 37
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
31 38
 # include <openssl/ui.h>
32 39
 #endif
... ...
@@ -1113,7 +1120,109 @@ err:
1113 1120
 #endif
1114 1121
 }
1115 1122
 
1123
+#ifndef OPENSSL_NO_ENGINE
1124
+/*
1125
+ * Implement a hash map from SSL_CTX to private key
1126
+ * as HSM keys need to be process local
1127
+ */
1128
+static map_void_t private_key_map;
1129
+
1130
+/**
1131
+ * @brief Return a private key from the lookup table
1132
+ * @param p SSL_CTX*
1133
+ * @return EVP_PKEY on success, NULL on error
1134
+ */
1135
+EVP_PKEY* tls_lookup_private_key(SSL_CTX* ctx)
1136
+{
1137
+	void *pkey;
1138
+	char ctx_str[64];
1139
+	snprintf(ctx_str, 64, "SSL_CTX-%p", ctx);
1140
+	pkey =  map_get(&private_key_map, ctx_str);
1141
+	LM_DBG("Private key lookup for %s: %p\n", ctx_str, pkey);
1142
+	if (pkey)
1143
+		return *(EVP_PKEY**)pkey;
1144
+	else
1145
+		return NULL;
1146
+}
1147
+
1148
+
1149
+
1150
+/**
1151
+ * @brief Load a private key from an OpenSSL engine
1152
+ * @param d TLS domain
1153
+ * @return 0 on success, -1 on error
1154
+ *
1155
+ * Do this in mod_child() as PKCS#11 libraries are not guaranteed
1156
+ * to be fork() safe
1157
+ *
1158
+ * private_key setting which starts with /engine: is assumed to be
1159
+ * an HSM key and not a file-based key
1160
+ *
1161
+ * We store the private key in a local memory hash table as
1162
+ * HSM keys must be process-local. We use the SSL_CTX* address
1163
+ * as the key. We cannot put the key into d->ctx[i] as that is
1164
+ * in shared memory.
1165
+ */
1166
+static int load_engine_private_key(tls_domain_t* d)
1167
+{
1168
+	int idx, ret_pwd, i;
1169
+	EVP_PKEY *pkey;
1170
+	int procs_no;
1171
+	char ctx_str[64];
1172
+
1173
+	if (!d->pkey_file.s || !d->pkey_file.len) {
1174
+		DBG("%s: No private key specified\n", tls_domain_str(d));
1175
+		return 0;
1176
+	}
1177
+	if (strncmp(d->pkey_file.s, "/engine:", 8) != 0)
1178
+		return 0;
1179
+	procs_no = get_max_procs();
1180
+	for (i = 0; i<procs_no; i++) {
1181
+		snprintf(ctx_str, 64, "SSL_CTX-%p", d->ctx[i]);
1182
+		for(idx = 0, ret_pwd = 0; idx < 3; idx++) {
1183
+			if (i) {
1184
+				map_set(&private_key_map, ctx_str, pkey);
1185
+				ret_pwd = 1;
1186
+			} else {
1187
+				pkey = tls_engine_private_key(d->pkey_file.s+8);
1188
+				if (pkey) {
1189
+					map_set(&private_key_map, ctx_str, pkey);
1190
+					// store the key for i = 0 to perform certificate sanity check
1191
+					ret_pwd = SSL_CTX_use_PrivateKey(d->ctx[i], pkey);
1192
+				} else {
1193
+					ret_pwd = 0;
1194
+				}
1195
+			}
1196
+			if (ret_pwd) {
1197
+				break;
1198
+			} else {
1199
+				ERR("%s: Unable to load private key '%s'\n",
1200
+				    tls_domain_str(d), d->pkey_file.s);
1201
+				TLS_ERR("load_private_key:");
1202
+				continue;
1203
+			}
1204
+		}
1205
+
1206
+		if (!ret_pwd) {
1207
+			ERR("%s: Unable to load engine key label '%s'\n",
1208
+			    tls_domain_str(d), d->pkey_file.s);
1209
+			TLS_ERR("load_private_key:");
1210
+			return -1;
1211
+		}
1212
+		if (i == 0 && !SSL_CTX_check_private_key(d->ctx[i])) {
1213
+			ERR("%s: Key '%s' does not match the public key of the"
1214
+			    " certificate\n", tls_domain_str(d), d->pkey_file.s);
1215
+			TLS_ERR("load_engine_private_key:");
1216
+			return -1;
1217
+		}
1218
+	}
1219
+
1116 1220
 
1221
+	LM_INFO("%s: Key '%s' successfully loaded\n",
1222
+		tls_domain_str(d), d->pkey_file.s);
1223
+	return 0;
1224
+}
1225
+#endif
1117 1226
 /**
1118 1227
  * @brief Load a private key from a file 
1119 1228
  * @param d TLS domain
... ...
@@ -1137,8 +1246,19 @@ static int load_private_key(tls_domain_t* d)
1137 1246
 		SSL_CTX_set_default_passwd_cb_userdata(d->ctx[i], d->pkey_file.s);
1138 1247
 		
1139 1248
 		for(idx = 0, ret_pwd = 0; idx < 3; idx++) {
1249
+#ifndef OPENSSL_NO_ENGINE
1250
+			// in PROC_INIT skip loading HSM keys due to
1251
+			// fork() issues with PKCS#11 libaries
1252
+			if (strncmp(d->pkey_file.s, "/engine:", 8) != 0) {
1253
+				ret_pwd = SSL_CTX_use_PrivateKey_file(d->ctx[i], d->pkey_file.s,
1254
+					SSL_FILETYPE_PEM);
1255
+			} else {
1256
+				ret_pwd = 1;
1257
+			}
1258
+#else
1140 1259
 			ret_pwd = SSL_CTX_use_PrivateKey_file(d->ctx[i], d->pkey_file.s,
1141 1260
 					SSL_FILETYPE_PEM);
1261
+#endif
1142 1262
 			if (ret_pwd) {
1143 1263
 				break;
1144 1264
 			} else {
... ...
@@ -1155,7 +1275,12 @@ static int load_private_key(tls_domain_t* d)
1155 1275
 			TLS_ERR("load_private_key:");
1156 1276
 			return -1;
1157 1277
 		}
1158
-		
1278
+#ifndef OPENSSL_NO_ENGINE
1279
+		if (strncmp(d->pkey_file.s, "/engine:", 8) == 0) {
1280
+			// skip private key validity check for HSM keys
1281
+			continue;
1282
+		}
1283
+#endif
1159 1284
 		if (!SSL_CTX_check_private_key(d->ctx[i])) {
1160 1285
 			ERR("%s: Key '%s' does not match the public key of the"
1161 1286
 					" certificate\n", tls_domain_str(d), d->pkey_file.s);
... ...
@@ -1170,6 +1295,36 @@ static int load_private_key(tls_domain_t* d)
1170 1295
 }
1171 1296
 
1172 1297
 
1298