From 98cc62eacebf76e21a36b1ba27bf9c166d3b0e2c Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 12 Jun 2019 18:15:44 +0200 Subject: [PATCH] Fixed a problem with some netconf error messages caused restconf daemon to exit due to no XML encoding --- CHANGELOG.md | 1 + lib/src/clixon_netconf_lib.c | 76 ++++++++++++++++++++++++----------- lib/src/clixon_xml_map.c | 4 +- test/test_nacm_ext.sh | 3 +- test/test_netconf.sh | 2 +- test/test_restconf_listkey.sh | 7 ++++ test/test_rpc.sh | 4 +- 7 files changed, 68 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9bfcd38..4584002e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -237,6 +237,7 @@ ### Corrected Bugs +* Fixed a problem with some netconf error messages caused restconf daemon to exit due to no XML encoding * Check cligen tab mode, dont start if CLICON_CLI_TAB_MODE is undefined * Startup transactions did not mark added tree with XML_FLAG_ADD as it should. * Restconf PUT different keys detected (thanks @dcornejo) and fixed diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index 6667b436..bf59a9bb 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -74,7 +74,7 @@ * The request requires a resource that already is in use. * @param[out] cb CLIgen buf. Error XML is written in this buffer * @param[in] type Error type: "application" or "protocol" - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ int netconf_in_use(cbuf *cb, @@ -113,7 +113,7 @@ netconf_in_use(cbuf *cb, * The request specifies an unacceptable value for one or more parameters. * @param[out] cb CLIgen buf. Error XML is written in this buffer * @param[in] type Error type: "application" or "protocol" - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ int netconf_invalid_value(cbuf *cb, @@ -153,7 +153,7 @@ netconf_invalid_value(cbuf *cb, * too large for the implementation to handle. * @param[out] cb CLIgen buf. Error XML is written in this buffer * @param[in] type Error type: "transport", "rpc", "application", "protocol" - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ int netconf_too_big(cbuf *cb, @@ -193,7 +193,7 @@ netconf_too_big(cbuf *cb, * @param[out] cb CLIgen buf. Error XML is written in this buffer * @param[in] type Error type: "rpc", "application" or "protocol" * @param[in] info bad-attribute or bad-element xml - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ int netconf_missing_attribute(cbuf *cb, @@ -234,7 +234,7 @@ netconf_missing_attribute(cbuf *cb, * @param[out] cb CLIgen buf. Error XML is written in this buffer * @param[in] type Error type: "rpc", "application" or "protocol" * @param[in] info bad-attribute or bad-element xml - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ int netconf_bad_attribute(cbuf *cb, @@ -317,7 +317,7 @@ netconf_unknown_attribute(cbuf *cb, * @param[in] type Error type: "application" or "protocol" * @param[in] tag Error tag * @param[in] element bad-element xml - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) */ static int netconf_common_xml(cxobj **xret, @@ -327,8 +327,9 @@ netconf_common_xml(cxobj **xret, char *element, char *message) { - int retval =-1; + int retval =-1; cxobj *xerr; + char *encstr = NULL; if (*xret == NULL){ if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) @@ -344,11 +345,17 @@ netconf_common_xml(cxobj **xret, "error", type, tag, infotag, element, infotag) < 0) goto done; - if (message && xml_parse_va(&xerr, NULL, "%s", - message) < 0) - goto done; + if (message){ + if (xml_chardata_encode(&encstr, "%s", message) < 0) + goto done; + if (xml_parse_va(&xerr, NULL, "%s", + encstr) < 0) + goto done; + } retval = 0; done: + if (encstr) + free(encstr); return retval; } @@ -555,7 +562,7 @@ netconf_access_denied(cbuf *cb, * authorization failed. * @param[out] xret Error XML tree. Free with xml_free after use * @param[in] type Error type: "application" or "protocol" - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) * @code * cxobj *xret = NULL; * if (netconf_access_denied_xml(&xret, "protocol", "Unauthorized") < 0) @@ -569,9 +576,10 @@ netconf_access_denied_xml(cxobj **xret, char *type, char *message) { - int retval =-1; + int retval =-1; cxobj *xerr; - + char *encstr = NULL; + if (*xret == NULL){ if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) goto done; @@ -584,11 +592,17 @@ netconf_access_denied_xml(cxobj **xret, "access-denied" "error", type) < 0) goto done; - if (message && xml_parse_va(&xerr, NULL, "%s", - message) < 0) - goto done; + if (message){ + if (xml_chardata_encode(&encstr, "%s", message) < 0) + goto done; + if (xml_parse_va(&xerr, NULL, "%s", + encstr) < 0) + goto done; + } retval = 0; done: + if (encstr) + free(encstr); return retval; } @@ -905,7 +919,7 @@ netconf_operation_failed(cbuf *cb, * some reason not covered by any other error condition. * @param[out] xret Error XML tree * @param[in] type Error type: "rpc", "application" or "protocol" - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) * @code * cxobj *xret = NULL; * if (netconf_operation_failed_xml(&xret, "protocol", "Unauthorized") < 0) @@ -921,6 +935,7 @@ netconf_operation_failed_xml(cxobj **xret, { int retval =-1; cxobj *xerr; + char *encstr = NULL; if (*xret == NULL){ if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) @@ -934,11 +949,17 @@ netconf_operation_failed_xml(cxobj **xret, "operation-failed" "error", type) < 0) goto done; - if (message && xml_parse_va(&xerr, NULL, "%s", - message) < 0) + if (message){ + if (xml_chardata_encode(&encstr, "%s", message) < 0) + goto done; + if (xml_parse_va(&xerr, NULL, "%s", + encstr) < 0) goto done; + } retval = 0; done: + if (encstr) + free(encstr); return retval; } @@ -976,7 +997,7 @@ netconf_malformed_message(cbuf *cb, * For example, the message is not well-formed XML or it uses an * invalid character set. * @param[out] xret Error XML tree - * @param[in] message Error message + * @param[in] message Error message (will be XML encoded) * @note New in :base:1.1 * @code * cxobj *xret = NULL; @@ -990,8 +1011,9 @@ int netconf_malformed_message_xml(cxobj **xret, char *message) { - int retval =-1; + int retval =-1; cxobj *xerr; + char *encstr = NULL; if (*xret == NULL){ if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL) @@ -1005,11 +1027,17 @@ netconf_malformed_message_xml(cxobj **xret, "malformed-message" "error") < 0) goto done; - if (message && xml_parse_va(&xerr, NULL, "%s", - message) < 0) - goto done; + if (message){ + if (xml_chardata_encode(&encstr, "%s", message) < 0) + goto done; + if (xml_parse_va(&xerr, NULL, "%s", + encstr) < 0) + goto done; + } retval = 0; done: + if (encstr) + free(encstr); return retval; } diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 04cb8b79..6ef46b70 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2212,7 +2212,9 @@ xml_spec_populate_rpc(clicon_handle h, if (yrpc){ xml_spec_set(x, yrpc); if ((yi = yang_find(yrpc, Y_INPUT, NULL)) != NULL){ - /* kludge rpc -> input XXX THIS HIDES AN ERROR IN xml_spec_populate */ + /* xml_spec_populate need to have parent with yang spec for + * recursive population to work. Therefore, assign input yang + * to rpc level although not 100% intuitive */ xml_spec_set(x, yi); if (xml_apply(x, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; diff --git a/test/test_nacm_ext.sh b/test/test_nacm_ext.sh index e2207ea8..9453978a 100755 --- a/test/test_nacm_ext.sh +++ b/test/test_nacm_ext.sh @@ -149,7 +149,8 @@ new "start restconf daemon (-a is enable http basic auth)" start_restconf -f $cfg -- -a new "waiting" -sleep $RCWAIT +wait_backend +wait_restconf new "auth get" expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data)" 0 '{"data": {"clixon-example:state": {"op": ["42","41","43"]}}} diff --git a/test/test_netconf.sh b/test/test_netconf.sh index 6ec9e127..05cfdfe5 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -46,7 +46,7 @@ if [ $BE -ne 0 ]; then start_backend -s init -f $cfg -- -s new "waiting" - sleep $RCWAIT + wait_backend fi new "netconf hello" diff --git a/test/test_restconf_listkey.sh b/test/test_restconf_listkey.sh index 2426e4b9..cb0546e4 100755 --- a/test/test_restconf_listkey.sh +++ b/test/test_restconf_listkey.sh @@ -90,6 +90,10 @@ wait_restconf new "restconf PUT add whole list entry" expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"x","c":"y","nonkey":"0"}}' 0 '' +new "restconf PUT add whole list entry XML" +expecteq "$(curl -s -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d 'xxxy0' http://localhost/restconf/data/list:c/a=xx,xy)" 0 '' + + new "restconf PUT change whole list entry (same keys)" expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"x","c":"y","nonkey":"z"}}' 0 '' @@ -99,6 +103,9 @@ expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"a":{"b new "restconf PUT change list entry (wrong keys)(expect fail)" expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x,y -d {"list:a":{"b":"y","c":"x"}}' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "api-path keys do not match data keys"}}}' +new "restconf PUT change list entry (wrong keys)(expect fail) XML" +expecteq "$(curl -s -X PUT -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+xml' -d 'xyxz0' http://localhost/restconf/data/list:c/a=xx,xy)" 0 'protocoloperation-failederrorapi-path keys do not match data keys ' + new "restconf PUT change list entry (just one key)(expect fail)" expectfn 'curl -s -X PUT http://localhost/restconf/data/list:c/a=x -d {"list:a":{"b":"x"}}' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "rpc","error-tag": "malformed-message","error-severity": "error","error-message": "List key a length mismatch"}}} ' diff --git a/test/test_rpc.sh b/test/test_rpc.sh index d78ec54e..e39b6847 100755 --- a/test/test_rpc.sh +++ b/test/test_rpc.sh @@ -77,11 +77,11 @@ expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"x":"0","y":"99"}}' htt new "restconf example rpc json/json" # XXX example:input example:output -expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+json' -H 'Content-Type: application/yang-data+json' -d '{"clixon-example:input":{"x":"0"}}' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}} +expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+json' -H 'Accept: application/yang-data+json' -d '{"clixon-example:input":{"x":"0"}}' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}} ' new "restconf example rpc xml/json" -expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+xml' -H 'Content-Type: application/yang-data+json' -d '0' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}} +expecteq "$(curl -s -X POST -H 'Content-Type: application/yang-data+xml' -H 'Accept: application/yang-data+json' -d '0' http://localhost/restconf/operations/clixon-example:example)" 0 '{"clixon-example:output": {"x": "0","y": "42"}} ' new "restconf example rpc json/xml"