summaryrefslogtreecommitdiff
path: root/dbus
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-04-22 19:34:33 +0000
committerHavoc Pennington <hp@redhat.com>2003-04-22 19:34:33 +0000
commitb3a3969897930eeda308113acbbb3f98069ee1ab (patch)
tree5cd99199ea35eb1f61d5d3cda9013130af488270 /dbus
parent983200f912f41ba75a873c011bfbcd3b0285bf4c (diff)
downloaddbus-b3a3969897930eeda308113acbbb3f98069ee1ab.tar.gz
2003-04-22 Havoc Pennington <hp@redhat.com>
* test/data/valid-messages/opposite-endian.message: fix test to use proper type for rply field * test/data/invalid-messages: add tests for below validation * dbus/dbus-message.c (decode_header_data): validate field types, and validate that named fields are valid names (decode_name_field): consider messages in the org.freedesktop.Local. namespace to be invalid. * dbus/dbus-string.c (_dbus_string_validate_name): new
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-connection.c2
-rw-r--r--dbus/dbus-message.c186
-rw-r--r--dbus/dbus-protocol.h12
-rw-r--r--dbus/dbus-string.c120
-rw-r--r--dbus/dbus-string.h6
5 files changed, 257 insertions, 69 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 7a89da3e..eb331662 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -267,7 +267,7 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection,
_dbus_list_append_link (&connection->incoming_messages,
link);
message = link->data;
-
+
/* If this is a reply we're waiting on, remove timeout for it */
reply_serial = dbus_message_get_reply_serial (message);
if (reply_serial != -1)
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index ee42947d..af949fb4 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -2910,8 +2910,9 @@ append_array_type (DBusMessageRealIter *real,
existing_element_type = iter_get_array_type (real, array_type_pos);
if (existing_element_type != element_type)
{
- _dbus_warn ("Appending array of %d, when expecting array of %d\n",
- element_type, existing_element_type);
+ _dbus_warn ("Appending array of %s, when expecting array of %s\n",
+ _dbus_type_to_string (element_type),
+ _dbus_type_to_string (existing_element_type));
_dbus_string_set_length (&real->message->body, real->pos);
return FALSE;
}
@@ -3627,7 +3628,76 @@ _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
#define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
-/* FIXME impose max length on name, srvc, sndr */
+static dbus_bool_t
+decode_string_field (const DBusString *data,
+ HeaderField fields[FIELD_LAST],
+ int pos,
+ int type,
+ int field,
+ const char *field_name)
+{
+ DBusString tmp;
+ int string_data_pos;
+
+ if (fields[field].offset >= 0)
+ {
+ _dbus_verbose ("%s field provided twice\n",
+ field_name);
+ return FALSE;
+ }
+
+ if (type != DBUS_TYPE_STRING)
+ {
+ _dbus_verbose ("%s field has wrong type\n", field_name);
+ return FALSE;
+ }
+
+ /* skip padding after typecode, skip string length;
+ * we assume that the string arg has already been validated
+ * for sanity and UTF-8
+ */
+ string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
+ _dbus_assert (string_data_pos < _dbus_string_get_length (data));
+
+ _dbus_string_init_const (&tmp,
+ _dbus_string_get_const_data (data) + string_data_pos);
+
+ if (field == FIELD_NAME)
+ {
+ if (!_dbus_string_validate_name (&tmp, 0, _dbus_string_get_length (&tmp)))
+ {
+ _dbus_verbose ("%s field has invalid content \"%s\"\n",
+ field_name, _dbus_string_get_const_data (&tmp));
+ return FALSE;
+ }
+
+ if (_dbus_string_starts_with_c_str (&tmp,
+ DBUS_NAMESPACE_LOCAL_MESSAGE))
+ {
+ _dbus_verbose ("Message is in the local namespace\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
+ {
+ _dbus_verbose ("%s field has invalid content \"%s\"\n",
+ field_name, _dbus_string_get_const_data (&tmp));
+ return FALSE;
+ }
+ }
+
+ fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
+
+#if 0
+ _dbus_verbose ("Found field %s name at offset %d\n",
+ field_name, fields[field].offset);
+#endif
+
+ return TRUE;
+}
+
static dbus_bool_t
decode_header_data (const DBusString *data,
int header_len,
@@ -3672,51 +3742,46 @@ decode_header_data (const DBusString *data,
pos += 4;
_dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
+
+ if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
+ {
+ _dbus_verbose ("Failed to validate type of named header field\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
+ {
+ _dbus_verbose ("Failed to validate argument to named header field\n");
+ return FALSE;
+ }
+ if (new_pos > header_len)
+ {
+ _dbus_verbose ("Named header field tries to extend beyond header length\n");
+ return FALSE;
+ }
+
switch (DBUS_UINT32_FROM_BE (*(int*)field))
{
case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
- if (fields[FIELD_SERVICE].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_SERVICE);
- return FALSE;
- }
-
- fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
-#if 0
- _dbus_verbose ("Found service name at offset %d\n",
- fields[FIELD_SERVICE].offset);
-#endif
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_SERVICE,
+ DBUS_HEADER_FIELD_SERVICE))
+ return FALSE;
break;
case DBUS_HEADER_FIELD_NAME_AS_UINT32:
- if (fields[FIELD_NAME].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_NAME);
- return FALSE;
- }
-
- fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
-
-#if 0
- _dbus_verbose ("Found message name at offset %d\n",
- fields[FIELD_NAME].offset);
-#endif
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_NAME,
+ DBUS_HEADER_FIELD_NAME))
+ return FALSE;
break;
- case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
- if (fields[FIELD_SENDER].offset >= 0)
- {
- _dbus_verbose ("%s field provided twice\n",
- DBUS_HEADER_FIELD_SENDER);
- return FALSE;
- }
-
- fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
- _dbus_verbose ("Found sender name at offset %d\n",
- fields[FIELD_NAME].offset);
+ case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
+ if (!decode_string_field (data, fields, pos, type,
+ FIELD_SENDER,
+ DBUS_HEADER_FIELD_SENDER))
+ return FALSE;
break;
case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
@@ -3726,8 +3791,14 @@ decode_header_data (const DBusString *data,
DBUS_HEADER_FIELD_REPLY);
return FALSE;
}
+
+ if (type != DBUS_TYPE_UINT32)
+ {
+ _dbus_verbose ("%s field has wrong type\n", DBUS_HEADER_FIELD_REPLY);
+ return FALSE;
+ }
- fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
+ fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos, 4);
_dbus_verbose ("Found reply serial at offset %d\n",
fields[FIELD_REPLY_SERIAL].offset);
@@ -3737,24 +3808,6 @@ decode_header_data (const DBusString *data,
_dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
field[0], field[1], field[2], field[3], pos);
}
-
- if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
- {
- _dbus_verbose ("Failed to validate type of named header field\n");
- return FALSE;
- }
-
- if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
- {
- _dbus_verbose ("Failed to validate argument to named header field\n");
- return FALSE;
- }
-
- if (new_pos > header_len)
- {
- _dbus_verbose ("Named header field tries to extend beyond header length\n");
- return FALSE;
- }
pos = new_pos;
}
@@ -3772,12 +3825,13 @@ decode_header_data (const DBusString *data,
}
}
- if (fields[FIELD_NAME].offset < 0)
- {
- _dbus_verbose ("No %s field provided\n",
- DBUS_HEADER_FIELD_NAME);
- return FALSE;
- }
+ /* Name field is mandatory */
+ if (fields[FIELD_NAME].offset < 0)
+ {
+ _dbus_verbose ("No %s field provided\n",
+ DBUS_HEADER_FIELD_NAME);
+ return FALSE;
+ }
if (message_padding)
*message_padding = header_len - pos;
@@ -5076,7 +5130,7 @@ _dbus_message_test (const char *test_data_dir)
_dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
/* Test the vararg functions */
- message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
+ message = dbus_message_new ("org.freedesktop.DBus.Test", "test.Message");
_dbus_message_set_serial (message, 1);
dbus_message_append_args (message,
DBUS_TYPE_INT32, -0x12345678,
@@ -5121,7 +5175,7 @@ _dbus_message_test (const char *test_data_dir)
dbus_message_unref (message);
dbus_message_unref (copy);
- message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
+ message = dbus_message_new ("org.freedesktop.DBus.Test", "test.Message");
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index 651969c4..314a9934 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -53,7 +53,10 @@ extern "C" {
#define DBUS_TYPE_DICT 10
#define DBUS_TYPE_LAST DBUS_TYPE_DICT
-
+
+/* Max length in bytes of a service or message name */
+#define DBUS_MAXIMUM_NAME_LENGTH 256
+
/* Header flags */
#define DBUS_HEADER_FLAG_ERROR 0x1
@@ -92,7 +95,12 @@ extern "C" {
#define DBUS_MESSAGE_SERVICE_DELETED "org.freedesktop.DBus.ServiceDeleted"
#define DBUS_MESSAGE_SERVICE_LOST "org.freedesktop.DBus.ServiceLost"
-#define DBUS_MESSAGE_LOCAL_DISCONNECT "org.freedesktop.Local.Disconnect"
+
+/* This namespace is reserved for locally-synthesized messages, you can't
+ * send messages that have this namespace.
+ */
+#define DBUS_NAMESPACE_LOCAL_MESSAGE "org.freedesktop.Local."
+#define DBUS_MESSAGE_LOCAL_DISCONNECT DBUS_NAMESPACE_LOCAL_MESSAGE"Disconnect"
#ifdef __cplusplus
}
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index 71fc5fcc..8abc74ac 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -28,6 +28,7 @@
#include "dbus-marshal.h"
#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
#include "dbus-string-private.h"
+#include "dbus-protocol.h"
/**
* @defgroup DBusString string class
@@ -2642,6 +2643,125 @@ _dbus_string_validate_nul (const DBusString *str,
}
/**
+ * Checks that the given range of the string is a valid message name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_name (const DBusString *str,
+ int start,
+ int len)
+{
+ const unsigned char *s;
+ const unsigned char *end;
+ dbus_bool_t saw_dot;
+
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (start >= 0);
+ _dbus_assert (len >= 0);
+ _dbus_assert (start <= real->len);
+
+ if (len > real->len - start)
+ return FALSE;
+
+ if (len > DBUS_MAXIMUM_NAME_LENGTH)
+ return FALSE;
+
+ if (len == 0)
+ return FALSE;
+
+ saw_dot = FALSE;
+ s = real->str + start;
+ end = s + len;
+ while (s != end)
+ {
+ if (*s == '.')
+ {
+ saw_dot = TRUE;
+ break;
+ }
+
+ ++s;
+ }
+
+ if (!saw_dot)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Checks that the given range of the string is a valid service name
+ * in the D-BUS protocol. This includes a length restriction, etc.,
+ * see the specification. It does not validate UTF-8, that has to be
+ * done separately for now.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that isn't in the string.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_string_validate_service (const DBusString *str,
+ int start,
+ int len)
+{
+ const unsigned char *s;
+ const unsigned char *end;
+ dbus_bool_t saw_dot;
+ dbus_bool_t is_base_service;
+
+ DBUS_CONST_STRING_PREAMBLE (str);
+ _dbus_assert (start >= 0);
+ _dbus_assert (len >= 0);
+ _dbus_assert (start <= real->len);
+
+ if (len > real->len - start)
+ return FALSE;
+
+ if (len > DBUS_MAXIMUM_NAME_LENGTH)
+ return FALSE;
+
+ if (len == 0)
+ return FALSE;
+
+ is_base_service = _dbus_string_get_byte (str, start) == ':';
+ if (is_base_service)
+ return TRUE; /* can have any content */
+
+ /* non-base-service must have the '.' indicating a namespace */
+
+ saw_dot = FALSE;
+ s = real->str + start;
+ end = s + len;
+ while (s != end)
+ {
+ if (*s == '.')
+ {
+ saw_dot = TRUE;
+ break;
+ }
+
+ ++s;
+ }
+
+ return saw_dot;
+}
+
+/**
* Clears all allocated bytes in the string to zero.
*
* @param str the string
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index 065c9caa..b9b298ae 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -210,6 +210,12 @@ dbus_bool_t _dbus_string_validate_utf8 (const DBusString *str,
dbus_bool_t _dbus_string_validate_nul (const DBusString *str,
int start,
int len);
+dbus_bool_t _dbus_string_validate_name (const DBusString *str,
+ int start,
+ int len);
+dbus_bool_t _dbus_string_validate_service (const DBusString *str,
+ int start,
+ int len);
void _dbus_string_zero (DBusString *str);