head	1.13;
access;
symbols;
locks; strict;
comment	@# @;


1.13
date	96.06.02.19.30.05;	author tobias;	state Exp;
branches;
next	1.12;

1.12
date	96.06.02.19.09.38;	author tobias;	state Exp;
branches;
next	1.11;

1.11
date	96.05.16.20.52.43;	author tobias;	state Exp;
branches;
next	1.10;

1.10
date	95.11.14.17.02.08;	author tobias;	state Exp;
branches;
next	1.9;

1.9
date	95.10.11.18.05.11;	author tobias;	state Exp;
branches;
next	1.8;

1.8
date	95.08.21.22.36.13;	author tobias;	state Exp;
branches;
next	1.7;

1.7
date	95.08.20.21.55.01;	author tobias;	state Exp;
branches;
next	1.6;

1.6
date	95.08.05.21.21.05;	author tobias;	state Exp;
branches;
next	1.5;

1.5
date	95.08.05.21.10.36;	author tobias;	state Exp;
branches;
next	1.4;

1.4
date	95.08.05.21.08.56;	author tobias;	state Exp;
branches;
next	;


desc
@A utility to create an anonymous FTP account
@


1.13
log
@install ~ftp/bin/zip with the correct permissions
remove loader if they are not needed
@
text
@#!/usr/bin/perl
#
# addftpuser: a utility to create an anonymous FTP account
#
# Copyright (C) 1995 Peter Tobias <tobias@@et-inf.fho-emden.de>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

$version = '$Revision: 1.12 $';
$version =~ s/\S+: (\S+) \$/$1/;

$plock = "/etc/ptmp";             # standard method of locking the passwd file
$uid = 10;                        # start searching for a free uid at uid 10
$default_home = "/home/ftp";      # the default ftp home directory
$default_dir_mode = 0755;         # the default directory permissions
$group = "staff";                 # the default group for the ftp hierarchy
$pathmsg = "/etc/ftpd/pathmsg";   # the pathmsg file
$welcomemsg = "/etc/ftpd/welcome.msg"; # the welcome.msg file


# strip directory from the filename
$0 =~ s#.*/##;

# set OUTPUT_AUTOFLUSH
$| = 1;

# don't change the permissions
umask(000);

$updatebin = 0;

while ($ARGV[0] =~ m/^-/) {
  $_ = shift(@@ARGV);
  if (/--help$/) {
    &usage;
  } elsif (/--version$/) {
    &version;
  } elsif (/--check-binaries$/) {
    &checkbin;
  } elsif (/--update-binaries$/) {
    $updatebin = 1;
  } elsif (/--group$/) {
    $group = shift(@@ARGV);
    die "$0: Option group requires an argument\n" unless ($group);
  } else {
    print "$0: Unknown option: $_\n";
    print "$0: Try `$0 --help' for more information.\n";
    exit(10);
  }
}

if (@@ARGV) {
  print "$0: Unknown argument: @@ARGV\n";
  print "$0: Try `$0 --help' for more information.\n";
  exit(10);
}

die "You must be root to run this script.\n" if ($> != 0);

# check if the user "ftp" already exists
setpwent;
if ($home = (getpwnam("ftp"))[7]) {
   if (-d $home) {
     exit(0) unless $updatebin;
   } else {
     print "\nYou already have an anonymous FTP account, but the FTP home\n";
     print "directory [$home] does not exist!\n\nDo you want to create it? [y] ";

     if (<STDIN> =~ /^n/i) {
       exit(0);
     }
   }
   $have_passwd_entry = 1;
}
endpwent;

