NACM datanode write rules have been changed from looking at datastore being chekend (eg running/candidate/startup) to *only* look at running.

Fixed: NACM datanode write problem: read/write/exec default rules did not work.
This commit is contained in:
Olof hagsand 2020-03-12 14:58:30 +01:00
parent 78aac85b18
commit 71efe18f94
11 changed files with 205 additions and 158 deletions

View file

@ -264,6 +264,44 @@ clicon_nacm_ext_set(clicon_handle h,
return 0;
}
/*! Get NACM (rfc 8341) XML parse tree cache
* @param[in] h Clicon handle
* @retval xn XML NACM tree, or NULL. Direct pointer, no copying
* @note Use with caution, only valid on a stack, direct pointer freed on function return
* @see from_client_msg
*/
cxobj *
clicon_nacm_cache(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *p;
if ((p = clicon_hash_value(cdat, "nacm_cache", &len)) != NULL)
return *(cxobj **)p;
return NULL;
}
/*! Set NACM (rfc 8341) external XML parse tree cache
* @param[in] h Clicon handle
* @param[in] xn XML Nacm tree direct pointer, no copying
* @note Use with caution, only valid on a stack, direct pointer freed on function return
* @see from_client_msg
*/
int
clicon_nacm_cache_set(clicon_handle h,
cxobj *xn)
{
clicon_hash_t *cdat = clicon_data(h);
/* It is the pointer to xn that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy.
*/
if (clicon_hash_add(cdat, "nacm_cache", &xn, sizeof(xn)) == NULL)
return -1;
return 0;
}
/*! Get YANG specification for Clixon system options and features
* Must use hash functions directly since they are not strings.
* Example: features are typically accessed directly in the config tree.

View file

@ -830,9 +830,7 @@ xmldb_put(clicon_handle h,
cxobj *x0 = NULL;
db_elmnt *de = NULL;
int ret;
cxobj *xnacm = NULL;
char *mode;
cxobj *xnacm0 = NULL;
cxobj *xnacm = NULL;
cxobj *xmodst = NULL;
cxobj *x;
int permit = 0; /* nacm permit all */
@ -874,23 +872,10 @@ xmldb_put(clicon_handle h,
if (xml_apply0(x1, -1, xml_sort_verify, NULL) < 0)
clicon_log(LOG_NOTICE, "%s: verify failed #1", __FUNCTION__);
#endif
mode = clicon_option_str(h, "CLICON_NACM_MODE");
if (mode){
if (strcmp(mode, "external")==0)
xnacm0 = clicon_nacm_ext(h);
else if (strcmp(mode, "internal")==0)
xnacm0 = x0;
}
/* Create namespace context for with nacm namespace as default */
if ((nsc = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-netconf-acm")) == NULL)
goto done;
if (xnacm0 != NULL &&
(xnacm = xpath_first(xnacm0, nsc, "nacm")) != NULL){
/* Pre-NACM access step, if permit, then dont do any nacm checks in
* text_modify_* below */
if ((permit = nacm_access(h, mode, xnacm, username)) < 0)
goto done;
}
xnacm = clicon_nacm_cache(h);
permit = (xnacm==NULL);
/* Here assume if xnacm is set and !permit do NACM */
/*
* Modify base tree x with modification x1. This is where the

View file

@ -832,14 +832,12 @@ nacm_datanode_write(cxobj *xt,
* @endcode
* @see RFC8341 3.4 Access Control Enforcement Procedures
*/
int
static int
nacm_access(clicon_handle h,
char *mode,
cxobj *xnacm,
char *username)
{
int retval = -1;
cxobj *xnacm0 = NULL;
char *enabled;
cxobj *x;
cvec *nsc = NULL;
@ -847,17 +845,6 @@ nacm_access(clicon_handle h,
clicon_debug(1, "%s", __FUNCTION__);
if ((nsc = xml_nsctx_init(NULL, NACM_NS)) == NULL)
goto done;
if (mode == NULL || strcmp(mode, "disabled") == 0)
goto permit;
/* 0. If nacm-mode is external, get NACM defintion from separet tree,
otherwise get it from internal configuration */
if (strcmp(mode, "external") && strcmp(mode, "internal")){
clicon_err(OE_XML, 0, "Invalid NACM mode: %s", mode);
goto done;
}
/* If config does not exist, then the operation is permitted. (?) */
if (xnacm == NULL)
goto permit;
/* Do initial nacm processing common to all access validation in
* RFC8341 3.4 */
/* 1. If the "enable-nacm" leaf is set to "false", then the protocol
@ -876,8 +863,6 @@ nacm_access(clicon_handle h,
done:
if (nsc)
xml_nsctx_free(nsc);
if (retval != 0 && xnacm0)
xml_free(xnacm0);
clicon_debug(1, "%s retval:%d (0:deny 1:permit)", __FUNCTION__, retval);
return retval;
permit:
@ -891,7 +876,6 @@ nacm_access(clicon_handle h,
* etc. If retval = 1 access is OK and skip next NACM step.
* @param[in] h Clicon handle
* @param[in] username User name of requestor
* @param[in] point NACM access control point
* @param[out] xncam NACM XML tree, set if retval=0. Free after use
* @retval -1 Error
* @retval 0 OK but not validated. Need to do NACM step using xnacm
@ -910,7 +894,6 @@ nacm_access(clicon_handle h,
int
nacm_access_pre(clicon_handle h,
char *username,
enum nacm_point point,
cxobj **xnacmp)
{
int retval = -1;
@ -920,19 +903,27 @@ nacm_access_pre(clicon_handle h,
cxobj *xnacm = NULL;
cvec *nsc = NULL;
mode = clicon_option_str(h, "CLICON_NACM_MODE");
if (mode == NULL)
goto permit;
else if (strcmp(mode, "disabled")==0)
goto permit;
else if (strcmp(mode, "external")==0){
if ((x = clicon_nacm_ext(h)))
if ((xnacm0 = xml_dup(x)) == NULL)
goto done;
}
else if (strcmp(mode, "internal")==0){
if (xmldb_get0(h, "running", nsc, "nacm", 1, &xnacm0, NULL) < 0)
goto done;
}
else{
clicon_err(OE_XML, 0, "Invalid NACM mode: %s", mode);
goto done;
}
if ((nsc = xml_nsctx_init(NULL, NACM_NS)) == NULL)
goto done;
if ((mode = clicon_option_str(h, "CLICON_NACM_MODE")) != NULL){
if (strcmp(mode, "external")==0){
if ((x = clicon_nacm_ext(h)))
if ((xnacm0 = xml_dup(x)) == NULL)
goto done;
}
else if (strcmp(mode, "internal")==0){
if (xmldb_get0(h, "running", nsc, "nacm", 1, &xnacm0, NULL) < 0)
goto done;
}
}
/* If config does not exist then the operation is permitted(?) */
if (xnacm0 == NULL)
goto permit;
@ -943,7 +934,7 @@ nacm_access_pre(clicon_handle h,
goto done;
xnacm0 = NULL;
/* Initial NACM steps and common to all NACM access validation. */
if ((retval = nacm_access(h, mode, xnacm, username)) < 0)
if ((retval = nacm_access(h, xnacm, username)) < 0)
goto done;
if (retval == 0){ /* if retval == 0 then return an xml nacm tree */
*xnacmp = xnacm;