patch: bus: Fix timeout restarts
[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                                     BusResult result)
134 {
135   _dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message);
136
137   deferred_message->response = result;
138   _dbus_connection_enable_dispatch(deferred_message->sender);
139 }
140
141 static void
142 bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message,
143                                          BusResult result)
144 {
145   int status;
146
147   _dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message);
148
149   if (!bus_connection_is_active(deferred_message->proposed_recipient))
150     return;
151
152   status = deferred_message->status;
153
154   deferred_message->status = 0; /* mark message as not waiting for response */
155   deferred_message->response = result;
156
157   /*
158    * If send rule allows us to send message we still need to check receive rules.
159    */
160   if ((status & BUS_DEFERRED_MESSAGE_CHECK_SEND) && (result == BUS_RESULT_TRUE))
161     {
162       int toggles;
163       BusContext *context;
164       BusRegistry *registry;
165       BusClientPolicy *recipient_policy;
166       BusDeferredMessage *deferred_message_receive;
167
168       context = bus_connection_get_context(deferred_message->proposed_recipient);
169       registry = bus_context_get_registry(context);
170       recipient_policy = bus_connection_get_policy(deferred_message->proposed_recipient);
171
172       deferred_message->response = bus_client_policy_check_can_receive(recipient_policy, registry,
173           deferred_message->requested_reply, deferred_message->sender,
174           deferred_message->addressed_recipient, deferred_message->proposed_recipient, deferred_message->message,
175           &toggles, NULL, &deferred_message_receive);
176       if (deferred_message->response == BUS_RESULT_LATER)
177         {
178           /* replace deferred message associated with send check with the one associated with
179            * receive check */
180           if (!bus_deferred_message_replace(deferred_message, deferred_message_receive))
181             {
182               /* failed to replace deferred message (due to oom). Set it to rejected */
183               deferred_message->response = BUS_RESULT_FALSE;
184             }
185         }
186     }
187
188   bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
189 }
190
191 static void
192 queue_deferred_message_cancel_transaction_hook (void *data)
193 {
194   BusDeferredMessage *deferred_message = (BusDeferredMessage *)data;
195   bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
196 }
197
198
199 dbus_bool_t
200 bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message,
201                                          BusTransaction *transaction,
202                                          dbus_bool_t full_dispatch,
203                                          dbus_bool_t prepend)
204 {
205   _dbus_assert(deferred_message != NULL);
206   _dbus_assert(deferred_message->proposed_recipient != NULL);
207
208   if (!bus_connection_queue_deferred_message(deferred_message->proposed_recipient,
209          deferred_message, prepend))
210     return FALSE;
211
212   if (!bus_transaction_add_cancel_hook(transaction, queue_deferred_message_cancel_transaction_hook,
213       deferred_message, NULL))
214     {
215       bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message);
216       return FALSE;
217     }
218   deferred_message->response_callback = bus_check_queued_message_reply_callback;
219   deferred_message->full_dispatch = full_dispatch;
220
221   return TRUE;
222 }
223
224 static void
225 deferred_message_free_function(void *data)
226 {
227   BusDeferredMessage *deferred_message = (BusDeferredMessage *)data;
228   bus_deferred_message_unref(deferred_message);
229 }
230
231 void
232 bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message)
233 {
234   _dbus_assert(deferred_message != NULL);
235   _dbus_assert(deferred_message->sender != NULL);
236
237   if (dbus_message_get_data(deferred_message->message, deferred_message_data_slot) == NULL)
238     {
239       if (dbus_message_set_data(deferred_message->message, deferred_message_data_slot, deferred_message,
240           deferred_message_free_function))
241         bus_deferred_message_ref(deferred_message);
242     }
243
244   _dbus_connection_disable_dispatch(deferred_message->sender);
245   deferred_message->response_callback = bus_check_enable_dispatch_callback;
246 }
247
248 void
249 bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message,
250                                             dbus_bool_t requested_reply,
251                                             int matched_rules,
252                                             const char *privilege)
253 {
254   _dbus_assert(deferred_message != NULL);
255
256   deferred_message->requested_reply = requested_reply;
257   deferred_message->matched_rules = matched_rules;
258   deferred_message->privilege = privilege;
259 }
260
261
262 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
263 dbus_bool_t (*bus_check_test_override) (DBusConnection *connection,
264                                         const char *privilege);
265 #endif
266
267 BusResult
268 bus_check_privilege (BusCheck *check,
269                      DBusMessage *message,
270                      DBusConnection *sender,
271                      DBusConnection *addressed_recipient,
272                      DBusConnection *proposed_recipient,
273                      const char *privilege,
274                      BusDeferredMessageStatus check_type,
275                      BusDeferredMessage **deferred_message)
276 {
277   BusDeferredMessage *previous_deferred_message;
278   BusResult result = BUS_RESULT_FALSE;
279   BusCynara *cynara;
280   DBusConnection *connection;
281
282   connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
283
284 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
285   if (bus_check_test_override)
286     return bus_check_test_override (connection, privilege);
287 #endif
288
289   previous_deferred_message = dbus_message_get_data(message, deferred_message_data_slot);
290   /* check if message blocked at sender's queue is being processed */
291   if (previous_deferred_message != NULL)
292     {
293       if ((check_type & BUS_DEFERRED_MESSAGE_CHECK_SEND) &&
294           !(previous_deferred_message->status & BUS_DEFERRED_MESSAGE_CHECK_SEND))
295         {
296           /**
297            * Message has been deferred due to receive or own rule which means that sending this message
298            * is allowed - it must have been checked previously.
299            */
300           result = BUS_RESULT_TRUE;
301         }
302       else
303         {
304           result = previous_deferred_message->response;
305           if (result == BUS_RESULT_LATER)
306             {
307               /* result is still not known - reuse deferred message object */
308               if (deferred_message != NULL)
309                 *deferred_message = previous_deferred_message;
310             }
311           else
312             {
313               /* result is available - we can remove deferred message from the processed message */
314               dbus_message_set_data(message, deferred_message_data_slot, NULL, NULL);
315             }
316         }
317     }
318   else
319     {
320       /* ask policy checkers */
321 #ifdef DBUS_ENABLE_CYNARA
322       cynara = bus_check_get_cynara(check);
323       result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient,
324           proposed_recipient, privilege, check_type, deferred_message);
325 #endif
326       if (result == BUS_RESULT_LATER && deferred_message != NULL)
327         {
328           (*deferred_message)->status |= check_type;
329         }
330     }
331   return result;
332 }
333
334 BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
335                                               DBusConnection *sender,
336                                               DBusConnection *addressed_recipient,
337                                               DBusConnection *proposed_recipient,
338                                               BusResult response)
339 {
340   BusDeferredMessage *deferred_message;
341
342   deferred_message = dbus_new(BusDeferredMessage, 1);
343   if (deferred_message == NULL)
344     {
345       return NULL;
346     }
347
348   deferred_message->refcount = 1;
349   deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL;
350   deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
351   deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
352   deferred_message->message = dbus_message_ref(message);
353   deferred_message->requested_reply = FALSE;
354   deferred_message->matched_rules = 0;
355   deferred_message->privilege = NULL;
356   deferred_message->response = response;
357   deferred_message->status = 0;
358   deferred_message->full_dispatch = FALSE;
359   deferred_message->response_callback = NULL;
360
361   return deferred_message;
362 }
363
364 BusDeferredMessage *
365 bus_deferred_message_ref (BusDeferredMessage *deferred_message)
366 {
367   _dbus_assert (deferred_message->refcount > 0);
368   deferred_message->refcount += 1;
369   return deferred_message;
370 }
371
372 void
373 bus_deferred_message_unref (BusDeferredMessage *deferred_message)
374 {
375   _dbus_assert (deferred_message->refcount > 0);
376
377   deferred_message->refcount -= 1;
378
379    if (deferred_message->refcount == 0)
380      {
381        dbus_message_unref(deferred_message->message);
382        if (deferred_message->sender != NULL)
383            dbus_connection_unref(deferred_message->sender);
384        if (deferred_message->addressed_recipient != NULL)
385            dbus_connection_unref(deferred_message->addressed_recipient);
386        if (deferred_message->proposed_recipient != NULL)
387            dbus_connection_unref(deferred_message->proposed_recipient);
388        dbus_free(deferred_message);
389      }
390 }
391
392 dbus_bool_t
393 bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, DBusError *error)
394 {
395   BusContext *context = bus_connection_get_context(deferred_message->proposed_recipient);
396
397   return bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
398       deferred_message->sender, deferred_message->message, deferred_message->requested_reply,
399       error);
400 }
401
402 dbus_bool_t
403 bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, BusTransaction *transaction, DBusError *error)
404 {
405   int type = dbus_message_get_type(deferred_message->message);
406   if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
407         deferred_message->sender &&
408         deferred_message->addressed_recipient &&
409         deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */
410         !bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender),
411                                        transaction,
412                                        deferred_message->sender, deferred_message->addressed_recipient,
413                                        deferred_message->message, error))
414     {
415       _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
416       return FALSE;
417     }
418   return TRUE;
419 }
420
421 void
422 bus_deferred_message_create_error(BusDeferredMessage *deferred_message,
423     const char *error_message, DBusError *error)
424 {
425   BusContext *context;
426   _dbus_assert (deferred_message->status == 0 && deferred_message->response == BUS_RESULT_FALSE);
427
428   if (deferred_message->sender == NULL)
429     return; /* error won't be sent to bus driver anyway */
430
431   context = bus_connection_get_context(deferred_message->sender);
432   bus_context_complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected message",
433       deferred_message->matched_rules, deferred_message->message, deferred_message->sender,
434       deferred_message->proposed_recipient, deferred_message->requested_reply, FALSE,
435       deferred_message->privilege, error);
436 }
437
438 BusResult
439 bus_deferred_message_dispatch (BusDeferredMessage *deferred_message)
440 {
441   BusContext *context = bus_connection_get_context (deferred_message->proposed_recipient);
442   BusTransaction *transaction = bus_transaction_new (context);
443   BusResult result = BUS_RESULT_TRUE;
444   DBusError error;
445
446   if (transaction == NULL)
447     {
448       return BUS_RESULT_FALSE;
449     }
450
451   dbus_error_init(&error);
452
453   if (!deferred_message->full_dispatch)
454     {
455       result = deferred_message->response;
456       switch (result)
457         {
458         case BUS_RESULT_TRUE:
459           if (!bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient,
460                deferred_message->sender, deferred_message->message, deferred_message->requested_reply, &error))
461               result = BUS_RESULT_FALSE;
462           break;
463         case BUS_RESULT_FALSE:
464           break;
465         case BUS_RESULT_LATER:
466           {
467             BusDeferredMessage *deferred_message2;
468             result = bus_context_check_security_policy (context, transaction,
469                                                         deferred_message->sender,
470                                                         deferred_message->addressed_recipient,
471                                                         deferred_message->proposed_recipient,
472                                                         deferred_message->message, NULL,
473                                                         &deferred_message2);
474
475             if (result == BUS_RESULT_LATER)
476               {
477                 /* prepend at recipient */
478                 if (!bus_deferred_message_queue_at_recipient(deferred_message2, transaction,
479                     FALSE, TRUE))
480                   result = BUS_RESULT_FALSE;
481               }
482           }
483         }
484
485       /* silently drop messages on access denial */
486       if (result == BUS_RESULT_TRUE)
487         {
488           if (!bus_transaction_send (transaction, deferred_message->proposed_recipient, deferred_message->message, TRUE))
489             result = BUS_RESULT_FALSE;
490         }
491
492       bus_transaction_execute_and_free(transaction);
493
494       goto out;
495     }
496
497   /* do not attempt to send message if sender has disconnected */
498   if (deferred_message->sender != NULL && !bus_connection_is_active(deferred_message->sender))
499     {
500       bus_transaction_cancel_and_free(transaction);
501       result = BUS_RESULT_FALSE;
502       goto out;
503     }
504
505   result = bus_dispatch_matches(transaction, deferred_message->sender,
506       deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error);
507
508   if (result == BUS_RESULT_LATER)
509     {
510       /* Message deferring was already done in bus_dispatch_matches */
511       bus_transaction_cancel_and_free(transaction);
512       goto out;
513     }
514
515   /* this part is a copy & paste from bus_dispatch function. Probably can be moved to a function */
516   if (dbus_error_is_set (&error))
517     {
518       if (!dbus_connection_get_is_connected (deferred_message->sender))
519         {
520           /* If we disconnected it, we won't bother to send it any error
521            * messages.
522            */
523           _dbus_verbose ("Not sending error to connection we disconnected\n");
524         }
525       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
526         {
527           bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
528
529           /* cancel transaction due to OOM */
530           if (transaction != NULL)
531             {
532               bus_transaction_cancel_and_free (transaction);
533               transaction = NULL;
534             }
535         }
536       else
537         {
538           /* Try to send the real error, if no mem to do that, send
539            * the OOM error
540            */
541           _dbus_assert (transaction != NULL);
542           if (!bus_transaction_send_error_reply (transaction, deferred_message->sender,
543                                                  &error, deferred_message->message))
544             {
545               bus_connection_send_oom_error (deferred_message->sender, deferred_message->message);
546
547               /* cancel transaction due to OOM */
548               if (transaction != NULL)
549                 {
550                   bus_transaction_cancel_and_free (transaction);
551                   transaction = NULL;
552                 }
553             }
554         }
555     }
556
557   if (transaction != NULL)
558     {
559       bus_transaction_execute_and_free (transaction);
560     }
561
562 out:
563   dbus_error_free(&error);
564
565   return result;
566 }
567
568 dbus_bool_t
569 bus_deferred_message_replace (BusDeferredMessage *old_message, BusDeferredMessage *new_message)
570 {
571   if (bus_connection_replace_deferred_message(old_message->proposed_recipient,
572         old_message, new_message))
573     {
574       new_message->response_callback = old_message->response_callback;
575       new_message->full_dispatch = old_message->full_dispatch;
576       return TRUE;
577     }
578   return FALSE;
579 }
580
581 dbus_bool_t
582 bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message)
583 {
584   return deferred_message->status != 0;
585 }
586
587 DBusConnection *
588 bus_deferred_message_get_recipient(BusDeferredMessage *deferred_message)
589 {
590   return deferred_message->proposed_recipient;
591 }
592
593 BusDeferredMessageStatus
594 bus_deferred_message_get_status (BusDeferredMessage *deferred_message)
595 {
596   return deferred_message->status;
597 }
598
599 BusResult
600 bus_deferred_message_get_response (BusDeferredMessage *deferred_message)
601 {
602   return deferred_message->response;
603 }
604
605 void
606 bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
607                                         BusResult result)
608 {
609   if (deferred_message->response_callback != NULL)
610     {
611       deferred_message->response_callback(deferred_message, result);
612     }
613 }
614