Skip to content

Commit bcd3e7b

Browse files
feat: Unify TLS config reload from files and database
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
1 parent 905c17a commit bcd3e7b

5 files changed

Lines changed: 388 additions & 329 deletions

File tree

modules/tls_mgm/doc/tls_mgm_admin.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,10 @@ if (is_peer_verified()) {
196196
<function moreinfo="none">tls_reload</function>
197197
</title>
198198
<para>
199-
Reloads the TLS domains information from the database.
200-
The previous DB defined domains are discarded but the
201-
script defined domains are preserved.
199+
Reloads all TLS domain information. Domains defined in the database are
200+
re-queried, and script-defined domains are re-initialized (which
201+
reloads their certificates and key files). The entire previous
202+
domain configuration is discarded and replaced.
202203
</para>
203204
</section>
204205
</section>

modules/tls_mgm/tls_domain.c

Lines changed: 109 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,20 @@
3737
#include "../../lib/csv.h"
3838
#include "tls_domain.h"
3939
#include "tls_params.h"
40-
#include "api.h"
4140
#include <stdlib.h>
4241
#include <fnmatch.h>
4342

4443

4544
struct tls_domain **tls_server_domains;
4645
struct tls_domain **tls_client_domains;
4746

48-
map_t server_dom_matching;
49-
map_t client_dom_matching;
47+
struct tls_domain **script_srv_domains_template;
48+
struct tls_domain **script_cli_domains_template;
5049

51-
rw_lock_t *dom_lock;
50+
map_t *server_dom_matching;
51+
map_t *client_dom_matching;
5252

53-
extern struct openssl_binds openssl_api;
54-
extern struct wolfssl_binds wolfssl_api;
53+
rw_lock_t *dom_lock;
5554

5655
void destroy_tls_dom(struct tls_domain *d);
5756

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

70-
struct tls_domain *find_first_script_dom(struct tls_domain *dom)
71-
{
72-
struct tls_domain *d;
73-
74-
for (d = dom; d && d->flags & DOM_FLAG_DB; d = d->next) ;
75-
76-
return d;
77-
}
78-
7969
void map_free_node(void *val)
8070
{
8171
if (val)
8272
shm_free(val);
8373
}
8474

85-
void map_remove_tls_dom(struct tls_domain *dom)
86-
{
87-
map_t map = dom->flags & DOM_FLAG_SRV ? server_dom_matching : client_dom_matching;
88-
map_iterator_t it, it_tmp;
89-
struct dom_filt_array *doms_array;
90-
void **val;
91-
int i, j;
92-
93-
map_first(map, &it);
94-
while (iterator_is_valid(&it)) {
95-
it_tmp = it;
96-
iterator_next(&it);
97-
98-
val = iterator_val(&it_tmp);
99-
doms_array = (struct dom_filt_array *)*val;
100-
for (i = 0; i < doms_array->size;)
101-
if (doms_array->arr[i].dom_link == dom) {
102-
for (j = i + 1; j < doms_array->size; j++)
103-
doms_array->arr[j-1] = doms_array->arr[j];
104-
doms_array->size--;
105-
}
106-
else {
107-
i++;
108-
}
109-
if (doms_array->size == 0) {
110-
map_free_node(doms_array);
111-
iterator_delete(&it_tmp);
112-
}
113-
}
114-
}
115-
116-
void tls_free_domain(struct tls_domain *dom)
75+
void tls_release_domain(struct tls_domain *dom)
11776
{
11877
str_list *m_it, *m_tmp;
78+
int free_it = 0;
11979

120-
dom->refs--;
121-
if (dom->refs == 0) {
122-
LM_DBG("Freeing domain: %.*s\n",
123-
dom->name.len, dom->name.s);
124-
125-
destroy_tls_dom(dom);
80+
if (!dom)
81+
return;
12682

127-
lock_destroy(dom->lock);
128-
lock_dealloc(dom->lock);
83+
lock_get(dom->lock);
84+
if (--dom->refs == 0)
85+
free_it = 1;
86+
lock_release(dom->lock);
12987

130-
map_remove_tls_dom(dom);
88+
if (!free_it)
89+
return;
13190

132-
m_it = dom->match_domains;
133-
while (m_it) {
134-
m_tmp = m_it;
135-
m_it = m_it->next;
136-
shm_free(m_tmp);
137-
}
138-
m_it = dom->match_addresses;
139-
while (m_it) {
140-
m_tmp = m_it;
141-
m_it = m_it->next;
142-
shm_free(m_tmp);
143-
}
91+
LM_DBG("Freeing domain: %.*s\n",
92+
dom->name.len, dom->name.s);
14493

145-
shm_free(dom);
146-
}
147-
}
94+
destroy_tls_dom(dom);
14895

149-
/* frees the DB domains */
150-
void tls_free_db_domains(struct tls_domain *dom)
151-
{
152-
struct tls_domain *tmp;
96+
lock_destroy(dom->lock);
97+
lock_dealloc(dom->lock);
15398

154-
while (dom && dom->flags & DOM_FLAG_DB) {
155-
tmp = dom;
156-
dom = dom->next;
157-
map_remove_tls_dom(tmp);
158-
tls_free_domain(tmp);
99+
m_it = dom->match_domains;
100+
while (m_it) {
101+
m_tmp = m_it;
102+
m_it = m_it->next;
103+
shm_free(m_tmp);
104+
}
105+
m_it = dom->match_addresses;
106+
while (m_it) {
107+
m_tmp = m_it;
108+
m_it = m_it->next;
109+
shm_free(m_tmp);
159110
}
160-
}
161-
162-
void tls_release_domain(struct tls_domain* dom)
163-
{
164-
if (!dom || !(dom->flags & DOM_FLAG_DB))
165-
return;
166-
167-
if (dom_lock)
168-
lock_start_write(dom_lock);
169-
170-
tls_free_domain(dom);
171111

172-
if (dom_lock)
173-
lock_stop_write(dom_lock);
112+
shm_free(dom);
174113
}
175114

176115
int set_all_domain_attr(struct tls_domain **dom, char **str_vals, int *int_vals,
@@ -340,10 +279,10 @@ tls_find_server_domain(struct ip_addr *ip, unsigned short port)
340279
addr_s.s = addr_buf;
341280
addr_s.len = strlen(addr_buf);
342281

343-
val = map_find(server_dom_matching, addr_s);
282+
val = map_find(*server_dom_matching, addr_s);
344283
if (!val) {
345284
/* try to find a domain which matches any address */
346-
val = map_find(server_dom_matching, match_any_s);
285+
val = map_find(*server_dom_matching, match_any_s);
347286
if (!val) {
348287
if (dom_lock)
349288
lock_stop_read(dom_lock);
@@ -384,11 +323,11 @@ tls_find_domain_by_filters(struct ip_addr *ip, unsigned short port,
384323
addr_s.len = strlen(addr_buf);
385324

386325
val = map_find(type == DOM_FLAG_SRV ?
387-
server_dom_matching : client_dom_matching, addr_s);
326+
*server_dom_matching : *client_dom_matching, addr_s);
388327
if (!val) {
389328
/* try to find domains which match any address */
390329
val = map_find(type == DOM_FLAG_SRV ?
391-
server_dom_matching : client_dom_matching, match_any_s);
330+
*server_dom_matching : *client_dom_matching, match_any_s);
392331
if (!val) {
393332
if (dom_lock)
394333
lock_stop_read(dom_lock);
@@ -554,6 +493,77 @@ int tls_new_domain(str *name, int type, struct tls_domain **dom)
554493
return 0;
555494
}
556495

496+
497+
/*
498+
* Creates a deep-copy of a TLS domain. This is only appropriate for
499+
* script-defined domains that are instantiated from a template, as it
500+
* performs a mix of shallow and deep copying.
501+
*/
502+
struct tls_domain* tls_copy_domain(struct tls_domain* d)
503+
{
504+
struct tls_domain *n;
505+
506+
if (!d) return NULL;
507+
508+
/* Allocate space for the struct and the domain name, like tls_new_domain */
509+
n = shm_malloc(sizeof(struct tls_domain) + d->name.len);
510+
if (!n) {
511+
LM_ERR("No more shm mem\n");
512+
return NULL;
513+
}
514+
memset(n, 0, sizeof(struct tls_domain));
515+
516+
/* copy config fields */
517+
n->flags = d->flags;
518+
n->verify_cert = d->verify_cert;
519+
n->require_client_cert = d->require_client_cert;
520+
n->crl_check_all = d->crl_check_all;
521+
n->cert = d->cert;
522+
n->pkey = d->pkey;
523+
n->crl_directory = d->crl_directory;
524+
n->ca = d->ca;
525+
n->dh_param = d->dh_param;
526+
n->tls_ec_curve = d->tls_ec_curve;
527+
n->ca_directory = d->ca_directory;
528+
n->ciphers_list = d->ciphers_list;
529+
n->method_str = d->method_str;
530+
n->method = d->method;
531+
n->method_max = d->method_max;
532+
533+
/* Fix the name pointer and copy the content from the template */
534+
n->name.s = (char*)(n + 1);
535+
n->name.len = d->name.len;
536+
memcpy(n->name.s, d->name.s, d->name.len);
537+
538+
/* Initialize runtime state that must not be shared from the template */
539+
n->refs = 1;
540+
n->lock = lock_alloc();
541+
if (!n->lock || lock_init(n->lock) == NULL) {
542+
LM_ERR("failed to init lock for domain clone\n");
543+
if (n->lock) lock_dealloc(n->lock);
544+
shm_free(n);
545+
return NULL;
546+
}
547+
548+
/*
549+
* The matching lists are dynamically built in shm and freed by
550+
* tls_free_domain, so they need a deep copy. Other config strings
551+
* are pointers into the static config buffer and are correctly
552+
* shallow-copied.
553+
*/
554+
if ((d->match_domains && !(n->match_domains = dup_shm_str_list(d->match_domains))) ||
555+
(d->match_addresses && !(n->match_addresses = dup_shm_str_list(d->match_addresses)))
556+
) {
557+
goto error;
558+
}
559+
560+
return n;
561+
562+
error:
563+
if (n) tls_release_domain(n);
564+
return NULL;
565+
}
566+
557567
static int add_match_filt_to_dom(str *filter_s, str_list **filter_list)
558568
{
559569
str_list *match_filt;
@@ -768,16 +778,15 @@ int db_add_domain(char **str_vals, int *int_vals, str* blob_vals,
768778
return 0;
769779
}
770780

771-
int update_matching_map(struct tls_domain *tls_dom)
781+
int update_matching_map(struct tls_domain *tls_dom, map_t matching_map)
772782
{
773783
str_list *addrf_s, *domf_s;
774784
struct dom_filt_array *doms_array;
775785
void **val;
776786
int pos;
777787

778788
for (addrf_s = tls_dom->match_addresses; addrf_s; addrf_s = addrf_s->next) {
779-
val = map_get(tls_dom->flags & DOM_FLAG_SRV ?
780-
server_dom_matching : client_dom_matching, addrf_s->s);
789+
val = map_get(matching_map, addrf_s->s);
781790
if (!val) {
782791
LM_ERR("No more shm memory!\n");
783792
return -1;

modules/tls_mgm/tls_domain.h

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,19 @@ struct dom_filt_array {
9696

9797
#define ref_tls_dom(_d) \
9898
do { \
99-
if ((_d)->flags & DOM_FLAG_DB) { \
100-
lock_get((_d)->lock); \
101-
(_d)->refs++; \
102-
lock_release((_d)->lock); \
103-
} \
99+
lock_get((_d)->lock); \
100+
(_d)->refs++; \
101+
lock_release((_d)->lock); \
104102
} while (0)
105103

106104
extern struct tls_domain **tls_server_domains;
107105
extern struct tls_domain **tls_client_domains;
108106

109-
extern map_t server_dom_matching;
110-
extern map_t client_dom_matching;
107+
extern struct tls_domain **script_srv_domains_template;
108+
extern struct tls_domain **script_cli_domains_template;
109+
110+
extern map_t *server_dom_matching;
111+
extern map_t *client_dom_matching;
111112

112113
extern rw_lock_t *dom_lock;
113114

@@ -130,15 +131,10 @@ struct tls_domain *tls_find_client_domain_name(str *name);
130131
* TLS domain structure
131132
*/
132133
int tls_new_domain(str *name, int type, struct tls_domain **dom);
134+
struct tls_domain* tls_copy_domain(struct tls_domain* d);
133135

134136
void tls_release_domain(struct tls_domain* dom);
135137

136-
void tls_free_domain(struct tls_domain *dom);
137-
138-
void tls_free_db_domains(struct tls_domain* dom);
139-
140-
struct tls_domain *find_first_script_dom(struct tls_domain *dom);
141-
142138
int set_all_domain_attr(struct tls_domain **dom, char **str_vals, int *int_vals,
143139
str* blob_vals);
144140

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

152-
int update_matching_map(struct tls_domain *tls_dom);
148+
int update_matching_map(struct tls_domain *tls_dom, map_t matching_map);
153149
int sort_map_dom_arrays(map_t matching_map);
154150
void map_free_node(void *val);
155151

0 commit comments

Comments
 (0)