summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2007-06-09 23:41:33 +0000
committerHavoc Pennington <hp@redhat.com>2007-06-09 23:41:33 +0000
commit7be5fd95cdccdca28937804f32ca8b1308887d09 (patch)
tree2425bc50d77fbbbe6b6077d9e6dd053b936dcde1
parent23832672266bb4ff23b66247c0cfa1a2ed0cc97b (diff)
2007-06-09 Havoc Pennington <hp@redhat.com>
* bus/policy.c (bus_policy_create_client_policy): gracefully continue if the connection has no unix user - just don't apply any unix user dependent rules. * bus/config-parser.c: remove dbus-userdb.h usage * bus/bus.c: remove dbus-userdb.h usage * dbus/dbus-transport.c (_dbus_transport_get_is_authenticated): support Windows user function; also, fix the logic for checking auth as root in the default auth code (broken in the previous commit) * dbus/dbus-connection.c (dbus_connection_set_windows_user_function): new function (dbus_connection_get_windows_user): new function
-rw-r--r--ChangeLog19
-rw-r--r--bus/bus.c23
-rw-r--r--bus/bus.h4
-rw-r--r--bus/config-parser.c15
-rw-r--r--bus/connection.c43
-rw-r--r--bus/connection.h12
-rw-r--r--bus/policy.c88
-rw-r--r--bus/policy.h4
-rw-r--r--dbus/dbus-connection.c141
-rw-r--r--dbus/dbus-connection.h24
-rw-r--r--dbus/dbus-sysdeps-unix.c13
-rw-r--r--dbus/dbus-sysdeps-unix.h2
-rw-r--r--dbus/dbus-sysdeps-util-unix.c92
-rw-r--r--dbus/dbus-sysdeps.h20
-rw-r--r--dbus/dbus-test.c4
-rw-r--r--dbus/dbus-transport-protected.h5
-rw-r--r--dbus/dbus-transport.c319
-rw-r--r--dbus/dbus-transport.h8
18 files changed, 644 insertions, 192 deletions
diff --git a/ChangeLog b/ChangeLog
index 4fe45e26..c7d2479b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2007-06-09 Havoc Pennington <hp@redhat.com>
+ * bus/policy.c (bus_policy_create_client_policy): gracefully
+ continue if the connection has no unix user - just don't apply
+ any unix user dependent rules.
+
+ * bus/config-parser.c: remove dbus-userdb.h usage
+
+ * bus/bus.c: remove dbus-userdb.h usage
+
+ * dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+ support Windows user function; also, fix the logic for checking
+ auth as root in the default auth code (broken in the previous
+ commit)
+
+ * dbus/dbus-connection.c
+ (dbus_connection_set_windows_user_function): new function
+ (dbus_connection_get_windows_user): new function
+
+2007-06-09 Havoc Pennington <hp@redhat.com>
+
* bus/dispatch.c (check_get_connection_unix_process_id): adapt
since sysdeps-unix.h stuff isn't included anymore
diff --git a/bus/bus.c b/bus/bus.c
index e1396f23..073f0a5b 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -34,7 +34,6 @@
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-internals.h>
-#include <dbus/dbus-userdb.h>
struct BusContext
{
@@ -794,7 +793,7 @@ bus_context_reload_config (BusContext *context,
dbus_bool_t ret;
/* Flush the user database cache */
- _dbus_user_database_flush_system ();
+ _dbus_flush_caches ();
ret = FALSE;
_dbus_string_init_const (&config_file, context->config_file);
@@ -995,11 +994,23 @@ bus_context_get_loop (BusContext *context)
}
dbus_bool_t
-bus_context_allow_user (BusContext *context,
- unsigned long uid)
+bus_context_allow_unix_user (BusContext *context,
+ unsigned long uid)
{
- return bus_policy_allow_user (context->policy,
- uid);
+ return bus_policy_allow_unix_user (context->policy,
+ uid);
+}
+
+/* For now this is never actually called because the default
+ * DBusConnection behavior of 'same user that owns the bus can connect'
+ * is all it would do.
+ */
+dbus_bool_t
+bus_context_allow_windows_user (BusContext *context,
+ const char *windows_sid)
+{
+ return bus_policy_allow_windows_user (context->policy,
+ windows_sid);
}
BusPolicy *
diff --git a/bus/bus.h b/bus/bus.h
index bb51004b..e17de060 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -85,8 +85,10 @@ BusConnections* bus_context_get_connections (BusContext
BusActivation* bus_context_get_activation (BusContext *context);
BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
DBusLoop* bus_context_get_loop (BusContext *context);
-dbus_bool_t bus_context_allow_user (BusContext *context,
+dbus_bool_t bus_context_allow_unix_user (BusContext *context,
unsigned long uid);
+dbus_bool_t bus_context_allow_windows_user (BusContext *context,
+ const char *windows_sid);
BusPolicy* bus_context_get_policy (BusContext *context);
BusClientPolicy* bus_context_create_client_policy (BusContext *context,
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 27528e03..7b6a368c 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -27,7 +27,6 @@
#include "selinux.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-internals.h>
-#include <dbus/dbus-userdb.h>
#include <string.h>
typedef enum
@@ -983,8 +982,8 @@ start_busconfig_child (BusConfigParser *parser,
DBusString username;
_dbus_string_init_const (&username, user);
- if (_dbus_get_user_id (&username,
- &e->d.policy.gid_uid_or_at_console))
+ if (_dbus_parse_unix_user_from_config (&username,
+ &e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_USER;
else
_dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
@@ -995,8 +994,8 @@ start_busconfig_child (BusConfigParser *parser,
DBusString group_name;
_dbus_string_init_const (&group_name, group);
- if (_dbus_get_group_id (&group_name,
- &e->d.policy.gid_uid_or_at_console))
+ if (_dbus_parse_unix_group_from_config (&group_name,
+ &e->d.policy.gid_uid_or_at_console))
e->d.policy.type = POLICY_GROUP;
else
_dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
@@ -1469,7 +1468,7 @@ append_rule_from_element (BusConfigParser *parser,
_dbus_string_init_const (&username, user);
- if (_dbus_get_user_id (&username, &uid))
+ if (_dbus_parse_unix_user_from_config (&username, &uid))
{
rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
if (rule == NULL)
@@ -1501,7 +1500,7 @@ append_rule_from_element (BusConfigParser *parser,
_dbus_string_init_const (&groupname, group);
- if (_dbus_get_user_id (&groupname, &gid))
+ if (_dbus_parse_unix_group_from_config (&groupname, &gid))
{
rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
if (rule == NULL)
@@ -1571,7 +1570,7 @@ append_rule_from_element (BusConfigParser *parser,
case POLICY_CONSOLE:
if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
- rule))
+ rule))
goto nomem;
break;
}
diff --git a/bus/connection.c b/bus/connection.c
index d063afca..10247e25 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -31,7 +31,6 @@
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-timeout.h>
-#include <dbus/dbus-userdb.h>
static void bus_connection_remove_transactions (DBusConnection *connection);
@@ -243,7 +242,9 @@ bus_connection_disconnected (DBusConnection *connection)
dbus_connection_set_unix_user_function (connection,
NULL, NULL, NULL);
-
+ dbus_connection_set_windows_user_function (connection,
+ NULL, NULL, NULL);
+
dbus_connection_set_dispatch_status_function (connection,
NULL, NULL, NULL);
@@ -369,9 +370,9 @@ dispatch_status_function (DBusConnection *connection,
}
static dbus_bool_t
-allow_user_function (DBusConnection *connection,
- unsigned long uid,
- void *data)
+allow_unix_user_function (DBusConnection *connection,
+ unsigned long uid,
+ void *data)
{
BusConnectionData *d;
@@ -379,7 +380,7 @@ allow_user_function (DBusConnection *connection,
_dbus_assert (d != NULL);
- return bus_context_allow_user (d->connections->context, uid);
+ return bus_context_allow_unix_user (d->connections->context, uid);
}
static void
@@ -597,9 +598,14 @@ bus_connections_setup_connection (BusConnections *connections,
NULL,
connection, NULL))
goto out;
-
+
+ /* For now we don't need to set a Windows user function because
+ * there are no policies in the config file controlling what
+ * Windows users can connect. The default 'same user that owns the
+ * bus can connect' behavior of DBusConnection is fine on Windows.
+ */
dbus_connection_set_unix_user_function (connection,
- allow_user_function,
+ allow_unix_user_function,
NULL, NULL);
dbus_connection_set_dispatch_status_function (connection,
@@ -679,6 +685,9 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_set_unix_user_function (connection,
NULL, NULL, NULL);
+ dbus_connection_set_windows_user_function (connection,
+ NULL, NULL, NULL);
+
dbus_connection_set_dispatch_status_function (connection,
NULL, NULL, NULL);
@@ -772,10 +781,10 @@ expire_incomplete_timeout (void *data)
}
dbus_bool_t
-bus_connection_get_groups (DBusConnection *connection,
- unsigned long **groups,
- int *n_groups,
- DBusError *error)
+bus_connection_get_unix_groups (DBusConnection *connection,
+ unsigned long **groups,
+ int *n_groups,
+ DBusError *error)
{
BusConnectionData *d;
unsigned long uid;
@@ -789,7 +798,7 @@ bus_connection_get_groups (DBusConnection *connection,
if (dbus_connection_get_unix_user (connection, &uid))
{
- if (!_dbus_groups_from_uid (uid, groups, n_groups))
+ if (!_dbus_unix_groups_from_uid (uid, groups, n_groups))
{
_dbus_verbose ("Did not get any groups for UID %lu\n",
uid);
@@ -807,15 +816,15 @@ bus_connection_get_groups (DBusConnection *connection,
}
dbus_bool_t
-bus_connection_is_in_group (DBusConnection *connection,
- unsigned long gid)
+bus_connection_is_in_unix_group (DBusConnection *connection,
+ unsigned long gid)
{
int i;
unsigned long *group_ids;
int n_group_ids;
- if (!bus_connection_get_groups (connection, &group_ids, &n_group_ids,
- NULL))
+ if (!bus_connection_get_unix_groups (connection, &group_ids, &n_group_ids,
+ NULL))
return FALSE;
i = 0;
diff --git a/bus/connection.h b/bus/connection.h
index a0703c55..75d94cf9 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -105,12 +105,12 @@ dbus_bool_t bus_connection_complete (DBusConnection *connection,
/* called by dispatch.c when the connection is dropped */
void bus_connection_disconnected (DBusConnection *connection);
-dbus_bool_t bus_connection_is_in_group (DBusConnection *connection,
- unsigned long gid);
-dbus_bool_t bus_connection_get_groups (DBusConnection *connection,
- unsigned long **groups,
- int *n_groups,
- DBusError *error);
+dbus_bool_t bus_connection_is_in_unix_group (DBusConnection *connection,
+ unsigned long gid);
+dbus_bool_t bus_connection_get_unix_groups (DBusConnection *connection,
+ unsigned long **groups,
+ int *n_groups,
+ DBusError *error);
BusClientPolicy* bus_connection_get_policy (DBusConnection *connection);
/* transaction API so we can send or not send a block of messages as a whole */
diff --git a/bus/policy.c b/bus/policy.c
index 7782563b..0d467ab9 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -28,7 +28,6 @@
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-internals.h>
-#include <dbus/dbus-userdb.h>
BusPolicyRule*
bus_policy_rule_new (BusPolicyRuleType type,
@@ -296,7 +295,7 @@ bus_policy_create_client_policy (BusPolicy *policy,
int n_groups;
int i;
- if (!bus_connection_get_groups (connection, &groups, &n_groups, error))
+ if (!bus_connection_get_unix_groups (connection, &groups, &n_groups, error))
goto failed;
i = 0;
@@ -321,43 +320,39 @@ bus_policy_create_client_policy (BusPolicy *policy,
dbus_free (groups);
}
-
- if (!dbus_connection_get_unix_user (connection, &uid))
+
+ if (dbus_connection_get_unix_user (connection, &uid))
{
- dbus_set_error (error, DBUS_ERROR_FAILED,
- "No user ID known for connection, cannot determine security policy\n");
- goto failed;
- }
+ if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
+ {
+ DBusList **list;
+
+ list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
+ uid);
+
+ if (list != NULL)
+ {
+ if (!add_list_to_client (list, client))
+ goto nomem;
+ }
+ }
- if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
- {
- DBusList **list;
+ /* Add console rules */
+ at_console = _dbus_unix_user_is_at_console (uid, error);
- list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
- uid);
-
- if (list != NULL)
+ if (at_console)
{
- if (!add_list_to_client (list, client))
+ if (!add_list_to_client (&policy->at_console_true_rules, client))
goto nomem;
}
- }
-
- /* Add console rules */
- at_console = _dbus_is_console_user (uid, error);
-
- if (at_console)
- {
- if (!add_list_to_client (&policy->at_console_true_rules, client))
- goto nomem;
- }
- else if (dbus_error_is_set (error) == TRUE)
- {
- goto failed;
- }
- else if (!add_list_to_client (&policy->at_console_false_rules, client))
- {
- goto nomem;
+ else if (dbus_error_is_set (error) == TRUE)
+ {
+ goto failed;
+ }
+ else if (!add_list_to_client (&policy->at_console_false_rules, client))
+ {
+ goto nomem;
+ }
}
if (!add_list_to_client (&policy->mandatory_rules,
@@ -438,23 +433,23 @@ list_allows_user (dbus_bool_t def,
}
dbus_bool_t
-bus_policy_allow_user (BusPolicy *policy,
- unsigned long uid)
+bus_policy_allow_unix_user (BusPolicy *policy,
+ unsigned long uid)
{
dbus_bool_t allowed;
unsigned long *group_ids;
int n_group_ids;
/* On OOM or error we always reject the user */
- if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids))
+ if (!_dbus_unix_groups_from_uid (uid, &group_ids, &n_group_ids))
{
_dbus_verbose ("Did not get any groups for UID %lu\n",
uid);
return FALSE;
}
- /* Default to "user owning bus" or root can connect */
- allowed = uid == _dbus_getuid ();
+ /* Default to "user owning bus" can connect */
+ allowed = _dbus_unix_user_is_process_owner (uid);
allowed = list_allows_user (allowed,
&policy->default_rules,
@@ -473,6 +468,23 @@ bus_policy_allow_user (BusPolicy *policy,
return allowed;
}
+/* For now this is never actually called because the default
+ * DBusConnection behavior of 'same user that owns the bus can
+ * connect' is all it would do. Set the windows user function in
+ * connection.c if the config file ever supports doing something
+ * interesting here.
+ */
+dbus_bool_t
+bus_policy_allow_windows_user (BusPolicy *policy,
+ const char *windows_sid)
+{
+ /* Windows has no policies here since only the session bus
+ * is really used for now, so just checking that the
+ * connecting person is the same as the bus owner is fine.
+ */
+ return _dbus_windows_user_is_process_owner (windows_sid);
+}
+
dbus_bool_t
bus_policy_append_default_rule (BusPolicy *policy,
BusPolicyRule *rule)
diff --git a/bus/policy.h b/bus/policy.h
index e2574bc3..b58b3862 100644
--- a/bus/policy.h
+++ b/bus/policy.h
@@ -113,8 +113,10 @@ void bus_policy_unref (BusPolicy *policy);
BusClientPolicy* bus_policy_create_client_policy (BusPolicy *policy,
DBusConnection *connection,
DBusError *error);
-dbus_bool_t bus_policy_allow_user (BusPolicy *policy,
+dbus_bool_t bus_policy_allow_unix_user (BusPolicy *policy,
unsigned long uid);
+dbus_bool_t bus_policy_allow_windows_user (BusPolicy *policy,
+ const char *windows_sid);
dbus_bool_t bus_policy_append_default_rule (BusPolicy *policy,
BusPolicyRule *rule);
dbus_bool_t bus_policy_append_mandatory_rule (BusPolicy *policy,
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 5dc463a4..1cd3d05d 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -4763,8 +4763,10 @@ dbus_connection_get_socket(DBusConnection *connection,
/**
* Gets the UNIX user ID of the connection if known. Returns #TRUE if
- * the uid is filled in. Always returns #FALSE on non-UNIX platforms.
- * Always returns #FALSE prior to authenticating the connection.
+ * the uid is filled in. Always returns #FALSE on non-UNIX platforms
+ * for now, though in theory someone could hook Windows to NIS or
+ * something. Always returns #FALSE prior to authenticating the
+ * connection.
*
* The UID is only read by servers from clients; clients can't usually
* get the UID of servers, because servers do not authenticate to
@@ -4789,14 +4791,6 @@ dbus_connection_get_unix_user (DBusConnection *connection,
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (uid != NULL, FALSE);
-
-#ifdef DBUS_WIN
- /* FIXME this should be done at a lower level, but it's kind of hard,
- * just want to be sure we don't ship with this API returning
- * some weird internal fake uid for 1.0
- */
- return FALSE;
-#endif
CONNECTION_LOCK (connection);
@@ -4805,6 +4799,11 @@ dbus_connection_get_unix_user (DBusConnection *connection,
else
result = _dbus_transport_get_unix_user (connection->transport,
uid);
+
+#ifdef DBUS_WIN
+ _dbus_assert (!result);
+#endif
+
CONNECTION_UNLOCK (connection);
return result;
@@ -4812,7 +4811,7 @@ dbus_connection_get_unix_user (DBusConnection *connection,
/**
* Gets the process ID of the connection if any.
- * Returns #TRUE if the uid is filled in.
+ * Returns #TRUE if the pid is filled in.
* Always returns #FALSE prior to authenticating the
* connection.
*
@@ -4828,14 +4827,6 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (pid != NULL, FALSE);
-
-#ifdef DBUS_WIN
- /* FIXME this should be done at a lower level, but it's kind of hard,
- * just want to be sure we don't ship with this API returning
- * some weird internal fake uid for 1.0
- */
- return FALSE;
-#endif
CONNECTION_LOCK (connection);
@@ -4844,6 +4835,10 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
else
result = _dbus_transport_get_unix_process_id (connection->transport,
pid);
+#ifdef DBUS_WIN
+ _dbus_assert (!result);
+#endif
+
CONNECTION_UNLOCK (connection);
return result;
@@ -4858,14 +4853,13 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
*
* If the function is set to #NULL (as it is by default), then
* only the same UID as the server process will be allowed to
- * connect.
+ * connect. Also, root is always allowed to connect.
*
* On Windows, the function will be set and its free_data_function will
* be invoked when the connection is freed or a new function is set.
* However, the function will never be called, because there are
- * no UNIX user ids to pass to it.
- *
- * @todo add a Windows API analogous to dbus_connection_set_unix_user_function()
+ * no UNIX user ids to pass to it, or at least none of the existing
+ * auth protocols would allow authenticating as a UNIX user on Windows.
*
* @param connection the connection
* @param function the predicate
@@ -4890,7 +4884,106 @@ dbus_connection_set_unix_user_function (DBusConnection *connection,
CONNECTION_UNLOCK (connection);
if (old_free_function != NULL)
- (* old_free_function) (old_data);
+ (* old_free_function) (old_data);
+}
+
+/**
+ * Gets the Windows user SID of the connection if known. Returns
+ * #TRUE if the ID is filled in. Always returns #FALSE on non-Windows
+ * platforms for now, though in theory someone could hook UNIX to
+ * Active Directory or something. Always returns #FALSE prior to
+ * authenticating the connection.
+ *
+ * The user is only read by servers from clients; clients can't usually
+ * get the user of servers, because servers do not authenticate to
+ * clients. The returned user is the user the connection authenticated
+ * as.
+ *
+ * The message bus is a server and the apps connecting to the bus
+ * are clients.
+ *
+ * The returned user string has to be freed with dbus_free().
+ *
+ * The return value indicates whether the user SID is available;
+ * if it's available but we don't have the memory to copy it,
+ * then the return value is #TRUE and #NULL is given as the SID.
+ *
+ * @todo We would like to be able to say "You can ask the bus to tell
+ * you the user of another connection though if you like; this is done
+ * with dbus_bus_get_windows_user()." But this has to be implemented
+ * in bus/driver.c and dbus/dbus-bus.c, and is pointless anyway
+ * since on Windows we only use the session bus for now.
+ *
+ * @param connection the connection
+ * @param windows_sid_p return location for an allocated copy of the user ID, or #NULL if no memory
+ * @returns #TRUE if user is available (returned value may be #NULL anyway if no memory)
+ */
+dbus_bool_t
+dbus_connection_get_windows_user (DBusConnection *connection,
+ char **windows_sid_p)
+{
+ dbus_bool_t result;
+
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
+
+ CONNECTION_LOCK (connection);
+
+ if (!_dbus_transport_get_is_authenticated (connection->transport))
+ result = FALSE;
+ else
+ result = _dbus_transport_get_windows_user (connection->transport,
+ windows_sid_p);
+
+#ifdef DBUS_UNIX
+ _dbus_assert (!result);
+#endif
+
+ CONNECTION_UNLOCK (connection);
+
+ return result;
+}
+
+/**
+ * Sets a predicate function used to determine whether a given user ID
+ * is allowed to connect. When an incoming connection has
+ * authenticated with a particular user ID, this function is called;
+ * if it returns #TRUE, the connection is allowed to proceed,
+ * otherwise the connection is disconnected.
+ *
+ * If the function is set to #NULL (as it is by default), then
+ * only the same user owning the server process will be allowed to
+ * connect.
+ *
+ * On UNIX, the function will be set and its free_data_function will
+ * be invoked when the connection is freed or a new function is set.
+ * However, the function will never be called, because there is no
+ * way right now to authenticate as a Windows user on UNIX.
+ *
+ * @param connection the connection
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ */
+void
+dbus_connection_set_windows_user_function (DBusConnection *connection,
+ DBusAllowWindowsUserFunction function,
+ void *data,
+ DBusFreeFunction free_data_function)
+{
+ void *old_data = NULL;
+ DBusFreeFunction old_free_function = NULL;
+
+ _dbus_return_if_fail (connection != NULL);
+
+ CONNECTION_LOCK (connection);
+ _dbus_transport_set_windows_user_function (connection->transport,
+ function, data, free_data_function,
+ &old_data, &old_free_function);
+ CONNECTION_UNLOCK (connection);
+
+ if (old_free_function != NULL)
+ (* old_free_function) (old_data);
}
/**
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index 819e96c8..2b673fda 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -132,14 +132,28 @@ typedef void (* DBusDispatchStatusFunction) (DBusConnection *connection,
* to do. Set with dbus_connection_set_wakeup_main_function().
*/
typedef void (* DBusWakeupMainFunction) (void *data);
+
/**
- * Called during authentication on UNIX systems to check whether the given
- * user ID is allowed to connect. Never called on Windows. Set with
+ * Called during authentication to check whether the given UNIX user
+ * ID is allowed to connect, if the client tried to auth as a UNIX
+ * user ID. Normally on Windows this would never happen. Set with
* dbus_connection_set_unix_user_function().
*/
typedef dbus_bool_t (* DBusAllowUnixUserFunction) (DBusConnection *connection,
unsigned long uid,
void *data);
+
+/**
+ * Called during authentication to check whether the given Windows user
+ * ID is allowed to connect, if the client tried to auth as a Windows
+ * user ID. Normally on UNIX this would never happen. Set with
+ * dbus_connection_set_windows_user_function().
+ */
+typedef dbus_bool_t (* DBusAllowWindowsUserFunction) (DBusConnection *connection,
+ const char *user_sid,
+ void *data);
+
+
/**
* Called when a pending call now has a reply available. Set with
* dbus_pending_call_set_notify().
@@ -219,6 +233,12 @@ void dbus_connection_set_unix_user_function (DBusConnection
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function);
+dbus_bool_t dbus_connection_get_windows_user (DBusConnection *connection,
+ char **windows_sid_p);
+void dbus_connection_set_windows_user_function (DBusConnection *connection,
+ DBusAllowWindowsUserFunction function,
+ void *data,
+ DBusFreeFunction free_data_function);
void dbus_connection_set_route_peer_messages (DBusConnection *connection,
dbus_bool_t value);
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 135f7c9f..f1c133fd 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -2916,4 +2916,17 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs)
return FALSE;
}
+/**
+ * Called when the bus daemon is signaled to reload its configuration; any
+ * caches should be nuked. Of course any caches that need explicit reload
+ * are probably broken, but c'est la vie.
+ *
+ *
+ */
+void
+_dbus_flush_caches (void)
+{
+ _dbus_user_database_flush_system ();
+}
+
/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index 58fce9ce..0e8bdbb3 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -120,8 +120,6 @@ dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo *info,
DBusError *error);
void _dbus_group_info_free (DBusGroupInfo *info);
-
-dbus_pid_t _dbus_getpid (void);
dbus_uid_t _dbus_getuid (void);
dbus_gid_t _dbus_getgid (void);
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 9963432b..339b8f96 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -780,6 +780,98 @@ _dbus_group_info_fill_gid (DBusGroupInfo *info,
return fill_group_info (info, gid, NULL, error);
}
+/**
+ * Parse a UNIX user from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param username the username text
+ * @param uid_p place to return the uid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_user_from_config (const DBusString *username,
+ dbus_uid_t *uid_p)
+{
+ return _dbus_get_user_id (username, uid_p);
+
+}
+
+/**
+ * Parse a UNIX group from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param groupname the groupname text
+ * @param gid_p place to return the gid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_group_from_config (const DBusString *groupname,
+ dbus_gid_t *gid_p)
+{
+ return _dbus_get_group_id (groupname, gid_p);
+}
+
+/**
+ * Gets all groups corresponding to the given UNIX user ID. On UNIX,
+ * just calls _dbus_groups_from_uid(). On Windows, should always
+ * fail since we don't know any UNIX groups.
+ *
+ * @param uid the UID
+ * @param group_ids return location for array of group IDs
+ * @param n_group_ids return location for length of returned array
+ * @returns #TRUE if the UID existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_unix_groups_from_uid (dbus_uid_t uid,
+ dbus_gid_t **group_ids,
+ int *n_group_ids)
+{
+ return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
+}
+
+/**
+ * Checks to see if the UNIX user ID is at the console.
+ * Should always fail on Windows (set the error to
+ * #DBUS_ERROR_NOT_SUPPORTED).
+ *
+ * @param uid UID of person to check
+ * @param error return location for errors
+ * @returns #TRUE if the UID is the same as the console user and there are no errors
+ */
+dbus_bool_t
+_dbus_unix_user_is_at_console (dbus_uid_t uid,
+ DBusError *error)
+{
+ return _dbus_is_console_user (uid, error);
+
+}
+
+/**
+ * Checks to see if the UNIX user ID matches the UID of
+ * the process. Should always return #FALSE on Windows.
+ *
+ * @param uid the UNIX user ID
+ * @returns #TRUE if this uid owns the process.
+ */
+dbus_bool_t
+_dbus_unix_user_is_process_owner (dbus_uid_t uid)
+{
+ return uid == _dbus_getuid ();
+}
+
+/**
+ * Checks to see if the Windows user SID matches the owner of
+ * the process. Should always return #FALSE on UNIX.
+ *
+ * @param windows_sid the Windows user SID
+ * @returns #TRUE if this user owns the process.
+ */
+dbus_bool_t
+_dbus_windows_user_is_process_owner (const char *windows_sid)
+{
+ return FALSE;
+}
+
/** @} */ /* End of DBusInternalsUtils functions */
/**
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index f83c17ca..87bfc8fa 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -173,6 +173,18 @@ dbus_bool_t _dbus_append_desired_identity (DBusString *str);
dbus_bool_t _dbus_homedir_from_current_process (const DBusString **homedir);
dbus_bool_t _dbus_homedir_from_username (const DBusString *username,
DBusString *homedir);
+dbus_bool_t _dbus_parse_unix_user_from_config (const DBusString *username,
+ dbus_uid_t *uid_p);
+dbus_bool_t _dbus_parse_unix_group_from_config (const DBusString *groupname,
+ dbus_gid_t *gid_p);
+dbus_bool_t _dbus_unix_groups_from_uid (dbus_uid_t uid,
+ dbus_gid_t **group_ids,
+ int *n_group_ids);
+dbus_bool_t _dbus_unix_user_is_at_console (dbus_uid_t uid,
+ DBusError *error);
+dbus_bool_t _dbus_unix_user_is_process_owner (dbus_uid_t uid);
+dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid);
+
/** Opaque type representing an atomically-modifiable integer
* that can be used from multiple threads.
@@ -420,6 +432,14 @@ dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs,
unsigned long _dbus_pid_for_log (void);
+/* FIXME move back to dbus-sysdeps-unix.h probably -
+ * the PID file handling just needs a little more abstraction
+ * in the bus daemon first.
+ */
+dbus_pid_t _dbus_getpid (void);
+
+void _dbus_flush_caches (void);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c
index a1df3604..818c4ed0 100644
--- a/dbus/dbus-test.c
+++ b/dbus/dbus-test.c
@@ -161,8 +161,10 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *speci
#endif
run_data_test ("credentials", specific_test, _dbus_credentials_test, test_data_dir);
-
+
+#ifdef DBUS_UNIX
run_data_test ("userdb", specific_test, _dbus_userdb_test, test_data_dir);
+#endif
run_test ("keyring", specific_test, _dbus_keyring_test);
diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h
index bfdff0e2..6d3f1f3c 100644
--- a/dbus/dbus-transport-protected.h
+++ b/dbus/dbus-transport-protected.h
@@ -104,6 +104,11 @@ struct DBusTransport
void *unix_user_data; /**< Data for unix_user_function */
DBusFreeFunction free_unix_user_data; /**< Function to free unix_user_data */
+
+ DBusAllowWindowsUserFunction windows_user_function; /**< Function for checking whether a user is authorized. */
+ void *windows_user_data; /**< Data for windows_user_function */
+
+ DBusFreeFunction free_windows_user_data; /**< Function to free windows_user_data */
unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */
unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index e922eb5d..029cc6cf 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -167,6 +167,10 @@ _dbus_transport_init_base (DBusTransport *transport,
transport->unix_user_data = NULL;
transport->free_unix_user_data = NULL;
+ transport->windows_user_function = NULL;
+ transport->windows_user_data = NULL;
+ transport->free_windows_user_data = NULL;
+
transport->expected_guid = NULL;
/* Try to default to something that won't totally hose the system,
@@ -202,6 +206,9 @@ _dbus_transport_finalize_base (DBusTransport *transport)
if (transport->free_unix_user_data != NULL)
(* transport->free_unix_user_data) (transport->unix_user_data);
+
+ if (transport->free_windows_user_data != NULL)
+ (* transport->free_windows_user_data) (transport->windows_user_data);
_dbus_message_loader_unref (transport->loader);
_dbus_auth_unref (transport->auth);
@@ -491,12 +498,157 @@ _dbus_transport_get_is_connected (DBusTransport *transport)
return !transport->disconnected;
}
+static dbus_bool_t
+auth_via_unix_user_function (DBusTransport *transport)
+{
+ DBusCredentials *auth_identity;
+ dbus_bool_t allow;
+ DBusConnection *connection;
+ DBusAllowUnixUserFunction unix_user_function;
+ void *unix_user_data;
+ dbus_uid_t uid;
+
+ /* Dropping the lock here probably isn't that safe. */
+
+ auth_identity = _dbus_auth_get_identity (transport->auth);
+ _dbus_assert (auth_identity != NULL);
+
+ connection = transport->connection;
+ unix_user_function = transport->unix_user_function;
+ unix_user_data = transport->unix_user_data;
+ uid = _dbus_credentials_get_unix_uid (auth_identity),
+
+ _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
+ _dbus_connection_unlock (connection);
+
+ allow = (* unix_user_function) (connection,
+ uid,
+ unix_user_data);
+
+ _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
+ _dbus_connection_lock (connection);
+
+ if (allow)
+ {
+ _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
+ }
+ else
+ {
+ _dbus_verbose ("Client UID "DBUS_UID_FORMAT
+ " was rejected, disconnecting\n",
+ _dbus_credentials_get_unix_uid (auth_identity));
+ _dbus_transport_disconnect (transport);
+ }
+
+ return allow;
+}
+
+static dbus_bool_t
+auth_via_windows_user_function (DBusTransport *transport)
+{
+ DBusCredentials *auth_identity;
+ dbus_bool_t allow;
+ DBusConnection *connection;
+ DBusAllowWindowsUserFunction windows_user_function;
+ void *windows_user_data;
+ char *windows_sid;
+
+ /* Dropping the lock here probably isn't that safe. */
+
+ auth_identity = _dbus_auth_get_identity (transport->auth);
+ _dbus_assert (auth_identity != NULL);
+
+ connection = transport->connection;
+ windows_user_function = transport->windows_user_function;
+ windows_user_data = transport->unix_user_data;
+ windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
+
+ if (windows_sid == NULL)
+ {
+ /* OOM */
+ return FALSE;
+ }
+
+ _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
+ _dbus_connection_unlock (connection);
+
+ allow = (* windows_user_function) (connection,
+ windows_sid,
+ windows_user_data);
+
+ _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
+ _dbus_connection_lock (connection);
+
+ if (allow)
+ {
+ _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
+ }
+ else
+ {
+ _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
+ _dbus_credentials_get_windows_sid (auth_identity));
+ _dbus_transport_disconnect (transport);
+ }
+
+ return allow;
+}
+
+static dbus_bool_t
+auth_via_default_rules (DBusTransport *transport)
+{
+ DBusCredentials *auth_identity;
+ DBusCredentials *our_identity;
+ dbus_bool_t allow;
+
+ auth_identity = _dbus_auth_get_identity (transport->auth);
+ _dbus_assert (auth_identity != NULL);
+
+ /* By default, connection is allowed if the client is
+ * 1) root or 2) has the same UID as us
+ */
+
+ our_identity = _dbus_credentials_new_from_current_process ();
+ if (our_identity == NULL)
+ {
+ /* OOM */
+ return FALSE;
+ }
+
+ if (_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
+ _dbus_credentials_same_user (our_identity,
+ auth_identity))
+ {
+ /* FIXME the verbose spam here is unix-specific */
+ _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
+ " matching our UID "DBUS_UID_FORMAT"\n",
+ _dbus_credentials_get_unix_uid(auth_identity),
+ _dbus_credentials_get_unix_uid(our_identity));
+ /* We have authenticated! */
+ allow = TRUE;
+ }
+ else
+ {
+ /* FIXME the verbose spam here is unix-specific */
+ _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
+ " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
+ _dbus_credentials_get_unix_uid(our_identity),
+ _dbus_credentials_get_unix_uid(our_identity));
+ _dbus_transport_disconnect (transport);
+ allow = FALSE;
+ }
+
+ _dbus_credentials_unref (our_identity);
+
+ return allow;
+}
+
+
/**
* Returns #TRUE if we have been authenticated. Will return #TRUE
* even if the transport is disconnected.
*
* @todo we drop connection->mutex when calling the unix_user_function,
- * which may not be safe really.
+ * and windows_user_function, which may not be safe really.
*
* @param transport the transport
* @returns whether we're authenticated
@@ -532,6 +684,8 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
}
}
+ /* If we're the client, verify the GUID
+ */
if (maybe_authenticated && !transport->is_server)
{
const char *server_guid;
@@ -560,106 +714,40 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
}
}
}
-
- /* If we've authenticated as some identity, check that the auth
- * identity is the same as our own identity. In the future, we
- * may have API allowing applications to specify how this is
- * done, for example they may allow connection as any identity,
- * but then impose restrictions on certain identities.
- * Or they may give certain identities extra privileges.
+
+ /* If we're the server, see if we want to allow this identity to proceed.
*/
-
if (maybe_authenticated && transport->is_server)
{
+ dbus_bool_t allow;
DBusCredentials *auth_identity;
-
+
auth_identity = _dbus_auth_get_identity (transport->auth);
_dbus_assert (auth_identity != NULL);
-
- /* If we have a UNIX user and a unix user function, delegate
- * deciding whether auth credentials are good enough to the app;
- * otherwise, use our default decision process.
+
+ /* If we have an auth'd user and a user function, delegate
+ * deciding whether auth credentials are good enough to the
+ * app; otherwise, use our default decision process.
*/
if (transport->unix_user_function != NULL &&
_dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
{
- dbus_bool_t allow;
- DBusConnection *connection;
- DBusAllowUnixUserFunction unix_user_function;
- void *unix_user_data;
- dbus_uid_t uid;
-
- /* Dropping the lock here probably isn't that safe. */
-
- connection = transport->connection;
- unix_user_function = transport->unix_user_function;
- unix_user_data = transport->unix_user_data;
- uid = _dbus_credentials_get_unix_uid (auth_identity),
-
- _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
- _dbus_connection_unlock (connection);
-
- allow = (* unix_user_function) (connection,
- uid,
- unix_user_data);
-
- _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
- _dbus_connection_lock (connection);
-
- if (allow)
- {
- _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
- }
- else
- {
- _dbus_verbose ("Client UID "DBUS_UID_FORMAT
- " was rejected, disconnecting\n",
- _dbus_credentials_get_unix_uid (auth_identity));
- _dbus_transport_disconnect (transport);
- _dbus_connection_unref_unlocked (connection);
- return FALSE;
- }
+ allow = auth_via_unix_user_function (transport);
}
+ else if (transport->windows_user_function != NULL &&
+ _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
+ {
+ allow = auth_via_windows_user_function (transport);
+ }
else
{
- DBusCredentials *our_identity;
-
- /* By default, connection is allowed if the client is
- * 1) root or 2) has the same UID as us
- */
-
- our_identity = _dbus_credentials_new_from_current_process ();
- if (our_identity == NULL)
- {
- /* OOM */
- _dbus_connection_unref_unlocked (transport->connection);
- return FALSE;
- }
-
- if (_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
- !_dbus_credentials_same_user (our_identity,
- auth_identity))
- {
- /* FIXME the verbose spam here is unix-specific */
- _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
- " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
- _dbus_credentials_get_unix_uid(our_identity),
- _dbus_credentials_get_unix_uid(our_identity));
- _dbus_transport_disconnect (transport);
- _dbus_connection_unref_unlocked (transport->connection);
- return FALSE;
- }
- else
- {
- /* FIXME the verbose spam here is unix-specific */
- _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
- " matching our UID "DBUS_UID_FORMAT"\n",
- _dbus_credentials_get_unix_uid(auth_identity),
- _dbus_credentials_get_unix_uid(our_identity));
- }
+ allow = auth_via_default_rules (transport);
}
+
+ if (!allow)
+ maybe_authenticated = FALSE;
}
-
+
transport->authenticated = maybe_authenticated;
_dbus_connection_unref_unlocked (transport->connection);
@@ -1137,6 +1225,65 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport,
}
/**
+ * See dbus_connection_get_windows_user().
+ *
+ * @param transport the transport
+ * @param windows_sid_p return location for the user ID
+ * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
+ */
+dbus_bool_t
+_dbus_transport_get_windows_user (DBusTransport *transport,
+ char **windows_sid_p)
+{
+ DBusCredentials *auth_identity;
+
+ *windows_sid_p = NULL;
+
+ if (!transport->authenticated)
+ return FALSE;
+
+ auth_identity = _dbus_auth_get_identity (transport->auth);
+
+ if (_dbus_credentials_include (auth_identity,
+ DBUS_CREDENTIAL_WINDOWS_SID))
+ {
+ /* If no memory, we are supposed to return TRUE and set NULL */
+ *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * See dbus_connection_set_windows_user_function().
+ *
+ * @param transport the transport
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ * @param old_data the old user data to be freed
+ * @param old_free_data_function old free data function to free it with
+ */
+
+void
+_dbus_transport_set_windows_user_function (DBusTransport *transport,
+ DBusAllowWindowsUserFunction function,
+ void *data,
+ DBusFreeFunction free_data_function,
+ void **old_data,
+ DBusFreeFunction *old_free_data_function)
+{
+ *old_data = transport->windows_user_data;
+ *old_free_data_function = transport->free_windows_user_data;
+
+ transport->windows_user_function = function;
+ transport->windows_user_data = data;
+ transport->free_windows_user_data = free_data_function;
+}
+
+/**
* Sets the SASL authentication mechanisms supported by this transport.
*
* @param transport the transport
diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
index 4784e462..9e952a1e 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -68,6 +68,14 @@ void _dbus_transport_set_unix_user_function (DBusTransport
DBusFreeFunction free_data_function,
void **old_data,
DBusFreeFunction *old_free_data_function);
+dbus_bool_t _dbus_transport_get_windows_user (DBusTransport *transport,
+ char **windows_sid_p);
+void _dbus_transport_set_windows_user_function (DBusTransport *transport,
+ DBusAllowWindowsUserFunction function,
+ void *data,
+ DBusFreeFunction free_data_function,
+ void **old_data,
+ DBusFreeFunction *old_free_data_function);
dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
const char **mechanisms);