Skip to content

Commit

Permalink
registrar: Configurable max username/domain/AoR lengths
Browse files Browse the repository at this point in the history
Also merge copy-pasted extract_aor() function into lib/reg directory.
  • Loading branch information
liviuchircu authored and razvancrainea committed Feb 11, 2020
1 parent 29ba576 commit 5f6710c
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 389 deletions.
174 changes: 173 additions & 1 deletion lib/reg/sip_msg.c
Expand Up @@ -2,7 +2,7 @@
* Registrar specific SIP message processing
*
* Copyright (C) 2001-2003 FhG Fokus
* Copyright (C) 2016 OpenSIPS Solutions
* Copyright (C) 2016-2020 OpenSIPS Solutions
*
* This file is part of opensips, a free SIP server.
*
Expand All @@ -22,9 +22,28 @@
*/

#include "../../parser/contact/parse_contact.h"
#include "../../parser/parse_uri.h"

#include "sip_msg.h"
#include "rerrno.h"

#define TEMP_GRUU "tgruu."
#define TEMP_GRUU_SIZE (sizeof(TEMP_GRUU)-1)

#define MAX_TGRUU_SIZE 255
#define GR_MAGIC 73
char tgruu_dec[MAX_TGRUU_SIZE];

/* each variable must be exported by each registrar */
extern str gruu_secret;
extern str default_gruu_secret;
extern int case_sensitive;
extern str realm_prefix;
extern int reg_use_domain;
extern int max_username_len;
extern int max_domain_len;
extern int max_aor_len;

