[svn-upgrade] Integrating new upstream version, shadow (19990709)

This commit is contained in:
nekral-guest
2007-10-07 11:44:02 +00:00
parent 9c72ed9062
commit 45c6603cc8
350 changed files with 89554 additions and 0 deletions

5
contrib/Makefile.am Normal file
View File

@@ -0,0 +1,5 @@
# This is a dummy Makefile.am to get automake work flawlessly,
# and also cooperate to make a distribution for `make dist'
EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \
atudel pwdauth.c rpasswd.c shadow-anonftp.patch udbachk.v012.tgz

196
contrib/Makefile.in Normal file
View File

@@ -0,0 +1,196 @@
# Makefile.in generated automatically by automake 1.3 from Makefile.am
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# This is a dummy Makefile.am to get automake work flawlessly,
# and also cooperate to make a distribution for `make dist'
SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
CATALOGS = @CATALOGS@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CPP = @CPP@
DATADIRNAME = @DATADIRNAME@
GENCAT = @GENCAT@
GMOFILES = @GMOFILES@
GMSGFMT = @GMSGFMT@
GT_NO = @GT_NO@
GT_YES = @GT_YES@
INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
INSTOBJEXT = @INSTOBJEXT@
INTLDEPS = @INTLDEPS@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
LD = @LD@
LIBCRACK = @LIBCRACK@
LIBCRYPT = @LIBCRYPT@
LIBPAM = @LIBPAM@
LIBSKEY = @LIBSKEY@
LIBTCFS = @LIBTCFS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
NM = @NM@
PACKAGE = @PACKAGE@
POFILES = @POFILES@
POSUB = @POSUB@
RANLIB = @RANLIB@
U = @U@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
YACC = @YACC@
l = @l@
EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \
atudel pwdauth.c rpasswd.c shadow-anonftp.patch udbachk.v012.tgz
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
DIST_COMMON = README Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
all: Makefile
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps contrib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
tags: TAGS
TAGS:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = contrib
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
info:
dvi:
check: all
$(MAKE)
installcheck:
install-exec:
@$(NORMAL_INSTALL)
install-data:
@$(NORMAL_INSTALL)
install: install-exec install-data all
@:
uninstall:
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-generic
clean: clean-generic mostlyclean
distclean: distclean-generic clean
-rm -f config.status
-rm -f libtool
maintainer-clean: maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
.PHONY: tags distdir info dvi installcheck install-exec install-data \
install uninstall all installdirs mostlyclean-generic distclean-generic \
clean-generic maintainer-clean-generic clean mostlyclean distclean \
maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

10
contrib/README Normal file
View File

@@ -0,0 +1,10 @@
People keep sending various adduser programs and scripts... They are
all in this directory. I haven't tested them, use at your own risk.
Anyway, the best one I've seen so far is adduser-3.x from Debian.
atudel is a perl script to remove at jobs owned by the specified user
(atrm in at-2.9 for Linux can't do that).
udbachk.tgz is a passwd/group/shadow file integrity checker.
--marekm

300
contrib/adduser-old.c Normal file
View File

@@ -0,0 +1,300 @@
/****
** 03/17/96
** hacked a bit more, removed unused code, cleaned up for gcc -Wall.
** --marekm
**
** 02/26/96
** modified to call shadow utils (useradd,chage,passwd) on shadowed
** systems - Cristian Gafton, gafton@sorosis.ro
**
** 6/27/95
** shadow-adduser 1.4:
**
** now it copies the /etc/skel dir into the person's dir,
** makes the mail folders, changed some defaults and made a 'make
** install' just for the hell of it.
**
** Greg Gallagher
** CIN.Net
**
** 1/28/95
** shadow-adduser 1.3:
**
** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
** It was such a stupid bug that I would have never seen it myself.
**
** Brandon
*****
** 01/27/95
**
** shadow-adduser 1.2:
** I took the C source from adduser-shadow (credits are below) and made
** it a little more worthwhile. Many small changes... Here's
** the ones I can remember:
**
** Removed support for non-shadowed systems (if you don't have shadow,
** use the original adduser, don't get this shadow version!)
** Added support for the correct /etc/shadow fields (Min days before
** password change, max days before password change, Warning days,
** and how many days from expiry date does the account go invalid)
** The previous version just left all of those fields blank.
** There is still one field left (expiry date for the account, period)
** which I have left blank because I do not use it and didn't want to
** spend any more time on this. I'm sure someone will put it in and
** tack another plethora of credits on here. :)
** Added in the password date field, which should always reflect the last
** date the password was changed, for expiry purposes. "passwd" always
** updates this field, so the adduser program should set it up right
** initially (or a user could keep thier initial password forever ;)
** The number is in days since Jan 1st, 1970.
**
** Have fun with it, and someone please make
** a real version(this is still just a hack)
** for us all to use (and Email it to me???)
**
** Brandon
** photon@usis.com
**
*****
** adduser 1.0: add a new user account (For systems not using shadow)
** With a nice little interface and a will to do all the work for you.
**
** Craig Hagan
** hagan@opine.cs.umass.edu
**
** Modified to really work, look clean, and find unused uid by Chris Cappuccio
** chris@slinky.cs.umass.edu
**
*****
**
** 01/19/95
**
** FURTHER modifications to enable shadow passwd support (kludged, but
** no more so than the original) by Dan Crowson - dcrowson@mo.net
**
** Search on DAN for all changes...
**
*****
**
** cc -O -o adduser adduser.c
** Use gcc if you have it... (political reasons beyond my control) (chris)
**
** I've gotten this program to work with success under Linux (without
** shadow) and SunOS 4.1.3. I would assume it should work pretty well
** on any system that uses no shadow. (chris)
**
** If you have no crypt() then try
** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c
** I'm not sure how login operates with no crypt()... I guess
** the same way we're doing it here.
*/
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/stat.h>
#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */
#define DEFAULT_HOME "/home"
#define USERADD_PATH "/usr/sbin/useradd"
#define CHAGE_PATH "/usr/sbin/chage"
#define PASSWD_PATH "/usr/bin/passwd"
#define DEFAULT_GROUP 100
#define DEFAULT_MAX_PASS 60
#define DEFAULT_WARN_PASS 10
/* if you use this feature, you will get a lot of complaints from users
who rarely use their accounts :) (something like 3 months would be
more reasonable) --marekm */
#define DEFAULT_USER_DIE /* 10 */ 0
void main()
{
char foo[32];
char uname[9],person[32],dir[32],shell[32];
unsigned int group,min_pass,max_pass,warn_pass,user_die;
/* the group and uid of the new user */
int bad=0,done=0,correct=0,gets_warning=0;
char cmd[255];
struct group *grp;
/* flags, in order:
* bad to see if the username is in /etc/passwd, or if strange stuff has
* been typed if the user might be put in group 0
* done allows the program to exit when a user has been added
* correct loops until a password is found that isn't in /etc/passwd
* gets_warning allows the fflush to be skipped for the first gets
* so that output is still legible
*/
/* The real program starts HERE! */
if(geteuid()!=0)
{
printf("It seems you don't have access to add a new user. Try\n");
printf("logging in as root or su root to gain super-user access.\n");
exit(1);
}
/* Sanity checks
*/
if (!(grp=getgrgid(DEFAULT_GROUP))){
printf("Error: the default group %d does not exist on this system!\n",
DEFAULT_GROUP);
printf("adduser must be recompiled.\n");
exit(1);
};
while(!correct) { /* loop until a "good" uname is chosen */
while(!done) {
printf("\nLogin to add (^C to quit): ");
if(gets_warning) /* if the warning was already shown */
fflush(stdout); /* fflush stdout, otherwise set the flag */
else
gets_warning=1;
gets(uname);
if(!strlen(uname)) {
printf("Empty input.\n");
done=0;
continue;
};
/* what I saw here before made me think maybe I was running DOS */
/* might this be a solution? (chris) */
if (getpwnam(uname) != NULL) {
printf("That name is in use, choose another.\n");
done=0;
} else
done=1;
}; /* done, we have a valid new user name */
/* all set, get the rest of the stuff */
printf("\nEditing information for new user [%s]\n",uname);
printf("\nFull Name [%s]: ",uname);
gets(person);
if (!strlen(person)) {
bzero(person,sizeof(person));
strcpy(person,uname);
};
do {
bad=0;
printf("GID [%d]: ",DEFAULT_GROUP);
gets(foo);
if (!strlen(foo))
group=DEFAULT_GROUP;
else
if (isdigit (*foo)) {
group = atoi(foo);
if (! (grp = getgrgid (group))) {
printf("unknown gid %s\n",foo);
group=DEFAULT_GROUP;
bad=1;
};
} else
if ((grp = getgrnam (foo)))
group = grp->gr_gid;
else {
printf("unknown group %s\n",foo);
group=DEFAULT_GROUP;
bad=1;
}
if (group==0){ /* You're not allowed to make root group users! */
printf("Creation of root group users not allowed (must be done by hand)\n");
group=DEFAULT_GROUP;
bad=1;
};
} while(bad);
fflush(stdin);
printf("\nIf home dir ends with a / then [%s] will be appended to it\n",uname);
printf("Home Directory [%s/%s]: ",DEFAULT_HOME,uname);
fflush(stdout);
gets(dir);
if (!strlen(dir)) { /* hit return */
sprintf(dir,"%s/%s",DEFAULT_HOME,uname);
fflush(stdin);
} else
if (dir[strlen(dir)-1]=='/')
sprintf(dir,"%s%s",dir,uname);
printf("\nShell [%s]: ",DEFAULT_SHELL);
fflush(stdout);
gets(shell);
if (!strlen(shell))
sprintf(shell,"%s",DEFAULT_SHELL);
printf("\nMin. Password Change Days [0]: ");
gets(foo);
min_pass=atoi(foo);
printf("Max. Password Change Days [%d]: ",DEFAULT_MAX_PASS);
gets(foo);
if (strlen(foo) > 1)
max_pass = atoi(foo);
else
max_pass = DEFAULT_MAX_PASS;
printf("Password Warning Days [%d]: ",DEFAULT_WARN_PASS);
gets(foo);
warn_pass = atoi(foo);
if (warn_pass==0)
warn_pass = DEFAULT_WARN_PASS;
printf("Days after Password Expiry for Account Locking [%d]: ",DEFAULT_USER_DIE);
gets(foo);
user_die = atoi(foo);
if (user_die == 0)
user_die = DEFAULT_USER_DIE;
printf("\nInformation for new user [%s] [%s]:\n",uname,person);
printf("Home directory: [%s] Shell: [%s]\n",dir,shell);
printf("GID: [%d]\n",group);
printf("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n",
min_pass,max_pass,warn_pass,user_die);
printf("\nIs this correct? [y/N]: ");
fflush(stdout);
gets(foo);
done=bad=correct=(foo[0]=='y'||foo[0]=='Y');
if(bad!=1)
printf("\nUser [%s] not added\n",uname);
}
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s",
USERADD_PATH,group,dir,shell,person,uname);
printf("Calling useradd to add new user:\n%s\n",cmd);
if(system(cmd)){
printf("User add failed!\n");
exit(errno);
};
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH,
min_pass,max_pass,warn_pass,user_die,uname);
printf("%s\n",cmd);
if(system(cmd)){
printf("There was an error setting password expire values\n");
exit(errno);
};
bzero(cmd,sizeof(cmd));
sprintf(cmd,"%s %s",PASSWD_PATH,uname);
system(cmd);
printf("\nDone.\n");
}

