Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions modules/tls_mgm/doc/tls_mgm_admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ if (is_peer_verified()) {
<function moreinfo="none">tls_reload</function>
</title>
<para>
Reloads the TLS domains information from the database.
The previous DB defined domains are discarded but the
script defined domains are preserved.
Reloads all TLS domain information. Domains defined in the database are
re-queried, and script-defined domains are re-initialized (which
reloads their certificates and key files). The entire previous
domain configuration is discarded and replaced.
</para>
</section>
</section>
Expand Down
221 changes: 121 additions & 100 deletions modules/tls_mgm/tls_domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,20 @@
#include "../../lib/csv.h"
#include "tls_domain.h"
#include "tls_params.h"
#include "api.h"
#include <stdlib.h>
#include <fnmatch.h>


struct tls_domain **tls_server_domains;
struct tls_domain **tls_client_domains;

map_t server_dom_matching;
map_t client_dom_matching;
struct tls_domain **script_srv_domains_template;
struct tls_domain **script_cli_domains_template;

rw_lock_t *dom_lock;
map_t *server_dom_matching;
map_t *client_dom_matching;

extern struct openssl_binds openssl_api;
extern struct wolfssl_binds wolfssl_api;
rw_lock_t *dom_lock;

void destroy_tls_dom(struct tls_domain *d);

Expand All @@ -67,110 +66,50 @@ struct tls_domain *tls_find_domain_by_name(str *name, struct tls_domain **dom_li
return NULL;
}

struct tls_domain *find_first_script_dom(struct tls_domain *dom)
{
struct tls_domain *d;

for (d = dom; d && d->flags & DOM_FLAG_DB; d = d->next) ;

return d;
}

void map_free_node(void *val)
{
if (val)
shm_free(val);
}

void map_remove_tls_dom(struct tls_domain *dom)
{
map_t map = dom->flags & DOM_FLAG_SRV ? server_dom_matching : client_dom_matching;
map_iterator_t it, it_tmp;
struct dom_filt_array *doms_array;
void **val;
int i, j;

map_first(map, &it);
while (iterator_is_valid(&it)) {
it_tmp = it;
iterator_next(&it);

val = iterator_val(&it_tmp);
doms_array = (struct dom_filt_array *)*val;
for (i = 0; i < doms_array->size;)
if (doms_array->arr[i].dom_link == dom) {
for (j = i + 1; j < doms_array->size; j++)
doms_array->arr[j-1] = doms_array->arr[j];
doms_array->size--;
}
else {
i++;
}
if (doms_array->size == 0) {
map_free_node(doms_array);
iterator_delete(&it_tmp);
}
}
}

void tls_free_domain(struct tls_domain *dom)
void tls_release_domain(struct tls_domain *dom)
{
str_list *m_it, *m_tmp;
int free_it = 0;

dom->refs--;
if (dom->refs == 0) {
LM_DBG("Freeing domain: %.*s\n",
dom->name.len, dom->name.s);
if (!dom)
return;

destroy_tls_dom(dom);
lock_get(dom->lock);
if (--dom->refs == 0)
free_it = 1;
lock_release(dom->lock);

lock_destroy(dom->lock);
lock_dealloc(dom->lock);
if (!free_it)
return;

map_remove_tls_dom(dom);
LM_DBG("Freeing domain: %.*s\n",
dom->name.len, dom->name.s);

m_it = dom->match_domains;
while (m_it) {
m_tmp = m_it;
m_it = m_it->next;
shm_free(m_tmp);
}
m_it = dom->match_addresses;
while (m_it) {
m_tmp = m_it;
m_it = m_it->next;
shm_free(m_tmp);
}
destroy_tls_dom(dom);

shm_free(dom);
}
}

/* frees the DB domains */
void tls_free_db_domains(struct tls_domain *dom)
{
struct tls_domain *tmp;
lock_destroy(dom->lock);
lock_dealloc(dom->lock);

while (dom && dom->flags & DOM_FLAG_DB) {
tmp = dom;
dom = dom->next;
map_remove_tls_dom(tmp);
tls_free_domain(tmp);
m_it = dom->match_domains;
while (m_it) {
m_tmp = m_it;
m_it = m_it->next;
shm_free(m_tmp);
}
m_it = dom->match_addresses;
while (m_it) {
m_tmp = m_it;
m_it = m_it->next;
shm_free(m_tmp);
}
}

void tls_release_domain(struct tls_domain* dom)
{
if (!dom || !(dom->flags & DOM_FLAG_DB))
return;

if (dom_lock)
lock_start_write(dom_lock);

tls_free_domain(dom);

if (dom_lock)
lock_stop_write(dom_lock);
shm_free(dom);
}

int set_all_domain_attr(struct tls_domain **dom, char **str_vals, int *int_vals,
Expand Down Expand Up @@ -220,6 +159,13 @@ int set_all_domain_attr(struct tls_domain **dom, char **str_vals, int *int_vals,
if(blob_vals[BLOB_VALS_DHPARAMS_COL].len && blob_vals[BLOB_VALS_DHPARAMS_COL].s)
len += blob_vals[BLOB_VALS_DHPARAMS_COL].len;

if (d->name.len >= sizeof(name_buf)) {
LM_ERR("domain name '%.*s' is too long (max %zu chars)\n",
d->name.len, d->name.s, sizeof(name_buf) - 1);
*dom = d->next;
tls_release_domain(d);
return -1;
}
memcpy(name_buf, d->name.s, d->name.len);
name_len = d->name.len;

Expand Down Expand Up @@ -340,10 +286,10 @@ tls_find_server_domain(struct ip_addr *ip, unsigned short port)
addr_s.s = addr_buf;
addr_s.len = strlen(addr_buf);

val = map_find(server_dom_matching, addr_s);
val = map_find(*server_dom_matching, addr_s);
if (!val) {
/* try to find a domain which matches any address */
val = map_find(server_dom_matching, match_any_s);
val = map_find(*server_dom_matching, match_any_s);
if (!val) {
if (dom_lock)
lock_stop_read(dom_lock);
Expand Down Expand Up @@ -384,11 +330,11 @@ tls_find_domain_by_filters(struct ip_addr *ip, unsigned short port,
addr_s.len = strlen(addr_buf);

val = map_find(type == DOM_FLAG_SRV ?
server_dom_matching : client_dom_matching, addr_s);
*server_dom_matching : *client_dom_matching, addr_s);
if (!val) {
/* try to find domains which match any address */
val = map_find(type == DOM_FLAG_SRV ?
server_dom_matching : client_dom_matching, match_any_s);
*server_dom_matching : *client_dom_matching, match_any_s);
if (!val) {
if (dom_lock)
lock_stop_read(dom_lock);
Expand All @@ -399,6 +345,11 @@ tls_find_domain_by_filters(struct ip_addr *ip, unsigned short port,
dom_array = (struct dom_filt_array *)*val;

for (i = 0; i < dom_array->size; i++) {
if (domain_filter->len >= sizeof(fnm_s)) {
LM_WARN("domain filter '%.*s' too long, skipping match\n",
domain_filter->len, domain_filter->s);
continue;
}
memcpy(fnm_s, domain_filter->s, domain_filter->len);
fnm_s[domain_filter->len] = 0;
if (!fnmatch(dom_array->arr[i].hostname->s.s, fnm_s, 0)) {
Expand Down Expand Up @@ -554,6 +505,77 @@ int tls_new_domain(str *name, int type, struct tls_domain **dom)
return 0;
}


/*
* Creates a deep-copy of a TLS domain. This is only appropriate for
* script-defined domains that are instantiated from a template, as it
* performs a mix of shallow and deep copying.
*/
struct tls_domain* tls_copy_domain(struct tls_domain* d)
{
struct tls_domain *n;

if (!d) return NULL;

/* Allocate space for the struct and the domain name, like tls_new_domain */
n = shm_malloc(sizeof(struct tls_domain) + d->name.len);
if (!n) {
LM_ERR("No more shm mem\n");
return NULL;
}
memset(n, 0, sizeof(struct tls_domain));

/* copy config fields */
n->flags = d->flags;
n->verify_cert = d->verify_cert;
n->require_client_cert = d->require_client_cert;
n->crl_check_all = d->crl_check_all;
n->cert = d->cert;
n->pkey = d->pkey;
n->crl_directory = d->crl_directory;
n->ca = d->ca;
n->dh_param = d->dh_param;
n->tls_ec_curve = d->tls_ec_curve;
n->ca_directory = d->ca_directory;
n->ciphers_list = d->ciphers_list;
n->method_str = d->method_str;
n->method = d->method;
n->method_max = d->method_max;

/* Fix the name pointer and copy the content from the template */
n->name.s = (char*)(n + 1);
n->name.len = d->name.len;
memcpy(n->name.s, d->name.s, d->name.len);

/* Initialize runtime state that must not be shared from the template */
n->refs = 1;
n->lock = lock_alloc();
if (!n->lock || lock_init(n->lock) == NULL) {
LM_ERR("failed to init lock for domain clone\n");
if (n->lock) lock_dealloc(n->lock);
shm_free(n);
return NULL;
}

/*
* The matching lists are dynamically built in shm and freed by
* tls_free_domain, so they need a deep copy. Other config strings
* are pointers into the static config buffer and are correctly
* shallow-copied.
*/
if ((d->match_domains && !(n->match_domains = dup_shm_str_list(d->match_domains))) ||
(d->match_addresses && !(n->match_addresses = dup_shm_str_list(d->match_addresses)))
) {
goto error;
}

return n;

error:
if (n) tls_release_domain(n);
return NULL;
}

static int add_match_filt_to_dom(str *filter_s, str_list **filter_list)
{
str_list *match_filt;
Expand Down Expand Up @@ -768,16 +790,15 @@ int db_add_domain(char **str_vals, int *int_vals, str* blob_vals,
return 0;
}

int update_matching_map(struct tls_domain *tls_dom)
int update_matching_map(struct tls_domain *tls_dom, map_t matching_map)
{
str_list *addrf_s, *domf_s;
struct dom_filt_array *doms_array;
void **val;
int pos;

for (addrf_s = tls_dom->match_addresses; addrf_s; addrf_s = addrf_s->next) {
val = map_get(tls_dom->flags & DOM_FLAG_SRV ?
server_dom_matching : client_dom_matching, addrf_s->s);
val = map_get(matching_map, addrf_s->s);
if (!val) {
LM_ERR("No more shm memory!\n");
return -1;
Expand Down
24 changes: 10 additions & 14 deletions modules/tls_mgm/tls_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,19 @@ struct dom_filt_array {

#define ref_tls_dom(_d) \
do { \
if ((_d)->flags & DOM_FLAG_DB) { \
lock_get((_d)->lock); \
(_d)->refs++; \
lock_release((_d)->lock); \
} \
lock_get((_d)->lock); \
(_d)->refs++; \
lock_release((_d)->lock); \
} while (0)

extern struct tls_domain **tls_server_domains;
extern struct tls_domain **tls_client_domains;

extern map_t server_dom_matching;
extern map_t client_dom_matching;
extern struct tls_domain **script_srv_domains_template;
extern struct tls_domain **script_cli_domains_template;

extern map_t *server_dom_matching;
extern map_t *client_dom_matching;

extern rw_lock_t *dom_lock;

Expand All @@ -130,15 +131,10 @@ struct tls_domain *tls_find_client_domain_name(str *name);
* TLS domain structure
*/
int tls_new_domain(str *name, int type, struct tls_domain **dom);
struct tls_domain* tls_copy_domain(struct tls_domain* d);

void tls_release_domain(struct tls_domain* dom);

void tls_free_domain(struct tls_domain *dom);

void tls_free_db_domains(struct tls_domain* dom);

struct tls_domain *find_first_script_dom(struct tls_domain *dom);

int set_all_domain_attr(struct tls_domain **dom, char **str_vals, int *int_vals,
str* blob_vals);

Expand All @@ -149,7 +145,7 @@ int db_add_domain(char **str_vals, int *int_vals, str* blob_vals,
int parse_match_domains(struct tls_domain *tls_dom, str *domains_s);
int parse_match_addresses(struct tls_domain *tls_dom, str *addresses_s);

int update_matching_map(struct tls_domain *tls_dom);
int update_matching_map(struct tls_domain *tls_dom, map_t matching_map);
int sort_map_dom_arrays(map_t matching_map);
void map_free_node(void *val);

Expand Down
Loading
Loading