Use afb_token in contexts
[src/app-framework-binder.git] / src / afb-auth.c
1 /*
2  * Copyright (C) 2016-2019 "IoT.bzh"
3  * Author "Fulup Ar Foll"
4  * Author José Bollo <jose.bollo@iot.bzh>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #define _GNU_SOURCE
20
21 #include <stdlib.h>
22
23 #include <json-c/json.h>
24 #include <afb/afb-auth.h>
25 #include <afb/afb-session-x2.h>
26
27 #include "afb-auth.h"
28 #include "afb-context.h"
29 #include "afb-xreq.h"
30 #include "afb-cred.h"
31 #include "verbose.h"
32
33 int afb_auth_check(struct afb_xreq *xreq, const struct afb_auth *auth)
34 {
35         switch (auth->type) {
36         default:
37         case afb_auth_No:
38                 return 0;
39
40         case afb_auth_Token:
41                 return afb_context_check(&xreq->context);
42
43         case afb_auth_LOA:
44                 return afb_context_check_loa(&xreq->context, auth->loa);
45
46         case afb_auth_Permission:
47                 return afb_auth_has_permission(xreq, auth->text);
48
49         case afb_auth_Or:
50                 return afb_auth_check(xreq, auth->first) || afb_auth_check(xreq, auth->next);
51
52         case afb_auth_And:
53                 return afb_auth_check(xreq, auth->first) && afb_auth_check(xreq, auth->next);
54
55         case afb_auth_Not:
56                 return !afb_auth_check(xreq, auth->first);
57
58         case afb_auth_Yes:
59                 return 1;
60         }
61 }
62
63 int afb_auth_has_permission(struct afb_xreq *xreq, const char *permission)
64 {
65         return afb_cred_has_permission(xreq->cred, permission, &xreq->context);
66 }
67
68 /*********************************************************************************/
69
70 static struct json_object *addperm(struct json_object *o, struct json_object *x)
71 {
72         struct json_object *a;
73
74         if (!o)
75                 return x;
76
77         if (!json_object_object_get_ex(o, "allOf", &a)) {
78                 a = json_object_new_array();
79                 json_object_array_add(a, o);
80                 o = json_object_new_object();
81                 json_object_object_add(o, "allOf", a);
82         }
83         json_object_array_add(a, x);
84         return o;
85 }
86
87 static struct json_object *addperm_key_val(struct json_object *o, const char *key, struct json_object *val)
88 {
89         struct json_object *x = json_object_new_object();
90         json_object_object_add(x, key, val);
91         return addperm(o, x);
92 }
93
94 static struct json_object *addperm_key_valstr(struct json_object *o, const char *key, const char *val)
95 {
96         return addperm_key_val(o, key, json_object_new_string(val));
97 }
98
99 static struct json_object *addperm_key_valint(struct json_object *o, const char *key, int val)
100 {
101         return addperm_key_val(o, key, json_object_new_int(val));
102 }
103
104 static struct json_object *addauth_or_array(struct json_object *o, const struct afb_auth *auth);
105
106 static struct json_object *addauth(struct json_object *o, const struct afb_auth *auth)
107 {
108         switch(auth->type) {
109         case afb_auth_No: return addperm(o, json_object_new_boolean(0));
110         case afb_auth_Token: return addperm_key_valstr(o, "session", "check");
111         case afb_auth_LOA: return addperm_key_valint(o, "LOA", auth->loa);
112         case afb_auth_Permission: return addperm_key_valstr(o, "permission", auth->text);
113         case afb_auth_Or: return addperm_key_val(o, "anyOf", addauth_or_array(json_object_new_array(), auth));
114         case afb_auth_And: return addauth(addauth(o, auth->first), auth->next);
115         case afb_auth_Not: return addperm_key_val(o, "not", addauth(NULL, auth->first));
116         case afb_auth_Yes: return addperm(o, json_object_new_boolean(1));
117         }
118         return o;
119 }
120
121 static struct json_object *addauth_or_array(struct json_object *o, const struct afb_auth *auth)
122 {
123         if (auth->type != afb_auth_Or)
124                 json_object_array_add(o, addauth(NULL, auth));
125         else {
126                 addauth_or_array(o, auth->first);
127                 addauth_or_array(o, auth->next);
128         }
129
130         return o;
131 }
132
133 struct json_object *afb_auth_json_v2(const struct afb_auth *auth, int session)
134 {
135         struct json_object *result = NULL;
136
137         if (session & AFB_SESSION_CLOSE_X2)
138                 result = addperm_key_valstr(result, "session", "close");
139
140         if (session & AFB_SESSION_CHECK_X2)
141                 result = addperm_key_valstr(result, "session", "check");
142
143         if (session & AFB_SESSION_REFRESH_X2)
144                 result = addperm_key_valstr(result, "token", "refresh");
145
146         if (session & AFB_SESSION_LOA_MASK_X2)
147                 result = addperm_key_valint(result, "LOA", session & AFB_SESSION_LOA_MASK_X2);
148
149         if (auth)
150                 result = addauth(result, auth);
151
152         return result;
153 }
154