From cfa261b49dd9cafb172deae3db22dba0c2e54bf9 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 2 Apr 2003 00:29:33 +0000 Subject: [PATCH] 2003-04-01 Havoc Pennington * bus/config-parser.c, bus/bus.c: implement and (at least mostly) * dbus/dbus-sysdeps.c (_dbus_change_identity): set the group ID first, then the user ID --- ChangeLog | 8 ++ bus/activation.c | 14 +- bus/activation.h | 3 +- bus/bus.c | 4 +- bus/config-parser.c | 223 +++++++++++++++++++++++++++----- bus/config-parser.h | 9 +- dbus/dbus-keyring.c | 4 + dbus/dbus-sysdeps.c | 13 +- test/data/valid-config-files/basic.conf | 2 + 9 files changed, 226 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 602341a..ba9cb71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-04-01 Havoc Pennington + + * bus/config-parser.c, bus/bus.c: implement and + (at least mostly) + + * dbus/dbus-sysdeps.c (_dbus_change_identity): set the group ID + first, then the user ID + 2003-04-01 Havoc Pennington * dbus/dbus-server.c (dbus_server_set_auth_mechanisms): new diff --git a/bus/activation.c b/bus/activation.c index fe069c7..7f3693a 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -316,12 +316,12 @@ load_directory (BusActivation *activation, BusActivation* bus_activation_new (BusContext *context, const DBusString *address, - const char **directories, + DBusList **directories, DBusError *error) { - int i; BusActivation *activation; - + DBusList *link; + _DBUS_ASSERT_ERROR_IS_CLEAR (error); activation = dbus_new0 (BusActivation, 1); @@ -358,12 +358,12 @@ bus_activation_new (BusContext *context, } /* Load service files */ - i = 0; - while (directories[i] != NULL) + link = _dbus_list_get_first_link (directories); + while (link != NULL) { - if (!load_directory (activation, directories[i], error)) + if (!load_directory (activation, link->data, error)) goto failed; - ++i; + link = _dbus_list_get_next_link (directories, link); } return activation; diff --git a/bus/activation.h b/bus/activation.h index fd3a72c..0e9e6ea 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -25,11 +25,12 @@ #define BUS_ACTIVATION_H #include +#include #include "bus.h" BusActivation* bus_activation_new (BusContext *context, const DBusString *address, - const char **paths, + DBusList **directories, DBusError *error); void bus_activation_ref (BusActivation *activation); void bus_activation_unref (BusActivation *activation); diff --git a/bus/bus.c b/bus/bus.c index 1ca4feb..82452d0 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -187,7 +187,6 @@ bus_context_new (const DBusString *config_file, DBusList **addresses; BusConfigParser *parser; DBusString full_address; - const char *service_dirs[] = { NULL, NULL }; const char *user; char **auth_mechanisms; DBusList **auth_mechanisms_list; @@ -336,7 +335,8 @@ bus_context_new (const DBusString *config_file, /* Create activation subsystem */ context->activation = bus_activation_new (context, &full_address, - service_dirs, error); + bus_config_parser_get_service_dirs (parser), + error); if (context->activation == NULL) { _DBUS_ASSERT_ERROR_IS_SET (error); diff --git a/bus/config-parser.c b/bus/config-parser.c index dc3cb4d..77b68ca 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -38,7 +38,9 @@ typedef enum ELEMENT_LIMIT, ELEMENT_ALLOW, ELEMENT_DENY, - ELEMENT_FORK + ELEMENT_FORK, + ELEMENT_SERVICEDIR, + ELEMENT_INCLUDEDIR } ElementType; typedef struct @@ -87,6 +89,8 @@ struct BusConfigParser DBusList *listen_on; /**< List of addresses to listen to */ DBusList *mechanisms; /**< Auth mechanisms */ + + DBusList *service_dirs; /**< Directories to look for services in */ unsigned int fork : 1; /**< TRUE to fork into daemon mode */ }; @@ -118,6 +122,10 @@ element_type_to_name (ElementType type) return "deny"; case ELEMENT_FORK: return "fork"; + case ELEMENT_SERVICEDIR: + return "servicedir"; + case ELEMENT_INCLUDEDIR: + return "includedir"; } _dbus_assert_not_reached ("bad element type"); @@ -210,6 +218,9 @@ merge_included (BusConfigParser *parser, while ((link = _dbus_list_pop_first_link (&included->mechanisms))) _dbus_list_append_link (&parser->mechanisms, link); + + while ((link = _dbus_list_pop_first_link (&included->service_dirs))) + _dbus_list_append_link (&parser->service_dirs, link); return TRUE; } @@ -256,6 +267,12 @@ bus_config_parser_unref (BusConfigParser *parser) _dbus_list_clear (&parser->listen_on); + _dbus_list_foreach (&parser->service_dirs, + (DBusForeachFunction) dbus_free, + NULL); + + _dbus_list_clear (&parser->service_dirs); + dbus_free (parser); } } @@ -463,6 +480,32 @@ start_busconfig_child (BusConfigParser *parser, return TRUE; } + else if (strcmp (element_name, "includedir") == 0) + { + if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return FALSE; + } + + return TRUE; + } + else if (strcmp (element_name, "servicedir") == 0) + { + if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error)) + return FALSE; + + if (push_element (parser, ELEMENT_SERVICEDIR) == NULL) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return FALSE; + } + + return TRUE; + } else if (strcmp (element_name, "include") == 0) { Element *e; @@ -681,6 +724,8 @@ bus_config_parser_end_element (BusConfigParser *parser, case ELEMENT_USER: case ELEMENT_LISTEN: case ELEMENT_AUTH: + case ELEMENT_SERVICEDIR: + case ELEMENT_INCLUDEDIR: if (!e->had_content) { dbus_set_error (error, DBUS_ERROR_FAILED, @@ -714,6 +759,112 @@ all_whitespace (const DBusString *str) return i == _dbus_string_get_length (str); } +static dbus_bool_t +include_file (BusConfigParser *parser, + const DBusString *filename, + dbus_bool_t ignore_missing, + DBusError *error) +{ + /* FIXME good test case for this would load each config file in the + * test suite both alone, and as an include, and check + * that the result is the same + */ + BusConfigParser *included; + DBusError tmp_error; + + dbus_error_init (&tmp_error); + included = bus_config_load (filename, &tmp_error); + if (included == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); + + if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) && + ignore_missing) + { + dbus_error_free (&tmp_error); + return TRUE; + } + else + { + dbus_move_error (&tmp_error, error); + return FALSE; + } + } + else + { + _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); + + if (!merge_included (parser, included, error)) + { + bus_config_parser_unref (included); + return FALSE; + } + + bus_config_parser_unref (included); + return TRUE; + } +} + +static dbus_bool_t +include_dir (BusConfigParser *parser, + const DBusString *dirname, + DBusError *error) +{ + DBusString filename; + dbus_bool_t retval; + DBusError tmp_error; + DBusDirIter *dir; + + if (!_dbus_string_init (&filename)) + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return FALSE; + } + + retval = FALSE; + + dir = _dbus_directory_open (dirname, error); + + /* FIXME this is just so the tests pass for now, it needs to come out + * once I implement make-dirname-relative-to-currently-parsed-files-dir + */ + if (dir == NULL) + { + if (error) + dbus_error_free (error); + _dbus_string_free (&filename); + return TRUE; + } + + if (dir == NULL) + goto failed; + + while (_dbus_directory_get_next_file (dir, &filename, &tmp_error)) + { + if (_dbus_string_ends_with_c_str (&filename, ".conf")) + { + if (!include_file (parser, &filename, TRUE, error)) + goto failed; + } + } + + if (dbus_error_is_set (&tmp_error)) + { + dbus_move_error (&tmp_error, error); + goto failed; + } + + retval = TRUE; + + failed: + _dbus_string_free (&filename); + + if (dir) + _dbus_directory_close (dir); + + return retval; +} + dbus_bool_t bus_config_parser_content (BusConfigParser *parser, const DBusString *content, @@ -770,45 +921,23 @@ bus_config_parser_content (BusConfigParser *parser, case ELEMENT_INCLUDE: { - /* FIXME good test case for this would load each config file in the - * test suite both alone, and as an include, and check - * that the result is the same - */ - BusConfigParser *included; - DBusError tmp_error; - e->had_content = TRUE; - - dbus_error_init (&tmp_error); - included = bus_config_load (content, &tmp_error); - if (included == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); - if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) && - e->d.include.ignore_missing) - { - dbus_error_free (&tmp_error); - return TRUE; - } - else - { - dbus_move_error (&tmp_error, error); - return FALSE; - } - } - else - { - _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); - if (!merge_included (parser, included, error)) - return FALSE; - - bus_config_parser_unref (included); - return TRUE; - } + if (!include_file (parser, content, + e->d.include.ignore_missing, error)) + return FALSE; } break; + case ELEMENT_INCLUDEDIR: + { + e->had_content = TRUE; + + if (!include_dir (parser, content, error)) + return FALSE; + } + break; + case ELEMENT_USER: { char *s; @@ -858,6 +987,24 @@ bus_config_parser_content (BusConfigParser *parser, } } break; + + case ELEMENT_SERVICEDIR: + { + char *s; + + e->had_content = TRUE; + + if (!_dbus_string_copy_data (content, &s)) + goto nomem; + + if (!_dbus_list_append (&parser->service_dirs, + s)) + { + dbus_free (s); + goto nomem; + } + } + break; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -911,6 +1058,12 @@ bus_config_parser_get_mechanisms (BusConfigParser *parser) return &parser->mechanisms; } +DBusList** +bus_config_parser_get_service_dirs (BusConfigParser *parser) +{ + return &parser->service_dirs; +} + dbus_bool_t bus_config_parser_get_fork (BusConfigParser *parser) { diff --git a/bus/config-parser.h b/bus/config-parser.h index 101b4c6..d06cde0 100644 --- a/bus/config-parser.h +++ b/bus/config-parser.h @@ -55,10 +55,11 @@ 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); -DBusList** bus_config_parser_get_mechanisms (BusConfigParser *parser); -dbus_bool_t bus_config_parser_get_fork (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); +DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser); /* Loader functions (backended off one of the XML parsers). Returns a * finished ConfigParser. diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c index d63bc3e..b920340 100644 --- a/dbus/dbus-keyring.c +++ b/dbus/dbus-keyring.c @@ -41,6 +41,10 @@ * file in the user's homedir. However they are transient (only used * by a single server instance for a fixed period of time, then * discarded). Also, the keys are not sent over the wire. + * + * @todo there's a memory leak on some codepath in here, I saw it once + * when running make check - probably some specific initial cookies + * present in the cookie file, then depending on what we do with them. */ /** diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 71863ef..8aa9181 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -3185,18 +3185,21 @@ _dbus_change_identity (unsigned long uid, unsigned long gid, DBusError *error) { - if (setuid (uid) < 0) + /* Set GID first, or the setuid may remove our permission + * to change the GID + */ + if (setgid (gid) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to set UID to %lu: %s", uid, + "Failed to set GID to %lu: %s", gid, _dbus_strerror (errno)); return FALSE; } - - if (setgid (gid) < 0) + + if (setuid (uid) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to set GID to %lu: %s", gid, + "Failed to set UID to %lu: %s", uid, _dbus_strerror (errno)); return FALSE; } diff --git a/test/data/valid-config-files/basic.conf b/test/data/valid-config-files/basic.conf index 222122c..d109d71 100644 --- a/test/data/valid-config-files/basic.conf +++ b/test/data/valid-config-files/basic.conf @@ -4,6 +4,8 @@ mybususer unix:path=/foo/bar tcp:port=1234 + basic.d + /usr/share/foo nonexistent.conf -- 2.7.4