* Added a "user" parameter to plugin_credentials() restconf callback.
To enable authentication and in preparation for access control a la RFC 6536. * yang string length "max" keyword set to MAXPATHLEN
This commit is contained in:
parent
3ffe68d124
commit
e40d785d5c
12 changed files with 514 additions and 34 deletions
|
|
@ -238,12 +238,21 @@ yang2cli_var_sub(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
else{ /* Cligen does not have 'max' keyword in range so need to find actual
|
||||
max value of type if yang range expression is 0..max */
|
||||
if ((r = cvtype_max2str_dup(cvtype)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cvtype_max2str");
|
||||
goto done;
|
||||
max value of type if yang range expression is 0..max
|
||||
*/
|
||||
if (cvtype==CGV_STRING){
|
||||
if ((r = malloc(512)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
snprintf(r, 512, "%d", MAXPATHLEN);
|
||||
}
|
||||
else if ((r = cvtype_max2str_dup(cvtype)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cvtype_max2str");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
cprintf(cb, "%s]", r);
|
||||
free(r);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
* Returns an expand-type list of commands as used by cligen 'expand'
|
||||
* functionality.
|
||||
*
|
||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar("arg")
|
||||
* Assume callback given in a cligen spec: a <x:int expand_dbvar("db" "<xmlkeyfmt>")
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] name Name of this function (eg "expand_dbvar")
|
||||
* @param[in] cvv The command so far. Eg: cvec [0]:"a 5 b"; [1]: x=5;
|
||||
|
|
|
|||
|
|
@ -296,11 +296,10 @@ readdata(FCGX_Request *r)
|
|||
return cb;
|
||||
}
|
||||
|
||||
typedef int (credentials_t)(clicon_handle h, FCGX_Request *r);
|
||||
|
||||
static int nplugins = 0;
|
||||
static plghndl_t *plugins = NULL;
|
||||
static credentials_t *p_credentials = NULL; /* Credentials callback */
|
||||
static plgcredentials_t *_credentials_fn = NULL; /* Credentials callback */
|
||||
|
||||
/*! Load all plugins you can find in CLICON_RESTCONF_DIR
|
||||
*/
|
||||
|
|
@ -330,7 +329,7 @@ restconf_plugin_load(clicon_handle h)
|
|||
(int)strlen(filename), filename);
|
||||
if ((handle = plugin_load(h, filename, RTLD_NOW)) == NULL)
|
||||
goto quit;
|
||||
p_credentials = dlsym(handle, PLUGIN_CREDENTIALS);
|
||||
_credentials_fn = dlsym(handle, PLUGIN_CREDENTIALS);
|
||||
if ((plugins = realloc(plugins, (nplugins+1) * sizeof (*plugins))) == NULL) {
|
||||
clicon_err(OE_UNIX, errno, "realloc");
|
||||
goto quit;
|
||||
|
|
@ -385,23 +384,24 @@ restconf_plugin_start(clicon_handle h,
|
|||
}
|
||||
|
||||
int
|
||||
plugin_credentials(clicon_handle h,
|
||||
FCGX_Request *r,
|
||||
int *auth)
|
||||
restconf_credentials(clicon_handle h,
|
||||
FCGX_Request *r,
|
||||
char **user)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
/* If no authentication callback then allow anything. Is this OK? */
|
||||
if (p_credentials == 0){
|
||||
*auth = 1;
|
||||
if (_credentials_fn == NULL){
|
||||
if ((*user = strdup("none")) == NULL){
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
if (p_credentials(h, r) < 0)
|
||||
*auth = 0;
|
||||
else
|
||||
*auth = 1;
|
||||
if (_credentials_fn(h, r, user) < 0)
|
||||
user = NULL;
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ cbuf *readdata(FCGX_Request *r);
|
|||
int restconf_plugin_load(clicon_handle h);
|
||||
int restconf_plugin_start(clicon_handle h, int argc, char **argv);
|
||||
int restconf_plugin_unload(clicon_handle h);
|
||||
int plugin_credentials(clicon_handle h, FCGX_Request *r, int *auth);
|
||||
int restconf_credentials(clicon_handle h, FCGX_Request *r, char **user);
|
||||
int get_user_cookie(char *cookiestr, char *attribute, char **val);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ api_operations(clicon_handle h,
|
|||
cvec *pcvec,
|
||||
int pi,
|
||||
cvec *qvec,
|
||||
char *data)
|
||||
char *data,
|
||||
char *username)
|
||||
{
|
||||
int retval = -1;
|
||||
char *request_method;
|
||||
|
|
@ -153,7 +154,7 @@ api_operations(clicon_handle h,
|
|||
if (strcmp(request_method, "GET")==0)
|
||||
retval = api_operation_get(h, r, path, pcvec, pi, qvec, data);
|
||||
else if (strcmp(request_method, "POST")==0)
|
||||
retval = api_operation_post(h, r, path, pcvec, pi, qvec, data);
|
||||
retval = api_operation_post(h, r, path, pcvec, pi, qvec, data, username);
|
||||
else
|
||||
retval = notfound(r);
|
||||
return retval;
|
||||
|
|
@ -275,7 +276,7 @@ api_restconf(clicon_handle h,
|
|||
cvec *pcvec = NULL; /* for rest api */
|
||||
cbuf *cb = NULL;
|
||||
char *data;
|
||||
int auth = 0;
|
||||
char *username = NULL;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
path = FCGX_GetParam("REQUEST_URI", r->envp);
|
||||
|
|
@ -318,20 +319,21 @@ api_restconf(clicon_handle h,
|
|||
|
||||
retval = 0;
|
||||
test(r, 1);
|
||||
/* If present, check credentials */
|
||||
if (plugin_credentials(h, r, &auth) < 0)
|
||||
/* If present, check credentials. See "plugin_credentials" in plugin
|
||||
* See RFC 8040 section 2.5
|
||||
*/
|
||||
if (restconf_credentials(h, r, &username) < 0)
|
||||
goto done;
|
||||
clicon_debug(1, "%s credentials ok auth:%d (should be 1)",
|
||||
__FUNCTION__, auth);
|
||||
if (auth == 0)
|
||||
clicon_debug(1, "%s credentials ok username:%s (should be non-NULL)",
|
||||
__FUNCTION__, username);
|
||||
if (username == NULL)
|
||||
goto done;
|
||||
clicon_debug(1, "%s credentials ok 2", __FUNCTION__);
|
||||
if (strcmp(method, "yang-library-version")==0)
|
||||
retval = api_yang_library_version(h, r);
|
||||
else if (strcmp(method, "data") == 0) /* restconf, skip /api/data */
|
||||
retval = api_data(h, r, path, pcvec, 2, qvec, data);
|
||||
else if (strcmp(method, "operations") == 0) /* rpc */
|
||||
retval = api_operations(h, r, path, pcvec, 2, qvec, data);
|
||||
retval = api_operations(h, r, path, pcvec, 2, qvec, data, username);
|
||||
else if (strcmp(method, "test") == 0)
|
||||
retval = test(r, 0);
|
||||
else
|
||||
|
|
@ -348,6 +350,8 @@ api_restconf(clicon_handle h,
|
|||
cvec_free(pcvec);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (username)
|
||||
free(username);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -846,7 +846,8 @@ api_operation_post(clicon_handle h,
|
|||
cvec *pcvec,
|
||||
int pi,
|
||||
cvec *qvec,
|
||||
char *data)
|
||||
char *data,
|
||||
char *username)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
|
|
@ -869,7 +870,8 @@ api_operation_post(clicon_handle h,
|
|||
char *media_accept;
|
||||
int use_xml = 0; /* By default return JSON */
|
||||
int pretty;
|
||||
|
||||
cxobj *xa;
|
||||
|
||||
clicon_debug(1, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, path);
|
||||
pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY");
|
||||
if ((media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp)) &&
|
||||
|
|
@ -939,8 +941,17 @@ api_operation_post(clicon_handle h,
|
|||
}
|
||||
}
|
||||
}
|
||||
/* Non-standard: add cookie as attribute for backend
|
||||
/* 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;
|
||||
|
|
@ -957,6 +968,7 @@ api_operation_post(clicon_handle h,
|
|||
free(cookieval);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Send to backend */
|
||||
if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ int api_operation_get(clicon_handle h, FCGX_Request *r,
|
|||
|
||||
int api_operation_post(clicon_handle h, FCGX_Request *r,
|
||||
char *path,
|
||||
cvec *pcvec, int pi, cvec *qvec, char *data);
|
||||
cvec *pcvec, int pi, cvec *qvec, char *data,
|
||||
char *username);
|
||||
|
||||
#endif /* _RESTCONF_METHODS_H_ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue