Browse code

tls: option to match TLS client config profile based on server_id

- server_id can be any string that uniquely identifies a client config
profile, overriding the attempt to match on ip:port (+sni). This makes
it easier to select the desired config profile, because the port is
hard to guess for stream connections
- prameter xavp_cfg has to be enabled and inner xavp 'server_id' has to
be set before relaying the sip message (before opening the client
connection)

Daniel-Constantin Mierla authored on 12/11/2015 13:38:07
Showing 6 changed files
... ...
@@ -36,6 +36,7 @@ struct cfg_group_tls default_tls_cfg = {
36 36
 	0, /* tls_force_run */
37 37
 	STR_STATIC_INIT("TLSv1"), /* method */
38 38
 	STR_NULL, /* server name (sni) */
39
+	STR_NULL, /* server id */
39 40
 	0, /* verify_certificate */
40 41
 	9, /* verify_depth */
41 42
 	0, /* require_certificate */
... ...
@@ -142,6 +143,8 @@ cfg_def_t	tls_cfg_def[] = {
142 142
 		"TLS method used (TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23)"},
143 143
 	{"server_name",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
144 144
 		"Server name (SNI)"},
145
+	{"server_id",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
146
+		"Server id (match tls profile for outgoing connections)"},
145 147
 	{"verify_certificate", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
146 148
 		"if enabled the certificates will be verified" },
147 149
 	{"verify_depth", CFG_VAR_INT | CFG_READONLY, 0, 100, 0, 0,
... ...
@@ -42,6 +42,7 @@ struct cfg_group_tls {
42 42
 	int force_run;
43 43
 	str method;
44 44
 	str server_name;
45
+	str server_id;
45 46
 	int verify_cert;
46 47
 	int verify_depth;
47 48
 	int require_cert;
... ...
@@ -164,6 +164,7 @@ static cfg_option_t options[] = {
164 164
 	{"ca_list",             .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
165 165
 	{"crl",                 .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
166 166
 	{"server_name",         .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
167
+	{"server_id",           .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
167 168
 	{0}
168 169
 };
169 170
 
... ...
@@ -188,6 +189,7 @@ static void update_opt_variables(void)
188 188
 	options[13].param = &domain->ca_file;
189 189
 	options[14].param = &domain->crl_file;
190 190
 	options[15].param = &domain->server_name;
191
+	options[16].param = &domain->server_id;
191 192
 }
192 193
 
193 194
 
... ...
@@ -182,6 +182,8 @@ void tls_free_domain(tls_domain_t* d)
182 182
 	if (d->crl_file.s) shm_free(d->crl_file.s);
183 183
 	if (d->pkey_file.s) shm_free(d->pkey_file.s);
184 184
 	if (d->cert_file.s) shm_free(d->cert_file.s);
185
+	if (d->server_name.s) shm_free(d->server_name.s);
186
+	if (d->server_id.s) shm_free(d->server_id.s);
185 187
 	shm_free(d);
186 188
 }
187 189
 
... ...
@@ -904,7 +906,7 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
904 904
 	server_name.len = strlen(server_name.s);
905 905
 
906 906
 	new_domain = tls_lookup_cfg(*tls_domains_cfg, TLS_DOMAIN_SRV,
907
-			&orig_domain->ip, orig_domain->port, &server_name);
907
+			&orig_domain->ip, orig_domain->port, &server_name, 0);
908 908
 	if (new_domain==NULL) {
909 909
 		LM_DBG("TLS domain for socket [%s:%d] and server_name='%s' "
910 910
 			"not found\n", ip_addr2a(&orig_domain->ip),
... ...
@@ -1289,7 +1291,7 @@ tls_domains_cfg_t* tls_new_cfg(void)
1289 1289
  * @return found configuration or default, if not found
1290 1290
  */
1291 1291
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1292
-		struct ip_addr* ip, unsigned short port, str *sname)
1292
+		struct ip_addr* ip, unsigned short port, str *sname, str *srvid)
1293 1293
 {
1294 1294
 	tls_domain_t *p;
1295 1295
 
... ...
@@ -1302,6 +1304,18 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
1302 1302
 	}
1303 1303
 
1304 1304
 	while (p) {
1305
+		if(srvid && srvid->len>0) {
1306
+			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- id: [%.*s] [%.*s]\n",
1307
+				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
1308
+				p->server_id.len, ZSW(p->server_id.s),
1309
+				srvid->len, ZSW(srvid->s));
1310
+			if(p->server_id.s && p->server_id.len==srvid->len
1311
+					&& strncasecmp(p->server_name.s, srvid->s, srvid->len)==0) {
1312
+				LM_DBG("TLS config found by server id\n");
1313
+				return p;
1314
+			}
1315
+
1316
+		}
1305 1317
 		if(sname) {
1306 1318
 			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s]\n",
1307 1319
 				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
... ...
@@ -106,6 +106,7 @@ typedef struct tls_domain {
106 106
 	enum tls_method method;
107 107
 	str crl_file;
108 108
 	str server_name;
109
+	str server_id;
109 110
 	struct tls_domain* next;
110 111
 } tls_domain_t;
111 112
 
... ...
@@ -194,7 +195,7 @@ int tls_fix_domains_cfg(tls_domains_cfg_t* cfg, tls_domain_t* srv_defaults,
194 194
  * @return found configuration or default, if not found
195 195
  */
196 196
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
197
-				struct ip_addr* ip, unsigned short port, str *sname);
197
+			struct ip_addr* ip, unsigned short port, str *sname, str *srvid);
198 198
 
199 199
 
200 200
 /**
... ...
@@ -130,6 +130,21 @@ int tls_run_event_routes(struct tcp_connection *c);
130 130
 
131 131
 extern str sr_tls_xavp_cfg;
132 132
 
133
+static str *tls_get_connect_server_id(void)
134
+{
135
+	sr_xavp_t *vavp = NULL;
136
+	str sid = {"server_id", 9};
137
+	if(sr_tls_xavp_cfg.s!=NULL)
138
+		vavp = xavp_get_child_with_sval(&sr_tls_xavp_cfg, &sid);
139
+	if(vavp==NULL || vavp->val.v.s.len<=0) {
140
+		LM_DBG("xavp with outbound server id not found\n");
141
+		return NULL;
142
+	}
143
+	LM_DBG("found xavp with outbound server id: %s\n", vavp->val.v.s.s);
144
+	return &vavp->val.v.s;
145
+
146
+}
147
+
133 148
 /**
134 149
  * get the server name (sni) for outbound connections from xavp
135 150
  */
... ...
@@ -167,6 +182,7 @@ static int tls_complete_init(struct tcp_connection* c)
167 167
 	tls_domains_cfg_t* cfg;
168 168
 	enum tls_conn_states state;
169 169
 	str *sname = NULL;
170
+	str *srvid = NULL;
170 171
 
171 172
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
172 173
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
... ...
@@ -192,12 +208,13 @@ static int tls_complete_init(struct tcp_connection* c)
192 192
 	if (c->flags & F_CONN_PASSIVE) {
193 193
 		state=S_TLS_ACCEPTING;
194 194
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
195
-								&c->rcv.dst_ip, c->rcv.dst_port, 0);
195
+								&c->rcv.dst_ip, c->rcv.dst_port, 0, 0);
196 196
 	} else {
197 197
 		state=S_TLS_CONNECTING;
198 198
 		sname = tls_get_connect_server_name();
199
+		srvid = tls_get_connect_server_id();
199 200
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
200
-						&c->rcv.dst_ip, c->rcv.dst_port, sname);
201
+						&c->rcv.dst_ip, c->rcv.dst_port, sname, srvid);
201 202
 	}
202 203
 	if (unlikely(c->state<0)) {
203 204
 		BUG("Invalid connection (state %d)\n", c->state);