Clarify license declaration
[platform/upstream/dbus.git] / bus / check.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* check.c  Bus security policy runtime check
3  *
4  * Copyright (C) 2014  Intel, Inc.
5  * Copyright (c) 2014  Samsung Electronics, Ltd.
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include "check.h"
27 #include "connection.h"
28 #include "dispatch.h"
29 #include "cynara.h"
30 #include "utils.h"
31 #include <dbus/dbus-connection-internal.h>
32 #include <dbus/dbus-message-internal.h>
33 #include <dbus/dbus-internals.h>
34
35
36 typedef struct BusCheck
37 {
38   int refcount;
39
40   BusContext *context;
41   BusCynara *cynara;
42 } BusCheck;
43
44 typedef struct BusDeferredMessage
45 {
46   int refcount;
47
48   DBusMessage *message;
49   DBusConnection *sender;
50   DBusConnection *proposed_recipient;
51   DBusConnection *addressed_recipient;
52   dbus_bool_t requested_reply;
53   int matched_rules;
54   const char *privilege;
55   dbus_bool_t full_dispatch;
56   BusDeferredMessageStatus status;
57   BusResult response;
58   BusCheckResponseFunc response_callback;
59 } BusDeferredMessage;
60
61 static dbus_int32_t deferred_message_data_slot = -1;
62
63 BusCheck *
64 bus_check_new (BusContext *context, DBusError *error)
65 {
66   BusCheck *check;
67
68   check = dbus_new(BusCheck, 1);
69   if (check == NULL)
70     {
71       BUS_SET_OOM(error);
72       return NULL;
73     }
74
75   if (!dbus_message_allocate_data_slot(&deferred_message_data_slot))
76     {
77       dbus_free(check);
78       BUS_SET_OOM(error);
79       return NULL;
80     }
81
82   check->refcount = 1;
83   check->context = context;
84   check->cynara = bus_cynara_new(check, error);
85   if (dbus_error_is_set(error))
86     {
87       dbus_message_free_data_slot(&deferred_message_data_slot);
88       dbus_free(check);
89       return NULL;
90     }
91
92   return check;
93 }
94
95 BusCheck *
96 bus_check_ref (BusCheck *check)
97 {
98   _dbus_assert (check->refcount > 0);
99   check->refcount += 1;
100
101   return check;
102 }
103
104 void
105 bus_check_unref (BusCheck *check)
106 {
107   _dbus_assert (check->refcount > 0);
108
109   check->refcount -= 1;
110
111   if (check->refcount == 0)
112     {
113       bus_cynara_unref(check->cynara);
114       dbus_message_free_data_slot(&deferred_message_data_slot);
115       dbus_free(check);
116     }
117 }
118
119 BusContext *
120 bus_check_get_context (BusCheck *check)
121 {
122   return check->context;
123 }
124
125 BusCynara *
126 bus_check_get_cynara (BusCheck *check)
127 {
128   return check->cynara;
129 }
130
131 static void
132 bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message,
133                                     BusDeferredMessageStatus check_type,
134                                     BusResult result)
135 {
136   _dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message);
137
138   deferred_message->response = result;
139   _dbus_connection_enable_dispatch(deferred_message->sender);
140 }
141
142 static void
143 bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message,
144                                          BusDeferredMessageStatus check_type,
145                                          BusResult result)
146 {
147   _dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message);
148
149   if (!(dbus_connection_get_is_connected(deferred_message->proposed_recipient)
150                           && bus_connection_is_active(deferred_message->proposed_recipient)))
151     return;
152
153   deferred_message->status &= ~check_type; /* mark message as not waiting for response of this type*/
154   if (deferred_message->response != BUS_RESULT_FALSE)
155     deferred_message->response = result;
156
157   _dbus_assert (deferred_message->response != BUS_RESULT_LATER || deferred_message->status != 0);
158
159   if (!deferred_message->status)
160     bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
161 }
162
163 static void
164 queue_deferred_message_cancel_transaction_hook (void *data)
165 {
166   BusDeferredMessage *deferred_message = (BusDeferredMessage *)data;
167   bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
168 }
169
170
171 dbus_bool_t
172 bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message,
173                                          BusTransaction *transaction,
174                                          dbus_bool_t full_dispatch,
175                                          dbus_bool_t prepend)
176 {
177   _dbus_assert(deferred_message != NULL);
178   _dbus_assert(deferred_message->proposed_recipient != NULL);
179
180   if (!bus_connection_queue_deferred_message(deferred_message->proposed_recipient,
181          deferred_message, prepend))
182     return FALSE;
183
184   if (!bus_transaction_add_cancel_hook(transaction, queue_deferred_message_cancel_transaction_hook,
185       deferred_message, NULL))
186     {
187       bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
188       return FALSE;
189     }
190   deferred_message->response_callback = bus_check_queued_message_reply_callback;
191   deferred_message->full_dispatch = full_dispatch;
192
193   return TRUE;
194 }
195
196 static void
197 deferred_message_free_function(void *data)
198 {
199   BusDeferredMessage *deferred_message = (BusDeferredMessage *)data;
200   bus_deferred_message_unref(deferred_message);
201 }
202
203 void
204 bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message)
205 {
206   _dbus_assert(deferred_message != NULL);
207   _dbus_assert(deferred_message->sender != NULL);
208
209   if (dbus_message_get_data(deferred_message->message, deferred_message_data_slot) == NULL)
210     {
211       if (dbus_message_set_data(deferred_message->message, deferred_message_data_slot, deferred_message,
212           deferred_message_free_function))
213         bus_deferred_message_ref(deferred_message);
214     }
215
216   _dbus_connection_disable_dispatch(deferred_message->sender);
217   deferred_message->response_callback = bus_check_enable_dispatch_callback;
218 }
219
220 void
221 bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message,
222                                             dbus_bool_t requested_reply,
223                                             int matched_rules,
224                                             const char *privilege)
225 {
226   _dbus_assert(deferred_message != NULL);
227
228   deferred_message->requested_reply = requested_reply;
229   deferred_message->matched_rules = matched_rules;
230   deferred_message->privilege = privilege;
231 }
232
233
234 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
235 dbus_bool_t (*bus_check_test_override) (DBusConnection *connection,
236                                         const char *privilege);
237 #endif
238
239 BusResult
240 bus_check_privilege (BusCheck *check,
241                      DBusMessage *message,
242                      DBusConnection *sender,
243                      DBusConnection *addressed_recipient,
244                      DBusConnection *proposed_recipient,
245                      const char *privilege,
246                      BusDeferredMessageStatus check_type,
247                      BusDeferredMessage **deferred_message)
248 {
249   BusDeferredMessage *previous_deferred_message;
250   BusResult result = BUS_RESULT_FALSE;
251   BusCynara *cynara;
252   DBusConnection *connection;
253
254   connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
255
256 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
257   if (bus_check_test_override)
258     return bus_check_test_override (connection, privilege);
259 #endif
260
261   previous_deferred_message = dbus_message_get_data(message, deferred_message_data_slot);
262   /* check if message blocked at sender's queue is being processed */
263   if (previous_deferred_message != NULL)
264     {
265       if ((check_type & BUS_DEFERRED_MESSAGE_CHECK_SEND) &&
266           !(previous_deferred_message->status & BUS_DEFERRED_MESSAGE_CHECK_SEND))
267         {
268           /**
269            * Message has been deferred due to receive or own rule which means that sending this message
270            * is allowed - it must have been checked previously.
271            */
272           result = BUS_RESULT_TRUE;
273         }
274       else
275         {
276           result = previous_deferred_message->response;
277           if (result == BUS_RESULT_LATER)
278             {
279               /* result is still not known - reuse deferred message object */
280               if (deferred_message != NULL)
281                 *deferred_message = previous_deferred_message;
282             }
283           else
284             {
285               /* result is available - we can remove deferred message from the processed message */
286               dbus_message_set_data(message, deferred_message_data_slot, NULL, NULL);
287             }
288         }
289     }
290   else
291     {
292       /* ask policy checkers */
293 #ifdef DBUS_ENABLE_CYNARA
294       cynara = bus_check_get_cynara(check);
295       result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient,
296           proposed_recipient, privilege, check_type, deferred_message);
297 #endif
298       if (result == BUS_RESULT_LATER && deferred_message != NULL)
299         {
300           (*deferred_message)->status |= check_type;
301         }
302     }
303   return result;
304 }
305
306 BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
307                                               DBusConnection *sender,
308                                               DBusConnection *addressed_recipient,
309                                               DBusConnection *proposed_recipient,
310                                               BusResult response)
311 {
312   BusDeferredMessage *deferred_message;
313
314   deferred_message = dbus_new(BusDeferredMessage, 1);
315   if (deferred_message == NULL)
316     {
317       return NULL;
318     }
319
320   deferred_message->refcount = 1;
321   deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL;
322   deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
323   deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
324   deferred_message->message = dbus_message_ref(message);
325   deferred_message->requested_reply = FALSE;
326   deferred_message->matched_rules = 0;
327   deferred_message->privilege = NULL;
328   deferred_message->response = response;
329   deferred_message->status = 0;
330   deferred_message->full_dispatch = FALSE;
331   deferred_message->response_callback = NULL;
332
333   return deferred_message;
334 }
335
336 BusDeferredMessage *
337 bus_deferred_message_ref (BusDeferredMessage *deferred_message)
338 {
339   _dbus_assert (deferred_message->refcount > 0);
340   deferred_message->refcount += 1;
341   return deferred_message;
342 }
343
344 void
345 bus_deferred_message_unref (BusDeferredMessage *deferred_message)
346 {
347   _dbus_assert (deferred_message->refcount > 0);
348
349   deferred_message->refcount -= 1;
350
351    if (deferred_message->refcount == 0)
352      {
353        dbus_message_unref(deferred_message->message);
354        if (deferred_message->sender != NULL)
355            dbus_connection_unref(deferred_message->sender);
356        if (deferred_message->addressed_recipient != NULL)
357            dbus_connection_unref(deferred_message->addressed_recipient);
358        if (deferred_message->proposed_recipient != NULL)
359            dbus_connection_unref(deferred_message->proposed_recipient);
360        dbus_free(deferred_message);
361      }
362 }
363
364 dbus_bool_t
365 bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, DBusError *error)
366 {
367   BusContext *context = bus_connection_get_context(deferred_message->proposed_recipient);
368
369   return bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
370       deferred_message->sender, deferred_message->message, deferred_message->requested_reply,
371       error);
372 }
373
374 dbus_bool_t
375 bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, BusTransaction *transaction, DBusError *error)
376 {
377   int type = dbus_message_get_type(deferred_message->message);
378   if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
379         deferred_message->sender &&
380         dbus_connection_get_is_connected(deferred_message->sender) &&
381         bus_connection_is_active(deferred_message->sender) &&
382         deferred_message->addressed_recipient &&
383         deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */
384         !bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender),
385                                        transaction,
386                                        deferred_message->sender, deferred_message->addressed_recipient,
387                                        deferred_message->message, error))
388     {
389       _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
390       return FALSE;
391     }
392   return TRUE;
393 }
394
395 void
396 bus_deferred_message_create_error(BusDeferredMessage *deferred_message,
397     const char *error_message, DBusError *error)
398 {
399   BusContext *context;
400   _dbus_assert (deferred_message->status == 0 && deferred_message->response == BUS_RESULT_FALSE);
401
402   if (deferred_message->sender == NULL)
403     return; /* error won't be sent to bus driver anyway */
404
405   context = bus_connection_get_context(deferred_message->sender);
406   bus_context_complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected message",
407       deferred_message->matched_rules, deferred_message->message, deferred_message->sender,
408       deferred_message->proposed_recipient, deferred_message->requested_reply, FALSE,
409       deferred_message->privilege, error);
410 }
411
412 BusResult
413 bus_deferred_message_dispatch (BusDeferredMessage *deferred_message)
414 {
415   BusContext *context = bus_connection_get_context (deferred_message->proposed_recipient);
416   BusTransaction *transaction = bus_transaction_new (context);
417   BusResult result = BUS_RESULT_TRUE;
418   DBusError error;
419
420   if (transaction == NULL)
421     {
422       return BUS_RESULT_FALSE;
423     }
424
425   dbus_error_init(&error);
426
427   if (!deferred_message->full_dispatch)
428     {
429       result = deferred_message->response;
430       switch (result)
431         {
432         case BUS_RESULT_TRUE:
433           if (!bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
434                deferred_message->sender, deferred_message->message, deferred_message->requested_reply, &error))
435               result = BUS_RESULT_FALSE;
436           break;
437         case BUS_RESULT_FALSE:
438           break;
439         case BUS_RESULT_LATER:
440           {
441             BusDeferredMessage *deferred_message2 = NULL;
442             result = bus_context_check_security_policy (context, transaction,
443                                                         deferred_message->sender,
444                                                         deferred_message->addressed_recipient,
445                                                         deferred_message->proposed_recipient,
446                                                         deferred_message->message, NULL, NULL,
447                                                         &deferred_message2);
448
449             if (result == BUS_RESULT_LATER)
450               {
451                 /* prepend at recipient */
452                 if (!bus_deferred_message_queue_at_recipient(deferred_message2, transaction,
453                     FALSE, TRUE))
454                   result = BUS_RESULT_FALSE;
455               }
456           }
457         }
458
459       /* silently drop messages on access denial */
460       if (result == BUS_RESULT_TRUE)
461         {
462           if (!bus_transaction_send (transaction, deferred_message->proposed_recipient, deferred_message->message, TRUE))
463             result = BUS_RESULT_FALSE;
464         }
465
466       bus_transaction_execute_and_free(transaction);
467
468       goto out;
469     }
470
471   result = bus_dispatch_matches(transaction, deferred_message->sender,
472       deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error);
473
474   if (result == BUS_RESULT_LATER)
475     {
476       /* Message deferring was already done in bus_dispatch_matches */
477       bus_transaction_cancel_and_free(transaction);
478       goto out;
479     }
480
481   /* this part is a copy & paste from bus_dispatch function. Probably can be moved to a function */
482   if (dbus_error_is_set (&error))
483     {
484       if (!dbus_connection_get_is_connected (deferred_message->sender))
485         {
486           /* If we disconnected it, we won't bother to send it any error
487            * messages.
488            */
489           _dbus_verbose ("Not sending error to connection we disconnected\n");
490         }
491       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
492         {
493           bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
494
495           /* cancel transaction due to OOM */
496           if (transaction != NULL)
497             {
498               bus_transaction_cancel_and_free (transaction);
499               transaction = NULL;
500             }
501         }
502       else
503         {
504           /* Try to send the real error, if no mem to do that, send
505            * the OOM error
506            */
507           _dbus_assert (transaction != NULL);
508           if (!bus_transaction_send_error_reply (transaction, deferred_message->sender,
509                                                  &error, deferred_message->message))
510             {
511               bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
512
513               /* cancel transaction due to OOM */
514               if (transaction != NULL)
515                 {
516                   bus_transaction_cancel_and_free (transaction);
517                   transaction = NULL;
518                 }
519             }
520         }
521     }
522
523   if (transaction != NULL)
524     {
525       bus_transaction_execute_and_free (transaction);
526     }
527
528 out:
529   dbus_error_free(&error);
530
531   return result;
532 }
533
534 dbus_bool_t
535 bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message)
536 {
537   return deferred_message->status != 0;
538 }
539
540 DBusConnection *
541 bus_deferred_message_get_recipient(BusDeferredMessage *deferred_message)
542 {
543   return deferred_message->proposed_recipient;
544 }
545
546 BusDeferredMessageStatus
547 bus_deferred_message_get_status (BusDeferredMessage *deferred_message)
548 {
549   return deferred_message->status;
550 }
551
552 BusResult
553 bus_deferred_message_get_response (BusDeferredMessage *deferred_message)
554 {
555   return deferred_message->response;
556 }
557
558 void
559 bus_deferred_message_set_response (BusDeferredMessage *deferred_message, BusResult response)
560 {
561   deferred_message->response = response;
562 }
563
564 void
565 bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
566                                         BusDeferredMessageStatus check_type,
567                                         BusResult result)
568 {
569   if (deferred_message->response_callback != NULL)
570     {
571       deferred_message->response_callback(deferred_message, check_type, result);
572     }
573 }
574