diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c index 8cc4048..a31941e 100644 --- a/dbus/dbus-keyring.c +++ b/dbus/dbus-keyring.c @@ -837,15 +837,14 @@ _dbus_keyring_new_for_credentials (DBusCredentials *credentials, * in filenames are not allowed (contexts can't * start with a dot or contain dir separators). * - * @todo this is the most inefficient implementation - * imaginable. - * * @param context the context * @returns #TRUE if valid */ dbus_bool_t _dbus_keyring_validate_context (const DBusString *context) { + int found; + if (_dbus_string_get_length (context) == 0) { _dbus_verbose ("context is zero-length\n"); @@ -858,26 +857,38 @@ _dbus_keyring_validate_context (const DBusString *context) _dbus_verbose ("context not valid ascii\n"); return FALSE; } - - /* no directory separators */ - if (_dbus_string_find (context, 0, "/", NULL)) - { - _dbus_verbose ("context contains a slash\n"); - return FALSE; - } - if (_dbus_string_find (context, 0, "\\", NULL)) - { - _dbus_verbose ("context contains a backslash\n"); - return FALSE; - } - - /* prevent attempts to use dotfiles or ".." or ".lock" + /* no directory separators, and no dots to + * prevent attempts to use dotfiles or ".." or ".lock" * all of which might allow some kind of attack */ - if (_dbus_string_find (context, 0, ".", NULL)) + if (_dbus_string_find_char_from_sorted_array(context, 0, + _dbus_string_get_length (context), + "\n\r./\\", + &found)) { - _dbus_verbose ("context contains a dot\n"); +#ifdef DBUS_ENABLE_VERBOSE_MODE + unsigned char c; + + c = _dbus_string_get_byte(context, found); + switch(c) + { + case '\n': + _dbus_verbose ("context contains a newline\n"); + break; + case '\r': + _dbus_verbose ("context contains a carriage return\n"); + break; + case '.': + _dbus_verbose ("context contains a dot\n"); + break; + case '/': + _dbus_verbose ("context contains a slash\n"); + break; + default: + break; + } +#endif return FALSE; } @@ -888,18 +899,6 @@ _dbus_keyring_validate_context (const DBusString *context) return FALSE; } - if (_dbus_string_find (context, 0, "\n", NULL)) - { - _dbus_verbose ("context contains a newline\n"); - return FALSE; - } - - if (_dbus_string_find (context, 0, "\r", NULL)) - { - _dbus_verbose ("context contains a carriage return\n"); - return FALSE; - } - return TRUE; } diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index aed9487..0f72b10 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -685,7 +685,31 @@ _dbus_string_test (void) if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i)) _dbus_assert_not_reached ("Didn't find 'e'"); _dbus_assert (i == 1); - + + if (_dbus_string_find_char_from_sorted_array(&str, 0, _dbus_string_get_length (&str), "abc", &i)) + _dbus_assert_not_reached ("Did find 'abc'"); + _dbus_assert (i == -1); + + if (!_dbus_string_find_char_from_sorted_array(&str, 0, _dbus_string_get_length (&str), "abcl", &i)) + _dbus_assert_not_reached ("Didn't find 'l'"); + _dbus_assert (i == 2); + + if (!_dbus_string_find_char_from_sorted_array(&str, 0, _dbus_string_get_length (&str), "cel", &i)) + _dbus_assert_not_reached ("Didn't find 'e'"); + _dbus_assert (i == 1); + + if (_dbus_string_find_char_from_sorted_array(&str, 2, _dbus_string_get_length (&str) - 1, "abc", &i)) + _dbus_assert_not_reached ("Did find 'abc'"); + _dbus_assert (i == -1); + + if (!_dbus_string_find_char_from_sorted_array(&str, 2, _dbus_string_get_length (&str) - 1, "abcl", &i)) + _dbus_assert_not_reached ("Didn't find 'l'"); + _dbus_assert (i == 2); + + if (_dbus_string_find_char_from_sorted_array(&str, 2, _dbus_string_get_length (&str) - 1, "cem", &i)) + _dbus_assert_not_reached ("Did find 'e'"); + _dbus_assert (i == -1); + _dbus_string_free (&str); /* Hex encoding */ diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 6b9b2bf..b22fb5a 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -2024,6 +2024,88 @@ _dbus_string_find_to (const DBusString *str, } /** + * Finds a char from an array sorted in ASCII order + * in the string, starting from a certain position + * up to another. + * Returns #TRUE and filling in the byte index + * where one of the char was found, if it was found. + * Returns #FALSE if any char is found. + * Sets *found to -1 if none of the chars is found + * + * @param str the string + * @param start where to start looking + * @param end where to stop looking + * @param chars a \0 terminated array of chars, sorted by ASCII code + * @param found return location for where it was found, or #NULL + * @returns #TRUE if found + */ +dbus_bool_t +_dbus_string_find_char_from_sorted_array (const DBusString *str, + int start, + int end, + const char *chars, + int *found) +{ + int i; + int last_char_pos; + DBUS_CONST_STRING_PREAMBLE (str); + _dbus_assert (chars != NULL); + _dbus_assert (start <= real->len); + _dbus_assert (start >= 0); + _dbus_assert (end <= real->len); + _dbus_assert (start <= end); + + /* '\0' is found in every string */ + if (*chars == '\0') + { + if (found) + *found = start; + return TRUE; + } + + last_char_pos = strlen(chars) - 1; + +#ifndef DBUS_DISABLE_ASSERT + for ( i = 0; i < last_char_pos; i++ ) + { + _dbus_assert (chars[i] < chars[i + 1]); + } +#endif + + i = start; + while (i < end) + { + if (real->str[i] <= chars[last_char_pos]) + { + int j = last_char_pos; + + while (j >= 0) + { + if (real->str[i] == chars[j]) + { + if (found) + *found = i; + return TRUE; + } + else if (real->str[i] > chars[j]) + { + break; + } + + --j; + } + } + + ++i; + } + + if (found) + *found = -1; + + return FALSE; +} + +/** * Finds a blank (space or tab) in the string. Returns #TRUE * if found, #FALSE otherwise. If a blank is not found sets * *found to the length of the string. diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index 374f0a8..72bb213 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -237,6 +237,11 @@ dbus_bool_t _dbus_string_find_byte_backward (const DBusString *str, int start, unsigned char byte, int *found); +dbus_bool_t _dbus_string_find_char_from_sorted_array (const DBusString *str, + int start, + int end, + const char *chars, + int *found); dbus_bool_t _dbus_string_find_blank (const DBusString *str, int start, int *found);