2007-06-12 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Tue, 12 Jun 2007 18:36:19 +0000 (18:36 +0000)
committerHavoc Pennington <hp@redhat.com>
Tue, 12 Jun 2007 18:36:19 +0000 (18:36 +0000)
* dbus/dbus-auth.c (sha1_handle_second_client_response)
(handle_server_data_anonymous_mech): add the process ID from
socket credentials, if available, even if not using EXTERNAL

* dbus/dbus-transport.c (auth_via_default_rules): support
allow_anonymous flag

* dbus/dbus-connection.c (dbus_connection_get_is_anonymous)
(dbus_connection_set_allow_anonymous): new API for controlling
anonymous access

dbus/dbus-auth-script.c
dbus/dbus-auth.c
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-credentials-util.c
dbus/dbus-credentials.c
dbus/dbus-credentials.h
dbus/dbus-transport-protected.h
dbus/dbus-transport.c
dbus/dbus-transport.h

index dd864ca..eb145e4 100644 (file)
@@ -665,7 +665,7 @@ _dbus_auth_script_run (const DBusString *filename)
           DBusCredentials *authorized_identity;
           
           authorized_identity = _dbus_auth_get_identity (auth);
-          if (!_dbus_credentials_are_empty (authorized_identity))
+          if (!_dbus_credentials_are_anonymous (authorized_identity))
             {
               _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
               goto out;
@@ -677,7 +677,7 @@ _dbus_auth_script_run (const DBusString *filename)
           DBusCredentials *authorized_identity;
           
           authorized_identity = _dbus_auth_get_identity (auth);
-          if (_dbus_credentials_are_empty (authorized_identity))
+          if (_dbus_credentials_are_anonymous (authorized_identity))
             {
               _dbus_warn ("Expected to have some credentials, but we don't\n");
               goto out;
index 657f8d3..e47f6e3 100644 (file)
@@ -731,6 +731,13 @@ sha1_handle_second_client_response (DBusAuth         *auth,
   if (!_dbus_credentials_add_credentials (auth->authorized_identity,
                                           auth->desired_identity))
     goto out_3;
+
+  /* Copy process ID from the socket credentials if it's there
+   */
+  if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                         DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                         auth->credentials))
+    goto out_3;
   
   if (!send_ok (auth))
     goto out_3;
@@ -994,7 +1001,7 @@ static dbus_bool_t
 handle_server_data_external_mech (DBusAuth         *auth,
                                   const DBusString *data)
 {
-  if (_dbus_credentials_are_empty (auth->credentials))
+  if (_dbus_credentials_are_anonymous (auth->credentials))
     {
       _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
                      DBUS_AUTH_NAME (auth));
@@ -1059,7 +1066,7 @@ handle_server_data_external_mech (DBusAuth         *auth,
         }
     }
 
-  if (_dbus_credentials_are_empty (auth->desired_identity))
+  if (_dbus_credentials_are_anonymous (auth->desired_identity))
     {
       _dbus_verbose ("%s: desired user %s is no good\n",
                      DBUS_AUTH_NAME (auth),
@@ -1075,8 +1082,7 @@ handle_server_data_external_mech (DBusAuth         *auth,
                                               auth->desired_identity))
         return FALSE;
 
-      /* also copy process ID from the socket credentials - FIXME this
-       * should be done even if auth EXTERNAL not used
+      /* also copy process ID from the socket credentials
        */
       if (!_dbus_credentials_add_credential (auth->authorized_identity,
                                              DBUS_CREDENTIAL_UNIX_PROCESS_ID,
@@ -1192,6 +1198,13 @@ handle_server_data_anonymous_mech (DBusAuth         *auth,
   /* We want to be anonymous (clear in case some other protocol got midway through I guess) */
   _dbus_credentials_clear (auth->desired_identity);
 
+  /* Copy process ID from the socket credentials
+   */
+  if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                         DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                         auth->credentials))
+    return FALSE;
+  
   /* Anonymous is always allowed */
   if (!send_ok (auth))
     return FALSE;
index 1cd3d05..656f750 100644 (file)
@@ -2811,6 +2811,40 @@ dbus_connection_get_is_authenticated (DBusConnection *connection)
 }
 
 /**
+ * Gets whether the connection is not authenticated as a specific
+ * user.  If the connection is not authenticated, this function
+ * returns #TRUE, and if it is authenticated but as an anonymous user,
+ * it returns #TRUE.  If it is authenticated as a specific user, then
+ * this returns #FALSE. (Note that if the connection was authenticated
+ * as anonymous then disconnected, this function still returns #TRUE.)
+ *
+ * If the connection is not anonymous, you can use
+ * dbus_connection_get_unix_user() and
+ * dbus_connection_get_windows_user() to see who it's authorized as.
+ *
+ * If you want to prevent non-anonymous authorization, use
+ * dbus_server_set_auth_mechanisms() to remove the mechanisms that
+ * allow proving user identity (i.e. only allow the ANONYMOUS
+ * mechanism).
+ * 
+ * @param connection the connection
+ * @returns #TRUE if not authenticated or authenticated as anonymous 
+ */
+dbus_bool_t
+dbus_connection_get_is_anonymous (DBusConnection *connection)
+{
+  dbus_bool_t res;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_is_anonymous (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  
+  return res;
+}
+
+/**
  * Set whether _exit() should be called when the connection receives a
  * disconnect signal. The call to _exit() comes after any handlers for
  * the disconnect signal run; handlers can cancel the exit by calling
@@ -4987,6 +5021,43 @@ dbus_connection_set_windows_user_function (DBusConnection              *connecti
 }
 
 /**
+ * This function must be called on the server side of a connection when the
+ * connection is first seen in the #DBusNewConnectionFunction. If set to
+ * #TRUE (the default is #FALSE), then the connection can proceed even if
+ * the client does not authenticate as some user identity, i.e. clients
+ * can connect anonymously.
+ * 
+ * This setting interacts with the available authorization mechanisms
+ * (see dbus_server_set_auth_mechanisms()). Namely, an auth mechanism
+ * such as ANONYMOUS that supports anonymous auth must be included in
+ * the list of available mechanisms for anonymous login to work.
+ *
+ * This setting also changes the default rule for connections
+ * authorized as a user; normally, if a connection authorizes as
+ * a user identity, it is permitted if the user identity is
+ * root or the user identity matches the user identity of the server
+ * process. If anonymous connections are allowed, however,
+ * then any user identity is allowed.
+ *
+ * You can override the rules for connections authorized as a
+ * user identity with dbus_connection_set_unix_user_function()
+ * and dbus_connection_set_windows_user_function().
+ * 
+ * @param connection the connection
+ * @param value whether to allow authentication as an anonymous user
+ */
+void
+dbus_connection_set_allow_anonymous (DBusConnection             *connection,
+                                     dbus_bool_t                 value)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_allow_anonymous (connection->transport, value);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
  *
  * Normally #DBusConnection automatically handles all messages to the
  * org.freedesktop.DBus.Peer interface. However, the message bus wants
@@ -4997,7 +5068,6 @@ dbus_connection_set_windows_user_function (DBusConnection              *connecti
  * handled by the #DBusConnection and instead will be dispatched
  * normally to the application.
  *
- *
  * If a normal application sets this flag, it can break things badly.
  * So don't set this unless you are the message bus.
  *
index 2b673fd..533ac98 100644 (file)
@@ -178,6 +178,7 @@ void               dbus_connection_unref                        (DBusConnection
 void               dbus_connection_close                        (DBusConnection             *connection);
 dbus_bool_t        dbus_connection_get_is_connected             (DBusConnection             *connection);
 dbus_bool_t        dbus_connection_get_is_authenticated         (DBusConnection             *connection);
+dbus_bool_t        dbus_connection_get_is_anonymous             (DBusConnection             *connection);
 void               dbus_connection_set_exit_on_disconnect       (DBusConnection             *connection,
                                                                  dbus_bool_t                 exit_on_disconnect);
 void               dbus_connection_flush                        (DBusConnection             *connection);
@@ -239,6 +240,8 @@ void               dbus_connection_set_windows_user_function    (DBusConnection
                                                                  DBusAllowWindowsUserFunction function,
                                                                  void                       *data,
                                                                  DBusFreeFunction            free_data_function);
+void               dbus_connection_set_allow_anonymous          (DBusConnection             *connection,
+                                                                 dbus_bool_t                 value);
 void               dbus_connection_set_route_peer_messages      (DBusConnection             *connection,
                                                                  dbus_bool_t                 value);
 
index 9b81aca..a76ad09 100644 (file)
@@ -104,6 +104,7 @@ _dbus_credentials_test (const char *test_data_dir)
   _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0);
 
   _dbus_assert (!_dbus_credentials_are_empty (creds));
+  _dbus_assert (!_dbus_credentials_are_anonymous (creds));
 
   /* Test copy */
   creds2 = _dbus_credentials_copy (creds);
@@ -193,6 +194,7 @@ _dbus_credentials_test (const char *test_data_dir)
   _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL);
 
   _dbus_assert (_dbus_credentials_are_empty (creds));
+  _dbus_assert (_dbus_credentials_are_anonymous (creds));
 
   _dbus_credentials_unref (creds);
   
index dde6928..2023c17 100644 (file)
@@ -289,6 +289,20 @@ _dbus_credentials_are_empty (DBusCredentials    *credentials)
 }
 
 /**
+ * Checks whether a credentials object contains a user identity.
+ * 
+ * @param credentials the object
+ * @returns #TRUE if there are no user identities in the object
+ */
+dbus_bool_t
+_dbus_credentials_are_anonymous (DBusCredentials    *credentials)
+{
+  return
+    credentials->unix_uid == DBUS_UID_UNSET &&
+    credentials->windows_sid == NULL;
+}
+
+/**
  * Merge all credentials found in the second object into the first object,
  * overwriting the first object if there are any overlaps.
  * 
index b47c9c4..f728b37 100644 (file)
@@ -54,6 +54,7 @@ const char*      _dbus_credentials_get_windows_sid          (DBusCredentials
 dbus_bool_t      _dbus_credentials_are_superset             (DBusCredentials    *credentials,
                                                              DBusCredentials    *possible_subset);
 dbus_bool_t      _dbus_credentials_are_empty                (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_are_anonymous            (DBusCredentials    *credentials);
 dbus_bool_t      _dbus_credentials_add_credentials          (DBusCredentials    *credentials,
                                                              DBusCredentials    *other_credentials);
 /* must silently allow 'which' to not exist */
index 6d3f1f3..76a17cf 100644 (file)
@@ -116,6 +116,7 @@ struct DBusTransport
   unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */
   unsigned int is_server : 1;                 /**< #TRUE if on the server side */
   unsigned int unused_bytes_recovered : 1;    /**< #TRUE if we've recovered unused bytes from auth */
+  unsigned int allow_anonymous : 1;           /**< #TRUE if an anonymous client can connect */
 };
 
 dbus_bool_t _dbus_transport_init_base     (DBusTransport             *transport,
index 029cc6c..d738cc0 100644 (file)
@@ -603,10 +603,10 @@ auth_via_default_rules (DBusTransport *transport)
   auth_identity = _dbus_auth_get_identity (transport->auth);
   _dbus_assert (auth_identity != NULL);
 
-  /* By default, connection is allowed if the client is
-   * 1) root or 2) has the same UID as us
+  /* By default, connection is allowed if the client is 1) root or 2)
+   * has the same UID as us or 3) anonymous is allowed.
    */
-              
+  
   our_identity = _dbus_credentials_new_from_current_process ();
   if (our_identity == NULL)
     {
@@ -614,7 +614,8 @@ auth_via_default_rules (DBusTransport *transport)
       return FALSE;
     }
               
-  if (_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
+  if (transport->allow_anonymous ||
+      _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
       _dbus_credentials_same_user (our_identity,
                                    auth_identity))
     {
@@ -756,6 +757,28 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
 }
 
 /**
+ * See dbus_connection_get_is_anonymous().
+ *
+ * @param transport the transport
+ * @returns #TRUE if not authenticated or authenticated as anonymous
+ */
+dbus_bool_t
+_dbus_transport_get_is_anonymous (DBusTransport *transport)
+{
+  DBusCredentials *auth_identity;
+  
+  if (!transport->authenticated)
+    return TRUE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_are_anonymous (auth_identity))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
  * Gets the address of a transport. It will be
  * #NULL for a server-side transport.
  *
@@ -1298,5 +1321,17 @@ _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
 }
 
+/**
+ * See dbus_connection_set_allow_anonymous()
+ *
+ * @param transport the transport
+ * @param value #TRUE to allow anonymous connection
+ */
+void
+_dbus_transport_set_allow_anonymous (DBusTransport              *transport,
+                                     dbus_bool_t                 value)
+{
+  transport->allow_anonymous = value != FALSE;
+}
 
 /** @} */
index 9e952a1..3335c46 100644 (file)
@@ -39,6 +39,7 @@ void               _dbus_transport_unref                  (DBusTransport
 void               _dbus_transport_disconnect             (DBusTransport              *transport);
 dbus_bool_t        _dbus_transport_get_is_connected       (DBusTransport              *transport);
 dbus_bool_t        _dbus_transport_get_is_authenticated   (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_get_is_anonymous       (DBusTransport              *transport);
 const char*        _dbus_transport_get_address            (DBusTransport              *transport);
 dbus_bool_t        _dbus_transport_handle_watch           (DBusTransport              *transport,
                                                            DBusWatch                  *watch,
@@ -78,8 +79,8 @@ void               _dbus_transport_set_windows_user_function (DBusTransport
                                                               DBusFreeFunction           *old_free_data_function);
 dbus_bool_t        _dbus_transport_set_auth_mechanisms    (DBusTransport              *transport,
                                                            const char                **mechanisms);
-
-
+void               _dbus_transport_set_allow_anonymous    (DBusTransport              *transport,
+                                                           dbus_bool_t                 value);
 
 
 DBUS_END_DECLS