diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/afb-context.c | 71 | ||||
-rw-r--r-- | src/afb-context.h | 15 | ||||
-rw-r--r-- | src/afb-cred.c | 60 | ||||
-rw-r--r-- | src/afb-cred.h | 2 | ||||
-rw-r--r-- | src/afb-perm.c | 93 | ||||
-rw-r--r-- | src/afb-perm.h | 31 |
7 files changed, 206 insertions, 67 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d422f6b9..cf978c95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,6 +100,7 @@ SET(AFB_LIB_SOURCES afb-method.c afb-monitor.c afb-msg-json.c + afb-perm.c afb-permission-text.c afb-proto-ws.c afb-session.c diff --git a/src/afb-context.c b/src/afb-context.c index 3d6dee06..7d2f3678 100644 --- a/src/afb-context.c +++ b/src/afb-context.c @@ -27,6 +27,7 @@ #include "afb-context.h" #include "afb-token.h" #include "afb-cred.h" +#include "afb-perm.h" #include "afb-permission-text.h" #include "verbose.h" @@ -160,7 +161,17 @@ void afb_context_on_behalf_other_context(struct afb_context *context, struct afb int afb_context_has_permission(struct afb_context *context, const char *permission) { - return afb_cred_has_permission(context->credentials, permission, context); + return afb_perm_check(context, permission); +} + +void afb_context_has_permission_async( + struct afb_context *context, + const char *permission, + void (*callback)(void *_closure, int _status), + void *closure +) +{ + return afb_perm_check_async(context, permission, callback, closure); } const char *afb_context_uuid(struct afb_context *context) @@ -191,9 +202,34 @@ void afb_context_close(struct afb_context *context) context->closing = 1; } -int afb_context_check(struct afb_context *context) +struct chkctx { + struct afb_context *context; + void (*callback)(void *_closure, int _status); + void *closure; +}; + +static void check_context_cb(void *closure_chkctx, int status) { + struct chkctx *cc = closure_chkctx; + struct afb_context *context = cc->context; + void (*callback)(void*,int) = cc->callback; + void *closure = cc->closure; + + free(cc); + if (status) + context->validated = 1; + else + context->invalidated = 1; + callback(closure, status); +} + +static int check_context( + struct afb_context *context, + void (*callback)(void *_closure, int _status), + void *closure +) { int r; + struct chkctx *cc; if (context->validated) r = 1; @@ -201,9 +237,21 @@ int afb_context_check(struct afb_context *context) r = 0; else { if (context->super) - r = afb_context_check(context->super); - else + r = check_context(context->super, callback, closure); + else if (!callback) r = afb_context_has_permission(context, afb_permission_token_valid); + else { + cc = malloc(sizeof *cc); + if (cc) { + cc->context = context; + cc->callback = callback; + cc->closure = closure; + afb_context_has_permission_async(context, afb_permission_token_valid, check_context_cb, cc); + return -1; + } + ERROR("out-of-memory"); + r = 0; + } if (r) context->validated = 1; else @@ -212,6 +260,21 @@ int afb_context_check(struct afb_context *context) return r; } +int afb_context_check(struct afb_context *context) +{ + return check_context(context, 0, 0); +} + +void afb_context_check_async( + struct afb_context *context, + void (*callback)(void *_closure, int _status), + void *closure +) { + int r = check_context(context, callback, closure); + if (r >= 0) + callback(closure, r); +} + static inline const void *loa_key(struct afb_context *context) { return (const void*)(1+(intptr_t)(context->api_key)); diff --git a/src/afb-context.h b/src/afb-context.h index e3cf4151..c5d50914 100644 --- a/src/afb-context.h +++ b/src/afb-context.h @@ -59,10 +59,23 @@ extern void afb_context_change_cred(struct afb_context *context, struct afb_cred extern int afb_context_on_behalf_import(struct afb_context *context, const char *exported); extern const char *afb_context_on_behalf_export(struct afb_context *context); extern void afb_context_on_behalf_other_context(struct afb_context *context, struct afb_context *other); + extern int afb_context_has_permission(struct afb_context *context, const char *permission); +extern void afb_context_has_permission_async( + struct afb_context *context, + const char *permission, + void (*callback)(void *_closure, int _status), + void *closure +); -extern void afb_context_close(struct afb_context *context); extern int afb_context_check(struct afb_context *context); +extern void afb_context_check_async( + struct afb_context *context, + void (*callback)(void *_closure, int _status), + void *closure +); + +extern void afb_context_close(struct afb_context *context); extern int afb_context_check_loa(struct afb_context *context, unsigned loa); extern int afb_context_change_loa(struct afb_context *context, unsigned loa); extern unsigned afb_context_get_loa(struct afb_context *context); diff --git a/src/afb-cred.c b/src/afb-cred.c index b6e6feba..88c29c5e 100644 --- a/src/afb-cred.c +++ b/src/afb-cred.c @@ -28,8 +28,6 @@ #include <sys/socket.h> #include "afb-cred.h" -#include "afb-context.h" -#include "afb-token.h" #include "verbose.h" #define MAX_LABEL_LENGTH 1024 @@ -219,61 +217,3 @@ struct afb_cred *afb_cred_import(const char *string) } return cred; } - -/*********************************************************************************/ -static const char *token_of_context(struct afb_context *context) -{ - return context && context->token ? afb_token_string(context->token) : "X"; -} - -/*********************************************************************************/ -#ifdef BACKEND_PERMISSION_IS_CYNARA - -#include <pthread.h> -#include <cynara-client.h> - -static cynara *handle; -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -int afb_cred_has_permission(struct afb_cred *cred, const char *permission, struct afb_context *context) -{ - int rc; - - if (!cred) { - /* case of permission for self */ - return 1; - } - if (!permission) { - ERROR("Got a null permission!"); - return 0; - } - - /* cynara isn't reentrant */ - pthread_mutex_lock(&mutex); - - /* lazy initialisation */ - if (!handle) { - rc = cynara_initialize(&handle, NULL); - if (rc != CYNARA_API_SUCCESS) { - handle = NULL; - ERROR("cynara initialisation failed with code %d", rc); - return 0; - } - } - - /* query cynara permission */ - rc = cynara_check(handle, cred->label, token_of_context(context), cred->user, permission); - - pthread_mutex_unlock(&mutex); - return rc == CYNARA_API_ACCESS_ALLOWED; -} - -/*********************************************************************************/ -#else -int afb_cred_has_permission(struct afb_cred *cred, const char *permission, struct afb_context *context) -{ - WARNING("Granting permission %s by default of backend", permission ?: "(null)"); - return !!permission; -} -#endif - diff --git a/src/afb-cred.h b/src/afb-cred.h index 46639408..9483ac33 100644 --- a/src/afb-cred.h +++ b/src/afb-cred.h @@ -39,7 +39,5 @@ extern struct afb_cred *afb_cred_create_for_socket(int fd); extern struct afb_cred *afb_cred_addref(struct afb_cred *cred); extern void afb_cred_unref(struct afb_cred *cred); -extern int afb_cred_has_permission(struct afb_cred *cred, const char *permission, struct afb_context *context); - extern const char *afb_cred_export(struct afb_cred *cred); extern struct afb_cred *afb_cred_import(const char *string); diff --git a/src/afb-perm.c b/src/afb-perm.c new file mode 100644 index 00000000..e3fab4b6 --- /dev/null +++ b/src/afb-perm.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017-2019 "IoT.bzh" + * Author: José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> + +#include "afb-context.h" +#include "afb-cred.h" +#include "afb-token.h" +#include "afb-session.h" +#include "verbose.h" + +/*********************************************************************************/ + +static inline const char *session_of_context(struct afb_context *context) +{ + return context->token ? afb_token_string(context->token) + : context->session ? afb_session_uuid(context->session) + : ""; +} + +/*********************************************************************************/ +#ifdef BACKEND_PERMISSION_IS_CYNARA + +#include <pthread.h> +#include <cynara-client.h> + +static cynara *handle; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +int afb_perm_check(struct afb_context *context, const char *permission) +{ + int rc; + + if (!context->credentials) { + /* case of permission for self */ + return 1; + } + if (!permission) { + ERROR("Got a null permission!"); + return 0; + } + + /* cynara isn't reentrant */ + pthread_mutex_lock(&mutex); + + /* lazy initialisation */ + if (!handle) { + rc = cynara_initialize(&handle, NULL); + if (rc != CYNARA_API_SUCCESS) { + handle = NULL; + ERROR("cynara initialisation failed with code %d", rc); + return 0; + } + } + + /* query cynara permission */ + rc = cynara_check(handle, context->credentials->label, session_of_context(context), context->credentials->user, permission); + + pthread_mutex_unlock(&mutex); + return rc == CYNARA_API_ACCESS_ALLOWED; +} +/*********************************************************************************/ +#else +int afb_perm_check(struct afb_context *context, const char *permission) +{ + NOTICE("Granting permission %s by default of backend", permission ?: "(null)"); + return !!permission; +} +#endif + +void afb_perm_check_async( + struct afb_context *context, + const char *permission, + void (*callback)(void *closure, int status), + void *closure +) +{ + callback(closure, afb_perm_check(context, permission)); +} diff --git a/src/afb-perm.h b/src/afb-perm.h new file mode 100644 index 00000000..4a4df84b --- /dev/null +++ b/src/afb-perm.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017-2019 "IoT.bzh" + * Author: José Bollo <jose.bollo@iot.bzh> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <sys/types.h> + +struct afb_context; + +extern int afb_perm_check(struct afb_context *context, const char *permission); + +extern void afb_perm_check_async( + struct afb_context *context, + const char *permission, + void (*callback)(void *closure, int status), + void *closure +); |