Skip to content

Commit

Permalink
sip,uri,test: Escape SIP URIs (#740)
Browse files Browse the repository at this point in the history
* Escape SIP URIs

According to RFC 3261, SIP URIs need to escape UTF-8 characters.

* uric & print: use %W for printing escaped characters

* uri: remove ipv6 ifdef checks

* uric: cast isalnum argument
  • Loading branch information
maximilianfridrich authored Mar 28, 2023
1 parent 456b764 commit e03e282
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 14 deletions.
3 changes: 3 additions & 0 deletions include/re_uri.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ int uri_param_escape(struct re_printf *pf, const struct pl *pl);
int uri_param_unescape(struct re_printf *pf, const struct pl *pl);
int uri_header_escape(struct re_printf *pf, const struct pl *pl);
int uri_header_unescape(struct re_printf *pf, const struct pl *pl);
int uri_display_name_escape(struct re_printf *pf, const struct pl *pl);
int uri_escape(struct re_printf *pf, const char *uri);
int uri_escape_pl(struct re_printf *pf, const struct pl *pl);
3 changes: 2 additions & 1 deletion src/sip/ctrans.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ static bool route_handler(const struct sip_hdr *hdr, const struct sip_msg *msg,
void *arg)
{
(void)msg;
return 0 != mbuf_printf(arg, "Route: %r\r\n", &hdr->val);
return 0 != mbuf_printf(arg, "Route: %H\r\n", uri_escape_pl,
&hdr->val);
}


Expand Down
19 changes: 12 additions & 7 deletions src/sip/dialog.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,21 @@ int sip_dialog_alloc(struct sip_dialog **dlgp,
}

for (i=0; i<routec; i++) {
err |= mbuf_printf(dlg->mb, "Route: <%s;lr>\r\n", routev[i]);
err |= mbuf_printf(dlg->mb, "Route: <%H;lr>\r\n", uri_escape,
routev[i]);
if (i == 0)
rend = dlg->mb->pos - 2;
}
err |= mbuf_printf(dlg->mb, "To: <%s>\r\n", to_uri);
err |= mbuf_printf(dlg->mb, "To: <%H>\r\n", uri_escape, to_uri);
dlg->cpos = dlg->mb->pos;
err |= mbuf_printf(dlg->mb, "From: %s%s%s<%s>;tag=%016llx\r\n",
from_name ? "\"" : "", from_name,
from_name ? "\" " : "",
from_uri, ltag);
err |= mbuf_printf(dlg->mb, "From: ");
if (from_name) {
pl_set_str(&pl, from_name);
err |= mbuf_printf(dlg->mb, "\"%H\" ", uri_display_name_escape,
&pl);
}
err |= mbuf_printf(dlg->mb, "<%H>", uri_escape, from_uri);
err |= mbuf_printf(dlg->mb, ";tag=%016llx\r\n", ltag);
if (err)
goto out;

Expand Down Expand Up @@ -156,7 +161,7 @@ static bool record_route_handler(const struct sip_hdr *hdr,
struct route_enc *renc = arg;
(void)msg;

if (mbuf_printf(renc->mb, "Route: %r\r\n", &hdr->val))
if (mbuf_printf(renc->mb, "Route: %H\r\n", uri_escape_pl, &hdr->val))
return true;

if (!renc->end)
Expand Down
3 changes: 2 additions & 1 deletion src/sip/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ static int request(struct sip_request *req, enum sip_transp tp,
goto out;

mbuf_set_pos(mbs, 0);
err = mbuf_printf(mb, "%s %s SIP/2.0\r\n", req->met, req->uri);
err = mbuf_printf(mb, "%s ", req->met);
err |= mbuf_printf(mb, "%H SIP/2.0\r\n", uri_escape, req->uri);
err |= mbuf_printf(mb, "Via: SIP/2.0/%s %J;branch=%s;rport\r\n",
sip_transp_name(tp), &laddr, branch);
err |= mbuf_write_mem(mb, mbuf_buf(mbs), mbuf_get_left(mbs));
Expand Down
81 changes: 79 additions & 2 deletions src/uri/uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ int uri_encode(struct re_printf *pf, const struct uri *uri)
/* The IPv6 address is delimited by '[' and ']' */
switch (uri->af) {

#ifdef HAVE_INET6
case AF_INET6:
err = re_hprintf(pf, "[%r]", &uri->host);
break;
#endif

default:
err = re_hprintf(pf, "%r", &uri->host);
Expand Down Expand Up @@ -271,3 +269,82 @@ int uri_headers_apply(const struct pl *pl, uri_apply_h *ah, void *arg)

return err;
}


/**
* Escape SIP URI
*
* @param pf Print function to encode into
* @param uri URI
*
* @return 0 if success, otherwise errorcode
*/
int uri_escape(struct re_printf *pf, const char *uri)
{
struct pl pl;
pl_set_str(&pl, uri);
return uri_escape_pl(pf, &pl);
}


/**
* Escape SIP URI
*
* @param pf Print function to encode into
* @param pl URI
*
* @return 0 if success, otherwise errorcode
*/
int uri_escape_pl(struct re_printf *pf, const struct pl *pl)
{
int err;
struct uri uri;

if (!pl)
return 0;

err = uri_decode(&uri, pl);
if (err)
return err;

if (!pl_isset(&uri.scheme) || !pl_isset(&uri.host))
return EINVAL;

err = re_hprintf(pf, "%r:", &uri.scheme);
if (err)
return err;

if (pl_isset(&uri.user)) {
err = re_hprintf(pf, "%H", uri_user_escape, &uri.user);

if (pl_isset(&uri.password))
err |= re_hprintf(pf, ":%H", uri_password_escape,
&uri.password);

err |= pf->vph("@", 1, pf->arg);
if (err)
return err;
}

/* The IPv6 address is delimited by '[' and ']' */
switch (uri.af) {

case AF_INET6:
err = re_hprintf(pf, "[%r]", &uri.host);
break;

default:
err = re_hprintf(pf, "%r", &uri.host);
break;
}
if (err)
return err;

if (uri.port)
err = re_hprintf(pf, ":%u", uri.port);

err |= re_hprintf(pf, "%r%r%r", &uri.path, &uri.params,
&uri.headers);

return err;
}
45 changes: 43 additions & 2 deletions src/uri/uric.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static bool is_mark(int c)

static bool is_unreserved(char c)
{
return isalnum(c) || is_mark(c);
return isalnum((unsigned char)c) || is_mark(c);
}


Expand Down Expand Up @@ -120,6 +120,33 @@ static bool is_param_unreserved(char c)
}


static bool is_token_non_alphanum(int c)
{
switch (c) {

case '-':
case '.':
case '!':
case '%':
case '*':
case '_':
case '+':
case '`':
case '\'':
case '~':
return true;
default:
return false;
}
}


static bool is_token(char c)
{
return isalnum((unsigned char)c) || is_token_non_alphanum(c);
}


static bool is_paramchar(char c)
{
return is_param_unreserved(c) || is_unreserved(c);
Expand Down Expand Up @@ -147,7 +174,7 @@ static int comp_escape(struct re_printf *pf, const struct pl *pl, esc_h *eh)
err = pf->vph(&c, 1, pf->arg);
}
else {
err = re_hprintf(pf, "%%%02X", c);
err = re_hprintf(pf, "%%%W", &c, 1);
}
}

Expand Down Expand Up @@ -304,3 +331,17 @@ int uri_header_unescape(struct re_printf *pf, const struct pl *pl)
{
return comp_unescape(pf, pl, is_hvalue);
}


/**
* Escape display name
*
* @param pf Print function
* @param pl String to escape
*
* @return 0 if success, otherwise errorcode
*/
int uri_display_name_escape(struct re_printf *pf, const struct pl *pl)
{
return comp_escape(pf, pl, is_token);
}
3 changes: 2 additions & 1 deletion test/uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ int test_uri_user(void)
} uriv[] = {
{"alice%40atlanta.com", "[email protected]"},
{"project%20x", "project x"},
{"*21%23", "*21#"}
{"*21%23", "*21#"},
{"*21%23%C3%A4%E2%82%AC%40%20", "*21#ä\xE2\x82\xAC@ "}
};
struct mbuf mbe, mbd;
int err = EINVAL;
Expand Down

0 comments on commit e03e282

Please sign in to comment.