mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-06 09:18:12 +02:00
2003-04-01 Havoc Pennington <hp@pobox.com>
* dbus/dbus-server.c (dbus_server_set_auth_mechanisms): new function * dbus/dbus-auth.c (_dbus_auth_set_mechanisms): new * dbus/dbus-internals.c (_dbus_dup_string_array): new function * dbus/dbus-sysdeps.c (_dbus_listen_unix_socket): chmod the socket 0777, and unlink any existing socket. * bus/bus.c (bus_context_new): change our UID/GID and fork if the configuration file so specifies; set up auth mechanism restrictions * bus/config-parser.c (bus_config_parser_content): add support for <fork> option and fill in code for <auth> * bus/system.conf.in: add <fork/> to default configuration, and limit auth mechanisms to EXTERNAL * doc/config-file.txt (Elements): add <fork> * dbus/dbus-sysdeps.c (_dbus_become_daemon): new function (_dbus_change_identity): new function
This commit is contained in:
parent
8dfe82beb5
commit
44ed933284
19 changed files with 574 additions and 36 deletions
27
ChangeLog
27
ChangeLog
|
|
@ -1,3 +1,30 @@
|
|||
2003-04-01 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-server.c (dbus_server_set_auth_mechanisms): new
|
||||
function
|
||||
|
||||
* dbus/dbus-auth.c (_dbus_auth_set_mechanisms): new
|
||||
|
||||
* dbus/dbus-internals.c (_dbus_dup_string_array): new function
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_listen_unix_socket): chmod the
|
||||
socket 0777, and unlink any existing socket.
|
||||
|
||||
* bus/bus.c (bus_context_new): change our UID/GID and fork if
|
||||
the configuration file so specifies; set up auth mechanism
|
||||
restrictions
|
||||
|
||||
* bus/config-parser.c (bus_config_parser_content): add support
|
||||
for <fork> option and fill in code for <auth>
|
||||
|
||||
* bus/system.conf.in: add <fork/> to default configuration,
|
||||
and limit auth mechanisms to EXTERNAL
|
||||
|
||||
* doc/config-file.txt (Elements): add <fork>
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_become_daemon): new function
|
||||
(_dbus_change_identity): new function
|
||||
|
||||
2003-03-31 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_connect_unix_socket)
|
||||
|
|
|
|||
84
bus/bus.c
84
bus/bus.c
|
|
@ -141,8 +141,15 @@ free_rule_list_func (void *data)
|
|||
static dbus_bool_t
|
||||
setup_server (BusContext *context,
|
||||
DBusServer *server,
|
||||
char **auth_mechanisms,
|
||||
DBusError *error)
|
||||
{
|
||||
{
|
||||
if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_server_set_new_connection_function (server,
|
||||
new_connection_callback,
|
||||
context, NULL);
|
||||
|
|
@ -181,6 +188,10 @@ bus_context_new (const DBusString *config_file,
|
|||
BusConfigParser *parser;
|
||||
DBusString full_address;
|
||||
const char *service_dirs[] = { NULL, NULL };
|
||||
const char *user;
|
||||
char **auth_mechanisms;
|
||||
DBusList **auth_mechanisms_list;
|
||||
int len;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
|
|
@ -189,6 +200,7 @@ bus_context_new (const DBusString *config_file,
|
|||
|
||||
parser = NULL;
|
||||
context = NULL;
|
||||
auth_mechanisms = NULL;
|
||||
|
||||
parser = bus_config_load (config_file, error);
|
||||
if (parser == NULL)
|
||||
|
|
@ -202,6 +214,36 @@ bus_context_new (const DBusString *config_file,
|
|||
}
|
||||
|
||||
context->refcount = 1;
|
||||
|
||||
/* Build an array of auth mechanisms */
|
||||
|
||||
auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
|
||||
len = _dbus_list_get_length (auth_mechanisms_list);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
auth_mechanisms = dbus_new0 (char*, len + 1);
|
||||
if (auth_mechanisms == NULL)
|
||||
goto failed;
|
||||
|
||||
i = 0;
|
||||
link = _dbus_list_get_first_link (auth_mechanisms_list);
|
||||
while (link != NULL)
|
||||
{
|
||||
auth_mechanisms[i] = _dbus_strdup (link->data);
|
||||
if (auth_mechanisms[i] == NULL)
|
||||
goto failed;
|
||||
link = _dbus_list_get_next_link (auth_mechanisms_list, link);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_mechanisms = NULL;
|
||||
}
|
||||
|
||||
/* Listen on our addresses */
|
||||
|
||||
addresses = bus_config_parser_get_addresses (parser);
|
||||
|
||||
|
|
@ -213,7 +255,7 @@ bus_context_new (const DBusString *config_file,
|
|||
server = dbus_server_listen (link->data, error);
|
||||
if (server == NULL)
|
||||
goto failed;
|
||||
else if (!setup_server (context, server, error))
|
||||
else if (!setup_server (context, server, auth_mechanisms, error))
|
||||
goto failed;
|
||||
|
||||
if (!_dbus_list_append (&context->servers, server))
|
||||
|
|
@ -225,6 +267,31 @@ bus_context_new (const DBusString *config_file,
|
|||
link = _dbus_list_get_next_link (addresses, link);
|
||||
}
|
||||
|
||||
/* Here we change our credentials if required,
|
||||
* as soon as we've set up our sockets
|
||||
*/
|
||||
user = bus_config_parser_get_user (parser);
|
||||
if (user != NULL)
|
||||
{
|
||||
DBusCredentials creds;
|
||||
DBusString u;
|
||||
|
||||
_dbus_string_init_const (&u, user);
|
||||
|
||||
if (!_dbus_credentials_from_username (&u, &creds) ||
|
||||
creds.uid < 0 ||
|
||||
creds.gid < 0)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Could not get UID and GID for username \"%s\"",
|
||||
user);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!_dbus_change_identity (creds.uid, creds.gid, error))
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* We have to build the address backward, so that
|
||||
* <listen> later in the config file have priority
|
||||
*/
|
||||
|
|
@ -265,6 +332,8 @@ bus_context_new (const DBusString *config_file,
|
|||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Create activation subsystem */
|
||||
|
||||
context->activation = bus_activation_new (context, &full_address,
|
||||
service_dirs, error);
|
||||
|
|
@ -306,12 +375,20 @@ bus_context_new (const DBusString *config_file,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
/* Now become a daemon if appropriate */
|
||||
if (bus_config_parser_get_fork (parser))
|
||||
{
|
||||
if (!_dbus_become_daemon (error))
|
||||
goto failed;
|
||||
}
|
||||
|
||||
bus_config_parser_unref (parser);
|
||||
_dbus_string_free (&full_address);
|
||||
dbus_free_string_array (auth_mechanisms);
|
||||
|
||||
return context;
|
||||
|
||||
failed:
|
||||
failed:
|
||||
if (parser != NULL)
|
||||
bus_config_parser_unref (parser);
|
||||
|
||||
|
|
@ -319,6 +396,7 @@ bus_context_new (const DBusString *config_file,
|
|||
bus_context_unref (context);
|
||||
|
||||
_dbus_string_free (&full_address);
|
||||
dbus_free_string_array (auth_mechanisms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ typedef enum
|
|||
ELEMENT_POLICY,
|
||||
ELEMENT_LIMIT,
|
||||
ELEMENT_ALLOW,
|
||||
ELEMENT_DENY
|
||||
ELEMENT_DENY,
|
||||
ELEMENT_FORK
|
||||
} ElementType;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -84,6 +85,10 @@ struct BusConfigParser
|
|||
char *user; /**< user to run as */
|
||||
|
||||
DBusList *listen_on; /**< List of addresses to listen to */
|
||||
|
||||
DBusList *mechanisms; /**< Auth mechanisms */
|
||||
|
||||
unsigned int fork : 1; /**< TRUE to fork into daemon mode */
|
||||
};
|
||||
|
||||
static const char*
|
||||
|
|
@ -111,6 +116,8 @@ element_type_to_name (ElementType type)
|
|||
return "allow";
|
||||
case ELEMENT_DENY:
|
||||
return "deny";
|
||||
case ELEMENT_FORK:
|
||||
return "fork";
|
||||
}
|
||||
|
||||
_dbus_assert_not_reached ("bad element type");
|
||||
|
|
@ -195,9 +202,15 @@ merge_included (BusConfigParser *parser,
|
|||
included->user = NULL;
|
||||
}
|
||||
|
||||
if (included->fork)
|
||||
parser->fork = TRUE;
|
||||
|
||||
while ((link = _dbus_list_pop_first_link (&included->listen_on)))
|
||||
_dbus_list_append_link (&parser->listen_on, link);
|
||||
|
||||
while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
|
||||
_dbus_list_append_link (&parser->mechanisms, link);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -407,6 +420,21 @@ start_busconfig_child (BusConfigParser *parser,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "fork") == 0)
|
||||
{
|
||||
if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
|
||||
return FALSE;
|
||||
|
||||
if (push_element (parser, ELEMENT_FORK) == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
parser->fork = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "listen") == 0)
|
||||
|
|
@ -420,6 +448,19 @@ start_busconfig_child (BusConfigParser *parser,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "auth") == 0)
|
||||
{
|
||||
if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
|
||||
return FALSE;
|
||||
|
||||
if (push_element (parser, ELEMENT_AUTH) == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "include") == 0)
|
||||
|
|
@ -654,6 +695,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
|
|||
case ELEMENT_LIMIT:
|
||||
case ELEMENT_ALLOW:
|
||||
case ELEMENT_DENY:
|
||||
case ELEMENT_FORK:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -715,6 +757,7 @@ bus_config_parser_content (BusConfigParser *parser,
|
|||
case ELEMENT_LIMIT:
|
||||
case ELEMENT_ALLOW:
|
||||
case ELEMENT_DENY:
|
||||
case ELEMENT_FORK:
|
||||
if (all_whitespace (content))
|
||||
return TRUE;
|
||||
else
|
||||
|
|
@ -800,8 +843,19 @@ bus_config_parser_content (BusConfigParser *parser,
|
|||
|
||||
case ELEMENT_AUTH:
|
||||
{
|
||||
char *s;
|
||||
|
||||
e->had_content = TRUE;
|
||||
/* FIXME */
|
||||
|
||||
if (!_dbus_string_copy_data (content, &s))
|
||||
goto nomem;
|
||||
|
||||
if (!_dbus_list_append (&parser->mechanisms,
|
||||
s))
|
||||
{
|
||||
dbus_free (s);
|
||||
goto nomem;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -851,6 +905,18 @@ bus_config_parser_get_addresses (BusConfigParser *parser)
|
|||
return &parser->listen_on;
|
||||
}
|
||||
|
||||
DBusList**
|
||||
bus_config_parser_get_mechanisms (BusConfigParser *parser)
|
||||
{
|
||||
return &parser->mechanisms;
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
bus_config_parser_get_fork (BusConfigParser *parser)
|
||||
{
|
||||
return parser->fork;
|
||||
}
|
||||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,10 @@ dbus_bool_t bus_config_parser_finished (BusConfigParser *parser,
|
|||
DBusError *error);
|
||||
|
||||
/* Functions for extracting the parse results */
|
||||
const char* bus_config_parser_get_user (BusConfigParser *parser);
|
||||
DBusList** bus_config_parser_get_addresses (BusConfigParser *parser);
|
||||
const char* bus_config_parser_get_user (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);
|
||||
|
||||
/* Loader functions (backended off one of the XML parsers). Returns a
|
||||
* finished ConfigParser.
|
||||
|
|
|
|||
|
|
@ -2,13 +2,29 @@
|
|||
Add a system-local.conf and edit that rather than changing this
|
||||
file directly. -->
|
||||
|
||||
<!-- Note that there are any number of ways you can hose yourself
|
||||
security-wise by screwing up this file; in particular, you
|
||||
probably don't want to listen on any more addresses, add any more
|
||||
auth mechanisms, run as a different user, etc. -->
|
||||
|
||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<user>fixme</user>
|
||||
|
||||
<!-- Run as special user -->
|
||||
<user>messagebus</user>
|
||||
|
||||
<!-- Fork into daemon mode -->
|
||||
<fork/>
|
||||
|
||||
<!-- Only allow socket-credentials-based authentication -->
|
||||
<auth>EXTERNAL</auth>
|
||||
|
||||
<!-- Only listen on a local socket -->
|
||||
<listen>unix:path=@EXPANDED_LOCALSTATEDIR@/@DBUS_SYSTEM_SOCKET@</listen>
|
||||
|
||||
<policy context="default">
|
||||
<!-- Deny everything -->
|
||||
<!-- Deny everything then punch holes -->
|
||||
<deny send="*"/>
|
||||
<deny receive="*"/>
|
||||
<deny own="*"/>
|
||||
|
|
|
|||
|
|
@ -159,6 +159,10 @@ struct DBusAuth
|
|||
DBusKeyring *keyring; /**< Keyring for cookie mechanism. */
|
||||
int cookie_id; /**< ID of cookie to use */
|
||||
DBusString challenge; /**< Challenge sent to client */
|
||||
|
||||
char **allowed_mechs; /**< Mechanisms we're allowed to use,
|
||||
* or #NULL if we can use any
|
||||
*/
|
||||
|
||||
unsigned int needed_memory : 1; /**< We needed memory to continue since last
|
||||
* successful getting something done
|
||||
|
|
@ -1134,13 +1138,19 @@ all_mechanisms[] = {
|
|||
};
|
||||
|
||||
static const DBusAuthMechanismHandler*
|
||||
find_mech (const DBusString *name)
|
||||
find_mech (const DBusString *name,
|
||||
char **allowed_mechs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (allowed_mechs != NULL &&
|
||||
!_dbus_string_array_contains ((const char**) allowed_mechs,
|
||||
_dbus_string_get_const_data (name)))
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while (all_mechanisms[i].mechanism != NULL)
|
||||
{
|
||||
{
|
||||
if (_dbus_string_equal_c_str (name,
|
||||
all_mechanisms[i].mechanism))
|
||||
|
||||
|
|
@ -1259,7 +1269,7 @@ process_auth (DBusAuth *auth,
|
|||
&decoded_response, 0))
|
||||
goto failed;
|
||||
|
||||
auth->mech = find_mech (&mech);
|
||||
auth->mech = find_mech (&mech, auth->allowed_mechs);
|
||||
if (auth->mech != NULL)
|
||||
{
|
||||
_dbus_verbose ("Trying mechanism %s with initial response of %d bytes\n",
|
||||
|
|
@ -1418,7 +1428,7 @@ record_mechanisms (DBusAuth *auth,
|
|||
if (!get_word (args, &next, &m))
|
||||
goto nomem;
|
||||
|
||||
mech = find_mech (&m);
|
||||
mech = find_mech (&m, auth->allowed_mechs);
|
||||
|
||||
if (mech != NULL)
|
||||
{
|
||||
|
|
@ -1462,12 +1472,33 @@ client_try_next_mechanism (DBusAuth *auth)
|
|||
{
|
||||
const DBusAuthMechanismHandler *mech;
|
||||
DBusString auth_command;
|
||||
DBusAuthClient *client;
|
||||
|
||||
if (DBUS_AUTH_CLIENT (auth)->mechs_to_try == NULL)
|
||||
client = DBUS_AUTH_CLIENT (auth);
|
||||
|
||||
/* Pop any mechs not in the list of allowed mechanisms */
|
||||
mech = NULL;
|
||||
while (client->mechs_to_try != NULL)
|
||||
{
|
||||
mech = client->mechs_to_try->data;
|
||||
|
||||
if (auth->allowed_mechs != NULL &&
|
||||
!_dbus_string_array_contains ((const char**) auth->allowed_mechs,
|
||||
mech->mechanism))
|
||||
{
|
||||
/* don't try this one after all */
|
||||
_dbus_verbose ("Mechanism %s isn't in the list of allowed mechanisms\n",
|
||||
mech->mechanism);
|
||||
mech = NULL;
|
||||
_dbus_list_pop_first (& client->mechs_to_try);
|
||||
}
|
||||
else
|
||||
break; /* we'll try this one */
|
||||
}
|
||||
|
||||
if (mech == NULL)
|
||||
return FALSE;
|
||||
|
||||
mech = DBUS_AUTH_CLIENT (auth)->mechs_to_try->data;
|
||||
|
||||
if (!_dbus_string_init (&auth_command))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -1859,10 +1890,43 @@ _dbus_auth_unref (DBusAuth *auth)
|
|||
_dbus_string_free (&auth->identity);
|
||||
_dbus_string_free (&auth->incoming);
|
||||
_dbus_string_free (&auth->outgoing);
|
||||
|
||||
dbus_free_string_array (auth->allowed_mechs);
|
||||
|
||||
dbus_free (auth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of authentication mechanism names
|
||||
* that we are willing to use.
|
||||
*
|
||||
* @param auth the auth conversation
|
||||
* @param mechanisms #NULL-terminated array of mechanism names
|
||||
* @returns #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_auth_set_mechanisms (DBusAuth *auth,
|
||||
const char **mechanisms)
|
||||
{
|
||||
char **copy;
|
||||
|
||||
if (mechanisms != NULL)
|
||||
{
|
||||
copy = _dbus_dup_string_array (mechanisms);
|
||||
if (copy == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
copy = NULL;
|
||||
|
||||
dbus_free_string_array (auth->allowed_mechs);
|
||||
|
||||
auth->allowed_mechs = copy;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param auth the auth conversation object
|
||||
* @returns #TRUE if we're in a final state
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ DBusAuth* _dbus_auth_server_new (void);
|
|||
DBusAuth* _dbus_auth_client_new (void);
|
||||
void _dbus_auth_ref (DBusAuth *auth);
|
||||
void _dbus_auth_unref (DBusAuth *auth);
|
||||
dbus_bool_t _dbus_auth_set_mechanisms (DBusAuth *auth,
|
||||
const char **mechanisms);
|
||||
DBusAuthState _dbus_auth_do_work (DBusAuth *auth);
|
||||
dbus_bool_t _dbus_auth_get_bytes_to_send (DBusAuth *auth,
|
||||
const DBusString **str);
|
||||
|
|
|
|||
|
|
@ -107,18 +107,6 @@
|
|||
*
|
||||
* Maximum value of type "int"
|
||||
*/
|
||||
/**
|
||||
* @def _DBUS_MAX_SUN_PATH_LENGTH
|
||||
*
|
||||
* Maximum length of the path to a UNIX domain socket,
|
||||
* sockaddr_un::sun_path member. POSIX requires that all systems
|
||||
* support at least 100 bytes here, including the nul termination.
|
||||
* We use 99 for the max value to allow for the nul.
|
||||
*
|
||||
* We could probably also do sizeof (addr.sun_path)
|
||||
* but this way we are the same on all platforms
|
||||
* which is probably a good idea.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef DBusForeachFunction
|
||||
|
|
@ -250,6 +238,71 @@ _dbus_strdup (const char *str)
|
|||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates a string array. Result may be freed with
|
||||
* dbus_free_string_array(). Returns #NULL if memory allocation fails.
|
||||
* If the array to be duplicated is #NULL, returns #NULL.
|
||||
*
|
||||
* @param array array to duplicate.
|
||||
* @returns newly-allocated copy.
|
||||
*/
|
||||
char**
|
||||
_dbus_dup_string_array (const char **array)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
char **copy;
|
||||
|
||||
if (array == NULL)
|
||||
return NULL;
|
||||
|
||||
for (len = 0; array[len] != NULL; ++len)
|
||||
;
|
||||
|
||||
copy = dbus_new0 (char*, len + 1);
|
||||
if (copy == NULL)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
copy[i] = _dbus_strdup (array[i]);
|
||||
if (copy[i] == NULL)
|
||||
{
|
||||
dbus_free_string_array (copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a string array contains the given string.
|
||||
*
|
||||
* @param array array to search.
|
||||
* @param str string to look for
|
||||
* @returns #TRUE if array contains string
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_array_contains (const char **array,
|
||||
const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (array[i] != NULL)
|
||||
{
|
||||
if (strcmp (array[i], str) == 0)
|
||||
return TRUE;
|
||||
++i;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing the given type.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -128,12 +128,15 @@ do {
|
|||
#define _DBUS_ALIGN_ADDRESS(this, boundary) \
|
||||
((void*)_DBUS_ALIGN_VALUE(this, boundary))
|
||||
|
||||
char* _dbus_strdup (const char *str);
|
||||
char* _dbus_strdup (const char *str);
|
||||
dbus_bool_t _dbus_string_array_contains (const char **array,
|
||||
const char *str);
|
||||
char** _dbus_dup_string_array (const char **array);
|
||||
|
||||
|
||||
#define _DBUS_INT_MIN (-_DBUS_INT_MAX - 1)
|
||||
#define _DBUS_INT_MAX 2147483647
|
||||
#define _DBUS_UINT_MAX 0xffffffff
|
||||
#define _DBUS_MAX_SUN_PATH_LENGTH 99
|
||||
#define _DBUS_ONE_KILOBYTE 1024
|
||||
#define _DBUS_ONE_MEGABYTE 1024 * _DBUS_ONE_KILOBYTE
|
||||
#define _DBUS_ONE_HOUR_IN_MILLISECONDS (1000 * 60 * 60)
|
||||
|
|
|
|||
|
|
@ -283,6 +283,15 @@ _dbus_transport_debug_pipe_new (const char *server_name,
|
|||
|
||||
server_fd = -1;
|
||||
|
||||
if (!_dbus_transport_set_auth_mechanisms (server_transport,
|
||||
(const char**) server->auth_mechanisms))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
_dbus_transport_unref (server_transport);
|
||||
_dbus_transport_unref (client_transport);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
connection = _dbus_connection_new_for_transport (server_transport);
|
||||
_dbus_transport_unref (server_transport);
|
||||
server_transport = NULL;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ struct DBusServer
|
|||
/**< Callback to invoke to free new_connection_data
|
||||
* when server is finalized or data is replaced.
|
||||
*/
|
||||
|
||||
char **auth_mechanisms; /**< Array of allowed authentication mechanisms */
|
||||
|
||||
unsigned int disconnected : 1; /**< TRUE if we are disconnected. */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,6 +90,13 @@ handle_new_client_fd (DBusServer *server,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_dbus_transport_set_auth_mechanisms (transport,
|
||||
(const char **) server->auth_mechanisms))
|
||||
{
|
||||
_dbus_transport_unref (transport);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* note that client_fd is now owned by the transport, and will be
|
||||
* closed on transport disconnection/finalization
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ _dbus_server_finalize_base (DBusServer *server)
|
|||
_dbus_counter_unref (server->connection_counter);
|
||||
|
||||
dbus_free (server->address);
|
||||
|
||||
dbus_free_string_array (server->auth_mechanisms);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -599,6 +601,37 @@ dbus_server_handle_watch (DBusServer *server,
|
|||
return (* server->vtable->handle_watch) (server, watch, condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authentication mechanisms that this server offers
|
||||
* to clients, as a list of SASL mechanisms. This function
|
||||
* only affects connections created *after* it is called.
|
||||
* Pass #NULL instead of an array to use all available mechanisms.
|
||||
*
|
||||
* @param server the server
|
||||
* @param mechanisms #NULL-terminated array of mechanisms
|
||||
* @returns #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_server_set_auth_mechanisms (DBusServer *server,
|
||||
const char **mechanisms)
|
||||
{
|
||||
char **copy;
|
||||
|
||||
if (mechanisms != NULL)
|
||||
{
|
||||
copy = _dbus_dup_string_array (mechanisms);
|
||||
if (copy == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
copy = NULL;
|
||||
|
||||
dbus_free_string_array (server->auth_mechanisms);
|
||||
server->auth_mechanisms = copy;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of connections that can be open at one
|
||||
* time for this server. If the maximum is reached, and another
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ void dbus_server_set_max_connections (DBusServer *
|
|||
int dbus_server_get_max_connections (DBusServer *server);
|
||||
int dbus_server_get_n_connections (DBusServer *server);
|
||||
|
||||
dbus_bool_t dbus_server_set_auth_mechanisms (DBusServer *server,
|
||||
const char **mechanisms);
|
||||
|
||||
int dbus_server_allocate_data_slot (void);
|
||||
void dbus_server_free_data_slot (int slot);
|
||||
|
|
|
|||
|
|
@ -313,6 +313,21 @@ _dbus_write_two (int fd,
|
|||
#endif /* !HAVE_WRITEV */
|
||||
}
|
||||
|
||||
#define _DBUS_MAX_SUN_PATH_LENGTH 99
|
||||
|
||||
/**
|
||||
* @def _DBUS_MAX_SUN_PATH_LENGTH
|
||||
*
|
||||
* Maximum length of the path to a UNIX domain socket,
|
||||
* sockaddr_un::sun_path member. POSIX requires that all systems
|
||||
* support at least 100 bytes here, including the nul termination.
|
||||
* We use 99 for the max value to allow for the nul.
|
||||
*
|
||||
* We could probably also do sizeof (addr.sun_path)
|
||||
* but this way we are the same on all platforms
|
||||
* which is probably a good idea.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the UNIX domain socket at the
|
||||
* given path. The connection fd is returned, and is set up as
|
||||
|
|
@ -345,8 +360,7 @@ _dbus_connect_unix_socket (const char *path,
|
|||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH-1] = '\0';
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
|
||||
|
||||
if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
|
||||
{
|
||||
|
|
@ -377,7 +391,13 @@ _dbus_connect_unix_socket (const char *path,
|
|||
/**
|
||||
* Creates a socket and binds it to the given path,
|
||||
* then listens on the socket. The socket is
|
||||
* set to be nonblocking.
|
||||
* set to be nonblocking.
|
||||
*
|
||||
* @todo we'd like to be able to use the abstract namespace on linux
|
||||
* (see "man 7 unix"). The question is whether to silently move all
|
||||
* paths into that namespace if we can (I think that's best) or to
|
||||
* require it to be specified explicitly in the dbus address. Also,
|
||||
* need to sort out how to check for abstract namespace support.
|
||||
*
|
||||
* @param path the socket name
|
||||
* @param error return location for errors
|
||||
|
|
@ -402,10 +422,27 @@ _dbus_listen_unix_socket (const char *path,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* FIXME discussed security implications of this with Nalin,
|
||||
* and we couldn't think of where it would kick our ass, but
|
||||
* it still seems a bit sucky. It also has non-security suckage;
|
||||
* really we'd prefer to exit if the socket is already in use.
|
||||
* But there doesn't seem to be a good way to do this.
|
||||
*
|
||||
* Just to be extra careful, I threw in the stat() - clearly
|
||||
* the stat() can't *fix* any security issue, but it probably
|
||||
* makes it harder to exploit.
|
||||
*/
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat (path, &sb) == 0 &&
|
||||
S_ISSOCK (sb.st_mode))
|
||||
unlink (path);
|
||||
}
|
||||
|
||||
_DBUS_ZERO (addr);
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH);
|
||||
addr.sun_path[_DBUS_MAX_SUN_PATH_LENGTH-1] = '\0';
|
||||
strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
|
||||
|
||||
if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
|
||||
{
|
||||
|
|
@ -431,6 +468,13 @@ _dbus_listen_unix_socket (const char *path,
|
|||
close (listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try opening up the permissions, but if we can't, just go ahead
|
||||
* and continue, maybe it will be good enough.
|
||||
*/
|
||||
if (chmod (path, 0777) < 0)
|
||||
_dbus_warn ("Could not set mode 0777 on socket %s\n",
|
||||
path);
|
||||
|
||||
return listen_fd;
|
||||
}
|
||||
|
|
@ -3063,4 +3107,101 @@ _dbus_print_backtrace (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the chdir, fork, setsid, etc. to become a daemon process.
|
||||
*
|
||||
* @param error return location for errors
|
||||
* @returns #FALSE on failure
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_become_daemon (DBusError *error)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
/* This is so we don't prevent unmounting of devices. We divert
|
||||
* all messages to syslog
|
||||
*/
|
||||
if (chdir ("/") < 0)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Could not chdir() to root directory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
|
||||
if (s == NULL || *s == '\0')
|
||||
{
|
||||
int dev_null_fd;
|
||||
|
||||
/* silently ignore failures here, if someone
|
||||
* doesn't have /dev/null we may as well try
|
||||
* to continue anyhow
|
||||
*/
|
||||
|
||||
dev_null_fd = open ("/dev/null", O_RDWR);
|
||||
if (dev_null_fd >= 0)
|
||||
{
|
||||
dup2 (dev_null_fd, 0);
|
||||
dup2 (dev_null_fd, 1);
|
||||
dup2 (dev_null_fd, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a predictable umask */
|
||||
umask (022);
|
||||
|
||||
switch (fork ())
|
||||
{
|
||||
case -1:
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to fork daemon: %s", _dbus_strerror (errno));
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
_exit (0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (setsid () == -1)
|
||||
_dbus_assert_not_reached ("setsid() failed");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the user and group the bus is running as.
|
||||
*
|
||||
* @param uid the new user ID
|
||||
* @param gid the new group ID
|
||||
* @param error return location for errors
|
||||
* @returns #FALSE on failure
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_change_identity (unsigned long uid,
|
||||
unsigned long gid,
|
||||
DBusError *error)
|
||||
{
|
||||
if (setuid (uid) < 0)
|
||||
{
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to set UID to %lu: %s", uid,
|
||||
_dbus_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (setgid (gid) < 0)
|
||||
{
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Failed to set GID to %lu: %s", gid,
|
||||
_dbus_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** @} end of sysdeps */
|
||||
|
|
|
|||
|
|
@ -217,6 +217,12 @@ dbus_bool_t _dbus_close (int fd,
|
|||
|
||||
void _dbus_print_backtrace (void);
|
||||
|
||||
dbus_bool_t _dbus_become_daemon (DBusError *error);
|
||||
|
||||
dbus_bool_t _dbus_change_identity (unsigned long uid,
|
||||
unsigned long gid,
|
||||
DBusError *error);
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_SYSDEPS_H */
|
||||
|
|
|
|||
|
|
@ -907,4 +907,20 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport,
|
|||
transport->free_unix_user_data = free_data_function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SASL authentication mechanisms supported by this transport.
|
||||
*
|
||||
* @param transport the transport
|
||||
* @param mechanisms the #NULL-terminated array of mechanisms
|
||||
*
|
||||
* @returns #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_transport_set_auth_mechanisms (DBusTransport *transport,
|
||||
const char **mechanisms)
|
||||
{
|
||||
return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ 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_set_auth_mechanisms (DBusTransport *transport,
|
||||
const char **mechanisms);
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,15 @@ Elements:
|
|||
|
||||
The last <user> entry in the file "wins", the others are ignored.
|
||||
|
||||
The user is changed after the bus has completed initialization.
|
||||
So sockets etc. will be created before changing user, but no
|
||||
data will be read from clients before changing user.
|
||||
|
||||
<fork>
|
||||
|
||||
If present, the bus daemon becomes a real daemon (forks
|
||||
into the background, etc.)
|
||||
|
||||
<listen>
|
||||
|
||||
Add an address that the bus should listen on. The
|
||||
|
|
@ -72,6 +81,7 @@ Elements:
|
|||
Lists permitted authorization mechanisms. If this element doesn't
|
||||
exist, then all known mechanisms are allowed. If there are
|
||||
multiple <auth> elements, the last one wins (they are not merged).
|
||||
The order in which mechanisms are listed is not meaningful.
|
||||
|
||||
Example: <auth>EXTERNAL</auth>
|
||||
Example: <auth>DBUS_COOKIE_SHA1</auth>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue