gam-resource-manager: adjust to updated proxied call callback signature.
[profile/ivi/murphy.git] / src / core / auth.c
1 /*
2  * Copyright (c) 2012, 2013, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *   * Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *   * Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *   * Neither the name of Intel Corporation nor the names of its contributors
14  *     may be used to endorse or promote products derived from this software
15  *     without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <errno.h>
31
32 #include <murphy/common/macros.h>
33 #include <murphy/common/mm.h>
34 #include <murphy/common/log.h>
35
36 #include <murphy/core/context.h>
37 #include <murphy/core/auth.h>
38
39
40 typedef struct {
41     char            *name;               /* backend name */
42     mrp_auth_cb_t    cb;                 /* backend method */
43     void            *auth_data;          /* backend data */
44     mrp_list_hook_t  hook;               /* to list of backends */
45 } auth_backend_t;
46
47
48 static MRP_LIST_HOOK(pending);
49
50
51 static auth_backend_t *find_auth(mrp_list_hook_t *backends, const char *name)
52 {
53     mrp_list_hook_t *p, *n;
54     auth_backend_t  *auth;
55
56     mrp_list_foreach(backends, p, n) {
57         auth = mrp_list_entry(p, typeof(*auth), hook);
58
59         if (!strcmp(auth->name, name))
60             return auth;
61     }
62
63     return NULL;
64 }
65
66
67 static int register_auth(mrp_list_hook_t *backends, const char *name,
68                          mrp_auth_cb_t cb, void *auth_data)
69 {
70     auth_backend_t *auth;
71
72     if (find_auth(backends, name) != NULL)
73         return FALSE;
74
75     auth = mrp_allocz(sizeof(*auth));
76
77     if (auth != NULL) {
78         mrp_list_init(&auth->hook);
79
80         auth->name      = mrp_strdup(name);
81         auth->cb        = cb;
82         auth->auth_data = auth_data;
83
84         if (auth->name != NULL) {
85             /*
86              * Notes:
87              *     Prepending here is a crude hack to make sure the first
88              *     registered backend, which is 'deny', ends up being the
89              *     last in the list of authenticators. Maybe we should add
90              *     a priority to the backend registration interface and
91              *     use it to make this more explicit...
92              */
93
94             mrp_list_prepend(backends, &auth->hook);
95
96             mrp_debug("registered authentication backend %s", auth->name);
97
98             return TRUE;
99         }
100
101         mrp_free(auth);
102     }
103
104     return FALSE;
105 }
106
107
108 static void unregister_auth(mrp_list_hook_t *backends, const char *name)
109 {
110     auth_backend_t *auth;
111
112     auth = find_auth(backends, name);
113
114     if (auth != NULL) {
115         mrp_list_delete(&auth->hook);
116         mrp_free(auth->name);
117         mrp_free(auth);
118     }
119 }
120
121
122 int mrp_register_authenticator(mrp_context_t *ctx, const char *name,
123                                mrp_auth_cb_t cb, void *auth_data)
124 {
125     mrp_list_hook_t *backends;
126
127     if (ctx != NULL) {
128         if (MRP_UNLIKELY(!mrp_list_empty(&pending)))
129             mrp_list_move(&ctx->auth, &pending);
130
131         backends = &ctx->auth;
132     }
133     else
134         backends = &pending;
135
136     if (register_auth(backends, name, cb, auth_data) == 0)
137         return TRUE;
138     else
139         return FALSE;
140 }
141
142
143 void mrp_unregister_authenticator(mrp_context_t *ctx, const char *name)
144 {
145     mrp_list_hook_t *backends = ctx ? &ctx->auth : &pending;
146
147     unregister_auth(backends, name);
148 }
149
150
151 int mrp_authenticate(mrp_context_t *ctx, const char *backend,
152                      const char *target, mrp_auth_mode_t mode,
153                      const char *id, const char *token)
154 {
155     auth_backend_t  *auth;
156     mrp_list_hook_t *p, *n;
157     int              status, result;
158
159     if (MRP_UNLIKELY(!mrp_list_empty(&pending)))
160         mrp_list_move(&ctx->auth, &pending);
161
162     /*
163      * Notes:
164      *
165      * Currently we let the caller request authentication by any available
166      * backend by using MRP_AUTH_ANY. If requested so, access is granted
167      * if any of the backends grants access.
168      *
169      * We might want to change this in the future, probably by either
170      * requiring the caller to always specify a valid authentication backend,
171      * or by having one of the backends be marked as default which then would
172      * be used for authentication in these cases. Either of those would make
173      * it more difficult to grant unwanted access accidentially in the case
174      * of multiple available backends.
175      */
176
177     result = MRP_AUTH_RESULT_ERROR;
178
179     mrp_list_foreach(&ctx->auth, p, n) {
180         auth = mrp_list_entry(p, typeof(*auth), hook);
181
182         if (backend == MRP_AUTH_ANY || !strcmp(backend, auth->name)) {
183             status = auth->cb(target, mode, id, token, auth->auth_data);
184
185             mrp_debug("backend %s, access 0x%x of %s/%s to %s: %d", auth->name,
186                       mode, id, token ? token : "<none>", target, status);
187
188             if (backend != MRP_AUTH_ANY)
189                 return status;
190
191             switch (status) {
192             case MRP_AUTH_RESULT_GRANT:
193                 return MRP_AUTH_RESULT_GRANT;
194             case MRP_AUTH_RESULT_DENY:
195                 result = MRP_AUTH_RESULT_DENY;
196                 break;
197             default:
198                 break;
199             }
200         }
201     }
202
203     return result;
204 }