/*! \brief
* Parse the whole message and bodies of all header fields
* that will be needed by registrar
Expand Down Expand Up @@ -80,6 +99,159 @@ int parse_reg_headers(struct sip_msg* _m)
return 0;
}

/*! \brief
* Extract Address of Record
* In case of public GRUUs, also populates sip_instance
* In case of temp GRUUs, also populates call_id
*/
int extract_aor(str* _uri, str* _a, str *sip_instance, str* call_id)
{
static char *aor_buf;

str tmp;
struct sip_uri puri;
int user_len,tgruu_len,dec_size,i;
str *magic;

if (parse_uri(_uri->s, _uri->len, &puri) < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

/* if have ;gr param and func caller is interested in
* potentially extracting the sip instance */
if ((puri.gr.s && puri.gr.len) && sip_instance)
{
LM_DBG("has gruu\n");

/* ;gr param detected */
if (memcmp(puri.user.s,TEMP_GRUU,TEMP_GRUU_SIZE) == 0)
{
LM_DBG("temp gruu\n");
/* temp GRUU, decode and extract aor, sip_instance
* and call_id */
tgruu_len = puri.user.len - TEMP_GRUU_SIZE;
memcpy(tgruu_dec,puri.user.s+TEMP_GRUU_SIZE,tgruu_len);

if (gruu_secret.s)
magic = &gruu_secret;
else
magic = &default_gruu_secret;

dec_size = base64decode((unsigned char *)tgruu_dec,
(unsigned char *)tgruu_dec,tgruu_len);

for (i=0;i<tgruu_len;i++)
tgruu_dec[i] ^= magic->s[i%magic->len];

LM_DBG("decoded [%.*s]\n",dec_size,tgruu_dec);
/* extract aor - skip tgruu generation time at
* the beggining */
_a->s = (char *)memchr(tgruu_dec,' ',dec_size) + 1;
if (_a->s == NULL) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
_a->len = (char *)memchr(_a->s,' ',dec_size - (_a->s-tgruu_dec)) - _a->s;
if (_a->len < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

sip_instance->s = _a->s+_a->len+1; /* skip ' ' */
if (sip_instance->s >= tgruu_dec + dec_size) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
sip_instance->len = (char *)memchr(sip_instance->s,' ',
dec_size-(sip_instance->s-tgruu_dec)) - sip_instance->s;
if (sip_instance->len < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

call_id->s = sip_instance->s + sip_instance->len + 1;
if (call_id->s >= tgruu_dec + dec_size) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
call_id->len = (tgruu_dec+dec_size) - call_id->s;

LM_DBG("extracted aor [%.*s] and instance [%.*s] and callid [%.*s]\n",_a->len,_a->s,
sip_instance->len,sip_instance->s,call_id->len,call_id->s);

/* skip checks - done at save() */
return 0;
}
else
{
LM_DBG("public gruu\n");
*sip_instance = puri.gr_val;
}
}

if ( (puri.user.len + puri.host.len + 1) > max_aor_len
|| puri.user.len > max_username_len
|| puri.host.len > max_domain_len ) {
rerrno = R_AOR_LEN;
LM_ERR("Address Of Record too long\n");
return -2;
}

if (!aor_buf) {
aor_buf = pkg_malloc(max_aor_len + 1);
if (!aor_buf) {
LM_ERR("oom\n");
rerrno = R_INTERNAL;
return -1;
}
}

_a->s = aor_buf;
_a->len = puri.user.len;

if (un_escape(&puri.user, _a) < 0) {
rerrno = R_UNESCAPE;
LM_ERR("failed to unescape username\n");
return -3;
}

user_len = _a->len;

if (reg_use_domain) {
if (user_len)
aor_buf[_a->len++] = '@';
/* strip prefix (if defined) */
if (realm_prefix.len && realm_prefix.len<puri.host.len &&
(memcmp(realm_prefix.s, puri.host.s, realm_prefix.len)==0) ) {
memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len,
puri.host.len - realm_prefix.len);
_a->len += puri.host.len - realm_prefix.len;
} else {
memcpy(aor_buf + _a->len, puri.host.s, puri.host.len);
_a->len += puri.host.len;
}
}

_a->s[_a->len] = '\0';

if (case_sensitive && user_len) {
tmp.s = _a->s + user_len + 1;
tmp.len = _a->s + _a->len - tmp.s;
strlower(&tmp);
} else {
strlower(_a);
}

return 0;
}

#define has_nonzero_exp(_m) \
(!_m->expires || !((exp_body_t*)_m->expires->parsed)->valid || \
((exp_body_t*)_m->expires->parsed)->val != 0)
Expand Down
4 changes: 4 additions & 0 deletions lib/reg/sip_msg.h
Expand Up @@ -40,6 +40,10 @@
*/
int parse_reg_headers(struct sip_msg* _m);

/*! \brief
* Extract Address Of Record
*/
int extract_aor(str* _uri, str* _a, str* sip_instance, str* call_id);

/*! \brief
* Check if the originating REGISTER message was formed correctly
Expand Down
1 change: 1 addition & 0 deletions modules/mid_registrar/lookup.c
Expand Up @@ -35,6 +35,7 @@

#include "../../lib/reg/regtime.h"
#include "../../lib/reg/ci.h"
#include "../../lib/reg/sip_msg.h"
#include "../../parser/parse_rr.h"
#include "../../parser/parse_uri.h"
#include "../../dset.h"
Expand Down
2 changes: 0 additions & 2 deletions modules/mid_registrar/mid_registrar.h
Expand Up @@ -163,8 +163,6 @@ void mri_free(struct mid_reg_info *mri);
void set_ct(struct mid_reg_info *ct);
struct mid_reg_info *get_ct(void);

int extract_aor(str* _uri, str* _a,str *sip_instance,str *call_id);

int get_expires_hf(struct sip_msg* _m);
str get_extra_ct_params(struct sip_msg *msg);

Expand Down
138 changes: 0 additions & 138 deletions modules/mid_registrar/save.c
Expand Up @@ -2088,144 +2088,6 @@ int send_reply(struct sip_msg* _m, unsigned int _flags)
} else return 0;
}

int extract_aor(str* _uri, str* _a,str *sip_instance,str *call_id)
{
char aor_buf[max_aor_len + 1];

str tmp;
struct sip_uri puri;
int user_len,tgruu_len,dec_size,i;
str *magic;

if (parse_uri(_uri->s, _uri->len, &puri) < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

/* if have ;gr param and func caller is interested in
* potentially extracting the sip instance */
if ((puri.gr.s && puri.gr.len) && sip_instance)
{
LM_DBG("has gruu\n");

/* ;gr param detected */
if (memcmp(puri.user.s,TEMP_GRUU,TEMP_GRUU_SIZE) == 0)
{
LM_DBG("temp gruu\n");
/* temp GRUU, decode and extract aor, sip_instance
* and call_id */
tgruu_len = puri.user.len - TEMP_GRUU_SIZE;
memcpy(tgruu_dec,puri.user.s+TEMP_GRUU_SIZE,tgruu_len);

if (gruu_secret.s != NULL)
magic = &gruu_secret;
else
magic = &default_gruu_secret;

dec_size = base64decode((unsigned char *)tgruu_dec,
(unsigned char *)tgruu_dec,tgruu_len);

for (i=0;i<tgruu_len;i++)
tgruu_dec[i] ^= magic->s[i%magic->len];

LM_DBG("decoded [%.*s]\n",dec_size,tgruu_dec);
/* extract aor - skip tgruu generation time at
* the beggining */
_a->s = (char *)memchr(tgruu_dec,' ',dec_size) + 1;
if (_a->s == NULL) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
_a->len = (char *)memchr(_a->s,' ',dec_size - (_a->s-tgruu_dec)) - _a->s;
if (_a->len < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

sip_instance->s = _a->s+_a->len+1; /* skip ' ' */
if (sip_instance->s >= tgruu_dec + dec_size) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
sip_instance->len = (char *)memchr(sip_instance->s,' ',
dec_size-(sip_instance->s-tgruu_dec)) - sip_instance->s;
if (sip_instance->len < 0) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}

call_id->s = sip_instance->s + sip_instance->len + 1;
if (call_id->s >= tgruu_dec + dec_size) {
rerrno = R_AOR_PARSE;
LM_ERR("failed to parse Address of Record\n");
return -1;
}
call_id->len = (tgruu_dec+dec_size) - call_id->s;

LM_DBG("extracted aor [%.*s] and instance [%.*s] and callid [%.*s]\n",_a->len,_a->s,
sip_instance->len,sip_instance->s,call_id->len,call_id->s);

/* skip checks - done at save() */
return 0;
}
else
{
LM_DBG("public gruu\n");
*sip_instance = puri.gr_val;
}
}

if ( (puri.user.len + puri.host.len + 1) > max_aor_len
|| puri.user.len > max_username_len
|| puri.host.len > max_domain_len ) {
rerrno = R_AOR_LEN;
LM_ERR("Address Of Record too long\n");
return -2;
}

_a->s = aor_buf;
_a->len = puri.user.len;

if (un_escape(&puri.user, _a) < 0) {
rerrno = R_UNESCAPE;
LM_ERR("failed to unescape username\n");
return -3;
}

user_len = _a->len;

if (reg_use_domain) {
if (user_len)
aor_buf[_a->len++] = '@';
/* strip prefix (if defined) */
if (realm_prefix.len && realm_prefix.len<puri.host.len &&
(memcmp(realm_prefix.s, puri.host.s, realm_prefix.len)==0) ) {
memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len,
puri.host.len - realm_prefix.len);
_a->len += puri.host.len - realm_prefix.len;
} else {
memcpy(aor_buf + _a->len, puri.host.s, puri.host.len);
_a->len += puri.host.len;
}
}

_a->s[_a->len] = '\0';

if (case_sensitive && user_len) {
tmp.s = _a->s + user_len + 1;
tmp.len = _a->s + _a->len - tmp.s;
strlower(&tmp);
} else {
strlower(_a);
}

return 0;
}

/**
* In MID_REG_THROTTLE_CT mode, when a REGISTER comes in:
Expand Down

0 comments on commit 5f6710c

Please sign in to comment.