502
contrib/adduser.c Normal file
View File

@@ -0,0 +1,502 @@
/****
** 04/21/96
** hacked even more, replaced gets() with something slightly harder to buffer
** overflow. Added support for setting a default quota on new account, with
** edquota -p. Other cleanups for security, I let some users run adduser suid
** root to add new accounts. (overflow checks, clobber environment, valid
** shell checks, restrictions on gid + home dir settings).
** Added max. username length. Used syslog() a bit for important events.
** Support to immediately expire account with passwd -e.
** Called it version 2.0! Because I felt like it!
** -- Chris, chris@ferret.lmh.ox.ac.uk
** 03/17/96
** hacked a bit more, removed unused code, cleaned up for gcc -Wall.
** --marekm
**
** 02/26/96
** modified to call shadow utils (useradd,chage,passwd) on shadowed
** systems - Cristian Gafton, gafton@sorosis.ro
**
** 6/27/95
** shadow-adduser 1.4:
**
** now it copies the /etc/skel dir into the person's dir,
** makes the mail folders, changed some defaults and made a 'make
** install' just for the hell of it.
**
** Greg Gallagher
** CIN.Net
**
** 1/28/95
** shadow-adduser 1.3:
**
** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart
** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced.
** It was such a stupid bug that I would have never seen it myself.
**
** Brandon
*****
** 01/27/95
**
** shadow-adduser 1.2:
** I took the C source from adduser-shadow (credits are below) and made
** it a little more worthwhile. Many small changes... Here's
** the ones I can remember:
**
** Removed support for non-shadowed systems (if you don't have shadow,
** use the original adduser, don't get this shadow version!)
** Added support for the correct /etc/shadow fields (Min days before
** password change, max days before password change, Warning days,
** and how many days from expiry date does the account go invalid)
** The previous version just left all of those fields blank.
** There is still one field left (expiry date for the account, period)
** which I have left blank because I do not use it and didn't want to
** spend any more time on this. I'm sure someone will put it in and
** tack another plethora of credits on here. :)
** Added in the password date field, which should always reflect the last
** date the password was changed, for expiry purposes. "passwd" always
** updates this field, so the adduser program should set it up right
** initially (or a user could keep thier initial password forever ;)
** The number is in days since Jan 1st, 1970.
**
** Have fun with it, and someone please make
** a real version(this is still just a hack)
** for us all to use (and Email it to me???)
**
** Brandon
** photon@usis.com
**
*****
** adduser 1.0: add a new user account (For systems not using shadow)
** With a nice little interface and a will to do all the work for you.
**
** Craig Hagan
** hagan@opine.cs.umass.edu
**
** Modified to really work, look clean, and find unused uid by Chris Cappuccio
** chris@slinky.cs.umass.edu
**
*****
**
** 01/19/95
**
** FURTHER modifications to enable shadow passwd support (kludged, but
** no more so than the original) by Dan Crowson - dcrowson@mo.net
**
** Search on DAN for all changes...
**
*****
**
** cc -O -o adduser adduser.c
** Use gcc if you have it... (political reasons beyond my control) (chris)
**
** I've gotten this program to work with success under Linux (without
** shadow) and SunOS 4.1.3. I would assume it should work pretty well
** on any system that uses no shadow. (chris)
**
** If you have no crypt() then try
** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c
** I'm not sure how login operates with no crypt()... I guess
** the same way we're doing it here.
*/
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <syslog.h>
#define IMMEDIATE_CHANGE /* Expire newly created password, must be changed
* immediately upon next login */
#define HAVE_QUOTAS /* Obvious */
#define EXPIRE_VALS_SET /* If defined, 'normal' users can't change
* password expiry values (if running suid root) */
#define HAVE_GETUSERSHELL /* FIXME: Isn't this defined in config.h too? */
#define LOGGING /* If we want to log various things to syslog */
#define MAX_USRNAME 8 /* Longer usernames seem to work on my system....
* But they're probably a poor idea */
#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */
#define DEFAULT_HOME "/home"
#define USERADD_PATH "/usr/sbin/useradd"
#define CHAGE_PATH "/usr/bin/chage"
#define PASSWD_PATH "/usr/bin/passwd"
#define EDQUOTA_PATH "/usr/sbin/edquota"
#define QUOTA_DEFAULT "defuser"
#define DEFAULT_GROUP 100
#define DEFAULT_MIN_PASS 0
#define DEFAULT_MAX_PASS 100
#define DEFAULT_WARN_PASS 14
#define DEFAULT_USER_DIE 366
void safeget (char *, int);
void
main (void)
{
char foo[32];
char usrname[32], person[32], dir[32], shell[32];
unsigned int group, min_pass, max_pass, warn_pass, user_die;
/* the group and uid of the new user */
int bad = 0, done = 0, correct = 0, olduid;
char cmd[255];
struct group *grp;
/* flags, in order:
* bad to see if the username is in /etc/passwd, or if strange stuff has
* been typed if the user might be put in group 0
* done allows the program to exit when a user has been added
* correct loops until a username is found that isn't in /etc/passwd
*/
/* The real program starts HERE! */
if (geteuid () != 0)
{
printf ("It seems you don't have access to add a new user. Try\n");
printf ("logging in as root or su root to gain super-user access.\n");
exit (1);
}
/* Sanity checks
*/
#ifdef LOGGING
openlog ("adduser", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
syslog (LOG_INFO, "invoked by user %s\n", getpwuid (getuid ())->pw_name);
#endif
if (!(grp = getgrgid (DEFAULT_GROUP)))
{
printf ("Error: the default group %d does not exist on this system!\n",
DEFAULT_GROUP);
printf ("adduser must be recompiled.\n");
#ifdef LOGGING
syslog (LOG_ERR, "warning: failed. no such default group\n");
closelog ();
#endif
exit (1);
};
while (!correct)
{ /* loop until a "good" usrname is chosen */
while (!done)
{
printf ("\nLogin to add (^C to quit): ");
fflush (stdout);
safeget (usrname, sizeof (usrname));
if (!strlen (usrname))
{
printf ("Empty input.\n");
done = 0;
continue;
};
/* what I saw here before made me think maybe I was running DOS */
/* might this be a solution? (chris) */
if (strlen (usrname) > MAX_USRNAME)
{
printf ("That name is longer than the maximum of %d characters. Choose another.\n", MAX_USRNAME);
done = 0;
}
else if (getpwnam (usrname) != NULL)
{
printf ("That name is in use, choose another.\n");
done = 0;
}
else if (strchr (usrname, ' ') != NULL)
{
printf ("No spaces in username!!\n");
done = 0;
}
else
done = 1;
}; /* done, we have a valid new user name */
/* all set, get the rest of the stuff */
printf ("\nEditing information for new user [%s]\n", usrname);
printf ("\nFull Name [%s]: ", usrname);
fflush (stdout);
safeget (person, sizeof (person));
if (!strlen (person))
{
bzero (person, sizeof (person));
strcpy (person, usrname);
};
if (getuid () == 0)
{
do
{
bad = 0;
printf ("GID [%d]: ", DEFAULT_GROUP);
fflush (stdout);
safeget (foo, sizeof (foo));
if (!strlen (foo))
group = DEFAULT_GROUP;
else if (isdigit (*foo))
{
group = atoi (foo);
if (!(grp = getgrgid (group)))
{
printf ("unknown gid %s\n", foo);
group = DEFAULT_GROUP;
bad = 1;
};
}
else if ((grp = getgrnam (foo)))
group = grp->gr_gid;
else
{
printf ("unknown group %s\n", foo);
group = DEFAULT_GROUP;
bad = 1;
}
if (group == 0)
{ /* You're not allowed to make root group users! */
printf ("Creation of root group users not allowed (must be done by hand)\n");
group = DEFAULT_GROUP;
bad = 1;
};
}
while (bad);
}
else
{
printf ("Group will be default of: %d\n", DEFAULT_GROUP);
group = DEFAULT_GROUP;
}
if (getuid () == 0)
{
printf ("\nIf home dir ends with a / then '%s' will be appended to it\n", usrname);
printf ("Home Directory [%s/%s]: ", DEFAULT_HOME, usrname);
fflush (stdout);
safeget (dir, sizeof (dir));
if (!strlen (dir))
{ /* hit return */
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
}
else if (dir[strlen (dir) - 1] == '/')
sprintf (dir, "%s%s", dir, usrname);
}
else
{
printf ("\nHome directory will be %s/%s\n", DEFAULT_HOME, usrname);
sprintf (dir, "%s/%s", DEFAULT_HOME, usrname);
}
printf ("\nShell [%s]: ", DEFAULT_SHELL);
fflush (stdout);
safeget (shell, sizeof (shell));
if (!strlen (shell))
sprintf (shell, "%s", DEFAULT_SHELL);
else
{
char *sh;
int ok = 0;
#ifdef HAVE_GETUSERSHELL
setusershell ();
while ((sh = getusershell ()) != NULL)
if (!strcmp (shell, sh))
ok = 1;
endusershell ();
#endif
if (!ok)
{
if (getuid () == 0)
printf ("Warning: root allowed non standard shell\n");
else
{
printf ("Shell NOT in /etc/shells, DEFAULT used\n");
sprintf (shell, "%s", DEFAULT_SHELL);
}
}
}
#ifdef EXPIRE_VALS_SET
if (getuid () == 0)
{
#endif
printf ("\nMin. Password Change Days [%d]: ", DEFAULT_MIN_PASS);
fflush (stdout);
safeget (foo, sizeof (foo));
if (strlen (foo) > 1)
min_pass = DEFAULT_MIN_PASS;
else
min_pass = atoi (foo);
printf ("Max. Password Change Days [%d]: ", DEFAULT_MAX_PASS);
fflush (stdout);
safeget (foo, sizeof (foo));
if (strlen (foo) > 1)
max_pass = atoi (foo);
else
max_pass = DEFAULT_MAX_PASS;
printf ("Password Warning Days [%d]: ", DEFAULT_WARN_PASS);
fflush (stdout);
safeget (foo, sizeof (foo));
warn_pass = atoi (foo);
if (warn_pass == 0)
warn_pass = DEFAULT_WARN_PASS;
printf ("Days after Password Expiry for Account Locking [%d]: ", DEFAULT_USER_DIE);
fflush (stdout);
safeget (foo, sizeof (foo));
user_die = atoi (foo);
if (user_die == 0)
user_die = DEFAULT_USER_DIE;
#ifdef EXPIRE_VALS_SET
}
else
{
printf ("\nSorry, account expiry values are set.\n");
user_die = DEFAULT_USER_DIE;
warn_pass = DEFAULT_WARN_PASS;
max_pass = DEFAULT_MAX_PASS;
min_pass = DEFAULT_MIN_PASS;
}
#endif
printf ("\nInformation for new user [%s] [%s]:\n", usrname, person);
printf ("Home directory: [%s] Shell: [%s]\n", dir, shell);
printf ("GID: [%d]\n", group);
printf ("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n",
min_pass, max_pass, warn_pass, user_die);
printf ("\nIs this correct? [y/N]: ");
fflush (stdout);
safeget (foo, sizeof (foo));
done = bad = correct = (foo[0] == 'y' || foo[0] == 'Y');
if (bad != 1)
printf ("\nUser [%s] not added\n", usrname);
}
/* Clobber the environment, I run this suid root sometimes to let
* non root privileged accounts add users --chris */
*environ = NULL;
bzero (cmd, sizeof (cmd));
sprintf (cmd, "%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s",
USERADD_PATH, group, dir, shell, person, usrname);
printf ("Calling useradd to add new user:\n%s\n", cmd);
if (system (cmd))
{
printf ("User add failed!\n");
#ifdef LOGGING
syslog (LOG_ERR, "could not add new user\n");
closelog ();
#endif
exit (errno);
};
olduid = getuid (); /* chage, passwd, edquota etc. require ruid = root
*/
setuid (0);
bzero (cmd, sizeof (cmd));
/* Chage runs suid root. => we need ruid root to run it with
* anything other than chage -l
*/
sprintf (cmd, "%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH,
min_pass, max_pass, warn_pass, user_die, usrname);
printf ("%s\n", cmd);
if (system (cmd))
{
printf ("There was an error setting password expire values\n");
#ifdef LOGGING
syslog (LOG_ERR, "password expire values could not be set\n");
#endif
};
/* I want to add a user completely with one easy command --chris */
#ifdef HAVE_QUOTAS
bzero (cmd, sizeof (cmd));
sprintf (cmd, "%s -p %s -u %s", EDQUOTA_PATH, QUOTA_DEFAULT, usrname);
printf ("%s\n", cmd);
if (system (cmd))
{
printf ("\nWarning: error setting quota\n");
#ifdef LOGGING
syslog (LOG_ERR, "warning: account created but NO quotas set!\n");
#endif /* LOGGING */
}
else
printf ("\nDefault quota set.\n");
#endif /* HAVE_QUOTAS */
bzero (cmd, sizeof (cmd));
sprintf (cmd, "%s %s", PASSWD_PATH, usrname);
if (system (cmd))
{
printf ("\nWarning: error setting password\n");
#ifdef LOGGING
syslog (LOG_ERR, "warning: password set failed!\n");
#endif
}
#ifdef IMMEDIATE_CHANGE
bzero (cmd, sizeof (cmd));
sprintf (cmd, "%s -e %s", PASSWD_PATH, usrname);
if (system (cmd))
{
printf ("\nWarning: error expiring password\n");
#ifdef LOGGING
syslog (LOG_ERR, "warning: password expire failed!\n");
#endif /* LOGGING */
}
#endif /* IMMEDIATE_CHANGE */
setuid (olduid);
#ifdef LOGGING
closelog ();
#endif
printf ("\nDone.\n");
}
void
safeget (char *buf, int maxlen)
{
int c, i = 0, bad = 0;
char *bstart = buf;
while ((c = getc (stdin)) != EOF && (c != '\n') && (++i < maxlen))
{
bad = (!isalnum (c) && (c != '_') && (c != ' '));
*(buf++) = (char) c;
}
*buf = '\0';
if (bad)
{
printf ("\nString contained banned character. Please stick to alphanumerics.\n");
*bstart = '\0';
}
}

90
contrib/adduser.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
# adduser script for use with shadow passwords and useradd command.
# by Hrvoje Dogan <hdogan@student.math.hr>, Dec 1995.
echo -n "Login name for new user []:"
read LOGIN
if [ -z $LOGIN ]
then echo "Come on, man, you can't leave the login field empty...";exit
fi
echo
echo -n "User id for $LOGIN [ defaults to next available]:"
read ID
GUID="-u $ID"
if [ -z $ID ]
then GUID=""
fi
echo
echo -n "Initial group for $LOGIN [users]:"
read GID
GGID="-g $GID"
if [ -z $GID ]
then GGID=""
fi
echo
echo -n "Additional groups for $LOGIN []:"
read AGID
GAGID="-G $AGID"
if [ -z $AGID ]
then GAGID=""
fi
echo
echo -n "$LOGIN's home directory [/home/$LOGIN]:"
read HME
GHME="-d $HME"
if [ -z $HME ]
then GHME=""
fi
echo
echo -n "$LOGIN's shell [/bin/bash]:"
read SHL
GSHL="-s $SHL"
if [ -z $SHL ]
then GSHL=""
fi
echo
echo -n "$LOGIN's account expiry date (MM/DD/YY) []:"
read EXP
GEXP="-e $EXP"
if [ -z $EXP ]
then GEXP=""
fi
echo
echo OK, I'm about to make a new account. Here's what you entered so far:
echo New login name: $LOGIN
if [ -z $GUID ]
then echo New UID: [Next available]
else echo New UID: $UID
fi
if [ -z $GGID ]
then echo Initial group: users
else echo Initial group: $GID
fi
if [ -z $GAGID ]
then echo Additional groups: [none]
else echo Additional groups: $AGID
fi
if [ -z $GHME ]
then echo Home directory: /home/$LOGIN
else echo Home directory: $HME
fi
if [ -z $GSHL ]
then echo Shell: /bin/bash
else echo Shell: $SHL
fi
if [ -z $GEXP ]
then echo Expiry date: [no expiration]
else echo Expiry date: $EXP
fi
echo "This is it... if you want to bail out, you'd better do it now."
read FOO
echo Making new account...
/usr/sbin/useradd $GHME -m $GEXP $GGID $GAGID $GSHL $GUID $LOGIN
/usr/bin/chfn $LOGIN
/usr/bin/passwd $LOGIN
echo "Done..."

743
contrib/adduser2.sh Executable file
View File

@@ -0,0 +1,743 @@
#!/bin/bash
#
# adduser Interactive user adding program.
#
# Copyright (C) 1996 Petri Mattila, Prihateam Networks
# petri@prihateam.fi
#
# 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, or (at your option)
# any later version.
#
# Changes:
# 220496 v0.01 Initial version
# 230496 v0.02 More checks, embolden summary
# 240496 Even more checks
# 250496 Help with ?
# 040596 v0.03 Cleanups
# 050596 v0.04 Bug fixes, expire date checks
# 070596 v0.05 Iso-latin-1 names
#
## Defaults
# default groups
def_group="users"
def_other_groups=""
# default home directory
def_home_dir=/home/users
# default shell
def_shell=/bin/tcsh
# Defaul expiration date (mm/dd/yy)
def_expire=""
# default dates
def_pwd_min=0
def_pwd_max=90
def_pwd_warn=14
def_pwd_iact=14
# possible UIDs
uid_low=1000
uid_high=64000
# skel directory
skel=/etc/skel
# default mode for home directory
def_mode=711
# Regex, that the login name must meet, only ANSI characters
login_regex='^[0-9a-zA-Z_-]*$'
# Regex, that the user name must meet
# ANSI version
##name_regex='^[0-9a-zA-Z_-\ ]*$'
# ISO-LATIN-1 version
name_regex='^[0-9a-zA-Z<><5A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>_-\ ]*$'
# set PATH
export PATH="/bin:/sbin:/usr/bin:/usr/sbin"
# Some special characters
case "$TERM" in
vt*|ansi*|con*|xterm*|linux*)
S='' # start embolden
E='' # end embolden
;;
*)
S=''
E=''
;;
esac
## Functions
check_root() {
if test "$EUID" -ne 0
then
echo "You must be root to run this program."
exit 1
fi
}
check_user() {
local usr pwd uid gid name home sh
cat /etc/passwd | (
while IFS=":" read usr pwd uid gid name home sh
do
if test "$1" = "${usr}"
then
return 1
fi
done
return 0
)
}
check_group() {
local read grp pwd gid members
cat /etc/group | (
while IFS=":" read grp pwd gid members
do
if test "$1" = "${grp}"
then
return 1
fi
done
return 0
)
}
check_other_groups() {
local grp check IFS
check="$1"
IFS=","
set ${check}
for grp
do
if check_group "${grp}"
then
echo "Group ${grp} does not exist."
return 1
fi
done
return 0
}
check_uid() {
local usr pwd uid gid name home sh
cat /etc/passwd | (
while IFS=":" read usr pwd uid gid name home sh
do
if test "$1" = "${uid}"
then
return 1
fi
done
return 0
)
}
read_yn() {
local ans ynd
ynd="$1"
while :
do
read ans
case "${ans}" in
"") return ${ynd} ;;
[nN]) return 1 ;;
[yY]) return 0 ;;
*) echo -n "Y or N, please ? " ;;
esac
done
}
read_login() {
echo
while :
do
echo -n "Login: ${def_login:+[${def_login}] }"
read login
if test "${login}" = '?'
then
less /etc/passwd
echo
continue
fi
if test -z "${login}" -a -n "${def_login}"
then
login="${def_login}"
echo "Using ${login}"
return
fi
if test "${#login}" -gt 8
then
echo "Login must be at most 8 characters long"
continue
fi
if test "${#login}" -lt 2
then
echo "Login must be at least 2 characters long"
continue
fi
if ! expr "${login}" : "${login_regex}" &> /dev/null
then
echo "Please use letters, numbers and special characters _-,."
continue
fi
if ! check_user "${login}"
then
echo "Username ${login} is already in use"
continue
fi
def_login="${login}"
return
done
}
read_name () {
echo
while :
do
echo -n "Real name: ${def_name:+[${def_name}] }"
read name
if test "${name}" = '?'
then
less /etc/passwd
echo
continue
fi
if test -z "${name}" -a -n "${def_name}"
then
name="${def_name}"
echo "Using ${name}"
fi
if test "${#name}" -gt 32
then
echo "Name should be at most 32 characters long"
continue
fi
if ! expr "${name}" : "${name_regex}" &> /dev/null
then
echo "Please use letters, numbers, spaces and special characters ,._-"
continue
fi
def_name="${name}"
return
done
}
read_home() {
local x
echo
while :
do
echo -n "Home Directory: [${def_home_dir}/${login}] "
read home
if test -z "${home}"
then
home="${def_home_dir}/${login}"
echo "Using ${home}"
fi
if ! expr "${home}" : '^[0-9a-zA-Z,._-\/]*$' &> /dev/null
then
echo "Please use letters, numbers, spaces and special characters ,._-/"
continue
fi
x="$(basename ${home})"
if test "${x}" != "${login}"
then
echo "Warning: you are about to use different login name and home directory."
fi
x="$(dirname ${home})"
if ! test -d "${x}"
then
echo "Directory ${x} does not exist."
echo "If you still want to use it, please make it manually."
continue
fi
def_home_dir="${x}"
return
done
}
read_shell () {
local x
echo
while :
do
echo -n "Shell: [${def_shell}] "
read shell
if test -z "${shell}"
then
shell="${def_shell}"
echo "Using ${shell}"
fi
for x in $(cat /etc/shells)
do
if test "${x}" = "${shell}"
then
def_shell="${shell}"
return
fi
done
echo "Possible shells are:"
cat /etc/shells
done
}
read_group () {
echo
while :
do
echo -n "Group: [${def_group}] "
read group
if test -z "${group}"
then
group="${def_group}"
echo "Using ${group}"
fi
if test "${group}" = '?'
then
less /etc/group
echo
continue
fi
if check_group "${group}"
then
echo "Group ${group} does not exist."
continue
fi
def_group="${group}"
return
done
}
read_other_groups () {
echo
while :
do
echo -n "Other groups: [${def_og:-none}] "
read other_groups
if test "${other_groups}" = '?'
then
less /etc/group
echo
continue
fi
if test -z "${other_groups}"
then
if test -n "${def_og}"
then
other_groups="${def_og}"
echo "Using ${other_groups}"
else
echo "No other groups"
return
fi
fi
if ! check_other_groups "${other_groups}"
then
continue
fi
def_og="${other_groups}"
return
done
}
read_uid () {
echo
while :
do
echo -n "uid: [first free] "
read uid
if test -z "${uid}"
then
echo "Using first free UID."
return
fi
if test "${uid}" = '?'
then
less /etc/passwd
echo
continue
fi
if ! expr "${uid}" : '^[0-9]+$' &> /dev/null
then
echo "Please use numbers only."
continue
fi
if test "${uid}" -lt "${uid_low}"
then
echo "UID must be greater than ${uid_low}"
continue
fi
if test "${uid}" -gt "${uid_high}"
then
echo "UID must be smaller than ${uid_high}"
continue
fi
if ! check_uid "${uid}"
then
echo "UID ${uid} is already in use"
continue
fi
return
done
}
read_max_valid_days() {
echo
while :
do
echo -en "Maximum days between password changes: [${def_pwd_max}] "
read max_days
if test -z "${max_days}"
then
max_days="${def_pwd_max}"
echo "Using ${max_days}"
return
fi
if ! expr "${max_days}" : '^[0-9]+$' &> /dev/null
then
echo "Please use numbers only."
continue
fi
if test "${max_days}" -lt 7
then
echo "Warning: you are using a value shorter than a week."
fi
def_pwd_max="${max_days}"
return
done
}
read_min_valid_days() {
echo
while :
do
echo -en "Minimum days between password changes: [${def_pwd_min}] "
read min_days
if test -z "${min_days}"
then
min_days="${def_pwd_min}"
echo "Using ${min_days}"
return
fi
if ! expr "${min_days}" : '^[0-9]+$' &> /dev/null
then
echo "Please use numbers only."
continue
fi
if test "${min_days}" -gt 7
then
echo "Warning: you are using a value longer than a week."
fi
def_pwd_min="${min_days}"
return
done
}
read_warning_days() {
echo
while :
do
echo -en "Number of warning days before password expires: [${def_pwd_warn}] "
read warn_days
if test -z "${warn_days}"
then
warn_days="${def_pwd_warn}"
echo "Using ${warn_days}"
fi
if ! expr "${warn_days}" : '^[0-9]+$' &> /dev/null
then
echo "Please use numbers only."
continue
fi
if test "${warn_days}" -gt 14
then
echo "Warning: you are using a value longer than two week."
fi
def_pwd_warn="${warn_days}"
return
done
}
read_inactive_days() {
echo
while :
do
echo -en "Number of usable days after expiration: [${def_pwd_iact}] "
read iact_days
if test -z "${iact_days}"
then
iact_days="${def_pwd_iact}"
echo "Using ${iact_days}"
return
fi
if ! expr "${iact_days}" : '^[0-9]+$' &> /dev/null
then
echo "Please use numbers only."
continue
fi
if test "${iact_days}" -gt 14
then
echo "Warning: you are using a value that is more than two weeks."
fi
def_pwd_iact="${iact_days}"
return
done
}
read_expire_date() {
local ans
echo
while :
do
echo -en "Expire date of this account (mm/dd/yy): [${def_expire:-never}] "
read ans
if test -z "${ans}"
then
if test -z "${def_expire}"
then
ans="never"
else
ans="${def_expire}"
echo "Using ${def_expire}"
fi
fi
if test "${ans}" = "never"
then
echo "Account will never expire."
def_expire=""
expire=""
return
fi
if ! expr "${ans}" : '^[0-9][0-9]/[0-9][0-9]/[0-9][0-9]$' &> /dev/null
then
echo "Please use format mm/dd/yy"
continue
fi
if ! expire_date="$(date -d ${ans} '+%A, %B %d %Y')"
then
continue
fi
def_expire="${expire}"
return
done
}
read_passwd_yn() {
echo -en "\nDo you want to set password [Y/n] ? "
if read_yn 0
then
set_pwd="YES"
else
set_pwd=""
fi
}
print_values() {
clear
cat << EOM
Login: ${S}${login}${E}
Group: ${S}${group}${E}
Other groups: ${S}${other_groups:-[none]}${E}
Real Name: ${S}${name}${E}
uid: ${S}${uid:-[first free]}${E}
home: ${S}${home}${E}
shell: ${S}${shell}${E}
Account expiration date: ${S}${expire_date:-never}${E}
Minimum days between password changes: ${S}${min_days}${E}
Maximum days between password changes: ${S}${max_days}${E}
Number of usable days after expiration: ${S}${iact_days}${E}
Number of warning days before expiration: ${S}${warn_days}${E}
${S}${set_pwd:+Set password for this account.}${E}
EOM
}
set_user() {
if ! useradd \
-c "${name}" \
-d "${home}" \
-g "${group}" \
-s "${shell}" \
${expire:+-e ${expire}} \
${uid:+-u ${uid}} \
${other_groups:+-G ${other_groups}} \
${login}
then
echo "Error ($?) in useradd...exiting..."
exit 1
fi
}
set_aging() {
if ! passwd \
-x ${max_days} \
-n ${min_days} \
-w ${warn_days} \
-i ${iact_days} \
${login}
then
echo "Error ($?) in setting password aging...exiting..."
exit 1
fi
}
set_password() {
if test -n "${set_pwd}"
then
echo
passwd ${login}
echo
fi
}
set_system() {
if test -d "${home}"
then
echo "Directory ${home} already exists."
echo "Skeleton files not copied."
return
fi
echo -n "Copying skeleton files..."
(
mkdir ${home}
cd ${skel} && cp -af . ${home}
chmod ${def_mode} ${home}
chown -R ${login}:${group} ${home}
)
echo "done."
## Add your own stuff here:
echo -n "Setting up other files..."
(
mailbox="/var/spool/mail/${login}"
touch ${mailbox}
chown "${login}:mail" ${mailbox}
chmod 600 ${mailbox}
)
echo "done."
}
read_values() {
clear
echo -e "\nPlease answer the following questions about the new user to be added."
while :
do
read_login
read_name
read_group
read_other_groups
read_home
read_shell
read_uid
read_expire_date
read_max_valid_days
read_min_valid_days
read_warning_days
read_inactive_days
read_passwd_yn
print_values
echo -n "Is this correct [N/y] ? "
read_yn 1 && return
done
}
main() {
check_root
read_values
set_user
set_aging
set_system
set_password
}
## Run it 8-)
main
# End.