unless ($have_passwd_entry) {

  print "\nDo you want to set up an anonymous FTP account now? [n] ";
  if (<STDIN> =~ /^[^y]/i) {
    print "\nYou can add an anonymous FTP account later using /usr/sbin/addftpuser\n";
    exit(0);
  }

  # find the first free uid
  setpwent;
  while (getpwuid($uid)) {
    ++$uid;
  }
  endpwent;

  # we need the gid for the ftp account
  setgrent;
   $gid = (getgrnam($group))[2] ||
     die "$0: Oops, I can't find your \"$group\" group\n";
  endgrent;

  # we need the name of the home directory
  while(1) {
    $home = "";
    print "\nEnter the name of the FTP home directory: [$default_home] ";
    chop($home = <STDIN>);
    $home =~ s/\s+//g;         # remove spaces ...
    $home =~ s#//+#/#g;        # we don't want things like // in $home
    $home =~ s#/$##;           # remove trailing slash if it exists

    if (! $home) {
      $home = $default_home;
    }

    if (! ($home =~ m#^/#)) {
      print "\nYou have to use an absolute path for the home directory.\n";
      print "In other words, it must begin with a slash.\n";
      next;
    }
    if (-d $home) {
      print "\n$home does already exist, should I use it? [n] ";
      if (<STDIN> =~ /^[^y]/i) {
        next;
      }
    }
    last;
  }

  print "\nDo you want to create a directory for user uploads? [n] ";
  if (<STDIN> =~ /^[^y]/i) {
    $want_incoming = 0;
  } else {
    $want_incoming = 1;
    print "\nPlease look at /etc/ftpd/ftpaccess and its manual page for\n";
    print "further information on how to make /pub/incoming more secure.\n";
  }

  # don't let the user interrupt us
  &ignore_signals;

  # create a lockfile, add the "ftp" user and remove the lockfile
  if (-f $plock) {
    die "$0: /etc/passwd is locked. Try again later.\n";
  }
  link("/etc/passwd", "$plock") || die "$0: Can't create lockfile\n";

  print "\nCreating anonymous FTP account ...\n";

  open(PASSWD, ">>/etc/passwd") || die "$0: Couldn't append to /etc/passwd\n";
    print PASSWD "ftp:*:$uid:$gid:Anonymous FTP:$home:\n";
  close(PASSWD);

  unlink($plock);
}

# don't let the user interrupt us
if($have_passwd_entry) {
  &ignore_signals;
}

# create the ftp home directory and its subdirectories
@@dirs = split(/\//, $home);
shift(@@dirs);    # remove the first element (it's empty because of the
                 # leading slash in $home)
pop(@@dirs);      # remove the last element (we will create it later)
$done = "";

while(@@dirs) {
   $element = shift(@@dirs);
   unless(-d "$done/$element") {
     mkdir("$done/$element", $default_dir_mode);
   }
   $done = "$done/$element";
}

# if the directory exist fix at least the permissions
chmod(0555, "$home") || mkdir("$home", 0555) ||
	die "$0: can't mkdir $home: $!\n";
chmod(0111, "$home/bin") || mkdir("$home/bin", 0111) ||
	die "$0: can't mkdir $home/bin: $!\n";
chmod(0111, "$home/lib") || mkdir("$home/lib", 0111) ||
	die "$0: can't mkdir $home/lib: $!\n";
chmod(0111, "$home/etc") || mkdir("$home/etc", 0111) ||
	die "$0: can't mkdir $home/etc: $!\n";
chmod(0555, "$home/pub") || mkdir("$home/pub", 0555) ||
	die "$0: can't mkdir $home/pub: $!\n";
chown(0, 0, "$home", "$home/bin", "$home/lib", "$home/etc", "$home/pub");

if ($want_incoming and not $updatebin) {
  chmod(0753, "$home/pub/incoming") || mkdir("$home/pub/incoming", 0753) ||
	die "$0: can't mkdir $home/pub/incoming: $!\n";
  chown(0, 0, "$home/pub/incoming");
}

foreach $prog ("/bin/ls", "/bin/gzip", "/bin/tar") {
  unlink("$home$prog");
  system("cp $prog $home$prog") &&
    die "$0: can't copy $prog to $home$prog. Giving up\n";
}

# optional binaries
if (-f "/usr/bin/zip") {
  system("cp /usr/bin/zip $home/bin/zip") &&
    warn "$0: can't copy /usr/bin/zip to $home/bin/zip (ignored)\n";
  chmod(0111, "$home/bin/zip");
}

opendir(FTPBIN, "$home/bin");
  @@ftpfiles = readdir(FTPBIN);
closedir(FTPBIN);

($aout, $elf) = &filetype("$home/bin", @@ftpfiles);

if($elf) {
    $libc_link=&findlib(5);
    if ($libc_link) {
        $libc=readlink($libc_link) || die "$0: broken symbolic link: $!";
        ($dir = $libc_link) =~ s#[^/]+$## unless($libc =~ m#/#);
        system("cp /lib/ld-linux.so.1 $home/lib") && die "$0: can't copy ld-linux.so.1: $!\n";
        system("cp $dir$libc $home/lib") && die "$0: can't copy $dir$libc: $!\n";
        chmod(0555, "$home/lib/ld-linux.so.1", "$dir$libc");
        if ($libc =~ /\.old$/) {
            $libc =~ s/\.old$//;
            system("mv $home/lib/$libc.old $home/lib/$libc");
        }
        symlink("$libc", "$home/lib/libc.so.5");
#        system("mknod -m 0666 $home/dev/zero c 1 5") && die "$0: mknod failed: $!\n";
    } else {
        print "$0: ELF binaries found but libc.so.5 not available\n";
    }
} else {
    $ftplib = readlink("$home/lib/libc.so.5");
    unlink("$home/lib/$ftplib");
    unlink("$home/lib/ld-linux.so.1");
    unlink("$home/lib/libc.so.5");
}
if($aout) {
    $libc_link=&findlib(4);
    if ($libc_link) {
        $libc = readlink($libc_link) || die "$0: broken symbolic link: $!";
        ($dir = $libc_link) =~ s#[^/]+$## unless($libc =~ m#/#);
        system("cp /lib/ld.so $home/lib") && die "$0: can't copy ld.so: $!\n";
        system("cp $dir$libc $home/lib") && die "$0: can't copy $dir$libc: $!\n";
        chmod(0555, "$home/lib/ld.so", "$dir$libc");
        if ($libc =~ /\.old$/) {
            $libc =~ s/\.old$//;
            system("mv $home/lib/$libc.old $home/lib/$libc");
        }
        symlink("$libc", "$home/lib/libc.so.4");
    } else {
        print "$0: a.out binaries found but libc.so.4 not available\n";
    }
} else {
    $ftplib = readlink("$home/lib/libc.so.4");
    unlink("$home/lib/$ftplib");
    unlink("$home/lib/ld.so");
    unlink("$home/lib/libc.so.4");
}

# copy the pathmsg file (if available)
system("cp $pathmsg $home/etc/pathmsg") unless (-f "$home/etc/pathmsg");

# copy the welcome.msg file (if available)
system("cp $welcomemsg $home/welcome.msg") unless (-f "$home/welcome.msg");

# create the passwd file for the new anonymous ftp hierarchy
open(FPASSWD,">$home/etc/passwd");
  print FPASSWD "root:*:0:0:root::\n";
  print FPASSWD "ftp:*:$uid:$gid:Anonymous FTP::\n";
close(FPASSWD);

# create the group file for the new anonymous ftp hierarchy
open(FGROUP,">$home/etc/group");
  print FGROUP "root\:\:0:\n";
  print FGROUP "$group\:\:$gid:\n";
close(FGROUP);

# fix a few permissions
chmod(0444, "$home/etc/passwd", "$home/etc/group", "$home/etc/pathmsg");
chmod(0111, "$home/bin/ls", "$home/bin/gzip", "$home/bin/tar");

# restore the default signal action. Not really necessary ...
&restore_signals;

############################################################################

sub usage {
  print "Usage: $0 [OPTION]\n\n";
  print "--group group         use this group for the anonymous FTP account\n";
  print "--check-binaries      check whether the binaries and libraries of the\n";
  print "                      ftp hierarchy should be updated or not\n";
  print "--update-binaries     update binaries and libraries of the ftp hierarchy\n";
  print "--help                display this help and exit\n";
  print "--version             output version information and exit\n";
  exit(0);
}

sub version {
  print "$0 $version\n";
  exit(0);
}

sub ignore_signals {
  $SIG{'HUP'} = 'IGNORE';
  $SIG{'INT'} = 'IGNORE';
  $SIG{'QUIT'} = 'IGNORE';
  $SIG{'TERM'} = 'IGNORE';
}

sub restore_signals {
  $SIG{'HUP'} = 'DEFAULT';
  $SIG{'INT'} = 'DEFAULT';
  $SIG{'QUIT'} = 'DEFAULT';
  $SIG{'TERM'} = 'DEFAULT';
}

sub findlib {
    my($v) = @@_;
    open(LD, "/etc/ld.so.conf");
        chomp(@@ld=<LD>);
    close(LD);
    unshift(@@ld, ("/lib", "/usr/lib"));

    while(@@ld) {
        $_ = shift(@@ld);
        return("$_/libc.so.$v") if (-f "$_/libc.so.$v");
    }
    return(0);
}

sub filetype {
    # ($aout, $elf) = &filetype($base_directory, @@filenames_without_path);
    my($dir, @@files) = @@_;
    my($aout, $elf, $string);
    while(@@files) {
        $_ = shift(@@files);
        next if ($_ eq "." or $_ eq "..");
        open(CH, "$dir/$_");
        read(CH, $string, 4);
        if ($string =~ m/\177ELF/) {
           ++$elf;
        } elsif ($string =~ m/..\144./) {
           ++$aout;
        }
        close(CH);
        undef($string);
    }
    return($aout, $elf);
}

sub checkbin {
    # exit with error level 1 if the file formats of /bin/ls
    # and ~ftp/bin/ls are different.
    my($home, $binls_elf, $ftpls_elf);
    setpwent;
    if ($home = (getpwnam("ftp"))[7]) {
        if (-d $home) {
	   (undef, $binls_elf) = &filetype("/bin", "ls");
	   (undef, $ftpls_elf) = &filetype("$home/bin", "ls");
	   if ($binls_elf == $ftpls_elf) {
              # /bin/ls and ~ftp/bin/ls are both elf or a.out
              # no action required
              exit(0);
           } else {
              # the file formats of /bin/ls and ~ftp/bin/ls are
              # different. Return err_lvl 1
              print "\nOld binaries/libraries in $home/bin detected ...\n";
              exit(1);
           }
        }
    }
    endpwent;
}

@


1.12
log
@added --check-binaries and --update-binaries options
@
text
@d22 1
a22 1
$version = '$Revision: 1.11 $';
d214 1
a214 1
  chmod(0111, "/usr/bin/zip");
d243 1
d265 1
d376 1
a376 1
              print "\nOld binaries/libraries in $home/bin detected\n";
@


1.11
log
@set OUTPUT_AUTOFLUSH
@
text
@d22 1
a22 1
$version = '$Revision: 1.10 $';
d43 2
d51 4
d61 1
a61 1
    exit(1);
d68 1
a68 1
  exit(1);
d77 1
a77 1
     exit(0);
a84 1
     $have_passwd_entry = 1;
d86 1
d198 1
a198 1
if ($want_incoming) {
d240 4
d261 4
d297 3
d339 1
d357 25
@


1.10
log
@copy welcome.msg to ~ftp
print a warning if an optional binary does not exist (don't quit)
@
text
@d22 1
a22 1
$version = '$Revision: 1.9 $';
d36 3
@


1.9
log
@using group "staff" in the ~ftp/etc/group file
don't create /dev/zero when using ELF libraries
@
text
@d22 1
a22 1
$version = '$Revision: 1.8 $';
d25 7
a31 6
$plock = "/etc/ptmp";           # standard method of locking the passwd file
$uid = 10;                      # start searching for a free uid at uid 10
$default_home = "/home/ftp";    # the default ftp home directory
$default_dir_mode = 0755;       # the default directory permissions
$group = "staff";               # the default group for the ftp hierarchy
$pathmsg = "/etc/ftpd/pathmsg"; # the pathmsg file
d176 1
d201 1
d204 1
a204 1
    die "$0: can't copy /usr/bin/zip to $home/bin/zip. Giving up\n";
d251 4
a254 1
system("cp $pathmsg $home/etc/pathmsg");
@


1.8
log
@don't ask silly questions if you already have an ftp user
@
text
@d7 4
a10 4
#    addftpuser is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published
#    by the Free Software Foundation; either version 2 of the License,
#    or (at your option) any later version.
d12 4
a15 4
#    addftpuser is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.
d18 2
a19 2
#    along with addftpuser; if not, write to the Free Software Foundation,
#    Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d22 1
a22 1
$version = '$Revision: 1.7 $';
d25 6
a30 5
$plock = "/etc/ptmp";        # standard method of locking the passwd file
$uid = 10;                   # start searching for a free uid at uid 10
$default_home = "/home/ftp"; # the default ftp home directory
$default_dir_mode = 0755;    # the default directory permissions
$group = "staff";            # the default group for the ftp hierarchy
a32 2
die "You must be root to run this script.\n" if ($> != 0);

d61 2
a178 2
chmod(0111, "$home/dev") || mkdir("$home/dev", 0111) ||
	die "$0: can't mkdir $home/dev: $!\n";
d185 1
a185 1
chown(0, 0, "$home", "$home/bin", "$home/dev", "$home/lib", "$home/etc", "$home/pub");
d219 4
d224 1
a224 1
        system("mknod -m 0666 $home/dev/zero c 1 5") && die "$0: mknod failed: $!\n";
d237 4
d247 2
a248 2
system("cp /etc/ftpd/pathmsg $home/etc/pathmsg") &&
  die "$0: can't copy /etc/ftpd/pathmsg to $home/etc/pathmsg. Giving up\n";
d258 2
a259 2
  print FGROUP "root::0:\n";
  print FGROUP "ftp::$gid:\n";
@


1.7
log
@removed --link option (hardlinks)
copy zip to ~ftp/bin if possible
check binaries in ~ftp/bin and copy a.out and/or ELF libraries
search for libraries using /etc/ld.so.conf
@
text
@d22 1
a22 1
$version = '$Revision$';
a61 7
print "\nDo you want to set up an anonymous FTP account now? [n] ";

if (<STDIN> =~ /^[^y]/i) {
  print "\nYou can add an anonymous FTP account later using /usr/sbin/addftpuser\n";
  exit(0);
}

a64 1
   print "\nYou already have an anonymous FTP account";
a65 1
     print ".\n";
d68 2
a69 2
     print ", but the FTP home\ndirectory [$home] does not exist!\n\nDo you want ";
     print "to create it? [y] ";
d80 6
@


1.6
log
@rewrote the newgetopt stuff (newgetopt is not necessary anymore)
@
text
@d18 1
a18 1
#    along with adduser; if not, write to the Free Software Foundation,
d22 2
a23 1
$version = "1.6";
a29 2
$use_hard_links = "no";      # should we create hardlinks instead of copies
                             # when possible? (using copies is more secure!)
a45 2
  } elsif (/--link$/) {
    $use_hard_links = "yes";
d181 2
d189 1
a189 1
chown(0, 0, "$home", "$home/bin", "$home/lib", "$home/etc", "$home/pub");
d197 5
a201 1
# check if we have /lib/libc.so.4 or newer
d203 38
a240 25
# @@libc_link = </lib/libc.so.?>;

opendir(LIB, "/lib/.") || die "$0: opendir failed\n";
(@@libc_link = grep(/^libc\.so\..{1}$/, readdir(LIB))) || die "$0: readdir failed\n";
closedir(LIB);

@@libc_link = sort(@@libc_link);
$libc_link = pop(@@libc_link) || die "$0: can't find /lib/libc.so.*\n";
$libc_link = "/lib/$libc_link";
$libc = readlink($libc_link) || die "$0: broken symbolic link ($libc_link)\n";

# try to create hard links for the following files. If it fails (e.g. they
# are not on the same partition) try to copy them.
@@files = ("/lib/$libc", "/lib/ld.so", "/bin/ls", "/bin/gzip", "/bin/tar");

foreach $prog (@@files) {
  unlink("$home$prog");
  if($use_hard_links eq "yes") {
    link("$prog", "$home$prog") ||
      system("cp $prog $home$prog") &&
        die "$0: can't link/copy $prog to $home$prog. Giving up\n";
  } else {
      system("cp $prog $home$prog") &&
        die "$0: can't copy $prog to $home$prog. Giving up\n";
  }
a241 2
unlink("$home$libc_link");
symlink("$libc", "$home$libc_link");
a258 1
chmod(0555, "$home/lib/libc.so.4", "$home/lib/ld.so");
a268 1
  print "--link                create hard links instead of copies\n";
d294 32
@


1.5
log
@replaced the glob() stuff with readdir ...
@
text
@d22 1
a22 1
$version = "1.5";
d41 17
a57 1
require 'newgetopt.pl';
d59 4
a62 2
unless (&NGetOpt('link', 'group=s', 'help', 'version')) {
  die "$0: Try `$0 --help' for more information.\n"
a63 5

&usage if $opt_help;
&version if $opt_version;
$use_hard_links = "yes" if $opt_link;
$group = $opt_group if $opt_group;
@


1.4
log
@fix permissions of existing directories
@
text
@d22 1
a22 1
$version = "1.4";
d38 3
d186 8
a193 1
@@libc_link = </lib/libc.so.?>;
d195 1
@
