Skip to content

Commit

Permalink
stir_shaken: allow the new Identity header to be appended to replies
Browse files Browse the repository at this point in the history
Add a new parameter to the stir_shaken_auth() function that adds the
ability to append the new Identity header to replies or to return it
via an output variable.

Closes #2440
  • Loading branch information
rvlad-patrascu committed Aug 16, 2021
1 parent 06b78a9 commit b9f68a4
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 22 deletions.
28 changes: 27 additions & 1 deletion modules/stir_shaken/doc/stir_shaken_admin.xml
Expand Up @@ -215,7 +215,7 @@ modparam("stir_shaken", "require_date_hdr", 0)

<section id="func_stir_shaken_auth" xreflabel="stir_shaken_auth()">
<title>
<function moreinfo="none">stir_shaken_auth(attest, origid, cert, pkey, x5u, [orig], [dest])</function>
<function moreinfo="none">stir_shaken_auth(attest, origid, cert, pkey, x5u, [orig], [dest], [out])</function>
</title>
<para>
This function performs the steps of an authentication service. Before
Expand Down Expand Up @@ -280,6 +280,32 @@ modparam("stir_shaken", "require_date_hdr", 0)
will be derived from the SIP message.
</para>
</listitem>
<listitem>
<para><emphasis>out (string, no expand, optional)</emphasis> - name of an
output variable to store the Identity header or the following flags:
<itemizedlist>
<listitem>
<para><emphasis>req</emphasis> - the Identity header will be appended
to the current request message;
</para>
</listitem>
<listitem>
<para><para><emphasis>rpl</emphasis> - the Identity header will be appended
to all replies that will be generated by OpenSIPS for this request.
</para>
</para>
</listitem>
</itemizedlist>
</para>
<para>
If this parameter is missing, the Identity header will be appended
to the current request message.
</para>
<para>
If an output variable is provided, it should be given as a quoted string,
eg. <emphasis>"$var(identity_hdr)"</emphasis>.
</para>
</listitem>
</itemizedlist>

<para>The function returns the following values:</para>
Expand Down
104 changes: 83 additions & 21 deletions modules/stir_shaken/stir_shaken.c
Expand Up @@ -70,6 +70,8 @@
#include "../../data_lump.h"
#include "../../lib/cJSON.h"
#include "../../context.h"
#include "../../mod_fix.h"
#include "../../data_lump_rpl.h"

#include "stir_shaken.h"

Expand All @@ -84,8 +86,11 @@
static int mod_init(void);
static void mod_destroy(void);

static int fixup_auth_out(void** param);

