Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
8579b8a9
Commit
8579b8a9
authored
Aug 15, 2016
by
Tatsuhiro Tsujikawa
Committed by
GitHub
Aug 15, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #646 from nghttp2/invalid-header-cb
Add nghttp2_on_invalid_header_callback
parents
8df2c357
271f7fbb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
240 additions
and
7 deletions
+240
-7
doc/Makefile.am
doc/Makefile.am
+2
-0
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+89
-6
lib/nghttp2_callbacks.c
lib/nghttp2_callbacks.c
+12
-0
lib/nghttp2_callbacks.h
lib/nghttp2_callbacks.h
+7
-0
lib/nghttp2_session.c
lib/nghttp2_session.c
+33
-0
tests/nghttp2_session_test.c
tests/nghttp2_session_test.c
+97
-1
No files found.
doc/Makefile.am
View file @
8579b8a9
...
...
@@ -87,6 +87,8 @@ APIDOCS= \
nghttp2_session_callbacks_set_on_header_callback.rst
\
nghttp2_session_callbacks_set_on_header_callback2.rst
\
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst
\
nghttp2_session_callbacks_set_on_invalid_header_callback.rst
\
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst
\
nghttp2_session_callbacks_set_on_stream_close_callback.rst
\
nghttp2_session_callbacks_set_pack_extension_callback.rst
\
nghttp2_session_callbacks_set_recv_callback.rst
\
...
...
lib/includes/nghttp2/nghttp2.h
View file @
8579b8a9
...
...
@@ -1721,6 +1721,65 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
nghttp2_rcbuf
*
value
,
uint8_t
flags
,
void
*
user_data
);
/**
* @functypedef
*
* Callback function invoked when a invalid header name/value pair is
* received for the |frame|.
*
* The parameter and behaviour are similar to
* :type:`nghttp2_on_header_callback`. The difference is that this
* callback is only invoked when a invalid header name/value pair is
* received which is silently ignored if this callback is not set.
* Only invalid regular header field are passed to this callback. In
* other words, invalid pseudo header field is not passed to this
* callback. Also header fields which includes upper cased latter are
* also treated as error without passing them to this callback.
*
* This callback is only considered if HTTP messaging validation is
* turned on (which is on by default, see
* `nghttp2_option_set_no_http_messaging()`).
*
* With this callback, application inspects the incoming invalid
* field, and it also can reset stream from this callback by returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, or using
* `nghttp2_submit_rst_stream()` directly with the error code of
* choice.
*/
typedef
int
(
*
nghttp2_on_invalid_header_callback
)(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
uint8_t
flags
,
void
*
user_data
);
/**
* @functypedef
*
* Callback function invoked when a invalid header name/value pair is
* received for the |frame|.
*
* The parameter and behaviour are similar to
* :type:`nghttp2_on_header_callback2`. The difference is that this
* callback is only invoked when a invalid header name/value pair is
* received which is silently ignored if this callback is not set.
* Only invalid regular header field are passed to this callback. In
* other words, invalid pseudo header field is not passed to this
* callback. Also header fields which includes upper cased latter are
* also treated as error without passing them to this callback.
*
* This callback is only considered if HTTP messaging validation is
* turned on (which is on by default, see
* `nghttp2_option_set_no_http_messaging()`).
*
* With this callback, application inspects the incoming invalid
* field, and it also can reset stream from this callback by returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, or using
* `nghttp2_submit_rst_stream()` directly with the error code of
* choice.
*/
typedef
int
(
*
nghttp2_on_invalid_header_callback2
)(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
nghttp2_rcbuf
*
name
,
nghttp2_rcbuf
*
value
,
uint8_t
flags
,
void
*
user_data
);
/**
* @functypedef
*
...
...
@@ -2079,6 +2138,29 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
nghttp2_session_callbacks
*
cbs
,
nghttp2_on_header_callback2
on_header_callback2
);
/**
* @function
*
* Sets callback function invoked when a invalid header name/value
* pair is received. If both
* `nghttp2_session_callbacks_set_on_invalid_header_callback()` and
* `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are
* used to set callbacks, the latter takes the precedence.
*/
NGHTTP2_EXTERN
void
nghttp2_session_callbacks_set_on_invalid_header_callback
(
nghttp2_session_callbacks
*
cbs
,
nghttp2_on_invalid_header_callback
on_invalid_header_callback
);
/**
* @function
*
* Sets callback function invoked when a invalid header name/value
* pair is received.
*/
NGHTTP2_EXTERN
void
nghttp2_session_callbacks_set_on_invalid_header_callback2
(
nghttp2_session_callbacks
*
cbs
,
nghttp2_on_invalid_header_callback2
on_invalid_header_callback2
);
/**
* @function
*
...
...
@@ -2738,12 +2820,13 @@ nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr);
* taken. If the frame is either HEADERS or PUSH_PROMISE,
* :type:`nghttp2_on_begin_headers_callback` is invoked. Then
* :type:`nghttp2_on_header_callback` is invoked for each header
* name/value pair. After all name/value pairs are emitted
* successfully, :type:`nghttp2_on_frame_recv_callback` is
* invoked. For other frames,
* :type:`nghttp2_on_frame_recv_callback` is invoked. If the
* reception of the frame triggers the closure of the stream,
* :type:`nghttp2_on_stream_close_callback` is invoked.
* name/value pair. For invalid header field,
* :type:`nghttp2_on_invalid_header_callback` is called. After
* all name/value pairs are emitted successfully,
* :type:`nghttp2_on_frame_recv_callback` is invoked. For other
* frames, :type:`nghttp2_on_frame_recv_callback` is invoked.
* If the reception of the frame triggers the closure of the
* stream, :type:`nghttp2_on_stream_close_callback` is invoked.
*
* 3. If the received frame is unpacked but is interpreted as
* invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is
...
...
lib/nghttp2_callbacks.c
View file @
8579b8a9
...
...
@@ -110,6 +110,18 @@ void nghttp2_session_callbacks_set_on_header_callback2(
cbs
->
on_header_callback2
=
on_header_callback2
;
}
void
nghttp2_session_callbacks_set_on_invalid_header_callback
(
nghttp2_session_callbacks
*
cbs
,
nghttp2_on_invalid_header_callback
on_invalid_header_callback
)
{
cbs
->
on_invalid_header_callback
=
on_invalid_header_callback
;
}
void
nghttp2_session_callbacks_set_on_invalid_header_callback2
(
nghttp2_session_callbacks
*
cbs
,
nghttp2_on_invalid_header_callback2
on_invalid_header_callback2
)
{
cbs
->
on_invalid_header_callback2
=
on_invalid_header_callback2
;
}
void
nghttp2_session_callbacks_set_select_padding_callback
(
nghttp2_session_callbacks
*
cbs
,
nghttp2_select_padding_callback
select_padding_callback
)
{
...
...
lib/nghttp2_callbacks.h
View file @
8579b8a9
...
...
@@ -92,6 +92,13 @@ struct nghttp2_session_callbacks {
*/
nghttp2_on_header_callback
on_header_callback
;
nghttp2_on_header_callback2
on_header_callback2
;
/**
* Callback function invoked when a invalid header name/value pair
* is received which is silently ignored if these callbacks are not
* set.
*/
nghttp2_on_invalid_header_callback
on_invalid_header_callback
;
nghttp2_on_invalid_header_callback2
on_invalid_header_callback2
;
/**
* Callback function invoked when the library asks application how
* many padding bytes are required for the transmission of the given
...
...
lib/nghttp2_session.c
View file @
8579b8a9
...
...
@@ -3345,6 +3345,31 @@ static int session_call_on_header(nghttp2_session *session,
return
0
;
}
static
int
session_call_on_invalid_header
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
nghttp2_hd_nv
*
nv
)
{
int
rv
;
if
(
session
->
callbacks
.
on_invalid_header_callback2
)
{
rv
=
session
->
callbacks
.
on_invalid_header_callback2
(
session
,
frame
,
nv
->
name
,
nv
->
value
,
nv
->
flags
,
session
->
user_data
);
}
else
if
(
session
->
callbacks
.
on_invalid_header_callback
)
{
rv
=
session
->
callbacks
.
on_invalid_header_callback
(
session
,
frame
,
nv
->
name
->
base
,
nv
->
name
->
len
,
nv
->
value
->
base
,
nv
->
value
->
len
,
nv
->
flags
,
session
->
user_data
);
}
else
{
return
0
;
}
if
(
rv
==
NGHTTP2_ERR_PAUSE
||
rv
==
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
)
{
return
rv
;
}
if
(
rv
!=
0
)
{
return
NGHTTP2_ERR_CALLBACK_FAILURE
;
}
return
0
;
}
static
int
session_call_on_extension_chunk_recv_callback
(
nghttp2_session
*
session
,
const
uint8_t
*
data
,
size_t
len
)
{
...
...
@@ -3608,6 +3633,14 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
if
(
rv
==
NGHTTP2_ERR_IGN_HTTP_HEADER
)
{
/* Don't overwrite rv here */
int
rv2
;
rv2
=
session_call_on_invalid_header
(
session
,
frame
,
&
nv
);
/* This handles NGHTTP2_ERR_PAUSE and
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
if
(
rv2
!=
0
)
{
return
rv2
;
}
/* header is ignored */
DEBUGF
(
fprintf
(
stderr
,
"recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s
\n
"
,
...
...
tests/nghttp2_session_test.c
View file @
8579b8a9
...
...
@@ -70,6 +70,7 @@ typedef struct {
const
nghttp2_frame
*
frame
;
size_t
fixed_sendlen
;
int
header_cb_called
;
int
invalid_header_cb_called
;
int
begin_headers_cb_called
;
nghttp2_nv
nv
;
size_t
data_chunk_len
;
...
...
@@ -395,6 +396,44 @@ static int temporal_failure_on_header_callback(
return
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
;
}
static
int
on_invalid_header_callback
(
nghttp2_session
*
session
_U_
,
const
nghttp2_frame
*
frame
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
uint8_t
flags
_U_
,
void
*
user_data
)
{
my_user_data
*
ud
=
(
my_user_data
*
)
user_data
;
++
ud
->
invalid_header_cb_called
;
ud
->
nv
.
name
=
(
uint8_t
*
)
name
;
ud
->
nv
.
namelen
=
namelen
;
ud
->
nv
.
value
=
(
uint8_t
*
)
value
;
ud
->
nv
.
valuelen
=
valuelen
;
ud
->
frame
=
frame
;
return
0
;
}
static
int
pause_on_invalid_header_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
uint8_t
flags
,
void
*
user_data
)
{
on_invalid_header_callback
(
session
,
frame
,
name
,
namelen
,
value
,
valuelen
,
flags
,
user_data
);
return
NGHTTP2_ERR_PAUSE
;
}
static
int
reset_on_invalid_header_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
uint8_t
flags
,
void
*
user_data
)
{
on_invalid_header_callback
(
session
,
frame
,
name
,
namelen
,
value
,
valuelen
,
flags
,
user_data
);
return
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
;
}
static
int
on_begin_headers_callback
(
nghttp2_session
*
session
_U_
,
const
nghttp2_frame
*
frame
_U_
,
void
*
user_data
)
{
...
...
@@ -10613,6 +10652,7 @@ void test_nghttp2_http_ignore_regular_header(void) {
MAKE_NV
(
":path"
,
"/"
),
MAKE_NV
(
":method"
,
"GET"
),
MAKE_NV
(
"bar"
,
"buzz"
)};
size_t
proclen
;
size_t
i
;
nghttp2_outbound_item
*
item
;
mem
=
nghttp2_mem_default
();
frame_pack_bufs_init
(
&
bufs
);
...
...
@@ -10630,6 +10670,8 @@ void test_nghttp2_http_ignore_regular_header(void) {
CU_ASSERT_FATAL
(
0
==
rv
);
nghttp2_hd_deflate_free
(
&
deflater
);
proclen
=
0
;
for
(
i
=
0
;
i
<
4
;
++
i
)
{
...
...
@@ -10650,7 +10692,61 @@ void test_nghttp2_http_ignore_regular_header(void) {
CU_ASSERT
(
nghttp2_buf_len
(
&
bufs
.
head
->
buf
)
==
proclen
);
nghttp2_hd_deflate_free
(
&
deflater
);
nghttp2_session_del
(
session
);
/* use on_invalid_header_callback */
callbacks
.
on_invalid_header_callback
=
pause_on_invalid_header_callback
;
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
);
proclen
=
0
;
ud
.
invalid_header_cb_called
=
0
;
for
(
i
=
0
;
i
<
4
;
++
i
)
{
rv
=
nghttp2_session_mem_recv
(
session
,
bufs
.
head
->
buf
.
pos
+
proclen
,
nghttp2_buf_len
(
&
bufs
.
head
->
buf
)
-
proclen
);
CU_ASSERT_FATAL
(
rv
>
0
);
proclen
+=
(
size_t
)
rv
;
CU_ASSERT
(
nghttp2_nv_equal
(
&
bad_ansnv
[
i
],
&
ud
.
nv
));
}
CU_ASSERT
(
0
==
ud
.
invalid_header_cb_called
);
rv
=
nghttp2_session_mem_recv
(
session
,
bufs
.
head
->
buf
.
pos
+
proclen
,
nghttp2_buf_len
(
&
bufs
.
head
->
buf
)
-
proclen
);
CU_ASSERT_FATAL
(
rv
>
0
);
CU_ASSERT
(
1
==
ud
.
invalid_header_cb_called
);
CU_ASSERT
(
nghttp2_nv_equal
(
&
bad_reqnv
[
4
],
&
ud
.
nv
));
proclen
+=
(
size_t
)
rv
;
rv
=
nghttp2_session_mem_recv
(
session
,
bufs
.
head
->
buf
.
pos
+
proclen
,
nghttp2_buf_len
(
&
bufs
.
head
->
buf
)
-
proclen
);
CU_ASSERT
(
rv
>
0
);
CU_ASSERT
(
nghttp2_nv_equal
(
&
bad_ansnv
[
4
],
&
ud
.
nv
));
nghttp2_session_del
(
session
);
/* make sure that we can reset stream from
on_invalid_header_callback */
callbacks
.
on_header_callback
=
on_header_callback
;
callbacks
.
on_invalid_header_callback
=
reset_on_invalid_header_callback
;
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
);
rv
=
nghttp2_session_mem_recv
(
session
,
bufs
.
head
->
buf
.
pos
,
nghttp2_buf_len
(
&
bufs
.
head
->
buf
));
CU_ASSERT
(
rv
==
(
ssize_t
)
nghttp2_buf_len
(
&
bufs
.
head
->
buf
));
item
=
nghttp2_session_get_next_ob_item
(
session
);
CU_ASSERT
(
NGHTTP2_RST_STREAM
==
item
->
frame
.
hd
.
type
);
CU_ASSERT
(
1
==
item
->
frame
.
hd
.
stream_id
);
nghttp2_session_del
(
session
);
nghttp2_bufs_free
(
&
bufs
);
}
...
...
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