tls: added server_name_mode attribute for tls domain profiles
authorDaniel-Constantin Mierla <miconda@gmail.com>
Wed, 5 Sep 2018 12:59:37 +0000 (14:59 +0200)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Wed, 5 Sep 2018 12:59:37 +0000 (14:59 +0200)
- define how to match server_name (SNI):
  * 0 - match only the domain
  * 1 - match the domain and subdomains
  * 2 - match only the subdomains

src/modules/tls/tls_cfg.c
src/modules/tls/tls_cfg.h
src/modules/tls/tls_config.c
src/modules/tls/tls_domain.c
src/modules/tls/tls_domain.h
src/modules/tls/tls_mod.c

index e847b95..7bfa75a 100644 (file)
@@ -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,
index b164fc1..b4427dd 100644 (file)
@@ -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;
index a2cade2..3889026 100644 (file)
@@ -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;
 }
 
 
index dcafcdf..af2f03c 100644 (file)
@@ -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;
                                }
                        }
index a34a84a..334e2a0 100644 (file)
@@ -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;
index cf77a8b..ac2281b 100644 (file)
@@ -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 */
 };