[system-tools-backends-clone] New users D-Bus protocol



commit 37125b5f3ede949e038fccdd2a6fe4022503fc86
Author: Milan Bouchet-Valat <nalimilan club fr>
Date:   Sun Dec 27 13:33:16 2009 +0100

    New users D-Bus protocol
    
    Going through UsersConfig to commit changes to users is not the best solution since this can affect users that were not edited in case of a bug on the client's side. Thus, remove UsersConfig::set() in favor of new UserConfig::add(), del() and set(), which take a generic user structure. Allow these functions in dispatcher.c, but always check for "set" PolicyKit authorization (making distinction between "add", "set", "del" makes no sense at this point).
    
    Add some fields to the user struct to be used later: encrypted home, locale and location, plus password and home directory flags. GID is now an unsigned 32 bits integer, with its max value meaning no group.
    
    Rename D-Bus interfaces to UserConfig2 and UsersConfig2, since we break compatibility. Update DBus config file to reflect that.

 UserConfig.pm                            |   36 ++++++--
 Users/Users.pm                           |  153 +++++++++++++++---------------
 UsersConfig.pm                           |   35 ++++---
 dispatcher/dispatcher.c                  |   25 +++---
 org.freedesktop.SystemToolsBackends.conf |   12 +-
 5 files changed, 143 insertions(+), 118 deletions(-)
---
diff --git a/UserConfig.pm b/UserConfig.pm
index 79a0056..0a4b7de 100644
--- a/UserConfig.pm
+++ b/UserConfig.pm
@@ -4,7 +4,8 @@
 #
 # Copyright (C) 2007 Carlos Garnacho
 #
-# Authors: Carlos Garnacho Parro  <carlosg gnome org>
+# Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+#          Milan Bouchet-Valat <nalimilan club fr>.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Library General Public License as published
@@ -26,9 +27,14 @@ use base qw(StbObject);
 use Net::DBus::Exporter ($Utils::Backend::DBUS_PREFIX);
 use Users::Users;
 
-my $OBJECT_NAME = "UserConfig";
+my $OBJECT_NAME = "UserConfig2";
 my $OBJECT_PATH = "$Utils::Backend::DBUS_PATH/$OBJECT_NAME";
-my $format = [ "uint32", "string", [ "array", "string" ]];
+
+# base user struct, also used in UsersConfig
+# variables: login, password, UID, main group GID, GECOS fields, home, shell,
+# password flags, encrypted home, home dir flags, locale, location
+our $USER_FORMAT = [ "struct", "string", "string", "uint32", "uint32", [ "array", "string" ], "string", "string",
+                     "int32", "bool", "int32", "string", "string" ];
 
 sub new
 {
@@ -40,14 +46,16 @@ sub new
   return $self;
 }
 
-dbus_method ("get", [ "uint32" ], $format);
-dbus_method ("set", $format, []);
+dbus_method ("get", [ "string" ], [ $USER_FORMAT ]);
+dbus_method ("set", [ $USER_FORMAT ], []);
+dbus_method ("add", [ $USER_FORMAT ], []);
+dbus_method ("del", [ $USER_FORMAT ], []);
 
 sub get
 {
-  my ($self, $uid) = @_;
+  my ($self, $login) = @_;
 
-  return Users::Users::get_user ($uid);
+  return Users::Users::get_user ($login);
 }
 
 sub set
@@ -57,6 +65,20 @@ sub set
   Users::Users::set_user (@config);
 }
 
