Pārlūkot izejas kodu

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 7 gadi atpakaļ
vecāks
revīzija
7dbe407d31

+ 3 - 0
src/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) */
+	0, /* server name (sni) mode */
 	STR_NULL, /* server id */
 	0, /* verify_certificate */
 	9, /* verify_depth */
@@ -143,6 +144,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_name_mode", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
+		"Server name (SNI) mode" },
 	{"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,

+ 1 - 0
src/modules/tls/tls_cfg.h

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

+ 3 - 1
src/modules/tls/tls_config.c

@@ -170,6 +170,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_name_mode",    .f = cfg_parse_int_opt},
 	{"server_id",           .f = cfg_parse_str_opt, .flags = CFG_STR_SHMMEM},
 	{0}
 };
@@ -195,7 +196,8 @@ 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;
+	options[16].param = &domain->server_name_mode;
+	options[17].param = &domain->server_id;
 }
 
 

+ 27 - 7
src/modules/tls/tls_domain.c

@@ -1498,6 +1498,7 @@ tls_domain_t* tls_lookup_cfg(tls_domains_cfg_t* cfg, int type,
 		struct ip_addr* ip, unsigned short port, str *sname, str *srvid)
 {
 	tls_domain_t *p;
+	int dotpos;
 
 	if (type & TLS_DOMAIN_DEF) {
 		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,
 
 		}
 		if(sname) {
-			LM_DBG("comparing addr: [%s:%d]  [%s:%d] -- sni: [%.*s] [%.*s] -- %d\n",
+			LM_DBG("comparing addr: l[%s:%d]  r[%s:%d] -- sni: l[%.*s] r[%.*s] %d"
+				" -- type: %d\n",
 				ip_addr2a(&p->ip), p->port, ip_addr2a(ip), port,
 				p->server_name.len, ZSW(p->server_name.s),
-				sname->len, ZSW(sname->s), p->type);
+				sname->len, ZSW(sname->s), p->server_name_mode, p->type);
 		}
 		if ((p->type & TLS_DOMAIN_ANY)
 				|| ((p->port==0 || p->port == port)
 						&& ip_addr_cmp(&p->ip, ip))) {
-			if(sname && sname->len>0) {
-				if(p->server_name.s && p->server_name.len==sname->len
-					&& strncasecmp(p->server_name.s, sname->s, sname->len)==0) {
-					LM_DBG("socket+server_name based TLS server domain found\n");
-					return p;
+			if(sname && sname->s && sname->len>0
+						&& p->server_name.s && p->server_name.len>0) {
+				if (p->server_name_mode!=KSR_TLS_SNM_SUBDOM) {
+					/* match sni domain */
+					if(p->server_name.len==sname->len
+								&& strncasecmp(p->server_name.s, sname->s,
+									sname->len)==0) {
+						LM_DBG("socket+server_name based TLS server domain found\n");
+						return p;
+					}
+				}
+				if ((p->server_name_mode==KSR_TLS_SNM_INCDOM
+							|| p->server_name_mode==KSR_TLS_SNM_SUBDOM)
+						&& (p->server_name.len<sname->len)) {
+					dotpos = sname->len - p->server_name.len;
+					if(sname->s[dotpos] == '.'
+							&& strncasecmp(p->server_name.s,
+									sname->s + dotpos + 1,
+									p->server_name.len)==0) {
+						LM_DBG("socket+server_name based TLS server sub-domain found\n");
+						return p;
+					}
 				}
 			} else {
 				if (!(p->type & TLS_DOMAIN_ANY)) {
+					LM_DBG("socket based TLS server domain found\n");
 					return p;
 				}
 			}

+ 4 - 1
src/modules/tls/tls_domain.h

@@ -88,7 +88,9 @@ enum tls_domain_type {
 	TLS_DOMAIN_ANY = (1 << 3)  /**< Any address */
 };
 
-
+#define KSR_TLS_SNM_STRICT 0 /**< Match server_name only */
+#define KSR_TLS_SNM_INCDOM 1 /**< Match server_name and subdomains */
+#define KSR_TLS_SNM_SUBDOM 2 /**< Match subdomains only */
 /**
  * separate configuration per ip:port
  */
@@ -107,6 +109,7 @@ typedef struct tls_domain {
 	enum tls_method method;
 	str crl_file;
 	str server_name;
+	int server_name_mode;
 	str server_id;
 	struct tls_domain* next;
 } tls_domain_t;

+ 3 - 0
src/modules/tls/tls_mod.c

@@ -103,6 +103,7 @@ static tls_domain_t mod_params = {
 	TLS_USE_TLSv1,    /* TLS method */
 	STR_STATIC_INIT(TLS_CRL_FILE), /* Certificate revocation list */
 	{0, 0},           /* Server name (SNI) */
+	0,                /* Server name (SNI) mode */
 	{0, 0},           /* Server id */
 	0                 /* next */
 };
@@ -126,6 +127,7 @@ tls_domain_t srv_defaults = {
 	TLS_USE_TLSv1,    /* TLS method */
 	STR_STATIC_INIT(TLS_CRL_FILE), /* Certificate revocation list */
 	{0, 0},           /* Server name (SNI) */
+	0,                /* Server name (SNI) mode */
 	{0, 0},           /* Server id */
 	0                 /* next */
 };
@@ -166,6 +168,7 @@ tls_domain_t cli_defaults = {
 	TLS_USE_TLSv1,    /* TLS method */
 	{0, 0}, /* Certificate revocation list */
 	{0, 0},           /* Server name (SNI) */
+	0,                /* Server name (SNI) mode */
 	{0, 0},           /* Server id */
 	0                 /* next */
 };