bus/policy: separate prefix rules in default context
[platform/upstream/dbus.git] / bus / config-parser.c
index 4dc7d92..4221854 100644 (file)
@@ -66,7 +66,7 @@ typedef struct
     struct
     {
       PolicyType type;
-      unsigned long gid_uid_or_at_console;      
+      unsigned long gid_uid_or_at_console;
     } policy;
 
     struct
@@ -512,7 +512,7 @@ bus_config_parser_new (const DBusString      *basedir,
       parser->limits.pending_fd_timeout = 150000; /* 2.5 minutes */
       
       parser->limits.max_incomplete_connections = 64;
-      parser->limits.max_connections_per_user = 256;
+      parser->limits.max_connections_per_user = 512; /* 256 -> 512 */
       
       /* Note that max_completed_connections / max_connections_per_user
        * is the number of users that would have to work together to
@@ -538,7 +538,7 @@ bus_config_parser_new (const DBusString      *basedir,
       /* this is effectively a limit on message queue size for messages
        * that require a reply
        */
-      parser->limits.max_replies_per_connection = 128;
+      parser->limits.max_replies_per_connection = 1024; /* 128 -> 1024 */
     }
       
   parser->refcount = 1;
@@ -648,7 +648,7 @@ locate_attributes (BusConfigParser  *parser,
   const char *name;
   const char **retloc;
   int n_attrs;
-#define MAX_ATTRS 24
+#define MAX_ATTRS 25
   LocateAttr attrs[MAX_ATTRS];
   dbus_bool_t retval;
   int i;
@@ -1276,12 +1276,49 @@ start_busconfig_child (BusConfigParser   *parser,
     }
 }
 
