|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T n
Length: 15199 (0x3b5f)
Types: TextFile
Names: »npasswd.c«
└─⟦4f9d7c866⟧ Bits:30007245 EUUGD6: Sikkerheds distributionen
└─⟦123909933⟧ »./npasswd/npasswd.tar.Z«
└─⟦22a202e7d⟧
└─⟦this⟧ »npass-new/npasswd_jpl/npasswd.c«
/* -------------------------------------------------------------------- */
/* */
/* Author: Clyde Hoover */
/* Computation Center */
/* The University of Texas at Austin */
/* Austin, Texas 78712 */
/* clyde@emx.utexas.edu */
/* uunet!cs.utexas.edu!ut-emx!clyde */
/* */
/*This code may be distributed freely, provided this notice is retained. */
/* */
/* -------------------------------------------------------------------- */
/*
* This program duplicates the manual page behavior of the 4.XBSD
* passwd(1) command. It can be configured for use with a variety
* of passwd systems (/etc/passwd, /etc/shadow, databases).
*
* The System V support is untested (by the author - other sites
* tell me it works).
*
* Here we have only the most abstract data needed (login name,
* user id, current password, new password).
* All other information needed (the full password line, etc),
* is kept down in the 'method' routines.
*
* The 'method' routines are:
*
* pw_initalize() Do initializations
* pw_getuserbyname() Get user information by name
* pw_permission() Check if user has permission
* to change this users' password
* pw_compare() Compare passwords
* pw_check() Check password
* Returns 1 if ok, 0 otherwise
* pw_replace() Replace the password
* pw_cleanup() Cleanup
*/
#ifdef SYSLOG
#include <syslog.h>
# ifndef LOG_AUTH
# define LOG_AUTH 0
# endif
# ifndef LOG_CONS
# define LOG_CONS 0
# endif
#endif
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
#include <errno.h>
#include "version.h"
#ifndef lint
static char sccsid[] = "@(#)npasswd.c 1.16 9/24/90 (cc.utexas.edu) /usr/share/src/private/ut/share/bin/passwd/SCCS/s.npasswd.c";
#endif
#ifndef CONFIG_FILE
#define CONFIG_FILE "/usr/adm/passwd.conf"
#endif
#ifndef HELP_FILE
#define HELP_FILE "/usr/adm/passwd.help"
#endif
#ifndef MOTD_FILE
#define MOTD_FILE "/usr/adm/passwd.motd"
#endif
extern int errno; /* System error code */
#ifdef sun
static char *options = "alyd:e:F:n:fPsVx:"; /* Command line options */
#else
static char *options = "fPsV"; /* Command line options */
#endif
static int retries = 3; /* Retry limit */
static int from_prog = 0; /* Data source is a program */
static char username[16], /* Name of user changing password */
password[16]; /* Current password (encrypted) */
char pbuf[16], /* Password read buffer 1 */
pbuf2[16], /* Password read buffer 2 */
ppbuf[16], /* Current password */
mylogin[16]; /* My login name (saved) */
char *getpass(),
*malloc(),
*ttyname(),
*getlogin();
#ifdef SYSV
#define index strchr
#endif
char *index();
int catchit(); /* Signal catcher */
/*
* passwd - change the password for a user.
*
* This program impliments the 'passwd' command.
*/
main(argc, argv)
int argc;
char *argv[];
{
char *myname, mysavedname[16];/* My login name */
struct passwd *pw; /* My passwd entry */
int opt; /* Option processing temp */
extern char *optarg; /* From getopt() */
extern int optind; /* From getopt() */
/*
* Handle the 4.3BSD & SunOS 4.0 command line options.
* Defer everything except password change to other programs.
*/
while ((opt = getopt(argc, argv, options)) != EOF) {
switch (opt) {
#ifdef sun
/*
* Recognized the SunOS 4.1 switches
* but just say that we don't handle them.
*/
case 'a':
printf("Option \"-a\" not supported.\n");
exit(1);
case 'l':
printf("Option \"-l\" not supported.\n");
exit(1);
case 'y':
printf("Option \"-y\" not supported.\n");
exit(1);
case 'd':
printf("Option \"-d\" not supported.\n");
exit(1);
case 'e':
printf("Option \"-e\" not supported.\n");
exit(1);
case 'n':
printf("Option \"-n\" not supported.\n");
exit(1);
case 'x':
printf("Option \"-x\" not supported.\n");
exit(1);
case 'F':
printf("Option \"-F\" not supported.\n");
exit(1);
#endif
case 'f':
punt("chfn");
break;
case 's':
punt("chsh");
break;
case 'P': /* Data source is a program */
if (getuid())
quit(0, "Option \"-P\" reserved for super-user.\n");
from_prog = 1;
break;
case 'V':
printf("%s; patch level %s\n", version, patchlevel);
exit(0);
}
}
bzero(ppbuf, sizeof(ppbuf));
#ifndef DEBUG
if (geteuid())
quit(0,"Permission denied.\n");
#endif
checktty();
savetty();
myname = getlogin();
if (myname == 0 || *myname == '\0') {
if ((pw = getpwuid(getuid())) == ((struct passwd *)NULL))
quit(1, "Cannot get your login name.\n");
strncpy(mysavedname, pw->pw_name, sizeof(mysavedname));
myname = mysavedname;
}
(void) strcpy(mylogin, myname);
(void) signal(SIGINT, catchit);
(void) signal(SIGQUIT, catchit);
#ifdef SYSLOG
openlog("passwd", LOG_PID | LOG_CONS, LOG_AUTH);
#endif
setcheckpasswd("-c", CONFIG_FILE, 0);
pw_initialize();
if (argv[optind])
(void) strcpy(username, argv[optind]);
else
(void) strcpy(username, mylogin);
if (strcmp(username, mylogin) == 0 && getuid()) {
if (pw_getuserbyname(username, password) == 0)
quit(1, "Cannot get your password information.\n");
if (password[0])
getpassword(password, ppbuf, sizeof(ppbuf));
}
else {
if (pw_getuserbyname(username, password) == 0)
quit(0, "No such user %s\n", argv[optind]);
if (pw_permission() == 0)
quit(0, "Permission denied.\n");
printf("Changing password for %s\n", username);
}
motd(MOTD_FILE, (char *)0);
for (;;) {
char *px; /* Temp */
int ntries = 0; /* Password match counter */
px = getpass(from_prog ? "" : "New password (? for help): ");
if (px == NULL)
quit(0, "EOF during new password read.\n");
(void) strcpy(pbuf, px);
if (pbuf[0] == '?') {
motd(HELP_FILE, "Missing help file");
continue;
}
/* Sanity check the new password */
if (pw_check(pbuf) == 0)
continue;
/* Get confirmation */
px = getpass(from_prog ? "" : "New password (again): ");
if (px == NULL)
quit(0, "EOF during new password read.\n");
(void) strcpy(pbuf2, px);
if (strcmp(pbuf, pbuf2)) {
if (ntries++ >= retries)
quit(0, "Too many attempts.\n");
else
printf("They don't match; try again.\n");
if (from_prog)
quit(0, (char *)0);
else
continue;
}
/* Disallow new password == old password */
if (pw_compare(password, pbuf)) {
printf("New password must be different than old; try again.\n");
if (from_prog)
quit(0, (char *)0);
else
continue;
}
else
break;
}
pw_replace(pbuf, ppbuf);
#ifdef SYSLOG
syslog(LOG_INFO, "Password changed for %s by %s\n",
username, mylogin);
#endif
printf("Password changed for %s\n", username);
pw_cleanup(0);
exit(0);
}
/*
* getpassword -- read password and check against current.
*/
getpassword(pwd_crypt, pwd_plain, pwlen)
char *pwd_crypt, /* Present password (encrypted) */
*pwd_plain; /* Present password (plain) */
int pwlen; /* Length of present password buffer */
{
int ntries = 0; /* Match attempt counter */
char *px; /* Temp */
for (;;) {
px = getpass(from_prog ? "" : "Current password: ");
if (px == 0)
quit(0, "EOF during password read.\n");
if (*px == '\0')
continue;
if (!pw_compare(pwd_crypt, px)) {
printf("Password incorrect.\n");
if (ntries++ == retries)
quit(0, "Password not matched.\n");
}
else
break;
}
if (pwd_plain)
(void) strncpy(pwd_plain, px, pwlen);
}
/*
* randomstring - create a string of random characters
*/
randomstring(buf, len)
char buf[]; /* String buffer */
int len; /* Length of buf */
{
register int i, /* Temp */
n; /* Temp */
time_t tv; /* Current time */
char proto[128]; /* Build buffer */
(void) time (&tv);
/*
* Assumes (implicitly) that sizeof(int) == sizeof(long)
*/
(void) srand ( (tv & 0x38d9fcff) ^ getpid ());
for (i = 0; i < sizeof(proto); i++) { /* fill proto vector */
int c; /* Temp */
for (;;) {
c = rand () % 0x7f; /* turn into ASCII */
if (isalnum (c))
break;
}
proto[i] = (char )c;
}
(void) srand(((unsigned )tv & 0x1a90fefc) ^ getpid());
for (i = 0; i < len; i++) {
n = rand() % sizeof(proto);
buf[i] = proto[n];
}
buf[len] = 0;
}
/*
* quit - print/log error message and exit
*/
quit(logit, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
/*VARARGS2*/
int logit; /* 0 = don't log, <> 0 = log message */
char *message; /* Message */
int *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10; /* Args */
{
if (message) {
/*
* If used from program, direct failure messages to stdout,
* else send to stderr.
*/
fprintf(from_prog ? stdout : stderr, message,
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
#ifdef SYSLOG
if (logit)
syslog(LOG_ERR, message,
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
#endif
}
pw_cleanup(1);
exit(1);
}
/*
* motd - issue 'message of the day'
*/
motd(fn, complaint)
char *fn, /* Name of file to present */
*complaint; /* Complaint if missing */
{
char cmdbuf[BUFSIZ]; /* Buffer to build command in */
if (access(fn, 0) < 0) {
if (complaint)
printf("%s\n", complaint);
return;
}
if (isatty(0))
#ifdef SYSV
(void) sprintf(cmdbuf, "pg -n -s %s", fn);
#else
(void) sprintf(cmdbuf, "more -d %s", fn);
#endif
else
(void) sprintf(cmdbuf, "cat %s", fn);
if (fork() == 0) {
(void) setgid(getgid());
(void) setuid(getuid());
(void) system(cmdbuf);
exit(0);
}
(void) wait((int *)0); /* "Wrong" for BSD, right for SYS V */
}
/*
* checktty - Attempt to check against being pipe-fed
*/
checktty()
{
char *stdin_tty, /* ttyname(0) */
*stdout_tty, /* ttyname(1) */
*t; /* Temp */
if (!isatty(0)) {
if (from_prog == 0)
quit(0, "Input not a tty.\n");
if (lseek(0, 0L, 1) < 0) {
if (errno != ESPIPE)
quit(0, "Input not a tty or pipe.\n");
else
return;
}
}
from_prog = 0; /* Stdin is a tty - behave normal */
stdin_tty = ttyname(0);
if (stdin_tty == NULL || *stdin_tty == 0)
quit(0, "Cannot get name (stdin).\n");
t = malloc(strlen(stdin_tty) + 1);
if (t == NULL)
quit(1, "Cannot allocate temp memory.");
(void) strcpy(t, stdin_tty);
stdin_tty = t;
stdout_tty = ttyname(1);
if (stdout_tty == NULL || *stdout_tty == 0)
quit(0, "Cannot get name (stdout).\n");
if (strcmp(stdin_tty, stdout_tty))
quit(0, "Input and output are not the same tty.\n");
free(stdin_tty);
}
/*
* catchit - tty interrupt catcher
*/
catchit()
{
fixtty();
pw_cleanup(1);
quit(0, "\nInterrupted; changes discarded.\n");
}
#if defined(SYSV)
# include <termio.h> /* Vanilla SV termio */
struct termio saved_tty_mode;
#endif
#if defined(SUNOS4)
# include <sys/termios.h> /* SUN OS 4.0 termio */
#define TCGETA TCGETS
#define TCSETA TCSETS
struct termios saved_tty_mode;
#endif
#if !defined(SUNOS4) && !defined(SYSV)
# include <sgtty.h> /* BSD tty */
struct sgttyb saved_tty_mode;
int saved_local_flags;
#endif
char saves_valid = 0; /* Are the saved values valid? */
/*
* savetty - save current terminal settings
*/
savetty()
{
#if defined(SYSV) || defined(SUNOS4)
(void) ioctl(0, TCGETA, &saved_tty_mode);
#else
(void) ioctl(0, TIOCGETP, &saved_tty_mode);
(void) ioctl(0, TIOCLGET, &saved_local_flags);
#endif
saves_valid++;
}
/*
* fixtty - restore saved terminal settings
*/
fixtty()
{
if (saves_valid) {
#if defined(SYSV) || defined(SUNOS4)
(void) ioctl(0, TCSETA, &saved_tty_mode);
#else
(void) ioctl(0, TIOCSETP, &saved_tty_mode);
(void) ioctl(0, TIOCLSET, &saved_local_flags);
#endif
}
}
#ifdef XGETPASS
/*
* The system getpass() throws away all but the first 8 characters
* of a password string. If this isn't enough for you, use this
* routine instead. This code assumes that stdin is the terminal.
*/
char *
getpass(prompt)
char *prompt;
{
#if defined(SYSV)
struct termio saved, /* Saved tty characteristics */
noecho; /* No-echo tty characteristics */
char *strchr();
#endif
#if defined(SUNOS4)
struct termios saved, /* Saved tty characteristics */
noecho; /* No-echo tty characteristics */
#else
struct sgttyb saved, /* Saved tty characteristics */
noecho; /* No-echo tty characteristics */
#endif
static char ib[64]; /* Input buffer */
char *rc; /* Temp */
#if defined(SYSV) || defined(SUNOS4)
(void) ioctl(0, TCGETA, &saved);
noecho = saved;
noecho.c_lflag &= ~ECHO;
(void) ioctl(0, TCSETA, &noecho);
#else
(void) ioctl(0, TIOCGETP, &saved);
noecho = saved;
noecho.sg_flags &= ~ECHO;
(void) ioctl(0, TIOCSETP, &noecho);
#endif
fprintf(stderr, "%s", prompt);
fflush(stderr);
rc = fgets(ib, sizeof(ib), stdin);
putc('\n', stderr);
fflush(stderr);
#if defined(SYSV) || defined(SUNOS4)
(void) ioctl(0, TCSETA, &saved);
#else
(void) ioctl(0, TIOCSETP, &saved);
#endif
if (rc == NULL)
return(NULL);
if (rc = index(ib, '\n'))
*rc = 0;
return(ib);
}
#endif
#ifdef XPUTPWENT
/*
* putpwent - replacement for the System V routine
* This writes the "standard" passwd file format.
*/
putpwent(p, f)
struct passwd *p; /* Passwd entry to put */
FILE *f; /* File pointer */
{
#ifdef UNSIGNED_UID
fprintf(f, "%s:%s:%u:%u:%s:%s:%s\n",
#else
fprintf(f, "%s:%s:%d:%d:%s:%s:%s\n",
#endif
p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
p->pw_gecos, p->pw_dir, p->pw_shell);
}
#endif
#ifdef XFGETPWENT
/*
* fgetpwent() - read passwd(5) entry from a file
* This reads the "standard" passwd file format.
*/
struct passwd *
fgetpwent(f)
FILE *f; /* Pointer to open passwd format file */
{
static struct passwd pwdata; /* Return data */
static char ibuf[BUFSIZ]; /* Input and return data buffer */
char *p; /* ACME Pointer Works, Inc */
bzero((char *)&pwdata, sizeof(pwdata));
pwdata.pw_name = pwdata.pw_passwd = pwdata.pw_comment =
pwdata.pw_gecos = pwdata.pw_dir = pwdata.pw_shell = "";
if (fgets(ibuf, sizeof(ibuf), f) == NULL)
return(0);
if ((p = index(ibuf, '\n')) == 0) /* Zap newline */
quit(1, "Ill-formed passwd entry \"%s\".\n", ibuf);
else
*p = 0;
#define skipc while (*p && *p != ':' && *p != '\n') ++p; if (*p) *p++ = 0
p = ibuf;
pwdata.pw_name = p; skipc;
pwdata.pw_passwd = p; skipc;
pwdata.pw_uid = atoi(p); skipc;
pwdata.pw_gid = atoi(p); skipc;
pwdata.pw_gecos = p; skipc;
pwdata.pw_dir = p; skipc;
pwdata.pw_shell = p;
return(&pwdata);
#undef skipc
}
#endif
#ifdef SYSV
/*
* rename - replacement for the 4.2/4.3 BSD rename system call
*/
rename(src, dst)
char *src, /* Source path */
*dst; /* Destination path */
{
if (unlink(dst) < 0) {
if (errno != ENOENT)
return(-1);
}
if (link(src, dst) < 0)
return(-1);
return(unlink(src));
}
#endif
/*
* punt() - run another program to do what we don't do
*/
punt(prog)
char *prog; /* Program to run */
{
(void) setgid(getgid());
(void) setuid(getuid());
(void) execlp(prog, prog, 0);
perror(prog);
exit(1);
}
/* End npasswd.c */