v06i024: shadow password routines, part 3 of ???
Brandon S. Allbery - comp.sources.misc
allbery at uunet.UU.NET
Mon Jan 30 07:14:21 AEST 1989
Posting-number: Volume 6, Issue 24
Submitted-by: jfh at hal.CWRU.Edu@convex.UUCP (John F. Haugh II)
Archive-name: shadow-2.pt3
[See part 1 for information (part 2 for my lament). ++bsa]
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# lastlog.h
# login.c
# motd.c
# password.c
# shell.c
# utmp.c
# age.c
# env.c
# pwent.c
# shadow.c
# valid.c
# lmain.c
# smain.c
# pwconv.c
# dialup.c
# dialchk.c
# pwunconv.c
# This archive created: Sun Jan 22 22:24:55 1989
# By: John F. Haugh II (River Parishes Programming, Dallas TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'lastlog.h'
then
echo shar: "will not over-write existing file 'lastlog.h'"
else
cat << \SHAR_EOF > 'lastlog.h'
/*
* lastlog.h - structure of lastlog file
*
* This file defines a lastlog file structure which should be sufficient
* to hold the information required by login. It should only be used if
* there is no real lastlog.h file.
*/
struct lastlog {
time_t ll_time;
char ll_line[8];
};
SHAR_EOF
fi
if test -f 'login.c'
then
echo shar: "will not over-write existing file 'login.c'"
else
cat << \SHAR_EOF > 'login.c'
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void setenv ();
void login (name)
char *name;
{
char buf[BUFSIZ];
char *envp[32];
int envc;
char *cp;
int i;
memset (buf, 0, BUFSIZ);
fputs ("login: ", stdout);
if (fgets (buf, BUFSIZ, stdin) != buf)
exit (1);
buf[strlen (buf) - 1] = '\0'; /* remove \n [ must be there ] */
for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
;
for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++)
;
if (*cp)
cp++;
name[i] = '\0';
if (*cp != '\0') { /* process new variables */
for (envc = 0;envc < 32;envc++) {
envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,");
if (envp[envc] == (char *) 0)
break;
}
setenv (envc, envp);
}
}
SHAR_EOF
fi
if test -f 'motd.c'
then
echo shar: "will not over-write existing file 'motd.c'"
else
cat << \SHAR_EOF > 'motd.c'
#include <stdio.h>
#include <string.h>
#include "config.h"
extern char home[];
void motd ()
{
#ifdef MOTD
FILE *fp;
register int c;
#ifdef HUSHLOGIN
char hush[BUFSIZ];
(void) strcat (strcpy (hush, home + 5), "/.hushlogin");
if (access (hush, 0) == 0)
return;
#endif
if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0)
return;
while ((c = getc (fp)) != EOF)
putchar (c);
fclose (fp);
fflush (stdout);
#endif
}
SHAR_EOF
fi
if test -f 'password.c'
then
echo shar: "will not over-write existing file 'password.c'"
else
cat << \SHAR_EOF > 'password.c'
#include <stdio.h>
#include <string.h>
#include <termio.h>
#include <fcntl.h>
/*
* password - prompt for password and return entry
*
* Need to fake up getpass(). Returns TRUE if a password
* was successfully input, and FALSE otherwise, including
* EOF on input or ioctl() failure. pass is not modified
* on failure.
*/
int password (prompt, pass)
char *prompt;
char *pass;
{
char buf[BUFSIZ];
int eof;
int ttyopened = 0;
struct termio termio;
struct termio save;
FILE *fp;
if ((fp = fopen ("/dev/tty", "r")) == (FILE *) 0)
fp = stdin;
else
ttyopened = 1;
if (ioctl (fileno (fp), TCGETA, &termio))
return (0);
save = termio;
termio.c_lflag &= ~ECHO;
ioctl (fileno (fp), TCSETAF, &termio);
fputs (prompt, stdout);
eof = gets (buf) == (char *) 0 || feof (fp) || ferror (fp);
putchar ('\n');
ioctl (fileno (fp), TCSETAF, &save);
if (! eof) {
buf[8] = '\0';
(void) strcpy (pass, buf);
}
if (ttyopened)
fclose (fp);
return (! eof);
}
SHAR_EOF
fi
if test -f 'shell.c'
then
echo shar: "will not over-write existing file 'shell.c'"
else
cat << \SHAR_EOF > 'shell.c'
#include <stdio.h>
#include <string.h>
#include "config.h"
extern char *newenvp[];
void shell (file)
char *file;
{
char arg0[BUFSIZ];
#ifndef SU
char *path;
#endif
char *strrchr ();
extern int errno;
if (file == (char *) 0)
exit (1);
#ifndef SU
if (path = strrchr (file, '/'))
path++;
else
path = file;
(void) strcpy (arg0 + 1, path);
arg0[0] = '-';
#else
(void) strcpy (arg0, "-su");
#endif
#ifndef NDEBUG
printf ("Executing shell %s\n", file);
#endif
execle (file, arg0, (char *) 0, newenvp);
printf ("Can't execute %s\n", file);
exit (errno);
}
SHAR_EOF
fi
if test -f 'utmp.c'
then
echo shar: "will not over-write existing file 'utmp.c'"
else
cat << \SHAR_EOF > 'utmp.c'
#include <sys/types.h>
#include <utmp.h>
#include <string.h>
#include <stdio.h>
#include "config.h"
extern struct utmp utent;
extern char name[];
struct utmp *getutent ();
void setutent ();
void endutent ();
void pututline ();
char *memset ();
time_t time ();
void checkutmp ()
{
struct utmp *ut;
#ifndef NDEBUG
int pid = getppid ();
#else
int pid = getpid ();
#endif
setutent ();
while (ut = getutent ())
if (ut->ut_pid == pid)
break;
if (ut)
utent = *ut;
endutent ();
if (ut && utent.ut_pid == pid)
return;
puts ("No utmp entry. You must exec \"login\" from the lowest level \"sh\"");
exit (1);
}
void setutmp ()
{
FILE *wtmp;
char tty[sizeof utent.ut_line + 1];
char *line;
setutent ();
(void) strncpy (utent.ut_user, name, sizeof utent.ut_user);
utent.ut_type = USER_PROCESS;
if (line = strrchr (utent.ut_line, '/')) {
(void) strcpy (tty, line + 1);
(void) memset (utent.ut_line, '\0', sizeof utent.ut_line);
(void) strcpy (utent.ut_line, tty);
}
(void) time (&utent.ut_time);
pututline (&utent);
endutent ();
if ((wtmp = fopen (WTMP_FILE, "a+"))) {
fwrite (&utent, sizeof utent, 1, wtmp);
fclose (wtmp);
}
}
SHAR_EOF
fi
if test -f 'age.c'
then
echo shar: "will not over-write existing file 'age.c'"
else
cat << \SHAR_EOF > 'age.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include "config.h"
#ifndef PASSWD
extern char *newenvp[];
#endif
time_t time ();
#ifdef AGING
#ifdef PASSWD
char *l64a (l)
long l;
{
static char buf[8];
int i = 0;
if (i < 0L)
return ((char *) 0);
do {
buf[i++] = i64c ((int) (l % 64));
buf[i] = '\0';
} while (l /= 64L, l > 0 && i < 6);
return (buf);
}
#endif
int i64c (i)
int i;
{
if (i < 0)
return ('.');
else if (i > 63)
return ('z');
if (i == 0)
return ('.');
if (i == 1)
return ('/');
if (i >= 2 && i <= 11)
return ('0' - 2 + i);
if (i >= 12 && i <= 37)
return ('A' - 12 + i);
if (i >= 38 && i <= 63)
return ('a' - 38 + i);
return ('\0');
}
int c64i (c)
char c;
{
if (c == '.')
return (0);
if (c == '/')
return (1);
if (c >= '0' && c <= '9')
return (c - '0' + 2);
if (c >= 'A' && c <= 'Z')
return (c - 'A' + 12);
if (c >= 'a' && c <= 'z')
return (c - 'a' + 38);
else
return (-1);
}
long a64l (s)
char *s;
{
int i;
long value;
long shift = 0;
for (i = 0, value = 0L;i < 6 && *s;s++) {
value += (c64i (*s) << shift);
shift += 6;
}
return (value);
}
#ifndef PASSWD
void expire (age)
char *age;
{
long clock;
long week;
extern char name[];
extern int errno;
(void) time (&clock);
clock /= (7L * 24L * 60L * 60L);
if (strlen (age) < 4)
week = 0L;
else
week = a64l (age + 2);
if (clock >= week + c64i (age[0])) {
printf ("Your password has expired.");
if (c64i (age[0]) < c64i (age[1])) {
puts (" Contact the system administrator.\n");
exit (1);
}
puts (" Choose a new one.\n");
execl ("/bin/passwd", "-passwd", name, (char *) 0);
puts ("Can't execute /bin/passwd");
exit (errno);
}
}
#endif
#endif
SHAR_EOF
fi
if test -f 'env.c'
then
echo shar: "will not over-write existing file 'env.c'"
else
cat << \SHAR_EOF > 'env.c'
#include <stdio.h>
#include <string.h>
extern char **environ;
extern char *newenvp[];
extern int newenvc;
extern int maxenv;
char *strdup ();
void free ();
static char *forbid[] = {
"HOME",
"IFS",
"PATH",
"SHELL",
(char *) 0
};
void addenv (entry)
char *entry;
{
char *cp;
int i;
int len;
if (cp = strchr (entry, '='))
len = cp - entry;
else
len = strlen (entry);
for (i = 0;i < newenvc;i++)
if (strncmp (entry, newenvp[i], len) == 0 &&
(newenvp[i][len] == '=' || newenvp[i][len] == '\0'))
break;
if (i == maxenv) {
puts ("Environment overflow");
return;
}
if (i == newenvc) {
newenvp[newenvc++] = strdup (entry);
} else {
free (newenvp[i]);
newenvp[i] = strdup (entry);
}
}
void setenv (argc, argv)
int argc;
char **argv;
{
int i;
int n;
char variable[BUFSIZ];
char *cp;
for (i = 0;i < argc;i++) {
if ((n = strlen (argv[i])) >= BUFSIZ)
continue; /* ignore long entries */
if (! (cp = strchr (argv[i], '='))) {
(void) strcpy (variable, argv[i]);
} else {
(void) strncpy (variable, argv[i], cp - argv[i]);
variable[cp - argv[i]] = '\0';
}
for (n = 0;forbid[n] != (char *) 0;n++)
if (strcmp (variable, forbid[n]) == 0)
break;
if (forbid[n] != (char *) 0) {
printf ("You may not change $%s\n", forbid[n]);
continue;
}
addenv (argv[i]);
}
}
SHAR_EOF
fi
if test -f 'pwent.c'
then
echo shar: "will not over-write existing file 'pwent.c'"
else
cat << \SHAR_EOF > 'pwent.c'
#include <stdio.h>
#include <pwd.h>
#include <string.h>
#define SBUFSIZ 64
static char *tokcpy (buf, token)
char *buf;
char *token;
{
static char *cp;
char *start;
if (buf == (char *) 0)
buf = cp;
else
cp = buf;
start = cp;
if (*buf == '\0')
return ((char *) 0);
while (*buf && *buf != ':')
*token++ = *buf++;
*token = '\0';
if (*buf)
cp = buf + 1;
return (start);
}
struct passwd *sgetpwent (buf)
char *buf;
{
static struct passwd pwent;
static char name[SBUFSIZ];
static char password[SBUFSIZ];
static char gecos[SBUFSIZ];
static char home[SBUFSIZ];
static char shell[SBUFSIZ];
static char age[SBUFSIZ];
char tmp[BUFSIZ];
char *cp;
pwent.pw_name = name;
pwent.pw_passwd = password;
pwent.pw_uid = -1;
pwent.pw_gid = -1;
pwent.pw_age = age;
pwent.pw_comment = (char *) 0;
pwent.pw_gecos = gecos;
pwent.pw_dir = home;
pwent.pw_shell = shell;
(void) strcpy (tmp, buf);
if (! tokcpy (tmp, name) || ! name[0])
return ((struct passwd *) 0);
if (! tokcpy ((char *) 0, password))
return ((struct passwd *) 0);
if (tokcpy ((char *) 0, tmp) && *tmp)
pwent.pw_uid = atoi (tmp);
else
return ((struct passwd *) 0);
if (tokcpy ((char *) 0, tmp) && *tmp)
pwent.pw_gid = atoi (tmp);
else
return ((struct passwd *) 0);
if (cp = strchr (password, ',')) {
(void) strcpy (age, cp + 1);
*cp = '\0';
} else
pwent.pw_age = (char *) 0;
if (! tokcpy ((char *) 0, gecos))
return ((struct passwd *) 0);
if (! tokcpy ((char *) 0, home))
return ((struct passwd *) 0);
if (! tokcpy ((char *) 0, shell) && *shell)
pwent.pw_shell = (char *) 0;
if (pwent.pw_passwd && pwent.pw_passwd[0] == '\0')
pwent.pw_passwd = (char *) 0;
return (&pwent);
}
#ifdef FGETPWENT
struct passwd *fgetpwent (fp)
FILE *fp;
{
char buf[BUFSIZ];
while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
if (buf[0] == '#')
continue;
buf[strlen (buf) - 1] = '\0';
return (sgetpwent (buf));
}
return ((struct passwd *) 0);
}
#endif
SHAR_EOF
fi
if test -f 'shadow.c'
then
echo shar: "will not over-write existing file 'shadow.c'"
else
cat << \SHAR_EOF > 'shadow.c'
#include "shadow.h"
#include <stdio.h>
#include <string.h>
static FILE *shadow;
void setspent ()
{
if (shadow)
rewind (shadow);
else
shadow = fopen (SHADOW, "r");
}
void endspent ()
{
if (shadow)
(void) fclose (shadow);
shadow = (FILE *) 0;
}
struct spwd *fgetspent (fp)
FILE *fp;
{
static struct spwd spwd;
static char name[32];
static char pass[32];
char buf[BUFSIZ];
char *cp;
int atoi ();
long atol ();
if (! fp)
return (0);
if (fgets (buf, BUFSIZ, fp) == (char *) 0)
return (0);
buf[strlen (buf) - 1] = '\0';
if ((cp = strtok (buf, ":")) && *cp)
(void) strcpy (name, cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
(void) strcpy (pass, cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_lstchg = atol (cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_min = atoi (cp);
else
return (0);
if ((cp = strtok ((char *) 0, ":")) && *cp)
spwd.sp_max = atoi (cp);
else
return (0);
spwd.sp_namp = name;
spwd.sp_pwdp = pass;
return (&spwd);
}
struct spwd *getspent ()
{
if (! shadow)
setspent ();
return (fgetspent (shadow));
}
struct spwd *getspnam (name)
char *name;
{
struct spwd *spwd;
setspent ();
while ((spwd = getspent ()) != (struct spwd *) 0) {
if (strcmp (name, spwd->sp_namp) == 0)
return (spwd);
}
return (0);
}
int putspent (spwd, fp)
struct spwd *spwd;
FILE *fp;
{
if (! fp)
return (0);
return (fprintf (fp, "%s:%s:%ld:%d:%d\n",
spwd->sp_namp, spwd->sp_pwdp,
spwd->sp_lstchg, spwd->sp_min, spwd->sp_max) != EOF);
}
SHAR_EOF
fi
if test -f 'valid.c'
then
echo shar: "will not over-write existing file 'valid.c'"
else
cat << \SHAR_EOF > 'valid.c'
#include <pwd.h>
/*
* valid - compare encrypted passwords
*
* Valid() compares the DES encrypted password from the password file
* against the password which the user has entered after it has been
* encrypted using the same salt as the original.
*/
int valid (password, entry)
char *password;
struct passwd *entry;
{
char *encrypt;
char *salt;
char *crypt ();
/*
* Start with blank or empty password entries. Always encrypt
* a password if no such user exists. Only if the ID exists and
* the password is really empty do you return quickly. This
* routine is meant to waste CPU time.
*/
if (entry->pw_name &&
(entry->pw_passwd == (char *) 0 ||
strlen (entry->pw_passwd) == 0)) {
if (strlen (password) == 0)
return (1); /* user entered nothing */
else
return (0); /* user entered something! */
}
/*
* If there is no entry then we need a salt to use.
*/
if (entry->pw_passwd == (char *) 0 || entry->pw_passwd[0] == '\0')
salt = "xx";
else
salt = entry->pw_passwd;
/*
* Now, perform the encryption using the salt from before on
* the users input. Since we always encrypt the string, it
* should be very difficult to determine if the user exists by
* looking at execution time.
*/
encrypt = crypt (password, salt);
/*
* One last time we must deal with there being no password file
* entry for the user. We use the pw_passwd == NULL idiom to
* cause non-existent users to not be validated. Even still,
* we are safe because if the string were == "", any encrypted
* string is not going to match - the output of crypt() begins
* with the salt, which is "xx", not "".
*/
if (entry->pw_passwd && strcmp (encrypt, entry->pw_passwd) == 0)
return (1);
else
return (0);
}
SHAR_EOF
fi
if test -f 'lmain.c'
then
echo shar: "will not over-write existing file 'lmain.c'"
else
cat << \SHAR_EOF > 'lmain.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <utmp.h>
#include <time.h>
#include <string.h>
#include <signal.h>
#include "config.h"
#include "lastlog.h"
char name[BUFSIZ];
char pass[BUFSIZ];
char home[BUFSIZ];
char prog[BUFSIZ];
char mail[BUFSIZ];
struct passwd pwent;
struct utmp utent;
struct lastlog lastlog;
#ifndef MAXENV
#define MAXENV 64
#endif
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
extern char **environ;
char *getenv ();
char *memset ();
void checkutmp ();
void addenv ();
void setenv ();
unsigned alarm ();
void login ();
void entry ();
void setutmp ();
void subsystem ();
void log ();
void setup ();
void expire ();
void motd ();
void mailcheck ();
void shell ();
#ifndef ALARM
#define ALARM 60
#endif
#ifndef RETRIES
#define RETRIES 3
#endif
int main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
int retries = RETRIES;
checkutmp (); /* must be lowest level shell */
if (! isatty (0)) /* must be a terminal */
exit (1);
while (*envp) /* add inherited environment, */
addenv (*envp++); /* some variables change later */
#ifdef TZ
addenv (TZ); /* set the default $TZ, if one */
#endif
#ifdef HZ
addenv (HZ); /* set the default $HZ, if one */
#endif
if (argc >= 2) { /* now set command line variables */
setenv (argc - 2, &argv[2]);
(void) strncpy (name, argv[1], sizeof name);
}
(void) alarm (ALARM); /* only allow ALARM sec. for login */
while (1) { /* repeatedly get login/password pairs */
if (! name[0]) { /* need to get a login id */
login (name);
continue;
}
entry (name, &pwent); /* get entry from password file */
/*
* Here we have a sticky situation. Some accounts may have no
* password entry in the password file. So, we don't ask for a
* password. Others, have a blank password entered - you be the
* judge. The conditional compilation NOBLANK requires even
* blank passwords to be prompted for. This may well break
* quite a few systems. Use with discretion.
*/
#ifdef NOBLANK
/* get a password from user */
if (! password ("Password:", pass))
continue;
#else
if ((! pwent.pw_name || pwent.pw_passwd)
&& ! password ("Password:", pass))
continue;
#endif
if (valid (pass, &pwent)) /* check encrypted passwords ... */
break; /* ... encrypted passwords matched */
if (--retries <= 0) /* only allow so many failures */
exit (1);
puts ("Login incorrect");
(void) memset (name, '\0', sizeof name);
}
#ifdef DIALUP
if (! dialcheck (utent.ut_line,
pwent.pw_shell ? pwent.pw_shell:"/bin/sh")) {
puts ("Dialup password incorrect");
exit (1);
}
#endif
(void) alarm (0); /* turn off alarm clock */
environ = newenvp; /* make new environment active */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
setutmp (); /* make entry in utmp & wtmp files */
#ifdef CONSOLE
if (pwent.pw_uid == 0 && /* root no logging in on console ? */
strncmp (CONSOLE, utent.ut_line, sizeof utent.ut_line))
exit (1); /* then exit! */
#endif
if (pwent.pw_shell[0] == '*') /* subsystem root required */
subsystem (); /* figure out what to execute */
#ifdef LASTLOG
log (); /* give last login and log this one */
#endif
setup (&pwent); /* set UID, GID, HOME, etc ... */
#ifdef AGING
if (pwent.pw_age) /* check for age of password ... */
expire (pwent.pw_age); /* ... ask for new one if expired */
#endif
#ifdef MOTD
motd (); /* print the message of the day */
#endif
#ifdef LASTLOG
if (lastlog.ll_time != 0)
printf ("Last login: %.19s on %s\n",
ctime (&lastlog.ll_time), lastlog.ll_line);
#endif
#ifdef MAILCHECK
mailcheck (); /* report on the status of mail */
#endif
signal (SIGINT, SIG_DFL); /* default interrupt signal */
signal (SIGQUIT, SIG_DFL); /* default quit signal */
signal (SIGTERM, SIG_DFL); /* default terminate signal */
signal (SIGALRM, SIG_DFL); /* default alarm signal */
shell (pwent.pw_shell); /* exec the shell finally. */
/*NOTREACHED*/
}
SHAR_EOF
fi
if test -f 'smain.c'
then
echo shar: "will not over-write existing file 'smain.c'"
else
cat << \SHAR_EOF > 'smain.c'
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include <signal.h>
#include "config.h"
#include "lastlog.h"
#ifndef MAXENV
#define MAXENV 64
#endif
char name[BUFSIZ];
char pass[BUFSIZ];
char home[BUFSIZ];
char prog[BUFSIZ];
char mail[BUFSIZ];
char oldname[BUFSIZ];
char *newenvp[MAXENV];
int newenvc = 0;
int maxenv = MAXENV;
struct passwd pwent;
void addenv ();
void entry ();
void sulog ();
void subsystem ();
void setup ();
void motd ();
void mailcheck ();
void shell ();
extern char **environ;
int main (argc, argv, envp)
int argc;
char **argv;
char **envp;
{
char *getenv ();
int doshell;
int fakelogin = 0;
int amroot;
struct passwd *pw;
struct passwd *getpwuid ();
while (*envp) /* add inherited environment, */
addenv (*envp++); /* some variables change later */
#ifdef TZ
addenv (TZ); /* set the default $TZ, if one */
#endif
#ifdef HZ
addenv (HZ); /* set the default $HZ, if one */
#endif
argc--; argv++; /* shift out command name */
if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') {
fakelogin = 1;
argc--; argv++; /* shift ... */
}
if (argc > 0 && argv[0][0] != '-') {
(void) strcpy (name, argv[0]); /* use this login id */
argc--; argv++; /* shift ... */
}
doshell = argc == 0; /* any arguments remaining? */
if (pw = getpwuid (getuid ())) /* need old user name */
(void) strcpy (oldname, pw->pw_name);
else /* user ID MUST exist */
goto failure;
amroot = getuid () == 0; /* currently am super user */
if (! name[0]) /* use default user ID */
(void) strcpy (name, "root");
entry (name, &pwent); /* get password file entry */
if (pwent.pw_name == (char *) 0) { /* unknown user */
(void) fprintf (stderr, "Unknown id: %s\n", pwent.pw_name);
exit (1);
}
/*
* Here we have a sticky situation. Some accounts may have no
* password entry in the password file. So, we don't ask for a
* password. Others, have a blank password entered - you be the
* judge. The conditional compilation NOBLANK requires even
* blank passwords to be prompted for. This may well break
* quite a few systems. Use with discretion.
*/
#ifdef NOBLANK
if (! amroot && ! password ("Password:", pass))
goto failure;
#else
if (! amroot && (pwent.pw_name == (char *) 0 || pwent.pw_passwd)
&& ! password ("Password:", pass))
goto failure;
#endif
/* check encrypted passwords ... */
if (! amroot && ! valid (pass, &pwent)) {
failure: sulog (0); /* log failed attempt */
puts ("Sorry.");
exit (1);
}
#ifdef SULOG
sulog (1); /* save SU information */
#endif
if (pwent.pw_uid == 0)
addenv (SUPATH);
else
addenv (PATH);
environ = newenvp; /* make new environment active */
if (getenv ("IFS")) /* don't export user IFS ... */
addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */
subsystem (); /* figure out what to execute */
if (fakelogin)
setup (&pwent); /* set UID, GID, HOME, etc ... */
else {
if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid)) {
perror ("Can't set ID");
exit (1);
}
}
if (! doshell) { /* execute arguments as command */
if (! pwent.pw_shell)
pwent.pw_shell = "/bin/sh";
argv[-1] = pwent.pw_shell;
(void) execv (pwent.pw_shell, &argv[-1]);
(void) fprintf (stderr, "No shell\n");
exit (1);
}
if (fakelogin) {
#ifdef MOTD
motd (); /* print the message of the day */
#endif
#ifdef MAILCHECK
mailcheck (); /* report on the status of mail */
#endif
shell (pwent.pw_shell); /* exec the shell finally. */
} else {
if (pwent.pw_shell == (char *) 0)
pwent.pw_shell = "/bin/sh";
execl (pwent.pw_shell, "su", (char *) 0);
perror (pwent.pw_shell);
exit (1);
}
/*NOTREACHED*/
}
SHAR_EOF
fi
if test -f 'pwconv.c'
then
echo shar: "will not over-write existing file 'pwconv.c'"
else
cat << \SHAR_EOF > 'pwconv.c'
/*
* pwconv - convert and update shadow password files
*
* Pwconv copies the old password file information to a new shadow
* password file, merging entries from an optional existing shadow
* file.
*
* The new password file is left in npasswd, the new shadow file is
* left in nshadow. Existing shadow entries are copied as is.
* New entries are created with passwords which expire in 10000 days,
* with a last changed date of today, unless password aging
* information was already present. Entries with blank passwords
* are not copied to the shadow file at all.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include "config.h"
#include "lastlog.h"
#include "shadow.h"
char buf[BUFSIZ];
long time ();
long a64l ();
int main ()
{
long today;
struct passwd *pw;
struct passwd *sgetpwent ();
FILE *pwd;
FILE *npwd;
FILE *shadow;
struct spwd *spwd;
struct spwd tspwd;
int fd;
if (! (pwd = fopen (PWDFILE, "r"))) {
perror (PWDFILE);
return (1);
}
unlink ("npasswd");
if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (npwd = fdopen (fd, "w"))) {
perror ("npasswd");
return (1);
}
unlink ("nshadow");
if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (shadow = fdopen (fd, "w"))) {
perror ("nshadow");
return (1);
}
(void) time (&today);
today /= (24L * 60L * 60L);
while (fgets (buf, BUFSIZ, pwd) == buf) {
buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
if (buf[0] == '#') { /* comment line */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (pw->pw_passwd == (char *) 0) { /* no password, skip */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
setspent (); /* rewind old shadow file */
if (spwd = getspnam (pw->pw_name)) {
if (! putspent (spwd, shadow)) { /* copy old entry */
perror ("nshadow");
return (1);
}
} else { /* need a new entry. */
tspwd.sp_namp = pw->pw_name;
tspwd.sp_pwdp = pw->pw_passwd;
pw->pw_passwd = "x";
if (pw->pw_age) { /* copy old password age stuff */
tspwd.sp_min = c64i (pw->pw_age[1]);
tspwd.sp_max = c64i (pw->pw_age[0]);
if (strlen (pw->pw_age) == 4)
tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
else
tspwd.sp_lstchg = 0L;
/*
* Convert weeks to days
*/
tspwd.sp_min *= 7;
tspwd.sp_max *= 7;
tspwd.sp_lstchg *= 7;
} else { /* fake up new password age stuff */
tspwd.sp_max = 10000;
tspwd.sp_min = 0;
tspwd.sp_lstchg = today;
}
if (! putspent (&tspwd, shadow)) { /* output entry */
perror ("nshadow");
return (1);
}
}
(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir);
if (fprintf (npwd, "%s\n",
pw->pw_shell ? pw->pw_shell:"") == EOF) {
perror ("npasswd");
return (1);
}
}
endspent ();
if (ferror (npwd) || ferror (shadow)) {
perror ("pwconv");
(void) unlink ("npasswd");
(void) unlink ("nshadow");
}
(void) fclose (pwd);
(void) fclose (npwd);
(void) fclose (shadow);
return (0);
}
SHAR_EOF
fi
if test -f 'dialup.c'
then
echo shar: "will not over-write existing file 'dialup.c'"
else
cat << \SHAR_EOF > 'dialup.c'
#include <stdio.h>
#include <string.h>
#include "dialup.h"
static FILE *dialpwd;
void setduent ()
{
if (dialpwd)
rewind (dialpwd);
else
dialpwd = fopen (DIALPWD, "r");
}
void endduent ()
{
if (dialpwd)
fclose (dialpwd);
dialpwd = (FILE *) 0;
}
struct dialup *getduent ()
{
static struct dialup dialup; /* static structure to point to */
static char shell[64]; /* some space for a login shell */
static char passwd[16]; /* some space for dialup password */
char buf[BUFSIZ];
char *cp;
if (! dialpwd)
setduent ();
if (! dialpwd || feof (dialpwd))
return ((struct dialup *) 0);
while (fgets (buf, BUFSIZ, dialpwd) == buf)
if (buf[0] == '#')
continue;
if (feof (dialpwd))
return ((struct dialup *) 0);
cp = strchr (buf, ':');
if (cp - buf > sizeof shell) /* something is fishy ... */
return ((struct dialup *) 0);
(void) strncpy (shell, buf, cp - buf);
shell[cp - buf] = '\0';
if (strlen (cp + 1) > sizeof passwd) /* something is REALLY fishy */
return ((struct dialup *) 0);
(void) strcpy (passwd, cp + 1);
passwd[strlen (passwd) - 1] = '\0';
if (cp = strchr (passwd, ':'))
*cp = '\0';
dialup.du_shell = shell;
dialup.du_passwd = passwd;
return (&dialup);
}
struct dialup *getdushell (shell)
char *shell;
{
struct dialup *dialup;
while (dialup = getduent ())
if (strcmp (shell, dialup->du_shell) == 0)
return (dialup);
return ((struct dialup *) 0);
}
int isadialup (tty)
char *tty;
{
FILE *fp;
char buf[BUFSIZ];
int dialup = 0;
if (! (fp = fopen (DIALUPS, "r")))
return (0);
while (fgets (buf, BUFSIZ, fp) == buf) {
buf[strlen (buf) - 1] = '\0';
if (strcmp (buf, tty) == 0) {
dialup = 1;
break;
}
}
fclose (fp);
return (dialup);
}
SHAR_EOF
fi
if test -f 'dialchk.c'
then
echo shar: "will not over-write existing file 'dialchk.c'"
else
cat << \SHAR_EOF > 'dialchk.c'
#include <stdio.h>
#include "config.h"
#include "dialup.h"
/*
* Check for dialup password
*
* dialcheck tests to see if tty is listed as being a dialup
* line. If so, a dialup password may be required if the shell
* is listed as one which requires a second password.
*/
#ifdef DIALUP
int dialcheck (tty, shell)
char *tty;
char *shell;
{
char *crypt ();
char *getpass ();
struct dialup *dialup;
char *pass;
char *cp;
if (! isadialup (tty))
return (1);
if (! (dialup = getdushell (shell)))
return (1);
endduent ();
if (dialup->du_passwd[0] == '\0')
return (1);
if (! (pass = getpass ("Dialup Password:")))
return (0);
cp = crypt (pass, dialup->du_passwd);
return (strcmp (cp, dialup->du_passwd) == 0);
}
#endif
SHAR_EOF
fi
if test -f 'pwunconv.c'
then
echo shar: "will not over-write existing file 'pwunconv.c'"
else
cat << \SHAR_EOF > 'pwunconv.c'
/*
* pwunconv - restore old password file from shadow password file.
*
* Pwunconv copies the password file information from the shadow
* password file, merging entries from an optional existing shadow
* file.
*
* The new password file is left in npasswd. There is no new
* shadow file. Password aging information is translated where
* possible.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include "config.h"
#include "lastlog.h"
#include "shadow.h"
char buf[BUFSIZ];
char *l64a ();
int main ()
{
struct passwd *pw;
struct passwd *sgetpwent ();
FILE *pwd;
FILE *npwd;
struct spwd *spwd;
int fd;
if (! (pwd = fopen (PWDFILE, "r"))) {
perror (PWDFILE);
return (1);
}
unlink ("npasswd");
if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
! (npwd = fdopen (fd, "w"))) {
perror ("npasswd");
return (1);
}
while (fgets (buf, BUFSIZ, pwd) == buf) {
buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */
if (buf[0] == '#') { /* comment line */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
(void) fprintf (npwd, "%s\n", buf);
continue;
}
setspent (); /* rewind shadow file */
if (! (spwd = getspnam (pw->pw_name))) {
(void) fprintf (npwd, "%s\n", buf);
continue;
}
pw->pw_passwd = spwd->sp_pwdp;
/*
* Password aging works differently in the two different systems.
* With shadow password files you apparently must have some aging
* information. The maxweeks or minweeks may not map exactly.
* In pwconv we set max == 10000, which is about 30 years. Here
* we have to undo that kludge. So, if maxdays == 10000, no aging
* information is put into the new file. Otherwise, the days are
* converted to weeks and so on.
*/
if (spwd->sp_max > (63*7) && spwd->sp_max < 10000)
spwd->sp_max = (63*7); /* 10000 is infinity this week */
if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
spwd->sp_max /= 7; /* turn it into weeks */
spwd->sp_min /= 7;
spwd->sp_lstchg /= 7;
pw->pw_age = l64a ((long) spwd->sp_lstchg * (64L*64L) +
spwd->sp_min * (64L) +
spwd->sp_max);
} else
pw->pw_age = (char *) 0;
if (pw->pw_age)
(void) fprintf (npwd, "%s:%s,%s:%d:%d:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_age, pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir,
pw->pw_shell ? pw->pw_shell:"");
else
(void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd ? pw->pw_passwd:"",
pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir,
pw->pw_shell ? pw->pw_shell:"");
}
endspent ();
if (ferror (npwd)) {
perror ("pwunconv");
(void) unlink ("npasswd");
}
(void) fclose (npwd);
(void) fclose (pwd);
return (0);
}
SHAR_EOF
fi
exit 0
# End of shell archive
More information about the Comp.sources.misc
mailing list