diff options
Diffstat (limited to 'bus')
-rw-r--r-- | bus/activation.c | 2 | ||||
-rw-r--r-- | bus/bus.c | 186 | ||||
-rw-r--r-- | bus/bus.h | 6 | ||||
-rw-r--r-- | bus/config-parser-common.c | 18 | ||||
-rw-r--r-- | bus/config-parser-common.h | 5 | ||||
-rw-r--r-- | bus/config-parser.c | 85 | ||||
-rw-r--r-- | bus/config-parser.h | 3 | ||||
-rw-r--r-- | bus/connection.c | 104 | ||||
-rw-r--r-- | bus/connection.h | 1 | ||||
-rw-r--r-- | bus/dbus-daemon.1.in | 37 | ||||
-rw-r--r-- | bus/driver.c | 2 | ||||
-rw-r--r-- | bus/main.c | 23 | ||||
-rw-r--r-- | bus/policy.c | 12 | ||||
-rw-r--r-- | bus/policy.h | 8 | ||||
-rw-r--r-- | bus/session.conf.in | 4 | ||||
-rw-r--r-- | bus/system.conf.in | 35 |
16 files changed, 449 insertions, 82 deletions
diff --git a/bus/activation.c b/bus/activation.c index 18630958..a273c4ad 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -679,7 +679,7 @@ populate_environment (BusActivation *activation) DBusString value; int i; char **environment; - dbus_bool_t retval; + dbus_bool_t retval = FALSE; environment = _dbus_get_environment (); @@ -54,6 +54,9 @@ struct BusContext BusMatchmaker *matchmaker; BusLimits limits; unsigned int fork : 1; + unsigned int syslog : 1; + unsigned int keep_umask : 1; + unsigned int allow_anonymous : 1; }; static dbus_int32_t server_data_slot = -1; @@ -188,6 +191,9 @@ new_connection_callback (DBusServer *server, dbus_connection_set_max_message_size (new_connection, context->limits.max_message_size); + dbus_connection_set_allow_anonymous (new_connection, + context->allow_anonymous); + /* on OOM, we won't have ref'd the connection so it will die. */ } @@ -384,6 +390,9 @@ process_config_first_time_only (BusContext *context, } context->fork = bus_config_parser_get_fork (parser); + context->syslog = bus_config_parser_get_syslog (parser); + context->keep_umask = bus_config_parser_get_keep_umask (parser); + context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser); _DBUS_ASSERT_ERROR_IS_CLEAR (error); retval = TRUE; @@ -708,7 +717,8 @@ bus_context_new (const DBusString *config_file, if (!_dbus_become_daemon (context->pidfile ? &u : NULL, print_pid_pipe, - error)) + error, + context->keep_umask)) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed; @@ -736,6 +746,11 @@ bus_context_new (const DBusString *config_file, if (print_pid_pipe && _dbus_pipe_is_valid (print_pid_pipe) && !_dbus_pipe_is_stdout_or_stderr (print_pid_pipe)) _dbus_pipe_close (print_pid_pipe, NULL); + + if (!bus_selinux_full_init ()) + { + _dbus_warn ("SELinux initialization failed\n"); + } if (!process_config_postinit (context, parser, error)) { @@ -766,11 +781,6 @@ bus_context_new (const DBusString *config_file, #endif } - if (!bus_selinux_full_init ()) - { - _dbus_warn ("SELinux initialization failed\n"); - } - dbus_server_free_data_slot (&server_data_slot); return context; @@ -826,7 +836,10 @@ bus_context_reload_config (BusContext *context, } ret = TRUE; + bus_context_log_info (context, "Reloaded configuration"); failed: + if (!ret) + bus_context_log_info (context, "Unable to reload configuration: %s", error->message); if (parser != NULL) bus_config_parser_unref (parser); return ret; @@ -1107,6 +1120,32 @@ bus_context_get_reply_timeout (BusContext *context) return context->limits.reply_timeout; } +void +bus_context_log_info (BusContext *context, const char *msg, ...) +{ + va_list args; + + va_start (args, msg); + + if (context->syslog) + _dbus_log_info (msg, args); + + va_end (args); +} + +void +bus_context_log_security (BusContext *context, const char *msg, ...) +{ + va_list args; + + va_start (args, msg); + + if (context->syslog) + _dbus_log_security (msg, args); + + va_end (args); +} + /* * addressed_recipient is the recipient specified in the message. * @@ -1129,20 +1168,44 @@ bus_context_check_security_policy (BusContext *context, DBusMessage *message, DBusError *error) { + const char *dest; BusClientPolicy *sender_policy; BusClientPolicy *recipient_policy; + dbus_int32_t toggles; + dbus_bool_t log; int type; dbus_bool_t requested_reply; + const char *sender_name; + const char *sender_loginfo; + const char *proposed_recipient_loginfo; type = dbus_message_get_type (message); + dest = dbus_message_get_destination (message); /* dispatch.c was supposed to ensure these invariants */ - _dbus_assert (dbus_message_get_destination (message) != NULL || + _dbus_assert (dest != NULL || type == DBUS_MESSAGE_TYPE_SIGNAL || (sender == NULL && !bus_connection_is_active (proposed_recipient))); _dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL || addressed_recipient != NULL || - strcmp (dbus_message_get_destination (message), DBUS_SERVICE_DBUS) == 0); + strcmp (dest, DBUS_SERVICE_DBUS) == 0); + + /* Used in logging below */ + if (sender != NULL) + { + sender_name = bus_connection_get_name (sender); + sender_loginfo = bus_connection_get_loginfo (sender); + } + else + { + sender_name = NULL; + sender_loginfo = "(bus)"; + } + + if (proposed_recipient != NULL) + proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient); + else + proposed_recipient_loginfo = "bus"; switch (type) { @@ -1166,10 +1229,6 @@ bus_context_check_security_policy (BusContext *context, if (sender != NULL) { - const char *dest; - - dest = dbus_message_get_destination (message); - /* First verify the SELinux access controls. If allowed then * go on with the standard checks. */ @@ -1185,8 +1244,9 @@ bus_context_check_security_policy (BusContext *context, dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "An SELinux policy prevents this sender " "from sending this message to this recipient " - "(rejected message had interface \"%s\" " + "(rejected message had sender \"%s\" interface \"%s\" " "member \"%s\" error name \"%s\" destination \"%s\")", + sender_name ? sender_name : "(unset)", dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "(unset)", dbus_message_get_member (message) ? @@ -1299,57 +1359,112 @@ bus_context_check_security_policy (BusContext *context, (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) || (proposed_recipient == NULL && recipient_policy == NULL)); + log = FALSE; if (sender_policy && !bus_client_policy_check_can_send (sender_policy, context->registry, requested_reply, proposed_recipient, - message)) + message, &toggles, &log)) { - const char *dest; - - dest = dbus_message_get_destination (message); - dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, - "A security policy in place prevents this sender " - "from sending this message to this recipient, " - "see message bus configuration file (rejected message " - "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\")", + const char *msg = "Rejected send message, %d matched rules; " + "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))"; + + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg, + toggles, + dbus_message_type_to_string (dbus_message_get_type (message)), + sender_name ? sender_name : "(unset)", + sender_loginfo, dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "(unset)", dbus_message_get_member (message) ? dbus_message_get_member (message) : "(unset)", dbus_message_get_error_name (message) ? dbus_message_get_error_name (message) : "(unset)", - dest ? dest : DBUS_SERVICE_DBUS); + requested_reply, + dest ? dest : DBUS_SERVICE_DBUS, + proposed_recipient_loginfo); + /* Needs to be duplicated to avoid calling malloc and having to handle OOM */ + if (addressed_recipient == proposed_recipient) + bus_context_log_security (context, msg, + toggles, + dbus_message_type_to_string (dbus_message_get_type (message)), + sender_name ? sender_name : "(unset)", + sender_loginfo, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : "(unset)", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : "(unset)", + dbus_message_get_error_name (message) ? + dbus_message_get_error_name (message) : "(unset)", + requested_reply, + dest ? dest : DBUS_SERVICE_DBUS, + proposed_recipient_loginfo); _dbus_verbose ("security policy disallowing message due to sender policy\n"); return FALSE; } + if (log) + bus_context_log_security (context, + "Would reject message, %d matched rules; " + "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))", + toggles, + dbus_message_type_to_string (dbus_message_get_type (message)), + sender_name ? sender_name : "(unset)", + sender_loginfo, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : "(unset)", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : "(unset)", + dbus_message_get_error_name (message) ? + dbus_message_get_error_name (message) : "(unset)", + requested_reply, + dest ? dest : DBUS_SERVICE_DBUS, + proposed_recipient_loginfo); + if (recipient_policy && !bus_client_policy_check_can_receive (recipient_policy, context->registry, requested_reply, sender, addressed_recipient, proposed_recipient, - message)) + message, &toggles)) { - const char *dest; - - dest = dbus_message_get_destination (message); - dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, - "A security policy in place prevents this recipient " - "from receiving this message from this sender, " - "see message bus configuration file (rejected message " - "had interface \"%s\" member \"%s\" error name \"%s\" destination \"%s\" reply serial %u requested_reply=%d)", + const char *msg = "Rejected receive message, %d matched rules; " + "type=\"%s\" sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" reply serial=%u requested_reply=%d destination=\"%s\" (%s))"; + + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg, + toggles, + dbus_message_type_to_string (dbus_message_get_type (message)), + sender_name ? sender_name : "(unset)", + sender_loginfo, dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "(unset)", dbus_message_get_member (message) ? dbus_message_get_member (message) : "(unset)", dbus_message_get_error_name (message) ? dbus_message_get_error_name (message) : "(unset)", - dest ? dest : DBUS_SERVICE_DBUS, dbus_message_get_reply_serial (message), - requested_reply); + requested_reply, + dest ? dest : DBUS_SERVICE_DBUS, + proposed_recipient_loginfo); + /* Needs to be duplicated to avoid calling malloc and having to handle OOM */ + if (addressed_recipient == proposed_recipient) + bus_context_log_security (context, msg, + toggles, + dbus_message_type_to_string (dbus_message_get_type (message)), + sender_name ? sender_name : "(unset)", + sender_loginfo, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : "(unset)", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : "(unset)", + dbus_message_get_error_name (message) ? + dbus_message_get_error_name (message) : "(unset)", + dbus_message_get_reply_serial (message), + requested_reply, + dest ? dest : DBUS_SERVICE_DBUS, + proposed_recipient_loginfo); _dbus_verbose ("security policy disallowing message due to recipient policy\n"); return FALSE; } @@ -1359,9 +1474,6 @@ bus_context_check_security_policy (BusContext *context, dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) { - const char *dest; - - dest = dbus_message_get_destination (message); dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "The destination service \"%s\" has a full message queue", dest ? dest : (proposed_recipient ? @@ -107,6 +107,12 @@ int bus_context_get_max_services_per_connection (BusContext int bus_context_get_max_match_rules_per_connection (BusContext *context); int bus_context_get_max_replies_per_connection (BusContext *context); int bus_context_get_reply_timeout (BusContext *context); +void bus_context_log_info (BusContext *context, + const char *msg, + ...); +void bus_context_log_security (BusContext *context, + const char *msg, + ...); dbus_bool_t bus_context_check_security_policy (BusContext *context, BusTransaction *transaction, DBusConnection *sender, diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c index 6e4bb701..4965c192 100644 --- a/bus/config-parser-common.c +++ b/bus/config-parser-common.c @@ -114,6 +114,18 @@ bus_config_parser_element_name_to_type (const char *name) { return ELEMENT_ASSOCIATE; } + else if (strcmp (name, "keep_umask") == 0) + { + return ELEMENT_KEEP_UMASK; + } + else if (strcmp (name, "syslog") == 0) + { + return ELEMENT_SYSLOG; + } + else if (strcmp (name, "allow_anonymous") == 0) + { + return ELEMENT_ALLOW_ANONYMOUS; + } return ELEMENT_NONE; } @@ -162,6 +174,12 @@ bus_config_parser_element_type_to_name (ElementType type) return "selinux"; case ELEMENT_ASSOCIATE: return "associate"; + case ELEMENT_KEEP_UMASK: + return "keep_umask"; + case ELEMENT_SYSLOG: + return "syslog"; + case ELEMENT_ALLOW_ANONYMOUS: + return "allow_anonymous"; } _dbus_assert_not_reached ("bad element type"); diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h index 3718c958..2c296433 100644 --- a/bus/config-parser-common.h +++ b/bus/config-parser-common.h @@ -47,7 +47,10 @@ typedef enum ELEMENT_SELINUX, ELEMENT_ASSOCIATE, ELEMENT_STANDARD_SESSION_SERVICEDIRS, - ELEMENT_STANDARD_SYSTEM_SERVICEDIRS + ELEMENT_STANDARD_SYSTEM_SERVICEDIRS, + ELEMENT_KEEP_UMASK, + ELEMENT_SYSLOG, + ELEMENT_ALLOW_ANONYMOUS } ElementType; ElementType bus_config_parser_element_name_to_type (const char *element_name); diff --git a/bus/config-parser.c b/bus/config-parser.c index f9e0b7d7..34d8684a 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -111,7 +111,13 @@ struct BusConfigParser unsigned int fork : 1; /**< TRUE to fork into daemon mode */ + unsigned int keep_umask : 1; /**< TRUE to keep original umask when forking */ + + unsigned int syslog : 1; /**< TRUE to enable syslog */ + unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */ + + unsigned int allow_anonymous : 1; /**< TRUE to allow anonymous connections */ }; static Element* @@ -306,6 +312,9 @@ merge_included (BusConfigParser *parser, if (included->fork) parser->fork = TRUE; + if (included->keep_umask) + parser->keep_umask = TRUE; + if (included->pidfile != NULL) { dbus_free (parser->pidfile); @@ -698,6 +707,36 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (element_type == ELEMENT_KEEP_UMASK) + { + if (!check_no_attributes (parser, "keep_umask", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_KEEP_UMASK) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + parser->keep_umask = TRUE; + + return TRUE; + } + else if (element_type == ELEMENT_SYSLOG) + { + if (!check_no_attributes (parser, "syslog", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_SYSLOG) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + parser->syslog = TRUE; + + return TRUE; + } else if (element_type == ELEMENT_PIDFILE) { if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error)) @@ -815,6 +854,20 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (element_type == ELEMENT_ALLOW_ANONYMOUS) + { + if (!check_no_attributes (parser, "allow_anonymous", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_ALLOW_ANONYMOUS) == NULL) + { + BUS_SET_OOM (error); + return FALSE; + } + + parser->allow_anonymous = TRUE; + return TRUE; + } else if (element_type == ELEMENT_SERVICEDIR) { if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error)) @@ -1073,6 +1126,7 @@ append_rule_from_element (BusConfigParser *parser, dbus_bool_t allow, DBusError *error) { + const char *log; const char *send_interface; const char *send_member; const char *send_error; @@ -1116,6 +1170,7 @@ append_rule_from_element (BusConfigParser *parser, "own", &own, "user", &user, "group", &group, + "log", &log, NULL)) return FALSE; @@ -1320,6 +1375,9 @@ append_rule_from_element (BusConfigParser *parser, if (eavesdrop) rule->d.send.eavesdrop = (strcmp (eavesdrop, "true") == 0); + if (log) + rule->d.send.log = (strcmp (log, "true") == 0); + if (send_requested_reply) rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0); @@ -1947,10 +2005,13 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_ALLOW: case ELEMENT_DENY: case ELEMENT_FORK: + case ELEMENT_KEEP_UMASK: + case ELEMENT_SYSLOG: case ELEMENT_SELINUX: case ELEMENT_ASSOCIATE: case ELEMENT_STANDARD_SESSION_SERVICEDIRS: case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_ALLOW_ANONYMOUS: break; } @@ -2232,8 +2293,11 @@ bus_config_parser_content (BusConfigParser *parser, case ELEMENT_ALLOW: case ELEMENT_DENY: case ELEMENT_FORK: + case ELEMENT_KEEP_UMASK: + case ELEMENT_SYSLOG: case ELEMENT_STANDARD_SESSION_SERVICEDIRS: case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS: + case ELEMENT_ALLOW_ANONYMOUS: case ELEMENT_SELINUX: case ELEMENT_ASSOCIATE: if (all_whitespace (content)) @@ -2554,6 +2618,24 @@ bus_config_parser_get_fork (BusConfigParser *parser) return parser->fork; } +dbus_bool_t +bus_config_parser_get_keep_umask (BusConfigParser *parser) +{ + return parser->keep_umask; +} + +dbus_bool_t +bus_config_parser_get_syslog (BusConfigParser *parser) +{ + return parser->syslog; +} + +dbus_bool_t +bus_config_parser_get_allow_anonymous (BusConfigParser *parser) +{ + return parser->allow_anonymous; +} + const char * bus_config_parser_get_pidfile (BusConfigParser *parser) { @@ -2947,6 +3029,9 @@ config_parsers_equal (const BusConfigParser *a, if (! bools_equal (a->fork, b->fork)) return FALSE; + if (! bools_equal (a->keep_umask, b->keep_umask)) + return FALSE; + if (! bools_equal (a->is_toplevel, b->is_toplevel)) return FALSE; diff --git a/bus/config-parser.h b/bus/config-parser.h index ec0dfed1..bb3a30f4 100644 --- a/bus/config-parser.h +++ b/bus/config-parser.h @@ -65,6 +65,9 @@ const char* bus_config_parser_get_type (BusConfigParser *parser); DBusList** bus_config_parser_get_addresses (BusConfigParser *parser); DBusList** bus_config_parser_get_mechanisms (BusConfigParser *parser); dbus_bool_t bus_config_parser_get_fork (BusConfigParser *parser); +dbus_bool_t bus_config_parser_get_allow_anonymous (BusConfigParser *parser); +dbus_bool_t bus_config_parser_get_syslog (BusConfigParser *parser); +dbus_bool_t bus_config_parser_get_keep_umask (BusConfigParser *parser); const char* bus_config_parser_get_pidfile (BusConfigParser *parser); const char* bus_config_parser_get_servicehelper (BusConfigParser *parser); DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser); diff --git a/bus/connection.c b/bus/connection.c index ed1b1391..9159c898 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -32,6 +32,9 @@ #include <dbus/dbus-hash.h> #include <dbus/dbus-timeout.h> +/* Trim executed commands to this length; we want to keep logs readable */ +#define MAX_LOG_COMMAND_LEN 50 + static void bus_connection_remove_transactions (DBusConnection *connection); typedef struct @@ -76,6 +79,7 @@ typedef struct DBusPreallocatedSend *oom_preallocated; BusClientPolicy *policy; + char *cached_loginfo_string; BusSELinuxID *selinux_id; long connection_tv_sec; /**< Time when we connected (seconds component) */ @@ -406,6 +410,8 @@ free_connection_data (void *data) if (d->selinux_id) bus_selinux_id_unref (d->selinux_id); + dbus_free (d->cached_loginfo_string); + dbus_free (d->name); dbus_free (d); @@ -537,13 +543,72 @@ bus_connections_unref (BusConnections *connections) } } +/* Used for logging */ +static dbus_bool_t +cache_peer_loginfo_string (BusConnectionData *d, + DBusConnection *connection) +{ + DBusString loginfo_buf; + unsigned long uid; + unsigned long pid; + char *windows_sid; + dbus_bool_t prev_added; + + if (!_dbus_string_init (&loginfo_buf)) + return FALSE; + + prev_added = FALSE; + if (dbus_connection_get_unix_user (connection, &uid)) + { + if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid)) + goto oom; + else + prev_added = TRUE; + } + + if (dbus_connection_get_unix_process_id (connection, &pid)) + { + if (prev_added) + { + if (!_dbus_string_append_byte (&loginfo_buf, ' ')) + goto oom; + } + if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid)) + goto oom; + /* Ignore errors here; we may not have permissions to read the + * proc file. */ + _dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL); + if (!_dbus_string_append_byte (&loginfo_buf, '"')) + goto oom; + } + + if (dbus_connection_get_windows_user (connection, &windows_sid)) + { + if (!_dbus_string_append_printf (&loginfo_buf, "sid=\"%s\" ", windows_sid)) + goto oom; + dbus_free (windows_sid); + } + + if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string))) + goto oom; + + _dbus_string_free (&loginfo_buf); + + return TRUE; +oom: + _dbus_string_free (&loginfo_buf); + return FALSE; +} + dbus_bool_t bus_connections_setup_connection (BusConnections *connections, DBusConnection *connection) { + BusConnectionData *d; dbus_bool_t retval; DBusError error; + d = dbus_new0 (BusConnectionData, 1); @@ -583,7 +648,7 @@ bus_connections_setup_connection (BusConnections *connections, dbus_error_free (&error); goto out; } - + if (!dbus_connection_set_watch_functions (connection, add_connection_watch, remove_connection_watch, @@ -842,6 +907,18 @@ bus_connection_is_in_unix_group (DBusConnection *connection, return FALSE; } +const char * +bus_connection_get_loginfo (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + + if (!bus_connection_is_active (connection)) + return "inactive"; + return d->cached_loginfo_string; +} + BusClientPolicy* bus_connection_get_policy (DBusConnection *connection) { @@ -1302,16 +1379,15 @@ bus_connection_complete (DBusConnection *connection, { if (!adjust_connections_for_uid (d->connections, uid, 1)) - { - BUS_SET_OOM (error); - dbus_free (d->name); - d->name = NULL; - bus_client_policy_unref (d->policy); - d->policy = NULL; - return FALSE; - } + goto fail; } - + + /* Create and cache a string which holds information about the + * peer process; used for logging purposes. + */ + if (!cache_peer_loginfo_string (d, connection)) + goto fail; + /* Now the connection is active, move it between lists */ _dbus_list_unlink (&d->connections->incomplete, d->link_in_connection_list); @@ -1329,6 +1405,14 @@ bus_connection_complete (DBusConnection *connection, _dbus_assert (bus_connection_is_active (connection)); return TRUE; +fail: + BUS_SET_OOM (error); + dbus_free (d->name); + d->name = NULL; + if (d->policy) + bus_client_policy_unref (d->policy); + d->policy = NULL; + return FALSE; } const char * diff --git a/bus/connection.h b/bus/connection.h index 5099bcf9..4f352169 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -50,6 +50,7 @@ BusConnections* bus_connection_get_connections (DBusConnection BusRegistry* bus_connection_get_registry (DBusConnection *connection); BusActivation* bus_connection_get_activation (DBusConnection *connection); BusMatchmaker* bus_connection_get_matchmaker (DBusConnection *connection); +const char * bus_connection_get_loginfo (DBusConnection *connection); BusSELinuxID* bus_connection_get_selinux_id (DBusConnection *connection); dbus_bool_t bus_connections_check_limits (BusConnections *connections, DBusConnection *requesting_completion, diff --git a/bus/dbus-daemon.1.in b/bus/dbus-daemon.1.in index 5599afe6..4b55ac29 100644 --- a/bus/dbus-daemon.1.in +++ b/bus/dbus-daemon.1.in @@ -1,6 +1,6 @@ .\" .\" dbus-daemon manual page. -.\" Copyright (C) 2003 Red Hat, Inc. +.\" Copyright (C) 2003,2008 Red Hat, Inc. .\" .TH dbus-daemon 1 .SH NAME @@ -214,6 +214,13 @@ into the background, etc.). This is generally used rather than the \-\-fork command line option. .TP +.I "<keep_umask>" + +.PP +If present, the bus daemon keeps its original umask when forking. +This may be useful to avoid affecting the behavior of child processes. + +.TP .I "<listen>" .PP @@ -410,15 +417,27 @@ they are analogous to a firewall in that they allow expected traffic and prevent unexpected traffic. .PP -The <policy> element has one of three attributes: +Currently, the system bus has a default-deny policy for sending method calls +and owning bus names. Everything else, in particular reply messages, receive +checks, and signals has a default allow policy. + +.PP +In general, it is best to keep system services as small, targeted programs which +run in their own process and provide a single bus name. Then, all that is needed +is an <allow> rule for the "own" permission to let the process claim the bus +name, and a "send_destination" rule to allow traffic from some or all uids to +your service. + +.PP +The <policy> element has one of four attributes: .nf context="(default|mandatory)" + at_console="(true|false)" user="username or userid" group="group name or gid" .fi .PP - Policies are applied to a connection as follows: .nf - all context="default" policies are applied @@ -426,6 +445,8 @@ Policies are applied to a connection as follows: in undefined order - all user="connection's auth user" policies are applied in undefined order + - all at_console="true" policies are applied + - all at_console="false" policies are applied - all context="mandatory" policies are applied .fi @@ -474,9 +495,7 @@ The possible attributes of these elements are: .PP Examples: .nf - <deny send_interface="org.freedesktop.System" send_member="Reboot"/> - <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/> - <deny own="org.freedesktop.System"/> + <deny send_destination="org.freedesktop.Service" send_interface="org.freedesktop.System" send_member="Reboot"/> <deny send_destination="org.freedesktop.System"/> <deny receive_sender="org.freedesktop.System"/> <deny user="john"/> @@ -566,7 +585,11 @@ received" are evaluated separately. .PP Be careful with send_interface/receive_interface, because the -interface field in messages is optional. +interface field in messages is optional. In particular, do NOT +specify <deny send_interface="org.foo.Bar"/>! This will cause +no-interface messages to be blocked for all services, which is +almost certainly not what you intended. Always use rules of +the form: <deny send_interface="org.foo.Bar" send_destination="org.foo.Service"/> .TP .I "<selinux>" diff --git a/bus/driver.c b/bus/driver.c index 05ecd56c..c97bff5d 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1411,7 +1411,7 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, BusService *serv; DBusConnection *conn; DBusMessage *reply; - char *data = NULL; + void *data = NULL; dbus_uint32_t data_size; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -44,7 +44,6 @@ static void close_reload_pipe (void); static void signal_handler (int sig) { - DBusString str; switch (sig) { @@ -52,16 +51,20 @@ signal_handler (int sig) case SIGIO: /* explicit fall-through */ #endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */ +#ifdef SIGHUP case SIGHUP: - _dbus_string_init_const (&str, "foo"); - if ((reload_pipe[RELOAD_WRITE_END] > 0) && - !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1)) - { - _dbus_warn ("Unable to write to reload pipe.\n"); - close_reload_pipe (); - } + { + DBusString str; + _dbus_string_init_const (&str, "foo"); + if ((reload_pipe[RELOAD_WRITE_END] > 0) && + !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1)) + { + _dbus_warn ("Unable to write to reload pipe.\n"); + close_reload_pipe (); + } + } break; - +#endif case SIGTERM: _dbus_loop_quit (bus_context_get_loop (context)); break; @@ -458,7 +461,9 @@ main (int argc, char **argv) setup_reload_pipe (bus_context_get_loop (context)); +#ifdef SIGHUP _dbus_set_signal_handler (SIGHUP, signal_handler); +#endif _dbus_set_signal_handler (SIGTERM, signal_handler); #ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX _dbus_set_signal_handler (SIGIO, signal_handler); diff --git a/bus/policy.c b/bus/policy.c index caa544e7..ef31800f 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -866,7 +866,9 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, BusRegistry *registry, dbus_bool_t requested_reply, DBusConnection *receiver, - DBusMessage *message) + DBusMessage *message, + dbus_int32_t *toggles, + dbus_bool_t *log) { DBusList *link; dbus_bool_t allowed; @@ -876,6 +878,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, */ _dbus_verbose (" (policy) checking send rules\n"); + *toggles = 0; allowed = FALSE; link = _dbus_list_get_first_link (&policy->rules); @@ -1026,6 +1029,8 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, /* Use this rule */ allowed = rule->allow; + *log = rule->d.send.log; + (*toggles)++; _dbus_verbose (" (policy) used rule, allow now = %d\n", allowed); @@ -1044,7 +1049,8 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, DBusConnection *sender, DBusConnection *addressed_recipient, DBusConnection *proposed_recipient, - DBusMessage *message) + DBusMessage *message, + dbus_int32_t *toggles) { DBusList *link; dbus_bool_t allowed; @@ -1059,6 +1065,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, */ _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping); + *toggles = 0; allowed = FALSE; link = _dbus_list_get_first_link (&policy->rules); @@ -1223,6 +1230,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, /* Use this rule */ allowed = rule->allow; + (*toggles)++; _dbus_verbose (" (policy) used rule, allow now = %d\n", allowed); diff --git a/bus/policy.h b/bus/policy.h index adb9a059..a75e0dd9 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -65,6 +65,7 @@ struct BusPolicyRule char *destination; unsigned int eavesdrop : 1; unsigned int requested_reply : 1; + unsigned int log : 1; } send; struct @@ -141,14 +142,17 @@ dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy, BusRegistry *registry, dbus_bool_t requested_reply, DBusConnection *receiver, - DBusMessage *message); + DBusMessage *message, + dbus_int32_t *toggles, + dbus_bool_t *log); dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy, BusRegistry *registry, dbus_bool_t requested_reply, DBusConnection *sender, DBusConnection *addressed_recipient, DBusConnection *proposed_recipient, - DBusMessage *message); + DBusMessage *message, + dbus_int32_t *toggles); dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy, DBusConnection *connection, const DBusString *service_name); diff --git a/bus/session.conf.in b/bus/session.conf.in index b2dee5b3..794eb8da 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -8,6 +8,10 @@ <!-- Our well-known bus type, don't change this --> <type>session</type> + <!-- If we fork, keep the user's original umask to avoid affecting + the behavior of child processes. --> + <keep_umask/> + <listen>unix:tmpdir=@DBUS_SESSION_SOCKET_DIR@</listen> <standard_session_servicedirs /> diff --git a/bus/system.conf.in b/bus/system.conf.in index 6a71926e..92f4cc42 100644 --- a/bus/system.conf.in +++ b/bus/system.conf.in @@ -29,6 +29,9 @@ <!-- Write a pid file --> <pidfile>@DBUS_SYSTEM_PID_FILE@</pidfile> + <!-- Enable logging to syslog --> + <syslog/> + <!-- Only allow socket-credentials-based authentication --> <auth>EXTERNAL</auth> @@ -39,21 +42,29 @@ <listen>@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@</listen> <policy context="default"> - <!-- Deny everything then punch holes --> - <deny send_interface="*"/> - <deny receive_interface="*"/> - <deny own="*"/> - <!-- But allow all users to connect --> + <!-- All users can connect to system bus --> <allow user="*"/> + + <!-- Holes must be punched in service configuration files for + name ownership and sending method calls --> + <deny own="*"/> + <deny send_type="method_call"/> + + <!-- Signals and reply messages (method returns, errors) are allowed + by default --> + <allow send_type="signal"/> + <allow send_requested_reply="true" send_type="method_return"/> + <allow send_requested_reply="true" send_type="error"/> + + <!-- All messages may be received by default --> + <allow receive_type="method_call"/> + <allow receive_type="method_return"/> + <allow receive_type="error"/> + <allow receive_type="signal"/> + <!-- Allow anyone to talk to the message bus --> - <!-- FIXME I think currently these allow rules are always implicit - even if they aren't in here --> <allow send_destination="org.freedesktop.DBus"/> - <allow receive_sender="org.freedesktop.DBus"/> - <!-- valid replies are always allowed --> - <allow send_requested_reply="true"/> - <allow receive_requested_reply="true"/> - <!-- disallow changing the activation environment of system services --> + <!-- But disallow some specific bus services --> <deny send_destination="org.freedesktop.DBus" send_interface="org.freedesktop.DBus" send_member="UpdateActivationEnvironment"/> |