Skip to content

Commit

Permalink
sip/auth: SHA-256 digest algorithm support
Browse files Browse the repository at this point in the history
  • Loading branch information
sreimers committed Apr 21, 2024
1 parent 04e9e03 commit f1a2804
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 31 deletions.
1 change: 1 addition & 0 deletions include/re_sip.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ typedef int(sip_auth_h)(char **username, char **password, const char *realm,
typedef bool(sip_hdr_h)(const struct sip_hdr *hdr, const struct sip_msg *msg,
void *arg);
typedef void(sip_keepalive_h)(int err, void *arg);
typedef int(digest_printf_h)(uint8_t *md, const char *fmt, ...);

#define LIBRE_HAVE_SIPTRACE 1
typedef void(sip_trace_h)(bool tx, enum sip_transp tp,
Expand Down
107 changes: 76 additions & 31 deletions src/sip/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
#include <re_sa.h>
#include <re_sys.h>
#include <re_md5.h>
#include <re_sha.h>
#include <re_httpauth.h>
#include <re_udp.h>
#include <re_msg.h>
#include <re_sip.h>
#include "sip.h"

#define DEBUG_MODULE "sip_auth"
#define DEBUG_LEVEL 5
#include <re_dbg.h>

enum {
NONCE_EXPIRES = 300,
NONCE_MIN_SIZE = 33,
Expand All @@ -42,6 +47,7 @@ struct realm {
char *opaque;
char *user;
char *pass;
char *algorithm;
uint32_t nc;
enum sip_hdrid hdr;
};
Expand Down Expand Up @@ -69,6 +75,7 @@ static void realm_destructor(void *arg)
mem_deref(realm->opaque);
mem_deref(realm->user);
mem_deref(realm->pass);
mem_deref(realm->algorithm);
}


Expand All @@ -83,33 +90,61 @@ static void auth_destructor(void *arg)
}


static int mkdigest(uint8_t *digest, const struct realm *realm,
static int mkdigest(struct mbuf **digestp, const struct realm *realm,
const char *met, const char *uri, uint64_t cnonce)
{
uint8_t ha1[MD5_SIZE], ha2[MD5_SIZE];
struct mbuf *digest;
digest_printf_h *digest_printf;
int err;

err = md5_printf(ha1, "%s:%s:%s",
realm->user, realm->realm, realm->pass);
bool use_sha256 = str_casecmp(realm->algorithm, "sha-256") == 0;
int h_size = use_sha256 ? SHA256_DIGEST_SIZE : MD5_SIZE;

digest = mbuf_alloc(h_size);
if (!digest)
return ENOMEM;

mbuf_set_end(digest, h_size);

uint8_t *ha1 = mem_alloc(h_size, NULL);
if (!ha1)
return ENOMEM;

uint8_t *ha2 = mem_alloc(h_size, NULL);
if (!ha2) {
mem_deref(ha1);
return ENOMEM;
}

if (use_sha256)
digest_printf = &sha256_printf;
else
digest_printf = &md5_printf;

err = digest_printf(ha1, "%s:%s:%s", realm->user, realm->realm,
realm->pass);
if (err)
return err;
goto out;

err = md5_printf(ha2, "%s:%s", met, uri);
err = digest_printf(ha2, "%s:%s", met, uri);
if (err)
return err;
goto out;

if (realm->qop)
return md5_printf(digest, "%w:%s:%08x:%016llx:auth:%w",
ha1, sizeof(ha1),
realm->nonce,
realm->nc,
cnonce,
ha2, sizeof(ha2));
err = digest_printf(
mbuf_buf(digest), "%w:%s:%08x:%016llx:auth:%w", ha1,
h_size, realm->nonce, realm->nc, cnonce, ha2, h_size);
else
return md5_printf(digest, "%w:%s:%w",
ha1, sizeof(ha1),
realm->nonce,
ha2, sizeof(ha2));
err = digest_printf(mbuf_buf(digest), "%w:%s:%w", ha1, h_size,
realm->nonce, ha2, h_size);
out:
mem_deref(ha1);
mem_deref(ha2);

if (!err)
*digestp = digest;

return err;
}


Expand All @@ -131,7 +166,7 @@ static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
{
struct httpauth_digest_chall ch;
struct sip_auth *auth = arg;
struct realm *realm = NULL;
struct realm *realm = NULL;
int err;
(void)msg;

Expand All @@ -140,7 +175,11 @@ static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
goto out;
}

if (pl_isset(&ch.algorithm) && pl_strcasecmp(&ch.algorithm, "md5")) {
if (!pl_isset(&ch.algorithm))
pl_set_str(&ch.algorithm, "md5");

if (pl_strcasecmp(&ch.algorithm, "md5") &&
pl_strcasecmp(&ch.algorithm, "sha-256")) {
err = ENOSYS;
goto out;
}
Expand All @@ -159,6 +198,10 @@ static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
err = pl_strdup(&realm->realm, &ch.realm);
if (err)
goto out;

err = pl_strdup(&realm->algorithm, &ch.algorithm);
if (err)
goto out;

err = auth->authh(&realm->user, &realm->pass,
realm->realm, auth->arg);
Expand All @@ -171,9 +214,10 @@ static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
goto out;
}

realm->nonce = mem_deref(realm->nonce);
realm->qop = mem_deref(realm->qop);
realm->opaque = mem_deref(realm->opaque);
realm->nonce = mem_deref(realm->nonce);
realm->qop = mem_deref(realm->qop);
realm->opaque = mem_deref(realm->opaque);
realm->algorithm = mem_deref(realm->algorithm);
}

realm->hdr = hdr->id;
Expand All @@ -195,7 +239,7 @@ static bool auth_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
}

return false;
}
}


/**
Expand Down Expand Up @@ -236,11 +280,7 @@ int sip_auth_encode(struct mbuf *mb, struct sip_auth *auth, const char *met,

const uint64_t cnonce = rand_u64();
struct realm *realm = le->data;
uint8_t digest[MD5_SIZE];

err = mkdigest(digest, realm, met, uri, cnonce);
if (err)
break;
struct mbuf *digest = NULL;

switch (realm->hdr) {

Expand All @@ -256,12 +296,17 @@ int sip_auth_encode(struct mbuf *mb, struct sip_auth *auth, const char *met,
continue;
}

err = mkdigest(&digest, realm, met, uri, cnonce);
if (err)
break;

err |= mbuf_printf(mb, "Digest username=\"%s\"", realm->user);
err |= mbuf_printf(mb, ", realm=\"%s\"", realm->realm);
err |= mbuf_printf(mb, ", nonce=\"%s\"", realm->nonce);
err |= mbuf_printf(mb, ", uri=\"%s\"", uri);
err |= mbuf_printf(mb, ", response=\"%w\"",
digest, sizeof(digest));
err |= mbuf_printf(mb, ", response=\"%w\"", digest->buf,
digest->end);
digest = mem_deref(digest);

if (realm->opaque)
err |= mbuf_printf(mb, ", opaque=\"%s\"",
Expand All @@ -275,7 +320,7 @@ int sip_auth_encode(struct mbuf *mb, struct sip_auth *auth, const char *met,

++realm->nc;

err |= mbuf_write_str(mb, ", algorithm=MD5");
err |= mbuf_printf(mb, ", algorithm=%s", realm->algorithm);
err |= mbuf_write_str(mb, "\r\n");
if (err)
break;
Expand Down

0 comments on commit f1a2804

Please sign in to comment.