CAP/contrib/aufsmkusr.c

476 lines
10 KiB
C

/*
* $Author: djh $ $Date: 1995/06/26 06:06:02 $
* $Header: /local/mulga/mac/src/cap60/contrib/RCS/aufsmkusr.c,v 2.1 1995/06/26 06:06:02 djh Rel djh $
* $Revision: 2.1 $
*
*/
/*
* CAP AFP 2.1 Distributed Passwords
*
* Copyright 1995 - The University of Melbourne. All rights reserved.
* May be used only for CAP/AUFS authentication. Any other use
* requires prior permission in writing from the copyright owner.
*
* djh@munnari.OZ.AU
* June 1995
*
* aufsmkusr - modify or create a new .afppass file
*
* usage: aufsmkusr
* aufsmkusr user1 ...
* aufsmkusr -f batchfile
*
* The .afppass file stores the values for minimum password
* length, maximum login failures, current login failures,
* password expiry date and the user's AUFS password.
*
* It is encrypted with the global key set with aufsmkkey.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <netat/appletalk.h>
#include <netat/afppass.h>
#ifdef DISTRIB_PASSWDS
char *linep;
char *progname;
char *batchfile = NULL;
main(argc, argv)
int argc;
char *argv[];
{
int c;
char *cp;
char user[10];
extern char *optarg;
extern int optind, opterr;
int aufsmkbatch(), aufsmkuser();
opterr = 0;
progname = argv[0];
if (geteuid() != 0) {
fprintf(stderr, "%s: Permission Denied.\n", progname);
exit(1);
}
/*
* get global key parameters
*
*/
if (afpdp_init(AFP_DISTPW_FILE) < 0) {
fprintf(stderr, "%s: can't get key from %s\n", progname, AFP_DISTPW_FILE);
exit(2);
}
/*
* process command line options
*
*/
while ((c = getopt(argc, argv, "f:")) != -1) {
switch (c) {
case 'f':
batchfile = optarg;
break;
default:
fprintf(stderr, "usage: aufsmkusr [-f file] [user ...]\n");
exit(1);
break;
}
}
/*
* process users in batch file
*
*/
if (batchfile != NULL) {
(void)aufsmkbatch(batchfile);
exit(0);
}
/*
* process users in argument list
*
*/
if (optind < argc) {
for ( ; optind < argc; optind++) {
fprintf(stderr, "\nSetting AUFS password for %s\n", argv[optind]);
(void)aufsmkuser(argv[optind]);
}
exit(0);
}
/*
* do single users
*
*/
printf("AUFS user: ");
fgets(user, sizeof(user), stdin);
if ((cp = (char *)index(user, '\n')) != NULL)
*cp = '\0';
if (user[0] == '\0')
exit(0);
if (aufsmkuser(user) < 0)
exit(3);
exit(0);
}
/*
* make password file for 'user'
*
*/
int
aufsmkuser(user)
char *user;
{
char abuf[80], *cp;
char pass1[10], pass2[10];
struct passwd *pw, *getpwnam();
extern struct afppass *afp_glob;
time_t now, when, then, afpdp_gdat();
struct afppass afppass, *afp, *afpdp_read();
int afpdp_init(), afpdp_gnum(), afpdp_writ();
void print_date();
if ((pw = getpwnam(user)) == NULL) {
fprintf(stderr, "%s: no such user: \"%s\"\n", progname, user);
return(-1);
}
bzero((char *)&afppass, sizeof(struct afppass));
/*
* get current values or set defaults
*
*/
if ((afp = afpdp_read(user, pw->pw_uid, pw->pw_dir)) != NULL)
bcopy((char *)afp, (char *)&afppass, sizeof(struct afppass));
else
bcopy((char *)afp_glob, (char *)&afppass, 8); /* not password */
/*
* minimum password length 0 - 8 (0 to disable)
*
*/
printf("Minimum AUFS password length: [%d] ? ", afppass.afp_minmpwlen);
afppass.afp_minmpwlen = (u_char)afpdp_gnum(afppass.afp_minmpwlen, KEYSIZE);
/*
* maximum failed logins (0 - 255) (0 to disable)
*
*/
printf("Maximum failed login attempts: [%d] ? ", afppass.afp_maxattempt);
afppass.afp_maxattempt = (u_char)afpdp_gnum(afppass.afp_maxattempt, 255);
/*
* current login attempt failures
*
*/
if (afppass.afp_numattempt > 0) {
printf("User \"%s\" has %d failed login attempt%s.\n", user,
afppass.afp_numattempt, (afppass.afp_numattempt== 1) ? "" : "s");
printf("Reset number of failed login attempts: [%d] ? ",
afppass.afp_numattempt);
afppass.afp_numattempt = (u_char)afpdp_gnum(afppass.afp_numattempt, 255);
}
/*
* make sure user afppass not period
* (except if disabled)
*
*/
time(&now);
when = ntohl(afppass.afp_expires);
if (when <= SECS_10_YRS && when != 0) {
afppass.afp_expires = htonl(when+now);
when = ntohl(afppass.afp_expires);
}
/*
* expiry date (0 to disable)
*
*/
print_date(when);
printf("Password Expires (NNd or NNm or YY/MM/DD [HH:MM:SS]): ? ");
if ((then = afpdp_gdat()) != 0xffffffff) {
if (then <= SECS_10_YRS && then != 0)
then += now;
afppass.afp_expires = htonl(then);
when = then;
}
print_date(when);
then = ntohl(afp_glob->afp_expires);
if (then > SECS_10_YRS && when > then)
printf("WARNING: Global expiry date is %s", ctime(&then));
/*
* user password, up to 8 characters
*
*/
if (*afppass.afp_password) {
printf("Change %s's Password (y/n): [n] ? ", user);
fgets(abuf, sizeof(abuf), stdin);
if (abuf[0] == 'y' || abuf[0] == 'Y')
afppass.afp_password[0] = '\0';
}
while (*afppass.afp_password == '\0') {
strcpy(pass1, (char *)getpass("User Password: "));
if (strlen(pass1) < afppass.afp_minmpwlen) {
printf("Password is shorter than minimum length (%d)\n");
continue;
}
strcpy(pass2, (char *)getpass("Reenter User Password: "));
if (strcmp(pass1, pass2) != 0) {
printf("Password mismatch!\n");
continue;
}
strcpy(afppass.afp_password, pass1);
}
/*
* reset defaults and write
*
*/
afppass.afp_magic = AFPDP_MAGIC;
if (afpdp_writ(user, pw->pw_uid, pw->pw_dir, &afppass) < 0) {
fprintf(stderr, "%s: failed to set AUFS password (same as UNIX ?)\n",
progname);
return(-1);
}
return(0);
}
/*
* handle bulk batch file
*
* each line is expected to be of the format: user "password"
* passwords containing spaces must be enclosed in double quotes
*
* NB: the expiry date is set to now. This requires the user to change
* their password when they first login.
*
*/
int
aufsmkbatch(file)
char *file;
{
time_t now;
struct stat buf;
FILE *fp, *fopen();
struct afppass afppass;
extern struct afppass *afp_glob;
struct passwd *pw, *getpwnam();
char *cp, line[96], user[32];
int afpdp_writ();
void getfield();
if (stat(file, &buf) >= 0) {
if ((buf.st_mode&0777) != 0600) {
fprintf(stderr, "WARNING: %s is mode %0o\n", file, buf.st_mode&0777);
exit(1);
}
}
bzero((char *)&afppass, sizeof(struct afppass));
bcopy((char *)afp_glob, (char *)&afppass, 8); /* not password */
if ((fp = fopen(file, "r")) == NULL) {
perror(file);
return(-1);
}
time(&now);
while (fgets(line, sizeof(line), fp) != NULL) {
if (line[0] == '#' || line[0] == '\n')
continue;
if ((cp = (char *)index(line, '\n')) != NULL)
*cp = '\0';
linep = line;
getfield(user, sizeof(user), 0);
getfield(afppass.afp_password, sizeof(afppass.afp_password), 0);
printf("User \"%s\" - ", user);
/*
* user exists ?
*
*/
if ((pw = getpwnam(user)) == NULL) {
printf("does not exist - continuing\n");
continue;
}
/*
* and has a passwod
*
*/
if (afppass.afp_password[0] == '\0') {
printf("has no password set - continuing\n");
continue;
}
/*
* which expires NOW
*
*/
afppass.afp_expires = htonl(now);
/*
* then set defaults and write
*
*/
afppass.afp_numattempt = 0;
afppass.afp_magic = AFPDP_MAGIC;
if (afpdp_writ(user, pw->pw_uid, pw->pw_dir, &afppass) < 0) {
printf("can't create .afppass file - continuing\n");
continue;
}
printf("OK\n");
}
(void)fclose(fp);
return(0);
}
/*
* output date string
*
*/
void
print_date(when)
time_t when;
{
time_t now;
time(&now);
if (when < SECS_10_YRS) {
if (when == 0)
printf("Password Expiry disabled.\n");
else
printf("Password Expiry period %d day%s.\n",
when/(SECS_IN_DAY), (when/(SECS_IN_DAY) == 1) ? "" : "s");
} else {
if (when < now)
printf("Warning, expiry date has already passed\n");
printf("Password Expires on %s", ctime(&when));
}
return;
}
/*
* Get next field from 'line' buffer into 'str'. 'linep' is the
* pointer to current position.
*
* Fields are white space separated, except within quoted strings.
* If 'quote' is true the quotes of such a string are retained, otherwise
* they are stripped. Quotes are included in strings by doubling them or
* escaping with '\'.
*
*/
void
getfield(str, len, quote)
char *str;
int len, quote;
{
register char *lp = linep;
register char *cp = str;
while (*lp == ' ' || *lp == '\t')
lp++; /* skip spaces/tabs */
if (*lp == 0 || *lp == '#') {
*cp = 0;
return;
}
len--; /* save a spot for a null */
if (*lp == '"' || *lp == '\'') { /* quoted string */
register term = *lp;
if (quote) {
*cp++ = term;
len -= 2; /* one for now, one for later */
}
lp++;
while (*lp) {
if (*lp == term) {
if (lp[1] == term)
lp++;
else
break;
}
/* check for \', \", \\ only */
if (*lp == '\\'
&& (lp[1] == '\'' || lp[1] == '"' || lp[1] == '\\'))
lp++;
*cp++ = *lp++;
if (--len <= 0) {
fprintf(stderr, "string truncated: %s\n", str);
if (quote)
*cp++ = term;
*cp = 0;
linep = lp;
return;
}
}
if (!*lp)
fprintf(stderr,"unterminated string: %s", str);
else {
lp++; /* skip the terminator */
if (*lp && *lp != ' ' && *lp != '\t' && *lp != '#') {
fprintf(stderr, "garbage after string: %s", str);
while (*lp && *lp != ' ' && *lp != '\t' && *lp != '#')
lp++;
}
}
if (quote)
*cp++ = term;
} else {
while (*lp && *lp != ' ' && *lp != '\t' && *lp != '#') {
*cp++ = *lp++;
if (--len <= 0) {
fprintf(stderr, "string truncated: %s\n", str);
break;
}
}
}
*cp = 0;
linep = lp;
return;
}
#else /* DISTRIB_PASSWDS */
main()
{
printf("CAP not compiled with DISTRIB_PASSWDS\n");
}
#endif /* DISTRIB_PASSWDS */