Respond RST_STREAM with PROTOCOL_ERROR when upper cased name is present in nv.

This commit is contained in:
Tatsuhiro Tsujikawa 2012-02-15 22:11:42 +09:00
parent f71572b835
commit 938f51964d
2 changed files with 74 additions and 14 deletions

View File

@ -949,6 +949,33 @@ static int spdylay_session_is_new_peer_stream_id(spdylay_session *session,
}
}
/*
* Returns non-zero iff version == SPDYLAY_PROTO_VERSION
*/
static int spdylay_session_check_version(uint16_t version)
{
return version == SPDYLAY_PROTO_VERSION;
}
/*
* Returns non-zero iff name/value pairs |nv| are good shape.
* Currently, we only checks whether names are lower cased. The spdy/2
* spec requires that names must be lower cased.
*/
static int spdylay_session_check_nv(char **nv)
{
int i;
for(i = 0; nv[i]; i += 2) {
int j;
for(j = 0; nv[i][j] != '\0'; ++j) {
if('A' <= nv[i][j] && nv[i][j] <= 'Z') {
return 0;
}
}
}
return 1;
}
/*
* Validates SYN_STREAM frame |frame|. This function returns 0 if it
* succeeds, or non-zero spdylay_status_code.
@ -959,7 +986,7 @@ static int spdylay_session_validate_syn_stream(spdylay_session *session,
if(!spdylay_session_is_new_peer_stream_id(session, frame->stream_id)) {
return SPDYLAY_PROTOCOL_ERROR;
}
if(frame->hd.version != SPDYLAY_PROTO_VERSION) {
if(!spdylay_session_check_version(frame->hd.version)) {
return SPDYLAY_UNSUPPORTED_VERSION;
}
if(session->server) {
@ -988,9 +1015,13 @@ static int spdylay_session_validate_syn_stream(spdylay_session *session,
follow it. */
return SPDYLAY_REFUSED_STREAM;
}
if(!spdylay_session_check_nv(frame->nv)) {
return SPDYLAY_PROTOCOL_ERROR;
}
return 0;
}
static int spdylay_session_handle_invalid_stream
(spdylay_session *session,
int32_t stream_id,
@ -1070,14 +1101,6 @@ int spdylay_session_on_syn_stream_received(spdylay_session *session,
return r;
}
/*
* Returns non-zero iff version == SPDYLAY_PROTOCOL_ERROR.
*/
static int spdylay_session_check_version(uint16_t version)
{
return version == SPDYLAY_PROTO_VERSION;
}
int spdylay_session_on_syn_reply_received(spdylay_session *session,
spdylay_frame *frame)
{
@ -1087,8 +1110,10 @@ int spdylay_session_on_syn_reply_received(spdylay_session *session,
if(!spdylay_session_check_version(frame->syn_reply.hd.version)) {
return 0;
}
stream = spdylay_session_get_stream(session, frame->syn_reply.stream_id);
if(stream && (stream->shut_flags & SPDYLAY_SHUT_RD) == 0) {
if((stream = spdylay_session_get_stream(session,
frame->syn_reply.stream_id)) &&
(stream->shut_flags & SPDYLAY_SHUT_RD) == 0 &&
spdylay_session_check_nv(frame->syn_reply.nv)) {
if(spdylay_session_is_my_stream_id(session, frame->syn_reply.stream_id)) {
if(stream->state == SPDYLAY_STREAM_OPENING) {
valid = 1;
@ -1190,9 +1215,10 @@ int spdylay_session_on_headers_received(spdylay_session *session,
if(!spdylay_session_check_version(frame->headers.hd.version)) {
return 0;
}
stream = spdylay_session_get_stream(session, frame->headers.stream_id);
/* First we check readability from this stream. */
if(stream && (stream->shut_flags & SPDYLAY_SHUT_RD) == 0) {
if((stream = spdylay_session_get_stream(session,
frame->headers.stream_id)) &&
(stream->shut_flags & SPDYLAY_SHUT_RD) == 0 &&
spdylay_session_check_nv(frame->headers.nv)) {
if(spdylay_session_is_my_stream_id(session, frame->headers.stream_id)) {
if(stream->state == SPDYLAY_STREAM_OPENED) {
valid = 1;

View File

@ -310,6 +310,7 @@ void test_spdylay_session_on_syn_stream_received()
spdylay_session_callbacks callbacks;
my_user_data user_data;
const char *nv[] = { NULL };
const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL };
spdylay_frame frame;
spdylay_stream *stream;
int32_t stream_id = 1;
@ -341,6 +342,14 @@ void test_spdylay_session_on_syn_stream_received()
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_syn_stream_free(&frame.syn_stream);
/* Upper cased name/value pairs */
spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 3, 0, 3,
dup_nv(upcase_nv));
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_syn_stream_free(&frame.syn_stream);
spdylay_session_del(session);
}
@ -409,6 +418,7 @@ void test_spdylay_session_on_syn_reply_received()
};
my_user_data user_data;
const char *nv[] = { NULL };
const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL };
spdylay_frame frame;
spdylay_stream *stream;
user_data.ctrl_recv_cb_called = 0;
@ -441,6 +451,17 @@ void test_spdylay_session_on_syn_reply_received()
CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_syn_reply_free(&frame.syn_reply);
/* Upper cased name/value pairs */
spdylay_session_open_stream(session, 5, SPDYLAY_FLAG_NONE, 0,
SPDYLAY_STREAM_OPENING, NULL);
spdylay_frame_syn_reply_init(&frame.syn_reply, SPDYLAY_FLAG_NONE, 5,
dup_nv(upcase_nv));
CU_ASSERT(0 == spdylay_session_on_syn_reply_received(session, &frame));
CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_syn_reply_free(&frame.syn_reply);
spdylay_session_del(session);
}
@ -572,6 +593,7 @@ void test_spdylay_session_on_headers_received()
spdylay_session_callbacks callbacks;
my_user_data user_data;
const char *nv[] = { NULL };
const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL };
spdylay_frame frame;
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback;
@ -629,6 +651,18 @@ void test_spdylay_session_on_headers_received()
CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_headers_free(&frame.headers);
/* Upper cased name/value pairs */
spdylay_session_open_stream(session, 5, SPDYLAY_FLAG_NONE, 0,
SPDYLAY_STREAM_OPENED, NULL);
spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_NONE, 5,
dup_nv(upcase_nv));
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called);
spdylay_frame_headers_free(&frame.headers);
spdylay_session_del(session);
}