From 85bca06fe0ee2923421f013da3e9f53abbfff673 Mon Sep 17 00:00:00 2001 From: José Bollo Date: Mon, 4 Sep 2017 11:37:39 +0200 Subject: Implement afb_req_has_permission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new verb is available in bindings to check whether the client identified by a request has a given permission or not. Change-Id: I5eaa0892d8260d26bd76f37123251c103c981e10 Signed-off-by: José Bollo --- bindings/samples/HelloWorld.c | 10 +++++++++ docs/afb-binding-references.md | 14 ++++++++++++ include/afb/afb-req-common.h | 14 ++++++++++++ src/afb-auth.c | 6 ++--- src/afb-auth.h | 2 +- src/afb-hook.c | 14 +++++++++++- src/afb-hook.h | 51 ++++++++++++++++++++++-------------------- src/afb-xreq.c | 19 ++++++++++++++-- 8 files changed, 99 insertions(+), 31 deletions(-) diff --git a/bindings/samples/HelloWorld.c b/bindings/samples/HelloWorld.c index 002c4721..4125e77f 100644 --- a/bindings/samples/HelloWorld.c +++ b/bindings/samples/HelloWorld.c @@ -412,6 +412,15 @@ static void broadcast(afb_req request) json_object_put(object); } +static void hasperm (afb_req request) +{ + const char *perm = afb_req_value(request, "perm"); + if (afb_req_has_permission(request, perm)) + afb_req_success_f(request, NULL, "permission %s granted", perm?:"(null)"); + else + afb_req_fail_f(request, "not-granted", "permission %s NOT granted", perm?:"(null)"); +} + static int preinit() { AFB_NOTICE("hello binding comes to live"); @@ -450,6 +459,7 @@ static const afb_verb_v2 verbs[]= { { .verb="callsync", .callback=callsync }, { .verb="verbose", .callback=verbose }, { .verb="broadcast", .callback=broadcast }, + { .verb="hasperm", .callback=hasperm }, { .verb="exit", .callback=exitnow }, { .verb=NULL} }; diff --git a/docs/afb-binding-references.md b/docs/afb-binding-references.md index d0a9a6d0..e340d6b5 100644 --- a/docs/afb-binding-references.md +++ b/docs/afb-binding-references.md @@ -677,6 +677,20 @@ Instead, you should use the macros: void afb_req_verbose(struct afb_req req, int level, const char *file, int line, const char * func, const char *fmt, ...); ``` +The function below allows a binding to check whether a client +has a permission of not. + +```C + +/* + * Check whether the 'permission' is granted or not to the client + * identified by 'req'. + * + * Returns 1 if the permission is granted or 0 otherwise. + */ +int afb_req_has_permission(struct afb_req req, const char *permission); +``` + ## Logging macros The following macros must be used for logging: diff --git a/include/afb/afb-req-common.h b/include/afb/afb-req-common.h index d6d02583..8bb25f75 100644 --- a/include/afb/afb-req-common.h +++ b/include/afb/afb-req-common.h @@ -74,6 +74,8 @@ struct afb_req_itf void (*vverbose)(void *closure, int level, const char *file, int line, const char * func, const char *fmt, va_list args); struct afb_stored_req *(*store)(void *closure); void (*subcall_req)(void *closure, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*, struct afb_req), void *cb_closure); + + int (*has_permission)(void *closure, const char *permission); }; /* @@ -431,3 +433,15 @@ static inline void afb_req_verbose(struct afb_req req, int level, const char *fi #else #define AFB_REQ_VERBOSE(req,level,...) afb_req_verbose(req,level,NULL,0,NULL,__VA_ARGS__) #endif + +/* + * Check whether the 'permission' is granted or not to the client + * identified by 'req'. + * + * Returns 1 if the permission is granted or 0 otherwise. + */ +static inline int afb_req_has_permission(struct afb_req req, const char *permission) +{ + return req.itf->has_permission(req.closure, permission); +} + diff --git a/src/afb-auth.c b/src/afb-auth.c index ff4ff9da..9d54a03b 100644 --- a/src/afb-auth.c +++ b/src/afb-auth.c @@ -43,7 +43,7 @@ int afb_auth_check(struct afb_xreq *xreq, const struct afb_auth *auth) return afb_context_check_loa(&xreq->context, auth->loa); case afb_auth_Permission: - return afb_auth_check_permission(xreq, auth->text); + return afb_auth_has_permission(xreq, auth->text); case afb_auth_Or: return afb_auth_check(xreq, auth->first) || afb_auth_check(xreq, auth->next); @@ -68,7 +68,7 @@ int afb_auth_check(struct afb_xreq *xreq, const struct afb_auth *auth) static cynara *handle; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -int afb_auth_check_permission(struct afb_xreq *xreq, const char *permission) +int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission) { int rc; @@ -103,7 +103,7 @@ int afb_auth_check_permission(struct afb_xreq *xreq, const char *permission) /*********************************************************************************/ #else -int afb_auth_check_permission(struct afb_xreq *xreq, const char *permission) +int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission) { WARNING("Granting permission %s by default of backend", permission ?: "(null)"); return !!permission; diff --git a/src/afb-auth.h b/src/afb-auth.h index d388e777..db084037 100644 --- a/src/afb-auth.h +++ b/src/afb-auth.h @@ -21,5 +21,5 @@ struct afb_auth; struct afb_xreq; extern int afb_auth_check(struct afb_xreq *xreq, const struct afb_auth *auth); -extern int afb_auth_check_permission(struct afb_xreq *xreq, const char *permission); +extern int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission); diff --git a/src/afb-hook.c b/src/afb-hook.c index 14076281..a8c836f8 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -317,6 +317,11 @@ static void hook_xreq_subcall_req_result_default_cb(void *closure, const struct _hook_xreq_(xreq, " ...subcall_req... -> %d: %s", status, json_object_to_json_string(result)); } +static void hook_xreq_has_permission_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result) +{ + _hook_xreq_(xreq, "has_permission(%s) -> %d", permission, result); +} + static struct afb_hook_xreq_itf hook_xreq_default_itf = { .hook_xreq_begin = hook_xreq_begin_default_cb, .hook_xreq_end = hook_xreq_end_default_cb, @@ -340,7 +345,8 @@ static struct afb_hook_xreq_itf hook_xreq_default_itf = { .hook_xreq_store = hook_xreq_store_default_cb, .hook_xreq_unstore = hook_xreq_unstore_default_cb, .hook_xreq_subcall_req = hook_xreq_subcall_req_default_cb, - .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result_default_cb + .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result_default_cb, + .hook_xreq_has_permission = hook_xreq_has_permission_default_cb }; /****************************************************************************** @@ -488,6 +494,12 @@ void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int status, s _HOOK_XREQ_(subcall_req_result, xreq, status, result); } +int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result) +{ + _HOOK_XREQ_(has_permission, xreq, permission, result); + return result; +} + /****************************************************************************** * section: hooking xreqs *****************************************************************************/ diff --git a/src/afb-hook.h b/src/afb-hook.h index 43341242..235e19d9 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -52,29 +52,30 @@ struct afb_hookid *********************************************************/ /* individual flags */ -#define afb_hook_flag_req_begin 0x000001 -#define afb_hook_flag_req_end 0x000002 -#define afb_hook_flag_req_json 0x000004 -#define afb_hook_flag_req_get 0x000008 -#define afb_hook_flag_req_success 0x000010 -#define afb_hook_flag_req_fail 0x000020 -#define afb_hook_flag_req_context_get 0x000040 -#define afb_hook_flag_req_context_set 0x000080 -#define afb_hook_flag_req_addref 0x000100 -#define afb_hook_flag_req_unref 0x000200 -#define afb_hook_flag_req_session_close 0x000400 -#define afb_hook_flag_req_session_set_LOA 0x000800 -#define afb_hook_flag_req_subscribe 0x001000 -#define afb_hook_flag_req_unsubscribe 0x002000 -#define afb_hook_flag_req_subcall 0x004000 -#define afb_hook_flag_req_subcall_result 0x008000 -#define afb_hook_flag_req_subcallsync 0x010000 -#define afb_hook_flag_req_subcallsync_result 0x020000 -#define afb_hook_flag_req_vverbose 0x040000 -#define afb_hook_flag_req_store 0x080000 -#define afb_hook_flag_req_unstore 0x100000 -#define afb_hook_flag_req_subcall_req 0x200000 -#define afb_hook_flag_req_subcall_req_result 0x400000 +#define afb_hook_flag_req_begin 0x00000001 +#define afb_hook_flag_req_end 0x00000002 +#define afb_hook_flag_req_json 0x00000004 +#define afb_hook_flag_req_get 0x00000008 +#define afb_hook_flag_req_success 0x00000010 +#define afb_hook_flag_req_fail 0x00000020 +#define afb_hook_flag_req_context_get 0x00000040 +#define afb_hook_flag_req_context_set 0x00000080 +#define afb_hook_flag_req_addref 0x00000100 +#define afb_hook_flag_req_unref 0x00000200 +#define afb_hook_flag_req_session_close 0x00000400 +#define afb_hook_flag_req_session_set_LOA 0x00000800 +#define afb_hook_flag_req_subscribe 0x00001000 +#define afb_hook_flag_req_unsubscribe 0x00002000 +#define afb_hook_flag_req_subcall 0x00004000 +#define afb_hook_flag_req_subcall_result 0x00008000 +#define afb_hook_flag_req_subcallsync 0x00010000 +#define afb_hook_flag_req_subcallsync_result 0x00020000 +#define afb_hook_flag_req_vverbose 0x00040000 +#define afb_hook_flag_req_store 0x00080000 +#define afb_hook_flag_req_unstore 0x00100000 +#define afb_hook_flag_req_subcall_req 0x00200000 +#define afb_hook_flag_req_subcall_req_result 0x00400000 +#define afb_hook_flag_req_has_permission 0x00800000 /* common flags */ #define afb_hook_flags_req_life (afb_hook_flag_req_begin|afb_hook_flag_req_end) @@ -94,7 +95,7 @@ struct afb_hookid /* predefined groups */ #define afb_hook_flags_req_common (afb_hook_flags_req_life|afb_hook_flags_req_args|afb_hook_flags_req_result\ |afb_hook_flags_req_session|afb_hook_flags_req_event|afb_hook_flags_req_subcalls\ - |afb_hook_flag_req_vverbose) + |afb_hook_flag_req_vverbose|afb_hook_flag_req_has_permission) #define afb_hook_flags_req_extra (afb_hook_flags_req_common|afb_hook_flags_req_ref|afb_hook_flags_req_context\ |afb_hook_flags_req_stores) #define afb_hook_flags_req_all (afb_hook_flags_req_extra) @@ -123,6 +124,7 @@ struct afb_hook_xreq_itf { void (*hook_xreq_unstore)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq); void (*hook_xreq_subcall_req)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args); void (*hook_xreq_subcall_req_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result); + void (*hook_xreq_has_permission)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result); }; extern void afb_hook_init_xreq(struct afb_xreq *xreq); @@ -155,6 +157,7 @@ extern void afb_hook_xreq_store(const struct afb_xreq *xreq, struct afb_stored_r extern void afb_hook_xreq_unstore(const struct afb_xreq *xreq); extern void afb_hook_xreq_subcall_req(const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args); extern void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int status, struct json_object *result); +extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result); /********************************************************* * section hooking ditf (daemon interface) diff --git a/src/afb-xreq.c b/src/afb-xreq.c index 8c7a38d5..3535ce5c 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -448,6 +448,12 @@ static struct afb_stored_req *xreq_store_cb(void *closure) return closure; } +static int xreq_has_permission_cb(void*closure, const char *permission) +{ + struct afb_xreq *xreq = closure; + return afb_auth_has_permission(xreq, permission); +} + /******************************************************************************/ static struct json_object *xreq_hooked_json_cb(void *closure) @@ -627,6 +633,13 @@ static struct afb_stored_req *xreq_hooked_store_cb(void *closure) return r; } +static int xreq_hooked_has_permission_cb(void*closure, const char *permission) +{ + struct afb_xreq *xreq = closure; + int r = xreq_has_permission_cb(closure, permission); + return afb_hook_xreq_has_permission(xreq, permission, r); +} + /******************************************************************************/ const struct afb_req_itf xreq_itf = { @@ -648,7 +661,8 @@ const struct afb_req_itf xreq_itf = { .subcallsync = xreq_subcallsync_cb, .vverbose = xreq_vverbose_cb, .store = xreq_store_cb, - .subcall_req = xreq_subcall_req_cb + .subcall_req = xreq_subcall_req_cb, + .has_permission = xreq_has_permission_cb }; const struct afb_req_itf xreq_hooked_itf = { @@ -670,7 +684,8 @@ const struct afb_req_itf xreq_hooked_itf = { .subcallsync = xreq_hooked_subcallsync_cb, .vverbose = xreq_hooked_vverbose_cb, .store = xreq_hooked_store_cb, - .subcall_req = xreq_hooked_subcall_req_cb + .subcall_req = xreq_hooked_subcall_req_cb, + .has_permission = xreq_hooked_has_permission_cb }; /******************************************************************************/ -- cgit 1.2.3-korg