Skip to content

Commit

Permalink
sip/transp: add client certificate to all TLS transports
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 committed Jul 31, 2024
1 parent 7d8ac60 commit aa8fad4
Showing 1 changed file with 66 additions and 23 deletions.
89 changes: 66 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 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,33 @@ 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)
{
struct le *le;

if (!ah)
return NULL;

for (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 +1434,27 @@ int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
}


static bool add_ccert(struct le *le, void *arg)
{
const struct sip_transport *transp = le->data;
struct 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 +1470,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 ccert_data cc_data;
struct mbuf *sup = NULL;
uint32_t hsup = 0;

if (!sip || !uri || !cert)
return EINVAL;
Expand All @@ -1435,30 +1488,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,
&cc_data);
(void)transp_apply_all(sip, SIP_TRANSP_TLS, AF_INET6, add_ccert,
&cc_data);

out:
mem_deref(sup);
Expand Down

0 comments on commit aa8fad4

Please sign in to comment.