From abaf122bfc737d317132179cbc8e8a1c2d4464e9 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 9 Feb 2022 10:10:52 +0100 Subject: [PATCH] RESTCONF HTTP/1 Incomplete header handling --- apps/restconf/restconf_native.c | 53 +++++++++++++++++++++++---------- test/fuzz/http1/README.md | 1 + test/test_restconf_continue.sh | 3 +- test/test_restconf_err.sh | 11 ++++--- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/apps/restconf/restconf_native.c b/apps/restconf/restconf_native.c index 3b2c6286..e34a20fb 100644 --- a/apps/restconf/restconf_native.c +++ b/apps/restconf/restconf_native.c @@ -441,6 +441,32 @@ native_send_badrequest(clicon_handle h, return retval; } +#ifdef HAVE_HTTP1 +/*! Clear all input stream data if input is interrupted for some reason + * + * Only used by HTTP/1. + * @param[in] h Clixon handle + * @param[in] sd Http stream + * @retval 0 OK + * @retval -1 Error + */ +static int +native_clear_input(clicon_handle h, + restconf_stream_data *sd) +{ + int retval = -1; + + cbuf_reset(sd->sd_indata); + if (sd->sd_qvec) + cvec_free(sd->sd_qvec); + if (restconf_param_del_all(h) < 0) + goto done; + retval = 0; + done: + return retval; +} +#endif + /*! New data connection after accept, receive and reply on data socket * * @param[in] s Socket where message arrived. read from this. @@ -461,7 +487,7 @@ restconf_connection(int s, int retval = -1; restconf_conn *rc = NULL; ssize_t n; - char buf[BUFSIZ]; /* from stdio.h, typically 8K. 256 fails some tests*/ + char buf[1024]; /* Alter BUFSIZ (8K) from stdio.h 8K. 256 fails some tests */ char *totbuf = NULL; size_t totlen = 0; int readmore = 1; @@ -561,6 +587,15 @@ restconf_connection(int s, memcpy(&totbuf[totlen-n], buf, n); totbuf[totlen] = '\0'; if (clixon_http1_parse_string(h, rc, totbuf) < 0){ + /* Maybe only for non-ssl ? */ + if ((ret = clixon_event_poll(rc->rc_s)) < 0) + goto done; + if (ret == 1){ + if (native_clear_input(h, sd) < 0) + goto done; + readmore++; + continue; + } if (native_send_badrequest(h, rc->rc_s, rc->rc_ssl, "application/yang-data+xml", "protocolmalformed-messageThe requested URL or a header is in some way badly formed") < 0) goto done; @@ -587,21 +622,9 @@ restconf_connection(int s, if ((ret = http1_check_readmore(h, sd)) < 0) goto done; if (ret == 0){ - readmore++; -#if 1 - /* Clear all stream data if reading more - * Alternative would be to not adding new data to totbuf ^ - * and just append to sd->sd_indata but that would assume - * all headers read on first round. But that cant be done withut - * some probing on the socket if there is more data since it - * would hang on read otherwise - */ - cbuf_reset(sd->sd_indata); - if (sd->sd_qvec) - cvec_free(sd->sd_qvec); - if (restconf_param_del_all(h) < 0) + if (native_clear_input(h, sd) < 0) goto done; -#endif + readmore++; continue; } if (restconf_http1_path_root(h, rc) < 0) diff --git a/test/fuzz/http1/README.md b/test/fuzz/http1/README.md index c501da86..a74c80b1 100644 --- a/test/fuzz/http1/README.md +++ b/test/fuzz/http1/README.md @@ -21,6 +21,7 @@ main function and replacing it with the unit testing `main`: Build and install clixon libraries and restconf statically ``` ./configure LINKAGE=static INSTALLFLAGS="" CC=/usr/bin/afl-clang-fast + make clean make sudo make install ./runfuzz.sh diff --git a/test/test_restconf_continue.sh b/test/test_restconf_continue.sh index eded682f..bc5d674a 100755 --- a/test/test_restconf_continue.sh +++ b/test/test_restconf_continue.sh @@ -79,13 +79,12 @@ fi new "wait restconf" wait_restconf - new "generate large request" # Add large put, curl seems to create a Expect:100-continue after 1024 bytes # Alt: add in file if nr=5000 reacts with "Argument list too long" echo -n '{"example:table":{"parameter":[' > $fjson -nr=10000 +nr=1000 for (( i=0; i<$nr; i++ )); do if [ $i -ne 0 ]; then echo -n ", diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh index 9dce3537..7d7d002c 100755 --- a/test/test_restconf_err.sh +++ b/test/test_restconf_err.sh @@ -218,7 +218,7 @@ if [ -n "$netcat" ]; then # new "restconf try fuzz crash" # expectpart "$(${netcat} 127.0.0.1 80 < ~/tmp/crashes/id:000000,sig:06,src:000493+000365,op:splice,rep:8)" 0 "HTTP/$HVER 400" - new "restconf GET initial datastore netcat" + new "netcat restconf GET initial datastore netcat" expectpart "$(${netcat} 127.0.0.1 80 <50% does not work on docker alpine + new "netcat restconf GET wrong http version raw" expectpart "$(${netcat} 127.0.0.1 80 <malformed-messageThe requested URL or a header is in some way badly formed' + fi fi # netcat Cannot get to work on all platforms new "restconf XYZ not found"