2007-06-09 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Sat, 9 Jun 2007 21:53:20 +0000 (21:53 +0000)
committerHavoc Pennington <hp@redhat.com>
Sat, 9 Jun 2007 21:53:20 +0000 (21:53 +0000)
* bus/dispatch.c (check_get_connection_unix_process_id): adapt
since sysdeps-unix.h stuff isn't included anymore

* bus/bus.c (bus_context_new): use more abstract functions to
change user, so they can be no-ops on Windows

* dbus/dbus-credentials.c, dbus/dbus-credentials.h,
dbus/dbus-credentials-util.c: new files containing a fully opaque
DBusCredentials data type to replace the old not opaque one.

* configure.in (DBUS_UNIX): define DBUS_UNIX to match DBUS_WIN on
windows

* dbus/dbus-userdb.h: prohibit on Windows, next step is to clean
up the uses of it in bus/*.c and factor out the parts of
cookie auth that depend on it

31 files changed:
ChangeLog
bus/bus.c
bus/dispatch.c
bus/policy.c
configure.in
dbus/Makefile.am
dbus/dbus-auth-script.c
dbus/dbus-auth.c
dbus/dbus-auth.h
dbus/dbus-credentials-util.c [new file with mode: 0644]
dbus/dbus-credentials.c [new file with mode: 0644]
dbus/dbus-credentials.h [new file with mode: 0644]
dbus/dbus-internals.c
dbus/dbus-keyring.c
dbus/dbus-marshal-recursive-util.c
dbus/dbus-spawn.c
dbus/dbus-sysdeps-unix.c
dbus/dbus-sysdeps-unix.h
dbus/dbus-sysdeps-util-unix.c
dbus/dbus-sysdeps-win.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
dbus/dbus-test.c
dbus/dbus-test.h
dbus/dbus-transport-protected.h
dbus/dbus-transport-socket.c
dbus/dbus-transport.c
dbus/dbus-userdb-util.c
dbus/dbus-userdb.c
dbus/dbus-userdb.h
test/Makefile.am

index 1423b0d..4fe45e2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-06-09  Havoc Pennington  <hp@redhat.com>
+
+       * bus/dispatch.c (check_get_connection_unix_process_id): adapt
+       since sysdeps-unix.h stuff isn't included anymore
+
+       * bus/bus.c (bus_context_new): use more abstract functions to
+       change user, so they can be no-ops on Windows
+
+       * dbus/dbus-credentials.c, dbus/dbus-credentials.h,
+       dbus/dbus-credentials-util.c: new files containing a fully opaque
+       DBusCredentials data type to replace the old not opaque one.
+
+       * configure.in (DBUS_UNIX): define DBUS_UNIX to match DBUS_WIN on
+       windows
+
+       * dbus/dbus-userdb.h: prohibit on Windows, next step is to clean
+       up the uses of it in bus/*.c and factor out the parts of 
+       cookie auth that depend on it
+       
 2007-06-07  Havoc Pennington  <hp@redhat.com>
 
        * dbus/dbus-message.c: improve some docs related to reading values
index fb9322a..e1396f2 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -533,7 +533,6 @@ bus_context_new (const DBusString *config_file,
 {
   BusContext *context;
   BusConfigParser *parser;
-  DBusCredentials creds;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -660,13 +659,7 @@ bus_context_new (const DBusString *config_file,
   /* check user before we fork */
   if (context->user != NULL)
     {
-      DBusString u;
-
-      _dbus_string_init_const (&u, context->user);
-
-      if (!_dbus_credentials_from_username (&u, &creds) ||
-          creds.uid < 0 ||
-          creds.gid < 0)
+      if (!_dbus_verify_daemon_user (context->user))
         {
           dbus_set_error (error, DBUS_ERROR_FAILED,
                           "Could not get UID and GID for username \"%s\"",
@@ -769,7 +762,7 @@ bus_context_new (const DBusString *config_file,
    */
   if (context->user != NULL)
     {
-      if (!_dbus_change_identity (creds.uid, creds.gid, error))
+      if (!_dbus_change_to_daemon_user (context->user, error))
        {
          _DBUS_ASSERT_ERROR_IS_SET (error);
          goto failed;
index f491ef4..ef75933 100644 (file)
@@ -399,6 +399,10 @@ bus_dispatch_remove_connection (DBusConnection *connection)
 #ifdef DBUS_BUILD_TESTS
 
 #include <stdio.h>
+#ifdef DBUS_UNIX
+#include <sys/types.h>
+#include <unistd.h>
+#endif
 
 /* This is used to know whether we need to block in order to finish
  * sending a message, or whether the initial dbus_connection_send()
@@ -1313,7 +1317,7 @@ check_get_connection_unix_process_id (BusContext     *context,
            *       cause then we can test that the pid returned matches
            *       getppid()
            */
-          if (pid != (dbus_uint32_t) _dbus_getpid ())
+          if (pid != (dbus_uint32_t) getpid ())
             {
               _dbus_assert (dbus_error_is_set (&error));
               _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
index 52ae72a..7782563 100644 (file)
@@ -324,13 +324,9 @@ bus_policy_create_client_policy (BusPolicy      *policy,
 
   if (!dbus_connection_get_unix_user (connection, &uid))
     {
-#ifdef DBUS_WIN_FIXME
-      _dbus_verbose ("policy.c: dbus_connection_get_unix_user check disabled under windows\n");
-#else
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "No user ID known for connection, cannot determine security policy\n");
       goto failed;
-#endif
     }
 
   if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
index 6cbcb9b..4836342 100644 (file)
@@ -1169,6 +1169,8 @@ fi
 AC_DEFINE_UNQUOTED(DBUS_SESSION_SOCKET_DIR, "$DBUS_SESSION_SOCKET_DIR", [Where per-session bus puts its sockets])
 AC_SUBST(DBUS_SESSION_SOCKET_DIR)
 
+AC_DEFINE_UNQUOTED(DBUS_UNIX, "1", [Defined on UNIX and Linux systems and not on Windows])
+
 AC_OUTPUT([
 Doxyfile
 dbus/dbus-arch-deps.h
index 70d5b37..d27ca6f 100644 (file)
@@ -41,6 +41,8 @@ DBUS_LIB_SOURCES=                             \
        dbus-bus.c                              \
        dbus-connection.c                       \
        dbus-connection-internal.h              \
+       dbus-credentials.c                      \
+       dbus-credentials.h                      \
        dbus-errors.c                           \
        dbus-keyring.c                          \
        dbus-keyring.h                          \
@@ -128,6 +130,7 @@ DBUS_SHARED_SOURCES=                                \
 ### to be unless they move to DBUS_SHARED_SOURCES later)
 DBUS_UTIL_SOURCES=                             \
        dbus-auth-util.c                        \
+       dbus-credentials-util.c                 \
        dbus-mainloop.c                         \
        dbus-mainloop.h                         \
        dbus-marshal-byteswap-util.c            \
index 3cb86d0..5aa17d4 100644 (file)
@@ -28,8 +28,8 @@
 #include "dbus-auth.h"
 #include "dbus-string.h"
 #include "dbus-hash.h"
+#include "dbus-credentials.h"
 #include "dbus-internals.h"
-#include "dbus-userdb.h"
 
 /**
  * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
@@ -209,6 +209,29 @@ split_string (DBusString *str)
   return array;
 }
 
+static void
+auth_set_unix_credentials(DBusAuth  *auth,
+                          dbus_uid_t uid,
+                          dbus_pid_t pid)
+{
+  DBusCredentials *credentials;
+
+  credentials = _dbus_credentials_new ();
+  if (credentials == NULL)
+    {
+      _dbus_warn ("no memory\n");
+      return;
+    }
+  if (uid != DBUS_UID_UNSET)
+    _dbus_credentials_add_unix_uid (credentials, uid);
+  if (pid != DBUS_PID_UNSET)
+    _dbus_credentials_add_unix_pid (credentials, pid);
+
+  _dbus_auth_set_credentials (auth, credentials);
+
+  _dbus_credentials_unref (credentials);
+}
+
 /**
  * Runs an "auth script" which is a script for testing the
  * authentication protocol. Scripts send and receive data, and then
@@ -303,7 +326,7 @@ _dbus_auth_script_run (const DBusString *filename)
       else if (_dbus_string_starts_with_c_str (&line,
                                                "CLIENT"))
         {
-          DBusCredentials creds;
+          DBusCredentials *creds;
           
           if (auth != NULL)
             {
@@ -321,14 +344,31 @@ _dbus_auth_script_run (const DBusString *filename)
           /* test ref/unref */
           _dbus_auth_ref (auth);
           _dbus_auth_unref (auth);
+
+          creds = _dbus_credentials_new_from_current_process ();
+          if (creds == NULL)
+            {
+              _dbus_warn ("no memory for credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              goto out;
+            }
+              
+          if (!_dbus_auth_set_credentials (auth, creds))
+            {
+              _dbus_warn ("no memory for setting credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              _dbus_credentials_unref (creds);
+              goto out;
+            }
           
-          _dbus_credentials_from_current_process (&creds);
-          _dbus_auth_set_credentials (auth, &creds);
+          _dbus_credentials_unref (creds);
         }
       else if (_dbus_string_starts_with_c_str (&line,
                                                "SERVER"))
         {
-          DBusCredentials creds;
+          DBusCredentials *creds;
           
           if (auth != NULL)
             {
@@ -346,9 +386,27 @@ _dbus_auth_script_run (const DBusString *filename)
           /* test ref/unref */
           _dbus_auth_ref (auth);
           _dbus_auth_unref (auth);
+
+          creds = _dbus_credentials_new_from_current_process ();
+          if (creds == NULL)
+            {
+              _dbus_warn ("no memory for credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              goto out;
+            }
+              
+          if (!_dbus_auth_set_credentials (auth, creds))
+            {
+              _dbus_warn ("no memory for setting credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              _dbus_credentials_unref (creds);
+              goto out;
+            }
           
-          _dbus_credentials_from_current_process (&creds);
-          _dbus_auth_set_credentials (auth, &creds);
+          _dbus_credentials_unref (creds);
+
           _dbus_auth_set_context (auth, &context);
         }
       else if (auth == NULL)
@@ -360,20 +418,17 @@ _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);
+          auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
         }
       else if (_dbus_string_starts_with_c_str (&line,
                                                "ROOT_CREDENTIALS"))
         {
-          DBusCredentials creds = { -1, 0, 0 };
-          _dbus_auth_set_credentials (auth, &creds);          
+          auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
         }
       else if (_dbus_string_starts_with_c_str (&line,
                                                "SILLY_CREDENTIALS"))
         {
-          DBusCredentials creds = { -1, 4312, 1232 };
-          _dbus_auth_set_credentials (auth, &creds);          
+          auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
         }
       else if (_dbus_string_starts_with_c_str (&line,
                                                "ALLOWED_MECHS"))
@@ -432,8 +487,7 @@ _dbus_auth_script_run (const DBusString *filename)
                     goto out;
                   }
 
-                if (!_dbus_string_append_uint (&username,
-                                               _dbus_getuid ()))
+                if (!_dbus_append_desired_identity (&username))
                   {
                     _dbus_warn ("no memory for userid\n");
                     _dbus_string_free (&username);
index 7ece76e..b1d57a4 100644 (file)
@@ -27,7 +27,7 @@
 #include "dbus-keyring.h"
 #include "dbus-sha.h"
 #include "dbus-protocol.h"
-#include "dbus-userdb.h"
+#include "dbus-credentials.h"
 
 /**
  * @defgroup DBusAuth Authentication
@@ -162,13 +162,12 @@ struct DBusAuth
                                           *   as.
                                           */
   
-  DBusCredentials credentials;      /**< Credentials read from socket,
-                                     * fields may be -1
-                                     */
+  DBusCredentials *credentials;          /**< Credentials read from socket
+                                          */
 
-  DBusCredentials authorized_identity; /**< Credentials that are authorized */
+  DBusCredentials *authorized_identity; /**< Credentials that are authorized */
 
-  DBusCredentials desired_identity;    /**< Identity client has requested */
+  DBusCredentials *desired_identity;    /**< Identity client has requested */
   
   DBusString context;               /**< Cookie scope */
   DBusKeyring *keyring;             /**< Keyring for cookie mechanism. */
@@ -331,10 +330,6 @@ _dbus_auth_new (int size)
     return NULL;
   
   auth->refcount = 1;
-
-  _dbus_credentials_clear (&auth->credentials);
-  _dbus_credentials_clear (&auth->authorized_identity);
-  _dbus_credentials_clear (&auth->desired_identity);
   
   auth->keyring = NULL;
   auth->cookie_id = -1;
@@ -365,9 +360,31 @@ _dbus_auth_new (int size)
   /* default context if none is specified */
   if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
     goto enomem_5;
+
+  auth->credentials = _dbus_credentials_new ();
+  if (auth->credentials == NULL)
+    goto enomem_6;
+  
+  auth->authorized_identity = _dbus_credentials_new ();
+  if (auth->authorized_identity == NULL)
+    goto enomem_7;
+
+  auth->desired_identity = _dbus_credentials_new ();
+  if (auth->desired_identity == NULL)
+    goto enomem_8;
   
   return auth;
 
+#if 0
+ enomem_9:
+  _dbus_credentials_unref (auth->desired_identity);
+#endif
+ enomem_8:
+  _dbus_credentials_unref (auth->authorized_identity);
+ enomem_7:
+  _dbus_credentials_unref (auth->credentials);
+ enomem_6:
+ /* last alloc was an append to context, which is freed already below */ ;
  enomem_5:
   _dbus_string_free (&auth->challenge);
  enomem_4:
@@ -390,8 +407,8 @@ shutdown_mech (DBusAuth *auth)
   auth->already_asked_for_initial_response = FALSE;
   _dbus_string_set_length (&auth->identity, 0);
 
-  _dbus_credentials_clear (&auth->authorized_identity);
-  _dbus_credentials_clear (&auth->desired_identity);
+  _dbus_credentials_clear (auth->authorized_identity);
+  _dbus_credentials_clear (auth->desired_identity);
   
   if (auth->mech != NULL)
     {
@@ -513,7 +530,7 @@ sha1_handle_first_client_response (DBusAuth         *auth,
         }
     }
       
-  if (!_dbus_credentials_from_username (data, &auth->desired_identity))
+  if (!_dbus_credentials_add_from_username (auth->desired_identity, data))
     {
       _dbus_verbose ("%s: Did not get a valid username from client\n",
                      DBUS_AUTH_NAME (auth));
@@ -706,14 +723,17 @@ sha1_handle_second_client_response (DBusAuth         *auth,
         retval = TRUE;
       goto out_3;
     }
-      
+
+  if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+                                          auth->desired_identity))
+    goto out_3;
+  
   if (!send_ok (auth))
     goto out_3;
 
-  _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT" using DBUS_COOKIE_SHA1\n",
-                 DBUS_AUTH_NAME (auth), auth->desired_identity.uid);
+  _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n",
+                 DBUS_AUTH_NAME (auth));
   
-  auth->authorized_identity = auth->desired_identity;
   retval = TRUE;
   
  out_3:
@@ -966,7 +986,7 @@ static dbus_bool_t
 handle_server_data_external_mech (DBusAuth         *auth,
                                   const DBusString *data)
 {
-  if (auth->credentials.uid == DBUS_UID_UNSET)
+  if (_dbus_credentials_are_empty (auth->credentials))
     {
       _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
                      DBUS_AUTH_NAME (auth));
@@ -1005,7 +1025,7 @@ handle_server_data_external_mech (DBusAuth         *auth,
         return FALSE;
     }
 
-  _dbus_credentials_clear (&auth->desired_identity);
+  _dbus_credentials_clear (auth->desired_identity);
   
   /* If auth->identity is still empty here, then client
    * responded with an empty string after we poked it for
@@ -1014,12 +1034,16 @@ handle_server_data_external_mech (DBusAuth         *auth,
    */
   if (_dbus_string_get_length (&auth->identity) == 0)
     {
-      auth->desired_identity.uid = auth->credentials.uid;
+      if (!_dbus_credentials_add_credentials (auth->desired_identity,
+                                              auth->credentials))
+        {
+          return FALSE; /* OOM */
+        }
     }
   else
     {
-      if (!_dbus_parse_uid (&auth->identity,
-                            &auth->desired_identity.uid))
+      if (!_dbus_credentials_parse_and_add_desired(auth->desired_identity,
+                                                   &auth->identity))
         {
           _dbus_verbose ("%s: could not get credentials from uid string\n",
                          DBUS_AUTH_NAME (auth));
@@ -1027,7 +1051,7 @@ handle_server_data_external_mech (DBusAuth         *auth,
         }
     }
 
-  if (auth->desired_identity.uid == DBUS_UID_UNSET)
+  if (_dbus_credentials_are_empty(auth->desired_identity))
     {
       _dbus_verbose ("%s: desired user %s is no good\n",
                      DBUS_AUTH_NAME (auth),
@@ -1035,32 +1059,34 @@ handle_server_data_external_mech (DBusAuth         *auth,
       return send_rejected (auth);
     }
   
-  if (_dbus_credentials_match (&auth->desired_identity,
-                               &auth->credentials))
+  if (_dbus_credentials_are_superset (auth->credentials,
+                                      auth->desired_identity))
     {
-      /* client has authenticated */      
+      /* client has authenticated */
+      if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+                                              auth->desired_identity))
+        return FALSE;
+
+      /* also copy process ID from the socket credentials - FIXME this
+       * should be done even if auth EXTERNAL not used
+       */
+      if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                             DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                             auth->credentials))
+        return FALSE;
+      
       if (!send_ok (auth))
         return FALSE;
 
-      _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT
-                     " matching socket credentials UID "DBUS_UID_FORMAT"\n",
-                     DBUS_AUTH_NAME (auth),
-                     auth->desired_identity.uid,
-                     auth->credentials.uid);
+      _dbus_verbose ("%s: authenticated client based on socket credentials\n",
+                     DBUS_AUTH_NAME (auth));
 
-      auth->authorized_identity.pid = auth->credentials.pid;
-      auth->authorized_identity.uid = auth->desired_identity.uid;
       return TRUE;
     }
   else
     {
-      _dbus_verbose ("%s: credentials uid="DBUS_UID_FORMAT
-                     " gid="DBUS_GID_FORMAT
-                     " do not allow uid="DBUS_UID_FORMAT
-                     " gid="DBUS_GID_FORMAT"\n",
-                     DBUS_AUTH_NAME (auth),
-                     auth->credentials.uid, auth->credentials.gid,
-                     auth->desired_identity.uid, auth->desired_identity.gid);
+      _dbus_verbose ("%s: desired identity not found in socket credentials\n",
+                     DBUS_AUTH_NAME (auth));
       return send_rejected (auth);
     }
 }
@@ -1084,9 +1110,8 @@ handle_client_initial_response_external_mech (DBusAuth         *auth,
 
   if (!_dbus_string_init (&plaintext))
     return FALSE;
-  
-  if (!_dbus_string_append_uint (&plaintext,
-                                 _dbus_getuid ()))
+
+  if (!_dbus_append_desired_identity (&plaintext))
     goto failed;
 
   if (!_dbus_string_hex_encode (&plaintext, 0,
@@ -2105,6 +2130,10 @@ _dbus_auth_unref (DBusAuth *auth)
       _dbus_string_free (&auth->outgoing);
 
       dbus_free_string_array (auth->allowed_mechs);
+
+      _dbus_credentials_unref (auth->credentials);
+      _dbus_credentials_unref (auth->authorized_identity);
+      _dbus_credentials_unref (auth->desired_identity);
       
       dbus_free (auth);
     }
@@ -2435,29 +2464,42 @@ _dbus_auth_decode_data (DBusAuth         *auth,
  *
  * @param auth the auth conversation
  * @param credentials the credentials received
+ * @returns #FALSE on OOM
  */
-void
+dbus_bool_t
 _dbus_auth_set_credentials (DBusAuth               *auth,
-                            const DBusCredentials  *credentials)
+                            DBusCredentials        *credentials)
 {
-  auth->credentials = *credentials;
+  _dbus_credentials_clear (auth->credentials);
+  return _dbus_credentials_add_credentials (auth->credentials,
+                                            credentials);
 }
 
 /**
  * Gets the identity we authorized the client as.  Apps may have
  * different policies as to what identities they allow.
  *
+ * Returned credentials are not a copy and should not be modified
+ *
  * @param auth the auth conversation
- * @param credentials the credentials we've authorized
+ * @returns the credentials we've authorized BY REFERENCE do not modify
  */
-void
-_dbus_auth_get_identity (DBusAuth               *auth,
-                         DBusCredentials        *credentials)
+DBusCredentials*
+_dbus_auth_get_identity (DBusAuth               *auth)
 {
   if (auth->state == &common_state_authenticated)
-    *credentials = auth->authorized_identity;
+    {
+      return auth->authorized_identity;
+    }
   else
-    _dbus_credentials_clear (credentials);
+    {
+      /* FIXME instead of this, keep an empty credential around that
+       * doesn't require allocation or something
+       */
+      /* return empty credentials */
+      _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
+      return auth->authorized_identity;
+    }
 }
 
 /**
index 9cff8b5..4b6b106 100644 (file)
@@ -68,10 +68,9 @@ dbus_bool_t   _dbus_auth_needs_decoding      (DBusAuth               *auth);
 dbus_bool_t   _dbus_auth_decode_data         (DBusAuth               *auth,
                                               const DBusString       *encoded,
                                               DBusString             *plaintext);
-void          _dbus_auth_set_credentials     (DBusAuth               *auth,
-                                              const DBusCredentials  *credentials);
-void          _dbus_auth_get_identity        (DBusAuth               *auth,
+dbus_bool_t   _dbus_auth_set_credentials     (DBusAuth               *auth,
                                               DBusCredentials        *credentials);
+DBusCredentials* _dbus_auth_get_identity     (DBusAuth               *auth);
 dbus_bool_t   _dbus_auth_set_context         (DBusAuth               *auth,
                                               const DBusString       *context);
 const char*   _dbus_auth_get_guid_from_server(DBusAuth               *auth);
diff --git a/dbus/dbus-credentials-util.c b/dbus/dbus-credentials-util.c
new file mode 100644 (file)
index 0000000..9b81aca
--- /dev/null
@@ -0,0 +1,202 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials-util.c Would be in dbus-credentials.c, but only used for tests/bus
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-credentials.h"
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+#include <string.h>
+
+static DBusCredentials*
+make_credentials(dbus_uid_t  unix_uid,
+                 dbus_pid_t  unix_pid,
+                 const char *windows_sid)
+{
+  DBusCredentials *credentials;
+
+  credentials = _dbus_credentials_new ();
+
+  if (unix_uid != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, unix_uid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  if (unix_pid != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, unix_pid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  if (windows_sid != NULL)
+    {
+      if (!_dbus_credentials_add_windows_sid (credentials, windows_sid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  return credentials;
+}
+
+#define SAMPLE_SID "whatever a windows sid looks like"
+#define OTHER_SAMPLE_SID "whatever else"
+
+dbus_bool_t
+_dbus_credentials_test (const char *test_data_dir)
+{
+  DBusCredentials *creds;
+  DBusCredentials *creds2;
+  
+  if (test_data_dir == NULL)
+    return TRUE;
+
+  creds = make_credentials (12, 511, SAMPLE_SID);
+  if (creds == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  /* test refcounting */
+  _dbus_credentials_ref (creds);
+  _dbus_credentials_unref (creds);
+  
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds) == 12);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds) == 511);
+  _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0);
+
+  _dbus_assert (!_dbus_credentials_are_empty (creds));
+
+  /* Test copy */
+  creds2 = _dbus_credentials_copy (creds);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds2) == 12);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds2) == 511);
+  _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds2), SAMPLE_SID) == 0);  
+
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+  
+  /* Same user if both unix and windows are the same */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (_dbus_credentials_same_user (creds, creds2));
+
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Windows is missing */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, NULL);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Windows is different */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, OTHER_SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Unix is missing */
+  creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Unix is different */
+  creds2 = make_credentials (15, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if both are missing */
+  creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, NULL);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Clearing credentials works */
+  _dbus_credentials_clear (creds);
+
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds) == DBUS_UID_UNSET);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds) == DBUS_PID_UNSET);
+  _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL);
+
+  _dbus_assert (_dbus_credentials_are_empty (creds));
+
+  _dbus_credentials_unref (creds);
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c
new file mode 100644 (file)
index 0000000..dde6928
--- /dev/null
@@ -0,0 +1,418 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials.c Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include <config.h>
+#include <string.h>
+#include "dbus-credentials.h"
+#include "dbus-internals.h"
+
+/**
+ * @defgroup DBusCredentials Credentials provable through authentication
+ * @ingroup  DBusInternals
+ * @brief DBusCredentials object
+ *
+ * Credentials are what you have to prove you have in order to
+ * authenticate.  The main credentials right now are a unix user
+ * account, a Windows user account, or a UNIX process ID.
+ */
+
+/**
+ * @defgroup DBusCredentialsInternals Credentials implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusCredentials implementation details
+ *
+ * Private details of credentials code.
+ *
+ * @{
+ */
+
+struct DBusCredentials {
+  int refcount;
+  dbus_uid_t unix_uid;
+  dbus_pid_t unix_pid;
+  char *windows_sid;
+};
+
+/** @} */
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/**
+ * Creates a new credentials object.
+ *
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new (void)
+{
+  DBusCredentials *creds;
+
+  creds = dbus_new (DBusCredentials, 1);
+  if (creds == NULL)
+    return NULL;
+  
+  creds->refcount = 1;
+  creds->unix_uid = DBUS_UID_UNSET;
+  creds->unix_pid = DBUS_PID_UNSET;
+  creds->windows_sid = NULL;
+
+  return creds;
+}
+
+/**
+ * Creates a new object with credentials (user ID and process ID) from the current process.
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new_from_current_process (void)
+{
+  DBusCredentials *creds;
+
+  creds = _dbus_credentials_new ();
+  if (creds == NULL)
+    return NULL;
+
+  if (!_dbus_credentials_add_from_current_process (creds))
+    {
+      _dbus_credentials_unref (creds);
+      return NULL;
+    }
+  
+  return creds;
+}
+
+/**
+ * Increment refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_ref (DBusCredentials *credentials)
+{
+  _dbus_assert (credentials->refcount > 0);
+  credentials->refcount += 1;
+}
+
+/**
+ * Decrement refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_unref (DBusCredentials    *credentials)
+{
+  _dbus_assert (credentials->refcount > 0);
+
+  credentials->refcount -= 1;
+  if (credentials->refcount == 0)
+    {
+      dbus_free (credentials->windows_sid);
+      dbus_free (credentials);
+    }
+}
+
+/**
+ * Add a UNIX process ID to the credentials.
+ *
+ * @param credentials the object
+ * @param pid the process ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_pid (DBusCredentials    *credentials,
+                                dbus_pid_t          pid)
+{
+  credentials->unix_pid = pid;
+  return TRUE;
+}
+
+/**
+ * Add a UNIX user ID to the credentials.
+ *
+ * @param credentials the object
+ * @param uid the user ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_uid(DBusCredentials    *credentials,
+                               dbus_uid_t          uid)
+{
+  credentials->unix_uid = uid;
+  return TRUE;
+
+}
+
+/**
+ * Add a Windows user SID to the credentials.
+ *
+ * @param credentials the object
+ * @param windows_sid the user SID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_windows_sid (DBusCredentials    *credentials,
+                                   const char         *windows_sid)
+{
+  char *copy;
+
+  copy = _dbus_strdup (windows_sid);
+  if (copy == NULL)
+    return FALSE;
+
+  dbus_free (credentials->windows_sid);
+  credentials->windows_sid = copy;
+
+  return TRUE;
+}
+
+/**
+ * Checks whether the given credential is present.
+ *
+ * @param credentials the object
+ * @param type the credential to check for
+ * @returns #TRUE if the credential is present
+ */
+dbus_bool_t
+_dbus_credentials_include (DBusCredentials    *credentials,
+                           DBusCredentialType  type)
+{
+  switch (type)
+    {
+    case DBUS_CREDENTIAL_UNIX_PROCESS_ID:
+      return credentials->unix_pid != DBUS_PID_UNSET;
+    case DBUS_CREDENTIAL_UNIX_USER_ID:
+      return credentials->unix_uid != DBUS_UID_UNSET;
+    case DBUS_CREDENTIAL_WINDOWS_SID:
+      return credentials->windows_sid != NULL;
+    }
+
+  _dbus_assert_not_reached ("Unknown credential enum value");
+  return FALSE;
+}
+
+/**
+ * Gets the UNIX process ID in the credentials, or #DBUS_PID_UNSET if
+ * the credentials object doesn't contain a process ID.
+ *
+ * @param credentials the object
+ * @returns UNIX process ID
+ */
+dbus_pid_t
+_dbus_credentials_get_unix_pid (DBusCredentials    *credentials)
+{
+  return credentials->unix_pid;
+}
+
+/**
+ * Gets the UNIX user ID in the credentials, or #DBUS_UID_UNSET if
+ * the credentials object doesn't contain a user ID.
+ *
+ * @param credentials the object
+ * @returns UNIX user ID
+ */
+dbus_uid_t
+_dbus_credentials_get_unix_uid (DBusCredentials    *credentials)
+{
+  return credentials->unix_uid;
+}
+
+/**
+ * Gets the Windows user SID in the credentials, or #NULL if
+ * the credentials object doesn't contain a Windows user SID.
+ *
+ * @param credentials the object
+ * @returns Windows user SID
+ */
+const char*
+_dbus_credentials_get_windows_sid (DBusCredentials    *credentials)
+{
+  return credentials->windows_sid;
+}
+
+/**
+ * Checks whether the first credentials object contains
+ * all the credentials found in the second credentials object.
+ *
+ * @param credentials the object
+ * @param possible_subset see if credentials in here are also in the first arg
+ * @returns #TRUE if second arg is contained in first
+ */
+dbus_bool_t
+_dbus_credentials_are_superset (DBusCredentials    *credentials,
+                                DBusCredentials    *possible_subset)
+{
+  return
+    (possible_subset->unix_pid == DBUS_PID_UNSET ||
+     possible_subset->unix_pid == credentials->unix_pid) &&
+    (possible_subset->unix_uid == DBUS_UID_UNSET ||
+     possible_subset->unix_uid == credentials->unix_uid) &&
+    (possible_subset->windows_sid == NULL ||
+     (credentials->windows_sid && strcmp (possible_subset->windows_sid,
+                                          credentials->windows_sid) == 0));
+}
+
+/**
+ * Checks whether a credentials object contains anything.
+ * 
+ * @param credentials the object
+ * @returns #TRUE if there are no credentials in the object
+ */
+dbus_bool_t
+_dbus_credentials_are_empty (DBusCredentials    *credentials)
+{
+  return
+    credentials->unix_pid == DBUS_PID_UNSET &&
+    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.
+ * 
+ * @param credentials the object
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credentials (DBusCredentials    *credentials,
+                                   DBusCredentials    *other_credentials)
+{
+  return
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                      other_credentials) &&
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_UNIX_USER_ID,
+                                      other_credentials) &&
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_WINDOWS_SID,
+                                      other_credentials);
+}
+
+/**
+ * Merge the given credential found in the second object into the first object,
+ * overwriting the first object's value for that credential.
+ *
+ * Does nothing if the second object does not contain the specified credential.
+ * i.e., will never delete a credential from the first object.
+ * 
+ * @param credentials the object
+ * @param which the credential to overwrite
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credential (DBusCredentials    *credentials,
+                                  DBusCredentialType  which,
+                                  DBusCredentials    *other_credentials)
+{
+  if (which == DBUS_CREDENTIAL_UNIX_PROCESS_ID &&
+      other_credentials->unix_pid != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, other_credentials->unix_pid))
+        return FALSE;
+    }
+  else if (which == DBUS_CREDENTIAL_UNIX_USER_ID &&
+           other_credentials->unix_uid != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, other_credentials->unix_uid))
+        return FALSE;
+    }
+  else if (which == DBUS_CREDENTIAL_WINDOWS_SID &&
+           other_credentials->windows_sid != NULL)
+    {
+      if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Clear all credentials in the object.
+ * 
+ * @param credentials the object
+ */
+void
+_dbus_credentials_clear (DBusCredentials    *credentials)
+{
+  credentials->unix_pid = DBUS_PID_UNSET;
+  credentials->unix_uid = DBUS_UID_UNSET;
+  dbus_free (credentials->windows_sid);
+  credentials->windows_sid = NULL;
+}
+
+/**
+ * Copy a credentials object.
+ * 
+ * @param credentials the object
+ * @returns the copy or #NULL
+ */
+DBusCredentials*
+_dbus_credentials_copy (DBusCredentials    *credentials)
+{
+  DBusCredentials *copy;
+
+  copy = _dbus_credentials_new ();
+  if (copy == NULL)
+    return NULL;
+
+  if (!_dbus_credentials_add_credentials (copy, credentials))
+    {
+      _dbus_credentials_unref (copy);
+      return NULL;
+    }
+
+  return copy;
+}
+
+/**
+ * Check whether the user-identifying credentials in two credentials
+ * objects are identical. Credentials that are not related to the
+ * user are ignored, but any kind of user ID credentials must be the
+ * same (UNIX user ID, Windows user SID, etc.) and present in both
+ * objects for the function to return #TRUE.
+ * 
+ * @param credentials the object
+ * @param other_credentials credentials to compare
+ * @returns #TRUE if the two credentials refer to the same user
+ */
+dbus_bool_t
+_dbus_credentials_same_user (DBusCredentials    *credentials,
+                             DBusCredentials    *other_credentials)
+{
+  /* both windows and unix user must be the same (though pretty much
+   * in all conceivable cases, one will be unset)
+   */
+  return credentials->unix_uid == other_credentials->unix_uid &&
+    ((!(credentials->windows_sid || other_credentials->windows_sid)) ||
+     (credentials->windows_sid && other_credentials->windows_sid &&
+      strcmp (credentials->windows_sid, other_credentials->windows_sid) == 0));
+}
+
+/** @} */
+
+/* tests in dbus-credentials-util.c */
diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h
new file mode 100644 (file)
index 0000000..b47c9c4
--- /dev/null
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials.h Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef DBUS_CREDENTIALS_H
+#define DBUS_CREDENTIALS_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+typedef enum {
+  DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+  DBUS_CREDENTIAL_UNIX_USER_ID,
+  DBUS_CREDENTIAL_WINDOWS_SID
+} DBusCredentialType;
+
+DBusCredentials* _dbus_credentials_new_from_current_process (void);
+DBusCredentials* _dbus_credentials_new                      (void);
+void             _dbus_credentials_ref                      (DBusCredentials    *credentials);
+void             _dbus_credentials_unref                    (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_add_unix_pid             (DBusCredentials    *credentials,
+                                                             dbus_pid_t          pid);
+dbus_bool_t      _dbus_credentials_add_unix_uid             (DBusCredentials    *credentials,
+                                                             dbus_uid_t          uid);
+dbus_bool_t      _dbus_credentials_add_windows_sid          (DBusCredentials    *credentials,
+                                                             const char         *windows_sid);
+dbus_bool_t      _dbus_credentials_include                  (DBusCredentials    *credentials,
+                                                             DBusCredentialType  type);
+dbus_pid_t       _dbus_credentials_get_unix_pid             (DBusCredentials    *credentials);
+dbus_uid_t       _dbus_credentials_get_unix_uid             (DBusCredentials    *credentials);
+const char*      _dbus_credentials_get_windows_sid          (DBusCredentials    *credentials);
+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_add_credentials          (DBusCredentials    *credentials,
+                                                             DBusCredentials    *other_credentials);
+/* must silently allow 'which' to not exist */
+dbus_bool_t      _dbus_credentials_add_credential           (DBusCredentials    *credentials,
+                                                             DBusCredentialType  which,
+                                                             DBusCredentials    *other_credentials);
+void             _dbus_credentials_clear                    (DBusCredentials    *credentials);
+DBusCredentials* _dbus_credentials_copy                     (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_same_user                (DBusCredentials    *credentials,
+                                                             DBusCredentials    *other_credentials);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_CREDENTIALS_H */
index b0a0f02..86c1332 100644 (file)
@@ -271,7 +271,7 @@ _dbus_warn_check_failed(const char *format,
   if (!warn_initted)
     init_warnings ();
 
-  fprintf (stderr, "process %lu: ", _dbus_getpid ());
+  fprintf (stderr, "process %lu: ", _dbus_pid_for_log ());
   
   va_start (args, format);
   vfprintf (stderr, format, args);
@@ -349,9 +349,9 @@ _dbus_verbose_real (const char *format,
   if (need_pid)
     {
 #if PTHREAD_IN_VERBOSE
-      fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
+      fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
 #else
-      fprintf (stderr, "%lu: ", _dbus_getpid ());
+      fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
 #endif
     }
       
@@ -813,7 +813,7 @@ _dbus_real_assert (dbus_bool_t  condition,
   if (_DBUS_UNLIKELY (!condition))
     {
       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
-                  _dbus_getpid (), condition_text, file, line, func);
+                  _dbus_pid_for_log (), condition_text, file, line, func);
       _dbus_abort ();
     }
 }
@@ -834,7 +834,7 @@ _dbus_real_assert_not_reached (const char *explanation,
                                int         line)
 {
   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
-              file, line, _dbus_getpid (), explanation);
+              file, line, _dbus_pid_for_log (), explanation);
   _dbus_abort ();
 }
 #endif /* DBUS_DISABLE_ASSERT */
