summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2007-06-10 04:54:45 +0000
committerHavoc Pennington <hp@redhat.com>2007-06-10 04:54:45 +0000
commita789b7b38cb4f4540a41444cbd64bf7ada2d60d2 (patch)
treedb5164def7f5d19266bc4ebfb4ce740f269d79e2
parent7be5fd95cdccdca28937804f32ca8b1308887d09 (diff)
2007-06-09 Havoc Pennington <hp@redhat.com>
* dbus/dbus-string.c (_dbus_string_pop_line): fix this not to think an empty line is the end of the file. Also, fix some whitespace. * dbus/dbus-string-util.c: add more tests for _dbus_string_pop_line() revealing that it thinks an empty line is the end of the file, which broke dbus-auth-script.c so it didn't really run the scripts * dbus/dbus-auth.c: add ANONYMOUS mechanism * dbus/dbus-auth-script.c (_dbus_auth_script_run): fix to detect an empty/no-op auth script; add commands to check that we have or don't have the expected credentials
-rw-r--r--ChangeLog17
-rw-r--r--dbus/dbus-auth-script.c41
-rw-r--r--dbus/dbus-auth.c138
-rw-r--r--dbus/dbus-string-util.c112
-rw-r--r--dbus/dbus-string.c36
-rw-r--r--test/data/auth/anonymous-client-successful.auth-script16
-rw-r--r--test/data/auth/anonymous-server-successful.auth-script13
-rw-r--r--test/data/auth/external-failed.auth-script5
-rw-r--r--test/data/auth/external-root.auth-script3
-rw-r--r--test/data/auth/external-silly.auth-script6
-rw-r--r--test/data/auth/external-successful.auth-script5
11 files changed, 334 insertions, 58 deletions
diff --git a/ChangeLog b/ChangeLog
index c7d2479b..5806aee8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2007-06-09 Havoc Pennington <hp@redhat.com>
+ * dbus/dbus-string.c (_dbus_string_pop_line): fix this not to
+ think an empty line is the end of the file.
+ Also, fix some whitespace.
+
+ * dbus/dbus-string-util.c: add more tests for
+ _dbus_string_pop_line() revealing that it thinks an empty line is
+ the end of the file, which broke dbus-auth-script.c so
+ it didn't really run the scripts
+
+ * dbus/dbus-auth.c: add ANONYMOUS mechanism
+
+ * dbus/dbus-auth-script.c (_dbus_auth_script_run): fix to detect
+ an empty/no-op auth script; add commands to check that we have or
+ don't have the expected credentials
+
+2007-06-09 Havoc Pennington <hp@redhat.com>
+
* bus/policy.c (bus_policy_create_client_policy): gracefully
continue if the connection has no unix user - just don't apply
any unix user dependent rules.
diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index 5aa17d4b..dd864ca5 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -218,10 +218,8 @@ auth_set_unix_credentials(DBusAuth *auth,
credentials = _dbus_credentials_new ();
if (credentials == NULL)
- {
- _dbus_warn ("no memory\n");
- return;
- }
+ _dbus_assert_not_reached ("no memory");
+
if (uid != DBUS_UID_UNSET)
_dbus_credentials_add_unix_uid (credentials, uid);
if (pid != DBUS_PID_UNSET)
@@ -288,11 +286,14 @@ _dbus_auth_script_run (const DBusString *filename)
state = DBUS_AUTH_STATE_NEED_DISCONNECT;
line_no = 0;
+
next_iteration:
while (_dbus_string_pop_line (&file, &line))
{
line_no += 1;
+ /* _dbus_warn ("%s\n", _dbus_string_get_const_data (&line)); */
+
_dbus_string_delete_leading_blanks (&line);
if (auth != NULL)
@@ -659,6 +660,30 @@ _dbus_auth_script_run (const DBusString *filename)
}
}
else if (_dbus_string_starts_with_c_str (&line,
+ "EXPECT_HAVE_NO_CREDENTIALS"))
+ {
+ DBusCredentials *authorized_identity;
+
+ authorized_identity = _dbus_auth_get_identity (auth);
+ if (!_dbus_credentials_are_empty (authorized_identity))
+ {
+ _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
+ goto out;
+ }
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
+ "EXPECT_HAVE_SOME_CREDENTIALS"))
+ {
+ DBusCredentials *authorized_identity;
+
+ authorized_identity = _dbus_auth_get_identity (auth);
+ if (_dbus_credentials_are_empty (authorized_identity))
+ {
+ _dbus_warn ("Expected to have some credentials, but we don't\n");
+ goto out;
+ }
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
"EXPECT"))
{
DBusString expected;
@@ -708,8 +733,12 @@ _dbus_auth_script_run (const DBusString *filename)
}
}
- if (auth != NULL &&
- state == DBUS_AUTH_STATE_AUTHENTICATED)
+ if (auth == NULL)
+ {
+ _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
+ goto out;
+ }
+ else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
{
const DBusString *unused;
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index b1d57a49..657f8d3d 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -424,6 +424,10 @@ shutdown_mech (DBusAuth *auth)
}
}
+/*
+ * DBUS_COOKIE_SHA1 mechanism
+ */
+
/* Returns TRUE but with an empty string hash if the
* cookie_id isn't known. As with all this code
* TRUE just means we had enough memory.
@@ -982,6 +986,10 @@ handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)
_dbus_string_set_length (&auth->challenge, 0);
}
+/*
+ * EXTERNAL mechanism
+ */
+
static dbus_bool_t
handle_server_data_external_mech (DBusAuth *auth,
const DBusString *data)
@@ -1051,7 +1059,7 @@ handle_server_data_external_mech (DBusAuth *auth,
}
}
- if (_dbus_credentials_are_empty(auth->desired_identity))
+ if (_dbus_credentials_are_empty (auth->desired_identity))
{
_dbus_verbose ("%s: desired user %s is no good\n",
DBUS_AUTH_NAME (auth),
@@ -1142,13 +1150,120 @@ handle_client_shutdown_external_mech (DBusAuth *auth)
}
+/*
+ * ANONYMOUS mechanism
+ */
+
+static dbus_bool_t
+handle_server_data_anonymous_mech (DBusAuth *auth,
+ const DBusString *data)
+{
+ if (_dbus_string_get_length (data) > 0)
+ {
+ /* Client is allowed to send "trace" data, the only defined
+ * meaning is that if it contains '@' it is an email address,
+ * and otherwise it is anything else, and it's supposed to be
+ * UTF-8
+ */
+ if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data)))
+ {
+ _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n",
+ DBUS_AUTH_NAME (auth));
+
+ {
+ DBusString plaintext;
+ DBusString encoded;
+ _dbus_string_init_const (&plaintext, "D-Bus " VERSION);
+ _dbus_string_init (&encoded);
+ _dbus_string_hex_encode (&plaintext, 0,
+ &encoded,
+ 0);
+ _dbus_verbose ("%s: try '%s'\n",
+ DBUS_AUTH_NAME (auth), _dbus_string_get_const_data (&encoded));
+ }
+ return send_rejected (auth);
+ }
+
+ _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
+ DBUS_AUTH_NAME (auth),
+ _dbus_string_get_const_data (data));
+ }
+
+ /* We want to be anonymous (clear in case some other protocol got midway through I guess) */
+ _dbus_credentials_clear (auth->desired_identity);
+
+ /* Anonymous is always allowed */
+ if (!send_ok (auth))
+ return FALSE;
+
+ _dbus_verbose ("%s: authenticated client as anonymous\n",
+ DBUS_AUTH_NAME (auth));
+
+ return TRUE;
+}
+
+static void
+handle_server_shutdown_anonymous_mech (DBusAuth *auth)
+{
+
+}
+
+static dbus_bool_t
+handle_client_initial_response_anonymous_mech (DBusAuth *auth,
+ DBusString *response)
+{
+ /* Our initial response is a "trace" string which must be valid UTF-8
+ * and must be an email address if it contains '@'.
+ * We just send the dbus implementation info, like a user-agent or
+ * something, because... why not. There's nothing guaranteed here
+ * though, we could change it later.
+ */
+ DBusString plaintext;
+
+ if (!_dbus_string_init (&plaintext))
+ return FALSE;
+
+ if (!_dbus_string_append (&plaintext,
+ "libdbus " VERSION))
+ goto failed;
+
+ if (!_dbus_string_hex_encode (&plaintext, 0,
+ response,
+ _dbus_string_get_length (response)))
+ goto failed;
+
+ _dbus_string_free (&plaintext);
+
+ return TRUE;
+
+ failed:
+ _dbus_string_free (&plaintext);
+ return FALSE;
+}
+
+static dbus_bool_t
+handle_client_data_anonymous_mech (DBusAuth *auth,
+ const DBusString *data)
+{
+
+ return TRUE;
+}
+
+static void
+handle_client_shutdown_anonymous_mech (DBusAuth *auth)
+{
+
+}
+
/* Put mechanisms here in order of preference.
- * What I eventually want to have is:
+ * Right now we have:
+ *
+ * - EXTERNAL checks socket credentials (or in the future, other info from the OS)
+ * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE
+ * - ANONYMOUS checks nothing but doesn't auth the person as a user
*
- * - a mechanism that checks UNIX domain socket credentials
- * - a simple magic cookie mechanism like X11 or ICE
- * - mechanisms that chain to Cyrus SASL, so we can use anything it
- * offers such as Kerberos, X509, whatever.
+ * We might ideally add a mechanism to chain to Cyrus SASL so we can
+ * use its mechanisms as well.
*
*/
static const DBusAuthMechanismHandler
@@ -1169,6 +1284,14 @@ all_mechanisms[] = {
handle_client_data_cookie_sha1_mech,
NULL, NULL,
handle_client_shutdown_cookie_sha1_mech },
+ { "ANONYMOUS",
+ handle_server_data_anonymous_mech,
+ NULL, NULL,
+ handle_server_shutdown_anonymous_mech,
+ handle_client_initial_response_anonymous_mech,
+ handle_client_data_anonymous_mech,
+ NULL, NULL,
+ handle_client_shutdown_anonymous_mech },
{ NULL, NULL }
};
@@ -1881,7 +2004,8 @@ lookup_command_from_name (DBusString *command)
}
static void
-goto_state (DBusAuth *auth, const DBusAuthStateData *state)
+goto_state (DBusAuth *auth,
+ const DBusAuthStateData *state)
{
_dbus_verbose ("%s: going from state %s to state %s\n",
DBUS_AUTH_NAME (auth),
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
index 16a79340..27bd23a1 100644
--- a/dbus/dbus-string-util.c
+++ b/dbus/dbus-string-util.c
@@ -705,43 +705,93 @@ _dbus_string_test (void)
_dbus_string_free (&str);
{
- int found,found_len;
- _dbus_string_init_const (&str, "012\r\n567\n90");
-
- if (!_dbus_string_find_eol(&str, 0, &found, &found_len) || found != 3 || found_len != 2)
- _dbus_assert_not_reached ("Did not find '\\r\\n'");
- if (found != 3 || found_len != 2)
- _dbus_assert_not_reached ("invalid return values");
-
- if (!_dbus_string_find_eol(&str, 5, &found, &found_len))
- _dbus_assert_not_reached ("Did not find '\\n'");
- if (found != 8 || found_len != 1)
- _dbus_assert_not_reached ("invalid return values");
-
- if (_dbus_string_find_eol(&str, 9, &found, &found_len))
- _dbus_assert_not_reached ("Found not expected '\\n'");
- else if (found != 11 || found_len != 0)
- _dbus_assert_not_reached ("invalid return values '\\n'");
-
- _dbus_string_free (&str);
- }
-
- return TRUE;
-}
-
-#endif /* DBUS_BUILD_TESTS */
-
-
-
-
-
-
+ int found, found_len;
+ _dbus_string_init_const (&str, "012\r\n567\n90");
+
+ if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2)
+ _dbus_assert_not_reached ("Did not find '\\r\\n'");
+ if (found != 3 || found_len != 2)
+ _dbus_assert_not_reached ("invalid return values");
+
+ if (!_dbus_string_find_eol (&str, 5, &found, &found_len))
+ _dbus_assert_not_reached ("Did not find '\\n'");
+ if (found != 8 || found_len != 1)
+ _dbus_assert_not_reached ("invalid return values");
+
+ if (_dbus_string_find_eol (&str, 9, &found, &found_len))
+ _dbus_assert_not_reached ("Found not expected '\\n'");
+ else if (found != 11 || found_len != 0)
+ _dbus_assert_not_reached ("invalid return values '\\n'");
+
+ found = -1;
+ found_len = -1;
+ _dbus_string_init_const (&str, "");
+ if (_dbus_string_find_eol (&str, 0, &found, &found_len))
+ _dbus_assert_not_reached ("found an eol in an empty string");
+ _dbus_assert (found == 0);
+ _dbus_assert (found_len == 0);
+
+ found = -1;
+ found_len = -1;
+ _dbus_string_init_const (&str, "foobar");
+ if (_dbus_string_find_eol (&str, 0, &found, &found_len))
+ _dbus_assert_not_reached ("found eol in string that lacks one");
+ _dbus_assert (found == 6);
+ _dbus_assert (found_len == 0);
+
+ found = -1;
+ found_len = -1;
+ _dbus_string_init_const (&str, "foobar\n");
+ if (!_dbus_string_find_eol (&str, 0, &found, &found_len))
+ _dbus_assert_not_reached ("did not find eol in string that has one at end");
+ _dbus_assert (found == 6);
+ _dbus_assert (found_len == 1);
+ }
+ {
+ DBusString line;
+#define FIRST_LINE "this is a line"
+#define SECOND_LINE "this is a second line"
+ /* third line is empty */
+#define THIRD_LINE ""
+#define FOURTH_LINE "this is a fourth line"
+
+ if (!_dbus_string_init (&str))
+ _dbus_assert_not_reached ("no memory");
+ if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE))
+ _dbus_assert_not_reached ("no memory");
+
+ if (!_dbus_string_init (&line))
+ _dbus_assert_not_reached ("no memory");
+
+ if (!_dbus_string_pop_line (&str, &line))
+ _dbus_assert_not_reached ("failed to pop first line");
+ _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE));
+
+ if (!_dbus_string_pop_line (&str, &line))
+ _dbus_assert_not_reached ("failed to pop second line");
+ _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE));
+
+ if (!_dbus_string_pop_line (&str, &line))
+ _dbus_assert_not_reached ("failed to pop third line");
+ _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE));
+
+ if (!_dbus_string_pop_line (&str, &line))
+ _dbus_assert_not_reached ("failed to pop fourth line");
+ _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE));
+
+ _dbus_string_free (&str);
+ _dbus_string_free (&line);
+ }
+
+ return TRUE;
+}
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index d83a3f39..6177a751 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -1804,9 +1804,9 @@ _dbus_string_find (const DBusString *str,
*/
dbus_bool_t
_dbus_string_find_eol (const DBusString *str,
- int start,
- int *found,
- int *found_len)
+ int start,
+ int *found,
+ int *found_len)
{
int i;
@@ -1843,7 +1843,7 @@ _dbus_string_find_eol (const DBusString *str,
if (found_len)
*found_len = 1;
return TRUE;
- }
+ }
++i;
}
@@ -2093,17 +2093,33 @@ _dbus_string_pop_line (DBusString *source,
_dbus_string_set_length (dest, 0);
eol = 0;
+ eol_len = 0;
if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
- eol = _dbus_string_get_length (source);
+ {
+ _dbus_assert (eol == _dbus_string_get_length (source));
+ if (eol == 0)
+ {
+ /* If there's no newline and source has zero length, we're done */
+ return FALSE;
+ }
+ /* otherwise, the last line of the file has no eol characters */
+ }
- if (eol == 0)
- return FALSE; /* eof */
+ /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
+ * since find_eol returned TRUE
+ */
if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
- return FALSE;
-
+ return FALSE;
+
/* remove line ending */
- return _dbus_string_set_length(dest, eol);
+ if (!_dbus_string_set_length (dest, eol))
+ {
+ _dbus_assert_not_reached ("out of memory when shortening a string");
+ return FALSE;
+ }
+
+ return TRUE;
}
#ifdef DBUS_BUILD_TESTS
diff --git a/test/data/auth/anonymous-client-successful.auth-script b/test/data/auth/anonymous-client-successful.auth-script
new file mode 100644
index 00000000..9a1620bc
--- /dev/null
+++ b/test/data/auth/anonymous-client-successful.auth-script
@@ -0,0 +1,16 @@
+## this tests that a client can login anonymously
+
+CLIENT
+
+## Reject whatever mechanism the client picks first
+EXPECT_COMMAND AUTH
+SEND 'REJECTED DBUS_TEST_NONEXISTENT_MECH1 ANONYMOUS DBUS_TEST_NONEXISTENT_MECH2'
+
+## And this time we get ANONYMOUS
+
+EXPECT_COMMAND AUTH
+## of course real DBUS_COOKIE_SHA1 would not send this here...
+SEND 'OK 1234deadbeef'
+
+EXPECT_COMMAND BEGIN
+EXPECT_STATE AUTHENTICATED
diff --git a/test/data/auth/anonymous-server-successful.auth-script b/test/data/auth/anonymous-server-successful.auth-script
new file mode 100644
index 00000000..172ae9de
--- /dev/null
+++ b/test/data/auth/anonymous-server-successful.auth-script
@@ -0,0 +1,13 @@
+## this tests the server side in a successful auth of type ANONYMOUS
+
+SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH ANONYMOUS 442d42757320312e312e31'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+## verify that we are still anonymous
+EXPECT_HAVE_NO_CREDENTIALS
+
diff --git a/test/data/auth/external-failed.auth-script b/test/data/auth/external-failed.auth-script
index b11ee9c5..7c4e9001 100644
--- a/test/data/auth/external-failed.auth-script
+++ b/test/data/auth/external-failed.auth-script
@@ -2,7 +2,10 @@
SERVER
NO_CREDENTIALS
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
SEND 'AUTH EXTERNAL USERID_HEX'
EXPECT_COMMAND REJECTED
EXPECT_STATE WAITING_FOR_INPUT
-
+## verify that we still haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
diff --git a/test/data/auth/external-root.auth-script b/test/data/auth/external-root.auth-script
index b0189719..ca5b94ac 100644
--- a/test/data/auth/external-root.auth-script
+++ b/test/data/auth/external-root.auth-script
@@ -2,7 +2,8 @@
SERVER
ROOT_CREDENTIALS
-SEND 'AUTH EXTERNAL USERID_HEX'
+## 30 is ASCII '0' in hex
+SEND 'AUTH EXTERNAL 30'
EXPECT_COMMAND OK
EXPECT_STATE WAITING_FOR_INPUT
SEND 'BEGIN'
diff --git a/test/data/auth/external-silly.auth-script b/test/data/auth/external-silly.auth-script
index 8ac0688a..4e18ee8d 100644
--- a/test/data/auth/external-silly.auth-script
+++ b/test/data/auth/external-silly.auth-script
@@ -1,8 +1,12 @@
-## this tests we can't auth with silly credentials
+## this tests we can't auth if socket reports silly credentials but we ask for our own uid
SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
SILLY_CREDENTIALS
SEND 'AUTH EXTERNAL USERID_HEX'
EXPECT_COMMAND REJECTED
EXPECT_STATE WAITING_FOR_INPUT
+## verify that we still haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
diff --git a/test/data/auth/external-successful.auth-script b/test/data/auth/external-successful.auth-script
index 128d3294..222938cc 100644
--- a/test/data/auth/external-successful.auth-script
+++ b/test/data/auth/external-successful.auth-script
@@ -1,9 +1,12 @@
## this tests a successful auth of type EXTERNAL
SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
SEND 'AUTH EXTERNAL USERID_HEX'
EXPECT_COMMAND OK
EXPECT_STATE WAITING_FOR_INPUT
SEND 'BEGIN'
EXPECT_STATE AUTHENTICATED
-
+## verify that we now have some credentials
+EXPECT_HAVE_SOME_CREDENTIALS