Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
a9b6eb18
Commit
a9b6eb18
authored
Dec 03, 2010
by
Arnout Vandecappelle (Essensium/Mind)
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix for issue#209: support spaces, commas, quotes and other weirdness in Authorization header.
parent
d9c05f99
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
68 additions
and
26 deletions
+68
-26
mongoose.c
mongoose.c
+57
-25
test.pl
test/test.pl
+11
-1
No files found.
mongoose.c
View file @
a9b6eb18
...
@@ -639,24 +639,56 @@ static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
...
@@ -639,24 +639,56 @@ static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
}
}
// Skip the characters until one of the delimiters characters found.
// Skip the characters until one of the delimiters characters found.
// 0-terminate resulting word. Skip the
rest of the delimiter
s if any.
// 0-terminate resulting word. Skip the
delimiter and following whitespace
s if any.
// Advance pointer to buffer to the next word. Return found 0-terminated word.
// Advance pointer to buffer to the next word. Return found 0-terminated word.
static
char
*
skip
(
char
**
buf
,
const
char
*
delimiters
)
{
// Delimiters can be quoted with quotechar.
char
*
p
,
*
begin_word
,
*
end_word
,
*
end_delimiters
;
static
char
*
skip_quoted
(
char
**
buf
,
const
char
*
delimiters
,
const
char
*
whitespace
,
char
quotechar
)
{
char
*
p
,
*
begin_word
,
*
end_word
,
*
end_whitespace
;
begin_word
=
*
buf
;
begin_word
=
*
buf
;
end_word
=
begin_word
+
strcspn
(
begin_word
,
delimiters
);
end_word
=
begin_word
+
strcspn
(
begin_word
,
delimiters
);
end_delimiters
=
end_word
+
strspn
(
end_word
,
delimiters
);
for
(
p
=
end_word
;
p
<
end_delimiters
;
p
++
)
{
/* Check for quotechar */
if
(
end_word
>
begin_word
)
{
p
=
end_word
-
1
;
while
(
*
p
==
quotechar
)
{
/* If there is anything beyond end_word, copy it */
if
(
*
end_word
==
'\0'
)
{
*
p
=
'\0'
;
break
;
}
else
{
size_t
end_off
=
strcspn
(
end_word
+
1
,
delimiters
);
memmove
(
p
,
end_word
,
end_off
+
1
);
p
+=
end_off
;
/* p must correspond to end_word - 1 */
end_word
+=
end_off
+
1
;
}
}
for
(
p
++
;
p
<
end_word
;
p
++
)
{
*
p
=
'\0'
;
}
}
if
(
*
end_word
==
'\0'
)
{
*
buf
=
end_word
;
}
else
{
end_whitespace
=
end_word
+
1
+
strspn
(
end_word
+
1
,
whitespace
);
for
(
p
=
end_word
;
p
<
end_whitespace
;
p
++
)
{
*
p
=
'\0'
;
*
p
=
'\0'
;
}
}
*
buf
=
end_delimiters
;
*
buf
=
end_whitespace
;
}
return
begin_word
;
return
begin_word
;
}
}
// Simplified version of skip_quoted without quote char and whitespace == delimiters
static
char
*
skip
(
char
**
buf
,
const
char
*
delimiters
)
{
return
skip_quoted
(
buf
,
delimiters
,
delimiters
,
0
);
}
// Return HTTP header value, or NULL if not found.
// Return HTTP header value, or NULL if not found.
static
const
char
*
get_header
(
const
struct
mg_request_info
*
ri
,
static
const
char
*
get_header
(
const
struct
mg_request_info
*
ri
,
const
char
*
name
)
{
const
char
*
name
)
{
...
@@ -2058,26 +2090,26 @@ static int parse_auth_header(struct mg_connection *conn, char *buf,
...
@@ -2058,26 +2090,26 @@ static int parse_auth_header(struct mg_connection *conn, char *buf,
s
=
buf
;
s
=
buf
;
(
void
)
memset
(
ah
,
0
,
sizeof
(
*
ah
));
(
void
)
memset
(
ah
,
0
,
sizeof
(
*
ah
));
// Parse authorization header
for
(;;)
{
// Gobble initial spaces
// Gobble initial spaces
while
(
isspace
(
*
(
unsigned
char
*
)
s
))
{
while
(
isspace
(
*
(
unsigned
char
*
)
s
))
{
s
++
;
s
++
;
}
}
name
=
skip_quoted
(
&
s
,
"="
,
" "
,
0
);
// Parse authorization header
/* Value is either quote-delimited, or ends at first comma or space. */
for
(;;)
{
if
(
s
[
0
]
==
'\"'
)
{
name
=
skip
(
&
s
,
"="
);
s
++
;
value
=
skip
(
&
s
,
", "
);
// IE uses commas, FF uses spaces
value
=
skip_quoted
(
&
s
,
"
\"
"
,
" "
,
'\\'
);
if
(
s
[
0
]
==
','
)
{
// Handle commas: Digest username="a", realm="b", ...
s
++
;
if
(
value
[
strlen
(
value
)
-
1
]
==
','
)
{
value
[
strlen
(
value
)
-
1
]
=
'\0'
;
}
}
}
// Trim double quotes around values
else
if
(
*
value
==
'"'
)
{
{
value
++
;
value
=
skip_quoted
(
&
s
,
", "
,
" "
,
0
);
// IE uses commas, FF uses spaces
value
[
strlen
(
value
)
-
1
]
=
'\0'
;
}
}
else
if
(
*
valu
e
==
'\0'
)
{
if
(
*
nam
e
==
'\0'
)
{
break
;
break
;
}
}
...
@@ -2532,7 +2564,7 @@ static void parse_http_headers(char **buf, struct mg_request_info *ri) {
...
@@ -2532,7 +2564,7 @@ static void parse_http_headers(char **buf, struct mg_request_info *ri) {
int
i
;
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
ri
->
http_headers
);
i
++
)
{
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
ri
->
http_headers
);
i
++
)
{
ri
->
http_headers
[
i
].
name
=
skip
(
buf
,
": "
);
ri
->
http_headers
[
i
].
name
=
skip
_quoted
(
buf
,
":"
,
" "
,
0
);
ri
->
http_headers
[
i
].
value
=
skip
(
buf
,
"
\r\n
"
);
ri
->
http_headers
[
i
].
value
=
skip
(
buf
,
"
\r\n
"
);
if
(
ri
->
http_headers
[
i
].
name
[
0
]
==
'\0'
)
if
(
ri
->
http_headers
[
i
].
name
[
0
]
==
'\0'
)
break
;
break
;
...
...
test/test.pl
View file @
a9b6eb18
...
@@ -303,11 +303,19 @@ o("GET /$test_dir_uri/sort/?dd HTTP/1.0\n\n",
...
@@ -303,11 +303,19 @@ o("GET /$test_dir_uri/sort/?dd HTTP/1.0\n\n",
unless
(
scalar
(
@ARGV
)
>
0
and
$ARGV
[
0
]
eq
"basic_tests"
)
{
unless
(
scalar
(
@ARGV
)
>
0
and
$ARGV
[
0
]
eq
"basic_tests"
)
{
# Check that .htpasswd file existence trigger authorization
# Check that .htpasswd file existence trigger authorization
write_file
(
"$root/.htpasswd"
,
''
);
write_file
(
"$root/.htpasswd"
,
'
user with space, " and comma:mydomain.com:5deda12442309cbdcdffc6b2737a894f
'
);
o
(
"GET /hello.txt HTTP/1.1\n\n"
,
'401 Unauthorized'
,
o
(
"GET /hello.txt HTTP/1.1\n\n"
,
'401 Unauthorized'
,
'.htpasswd - triggering auth on file request'
);
'.htpasswd - triggering auth on file request'
);
o
(
"GET / HTTP/1.1\n\n"
,
'401 Unauthorized'
,
o
(
"GET / HTTP/1.1\n\n"
,
'401 Unauthorized'
,
'.htpasswd - triggering auth on directory request'
);
'.htpasswd - triggering auth on directory request'
);
# Test various funky things in an authentication header.
o
(
"GET /hello.txt HTTP/1.0\nAuthorization: Digest eq== empty=\"\", empty2=, quoted=\"blah foo bar, baz\\\"\\\" more\\\"\", unterminatedquoted=\" doesn't stop\n\n"
,
'401 Unauthorized'
,
'weird auth values should not cause crashes'
);
my
$auth_header
=
"Digest username=\"user with space, \\\" and comma\", "
.
"realm=\"mydomain.com\", nonce=\"1291376417\", uri=\"/\","
.
"response=\"e8dec0c2a1a0c8a7e9a97b4b5ea6a6e6\", qop=auth, nc=00000001, cnonce=\"1a49b53a47a66e82\""
;
o
(
"GET /hello.txt HTTP/1.0\nAuthorization: $auth_header\n\n"
,
'HTTP/1.1 200 OK'
,
'GET regular file with auth'
);
unlink
"$root/.htpasswd"
;
unlink
"$root/.htpasswd"
;
o
(
"GET /env.cgi HTTP/1.0\n\r\n"
,
'HTTP/1.1 200 OK'
,
'GET CGI file'
);
o
(
"GET /env.cgi HTTP/1.0\n\r\n"
,
'HTTP/1.1 200 OK'
,
'GET CGI file'
);
...
@@ -378,6 +386,8 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
...
@@ -378,6 +386,8 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
}
}
sub
do_PUT_test
{
sub
do_PUT_test
{
# This only works because mongoose currently doesn't look at the nonce.
# It should really be rejected...
my
$auth_header
=
"Authorization: Digest username=guest, "
.
my
$auth_header
=
"Authorization: Digest username=guest, "
.
"realm=mydomain.com, nonce=1145872809, uri=/put.txt, "
.
"realm=mydomain.com, nonce=1145872809, uri=/put.txt, "
.
"response=896327350763836180c61d87578037d9, qop=auth, "
.
"response=896327350763836180c61d87578037d9, qop=auth, "
.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment