]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
2003-02-13 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Thu, 13 Feb 2003 04:11:57 +0000 (04:11 +0000)
committerHavoc Pennington <hp@redhat.com>
Thu, 13 Feb 2003 04:11:57 +0000 (04:11 +0000)
* 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

ChangeLog
dbus/Makefile.am
dbus/dbus-auth-script.c
dbus/dbus-auth.c
doc/dbus-sasl-profile.txt
test/Makefile.am
test/data/auth/external-failed.auth-script [new file with mode: 0644]
test/data/auth/external-root.auth-script [new file with mode: 0644]
test/data/auth/external-silly.auth-script [new file with mode: 0644]
test/data/auth/external-successful.auth-script [new file with mode: 0644]
test/data/auth/extra-bytes.auth-script [new file with mode: 0644]

index 14ea9678cd595d5e840b42d312a6899381c9a046..645011eb89add1a1718dd4770638b86bcfcc74b5 100644 (file)
--- 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
index cc1294b6500657491a5119f3a3c55b0033f891cf..ae0188cf5e0e679dd03ce5e412ce480e756f01ee 100644 (file)
@@ -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
index 6c5009a522547fdd2ba4bf7eb6d665b3152530cb..21a9f996ddf8216d0b0175fa6ba60f89ab9f98c6 100644 (file)
  * @{
  */
 
+/* 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)
         {
@@ -257,6 +296,24 @@ _dbus_auth_script_run (const DBusString *filename)
           goto out;
 
         }
+      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"))
         {
@@ -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;
 
index 071e34166f2fd01fbd90f484f000fcd6949ef58f..324391ea263a64f782cda10c67b73ffc72a04c0f 100644 (file)
  *
  * 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,
index be97a8df80e6c6bd617169b445f511394ef5442a..e245f33531d34ae2a08788de2882874757599f63 100644 (file)
@@ -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
 ===
 
index 972d67cfd6dfd6a25897fb25045568270814192c..4ff6c49dd2d750cd9a8fe6d956b4ab908826fc13 100644 (file)
@@ -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 (file)
index 0000000..f572352
--- /dev/null
@@ -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 (file)
index 0000000..720b7e5
--- /dev/null
@@ -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 (file)
index 0000000..3e12c15
--- /dev/null
@@ -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 (file)
index 0000000..1b38080
--- /dev/null
@@ -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 (file)
index 0000000..df8df52
--- /dev/null
@@ -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