85
contrib/atudel Executable file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/perl
#
# Copyright (c) 1996 Brian R. Gaeke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Brian R. Gaeke.
# 4. The name of the author, Brian R. Gaeke, may not be used to endorse
# or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY BRIAN R. GAEKE ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL BRIAN R. GAEKE BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Additionally:
#
# This software is provided without support and without any obligation
# on the part of Brian R. Gaeke to assist in its use, correction,
# modification or enhancement.
#
#######################################################################
#
# this is atudel, version 2, by Brian R. Gaeke <brg@dgate.org>
#
require "getopts.pl";
&Getopts('v');
$username = shift(@ARGV);
&usage unless $username;
sub usage
{
print STDERR "atudel - remove all at jobs owned by a user\n";
print STDERR "usage: $0 [-v] username\n";
exit(1);
}
# odd. unless getpwnam($uname) doesn't seem to work for $uname eq "root" on
# my linux system. but this does.
die "user $username does not exist; stopping"
unless defined(getpwnam($username));
print "searching for at jobs owned by user $username ..." if $opt_v;
chdir "/var/spool/atjobs" ||
die "can't chdir to /var/spool/atjobs: $!\nstopping";
opendir(DIR,".") || die "can't opendir(/var/spool/atjobs): $!\nstopping";
@files = grep(!/^\./,grep(-f,readdir(DIR)));
closedir DIR;
foreach $x (@files)
{
$owner = (getpwuid((stat($x))[4]))[0];
push(@nuke_bait,$x) if $owner eq $username;
}
if (@nuke_bait)
{
print "removed jobIDs: @{nuke_bait}.\n" if $opt_v;
unlink @nuke_bait;
}
elsif ($opt_v)
{
print "\n";
}
exit 0;