index 018f45a..17c6b17 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include "dbus-keyring.h"
-#include "dbus-userdb.h"
 #include "dbus-protocol.h"
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-list.h>
index 3d4320d..bd9949c 100644 (file)
@@ -986,7 +986,7 @@ node_read_value (TestTypeNode   *node,
                  DBusTypeReader *reader,
                  int             seed)
 {
-  DBusTypeReader restored;
+  /* DBusTypeReader restored; */
 
   if (!(* node->klass->read_value) (node, reader, seed))
     return FALSE;
index 07535db..c3be333 100644 (file)
@@ -22,7 +22,7 @@
  *
  */
 #include "dbus-spawn.h"
-#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-unix.h"
 #include "dbus-internals.h"
 #include "dbus-test.h"
 #include "dbus-protocol.h"
@@ -849,7 +849,7 @@ do_exec (int                       child_err_report_fd,
 #endif
 
   _dbus_verbose_reset ();
-  _dbus_verbose ("Child process has PID %lu\n",
+  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
                  _dbus_getpid ());
   
   if (child_setup)
index 80732a7..135f7c9 100644 (file)
@@ -31,6 +31,7 @@
 #include "dbus-string.h"
 #include "dbus-userdb.h"
 #include "dbus-list.h"
+#include "dbus-credentials.h"
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
@@ -85,6 +86,7 @@ _dbus_open_socket (int              *fd_p,
   *fd_p = socket (domain, type, protocol);
   if (*fd_p >= 0)
     {
+      _dbus_verbose ("socket fd %d opened\n", *fd_p);
       return TRUE;
     }
   else
@@ -949,11 +951,14 @@ write_credentials_byte (int             server_fd,
 
 /**
  * Reads a single byte which must be nul (an error occurs otherwise),
- * and reads unix credentials if available. Fills in pid/uid/gid with
- * -1 if no credentials are available. Return value indicates whether
- * a byte was read, not whether we got valid credentials. On some
- * systems, such as Linux, reading/writing the byte isn't actually
- * required, but we do it anyway just to avoid multiple codepaths.
+ * and reads unix credentials if available. Clears the credentials
+ * object, then adds pid/uid if available, so any previous credentials
+ * stored in the object are lost.
+ *
+ * Return value indicates whether a byte was read, not whether
+ * we got valid credentials. On some systems, such as Linux,
+ * reading/writing the byte isn't actually required, but we do it
+ * anyway just to avoid multiple codepaths.
  * 
  * Fails if no byte is available, so you must select() first.
  *
@@ -961,19 +966,24 @@ write_credentials_byte (int             server_fd,
  * use sendmsg()/recvmsg() to transmit credentials.
  *
  * @param client_fd the client file descriptor
- * @param credentials struct to fill with credentials of client
+ * @param credentials object to add client credentials to
  * @param error location to store error code
  * @returns #TRUE on success
  */
 dbus_bool_t
-_dbus_read_credentials_unix_socket  (int              client_fd,
-                                     DBusCredentials *credentials,
-                                     DBusError       *error)
+_dbus_read_credentials_socket  (int              client_fd,
+                                DBusCredentials *credentials,
+                                DBusError       *error)
 {
   struct msghdr msg;
   struct iovec iov;
   char buf;
+  dbus_uid_t uid_read;
+  dbus_pid_t pid_read;
 
+  uid_read = DBUS_UID_UNSET;
+  pid_read = DBUS_PID_UNSET;
+  
 #ifdef HAVE_CMSGCRED 
   struct {
          struct cmsghdr hdr;
@@ -993,9 +1003,9 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
    * we need these assertions to fail as soon as we're wrong about
    * it so we can do the porting fixups
    */
-  _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
-  _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
-  _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
+  _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+  _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+  _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
 
   _dbus_credentials_clear (credentials);
 
@@ -1056,9 +1066,8 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
     if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
        cr_len == sizeof (cr))
       {
-       credentials->pid = cr.pid;
-       credentials->uid = cr.uid;
-       credentials->gid = cr.gid;
+       pid_read = cr.pid;
+       uid_read = cr.uid;
       }
     else
       {
@@ -1066,13 +1075,11 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
                       cr_len, (int) sizeof (cr), _dbus_strerror (errno));
       }
 #elif defined(HAVE_CMSGCRED)
-    credentials->pid = cmsg.cred.cmcred_pid;
-    credentials->uid = cmsg.cred.cmcred_euid;
-    credentials->gid = cmsg.cred.cmcred_groups[0];
+    pid_read = cmsg.cred.cmcred_pid;
+    uid_read = cmsg.cred.cmcred_euid;
 #elif defined(LOCAL_CREDS)
-    credentials->pid = DBUS_PID_UNSET;
-    credentials->uid = cmsg.cred.sc_uid;
-    credentials->gid = cmsg.cred.sc_gid;
+    pid_read = DBUS_PID_UNSET;
+    uid_read = cmsg.cred.sc_uid;
     /* Since we have already got the credentials from this socket, we can
      * disable its LOCAL_CREDS flag if it was ever set. */
     _dbus_set_local_creds (client_fd, FALSE);
@@ -1081,8 +1088,7 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
     gid_t egid;
     if (getpeereid (client_fd, &euid, &egid) == 0)
       {
-        credentials->uid = euid;
-        credentials->gid = egid;
+        uid_read = euid;
       }
     else
       {
@@ -1092,9 +1098,8 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
     ucred_t * ucred = NULL;
     if (getpeerucred (client_fd, &ucred) == 0)
       {
-        credentials->pid = ucred_getpid (ucred);
-        credentials->uid = ucred_geteuid (ucred);
-        credentials->gid = ucred_getegid (ucred);
+        pid_read = ucred_getpid (ucred);
+        uid_read = ucred_geteuid (ucred);
       }
     else
       {
@@ -1110,11 +1115,28 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
   _dbus_verbose ("Credentials:"
                  "  pid "DBUS_PID_FORMAT
                  "  uid "DBUS_UID_FORMAT
-                 "  gid "DBUS_GID_FORMAT"\n",
-                credentials->pid,
-                credentials->uid,
-                credentials->gid);
-    
+                 "\n",
+                pid_read,
+                uid_read);
+
+  if (pid_read != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+
+  if (uid_read != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+  
   return TRUE;
 }
 
@@ -1136,8 +1158,8 @@ _dbus_read_credentials_unix_socket  (int              client_fd,
  * @returns #TRUE if the byte was sent
  */
 dbus_bool_t
-_dbus_send_credentials_unix_socket  (int              server_fd,
-                                     DBusError       *error)
+_dbus_send_credentials_socket  (int              server_fd,
+                                DBusError       *error)
 {
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
@@ -1171,6 +1193,8 @@ _dbus_accept  (int listen_fd)
       if (errno == EINTR)
         goto retry;
     }
+
+  _dbus_verbose ("client fd %d accepted\n", client_fd);
   
   return client_fd;
 }
@@ -1446,31 +1470,77 @@ _dbus_user_info_fill_uid (DBusUserInfo *info,
 }
 
 /**
- * Gets the credentials of the current process.
+ * Adds the credentials of the current process to the
+ * passed-in credentials object.
  *
- * @param credentials credentials to fill in.
+ * @param credentials credentials to add to
+ * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
  */
-void
-_dbus_credentials_from_current_process (DBusCredentials *credentials)
+dbus_bool_t
+_dbus_credentials_add_from_current_process (DBusCredentials *credentials)
 {
   /* The POSIX spec certainly doesn't promise this, but
    * we need these assertions to fail as soon as we're wrong about
    * it so we can do the porting fixups
    */
-  _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
-  _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
-  _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
-  
-  credentials->pid = getpid ();
-  credentials->uid = getuid ();
-  credentials->gid = getgid ();
+  _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+  _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+  _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
+
+  if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
+    return FALSE;
+  if (!_dbus_credentials_add_unix_uid(credentials, _dbus_getuid()))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Parses a desired identity provided from a client in the auth protocol.
+ * On UNIX this means parsing a UID.
+ *
+ * @todo this is broken because it treats OOM and parse error
+ * the same way. Needs a #DBusError.
+ * 
+ * @param credentials the credentials to add what we parse to
+ * @param desired_identity the string to parse
+ * @returns #TRUE if we successfully parsed something
+ */
+dbus_bool_t
+_dbus_credentials_parse_and_add_desired (DBusCredentials  *credentials,
+                                         const DBusString *desired_identity)
+{
+  dbus_uid_t uid;
+
+  if (!_dbus_parse_uid (desired_identity, &uid))
+    return FALSE;
+
+  if (!_dbus_credentials_add_unix_uid (credentials, uid))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Append to the string the identity we would like to have when we authenticate,
+ * on UNIX this is the current process UID and on Windows something else.
+ * No escaping is required, that is done in dbus-auth.c.
+ * 
+ * @param str the string to append to
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_append_desired_identity (DBusString *str)
+{
+  return _dbus_string_append_uint (str,
+                                   _dbus_getuid ());
 }
 
 /**
  * Gets our process ID
  * @returns process ID
  */
-unsigned long
+dbus_pid_t
 _dbus_getpid (void)
 {
   return getpid ();
@@ -1485,6 +1555,59 @@ _dbus_getuid (void)
   return getuid ();
 }
 
+/**
+ * The only reason this is separate from _dbus_getpid() is to allow it
+ * on Windows for logging but not for other purposes.
+ * 
+ * @returns process ID to put in log messages
+ */
+unsigned long
+_dbus_pid_for_log (void)
+{
+  return getpid ();
+}
+
+/**
+ * Gets a UID from a UID string.
+ *
+ * @param uid_str the UID in string form
+ * @param uid UID to fill in
+ * @returns #TRUE if successfully filled in UID
+ */
+dbus_bool_t
+_dbus_parse_uid (const DBusString      *uid_str,
+                 dbus_uid_t            *uid)
+{
+  int end;
+  long val;
+  
+  if (_dbus_string_get_length (uid_str) == 0)
+    {
+      _dbus_verbose ("UID string was zero length\n");
+      return FALSE;
+    }
+
+  val = -1;
+  end = 0;
+  if (!_dbus_string_parse_int (uid_str, 0, &val,
+                               &end))
+    {
+      _dbus_verbose ("could not parse string as a UID\n");
+      return FALSE;
+    }
+  
+  if (end != _dbus_string_get_length (uid_str))
+    {
+      _dbus_verbose ("string contained trailing stuff after UID\n");
+      return FALSE;
+    }
+
+  *uid = val;
+
+  return TRUE;
+}
+
+
 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
 
 #ifdef DBUS_USE_ATOMIC_INT_486
@@ -1717,6 +1840,8 @@ _dbus_file_get_contents (DBusString       *str,
       return FALSE;
     }
 
+  _dbus_verbose ("file fd %d opened\n", fd);
+  
   if (fstat (fd, &sb) < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
@@ -1858,6 +1983,8 @@ _dbus_string_save_to_file (const DBusString *str,
       goto out;
     }
 
+  _dbus_verbose ("tmp file fd %d opened\n", fd);
+  
   need_unlink = TRUE;
   
   total = 0;
@@ -1983,6 +2110,8 @@ _dbus_create_file_exclusively (const DBusString *filename,
       return FALSE;
     }
 
+  _dbus_verbose ("exclusive file fd %d opened\n", fd);
+  
   if (!_dbus_close (fd, NULL))
     {
       dbus_set_error (error,
@@ -2181,6 +2310,8 @@ _dbus_generate_random_bytes (DBusString *str,
   if (fd < 0)
     return _dbus_generate_pseudorandom_bytes (str, n_bytes);
 
+  _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
+  
   if (_dbus_read (fd, str, n_bytes) != n_bytes)
     {
       _dbus_close (fd, NULL);
@@ -2571,6 +2702,8 @@ _dbus_get_autolaunch_address (DBusString *address,
         /* huh?! can't open /dev/null? */
         _exit (1);
 
+      _dbus_verbose ("/dev/null fd %d opened\n", fd);
+      
       /* set-up stdXXX */
       close (address_pipe[READ_END]);
       close (errors_pipe[READ_END]);
@@ -2757,7 +2890,7 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs)
   else
     {
       const DBusString *homedir;
-      const DBusString local_share;
+      DBusString local_share;
 
       if (!_dbus_homedir_from_current_process (&homedir))
         goto oom;
index f72493a..58fce9c 100644 (file)
@@ -71,6 +71,63 @@ int _dbus_listen_unix_socket  (const char     *path,
                                dbus_bool_t     abstract,
                                DBusError      *error);
 
+dbus_bool_t _dbus_read_credentials (int               client_fd,
+                                    DBusCredentials  *credentials,
+                                    DBusError        *error);
+dbus_bool_t _dbus_send_credentials (int              server_fd,
+                                    DBusError       *error);
+
+/** Information about a UNIX user */
+typedef struct DBusUserInfo  DBusUserInfo;
+/** Information about a UNIX group */
+typedef struct DBusGroupInfo DBusGroupInfo;
+
+/**
+ * Information about a UNIX user
+ */
+struct DBusUserInfo
+{
+  dbus_uid_t  uid;            /**< UID */
+  dbus_gid_t  primary_gid;    /**< GID */
+  dbus_gid_t *group_ids;      /**< Groups IDs, *including* above primary group */
+  int         n_group_ids;    /**< Size of group IDs array */
+  char       *username;       /**< Username */
+  char       *homedir;        /**< Home directory */
+};
+
+/**
+ * Information about a UNIX group
+ */
+struct DBusGroupInfo
+{
+  dbus_gid_t  gid;            /**< GID */
+  char       *groupname;      /**< Group name */
+};
+
+dbus_bool_t _dbus_user_info_fill     (DBusUserInfo     *info,
+                                      const DBusString *username,
+                                      DBusError        *error);
+dbus_bool_t _dbus_user_info_fill_uid (DBusUserInfo     *info,
+                                      dbus_uid_t        uid,
+                                      DBusError        *error);
+void        _dbus_user_info_free     (DBusUserInfo     *info);
+
+dbus_bool_t _dbus_group_info_fill     (DBusGroupInfo    *info,
+                                       const DBusString *groupname,
+                                       DBusError        *error);
+dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo    *info,
+                                       dbus_gid_t        gid,
+                                       DBusError        *error);
+void        _dbus_group_info_free     (DBusGroupInfo    *info);
+
+
+dbus_pid_t    _dbus_getpid (void);
+dbus_uid_t    _dbus_getuid (void);
+dbus_gid_t    _dbus_getgid (void);
+
+dbus_bool_t _dbus_parse_uid (const DBusString  *uid_str,
+                             dbus_uid_t        *uid);
+
 /** @} */
 
 DBUS_END_DECLS
index 5ffc90d..9963432 100644 (file)
@@ -243,20 +243,47 @@ _dbus_write_pid_file (const DBusString *filename,
   return TRUE;
 }
 
+/**
+ * Verify that after the fork we can successfully change to this user.
+ *
+ * @param user the username given in the daemon configuration
+ * @returns #TRUE if username is valid
+ */
+dbus_bool_t
+_dbus_verify_daemon_user (const char *user)
+{
+  DBusString u;
+
+  _dbus_string_init_const (&u, user);
+
+  return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
+}
 
 /**
  * Changes the user and group the bus is running as.
  *
- * @param uid the new user ID
- * @param gid the new group ID
+ * @param user the user to become
  * @param error return location for errors
  * @returns #FALSE on failure
  */
 dbus_bool_t
-_dbus_change_identity  (dbus_uid_t     uid,
-                        dbus_gid_t     gid,
-                        DBusError     *error)
+_dbus_change_to_daemon_user  (const char    *user,
+                              DBusError     *error)
 {
+  dbus_uid_t uid;
+  dbus_gid_t gid;
+  DBusString u;
+
+  _dbus_string_init_const (&u, user);
+  
+  if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "User '%s' does not appear to exist?",
+                      user);
+      return FALSE;
+    }
+  
   /* setgroups() only works if we are a privileged process,
    * so we don't return error on failure; the only possible
    * failure is that we don't have perms to do it.
index 3b9c841..0f26ce7 100644 (file)
@@ -42,7 +42,6 @@
 #include "dbus-protocol.h"
 #include "dbus-hash.h"
 #include "dbus-sockets-win.h"
-#include "dbus-userdb.h"
 #include "dbus-list.h"
 
 #include <windows.h>
index 8ccdb3f..cf689bc 100644 (file)
@@ -78,7 +78,7 @@ _dbus_abort (void)
   if (s && *s)
     {
       /* don't use _dbus_warn here since it can _dbus_abort() */
-      fprintf (stderr, "  Process %lu sleeping for gdb attach\n", (unsigned long) _dbus_getpid());
+      fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
       _dbus_sleep_milliseconds (1000 * 180);
     }
   
@@ -236,7 +236,8 @@ _dbus_pipe_invalidate (DBusPipe *pipe)
 }
 
 /**
- * split pathes into a list of char strings 
+ * Split paths into a list of char strings
+ * 
  * @param dirs string with pathes 
  * @param suffix string concated to each path in dirs
  * @param dir_list contains a list of splitted pathes
@@ -251,7 +252,7 @@ _dbus_split_paths_and_append (DBusString *dirs,
    int i;
    int len;
    char *cpath;
-   const DBusString file_suffix;
+   DBusString file_suffix;
 
    start = 0;
    i = 0;
@@ -770,68 +771,6 @@ _dbus_string_parse_double (const DBusString *str,
  * @{
  */
 
-/**
- * Frees the members of info
- * (but not info itself)
- * @param info the user info struct
- */
-void
-_dbus_user_info_free (DBusUserInfo *info)
-{
-  dbus_free (info->group_ids);
-  dbus_free (info->username);
-  dbus_free (info->homedir);
-}
-
-/**
- * Frees the members of info (but not info itself).
- *
- * @param info the group info
- */
-void
-_dbus_group_info_free (DBusGroupInfo    *info)
-{
-  dbus_free (info->groupname);
-}
-
-/**
- * Sets fields in DBusCredentials to DBUS_PID_UNSET,
- * DBUS_UID_UNSET, DBUS_GID_UNSET.
- *
- * @param credentials the credentials object to fill in
- */
-void
-_dbus_credentials_clear (DBusCredentials *credentials)
-{
-  credentials->pid = DBUS_PID_UNSET;
-  credentials->uid = DBUS_UID_UNSET;
-  credentials->gid = DBUS_GID_UNSET;
-}
-
-/**
- * Checks whether the provided_credentials are allowed to log in
- * as the expected_credentials.
- *
- * @param expected_credentials credentials we're trying to log in as
- * @param provided_credentials credentials we have
- * @returns #TRUE if we can log in
- */
-dbus_bool_t
-_dbus_credentials_match (const DBusCredentials *expected_credentials,
-                         const DBusCredentials *provided_credentials)
-{
-  if (provided_credentials->uid == DBUS_UID_UNSET)
-    return FALSE;
-  else if (expected_credentials->uid == DBUS_UID_UNSET)
-    return FALSE;
-  else if (provided_credentials->uid == 0)
-    return TRUE;
-  else if (provided_credentials->uid == expected_credentials->uid)
-    return TRUE;
-  else
-    return FALSE;
-}
-
 void
 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
                                           int   n_bytes)
@@ -929,46 +868,6 @@ _dbus_generate_random_ascii (DBusString *str,
 }
 
 /**
- * Gets a UID from a UID string.
- *
- * @param uid_str the UID in string form
- * @param uid UID to fill in
- * @returns #TRUE if successfully filled in UID
- */
-dbus_bool_t
-_dbus_parse_uid (const DBusString      *uid_str,
-                 dbus_uid_t            *uid)
-{
-  int end;
-  long val;
-  
-  if (_dbus_string_get_length (uid_str) == 0)
-    {
-      _dbus_verbose ("UID string was zero length\n");
-      return FALSE;
-    }
-
-  val = -1;
-  end = 0;
-  if (!_dbus_string_parse_int (uid_str, 0, &val,
-                               &end))
-    {
-      _dbus_verbose ("could not parse string as a UID\n");
-      return FALSE;
-    }
-  
-  if (end != _dbus_string_get_length (uid_str))
-    {
-      _dbus_verbose ("string contained trailing stuff after UID\n");
-      return FALSE;
-    }
-
-  *uid = val;
-
-  return TRUE;
-}
-
-/**
  * Converts a UNIX or Windows errno
  * into a #DBusError name.
  *
index c89d35f..f83c17c 100644 (file)
@@ -55,6 +55,9 @@ typedef struct DBusString DBusString;
 /** An opaque list type */
 typedef struct DBusList DBusList;
 
+/** Object that contains a list of credentials such as UNIX or Windows user ID */
+typedef struct DBusCredentials DBusCredentials;
+
 /**
  * @addtogroup DBusSysdeps
  *
@@ -151,79 +154,25 @@ int _dbus_listen_tcp_socket   (const char     *host,
                                DBusError      *error);
 int _dbus_accept              (int             listen_fd);
 
-/**
- * Struct representing socket credentials
- */
-typedef struct
-{
-  dbus_pid_t pid; /**< process ID or DBUS_PID_UNSET */
-  dbus_uid_t uid; /**< user ID or DBUS_UID_UNSET */
-  dbus_gid_t gid; /**< group ID or DBUS_GID_UNSET */
-} DBusCredentials;
-
-/* FIXME these read/send credentials should get moved to sysdeps-unix.h,
- * or renamed to reflect what they mean cross-platform
- */
-dbus_bool_t _dbus_read_credentials_unix_socket (int              client_fd,
-                                                DBusCredentials *credentials,
-                                                DBusError       *error);
-dbus_bool_t _dbus_send_credentials_unix_socket (int              server_fd,
-                                                DBusError       *error);
-
-
-void        _dbus_credentials_clear                (DBusCredentials       *credentials);
-void        _dbus_credentials_from_current_process (DBusCredentials       *credentials);
-dbus_bool_t _dbus_credentials_match                (const DBusCredentials *expected_credentials,
-                                                    const DBusCredentials *provided_credentials);
-
-
-/** Information about a UNIX user */
-typedef struct DBusUserInfo  DBusUserInfo;
-/** Information about a UNIX group */
-typedef struct DBusGroupInfo DBusGroupInfo;
-
-/**
- * Information about a UNIX user
- */
-struct DBusUserInfo
-{
-  dbus_uid_t  uid;            /**< UID */
-  dbus_gid_t  primary_gid;    /**< GID */
-  dbus_gid_t *group_ids;      /**< Groups IDs, *including* above primary group */
-  int         n_group_ids;    /**< Size of group IDs array */
-  char       *username;       /**< Username */
-  char       *homedir;        /**< Home directory */
-};
-
-/**
- * Information about a UNIX group
- */
-struct DBusGroupInfo
-{
-  dbus_gid_t  gid;            /**< GID */
-  char       *groupname;      /**< Group name */
-};
 
-dbus_bool_t _dbus_user_info_fill     (DBusUserInfo     *info,
-                                      const DBusString *username,
-                                      DBusError        *error);
-dbus_bool_t _dbus_user_info_fill_uid (DBusUserInfo     *info,
-                                      dbus_uid_t        uid,
-                                      DBusError        *error);
-void        _dbus_user_info_free     (DBusUserInfo     *info);
+dbus_bool_t _dbus_read_credentials_socket (int               client_fd,
+                                           DBusCredentials  *credentials,
+                                           DBusError        *error);
+dbus_bool_t _dbus_send_credentials_socket (int              server_fd,
+                                           DBusError       *error);
 
-dbus_bool_t _dbus_group_info_fill     (DBusGroupInfo    *info,
-                                       const DBusString *groupname,
-                                       DBusError        *error);
-dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo    *info,
-                                       dbus_gid_t        gid,
-                                       DBusError        *error);
-void        _dbus_group_info_free     (DBusGroupInfo    *info);
+dbus_bool_t _dbus_credentials_add_from_username        (DBusCredentials  *credentials,
+                                                        const DBusString *username);
+dbus_bool_t _dbus_credentials_add_from_current_process (DBusCredentials  *credentials);
+dbus_bool_t _dbus_credentials_parse_and_add_desired    (DBusCredentials  *credentials,
+                                                        const DBusString *desired_identity);
 
+dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
+dbus_bool_t _dbus_append_desired_identity       (DBusString *str);
 
-unsigned long _dbus_getpid (void);
-dbus_uid_t    _dbus_getuid (void);
-dbus_gid_t    _dbus_getgid (void);
+dbus_bool_t _dbus_homedir_from_current_process  (const DBusString **homedir);
+dbus_bool_t _dbus_homedir_from_username         (const DBusString  *username,
+                                                 DBusString        *homedir);
 
 /** Opaque type representing an atomically-modifiable integer
  * that can be used from multiple threads.
@@ -398,9 +347,9 @@ dbus_bool_t _dbus_become_daemon   (const DBusString *pidfile,
 dbus_bool_t _dbus_write_pid_file  (const DBusString *filename,
                                    unsigned long     pid,
                                    DBusError        *error);
-dbus_bool_t _dbus_change_identity (unsigned long     uid,
-                                   unsigned long     gid,
-                                   DBusError        *error);
+dbus_bool_t _dbus_verify_daemon_user    (const char *user);
+dbus_bool_t _dbus_change_to_daemon_user (const char *user,
+                                         DBusError  *error);
 
 /** A UNIX signal handler */
 typedef void (* DBusSignalHandler) (int sig);
@@ -446,9 +395,6 @@ dbus_bool_t _dbus_user_at_console (const char *username,
       _DBUS_BYTE_OF_PRIMITIVE (a, 6) == _DBUS_BYTE_OF_PRIMITIVE (b, 6) &&       \
       _DBUS_BYTE_OF_PRIMITIVE (a, 7) == _DBUS_BYTE_OF_PRIMITIVE (b, 7))
 
-dbus_bool_t _dbus_parse_uid (const DBusString  *uid_str,
-                             dbus_uid_t        *uid);
-
 dbus_bool_t _dbus_get_autolaunch_address (DBusString *address, 
                                          DBusError *error);
 
@@ -472,6 +418,8 @@ dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs,
                                           const char *suffix, 
                                           DBusList **dir_list);
 
+unsigned long _dbus_pid_for_log (void);
+
 /** @} */
 
 DBUS_END_DECLS
index 0754462..a1df360 100644 (file)
@@ -160,6 +160,8 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *speci
   run_data_test ("spawn", specific_test, _dbus_spawn_test, test_data_dir);
 #endif
   
+  run_data_test ("credentials", specific_test, _dbus_credentials_test, test_data_dir);
+  
   run_data_test ("userdb", specific_test, _dbus_userdb_test, test_data_dir);
   
   run_test ("keyring", specific_test, _dbus_keyring_test);
index e7c55d9..8619ae7 100644 (file)
@@ -54,6 +54,7 @@ dbus_bool_t _dbus_userdb_test            (const char *test_data_dir);
 dbus_bool_t _dbus_memory_test            (void);
 dbus_bool_t _dbus_object_tree_test       (void);
 dbus_bool_t _dbus_pending_call_test      (const char *test_data_dir);
+dbus_bool_t _dbus_credentials_test       (const char *test_data_dir);
 
 void        dbus_internal_do_not_use_run_tests         (const char          *test_data_dir,
                                                        const char          *specific_test);
index 2b3a6c6..bfdff0e 100644 (file)
@@ -89,7 +89,7 @@ struct DBusTransport
 
   DBusAuth *auth;                             /**< Authentication conversation */
 
-  DBusCredentials credentials;                /**< Credentials of other end */  
+  DBusCredentials *credentials;               /**< Credentials of other end read from the socket */  
 
   long max_live_messages_size;                /**< Max total size of received messages. */
 
index 76a6fcf..3f8c94d 100644 (file)
@@ -26,6 +26,7 @@
 #include "dbus-transport-socket.h"
 #include "dbus-transport-protected.h"
 #include "dbus-watch.h"
+#include "dbus-credentials.h"
 
 
 /**
@@ -332,7 +333,8 @@ write_data_from_auth (DBusTransport *transport)
   return FALSE;
 }
 
-static void
+/* FALSE on OOM */
+static dbus_bool_t
 exchange_credentials (DBusTransport *transport,
                       dbus_bool_t    do_reading,
                       dbus_bool_t    do_writing)
@@ -346,8 +348,8 @@ exchange_credentials (DBusTransport *transport,
   dbus_error_init (&error);
   if (do_writing && transport->send_credentials_pending)
     {
-      if (_dbus_send_credentials_unix_socket (socket_transport->fd,
-                                              &error))
+      if (_dbus_send_credentials_socket (socket_transport->fd,
+                                         &error))
         {
           transport->send_credentials_pending = FALSE;
         }
@@ -361,9 +363,10 @@ exchange_credentials (DBusTransport *transport,
   
   if (do_reading && transport->receive_credentials_pending)
     {
-      if (_dbus_read_credentials_unix_socket (socket_transport->fd,
-                                              &transport->credentials,
-                                              &error))
+      /* FIXME this can fail due to IO error _or_ OOM, broken */
+      if (_dbus_read_credentials_socket (socket_transport->fd,
+                                         transport->credentials,
+                                         &error))
         {
           transport->receive_credentials_pending = FALSE;
         }
@@ -378,9 +381,12 @@ exchange_credentials (DBusTransport *transport,
   if (!(transport->send_credentials_pending ||
         transport->receive_credentials_pending))
     {
-      _dbus_auth_set_credentials (transport->auth,
-                                  &transport->credentials);
+      if (!_dbus_auth_set_credentials (transport->auth,
+                                       transport->credentials))
+        return FALSE;
     }
+
+  return TRUE;
 }
 
 static dbus_bool_t
@@ -412,7 +418,12 @@ do_authentication (DBusTransport *transport,
   while (!_dbus_transport_get_is_authenticated (transport) &&
          _dbus_transport_get_is_connected (transport))
     {      
-      exchange_credentials (transport, do_reading, do_writing);
+      if (!exchange_credentials (transport, do_reading, do_writing))
+        {
+          /* OOM */
+          oom = TRUE;
+          goto out;
+        }
       
       if (transport->send_credentials_pending ||
           transport->receive_credentials_pending)
@@ -1161,7 +1172,7 @@ _dbus_transport_new_for_socket (int               fd,
                                                 NULL, NULL, NULL);
   if (socket_transport->read_watch == NULL)
     goto failed_3;
-  
+
   if (!_dbus_transport_init_base (&socket_transport->base,
                                   &socket_vtable,
                                   server_guid, address))
index d8d3bb2..e922eb5 100644 (file)
@@ -28,6 +28,7 @@
 #include "dbus-watch.h"
 #include "dbus-auth.h"
 #include "dbus-address.h"
+#include "dbus-credentials.h"
 #ifdef DBUS_BUILD_TESTS
 #include "dbus-server-debug-pipe.h"
 #endif
@@ -98,6 +99,7 @@ _dbus_transport_init_base (DBusTransport             *transport,
   DBusAuth *auth;
   DBusCounter *counter;
   char *address_copy;
+  DBusCredentials *creds;
   
   loader = _dbus_message_loader_new ();
   if (loader == NULL)
@@ -120,6 +122,15 @@ _dbus_transport_init_base (DBusTransport             *transport,
       _dbus_message_loader_unref (loader);
       return FALSE;
     }  
+
+  creds = _dbus_credentials_new ();
+  if (creds == NULL)
+    {
+      _dbus_counter_unref (counter);
+      _dbus_auth_unref (auth);
+      _dbus_message_loader_unref (loader);
+      return FALSE;
+    }
   
   if (server_guid)
     {
@@ -132,6 +143,7 @@ _dbus_transport_init_base (DBusTransport             *transport,
 
       if (!_dbus_string_copy_data (address, &address_copy))
         {
+          _dbus_credentials_unref (creds);
           _dbus_counter_unref (counter);
           _dbus_auth_unref (auth);
           _dbus_message_loader_unref (loader);
@@ -161,11 +173,10 @@ _dbus_transport_init_base (DBusTransport             *transport,
    * but doesn't impose too much of a limitation.
    */
   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
-  
-  transport->credentials.pid = -1;
-  transport->credentials.uid = -1;
-  transport->credentials.gid = -1;
 
+  /* credentials read from socket if any */
+  transport->credentials = creds;
+  
   _dbus_counter_set_notify (transport->live_messages_size,
                             transport->max_live_messages_size,
                             live_messages_size_notify,
@@ -199,6 +210,8 @@ _dbus_transport_finalize_base (DBusTransport *transport)
   _dbus_counter_unref (transport->live_messages_size);
   dbus_free (transport->address);
   dbus_free (transport->expected_guid);
+  if (transport->credentials)
+    _dbus_credentials_unref (transport->credentials);
 }
 
 
@@ -490,16 +503,7 @@ _dbus_transport_get_is_connected (DBusTransport *transport)
  */
 dbus_bool_t
 _dbus_transport_get_is_authenticated (DBusTransport *transport)
-{
-  /* We don't want to run unix_user_function on Windows, but it
-   * can exist, which allows application code to just unconditionally
-   * set it and have it only be invoked when appropriate.
-   */
-  dbus_bool_t on_windows = FALSE;
-#ifdef DBUS_WIN
-  on_windows = TRUE;
-#endif
-  
+{  
   if (transport->authenticated)
     return TRUE;
   else
@@ -567,28 +571,36 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
       
       if (maybe_authenticated && transport->is_server)
         {
-          DBusCredentials auth_identity;
+          DBusCredentials *auth_identity;
 
-          _dbus_auth_get_identity (transport->auth, &auth_identity);
+          auth_identity = _dbus_auth_get_identity (transport->auth);
+          _dbus_assert (auth_identity != NULL);
 
-          if (transport->unix_user_function != NULL && !on_windows)
+          /* If we have a UNIX user and a unix user function, delegate
+           * deciding whether auth credentials are good enough to the app;
+           * otherwise, use our default decision process.
+           */
+          if (transport->unix_user_function != NULL &&
+              _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
             {
               dbus_bool_t allow;
               DBusConnection *connection;
               DBusAllowUnixUserFunction unix_user_function;
               void *unix_user_data;
+              dbus_uid_t uid;
               
               /* Dropping the lock here probably isn't that safe. */
 
               connection = transport->connection;
               unix_user_function = transport->unix_user_function;
               unix_user_data = transport->unix_user_data;
-
+              uid = _dbus_credentials_get_unix_uid (auth_identity),
+              
               _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
               _dbus_connection_unlock (connection);
 
               allow = (* unix_user_function) (connection,
-                                              auth_identity.uid,
+                                              uid,
                                               unix_user_data);
               
               _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
@@ -596,13 +608,13 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
 
               if (allow)
                 {
-                  _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", auth_identity.uid);
+                  _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
                 }
               else
                 {
                   _dbus_verbose ("Client UID "DBUS_UID_FORMAT
                                  " was rejected, disconnecting\n",
-                                 auth_identity.uid);
+                                 _dbus_credentials_get_unix_uid (auth_identity));
                   _dbus_transport_disconnect (transport);
                   _dbus_connection_unref_unlocked (connection);
                   return FALSE;
@@ -610,25 +622,40 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
             }
           else
             {
-              DBusCredentials our_identity;
+              DBusCredentials *our_identity;
+
+              /* By default, connection is allowed if the client is
+               * 1) root or 2) has the same UID as us
+               */
               
-              _dbus_credentials_from_current_process (&our_identity);
+              our_identity = _dbus_credentials_new_from_current_process ();
+              if (our_identity == NULL)
+                {
+                  /* OOM */
+                  _dbus_connection_unref_unlocked (transport->connection);
+                  return FALSE;
+                }
               
-              if (!_dbus_credentials_match (&our_identity,
-                                            &auth_identity))
+              if (_dbus_credentials_get_unix_uid (auth_identity) == 0 ||
+                  !_dbus_credentials_same_user (our_identity,
+                                                auth_identity))
                 {
+                  /* FIXME the verbose spam here is unix-specific */
                   _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
                                  " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
-                                 auth_identity.uid, our_identity.uid);
+                                 _dbus_credentials_get_unix_uid(our_identity),
+                                 _dbus_credentials_get_unix_uid(our_identity));
                   _dbus_transport_disconnect (transport);
                   _dbus_connection_unref_unlocked (transport->connection);
                   return FALSE;
                 }
               else
                 {
+                  /* FIXME the verbose spam here is unix-specific */                  
                   _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
                                  " matching our UID "DBUS_UID_FORMAT"\n",
-                                 auth_identity.uid, our_identity.uid);
+                                 _dbus_credentials_get_unix_uid(auth_identity),
+                                 _dbus_credentials_get_unix_uid(our_identity));
                 }
             }
         }
@@ -1028,7 +1055,7 @@ dbus_bool_t
 _dbus_transport_get_unix_user (DBusTransport *transport,
                                unsigned long *uid)
 {
-  DBusCredentials auth_identity;
+  DBusCredentials *auth_identity;
 
   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
                            * case of bugs in the caller. Caller should
@@ -1038,11 +1065,12 @@ _dbus_transport_get_unix_user (DBusTransport *transport,
   if (!transport->authenticated)
     return FALSE;
   
-  _dbus_auth_get_identity (transport->auth, &auth_identity);
+  auth_identity = _dbus_auth_get_identity (transport->auth);
 
-  if (auth_identity.uid != DBUS_UID_UNSET)
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_UNIX_USER_ID))
     {
-      *uid = auth_identity.uid;
+      *uid = _dbus_credentials_get_unix_uid (auth_identity);
       return TRUE;
     }
   else
@@ -1060,7 +1088,7 @@ dbus_bool_t
 _dbus_transport_get_unix_process_id (DBusTransport *transport,
                                     unsigned long *pid)
 {
-  DBusCredentials auth_identity;
+  DBusCredentials *auth_identity;
 
   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
                          * but we set it to a safe number, INT_MAX,
@@ -1070,11 +1098,12 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport,
   if (!transport->authenticated)
     return FALSE;
   
-  _dbus_auth_get_identity (transport->auth, &auth_identity);
+  auth_identity = _dbus_auth_get_identity (transport->auth);
 
-  if (auth_identity.pid != DBUS_PID_UNSET)
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
     {
-      *pid = auth_identity.pid;
+      *pid = _dbus_credentials_get_unix_pid (auth_identity);
       return TRUE;
     }
   else
index 7b12de5..6e1653e 100644 (file)
@@ -103,20 +103,33 @@ _dbus_is_console_user (dbus_uid_t uid,
   return result;
 }
 
+/**
+ * Gets user ID given username
+ *
+ * @param username the username
+ * @param uid return location for UID
+ * @returns #TRUE if username existed and we got the UID
+ */
+dbus_bool_t
+_dbus_get_user_id (const DBusString  *username,
+                   dbus_uid_t        *uid)
+{
+  return _dbus_get_user_id_and_primary_group (username, uid, NULL);
+}
 
 /**
- * Gets the credentials corresponding to the given UID.
+ * Gets group ID given groupname
  *
- * @param uid the UID
- * @param credentials credentials to fill in
- * @returns #TRUE if the UID existed and we got some credentials
+ * @param groupname the groupname
+ * @param gid return location for GID
+ * @returns #TRUE if group name existed and we got the GID
  */
 dbus_bool_t
-_dbus_credentials_from_uid (dbus_uid_t        uid,
-                            DBusCredentials  *credentials)
+_dbus_get_group_id (const DBusString  *groupname,
+                    dbus_gid_t        *gid)
 {
   DBusUserDatabase *db;
-  const DBusUserInfo *info;
+  const DBusGroupInfo *info;
   _dbus_user_database_lock_system ();
 
   db = _dbus_user_database_get_system ();
@@ -126,61 +139,34 @@ _dbus_credentials_from_uid (dbus_uid_t        uid,
       return FALSE;
     }
 
-  if (!_dbus_user_database_get_uid (db, uid,
-                                    &info, NULL))
+  if (!_dbus_user_database_get_groupname (db, groupname,
+                                          &info, NULL))
     {
       _dbus_user_database_unlock_system ();
       return FALSE;
     }
 
-  _dbus_assert (info->uid == uid);
-  
-  credentials->pid = DBUS_PID_UNSET;
-  credentials->uid = info->uid;
-  credentials->gid = info->primary_gid;
+  *gid = info->gid;
   
   _dbus_user_database_unlock_system ();
   return TRUE;
 }
 
-
 /**
- * Gets user ID given username
+ * Gets user ID and primary group given username
  *
  * @param username the username
- * @param uid return location for UID
- * @returns #TRUE if username existed and we got the UID
+ * @param uid_p return location for UID
+ * @param gid_p return location for GID
+ * @returns #TRUE if username existed and we got the UID and GID
  */
 dbus_bool_t
-_dbus_get_user_id (const DBusString  *username,
-                   dbus_uid_t        *uid)
-{
-  DBusCredentials creds;
-
-  if (!_dbus_credentials_from_username (username, &creds))
-    return FALSE;
-
-  if (creds.uid == DBUS_UID_UNSET)
-    return FALSE;
-
-  *uid = creds.uid;
-
-  return TRUE;
-}
-
-/**
- * Gets group ID given groupname
- *
- * @param groupname the groupname
- * @param gid return location for GID
- * @returns #TRUE if group name existed and we got the GID
- */
-dbus_bool_t
-_dbus_get_group_id (const DBusString  *groupname,
-                    dbus_gid_t        *gid)
+_dbus_get_user_id_and_primary_group (const DBusString  *username,
+                                     dbus_uid_t        *uid_p,
+                                     dbus_gid_t        *gid_p)
 {
   DBusUserDatabase *db;
-  const DBusGroupInfo *info;
+  const DBusUserInfo *info;
   _dbus_user_database_lock_system ();
 
   db = _dbus_user_database_get_system ();
@@ -190,14 +176,17 @@ _dbus_get_group_id (const DBusString  *groupname,
       return FALSE;
     }
 
-  if (!_dbus_user_database_get_groupname (db, groupname,
-                                          &info, NULL))
+  if (!_dbus_user_database_get_username (db, username,
+                                         &info, NULL))
     {
       _dbus_user_database_unlock_system ();
       return FALSE;
     }
 
-  *gid = info->gid;
+  if (uid_p)
+    *uid_p = info->uid;
+  if (gid_p)
+    *gid_p = info->primary_gid;
   
   _dbus_user_database_unlock_system ();
   return TRUE;
@@ -434,7 +423,6 @@ _dbus_userdb_test (const char *test_data_dir)
   if (!_dbus_get_user_id (username, &uid))
     _dbus_assert_not_reached ("didn't get uid");
 
-
   if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids))
     _dbus_assert_not_reached ("didn't get groups");
 
index 2aa395d..c3ae8ef 100644 (file)
@@ -26,6 +26,7 @@
 #include "dbus-test.h"
 #include "dbus-internals.h"
 #include "dbus-protocol.h"
+#include "dbus-credentials.h"
 #include <string.h>
 
 /**
@@ -66,6 +67,30 @@ _dbus_group_info_free_allocated (DBusGroupInfo *info)
 }
 
 /**
+ * Frees the members of info
+ * (but not info itself)
+ * @param info the user info struct
+ */
+void
+_dbus_user_info_free (DBusUserInfo *info)
+{
+  dbus_free (info->group_ids);
+  dbus_free (info->username);
+  dbus_free (info->homedir);
+}
+
+/**
+ * Frees the members of info (but not info itself).
+ *
+ * @param info the group info
+ */
+void
+_dbus_group_info_free (DBusGroupInfo    *info)
+{
+  dbus_free (info->groupname);
+}
+
+/**
  * Checks if a given string is actually a number 
  * and converts it if it is 
  *
@@ -412,18 +437,19 @@ _dbus_homedir_from_username (const DBusString *username,
 }
 
 /**
- * Gets the credentials corresponding to the given username.
+ * Adds the credentials corresponding to the given username.
  *
+ * @param credentials credentials to fill in 
  * @param username the username
- * @param credentials credentials to fill in
  * @returns #TRUE if the username existed and we got some credentials
  */
 dbus_bool_t
-_dbus_credentials_from_username (const DBusString *username,
-                                 DBusCredentials  *credentials)
+_dbus_credentials_add_from_username (DBusCredentials  *credentials,
+                                     const DBusString *username)
 {
   DBusUserDatabase *db;
   const DBusUserInfo *info;
+
   _dbus_user_database_lock_system ();
 
   db = _dbus_user_database_get_system ();
@@ -440,9 +466,11 @@ _dbus_credentials_from_username (const DBusString *username,
       return FALSE;
     }
 
-  credentials->pid = DBUS_PID_UNSET;
-  credentials->uid = info->uid;
-  credentials->gid = info->primary_gid;
+  if (!_dbus_credentials_add_unix_uid(credentials, info->uid))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
   
   _dbus_user_database_unlock_system ();
   return TRUE;
index 9e27854..4fae6f0 100644 (file)
 #ifndef DBUS_USERDB_H
 #define DBUS_USERDB_H
 
-#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-sysdeps-unix.h>
+
+#ifdef DBUS_WIN
+#error "Don't include this on Windows"
+#endif
 
 DBUS_BEGIN_DECLS
 
@@ -86,16 +90,13 @@ void              _dbus_user_database_lock_system   (void);
 void              _dbus_user_database_unlock_system (void);
 void              _dbus_user_database_flush_system  (void);
 
-dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
-dbus_bool_t _dbus_homedir_from_current_process  (const DBusString **homedir);
-dbus_bool_t _dbus_homedir_from_username         (const DBusString  *username,
-                                                 DBusString        *homedir);
 dbus_bool_t _dbus_get_user_id                   (const DBusString  *username,
                                                  dbus_uid_t        *uid);
 dbus_bool_t _dbus_get_group_id                  (const DBusString  *group_name,
                                                  dbus_gid_t        *gid);
-dbus_bool_t _dbus_credentials_from_username     (const DBusString  *username,
-                                                 DBusCredentials   *credentials);
+dbus_bool_t _dbus_get_user_id_and_primary_group (const DBusString  *username,
+                                                 dbus_uid_t        *uid_p,
+                                                 dbus_gid_t        *gid_p);
 dbus_bool_t _dbus_credentials_from_uid          (dbus_uid_t         user_id,
                                                  DBusCredentials   *credentials);
 dbus_bool_t _dbus_groups_from_uid              (dbus_uid_t            uid,
index ddb489d..b3c9773 100644 (file)
@@ -88,6 +88,7 @@ TESTDIRS=                                     \
        data/sha-1                              \
        data/valid-config-files                 \
        data/valid-config-files/basic.d         \
+       data/valid-config-files/session.d       \
        data/valid-config-files/system.d        \
        data/valid-service-files                \
        data/invalid-config-files               \