Skip to content

Commit 91041c1

Browse files
committed
Add new nua_reload_tls() API for TLS certificate hot-reload
1 parent 0106ad0 commit 91041c1

File tree

10 files changed

+248
-101
lines changed

10 files changed

+248
-101
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,19 @@ test-driver
7070
utils/sip-date
7171
utils/sip-dig
7272
utils/sip-options
73+
libsofia-sip-ua/http/http_tag_dll.c
74+
libsofia-sip-ua/iptsec/auth_tag_dll.c
75+
libsofia-sip-ua/msg/msg_tag_dll.c
76+
libsofia-sip-ua/msg/msg_tag_ref.c
77+
libsofia-sip-ua/nea/nea_tag_dll.c
78+
libsofia-sip-ua/nta/nta_tag_dll.c
79+
libsofia-sip-ua/nth/nth_tag_dll.c
80+
libsofia-sip-ua/nua/nua_tag_dll.c
81+
libsofia-sip-ua/sdp/sdp_tag_dll.c
82+
libsofia-sip-ua/sip/sip_tag_dll.c
83+
libsofia-sip-ua/soa/soa_tag_dll.c
84+
libsofia-sip-ua/stun/stun_tag_dll.c
85+
libsofia-sip-ua/su/su_tag_dll.c
86+
libsofia-sip-ua/tport/tport_tag_dll.c
87+
libsofia-sip-ua/url/url_tag_dll.c
88+
win32/gawk.exe

libsofia-sip-ua/nta/nta.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,13 @@ void nta_agent_resolver_clean_cache(nta_agent_t *agent)
11201120
#endif
11211121
}
11221122

1123+
int nta_agent_reload_tls(nta_agent_t *agent, char const *cert_dir)
1124+
{
1125+
if (!agent || !agent->sa_tports)
1126+
return -1;
1127+
return tport_reload_tls(agent->sa_tports, cert_dir);
1128+
}
1129+
11231130
/** Return agent context. */
11241131
nta_agent_magic_t *nta_agent_magic(nta_agent_t const *agent)
11251132
{

libsofia-sip-ua/nta/sofia-sip/nta.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ nta_agent_t *nta_agent_create(su_root_t *root,
136136

137137
SOFIAPUBFUN void nta_agent_destroy(nta_agent_t *agent);
138138
SOFIAPUBFUN void nta_agent_resolver_clean_cache(nta_agent_t *agent);
139+
SOFIAPUBFUN int nta_agent_reload_tls(nta_agent_t *agent, char const *cert_dir);
139140

140141
SOFIAPUBFUN char const *nta_agent_version(nta_agent_t const *a);
141142
SOFIAPUBFUN nta_agent_magic_t *nta_agent_magic(nta_agent_t const *a);

libsofia-sip-ua/nua/nua.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <sofia-sip/sip_status.h>
4848
#include <sofia-sip/sip_header.h>
4949
#include <sofia-sip/nta.h>
50+
#include <sofia-sip/tport_tag.h>
5051

5152
#include "sofia-sip/nua.h"
5253
#include "sofia-sip/nua_tag.h"
@@ -89,7 +90,7 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
8990
* @param root Pointer to a root object
9091
* @param callback Pointer to event callback function
9192
* @param magic Pointer to callback context
92-
* @param tag, value, ... List of tagged parameters
93+
* @param tag, value, ... List of tagged parameters
9394
*
9495
* @retval !=NULL a pointer to a @nua stack object
9596
* @retval NULL upon an error
@@ -1131,6 +1132,21 @@ nta_agent_t *nua_get_agent(nua_t *nua)
11311132
return NULL;
11321133
}
11331134

1135+
/** Reload TLS certificates for all TLS transports in this nua instance.
1136+
* Sends a signal to the nua event loop so the reload happens on the
1137+
* internal thread that handles signals (thread-safe).
1138+
*/
1139+
int nua_reload_tls(nua_t *nua, char const *cert_dir)
1140+
{
1141+
if (!nua || !cert_dir)
1142+
return -1;
1143+
1144+
enter;
1145+
1146+
return nua_signal(nua, NULL, NULL, nua_r_reload_tls, 0, NULL,
1147+
TPTAG_CERTIFICATE(cert_dir), TAG_NULL());
1148+
}
1149+
11341150
/** Set has invite of a nua handle */
11351151
void nua_handle_set_has_invite(nua_handle_t *nh, unsigned val)
11361152
{

libsofia-sip-ua/nua/nua_stack.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,14 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee)
699699
case nua_r_nta_agent_resolver_clean_dns_cache:
700700
nta_agent_resolver_clean_cache(nua->nua_nta);
701701
break;
702+
case nua_r_reload_tls:
703+
{
704+
char const *cert_dir = NULL;
705+
706+
tl_gets(tags, TPTAG_CERTIFICATE_REF(cert_dir), TAG_END());
707+
nta_agent_reload_tls(nua->nua_nta, cert_dir);
708+
break;
709+
}
702710
default:
703711
break;
704712
}