308
contrib/pwdauth.c Normal file
View File

@@ -0,0 +1,308 @@
/*
* pwdauth.c - program to verify a given username/password pair.
*
* Run it with username in argv[1] (may be omitted - default is the
* current user), and send it the password over a pipe on stdin.
* Exit status: 0 - correct password, 1 - wrong password, >1 - other
* errors. For use with shadow passwords, this program should be
* installed setuid root.
*
* This can be used, for example, by xlock - you don't have to install
* this large and complex (== possibly insecure) program setuid root,
* just modify it to run this simple program to do the authentication.
*
* Recent versions (xlockmore-3.9) are cleaner, and drop privileges as
* soon as possible after getting the user's encrypted password.
* Using this program probably doesn't make it more secure, and has one
* disadvantage: since we don't get the encrypted user's password at
* startup (but at the time the user is authenticated), it is not clear
* how we should handle errors (like getpwnam() returning NULL).
* - fail the authentication? Problem: no way to unlock (other than kill
* the process from somewhere else) if the NIS server stops responding.
* - succeed and unlock? Problem: it's too easy to unlock by unplugging
* the box from the network and waiting until NIS times out...
*
* This program is Copyright (C) 1996 Marek Michalkiewicz
* <marekm@i17linuxb.ists.pwr.wroc.pl>.
*
* It may be used and distributed freely for any purposes. There is no
* warranty - use at your own risk. I am not liable for any damages etc.
* If you improve it, please send me your changes.
*/
static char rcsid[] = "$Id: pwdauth.c,v 1.2 1997/12/07 23:26:45 marekm Exp $";
/*
* Define USE_SYSLOG to use syslog() to log successful and failed
* authentication. This should be safe even if your system has
* the infamous syslog buffer overrun security problem...
*/
#define USE_SYSLOG
/*
* Define HAVE_GETSPNAM to get shadow passwords using getspnam().
* Some systems don't have getspnam(), but getpwnam() returns
* encrypted passwords only if running as root.
*
* According to the xlock source (not tested, except Linux) -
* define: Linux, Solaris 2.x, SVR4, ...
* undef: HP-UX with Secured Passwords, FreeBSD, NetBSD, QNX.
* Known not supported (yet): Ultrix, OSF/1, SCO.
*/
#define HAVE_GETSPNAM
/*
* Define HAVE_PW_ENCRYPT to use pw_encrypt() instead of crypt().
* pw_encrypt() is like the standard crypt(), except that it may
* support better password hashing algorithms.
*
* Define if linking with libshadow.a from the shadow password
* suite (Linux, SunOS 4.x?).
*/
#undef HAVE_PW_ENCRYPT
/*
* Define HAVE_AUTH_METHODS to support the shadow suite specific
* extension: the encrypted password field contains a list of
* administrator defined authentication methods, separated by
* semicolons. This program only supports the standard password
* authentication method (a string that doesn't start with '@').
*/
#undef HAVE_AUTH_METHODS
/*
* FAIL_DELAY - number of seconds to sleep before exiting if the
* password was wrong, to slow down password guessing attempts.
*/
#define FAIL_DELAY 2
/* No user-serviceable parts below :-). */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#ifdef USE_SYSLOG
#include <syslog.h>
#ifndef LOG_AUTHPRIV
#define LOG_AUTHPRIV LOG_AUTH
#endif
#endif
#ifdef HAVE_GETSPNAM
#include <shadow.h>
#endif
#ifdef HAVE_PW_ENCRYPT
extern char *pw_encrypt();
#define crypt pw_encrypt
#endif
/*
* Read the password (one line) from fp. We don't turn off echo
* because we expect input from a pipe.
*/
static char *
get_line(fp)
FILE *fp;
{
static char buf[128];
char *cp;
int ch;
cp = buf;
while ((ch = getc(fp)) != EOF && ch != '\0' && ch != '\n') {
if (cp >= buf + sizeof buf - 1)
break;
*cp++ = ch;
}
*cp = '\0';
return buf;
}
/*
* Get the password file entry for the current user. If the name
* returned by getlogin() is correct (matches the current real uid),
* return the entry for that user. Otherwise, return the entry (if
* any) matching the current real uid. Return NULL on failure.
*/
static struct passwd *
get_my_pwent()
{
uid_t uid = getuid();
char *name = getlogin();
if (name && *name) {
struct passwd *pw = getpwnam(name);
if (pw && pw->pw_uid == uid)
return pw;
}
return getpwuid(uid);
}
/*
* Verify the password. The system-dependent shadow support is here.
*/
static int
password_auth_ok(pw, pass)
const struct passwd *pw;
const char *pass;
{
int result;
char *cp;
#ifdef HAVE_AUTH_METHODS
char *buf;
#endif
#ifdef HAVE_GETSPNAM
struct spwd *sp;
#endif
if (pw) {
#ifdef HAVE_GETSPNAM
sp = getspnam(pw->pw_name);
if (sp)
cp = sp->sp_pwdp;
else
#endif
cp = pw->pw_passwd;
} else
cp = "xx";
#ifdef HAVE_AUTH_METHODS
buf = strdup(cp); /* will be modified by strtok() */
if (!buf) {
fprintf(stderr, "Out of memory.\n");
exit(13);
}
cp = strtok(buf, ";");
while (cp && *cp == '@')
cp = strtok(NULL, ";");
/* fail if no password authentication for this user */
if (!cp)
cp = "xx";
#endif
if (*pass || *cp)
result = (strcmp(crypt(pass, cp), cp) == 0);
else
result = 1; /* user with no password */
#ifdef HAVE_AUTH_METHODS
free(buf);
#endif
return result;
}
/*
* Main program.
*/
int
main(argc, argv)
int argc;
char **argv;
{
struct passwd *pw;
char *pass, *name;
char myname[32];
#ifdef USE_SYSLOG
openlog("pwdauth", LOG_PID | LOG_CONS, LOG_AUTHPRIV);
#endif
pw = get_my_pwent();
if (!pw) {
#ifdef USE_SYSLOG
syslog(LOG_ERR, "can't get login name for uid %d.\n",
(int) getuid());
#endif
fprintf(stderr, "Who are you?\n");
exit(2);
}
strncpy(myname, pw->pw_name, sizeof myname - 1);
myname[sizeof myname - 1] = '\0';
name = myname;
if (argc > 1) {
name = argv[1];
pw = getpwnam(name);
}
pass = get_line(stdin);
if (password_auth_ok(pw, pass)) {
#ifdef USE_SYSLOG
syslog(pw->pw_uid ? LOG_INFO : LOG_NOTICE,
"user `%s' entered correct password for `%.32s'.\n",
myname, name);
#endif
exit(0);
}
#ifdef USE_SYSLOG
/* be careful not to overrun the syslog buffer */
syslog((!pw || pw->pw_uid) ? LOG_NOTICE : LOG_WARNING,
"user `%s' entered incorrect password for `%.32s'.\n",
myname, name);
#endif
#ifdef FAIL_DELAY
sleep(FAIL_DELAY);
#endif
fprintf(stderr, "Wrong password.\n");
exit(1);
}
#if 0
/*
* You can use code similar to the following to run this program.
* Return values: >=0 - program exit status (use the <sys/wait.h>
* macros to get the exit code, it is shifted left by 8 bits),
* -1 - check errno.
*/
int
verify_password(const char *username, const char *password)
{
int pipe_fd[2];
int pid, wpid, status;
if (pipe(pipe_fd))
return -1;
if ((pid = fork()) == 0) {
char *arg[3];
char *env[1];
/* child */
close(pipe_fd[1]);
if (pipe_fd[0] != 0) {
if (dup2(pipe_fd[0], 0) != 0)
_exit(127);
close(pipe_fd[0]);
}
arg[0] = "/usr/bin/pwdauth";
arg[1] = username;
arg[2] = NULL;
env[0] = NULL;
execve(arg[0], arg, env);
_exit(127);
} else if (pid == -1) {
/* error */
close(pipe_fd[0]);
close(pipe_fd[1]);
return -1;
}
/* parent */
close(pipe_fd[0]);
write(pipe_fd[1], password, strlen(password));
write(pipe_fd[1], "\n", 1);
close(pipe_fd[1]);
while ((wpid = wait(&status)) != pid) {
if (wpid == -1)
return -1;
}
return status;
}
#endif

