From 5be5b02a849c3014cac88e45a6f1b0b28e4161f2 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 20 Apr 2020 22:29:09 +0200 Subject: [PATCH] NACM write path delete works as well --- CHANGELOG.md | 2 +- lib/clixon/clixon_nacm.h | 3 +- lib/clixon/clixon_xml.h | 1 + lib/src/clixon_datastore_write.c | 32 ++++++++++++--------- lib/src/clixon_nacm.c | 49 ++++++-------------------------- lib/src/clixon_xml.c | 16 +++++++++++ test/test_nacm_datanode.sh | 47 ++++++++++++++++++++++++------ 7 files changed, 86 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 198e2c8a..ec239b23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ Expected: May 2020 ### Major New features * NACM RFC8341 datanode read and write paths - * This completes the NACM RPC and Data node access checks (notification still remains) + * This completes the NACM RPC and Data node access checks (only remaining NACM access point is notification) ### API changes on existing protocol/config features (You may have have to change how you use Clixon) diff --git a/lib/clixon/clixon_nacm.h b/lib/clixon/clixon_nacm.h index 9b74372a..cfec270c 100644 --- a/lib/clixon/clixon_nacm.h +++ b/lib/clixon/clixon_nacm.h @@ -59,7 +59,8 @@ enum nacm_access{ int nacm_rpc(char *rpc, char *module, char *username, cxobj *xnacm, cbuf *cbret); int nacm_datanode_read(clicon_handle h, cxobj *xt, cxobj **xvec, size_t xlen, char *username, cxobj *nacm_xtree); -int nacm_datanode_write(clicon_handle h, cxobj *xt, cxobj *xr, enum nacm_access access, +int nacm_datanode_write(clicon_handle h, cxobj *xr, cxobj *xt, + enum nacm_access access, char *username, cxobj *xnacm, cbuf *cbret); int nacm_access_pre(clicon_handle h, char *username, cxobj **xnacmp); diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h index afda331a..c4769116 100644 --- a/lib/clixon/clixon_xml.h +++ b/lib/clixon/clixon_xml.h @@ -233,6 +233,7 @@ int xml_apply(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg int xml_apply0(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg); int xml_apply_ancestor(cxobj *xn, xml_applyfn_t fn, void *arg); int xml_isancestor(cxobj *x, cxobj *xp); +cxobj *xml_root(cxobj *xn); int xml_operation(char *opstr, enum operation_type *op); char *xml_operation2str(enum operation_type op); diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 4a7e56ca..3e673a0f 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -227,10 +227,11 @@ check_body_namespace(cxobj *x0, static int text_modify(clicon_handle h, cxobj *x0, - yang_stmt *y0, cxobj *x0p, + cxobj *x0t, cxobj *x1, cxobj *x1t, + yang_stmt *y0, enum operation_type op, char *username, cxobj *xnacm, @@ -319,7 +320,7 @@ text_modify(clicon_handle h, * of ordered-by user and (changed) insert attribute. */ if (!permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -336,7 +337,7 @@ text_modify(clicon_handle h, case OP_NONE: /* fall thru */ if (x0==NULL){ if ((op != OP_NONE) && !permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, NACM_CREATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, NACM_CREATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -403,7 +404,7 @@ text_modify(clicon_handle h, x0bstr = xml_value(x0b); if (x0bstr==NULL || strcmp(x0bstr, x1bstr)){ if ((op != OP_NONE) && !permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, + if ((ret = nacm_datanode_write(h, x1, x1t, x0bstr==NULL?NACM_CREATE:NACM_UPDATE, username, xnacm, cbret)) < 0) goto done; @@ -429,7 +430,7 @@ text_modify(clicon_handle h, case OP_REMOVE: /* fall thru */ if (x0){ if ((op != OP_NONE) && !permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -491,7 +492,7 @@ text_modify(clicon_handle h, * of ordered-by user and (changed) insert attribute. */ if (!permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -517,7 +518,7 @@ text_modify(clicon_handle h, if (op == OP_NONE) break; if (op==OP_MERGE && !permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x0, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -534,7 +535,7 @@ text_modify(clicon_handle h, } /* anyxml, anydata */ if (x0==NULL){ if (op==OP_MERGE && !permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, NACM_CREATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, NACM_CREATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -605,7 +606,8 @@ text_modify(clicon_handle h, x1cname = xml_name(x1c); x0c = x0vec[i++]; yc = yang_find_datanode(y0, x1cname); - if ((ret = text_modify(h, x0c, yc, x0, x1c, x1t, op, + if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t, + yc, op, username, xnacm, permit, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ @@ -626,7 +628,7 @@ text_modify(clicon_handle h, case OP_REMOVE: /* fall thru */ if (x0){ if (!permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -673,6 +675,7 @@ text_modify(clicon_handle h, static int text_modify_top(clicon_handle h, cxobj *x0, + cxobj *x0t, cxobj *x1, cxobj *x1t, yang_stmt *yspec, @@ -709,7 +712,7 @@ text_modify_top(clicon_handle h, case OP_REMOVE: case OP_REPLACE: if (!permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -743,7 +746,7 @@ text_modify_top(clicon_handle h, /* Special case top-level replace */ else if (op == OP_REPLACE || op == OP_DELETE){ if (!permit && xnacm){ - if ((ret = nacm_datanode_write(h, x1t, x1, NACM_UPDATE, username, xnacm, cbret)) < 0) + if ((ret = nacm_datanode_write(h, x1, x1t, NACM_UPDATE, username, xnacm, cbret)) < 0) goto done; if (ret == 0) goto fail; @@ -777,7 +780,8 @@ text_modify_top(clicon_handle h, goto done; x0c = NULL; } - if ((ret = text_modify(h, x0c, yc, x0, x1c, x1t, op, + if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t, + yc, op, username, xnacm, permit, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ @@ -921,7 +925,7 @@ xmldb_put(clicon_handle h, * Modify base tree x with modification x1. This is where the * new tree is made. */ - if ((ret = text_modify_top(h, x0, x1, x1, yspec, op, username, xnacm, permit, cbret)) < 0) + if ((ret = text_modify_top(h, x0, x0, x1, x1, yspec, op, username, xnacm, permit, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ if (ret == 0){ diff --git a/lib/src/clixon_nacm.c b/lib/src/clixon_nacm.c index 25da7526..01c6f863 100644 --- a/lib/src/clixon_nacm.c +++ b/lib/src/clixon_nacm.c @@ -462,9 +462,9 @@ nacm_datanode_prepare(clicon_handle h, */ /*! Match specific rule to specific requested node - * @param[in] xt XML root tree with "config" label * @param[in] xn XML node (requested node) * @param[in] xrule NACM rule + * @param[in] xp Xpath match * @param[in] yspec YANG spec * @retval -1 Error * @retval 0 OK and rule does not match @@ -473,43 +473,15 @@ nacm_datanode_prepare(clicon_handle h, */ static int nacm_data_write_xrule_xml(cxobj *xn, - enum nacm_access access, cxobj *xrule, cxobj *xp, yang_stmt *yspec) { int retval = -1; - cxobj *pathobj; yang_stmt *ymod; char *module_pattern; /* rule module name */ - char *access_operations; char *action; - access_operations = xml_find_body(xrule, "access-operations"); - switch (access){ - case NACM_CREATE: - /* 6d) For a "create" access operation, the rule's "access-operations" - leaf has the "create" bit set or has the special value "*". */ - if (!match_access(access_operations, "create", "write")) - goto nomatch; - break; - case NACM_DELETE: - /* 6e) For a "delete" access operation, the rule's "access-operations" - leaf has the "delete" bit set or has the special value "*". */ - if (!match_access(access_operations, "delete", "write")) - goto nomatch; - break; - case NACM_UPDATE: - /* 6f) For an "update" access operation, the rule's "access-operations" - leaf has the "update" bit set or has the special value "*". */ - if (!match_access(access_operations, "update", "write")) - goto nomatch; - break; - default: - clicon_err(OE_XML, EINVAL, "Access %d unupported (shouldnt happen)", access); - goto done; - break; - } if ((module_pattern = xml_find_body(xrule, "module-name")) == NULL) goto nomatch; /* 6a) The rule's "module-name" leaf is "*" or equals the name of @@ -525,7 +497,7 @@ nacm_data_write_xrule_xml(cxobj *xn, /* 6b) Either (1) the rule does not have a "rule-type" defined or (2) the "rule-type" is "data-node" and the "path" matches the Requested data node, action node, or notification node. */ - if ((pathobj = xml_find_type(xrule, NULL, "path", CX_ELMNT)) == NULL){ + if (xml_find_type(xrule, NULL, "path", CX_ELMNT) == NULL){ if (strcmp(action, "deny")==0) goto deny; goto permit; @@ -549,7 +521,6 @@ nacm_data_write_xrule_xml(cxobj *xn, /*! Recursive check for NACM write rules among all XML nodes * @param[in] h Clicon handle - * @param[in] access NACM access right * @param[in] xn XML node (requested node) * @param[in] rulevec Precomputed rules that apply to this user group * @param[in] xpathvec Precomputed xpath results that apply to this XML tree @@ -567,7 +538,6 @@ nacm_data_write_xrule_xml(cxobj *xn, static int nacm_datanode_write_recurse(clicon_handle h, cxobj *xn, - enum nacm_access access, clixon_xvec *rulevec, clixon_xvec *xpathvec, int defpermit, @@ -580,7 +550,7 @@ nacm_datanode_write_recurse(clicon_handle h, int ret = 0; for (i=0; i