+sub add
+{
+  my ($self, @config) = @_;
+
+  Users::Users::add_user (@config);
+}
+
+sub del
+{
+  my ($self, @config) = @_;
+
+  Users::Users::del_user (@config);
+}
+
 sub getFiles
 {
   my ($self) = @_;
diff --git a/Users/Users.pm b/Users/Users.pm
index 41bb5cc..2ee6ef7 100644
--- a/Users/Users.pm
+++ b/Users/Users.pm
@@ -6,7 +6,8 @@
 # Authors: Hans Petter Jansson <hpj ximian com>,
 #          Arturo Espinosa <arturo ximian com>,
 #          Tambet Ingo <tambet ximian com>.
-#          Grzegorz Golawski <grzegol pld-linux org> (PLD Support)
+#          Grzegorz Golawski <grzegol pld-linux org> (PLD Support),
+#          Milan Bouchet-Valat <nalimilan club fr>.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Library General Public License as published
@@ -74,13 +75,18 @@ $cmd_pw       = &Utils::File::locate_tool ("pw");
 
 # enum like for verbose group array positions
 my $i = 0;
-my $LOGIN   = $i++;
-my $PASSWD  = $i++;
-my $UID     = $i++;
-my $GID     = $i++;
-my $COMMENT = $i++;
-my $HOME    = $i++;
-my $SHELL   = $i++;
+my $LOGIN         = $i++;
+my $PASSWD        = $i++;
+my $UID           = $i++;
+my $GID           = $i++;
+my $COMMENT       = $i++;
+my $HOME          = $i++;
+my $SHELL         = $i++;
+my $PASSWD_STATUS = $i++;
+my $ENC_HOME      = $i++;
+my $HOME_FLAGS    = $i++;
+my $LOCALE        = $i++;
+my $LOCATION      = $i++;
 
 %login_defs_prop_map = ();
 %profiles_prop_map = ();
@@ -397,6 +403,16 @@ sub get
     $line[$COMMENT] = [ comment];
 
     $users_hash{$login} = [ line];
+
+    # max value for an unsigned 32 bits integer means no main group
+    $users_hash{$login}[$GID] = 0xFFFFFFFF if (!$users_hash{$login}[$GID]);
+
+    # TODO: read actual values
+    $users_hash{$login}[$PASSWD_STATUS] = 0;
+    $users_hash{$login}[$ENC_HOME] = 0;
+    $users_hash{$login}[$HOME_FLAGS] = 0;
+    $users_hash{$login}[$LOCALE] = "";
+    $users_hash{$login}[$LOCATION] = "";
   }
 
   &Utils::File::close_file ($ifh);
@@ -438,23 +454,43 @@ sub get
 
 sub del_user
 {
-	my ($user) = @_;
-  my (@command);
+  my ($user) = @_;
+  my (@command, $remove_home);
+  
+  $remove_home = $$user[$HOME_FLAGS] & 1;
 	
   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
   {
-    @command = ($cmd_pw, "userdel", "-n", $$user[$LOGIN]);
+    if ($remove_home)
+      {
+        @command = ($cmd_pw, "userdel", "-r", "-n", $$user[$LOGIN]);
+      }
+    else
+      {
+        @command = ($cmd_pw, "userdel", "-n", $$user[$LOGIN]);
+      }
   }
-  else
-  {
-    if ($cmd_deluser)
+  elsif ($cmd_deluser) # use deluser (preferred method)
     {
-      @command = ($cmd_deluser, $$user[$LOGIN]);
+      if ($remove_home)
+      {
+        @command = ($cmd_deluser, "--remove-home", $$user[$LOGIN]);
+      }
+      else
+      {
+        @command = ($cmd_deluser, $$user[$LOGIN]);
+      }
     }
-    else
+  else # use userdel
     {
-      @command = ($cmd_userdel, $$user[$LOGIN]);
-    }
+      if ($remove_home)
+      {
+        @command = ($cmd_userdel, "--remove", $$user[$LOGIN]);
+      }
+      else
+      {
+        @command = ($cmd_userdel, $$user[$LOGIN]);
+      }
   }
 
   &Utils::File::run (@command);
@@ -541,8 +577,8 @@ sub set_passwd
 
 sub add_user
 {
-	my ($user) = @_;
-	my ($home_parents, $tool_mkdir);
+  my ($user) = @_;
+  my ($home_parents, $tool_mkdir, $chown_home);
   
   $tool_mkdir = &Utils::File::locate_tool ("mkdir");
 
@@ -634,6 +670,14 @@ sub add_user
     }
   }
 
+  # ensure user owns its home dir if asked
+  $chown_home = $$user[$HOME_FLAGS] & (1 << 1);
+  if ($chown_home && $$user[$HOME] ne "/")
+  {
+    @command = ("chown", "-R", "$$user[$LOGIN]:", $$user[$HOME]);
+    &Utils::File::run (@command);
+  }
+
   &change_user_chfn ($$user[$LOGIN], undef, $$user[$COMMENT]);
 }
 
