2
0
Эх сурвалжийг харах

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 10 жил өмнө
parent
commit
4baf576076

+ 3 - 0
modules/tls/tls_cfg.c

@@ -36,6 +36,7 @@ struct cfg_group_tls default_tls_cfg = {
 	0, /* tls_force_run */
 	STR_STATIC_INIT("TLSv1"), /* method */
 	STR_NULL, /* server name (sni) */
+	STR_NULL, /* server id */
 	0, /* verify_certificate */
 	9, /* verify_depth */
 	0, /* require_certificate */
@@ -142,6 +143,8 @@ cfg_def_t	tls_cfg_def[] = {
 		"TLS method used (TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23)"},
 	{"server_name",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
 		"Server name (SNI)"},
+	{"server_id",   CFG_VAR_STR | CFG_READONLY, 0, 0, 0, 0,
+		"Server id (match tls profile for outgoing connections)"},
 	{"verify_certificate", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
 		"if enabled the certificates will be verified" },
 	{"verify_depth", CFG_VAR_INT | CFG_READONLY, 0, 100, 0, 0,

+ 1 - 0
modules/tls/tls_cfg.h

@@ -42,6 +42,7 @@ struct cfg_group_tls {
 	int force_run;
 	str method;
 	str server_name;
+	str server_id;
 	int verify_cert;
 	int verify_depth;
 	int require_cert;

+ 2 - 0
modules/tls/tls_config.c

@@ -164,6 +164,7 @@ static cfg_option_t options[] = {
 	{"ca_list",             .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{"crl",                 .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{"server_name",         .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
+	{"server_id",           .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{0}
 };
 
@@ -188,6 +189,7 @@ static void update_opt_variables(void)
 	options[13].param = &domain->ca_file;
 	options[14].param = &domain->crl_file;
 	options[15].param = &domain->server_name;
+	options[16].param = &domain->server_id;
 }
 
 

+ 16 - 2
modules/tls/tls_domain.c

@@ -182,6 +182,8 @@ void tls_free_domain(tls_domain_t* d)
 	if (d->crl_file.s) shm_free(d->crl_file.s);
 	if (d->pkey_file.s) shm_free(d->pkey_file.s);
 	if (d->cert_file.s) shm_free(d->cert_file.s);
+	if (d->server_name.s) shm_free(d->server_name.s);
+	if (d->server_id.s) shm_free(d->server_id.s);
 	shm_free(d);
 }
 
@@ -904,7 +906,7 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
 	server_name.len = strlen(server_name.s);
 
 	new_domain = tls_lookup_cfg(*tls_domains_cfg, TLS_DOMAIN_SRV,
-			&orig_domain->ip, orig_domain->port, &server_name);
+			&orig_domain->ip, orig_domain->port, &server_name, 0);
 	if (new_domain==NULL) {
 		LM_DBG("TLS domain for socket [%s:%d] and server_name='%s' "
 			"not found\n", ip_addr2a(&orig_domain->ip),
@@ -1289,7 +1291,7 @@ tls_domains_cfg_t* tls_new_cfg(void)
  * @return found configuration or default, if not found
  */
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
-		struct ip_addr* ip, unsigned short port, str *sname)
+		struct ip_addr* ip, unsigned short port, str *sname, str *srvid)
 {
 	tls_domain_t *p;
 
@@ -1302,6 +1304,18 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
 	}
 
 	while (p) {
+		if(srvid && srvid->len>0) {
+			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- id: [%.*s] [%.*s]\n",
+				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
+				p->server_id.len, ZSW(p->server_id.s),
+				srvid->len, ZSW(srvid->s));
+			if(p->server_id.s && p->server_id.len==srvid->len
+					&& strncasecmp(p->server_name.s, srvid->s, srvid->len)==0) {
+				LM_DBG("TLS config found by server id\n");
+				return p;
+			}
+
+		}
 		if(sname) {
 			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s]\n",
 				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,

+ 2 - 1
modules/tls/tls_domain.h

@@ -106,6 +106,7 @@ typedef struct tls_domain {
 	enum tls_method method;
 	str crl_file;
 	str server_name;
+	str server_id;
 	struct tls_domain* next;
 } tls_domain_t;
 
@@ -194,7 +195,7 @@ int tls_fix_domains_cfg(tls_domains_cfg_t* cfg, tls_domain_t* srv_defaults,
  * @return found configuration or default, if not found
  */
 tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
-				struct ip_addr* ip, unsigned short port, str *sname);
+			struct ip_addr* ip, unsigned short port, str *sname, str *srvid);
 
 
 /**

+ 19 - 2
modules/tls/tls_server.c

@@ -130,6 +130,21 @@ int tls_run_event_routes(struct tcp_connection *c);
 
 extern str sr_tls_xavp_cfg;
 
+static str *tls_get_connect_server_id(void)
+{
+	sr_xavp_t *vavp = NULL;
+	str sid = {"server_id", 9};
+	if(sr_tls_xavp_cfg.s!=NULL)
+		vavp = xavp_get_child_with_sval(&sr_tls_xavp_cfg, &sid);
+	if(vavp==NULL || vavp->val.v.s.len<=0) {
+		LM_DBG("xavp with outbound server id not found\n");
+		return NULL;
+	}
+	LM_DBG("found xavp with outbound server id: %s\n", vavp->val.v.s.s);
+	return &vavp->val.v.s;
+
+}
+
 /**
  * get the server name (sni) for outbound connections from xavp
  */
@@ -167,6 +182,7 @@ static int tls_complete_init(struct tcp_connection* c)
 	tls_domains_cfg_t* cfg;
 	enum tls_conn_states state;
 	str *sname = NULL;
+	str *srvid = NULL;
 
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
@@ -192,12 +208,13 @@ static int tls_complete_init(struct tcp_connection* c)
 	if (c->flags & F_CONN_PASSIVE) {
 		state=S_TLS_ACCEPTING;
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
-								&c->rcv.dst_ip, c->rcv.dst_port, 0);
+								&c->rcv.dst_ip, c->rcv.dst_port, 0, 0);
 	} else {
 		state=S_TLS_CONNECTING;
 		sname = tls_get_connect_server_name();
+		srvid = tls_get_connect_server_id();
 		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
-						&c->rcv.dst_ip, c->rcv.dst_port, sname);
+						&c->rcv.dst_ip, c->rcv.dst_port, sname, srvid);
 	}
 	if (unlikely(c->state<0)) {
 		BUG("Invalid connection (state %d)\n", c->state);