static int w_stir_auth(struct sip_msg *msg, str *attest, str *origid,
str *cert_buf, str *pkey_buf, str *cr_url, str *orig_tn_p, str *dest_tn_p);
str *cert_buf, str *pkey_buf, str *cr_url, str *orig_tn_p, str *dest_tn_p,
struct auth_out_param *out);
static int w_stir_verify(struct sip_msg *msg, str *cert_buf,
pv_spec_t *err_code, pv_spec_t *err_reason, str *orig_tn_p, str *dest_tn_p);
static int w_stir_check(struct sip_msg *msg);
Expand Down Expand Up @@ -139,7 +144,9 @@ static cmd_export_t cmds[] = {
{CMD_PARAM_STR, 0, 0},
{CMD_PARAM_STR, 0, 0},
{CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0},
{CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0}, {0,0,0}},
{CMD_PARAM_STR|CMD_PARAM_OPT, 0, 0},
{CMD_PARAM_STR|CMD_PARAM_OPT|CMD_PARAM_NO_EXPAND,
fixup_auth_out, fixup_free_pkg}, {0,0,0}},
REQUEST_ROUTE},
{"stir_shaken_verify", (cmd_function)w_stir_verify, {
{CMD_PARAM_STR, 0, 0},
Expand Down Expand Up @@ -695,16 +702,15 @@ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
}
#endif

static int add_identity_hf(struct sip_msg *msg, EVP_PKEY *pkey,
static str *build_identity_hf(EVP_PKEY *pkey,
time_t date_ts, str *attest, str *cr_url, str *orig_tn,
str *dest_tn, str *origid)
{
str hdr_buf = {0,0};
static str hdr_buf = {0,0};
str unsigned_buf;
str der_sig_buf = {0,0};
unsigned char *der_sig_p;
unsigned char raw_sig_buf[RAW_SIG_LEN];
struct lump* anchor;
EVP_MD_CTX *mdctx = NULL;
ECDSA_SIG *sig = NULL;
const BIGNUM *r, *s;
Expand All @@ -713,7 +719,7 @@ static int add_identity_hf(struct sip_msg *msg, EVP_PKEY *pkey,
if (build_unsigned_pport(&unsigned_buf, date_ts, attest, cr_url,
orig_tn, dest_tn, origid) < 0) {
LM_ERR("Failed to build PASSporT\n");
return -1;
return NULL;
}

mdctx = EVP_MD_CTX_create();
Expand Down Expand Up @@ -814,17 +820,7 @@ static int add_identity_hf(struct sip_msg *msg, EVP_PKEY *pkey,
memcpy(hdr_buf.s + hdr_buf.len, CRLF, CRLF_LEN);
hdr_buf.len += CRLF_LEN;

anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0);
if (!anchor) {
LM_ERR("Failed to get anchor lump\n");
goto error;
}
if (!insert_new_lump_before(anchor, hdr_buf.s, hdr_buf.len, 0)) {
LM_ERR("Failed to insert lump\n");
goto error;
}

return 0;
return &hdr_buf;

error:
pkg_free(unsigned_buf.s);
Expand All @@ -836,7 +832,8 @@ static int add_identity_hf(struct sip_msg *msg, EVP_PKEY *pkey,
pkg_free(der_sig_buf.s);
if (sig)
ECDSA_SIG_free(sig);
return -1;

return NULL;
}

static int load_cert(X509 **cert, STACK_OF(X509) **certchain, str *cert_buf)
Expand Down Expand Up @@ -948,15 +945,49 @@ static int check_passport_phonenum(str *num, int log_lev)
return 0;
}

static int fixup_auth_out(void** param)
{
struct auth_out_param *out_p;
str *s = (str*)*param;

out_p = pkg_malloc(sizeof *out_p);
memset(out_p, 0, sizeof *out_p);

if (!str_strcmp(_str(AUTH_OUT_REQ_STR), s)) {
out_p->type = AUTH_APPEND_TO_REQ;
} else if (!str_strcmp(_str(AUTH_OUT_RPL_STR), s)) {
out_p->type = AUTH_APPEND_TO_RPL;
} else if (*s->s == PV_MARKER) {
out_p->type = AUTH_OUT_VAR;

if (pv_parse_spec(s, &out_p->var) == NULL) {
pkg_free(out_p);
LM_ERR("Failed to parese output variable spec\n");
return -1;
}
} else {
LM_ERR("Expected variable or the 'req'/'rpl' flags\n");
return -1;
}

*param = out_p;

return 0;
}

static int w_stir_auth(struct sip_msg *msg, str *attest, str *origid,
str *cert_buf, str *pkey_buf, str *cr_url, str *orig_tn_p, str *dest_tn_p)
str *cert_buf, str *pkey_buf, str *cr_url, str *orig_tn_p, str *dest_tn_p,
struct auth_out_param *out_p)
{
time_t now, date_ts;
struct hdr_field *date_hf = NULL;
X509 *cert;
EVP_PKEY *pkey = NULL;
str orig_tn, dest_tn;
int rc, orig_log_lev = L_ERR, dest_log_lev = L_ERR;
str *hdr_buf = NULL;
struct lump* anchor;
pv_value_t out_val;

/* looking for 'Identity' and 'Date' */
if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
Expand Down Expand Up @@ -1053,18 +1084,49 @@ static int w_stir_auth(struct sip_msg *msg, str *attest, str *origid,
goto error;
}

if (add_identity_hf(msg, pkey, date_ts, attest, cr_url,
orig_tn_p, dest_tn_p, origid) < 0) {
if ((hdr_buf = build_identity_hf(pkey, date_ts, attest, cr_url,
orig_tn_p, dest_tn_p, origid)) == NULL) {
LM_ERR("Failed to add Identity header\n");
rc = -1;
goto error;
}

if (!out_p || out_p->type == AUTH_APPEND_TO_REQ) {
anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0);
if (!anchor) {
LM_ERR("Failed to get anchor lump\n");
rc = -1;
goto error;
}
if (!insert_new_lump_before(anchor, hdr_buf->s, hdr_buf->len, 0)) {
LM_ERR("Failed to insert lump\n");
rc = -1;
goto error;
}
} else if (out_p->type == AUTH_APPEND_TO_RPL) {
if (!add_lump_rpl(msg, hdr_buf->s, hdr_buf->len, LUMP_RPL_HDR)) {
LM_ERR("unable to add reply lump\n");
rc = -1;
goto error;
}
} else {
out_val.flags = PV_VAL_STR;
out_val.rs = *hdr_buf;
if (pv_set_value(msg, &out_p->var, 0, &out_val) != 0) {
rc = -1;
goto error;
}

pkg_free(hdr_buf->s);
}

X509_free(cert);
EVP_PKEY_free(pkey);

return 1;
error:
if (hdr_buf)
pkg_free(hdr_buf->s);
X509_free(cert);
if (pkey)
EVP_PKEY_free(pkey);
Expand Down
14 changes: 14 additions & 0 deletions modules/stir_shaken/stir_shaken.h
Expand Up @@ -94,6 +94,9 @@
#define R_S_INT_LEN 32
#define RAW_SIG_LEN 64

#define AUTH_OUT_REQ_STR "req"
#define AUTH_OUT_RPL_STR "rpl"

struct parsed_identity {
cJSON *header;
cJSON *x5u;
Expand Down Expand Up @@ -123,3 +126,14 @@ enum pv_identity_field {
PV_PAYLOAD_ORIG,
PV_PAYLOAD_ORIGID
};

enum auth_out_type {
AUTH_APPEND_TO_REQ,
AUTH_APPEND_TO_RPL,
AUTH_OUT_VAR
};

struct auth_out_param {
enum auth_out_type type;
pv_spec_t var;
};

0 comments on commit b9f68a4

Please sign in to comment.