From aa071099802f3bf866cffbfb25196dcdf1fbba1e Mon Sep 17 00:00:00 2001 From: Michael Leibowitz Date: Wed, 16 Mar 2011 22:29:06 -0700 Subject: [PATCH] Add a config file that specifies a whitelist of allowed devices This is in response to Bug 33431 "CVE-2011-0523: arbitrary file access and buffer overflows" A new config file, /etc/gypsy.conf, is added that specifies a whitelist of globs. By default, they are "/dev/tty*", "/dev/pgps", and "bluetooth" (which matches Bluetooth addresses). Signed-off-by: Michael Leibowitz Further changes by Bastien Nocera --- Makefile.am | 2 +- configure.ac | 3 ++ etc/Makefile.am | 2 + etc/gypsy.conf | 2 + src/gypsy-server.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/gypsy-server.h | 1 + 6 files changed, 78 insertions(+), 1 deletions(-) create mode 100644 etc/Makefile.am create mode 100644 etc/gypsy.conf diff --git a/Makefile.am b/Makefile.am index 8b4090e..174a2af 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = interfaces src gypsy examples docs +SUBDIRS = interfaces src gypsy examples docs etc pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gypsy.pc diff --git a/configure.ac b/configure.ac index 3484051..a441ceb 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,8 @@ DBUS_SYS_DIR="${sysconfdir}/dbus-1/system.d" AC_SUBST(DBUS_SYS_DIR) AC_DEFINE_UNQUOTED(DBUS_SYS_DIR, "$DBUS_SYS_DIR", [Where the system dir for D-Bus is]) +AC_DEFINE_UNQUOTED(CONFIG_FILE_PATH, "${sysconfdir}/gypsy.conf", [The absolute path of the config file]) + DBUS_SERVICES_DIR="${datadir}/dbus-1/system-services" AC_SUBST(DBUS_SERVICES_DIR) AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for D-Bus is]) @@ -72,6 +74,7 @@ docs/Makefile docs/reference/Makefile docs/reference/version.xml docs/tools/Makefile +etc/Makefile gypsy.pc ]) diff --git a/etc/Makefile.am b/etc/Makefile.am new file mode 100644 index 0000000..77d58f4 --- /dev/null +++ b/etc/Makefile.am @@ -0,0 +1,2 @@ +configdir = $(sysconfdir) +dist_config_DATA = gypsy.conf diff --git a/etc/gypsy.conf b/etc/gypsy.conf new file mode 100644 index 0000000..be76a35 --- /dev/null +++ b/etc/gypsy.conf @@ -0,0 +1,2 @@ +[gypsy] +AllowedDeviceGlobs=/dev/tty*;/dev/pgps;bluetooth diff --git a/src/gypsy-server.c b/src/gypsy-server.c index e2e3c1c..3ff13f4 100644 --- a/src/gypsy-server.c +++ b/src/gypsy-server.c @@ -28,12 +28,17 @@ /* * GypsyServer - The main control object that creates GPS connection objects. */ +#include "config.h" #include #include #include #include +#ifdef HAVE_BLUEZ +#include +#endif + #include "gypsy-server.h" #include "gypsy-debug.h" #include "gypsy-client.h" @@ -49,6 +54,9 @@ typedef struct _GypsyServerPrivate { int client_count; /* When client_count returns to 0, we quit the daemon after TERMINATE_TIMEOUT */ guint32 terminate_id; + + gchar **allowed_device_globs; + gsize allowed_device_glob_count; } GypsyServerPrivate; static guint32 signals[LAST_SIGNAL] = {0, }; @@ -60,6 +68,9 @@ G_DEFINE_TYPE (GypsyServer, gypsy_server, G_TYPE_OBJECT); #define GYPSY_GPS_PATH "/org/freedesktop/Gypsy/" #define TERMINATE_TIMEOUT 10000 /* 10 second timeout */ +#define GYPSY_CONF_GROUP "gypsy" +#define GYPSY_CONF_GLOB_KEY "AllowedDeviceGlobs" + static void gypsy_server_create (GypsyServer *gps, const char *IN_device_path, DBusGMethodInvocation *context); @@ -102,6 +113,8 @@ gypsy_server_create (GypsyServer *gps, GypsyClient *client; char *path, *device_name, *sender; GList *list; + int i; + gboolean allowed; priv = GET_PRIVATE (gps); @@ -113,6 +126,40 @@ gypsy_server_create (GypsyServer *gps, } GYPSY_NOTE (SERVER, "Creating client for %s", IN_device_path); + + /* compare priv->device_path to allowed globs + * if not allowed, error out */ + allowed = FALSE; + for (i = 0; i < priv->allowed_device_glob_count; i++) { + if (g_str_equal (priv->allowed_device_globs[i], "bluetooth")) { +#ifdef HAVE_BLUEZ + if (bachk (IN_device_path) == 0) { + allowed = TRUE; + break; + } +#else + continue; +#endif /* HAVE_BLUEZ */ + } + if (g_pattern_match_simple (priv->allowed_device_globs[i], + IN_device_path)) { + allowed = TRUE; + break; + } + } + if (allowed == FALSE) { + g_warning ("The device path %s is not allowed by config file", + IN_device_path); + GError *error = NULL; + error = g_error_new (GYPSY_SERVER_ERROR, + GYPSY_SERVER_ERROR_BAD_PATH, + "Bad path: %s", + IN_device_path); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + device_name = g_path_get_basename (IN_device_path); GYPSY_NOTE (SERVER, "Device name: %s", device_name); path = g_strdup_printf ("%s%s", GYPSY_GPS_PATH, @@ -250,6 +297,7 @@ gypsy_server_init (GypsyServer *gps) { GypsyServerPrivate *priv = GET_PRIVATE (gps); GError *error = NULL; + GKeyFile *key_file = NULL; priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); if (priv->connection == NULL) { @@ -265,6 +313,27 @@ gypsy_server_init (GypsyServer *gps) priv->client_count = 0; priv->terminate_id = 0; + + key_file = g_key_file_new(); + if (!g_key_file_load_from_file (key_file, CONFIG_FILE_PATH, + G_KEY_FILE_NONE, &error)) + goto error; + + priv->allowed_device_globs = g_key_file_get_string_list (key_file, + GYPSY_CONF_GROUP, + GYPSY_CONF_GLOB_KEY, + &(priv->allowed_device_glob_count), + &error); + if (!priv->allowed_device_globs) + goto error; + + return; + +error: + g_warning ("Error parsing config file:\n%s", + error->message); + g_error_free (error); + g_key_file_free (key_file); } void diff --git a/src/gypsy-server.h b/src/gypsy-server.h index 465f18e..3470ba7 100644 --- a/src/gypsy-server.h +++ b/src/gypsy-server.h @@ -37,6 +37,7 @@ G_BEGIN_DECLS typedef enum { GYPSY_SERVER_ERROR_NO_CLIENT, + GYPSY_SERVER_ERROR_BAD_PATH } GypsyServerError; typedef struct _GypsyServer { -- 1.7.6.2