From 85fce86f50117510663488b48bbc412e74bcfece Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 31 Mar 2021 12:55:38 +0200 Subject: [PATCH] Building problems with evhtp --- apps/restconf/README.md | 6 +- apps/restconf/restconf_api_evhtp.c | 3 + apps/restconf/restconf_main_evhtp.c | 152 ++++++++++++++-------------- configure | 10 +- configure.ac | 12 ++- docker/main/Dockerfile.evhtp | 6 +- example/main/example_restconf.c | 4 +- test/vagrant/vagrant.sh | 19 ++-- 8 files changed, 112 insertions(+), 100 deletions(-) diff --git a/apps/restconf/README.md b/apps/restconf/README.md index 482670e3..260704a4 100644 --- a/apps/restconf/README.md +++ b/apps/restconf/README.md @@ -12,9 +12,9 @@ There are two installation instructions: for libevhtp and nginx. Download, build and install libevhtp from source. Prereqs: libevent and cmake. ``` - git clone https://github.com/clicon/libevhtp.git - cd libevhtp/build - cmake -DEVHTP_DISABLE_REGEX=ON -DEVHTP_DISABLE_EVTHR=ON .. + sudo git clone https://github.com/clicon/clixon-libevhtp.git + cd clixon-libevhtp + ./configure --libdir=/usr/lib make sudo make install ``` diff --git a/apps/restconf/restconf_api_evhtp.c b/apps/restconf/restconf_api_evhtp.c index e36322b1..37f6ea9d 100644 --- a/apps/restconf/restconf_api_evhtp.c +++ b/apps/restconf/restconf_api_evhtp.c @@ -50,6 +50,9 @@ #include /* evhtp */ +#define EVHTP_DISABLE_REGEX +#define EVHTP_DISABLE_EVTHR +#define EVHTP_EXPORT #include /* cligen */ diff --git a/apps/restconf/restconf_main_evhtp.c b/apps/restconf/restconf_main_evhtp.c index 74904271..1bb767e0 100644 --- a/apps/restconf/restconf_main_evhtp.c +++ b/apps/restconf/restconf_main_evhtp.c @@ -134,6 +134,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,9 @@ /* evhtp */ #include /* evbuffer */ +#define EVHTP_DISABLE_REGEX +#define EVHTP_DISABLE_EVTHR +#define EVHTP_EXPORT #include #include /* XXX inline this / use SSL directly */ @@ -213,28 +217,25 @@ openspec_handle_set(clicon_handle h, * see also this function in restcont_api_openssl.c */ static ssize_t -evbuf_write(struct evbuffer *ev, - int s, - SSL *ssl) +buf_write(char *buf, + size_t buflen, + int s, + SSL *ssl) { ssize_t retval = -1; - size_t buflen; - unsigned char *buf; int ret; - if ((buflen = evbuffer_get_length(ev)) > 0){ - buf = evbuffer_pullup(ev, -1); - if (ssl){ - if ((ret = SSL_write(ssl, buf, buflen)) <= 0){ - clicon_err(OE_SSL, 0, "SSL_write"); - goto done; - } + clicon_debug(1, "%s %s", __FUNCTION__, buf); + if (ssl){ + if ((ret = SSL_write(ssl, buf, buflen)) <= 0){ + clicon_err(OE_SSL, 0, "SSL_write"); + goto done; } - else{ - if (write(s, buf, buflen) < 0){ - clicon_err(OE_UNIX, errno, "write"); - goto done; - } + } + else{ + if (write(s, buf, buflen) < 0){ + clicon_err(OE_UNIX, errno, "write"); + goto done; } } retval = 0; @@ -787,6 +788,25 @@ close_openssl_socket(int s, return retval; } +/*! Send initial bad request reply before actual packet received, just after accept + * @param[in] ssl if set, it will be freed + */ +static int +accept_badrequest(clicon_handle h, + int s, + SSL *ssl) +{ + int retval = -1; + char *buf = "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\nContent-Type: text/plain\r\n\r\n"; + + clicon_debug(1, "%s", __FUNCTION__); + if (buf_write(buf, strlen(buf)+1, s, ssl) < 0) + goto done; + retval = 0; + done: + return retval; +} + /*! New data connection after accept, receive and reply on data sockte * * @param[in] s Socket where message arrived. read from this. @@ -798,7 +818,7 @@ close_openssl_socket(int s, */ static int restconf_connection(int s, - void* arg) + void *arg) { int retval = -1; evhtp_connection_t *conn = NULL; @@ -841,27 +861,35 @@ restconf_connection(int s, * signature: */ if (connection_parse_nobev(buf, n, conn) < 0){ - evhtp_request_t *er; - er = evhtp_request_new(NULL, NULL); - er->conn = conn; - conn->request = er; - htparser_set_major(conn->parser, '\1'); - htparser_set_minor(conn->parser, '\1'); - if (restconf_badrequest(h, er) < 0) + clicon_debug(1, "%s connection_parse error", __FUNCTION__); + if (accept_badrequest(h, s, conn->ssl) < 0) + goto done; + if (close_openssl_socket(s, conn->ssl) < 0) goto done; - if (conn->bev != NULL) - if (evbuf_write(bufferevent_get_output(conn->bev), s, NULL) < 0) - goto done; evhtp_connection_free(conn); - if (close_openssl_socket(s, NULL) < 0) - goto done; goto ok; } if (conn->bev != NULL){ - /* This is for 100 Continue, typically bev is set but output is empty - * if sent by fini callback - */ - if (evbuf_write(bufferevent_get_output(conn->bev), conn->sock, conn->ssl) < 0) + char *buf; + size_t buflen; + struct evbuffer *ev; + + ev = bufferevent_get_output(conn->bev); + buf = (char*)evbuffer_pullup(ev, -1); + buflen = evbuffer_get_length(ev); + if (buflen){ + if (buf_write(buf, buflen, conn->sock, conn->ssl) < 0) + goto done; + } + else{ + clicon_debug(1, "%s bev is NULL", __FUNCTION__); + if (accept_badrequest(h, s, conn->ssl) < 0) /* actually error */ + goto done; + } + } + else{ + clicon_debug(1, "%s bev is NULL", __FUNCTION__); + if (accept_badrequest(h, s, conn->ssl) < 0) /* actually error */ goto done; } ok: @@ -935,42 +963,6 @@ restconf_checkcert_file(cxobj *xrestconf, return retval; } -/*! Send initial bad request reply before actual packet received, just after accept - * @param[in] ssl if set, it will be freed - */ -static int -accept_badrequest(clicon_handle h, - int s, - SSL *ssl, - evhtp_connection_t *conn) -{ - int retval = -1; - evhtp_request_t *er; - - /* - * Since message has not been read, the reply is constructed manually - * using http 1.1 - * See note (1) http to https port: - */ - er = evhtp_request_new(NULL, NULL); - er->conn = conn; - conn->request = er; - conn->ssl = NULL; - htparser_set_major(conn->parser, '\1'); - htparser_set_minor(conn->parser, '\1'); - if (restconf_badrequest(h, er) < 0) - goto done; - /* XXX: should there be a body? */ - if (conn->bev != NULL) - if (evbuf_write(bufferevent_get_output(conn->bev), s, ssl) < 0) - goto done; - evhtp_connection_free(conn); - if (close_openssl_socket(s, ssl) < 0) - goto done; - retval = 0; - done: - return retval; -} /*! Accept new socket client * @param[in] fd Socket (unix or ip) @@ -993,7 +985,8 @@ restconf_accept_client(int fd, int ret; evhtp_t *evhtp = NULL; evhtp_connection_t *conn; - + int e; + clicon_debug(1, "%s %d", __FUNCTION__, fd); if (rsock == NULL){ clicon_err(OE_YANG, EINVAL, "rsock is NULL"); @@ -1052,10 +1045,11 @@ restconf_accept_client(int fd, * Both error cases: Call SSL_get_error() with the return value ret */ if ((ret = SSL_accept(ssl)) != 1) { - int e = SSL_get_error(ssl, ret); + e = SSL_get_error(ssl, ret); + switch (e){ case SSL_ERROR_SSL: { /* 1 */ - if (accept_badrequest(h, s, NULL, conn) < 0) + if (accept_badrequest(h, s, NULL) < 0) goto done; SSL_free(ssl); goto ok; @@ -1092,8 +1086,18 @@ restconf_accept_client(int fd, */ if (restconf_auth_type_get(h) == CLIXON_AUTH_CLIENT_CERTIFICATE && SSL_get_peer_certificate(ssl) == NULL) { /* Get certificates (if available) */ - if (accept_badrequest(h, s, ssl, conn) < 0) + if (accept_badrequest(h, s, ssl) < 0) goto done; + if (ssl){ + if ((ret = SSL_shutdown(ssl)) < 0){ + int e = SSL_get_error(ssl, ret); + clicon_err(OE_SSL, 0, "SSL_shutdown, err:%d", e); + goto done; + } + SSL_free(ssl); + } + // close(s); Error (56 != 0) in Test14 [No cert: certificate required]: + // clixon_event_unreg_fd(s, restconf_connection); goto ok; } /* Get the actual peer, XXX this maybe could be done in ca-auth client-cert code ? diff --git a/configure b/configure index 6a2f0469..f7b5c9e9 100755 --- a/configure +++ b/configure @@ -4992,7 +4992,6 @@ else with_restconf=fcgi fi - # Actions for each specific package if test "x${with_restconf}" == xfcgi; then # Lives in libfcgi-dev @@ -5187,7 +5186,12 @@ fi for ac_header in evhtp/evhtp.h do : - ac_fn_c_check_header_mongrel "$LINENO" "evhtp/evhtp.h" "ac_cv_header_evhtp_evhtp_h" "$ac_includes_default" + ac_fn_c_check_header_compile "$LINENO" "evhtp/evhtp.h" "ac_cv_header_evhtp_evhtp_h" "$ac_includes_default + #define EVHTP_DISABLE_REGEX + #define EVHTP_DISABLE_EVTHR + #define EVHTP_EXPORT + +" if test "x$ac_cv_header_evhtp_evhtp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EVHTP_EVHTP_H 1 @@ -5246,7 +5250,6 @@ else as_fn_error $? "libevhtp missing" "$LINENO" 5 fi - elif test "x${with_restconf}" == xno; then # Cant get around "no" as an answer for --without-restconf that is reset here to undefined with_restconf= @@ -5254,6 +5257,7 @@ else as_fn_error $? "No such restconf package: ${with_restconf}" "$LINENO" 5 fi + if test "x${with_restconf}" != "x"; then # This is so it appears in config.h diff --git a/configure.ac b/configure.ac index 641eac97..b6df8683 100644 --- a/configure.ac +++ b/configure.ac @@ -205,7 +205,6 @@ AC_ARG_WITH([restconf], AS_HELP_STRING([--with-restconf=fcgi],[FCGI interface for stand-alone web rev-proxy eg nginx (default)]), , [with_restconf=fcgi]) - # Actions for each specific package if test "x${with_restconf}" == xfcgi; then # Lives in libfcgi-dev @@ -214,9 +213,15 @@ elif test "x${with_restconf}" == xevhtp; then AC_CHECK_LIB(ssl, OPENSSL_init_ssl ,, AC_MSG_ERROR([libssl missing])) AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, , AC_MSG_ERROR([libcrypto missing])) AC_CHECK_LIB(event, event_init,, AC_MSG_ERROR([libevent missing])) - AC_CHECK_HEADERS(evhtp/evhtp.h,, AC_MSG_ERROR([evhtp header missing. See https://github.com/clicon/libevhtp])) + AC_CHECK_HEADERS(evhtp/evhtp.h, + [], + AC_MSG_ERROR([evhtp header missing. See https://github.com/clicon/libevhtp]), + [AC_INCLUDES_DEFAULT[ + #define EVHTP_DISABLE_REGEX + #define EVHTP_DISABLE_EVTHR + #define EVHTP_EXPORT + ]]) AC_CHECK_LIB(evhtp, evhtp_new,, AC_MSG_ERROR([libevhtp missing]),[-lpthread -levent -levent_openssl -lssl -lcrypto]) - elif test "x${with_restconf}" == xno; then # Cant get around "no" as an answer for --without-restconf that is reset here to undefined with_restconf= @@ -224,6 +229,7 @@ else AC_MSG_ERROR([No such restconf package: ${with_restconf}]) fi + if test "x${with_restconf}" != "x"; then # This is so it appears in config.h AC_DEFINE_UNQUOTED(WITH_RESTCONF, ${with_restconf}, [Restconf package]) diff --git a/docker/main/Dockerfile.evhtp b/docker/main/Dockerfile.evhtp index 03a8b86d..e4d56f0f 100644 --- a/docker/main/Dockerfile.evhtp +++ b/docker/main/Dockerfile.evhtp @@ -41,15 +41,15 @@ RUN apk add --update git make build-base gcc flex bison curl-dev # Create a directory to hold source-code, dependencies etc RUN mkdir /clixon -# libevht +# evhtp # dependencies -RUN apk add --update libevent cmake libevent-dev +RUN apk add --update libevent libevent-dev # clone libevhtp WORKDIR /clixon RUN git clone https://github.com/clicon/clixon-libevhtp.git -WORKDIR /clixon/libevhtp +WORKDIR /clixon/clixon-libevhtp RUN ./configure RUN make diff --git a/example/main/example_restconf.c b/example/main/example_restconf.c index ce00c98b..04e9e397 100644 --- a/example/main/example_restconf.c +++ b/example/main/example_restconf.c @@ -254,7 +254,7 @@ example_basic_auth(clicon_handle h, user=NULL; /* to avoid free below */ retval = 1; done: /* error */ - clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, *authp); + clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, authp?"":*authp); if (user) free(user); if (cb) @@ -324,7 +324,7 @@ example_no_auth(clicon_handle h, user=NULL; /* to avoid free below */ retval = 1; done: /* error */ - clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, *authp); + clicon_debug(1, "%s retval:%d authp:%s", __FUNCTION__, retval, authp?"":*authp); if (user) free(user); if (cb) diff --git a/test/vagrant/vagrant.sh b/test/vagrant/vagrant.sh index 0be17639..bee130a5 100755 --- a/test/vagrant/vagrant.sh +++ b/test/vagrant/vagrant.sh @@ -97,7 +97,6 @@ system=$($sshcmd uname) # we use the release "hack" instead # Some release have packages, some need to be built from source buildfcgi=false -buildevhtp=false case $release in openbsd) # packages for building @@ -130,7 +129,7 @@ case $release in $sshcmd sudo pkg install -y fcgi-devkit nginx ;; evhtp) - $sshcmd sudo pkg install -y libevent libevhtp + $sshcmd sudo pkg install -y libevent ;; esac ;; @@ -157,7 +156,6 @@ case $release in ;; evhtp) $sshcmd sudo yum install -y libevent openssl - buildevhtp=true $sshcmd sudo yum install -y libevent-devel openssl-devel ;; esac @@ -203,7 +201,6 @@ case $release in ;; evhtp) # $sshcmd sudo apt install -y libevent-2.1 - buildevhtp=true $sshcmd sudo apt install -y libevent-dev libssl-dev ;; esac @@ -257,15 +254,13 @@ case ${with_restconf} in . ./nginx.sh $dir $idfile $port $wwwuser ;; evhtp) - if $buildevhtp; then - $sshcmd << 'EOF' - test -d libevhtp || git clone https://github.com/clicon/libevhtp.git - cd libevhtp; - ./configure --libdir=/usr/lib # otherwise in /usr/local/lib where RH dont look - make - sudo make install + $sshcmd << 'EOF' + test -d clixon-libevhtp || git clone https://github.com/clicon/clixon-libevhtp.git + cd clixon-libevhtp; + ./configure --libdir=/usr/lib # otherwise in /usr/local/lib where RH dont look + make + sudo make install EOF - fi ;; esac