@@ -719,81 +763,34 @@ sub set_logindefs
   }
 }
 
-sub set
-{
-  my ($config) = @_;
-  my ($old_config, %users);
-  my (%config_hash, %old_config_hash);
-
-  if ($config)
-  {
-    # Make backups manually, otherwise they don't get backed up.
-    &Utils::File::do_backup ($_) foreach (@passwd_names);
-    &Utils::File::do_backup ($_) foreach (@shadow_names);
-
-    $old_config = &get ();
-
-    foreach $i (@$config) 
-    {
-      $users{$$i[$LOGIN]} |= 1;
-      $config_hash{$$i[$LOGIN]} = $i;
-    }
-	
-    foreach $i (@$old_config)
-    {
-      $users{$$i[$LOGIN]} |= 2;
-      $old_config_hash{$$i[$LOGIN]} = $i;
-    }
-
-    # Delete all groups that only appeared in the old configuration
-    foreach $i (sort (keys (%users)))
-    {
-      $state = $users{$i};
-
-      if ($state == 1)
-      {
-        # Users with state 1 have been added to the config
-        &add_user ($config_hash{$i});
-      }
-      elsif ($state == 2)
-      {
-        # Users with state 2 have been deleted from the config
-        &del_user ($old_config_hash{$i});
-      }
-      elsif (($state == 3) &&
-             (!Utils::Util::struct_eq ($config_hash{$i}, $old_config_hash{$i})))
-      {
-        &change_user ($old_config_hash{$i}, $config_hash{$i});
-      }
-    }
-  }
-}
-
 sub get_user
 {
-  my ($uid) = @_;
+  my ($login) = @_;
   my ($users) = &get ();
 
   foreach $user (@$users)
   {
-    next if ($uid != $$user[$UID]);
-    return ($$user[$UID], $$user[$PASSWD], $$user[$COMMENT]);
+    next if ($login ne $$user[$LOGIN]);
+    return $user;
   }
 
-  return ($uid, "", []);
+  return NULL;
 }
 
 sub set_user
 {
-  my ($uid, $passwd, @comment) = @_;
+  my ($new_user) = @_;
   my ($users) = &get ();
 
+  # Make backups manually, otherwise they don't get backed up.
+  &Utils::File::do_backup ($_) foreach (@passwd_names);
+  &Utils::File::do_backup ($_) foreach (@shadow_names);
+
   foreach $user (@$users)
   {
-    if ($uid == $$user[$UID])
+    if ($$new_user[$UID] == $$user[$UID])
     {
-      &set_passwd ($$user[$LOGIN], $passwd);
-      &change_user_chfn ($$user[$LOGIN], undef, @comment);
+      &change_user ($user, $new_user);
       return;
     }
   }
diff --git a/UsersConfig.pm b/UsersConfig.pm
index e1bb16b..50c4ad4 100644
--- a/UsersConfig.pm
+++ b/UsersConfig.pm
@@ -4,7 +4,8 @@
 #
 # Copyright (C) 2005 Carlos Garnacho
 #
-# Authors: Carlos Garnacho Parro  <carlosg gnome org>
+# Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+#          Milan Bouchet-Valat <nalimilan club fr>.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU Library General Public License as published
@@ -24,13 +25,19 @@ package UsersConfig;
 
 use base qw(StbObject);
 use Net::DBus::Exporter ($Utils::Backend::DBUS_PREFIX);
+use UserConfig;
 use Users::Users;
 use Users::Shells;
 
-my $OBJECT_NAME = "UsersConfig";
+my $OBJECT_NAME = "UsersConfig2";
 my $OBJECT_PATH = "$Utils::Backend::DBUS_PATH/$OBJECT_NAME";
-my $format = [[ "array", [ "struct", "string", "string", "int32", "int32", [ "array", "string"], "string", "string" ]],
-              ["array", "string" ], "int32", "int32", "int32", "string", "string", "int32" ];
+
+# settings: list of shells, use MD5, umin, umax, home prefix, default shell, default group, encrypted home support
+# only configuration settings are set via UsersConfig
+my $set_format = [ [ "array", "string" ], "bool", "uint32", "uint32", "string", "string", "uint32", "bool" ];
+# array of users plus configuration settings
+my $get_format = [[ "array", $UserConfig::USER_FORMAT ], [ "array", "string" ], "bool", "uint32", "uint32", "string", "string", "uint32", "bool" ];
+
 
 sub new
 {
@@ -42,8 +49,8 @@ sub new
   return $self;
 }
 
-dbus_method ("get", [], $format);
-dbus_method ("set", $format, []);
+dbus_method ("get", [], $get_format);
+dbus_method ("set", $set_format, []);
 
 sub get
 {
@@ -58,7 +65,7 @@ sub get
 
   return ($users, $shells, $use_md5, $$logindefs{"umin"},
           $$logindefs{"umax"}, $$logindefs{"home_prefix"},
-          $$logindefs{"shell"}, $$logindefs{"group"});
+          $$logindefs{"shell"}, $$logindefs{"group"}, 0);
 }
 
 sub set
