home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************\
- ** **
- ** Program name: dpasswd.c (Manage "Dialup Passwords" for /bin/login) **
- ** **
- ** Programmer: Lenny Tropiano EMAIL: lenny@ICUS.COM **
- ** Organization: ICUS Software Systems (c)1988,1990 All rights reserved **
- ** Date: December 4, 1988 [Version 1.0] **
- ** May 16, 1990 [Version 1.6] **
- ** June 16, 1990 [Version 2.0] **
- ** **
- ** Modified by Gary Butler, ST, Pacific Bell [1.6] **
- ** Modified by Joe Wasik, ST, Pacific Bell [1.6] **
- ** Modified by Lenny Tropiano, ICUS Software Systems [2.0] **
- ** **
- **************************************************************************
- ** **
- ** Program to administer the "undocumented" feature /bin/login Dialup **
- ** Password's that is part of most UNIX System V releases **
- ** **
- ** compile with -dTEST to try out on local (current dir) files **
- ** **
- ** compile with -dDEBUG to see debug stuff **
- ** **
- **************************************************************************
- ** **
- ** Permission granted to redistribute without profit in the public **
- ** domain only. This header must remain in-tact as is. This program **
- ** carries no warranties, express or implied, and all consequences **
- ** resulting from the use of this program are the sole responsibility **
- ** of the user. Any modifications of this program must be mailed to **
- ** the author. **
- ** **
- \************************************************************************/
-
- /*
- ** Revision history:
- **
- ** May 16, 1990
- **
- ** Bugs and major problems fixed:
- **
- ** 1 - When writing out the d_passwd file, the file was opened for output
- ** before getting password or even checking for user errors. If any
- ** kind of interruption happened (signal, user error) then program quit
- ** without writing array contents - effectively nulling the file.
- **
- ** 2 - Program checked to see if progname on command line was already in
- ** the file; however, to get around the problem of the password being
- ** part of the string, the program compared only the number of
- ** chracters in the cmdline progname. So, if a name was provided
- ** that in its entirety matched only the first part of an existing
- ** progname, this was considered a match.
- **
- ** 3 - Both MAX_PROG and MAX_DIALUPS was applied to existing data, rather
- ** then only new data. So, if a user wanted to enter a new entry to
- ** a file that was already too large, the file was truncated.
- **
- ** 4 - A minor error was the PROGLEN variable which was described as the
- ** maximum length of the program name. It was really the maximum
- ** length of the d_passwd record.
- **
- **
- ** Improvements made:
- **
- ** 1 - Code run through indent(1) to rearrange braces, comments,
- ** indentation, and to line up variable definitions.
- **
- ** 2 - Added comments.
- **
- ** 3 - Several variables used as flags we're never initialized, while I didn't
- ** run into problems, it could have caused problems on some systems.
- **
- ** 4 - Made it easier to control permissions of new d_passwd and dialup
- ** files by using variables.
- **
- ** 5 - Greatly increased buffer sizes.
- **
- ** 6 - Added DEBUG variable (#define) to aid in future work.
- **
- ** 7 - Added TEST variable (#define) so that user can try out this program
- ** on local files (curr dir) before going live.
- **
- ** 8 - Eliminated all lint errors.
- **
- ** 9 - Tell user when a password was changed. As written, this program
- ** mislead the user by saying a changed password wasa new password.
- **
- ** 10 - Don't allow null password.
- **
- ** 11 - Default to 600 rather than 644 permissions.
- **
- **
- ** Improvements suggested:
- **
- ** 1 - Change -v (verbose) to -s (silent) so that errors appear by default.
- **
- ** 2 - Use write to temp file and rename rather than rewrite of files.
- **
- ** - Joe Wasik
- **
- ** June 16, 1990
- **
- ** Some minor improvements:
- **
- ** 1 - Code run through indent(1) again using the "-kr" option so it's more
- ** like the way I like to code. This is to rearrange braces, comments,
- ** indentation, and to line up variable definitions using tabs, and less
- ** spaces. Sorry for imposing my way of coding, but what can I say ...
- ** After running indent(1) I cleaned it up a little by hand, added some
- ** more spaces where it "looked" necessary for readability.
- **
- ** 2 - Changed -v (verbose) to -q (quiet) so that errors appear by default,
- ** as suggested (instead of silent [-s], I'm using the syntax quiet [-q]).
- **
- ** 3 - Another option -n (null password) has been added to create password
- ** entries for shells that require no password. It appears that certain
- ** versions of /bin/login will prompt for a dialup password for all shells
- ** if the restriction is in the /etc/dialups file, but will fail if there
- ** is no accompaning entry in /etc/d_passwd (even a null password entry).
- **
- ** - Lenny Tropiano
- **
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <pwd.h>
- #include <string.h>
-
- /*
- ** preprocessor parameters
- */
-
- /* permissions of dialups file (if created) */
- #ifndef DIALUPS_PERMS
- #define DIALUPS_PERMS 0600
- #endif
-
- /* permissions of d_passwd file (if created) */
- #ifndef DPASSWD_PERMS
- #define DPASSWD_PERMS 0600
- #endif
-
- /* maximum # of dialups on system */
- #ifndef MAX_DIALUPS
- #define MAX_DIALUPS 10
- #endif
-
- /* maximum # of program shells */
- #ifndef MAX_PROGS
- #define MAX_PROGS 20
- #endif
-
- /* tty device length "/dev/ttyXXX" */
- #ifndef TTYLEN
- #define TTYLEN 20
- #endif
-
- /* program pathname length */
- #ifndef PROGLEN
- #define PROGLEN 60
- #endif
-
- /* password buffer length */
- #ifndef PSWLEN
- #define PSWLEN 20
- #endif
-
- /* password password entry attempts */
- #ifndef PSWATTEMPTS
- #define PSWATTEMPTS 3
- #endif
-
- /* check debug flag */
- #ifdef DEBUG
- int debug = 1;
- #else
- int debug = 0;
- #endif
-
- /* compute buffer for d_passwd file (name + psw + separator space) */
- #define DPASSWDLEN (PROGLEN+PSWLEN+3)
-
- /*
- * global variables
- */
-
- int delete, /* remove dialup information */
- quiet, /* don't be verbose, be quiet */
- null; /* create a null password entry */
- long time();
- long salt;
- char saltc[2];
- char terminal[TTYLEN], /* device to declare as dialup line */
- program[PROGLEN], /* pathname to give dialup password */
- passwd[PSWLEN];
- char *thisprg;
-
- void exit();
- void perror();
-
- #ifdef TEST
- static char *dttyfile = "dialups";
- static char *dpswfile = "d_passwd";
-
- #else
- static char *dttyfile = "/etc/dialups";
- static char *dpswfile = "/etc/d_passwd";
-
- #endif
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int c,
- errflg,
- chgterm,
- chgprog;
- extern int optind;
- extern char *optarg;
- void manage_dialup(),
- manage_program();
-
-
- /*
- ** initialize program parameters
- */
-
- thisprg = argv[0];
- delete = errflg = quiet = null = chgterm = chgprog = 0;
- terminal[0] = program[0] = '\0';
-
- if (debug)
- (void) printf("buffer length: %d\n", DPASSWDLEN);
-
- /*
- ** read command line options
- */
-
- while ((c = getopt(argc, argv, "?qdnt:p:")) != EOF) {
- switch (c) {
- case 'q':
- quiet = 1;
- break;
- case 'd':
- delete = 1;
- break;
- case 'n':
- null = 1;
- break;
- case 't':
- if (strchr(optarg, '/') == NULL) {
- chgterm = 1;
- (void) sprintf(terminal, "/dev/%s", optarg);
- } else
- errflg++;
- break;
- case 'p':
- chgprog = 1;
- (void) sprintf(program, "%s", optarg);
- break;
- case '?':
- errflg++;
- break;
- } /* end switch */
- } /* end while */
-
- if (errflg || (!chgterm && !chgprog)) {
- (void) fprintf(stderr,
- "Usage: %s [-qnd] -p program -t terminal\n",
- thisprg);
- exit(1);
- }
-
- if (chgterm)
- manage_dialup();
-
- if (chgprog)
- manage_program();
-
- exit(0);
- }
-
- void manage_dialup()
- {
- FILE *fp,
- *fopen(),
- *fdopen();
- int fd,
- found;
- int ttyno,
- i;
- char dialtty[MAX_DIALUPS][TTYLEN],
- buffer[TTYLEN],
- *fgets(),
- *c;
-
- /* read in the old dialups file */
- /* if it doesn't exist,then create it */
-
- if ((fp = fopen(dttyfile, "r")) == NULL) {
-
- if (debug)
- (void) printf("creating %s\n", dttyfile);
-
- if ((fd = creat(dttyfile, DIALUPS_PERMS)) < 0) {
- perror(dttyfile);
- exit(1);
- }
-
- fp = fdopen(fd, "r");
- }
-
- found = ttyno = 0;
-
- /* loop thru all records and load them into array */
-
- while (fgets(buffer, TTYLEN, fp) != NULL) {
-
- /* If file is already bigger than allotted, tell user */
-
- if (ttyno >= MAX_DIALUPS) {
- if (!quiet)
- (void) printf("%s: %s is too big\n", thisprg, dttyfile);
- exit(1);
- }
-
- /* strip trailing newline */
- c = strrchr(buffer, '\n');
- *c = '\0';
-
- /* if this record matches cmd line argument then record
- * location
- */
- if (strcmp(buffer, terminal) == 0)
- found = ttyno + 1;
-
- if (debug)
- (void) printf("in %d: tty:%s\n", ttyno, buffer);
-
- /* move record into array space */
- (void) sprintf(dialtty[ttyno++], "%s", buffer);
- }
- (void) fclose(fp);
-
- /* start deleting */
- if (found && delete) {
- if ((fp = fopen(dttyfile, "w")) == NULL) {
- perror(dttyfile);
- exit(1);
- }
-
- /* index pos was increment by one so that position 0 would have
- ** a true value, i.e. 1.
- */
- found--;
-
- /* Write out all records */
-
- for (i = 0; i < ttyno; i++) {
-
- /* If index position matches cmd line arg, then skip
- ** this one
- */
- if (i != found) {
- if (debug)
- (void) printf("del/out %d: tty:%s\n", i,
- dialtty[i]);
-
- (void) fprintf(fp, "%s\n", dialtty[i]);
- }
- }
- (void) fclose(fp);
-
- if (!quiet)
- (void)
- printf("%s: Dialup terminal restriction removed from %s.\n",
- thisprg, terminal);
-
- /* start adding */
-
- } else if (!found && !delete) {
-
- /* If we're going to add, ensure that there is room */
-
- if (ttyno == MAX_DIALUPS) {
- if (!quiet)
- (void) printf("%s: %s is already at max size\n",
- thisprg, dttyfile);
- exit(1);
- }
-
- /* open dialups for output
- ** Could have just done an append instead of rewrite of file.
- ** I don't know what author had in mind, but I'll leave it
- ** alone
- */
-
- if ((fp = fopen(dttyfile, "w")) == NULL) {
- perror(dttyfile);
- exit(1);
- }
-
- /* loop through all records in array (old file) and write */
- for (i = 0; i < ttyno; i++) {
- if (debug)
- (void) printf("add/out %d: tty:%s\n", i, dialtty[i]);
- (void) fprintf(fp, "%s\n", dialtty[i]);
- }
-
- /* Append new record to end */
- (void) fprintf(fp, "%s\n", terminal);
-
- if (debug)
- (void) printf("add/out %d: tty:%s\n", i, terminal);
-
- (void) fclose(fp);
-
- if (!quiet)
- (void)
- printf("%s: Dialup terminal restriction added for %s.\n",
- thisprg, terminal);
-
- /* Some error handline follows */
-
- } else if (!found && delete && !quiet) {
- (void) printf("%s: Terminal %s not found in %s.\n",
- thisprg, terminal, dttyfile);
- } else if (found && !delete && !quiet) {
- (void) printf("%s: Terminal %s already found in %s.\n",
- thisprg, terminal, dttyfile);
- }
- }
-
- void manage_program()
- {
- FILE *fp,
- *fopen(),
- *fdopen();
- int get_password(),
- fd,
- found,
- pswno,
- i;
- char dialpsw[MAX_PROGS][DPASSWDLEN],
- buffer[DPASSWDLEN],
- cmpbuff[DPASSWDLEN],
- *crypt(),
- *fgets(),
- *c;
-
- /* open the d_passwd file, if it doesn't exist, create it */
-
- if ((fp = fopen(dpswfile, "r")) == NULL) {
-
- if (debug)
- (void) printf("creating %s\n", dpswfile);
-
- if ((fd = creat(dpswfile, DPASSWD_PERMS)) < 0) {
- perror(dpswfile);
- exit(1);
- }
-
- fp = fdopen(fd, "r");
- }
-
- found = pswno = 0;
-
- /* loop thorugh all records, then load them into array */
-
- while (fgets(buffer, DPASSWDLEN, fp) != NULL) {
-
- /* if file is already bigger than allotted then tell user */
-
- if (pswno >= MAX_PROGS) {
- if (!quiet)
- (void) printf("%s: %s is too big\n", thisprg, dpswfile);
- exit(1);
- }
-
- /* Strip trailing newline */
- c = strrchr(buffer, '\n');
- *c = '\0';
-
- /* Copy buffer of prog+pass to buffer that only uses prog */
- (void) strcpy(cmpbuff, buffer);
-
- /* The colon separates prog from psw, so making it null turns
- ** the prog name into a separate string
- */
- c = strchr(cmpbuff, ':');
- *c = '\0';
-
- /* If this prog name matches cmnd line entry then record
- ** its location
- */
- if (strcmp(cmpbuff, program) == 0)
- found = pswno + 1;
-
- if (debug)
- (void) printf("in %d: prog:%s\n", pswno, buffer);
-
- /* move record to array */
- (void) sprintf(dialpsw[pswno++], "%s", buffer);
- }
- (void) fclose(fp);
-
- /* start deleting */
-
- if (found && delete) {
- if ((fp = fopen(dpswfile, "w")) == NULL) {
- perror(dpswfile);
- exit(1);
- }
-
- /* index pos was increment by one so that position 0 would
- ** have a true value, i.e. 1.
- */
- found--;
-
- /* Write out all records */
-
- for (i = 0; i < pswno; i++) {
-
- /* If index position matches cmd line arg, then skip
- ** this one
- */
- if (i != found) {
- if (debug)
- (void) printf("del/out %d: prog:%s\n", i, dialpsw[i]);
- (void) fprintf(fp, "%s\n", dialpsw[i]);
- }
- }
- (void) fclose(fp);
-
- if (!quiet)
- (void)
- printf("%s: Dialup program restriction removed from %s.\n",
- thisprg, program);
-
- /* start to add a program and password
- ** if program already was in file then replace it
- */
-
- } else if (!delete) {
- if (!found && pswno == MAX_PROGS) {
- if (!quiet)
- (void) printf("%s: %s is already at max size\n",
- thisprg, dpswfile);
- exit(1);
- }
-
- /* initialize password */
- passwd[0] = '\0';
-
- if (!null)
- if (get_password())
- return;
-
- /* Create the file for output.
- ** Note, the author had this code before the password input.
- ** If the program was stopped while at the prompt, the
- ** d_passwd file would be deleted. So, I moved it here.
- ** An even better, but perhaps more involved fix would be
- ** to create a temp file, then rename the temp file back
- ** to the original
- */
-
- if ((fp = fopen(dpswfile, "w")) == NULL) {
- perror(dpswfile);
- exit(1);
- }
-
- /* index pos was increment by one so that position 0 would have
- ** a true value, i.e. 1.
- */
- found--;
-
- /* loop through array writing out all those accept the match
- ** against the input file
- */
-
- for (i = 0; i < pswno; i++)
- if (i != found) {
- if (debug)
- (void) printf("add/out %d: prog:%s\n",
- i, dialpsw[i]);
- (void) fprintf(fp, "%s\n", dialpsw[i]);
- }
-
- if (null)
- (void) fprintf(fp, "%s::\n", program);
- else
- (void) fprintf(fp, "%s:%s:\n",
- program, crypt(passwd, saltc));
- if (debug)
- if (null)
- (void) printf("add/out %d: prog:%s::\n",
- i, program);
- else
- (void) printf("add/out %d: prog:%s:%s:\n",
- i, program, crypt(passwd, saltc));
-
- (void) fclose(fp);
-
- /* if requested, tell user whether program was added
- ** or just changed
- */
- if (!quiet) {
- if (found >= 0) {
- (void) printf(
- "%s: Dialup program restriction changed for %s.\n",
- thisprg, program);
- } else {
- (void) printf(
- "%s: Dialup program restriction added for %s.\n",
- thisprg, program);
- }
- }
-
- /* tell user about this error (if requested) */
-
- } else if (!found && delete && !quiet)
- (void) printf("%s: Program %s not found in %s.\n",
- thisprg, program, dpswfile);
-
- }
-
- int get_password()
- {
- int i,
- d,
- bad,
- match;
- char *getpass(),
- retype[PSWLEN];
-
- /* keep getting passwords (as long as the user didn't ask for
- ** a null password entry) until user gets it right or until
- ** attempt counter reaches maximum
- */
- bad = 0;
-
- do {
- /* get password - repeat if user just presses return */
- do {
-
- (void) sprintf(passwd, "%s",
- getpass("New Dialup Password:"));
- } while (*passwd == '\0');
-
- /* get it again so that we can be sure that there
- ** are no typos
- */
- (void) sprintf(retype, "%s",
- getpass("Retype Dialup Password:"));
-
- /* was there a typo? if so, count this as a failed
- ** attempt
- */
- if ((match = strcmp(passwd, retype)) != 0) {
- (void) printf("They don't match; try again.\n\n");
- bad++;
- }
-
- } while (match != 0 && bad < PSWATTEMPTS);
-
- /* return user to caller if he just cannot get it right */
- if (bad == PSWATTEMPTS) {
- (void) printf("Too many tries; try again later.\n\n");
- return 1;
- }
-
- /* Construct salt, then encrypt the new password */
- (void) time(&salt);
- salt += getpid();
-
- /* Make sure the new key doesn't have the first two letters
- ** of the password in it, and only allow valid characters
- ** . / 0-9 A-Z a-z
- */
- saltc[0] = salt & 007;
- saltc[1] = (salt >> 6) & 077;
- for (i = 0; i < 2; i++) {
- d = saltc[i] + '.';
- if (d > '9')
- d += 7;
- if (d > 'Z')
- d += 6;
- saltc[i] = d;
- }
- return 0;
- }
-
- #ifndef lint
- static char sccsid[] = "@(#)dpasswd.c Version 2.0";
- #endif
-