591
contrib/rpasswd.c Normal file
View File

@@ -0,0 +1,591 @@
/* rpasswd.c -- restricted `passwd' wrapper.
Copyright (C) 1996 Adam Solesby, Joshua Cowan
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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This program is meant to be a wrapper for use with `sudo' and your
system's `passwd' program. It is *probably* secure, but there is no
warranty (see above). If you find errors or security holes, please
email me; please include a complete description of the problem in
your message in addition to any patches. */
/* This program currently assumes that the arguments given on the
command line are user names to pass to the `passwd' program; it loops
through the arguments calling `passwd' on each one. It might be
better to pass all remaining arguments after `--' to `passwd' (to
e.g., change the user's shell instead of the password by giving it
the `-s' option). */
/* Written by Adam Solesby <adam@shack.com>. */
/* Rewritten by Joshua Cowan <jcowan@hermit.reslife.okstate.edu>. */
/* Usage: rpasswd USERNAME...
Enforce password-changing guidelines.
--check[=file] check configuration information; if FILE is given,
use that instead of the standard configuration
file `./rpasswd.conf'
--help display this help and exit
--version output version information and exit
You may never change a superuser's password with this command.
Changing certain other users' passwords may also be forbidden; for
details of who's passwords may not be changed, try `rpasswd --check'. */
/* TODO:
- Make this more portable. It currently depends on several
GNU/Linux-specific features. */
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <ctype.h>
#include <pwd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
/* This is the absolute path to the `passwd' program on your system. */
#define _PATH_PASSWD "/usr/bin/passwd"
/* This is the absolute path to the configuration file. */
#define _PATH_RPASSWD_CONF "/etc/rpasswd.conf"
/* Don't change the password of any user with a uid equal to or below
this number--no matter what the configuration file says. */
#define UID_PWD_CHANGE_FLOOR 100
/* Everything past this point should probably be left alone. */
/* These are the facility and priority (respectively) used by the syslog
functions. */
#define LOG_FACILITY LOG_AUTH
#define LOG_PRIORITY LOG_WARNING
/* The name this program was run with. */
char *program_name;
/* The version information for this program. */
char *version_string = "1.2";
/* If nonzero, display usage information and exit. */
static int show_help;
/* If nonzero, print the version on standard output then exit. */
static int show_version;
/* If nonzero, check the configuration file for errors and print the
list of restrictions on the standard output, then exit. */
static int check_only;
struct user_list
{
char *name;
struct user_list *next;
};
struct config_info
{
/* Don't change the password for any user with a uid less than or
equal to this number. */
uid_t minimum_uid;
/* Don't change the password for any user matching this list of user
names. */
struct user_list *inviolate_user_names;
};
static const struct option long_options[] =
{
{"check", optional_argument, 0, 10},
{"version", no_argument, &show_version, 1},
{"help", no_argument, &show_help, 1},
{0, 0, 0, 0}
};
static struct config_info *get_config_info ();
static int dump_config_info ();
static void *xmalloc ();
static void *xrealloc ();
static void xsyslog (int, const char *, ...);
static void dal_error (int, int, const char *, ...);
static void
usage (status)
int status;
{
if (status != 0)
fprintf (stderr, "Try `%s --help' for more information.\n",
program_name);
else
{
printf ("Usage: %s USERNAME...\n", program_name);
fputs ("\
Enforce password-changing guidelines.\n\
\n\
--check[=file] check configuration information; if FILE is given,\n\
use that instead of the standard configuration file\n\
`"_PATH_RPASSWD_CONF"'\n\
--help display this help and exit\n\
--version output version information and exit\n",
stdout);
printf ("\n\
You may never change a superuser's password with this command. Changing\n\
certain other users' passwords may also be forbidden; for details of\n\
who's passwords may not be changed, try `%s --check'.\n",
program_name);
}
exit (status);
}
int
main (argc, argv)
int argc;
char **argv;
{
char *executing_user_name;
char *config_file_name = _PATH_RPASSWD_CONF;
int opt;
struct config_info *config;
/* Setting values of global variables. */
program_name = argv[0];
while ((opt = getopt_long (argc, argv, "", long_options, 0))
!= EOF)
switch (opt)
{
case 0:
break;
case 10:
check_only = 1;
if (optarg)
config_file_name = optarg;
break;
default:
usage (1);
}
if (show_version)
{
printf ("rpasswd %s\n", version_string);
return 0;
}
if (show_help)
{
usage (0);
}
if (check_only)
{
dump_config_info (config_file_name);
exit (0);
}
if (optind >= argc)
{
fprintf (stderr, "%s: missing argument\n", program_name);
usage (1);
}
/* FIXME: does `sudo' set the real user id to the effective user id?
If so, this won't work as intended: We want to get the name of the
user who ran `sudo'. I am reluctant to use `getlogin' for obvious
reasons, but it may be better than nothing. Maybe someone who
actually has `sudo' installed can tell me if this works, or how to
fix it if it doesn't. --JC */
do
{
struct passwd *pwd;
uid_t uid = getuid ();
pwd = getpwuid (uid);
if (!pwd || !pwd->pw_name)
{
xsyslog (LOG_PRIORITY,
"Unknown user (uid #%d) attempted to change password for `%s'.",
uid, argv[optind]);
fprintf (stderr, "%s: you do not exist, go away\n",
program_name);
exit (1);
}
else
executing_user_name = pwd->pw_name;
}
while (0);
config = get_config_info (config_file_name);
for (; optind < argc; optind++)
{
int immutable_p = 0;
struct user_list *user_names = config->inviolate_user_names;
/* Make sure we weren't given an illegal user name. */
for (; user_names; user_names = user_names->next)
{
if (strcmp (argv[optind], user_names->name)
== 0)
{
immutable_p = 1;
break;
}
}
if (!immutable_p)
{
struct passwd *pwd;
pwd = getpwnam (argv[optind]);
if (!pwd)
{
fprintf (stderr, "%s: invalid user `%s'\n",
program_name, argv[optind]);
continue;
}
else if (pwd->pw_uid <= config->minimum_uid)
immutable_p = 1;
}
if (immutable_p)
{
xsyslog (LOG_PRIORITY,
"`%s' attempted to change password for `%s'.",
executing_user_name, argv[optind]);
fprintf (stderr,
"You are not allowed to change the password for `%s'.\n",
argv[optind]);
}
else
{
int pid, status;
pid = fork ();
switch (pid)
{
case -1:
dal_error (1, errno, "cannot fork");
case 0:
execl (_PATH_PASSWD, _PATH_PASSWD, "--", argv[optind], 0);
_exit (1);
default:
while (wait (&status) != pid)
;
if (status & 0xFFFF)
dal_error (1, EIO, "%s", _PATH_PASSWD);
break;
}
}
}
exit (0);
}
/* Get configuration information from FILE and return a pointer to a
`config_info' structure containing that information. It currently
does minimal checking of the validity of the information.
This function never returns NULL, even when the configuration file is
empty. If the configuration file doesn't exist, it just exits with a
failed exit status. */
static struct config_info *
get_config_info (file)
const char *const file;
{
FILE *config_file;
struct config_info *config;
char linebuf[BUFSIZ];
unsigned int lineno = 0;
config = (struct config_info *) xmalloc (sizeof (struct config_info));
config->minimum_uid = (uid_t) 0;
config->inviolate_user_names = 0;
config_file = fopen (file, "r");
if (!config_file)
dal_error (1, errno, "%s", file);
if (fseek (config_file, 0L, SEEK_SET))
dal_error (1, errno, "%s", file);
while (fgets (linebuf, BUFSIZ, config_file))
{
int len, i, uid_found = 0;
lineno++;
len = strlen (linebuf);
/* Chomp any whitespace off the end of the line. */
while (isspace (linebuf[len - 1]))
linebuf[--len] = '\0';
/* If this line is empty or a comment, skip it and go to the next. */
if (len == 0 || *linebuf == '#')
continue;
for (i = 0; i < len; i++)
if (!isalnum (linebuf[i])
&& linebuf[i] != '.'
&& linebuf[i] != '-'
&& linebuf[i] != '_')
{
dal_error (1, 0, "%s:%u: invalid user name `%s'",
file, lineno, linebuf);
}
/* Only accept positive integers as candidates for `minimum_uid'. */
for (i = 0; i < len; i++)
if (!isdigit (linebuf[i]))
break;
if (!uid_found && i == len)
{
unsigned long num;
errno = 0;
num = strtoul (linebuf, 0, 10);
config->minimum_uid = (uid_t) num;
if (errno || config->minimum_uid != num)
dal_error (1, 0, "%s:%u: `%s' out of range",
file, lineno, linebuf);
uid_found = 1;
}
else
{
struct user_list *tail = config->inviolate_user_names;
struct user_list *user_names = 0;
/* This could be more efficient, but makes the list of users
printed out with the `--check' switch easier to read. */
for (; tail; tail = tail->next)
{
if (strcmp (linebuf, tail->name) == 0)
break;
user_names = tail;
}
if (!tail)
{
tail = user_names;
user_names = xmalloc (sizeof (struct user_list));
user_names->name = strcpy (xmalloc (len + 1), linebuf);
user_names->next = 0;
if (!config->inviolate_user_names)
config->inviolate_user_names = user_names;
else
tail->next = user_names;
}
}
}
fclose (config_file);
if (config->minimum_uid < UID_PWD_CHANGE_FLOOR)
config->minimum_uid = UID_PWD_CHANGE_FLOOR;
return config;
}
/* Dump the configuration info contained in FILE to the standard output. */
static int
dump_config_info (file)
char *file;
{
struct config_info *config;
config = get_config_info (file);
printf ("\
The lowest uid who's password may be changed is number %d. Changing
the following users' passwords is also forbidden:\n",
config->minimum_uid + 1);
if (!config->inviolate_user_names)
{
printf ("\n (no users listed in configuration file `%s')\n",
file);
}
else
{
int column;
struct user_list *user_names = config->inviolate_user_names;
for (column = 73; user_names; user_names = user_names->next)
{
int name_len = strlen (user_names->name);
if (user_names->next)
name_len++;
column += name_len;
if (column > 72)
{
fputs ("\n ", stdout);
column = name_len + 2;
}
else if (column - name_len > 0)
{
fputc (' ', stdout);
column++;
}
fputs (user_names->name, stdout);
if (user_names->next)
fputc (',', stdout);
}
fputc ('\n', stdout);
}
return 0;
}
static void *
xmalloc (n)
size_t n;
{
void *ptr;
ptr = malloc (n);
if (!ptr)
{
fprintf (stderr, "%s: Memory exhausted\n", program_name);
exit (1);
}
return ptr;
}
static void *
xrealloc (ptr, n)
void *ptr;
size_t n;
{
ptr = realloc (ptr, n);
if (!ptr)
{
fprintf (stderr, "%s: Memory exhausted\n", program_name);
exit (1);
}
return ptr;
}
static void
xsyslog (int priority, const char *format, ...)
{
va_list args;
static int logfd_opened = 0;
if (!logfd_opened)
{
openlog (program_name, LOG_PID, LOG_FACILITY);
logfd_opened = 1;
}
va_start (args, format);
vsyslog (priority, format, args);
va_end (args);
}
/* Format and display MESSAGE on the standard error and send it to the
system logger. If ERRNUM is not 0, append the system error message
corresponding to ERRNUM to the output. If STATUS is not 0, exit with
an exit status of STATUS. */
static void
dal_error (int status, int errnum, const char *message, ...)
{
va_list args;
size_t bufsize;
char *formatted_message;
fflush (stdout);
bufsize = strlen (message) * 2;
formatted_message = (char *) xmalloc (bufsize);
va_start (args, message);
while (1)
{
int printed;
printed = vsnprintf (formatted_message, bufsize, message, args);
if ((size_t) printed < bufsize)
break;
bufsize *= 2;
formatted_message = xrealloc (formatted_message, bufsize);
}
va_end (args);
if (errnum)
{
char *error_message = strerror (errnum);
formatted_message
= xrealloc (formatted_message,
(strlen (formatted_message)
+ strlen (error_message)
+ 3));
strcat (formatted_message, ": ");
strcat (formatted_message, error_message);
}
fprintf (stderr, "%s: %s\n", program_name, formatted_message);
xsyslog (LOG_PRIORITY, "%s", formatted_message);
free (formatted_message);
fflush (stderr);
if (status)
{
closelog ();
exit (status);
}
}

