1#!/usr/bin/perl 2# 3# $OpenBSD: adduser.perl,v 1.30 2001/07/06 15:39:36 mpech Exp $ 4# 5# Copyright (c) 1995-1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin. 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29# $From: adduser.perl,v 1.22 1996/12/07 21:25:12 ache Exp $ 30 31use IPC::Open2; 32use Fcntl qw(:DEFAULT :flock); 33 34################ 35# main 36# 37$test = 0; # test mode, only for development 38$check_only = 0; 39 40$SIG{'INT'} = 'cleanup'; 41$SIG{'QUIT'} = 'cleanup'; 42$SIG{'HUP'} = 'cleanup'; 43$SIG{'TERM'} = 'cleanup'; 44 45&check_root; # you must be root to run this script! 46&variables; # initialize variables 47&config_read(@ARGV); # read variables from config-file 48&parse_arguments(@ARGV); # parse arguments 49 50if (!$check_only && $#batch < 0) { 51 ©right; &hints; 52} 53 54# check 55$changes = 0; 56&variable_check; # check for valid variables 57&passwd_check; # check for valid passwdb 58&shells_read; # read /etc/shells 59&passwd_read; # read /etc/master.passwd 60&group_read; # read /etc/group 61&group_check; # check for incon* 62exit 0 if $check_only; # only check consistence and exit 63 64exit(!&batch(@batch)) if $#batch >= 0; # batch mode 65 66# Interactive: 67# main loop for creating new users 68&new_users; # add new users 69 70#end 71 72 73# Set adduser "default" variables internally before groking config file 74# Adduser.conf supercedes these 75sub variables { 76 $verbose = 1; # verbose = [0-2] 77 $defaultpasswd = "yes"; # use password for new users 78 $dotdir = "/etc/skel"; # copy dotfiles from this dir 79 $dotdir_bak = $dotdir; 80 $send_message = "no"; # send message to new user 81 $send_message_bak = '/etc/adduser.message'; 82 $config = "/etc/adduser.conf"; # config file for adduser 83 $config_read = 1; # read config file 84 $logfile = "/var/log/adduser"; # logfile 85 $home = "/home"; # default HOME 86 $etc_shells = "/etc/shells"; 87 $etc_passwd = "/etc/master.passwd"; 88 $etc_ptmp = "/etc/ptmp"; 89 $group = "/etc/group"; 90 $pwd_mkdb = "pwd_mkdb -p"; # program for building passwd database 91 $encryptionmethod = "blowfish"; 92 $rcsid = '$OpenBSD: adduser.perl,v 1.30 2001/07/06 15:39:36 mpech Exp $'; 93 94 # List of directories where shells located 95 @path = ('/bin', '/usr/bin', '/usr/local/bin'); 96 # common shells, first element has higher priority 97 @shellpref = ('csh', 'sh', 'bash', 'tcsh', 'ksh'); 98 99 @encryption_methods = ('blowfish', 'md5', 'des', 'old'); 100 101 $defaultshell = 'sh'; # defaultshell if not empty 102 $group_uniq = 'USER'; 103 $defaultgroup = $group_uniq;# login groupname, $group_uniq means username 104 105 $uid_start = 1000; # new users get this uid 106 $uid_end = 2147483647; # max. uid 107 108 # global variables 109 # passwd 110 $username = ''; # $username{username} = uid 111 $uid = ''; # $uid{uid} = username 112 $pwgid = ''; # $pwgid{pwgid} = username; gid from passwd db 113 114 $password = ''; # password for new users 115 116 # group 117 $groupname =''; # $groupname{groupname} = gid 118 $groupmembers = ''; # $groupmembers{gid} = members of group/kommalist 119 $gid = ''; # $gid{gid} = groupname; gid form group db 120 121 # shell 122 $shell = ''; # $shell{`basename sh`} = sh 123 124 # only for me (=Wolfram) 125 if ($test) { 126 $home = "/home/w/tmp/adduser/home"; 127 $etc_shells = "./shells"; 128 $etc_passwd = "./master.passwd"; 129 $group = "./group"; 130 $pwd_mkdb = "pwd_mkdb -p -d ."; 131 $config = "adduser.conf"; 132 $send_message = "./adduser.message"; 133 $logfile = "./log.adduser"; 134 } 135 136 umask 022; # don't give login group write access 137 138 $ENV{'PATH'} = "/sbin:/bin:/usr/sbin:/usr/bin"; 139 @passwd_backup = ''; 140 @group_backup = ''; 141 @message_buffer = ''; 142 @user_variable_list = ''; # user variables in /etc/adduser.conf 143 $do_not_delete = '## DO NOT DELETE THIS LINE!'; 144} 145 146# read shell database, see also: shells(5) 147sub shells_read { 148 local($sh); 149 local($err) = 0; 150 151 print "Reading $etc_shells\n" if $verbose; 152 open(S, $etc_shells) || die "$etc_shells:$!\n"; 153 154 while(<S>) { 155 if (/^\s*\//) { 156 s/^\s*//; s/\s+.*//; # chop 157 $sh = $_; 158 if (-x $sh) { 159 $shell{&basename($sh)} = $sh; 160 } else { 161 warn "Shell: $sh not executable!\n"; 162 $err++; 163 } 164 } 165 } 166 167 push(@list, "/sbin/nologin"); 168 &shell_pref_add("nologin"); 169 $shell{"nologin"} = "/sbin/nologin"; 170 171 return $err; 172} 173 174# add new shells if possible 175sub shells_add { 176 local($sh,$dir,@list); 177 178 return 1 unless $verbose; 179 180 foreach $sh (@shellpref) { 181 # all known shells 182 if (!$shell{$sh}) { 183 # shell $sh is not defined as login shell 184 foreach $dir (@path) { 185 if (-x "$dir/$sh") { 186 # found shell 187 if (&confirm_yn("Found shell: $dir/$sh. Add to $etc_shells?", "yes")) { 188 push(@list, "$dir/$sh"); 189 &shell_pref_add("$sh"); 190 $shell{&basename("$dir/$sh")} = "$dir/$sh"; 191 $changes++; 192 } 193 } 194 } 195 } 196 } 197 &append_file($etc_shells, @list) if $#list >= 0; 198} 199 200# add shell to preference list without duplication 201sub shell_pref_add { 202 local($new_shell) = @_; 203 local($shell); 204 205 foreach $shell (@shellpref) { 206 return if ($shell eq $new_shell); 207 } 208 push(@shellpref, $new_shell); 209} 210 211# choose your favourite shell and return the shell 212sub shell_default { 213 local($e,$i,$new_shell); 214 local($sh); 215 216 $sh = &shell_default_valid($defaultshell); 217 return $sh unless $verbose; 218 219 $new_shell = &confirm_list("Enter your default shell:", 0, 220 $sh, sort(keys %shell)); 221 print "Your default shell is: $new_shell -> $shell{$new_shell}\n"; 222 $changes++ if $new_shell ne $sh; 223 return $new_shell; 224} 225 226sub shell_default_valid { 227 local($sh) = @_; 228 local($s,$e); 229 230 return $sh if $shell{$sh}; 231 232 foreach $e (@shellpref) { 233 $s = $e; 234 last if defined($shell{$s}); 235 } 236 $s = "sh" unless $s; 237 warn "Shell ``$sh'' is undefined, use ``$s''\n"; 238 return $s; 239} 240 241# return default home partition (f.e. "/home") 242# create base directory if nesseccary 243sub home_partition { 244 local($home) = @_; 245 $home = &stripdir($home); 246 local($h) = $home; 247 248 return $h if !$verbose && $h eq &home_partition_valid($h); 249 250 while(1) { 251 $h = &confirm_list("Enter your default HOME partition:", 1, $home, ""); 252 $h = &stripdir($h); 253 last if $h eq &home_partition_valid($h); 254 } 255 256 $changes++ if $h ne $home; 257 return $h; 258} 259 260sub home_partition_valid { 261 local($h) = @_; 262 263 $h = &stripdir($h); 264 # all right (I hope) 265 return $h if $h =~ "^/" && -e $h && -w $h && (-d $h || -l $h); 266 267 # Errors or todo 268 if ($h !~ "^/") { 269 warn "Please use absolute path for home: ``$h''.\a\n"; 270 return 0; 271 } 272 273 if (-e $h) { 274 warn "$h exists, but is not a directory or symlink!\n" 275 unless -d $h || -l $h; 276 warn "$h is not writable!\n" 277 unless -w $h; 278 return 0; 279 } else { 280 # create home partition 281 return $h if &mkdir_home($h); 282 } 283 return 0; 284} 285 286# check for valid passwddb 287sub passwd_check { 288 system(split(/\s+/, "$pwd_mkdb -c $etc_passwd")); 289 die "\nInvalid $etc_passwd - cannot add any users!\n" if $?; 290} 291 292# read /etc/passwd 293sub passwd_read { 294 local($p_username, $pw, $p_uid, $p_gid, $sh, %shlist); 295 296 print "Check $etc_passwd\n" if $verbose; 297 open(P, "$etc_passwd") || die "$passwd: $!\n"; 298 299 # we only use this to lock the password file 300 sysopen(PTMP, $etc_ptmp, O_RDWR|O_CREAT|O_EXCL, 0600) || 301 die "Password file busy\n"; 302 303 while(<P>) { 304 chop; 305 push(@passwd_backup, $_); 306 ($p_username, $pw, $p_uid, $p_gid, $sh) = (split(/:/, $_))[0..3,9]; 307 308 print "$p_username already exists with uid: $username{$p_username}!\n" 309 if $username{$p_username} && $verbose; 310 $username{$p_username} = $p_uid; 311 print "User $p_username: uid $p_uid exists twice: $uid{$p_uid}\n" 312 if $uid{$p_uid} && $verbose && $p_uid; # don't warn for uid 0 313 print "User $p_username: illegal shell: ``$sh''\n" 314 if ($verbose && $sh && 315 !$shell{&basename($sh)} && 316 $p_username !~ /^(news|xten|bin|nobody|uucp)$/ && 317 $sh !~ /\/(pppd|sliplogin)$/); 318 $uid{$p_uid} = $p_username; 319 $pwgid{$p_gid} = $p_username; 320 } 321 close P; 322} 323 324# read /etc/group 325sub group_read { 326 local($g_groupname,$pw,$g_gid, $memb); 327 328 print "Check $group\n" if $verbose; 329 open(G, "$group") || die "$group: $!\n"; 330 while(<G>) { 331 chop; 332 push(@group_backup, $_); 333 ($g_groupname, $pw, $g_gid, $memb) = (split(/:/, $_))[0..3]; 334 335 $groupmembers{$g_gid} = $memb; 336 warn "Groupname exists twice: $g_groupname:$g_gid -> $g_groupname:$groupname{$g_groupname}\n" 337 if $groupname{$g_groupname} && $verbose; 338 $groupname{$g_groupname} = $g_gid; 339 warn "Groupid exists twice: $g_groupname:$g_gid -> $gid{$g_gid}:$g_gid\n" 340 if $gid{$g_gid} && $verbose; 341 $gid{$g_gid} = $g_groupname; 342 } 343 close G; 344} 345 346# check gids /etc/passwd <-> /etc/group 347sub group_check { 348 local($c_gid, $c_username, @list); 349 350 foreach $c_gid (keys %pwgid) { 351 if (!$gid{$c_gid}) { 352 $c_username = $pwgid{$c_gid}; 353 warn "User ``$c_username'' has gid $c_gid but a group with this " . 354 "gid does not exist.\n" if $verbose; 355 } 356 } 357} 358 359# 360# main loop for creating new users 361# 362 363# return username 364sub new_users_name { 365 local($name); 366 367 while(1) { 368 $name = &confirm_list("Enter username", 1, "a-z0-9_-", ""); 369 if (length($name) > 31) { 370 warn "Username is longer than 31 characters\a\n"; 371 next; 372 } 373 last if (&new_users_name_valid($name) eq $name); 374 } 375 return $name; 376} 377 378sub new_users_name_valid { 379 local($name) = @_; 380 381 if ($name !~ /^[a-z0-9_][a-z0-9_\-]*$/ || $name eq "a-z0-9_-") { 382 warn "Wrong username. " . 383 "Please use only lowercase characters or digits\a\n"; 384 return 0; 385 } elsif ($username{$name}) { 386 warn "Username ``$name'' already exists!\a\n"; return 0; 387 } 388 return $name; 389} 390 391# return full name 392sub new_users_fullname { 393 local($name) = @_; 394 local($fullname); 395 396 while(1) { 397 $fullname = &confirm_list("Enter full name", 1, "", ""); 398 last if $fullname eq &new_users_fullname_valid($fullname); 399 } 400 $fullname = $name unless $fullname; 401 return $fullname; 402} 403 404sub new_users_fullname_valid { 405 local($fullname) = @_; 406 407 return $fullname if $fullname !~ /:/; 408 409 warn "``:'' is not allowed!\a\n"; 410 return 0; 411} 412 413# return shell (full path) for user 414sub new_users_shell { 415 local($sh); 416 417 $sh = &confirm_list("Enter shell", 0, $defaultshell, keys %shell); 418 return $shell{$sh}; 419} 420 421# return free uid and gid 422sub new_users_id { 423 local($name) = @_; 424 local($u_id, $g_id) = &next_id($name); 425 local($u_id_tmp, $e); 426 427 while(1) { 428 $u_id_tmp = &confirm_list("Uid", 1, $u_id, ""); 429 last if $u_id_tmp =~ /^[0-9]+$/ && $u_id_tmp <= $uid_end && 430 ! $uid{$u_id_tmp}; 431 if ($uid{$u_id_tmp}) { 432 warn "Uid ``$u_id_tmp'' in use!\a\n"; 433 } else { 434 warn "Wrong uid.\a\n"; 435 } 436 } 437 # use calculated uid 438 return ($u_id_tmp, $g_id) if $u_id_tmp eq $u_id; 439 # recalculate gid 440 $uid_start = $u_id_tmp; 441 return &next_id($name); 442} 443 444# add user to group 445sub add_group { 446 local($gid, $name) = @_; 447 448 return 0 if 449 $groupmembers{$gid} =~ /^(.+,)?$name(,.+)?$/; 450 451 $groupmembers_bak{$gid} = $groupmembers{$gid}; 452 $groupmembers{$gid} .= "," if $groupmembers{$gid}; 453 $groupmembers{$gid} .= "$name"; 454 455 local(@l) = split(',', $groupmembers{$gid}); 456 # group(5): A group cannot have more than 200 members. 457 # The maximum line length of /etc/group is 1024 characters. 458 # Longer lines will be skiped. 459 if ($#l >= 200 || 460 length($groupmembers{$gid}) > 1024 - 50) { # 50 is for group name 461 warn "WARNING, maybe group line ``$gid{$gid}'' is to long or to\n" . 462 "much users in group, see group(5)\a\n"; 463 } 464 return $name; 465} 466 467 468# return login group 469sub new_users_grplogin { 470 local($name, $defaultgroup, $new_users_ok) = @_; 471 local($group_login, $group); 472 473 $group = $name; 474 $group = $defaultgroup if $defaultgroup ne $group_uniq; 475 476 if ($new_users_ok) { 477 # clean up backup 478 foreach $e (keys %groupmembers_bak) { delete $groupmembers_bak{$e}; } 479 } else { 480 # restore old groupmembers, user was not accept 481 foreach $e (keys %groupmembers_bak) { 482 $groupmembers{$e} = $groupmembers_bak{$e}; 483 } 484 } 485 486 while(1) { 487 $group_login = &confirm_list("Login group", 1, $group, 488 ($name, $group)); 489 last if $group_login eq $group; 490 last if $group_login eq $name; 491 last if defined $groupname{$group_login}; 492 if ($group_login eq $group_uniq) { 493 $group_login = $name; last; 494 } 495 496 if (defined $gid{$group_login}) { 497 # convert numeric groupname (gid) to groupname 498 $group_login = $gid{$group_login}; 499 last; 500 } 501 warn "Group does not exist!\a\n"; 502 } 503 504 #if (defined($groupname{$group_login})) { 505 # &add_group($groupname{$group_login}, $name); 506 #} 507 508 return ($group_login, $group_uniq) if $group_login eq $name; 509 return ($group_login, $group_login); 510} 511 512# return login group 513sub new_users_grplogin_batch { 514 local($name, $defaultgroup) = @_; 515 local($group_login, $group); 516 517 $group_login = $name; 518 $group_login = $defaultgroup if $defaultgroup ne $group_uniq; 519 520 if (defined $gid{$group_login}) { 521 # convert numeric groupname (gid) to groupname 522 $group_login = $gid{$group_login}; 523 } 524 525 # if (defined($groupname{$group_login})) { 526 # &add_group($groupname{$group_login}, $name); 527 # } 528 529 return $group_login 530 if defined($groupname{$group_login}) || $group_login eq $name; 531 warn "Group ``$group_login'' does not exist\a\n"; 532 return 0; 533} 534 535# return other groups (string) 536sub new_users_groups { 537 local($name, $other_groups) = @_; 538 local($string) = 539 "Login group is ``$group_login''. Invite $name into other groups:"; 540 local($e, $flag); 541 local($new_groups,$groups); 542 543 $other_groups = "no" unless $other_groups; 544 545 while(1) { 546 $groups = &confirm_list($string, 1, $other_groups, 547 ("no", $other_groups, "guest")); 548 # no other groups 549 return "" if $groups eq "no"; 550 551 ($flag, $new_groups) = &new_users_groups_valid($groups); 552 last unless $flag; 553 } 554 $new_groups =~ s/\s*$//; 555 return $new_groups; 556} 557 558sub new_users_groups_valid { 559 local($groups) = @_; 560 local($e, $new_groups); 561 local($flag) = 0; 562 563 foreach $e (split(/[,\s]+/, $groups)) { 564 # convert numbers to groupname 565 if ($e =~ /^[0-9]+$/ && $gid{$e}) { 566 $e = $gid{$e}; 567 } 568 if (defined($groupname{$e})) { 569 if ($e eq $group_login) { 570 # do not add user to a group if this group 571 # is also the login group. 572 } elsif (&add_group($groupname{$e}, $name)) { 573 $new_groups .= "$e "; 574 } else { 575 warn "$name is already member of group ``$e''\n"; 576 } 577 } else { 578 warn "Group ``$e'' does not exist\a\n"; $flag++; 579 } 580 } 581 return ($flag, $new_groups); 582} 583 584# your last change 585sub new_users_ok { 586 587 print <<EOF; 588 589Name: $name 590Password: **** 591Fullname: $fullname 592Uid: $u_id 593Gid: $g_id ($group_login) 594Groups: $group_login $new_groups 595HOME: $home/$name 596Shell: $sh 597EOF 598 599 return &confirm_yn("OK?", "yes"); 600} 601 602# make password database 603sub new_users_pwdmkdb { 604 local($last) = @_; 605 local($user); 606 607 $user = (split(/:/, $last))[0]; 608 system(split(/\s+/, "$pwd_mkdb -u $user $etc_passwd")); 609 if ($?) { 610 warn "$last\n"; 611 warn "``$pwd_mkdb'' failed\n"; 612 exit($? >> 8); 613 } 614} 615 616# update group database 617sub new_users_group_update { 618 local($e, @a); 619 620 # Add *new* group 621 if (!defined($groupname{$group_login}) && 622 !defined($gid{$groupname{$group_login}})) { 623 push(@group_backup, "$group_login:*:$g_id:"); 624 $groupname{$group_login} = $g_id; 625 $gid{$g_id} = $group_login; 626 # $groupmembers{$g_id} = $group_login; 627 } 628 629 if ($new_groups || defined($groupname{$group_login}) || 630 defined($gid{$groupname{$group_login}}) && 631 $gid{$groupname{$group_login}} ne "+") { 632 # new user is member of some groups 633 # new login group is already in name space 634 rename($group, "$group.bak"); 635 #warn "$group_login $groupname{$group_login} $groupmembers{$groupname{$group_login}}\n"; 636 foreach $e (sort {$a <=> $b} (keys %gid)) { 637 push(@a, "$gid{$e}:*:$e:$groupmembers{$e}"); 638 } 639 &append_file($group, @a); 640 } else { 641 &append_file($group, "$group_login:*:$g_id:"); 642 } 643 644} 645 646sub new_users_passwd_update { 647 # update passwd/group variables 648 push(@passwd_backup, $new_entry); 649 $username{$name} = $u_id; 650 $uid{$u_id} = $name; 651 $pwgid{$g_id} = $name; 652} 653 654# send message to new user 655sub new_users_sendmessage { 656 return 1 if $send_message eq "no"; 657 658 local($cc) = 659 &confirm_list("Send message to ``$name'' and:", 660 1, "no", ("root", "second_mail_address", 661 "no carbon copy")); 662 local($e); 663 $cc = "" if $cc eq "no"; 664 665 @message_buffer = (); 666 message_read ($send_message); 667 668 foreach $e (@message_buffer) { 669 print eval "\"$e\""; 670 } 671 print "\n"; 672 673 local(@message_buffer_append) = (); 674 if (!&confirm_yn("Add anything to default message", "no")) { 675 print "Use ``.'' or ^D alone on a line to finish your message.\n"; 676 push(@message_buffer_append, "\n"); 677 while($read = <STDIN>) { 678 last if $read eq "\.\n"; 679 push(@message_buffer_append, $read); 680 } 681 } 682 683 &sendmessage("$name $cc", (@message_buffer, @message_buffer_append)) 684 if (&confirm_yn("Send message", "yes")); 685} 686 687sub sendmessage { 688 local($to, @message) = @_; 689 local($e); 690 691 if (!open(M, "| mail -s Welcome $to")) { 692 warn "Cannot send mail to: $to!\n"; 693 return 0; 694 } else { 695 foreach $e (@message) { 696 print M eval "\"$e\""; 697 } 698 close M; 699 } 700} 701 702 703sub new_users_password { 704 705 # empty password 706 return "" if $defaultpasswd ne "yes"; 707 708 local($password); 709 710 while(1) { 711 system("stty", "-echo"); 712 $password = &confirm_list("Enter password", 1, "", ""); 713 system("stty", "echo"); 714 print "\n"; 715 if ($password ne "") { 716 system("stty", "-echo"); 717 $newpass = &confirm_list("Enter password again", 1, "", ""); 718 system("stty", "echo"); 719 print "\n"; 720 last if $password eq $newpass; 721 print "They didn't match, please try again\n"; 722 } 723 elsif (!&confirm_yn("Set the password so that user cannot logon?", "no")) { 724 last; 725 } 726 } 727 728 return $password; 729} 730 731 732sub new_users { 733 734 print "\n" if $verbose; 735 print "Ok, let's go.\n" . 736 "Don't worry about mistakes. I will give you the chance later to " . 737 "correct any input.\n" if $verbose; 738 739 # name: Username 740 # fullname: Full name 741 # sh: shell 742 # u_id: user id 743 # g_id: group id 744 # group_login: groupname of g_id 745 # new_groups: some other groups 746 local($name, $group_login, $fullname, $sh, $u_id, $g_id, $new_groups); 747 local($groupmembers_bak, $cryptpwd); 748 local($new_users_ok) = 1; 749 750 751 $new_groups = "no" unless $groupname{$new_groups}; 752 753 while(1) { 754 $name = &new_users_name; 755 $fullname = &new_users_fullname($name); 756 $sh = &new_users_shell; 757 ($u_id, $g_id) = &new_users_id($name); 758 ($group_login, $defaultgroup) = 759 &new_users_grplogin($name, $defaultgroup, $new_users_ok); 760 # do not use uniq username and login group 761 $g_id = $groupname{$group_login} if (defined($groupname{$group_login})); 762 763 $new_groups = &new_users_groups($name, $new_groups); 764 $password = &new_users_password; 765 766 767 if (&new_users_ok) { 768 $new_users_ok = 1; 769 770 $cryptpwd = "*"; # Locked by default 771 $cryptpwd = encrypt($password, &salt) if ($password ne ""); 772 773 # obscure perl bug 774 $new_entry = "$name\:" . "$cryptpwd" . 775 "\:$u_id\:$g_id\::0:0:$fullname:$home/$name:$sh"; 776 &append_file($etc_passwd, "$new_entry"); 777 &new_users_pwdmkdb("$new_entry"); 778 &new_users_group_update; 779 &new_users_passwd_update; print "Added user ``$name''\n"; 780 &adduser_log("$name:*:$u_id:$g_id($group_login):$fullname"); 781 &home_create($name, $group_login); 782 &new_users_sendmessage; 783 } else { 784 $new_users_ok = 0; 785 } 786 if (!&confirm_yn("Add another user?", "yes")) { 787 print "Goodbye!\n" if $verbose; 788 last; 789 } 790 print "\n" if !$verbose; 791 } 792} 793 794sub batch { 795 local($name, $groups, $fullname, $password) = @_; 796 local($sh); 797 798 $defaultshell = &shell_default_valid($defaultshell); 799 return 0 unless $home = &home_partition_valid($home); 800 return 0 if $dotdir ne &dotdir_default_valid($dotdir); 801 $send_message = &message_default; 802 803 return 0 if $name ne &new_users_name_valid($name); 804 $sh = $shell{$defaultshell}; 805 ($u_id, $g_id) = &next_id($name); 806 $group_login = &new_users_grplogin_batch($name, $defaultgroup); 807 return 0 unless $group_login; 808 $g_id = $groupname{$group_login} if (defined($groupname{$group_login})); 809 ($flag, $new_groups) = &new_users_groups_valid($groups); 810 return 0 if $flag; 811 812 $cryptpwd = "*"; # Locked by default 813 if ($password ne "" && $password ne "*") { 814 if($unencrypted) { $cryptpwd = encrypt($password, &salt) } 815 else { $cryptpwd = $password } 816 } 817 # obscure perl bug 818 $new_entry = "$name\:" . "$cryptpwd" . 819 "\:$u_id\:$g_id\::0:0:$fullname:$home/$name:$sh"; 820 &append_file($etc_passwd, "$new_entry"); 821 &new_users_pwdmkdb("$new_entry"); 822 &new_users_group_update; 823 &new_users_passwd_update; print "Added user ``$name''\n"; 824 &sendmessage($name, @message_buffer) if $send_message ne "no"; 825 &adduser_log("$name:*:$u_id:$g_id($group_login):$fullname"); 826 &home_create($name, $group_login); 827} 828 829# ask for password usage 830sub password_default { 831 local($p) = $defaultpasswd; 832 if ($verbose) { 833 $p = &confirm_yn("Prompt for passwords by default", $defaultpasswd); 834 $changes++ unless $p; 835 } 836 return "yes" if (($defaultpasswd eq "yes" && $p) || 837 ($defaultpasswd eq "no" && !$p)); 838 return "no"; # otherwise 839} 840 841# get default encryption method 842sub encryption_default { 843 local($m) = ""; 844 if ($verbose) { 845 while (&encryption_check($m) == 0) { 846 $m = &confirm_list("Default encryption method for passwords", 1, 847 $encryption_methods[0], @encryption_methods); 848 } 849 } 850 return($m); 851} 852 853# Confirm that we have a valid encryption method 854sub encryption_check { 855 local($m) = $_[0]; 856 857 foreach $i (@encryption_methods) { 858 if ($m eq $i) { return 1; } 859 } 860 861 if ($m =~ /^blowfish,(\d+)$/) { return 1; } 862 return 0; 863} 864 865# misc 866sub check_root { 867 die "You are not root!\n" if $< && !$test; 868} 869 870sub usage { 871 warn <<USAGE; 872usage: adduser 873 [-batch username [group[,group]...] [fullname] [password]] 874 [-check_only] 875 [-config_create] 876 [-dotdir dotdir] 877 [-e|-encryption method] 878 [-group login_group] 879 [-h|-help] 880 [-home home] 881 [-message message_file] 882 [-noconfig] 883 [-shell shell] 884 [-s|-silent|-q|-quiet] 885 [-uid_start uid_start] 886 [-uid_end uid_end] 887 [-unencrypted] 888 [-v|-verbose] 889 890home=$home shell=$defaultshell dotdir=$dotdir login_group=$defaultgroup 891message_file=$send_message uid_start=$uid_start uid_end=$uid_end 892USAGE 893 exit 1; 894} 895 896# uniq(1) 897sub uniq { 898 local(@list) = @_; 899 local($e, $last, @array); 900 901 foreach $e (sort @list) { 902 push(@array, $e) unless $e eq $last; 903 $last = $e; 904 } 905 return @array; 906} 907 908# Generate an appropriate argument to encrypt() 909# That may be a DES salt or a blowfish rotation count 910sub salt { 911 local($salt); # initialization 912 if ($encryptionmethod eq "des" || $encryptionmethod eq "old") { 913 local($i, $rand); 914 local(@itoa64) = ( '0' .. '9', 'a' .. 'z', 'A' .. 'Z' ); # 0 .. 63 915 916 warn "calculate salt\n" if $verbose > 1; 917 918 for ($i = 0; $i < 8; $i++) { 919 srand(time + $rand + $$); 920 $rand = rand(25*29*17 + $rand); 921 $salt .= $itoa64[$rand & $#itoa64]; 922 } 923 } elsif ($encryptionmethod eq "md5") { 924 $salt = ""; 925 } elsif ($encryptionmethod =~ /^blowfish/ ) { 926 ($encryptionmethod, $salt) = split(/\,/, $encryptionmethod); 927 if ($salt eq "") { $salt = 7; } # default rounds inf unspecified 928 } else { 929 warn "$encryptionmethod encryption method invalid\n" if ($verbose > 0); 930 warn "Falling back to blowfish,7...\n" if ($verbose > 0); 931 $encryptionmethod = "blowfish"; 932 $salt = 7; 933 } 934 935 warn "Salt is: $salt\n" if $verbose > 1; 936 937 return $salt; 938} 939 940# Encrypt a password using the selected method 941sub encrypt { 942 local($pass, $salt) = ($_[0], $_[1]); 943 local($args, $crypt); 944 local($goodpass); 945 946 if ($encryptionmethod eq "des" || $encryptionmethod eq "old") { 947 $args = "-s $salt"; 948 } elsif ($encryptionmethod eq "md5") { 949 $args = "-m"; 950 } elsif ($encryptionmethod eq "blowfish") { 951 $args = "-b $salt"; 952 } 953 954 open2(\*ENCRD, \*ENCWR, "/usr/bin/encrypt $args"); 955 print ENCWR "$pass\n"; 956 close ENCWR; 957 $crypt = <ENCRD>; 958 close ENCRD; 959 chomp $crypt; 960 die "encrypt failed" if (wait == -1 || $? != 0); 961 return($crypt); 962} 963 964# print banner 965sub copyright { 966 return; 967} 968 969# hints 970sub hints { 971 if ($verbose) { 972 print "Use option ``-silent'' if you don't want to see " . 973 "all warnings and questions.\n\n"; 974 } 975} 976 977# 978sub parse_arguments { 979 local(@argv) = @_; 980 981 while ($_ = $argv[0], /^-/) { 982 shift @argv; 983 last if /^--$/; 984 if (/^--?(v|verbose)$/) { $verbose = 1 } 985 elsif (/^--?(s|silent|q|quiet)$/) { $verbose = 0 } 986 elsif (/^--?(debug)$/) { $verbose = 2 } 987 elsif (/^--?(h|help|\?)$/) { &usage } 988 elsif (/^--?(home)$/) { $home = $argv[0]; shift @argv } 989 elsif (/^--?(shell)$/) { $defaultshell = $argv[0]; shift @argv } 990 elsif (/^--?(dotdir)$/) { $dotdir = $argv[0]; shift @argv } 991 elsif (/^--?(uid_start)$/) { $uid_start = $argv[0]; shift @argv } 992 elsif (/^--?(uid_end)$/) { $uid_end = $argv[0]; shift @argv } 993 elsif (/^--?(group)$/) { $defaultgroup = $argv[0]; shift @argv } 994 elsif (/^--?(check_only)$/) { $check_only = 1 } 995 elsif (/^--?(message)$/) { $send_message = $argv[0]; shift @argv; 996 $sendmessage = 1; } 997 elsif (/^--?(unencrypted)$/) { $unencrypted = 1 } 998 elsif (/^--?(batch)$/) { 999 @batch = splice(@argv, 0, 4); $verbose = 0; 1000 die "batch: too few arguments\n" if $#batch < 0; 1001 } 1002 # see &config_read 1003 elsif (/^--?(config_create)$/) { ©right; &hints; &create_conf; exit(0); } 1004 elsif (/^--?(noconfig)$/) { $config_read = 0; } 1005 elsif (/^--?(e|encryption)$/) { 1006 $encryptionmethod = $argv[0]; 1007 shift @argv; 1008 } 1009 else { &usage } 1010 } 1011 #&usage if $#argv < 0; 1012} 1013 1014sub basename { 1015 local($name) = @_; 1016 $name =~ s|/+$||; 1017 $name =~ s|.*/+||; 1018 return $name; 1019} 1020 1021sub dirname { 1022 local($name) = @_; 1023 $name = &stripdir($name); 1024 $name =~ s|/+[^/]+$||; 1025 $name = "/" unless $name; # dirname of / is / 1026 return $name; 1027} 1028 1029# return 1 if $file is a readable file or link 1030sub filetest { 1031 local($file, $verb) = @_; 1032 1033 if (-e $file) { 1034 if (-f $file || -l $file) { 1035 return 1 if -r _; 1036 warn "$file unreadable\n" if $verbose; 1037 } else { 1038 warn "$file is not a plain file or link\n" if $verbose; 1039 } 1040 } 1041 return 0; 1042} 1043 1044# create or recreate configuration file prompting for values 1045sub create_conf { 1046 $create_conf = 1; 1047 1048 &shells_read; # Pull in /etc/shells info 1049 &shells_add; # maybe add some new shells 1050 $defaultshell = &shell_default; # enter default shell 1051 $home = &home_partition($home); # find HOME partition 1052 $dotdir = &dotdir_default; # check $dotdir 1053 $send_message = &message_default; # send message to new user 1054 $defaultpasswd = &password_default; # maybe use password 1055 $defaultencryption = &encryption_default; # Encryption method 1056 1057 if ($send_message ne 'no') { 1058 &message_create($send_message); 1059 } else { 1060 &message_create($send_message_bak); 1061 } 1062 &config_write(1); 1063} 1064 1065# log for new user in /var/log/adduser 1066sub adduser_log { 1067 local($string) = @_; 1068 local($e); 1069 1070 return 1 if $logfile eq "no"; 1071 1072 local($sec, $min, $hour, $mday, $mon, $year) = localtime; 1073 $year += 1900; 1074 $mon++; 1075 1076 foreach $e ('sec', 'min', 'hour', 'mday', 'mon') { 1077 # '7' -> '07' 1078 eval "\$$e = 0 . \$$e" if (eval "\$$e" < 10); 1079 } 1080 1081 &append_file($logfile, "$year/$mon/$mday $hour:$min:$sec $string"); 1082} 1083 1084# create HOME directory, copy dotfiles from $dotdir to $HOME 1085sub home_create { 1086 local($name, $group) = @_; 1087 local($homedir) = "$home/$name"; 1088 1089 if (-e "$homedir") { 1090 warn "HOME Directory ``$homedir'' already exists\a\n"; 1091 return 0; 1092 } 1093 1094 if ($dotdir eq 'no') { 1095 if (!mkdir("$homedir",0755)) { 1096 warn "mkdir $homedir: $!\n"; return 0; 1097 } 1098 system 'chown', "$name:$group", $homedir; 1099 return !$?; 1100 } 1101 1102 # copy files from $dotdir to $homedir 1103 # rename 'dot.foo' files to '.foo' 1104 print "Copy files from $dotdir to $homedir\n" if $verbose; 1105 system("cp", "-r", $dotdir, $homedir); 1106 system("chmod", "-R", "u+wrX,go-w", $homedir); 1107 system("chown", "-R", "$name:$group", $homedir); 1108 1109 # security 1110 opendir(D, $homedir); 1111 foreach $file (readdir(D)) { 1112 if ($file =~ /^dot\./ && -f "$homedir/$file") { 1113 $file =~ s/^dot\././; 1114 rename("$homedir/dot$file", "$homedir/$file"); 1115 } 1116 chmod(0600, "$homedir/$file") 1117 if ($file =~ /^\.(rhosts|Xauthority|kermrc|netrc)$/); 1118 chmod(0700, "$homedir/$file") 1119 if ($file =~ /^(Mail|prv|\.(iscreen|term))$/); 1120 } 1121 closedir D; 1122 return 1; 1123} 1124 1125# makes a directory hierarchy 1126sub mkdir_home { 1127 local($dir) = @_; 1128 $dir = &stripdir($dir); 1129 local($user_partition) = "/usr"; 1130 local($dirname) = &dirname($dir); 1131 1132 1133 -e $dirname || &mkdirhier($dirname); 1134 1135 if (((stat($dirname))[0]) == ((stat("/"))[0])){ 1136 # home partition is on root partition 1137 # create home partition on $user_partition and make 1138 # a symlink from $dir to $user_partition/`basename $dir` 1139 # For instance: /home -> /usr/home 1140 1141 local($basename) = &basename($dir); 1142 local($d) = "$user_partition/$basename"; 1143 1144 1145 if (-d $d) { 1146 warn "Oops, $d already exists\n" if $verbose; 1147 } else { 1148 print "Create $d\n" if $verbose; 1149 if (!mkdir("$d", 0755)) { 1150 warn "$d: $!\a\n"; return 0; 1151 } 1152 } 1153 1154 unlink($dir); # symlink to nonexist file 1155 print "Create symlink: $dir -> $d\n" if $verbose; 1156 if (!symlink("$d", $dir)) { 1157 warn "Symlink $d: $!\a\n"; return 0; 1158 } 1159 } else { 1160 print "Create $dir\n" if $verbose; 1161 if (!mkdir("$dir", 0755)) { 1162 warn "Directory ``$dir'': $!\a\n"; return 0; 1163 } 1164 } 1165 return 1; 1166} 1167 1168sub mkdirhier { 1169 local($dir) = @_; 1170 local($d,$p); 1171 1172 $dir = &stripdir($dir); 1173 1174 foreach $d (split('/', $dir)) { 1175 $dir = "$p/$d"; 1176 $dir =~ s|^//|/|; 1177 if (! -e "$dir") { 1178 print "Create $dir\n" if $verbose; 1179 if (!mkdir("$dir", 0755)) { 1180 warn "$dir: $!\n"; return 0; 1181 } 1182 } 1183 $p .= "/$d"; 1184 } 1185 return 1; 1186} 1187 1188# stript unused '/' 1189# F.i.: //usr///home// -> /usr/home 1190sub stripdir { 1191 local($dir) = @_; 1192 1193 $dir =~ s|/+|/|g; # delete double '/' 1194 $dir =~ s|/$||; # delete '/' at end 1195 return $dir if $dir ne ""; 1196 return '/'; 1197} 1198 1199# Read one of the elements from @list. $confirm is default. 1200# If !$allow accept only elements from @list. 1201sub confirm_list { 1202 local($message, $allow, $confirm, @list) = @_; 1203 local($read, $c, $print); 1204 1205 $print = "$message" if $message; 1206 $print .= " " unless $message =~ /\n$/ || $#list == 0; 1207 1208 $print .= join($", &uniq(@list)); #" 1209 $print .= " " unless $message =~ /\n$/ && $#list == 0; 1210 print "$print"; 1211 print "\n" if (length($print) + length($confirm)) > 60; 1212 print "[$confirm]: "; 1213 1214 chop($read = <STDIN>); 1215 $read =~ s/^\s*//; 1216 $read =~ s/\s*$//; 1217 return $confirm if $read eq ""; 1218 return "$read" if $allow; 1219 1220 foreach $c (@list) { 1221 return $read if $c eq $read; 1222 } 1223 warn "$read: is not allowed!\a\n"; 1224 return &confirm_list($message, $allow, $confirm, @list); 1225} 1226 1227# YES or NO question 1228# return 1 if &confirm("message", "yes") and answer is yes 1229# or if &confirm("message", "no") an answer is no 1230# otherwise 0 1231sub confirm_yn { 1232 local($message, $confirm) = @_; 1233 local($yes) = '^(yes|YES|y|Y)$'; 1234 local($no) = '^(no|NO|n|N)$'; 1235 local($read, $c); 1236 1237 if ($confirm && ($confirm =~ "$yes" || $confirm == 1)) { 1238 $confirm = "y"; 1239 } else { 1240 $confirm = "n"; 1241 } 1242 print "$message (y/n) [$confirm]: "; 1243 chop($read = <STDIN>); 1244 $read =~ s/^\s*//; 1245 $read =~ s/\s*$//; 1246 return 1 unless $read; 1247 1248 if (($confirm eq "y" && $read =~ "$yes") || 1249 ($confirm eq "n" && $read =~ "$no")) { 1250 return 1; 1251 } 1252 1253 if ($read !~ "$yes" && $read !~ "$no") { 1254 warn "Wrong value. Enter again!\a\n"; 1255 return &confirm_yn($message, $confirm); 1256 } 1257 return 0; 1258} 1259 1260# test if $dotdir exist 1261# return "no" if $dotdir not exist or dotfiles should not copied 1262sub dotdir_default { 1263 local($dir) = $dotdir; 1264 1265 return &dotdir_default_valid($dir) unless $verbose; 1266 while($verbose) { 1267 $dir = &confirm_list("Copy dotfiles from:", 1, 1268 $dir, ("no", $dotdir_bak, $dir)); 1269 last if $dir eq &dotdir_default_valid($dir); 1270 } 1271 warn "Do not copy dotfiles.\n" if $verbose && $dir eq "no"; 1272 1273 $changes++ if $dir ne $dotdir; 1274 return $dir; 1275} 1276 1277sub dotdir_default_valid { 1278 local($dir) = @_; 1279 1280 return $dir if (-e $dir && -r _ && (-d _ || -l $dir) && $dir =~ "^/"); 1281 return $dir if $dir eq "no"; 1282 warn "Dotdir ``$dir'' is not a directory\a\n"; 1283 return "no"; 1284} 1285 1286# ask for messages to new users 1287sub message_default { 1288 local($file) = $send_message; 1289 local(@d) = ($file, $send_message_bak, "no"); 1290 1291 while($verbose) { 1292 $file = &confirm_list("Send message from file:", 1, $file, @d); 1293 last if $file eq "no"; 1294 last if &filetest($file, 1); 1295 1296 # maybe create message file 1297 &message_create($file) if &confirm_yn("Create ``$file''?", "yes"); 1298 last if &filetest($file, 0); 1299 last if !&confirm_yn("File ``$file'' does not exist, try again?", 1300 "yes"); 1301 } 1302 1303 if ($file eq "no" || !&filetest($file, 0)) { 1304 warn "Do not send message\n" if $verbose; 1305 $file = "no"; 1306 } else { 1307 &message_read($file); 1308 } 1309 1310 $changes++ if $file ne $send_message && $verbose; 1311 return $file; 1312} 1313 1314# create message file 1315sub message_create { 1316 local($file) = @_; 1317 1318 rename($file, "$file.bak"); 1319 if (!open(M, "> $file")) { 1320 warn "Messagefile ``$file'': $!\n"; return 0; 1321 } 1322 print M <<EOF; 1323# 1324# Message file for adduser(8) 1325# comment: ``#'' 1326# default variables: \$name, \$fullname, \$password 1327# other variables: see /etc/adduser.conf after 1328# line ``$do_not_delete'' 1329# 1330 1331\$fullname, 1332 1333your account ``\$name'' was created. 1334Have fun! 1335 1336See also chpass(1), finger(1), passwd(1) 1337EOF 1338 close M; 1339 return 1; 1340} 1341 1342# read message file into buffer 1343sub message_read { 1344 local($file) = @_; 1345 @message_buffer = (); 1346 1347 if (!open(R, "$file")) { 1348 warn "File ``$file'':$!\n"; return 0; 1349 } 1350 while(<R>) { 1351 push(@message_buffer, $_) unless /^\s*#/; 1352 } 1353 close R; 1354} 1355 1356# write @list to $file with file-locking 1357sub append_file { 1358 local($file,@list) = @_; 1359 local($e); 1360 1361 open(F, ">> $file") || die "$file: $!\n"; 1362 print "Lock $file.\n" if $verbose > 1; 1363 while(!flock(F, LOCK_EX | LOCK_NB)) { 1364 warn "Cannot lock file: $file\a\n"; 1365 die "Sorry, give up\n" 1366 unless &confirm_yn("Try again?", "yes"); 1367 } 1368 print F join("\n", @list) . "\n"; 1369 close F; 1370 print "Unlock $file.\n" if $verbose > 1; 1371 flock(F, LOCK_UN); 1372} 1373 1374# return free uid+gid 1375# uid == gid if possible 1376sub next_id { 1377 local($group) = @_; 1378 1379 $uid_start = 1000 if ($uid_start <= 0 || $uid_start >= $uid_end); 1380 # looking for next free uid 1381 while($uid{$uid_start}) { 1382 $uid_start++; 1383 $uid_start = 1000 if $uid_start >= $uid_end; 1384 print "$uid_start\n" if $verbose > 1; 1385 } 1386 1387 local($gid_start) = $uid_start; 1388 # group for user (username==groupname) already exist 1389 if ($groupname{$group}) { 1390 $gid_start = $groupname{$group}; 1391 } 1392 # gid is in use, looking for another gid. 1393 # Note: uid an gid are not equal 1394 elsif ($gid{$uid_start}) { 1395 while($gid{$gid_start} || $uid{$gid_start}) { 1396 $gid_start--; 1397 $gid_start = $uid_end if $gid_start < 100; 1398 } 1399 } 1400 return ($uid_start, $gid_start); 1401} 1402 1403# read config file - typically /etc/adduser.conf 1404sub config_read { 1405 local($opt) = @_; 1406 local($user_flag) = 0; 1407 1408 # don't read config file 1409 return 1 if $opt =~ /-(noconfig|config_create)/ || !$config_read; 1410 1411 if (!-f $config) { 1412 warn("Couldn't find $config: creating a new adduser configuration file\n"); 1413 &create_conf; 1414 } 1415 1416 if (!open(C, "$config")) { 1417 warn "$config: $!\n"; return 0; 1418 } 1419 1420 while(<C>) { 1421 # user defined variables 1422 /^$do_not_delete/ && $user_flag++; 1423 # found @array or $variable 1424 if (s/^(\w+\s*=\s*\()/\@$1/ || s/^(\w+\s*=)/\$$1/) { 1425 eval $_; 1426 #warn "$_"; 1427 } 1428 next if /^$/; 1429 # lines with '^##' are not saved 1430 push(@user_variable_list, $_) 1431 if $user_flag && !/^##/ && (s/^[\$\@]// || /^[#\s]/); 1432 } 1433 #warn "X @user_variable_list X\n"; 1434 close C; 1435} 1436 1437 1438# write config file 1439sub config_write { 1440 local($silent) = @_; 1441 1442 # nothing to do 1443 return 1 unless ($changes || ! -e $config || !$config_read || $silent); 1444 1445 if (!$silent) { 1446 if (-e $config) { 1447 return 1 if &confirm_yn("\nWrite your changes to $config?", "no"); 1448 } else { 1449 return 1 unless 1450 &confirm_yn("\nWrite your configuration to $config?", "yes"); 1451 } 1452 } 1453 1454 rename($config, "$config.bak"); 1455 open(C, "> $config") || die "$config: $!\n"; 1456 1457 # prepare some variables 1458 $send_message = "no" unless $send_message; 1459 $defaultpasswd = "no" unless $defaultpasswd; 1460 local($shpref) = "'" . join("', '", @shellpref) . "'"; 1461 local($shpath) = "'" . join("', '", @path) . "'"; 1462 local($user_var) = join('', @user_variable_list); 1463 1464 print C <<EOF; 1465# 1466# $rcsid 1467# $config - automatic generated by adduser(8) 1468# 1469# Note: adduser reads *and* writes this file. 1470# You may change values, but don't add new things before the 1471# line ``$do_not_delete'' 1472# 1473 1474# verbose = [0-2] 1475verbose = $verbose 1476 1477# Get new password for new users 1478# defaultpasswd = yes | no 1479defaultpasswd = $defaultpasswd 1480 1481# Default encryption method for user passwords 1482# Methods are all those listed in passwd.conf(5) 1483encryptionmethod = "$defaultencryption" 1484 1485# copy dotfiles from this dir ("/etc/skel" or "no") 1486dotdir = "$dotdir" 1487 1488# send this file to new user ("/etc/adduser.message" or "no") 1489send_message = "$send_message" 1490 1491# config file for adduser ("/etc/adduser.conf") 1492config = "$config" 1493 1494# logfile ("/var/log/adduser" or "no") 1495logfile = "$logfile" 1496 1497# default HOME directory ("/home") 1498home = "$home" 1499 1500# List of directories where shells located 1501# path = ('/bin', '/usr/bin', '/usr/local/bin') 1502path = ($shpath) 1503 1504# common shell list, first element has higher priority 1505# shellpref = ('bash', 'tcsh', 'ksh', 'csh', 'sh') 1506shellpref = ($shpref) 1507 1508# defaultshell if not empty ("bash") 1509defaultshell = "$defaultshell" 1510 1511# defaultgroup ('USER' for same as username or any other valid group) 1512defaultgroup = $defaultgroup 1513 1514# new users get this uid 1515uid_start = $uid_start 1516uid_end = $uid_end 1517 1518$do_not_delete 1519## your own variables, see /etc/adduser.message 1520EOF 1521 print C "$user_var\n" if ($user_var ne ''); 1522 print C "\n## end\n"; 1523 close C; 1524} 1525 1526# check for sane variables 1527sub variable_check { 1528 local($abort) = 0; 1529 1530 # Check uid_start & uid_end 1531 warn "WARNING: uid_start < 1000!\n" if($uid_start < 1000); 1532 die "ERROR: uid_start >= uid_end!\n" if($uid_start >= $uid_end); 1533 # unencrypted really only usable in batch mode 1534 warn "WARNING: unencrypted only effective in batch mode\n" 1535 if($#batch < 0 && $unencrypted); 1536} 1537 1538sub cleanup { 1539 local($sig) = @_; 1540 1541 print STDERR "Caught signal SIG$sig -- cleaning up.\n"; 1542 exit(0); 1543} 1544 1545END { 1546 if (-e $etc_ptmp) { 1547 unlink($etc_ptmp) || warn "Error: unable to remove $etc_ptmp: $!\nPlease verify that $etc_ptmp no longer exists!\n"; 1548 } 1549} 1550