|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 5717 (0x1655)
Types: TextFile
Notes: UNIX file
Names: »passwd.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/passwd.c«
/*
* Rec'd from Lauren Weinstein, 7-16-84.
* Passwd - set login password
* for a user.
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <signal.h>
#include <errno.h>
#define NSALT 64 /* Size of salt character set */
#define NSALTC 2 /* Number of characters in salt */
#define NPASSC 32 /* Maximum characters copied into pass. buf */
#define AWRITE 2 /* Access for write */
#define NLOKOUT 7 /* Maximum number of lockout attempts */
#define NPWCHAR 256 /* Number of characters in passwd file line */
char notrich[] = "\
Password is too easily broken\n\
Try again: \
";
char pfile[] = "/etc/passwd";
char tmpfile[] = "/tmp/passwd";
char salttab[NSALT] =
"./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
char pwline[NPWCHAR];
FILE *lockopen();
char *crypt();
int cleanup();
time_t time();
int tmpflag; /* Says tempfile is open */
main(argc, argv)
char *argv[];
{
register struct passwd *pwp;
register char *pass, *name;
char passbuf[NPASSC+1];
int myuid;
extern char *getpass();
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, cleanup);
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, cleanup);
myuid = getuid();
umask(077); /* mask out file access by other users */
if (argc > 1) {
if (argc != 2)
usage();
if ((pwp = getpwnam(argv[1])) == NULL)
perr("%s: bad user name\n", argv[1]);
if (myuid!=0 && pwp->pw_uid!=myuid)
perr("%s: not allowed to change password\n", argv[1]);
name = argv[1]; /* get name for change */
} else {
if ((pwp = getpwuid(myuid)) == NULL)
perr("Error on /etc/passwd\n");
name = pwp->pw_name; /* changing our own name */
}
if (myuid!=0 && pwp->pw_passwd[0]!='\0') {
if ((pass = getpass("Old password: ")) == NULL)
exit(1);
if (!checkpass(pwp->pw_passwd, pass))
perr("Sorry\n");
}
if ((pass = getpass("New password: ")) == NULL)
exit(1);
if (pass[0] != 0 || (pass[0] == 0 && getuid() != 0))
while (!richenough(pass) || !strcmp(pass, pwp->pw_name))
if ((pass = getpass(notrich)) == NULL)
exit(1);
strncpy(passbuf, pass, NPASSC);
if ((pass = getpass("Verification: ")) == NULL)
exit(1);
if (strncmp(pass, passbuf, NPASSC) != 0)
perr("No match: password not changed\n");
setpass(name, pass);
}
/*
* Tests to see if a password is rich enough
* (i.e. not too easy to break by exhaustion).
* A password must be 4 characters if the alphabet
* is rich enough and 6 characters if it is in a
* single case. Perhaps the dictionary should
* be searched as well for more security-conscious
* systems. We also check (above) to make sure
* that the selected password is not the same as the username!
*/
richenough(passwd)
char *passwd;
{
register char *cp;
register int uflag=0, lflag=0, oflag=0;
register int l;
for (cp = passwd; *cp != '\0'; cp++) {
if (islower(*cp))
lflag = 1;
else if (isupper(*cp))
uflag = 1;
else
oflag = 1;
}
l = cp-passwd;
if (l < 4)
return (0);
if (oflag==0 && lflag^uflag && l<6)
return (0);
return (1);
}
/*
* Check the passwd in the password file (`rpass')
* against the typed-in (`tpass') password.
*/
checkpass(rpass, tpass)
register char *rpass, *tpass;
{
char salt[3];
salt[0] = rpass[0];
salt[1] = rpass[1];
return (strcmp(crypt(tpass, salt), rpass) == 0);
}
/*
* Set password for specified name.
*/
setpass(name, passwd)
char *name, *passwd;
{
char salt[NSALTC+1];
char namebuff[NPWCHAR]; /* name buffer */
time_t xtime;
register char *p1, *p2;
register int c;
register FILE *pwf;
register FILE *tf;
/*
* Generate the salt for crypt.
*/
time(&xtime);
srand((int)xtime);
salt[0] = salttab[rand()%NSALT];
salt[1] = salttab[rand()%NSALT];
salt[2] = '\0';
if (*passwd != '\0')
passwd = crypt(passwd, salt);
/*
* Copy password file to tempfile
* looking for slot to change.
* The format of a passwd entry is:
* name:password:uid:...
*/
if ((pwf = fopen(pfile, "r")) == NULL)
perr("Cannot open %s\n", pfile);
tf = lockopen(tmpfile);
while (fgets(pwline, NPWCHAR, pwf) != NULL) {
strcpy(namebuff, pwline); /* copy line */
p1 = namebuff;
while (*p1 != '\0')
if (*p1++ == ':')
break;
*--p1 = '\0'; /* null terminate user name */
p1 = pwline;
while (*p1 != '\0')
if (*p1++ == ':')
break;
p2 = p1;
while (*p2 != '\0')
if (*p2++ == ':')
break;
if (!strcmp(namebuff, name)) { /* check for name match */
*p1 = '\0';
fputs(pwline, tf);
fputs(passwd, tf);
putc(':', tf);
fputs(p2, tf);
break;
}
fputs(pwline, tf);
}
while ((c = getc(pwf)) != EOF) /* copy rest of file */
putc(c, tf);
fclose(pwf);
/*
* Copy tempfile back to password
* file -- this runs protected
* from interrupts.
*/
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
if ((pwf = fopen(pfile, "w")) == NULL)
perr("Cannot create %s\n", pfile);
fflush(tf);
rewind(tf);
while ((c = getc(tf)) != EOF)
putc(c, pwf);
fflush(pwf);
unlink(tmpfile);
}
/*
* Open the tempfile waiting
* for the tempfile to come free.
*/
FILE *
lockopen(file)
char *file;
{
register int n;
register FILE *fp;
extern int errno;
for (n=NLOKOUT; n>0; n--)
if (access(file, AWRITE)<0 && errno==ENOENT) {
if ((fp=fopen(file, "w")) == NULL
|| (fp=freopen(file, "r+w", fp)) == NULL)
perr("Cannot create tempfile\n");
tmpflag = 1;
return (fp);
}
perr("Tempfile busy, try again later\n");
}
/*
* Cleanup the tempfile.
*/
cleanup()
{
if (tmpflag)
unlink(tmpfile);
exit (1);
}
/*
* Error routines
*/
usage()
{
perr("Usage: passwd [name]\n");
}
perr(x)
{
fprintf(stderr, "%r", &x);
exit(1);
}