+/*
+ * Parse an attribute named name, whose content is content, or NULL if
+ * missing. It is meant to be a (long) integer between min and max inclusive.
+ * If it is missing, use def as the default value (which does not
+ * necessarily need to be between min and max).
+ */
+static dbus_bool_t
+parse_int_attribute (const char *name,
+                     const char *content,
+                     long        min,
+                     long        max,
+                     long        def,
+                     long       *value,
+                     DBusError  *error)
+{
+  DBusString parse_string;
+
+  *value = def;
+
+  if (content == NULL)
+    return TRUE;
+
+  _dbus_string_init_const (&parse_string, content);
+
+  if (!_dbus_string_parse_int (&parse_string, 0, value, NULL) ||
+      *value < min || *value > max)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Bad value \"%s\" for %s attribute, must be an "
+                      "integer in range %ld to %ld inclusive",
+                      content, name, min, max);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static dbus_bool_t
 append_rule_from_element (BusConfigParser   *parser,
                           const char        *element_name,
                           const char       **attribute_names,
                           const char       **attribute_values,
-                          dbus_bool_t        allow,
+                          BusPolicyRuleAccess access,
                           DBusError         *error)
 {
   const char *log;
@@ -1291,9 +1328,11 @@ append_rule_from_element (BusConfigParser   *parser,
   const char *send_member;
   const char *send_error;
   const char *send_destination;
+  const char *send_destination_prefix;
   const char *send_path;
   const char *send_type;
   const char *send_requested_reply;
+  const char *send_broadcast;
   /* TRUE if any send_ attribute is present */
   dbus_bool_t any_send_attribute;
 
@@ -1310,6 +1349,10 @@ append_rule_from_element (BusConfigParser   *parser,
 
   /* Group: message-matching modifiers that can go on send_ or receive_ */
   const char *eavesdrop;
+  const char *max_fds_attr;
+  long max_fds = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
+  const char *min_fds_attr;
+  long min_fds = 0;
   /* TRUE if any message-matching modifier is present */
   dbus_bool_t any_message_attribute;
 
@@ -1318,6 +1361,7 @@ append_rule_from_element (BusConfigParser   *parser,
   const char *own_prefix;
   const char *user;
   const char *group;
+  const char *privilege;
 
   BusPolicyRule *rule;
 
@@ -1329,8 +1373,10 @@ append_rule_from_element (BusConfigParser   *parser,
                           "send_member", &send_member,
                           "send_error", &send_error,
                           "send_destination", &send_destination,
+                          "send_destination_prefix", &send_destination_prefix,
                           "send_path", &send_path,
                           "send_type", &send_type,
+                          "send_broadcast", &send_broadcast,
                           "receive_interface", &receive_interface,
                           "receive_member", &receive_member,
                           "receive_error", &receive_error,
@@ -1338,6 +1384,8 @@ append_rule_from_element (BusConfigParser   *parser,
                           "receive_path", &receive_path,
                           "receive_type", &receive_type,
                           "eavesdrop", &eavesdrop,
+                          "max_fds", &max_fds_attr,
+                          "min_fds", &min_fds_attr,
                           "send_requested_reply", &send_requested_reply,
                           "receive_requested_reply", &receive_requested_reply,
                           "own", &own,
@@ -1345,10 +1393,13 @@ append_rule_from_element (BusConfigParser   *parser,
                           "user", &user,
                           "group", &group,
                           "log", &log,
+                          "privilege", &privilege,
                           NULL))
     return FALSE;
 
   any_send_attribute = (send_destination != NULL ||
+                        send_destination_prefix != NULL ||
+                        send_broadcast != NULL ||
                         send_path != NULL ||
                         send_type != NULL ||
                         send_interface != NULL ||
@@ -1370,10 +1421,13 @@ append_rule_from_element (BusConfigParser   *parser,
                            (!any_send_attribute && eavesdrop != NULL));
   any_message_attribute = (any_send_attribute ||
                            any_receive_attribute ||
-                           eavesdrop != NULL);
+                           eavesdrop != NULL ||
+                           max_fds_attr != NULL ||
+                           min_fds_attr != NULL);
 
   if (!(any_send_attribute ||
         any_receive_attribute ||
+        privilege ||
         own || own_prefix || user || group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -1390,7 +1444,30 @@ append_rule_from_element (BusConfigParser   *parser,
                       element_name);
       return FALSE;
     }
-  
+
+  if (access == BUS_POLICY_RULE_ACCESS_CHECK)
+    {
+      if (privilege == NULL || !*privilege)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "On element <%s>, you must specify the privilege to be checked.",
+                          element_name);
+          return FALSE;
+        }
+    }
+  else
+    {
+      if (privilege != NULL && *privilege)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "On element <%s>, privilege %s is used outside of a check rule.",
+                          element_name, privilege);
+          return FALSE;
+        }
+      else
+        privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */
+    }
+
   /* Allowed combinations of elements are:
    *
    *   base, must be all send or all receive:
@@ -1399,7 +1476,8 @@ append_rule_from_element (BusConfigParser   *parser,
    *     interface + member
    *     error
    * 
-   *   base send_ can combine with send_destination, send_path, send_type, send_requested_reply, eavesdrop
+   *   base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop
+   *   send_destination must not occur with send_destination_prefix
    *   base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
    *
    *   user, group, own, own_prefix must occur alone
@@ -1496,6 +1574,29 @@ append_rule_from_element (BusConfigParser   *parser,
           return FALSE;
         }
 
+      if (send_broadcast &&
+          !(strcmp (send_broadcast, "true") == 0 ||
+            strcmp (send_broadcast, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for %s attribute, must be true or false",
+                          send_broadcast, "send_broadcast");
+          return FALSE;
+        }
+
+      if (send_destination != NULL &&
+          send_broadcast != NULL &&
+          strcmp (send_broadcast, "true") == 0)
+        {
+          /* Broadcast messages have no destination, so this cannot
+           * possibly match */
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Rule with send_broadcast=\"true\" and "
+                          "send_destination=\"%s\" cannot match anything",
+                          send_destination);
+          return FALSE;
+        }
+
       if (send_requested_reply &&
           !(strcmp (send_requested_reply, "true") == 0 ||
             strcmp (send_requested_reply, "false") == 0))
