* Restconf authentication callback (ca_auth) signature changed
* Not backward compatible: All uses of the ca-auth callback in restconf plugins must be changed
* New version is: `int ca_auth(h, req, auth_type, authp, userp)`
* where `auth_type` is the requested authentication-type (none, client-cert or user-defined)
* `authp` is the returned authentication flag
* `userp` is the returned associated authenticated user
* and the return value is three-valued: -1: Error, 0: ignored, 1: OK
* For more info see [clixon-docs](https://clixon-docs.readthedocs.io/en/latest/restconf.html)
* New clixon-restconf@2020-12-30.yang revision
This commit is contained in:
parent
1f0147f996
commit
710fc76887
54 changed files with 1216 additions and 485 deletions
|
|
@ -61,6 +61,7 @@
|
|||
/* clicon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
#include "restconf_lib.h"
|
||||
#include "restconf_handle.h"
|
||||
|
||||
/* header part is copied from struct clicon_handle in lib/src/clixon_handle.c */
|
||||
|
|
@ -90,6 +91,7 @@ struct restconf_handle {
|
|||
|
||||
/* ------ end of common handle ------ */
|
||||
clicon_hash_t *rh_params; /* restconf parameters, including http headers */
|
||||
clixon_auth_type_t rh_auth_type; /* authentication type */
|
||||
};
|
||||
|
||||
/*! Creates and returns a clicon config handle for other CLICON API calls
|
||||
|
|
@ -172,3 +174,33 @@ restconf_param_del_all(clicon_handle h)
|
|||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Get restconf http parameter
|
||||
* @param[in] h Clicon handle
|
||||
* @retval auth_type
|
||||
*/
|
||||
clixon_auth_type_t
|
||||
restconf_auth_type_get(clicon_handle h)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
return rh->rh_auth_type;
|
||||
}
|
||||
|
||||
/*! Set restconf http parameter
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] name Data name
|
||||
* @param[in] val Data value as null-terminated string
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* Currently using clixon runtime data but there is risk for colliding names
|
||||
*/
|
||||
int
|
||||
restconf_auth_type_set(clicon_handle h,
|
||||
clixon_auth_type_t type)
|
||||
{
|
||||
struct restconf_handle *rh = handle(h);
|
||||
|
||||
rh->rh_auth_type = type;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,5 +47,7 @@ int restconf_handle_exit(clicon_handle h);
|
|||
char *restconf_param_get(clicon_handle h, const char *param);
|
||||
int restconf_param_set(clicon_handle h, const char *param, char *val);
|
||||
int restconf_param_del_all(clicon_handle h);
|
||||
clixon_auth_type_t restconf_auth_type_get(clicon_handle h);
|
||||
int restconf_auth_type_set(clicon_handle h, clixon_auth_type_t type);
|
||||
|
||||
#endif /* _RESTCONF_HANDLE_H_ */
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@
|
|||
#include <clixon/clixon.h>
|
||||
|
||||
#include "restconf_api.h"
|
||||
#include "restconf_handle.h"
|
||||
#include "restconf_lib.h"
|
||||
#include "restconf_err.h"
|
||||
#include "restconf_handle.h"
|
||||
|
||||
/* See RFC 8040 Section 7: Mapping from NETCONF<error-tag> to Status Code
|
||||
* and RFC 6241 Appendix A. NETCONF Error list
|
||||
|
|
@ -495,3 +496,123 @@ restconf_drop_privileges(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Generic Www handle (can be part of clixon handle)
|
||||
* @retval -1 Error
|
||||
* @retval 0 Not authenticated
|
||||
* @retval 1 Authenticated
|
||||
*/
|
||||
int
|
||||
restconf_authentication_cb(clicon_handle h,
|
||||
void *req,
|
||||
int pretty,
|
||||
restconf_media media_out)
|
||||
{
|
||||
int retval = -1;
|
||||
clixon_auth_type_t auth_type;
|
||||
int authenticated;
|
||||
int ret;
|
||||
char *username = NULL;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
|
||||
auth_type = restconf_auth_type_get(h);
|
||||
clicon_debug(1, "%s auth-type:%s", __FUNCTION__, clixon_auth_type_int2str(auth_type));
|
||||
ret = 0;
|
||||
authenticated = 0;
|
||||
if (auth_type != CLIXON_AUTH_NONE)
|
||||
if ((ret = clixon_plugin_auth_all(h, req,
|
||||
auth_type,
|
||||
&authenticated,
|
||||
&username)) < 0)
|
||||
goto done;
|
||||
if (ret == 1){ /* OK, tag username to handle */
|
||||
clicon_username_set(h, username);
|
||||
}
|
||||
else { /* Default behaviour */
|
||||
switch (auth_type){
|
||||
case CLIXON_AUTH_NONE:
|
||||
clicon_username_set(h, "none");
|
||||
authenticated = 1;
|
||||
break;
|
||||
case CLIXON_AUTH_CLIENT_CERTIFICATE: {
|
||||
char *cn;
|
||||
/* Check for cert subject common name (CN) */
|
||||
if ((cn = restconf_param_get(h, "SSL_CN")) != NULL){
|
||||
clicon_username_set(h, cn);
|
||||
authenticated = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLIXON_AUTH_USER:
|
||||
authenticated = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (authenticated == 0){ /* Message is not authenticated (401 returned) */
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
goto done;
|
||||
goto notauth;
|
||||
}
|
||||
retval = 0;
|
||||
goto notauth;
|
||||
}
|
||||
/* If set but no user, set a dummy user */
|
||||
retval = 1;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d authenticated:%d user:%s",
|
||||
__FUNCTION__, retval, authenticated, clicon_username_get(h));
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
notauth:
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Basic config init
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] xrestconf XML config containing clixon-restconf top-level
|
||||
* @retval -1 Error
|
||||
* @retval 0 Restconf is disable
|
||||
* @retval 1 OK
|
||||
*/
|
||||
int
|
||||
restconf_config_init(clicon_handle h,
|
||||
cxobj *xrestconf)
|
||||
{
|
||||
int retval = -1;
|
||||
char *enable;
|
||||
cxobj *x;
|
||||
char *bstr;
|
||||
cvec *nsc = NULL;
|
||||
clixon_auth_type_t auth_type;
|
||||
|
||||
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
|
||||
(enable = xml_body(x)) != NULL){
|
||||
if (strcmp(enable, "false") == 0){
|
||||
clicon_debug(1, "%s restconf disabled", __FUNCTION__);
|
||||
goto disable;
|
||||
}
|
||||
}
|
||||
|
||||
/* get common fields */
|
||||
if ((x = xpath_first(xrestconf, nsc, "auth-type")) != NULL &&
|
||||
(bstr = xml_body(x)) != NULL){
|
||||
if ((auth_type = clixon_auth_type_str2int(bstr)) < 0){
|
||||
clicon_err(OE_CFG, EFAULT, "Invalid restconf auth-type: %s", bstr);
|
||||
goto done;
|
||||
}
|
||||
restconf_auth_type_set(h, auth_type);
|
||||
}
|
||||
retval = 1;
|
||||
done:
|
||||
return retval;
|
||||
disable:
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ int restconf_insert_attributes(cxobj *xdata, cvec *qvec);
|
|||
int restconf_main_extension_cb(clicon_handle h, yang_stmt *yext, yang_stmt *ys);
|
||||
char *restconf_uripath(clicon_handle h);
|
||||
int restconf_drop_privileges(clicon_handle h, char *user);
|
||||
int restconf_authentication_cb(clicon_handle h, void *req, int pretty, restconf_media media_out);
|
||||
int restconf_config_init(clicon_handle h, cxobj *xrestconf);
|
||||
|
||||
#endif /* _RESTCONF_LIB_H_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -83,19 +83,22 @@
|
|||
#include "restconf_err.h"
|
||||
#include "restconf_root.h"
|
||||
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:ro:"
|
||||
|
||||
/* See see listen(5) */
|
||||
#define SOCKET_LISTEN_BACKLOG 16
|
||||
|
||||
/* clixon evhtp handle */
|
||||
/* Clixon evhtp handle
|
||||
* Global data about evhtp lib,
|
||||
* See evhtp_request_t *req for per-message state data
|
||||
*/
|
||||
typedef struct {
|
||||
evhtp_t **eh_htpvec; /* One per socket */
|
||||
int eh_htplen; /* Number of sockets */
|
||||
struct event_base *eh_evbase; /* Change to list */
|
||||
evhtp_ssl_cfg_t *eh_ssl_config;
|
||||
clicon_handle eh_h;
|
||||
evhtp_t **eh_htpvec; /* One per socket */
|
||||
int eh_htplen; /* Number of sockets */
|
||||
struct event_base *eh_evbase; /* Change to list */
|
||||
evhtp_ssl_cfg_t *eh_ssl_config;
|
||||
} cx_evhtp_handle;
|
||||
|
||||
/* Need this global to pass to signal handler
|
||||
|
|
@ -150,7 +153,7 @@ restconf_sig_term(int arg)
|
|||
exit(-1);
|
||||
if (_EVHTP_HANDLE) /* global */
|
||||
evhtp_terminate(_EVHTP_HANDLE);
|
||||
if (_CLICON_HANDLE){
|
||||
if (_CLICON_HANDLE){ /* could be replaced by eh->eh_h */
|
||||
// stream_child_freeall(_CLICON_HANDLE);
|
||||
restconf_terminate(_CLICON_HANDLE);
|
||||
}
|
||||
|
|
@ -448,8 +451,9 @@ static void
|
|||
cx_path_wellknown(evhtp_request_t *req,
|
||||
void *arg)
|
||||
{
|
||||
clicon_handle h = arg;
|
||||
int ret;
|
||||
cx_evhtp_handle *eh = (cx_evhtp_handle*)arg;
|
||||
clicon_handle h = eh->eh_h;
|
||||
int ret;
|
||||
|
||||
clicon_debug(1, "------------");
|
||||
/* input debug */
|
||||
|
|
@ -479,15 +483,15 @@ static void
|
|||
cx_path_restconf(evhtp_request_t *req,
|
||||
void *arg)
|
||||
{
|
||||
clicon_handle h = arg;
|
||||
int ret;
|
||||
cvec *qvec = NULL;
|
||||
cx_evhtp_handle *eh = (cx_evhtp_handle*)arg;
|
||||
clicon_handle h = eh->eh_h;
|
||||
int ret;
|
||||
cvec *qvec = NULL;
|
||||
|
||||
clicon_debug(1, "------------");
|
||||
/* input debug */
|
||||
if (clicon_debug_get())
|
||||
evhtp_headers_for_each(req->headers_in, print_header, h);
|
||||
|
||||
|
||||
/* get accepted connection */
|
||||
/* Query vector, ie the ?a=x&b=y stuff */
|
||||
|
|
@ -844,8 +848,7 @@ cx_evhtp_socket(clicon_handle h,
|
|||
cvec *nsc,
|
||||
char *server_cert_path,
|
||||
char *server_key_path,
|
||||
char *server_ca_cert_path,
|
||||
int auth_type_client_certificate)
|
||||
char *server_ca_cert_path)
|
||||
{
|
||||
int retval = -1;
|
||||
char *netns = NULL;
|
||||
|
|
@ -862,7 +865,6 @@ cx_evhtp_socket(clicon_handle h,
|
|||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifndef EVHTP_DISABLE_EVTHR /* threads */
|
||||
evhtp_use_threads_wexit(htp, NULL, NULL, 4, NULL);
|
||||
#endif
|
||||
|
|
@ -871,12 +873,12 @@ cx_evhtp_socket(clicon_handle h,
|
|||
/* Callback right after a connection is accepted. */
|
||||
evhtp_set_post_accept_cb(htp, cx_post_accept, h);
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, "/" RESTCONF_API, cx_path_restconf, h) == NULL){
|
||||
if (evhtp_set_cb(htp, "/" RESTCONF_API, cx_path_restconf, eh) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, h) == NULL){
|
||||
if (evhtp_set_cb(htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, eh) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -933,41 +935,41 @@ cx_evhtp_init(clicon_handle h,
|
|||
cvec *nsc,
|
||||
cx_evhtp_handle *eh)
|
||||
{
|
||||
int retval = -1;
|
||||
char* enable;
|
||||
int ssl_enable = 0;
|
||||
cxobj **vec = NULL;
|
||||
size_t veclen;
|
||||
char *server_cert_path = NULL;
|
||||
char *server_key_path = NULL;
|
||||
char *server_ca_cert_path = NULL;
|
||||
char *auth_type = NULL;
|
||||
int auth_type_client_certificate = 0;
|
||||
cxobj *x;
|
||||
int i;
|
||||
int retval = -1;
|
||||
int ssl_enable = 0;
|
||||
int dbg = 0;
|
||||
cxobj **vec = NULL;
|
||||
size_t veclen;
|
||||
char *server_cert_path = NULL;
|
||||
char *server_key_path = NULL;
|
||||
char *server_ca_cert_path = NULL;
|
||||
cxobj *x;
|
||||
char *bstr;
|
||||
int i;
|
||||
int ret;
|
||||
clixon_auth_type_t auth_type;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if ((x = xpath_first(xrestconf, nsc, "enable")) != NULL &&
|
||||
(enable = xml_body(x)) != NULL){
|
||||
if (strcmp(enable, "false") == 0){
|
||||
clicon_debug(1, "%s restconf disabled", __FUNCTION__);
|
||||
goto disable;
|
||||
}
|
||||
}
|
||||
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto disable;
|
||||
auth_type = restconf_auth_type_get(h);
|
||||
/* If at least one socket has ssl then enable global ssl_enable */
|
||||
ssl_enable = xpath_first(xrestconf, nsc, "socket[ssl='true']") != NULL;
|
||||
/* get common fields */
|
||||
if ((x = xpath_first(xrestconf, nsc, "auth-type")) != NULL)
|
||||
auth_type = xml_body(x);
|
||||
if (auth_type && strcmp(auth_type, "client-certificate") == 0)
|
||||
auth_type_client_certificate = 1;
|
||||
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-cert-path")) != NULL)
|
||||
server_cert_path = xml_body(x);
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-key-path")) != NULL)
|
||||
server_key_path = xml_body(x);
|
||||
if ((x = xpath_first(xrestconf, nsc, "server-ca-cert-path")) != NULL)
|
||||
server_ca_cert_path = xml_body(x);
|
||||
|
||||
if ((x = xpath_first(xrestconf, nsc, "debug")) != NULL &&
|
||||
(bstr = xml_body(x)) != NULL){
|
||||
dbg = atoi(bstr);
|
||||
clicon_debug_init(dbg, NULL);
|
||||
}
|
||||
|
||||
/* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */
|
||||
if (ssl_enable){
|
||||
/* Init evhtp ssl config struct */
|
||||
|
|
@ -982,11 +984,11 @@ cx_evhtp_init(clicon_handle h,
|
|||
if (cx_get_ssl_server_certs(h, server_cert_path, server_key_path, eh->eh_ssl_config) < 0)
|
||||
goto done;
|
||||
/* If client auth get client CA cert */
|
||||
if (auth_type_client_certificate)
|
||||
if (auth_type == CLIXON_AUTH_CLIENT_CERTIFICATE)
|
||||
if (cx_get_ssl_client_ca_certs(h, server_ca_cert_path, eh->eh_ssl_config) < 0)
|
||||
goto done;
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
if (auth_type_client_certificate){
|
||||
if (auth_type == CLIXON_AUTH_CLIENT_CERTIFICATE){
|
||||
eh->eh_ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
eh->eh_ssl_config->verify_depth = 2;
|
||||
|
|
@ -998,8 +1000,7 @@ cx_evhtp_init(clicon_handle h,
|
|||
goto done;
|
||||
for (i=0; i<veclen; i++){
|
||||
if (cx_evhtp_socket(h, eh, ssl_enable, vec[i], nsc,
|
||||
server_cert_path, server_key_path, server_ca_cert_path,
|
||||
auth_type_client_certificate) < 0)
|
||||
server_cert_path, server_key_path, server_ca_cert_path) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 1;
|
||||
|
|
@ -1318,16 +1319,24 @@ main(int argc,
|
|||
|
||||
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||
clicon_argv_set(h, argv0, argc, argv);
|
||||
|
||||
/* Init restconf auth-type */
|
||||
restconf_auth_type_set(h, CLIXON_AUTH_NONE);
|
||||
|
||||
/* Dump configuration options on debug */
|
||||
/* Dump configuration options on debug */
|
||||
if (dbg)
|
||||
clicon_option_dump(h, dbg);
|
||||
|
||||
/* Call start function in all plugins before we go interactive */
|
||||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
if ((eh = malloc(sizeof *eh)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(eh, 0, sizeof *eh);
|
||||
eh->eh_h = h;
|
||||
_EVHTP_HANDLE = eh; /* global */
|
||||
|
||||
/* Read config */
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ usage(clicon_handle h,
|
|||
"\t-d <dir>\t Specify restconf plugin directory dir (default: %s)\n"
|
||||
"\t-y <file>\t Load yang spec file (override yang main module)\n"
|
||||
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
|
||||
|
||||
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
||||
"\t-r \t\t Do not drop privileges if run as root\n"
|
||||
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n",
|
||||
|
|
@ -215,7 +216,10 @@ main(int argc,
|
|||
size_t cligen_buflen;
|
||||
size_t cligen_bufthreshold;
|
||||
int dbg = 0;
|
||||
int drop_priveleges = 1;
|
||||
int drop_privileges = 1;
|
||||
cxobj *xconfig = NULL;
|
||||
cxobj *xrestconf = NULL;
|
||||
int ret;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -311,7 +315,7 @@ main(int argc,
|
|||
clicon_option_str_set(h, "CLICON_SOCK", optarg);
|
||||
break;
|
||||
case 'r':{ /* Do not drop privileges if run as root */
|
||||
drop_priveleges = 0;
|
||||
drop_privileges = 0;
|
||||
break;
|
||||
}
|
||||
case 'o':{ /* Configuration option */
|
||||
|
|
@ -332,7 +336,10 @@ main(int argc,
|
|||
|
||||
/* Access the remaining argv/argc options (after --) w clicon-argv_get() */
|
||||
clicon_argv_set(h, argv0, argc, argv);
|
||||
|
||||
|
||||
/* Init restconf auth-type */
|
||||
restconf_auth_type_set(h, CLIXON_AUTH_NONE);
|
||||
|
||||
/* Init cligen buffers */
|
||||
cligen_buflen = clicon_option_int(h, "CLICON_CLI_BUF_START");
|
||||
cligen_bufthreshold = clicon_option_int(h, "CLICON_CLI_BUF_THRESHOLD");
|
||||
|
|
@ -418,11 +425,18 @@ main(int argc,
|
|||
if (dbg)
|
||||
clicon_option_dump(h, dbg);
|
||||
|
||||
/* Call start function in all plugins before we go interactive
|
||||
*/
|
||||
/* Call start function in all plugins before we go interactive */
|
||||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
xconfig = clicon_conf_xml(h); /* Get local config */
|
||||
if ((xrestconf = xpath_first(xconfig, NULL, "restconf")) != NULL){
|
||||
if ((ret = restconf_config_init(h, xrestconf)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
clicon_err(OE_DAEMON, EFAULT, "Restconf daemon disabled in config");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if ((sockpath = clicon_option_str(h, "CLICON_RESTCONF_PATH")) == NULL){
|
||||
clicon_err(OE_CFG, errno, "No CLICON_RESTCONF_PATH in clixon configure file");
|
||||
goto done;
|
||||
|
|
@ -454,7 +468,7 @@ main(int argc,
|
|||
clicon_err(OE_UNIX, errno, "chmod");
|
||||
goto done;
|
||||
}
|
||||
if (drop_priveleges){
|
||||
if (drop_privileges){
|
||||
/* Drop privileges to WWWUSER if started as root */
|
||||
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -374,15 +374,15 @@ api_operations(clicon_handle h,
|
|||
}
|
||||
|
||||
/*! Process a /restconf root input, this is the root of the restconf processing
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Generic Www handle (can be part of clixon handle)
|
||||
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] req Generic Www handle (can be part of clixon handle)
|
||||
* @param[in] qvec Query parameters, ie the ?<id>=<val>&<id>=<val> stuff
|
||||
* @see api_root_restconf_exact for accessing /restconf/ exact
|
||||
*/
|
||||
int
|
||||
api_root_restconf(clicon_handle h,
|
||||
void *req,
|
||||
cvec *qvec)
|
||||
api_root_restconf(clicon_handle h,
|
||||
void *req,
|
||||
cvec *qvec)
|
||||
{
|
||||
int retval = -1;
|
||||
char *request_method = NULL; /* GET,.. */
|
||||
|
|
@ -396,9 +396,8 @@ api_root_restconf(clicon_handle h,
|
|||
char *media_str = NULL;
|
||||
restconf_media media_out = YANG_DATA_JSON;
|
||||
char *indata = NULL;
|
||||
int authenticated = 0;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
char *username = NULL;
|
||||
int ret;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (req == NULL){
|
||||
|
|
@ -426,7 +425,6 @@ api_root_restconf(clicon_handle h,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
clicon_debug(1, "%s ACCEPT: %s %s", __FUNCTION__, media_str, restconf_media_int2str(media_out));
|
||||
|
||||
if ((pvec = clicon_strsep(path, "/", &pn)) == NULL)
|
||||
|
|
@ -464,26 +462,10 @@ api_root_restconf(clicon_handle h,
|
|||
/* If present, check credentials. See "plugin_credentials" in plugin
|
||||
* See RFC 8040 section 2.5
|
||||
*/
|
||||
if ((authenticated = clixon_plugin_auth_all(h, req)) < 0)
|
||||
if ((ret = restconf_authentication_cb(h, req, pretty, media_out)) < 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s auth:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
|
||||
/* If set but no user, set a dummy user */
|
||||
if (authenticated){
|
||||
if (clicon_username_get(h) == NULL)
|
||||
clicon_username_set(h, "none");
|
||||
}
|
||||
else{
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (ret == 0)
|
||||
goto ok;
|
||||
}
|
||||
clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
if (strcmp(api_resource, "yang-library-version")==0){
|
||||
if (api_yang_library_version(h, req, pretty, media_out) < 0)
|
||||
goto done;
|
||||
|
|
@ -538,14 +520,14 @@ api_root_restconf(clicon_handle h,
|
|||
retval = 0;
|
||||
done:
|
||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||
if (username)
|
||||
free(username);
|
||||
if (pcvec)
|
||||
cvec_free(pcvec);
|
||||
if (pvec)
|
||||
free(pvec);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,13 +382,11 @@ api_stream(clicon_handle h,
|
|||
cvec *pcvec = NULL; /* for rest api */
|
||||
cbuf *cb = NULL;
|
||||
char *indata;
|
||||
int authenticated = 0;
|
||||
int pretty;
|
||||
restconf_media media_out = YANG_DATA_XML; /* XXX default */
|
||||
cbuf *cbret = NULL;
|
||||
cxobj *xret = NULL;
|
||||
cxobj *xerr;
|
||||
int s = -1;
|
||||
int ret;
|
||||
#ifdef STREAM_FORK
|
||||
int pid;
|
||||
struct stream_child *sc;
|
||||
|
|
@ -430,26 +428,10 @@ api_stream(clicon_handle h,
|
|||
/* If present, check credentials. See "plugin_credentials" in plugin
|
||||
* See RFC 8040 section 2.5
|
||||
*/
|
||||
if ((authenticated = clixon_plugin_auth_all(h, req)) < 0)
|
||||
if ((ret = restconf_authentication_cb(h, req, pretty, media_out)) < 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s auth:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
|
||||
/* If set but no user, we set a dummy user */
|
||||
if (authenticated){
|
||||
if (clicon_username_get(h) == NULL)
|
||||
clicon_username_set(h, "none");
|
||||
}
|
||||
else{
|
||||
if (netconf_access_denied_xml(&xret, "protocol", "The requested URL was unauthorized") < 0)
|
||||
goto done;
|
||||
if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){
|
||||
if (api_return_err(h, req, xerr, pretty, media_out, 0) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
if (ret == 0)
|
||||
goto ok;
|
||||
}
|
||||
clicon_debug(1, "%s auth2:%d %s", __FUNCTION__, authenticated, clicon_username_get(h));
|
||||
if (restconf_stream(h, req, method, qvec, pretty, media_out, &s) < 0)
|
||||
goto done;
|
||||
if (s != -1){
|
||||
|
|
@ -465,8 +447,6 @@ api_stream(clicon_handle h,
|
|||
cbuf_free(cb);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
#endif /* STREAM_FORK */
|
||||
/* Listen to backend socket */
|
||||
if (clixon_event_reg_fd(s,
|
||||
|
|
@ -523,7 +503,5 @@ api_stream(clicon_handle h,
|
|||
cbuf_free(cb);
|
||||
if (cbret)
|
||||
cbuf_free(cbret);
|
||||
if (xret)
|
||||
xml_free(xret);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue