summaryrefslogtreecommitdiff
path: root/Users
diff options
context:
space:
mode:
Diffstat (limited to 'Users')
-rw-r--r--Users/.cvsignore2
-rw-r--r--Users/Groups.pm243
-rw-r--r--Users/Makefile.am6
-rw-r--r--Users/Shells.pm99
-rw-r--r--Users/Users.pm707
5 files changed, 1057 insertions, 0 deletions
diff --git a/Users/.cvsignore b/Users/.cvsignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/Users/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/Users/Groups.pm b/Users/Groups.pm
new file mode 100644
index 0000000..e2935f4
--- /dev/null
+++ b/Users/Groups.pm
@@ -0,0 +1,243 @@
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# 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)
+#
+#
+# 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
+# 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 Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library 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.
+
+package Users::Groups;
+
+# enum like for verbose group array positions
+my $LOGIN = 0;
+my $PASSWD = 1;
+my $GID = 2;
+my $USERS = 3;
+
+# quite generic data
+$group_names = "/etc/group";
+
+# Where are the tools?
+$cmd_groupdel = &Utils::File::locate_tool ("groupdel");
+$cmd_groupadd = &Utils::File::locate_tool ("groupadd");
+$cmd_groupmod = &Utils::File::locate_tool ("groupmod");
+$cmd_gpasswd = &Utils::File::locate_tool ("gpasswd");
+$cmd_pw = &Utils::File::locate_tool ("pw");
+
+sub del_group
+{
+ my ($group) = @_;
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ $command = "$cmd_pw groupdel -n \'" . $$group[$LOGIN] . "\'";
+ }
+ else
+ {
+ $command = "$cmd_groupdel \'" . $$group[$LOGIN] . "\'";
+ }
+
+ &Utils::File::run ($command);
+}
+
+sub add_group
+{
+ my ($group) = @_;
+ my ($u, $user, $users);
+
+ $u = $$group[$USERS];
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ $users = join (",", sort @$u);
+
+ $command = "$cmd_pw groupadd -n \'" . $$group[$LOGIN] .
+ "\' -g \'" . $$group[$GID] .
+ "\' -M \'" . $users . "\'";
+
+ &Utils::File::run ($command);
+ }
+ else
+ {
+ $command = "$cmd_groupadd -g \'" . $$group[$GID] .
+ "\' " . $$group[$LOGIN];
+
+ &Utils::File::run ($command);
+
+ foreach $user (sort @$u)
+ {
+ $command = "$cmd_gpasswd -a \'" . $user .
+ "\' " . $$group[$LOGIN];
+
+ &Utils::File::run ($command);
+ }
+ }
+}
+
+sub change_group
+{
+ my ($old_group, $new_group) = @_;
+ my (%users, $user, $users_arr, $str);
+
+ my ($n, $o, $users, $i, $j, $max_n, $max_o, $r, @tmp); # for iterations
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ $users_arr = $$new_group[$USERS];
+ $str = join (",", sort @$users_arr);
+
+ $command = "$cmd_pw groupmod -n \'" . $$old_group[$LOGIN] .
+ "\' -g \'" . $$new_group[$GID] .
+ "\' -l \'" . $$new_group[$LOGIN] .
+ "\' -M \'" . $str . "\'";
+
+ &Utils::File::run ($command);
+ }
+ else
+ {
+ $command = "$cmd_groupmod -g \'" . $$new_group[$GID] .
+ "\' -n \'" . $$new_group[$LOGIN] . "\' " .
+ "\'" . $$old_group[$LOGIN] . "\'";
+
+ &Utils::File::run ($command);
+
+ # Let's see if the users that compose the group have changed.
+ if (!Utils::Util::struct_eq ($$new_group[$USERS], $$old_group[$USERS]))
+ {
+ $users{$_} |= 1 foreach (@{$$new_group[$USERS]});
+ $users{$_} |= 2 foreach (@{$$old_group[$USERS]});
+
+ foreach $user (keys %users)
+ {
+ $state = $users{$u};
+
+ if ($state == 2)
+ {
+ # users with state 2 are those that only appeared
+ # in the old group configuration, so we must delete them
+ $command = "$cmd_gpasswd -d \'" . $user . "\' \'" .
+ $$new_group[$LOGIN] . "\'";
+
+ &Utils::File::run ($command);
+ }
+ else
+ {
+ # users with state 1 are those who were added
+ # to the new group configuration
+ $command = "$cmd_gpasswd -a \'" . $user . "\' \'" .
+ $$new_group[$LOGIN] . "\'";
+
+ &Utils::File::run ($command);
+ }
+ }
+ }
+ }
+}
+
+sub get
+{
+ my ($ifh, @groups, $group_last_modified);
+ my (@line, $copy, @a);
+
+ # Find the file.
+
+ $ifh = &Utils::File::open_read_from_names($group_names);
+ return unless ($ifh);
+
+ # Parse the file.
+ @groups = ();
+
+ while (<$ifh>)
+ {
+ chomp;
+
+ # FreeBSD allows comments in the group file. */
+ next if &Utils::Util::ignore_line ($_);
+ $_ = &Utils::XML::unquote ($_);
+
+ @line = split ':', $_, -1;
+ @a = split ',', pop @line;
+ push @line, [@a];
+ $copy = [@line];
+ push (@groups, $copy);
+ }
+
+ &Utils::File::close_file ($ifh);
+
+ return \@groups;
+}
+
+sub get_files
+{
+ my @arr;
+
+ push @arr, $group_names;
+ return \@arr;
+}
+
+sub set
+{
+ my ($config) = @_;
+ my ($old_config, %groups);
+ my (%config_hash, %old_config_hash);
+
+ if ($config)
+ {
+ # Make backup manually, otherwise they don't get backed up.
+ &Utils::File::do_backup ($group_names);
+
+ $old_config = &get ();
+
+ foreach $i (@$config)
+ {
+ $groups{$$i[$LOGIN]} |= 1;
+ $config_hash{$$i[$LOGIN]} = $i;
+ }
+
+ foreach $i (@$old_config)
+ {
+ $groups{$$i[$LOGIN]} |= 2;
+ $old_config_hash{$$i[$LOGIN]} = $i;
+ }
+
+ # Delete all groups that only appeared in the old configuration
+ foreach $i (sort (keys (%groups)))
+ {
+ $state = $groups{$i};
+
+ if ($state == 1)
+ {
+ # Groups with state 1 have been added to the config
+ &add_group ($config_hash{$i});
+ }
+ elsif ($state == 2)
+ {
+ # Groups with state 2 have been deleted from the config
+ &del_group ($old_config_hash{$i});
+ }
+ elsif (($state == 3) &&
+ (!Utils::Util::struct_eq ($config_hash{$i}, $old_config_hash{$i})))
+ {
+ &change_group ($old_config_hash{$i}, $config_hash{$i});
+ }
+ }
+ }
+}
+
+1;
diff --git a/Users/Makefile.am b/Users/Makefile.am
new file mode 100644
index 0000000..1c0fdda
--- /dev/null
+++ b/Users/Makefile.am
@@ -0,0 +1,6 @@
+usersdir = $(scriptsdir)/Users
+
+users_SCRIPTS = \
+ Groups.pm \
+ Shells.pm \
+ Users.pm
diff --git a/Users/Shells.pm b/Users/Shells.pm
new file mode 100644
index 0000000..1c473ec
--- /dev/null
+++ b/Users/Shells.pm
@@ -0,0 +1,99 @@
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# 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)
+# Carlos Garnacho <carlosg@gnome.org>
+#
+# 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
+# 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 Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library 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.
+
+package Users::Shells;
+
+use Utils::Util;
+use Utils::Report;
+use Utils::File;
+use Utils::Replace;
+
+# Totally generic atm
+$shells_file = "/etc/shells";
+
+sub get_files
+{
+ return $shells_file;
+}
+
+sub get
+{
+ my ($ifh, @shells);
+
+ # Init @shells, I think every *nix has /bin/false.
+ if (stat ("/bin/false"))
+ {
+ push @shells, "/bin/false";
+ }
+
+ $ifh = &Utils::File::open_read_from_names($shells_file);
+ return unless $ifh;
+
+ while (<$ifh>)
+ {
+ next if &Utils::Util::ignore_line ($_);
+ chomp;
+ push @shells, $_ if (stat ($_));
+ }
+
+ &Utils::File::close_file ($ifh);
+
+ return \@shells;
+}
+
+sub set
+{
+ my ($shells) = @_;
+ my ($buff, $line, $nline);
+
+ $buff = &Utils::File::load_buffer ($shells_file);
+ return unless $buff;
+
+ &Utils::File::join_buffer_lines ($buff);
+ $nline = 0;
+
+ # delete all file entries that really exist,
+ # this is done for not deleting entries that
+ # might be installed later
+ while ($nline <= $#$buff)
+ {
+ $line = $$buff[$nline];
+ chomp $line;
+
+ if (!&Utils::Util::ignore_line ($line))
+ {
+ delete $$buff[$nline] if (stat ($line));
+ }
+
+ $nline++;
+ }
+
+ # Add shells list
+ foreach $line (@$shells)
+ {
+ push @$buff, "$line\n" if (stat ($line));
+ }
+
+ &Utils::File::save_buffer ($buff, $shells_file);
+}
diff --git a/Users/Users.pm b/Users/Users.pm
new file mode 100644
index 0000000..ae40d42
--- /dev/null
+++ b/Users/Users.pm
@@ -0,0 +1,707 @@
+#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+# Users account manager. Designed to be architecture and distribution independent.
+#
+# Copyright (C) 2000-2001 Ximian, Inc.
+#
+# 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)
+#
+# 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
+# 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 Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library 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.
+
+# Best viewed with 100 columns of width.
+
+# Configuration files affected:
+#
+# /etc/passwd
+# /etc/group
+# /etc/shadow
+# /etc/login.defs
+# /etc/shells
+# /etc/skel/
+
+# NIS support will come later.
+
+# Running programs affected/used:
+#
+# adduser: creating users.
+# usermod: modifying user data.
+# passwd: assigning or changing passwords. (Un)locking users.
+# chfn: modifying finger information - Name, Office, Office phone, Home phone.
+# pw: modifying users/groups and user/group data on FreeBSD.
+
+package Users::Users;
+
+use Utils::Util;
+use Utils::Report;
+use Utils::File;
+use Utils::Backend;
+use Utils::Replace;
+
+# --- System config file locations --- #
+
+# We list each config file type with as many alternate locations as possible.
+# They are tried in array order. First found = used.
+@passwd_names = ( "/etc/passwd" );
+@shadow_names = ( "/etc/shadow", "/etc/master.passwd" );
+@login_defs_names = ( "/etc/login.defs", "/etc/adduser.conf" );
+@shell_names = ( "/etc/shells" );
+@skel_dir = ( "/usr/share/skel", "/etc/skel" );
+
+# Where are the tools?
+$cmd_usermod = &Utils::File::locate_tool ("usermod");
+$cmd_userdel = &Utils::File::locate_tool ("userdel");
+$cmd_useradd = &Utils::File::locate_tool ("useradd");
+$cmd_chfn = &Utils::File::locate_tool ("chfn");
+$cmd_pw = &Utils::File::locate_tool ("pw");
+
+# enum like for verbose group array positions
+my $LOGIN = 0;
+my $PASSWD = 1;
+my $UID = 2;
+my $GID = 3;
+my $COMMENT = 4;
+my $HOME = 5;
+my $SHELL = 6;
+
+%login_defs_prop_map = ();
+%profiles_prop_map = ();
+
+sub get_login_defs_prop_array
+{
+ my @prop_array;
+ my @login_defs_prop_array_default =
+ (
+ "QMAIL_DIR", "qmail_dir",
+ "MAIL_DIR", "mailbox_dir",
+ "MAIL_FILE", "mailbox_file",
+ "PASS_MAX_DAYS", "pwd_maxdays",
+ "PASS_MIN_DAYS", "pwd_mindays",
+ "PASS_MIN_LEN", "pwd_min_length",
+ "PASS_WARN_AGE", "pwd_warndays",
+ "UID_MIN", "umin",
+ "UID_MAX", "umax",
+ "GID_MIN", "gmin",
+ "GID_MAX", "gmax",
+ "USERDEL_CMD", "del_user_additional_command",
+ "CREATE_HOME", "create_home",
+ "", "");
+
+ my @login_defs_prop_array_suse =
+ (
+ "QMAIL_DIR", "qmail_dir",
+ "MAIL_DIR", "mailbox_dir",
+ "MAIL_FILE", "mailbox_file",
+ "PASS_MAX_DAYS", "pwd_maxdays",
+ "PASS_MIN_DAYS", "pwd_mindays",
+ "PASS_MIN_LEN", "pwd_min_length",
+ "PASS_WARN_AGE", "pwd_warndays",
+ "UID_MIN", "umin",
+ "UID_MAX", "umax",
+ "SYSTEM_GID_MIN", "gmin",
+ "GID_MAX", "gmax",
+ "USERDEL_CMD", "del_user_additional_command",
+ "CREATE_HOME", "create_home",
+ "", "");
+
+ if ($Utils::Backend::tool{"platform"} =~ /^suse/)
+ {
+ @prop_array = @login_defs_prop_array_suse;
+ }
+ else
+ {
+ @prop_array = @login_defs_prop_array_default;
+ }
+
+ for ($i = 0; $prop_array [$i] ne ""; $i += 2)
+ {
+ $login_defs_prop_map {$prop_array [$i]} = $prop_array [$i + 1];
+ $login_defs_prop_map {$prop_array [$i + 1]} = $prop_array [$i];
+ }
+}
+
+sub get_profiles_prop_array
+{
+ my @prop_array;
+ my @profiles_prop_array_default =
+ (
+ "NAME" , "name",
+ "COMMENT", "comment",
+ "LOGINDEFS", "login_defs",
+ "HOME_PREFFIX", "home_prefix",
+ "SHELL", "shell",
+ "GROUP", "group",
+ "SKEL_DIR", "skel_dir",
+ "QMAIL_DIR" , "qmail_dir",
+ "MAIL_DIR" , "mailbox_dir",
+ "MAIL_FILE" , "mailbox_file",
+ "PASS_RANDOM", "pwd_random",
+ "PASS_MAX_DAYS" , "pwd_maxdays",
+ "PASS_MIN_DAYS" , "pwd_mindays",
+ "PASS_MIN_LEN" , "pwd_min_length",
+ "PASS_WARN_AGE" , "pwd_warndays",
+ "UID_MIN" , "umin",
+ "UID_MAX" , "umax",
+ "GID_MIN" , "gmin",
+ "GID_MAX" , "gmax",
+ "USERDEL_CMD" , "del_user_additional_command",
+ "CREATE_HOME" , "create_home",
+ "", "");
+
+ my @profiles_prop_array_suse =
+ (
+ "NAME" , "name",
+ "COMMENT", "comment",
+ "LOGINDEFS", "login_defs",
+ "HOME_PREFFIX", "home_prefix",
+ "SHELL", "shell",
+ "GROUP", "group",
+ "SKEL_DIR", "skel_dir",
+ "QMAIL_DIR" , "qmail_dir",
+ "MAIL_DIR" , "mailbox_dir",
+ "MAIL_FILE" , "mailbox_file",
+ "PASS_RANDOM", "pwd_random",
+ "PASS_MAX_DAYS" , "pwd_maxdays",
+ "PASS_MIN_DAYS" , "pwd_mindays",
+ "PASS_MIN_LEN" , "pwd_min_length",
+ "PASS_WARN_AGE" , "pwd_warndays",
+ "UID_MIN" , "umin",
+ "UID_MAX" , "umax",
+ "GID_MIN" , "gmin",
+ "GID_MAX" , "gmax",
+ "USERDEL_CMD" , "del_user_additional_command",
+ "CREATE_HOME" , "create_home",
+ "", "");
+
+ if ($Utils::Backend::tool{"platform"} =~ /suse/)
+ {
+ @prop_array = @profiles_prop_array_suse;
+ }
+ else
+ {
+ @prop_array = @profiles_prop_array_default;
+ }
+
+ for ($i = 0; $prop_array[$i] ne ""; $i += 2)
+ {
+ $profiles_prop_map {$prop_array [$i]} = $prop_array [$i + 1];
+ $profiles_prop_map {$prop_array [$i + 1]} = $prop_array [$i];
+ }
+}
+
+my $rh_logindefs_defaults = {
+ 'shell' => '/bin/bash',
+ 'group' => '$user',
+ 'skel_dir' => '/etc/skel/',
+};
+
+my $gentoo_logindefs_defaults = {
+ 'shell' => '/bin/bash',
+ 'group' => 'users',
+ 'skel_dir' => '/etc/skel/',
+};
+
+my $freebsd_logindefs_defaults = {
+ 'shell' => '/bin/sh',
+ 'group' => '$user',
+ 'skel_dir' => '/etc/skel/',
+};
+
+my $logindefs_dist_map = {
+ 'redhat-5.2' => $rh_logindefs_defaults,
+ 'redhat-6.0' => $rh_logindefs_defaults,
+ 'redhat-6.1' => $rh_logindefs_defaults,
+ 'redhat-6.2' => $rh_logindefs_defaults,
+ 'redhat-7.0' => $rh_logindefs_defaults,
+ 'redhat-7.1' => $rh_logindefs_defaults,
+ 'redhat-7.2' => $rh_logindefs_defaults,
+ 'redhat-7.3' => $rh_logindefs_defaults,
+ 'redhat-8.0' => $rh_logindefs_defaults,
+ 'redhat-9' => $rh_logindefs_defaults,
+ 'openna-1.0' => $rh_logindefs_defaults,
+ 'mandrake-7.1' => $rh_logindefs_defaults,
+ 'mandrake-7.2' => $rh_logindefs_defaults,
+ 'mandrake-9.0' => $rh_logindefs_defaults,
+ 'mandrake-9.1' => $rh_logindefs_defaults,
+ 'mandrake-9.2' => $rh_logindefs_defaults,
+ 'mandrake-10.0' => $rh_logindefs_defaults,
+ 'mandrake-10.1' => $rh_logindefs_defaults,
+ 'pld-1.0' => $rh_logindefs_defaults,
+ 'pld-1.1' => $rh_logindefs_defaults,
+ 'pld-1.99' => $rh_logindefs_defaults,
+ 'fedora-1' => $rh_logindefs_defaults,
+ 'fedora-2' => $rh_logindefs_defaults,
+ 'fedora-3' => $rh_logindefs_defaults,
+ 'rpath' => $rh_logindefs_defaults,
+ 'debian-2.2' => $rh_logindefs_defaults,
+ 'debian-3.0' => $rh_logindefs_defaults,
+ 'debian-sarge' => $rh_logindefs_defaults,
+ 'ubuntu-5.04' => $rh_logindefs_defaults,
+ 'ubuntu-5.10' => $rh_logindefs_defaults,
+ 'ubuntu-6.04' => $rh_logindefs_defaults,
+ 'vine-3.0' => $rh_logindefs_defaults,
+ 'vine-3.1' => $rh_logindefs_defaults,
+ 'gentoo' => $gentoo_logindefs_defaults,
+ 'vlos-1.2' => $gentoo_logindefs_defaults,
+ 'archlinux' => $gentoo_logindefs_defaults,
+ 'slackware-9.1.0' => $gentoo_logindefs_defaults,
+ 'slackware-10.0.0' => $gentoo_logindefs_defaults,
+ 'slackware-10.1.0' => $gentoo_logindefs_defaults,
+ 'slackware-10.2.0' => $gentoo_logindefs_defaults,
+ 'freebsd-4' => $freebsd_logindefs_defaults,
+ 'freebsd-5' => $freebsd_logindefs_defaults,
+ 'freebsd-6' => $freebsd_logindefs_defaults,
+ 'suse-7.0' => $gentoo_logindefs_defaults,
+ 'suse-9.0' => $gentoo_logindefs_defaults,
+ 'suse-9.1' => $gentoo_logindefs_defaults,
+
+ # FIXME: I don't know about those, so using RH values for now.
+ 'turbolinux-7.0' => $rh_logindefs_defaults,
+ 'slackware-8.0.0' => $rh_logindefs_defaults,
+ 'slackware-8.1' => $rh_logindefs_defaults,
+ 'slackware-9.0.0' => $rh_logindefs_defaults,
+};
+
+
+# Add reporting table.
+
+&Utils::Report::add ({
+ 'users_read_profiledb_success' => ['info', 'Profiles read successfully.'],
+ 'users_read_profiledb_fail' => ['warn', 'Profiles read failed.'],
+ 'users_read_users_success' => ['info', 'Users read successfully.'],
+ 'users_read_users_fail' => ['warn', 'Users read failed.'],
+ 'users_read_groups_success' => ['info', 'Groups read successfully.'],
+ 'users_read_groups_fail' => ['warn', 'Groups read failed.'],
+ 'users_read_shells_success' => ['info', 'Shells read successfully.'],
+ 'users_read_shells_fail' => ['warn', 'Reading shells failed.'],
+
+ 'users_write_profiledb_success' => ['info', 'Profiles written successfully.'],
+ 'users_write_profiledb_fail' => ['warn', 'Writing profiles failed.'],
+ 'users_write_users_success' => ['info', 'Users written successfully.'],
+ 'users_write_users_fail' => ['warn', 'Writing users failed.'],
+ 'users_write_groups_success' => ['info', 'Groups written successfully.'],
+ 'users_write_groups_fail' => ['warn', 'Writing groups failed.'],
+});
+
+
+sub do_get_use_md5
+{
+ my ($file) = @_;
+ my ($fh, @line, $i, $use_md5);
+
+ my $fh = &Utils::File::open_read_from_names ("/etc/pam.d/$file");
+ return 0 if (!$fh);
+
+ $use_md5 = 0;
+
+ while (<$fh>)
+ {
+ next if &Utils::Util::ignore_line ($_);
+ chomp;
+ @line = split /[ \t]+/;
+
+ if ($line[0] eq "\@include")
+ {
+ $use_md5 = &do_get_use_md5 ($line[1]);
+ }
+ elsif ($line[0] eq "password")
+ {
+ foreach $i (@line)
+ {
+ $use_md5 = 1 if ($i eq "md5");
+ }
+ }
+ }
+
+ close $fh;
+ return $use_md5;
+}
+
+sub get_use_md5
+{
+ return &do_get_use_md5 ("passwd");
+}
+
+sub logindefs_add_defaults
+{
+ # Common for all distros
+ my $logindefs = {
+ 'home_prefix' => '/home/',
+ };
+
+ &get_profiles_prop_array ();
+
+ # Distro specific
+ my $dist_specific = $logindefs_dist_map->{$Utils::Backend::tool{"platform"}};
+
+ # Just to be 100% sure SOMETHING gets filled:
+ unless ($dist_specific)
+ {
+ $dist_specific = $rh_logindefs_defaults;
+ }
+
+ foreach my $key (keys %$dist_specific)
+ {
+ # Make sure there's no crappy entries
+ if (exists ($profiles_prop_map{$key}) || $key eq "groups")
+ {
+ $logindefs->{$key} = $dist_specific->{$key};
+ }
+ }
+ return $logindefs;
+}
+
+sub get_logindefs
+{
+ my $logindefs;
+
+ &get_login_defs_prop_array ();
+ $logindefs = &logindefs_add_defaults ();
+
+ # Get new data in case someone has changed login_defs manually.
+ my $fh = &Utils::File::open_read_from_names (@login_defs_names);
+
+ if ($fh)
+ {
+ while (<$fh>)
+ {
+ next if &Utils::Util::ignore_line ($_);
+ chomp;
+ my @line = split /[ \t]+/;
+
+ if (exists $login_defs_prop_map{$line[0]})
+ {
+ $logindefs->{$login_defs_prop_map{$line[0]}} = $line[1];
+ }
+ }
+
+ close $fh;
+ }
+ else
+ {
+ # Put safe defaults for distros/OS that don't have any defaults file
+ $logindefs->{"umin"} = '1000';
+ $logindefs->{"umax"} = '60000';
+ $logindefs->{"gmin"} = '1000';
+ $logindefs->{"gmax"} = '60000';
+ }
+
+ return $logindefs;
+}
+
+sub get
+{
+ my ($ifh, @users, %users_hash);
+ my (@line);
+
+ # Find the passwd file.
+ $ifh = &Utils::File::open_read_from_names(@passwd_names);
+ return unless ($ifh);
+
+ %users_hash = ();
+
+ while (<$ifh>)
+ {
+ chomp;
+ # FreeBSD allows comments in the passwd file.
+ next if &Utils::Util::ignore_line ($_);
+
+ @line = split ':', $_, -1;
+
+ $login = $line[$LOGIN];
+ @comment = split ',', $line[$COMMENT], 5;
+
+ # we need to make sure that there are 5 elements
+ push @comment, "" while (scalar (@comment) < 5);
+ $line[$COMMENT] = [@comment];
+
+ $$users_hash{$login} = [@line];
+ }
+
+ &Utils::File::close_file ($ifh);
+ $ifh = &Utils::File::open_read_from_names(@shadow_names);
+
+ if ($ifh)
+ {
+ while (<$ifh>)
+ {
+ chomp;
+
+ # FreeBSD allows comments in the shadow passwd file.
+ next if &Utils::Util::ignore_line ($_);
+
+ @line = split ':', $_, -1;
+ $login = shift @line;
+ $passwd = shift @line;
+
+ $$users_hash{$login}[$PASSWD] = $passwd;
+
+ # FIXME: add the rest of the fields?
+ #push @{$$users_hash{$login}}, @line;
+ }
+
+ &Utils::File::close_file ($ifh);
+ }
+
+ # transform the hash into an array
+ foreach $login (keys %$users_hash)
+ {
+ push @users, $$users_hash{$login};
+ }
+
+ return \@users;
+}
+
+sub get_files
+{
+ my @arr;
+
+ push @arr, @passwd_names;
+ push @arr, @shadow_names;
+
+ return \@arr;
+}
+
+
+sub del_user
+{
+ my ($user) = @_;
+ my ($command);
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ $command = "$cmd_pw userdel -n \'" . $$user[$LOGIN] . "\' ";
+ }
+ else
+ {
+ $command = "$cmd_userdel \'" . $$user[$LOGIN] . "\'";
+ }
+
+ &Utils::File::run ($command);
+}
+
+sub change_user_chfn
+{
+ my ($login, $old_comment, $comment) = @_;
+ my ($fname, $office, $office_phone, $home_phone);
+ my ($command);
+
+ return if !$login;
+
+ # Compare old and new data
+ return if (Utils::Util::struct_eq ($old_comment, $comment));
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ my ($str);
+
+ $str = join (",", @$comment);
+ $command = "$cmd_pw usermod -n " . $login . " -c \'" . $str . "\'";
+ }
+ else
+ {
+ ($fname, $office, $office_phone, $home_phone) = @$comment;
+
+ $command = "$cmd_chfn" .
+ " -f \'" . $fname . "\'" .
+ " -h \'" . $home_phone . "\'";
+
+ if ($Utils::Backend::tool{"platform"} =~ /^debian/ ||
+ $Utils::Backend::tool{"platform"} =~ /^archlinux/)
+ {
+ $command .= " -r \'" . $office . "\'" .
+ " -w \'" . $office_phone . "\'";
+ }
+ else
+ {
+ $command .= " -o \'" . $office . "\'" .
+ " -p \'" . $office_phone . "\'";
+ }
+ }
+
+ &Utils::File::run ($command);
+}
+
+sub add_user
+{
+ my ($user) = @_;
+ my ($home_parents, $tool_mkdir);
+
+ $tool_mkdir = &Utils::File::locate_tool ("mkdir");
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ my $pwdpipe;
+ my $home;
+
+ # FreeBSD doesn't create the home directory
+ $home = $$user[$HOME];
+ &Utils::File::run ("$tool_mkdir -p $home");
+
+ $command = "$cmd_pw useradd " .
+ " -n \'" . $$user[$LOGIN] . "\'" .
+ " -u \'" . $$user[$UID] . "\'" .
+ " -d \'" . $$user[$HOME] . "\'" .
+ " -g \'" . $$user[$GID] . "\'" .
+ " -s \'" . $$user[$SHELL] . "\'" .
+ " -H 0"; # pw(8) reads password from STDIN
+
+ $pwdpipe = &Utils::File::run_pipe_write ($command);
+ print $pwdpipe $$user[$PASSWD];
+ &Utils::File::close_file ($pwdpipe);
+ }
+ else
+ {
+ $home_parents = $$user[$HOME];
+ $home_parents =~ s/\/+[^\/]+\/*$//;
+ &Utils::File::run ("$tool_mkdir -p $home_parents");
+
+ $command = "$cmd_useradd -m" .
+ " -d \'" . $$user[$HOME] . "\'" .
+ " -g \'" . $$user[$GID] . "\'" .
+ " -p \'" . $$user[$PASSWD] . "\'" .
+ " -s \'" . $$user[$SHELL] . "\'" .
+ " -u \'" . $$user[$UID] . "\'" .
+ " \'" . $$user[$LOGIN] . "\'";
+
+ &Utils::File::run ($command);
+ }
+
+ &change_user_chfn ($$user[$LOGIN], undef, $$user[$COMMENT]);
+}
+
+sub change_user
+{
+ my ($old_user, $new_user) = @_;
+
+ if ($Utils::Backend::tool{"system"} eq "FreeBSD")
+ {
+ my $pwdpipe;
+
+ $command = "$cmd_pw usermod \'" . $$old_user[$LOGIN] . "\'" .
+ " -l \'" . $$new_user[$LOGIN] . "\'" .
+ " -u \'" . $$new_user[$UID] . "\'" .
+ " -d \'" . $$new_user[$HOME] . "\'" .
+ " -g \'" . $$new_user[$GID] . "\'" .
+ " -s \'" . $$new_user[$SHELL] . "\'" .
+ " -H 0"; # pw(8) reads password from STDIN
+
+ $pwdpipe = &Utils::File::run_pipe_write ($command);
+ print $pwdpipe $$new_user[$PASSWD];
+ &Utils::File::close_file ($pwdpipe);
+ }
+ else
+ {
+ $command = "$cmd_usermod" .
+ " -d \'" . $$new_user[$HOME] . "\'" .
+ " -g \'" . $$new_user[$GID] . "\'" .
+ " -l \'" . $$new_user[$LOGIN] . "\'" .
+ " -p \'" . $$new_user[$PASSWD] . "\'" .
+ " -s \'" . $$new_user[$SHELL] . "\'" .
+ " -u \'" . $$new_user[$UID] . "\'" .
+ " \'" . $$old_user[$LOGIN] . "\'";
+
+ &Utils::File::run ($command);
+ }
+
+ &change_user_chfn ($$new_user[$LOGIN], $$old_user[$COMMENT], $$new_user[$COMMENT]);
+}
+
+sub set_logindefs
+{
+ my ($config) = @_;
+ my ($logindefs, $key, $file);
+
+ return unless $config;
+
+ &get_login_defs_prop_array ();
+
+ foreach $key (@login_defs_names)
+ {
+ if (-f $key)
+ {
+ $file = $key;
+ last;
+ }
+ }
+
+ unless ($file)
+ {
+ &Utils::Report::do_report ("file_open_read_failed", join (", ", @login_defs_names));
+ return;
+ }
+
+ foreach $key (keys (%$config))
+ {
+ # Write ONLY login.defs values.
+ if (exists ($login_defs_prop_map{$key}))
+ {
+ &Utils::Replace::split ($file, $login_defs_prop_map{$key}, "[ \t]+", $$config{$key});
+ }
+ }
+}
+
+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[0]} |= 1;
+ $config_hash{$$i[0]} = $i;
+ }
+
+ foreach $i (@$old_config)
+ {
+ $users{$$i[0]} |= 2;
+ $old_config_hash{$$i[0]} = $i;
+ }
+
+ # Delete all groups that only appeared in the old configuration
+ foreach $i (sort (keys (%users)))
+ {
+ $state = $users{$i};
+
+ if ($state == 1)
+ {
+ # Groups with state 1 have been added to the config
+ &add_user ($config_hash{$i});
+ }
+ elsif ($state == 2)
+ {
+ # Groups 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});
+ }
+ }
+ }
+}
+
+1;