@@ -66,15 +73,15 @@ sub set
   my ($self, @config) = @_;
   $self->SUPER::reset_counter ();
 
-  Users::Users::set ($config[0]);
-  Users::Shells::set ($config[1]);
-  Users::Users::set_logindefs ({"umin"        => $config[3],
-                                "umax"        => $config[4],
-                                "home_prefix" => $config[5],
-                                "shell"       => $config[6],
-                                "group"       => $config[7]});
+  Users::Shells::set ($config[0]);
+  Users::Users::set_logindefs ({"umin"        => $config[2],
+                                "umax"        => $config[3],
+                                "home_prefix" => $config[4],
+                                "shell"       => $config[5],
+                                "group"       => $config[6]});
 }
 
+
 sub getFiles
 {
   my ($self) = @_;
diff --git a/dispatcher/dispatcher.c b/dispatcher/dispatcher.c
index ad43dc6..e230d66 100644
--- a/dispatcher/dispatcher.c
+++ b/dispatcher/dispatcher.c
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- * Authors: Carlos Garnacho Parro  <carlosg gnome org>
+ * Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+ *          Milan Bouchet-Valat <nalimilan club fr>.
  */
 
 #include <unistd.h>
@@ -41,8 +42,8 @@
 #define DBUS_ADDRESS_ENVVAR "DBUS_SESSION_BUS_ADDRESS"
 #define DBUS_INTERFACE_STB "org.freedesktop.SystemToolsBackends"
 #define DBUS_INTERFACE_STB_PLATFORM "org.freedesktop.SystemToolsBackends.Platform"
-#define DBUS_PATH_USER_CONFIG "/org/freedesktop/SystemToolsBackends/UserConfig"
-#define DBUS_PATH_SELF_CONFIG "/org/freedesktop/SystemToolsBackends/SelfConfig"
+#define DBUS_PATH_USER_CONFIG "/org/freedesktop/SystemToolsBackends/UserConfig2"
+#define DBUS_PATH_SELF_CONFIG "/org/freedesktop/SystemToolsBackends/SelfConfig2"
 
 #define STB_DISPATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STB_TYPE_DISPATCHER, StbDispatcherPrivate))
 
@@ -320,7 +321,6 @@ can_caller_do_action (StbDispatcher *dispatcher,
   StbDispatcherPrivate *priv;
   PolkitSubject *subject;
   PolkitAuthorizationResult *result;
-  const gchar *member;
   gchar *action_id;
   gulong caller_pid;
   gboolean retval;
@@ -333,19 +333,18 @@ can_caller_do_action (StbDispatcher *dispatcher,
   if (dbus_message_has_member (message, "get"))
     return TRUE;
 
-  /* Do not allow anything besides "set" past this point */
-  if (!dbus_message_has_member (message, "set"))
+  /* Do not allow anything besides "set", "add" or "del" past this point */
+  if (!(dbus_message_has_member (message, "set")
+       || dbus_message_has_member (message, "add")
+       || dbus_message_has_member (message, "del")))
     return FALSE;
 
   priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
-  member = dbus_message_get_member (message);
-
-  g_return_val_if_fail (member != NULL, FALSE);
 
   if (name)
-    action_id = g_strdup_printf ("org.freedesktop.systemtoolsbackends.%s.%s", name, member);
+    action_id = g_strdup_printf ("org.freedesktop.systemtoolsbackends.%s.set", name);
   else
-    action_id = g_strdup_printf ("org.freedesktop.systemtoolsbackends.%s", member);
+    action_id = g_strdup_printf ("org.freedesktop.systemtoolsbackends.set");
 
   /* Get the caller's PID using the connection name */
   call = dbus_message_new_method_call ("org.freedesktop.DBus",
@@ -520,7 +519,7 @@ dispatch_user_config (StbDispatcher *dispatcher,
   if (dbus_message_has_member (message, "get"))
     {
       /* compose the call to UserConfig with the uid of the caller */
-      user_message = dbus_message_new_method_call (DBUS_INTERFACE_STB ".UserConfig",
+      user_message = dbus_message_new_method_call (DBUS_INTERFACE_STB ".UserConfig2",
 						   DBUS_PATH_USER_CONFIG,
 						   DBUS_INTERFACE_STB,
 						   "get");
@@ -541,7 +540,7 @@ dispatch_user_config (StbDispatcher *dispatcher,
 				 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &gecos, &gecos_elements,
 				 DBUS_TYPE_INVALID))
 	{
-	  user_message = dbus_message_new_method_call (DBUS_INTERFACE_STB ".UserConfig",
+	  user_message = dbus_message_new_method_call (DBUS_INTERFACE_STB ".UserConfig2",
 						       DBUS_PATH_USER_CONFIG,
 						       DBUS_INTERFACE_STB,
 						       "set");
diff --git a/org.freedesktop.SystemToolsBackends.conf b/org.freedesktop.SystemToolsBackends.conf
index d031525..52dcc51 100644
--- a/org.freedesktop.SystemToolsBackends.conf
+++ b/org.freedesktop.SystemToolsBackends.conf
@@ -16,8 +16,8 @@
     <allow own="org.freedesktop.SystemToolsBackends.ServicesConfig"/>
     <allow own="org.freedesktop.SystemToolsBackends.SMBConfig"/>
     <allow own="org.freedesktop.SystemToolsBackends.TimeConfig"/>
-    <allow own="org.freedesktop.SystemToolsBackends.UserConfig"/>
-    <allow own="org.freedesktop.SystemToolsBackends.UsersConfig"/>
+    <allow own="org.freedesktop.SystemToolsBackends.UserConfig2"/>
+    <allow own="org.freedesktop.SystemToolsBackends.UsersConfig2"/>
     <allow own="org.freedesktop.SystemToolsBackends.Platform"/>
     <allow send_interface="org.freedesktop.SystemToolsBackends.Platform" send_member="getPlatform"/>
     -->
@@ -39,8 +39,8 @@
     <allow own="org.freedesktop.SystemToolsBackends.ServicesConfig"/>
     <allow own="org.freedesktop.SystemToolsBackends.SMBConfig"/>
     <allow own="org.freedesktop.SystemToolsBackends.TimeConfig"/>
-    <allow own="org.freedesktop.SystemToolsBackends.UserConfig"/>
-    <allow own="org.freedesktop.SystemToolsBackends.UsersConfig"/>
+    <allow own="org.freedesktop.SystemToolsBackends.UserConfig2"/>
+    <allow own="org.freedesktop.SystemToolsBackends.UsersConfig2"/>
     <allow own="org.freedesktop.SystemToolsBackends.Platform"/>
 
     <!-- be able to speak to configuration modules,
@@ -57,7 +57,7 @@
     <allow send_destination="org.freedesktop.SystemToolsBackends.ServicesConfig"/>
     <allow send_destination="org.freedesktop.SystemToolsBackends.SMBConfig"/>
     <allow send_destination="org.freedesktop.SystemToolsBackends.TimeConfig"/>
-    <allow send_destination="org.freedesktop.SystemToolsBackends.UserConfig"/>
-    <allow send_destination="org.freedesktop.SystemToolsBackends.UsersConfig"/>
+    <allow send_destination="org.freedesktop.SystemToolsBackends.UserConfig2"/>
+    <allow send_destination="org.freedesktop.SystemToolsBackends.UsersConfig2"/>
   </policy>
 </busconfig>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]