@@ -1505,8 +1606,20 @@ append_rule_from_element (BusConfigParser   *parser,
                           "send_requested_reply", send_requested_reply);
           return FALSE;
         }
-      
-      rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
+
+      /* Matching only messages with DBUS_MAXIMUM_MESSAGE_UNIX_FDS or fewer
+       * fds is the same as matching all messages, so we always set a maximum,
+       * but perhaps an unrealistically high one. */
+      if (!parse_int_attribute ("max_fds", max_fds_attr,
+                                0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+                                DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+                                error) ||
+          !parse_int_attribute ("min_fds", min_fds_attr,
+                                0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+                                error))
+        return FALSE;
+
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access);
       if (rule == NULL)
         goto nomem;
       
@@ -1519,12 +1632,36 @@ append_rule_from_element (BusConfigParser   *parser,
       if (send_requested_reply)
         rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0);
 
+      if (send_broadcast)
+        {
+          if (strcmp (send_broadcast, "true") == 0)
+            rule->d.send.broadcast = BUS_POLICY_TRISTATE_TRUE;
+          else
+            rule->d.send.broadcast = BUS_POLICY_TRISTATE_FALSE;
+        }
+      else
+        {
+          rule->d.send.broadcast = BUS_POLICY_TRISTATE_ANY;
+        }
+
       rule->d.send.message_type = message_type;
       rule->d.send.path = _dbus_strdup (send_path);
       rule->d.send.interface = _dbus_strdup (send_interface);
       rule->d.send.member = _dbus_strdup (send_member);
       rule->d.send.error = _dbus_strdup (send_error);
-      rule->d.send.destination = _dbus_strdup (send_destination);
+      if (send_destination)
+        {
+          rule->d.send.destination = _dbus_strdup (send_destination);
+          rule->d.send.destination_prefix = 0;
+        }
+      else if (send_destination_prefix)
+        {
+          rule->d.send.destination = _dbus_strdup (send_destination_prefix);
+          rule->d.send.destination_prefix = 1;
+        }
+      rule->d.send.max_fds = max_fds;
+      rule->d.send.min_fds = min_fds;
+
       if (send_path && rule->d.send.path == NULL)
         goto nomem;
       if (send_interface && rule->d.send.interface == NULL)
@@ -1533,7 +1670,7 @@ append_rule_from_element (BusConfigParser   *parser,
         goto nomem;
       if (send_error && rule->d.send.error == NULL)
         goto nomem;
-      if (send_destination && rule->d.send.destination == NULL)
+      if ((send_destination || send_destination_prefix) && rule->d.send.destination == NULL)
         goto nomem;
     }
   else if (any_receive_attribute)
@@ -1586,8 +1723,17 @@ append_rule_from_element (BusConfigParser   *parser,
                           "receive_requested_reply", receive_requested_reply);
           return FALSE;
         }
-      
-      rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
+
+      if (!parse_int_attribute ("max_fds", max_fds_attr,
+                                0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+                                DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+                                error) ||
+          !parse_int_attribute ("min_fds", min_fds_attr,
+                                0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+                                error))
+        return FALSE;
+
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access);
       if (rule == NULL)
         goto nomem;
 
@@ -1603,6 +1749,8 @@ append_rule_from_element (BusConfigParser   *parser,
       rule->d.receive.member = _dbus_strdup (receive_member);
       rule->d.receive.error = _dbus_strdup (receive_error);
       rule->d.receive.origin = _dbus_strdup (receive_sender);
+      rule->d.receive.max_fds = max_fds;
+      rule->d.receive.min_fds = min_fds;
 
       if (receive_path && rule->d.receive.path == NULL)
         goto nomem;
@@ -1617,7 +1765,7 @@ append_rule_from_element (BusConfigParser   *parser,
     }
   else if (own || own_prefix)
     {
-      rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); 
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access);
       if (rule == NULL)
         goto nomem;
 
