[core] http_header_str_contains_token()

personal/stbuehler/ci-build
Glenn Strauss 2019-06-14 23:06:02 -04:00
parent 6f803af03c
commit e2b4c309f6
4 changed files with 32 additions and 83 deletions

View File

@ -57,6 +57,24 @@ enum http_header_e http_header_hkey_get(const char *s, size_t slen) {
}
int http_header_str_contains_token (const char * const s, const size_t slen, const char * const m, const size_t mlen)
{
/*if (slen < mlen) return 0;*//*(possible optimizations for caller)*/
/*if (slen == mlen && buffer_eq_icase_ssn(s, m, mlen)) return 1;*/
size_t i = 0;
do {
while (i < slen && (s[i]==' ' || s[i]=='\t' || s[i]==',')) ++i;
if (i == slen) return 0;
if (buffer_eq_icase_ssn(s+i, m, mlen)) {
i += mlen;
if (i == slen || s[i]==' ' || s[i]=='\t' || s[i]==',' || s[i]==';')
return 1;
}
while (i < slen && s[i]!=',') ++i;
} while (i < slen);
return 0;
}
buffer * http_header_response_get(connection *con, enum http_header_e id, const char *k, size_t klen) {
data_string * const ds =
(id <= HTTP_HEADER_OTHER || (con->response.htags & id))

View File

@ -42,6 +42,9 @@ enum http_header_e {
__attribute_pure__
enum http_header_e http_header_hkey_get(const char *s, size_t slen);
__attribute_pure__
int http_header_str_contains_token (const char *s, size_t slen, const char *m, size_t mlen);
buffer * http_header_response_get(connection *con, enum http_header_e id, const char *k, size_t klen);
void http_header_response_unset(connection *con, enum http_header_e id, const char *k, size_t klen);
void http_header_response_set(connection *con, enum http_header_e id, const char *k, size_t klen, const char *v, size_t vlen);

View File

@ -407,19 +407,6 @@ static void mod_wstunnel_patch_connection(server *srv, connection *con, plugin_d
#undef PATCH_GW
#undef PATCH
static int header_contains_token (buffer *b, const char *m, size_t mlen)
{
for (char *s = b->ptr; s; s = strchr(s, ',')) {
while (*s == ' ' || *s == '\t' || *s == ',') ++s;
if (buffer_eq_icase_ssn(s, m, mlen)) {
s += mlen;
if (*s == '\0' || *s == ' ' || *s == '\t' || *s == ',' || *s == ';')
return 1;
}
}
return 0;
}
static int wstunnel_is_allowed_origin(connection *con, handler_ctx *hctx) {
/* If allowed origins is set (and not empty list), fail closed if no match.
* Note that origin provided in request header has not been normalized, so
@ -594,11 +581,11 @@ static handler_t mod_wstunnel_check_extension(server *srv, connection *con, void
*/
vb = http_header_request_get(con, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"));
if (NULL == vb
|| !header_contains_token(vb, CONST_STR_LEN("websocket")))
|| !http_header_str_contains_token(CONST_BUF_LEN(vb), CONST_STR_LEN("websocket")))
return HANDLER_GO_ON;
vb = http_header_request_get(con, HTTP_HEADER_CONNECTION, CONST_STR_LEN("Connection"));
if (NULL == vb
|| !header_contains_token(vb, CONST_STR_LEN("upgrade")))
|| !http_header_str_contains_token(CONST_BUF_LEN(vb), CONST_STR_LEN("upgrade")))
return HANDLER_GO_ON;
mod_wstunnel_patch_connection(srv, con, p);

View File

@ -345,57 +345,6 @@ int http_request_host_policy (connection *con, buffer *b, const buffer *scheme)
&& 0 != http_request_host_normalize(b, scheme_port(scheme))));
}
static int http_request_split_value(array *vals, const char *current, size_t len) {
int state = 0;
const char *token_start = NULL, *token_end = NULL;
/*
* parse
*
* val1, val2, val3, val4
*
* into a array (more or less a explode() incl. stripping of whitespaces
*/
for (size_t i = 0; i <= len; ++i, ++current) {
switch (state) {
case 0: /* find start of a token */
switch (*current) {
case ' ':
case '\t': /* skip white space */
case ',': /* skip empty token */
break;
case '\0': /* end of string */
return 0;
default:
/* found real data, switch to state 1 to find the end of the token */
token_start = token_end = current;
state = 1;
break;
}
break;
case 1: /* find end of token and last non white space character */
switch (*current) {
case ' ':
case '\t':
/* space - don't update token_end */
break;
case ',':
case '\0': /* end of string also marks the end of a token */
array_insert_value(vals, token_start, token_end-token_start+1);
state = 0;
break;
default:
/* no white space, update token_end to include current character */
token_end = current;
break;
}
break;
}
}
return 0;
}
static int request_uri_is_valid_char(unsigned char c) {
return (c > 32 && c != 127 && c != 255);
}
@ -479,23 +428,15 @@ static int parse_single_header(server *srv, connection *con, parse_header_state
}
break;
case HTTP_HEADER_CONNECTION:
{
array * const vals = srv->split_vals;
array_reset_data_strings(vals);
http_request_split_value(vals, v, vlen); /* split on , */
for (size_t vi = 0; vi < vals->used; ++vi) {
data_string *dsv = (data_string *)vals->data[vi];
if (buffer_eq_icase_slen(dsv->value,
CONST_STR_LEN("keep-alive"))) {
state->keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
break;
}
else if (buffer_eq_icase_slen(dsv->value,
CONST_STR_LEN("close"))) {
state->keep_alive_set = HTTP_CONNECTION_CLOSE;
break;
}
}
/* "Connection: close" is common case if header is present */
if ((vlen == 5 && buffer_eq_icase_ssn(v, CONST_STR_LEN("close")))
|| http_header_str_contains_token(v,vlen,CONST_STR_LEN("close"))) {
state->keep_alive_set = HTTP_CONNECTION_CLOSE;
break;
}
if (http_header_str_contains_token(v,vlen,CONST_STR_LEN("keep-alive"))){
state->keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
break;
}
break;
case HTTP_HEADER_CONTENT_TYPE: