afb-perm: separate access to permission db 65/23165/1
authorJosé Bollo <jose.bollo@iot.bzh>
Fri, 29 Nov 2019 17:41:59 +0000 (18:41 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Tue, 3 Dec 2019 17:51:51 +0000 (18:51 +0100)
Access to permission database is better handled
in a separate file. It will afterward evolve to
integrate cynagora.

Bug-AGL: SPEC-2968

Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Change-Id: Iebcd4e227e3e6c318029926499afb9d41d3f72c7

src/CMakeLists.txt
src/afb-context.c
src/afb-context.h
src/afb-cred.c
src/afb-cred.h
src/afb-perm.c [new file with mode: 0644]
src/afb-perm.h [new file with mode: 0644]

index d422f6b..cf978c9 100644 (file)
@@ -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
index 3d6dee0..7d2f367 100644 (file)
@@ -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));
index e3cf415..c5d5091 100644 (file)
@@ -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);
index b6e6feb..88c29c5 100644 (file)
@@ -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
-
index 4663940..9483ac3 100644 (file)
@@ -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 (file)
index 0000000..e3fab4b
--- /dev/null
@@ -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 (file)
index 0000000..4a4df84
--- /dev/null
@@ -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
+);