Skip to content

Commit

Permalink
Merge branch 'master_fix_parse_qop_value' of https://github.com/sippy…
Browse files Browse the repository at this point in the history
…/opensips into sippy-master_fix_parse_qop_value
  • Loading branch information
liviuchircu committed Sep 25, 2020
2 parents da73077 + 7741da5 commit b532509
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 56 deletions.
67 changes: 37 additions & 30 deletions parser/parse_authenticate.c
Expand Up @@ -82,56 +82,63 @@
#define OPAQUE_STATE 6
#define ALGORITHM_STATE 7

#define STR_ADVANCE_BY(sptr, incr) {(sptr)->s += (incr); (sptr)->len -= (incr);}
#define STR_ADVANCE(sptr) STR_ADVANCE_BY(sptr, 1)

int parse_qop_value(str *val, struct authenticate_body *auth)
int parse_qop_value(str val, struct authenticate_body *auth)
{
char *q = val->s;

/* parse first token */
if (val->len<4 || LOWER4B(GET4B(q))!=0x61757468) /* "auth" */
if (val.len < 4 || LOWER4B(GET4B(val.s))!=0x61757468) /* "auth" */
return -1;
q += 4;
if (q==val->s+val->len) {
STR_ADVANCE_BY(&val, 4);
if (val.len == 0) {
auth->flags |= QOP_AUTH;
return 0;
}
switch (*q) {
switch (*val.s) {
case ' ':
case '\t':
STR_ADVANCE(&val);
auth->flags |= QOP_AUTH;
break;
case '-':
q++;
if (LOWER4B(GET3B(q))==0x696e74ff) {
STR_ADVANCE(&val);
if (val.len >= 3 && LOWER4B(GET3B(val.s))==0x696e74ff) {
auth->flags |= QOP_AUTH_INT;
q+=3;
STR_ADVANCE_BY(&val, 3);
} else
return -1;
break;
case ',':
auth->flags |= QOP_AUTH;
break;
goto postcomma;
default:
return -1;
}

if (q==val->s+val->len) return 0;
while (q<val->s+val->len && isspace((int)*q)) q++;
if (q==val->s+val->len) return 0;
if (*q!=',')
if (val.len == 0)
return 0;
while (val.len > 0 && is_ws(*val.s))
STR_ADVANCE(&val);
if (val.len == 0)
return 0;
if (*val.s != ',')
return -1;
q++;
while (q<val->s+val->len && isspace((int)*q)) q++;
postcomma:
STR_ADVANCE(&val);
while (val.len > 0 && is_ws(*val.s))
STR_ADVANCE(&val);

/* parse second token */
if (val->len-(q-val->s)<4 || LOWER4B(GET4B(q))!=0x61757468) /* "auth" */
if (val.len < 4 || LOWER4B(GET4B(val.s))!=0x61757468) /* "auth" */
return -1;
q += 4;
if (q==val->s+val->len) {
STR_ADVANCE_BY(&val, 4);
if (val.len == 0) {
auth->flags |= QOP_AUTH;
return 0;
}
if (*q == '-' && LOWER4B(GET3B(q+1))==0x696e74ff) {
if (val.len == 4 && *val.s == '-' && LOWER4B(GET3B(val.s+1))==0x696e74ff) {
auth->flags |= QOP_AUTH_INT;
return 0;
} else
Expand Down Expand Up @@ -159,17 +166,17 @@ int parse_authenticate_body( str *body, struct authenticate_body *auth)
end = body->s + body->len;

/* parse the "digest" */
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
if (p+AUTHENTICATE_DIGEST_LEN>=end )
goto parse_error;
if ( LOWER4B( GET4B(p) ) != 0x64696765 /*dige*/ ||
LOWER1B(*(p+4))!=0x73 /*s*/ || LOWER1B(*(p+5))!=0x74 /*t*/)
goto parse_error;
p += AUTHENTICATE_DIGEST_LEN;
if (!isspace((int)*p))
if (!is_ws(*p))
goto parse_error;
p++;
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
if (p==end)
goto parse_error;

Expand Down Expand Up @@ -216,19 +223,19 @@ int parse_authenticate_body( str *body, struct authenticate_body *auth)
}

/* parse to the "=" */
for( n=0 ; p<end&&!isspace((int)*p)&&*p!='=' ; n++,p++ );
for( n=0 ; p<end&&!is_ws(*p)&&*p!='=' ; n++,p++ );
if (p==end)
goto parse_error;
if (n!=0)
state = OTHER_STATE;
name.len = p-name.s;
/* get the '=' */
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
if (p==end || *p!='=')
goto parse_error;
p++;
/* get the value (quoted or not) */
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
if (p+1>=end || (quoted_val && *p!='\"'))
goto parse_error;
if (!quoted_val && *p=='\"')
Expand All @@ -242,19 +249,19 @@ int parse_authenticate_body( str *body, struct authenticate_body *auth)
goto error;
} else {
val.s = p;
while (p<end && !isspace((int)*p) && *p!=',')
while (p<end && !is_ws(*p) && *p!=',')
p++;
}
val.len = p - val.s;
if (val.len==0)
val.s = 0;
/* consume the closing '"' if quoted */
p += quoted_val;
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
if (p<end && *p==',')
{
p++;
while (p<end && isspace((int)*p)) p++;
while (p<end && is_ws(*p)) p++;
}

LM_DBG("<%.*s>=\"%.*s\" state=%d\n",
Expand All @@ -265,7 +272,7 @@ int parse_authenticate_body( str *body, struct authenticate_body *auth)
{
case QOP_STATE:
auth->qop = val;
if (parse_qop_value(&val, auth) < 0)
if (parse_qop_value(val, auth) < 0)
LM_DBG("Unknown token in qop value '%.*s'\n",
val.len, val.s);
break;
Expand Down
2 changes: 1 addition & 1 deletion parser/parse_authenticate.h
Expand Up @@ -55,7 +55,7 @@ int parse_proxy_authenticate_header( struct sip_msg *msg );
int parse_www_authenticate_header( struct sip_msg *msg );
int parse_authenticate_header(struct hdr_field *authenticate);

int parse_qop_value(str *val, struct authenticate_body *auth);
int parse_qop_value(str val, struct authenticate_body *auth);

void free_authenticate(struct authenticate_body *authenticate_b);

Expand Down
53 changes: 53 additions & 0 deletions parser/test/test_oob.c
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 Maksym Sobolyev
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
*/

#include <sys/mman.h>
#include <assert.h>
#include <unistd.h>

#include "../../str.h"
#include "test_oob.h"

void test_oob(const str *sarg, void (*tfunc)(const str *, void *), void *param)
{
char *mpages[3];
str targ;
long page_size = sysconf(_SC_PAGESIZE);

mpages[0] = mmap(NULL, page_size * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(mpages[0] != NULL);
mpages[1] = mpages[0] + page_size;
mpages[2] = mpages[1] + page_size;
for (targ.len = 0; targ.len <= sarg->len; targ.len++) {
targ.s = mpages[1] - targ.len;
assert(mprotect(mpages[0], page_size, PROT_WRITE) == 0);
memcpy(targ.s, sarg->s, targ.len);
assert(mprotect(mpages[0], page_size, PROT_READ) == 0);
tfunc(&targ, param);

targ.s = mpages[2];
assert(mprotect(mpages[2], page_size, PROT_WRITE) == 0);
memcpy(targ.s, sarg->s, targ.len);
assert(mprotect(mpages[2], page_size, PROT_READ) == 0);
tfunc(&targ, param);
}
munmap(mpages[0], page_size * 3);
return;
}
21 changes: 21 additions & 0 deletions parser/test/test_oob.h
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2020 Maksym Sobolyev
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
*/

void test_oob(const str *, void (*)(const str *, void *), void *);
67 changes: 42 additions & 25 deletions parser/test/test_parse_qop.c
Expand Up @@ -25,33 +25,50 @@

#include "../../parser/parse_authenticate.h"

#include "test_oob.h"

void test_parse_qop_oob(const str *, void *);

void test_parse_qop_val(void)
{
struct authenticate_body auth;
int i;
struct tts {
const str ts;
int tres;
int aflags;
} tset[] = {
{.ts = str_init("aut"), .tres = -1},
{.ts = str_init("auth-inti"), .tres = -1},
{.ts = str_init("auth,aut"), .tres = -1},
{.ts = str_init("auth,auth-inti"), .tres = -1},
{.ts = str_init("auth,,auth-int"), .tres = -1},
{.ts = str_init("auth-int,"), .tres = -1},
{.ts = str_init("auth,auth-int,"), .tres = -1},
{.ts = str_init("auth,auth-int,aut"), .tres = -1},
{.ts = str_init("auth-int , \tauth "), .tres = -1},
{.ts = str_init(" auth-int,auth"), .tres = -1},
{.ts = str_init("auth "), .tres = 0, .aflags = QOP_AUTH},
{.ts = str_init("auth-int"), .tres = 0, .aflags = QOP_AUTH_INT},
{.ts = str_init("auth, auth-int"), .tres = 0, .aflags = QOP_AUTH | QOP_AUTH_INT},
{.ts = str_init("auth-int , auth"), .tres = 0, .aflags = QOP_AUTH | QOP_AUTH_INT},
{.ts = STR_NULL}
};

for (i = 0; tset[i].ts.s != NULL; i++) {
memset(&auth, 0, sizeof(struct authenticate_body));
ok(parse_qop_value(tset[i].ts, &auth) == tset[i].tres,
"parse_qop_value(\"%s\") == %d", tset[i].ts.s, tset[i].tres);
if (tset[i].tres == 0)
ok(auth.flags == tset[i].aflags, "auth.flags == %d", tset[i].aflags);
test_oob(&tset[i].ts, test_parse_qop_oob, &auth);
}
}

void test_parse_qop_oob(const str *tstr, void *farg)
{
struct authenticate_body *ap = farg;

memset(&auth, 0, sizeof(struct authenticate_body));
ok(parse_qop_value(_str("aaa"), &auth));
ok(parse_qop_value(_str("auth-init"), &auth));
ok(parse_qop_value(_str("auth,aaa"), &auth));
ok(parse_qop_value(_str("auth,auth-init"), &auth));

memset(&auth, 0, sizeof(struct authenticate_body));
ok(!parse_qop_value(_str("auth "), &auth));
ok(auth.flags & QOP_AUTH);
ok(!(auth.flags & QOP_AUTH_INT));

memset(&auth, 0, sizeof(struct authenticate_body));
ok(!parse_qop_value(_str("auth-int"), &auth));
ok(!(auth.flags & QOP_AUTH));
ok(auth.flags & QOP_AUTH_INT);

memset(&auth, 0, sizeof(struct authenticate_body));
ok(!parse_qop_value(_str("auth, auth-int"), &auth));
ok(auth.flags & QOP_AUTH);
ok(auth.flags & QOP_AUTH_INT);

memset(&auth, 0, sizeof(struct authenticate_body));
ok(!parse_qop_value(_str("auth-int , auth"), &auth));
ok(auth.flags & QOP_AUTH);
ok(auth.flags & QOP_AUTH_INT);
parse_qop_value(*tstr, ap);
ok(1, "oob check: parse_qop_value(\"%.*s\")", tstr->len, tstr->s);
}

0 comments on commit b532509

Please sign in to comment.