From 84d88c8ad8dac325c23687826f05528242eb6917 Mon Sep 17 00:00:00 2001
From: Olof hagsand
Date: Sun, 24 Apr 2022 09:44:27 +0200
Subject: [PATCH] Restconf http-data server updates
Check data paths for .., ~ and soft links
Changed semantics of `CLICON_HTTP_DATA_PATH` and `_ROOT`
Change URI catch-all to 404 instead of 400
Fixed some memory leaks
---
apps/restconf/clixon_http_data.c | 178 ++++++++++++++++------
apps/restconf/clixon_http_data.h | 2 +-
apps/restconf/restconf_http1.c | 11 +-
apps/restconf/restconf_nghttp2.c | 11 +-
apps/restconf/restconf_root.c | 17 ++-
apps/restconf/restconf_stream_fcgi.c | 20 ++-
configure.ac | 1 +
doc/DEVELOP.md | 10 ++
test/lib.sh | 11 ++
test/test_http_data.sh | 114 +++++++++++---
test/test_restconf_err.sh | 13 --
yang/clixon/clixon-config@2022-03-21.yang | 21 ++-
12 files changed, 303 insertions(+), 106 deletions(-)
diff --git a/apps/restconf/clixon_http_data.c b/apps/restconf/clixon_http_data.c
index 72249aed..ba98acb0 100644
--- a/apps/restconf/clixon_http_data.c
+++ b/apps/restconf/clixon_http_data.c
@@ -86,32 +86,34 @@ static const map_str2str mime_map[] = {
/*! Check if uri path denotes a data path
*
- * @param[out] data Pointer to string where data starts if retval = 1
+ * @param[in] h Clixon handle
* @retval 0 No, not a data path, or not enabled
* @retval 1 Yes, a data path and "data" points to www-data if given
*/
int
-api_path_is_data(clicon_handle h,
- char **data)
+api_path_is_data(clicon_handle h)
{
- char *path;
+ int retval = 0;
+ char *path = NULL;
char *http_data_path;
if (restconf_http_data_get(h) == 0)
- return 0;
+ goto done;
if ((path = restconf_uripath(h)) == NULL)
- return 0;
+ goto done;
if ((http_data_path = clicon_option_str(h, "CLICON_HTTP_DATA_PATH")) == NULL)
- return 0;
+ goto done;
if (strlen(path) < strlen(http_data_path))
- return 0;
+ goto done;
if (path[0] != '/')
- return 0;
+ goto done;
if (strncmp(path, http_data_path, strlen(http_data_path)) != 0)
- return 0;
- if (data)
- *data = path + strlen(http_data_path);
- return 1;
+ goto done;
+ retval = 1;
+ done:
+ if (path)
+ free(path);
+ return retval;
}
/*! Generic restconf error function on get/head request
@@ -156,6 +158,75 @@ api_http_data_err(clicon_handle h,
return retval;
}
+/*! Check validity of path, may only be regular dir or file
+ * No .., soft link, ~, etc
+ * @param[in] prefix Prefix of path0, where to start file check
+ * @param[in] path0 Filepath
+ * @param[out] code Error code, if retval = 0
+ * @retval -1 Error
+ * @retval 0 Invalid, code set
+ * @retval 1 OK
+ */
+static int
+check_file_path(char *prefix,
+ char *path0,
+ int *code)
+{
+ int retval = -1;
+ char *path = NULL;
+ int i;
+ struct stat fstat;
+
+ if (prefix == NULL || path0 == NULL || code == NULL){
+ clicon_err(OE_UNIX, EINVAL, "prefix, path0 or code is NULL");
+ goto done;
+ }
+ if ((path = strdup(path0)) == NULL){
+ clicon_err(OE_UNIX, errno, "strdup");
+ goto done;
+ }
+ for (i=strlen(prefix); istrlen(prefix) && path[i-1] == '.'){
+ *code = 403;
+ goto invalid;
+ }
+ }
+ /* Resulting file (ensure not soft link) */
+ if (lstat(path, &fstat) < 0){
+ *code = 404;
+ goto invalid;
+ }
+ if (!S_ISREG(fstat.st_mode)){
+ *code = 403;
+ goto invalid;
+ }
+ retval = 1; /* OK */
+ done:
+ if (path)
+ free(path);
+ return retval;
+ invalid:
+ retval = 0;
+ goto done;
+}
+
/*! Read file data request
* @param[in] h Clicon handle
* @param[in] req Generic Www handle (can be part of clixon handle)
@@ -167,21 +238,23 @@ api_http_data_err(clicon_handle h,
*/
static int
api_http_data_file(clicon_handle h,
- void *req,
- char *pathname,
- int head)
+ void *req,
+ char *pathname,
+ int head)
{
int retval = -1;
cbuf *cbfile = NULL;
char *filename;
- struct stat fstat;
cbuf *cbdata = NULL;
FILE *f = NULL;
long fsize;
- size_t sz;
char *www_data_root = NULL;
char *suffix;
char *media;
+ int ret;
+ int code = 0;
+ char *str = NULL;
+ size_t sz;
if ((cbfile = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
@@ -204,8 +277,12 @@ api_http_data_file(clicon_handle h,
if (pathname)
cprintf(cbfile, "/%s", pathname);
filename = cbuf_get(cbfile);
- if (stat(filename, &fstat) < 0){
- if (api_http_data_err(h, req, 404) < 0) /* not found */
+ clicon_debug(1, "%s %s", __FUNCTION__, filename);
+ if ((ret = check_file_path(www_data_root, filename, &code)) < 0)
+ goto done;
+ if (ret == 0){
+ clicon_debug(1, "%s code:%d", __FUNCTION__, code);
+ if (api_http_data_err(h, req, code) < 0)
goto done;
goto ok;
}
@@ -214,6 +291,9 @@ api_http_data_file(clicon_handle h,
goto done;
goto ok;
}
+ /* Size could have been taken from stat() but this reduces the race condition interval
+ * There is still one without flock
+ */
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fseek(f, 0, SEEK_SET); /* same as rewind(f); */
@@ -221,31 +301,28 @@ api_http_data_file(clicon_handle h,
clicon_err(OE_UNIX, errno, "cbuf_new_alloc");
goto done;
}
-#if 0 /* Direct read but cannot set cb_len via API */
- fread(cbuf_get(cbdata), fsize, 1, f);
-#else
- {
- char *str;
- if ((str = malloc(fsize + 1)) == NULL){
- clicon_err(OE_UNIX, errno, "malloc");
- goto done;
- }
- if ((sz = fread(str, fsize, 1, f)) < 0){
- clicon_err(OE_UNIX, errno, "fread");
- goto done;
- }
- if (sz != 1){
- clicon_log(LOG_NOTICE, "%s: file read %s", __FUNCTION__, filename);
- // XXX error handling: file read
- goto done;
- }
- str[fsize] = 0;
- if (cbuf_append_str(cbdata, str) < 0){
- clicon_err(OE_UNIX, errno, "cbuf_append_str");
- goto done;
- }
+ /* Unoptimized, no direct read but requires an extra copy,
+ * the cligen buf API should have some mechanism for this case without the extra copy.
+ */
+ if ((str = malloc(fsize + 1)) == NULL){
+ clicon_err(OE_UNIX, errno, "malloc");
+ goto done;
+ }
+ if ((sz = fread(str, fsize, 1, f)) < 0){
+ clicon_err(OE_UNIX, errno, "fread");
+ goto done;
+ }
+ if (sz != 1){
+ if (api_http_data_err(h, req, 500) < 0) /* Internal error? */
+ goto done;
+ goto ok;
+ }
+ clicon_debug(1, "%s code:%d", __FUNCTION__, code);
+ str[fsize] = 0;
+ if (cbuf_append_str(cbdata, str) < 0){
+ clicon_err(OE_UNIX, errno, "cbuf_append_str");
+ goto done;
}
-#endif
if (restconf_reply_header(req, "Content-Type", "%s", media) < 0)
goto done;
if (restconf_reply_send(req, 200, cbdata, head) < 0)
@@ -254,6 +331,8 @@ api_http_data_file(clicon_handle h,
ok:
retval = 0;
done:
+ if (str)
+ free(str);
if (f)
fclose(f);
if (cbfile)
@@ -291,8 +370,8 @@ api_http_data(clicon_handle h,
int options = 0;
int ret;
cbuf *indata = NULL;
- char *pathname = NULL;
-
+ char *path = NULL;
+
clicon_debug(1, "%s", __FUNCTION__);
if (req == NULL){
errno = EINVAL;
@@ -300,11 +379,12 @@ api_http_data(clicon_handle h,
}
/* 1. path: with stripped prefix, ultimately: dir/filename
*/
- if (!api_path_is_data(h, &pathname)){
+ if (!api_path_is_data(h)){
if (api_http_data_err(h, req, 404) < 0) /* not found */
goto done;
goto ok;
}
+ path = restconf_uripath(h);
/* 2. operation GET or HEAD */
request_method = restconf_param_get(h, "REQUEST_METHOD");
if (strcmp(request_method, "GET") == 0){
@@ -360,11 +440,13 @@ api_http_data(clicon_handle h,
if (restconf_reply_send(req, 200, NULL, 0) < 0)
goto done;
}
- else if (api_http_data_file(h, req, pathname, head) < 0)
+ else if (api_http_data_file(h, req, path, head) < 0)
goto done;
ok:
retval = 0;
done:
+ if (path)
+ free(path);
clicon_debug(1, "%s %d", __FUNCTION__, retval);
return retval;
}
diff --git a/apps/restconf/clixon_http_data.h b/apps/restconf/clixon_http_data.h
index 0174f0e1..f1c70c44 100644
--- a/apps/restconf/clixon_http_data.h
+++ b/apps/restconf/clixon_http_data.h
@@ -41,7 +41,7 @@
/*
* Prototypes
*/
-int api_path_is_data(clicon_handle h, char **data);
+int api_path_is_data(clicon_handle h);
int api_http_data(clicon_handle h, void *req, cvec *qvec);
#endif /* _CLIXON_HTTP_DATA_H_ */
diff --git a/apps/restconf/restconf_http1.c b/apps/restconf/restconf_http1.c
index f5ea9c6b..7b3332e5 100644
--- a/apps/restconf/restconf_http1.c
+++ b/apps/restconf/restconf_http1.c
@@ -345,7 +345,7 @@ restconf_http1_path_root(clicon_handle h,
restconf_conn *rc)
{
int retval = -1;
- restconf_stream_data *sd;
+ restconf_stream_data *sd = NULL;
cvec *cvv = NULL;
char *cn;
char *subject = NULL;
@@ -380,6 +380,13 @@ restconf_http1_path_root(clicon_handle h,
goto done;
goto fail;
}
+#if 1
+ /* XXX gives mem leak in multiple requests,
+ * but maybe the error is that sd is not freed.
+ */
+ if (sd->sd_path != NULL)
+ free(sd->sd_path);
+#endif
if ((sd->sd_path = restconf_uripath(rc->rc_h)) == NULL)
goto done; // XXX SHOULDNT EXIT if no REQUEST_URI
if (rc->rc_proto_d2 == 0 && rc->rc_proto == HTTP_11)
@@ -427,7 +434,7 @@ restconf_http1_path_root(clicon_handle h,
if (api_root_restconf(h, sd, sd->sd_qvec) < 0)
goto done;
}
- else if (api_path_is_data(h, NULL)){
+ else if (api_path_is_data(h)){
if (api_http_data(h, sd, sd->sd_qvec) < 0)
goto done;
}
diff --git a/apps/restconf/restconf_nghttp2.c b/apps/restconf/restconf_nghttp2.c
index 059c50b2..4e1a222c 100644
--- a/apps/restconf/restconf_nghttp2.c
+++ b/apps/restconf/restconf_nghttp2.c
@@ -325,7 +325,7 @@ restconf_nghttp2_path(restconf_stream_data *sd)
if (api_root_restconf(h, sd, sd->sd_qvec) < 0)
goto done;
}
- else if (api_path_is_data(h, NULL)){
+ else if (api_path_is_data(h)){
if (api_http_data(h, sd, sd->sd_qvec) < 0)
goto done;
}
@@ -475,14 +475,17 @@ http2_exec(restconf_conn *rc,
sd->sd_proto = HTTP_2; /* XXX is this necessary? */
if (strncmp(sd->sd_path, "/" RESTCONF_API, strlen("/" RESTCONF_API)) == 0
|| strcmp(sd->sd_path, RESTCONF_WELL_KNOWN) == 0
- || api_path_is_data(rc->rc_h, NULL)){
+ || api_path_is_data(rc->rc_h)){
if (restconf_nghttp2_path(sd) < 0)
goto done;
}
else{
- sd->sd_code = 400;
- ; /* ignore */
+ sd->sd_code = 404; /* not found */
+
}
+ if (restconf_param_del_all(rc->rc_h) < 0) // XXX
+ goto done;
+
/* If body, add a content-length header
* A server MUST NOT send a Content-Length header field in any response
* with a status code of 1xx (Informational) or 204 (No Content). A
diff --git a/apps/restconf/restconf_root.c b/apps/restconf/restconf_root.c
index c75d5b85..e5893dcb 100644
--- a/apps/restconf/restconf_root.c
+++ b/apps/restconf/restconf_root.c
@@ -78,18 +78,23 @@
int
api_path_is_restconf(clicon_handle h)
{
- char *path;
+ int retval = 0;
+ char *path = NULL;
char *restconf_path = RESTCONF_API;
if ((path = restconf_uripath(h)) == NULL)
- return 0;
+ goto done;
if (strlen(path) < 1 + strlen(restconf_path)) /* "/" + restconf */
- return 0;
+ goto done;
if (path[0] != '/')
- return 0;
+ goto done;
if (strncmp(path+1, restconf_path, strlen(restconf_path)) != 0)
- return 0;
- return 1;
+ goto done;
+ retval = 1;
+ done:
+ if (path)
+ free(path);
+ return retval;
}
/*! Determine the root of the RESTCONF API by accessing /.well-known
diff --git a/apps/restconf/restconf_stream_fcgi.c b/apps/restconf/restconf_stream_fcgi.c
index 2792168c..1b14367a 100644
--- a/apps/restconf/restconf_stream_fcgi.c
+++ b/apps/restconf/restconf_stream_fcgi.c
@@ -126,20 +126,26 @@ static struct stream_child *STREAM_CHILD = NULL;
int
api_path_is_stream(clicon_handle h)
{
- char *path;
+ int retval = 0;
+ char *path = NULL;
char *stream_path;
if ((path = restconf_uripath(h)) == NULL)
- return 0;
+ goto done;
if ((stream_path = clicon_option_str(h, "CLICON_STREAM_PATH")) == NULL)
- return 0;
+ goto done;
if (strlen(path) < 1 + strlen(stream_path)) /* "/" + stream */
- return 0;
+ goto done;
if (path[0] != '/')
- return 0;
+ goto done;
if (strncmp(path+1, stream_path, strlen(stream_path)) != 0)
- return 0;
- return 1;
+ goto done;
+ retval = 1;
+ done:
+ if (path)
+ free(path);
+ return retval;
+
}
/*! Find restconf child using PID and cleanup FCGI Request data
diff --git a/configure.ac b/configure.ac
index 5b20156f..1cdf5601 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,6 +86,7 @@ AC_DEFINE_UNQUOTED(CLIXON_VERSION_PATCH, $CLIXON_VERSION_PATCH, [Clixon path ver
AC_CHECK_LIB(m, main)
+# defines: target_cpu, target_vendor, and target_os.
AC_CANONICAL_TARGET
# AC_SUBST(var) makes @var@ appear in makefiles.
diff --git a/doc/DEVELOP.md b/doc/DEVELOP.md
index 60b3447f..55b42d6f 100644
--- a/doc/DEVELOP.md
+++ b/doc/DEVELOP.md
@@ -113,6 +113,16 @@ Use:
- PRIu64 for uint64
- %p for pointers
+### Include files
+
+Avoid include statements in .h files, place them in .c files whenever possible.
+
+The reason is to avoid deep include chains where file dependencies are
+difficult to analyze and understand. If include statements are only placed in .c
+files, there is only a single level of include file dependencies.
+
+The drawback is that the same include file may need to be repeated in many .c files.
+
## How to work in git
Clixon uses semantic versioning (https://semver.org).
diff --git a/test/lib.sh b/test/lib.sh
index 74cbe64c..dbf58f1e 100755
--- a/test/lib.sh
+++ b/test/lib.sh
@@ -94,6 +94,17 @@ DEFAULTNS="$DEFAULTONLY message-id=\"42\""
# Minimal hello message as a prelude to netconf rpcs
DEFAULTHELLO="urn:ietf:params:netconf:base:1.0urn:ietf:params:netconf:base:1.1]]>]]>"
+# XXX cannot get this to work for all combinations of nc/netcat fcgi/native
+# But leave it here for debugging where netcat works properly
+if [ -n "$(type netcat 2> /dev/null)" ]; then
+ netcat="netcat -w 1" # -N does not work on fcgi
+# nc on freebsd does not work either
+#elif [ -n "$(type nc 2> /dev/null)" ]; then
+# netcat=nc
+else
+ netcat=
+fi
+
# Options passed to curl calls
# -s : silent
# -S : show error
diff --git a/test/test_http_data.sh b/test/test_http_data.sh
index 84612b13..44292c80 100755
--- a/test/test_http_data.sh
+++ b/test/test_http_data.sh
@@ -14,6 +14,7 @@ APPNAME=example
cfg=$dir/conf.xml
rm -rf $dir/www
mkdir $dir/www
+mkdir $dir/www/data
# Does not work with fcgi
if [ "${WITH_RESTCONF}" = "fcgi" ]; then
@@ -22,7 +23,7 @@ if [ "${WITH_RESTCONF}" = "fcgi" ]; then
fi
# Data file
-cat < $dir/www/index.html
+cat < $dir/www/data/index.html
@@ -43,7 +44,7 @@ working. Further configuration is required.
EOF
-cat < $dir/www/example.css
+cat < $dir/www/data/example.css
img {
display: inline;
border:
@@ -67,6 +68,54 @@ h1,h2,h3,h4,h5,h6 {
}
EOF
+# Outside wwwdir, should not be able to access this
+cat < $dir/outside.html
+
+
+
+Dont access this
+
+
+
+Dont access this!
+If you see this page, you accessed a file outside the root domain
+
+
+EOF
+
+# Create a soft link from inside to outside
+ln -s $dir/outside.html $dir/www/data/inside.html
+
+# Disable read access
+cat < $dir/www/data/noread.html
+
+
+
+No read
+
+
+
+No read!
+If you see this page, you have read access to root
+
+
+EOF
+
+# remove read access
+chmod 660 $dir/www/data/noread.html
+
# Http test routine with arguments:
# 1. proto:http/https
function testrun()
@@ -134,32 +183,55 @@ EOF
new "wait restconf"
wait_restconf $proto
-# echo "curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html"
- if $enable; then
+ echo "curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html"
+
+ if ! $enable; then
+ # XXX or bad request?
+ new "WWW get html, not enabled, expect not found"
+# echo "curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html"
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 404"
+ else
new "WWW get html"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "Content-Type: text/html" "Welcome to Clixon!"
- else
- new "WWW get html, not enabled, expect bad request"
- expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 400"
- return
- fi
- new "WWW get css"
- expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 200" "Content-Type: text/css" "display: inline;" --not-- "Content-Type: text/html"
+ new "WWW get css"
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/example.css)" 0 "HTTP/$HVER 200" "Content-Type: text/css" "display: inline;" --not-- "Content-Type: text/html"
- new "WWW head"
- expectpart "$(curl $CURLOPTS --head -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "Content-Type: text/html" --not-- "Welcome to Clixon!"
+ new "WWW head"
+ expectpart "$(curl $CURLOPTS --head -H 'Accept: text/html' $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "Content-Type: text/html" --not-- "Welcome to Clixon!"
- new "WWW options"
- expectpart "$(curl $CURLOPTS -X OPTIONS $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "allow: OPTIONS,HEAD,GET"
+ new "WWW options"
+ expectpart "$(curl $CURLOPTS -X OPTIONS $proto://localhost/data/index.html)" 0 "HTTP/$HVER 200" "allow: OPTIONS,HEAD,GET"
- # negative errors
- new "WWW get http not found"
- expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/notfound.html)" 0 "HTTP/$HVER 404" "Content-Type: text/html" "404 Not Found"
+ # negative errors
+ new "WWW get http not found"
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/notfound.html)" 0 "HTTP/$HVER 404" "Content-Type: text/html" "404 Not Found"
- new "WWW post not allowed"
- expectpart "$(curl $CURLOPTS -X POST -H 'Accept: text/html' -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $proto://localhost/data/notfound.html)" 0 "HTTP/$HVER 405" "Content-Type: text/html" "405 Method Not Allowed"
+ new "WWW get http soft link"
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/inside.html)" 0 "HTTP/$HVER 403" "Content-Type: text/html" "403 Forbidden" --not-- "Dont access this"
+
+ if [ ! -f /.dockerenv ] ; then # XXX Privs dont not work on docker/alpine?
+ new "WWW get http not read access"
+ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: text/html' $proto://localhost/data/noread.html)" 0 "HTTP/$HVER 403" "Content-Type: text/html" "403 Forbidden"
+ fi
+ # Try .. Cannot get .. in path to work in curl (it seems to remove it)
+ if [ "$proto" = http -a -n "$netcat" ]; then
+ new "WWW get outside using .. netcat"
+ expectpart "$(${netcat} 127.0.0.1 80 <405 Method Not Allowed"
+
+ fi
+
if [ $RC -ne 0 ]; then
new "Kill restconf daemon"
stop_restconf
@@ -190,7 +262,7 @@ if [ "${WITH_RESTCONF}" = "native" ]; then
fi
for proto in $protos; do
- for enable in true false; do
+ for enable in true false; do # false
new "http-data proto:$proto enabled:$enable"
testrun $proto $enable
done
diff --git a/test/test_restconf_err.sh b/test/test_restconf_err.sh
index 1a936cde..ef242012 100755
--- a/test/test_restconf_err.sh
+++ b/test/test_restconf_err.sh
@@ -209,19 +209,6 @@ expectpart "$(curl $CURLOPTS -X POST -H 'Content-Type: application/yang-data+xml
new "restconf GET initial datastore"
expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:a=0)" 0 "HTTP/$HVER 200" "$XML"
-# XXX cannot get this to work for all combinations of nc/netcat fcgi/native
-# But leave it here for debugging where netcat works properly
-# Alt try something like:
-# printf "Hello World!" | (exec 3<>/dev/tcp/127.0.0.1/80; cat >&3; cat <&3; exec 3<&-)
-# Look for netcat or nc for direct socket http calls
-if [ -n "$(type netcat 2> /dev/null)" ]; then
- netcat="netcat -w 1" # -N does not work on fcgi
-# nc on freebsd does not work either
-#elif [ -n "$(type nc 2> /dev/null)" ]; then
-# netcat=nc
-else
- netcat=
-fi
if [ -n "$netcat" -a "${WITH_RESTCONF}" != "fcgi" ]; then
# new "restconf try fuzz crash"
diff --git a/yang/clixon/clixon-config@2022-03-21.yang b/yang/clixon/clixon-config@2022-03-21.yang
index 4ea0af1f..c1e9eb3c 100644
--- a/yang/clixon/clixon-config@2022-03-21.yang
+++ b/yang/clixon/clixon-config@2022-03-21.yang
@@ -605,16 +605,28 @@ module clixon-config {
}
leaf CLICON_HTTP_DATA_PATH {
if-feature "clrc:http-data";
+ default "/";
type string;
description
- "If set, enable www data on this sub-path, must start with / (example: /data)";
+ "URI match for http-data serving files specified by CLICON_HTTP_DATA_ROOT.
+ Must start with / (example: /)
+ Restconf paths at /restconf is always done before data (or streams)
+ The PATH is appended to CLICON_HTTP_DATA_ROOT to find a file.
+ Example, if PATH is /data and ROOT is /www, and a GET /index.html, the
+ corresponding file is '/www/data/index.html'
+ Both feature clixon-restconf:http-data and restconf/enable-http-data
+ must be enabled for this match to occur.";
}
leaf CLICON_HTTP_DATA_ROOT {
if-feature "clrc:http-data";
type string;
default "/var/www";
description
- "public web root";
+ "Location in file system where http-data files are looked for.
+ Soft links, '..', '~' etc are not followed.
+ See also CLICON_HTTP_DATA_PATH
+ Both feature clixon-restconf:http-data and restconf/enable-http-data
+ must be enabled for this match to occur.";
}
leaf CLICON_CLI_DIR {
type string;
@@ -1051,8 +1063,9 @@ module clixon-config {
leaf CLICON_STREAM_PATH {
type string;
default "streams";
- description "Stream path appended to CLICON_STREAM_URL to form
- stream subscription URL.";
+ description
+ "Stream path appended to CLICON_STREAM_URL to form
+ stream subscription URL.";
}
leaf CLICON_STREAM_URL {
type string;