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