| 1 |
rb |
80 |
#!/usr/bin/perl |
| 2 |
zugschlus |
324 |
|
| 3 |
rb |
1 |
# adduser: a utility to add users to the system |
| 4 |
|
|
# addgroup: a utility to add groups to the system |
| 5 |
zugschlus |
324 |
my $version = "VERSION"; |
| 6 |
rb |
1 |
|
| 7 |
rb |
6 |
# Copyright (C) 1997, 1998, 1999 Guy Maor <maor@debian.org> |
| 8 |
rb |
1 |
# Copyright (C) 1995 Ted Hajek <tedhajek@boombox.micro.umn.edu> |
| 9 |
|
|
# Ian A. Murdock <imurdock@gnu.ai.mit.edu> |
| 10 |
rb |
15 |
# Bugfixes and other improvements Roland Bauerschmidt <rb@debian.org> |
| 11 |
rb |
1 |
# General scheme of the program adapted by the original debian 'adduser' |
| 12 |
|
|
# program by Ian A. Murdock <imurdock@gnu.ai.mit.edu>. |
| 13 |
|
|
# |
| 14 |
|
|
# This program is free software; you can redistribute it and/or modify |
| 15 |
|
|
# it under the terms of the GNU General Public License as published by |
| 16 |
|
|
# the Free Software Foundation; either version 2 of the License, or |
| 17 |
|
|
# (at your option) any later version. |
| 18 |
|
|
# |
| 19 |
|
|
# This program is distributed in the hope that it will be useful, |
| 20 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 22 |
|
|
# GNU General Public License for more details. |
| 23 |
|
|
# |
| 24 |
|
|
# You should have received a copy of the GNU General Public License |
| 25 |
|
|
# along with this program; if not, write to the Free Software |
| 26 |
rb |
10 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 27 |
rb |
1 |
# |
| 28 |
|
|
# |
| 29 |
|
|
#################### |
| 30 |
zugschlus |
220 |
# See the usage subroutine for explanation about how the program can be called |
| 31 |
|
|
#################### |
| 32 |
rb |
1 |
|
| 33 |
rb |
80 |
use warnings; |
| 34 |
joerghoh-guest |
528 |
use strict; |
| 35 |
rb |
52 |
use Debian::AdduserCommon; |
| 36 |
zugschlus |
255 |
use Getopt::Long; |
| 37 |
rb |
15 |
|
| 38 |
rb |
6 |
BEGIN { |
| 39 |
|
|
eval 'use Locale::gettext'; |
| 40 |
|
|
if ($@) { |
| 41 |
|
|
*gettext = sub { shift }; |
| 42 |
|
|
*textdomain = sub { "" }; |
| 43 |
|
|
*LC_MESSAGES = sub { 5 }; |
| 44 |
|
|
} |
| 45 |
|
|
eval { |
| 46 |
|
|
require POSIX; |
| 47 |
|
|
import POSIX qw(setlocale); |
| 48 |
|
|
}; |
| 49 |
|
|
if ($@) { |
| 50 |
zugschlus |
286 |
*setlocale = sub { return 1 }; |
| 51 |
rb |
6 |
} |
| 52 |
zugschlus |
350 |
eval { |
| 53 |
|
|
require I18N::Langinfo; |
| 54 |
|
|
import I18N::Langinfo qw(langinfo YESEXPR); |
| 55 |
|
|
}; |
| 56 |
|
|
if ($@) { |
| 57 |
|
|
*langinfo = sub { "^[yY]" }; |
| 58 |
|
|
*YESEXPR = sub { 1 }; |
| 59 |
|
|
} |
| 60 |
rb |
6 |
} |
| 61 |
|
|
|
| 62 |
|
|
setlocale(LC_MESSAGES, ""); |
| 63 |
|
|
textdomain("adduser"); |
| 64 |
zugschlus |
350 |
my $yesexpr = langinfo(YESEXPR()); |
| 65 |
rb |
6 |
|
| 66 |
zugschlus |
286 |
my %config; # configuration hash |
| 67 |
rb |
1 |
|
| 68 |
zugschlus |
330 |
my @defaults = ("/etc/adduser.conf"); |
| 69 |
zugschlus |
286 |
my $nogroup_id = getgrnam("nogroup") || 65534; |
| 70 |
rb |
1 |
$0 =~ s+.*/++; |
| 71 |
|
|
|
| 72 |
joerghoh-guest |
528 |
our $verbose = 1; # should we be verbose? |
| 73 |
|
|
my $allow_badname = 0; # should we allow bad names? |
| 74 |
|
|
my $ask_passwd = 1; # ask for a passwd? |
| 75 |
|
|
my $disabled_login = 0; # leave the new account disabled? |
| 76 |
rb |
1 |
|
| 77 |
joerghoh-guest |
528 |
our $configfile = undef; |
| 78 |
|
|
our $found_group_opt = undef; |
| 79 |
|
|
our $found_sys_opt = undef; |
| 80 |
|
|
our $ingroup_name = undef; |
| 81 |
|
|
our $new_firstuid = undef; |
| 82 |
|
|
our $new_gecos = undef; |
| 83 |
|
|
our $new_gid = undef; |
| 84 |
|
|
our $new_lastuid = undef; |
| 85 |
|
|
our $new_uid = undef; |
| 86 |
|
|
our $no_create_home = undef; |
| 87 |
|
|
our $special_home = undef; |
| 88 |
|
|
our $special_shell = undef; |
| 89 |
zugschlus |
557 |
our $add_extra_groups = 0; |
| 90 |
joerghoh-guest |
528 |
|
| 91 |
|
|
# Global variables we need later |
| 92 |
|
|
my $existing_user = undef; |
| 93 |
|
|
my $existing_group = undef; |
| 94 |
|
|
my $new_name = undef; |
| 95 |
|
|
my $make_group_also = 0; |
| 96 |
|
|
my $home_dir = undef; |
| 97 |
|
|
my $undohome = undef; |
| 98 |
|
|
my $undouser = undef; |
| 99 |
|
|
my $undogroup = undef; |
| 100 |
|
|
my $shell = undef; |
| 101 |
|
|
my $first_uid = undef; |
| 102 |
|
|
my $last_uid = undef; |
| 103 |
|
|
my $dir_mode = undef; |
| 104 |
|
|
my $perm = undef; |
| 105 |
|
|
|
| 106 |
joerghoh-guest |
539 |
our @names; |
| 107 |
joerghoh-guest |
528 |
|
| 108 |
zugschlus |
255 |
# Parse options, sanity checks |
| 109 |
zugschlus |
559 |
unless ( GetOptions ("quiet" => sub { $verbose = 0 }, |
| 110 |
zugschlus |
255 |
"force-badname" => \$allow_badname, |
| 111 |
|
|
"help|h" => sub { &usage(); exit 0 }, |
| 112 |
|
|
"version" => sub { &version(); exit 0 }, |
| 113 |
|
|
"system" => \$found_sys_opt, |
| 114 |
|
|
"group" => \$found_group_opt, |
| 115 |
|
|
"ingroup=s" => \$ingroup_name, |
| 116 |
|
|
"home=s" => \$special_home, |
| 117 |
|
|
"gecos=s" => \$new_gecos, |
| 118 |
|
|
"shell=s" => \$special_shell, |
| 119 |
zugschlus |
337 |
"disabled-password" => sub { $ask_passwd = 0 }, |
| 120 |
zugschlus |
306 |
"disabled-login" => sub { $disabled_login = 1; $ask_passwd = 0 }, |
| 121 |
zugschlus |
255 |
"uid=i" => \$new_uid, |
| 122 |
|
|
"firstuid=i" => \$new_firstuid, |
| 123 |
|
|
"lastuid=i" => \$new_lastuid, |
| 124 |
|
|
"gid=i" => \$new_gid, |
| 125 |
zugschlus |
330 |
"conf=s" => \$configfile, |
| 126 |
zugschlus |
255 |
"no-create-home" => \$no_create_home, |
| 127 |
zugschlus |
557 |
"add_extra_groups" => \$add_extra_groups, |
| 128 |
zugschlus |
561 |
"debug" => sub { $verbose = 2 } ) ) { |
| 129 |
zugschlus |
559 |
&usage; |
| 130 |
|
|
exit 1; |
| 131 |
|
|
} |
| 132 |
zugschlus |
255 |
|
| 133 |
zugschlus |
257 |
# everyone can issue "--help" and "--version", but only root can go on |
| 134 |
zugschlus |
559 |
dief (gtx("Only root may add a user or group to the system.\n")) if ($> != 0); |
| 135 |
zugschlus |
255 |
|
| 136 |
zugschlus |
330 |
if( defined($configfile) ) { @defaults = ($configfile); } |
| 137 |
zugschlus |
255 |
|
| 138 |
zugschlus |
286 |
# detect the right mode |
| 139 |
|
|
my $action = $0 eq "addgroup" ? "addgroup" : "adduser"; |
| 140 |
zugschlus |
255 |
if (defined($found_sys_opt)) { |
| 141 |
|
|
$action = "addsysuser" if ($action eq "adduser"); |
| 142 |
|
|
$action = "addsysgroup" if ($action eq "addgroup"); |
| 143 |
|
|
} |
| 144 |
rb |
1 |
|
| 145 |
|
|
|
| 146 |
zugschlus |
255 |
|
| 147 |
zugschlus |
257 |
############################ |
| 148 |
|
|
# checks related to @names # |
| 149 |
|
|
############################ |
| 150 |
zugschlus |
255 |
|
| 151 |
zugschlus |
257 |
|
| 152 |
joerghoh-guest |
528 |
while (defined(my $arg = shift(@ARGV))) { |
| 153 |
joerghoh-guest |
549 |
push (@names, $arg); |
| 154 |
zugschlus |
120 |
} |
| 155 |
|
|
|
| 156 |
joerghoh-guest |
385 |
if ( (! defined $names[0]) || length($names[0]) == 0 || @names > 2) { |
| 157 |
zugschlus |
559 |
dief (gtx("Only one or two names allowed.\n")); |
| 158 |
zugschlus |
350 |
} |
| 159 |
zugschlus |
257 |
|
| 160 |
zugschlus |
255 |
|
| 161 |
rb |
1 |
if (@names == 2) { # must be addusertogroup |
| 162 |
zugschlus |
559 |
dief (gtx("Specify only one name in this mode.\n")) |
| 163 |
rb |
1 |
if ($action eq "addsysuser" || $found_group_opt); |
| 164 |
|
|
$action = "addusertogroup"; |
| 165 |
|
|
$existing_user = shift (@names); |
| 166 |
|
|
$existing_group = shift (@names); |
| 167 |
|
|
} |
| 168 |
|
|
else { |
| 169 |
|
|
$new_name = shift (@names); |
| 170 |
|
|
} |
| 171 |
|
|
|
| 172 |
zugschlus |
257 |
################################### |
| 173 |
|
|
# check for consistent parameters # |
| 174 |
|
|
################################### |
| 175 |
|
|
|
| 176 |
zugschlus |
287 |
if ($action ne "addgroup" && |
| 177 |
zugschlus |
293 |
defined($found_group_opt) +defined($ingroup_name) +defined($new_gid) > 1 ) { |
| 178 |
zugschlus |
559 |
dief (gtx("The --group, --ingroup, and --gid options are mutually exclusive.\n")); |
| 179 |
zugschlus |
287 |
} |
| 180 |
zugschlus |
257 |
|
| 181 |
|
|
|
| 182 |
|
|
if ((defined($special_home)) && ($special_home !~ m+^/+ )) { |
| 183 |
zugschlus |
559 |
dief (gtx("The home dir must be an absolute path.\n")); |
| 184 |
zugschlus |
257 |
} |
| 185 |
|
|
|
| 186 |
|
|
if (defined($special_home) && $verbose) { |
| 187 |
zugschlus |
559 |
print gtx("Warning: The home dir you specified already exists.\n") |
| 188 |
zugschlus |
257 |
if (!defined($no_create_home) && -d $special_home); |
| 189 |
zugschlus |
559 |
print gtx("Warning: The home dir you specified does not exist.\n") |
| 190 |
zugschlus |
257 |
if (defined($no_create_home) && ! -d $special_home); |
| 191 |
|
|
} |
| 192 |
|
|
|
| 193 |
|
|
|
| 194 |
rb |
1 |
if ($found_group_opt) { |
| 195 |
|
|
if ($action eq "addsysuser") { |
| 196 |
|
|
$make_group_also = 1; |
| 197 |
|
|
} |
| 198 |
rb |
82 |
elsif ($found_sys_opt) { |
| 199 |
|
|
$action = "addsysgroup"; |
| 200 |
|
|
} |
| 201 |
rb |
1 |
else { |
| 202 |
|
|
$action = "addgroup"; |
| 203 |
|
|
} |
| 204 |
|
|
} |
| 205 |
|
|
|
| 206 |
|
|
|
| 207 |
joerghoh-guest |
385 |
$ENV{"VERBOSE"} = $verbose; |
| 208 |
joerghoh-guest |
395 |
$ENV{"DEBUG"} = $verbose; |
| 209 |
zugschlus |
130 |
|
| 210 |
joerghoh-guest |
385 |
|
| 211 |
joerghoh-guest |
383 |
# preseed configuration data and then read the config file |
| 212 |
zugschlus |
330 |
preseed_config(\@defaults,\%config); |
| 213 |
zugschlus |
130 |
|
| 214 |
zugschlus |
286 |
&checkname($new_name) if defined $new_name; |
| 215 |
|
|
$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler'; |
| 216 |
|
|
|
| 217 |
rb |
1 |
##### |
| 218 |
|
|
# OK, we've processed the arguments. $action equals one of the following, |
| 219 |
|
|
# and the appropriate variables have been set: |
| 220 |
|
|
# |
| 221 |
|
|
# $action = "adduser" |
| 222 |
|
|
# $new_name - the name of the new user. |
| 223 |
|
|
# $ingroup_name | $new_gid - the group to add the user to |
| 224 |
|
|
# $special_home, $new_uid, $new_gecos - optional overrides |
| 225 |
|
|
# $action = "addgroup" |
| 226 |
|
|
# $new_name - the name of the new group |
| 227 |
|
|
# $new_gid - optional override |
| 228 |
rb |
82 |
# $action = "addsysgroup" |
| 229 |
|
|
# $new_name - the name of the new group |
| 230 |
|
|
# $new_gid - optional override |
| 231 |
rb |
1 |
# $action = "addsysuser" |
| 232 |
|
|
# $new_name - the name of the new user |
| 233 |
|
|
# $make_group_also | $ingroup_name | $new_gid | 0 - which group |
| 234 |
|
|
# $special_home, $new_uid, $new_gecos - optional overrides |
| 235 |
|
|
# $action = "addusertogroup" |
| 236 |
|
|
# $existing_user - the user to be added |
| 237 |
|
|
# $existing_group - the group to add her to |
| 238 |
|
|
##### |
| 239 |
|
|
|
| 240 |
|
|
|
| 241 |
rb |
82 |
################# |
| 242 |
|
|
## addsysgroup ## |
| 243 |
|
|
################# |
| 244 |
|
|
if ($action eq "addsysgroup") { |
| 245 |
zugschlus |
112 |
# Check if requested group already exists and we can exit safely |
| 246 |
joerghoh-guest |
476 |
if (existing_group_ok($new_name, $new_gid) == 1) { |
| 247 |
zugschlus |
330 |
printf (gtx("The group `%s' already exists as a system group. Exiting...\n"), $new_name) if $verbose; |
| 248 |
zugschlus |
112 |
exit 0; |
| 249 |
|
|
} |
| 250 |
joerghoh-guest |
476 |
if (existing_group_ok($new_name, $new_gid) == 2) { |
| 251 |
|
|
printf (gtx("The group `%s' already exists, but has a different gid, aborting...\n"), $new_name) if $verbose; |
| 252 |
|
|
exit 1; |
| 253 |
|
|
} |
| 254 |
|
|
|
| 255 |
zugschlus |
330 |
dief (gtx("The group `%s' already exists and is not a system group.\n"),$new_name) |
| 256 |
rb |
82 |
if (defined getgrnam($new_name)); |
| 257 |
zugschlus |
330 |
dief (gtx("The GID `%s' is already in use.\n"),$new_gid) |
| 258 |
rb |
82 |
if (defined($new_gid) && defined(getgrgid($new_gid))); |
| 259 |
|
|
if (!defined($new_gid)) { |
| 260 |
joerghoh-guest |
448 |
$new_gid = &first_avail_gid($config{"first_system_gid"}, |
| 261 |
|
|
$config{"last_system_gid"}); |
| 262 |
rb |
82 |
|
| 263 |
|
|
if ($new_gid == -1) { |
| 264 |
zugschlus |
350 |
print STDERR "$0: "; |
| 265 |
|
|
printf STDERR gtx("No GID is available in the range %d-%d (FIRST_SYS_GID - LAST_SYS_GID).\n"),$config{"first_system_gid"},$config{"last_system_gid"}; |
| 266 |
zugschlus |
330 |
dief (gtx("The group `%s' was not created.\n"),$new_name); |
| 267 |
rb |
82 |
} |
| 268 |
|
|
} |
| 269 |
|
|
|
| 270 |
zugschlus |
330 |
printf (gtx("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose; |
| 271 |
rb |
82 |
&invalidate_nscd("group"); |
| 272 |
|
|
&systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); |
| 273 |
|
|
&invalidate_nscd("group"); |
| 274 |
zugschlus |
330 |
print (gtx("Done.\n")) if $verbose; |
| 275 |
rb |
82 |
exit 0; |
| 276 |
|
|
} |
| 277 |
|
|
|
| 278 |
|
|
|
| 279 |
rb |
1 |
############## |
| 280 |
|
|
## addgroup ## |
| 281 |
|
|
############## |
| 282 |
|
|
if ($action eq "addgroup") { |
| 283 |
zugschlus |
330 |
dief (gtx("The group `%s' already exists.\n"),$new_name) |
| 284 |
rb |
13 |
if (defined getgrnam($new_name)); |
| 285 |
zugschlus |
330 |
dief (gtx("The GID `%s' is already in use.\n"),$new_gid) |
| 286 |
rb |
13 |
if (defined($new_gid) && defined(getgrgid($new_gid))); |
| 287 |
rb |
1 |
if (!defined($new_gid)) { |
| 288 |
joerghoh-guest |
448 |
$new_gid = &first_avail_gid($config{"first_gid"}, |
| 289 |
|
|
$config{"last_gid"}); |
| 290 |
rb |
82 |
|
| 291 |
rb |
6 |
if ($new_gid == -1) { |
| 292 |
zugschlus |
350 |
print STDERR "$0: "; |
| 293 |
|
|
printf STDERR gtx("No GID is available in the range %d-%d (FIRST_GID - LAST_GID).\n"),$config{"first_gid"},$config{"last_gid"}; |
| 294 |
zugschlus |
330 |
dief (gtx("The group `%s' was not created.\n"),$new_name); |
| 295 |
rb |
6 |
} |
| 296 |
rb |
1 |
} |
| 297 |
|
|
|
| 298 |
zugschlus |
330 |
printf (gtx("Adding group `%s' (%s)...\n"),$new_name,$new_gid) if $verbose; |
| 299 |
rb |
15 |
&invalidate_nscd("group"); |
| 300 |
rb |
82 |
&systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); |
| 301 |
rb |
15 |
&invalidate_nscd("group"); |
| 302 |
zugschlus |
330 |
print (gtx("Done.\n")) if $verbose; |
| 303 |
rb |
1 |
exit 0; |
| 304 |
|
|
} |
| 305 |
|
|
|
| 306 |
|
|
|
| 307 |
|
|
#################### |
| 308 |
|
|
## addusertogroup ## |
| 309 |
|
|
#################### |
| 310 |
zugschlus |
256 |
if ($action eq "addusertogroup") { |
| 311 |
zugschlus |
330 |
dief (gtx("The user `%s' does not exist.\n"),$existing_user) |
| 312 |
rb |
8 |
if (!defined getpwnam($existing_user)); |
| 313 |
zugschlus |
330 |
dief (gtx("The group `%s' does not exist.\n"),$existing_group) |
| 314 |
rb |
15 |
if (!defined getgrnam($existing_group)); |
| 315 |
rb |
1 |
if (&user_is_member($existing_user, $existing_group)) { |
| 316 |
zugschlus |
332 |
printf gtx("The user `%s' is already a member of `%s'.\n"), |
| 317 |
|
|
$existing_user,$existing_group if $verbose; |
| 318 |
rb |
1 |
exit 0; # not really an error |
| 319 |
|
|
} |
| 320 |
|
|
|
| 321 |
zugschlus |
330 |
printf gtx("Adding user `%s' to group `%s'...\n"),$existing_user,$existing_group |
| 322 |
rb |
1 |
if $verbose; |
| 323 |
rb |
15 |
&invalidate_nscd(); |
| 324 |
rb |
6 |
# FIXME - the next line has a race condition. |
| 325 |
rb |
15 |
#&systemcall('usermod', '-G', |
| 326 |
|
|
#join(",", get_users_groups($existing_user), $existing_group), |
| 327 |
|
|
#$existing_user); |
| 328 |
rb |
82 |
&systemcall('/usr/bin/gpasswd', '-M', |
| 329 |
rb |
15 |
join(',', get_group_members($existing_group), $existing_user), |
| 330 |
|
|
$existing_group); |
| 331 |
rb |
17 |
#&systemcall('gpasswd', '-a',$existing_user,$existing_group); |
| 332 |
rb |
15 |
&invalidate_nscd(); |
| 333 |
zugschlus |
330 |
print (gtx("Done.\n")) if $verbose; |
| 334 |
rb |
1 |
exit 0; |
| 335 |
|
|
} |
| 336 |
|
|
|
| 337 |
|
|
|
| 338 |
|
|
################ |
| 339 |
|
|
## addsysuser ## |
| 340 |
|
|
################ |
| 341 |
zugschlus |
256 |
if ($action eq "addsysuser") { |
| 342 |
joerghoh-guest |
468 |
if (existing_user_ok($new_name, $new_uid) == 1) { |
| 343 |
zugschlus |
330 |
printf (gtx("The user `%s' already exists as a system user. Exiting...\n"), $new_name) if $verbose; |
| 344 |
rb |
37 |
exit 0; |
| 345 |
|
|
} |
| 346 |
joerghoh-guest |
468 |
if (existing_user_ok($new_name, $new_uid) == 2) { |
| 347 |
|
|
printf (gtx("The user `%s' already exists with a different uid. Aborting\n"), $new_name) if $verbose; |
| 348 |
|
|
exit 1; |
| 349 |
|
|
} |
| 350 |
|
|
|
| 351 |
zugschlus |
508 |
if (!$ingroup_name && !defined($new_gid) && !$make_group_also) { |
| 352 |
|
|
$new_gid = $nogroup_id; |
| 353 |
|
|
} |
| 354 |
zugschlus |
112 |
check_user_group(1); |
| 355 |
rb |
1 |
|
| 356 |
|
|
if (!defined($new_uid) && $make_group_also) { |
| 357 |
joerghoh-guest |
448 |
$new_uid = &first_avail_uid($config{"first_system_uid"}, |
| 358 |
|
|
$config{"last_system_uid"}); |
| 359 |
rb |
6 |
if ($new_uid == -1) { |
| 360 |
zugschlus |
350 |
print STDERR "$0: "; |
| 361 |
|
|
printf STDERR gtx("No UID/GID pair is available in the range %d-%d (FIRST_SYS_UID - LAST_SYS_UID).\n"),$config{"first_system_uid"},$config{"last_system_uid"}; |
| 362 |
zugschlus |
330 |
dief (gtx("The user `%s' was not created.\n"),$new_name); |
| 363 |
rb |
6 |
} |
| 364 |
zugschlus |
508 |
$new_gid = &first_avail_gid($config{"first_system_gid"}, |
| 365 |
|
|
$config{"last_system_gid"}); |
| 366 |
rb |
1 |
$ingroup_name = $new_name; |
| 367 |
|
|
} |
| 368 |
|
|
elsif (!defined($new_uid) && !$make_group_also) { |
| 369 |
joerghoh-guest |
448 |
$new_uid = &first_avail_uid($config{"first_system_uid"}, |
| 370 |
|
|
$config{"last_system_uid"}); |
| 371 |
rb |
6 |
if ($new_uid == -1) { |
| 372 |
zugschlus |
350 |
print STDERR "$0: "; |
| 373 |
|
|
printf STDERR gtx("No UID is available in the range %d-%d (FIRST_SYS_UID - LAST_SYS_UID).\n"),$config{"first_system_uid"},$config{"last_system_uid"}; |
| 374 |
|
|
dief (gtx("The user `%s' was not created.\n"),$new_name); |
| 375 |
rb |
6 |
} |
| 376 |
|
|
if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } |
| 377 |
rb |
1 |
elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } |
| 378 |
joerghoh-guest |
549 |
else { dief (gtx("Internal error")); } |
| 379 |
rb |
1 |
} |
| 380 |
|
|
else { |
| 381 |
|
|
if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } |
| 382 |
|
|
elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } |
| 383 |
|
|
elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; } |
| 384 |
joerghoh-guest |
549 |
else { dief (gtx("Internal error")); } |
| 385 |
rb |
1 |
} |
| 386 |
joerghoh-guest |
489 |
printf (gtx("Adding system user `%s' with uid %s...\n"),$new_name,$new_uid) if $verbose; |
| 387 |
rb |
82 |
|
| 388 |
rb |
15 |
&invalidate_nscd(); |
| 389 |
zugschlus |
112 |
# if we reach this point, and the group does already exist, we can use it. |
| 390 |
zugschlus |
287 |
if ($make_group_also && !getgrnam($new_name)) { |
| 391 |
zugschlus |
330 |
printf (gtx("Adding new group `%s' (%s).\n"),$new_name,$new_gid) if $verbose; |
| 392 |
rb |
1 |
$undogroup = $new_name; |
| 393 |
rb |
82 |
&systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); |
| 394 |
rb |
29 |
&invalidate_nscd("group"); |
| 395 |
rb |
1 |
} |
| 396 |
|
|
|
| 397 |
zugschlus |
330 |
printf gtx("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name |
| 398 |
rb |
1 |
if $verbose; |
| 399 |
|
|
$home_dir = $special_home || &homedir($new_name, $ingroup_name); |
| 400 |
rb |
56 |
$shell = $special_shell || '/bin/false'; |
| 401 |
rb |
1 |
$undouser = $new_name; |
| 402 |
rb |
82 |
&systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s', |
| 403 |
rb |
56 |
$shell, '-u', $new_uid, $new_name); |
| 404 |
joerghoh-guest |
383 |
print "/usr/bin/chage -M 99999 $new_name\n" if ($verbose > 1); |
| 405 |
zugschlus |
410 |
# do _not_ use systemcall() here, since systemcall() dies on |
| 406 |
|
|
# non-zero exit code and we need to do special handling here! |
| 407 |
|
|
if (system('/usr/bin/chage', '-M', '99999', $new_name)) { |
| 408 |
zugschlus |
274 |
if( ($?>>8) ne 15 ) { |
| 409 |
zugschlus |
239 |
&cleanup("$0: `/usr/bin/chage -M 99999 $new_name' returned error code " . ($?>>8) . ". Aborting.\n") |
| 410 |
zugschlus |
234 |
if ($?>>8); |
| 411 |
zugschlus |
239 |
&cleanup("$0: `/usr/bin/chage -M 99999 $new_name' exited from signal " . ($?&255) . ". Aborting.\n"); |
| 412 |
zugschlus |
234 |
} else { |
| 413 |
zugschlus |
330 |
print (gtx("chage failed with return code 15, shadow not enabled, password aging cannot be set. Continuing.\n")); |
| 414 |
zugschlus |
234 |
} |
| 415 |
|
|
} |
| 416 |
rb |
15 |
&invalidate_nscd(); |
| 417 |
rb |
1 |
|
| 418 |
rb |
33 |
if(defined($new_gecos)) { |
| 419 |
rb |
8 |
&ch_gecos($new_gecos); |
| 420 |
|
|
} |
| 421 |
|
|
|
| 422 |
zugschlus |
293 |
create_homedir (0); |
| 423 |
rb |
1 |
|
| 424 |
|
|
exit 0; |
| 425 |
|
|
} |
| 426 |
|
|
|
| 427 |
|
|
|
| 428 |
|
|
############# |
| 429 |
|
|
## adduser ## |
| 430 |
|
|
############# |
| 431 |
zugschlus |
256 |
if ($action eq "adduser") { |
| 432 |
rb |
1 |
if (!$ingroup_name && !defined($new_gid)) { |
| 433 |
zugschlus |
256 |
if ($config{"usergroups"} =~ /yes/i) { $make_group_also = 1; } |
| 434 |
rb |
1 |
else { $new_gid = $config{"users_gid"}; } |
| 435 |
|
|
} |
| 436 |
zugschlus |
112 |
check_user_group(0); |
| 437 |
rb |
43 |
$first_uid = $new_firstuid || $config{"first_uid"}; |
| 438 |
|
|
$last_uid = $new_lastuid || $config{"last_uid"}; |
| 439 |
zugschlus |
330 |
printf (gtx("Adding user `%s'...\n"),$new_name) if $verbose; |
| 440 |
rb |
1 |
|
| 441 |
|
|
if (!defined($new_uid) && $make_group_also) { |
| 442 |
joerghoh-guest |
448 |
$new_uid = &first_avail_uid($first_uid, |
| 443 |
|
|
$last_uid); |
| 444 |
|
|
|
| 445 |
rb |
6 |
if ($new_uid == -1) { |
| 446 |
zugschlus |
350 |
print STDERR "$0: "; |
| 447 |
|
|
printf STDERR gtx("No UID/GID pair is available in the range %d-%d (FIRST_UID - LAST_UID).\n"),$first_uid,$last_uid; |
| 448 |
|
|
dief (gtx("The user `%s' was not created.\n"),$new_name); |
| 449 |
rb |
6 |
} |
| 450 |
zugschlus |
508 |
$new_gid = &first_avail_gid($config{"first_gid"}, |
| 451 |
|
|
$config{"last_gid"}); |
| 452 |
rb |
1 |
$ingroup_name = $new_name; |
| 453 |
|
|
} |
| 454 |
|
|
elsif (!defined($new_uid) && !$make_group_also) { |
| 455 |
joerghoh-guest |
448 |
$new_uid = &first_avail_uid($first_uid, |
| 456 |
|
|
$last_uid); |
| 457 |
rb |
6 |
if ($new_uid == -1) { |
| 458 |
zugschlus |
350 |
print STDERR "$0: "; |
| 459 |
|
|
printf STDERR gtx("No UID is available in the range %d-%d (FIRST_UID - LAST_UID).\n"),$config{"first_uid"},$config{"last_uid"}; |
| 460 |
zugschlus |
330 |
dief (gtx("The user `%s' was not created.\n"),$new_name); |
| 461 |
rb |
6 |
} |
| 462 |
rb |
1 |
if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } |
| 463 |
|
|
elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } |
| 464 |
joerghoh-guest |
549 |
else { dief (gtx("Internal error")); } |
| 465 |
rb |
1 |
} |
| 466 |
|
|
else { |
| 467 |
|
|
if (defined($new_gid)) { $ingroup_name = getgrgid($new_gid); } |
| 468 |
|
|
elsif ($ingroup_name) { $new_gid = getgrnam($ingroup_name); } |
| 469 |
|
|
elsif ($make_group_also){ $new_gid=$new_uid; $ingroup_name=$new_name; } |
| 470 |
joerghoh-guest |
549 |
else { dien (gtx("Internal error")); } |
| 471 |
rb |
1 |
} |
| 472 |
|
|
|
| 473 |
rb |
15 |
&invalidate_nscd(); |
| 474 |
rb |
1 |
if ($make_group_also) { |
| 475 |
zugschlus |
330 |
printf (gtx("Adding new group `%s' (%s).\n"),$new_name,$new_gid) if $verbose; |
| 476 |
rb |
1 |
$undogroup = $new_name; |
| 477 |
rb |
82 |
&systemcall('/usr/sbin/groupadd', '-g', $new_gid, $new_name); |
| 478 |
rb |
15 |
&invalidate_nscd(); |
| 479 |
rb |
1 |
} |
| 480 |
|
|
|
| 481 |
zugschlus |
330 |
printf gtx("Adding new user `%s' (%s) with group `%s'.\n"),$new_name,$new_uid,$ingroup_name |
| 482 |
rb |
1 |
if $verbose; |
| 483 |
|
|
$home_dir = $special_home || &homedir($new_name, $ingroup_name); |
| 484 |
rb |
56 |
$shell = $special_shell || $config{"dshell"}; |
| 485 |
rb |
1 |
$undouser = $new_name; |
| 486 |
rb |
82 |
&systemcall('/usr/sbin/useradd', '-d', $home_dir, '-g', $ingroup_name, '-s', |
| 487 |
rb |
56 |
$shell, '-u', $new_uid, $new_name); |
| 488 |
rb |
15 |
&invalidate_nscd(); |
| 489 |
rb |
1 |
|
| 490 |
zugschlus |
293 |
create_homedir (1); # copy skeleton data |
| 491 |
rb |
1 |
|
| 492 |
zugschlus |
223 |
# useradd without -p has left the account disabled (password string is '!') |
| 493 |
rb |
1 |
if ($ask_passwd) { |
| 494 |
joerghoh-guest |
400 |
for (;;) { |
| 495 |
|
|
&systemcall('/usr/bin/passwd', $new_name); |
| 496 |
|
|
my $ok = $? & 128; |
| 497 |
|
|
if ($ok != 0) { |
| 498 |
|
|
my $noexpr = langinfo(NOEXPR()); |
| 499 |
|
|
my $answer; |
| 500 |
|
|
# hm, error, should we break now? |
| 501 |
|
|
print (gtx("Permission denied\n")) if ($ok == 1); |
| 502 |
|
|
print (gtx("invalid combination of options\n")) if ($ok == 2); |
| 503 |
|
|
print (gtx("unexpected failure, nothing done\n")) if ($ok == 3); |
| 504 |
|
|
print (gtx("unexpected failure, passwd file missing\n")) if ($ok == 3); |
| 505 |
|
|
print (gtx("passwd file busy, try again\n")) if ($ok == 4); |
| 506 |
|
|
print (gtx("invalid argument to option\n")) if ($ok == 5); |
| 507 |
|
|
|
| 508 |
|
|
# Translators: [y/N] has to be replaced by values defined in your |
| 509 |
|
|
# locale. You can see by running "locale noexpr" which regular |
| 510 |
|
|
# expression will be checked to find positive answer. |
| 511 |
joerghoh-guest |
445 |
print (gtx("Try again(Y/n)?")); |
| 512 |
joerghoh-guest |
400 |
chop ($answer=<STDIN>); |
| 513 |
|
|
last if ($answer =~ m/$noexpr/o); |
| 514 |
|
|
} |
| 515 |
|
|
else { |
| 516 |
|
|
last; ## passwd ok |
| 517 |
|
|
} |
| 518 |
|
|
} |
| 519 |
rb |
56 |
} else { |
| 520 |
|
|
if(!$disabled_login) { |
| 521 |
rb |
82 |
&systemcall('/usr/sbin/usermod', '-p', '*', $new_name); |
| 522 |
rb |
56 |
} |
| 523 |
rb |
1 |
} |
| 524 |
|
|
|
| 525 |
rb |
33 |
if (defined($new_gecos)) { |
| 526 |
rb |
8 |
&ch_gecos($new_gecos); |
| 527 |
rb |
1 |
} |
| 528 |
|
|
else { |
| 529 |
zugschlus |
348 |
my $yesexpr = langinfo(YESEXPR()); |
| 530 |
rb |
1 |
for (;;) { |
| 531 |
rb |
82 |
&systemcall('/usr/bin/chfn', $new_name); |
| 532 |
zugschlus |
348 |
# Translators: [y/N] has to be replaced by values defined in your |
| 533 |
|
|
# locale. You can see by running "locale yesexpr" which regular |
| 534 |
|
|
# expression will be checked to find positive answer. |
| 535 |
zugschlus |
330 |
print (gtx("Is the information correct? [y/N] ")); |
| 536 |
joerghoh-guest |
528 |
chop (my $answer=<STDIN>); |
| 537 |
zugschlus |
348 |
last if ($answer =~ m/$yesexpr/o); |
| 538 |
rb |
1 |
} |
| 539 |
|
|
} |
| 540 |
|
|
|
| 541 |
zugschlus |
557 |
if ( ( $add_extra_groups || $config{"add_extra_groups"} ) && defined($config{"extra_groups"}) ) { |
| 542 |
|
|
printf (gtx("Adding new user `%s' to extra groups\n"), $new_name); |
| 543 |
|
|
foreach my $newgrp ( split ' ', $config{"extra_groups"} ) { |
| 544 |
|
|
if (!defined getgrnam($newgrp)) { |
| 545 |
|
|
warnf (gtx("The group `%s' does not exist.\n"),$newgrp); |
| 546 |
|
|
next; |
| 547 |
|
|
} |
| 548 |
|
|
if (&user_is_member($new_name, $newgrp)) { |
| 549 |
|
|
printf gtx("The user `%s' is already a member of `%s'.\n"), |
| 550 |
|
|
$new_name,$newgrp if $verbose; |
| 551 |
|
|
next; |
| 552 |
|
|
|
| 553 |
|
|
} |
| 554 |
|
|
|
| 555 |
|
|
printf gtx("Adding user `%s' to group `%s'...\n"),$new_name,$newgrp |
| 556 |
|
|
if $verbose; |
| 557 |
|
|
&invalidate_nscd(); |
| 558 |
|
|
&systemcall('/usr/bin/gpasswd', '-M', |
| 559 |
|
|
join(',', get_group_members($newgrp), $new_name), |
| 560 |
|
|
$newgrp); |
| 561 |
|
|
&invalidate_nscd(); |
| 562 |
|
|
} |
| 563 |
|
|
} |
| 564 |
|
|
|
| 565 |
|
|
|
| 566 |
rb |
1 |
if ($config{"quotauser"}) { |
| 567 |
zugschlus |
330 |
printf (gtx("Setting quota from `%s'.\n"),$config{quotauser}); |
| 568 |
rb |
82 |
&systemcall('/usr/sbin/edquota', '-p', $config{quotauser}, $new_name); |
| 569 |
rb |
1 |
} |
| 570 |
|
|
|
| 571 |
|
|
&systemcall('/usr/local/sbin/adduser.local', $new_name, $new_uid, |
| 572 |
|
|
$new_gid, $home_dir) if (-x "/usr/local/sbin/adduser.local"); |
| 573 |
|
|
|
| 574 |
|
|
exit 0; |
| 575 |
|
|
} |
| 576 |
|
|
|
| 577 |
zugschlus |
256 |
# |
| 578 |
|
|
# we never go here |
| 579 |
|
|
# |
| 580 |
rb |
1 |
|
| 581 |
zugschlus |
256 |
|
| 582 |
rb |
1 |
# calculate home directory |
| 583 |
|
|
sub homedir { |
| 584 |
|
|
my $dir = $config{"dhome"}; |
| 585 |
|
|
$dir .= '/' . $_[1] if ($config{"grouphomes"} =~ /yes/i); |
| 586 |
|
|
$dir .= '/' . substr($_[0],0,1) if ($config{"letterhomes"} =~ /yes/i); |
| 587 |
|
|
$dir .= '/' . $_[0]; |
| 588 |
zugschlus |
256 |
return $dir; |
| 589 |
rb |
1 |
} |
| 590 |
|
|
|
| 591 |
|
|
|
| 592 |
zugschlus |
293 |
# create_homedir -- create the homedirectory |
| 593 |
|
|
# parameter 1: $copy_skeleton: |
| 594 |
|
|
# if 0 -> don't copy the skeleton data |
| 595 |
|
|
# if 1 -> copy the files in /etc/skel to the newly created home directory |
| 596 |
|
|
sub create_homedir { |
| 597 |
zugschlus |
306 |
my ($copy_skeleton) = @_; |
| 598 |
zugschlus |
293 |
|
| 599 |
|
|
if ($no_create_home) { |
| 600 |
zugschlus |
351 |
printf gtx("Not creating home directory `%s'.\n"), $home_dir if $verbose; |
| 601 |
zugschlus |
293 |
} |
| 602 |
|
|
elsif (-e $home_dir) { |
| 603 |
zugschlus |
330 |
printf gtx("The home directory `%s' already exists. Not copying from `%s'\n"), |
| 604 |
zugschlus |
293 |
$home_dir,$config{skel} if $verbose && !$no_create_home; |
| 605 |
|
|
my @homedir_stat = stat($home_dir); |
| 606 |
|
|
my $home_uid = $homedir_stat[4]; |
| 607 |
|
|
my $home_gid = $homedir_stat[5]; |
| 608 |
|
|
if (($home_uid != $new_uid) || ($home_gid != $new_gid)) { |
| 609 |
zugschlus |
350 |
warnf gtx("Warning: that home directory does not belong to the user you are currently creating\n"); |
| 610 |
zugschlus |
293 |
} |
| 611 |
|
|
undef @homedir_stat; undef $home_uid; undef $home_gid; |
| 612 |
|
|
} |
| 613 |
|
|
else { |
| 614 |
zugschlus |
330 |
printf gtx("Creating home directory `%s'.\n"),$home_dir if $verbose; |
| 615 |
zugschlus |
293 |
$undohome = $home_dir; |
| 616 |
|
|
&mktree($home_dir) || &cleanup("Couldn't create $home_dir: $!.\n"); |
| 617 |
|
|
chown($new_uid, $new_gid, $home_dir) |
| 618 |
|
|
|| &cleanup("chown $new_uid:$new_gid $home_dir: $!\n"); |
| 619 |
|
|
$dir_mode = get_dir_mode($make_group_also); |
| 620 |
|
|
chmod ($dir_mode, $home_dir) || |
| 621 |
|
|
&cleanup("chmod $dir_mode $home_dir: $!\n"); |
| 622 |
|
|
|
| 623 |
|
|
if ($config{"skel"} && $copy_skeleton) { |
| 624 |
zugschlus |
330 |
printf gtx("Copying files from `%s'\n"),$config{skel} if $verbose; |
| 625 |
zugschlus |
509 |
open(FIND, "cd $config{skel}; find . -print |") |
| 626 |
zugschlus |
293 |
|| &cleanup("fork for find: $!\n"); |
| 627 |
|
|
while (<FIND>) { |
| 628 |
|
|
chop; |
| 629 |
|
|
next if ($_ eq "."); |
| 630 |
zugschlus |
509 |
next if ($_ =~ qr/$config{skel_ignore_regex}/ ); |
| 631 |
zugschlus |
293 |
©_to_dir($config{"skel"}, $_, $home_dir, $new_uid, |
| 632 |
|
|
$new_gid, ($config{"setgid_home"} =~ /yes/i)); |
| 633 |
|
|
} |
| 634 |
|
|
} |
| 635 |
|
|
} |
| 636 |
|
|
} |
| 637 |
|
|
|
| 638 |
joerghoh-guest |
383 |
# create a directory and all parent directories |
| 639 |
|
|
# we don't care about the rights and so on |
| 640 |
rb |
1 |
sub mktree { |
| 641 |
|
|
my($tree) = @_; |
| 642 |
|
|
my($done, @path); |
| 643 |
|
|
my $default_dir_mode = 0755; |
| 644 |
|
|
|
| 645 |
|
|
$tree =~ s:^/*(.*)/*$:$1:; # chop off leading & trailing slashes |
| 646 |
|
|
@path = split(/\//, $tree); |
| 647 |
|
|
|
| 648 |
|
|
$done = ""; |
| 649 |
|
|
while (@path) { |
| 650 |
|
|
$done .= '/' . shift(@path); |
| 651 |
|
|
-d $done || mkdir($done, $default_dir_mode) || return 0; |
| 652 |
|
|
} |
| 653 |
zugschlus |
256 |
return 1; |
| 654 |
rb |
1 |
} |
| 655 |
|
|
|
| 656 |
zugschlus |
256 |
# returns 0 if the the user doesn't exist or |
| 657 |
joerghoh-guest |
476 |
# returns 1 if the user already exists with the specified uid (or $new_uid wasn't specified) |
| 658 |
|
|
# returns 2 if the user already exists, but $new_uid doesn't matches its uid |
| 659 |
zugschlus |
112 |
sub existing_user_ok { |
| 660 |
|
|
my($new_name,$new_uid) = @_; |
| 661 |
|
|
my ($dummy1,$dummy2,$uid); |
| 662 |
|
|
if (($dummy1,$dummy2,$uid) = getpwnam($new_name)) { |
| 663 |
|
|
if( defined($new_uid) && $uid == $new_uid ) { |
| 664 |
|
|
return 1; |
| 665 |
|
|
} |
| 666 |
joerghoh-guest |
476 |
if (! defined($new_uid)) { |
| 667 |
|
|
return 1; |
| 668 |
|
|
} |
| 669 |
zugschlus |
112 |
if( $uid >= $config{"first_system_uid"} && |
| 670 |
|
|
$uid <= $config{"last_system_uid" } ) { |
| 671 |
joerghoh-guest |
468 |
return 2; |
| 672 |
zugschlus |
112 |
} |
| 673 |
|
|
} else { |
| 674 |
|
|
return 0; |
| 675 |
|
|
} |
| 676 |
|
|
} |
| 677 |
rb |
1 |
|
| 678 |
zugschlus |
256 |
# returns 0 if the group doesn't exist or |
| 679 |
joerghoh-guest |
476 |
# returns 1 if the group already exists with the specified gid (or $new_gid wasn't specified) |
| 680 |
|
|
# returns 2 if the group already exists, but $new_gid doesn't match its gid |
| 681 |
zugschlus |
112 |
sub existing_group_ok { |
| 682 |
|
|
my($new_name,$new_gid) = @_; |
| 683 |
|
|
my ($dummy1,$dummy2,$gid); |
| 684 |
|
|
if (($dummy1,$dummy2,$gid) = getgrnam($new_name)) { |
| 685 |
|
|
if( defined($new_gid) && $gid == $new_gid ) { |
| 686 |
|
|
return 1; |
| 687 |
|
|
} |
| 688 |
joerghoh-guest |
476 |
if (! defined($new_gid)) { |
| 689 |
|
|
return 1; |
| 690 |
|
|
} |
| 691 |
zugschlus |
112 |
if( $gid >= $config{"first_system_gid"} && |
| 692 |
|
|
$gid <= $config{"last_system_gid" } ) { |
| 693 |
joerghoh-guest |
476 |
return 2; |
| 694 |
zugschlus |
112 |
} |
| 695 |
|
|
} else { |
| 696 |
|
|
return 0; |
| 697 |
|
|
} |
| 698 |
|
|
} |
| 699 |
|
|
|
| 700 |
|
|
sub check_user_group { |
| 701 |
|
|
my ($system) = @_; |
| 702 |
|
|
if( !$system || !existing_user_ok($new_name, $new_uid) ) { |
| 703 |
|
|
if( defined getpwnam($new_name) ) { |
| 704 |
|
|
if( $system ) { |
| 705 |
zugschlus |
330 |
dief (gtx("The user `%s' already exists, and is not a system user.\n"),$new_name); |
| 706 |
zugschlus |
112 |
} else { |
| 707 |
zugschlus |
330 |
dief (gtx("The user `%s' already exists.\n"),$new_name); |
| 708 |
zugschlus |
112 |
} |
| 709 |
|
|
} |
| 710 |
zugschlus |
330 |
dief (gtx("The UID %s is already in use.\n"),$new_uid) |
| 711 |
zugschlus |
112 |
if (defined($new_uid) && getpwuid($new_uid)); |
| 712 |
|
|
} |
| 713 |
rb |
1 |
if ($make_group_also) { |
| 714 |
zugschlus |
112 |
if( !$system || !existing_group_ok($new_name, $new_uid) ) { |
| 715 |
zugschlus |
330 |
dief (gtx("The group `%s' already exists.\n"),$new_name) |
| 716 |
zugschlus |
112 |
if (defined getgrnam($new_name)); |
| 717 |
zugschlus |
330 |
dief (gtx("The GID %s is already in use.\n"),$new_uid) |
| 718 |
zugschlus |
112 |
if (defined($new_uid) && defined(getgrgid($new_uid))); |
| 719 |
|
|
} |
| 720 |
rb |
1 |
} |
| 721 |
|
|
else { |
| 722 |
zugschlus |
330 |
dief (gtx("The group `%s' does not exist.\n"),$ingroup_name) |
| 723 |
rb |
13 |
if ($ingroup_name && !defined(getgrnam($ingroup_name))); |
| 724 |
zugschlus |
330 |
dief (gtx("The GID %s does not exist.\n"),$new_gid) |
| 725 |
rb |
13 |
if (defined($new_gid) && !defined(getgrgid($new_gid))); |
| 726 |
rb |
1 |
} |
| 727 |
|
|
} |
| 728 |
|
|
|
| 729 |
|
|
|
| 730 |
|
|
# copy files, directories, symlinks |
| 731 |
|
|
sub copy_to_dir { |
| 732 |
|
|
my($fromdir, $file, $todir, $newu, $newg, $sgiddir) = @_; |
| 733 |
|
|
|
| 734 |
|
|
if (-l "$fromdir/$file") { |
| 735 |
zugschlus |
219 |
my $target=readlink("$fromdir/$file") or &cleanup("readlink: $!\n"); |
| 736 |
zugschlus |
187 |
my $curgid="$)"; |
| 737 |
|
|
my $curuid="$>"; |
| 738 |
zugschlus |
219 |
my $error=""; |
| 739 |
zugschlus |
187 |
$)="$newg"; |
| 740 |
|
|
$>="$newu"; |
| 741 |
zugschlus |
526 |
symlink("$target", "$todir/$file") or $error="$!"; |
| 742 |
zugschlus |
187 |
$>="$curuid"; |
| 743 |
|
|
$)="$curgid"; |
| 744 |
zugschlus |
219 |
if( "$error" ne "" ) { |
| 745 |
|
|
&cleanup("symlink: $!\n"); |
| 746 |
|
|
} |
| 747 |
rb |
6 |
return; |
| 748 |
rb |
1 |
} |
| 749 |
|
|
elsif (-f "$fromdir/$file") { |
| 750 |
|
|
open (FILE, "$fromdir/$file") || &cleanup("open $fromdir/$file: $!"); |
| 751 |
|
|
open (NEWFILE, ">$todir/$file") || &cleanup("open >$todir/$file: $!"); |
| 752 |
|
|
|
| 753 |
|
|
(print NEWFILE <FILE>) || &cleanup("print $todir/$file: $!"); |
| 754 |
|
|
close FILE; |
| 755 |
|
|
close(NEWFILE) || &cleanup("close $todir/$file "); |
| 756 |
|
|
|
| 757 |
|
|
} |
| 758 |
|
|
elsif (-d "$fromdir/$file") { |
| 759 |
|
|
mkdir("$todir/$file", 700) || &cleanup("mkdir: $!"); |
| 760 |
|
|
} |
| 761 |
|
|
else { |
| 762 |
|
|
&cleanup("Can't deal with $fromdir/$file. " |
| 763 |
|
|
."Not a dir, file, or symlink.\n"); |
| 764 |
|
|
} |
| 765 |
|
|
|
| 766 |
|
|
chown($newu, $newg, "$todir/$file") |
| 767 |
|
|
|| &cleanup("chown $newu:$newg $todir/$file: $!\n"); |
| 768 |
|
|
$perm = (stat("$fromdir/$file"))[2] & 07777; |
| 769 |
|
|
$perm |= 02000 if (-d "$fromdir/$file" && ($perm & 010) && $sgiddir); |
| 770 |
|
|
chmod($perm, "$todir/$file") || &cleanup("chmod $todir/$file: $!\n"); |
| 771 |
|
|
} |
| 772 |
|
|
|
| 773 |
|
|
|
| 774 |
joerghoh-guest |
383 |
# check if the given name matches some sanity checks |
| 775 |
rb |
1 |
sub checkname { |
| 776 |
|
|
my ($name) = @_; |
| 777 |
zugschlus |
530 |
if ($name !~ /^[_.A-Za-z0-9][-_.A-Za-z0-9]*\$?$/) { |
| 778 |
rb |
1 |
print STDERR |
| 779 |
zugschlus |
559 |
("$0: " . gtx("To avoid problems, the username should consist of |
| 780 |
zugschlus |
530 |
letters, digits, underscores, periods and dashes, and not start with a |
| 781 |
|
|
dash (as defined by IEEE Std 1003.1-2001). For compatibility with Samba |
| 782 |
|
|
machine accounts \$ is also supported at the end of the username\n")); |
| 783 |
|
|
exit 1; |
| 784 |
rb |
1 |
} |
| 785 |
zugschlus |
202 |
if ($name !~ qr/$config{"name_regex"}/) { |
| 786 |
|
|
if ($allow_badname) { |
| 787 |
zugschlus |
330 |
print (gtx("Allowing use of questionable username.\n")) if ($verbose); |
| 788 |
zugschlus |
202 |
} |
| 789 |
|
|
else { |
| 790 |
|
|
print STDERR |
| 791 |
zugschlus |
559 |
("$0: " . gtx("Please enter a username matching the regular expression configured |
| 792 |
zugschlus |
202 |
via the name_regex configuration variable. Use the `--force-badname' |
| 793 |
zugschlus |
287 |
option to relax this check or reconfigure name_regex.\n")); |
| 794 |
zugschlus |
202 |
exit 1; |
| 795 |
|
|
} |
| 796 |
rb |
1 |
} |
| 797 |
|
|
} |
| 798 |
|
|
|
| 799 |
joerghoh-guest |
448 |
# return the first available uid in given range |
| 800 |
|
|
# return -1 if no free uid is available |
| 801 |
|
|
sub first_avail_uid { |
| 802 |
|
|
my ($min, $max) = @_; |
| 803 |
|
|
printf (gtx("Selecting uid from range %s to %s.\n"),$min,$max) if ($verbose > 1); |
| 804 |
rb |
1 |
|
| 805 |
joerghoh-guest |
448 |
my $t = $min; |
| 806 |
|
|
while ($t <= $max) { |
| 807 |
zugschlus |
455 |
return $t if (!defined(getpwuid($t))); |
| 808 |
joerghoh-guest |
448 |
$t++; |
| 809 |
rb |
1 |
} |
| 810 |
joerghoh-guest |
448 |
return -1; # nothing available |
| 811 |
rb |
1 |
} |
| 812 |
|
|
|
| 813 |
joerghoh-guest |
448 |
# return the first available gid in given range |
| 814 |
|
|
# return -1 if no free gid is available |
| 815 |
|
|
sub first_avail_gid { |
| 816 |
|
|
my ($min, $max) = @_; |
| 817 |
|
|
printf (gtx("Selecting gid from range %s to %s.\n"),$min,$max) if ($verbose > 1); |
| 818 |
rb |
1 |
|
| 819 |
joerghoh-guest |
448 |
my $t = $min; |
| 820 |
|
|
while ($t <= $max) { |
| 821 |
zugschlus |
455 |
return $t if (!defined(getgrgid($t))); |
| 822 |
joerghoh-guest |
448 |
$t++; |
| 823 |
|
|
} |
| 824 |
|
|
return -1; # nothing available |
| 825 |
rb |
1 |
} |
| 826 |
|
|
|
| 827 |
rb |
8 |
sub ch_gecos { |
| 828 |
|
|
my $gecos = shift; |
| 829 |
|
|
if($gecos =~ /,/) |
| 830 |
|
|
{ |
| 831 |
|
|
my($gecos_name,$gecos_room,$gecos_work,$gecos_home,$gecos_other) |
| 832 |
|
|
= split(/,/,$gecos); |
| 833 |
rb |
1 |
|
| 834 |
rb |
82 |
&systemcall('/usr/bin/chfn', '-f', $gecos_name, '-r', $gecos_room, $new_name); |
| 835 |
|
|
&systemcall('/usr/bin/chfn','-w',$gecos_work,$new_name) |
| 836 |
rb |
8 |
if(defined($gecos_work)); |
| 837 |
rb |
82 |
&systemcall('/usr/bin/chfn','-h',$gecos_home,$new_name) |
| 838 |
rb |
8 |
if(defined($gecos_home)); |
| 839 |
rb |
82 |
&systemcall('/usr/bin/chfn','-o',$gecos_other,$new_name) |
| 840 |
rb |
8 |
if(defined($gecos_other)); |
| 841 |
|
|
} |
| 842 |
|
|
else |
| 843 |
|
|
{ |
| 844 |
rb |
82 |
&systemcall('/usr/bin/chfn', '-f', $gecos, $new_name); |
| 845 |
rb |
8 |
} |
| 846 |
|
|
} |
| 847 |
|
|
|
| 848 |
rb |
1 |
# user is member of group? |
| 849 |
|
|
sub user_is_member { |
| 850 |
|
|
my($user, $group) = @_; |
| 851 |
|
|
for (split(/ /, (getgrnam($group))[3])) { |
| 852 |
|
|
return 1 if ($user eq $_); |
| 853 |
|
|
} |
| 854 |
zugschlus |
256 |
return 0; |
| 855 |
rb |
1 |
} |
| 856 |
|
|
|
| 857 |
|
|
|
| 858 |
|
|
sub cleanup { |
| 859 |
joerghoh-guest |
527 |
my ($msg) = @_; |
| 860 |
zugschlus |
546 |
printf (gtx("Stopped: %s\n"),$msg); |
| 861 |
rb |
1 |
if ($undohome) { |
| 862 |
zugschlus |
330 |
printf (gtx("Removing directory `%s'\n"),$undohome); |
| 863 |
joerghoh-guest |
383 |
&systemcall('rm', '-rf', $undohome); |
| 864 |
rb |
1 |
} |
| 865 |
|
|
if ($undouser) { |
| 866 |
zugschlus |
330 |
printf (gtx("Removing user `%s'.\n"),$undouser); |
| 867 |
joerghoh-guest |
383 |
&systemcall('userdel', $undouser); |
| 868 |
rb |
1 |
} |
| 869 |
|
|
if ($undogroup) { |
| 870 |
zugschlus |
330 |
printf (gtx("Removing group `%s'.\n"),$undogroup); |
| 871 |
joerghoh-guest |
383 |
&systemcall('groupdel', $undogroup); |
| 872 |
rb |
1 |
} |
| 873 |
rb |
15 |
# do we need to invalidate the nscd cache here, too? |
| 874 |
rb |
1 |
exit 1; |
| 875 |
|
|
} |
| 876 |
|
|
|
| 877 |
|
|
sub handler { |
| 878 |
|
|
my($sig) = @_; |
| 879 |
|
|
&cleanup("Caught a SIG$sig.\n"); |
| 880 |
|
|
} |
| 881 |
|
|
|
| 882 |
|
|
|
| 883 |
|
|
sub version { |
| 884 |
zugschlus |
293 |
print "$0: add a user or group to the system. Version VERSION |
| 885 |
rb |
6 |
Copyright (C) 1997, 1998, 1999 Guy Maor <maor\@debian.org> |
| 886 |
rb |
1 |
Copyright (C) 1995 Ian Murdock <imurdock\@gnu.ai.mit.edu>, |
| 887 |
|
|
Ted Hajek <tedhajek\@boombox.micro.umn.edu>, |
| 888 |
|
|
|
| 889 |
|
|
This program is free software; you can redistribute it and/or modify |
| 890 |
|
|
it under the terms of the GNU General Public License as published by |
| 891 |
|
|
the Free Software Foundation; either version 2 of the License, or (at |
| 892 |
|
|
your option) any later version. |
| 893 |
|
|
|
| 894 |
|
|
This program is distributed in the hope that it will be useful, but |
| 895 |
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of |
| 896 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 897 |
rb |
19 |
General Public License, /usr/share/common-licenses/GPL, for more details. |
| 898 |
zugschlus |
293 |
"; |
| 899 |
rb |
1 |
} |
| 900 |
|
|
|
| 901 |
|
|
sub usage { |
| 902 |
zugschlus |
330 |
printf gtx( |
| 903 |
rb |
58 |
"adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] |
| 904 |
|
|
[--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID] |
| 905 |
|
|
[--disabled-password] [--disabled-login] user |
| 906 |
rb |
4 |
Add a normal user |
| 907 |
rb |
1 |
|
| 908 |
rb |
58 |
adduser --system [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] |
| 909 |
|
|
[--gecos GECOS] [--group | --ingroup GROUP | --gid ID] [--disabled-password] |
| 910 |
|
|
[--disabled-login] user |
| 911 |
rb |
4 |
Add a system user |
| 912 |
rb |
1 |
|
| 913 |
rb |
4 |
adduser --group [--gid ID] group |
| 914 |
|
|
addgroup [--gid ID] group |
| 915 |
rb |
86 |
Add a user group |
| 916 |
|
|
|
| 917 |
|
|
addgroup --system [--gid ID] group |
| 918 |
rb |
4 |
Add a system group |
| 919 |
rb |
1 |
|
| 920 |
|
|
adduser user group |
| 921 |
rb |
4 |
Add an existing user to an existing group |
| 922 |
rb |
1 |
|
| 923 |
rb |
4 |
Other options are [--quiet] [--force-badname] [--help] [--version] [--conf |
| 924 |
|
|
FILE]. |
| 925 |
zugschlus |
330 |
"); |
| 926 |
rb |
1 |
} |
| 927 |
rb |
6 |
|
| 928 |
rb |
10 |
sub get_dir_mode |
| 929 |
|
|
{ |
| 930 |
|
|
my $setgid = shift; |
| 931 |
rb |
13 |
# no longer make home directories setgid per default (closes: #64806) |
| 932 |
zugschlus |
256 |
$setgid = 0 unless $config{"setgid_home"} =~ /yes/i; |
| 933 |
rb |
13 |
|
| 934 |
rb |
10 |
my $dir_mode = $config{"dir_mode"}; |
| 935 |
|
|
if(!defined($dir_mode) || ! ($dir_mode =~ /[0-7]{3}/ || |
| 936 |
|
|
$dir_mode =~ /[0-7]{4}/)) |
| 937 |
|
|
{ |
| 938 |
|
|
$dir_mode = $setgid ? 2755 : 0755; |
| 939 |
|
|
} |
| 940 |
|
|
else |
| 941 |
|
|
{ |
| 942 |
|
|
$dir_mode = $config{"dir_mode"}; |
| 943 |
|
|
if($setgid && (length($dir_mode) == 3 || $dir_mode =~ /^[0-1|4-5][0-7]{3}$/)) |
| 944 |
|
|
{ |
| 945 |
|
|
$dir_mode += 2000; |
| 946 |
|
|
} |
| 947 |
|
|
} |
| 948 |
|
|
return oct($dir_mode); |
| 949 |
|
|
} |
| 950 |
rb |
6 |
|
| 951 |
|
|
# Local Variables: |
| 952 |
|
|
# mode:cperl |
| 953 |
|
|
# cperl-indent-level:4 |
| 954 |
|
|
# End: |
| 955 |
rb |
10 |
|
| 956 |
|
|
|