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

sip,uri,test: Escape SIP URIs #740

Merged
merged 4 commits into from
Mar 28, 2023
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
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