Skip to content

Commit

Permalink
sip/transp: add client certificate to all TLS transports (#1173)
Browse files Browse the repository at this point in the history
Currently, when a client certificate is added to a SIP transport, it is
only added to the first matching transport in the transport list.
Then, if multiple SIP transports exist (e.g if there are multiple
network interfaces), the certificate might not be present in the
transport when it is needed.

Now, the certificate is added to all matching transports.
  • Loading branch information
maximilianfridrich authored Aug 6, 2024
1 parent fe0c201 commit ea2dfa4
Showing 1 changed file with 64 additions and 23 deletions.
87 changes: 64 additions & 23 deletions src/sip/transp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ struct sip_ccert {
};


struct sip_ccert_data {
uint32_t hsup;
struct sip_ccert *ccert;
};


struct sip_transport {
struct le le;
struct sa laddr;
Expand Down Expand Up @@ -191,6 +197,31 @@ static const struct sip_transport *transp_find(struct sip *sip,
}


static struct le *transp_apply_all(struct sip *sip, enum sip_transp tp, int af,
list_apply_h ah, void *arg)
{
if (!ah)
return NULL;

for (struct le *le = sip->transpl.head; le; le = le->next) {

const struct sip_transport *transp = le->data;
const struct sa *laddr = &transp->laddr;

if (transp->tp != tp)
continue;

if (af != AF_UNSPEC && sa_af(laddr) != af)
continue;

if (ah(le, arg))
return le;
}

return NULL;
}


static struct sip_conn *conn_find(struct sip *sip, const struct sa *paddr,
bool secure)
{
Expand Down Expand Up @@ -1401,6 +1432,27 @@ int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
}


static bool add_ccert_handler(struct le *le, void *arg)
{
const struct sip_transport *transp = le->data;
struct sip_ccert_data *cc = arg;

if (!cc->ccert->he.list)
hash_append(transp->ht_ccert, cc->hsup, &cc->ccert->he,
cc->ccert);
else {
struct sip_ccert *ccert = mem_zalloc(sizeof(*ccert), NULL);
if (!ccert)
return false;

ccert->file = cc->ccert->file;
hash_append(transp->ht_ccert, cc->hsup, &ccert->he, ccert);
}

return false;
}


/**
* Add a client certificate to the TLS transport object
* Client certificates are saved as hash-table.
Expand All @@ -1416,10 +1468,9 @@ int sip_transp_add_ccert(struct sip *sip, const struct uri *uri,
const char *cert)
{
int err = 0;
const struct sip_transport *transp = NULL;
struct sip_ccert *ccert = NULL;
struct sip_ccert_data cc_data;
struct mbuf *sup = NULL;
uint32_t hsup = 0;

if (!sip || !uri || !cert)
return EINVAL;
Expand All @@ -1435,30 +1486,20 @@ int sip_transp_add_ccert(struct sip *sip, const struct uri *uri,

mbuf_set_pos(sup, 0);

hsup = hash_joaat(mbuf_buf(sup), mbuf_get_left(sup));
transp = transp_find(sip, SIP_TRANSP_TLS, AF_INET, NULL);
if (transp) {
ccert = mem_zalloc(sizeof(*ccert), NULL);
if (!ccert) {
err = ENOMEM;
goto out;
}

pl_set_str(&ccert->file, cert);
hash_append(transp->ht_ccert, hsup, &ccert->he, ccert);
ccert = mem_zalloc(sizeof(*ccert), NULL);
if (!ccert) {
err = ENOMEM;
goto out;
}
pl_set_str(&ccert->file, cert);

transp = transp_find(sip, SIP_TRANSP_TLS, AF_INET6, NULL);
if (transp) {
ccert = mem_zalloc(sizeof(*ccert), NULL);
if (!ccert) {
err = ENOMEM;
goto out;
}
cc_data.hsup = hash_joaat(mbuf_buf(sup), mbuf_get_left(sup));
cc_data.ccert = ccert;

pl_set_str(&ccert->file, cert);
hash_append(transp->ht_ccert, hsup, &ccert->he, ccert);
}
(void)transp_apply_all(sip, SIP_TRANSP_TLS, AF_INET, add_ccert_handler,
&cc_data);
(void)transp_apply_all(sip, SIP_TRANSP_TLS, AF_INET6,
add_ccert_handler, &cc_data);

out:
mem_deref(sup);
Expand Down

0 comments on commit ea2dfa4

Please sign in to comment.