summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-02-13 04:11:57 +0000
committerHavoc Pennington <hp@redhat.com>2003-02-13 04:11:57 +0000
commit5970d04af540af4825958272cba950c0b7dff15d (patch)
treee06f9e7a8d0e93f851a2b4d6da3bc7c46f1cb685
parentc9ea8fac502c6109713aa372c4c8cfafd0b86858 (diff)
2003-02-13 Havoc Pennington <hp@pobox.com>
* dbus/dbus-auth.c (handle_server_data_external_mech): args to dbus_credentials_match were backward * dbus/dbus-auth-script.c (_dbus_auth_script_run): support NO_CREDENTIALS and ROOT_CREDENTIALS * dbus/dbus-auth.c (_dbus_auth_do_work): move get_state() routine into here. Never process more commands after we've reached an end state; store further data as unused bytes. * test/data/auth/*: add more auth tests * dbus/dbus-auth-script.c (_dbus_auth_script_run): support EXPECT command to match exact string and EXPECT_UNUSED to match unused bytes * test/Makefile.am (dist-hook): fix to dist all the test stuff
-rw-r--r--ChangeLog20
-rw-r--r--dbus/Makefile.am4
-rw-r--r--dbus/dbus-auth-script.c195
-rw-r--r--dbus/dbus-auth.c77
-rw-r--r--doc/dbus-sasl-profile.txt4
-rw-r--r--test/Makefile.am18
-rw-r--r--test/data/auth/external-failed.auth-script8
-rw-r--r--test/data/auth/external-root.auth-script10
-rw-r--r--test/data/auth/external-silly.auth-script8
-rw-r--r--test/data/auth/external-successful.auth-script9
-rw-r--r--test/data/auth/extra-bytes.auth-script10
11 files changed, 314 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 14ea9678..645011eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2003-02-13 Havoc Pennington <hp@pobox.com>
+
+ * dbus/dbus-auth.c (handle_server_data_external_mech): args to
+ dbus_credentials_match were backward
+
+ * dbus/dbus-auth-script.c (_dbus_auth_script_run): support
+ NO_CREDENTIALS and ROOT_CREDENTIALS
+
+ * dbus/dbus-auth.c (_dbus_auth_do_work): move get_state() routine
+ into here. Never process more commands after we've reached an
+ end state; store further data as unused bytes.
+
+ * test/data/auth/*: add more auth tests
+
+ * dbus/dbus-auth-script.c (_dbus_auth_script_run): support EXPECT
+ command to match exact string and EXPECT_UNUSED to match unused
+ bytes
+
+ * test/Makefile.am (dist-hook): fix to dist all the test stuff
+
2003-02-12 Havoc Pennington <hp@pobox.com>
* dbus/dbus-string.c (_dbus_string_pop_line): fix to also strip
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index cc1294b6..ae0188cf 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -111,3 +111,7 @@ dbus_test_SOURCES= \
dbus-test-main.c
dbus_test_LDADD= $(DBUS_CLIENT_LIBS) libdbus-convenience.la libdbus-1.la
+
+## mop up the gcov files
+clean-local:
+ /bin/rm *.bb *.bbg *.da *.gcov || true \ No newline at end of file
diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index 6c5009a5..21a9f996 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -42,11 +42,15 @@
* @{
*/
+/* this is slightly different from the other append_quoted_string
+ * in dbus-message-builder.c
+ */
static dbus_bool_t
append_quoted_string (DBusString *dest,
const DBusString *quoted)
{
dbus_bool_t in_quotes = FALSE;
+ dbus_bool_t in_backslash = FALSE;
int i;
i = 0;
@@ -55,8 +59,33 @@ append_quoted_string (DBusString *dest,
unsigned char b;
b = _dbus_string_get_byte (quoted, i);
-
- if (in_quotes)
+
+ if (in_backslash)
+ {
+ unsigned char a;
+
+ if (b == 'r')
+ a = '\r';
+ else if (b == 'n')
+ a = '\n';
+ else if (b == '\\')
+ a = '\\';
+ else
+ {
+ _dbus_warn ("bad backslashed byte %c\n", b);
+ return FALSE;
+ }
+
+ if (!_dbus_string_append_byte (dest, a))
+ return FALSE;
+
+ in_backslash = FALSE;
+ }
+ else if (b == '\\')
+ {
+ in_backslash = TRUE;
+ }
+ else if (in_quotes)
{
if (b == '\'')
in_quotes = FALSE;
@@ -222,6 +251,8 @@ _dbus_auth_script_run (const DBusString *filename)
else if (_dbus_string_starts_with_c_str (&line,
"CLIENT"))
{
+ DBusCredentials creds;
+
if (auth != NULL)
{
_dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
@@ -234,10 +265,15 @@ _dbus_auth_script_run (const DBusString *filename)
_dbus_warn ("no memory to create DBusAuth\n");
goto out;
}
+
+ _dbus_credentials_from_current_process (&creds);
+ _dbus_auth_set_credentials (auth, &creds);
}
else if (_dbus_string_starts_with_c_str (&line,
"SERVER"))
{
+ DBusCredentials creds;
+
if (auth != NULL)
{
_dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
@@ -250,6 +286,9 @@ _dbus_auth_script_run (const DBusString *filename)
_dbus_warn ("no memory to create DBusAuth\n");
goto out;
}
+
+ _dbus_credentials_from_current_process (&creds);
+ _dbus_auth_set_credentials (auth, &creds);
}
else if (auth == NULL)
{
@@ -258,6 +297,24 @@ _dbus_auth_script_run (const DBusString *filename)
}
else if (_dbus_string_starts_with_c_str (&line,
+ "NO_CREDENTIALS"))
+ {
+ DBusCredentials creds = { -1, -1, -1 };
+ _dbus_auth_set_credentials (auth, &creds);
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
+ "ROOT_CREDENTIALS"))
+ {
+ DBusCredentials creds = { -1, 0, 0 };
+ _dbus_auth_set_credentials (auth, &creds);
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
+ "SILLY_CREDENTIALS"))
+ {
+ DBusCredentials creds = { -1, 4312, 1232 };
+ _dbus_auth_set_credentials (auth, &creds);
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
"SEND"))
{
DBusString to_send;
@@ -291,10 +348,49 @@ _dbus_auth_script_run (const DBusString *filename)
_dbus_string_free (&to_send);
goto out;
}
+
+ /* Replace USERNAME_BASE64 with our username in base64 */
+ {
+ int where;
+
+ if (_dbus_string_find (&to_send, 0,
+ "USERNAME_BASE64", &where))
+ {
+ DBusString username;
+
+ if (!_dbus_string_init (&username, _DBUS_INT_MAX))
+ {
+ _dbus_warn ("no memory for username\n");
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ if (!_dbus_string_append_our_uid (&username))
+ {
+ _dbus_warn ("no memory for username\n");
+ _dbus_string_free (&username);
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ _dbus_string_delete (&to_send, where, strlen ("USERNAME_BASE64"));
+
+ if (!_dbus_string_base64_encode (&username, 0,
+ &to_send, where))
+ {
+ _dbus_warn ("no memory to subst USERNAME_BASE64\n");
+ _dbus_string_free (&username);
+ _dbus_string_free (&to_send);
+ goto out;
+ }
+
+ _dbus_string_free (&username);
+ }
+ }
if (!_dbus_auth_bytes_received (auth, &to_send))
{
- _dbus_warn ("not enough memory to call bytes_received\n");
+ _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
_dbus_string_free (&to_send);
goto out;
}
@@ -360,6 +456,99 @@ _dbus_auth_script_run (const DBusString *filename)
_dbus_string_free (&received);
}
+ else if (_dbus_string_starts_with_c_str (&line,
+ "EXPECT_UNUSED"))
+ {
+ DBusString expected;
+ DBusString unused;
+
+ _dbus_string_delete_first_word (&line);
+
+ if (!_dbus_string_init (&expected, _DBUS_INT_MAX))
+ {
+ _dbus_warn ("no mem to allocate string expected\n");
+ goto out;
+ }
+
+ if (!append_quoted_string (&expected, &line))
+ {
+ _dbus_warn ("failed to append quoted string line %d\n",
+ line_no);
+ _dbus_string_free (&expected);
+ goto out;
+ }
+
+ if (!_dbus_string_init (&unused, _DBUS_INT_MAX))
+ {
+ _dbus_warn ("no mem to allocate string unused\n");
+ _dbus_string_free (&expected);
+ goto out;
+ }
+
+ if (!_dbus_auth_get_unused_bytes (auth, &unused))
+ {
+ _dbus_warn ("couldn't get unused bytes\n");
+ _dbus_string_free (&expected);
+ _dbus_string_free (&unused);
+ goto out;
+ }
+
+ if (_dbus_string_equal (&expected, &unused))
+ {
+ _dbus_string_free (&expected);
+ _dbus_string_free (&unused);
+ }
+ else
+ {
+ const char *e1, *h1;
+ _dbus_string_get_const_data (&expected, &e1);
+ _dbus_string_get_const_data (&unused, &h1);
+ _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
+ e1, h1);
+ _dbus_string_free (&expected);
+ _dbus_string_free (&unused);
+ goto out;
+ }
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
+ "EXPECT"))
+ {
+ DBusString expected;
+
+ _dbus_string_delete_first_word (&line);
+
+ if (!_dbus_string_init (&expected, _DBUS_INT_MAX))
+ {
+ _dbus_warn ("no mem to allocate string expected\n");
+ goto out;
+ }
+
+ if (!append_quoted_string (&expected, &line))
+ {
+ _dbus_warn ("failed to append quoted string line %d\n",
+ line_no);
+ _dbus_string_free (&expected);
+ goto out;
+ }
+
+ if (_dbus_string_equal_len (&expected, &from_auth,
+ _dbus_string_get_length (&expected)))
+ {
+ _dbus_string_delete (&from_auth, 0,
+ _dbus_string_get_length (&expected));
+ _dbus_string_free (&expected);
+ }
+ else
+ {
+ const char *e1, *h1;
+ _dbus_string_get_const_data (&expected, &e1);
+ _dbus_string_get_const_data (&from_auth, &h1);
+ _dbus_warn ("Expected exact string '%s' and have '%s'\n",
+ e1, h1);
+ _dbus_string_free (&expected);
+ goto out;
+ }
+ }
else
goto parse_failed;
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index 071e3416..324391ea 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -38,6 +38,10 @@
*
* The file doc/dbus-sasl-profile.txt documents the network protocol
* used for authentication.
+ *
+ * @todo some SASL profiles require sending the empty string as a
+ * challenge/response, but we don't currently allow that in our
+ * protocol.
*/
/**
@@ -283,31 +287,6 @@ _dbus_auth_new (int size)
return auth;
}
-static DBusAuthState
-get_state (DBusAuth *auth)
-{
- if (DBUS_AUTH_IS_SERVER (auth) &&
- DBUS_AUTH_SERVER (auth)->failures >=
- DBUS_AUTH_SERVER (auth)->max_failures)
- auth->need_disconnect = TRUE;
-
- if (auth->need_disconnect)
- return DBUS_AUTH_STATE_NEED_DISCONNECT;
- else if (auth->authenticated)
- {
- if (_dbus_string_get_length (&auth->incoming) > 0)
- return DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES;
- else
- return DBUS_AUTH_STATE_AUTHENTICATED;
- }
- else if (auth->needed_memory)
- return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
- else if (_dbus_string_get_length (&auth->outgoing) > 0)
- return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
- else
- return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
-}
-
static void
shutdown_mech (DBusAuth *auth)
{
@@ -411,6 +390,7 @@ handle_server_data_external_mech (DBusAuth *auth,
if (_dbus_string_get_length (&auth->identity) > 0)
{
/* Tried to send two auth identities, wtf */
+ _dbus_verbose ("client tried to send auth identity, but we already have one\n");
return send_rejected (auth);
}
else
@@ -453,7 +433,10 @@ handle_server_data_external_mech (DBusAuth *auth,
{
if (!_dbus_credentials_from_uid_string (&auth->identity,
&desired_identity))
- return send_rejected (auth);
+ {
+ _dbus_verbose ("could not get credentials from uid string\n");
+ return send_rejected (auth);
+ }
}
if (desired_identity.uid < 0)
@@ -462,8 +445,8 @@ handle_server_data_external_mech (DBusAuth *auth,
return send_rejected (auth);
}
- if (_dbus_credentials_match (&auth->credentials,
- &desired_identity))
+ if (_dbus_credentials_match (&desired_identity,
+ &auth->credentials))
{
/* client has authenticated */
_dbus_verbose ("authenticated client with UID %d matching socket credentials UID %d\n",
@@ -482,6 +465,9 @@ handle_server_data_external_mech (DBusAuth *auth,
}
else
{
+ _dbus_verbose ("credentials uid=%d gid=%d do not allow uid=%d gid=%d\n",
+ auth->credentials.uid, auth->credentials.gid,
+ desired_identity.uid, desired_identity.gid);
return send_rejected (auth);
}
}
@@ -1061,7 +1047,7 @@ process_command (DBusAuth *auth)
int i, j;
dbus_bool_t retval;
- _dbus_verbose (" trying process_command()\n");
+ /* _dbus_verbose (" trying process_command()\n"); */
retval = FALSE;
@@ -1296,10 +1282,7 @@ _dbus_auth_unref (DBusAuth *auth)
*/
DBusAuthState
_dbus_auth_do_work (DBusAuth *auth)
-{
- if (DBUS_AUTH_IN_END_STATE (auth))
- return get_state (auth);
-
+{
auth->needed_memory = FALSE;
/* Max amount we'll buffer up before deciding someone's on crack */
@@ -1307,6 +1290,9 @@ _dbus_auth_do_work (DBusAuth *auth)
do
{
+ if (DBUS_AUTH_IN_END_STATE (auth))
+ break;
+
if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
_dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
{
@@ -1325,8 +1311,27 @@ _dbus_auth_do_work (DBusAuth *auth)
}
}
while (process_command (auth));
-
- return get_state (auth);
+
+ if (DBUS_AUTH_IS_SERVER (auth) &&
+ DBUS_AUTH_SERVER (auth)->failures >=
+ DBUS_AUTH_SERVER (auth)->max_failures)
+ auth->need_disconnect = TRUE;
+
+ if (auth->need_disconnect)
+ return DBUS_AUTH_STATE_NEED_DISCONNECT;
+ else if (auth->authenticated)
+ {
+ if (_dbus_string_get_length (&auth->incoming) > 0)
+ return DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES;
+ else
+ return DBUS_AUTH_STATE_AUTHENTICATED;
+ }
+ else if (auth->needed_memory)
+ return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
+ else if (_dbus_string_get_length (&auth->outgoing) > 0)
+ return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
+ else
+ return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
}
/**
@@ -1383,7 +1388,7 @@ _dbus_auth_bytes_sent (DBusAuth *auth,
*
* @param auth the auth conversation
* @param str the received bytes.
- * @returns #FALSE if not enough memory to store the bytes.
+ * @returns #FALSE if not enough memory to store the bytes or we were already authenticated.
*/
dbus_bool_t
_dbus_auth_bytes_received (DBusAuth *auth,
diff --git a/doc/dbus-sasl-profile.txt b/doc/dbus-sasl-profile.txt
index be97a8df..e245f335 100644
--- a/doc/dbus-sasl-profile.txt
+++ b/doc/dbus-sasl-profile.txt
@@ -1,4 +1,3 @@
-
D-BUS Authentication
===
@@ -117,6 +116,9 @@ DATA Command
contains a base64-encoded block of data to be interpreted
according to the SASL mechanism in use.
+ Some SASL mechanisms support sending an "empty string";
+ FIXME we need some way to do this.
+
BEGIN Command
===
diff --git a/test/Makefile.am b/test/Makefile.am
index 972d67cf..4ff6c49d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -37,13 +37,13 @@ unbase64_LDADD=$(TEST_LIBS)
break_loader_LDADD= $(TEST_LIBS)
bus_test_LDADD=$(TEST_LIBS) $(top_builddir)/bus/libdbus-daemon.la
-dist-hook:
- DIRS="data data/valid-messages data/invalid-messages data/incomplete-messages" ; \
- for D in $$DIRS; do \
- test -d $(distdir)/$$D || mkdir $(distdir)/$$D ; \
- done ; \
- FILES=`find -name "*.message"` ; \
- for F in $$FILES; do \
- echo '-- Disting file '$$F ; \
- cp $$F $(distdir)/$$F ; \
+dist-hook: \
+ DIRS="data data/valid-messages data/invalid-messages data/incomplete-messages data/auth" ; \
+ for D in $$DIRS; do \
+ test -d $(distdir)/$$D || mkdir $(distdir)/$$D ; \
+ done ; \
+ FILES=`find -name "*.message" -o -name "*.message-raw" -o -name "*.auth-script"` ; \
+ for F in $$FILES; do \
+ echo '-- Disting file '$$F ; \
+ cp $$F $(distdir)/$$F ; \
done
diff --git a/test/data/auth/external-failed.auth-script b/test/data/auth/external-failed.auth-script
new file mode 100644
index 00000000..f5723521
--- /dev/null
+++ b/test/data/auth/external-failed.auth-script
@@ -0,0 +1,8 @@
+## this tests that auth of type EXTERNAL without credentials will fail
+
+SERVER
+NO_CREDENTIALS
+SEND 'AUTH EXTERNAL USERNAME_BASE64'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
diff --git a/test/data/auth/external-root.auth-script b/test/data/auth/external-root.auth-script
new file mode 100644
index 00000000..720b7e51
--- /dev/null
+++ b/test/data/auth/external-root.auth-script
@@ -0,0 +1,10 @@
+## this tests we can auth EXTERNAL as ourselves, with root credentials
+
+SERVER
+ROOT_CREDENTIALS
+SEND 'AUTH EXTERNAL USERNAME_BASE64'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+
diff --git a/test/data/auth/external-silly.auth-script b/test/data/auth/external-silly.auth-script
new file mode 100644
index 00000000..3e12c153
--- /dev/null
+++ b/test/data/auth/external-silly.auth-script
@@ -0,0 +1,8 @@
+## this tests we can't auth with silly credentials
+
+SERVER
+SILLY_CREDENTIALS
+SEND 'AUTH EXTERNAL USERNAME_BASE64'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
diff --git a/test/data/auth/external-successful.auth-script b/test/data/auth/external-successful.auth-script
new file mode 100644
index 00000000..1b380802
--- /dev/null
+++ b/test/data/auth/external-successful.auth-script
@@ -0,0 +1,9 @@
+## this tests a successful auth of type EXTERNAL
+
+SERVER
+SEND 'AUTH EXTERNAL USERNAME_BASE64'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+
diff --git a/test/data/auth/extra-bytes.auth-script b/test/data/auth/extra-bytes.auth-script
new file mode 100644
index 00000000..df8df52b
--- /dev/null
+++ b/test/data/auth/extra-bytes.auth-script
@@ -0,0 +1,10 @@
+## this tests that we have the expected extra bytes at the end
+
+SERVER
+SEND 'AUTH EXTERNAL USERNAME_BASE64'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN\r\nHello'
+EXPECT_STATE AUTHENTICATED_WITH_UNUSED_BYTES
+EXPECT_UNUSED 'Hello\r\n'
+EXPECT_STATE AUTHENTICATED