dbus-marshal-byteswap: Byte-swap Unix fd indexes if needed
[platform/upstream/dbus.git] / bus / apparmor.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * apparmor.c  AppArmor security checks for D-Bus
3  *
4  * Based on selinux.c
5  *
6  * Copyright © 2014-2015 Canonical, Ltd.
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
23  *
24  */
25
26 #include <config.h>
27 #include "apparmor.h"
28
29 #ifdef HAVE_APPARMOR
30
31 #include <dbus/dbus-internals.h>
32 #include <dbus/dbus-string.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <limits.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/apparmor.h>
40 #include <sys/stat.h>
41 #include <sys/types.h>
42 #include <syslog.h>
43 #include <unistd.h>
44
45 #ifdef HAVE_LIBAUDIT
46 #include <libaudit.h>
47 #endif /* HAVE_LIBAUDIT */
48
49 #include "activation.h"
50 #include "audit.h"
51 #include "connection.h"
52 #include "utils.h"
53
54 /* Store the value telling us if AppArmor D-Bus mediation is enabled. */
55 static dbus_bool_t apparmor_enabled = FALSE;
56
57 typedef enum {
58   APPARMOR_DISABLED,
59   APPARMOR_ENABLED,
60   APPARMOR_REQUIRED
61 } AppArmorConfigMode;
62
63 /* Store the value of the AppArmor mediation mode in the bus configuration */
64 static AppArmorConfigMode apparmor_config_mode = APPARMOR_ENABLED;
65
66 /* The AppArmor context, consisting of a label and a mode. */
67 struct BusAppArmorConfinement
68 {
69   int refcount; /* Reference count */
70
71   char *label; /* AppArmor confinement label */
72   const char *mode; /* AppArmor confinement mode (freed by freeing *label) */
73 };
74
75 static BusAppArmorConfinement *bus_con = NULL;
76
77 /**
78  * Callers of this function give up ownership of the *label and *mode
79  * pointers.
80  *
81  * Additionally, the responsibility of freeing *label and *mode becomes the
82  * responsibility of the bus_apparmor_confinement_unref() function. However, it
83  * does not free *mode because libapparmor's aa_getcon(), and libapparmor's
84  * other related functions, allocate a single buffer for *label and *mode and
85  * then separate the two char arrays with a NUL char. See the aa_getcon(2) man
86  * page for more details.
87  */
88 static BusAppArmorConfinement*
89 bus_apparmor_confinement_new (char       *label,
90                               const char *mode)
91 {
92   BusAppArmorConfinement *confinement;
93
94   confinement = dbus_new0 (BusAppArmorConfinement, 1);
95   if (confinement != NULL)
96     {
97       confinement->refcount = 1;
98       confinement->label = label;
99       confinement->mode = mode;
100     }
101
102   return confinement;
103 }
104
105 /*
106  * Return TRUE on successful check, FALSE on OOM.
107  * Set *is_supported to whether AA has D-Bus features.
108  */
109 static dbus_bool_t
110 _bus_apparmor_detect_aa_dbus_support (dbus_bool_t *is_supported)
111 {
112   int mask_file;
113   DBusString aa_dbus;
114   char *aa_securityfs = NULL;
115   dbus_bool_t retval = FALSE;
116
117   *is_supported = FALSE;
118
119   if (!_dbus_string_init (&aa_dbus))
120     return FALSE;
121
122   if (aa_find_mountpoint (&aa_securityfs) != 0)
123     goto out;
124
125   /*
126    * John Johansen has confirmed that the mainline kernel will not have
127    * the apparmorfs/features/dbus/mask file until the mainline kernel
128    * has AppArmor getpeersec support.
129    */
130   if (!_dbus_string_append (&aa_dbus, aa_securityfs) ||
131       !_dbus_string_append (&aa_dbus, "/features/dbus/mask"))
132     goto out;
133
134   /* We need to open() the flag file, not just stat() it, because AppArmor
135    * does not mediate stat() in the apparmorfs. If you have a
136    * dbus-daemon inside an LXC container, with insufficiently broad
137    * AppArmor privileges to do its own AppArmor mediation, the desired
138    * result is that it behaves as if AppArmor was not present; but a stat()
139    * here would succeed, and result in it trying and failing to do full
140    * mediation. https://bugs.launchpad.net/ubuntu/+source/dbus/+bug/1238267 */
141   mask_file = open (_dbus_string_get_const_data (&aa_dbus),
142                     O_RDONLY | O_CLOEXEC);
143   if (mask_file != -1)
144     {
145       *is_supported = TRUE;
146       close (mask_file);
147     }
148
149   retval = TRUE;
150
151 out:
152   free (aa_securityfs);
153   _dbus_string_free (&aa_dbus);
154
155   return retval;
156 }
157
158 static dbus_bool_t
159 modestr_is_complain (const char *mode)
160 {
161   if (mode && strcmp (mode, "complain") == 0)
162     return TRUE;
163   return FALSE;
164 }
165
166 static void
167 log_message (dbus_bool_t allow, const char *op, DBusString *data)
168 {
169   const char *mstr;
170 #ifdef HAVE_LIBAUDIT
171   int audit_fd;
172 #endif
173
174   if (allow)
175     mstr = "ALLOWED";
176   else
177     mstr = "DENIED";
178
179 #ifdef HAVE_LIBAUDIT
180   audit_fd = bus_audit_get_fd ();
181
182   if (audit_fd >= 0)
183   {
184     DBusString avc;
185
186     if (!_dbus_string_init (&avc))
187       goto syslog;
188
189     if (!_dbus_string_append_printf (&avc,
190           "apparmor=\"%s\" operation=\"dbus_%s\" %s\n",
191           mstr, op, _dbus_string_get_const_data (data)))
192       {
193         _dbus_string_free (&avc);
194         goto syslog;
195       }
196
197     /* FIXME: need to change this to show real user */
198     audit_log_user_avc_message (audit_fd, AUDIT_USER_AVC,
199                                 _dbus_string_get_const_data (&avc),
200                                 NULL, NULL, NULL, getuid ());
201     _dbus_string_free (&avc);
202     return;
203   }
204
205 syslog:
206 #endif /* HAVE_LIBAUDIT */
207
208   syslog (LOG_USER | LOG_NOTICE, "apparmor=\"%s\" operation=\"dbus_%s\" %s\n",
209           mstr, op, _dbus_string_get_const_data (data));
210 }
211
212 static dbus_bool_t
213 _dbus_append_pair_uint (DBusString *auxdata, const char *name,
214                        unsigned long value)
215 {
216   return _dbus_string_append (auxdata, " ") &&
217          _dbus_string_append (auxdata, name) &&
218          _dbus_string_append (auxdata, "=") &&
219          _dbus_string_append_uint (auxdata, value);
220 }
221
222 static dbus_bool_t
223 _dbus_append_pair_str (DBusString *auxdata, const char *name, const char *value)
224 {
225   return _dbus_string_append (auxdata, " ") &&
226          _dbus_string_append (auxdata, name) &&
227          _dbus_string_append (auxdata, "=\"") &&
228          _dbus_string_append (auxdata, value) &&
229          _dbus_string_append (auxdata, "\"");
230 }
231
232 static dbus_bool_t
233 _dbus_append_mask (DBusString *auxdata, uint32_t mask)
234 {
235   const char *mask_str;
236
237   /* Only one permission bit can be set */
238   if (mask == AA_DBUS_SEND)
239     mask_str = "send";
240   else if (mask == AA_DBUS_RECEIVE)
241     mask_str = "receive";
242   else if (mask == AA_DBUS_BIND)
243     mask_str = "bind";
244   else
245     return FALSE;
246
247   return _dbus_append_pair_str (auxdata, "mask", mask_str);
248 }
249
250 static dbus_bool_t
251 is_unconfined (const char *con, const char *mode)
252 {
253   /* treat con == NULL as confined as it is going to result in a denial */
254   if ((!mode && con && strcmp (con, "unconfined") == 0) ||
255       strcmp (mode, "unconfined") == 0)
256     {
257       return TRUE;
258     }
259
260   return FALSE;
261 }
262
263 static dbus_bool_t
264 query_append (DBusString *query, const char *buffer)
265 {
266   if (!_dbus_string_append_byte (query, '\0'))
267     return FALSE;
268
269   if (buffer && !_dbus_string_append (query, buffer))
270     return FALSE;
271
272   return TRUE;
273 }
274
275 static dbus_bool_t
276 build_common_query (DBusString *query, const char *con, const char *bustype)
277 {
278   /**
279    * libapparmor's aa_query_label() function scribbles over the first
280    * AA_QUERY_CMD_LABEL_SIZE bytes of the query string with a private value.
281    */
282   return _dbus_string_insert_bytes (query, 0, AA_QUERY_CMD_LABEL_SIZE, 0) &&
283          _dbus_string_append (query, con) &&
284          _dbus_string_append_byte (query, '\0') &&
285          _dbus_string_append_byte (query, AA_CLASS_DBUS) &&
286          _dbus_string_append (query, bustype ? bustype : "");
287 }
288
289 static dbus_bool_t
290 build_service_query (DBusString *query,
291                      const char *con,
292                      const char *bustype,
293                      const char *name)
294 {
295   return build_common_query (query, con, bustype) &&
296          query_append (query, name);
297 }
298
299 static dbus_bool_t
300 build_message_query (DBusString *query,
301                      const char *src_con,
302                      const char *bustype,
303                      const char *name,
304                      const char *dst_con,
305                      const char *path,
306                      const char *interface,
307                      const char *member)
308 {
309   return build_common_query (query, src_con, bustype) &&
310          query_append (query, name) &&
311          query_append (query, dst_con) &&
312          query_append (query, path) &&
313          query_append (query, interface) &&
314          query_append (query, member);
315 }
316
317 static dbus_bool_t
318 build_eavesdrop_query (DBusString *query, const char *con, const char *bustype)
319 {
320   return build_common_query (query, con, bustype);
321 }
322
323 static void
324 set_error_from_query_errno (DBusError *error, int error_number)
325 {
326   dbus_set_error (error, _dbus_error_from_errno (error_number),
327                   "Failed to query AppArmor policy: %s",
328                   _dbus_strerror (error_number));
329 }
330
331 static void
332 set_error_from_denied_message (DBusError      *error,
333                                DBusConnection *sender,
334                                DBusConnection *proposed_recipient,
335                                dbus_bool_t     requested_reply,
336                                const char     *msgtype,
337                                const char     *path,
338                                const char     *interface,
339                                const char     *member,
340                                const char     *error_name,
341                                const char     *destination)
342 {
343   const char *proposed_recipient_loginfo;
344   const char *unset = "(unset)";
345
346   proposed_recipient_loginfo = proposed_recipient ?
347                                bus_connection_get_loginfo (proposed_recipient) :
348                                "bus";
349
350   dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
351                   "An AppArmor policy prevents this sender from sending this "
352                   "message to this recipient; type=\"%s\", "
353                   "sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" "
354                   "error name=\"%s\" requested_reply=\"%d\" "
355                   "destination=\"%s\" (%s)",
356                   msgtype,
357                   bus_connection_get_name (sender),
358                   bus_connection_get_loginfo (sender),
359                   interface ? interface : unset,
360                   member ? member : unset,
361                   error_name ? error_name : unset,
362                   requested_reply,
363                   destination,
364                   proposed_recipient_loginfo);
365 }
366 #endif /* HAVE_APPARMOR */
367
368 /**
369  * Do early initialization; determine whether AppArmor is enabled.
370  * Return TRUE on successful check (whether AppArmor is actually
371  * enabled or not) or FALSE on OOM.
372  */
373 dbus_bool_t
374 bus_apparmor_pre_init (void)
375 {
376 #ifdef HAVE_APPARMOR
377   apparmor_enabled = FALSE;
378
379   if (!aa_is_enabled ())
380     return TRUE;
381
382   if (!_bus_apparmor_detect_aa_dbus_support (&apparmor_enabled))
383     return FALSE;
384 #endif
385
386   return TRUE;
387 }
388
389 dbus_bool_t
390 bus_apparmor_set_mode_from_config (const char *mode, DBusError *error)
391 {
392 #ifdef HAVE_APPARMOR
393   if (mode != NULL)
394   {
395     if (strcmp (mode, "disabled") == 0)
396       apparmor_config_mode = APPARMOR_DISABLED;
397     else if (strcmp (mode, "enabled") == 0)
398       apparmor_config_mode = APPARMOR_ENABLED;
399     else if (strcmp (mode, "required") == 0)
400       apparmor_config_mode = APPARMOR_REQUIRED;
401     else
402       {
403         dbus_set_error (error, DBUS_ERROR_FAILED,
404                         "Mode attribute on <apparmor> must have value "
405                         "\"required\", \"enabled\" or \"disabled\", "
406                         "not \"%s\"", mode);
407         return FALSE;
408       }
409   }
410
411   return TRUE;
412 #else
413   if (mode == NULL || strcmp (mode, "disabled") == 0 ||
414                       strcmp (mode, "enabled") == 0)
415     return TRUE;
416
417   dbus_set_error (error, DBUS_ERROR_FAILED,
418                   "Mode attribute on <apparmor> must have value \"enabled\" or "
419                   "\"disabled\" but cannot be \"%s\" when D-Bus is built "
420                   "without AppArmor support", mode);
421   return FALSE;
422 #endif
423 }
424
425 /**
426  * Verify that the config mode is compatible with the kernel's AppArmor
427  * support. If AppArmor mediation will be enabled, determine the bus
428  * confinement label.
429  */
430 dbus_bool_t
431 bus_apparmor_full_init (DBusError *error)
432 {
433 #ifdef HAVE_APPARMOR
434   char *label, *mode;
435
436   if (apparmor_enabled)
437     {
438       if (apparmor_config_mode == APPARMOR_DISABLED)
439         {
440           apparmor_enabled = FALSE;
441           return TRUE;
442         }
443
444       if (bus_con == NULL)
445         {
446           if (aa_getcon (&label, &mode) == -1)
447             {
448               dbus_set_error (error, DBUS_ERROR_FAILED,
449                               "Error getting AppArmor context of bus: %s",
450                               _dbus_strerror (errno));
451               return FALSE;
452             }
453
454           bus_con = bus_apparmor_confinement_new (label, mode);
455           if (bus_con == NULL)
456             {
457               BUS_SET_OOM (error);
458               free (label);
459               return FALSE;
460             }
461         }
462     }
463   else
464     {
465       if (apparmor_config_mode == APPARMOR_REQUIRED)
466         {
467           dbus_set_error (error, DBUS_ERROR_FAILED,
468                           "AppArmor mediation required but not present");
469           return FALSE;
470         }
471       else if (apparmor_config_mode == APPARMOR_ENABLED)
472         {
473           return TRUE;
474         }
475     }
476 #endif
477
478   return TRUE;
479 }
480
481 void
482 bus_apparmor_shutdown (void)
483 {
484 #ifdef HAVE_APPARMOR
485   if (!apparmor_enabled)
486     return;
487
488   _dbus_verbose ("AppArmor shutdown\n");
489
490   bus_apparmor_confinement_unref (bus_con);
491   bus_con = NULL;
492 #endif /* HAVE_APPARMOR */
493 }
494
495 dbus_bool_t
496 bus_apparmor_enabled (void)
497 {
498 #ifdef HAVE_APPARMOR
499   return apparmor_enabled;
500 #else
501   return FALSE;
502 #endif
503 }
504
505 void
506 bus_apparmor_confinement_unref (BusAppArmorConfinement *confinement)
507 {
508 #ifdef HAVE_APPARMOR
509   if (!apparmor_enabled)
510     return;
511
512   _dbus_assert (confinement != NULL);
513   _dbus_assert (confinement->refcount > 0);
514
515   confinement->refcount -= 1;
516
517   if (confinement->refcount == 0)
518     {
519       /**
520        * Do not free confinement->mode, as libapparmor does a single malloc for
521        * both confinement->label and confinement->mode.
522        */
523       free (confinement->label);
524       dbus_free (confinement);
525     }
526 #endif
527 }
528
529 void
530 bus_apparmor_confinement_ref (BusAppArmorConfinement *confinement)
531 {
532 #ifdef HAVE_APPARMOR
533   if (!apparmor_enabled)
534     return;
535
536   _dbus_assert (confinement != NULL);
537   _dbus_assert (confinement->refcount > 0);
538
539   confinement->refcount += 1;
540 #endif /* HAVE_APPARMOR */
541 }
542
543 BusAppArmorConfinement*
544 bus_apparmor_init_connection_confinement (DBusConnection *connection,
545                                           DBusError      *error)
546 {
547 #ifdef HAVE_APPARMOR
548   BusAppArmorConfinement *confinement;
549   char *label, *mode;
550   int fd;
551
552   if (!apparmor_enabled)
553     return NULL;
554
555   _dbus_assert (connection != NULL);
556
557   if (!dbus_connection_get_socket (connection, &fd))
558     {
559       dbus_set_error (error, DBUS_ERROR_FAILED,
560                       "Failed to get socket file descriptor of connection");
561       return NULL;
562     }
563
564   if (aa_getpeercon (fd, &label, &mode) == -1)
565     {
566       if (errno == ENOMEM)
567         BUS_SET_OOM (error);
568       else
569         dbus_set_error (error, _dbus_error_from_errno (errno),
570                         "Failed to get AppArmor confinement information of socket peer: %s",
571                         _dbus_strerror (errno));
572       return NULL;
573     }
574
575   confinement = bus_apparmor_confinement_new (label, mode);
576   if (confinement == NULL)
577     {
578       BUS_SET_OOM (error);
579       free (label);
580       return NULL;
581     }
582
583   return confinement;
584 #else
585   return NULL;
586 #endif /* HAVE_APPARMOR */
587 }
588
589 /**
590  * Returns true if the given connection can acquire a service,
591  * using the tasks security context
592  *
593  * @param connection connection that wants to own the service
594  * @param bustype name of the bus
595  * @param service_name the name of the service to acquire
596  * @param error the reason for failure when FALSE is returned
597  * @returns TRUE if acquire is permitted
598  */
599 dbus_bool_t
600 bus_apparmor_allows_acquire_service (DBusConnection     *connection,
601                                      const char         *bustype,
602                                      const char         *service_name,
603                                      DBusError          *error)
604 {
605
606 #ifdef HAVE_APPARMOR
607   BusAppArmorConfinement *con = NULL;
608   DBusString qstr, auxdata;
609   dbus_bool_t free_auxdata = FALSE;
610   /* the AppArmor API uses pointers to int for pointers to boolean, and
611    * int is not strictly guaranteed to be the same as dbus_bool_t */
612   int allow = FALSE, audit = TRUE;
613   unsigned long pid;
614   int res, serrno = 0;
615
616   if (!apparmor_enabled)
617     return TRUE;
618
619   _dbus_assert (connection != NULL);
620
621   con = bus_connection_dup_apparmor_confinement (connection);
622
623   if (is_unconfined (con->label, con->mode))
624     {
625       allow = TRUE;
626       audit = FALSE;
627       goto out;
628     }
629
630   if (!_dbus_string_init (&qstr))
631     goto oom;
632
633   if (!build_service_query (&qstr, con->label, bustype, service_name))
634     {
635       _dbus_string_free (&qstr);
636       goto oom;
637     }
638
639   res = aa_query_label (AA_DBUS_BIND,
640                         _dbus_string_get_data (&qstr),
641                         _dbus_string_get_length (&qstr),
642                         &allow, &audit);
643   _dbus_string_free (&qstr);
644   if (res == -1)
645     {
646       serrno = errno;
647       set_error_from_query_errno (error, serrno);
648       goto audit;
649     }
650
651   /* Don't fail operations on profiles in complain mode */
652   if (modestr_is_complain (con->mode))
653       allow = TRUE;
654
655   if (!allow)
656     dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
657                     "Connection \"%s\" is not allowed to own the service "
658                     "\"%s\" due to AppArmor policy",
659                     bus_connection_is_active (connection) ?
660                      bus_connection_get_name (connection) : "(inactive)",
661                     service_name);
662
663   if (!audit)
664     goto out;
665
666  audit:
667   if (!_dbus_string_init (&auxdata))
668     goto oom;
669   free_auxdata = TRUE;
670
671   if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown"))
672     goto oom;
673
674   if (!_dbus_append_pair_str (&auxdata, "name", service_name))
675     goto oom;
676
677   if (serrno && !_dbus_append_pair_str (&auxdata, "info", strerror (serrno)))
678     goto oom;
679
680   if (!_dbus_append_mask (&auxdata, AA_DBUS_BIND))
681     goto oom;
682
683   if (connection && dbus_connection_get_unix_process_id (connection, &pid) &&
684       !_dbus_append_pair_uint (&auxdata, "pid", pid))
685     goto oom;
686
687   if (con->label && !_dbus_append_pair_str (&auxdata, "label", con->label))
688     goto oom;
689
690   log_message (allow, "bind", &auxdata);
691
692  out:
693   if (con != NULL)
694     bus_apparmor_confinement_unref (con);
695   if (free_auxdata)
696     _dbus_string_free (&auxdata);
697   return allow;
698
699  oom:
700   if (error != NULL && !dbus_error_is_set (error))
701     BUS_SET_OOM (error);
702   allow = FALSE;
703   goto out;
704
705 #else
706   return TRUE;
707 #endif /* HAVE_APPARMOR */
708 }
709
710 /**
711  * Check if Apparmor security controls allow the message to be sent to a
712  * particular connection based on the security context of the sender and
713  * that of the receiver. The destination connection need not be the
714  * addressed recipient, it could be an "eavesdropper"
715  *
716  * @param sender the sender of the message.
717  * @param proposed_recipient the connection the message is to be sent to.
718  * @param requested_reply TRUE if the message is a reply requested by
719  *                        proposed_recipient
720  * @param bustype name of the bus
721  * @param msgtype message type (DBUS_MESSAGE_TYPE_METHOD_CALL, etc.)
722  * @param path object path the message should be sent to
723  * @param interface the type of the object instance
724  * @param member the member of the object
725  * @param error_name the name of the error if the message type is error
726  * @param destination name that the message should be sent to
727  * @param source name that the message should be sent from
728  * @param error the reason for failure when FALSE is returned
729  * @returns TRUE if the message is permitted
730  */
731 dbus_bool_t
732 bus_apparmor_allows_send (DBusConnection     *sender,
733                           DBusConnection     *proposed_recipient,
734                           dbus_bool_t         requested_reply,
735                           const char         *bustype,
736                           int                 msgtype,
737                           const char         *path,
738                           const char         *interface,
739                           const char         *member,
740                           const char         *error_name,
741                           const char         *destination,
742                           const char         *source,
743                           BusActivationEntry *activation_entry,
744                           DBusError          *error)
745 {
746 #ifdef HAVE_APPARMOR
747   BusAppArmorConfinement *src_con = NULL, *dst_con = NULL;
748   DBusString qstr, auxdata;
749   int src_allow = FALSE, dst_allow = FALSE;
750   int src_audit = TRUE, dst_audit = TRUE;
751   dbus_bool_t free_auxdata = FALSE;
752   unsigned long pid;
753   int len, res, src_errno = 0, dst_errno = 0;
754   uint32_t src_perm = AA_DBUS_SEND, dst_perm = AA_DBUS_RECEIVE;
755   const char *msgtypestr = dbus_message_type_to_string(msgtype);
756   const char *dst_label = NULL;
757   const char *dst_mode = NULL;
758
759   if (!apparmor_enabled)
760     return TRUE;
761
762   /* We do not mediate activation attempts yet. */
763   if (activation_entry != NULL)
764     return TRUE;
765
766   _dbus_assert (sender != NULL);
767
768   src_con = bus_connection_dup_apparmor_confinement (sender);
769
770   if (proposed_recipient)
771     {
772       dst_con = bus_connection_dup_apparmor_confinement (proposed_recipient);
773     }
774   else if (activation_entry != NULL)
775     {
776       dst_label = bus_activation_entry_get_assumed_apparmor_label (activation_entry);
777     }
778   else
779     {
780       dst_con = bus_con;
781       bus_apparmor_confinement_ref (dst_con);
782     }
783
784   if (dst_con != NULL)
785     {
786       dst_label = dst_con->label;
787       dst_mode = dst_con->mode;
788     }
789
790   /* map reply messages to initial send and receive permission. That is
791    * permission to receive a message from X grants permission to reply to X.
792    * And permission to send a message to Y grants permission to receive a reply
793    * from Y. Note that this only applies to requested replies. Unrequested
794    * replies still require a policy query.
795    */
796   if (requested_reply)
797     {
798       /* ignore requested reply messages and let dbus reply mapping handle them
799        * as the send was already allowed
800        */
801       src_allow = TRUE;
802       dst_allow = TRUE;
803       goto out;
804     }
805
806   if (is_unconfined (src_con->label, src_con->mode))
807     {
808       src_allow = TRUE;
809       src_audit = FALSE;
810     }
811   else
812     {
813       if (!_dbus_string_init (&qstr))
814         goto oom;
815
816       if (!build_message_query (&qstr, src_con->label, bustype, destination,
817                                 dst_label, path, interface, member))
818         {
819           _dbus_string_free (&qstr);
820           goto oom;
821         }
822
823       res = aa_query_label (src_perm,
824                             _dbus_string_get_data (&qstr),
825                             _dbus_string_get_length (&qstr),
826                             &src_allow, &src_audit);
827       _dbus_string_free (&qstr);
828       if (res == -1)
829         {
830           src_errno = errno;
831           set_error_from_query_errno (error, src_errno);
832           goto audit;
833         }
834     }
835
836   /* When deciding whether we can activate a service, we only check that
837    * we are allowed to send a message to it, not that it is allowed to
838    * receive that message from us.
839    */
840   if (activation_entry != NULL || is_unconfined (dst_label, dst_mode))
841     {
842       dst_allow = TRUE;
843       dst_audit = FALSE;
844     }
845   else
846     {
847       if (!_dbus_string_init (&qstr))
848         goto oom;
849
850       if (!build_message_query (&qstr, dst_label, bustype, source,
851                                 src_con->label, path, interface, member))
852         {
853           _dbus_string_free (&qstr);
854           goto oom;
855         }
856
857       res = aa_query_label (dst_perm,
858                             _dbus_string_get_data (&qstr),
859                             _dbus_string_get_length (&qstr),
860                             &dst_allow, &dst_audit);
861       _dbus_string_free (&qstr);
862       if (res == -1)
863         {
864           dst_errno = errno;
865           set_error_from_query_errno (error, dst_errno);
866           goto audit;
867         }
868     }
869
870   /* Don't fail operations on profiles in complain mode */
871   if (modestr_is_complain (src_con->mode))
872     src_allow = TRUE;
873   if (modestr_is_complain (dst_mode))
874     dst_allow = TRUE;
875
876   if (!src_allow || !dst_allow)
877     set_error_from_denied_message (error,
878                                    sender,
879                                    proposed_recipient,
880                                    requested_reply,
881                                    msgtypestr,
882                                    path,
883                                    interface,
884                                    member,
885                                    error_name,
886                                    destination);
887
888   /* Don't audit the message if one of the following conditions is true:
889    *   1) The AppArmor query indicates that auditing should not happen.
890    *   2) The message is a reply type. Reply message are not audited because
891    *      the AppArmor policy language does not have the notion of a reply
892    *      message. Unrequested replies will be silently discarded if the sender
893    *      does not have permission to send to the receiver or if the receiver
894    *      does not have permission to receive from the sender.
895    */
896   if ((!src_audit && !dst_audit) ||
897       (msgtype == DBUS_MESSAGE_TYPE_METHOD_RETURN ||
898        msgtype == DBUS_MESSAGE_TYPE_ERROR))
899     goto out;
900
901  audit:
902   if (!_dbus_string_init (&auxdata))
903     goto oom;
904   free_auxdata = TRUE;
905
906   if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown"))
907     goto oom;
908
909   if (path && !_dbus_append_pair_str (&auxdata, "path", path))
910     goto oom;
911
912   if (interface && !_dbus_append_pair_str (&auxdata, "interface", interface))
913     goto oom;
914
915   if (member && !_dbus_append_pair_str (&auxdata, "member", member))
916     goto oom;
917
918   if (error_name && !_dbus_append_pair_str (&auxdata, "error_name", error_name))
919     goto oom;
920
921   len = _dbus_string_get_length (&auxdata);
922
923   if (src_audit)
924     {
925       if (!_dbus_append_mask (&auxdata, src_perm))
926         goto oom;
927
928       if (destination && !_dbus_append_pair_str (&auxdata, "name", destination))
929         goto oom;
930
931       if (sender && dbus_connection_get_unix_process_id (sender, &pid) &&
932           !_dbus_append_pair_uint (&auxdata, "pid", pid))
933         goto oom;
934
935       if (src_con->label &&
936           !_dbus_append_pair_str (&auxdata, "label", src_con->label))
937         goto oom;
938
939       if (proposed_recipient &&
940           dbus_connection_get_unix_process_id (proposed_recipient, &pid) &&
941           !_dbus_append_pair_uint (&auxdata, "peer_pid", pid))
942         goto oom;
943
944       if (dst_label &&
945           !_dbus_append_pair_str (&auxdata, "peer_label", dst_label))
946         goto oom;
947
948       if (src_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (src_errno)))
949         goto oom;
950
951       if (dst_errno &&
952           !_dbus_append_pair_str (&auxdata, "peer_info", strerror (dst_errno)))
953         goto oom;
954
955       log_message (src_allow, msgtypestr, &auxdata);
956     }
957   if (dst_audit)
958     {
959       _dbus_string_set_length (&auxdata, len);
960
961       if (source && !_dbus_append_pair_str (&auxdata, "name", source))
962         goto oom;
963
964       if (!_dbus_append_mask (&auxdata, dst_perm))
965         goto oom;
966
967       if (proposed_recipient &&
968           dbus_connection_get_unix_process_id (proposed_recipient, &pid) &&
969           !_dbus_append_pair_uint (&auxdata, "pid", pid))
970         goto oom;
971
972       if (dst_label &&
973           !_dbus_append_pair_str (&auxdata, "label", dst_label))
974         goto oom;
975
976       if (sender && dbus_connection_get_unix_process_id (sender, &pid) &&
977           !_dbus_append_pair_uint (&auxdata, "peer_pid", pid))
978         goto oom;
979
980       if (src_con->label &&
981           !_dbus_append_pair_str (&auxdata, "peer_label", src_con->label))
982         goto oom;
983
984       if (dst_errno && !_dbus_append_pair_str (&auxdata, "info", strerror (dst_errno)))
985         goto oom;
986
987       if (src_errno &&
988           !_dbus_append_pair_str (&auxdata, "peer_info", strerror (src_errno)))
989         goto oom;
990
991       log_message (dst_allow, msgtypestr, &auxdata);
992     }
993
994  out:
995   if (src_con != NULL)
996     bus_apparmor_confinement_unref (src_con);
997   if (dst_con != NULL)
998     bus_apparmor_confinement_unref (dst_con);
999   if (free_auxdata)
1000     _dbus_string_free (&auxdata);
1001
1002   return src_allow && dst_allow;
1003
1004  oom:
1005   if (error != NULL && !dbus_error_is_set (error))
1006     BUS_SET_OOM (error);
1007   src_allow = FALSE;
1008   dst_allow = FALSE;
1009   goto out;
1010
1011 #else
1012   return TRUE;
1013 #endif /* HAVE_APPARMOR */
1014 }
1015
1016 /**
1017  * Check if Apparmor security controls allow the connection to eavesdrop on
1018  * other connections.
1019  *
1020  * @param connection the connection attempting to eavesdrop.
1021  * @param bustype name of the bus
1022  * @param error the reason for failure when FALSE is returned
1023  * @returns TRUE if eavesdropping is permitted
1024  */
1025 dbus_bool_t
1026 bus_apparmor_allows_eavesdropping (DBusConnection     *connection,
1027                                    const char         *bustype,
1028                                    DBusError          *error)
1029 {
1030 #ifdef HAVE_APPARMOR
1031   BusAppArmorConfinement *con = NULL;
1032   DBusString qstr, auxdata;
1033   int allow = FALSE, audit = TRUE;
1034   dbus_bool_t free_auxdata = FALSE;
1035   unsigned long pid;
1036   int res, serrno = 0;
1037
1038   if (!apparmor_enabled)
1039     return TRUE;
1040
1041   con = bus_connection_dup_apparmor_confinement (connection);
1042
1043   if (is_unconfined (con->label, con->mode))
1044     {
1045       allow = TRUE;
1046       audit = FALSE;
1047       goto out;
1048     }
1049
1050   if (!_dbus_string_init (&qstr))
1051     goto oom;
1052
1053   if (!build_eavesdrop_query (&qstr, con->label, bustype))
1054     {
1055       _dbus_string_free (&qstr);
1056       goto oom;
1057     }
1058
1059   res = aa_query_label (AA_DBUS_EAVESDROP,
1060                         _dbus_string_get_data (&qstr),
1061                         _dbus_string_get_length (&qstr),
1062                         &allow, &audit);
1063   _dbus_string_free (&qstr);
1064   if (res == -1)
1065     {
1066       serrno = errno;
1067       set_error_from_query_errno (error, serrno);
1068       goto audit;
1069     }
1070
1071   /* Don't fail operations on profiles in complain mode */
1072   if (modestr_is_complain (con->mode))
1073     allow = TRUE;
1074
1075   if (!allow)
1076     dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1077                     "Connection \"%s\" is not allowed to eavesdrop due to "
1078                     "AppArmor policy",
1079                     bus_connection_is_active (connection) ?
1080                     bus_connection_get_name (connection) : "(inactive)");
1081
1082   if (!audit)
1083     goto out;
1084
1085  audit:
1086   if (!_dbus_string_init (&auxdata))
1087     goto oom;
1088   free_auxdata = TRUE;
1089
1090   if (!_dbus_append_pair_str (&auxdata, "bus", bustype ? bustype : "unknown"))
1091     goto oom;
1092
1093   if (serrno && !_dbus_append_pair_str (&auxdata, "info", strerror (serrno)))
1094     goto oom;
1095
1096   if (!_dbus_append_pair_str (&auxdata, "mask", "eavesdrop"))
1097     goto oom;
1098
1099   if (connection && dbus_connection_get_unix_process_id (connection, &pid) &&
1100       !_dbus_append_pair_uint (&auxdata, "pid", pid))
1101     goto oom;
1102
1103   if (con->label && !_dbus_append_pair_str (&auxdata, "label", con->label))
1104     goto oom;
1105
1106   log_message (allow, "eavesdrop", &auxdata);
1107
1108  out:
1109   if (con != NULL)
1110     bus_apparmor_confinement_unref (con);
1111   if (free_auxdata)
1112     _dbus_string_free (&auxdata);
1113
1114   return allow;
1115
1116  oom:
1117   if (error != NULL && !dbus_error_is_set (error))
1118     BUS_SET_OOM (error);
1119   allow = FALSE;
1120   goto out;
1121
1122 #else
1123   return TRUE;
1124 #endif /* HAVE_APPARMOR */
1125 }