This commit is contained in:
Olof hagsand 2019-04-07 15:47:10 +02:00
commit 4021d65d7a
15 changed files with 2168 additions and 1984 deletions

View file

@ -107,6 +107,8 @@
* Added libgen.h for baseline() * Added libgen.h for baseline()
### Corrected Bugs ### Corrected Bugs
* List ordering bug - lists with ints as keys behaved wrongly and slow.
* NACM read default rule did not work properly if nacm was enabled AND no groups were defined
* Re-inserted `cli_output_reset` for what was erroneuos thought to be an obsolete function * Re-inserted `cli_output_reset` for what was erroneuos thought to be an obsolete function
* See in 3.9.0 minro changes: Replaced all calls to (obsolete) `cli_output` with `fprintf` * See in 3.9.0 minro changes: Replaced all calls to (obsolete) `cli_output` with `fprintf`
* Allowed Yang extended Xpath functions (syntax only): * Allowed Yang extended Xpath functions (syntax only):

993
config.guess vendored

File diff suppressed because it is too large Load diff

2771
config.sub vendored

File diff suppressed because it is too large Load diff

View file

@ -141,11 +141,12 @@ server {
``` ```
Start nginx daemon Start nginx daemon
``` ```
sudo /etc/init.d/nginx start sudo /etc/init.d/nginx start
sudo systemctl start nginx.service # alternative using systemd
``` ```
Start the clixon restconf daemon Start the clixon restconf daemon
``` ```
sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
``` ```
then access using curl or wget: then access using curl or wget:
``` ```

View file

@ -542,7 +542,7 @@ clixon_plugin_init(clicon_handle h)
struct timeval retention = {0,0}; struct timeval retention = {0,0};
int argc; /* command-line options (after --) */ int argc; /* command-line options (after --) */
char **argv; char **argv;
char c; int c;
clicon_debug(1, "%s backend", __FUNCTION__); clicon_debug(1, "%s backend", __FUNCTION__);

View file

@ -40,7 +40,6 @@
#include <ctype.h> #include <ctype.h>
#include <signal.h> #include <signal.h>
#include <fcgiapp.h> #include <fcgiapp.h>
#include <curl/curl.h>
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
@ -329,7 +328,7 @@ clixon_plugin_init(clicon_handle h)
{ {
int argc; /* command-line options (after --) */ int argc; /* command-line options (after --) */
char **argv = NULL; char **argv = NULL;
char c; int c;
clicon_debug(1, "%s restconf", __FUNCTION__); clicon_debug(1, "%s restconf", __FUNCTION__);
/* Get user command-line options (after --) */ /* Get user command-line options (after --) */

View file

@ -567,22 +567,27 @@ nacm_datanode_read(cxobj *xt,
/* User's group */ /* User's group */
if (xpath_vec(xnacm, "groups/group[user-name='%s']", &gvec, &glen, username) < 0) if (xpath_vec(xnacm, "groups/group[user-name='%s']", &gvec, &glen, username) < 0)
goto done; goto done;
/* 4. If no groups are found, continue with step 9. */ /* 4. If no groups are found (glen=0), continue and check read-default
if (glen == 0) in step 11. */
goto step9;
/* 5. Process all rule-list entries, in the order they appear in the /* 5. Process all rule-list entries, in the order they appear in the
configuration. If a rule-list's "group" leaf-list does not configuration. If a rule-list's "group" leaf-list does not
match any of the user's groups, proceed to the next rule-list match any of the user's groups, proceed to the next rule-list
entry. */ entry. */
if (xpath_vec(xnacm, "rule-list", &rlistvec, &rlistlen) < 0) if (xpath_vec(xnacm, "rule-list", &rlistvec, &rlistlen) < 0)
goto done; goto done;
/* read-default has default permit so should never be NULL */
if ((read_default = xml_find_body(xnacm, "read-default")) == NULL){
clicon_err(OE_XML, EINVAL, "No nacm read-default rule");
goto done;
}
for (i=0; i<xrlen; i++){ /* Loop through requested nodes */ for (i=0; i<xrlen; i++){ /* Loop through requested nodes */
xr = xrvec[i]; /* requested node XR */ xr = xrvec[i]; /* requested node XR */
/* Loop through rule-list (steps 5,6,7) to find match of requested node /* Loop through rule-list (steps 5,6,7) to find match of requested node
*/ */
xrule = NULL; xrule = NULL;
if (nacm_data_read_xr(xt, xr, gvec, glen, rlistvec, rlistlen, /* Skip if no groups */
&xrule) < 0) if (glen && nacm_data_read_xr(xt, xr, gvec, glen, rlistvec, rlistlen,
&xrule) < 0)
goto done; goto done;
if (xrule){ /* xrule match requested node xr */ if (xrule){ /* xrule match requested node xr */
if ((action = xml_find_body(xrule, "action")) == NULL) if ((action = xml_find_body(xrule, "action")) == NULL)
@ -601,8 +606,7 @@ nacm_datanode_read(cxobj *xt,
to "permit", then include the requested data node in the reply; to "permit", then include the requested data node in the reply;
otherwise, do not include the requested data node or any of its otherwise, do not include the requested data node or any of its
descendants in the reply.*/ descendants in the reply.*/
read_default = xml_find_body(xnacm, "read-default"); if (strcmp(read_default, "deny")==0)
if (read_default == NULL || strcmp(read_default, "deny")==0)
if (xml_purge(xr) < 0) if (xml_purge(xr) < 0)
goto done; goto done;
} }
@ -668,7 +672,7 @@ nacm_datanode_write(cxobj *xt,
cxobj *xrule; cxobj *xrule;
int match = 0; int match = 0;
char *action; char *action;
char *write_default; char *write_default = NULL;
if (xnacm == NULL) if (xnacm == NULL)
goto permit; goto permit;
@ -747,8 +751,12 @@ nacm_datanode_write(cxobj *xt,
/*12. For a "write" access operation, if the "write-default" leaf is /*12. For a "write" access operation, if the "write-default" leaf is
set to "permit", then permit the data node access request; set to "permit", then permit the data node access request;
otherwise, deny the request.*/ otherwise, deny the request.*/
write_default = xml_find_body(xnacm, "write-default"); /* write-default has default permit so should never be NULL */
if (write_default == NULL || strcmp(write_default, "permit") != 0){ if ((write_default = xml_find_body(xnacm, "write-default")) == NULL){
clicon_err(OE_XML, EINVAL, "No nacm write-default rule");
goto done;
}
if (strcmp(write_default, "permit") != 0){
if (netconf_access_denied(cbret, "application", "default deny") < 0) if (netconf_access_denied(cbret, "application", "default deny") < 0)
goto done; goto done;
goto deny; goto deny;

View file

@ -730,8 +730,7 @@ match_base_child(cxobj *x0,
goto ok; goto ok;
if ((b = xml_body(xb)) == NULL) if ((b = xml_body(xb)) == NULL)
goto ok; goto ok;
// if ((b = xml_find_body(x1c, keyname)) == NULL)
// goto ok; /* not found */
keyval[i] = b; keyval[i] = b;
if (xml_cv_cache(xb, &keycvec[i]) < 0) /* error case */ if (xml_cv_cache(xb, &keycvec[i]) < 0) /* error case */
goto done; goto done;
@ -741,9 +740,7 @@ match_base_child(cxobj *x0,
default: default:
break; break;
} }
/* Get match. Sorting mode(optimized) or not? /* Get match. */
* This conditional is a mystery , but test_yang_namespace.sh breaks if set to (0)
*/
yorder = yang_order(yc); yorder = yang_order(yc);
x0c = xml_search(x0, xml_name(x1c), yorder, yc->ys_keyword, keynr, keyvec, keyval, keycvec); x0c = xml_search(x0, xml_name(x1c), yorder, yc->ys_keyword, keynr, keyvec, keyval, keycvec);
ok: ok:

View file

@ -1,126 +0,0 @@
/*
* Utility debug tool
* Static Compile: gcc -Wall json_xpath.c -o json_xpath -l clixon
gcc -O2 -o json_xpath json_xpath.c clixon_log.o clixon_err.o clixon_json.o clixon_xml.o clixon_xsl.o clixon_json_parse.tab.o clixon_xml_parse.tab.o lex.clixon_json_parse.o lex.clixon_xml_parse.o ../../../cligen/cligen_buf.o ../../../cligen/cligen_var.o ../../../cligen/cligen_gen.o ../../../cligen/cligen_cvec.o ../../../cligen/cligen_handle.o ../../../cligen/getline.o ../../../cligen/cligen_read.o ../../../cligen/cligen_match.o ../../../cligen/cligen_expand.o ../../../cligen/cligen_print.o
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include <clixon/clixon.h>
static int
usage(char *argv0)
{
fprintf(stderr, "usage:%s <xpath> # XML/JSON expected on stdin\n"
"\t-h Help\n"
"\t-b Strip to body value (eg \"<a>val</a>\" --> \"val\"\n"
"\t-j json input (not xml)\n",
argv0);
exit(0);
}
int
main(int argc, char **argv)
{
int i;
cxobj **xv;
cxobj *x;
cxobj *xn;
cxobj *xb;
char *xpath;
int body = 0;
int json = 0;
size_t xlen = 0;
size_t len;
size_t buflen = 128;
char *buf;
char *p;
int retval;
int c;
while ((c = getopt(argc, argv, "?hbj")) != -1)
switch (c) {
case '?':
case 'h':
usage(argv[0]);
break;
case 'b':
body++;
break;
case 'j':
json++;
break;
default:
usage(argv[0]);
}
if (optind >= argc)
usage(argv[0]);
xpath=argv[optind];
clicon_log_init("xpath", 0, CLICON_LOG_STDERR);
if ((buf = malloc(buflen)) == NULL){
perror("malloc");
return -1;
}
/* |---------------|-------------|
* buf p buf+buflen
*/
p = buf;
memset(p, 0, buflen);
while (1){
if ((retval = read(0, p, buflen-(p-buf))) < 0){
perror("read");
return -1;
}
if (retval == 0)
break;
p += retval;
len = p-buf;
if (buf+buflen-p < 10){ /* allocate more */
buflen *= 2;
if ((buf = realloc(buf, buflen)) == NULL){
perror("realloc");
return -1;
}
p = buf+len;
memset(p, 0, (buf+buflen)-p);
}
}
if (json){
if (json_parse_str(buf, &x) < 0)
return -1;
}
else
if (xml_parse_string(buf, &x) < 0)
return -1;
if (xpath_vec(x, xpath, &xv, &xlen) < 0)
return -1;
if (xv){
for (i=0; i<xlen; i++){
xn = xv[i];
if (body)
xb = xml_find(xn, "body");
else
xb = xn;
if (xb){
// xml2json(stdout, xb, 0);
clicon_xml2file(stdout, xb, 0, 0);
fprintf(stdout,"\n");
}
}
free(xv);
}
if (x)
xml_free(x);
if (buf)
free(buf);
return 0;
}

View file

@ -26,9 +26,11 @@ You need to build and install the clixon utility programs before running the tes
sudo make install sudo make install
``` ```
You need to start nginx for some of the text. There are instructions in You need to configure and start nginx for the restconf tests:
* The [example](../example/main/README.md) has instructions on how to edit your nginx config files
* If you run systemd: `sudo systemctl start nginx.service` * If you run systemd: `sudo systemctl start nginx.service`
* The [example](../example/README.md) has instructions
You may need to install the `time` utility (`/usr/bin/time`).
## Prefix variable ## Prefix variable
@ -65,7 +67,7 @@ You may add your site-specific modifications in a `site.sh` file. Example:
# Add test to this list that you dont want run # Add test to this list that you dont want run
SKIPLIST="test_openconfig.sh test_yangmodels.sh" SKIPLIST="test_openconfig.sh test_yangmodels.sh"
# Parse yang openconfig models from https://github.com/openconfig/public # Parse yang openconfig models from https://github.com/openconfig/public
OPENCONFIG=/home/olof/src/clixon/test/public OPENCONFIG=/usr/local/share/openconfig/public
# Parse yangmodels from https://github.com/YangModels/yang # Parse yangmodels from https://github.com/YangModels/yang
YANGMODELS=/usr/local/share/yangmodels YANGMODELS=/usr/local/share/yangmodels
# Standard IETF RFC yang files. # Standard IETF RFC yang files.

View file

@ -78,10 +78,10 @@ testname=
# Parse yangmodels from https://github.com/YangModels/yang # Parse yangmodels from https://github.com/YangModels/yang
# Recommended: checkout yangmodels elsewhere in the tree and set the env # Recommended: checkout yangmodels elsewhere in the tree and set the env
# to that # to that
: ${YANGMODELS=$(pwd)/yang} #: ${YANGMODELS=$(pwd)/yang} # just skip if not set
# Parse yang openconfig models from https://github.com/openconfig/public # Parse yang openconfig models from https://github.com/openconfig/public
: ${OPENCONFIG=$(pwd)/public} #: ${OPENCONFIG=$(pwd)/public} # just skip if not set
# Standard IETF RFC yang files. # Standard IETF RFC yang files.
: ${IETFRFC=../yang/standard} : ${IETFRFC=../yang/standard}

193
test/test_nacm_default.sh Executable file
View file

@ -0,0 +1,193 @@
#!/bin/bash
# Basic NACM default rulw without any groups
# Start from startup db
# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
APPNAME=example
cfg=$dir/conf_yang.xml
fyang=$dir/nacm-example.yang
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
<CLICON_RESTCONF_PRETTY>false</CLICON_RESTCONF_PRETTY>
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
</clixon-config>
EOF
cat <<EOF > $fyang
module nacm-example{
yang-version 1.1;
namespace "urn:example:nacm";
prefix nacm;
import clixon-example {
prefix ex;
}
import ietf-netconf-acm {
prefix nacm;
}
leaf x{
type int32;
description "something to edit";
}
}
EOF
#
# startup db with default values:
# 1: enable-nacm (true|false)
# 2: read-default (deny|permit)
# 3: write-default (deny|permit)
# 4: exec-defautl (deny|permit)
# 5: expected return value of test1
# 6: expected return value of test2
# 7: expected return value of test3
testrun(){
enablenacm=$1
readdefault=$2
writedefault=$3
execdefault=$4
ret1=$5
ret2=$6
ret3=$7
# NACM in startup
sudo tee $dir/startup_db > /dev/null << EOF
<config>
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<enable-nacm>${enablenacm}</enable-nacm>
<read-default>${readdefault}</read-default>
<write-default>${writedefault}</write-default>
<exec-default>${execdefault}</exec-default>
<enable-external-groups>true</enable-external-groups>
</nacm>
<x xmlns="urn:example:nacm">42</x>
</config>
EOF
if [ $BE -ne 0 ]; then # Bring your own backend
new "kill old backend"
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg"
start_backend -s startup -f $cfg
else
new "Restart backend as eg follows: -Ff $cfg -s startup"
sleep $BETIMEOUT
fi
new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
start_restconf -f $cfg -- -a
new "waiting"
sleep $RCWAIT
#----------- First get
case "$ret1" in
0) ret='{"nacm-example:x": 42}
'
;;
1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
;;
2) ret='null
'
;;
esac
new "get startup 42"
expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 "$ret"
#----------- Then edit
case "$ret2" in
0) ret=''
;;
1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
;;
esac
new "edit new 99"
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"nacm-example:x": 99}' http://localhost/restconf/data/nacm-example:x)" 0 "$ret"
#----------- Then second get
case "$ret3" in
0) ret='{"nacm-example:x": 99}
'
;;
1) ret='{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
;;
2) ret='null
'
;;
3) ret='{"nacm-example:x": 42}
'
esac
new "get 99"
expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" 0 "$ret"
new "Kill restconf daemon"
stop_restconf
if [ $BE -ne 0 ]; then # Bring your own backend
new "Kill backend"
# Check if premature kill
pid=`pgrep -u root -f clixon_backend`
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
stop_backend -f $cfg
fi
} # testrun
# Run a lot of tests with different settings of default read/write/exec
new "nacm enabled and all defaults permit"
testrun true permit permit permit 0 0 0
new "nacm disabled and all defaults permit"
testrun false permit permit permit 0 0 0
new "nacm disabled and all defaults deny"
testrun false deny deny deny 0 0 0
new "nacm enabled, all defaults deny (expect fail)"
testrun true deny deny deny 1 1 1
new "nacm enabled, exec default deny - read permit (expect fail)"
testrun true permit deny deny 1 1 1
new "nacm enabled, exec default deny - write permit (expect fail)"
testrun true deny permit deny 1 1 1
new "nacm enabled, exec default deny read/write permit (expect fail)"
testrun true permit permit deny 1 1 1
new "nacm enabled, exec default permit, all others deny (expect fail)"
testrun true deny deny permit 2 1 2
new "nacm enabled, exec default permit, read permit (expect fail)"
testrun true permit deny permit 0 1 3
new "nacm enabled, exec default permit, write permit (expect fail)"
testrun true deny permit permit 2 0 2
rm -rf $dir

View file

@ -18,7 +18,7 @@ fyang=$dir/test.yang
new "openconfig" new "openconfig"
if [ ! -d "$OPENCONFIG" ]; then if [ ! -d "$OPENCONFIG" ]; then
# err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?" # err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?"
exit if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi fi
OCDIR=$OPENCONFIG/release/models OCDIR=$OPENCONFIG/release/models

View file

@ -27,7 +27,7 @@ fyang=$dir/test.yang
if [ ! -d "$YANGMODELS" ]; then if [ ! -d "$YANGMODELS" ]; then
# err "Hmm Yangmodels dir does not seem to exist, try git clone https://github.com/YangModels/yang?" # err "Hmm Yangmodels dir does not seem to exist, try git clone https://github.com/YangModels/yang?"
exit if [ "$s" = $0 ]; then exit 0; else return 0; fi
fi fi
# Experimental IEEE # Experimental IEEE

View file

@ -3,3 +3,5 @@
This directory contains Clixon utility programs, ie, programs that are This directory contains Clixon utility programs, ie, programs that are
good to have for testing, analysis, etc, but not an actual part of good to have for testing, analysis, etc, but not an actual part of
delivered code. delivered code.
Note, streams utility may need: libcurl4-openssl-dev or corresponding.