View File

@@ -0,0 +1,147 @@
Hello Marek,
I have created a diffile against the 980403 release that adds
functionality to newusers for automatic handling of users with only
anonomous ftp login (using the guestgroup feature in ftpaccess, which
means that the users home directory looks like '/home/user/./'). It also
adds a commandline argument to specify an initial directory structure
for such users, with a tarball normally containing the bin,lib,etc
directories used in the chrooted environment.
I am using it to automatically create chunks of users with only ftp
access for a webserver.
I have tried to follow your coding standards and I believe it is bug
free but.. well, who knows. :) It's not much code however.
I hope you find it useful. Do what you like with it, feel free to ask if
anything is unclear.
Best rgds,
Calle Karlsson
ckn@kash.se
diff -uNr shadow-980403.orig/src/newusers.c shadow-980403/src/newusers.c
--- shadow-980403.orig/src/newusers.c Fri Jan 30 00:22:43 1998
+++ shadow-980403/src/newusers.c Fri Apr 17 16:55:33 1998
@@ -76,11 +76,35 @@
static void
usage(void)
{
- fprintf(stderr, "Usage: %s [ input ]\n", Prog);
+ fprintf (stderr, "Usage: %s [-p prototype tarfile] [ input ]\n", Prog);
+ fprintf (stderr, "The prototype tarfile is only used for users\n");
+ fprintf (stderr, "marked as anonymous ftp users. It must be a full pathname.\n");
exit(1);
}
/*
+ * createuserdir - create a directory and chmod it
+ */
+
+static int
+createuserdir (char * dir, int uid, int gid, int line)
+{
+ if (mkdir (dir, 0777 & ~getdef_num("UMASK", 077))) {
+ fprintf (stderr, "%s: line %d: mkdir %s failed\n",
+ Prog, line, dir);
+ return -1;
+ }
+
+ if (chown (dir, uid, gid)) {
+ fprintf (stderr, "%s: line %d: chown %s failed\n",
+ Prog, line, dir);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
* add_group - create a new group or add a user to an existing group
*/
@@ -328,6 +352,8 @@
main(int argc, char **argv)
{
char buf[BUFSIZ];
+ char anonproto[BUFSIZ];
+ int flag;
char *fields[8];
int nfields;
char *cp;
@@ -340,12 +366,23 @@
Prog = Basename(argv[0]);
- if (argc > 1 && argv[1][0] == '-')
- usage ();
+ * anonproto = '\0';
+
+ while ((flag = getopt (argc, argv, "p:h")) != EOF) {
+ switch (flag) {
+ case 'p':
+ STRFCPY(anonproto, optarg);
+ break;
+ case 'h':
+ default:
+ usage ();
+ break;
+ }
+ }
- if (argc == 2) {
- if (! freopen (argv[1], "r", stdin)) {
- snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]);
+ if (optind < argc) {
+ if (! freopen (argv[optind], "r", stdin)) {
+ snprintf(buf, sizeof buf, "%s: %s", Prog, argv[optind]);
perror (buf);
exit (1);
}
@@ -499,15 +536,36 @@
if (fields[6][0])
newpw.pw_shell = fields[6];
- if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) {
- if (mkdir (newpw.pw_dir,
- 0777 & ~getdef_num("UMASK", 077)))
- fprintf (stderr, "%s: line %d: mkdir failed\n",
- Prog, line);
- else if (chown (newpw.pw_dir,
- newpw.pw_uid, newpw.pw_gid))
- fprintf (stderr, "%s: line %d: chown failed\n",
- Prog, line);
+ if (newpw.pw_dir[0]) {
+ char * userdir = strdup (newpw.pw_dir);
+ char * anonpart;
+ int rc;
+
+ if ((anonpart = strstr (userdir, "/./"))) {
+ * anonpart = '\0';
+ anonpart += 2;
+ }
+
+ if (access(userdir, F_OK))
+ rc = createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+ else
+ rc = 0;
+
+ if (rc == 0 && anonpart) {
+ if (* anonproto) {
+ char cmdbuf [BUFSIZ];
+ snprintf(cmdbuf, sizeof cmdbuf,
+ "cd %s; tar xf %s",
+ userdir, anonproto);
+ system (cmdbuf);
+ }
+ if (strlen (anonpart) > 1) {
+ strcat (userdir, anonpart);
+ if (access (userdir, F_OK))
+ createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line);
+ }
+ }
+ free (userdir);
}
/*

BIN
contrib/udbachk.v012.tgz Normal file

Binary file not shown.