@@ -1643,7 +1791,7 @@ append_rule_from_element (BusConfigParser   *parser,
     {      
       if (IS_WILDCARD (user))
         {
-          rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
+          rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
           if (rule == NULL)
             goto nomem;
 
@@ -1658,7 +1806,7 @@ append_rule_from_element (BusConfigParser   *parser,
       
           if (_dbus_parse_unix_user_from_config (&username, &uid))
             {
-              rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
+              rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
               if (rule == NULL)
                 goto nomem;
 
@@ -1675,7 +1823,7 @@ append_rule_from_element (BusConfigParser   *parser,
     {
       if (IS_WILDCARD (group))
         {
-          rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
+          rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
           if (rule == NULL)
             goto nomem;
 
@@ -1690,7 +1838,7 @@ append_rule_from_element (BusConfigParser   *parser,
           
           if (_dbus_parse_unix_group_from_config (&groupname, &gid))
             {
-              rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
+              rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
               if (rule == NULL)
                 goto nomem;
 
@@ -1714,6 +1862,10 @@ append_rule_from_element (BusConfigParser   *parser,
       _dbus_assert (pe != NULL);
       _dbus_assert (pe->type == ELEMENT_POLICY);
 
+      rule->privilege = _dbus_strdup (privilege);
+      if (privilege && !rule->privilege)
+        goto nomem;
+
       switch (pe->d.policy.type)
         {
         case POLICY_IGNORED:
@@ -1755,8 +1907,6 @@ append_rule_from_element (BusConfigParser   *parser,
                                              rule))
             goto nomem;
           break;
-        
-
         case POLICY_CONSOLE:
           if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
                                                rule))
@@ -1789,7 +1939,7 @@ start_policy_child (BusConfigParser   *parser,
     {
       if (!append_rule_from_element (parser, element_name,
                                      attribute_names, attribute_values,
-                                     TRUE, error))
+                                     BUS_POLICY_RULE_ACCESS_ALLOW, error))
         return FALSE;
       
       if (push_element (parser, ELEMENT_ALLOW) == NULL)
@@ -1804,7 +1954,7 @@ start_policy_child (BusConfigParser   *parser,
     {
       if (!append_rule_from_element (parser, element_name,
                                      attribute_names, attribute_values,
-                                     FALSE, error))
+                                     BUS_POLICY_RULE_ACCESS_DENY, error))
         return FALSE;
       
       if (push_element (parser, ELEMENT_DENY) == NULL)
@@ -1815,6 +1965,21 @@ start_policy_child (BusConfigParser   *parser,
       
       return TRUE;
     }
+  else if (strcmp (element_name, "check") == 0)
+    {
+      if (!append_rule_from_element (parser, element_name,
+                                     attribute_names, attribute_values,
+                                     BUS_POLICY_RULE_ACCESS_CHECK, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_CHECK) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
   else
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -2175,6 +2340,7 @@ bus_config_parser_end_element (BusConfigParser   *parser,
     case ELEMENT_POLICY:
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
+    case ELEMENT_CHECK:
     case ELEMENT_FORK:
     case ELEMENT_SYSLOG:
     case ELEMENT_KEEP_UMASK:
@@ -2491,6 +2657,7 @@ bus_config_parser_content (BusConfigParser   *parser,
     case ELEMENT_POLICY:
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
+    case ELEMENT_CHECK:
     case ELEMENT_FORK:
     case ELEMENT_SYSLOG:
     case ELEMENT_KEEP_UMASK:
@@ -3018,6 +3185,8 @@ do_load (const DBusString *full_path,
   dbus_error_init (&error);
 
   parser = bus_config_load (full_path, TRUE, NULL, &error);
+  if (dbus_error_is_set (&error))
+    _dbus_verbose ("Failed to load file: %s\n", error.message);
   if (parser == NULL)
     {
       _DBUS_ASSERT_ERROR_IS_SET (&error);