Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tls sipcert per acc #96

Merged
merged 3 commits into from
Apr 24, 2021
Merged
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
2 changes: 2 additions & 0 deletions include/re_sip.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp,
int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
const struct sa *laddr,
bool server, const char *cert);
int sip_transp_add_ccert(struct sip *sip, const struct uri *uri,
const char *ccertfile);
void sip_transp_flush(struct sip *sip);
bool sip_transp_isladdr(const struct sip *sip, enum sip_transp tp,
const struct sa *laddr);
Expand Down
1 change: 1 addition & 0 deletions include/re_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,4 @@ void rand_bytes(uint8_t *p, size_t size);
int fs_mkdir(const char *path, uint16_t mode);
int fs_gethome(char *path, size_t sz);
bool fs_isdir(const char *path);
bool fs_isfile(const char *file);
1 change: 1 addition & 0 deletions include/re_tls.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void tls_disable_verify_server(struct tls *tls);

/* TCP */

int tls_conn_change_cert(struct tls_conn *tc, const char *file);
int tls_start_tcp(struct tls_conn **ptc, struct tls *tls,
struct tcp_conn *tcp, int layer);

Expand Down
135 changes: 134 additions & 1 deletion src/sip/transp.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,17 @@ enum {
};


struct sip_ccert {
struct le he;
struct pl file;
};


struct sip_transport {
struct le le;
struct sa laddr;
struct sip *sip;
struct hash *ht_ccert;
struct tls *tls;
void *sock;
enum sip_transp tp;
Expand Down Expand Up @@ -95,6 +102,8 @@ static void transp_destructor(void *arg)
udp_handler_set(transp->sock, NULL, NULL);

list_unlink(&transp->le);
hash_flush(transp->ht_ccert);
mem_deref(transp->ht_ccert);
mem_deref(transp->sock);
mem_deref(transp->tls);
mem_deref(transp->http_cli);
Expand Down Expand Up @@ -630,6 +639,40 @@ static void tcp_connect_handler(const struct sa *paddr, void *arg)
}
}

#ifdef USE_TLS
static uint32_t get_hash_of_fromhdr(struct mbuf *mb)
{
struct sip_msg *msg;
struct mbuf *sup = NULL;
uint32_t hsup = 0;
int err = 0;

err = sip_msg_decode(&msg, mb);
if (err)
return 0;

sup = mbuf_alloc(30);
if (!sup)
return ENOMEM;

err = mbuf_printf(sup, "\"%r\" <%r:%r@%r:%d>", &msg->from.uri.user,
&msg->from.uri.scheme, &msg->from.uri.user,
&msg->from.uri.host, msg->from.uri.port);
if (err)
goto out;

mbuf_set_pos(sup, 0);
hsup = hash_joaat(mbuf_buf(sup), mbuf_get_left(sup));
mbuf_set_pos(mb, 0);

out:
mem_deref(msg);
mem_deref(sup);

return hsup;
}
#endif


static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
const struct sa *dst, char *host, struct mbuf *mb,
Expand Down Expand Up @@ -677,6 +720,8 @@ static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
#ifdef USE_TLS
if (secure) {
const struct sip_transport *transp;
struct sip_ccert *ccert;
uint32_t hash = 0;

transp = transp_find(sip, SIP_TRANSP_TLS, sa_af(dst), dst);
if (!transp || !transp->tls) {
Expand All @@ -688,7 +733,22 @@ static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
if (err)
goto out;

err = tls_set_verify_server(conn->sc, host);
hash = get_hash_of_fromhdr(mb);
ccert = list_ledata(
list_head(hash_list(transp->ht_ccert, hash)));
if (ccert) {
char *f;
err = pl_strdup(&f, &ccert->file);
if (err)
goto out;

err = tls_conn_change_cert(conn->sc, f);
mem_deref(f);
if (err)
goto out;
}

err |= tls_set_verify_server(conn->sc, host);
if (err)
goto out;
}
Expand Down Expand Up @@ -1036,6 +1096,14 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp,
if (!transp)
return ENOMEM;

if (tp == SIP_TRANSP_TLS) {
err = hash_alloc(&transp->ht_ccert, 32);
if (err) {
mem_deref(transp);
return err;
}
}

list_append(&sip->transpl, &transp->le, transp);
transp->sip = sip;
transp->tp = tp;
Expand Down Expand Up @@ -1147,6 +1215,71 @@ int sip_transp_add_websock(struct sip *sip, enum sip_transp tp,
}


/**
* Add a client certificate to the TLS transport object
* Client certificates are saved as hash-table.
* Hashtable-Key: "username" <sip:username\@address:port>
*
* @param sip Global SIP stack
* @param uri Account uri information
* @param cert Certificate + Key file
*
* @return int 0 if success, otherwise errorcode
*/
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 mbuf *sup = NULL;
uint32_t hsup = 0;

if (!sip || !uri || !cert)
return EINVAL;

sup = mbuf_alloc(30);
if (!sup)
return ENOMEM;

err = mbuf_printf(sup, "\"%r\" <%r:%r@%r:%d>", &uri->user,
&uri->scheme, &uri->user, &uri->host, uri->port);
if (err)
goto out;

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);
}

transp = transp_find(sip, SIP_TRANSP_TLS, AF_INET6, 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);
}

out:
mem_deref(sup);
return err;
}


/**
* Flush all transports of a SIP stack instance
*
Expand Down
24 changes: 24 additions & 0 deletions src/sys/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,27 @@ bool fs_isdir(const char *path)

return true;
}


/**
* Check if given file exists and is a regular file
*
* @param file Filepath
*
* @return True if exists and is regular file, False if not
*/
bool fs_isfile(const char *file)
{
struct stat st;

if (!file)
return false;

if (stat(file, &st) < 0)
return false;

if ((st.st_mode & S_IFMT) != S_IFREG)
return false;

return true;
}
39 changes: 39 additions & 0 deletions src/tls/openssl/tls_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,45 @@ static bool send_handler(int *err, struct mbuf *mb, void *arg)
}


/**
* Change used certificate+key of an existing SSL object
*
* @param tc TLS connection object
* @param file Cert+Key file
*
* @return int 0 if success, otherwise errorcode
*/
int tls_conn_change_cert(struct tls_conn *tc, const char *file)
{
int r = 0;

if (!tc || !file)
return EINVAL;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
!defined(LIBRESSL_VERSION_NUMBER)
r = SSL_use_certificate_chain_file(tc->ssl, file);
#else
r = SSL_use_certificate_file(tc->ssl, file, SSL_FILETYPE_PEM);
#endif
if (r <= 0) {
DEBUG_WARNING("change cert: "
"cant't read certificate file: %s\n", file);
ERR_clear_error();
return EINVAL;
}

r = SSL_use_PrivateKey_file(tc->ssl, file, SSL_FILETYPE_PEM);
if (r <= 0) {
DEBUG_WARNING("change cert: key missmatch in %s\n", file);
ERR_clear_error();
return EKEYREJECTED;
}

return 0;
}


/**
* Start TLS on a TCP-connection
*
Expand Down