diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index c0266ab6..a3d40b51 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -654,13 +654,13 @@ compare_dbs(clicon_handle h, astext = cv_int32_get(cvec_i(argv, 0)); else astext = 0; - if (clicon_rpc_get_config(h, "running", "/", &xc1) < 0) + if (clicon_rpc_get_config(h, "running", "/", NULL, &xc1) < 0) goto done; if ((xerr = xpath_first(xc1, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); goto done; } - if (clicon_rpc_get_config(h, "candidate", "/", &xc2) < 0) + if (clicon_rpc_get_config(h, "candidate", "/", NULL, &xc2) < 0) goto done; if ((xerr = xpath_first(xc2, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); @@ -827,7 +827,7 @@ save_config_file(clicon_handle h, goto done; } filename = cv_string_get(cv); - if (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0) + if (clicon_rpc_get_config(h, dbstr,"/", NULL, &xt) < 0) goto done; if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); @@ -1171,7 +1171,7 @@ cli_copy_config(clicon_handle h, cprintf(cb, xpath, keyname, fromname); /* Get from object configuration and store in x1 */ - if (clicon_rpc_get_config(h, db, cbuf_get(cb), &x1) < 0) + if (clicon_rpc_get_config(h, db, cbuf_get(cb), NULL, &x1) < 0) goto done; if ((xerr = xpath_first(x1, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 0c3769d7..85645413 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -156,7 +156,7 @@ expand_dbvar(void *h, goto done; /* XXX read whole configuration, why not send xpath? */ - if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0) + if (clicon_rpc_get_config(h, dbstr, "/", NULL, &xt) < 0) goto done; if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); @@ -484,7 +484,7 @@ cli_show_config(clicon_handle h, else cprintf(cbxpath, "%s", xpath); /* Get configuration from database */ - if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), &xt) < 0) + if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), NULL, &xt) < 0) goto done; if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); @@ -568,7 +568,7 @@ show_conf_xpath(clicon_handle h, } cv = cvec_find_var(cvv, "xpath"); xpath = cv_string_get(cv); - if (clicon_rpc_get_config(h, str, xpath, &xt) < 0) + if (clicon_rpc_get_config(h, str, xpath, NULL, &xt) < 0) goto done; if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ clicon_rpc_generate_error("Get configuration", xerr); diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index 54b422ed..5ae99543 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -89,7 +89,8 @@ * @param[in] pcvec Vector of path ie DOCUMENT_URI element * @param[in] pi Offset, where to start pcvec * @param[in] qvec Vector of query string (QUERY_STRING) - * @param[in] dvec Stream input data + * @param[in] dvec Stream input daat + * @param[in] username Authenticated user */ static int api_data(clicon_handle h, @@ -98,7 +99,8 @@ api_data(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, - char *data) + char *data, + char *username) { int retval = -1; char *request_method; @@ -109,17 +111,17 @@ api_data(clicon_handle h, if (strcmp(request_method, "OPTIONS")==0) retval = api_data_options(h, r); else if (strcmp(request_method, "HEAD")==0) - retval = api_data_head(h, r, pcvec, pi, qvec); + retval = api_data_head(h, r, pcvec, pi, qvec, username); else if (strcmp(request_method, "GET")==0) - retval = api_data_get(h, r, pcvec, pi, qvec); + retval = api_data_get(h, r, pcvec, pi, qvec, username); else if (strcmp(request_method, "POST")==0) - retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data); + retval = api_data_post(h, r, api_path, pcvec, pi, qvec, data, username); else if (strcmp(request_method, "PUT")==0) - retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data); + retval = api_data_put(h, r, api_path, pcvec, pi, qvec, data, username); else if (strcmp(request_method, "PATCH")==0) - retval = api_data_patch(h, r, api_path, pcvec, pi, qvec, data); + retval = api_data_patch(h, r, api_path, pcvec, pi, qvec, data, username); else if (strcmp(request_method, "DELETE")==0) - retval = api_data_delete(h, r, api_path, pi); + retval = api_data_delete(h, r, api_path, pi, username); else retval = notfound(r); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); @@ -152,7 +154,7 @@ api_operations(clicon_handle h, request_method = FCGX_GetParam("REQUEST_METHOD", r->envp); clicon_debug(1, "%s method:%s", __FUNCTION__, request_method); if (strcmp(request_method, "GET")==0) - retval = api_operation_get(h, r, path, pcvec, pi, qvec, data); + retval = api_operation_get(h, r, path, pcvec, pi, qvec, data, username); else if (strcmp(request_method, "POST")==0) retval = api_operation_post(h, r, path, pcvec, pi, qvec, data, username); else @@ -335,7 +337,7 @@ api_restconf(clicon_handle h, goto done; } else if (strcmp(method, "data") == 0){ /* restconf, skip /api/data */ - if (api_data(h, r, path, pcvec, 2, qvec, data) < 0) + if (api_data(h, r, path, pcvec, 2, qvec, data, username) < 0) goto done; } else if (strcmp(method, "operations") == 0){ /* rpc */ diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index 69bae763..992a8662 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -218,6 +218,7 @@ api_data_get2(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, + char *username, int head) { int retval = -1; @@ -252,7 +253,7 @@ api_data_get2(clicon_handle h, } path = cbuf_get(cbpath); clicon_debug(1, "%s path:%s", __FUNCTION__, path); - if (clicon_rpc_get(h, path, &xret) < 0){ + if (clicon_rpc_get(h, path, username, &xret) < 0){ notfound(r); goto ok; } @@ -338,12 +339,13 @@ api_data_get2(clicon_handle h, */ int api_data_head(clicon_handle h, - FCGX_Request *r, - cvec *pcvec, - int pi, - cvec *qvec) + FCGX_Request *r, + cvec *pcvec, + int pi, + cvec *qvec, + char *username) { - return api_data_get2(h, r, pcvec, pi, qvec, 1); + return api_data_get2(h, r, pcvec, pi, qvec, username, 1); } /*! REST GET method @@ -374,9 +376,10 @@ api_data_get(clicon_handle h, FCGX_Request *r, cvec *pcvec, int pi, - cvec *qvec) + cvec *qvec, + char *username) { - return api_data_get2(h, r, pcvec, pi, qvec, 0); + return api_data_get2(h, r, pcvec, pi, qvec, username, 0); } /*! Generic REST POST method @@ -412,7 +415,8 @@ api_data_post(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, - char *data) + char *data, + char *username) { int retval = -1; enum operation_type op = OP_CREATE; @@ -425,6 +429,7 @@ api_data_post(clicon_handle h, yang_node *y = NULL; yang_spec *yspec; cxobj *xa; + cxobj *xu; char *media_content_type; int parse_xml = 0; /* By default expect and parse JSON */ @@ -446,6 +451,16 @@ api_data_post(clicon_handle h, goto done; /* Translate api_path to xtop/xbot */ xbot = xtop; + /* For internal XML protocol: add username attribute for backend access control + */ + if (username){ + if ((xu = xml_new("username", xtop, NULL)) == NULL) + goto done; + xml_type_set(xu, CX_ATTR); + if (xml_value_set(xu, username) < 0) + goto done; + } + if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0) goto done; /* Parse input data as json or xml into xml */ @@ -589,7 +604,8 @@ api_data_put(clicon_handle h, cvec *pcvec, int pi, cvec *qvec, - char *data) + char *data, + char *username) { int retval = -1; enum operation_type op = OP_REPLACE; @@ -603,6 +619,7 @@ api_data_put(clicon_handle h, yang_node *y = NULL; yang_spec *yspec; cxobj *xa; + cxobj *xu; char *media_content_type; int parse_xml = 0; /* By default expect and parse JSON */ char *api_path; @@ -625,6 +642,15 @@ api_data_put(clicon_handle h, goto done; /* Translate api_path to xtop/xbot */ xbot = xtop; + /* For internal XML protocol: add username attribute for backend access control + */ + if (username){ + if ((xu = xml_new("username", xtop, NULL)) == NULL) + goto done; + xml_type_set(xu, CX_ATTR); + if (xml_value_set(xu, username) < 0) + goto done; + } if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0) goto done; /* Parse input data as json or xml into xml */ @@ -727,12 +753,13 @@ api_data_put(clicon_handle h, */ int api_data_patch(clicon_handle h, - FCGX_Request *r, - char *api_path, - cvec *pcvec, - int pi, - cvec *qvec, - char *data) + FCGX_Request *r, + char *api_path, + cvec *pcvec, + int pi, + cvec *qvec, + char *data, + char *username) { notimplemented(r); return 0; @@ -751,13 +778,15 @@ int api_data_delete(clicon_handle h, FCGX_Request *r, char *api_path, - int pi) + int pi, + char *username) { int retval = -1; int i; cxobj *xtop = NULL; /* xpath root */ cxobj *xbot = NULL; cxobj *xa; + cxobj *xu; cbuf *cbx = NULL; yang_node *y = NULL; yang_spec *yspec; @@ -774,6 +803,15 @@ api_data_delete(clicon_handle h, if ((xtop = xml_new("config", NULL, NULL)) == NULL) goto done; xbot = xtop; + /* For internal XML protocol: add username attribute for backend access control + */ + if (username){ + if ((xu = xml_new("username", xtop, NULL)) == NULL) + goto done; + xml_type_set(xu, CX_ATTR); + if (xml_value_set(xu, username) < 0) + goto done; + } if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0) goto done; if ((xa = xml_new("operation", xbot, NULL)) == NULL) @@ -817,13 +855,15 @@ api_data_delete(clicon_handle h, */ int api_operation_get(clicon_handle h, - FCGX_Request *r, - char *path, - cvec *pcvec, - int pi, - cvec *qvec, - char *data) + FCGX_Request *r, + char *path, + cvec *pcvec, + int pi, + cvec *qvec, + char *data, + char *username) { + notimplemented(r); return 0; } @@ -837,8 +877,6 @@ api_operation_get(clicon_handle h, * @note We map post to edit-config create. POST {+restconf}/operations/ - - */ int api_operation_post(clicon_handle h, @@ -907,6 +945,16 @@ api_operation_post(clicon_handle h, if ((xtop = xml_new("rpc", NULL, NULL)) == NULL) goto done; xbot = xtop; + /* For internal XML protocol: add username attribute for backend access control + */ + if (username){ + if ((xa = xml_new("username", xtop, NULL)) == NULL) + goto done; + xml_type_set(xa, CX_ATTR); + if (xml_value_set(xa, username) < 0) + goto done; + } + /* XXX: something strange for rpc user */ if (api_path2xml(oppath, yspec, xtop, 1, &xbot, &y) < 0) goto done; @@ -951,34 +999,6 @@ api_operation_post(clicon_handle h, } } } - /* Non-standard: add username attribute for backend ACM (RFC 6536) - * - */ - if (username){ - if ((xa = xml_new("username", xtop, NULL)) == NULL) - goto done; - xml_type_set(xa, CX_ATTR); - if (xml_value_set(xa, username) < 0) - goto done; - } -#ifdef obsolete - { - cxobj *xa; - char *cookie; - char *cookieval = NULL; - - if ((cookie = FCGX_GetParam("HTTP_COOKIE", r->envp)) != NULL && - get_user_cookie(cookie, "c-user", &cookieval) ==0){ - if ((xa = xml_new("id", xtop, NULL)) == NULL) - goto done; - xml_type_set(xa, CX_ATTR); - if (xml_value_set(xa, cookieval) < 0) - goto done; - if (cookieval) - free(cookieval); - } - } -#endif /* Send to backend */ if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0) goto done; diff --git a/apps/restconf/restconf_methods.h b/apps/restconf/restconf_methods.h index 659a2c6c..b50b91a6 100644 --- a/apps/restconf/restconf_methods.h +++ b/apps/restconf/restconf_methods.h @@ -46,23 +46,24 @@ */ int api_data_options(clicon_handle h, FCGX_Request *r); int api_data_head(clicon_handle h, FCGX_Request *r, cvec *pcvec, int pi, - cvec *qvec); + cvec *qvec, char *username); int api_data_get(clicon_handle h, FCGX_Request *r, cvec *pcvec, int pi, - cvec *qvec); + cvec *qvec, char *username); int api_data_post(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, - cvec *qvec, char *data); + cvec *qvec, char *data, char *username); int api_data_put(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, - cvec *qvec, char *data); + cvec *qvec, char *data, char *username); int api_data_patch(clicon_handle h, FCGX_Request *r, char *api_path, cvec *pcvec, int pi, - cvec *qvec, char *data); -int api_data_delete(clicon_handle h, FCGX_Request *r, char *api_path, int pi); + cvec *qvec, char *data, char *username); +int api_data_delete(clicon_handle h, FCGX_Request *r, char *api_path, int pi, + char *username); int api_operation_get(clicon_handle h, FCGX_Request *r, - char *path, - cvec *pcvec, int pi, cvec *qvec, char *data); + char *path, + cvec *pcvec, int pi, cvec *qvec, char *data, char *username); int api_operation_post(clicon_handle h, FCGX_Request *r, char *path, diff --git a/lib/clixon/clixon_proto_client.h b/lib/clixon/clixon_proto_client.h index ac917d77..7adccc68 100644 --- a/lib/clixon/clixon_proto_client.h +++ b/lib/clixon/clixon_proto_client.h @@ -45,14 +45,14 @@ int clicon_rpc_msg(clicon_handle h, struct clicon_msg *msg, cxobj **xret0, int clicon_rpc_netconf(clicon_handle h, char *xmlst, cxobj **xret, int *sp); int clicon_rpc_netconf_xml(clicon_handle h, cxobj *xml, cxobj **xret, int *sp); int clicon_rpc_generate_error(char *format, cxobj *xerr); -int clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, cxobj **xret); +int clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, char *username, cxobj **xret); int clicon_rpc_edit_config(clicon_handle h, char *db, enum operation_type op, char *xml); int clicon_rpc_copy_config(clicon_handle h, char *db1, char *db2); int clicon_rpc_delete_config(clicon_handle h, char *db); int clicon_rpc_lock(clicon_handle h, char *db); int clicon_rpc_unlock(clicon_handle h, char *db); -int clicon_rpc_get(clicon_handle h, char *xpath, cxobj **xret); +int clicon_rpc_get(clicon_handle h, char *xpath, char *username, cxobj **xret); int clicon_rpc_close_session(clicon_handle h); int clicon_rpc_kill_session(clicon_handle h, int session_id); int clicon_rpc_validate(clicon_handle h, char *db); diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index 4a5808cf..05991b74 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -236,6 +236,7 @@ clicon_rpc_generate_error(char *format, * @param[in] h CLICON handle * @param[in] db Name of database * @param[in] xpath XPath (or "") + * @param[in] username Authenticated user (extra attribute) * @param[out] xt XML tree. Free with xml_free. * Either or . * @retval 0 OK @@ -257,6 +258,7 @@ int clicon_rpc_get_config(clicon_handle h, char *db, char *xpath, + char *username, cxobj **xt) { int retval = -1; @@ -267,7 +269,10 @@ clicon_rpc_get_config(clicon_handle h, if ((cb = cbuf_new()) == NULL) goto done; - cprintf(cb, "<%s/>", db); + cprintf(cb, "<%s/>", db); if (xpath && strlen(xpath)) cprintf(cb, "", xpath); cprintf(cb, ""); @@ -485,6 +490,7 @@ clicon_rpc_unlock(clicon_handle h, /*! Get database configuration and state data * @param[in] h CLICON handle * @param[in] xpath XPath (or "") + * @param[in] username Authenticated user (extra attribute) * @param[out] xt XML tree. Free with xml_free. * Either or . * @retval 0 OK @@ -505,6 +511,7 @@ clicon_rpc_unlock(clicon_handle h, int clicon_rpc_get(clicon_handle h, char *xpath, + char *username, cxobj **xt) { int retval = -1; @@ -515,7 +522,10 @@ clicon_rpc_get(clicon_handle h, if ((cb = cbuf_new()) == NULL) goto done; - cprintf(cb, ""); + cprintf(cb, ""); if (xpath && strlen(xpath)) cprintf(cb, "", xpath); cprintf(cb, "");