libsofia-sip-ua/nua/sofia-sip/nua.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ typedef enum nua_event_e {
161161
nua_i_register, /**< Incoming REGISTER. @NEW_1_12_4. */
162162
nua_r_unref, /** Calls nua_unref() from dispatcher @NEW_1_13_3 */
163163
nua_r_handle_unref, /** Calls nua_handle_unref() from dispatcher @NEW_1_13_3 */
164-
nua_r_nta_agent_resolver_clean_dns_cache /** Calls nua_resolver_clean_dns_cache() from dispatcher @NEW_1_13_12 */
164+
nua_r_nta_agent_resolver_clean_dns_cache, /** Calls nua_resolver_clean_dns_cache() from dispatcher @NEW_1_13_12 */
165+
nua_r_reload_tls /** Calls nta_agent_reload_tls() from dispatcher */
165166
} nua_event_t;
166167

167168
typedef struct event_s {
@@ -404,6 +405,7 @@ SOFIAPUBFUN void nua_unref_user(nua_t *nua);
404405
SOFIAPUBFUN void nua_handle_unref_user(nua_handle_t *nh);
405406
SOFIAPUBFUN su_home_t *nua_get_home(nua_t *nua);
406407
SOFIAPUBFUN nta_agent_t *nua_get_agent(nua_t *nua);
408+
SOFIAPUBFUN int nua_reload_tls(nua_t *nua, char const *cert_dir);
407409
SOFIAPUBFUN void nua_handle_set_has_invite(nua_handle_t *nh, unsigned val);
408410
SOFIAPUBFUN unsigned nua_handle_is_destroyed(nua_handle_t *nh);
409411
SOFIAPUBFUN void nua_handle_dialog_usage_set_refresh_range(nua_handle_t *nh,

libsofia-sip-ua/tport/sofia-sip/tport.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ TPORT_DLL int tport_has_tls(tport_t const *tport);
273273
/** Test if transport provided a verified certificate chain (TLS only) */
274274
TPORT_DLL int tport_is_verified(tport_t const *tport);
275275

276+
/** Reload TLS certificates on all TLS primaries. */
277+
TPORT_DLL int tport_reload_tls(tport_t *self, char const *cert_dir);
278+
276279
/** Return true if transport is being updated. */
277280
TPORT_DLL int tport_is_updating(tport_t const *self);
278281

libsofia-sip-ua/tport/tport.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ typedef struct tport_nat_s tport_nat_t;
6262
#include <errno.h>
6363
#include <limits.h>
6464

65+
#if HAVE_WIN32
66+
#include <io.h>
67+
#define access(_filename, _mode) _access(_filename, _mode)
68+
#define R_OK (04)
69+
#else
70+
#include <unistd.h>
71+
#endif
72+
6573
#ifndef IPPROTO_SCTP
6674
#define IPPROTO_SCTP (132)
6775
#endif
@@ -71,6 +79,7 @@ typedef struct tport_nat_s tport_nat_t;
7179
#include <sofia-sip/rbtree.h>
7280

7381
#include "tport_internal.h"
82+
#include "tport_tls.h"
7483

7584
#if HAVE_FUNC
7685
#elif HAVE_FUNCTION
@@ -280,6 +289,45 @@ int tport_is_verified(tport_t const *self)
280289
return tport_has_tls(self) && self->tp_is_connected && self->tp_verified;
281290
}
282291

292+
/** Reload TLS certificates on all TLS primary transports. */
293+
int tport_reload_tls(tport_t *self, char const *cert_dir)
294+
{
295+
su_home_t autohome[SU_HOME_AUTO_SIZE(1024)];
296+
tls_issues_t ti = {0};
297+
tport_t *tp;
298+
int reloaded = 0;
299+
300+
if (!self || !cert_dir)
301+
return -1;
302+
303+
su_home_auto(autohome, sizeof autohome);
304+
305+
ti.key = su_sprintf(autohome, "%s/%s", cert_dir, "agent.pem");
306+
if (access(ti.key, R_OK) != 0)
307+
ti.key = su_sprintf(autohome, "%s/%s", cert_dir, "tls.pem");
308+
ti.cert = ti.key;
309+
ti.CAfile = su_sprintf(autohome, "%s/%s", cert_dir, "cafile.pem");
310+
if (access(ti.CAfile, R_OK) != 0)
311+
ti.CAfile = su_sprintf(autohome, "%s/%s", cert_dir, "tls.pem");
312+
ti.CApath = su_strdup(autohome, cert_dir);
313+
ti.randFile = su_sprintf(autohome, "%s/%s", cert_dir, "tls_seed.dat");
314+
ti.configured = 1;
315+
316+
for (tp = tport_primaries(self); tp; tp = tport_next(tp)) {
317+
if (tport_has_tls(tp)) {
318+
tport_tls_primary_t *tlspri = (tport_tls_primary_t *)tp->tp_pri;
319+
if (tlspri->tlspri_master) {
320+
if (tls_reload_cert(tlspri->tlspri_master, &ti) == 0)
321+
reloaded++;
322+
}
323+
}
324+
}
325+
326+
su_home_deinit(autohome);
327+
328+
return reloaded;
329+
}
330+
283331
/** Return true if transport is being updated. */
284332
int tport_is_updating(tport_t const *self)
285333
{

0 commit comments

Comments
 (0)