/*, int extendedCommands- * Copyright (c) 1998-2003 Joe Marcus Clarke * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Gone - a terminal locking program with many improvements over lock(1) * * $Id: gone.c,v 1.3 2003/10/13 05:58:59 marcus Exp $ */ #include /* atoi() */ #include /* fprintf(), stderr, printf(), fgets(), stdin, BUFSIZ, fflush(), putchar(), clearerr() */ #include "config.h" #include /* signal(), SIGINT, SIGSTP, SIGQUIT, SIGALRM, SIGHUP, kill() */ #include /* getpass(), getuid(), getppid(), STDIN_FILENO, setuid() */ #include /* isdigit() */ #ifdef HAVE_CRYPT_H #include #endif #ifdef HAVE_SYS_STAT_H #include /* struct timeval, struct itimerval, chmod(), gettimeofday(), localtime(), asctime(), setitimer(), stat(), struct stat */ #endif #ifdef HAVE_SYS_TERMIO_H #include /* struct termio, TCGETA, ECHO, TCSETAF, TCSETA, TCGETA, ioctl() */ #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_TIME_H #include #endif #if defined(OSF1) && defined(EN_SEC) #include #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_PWD_H #include #endif #include "gone.h" #define TIMEOUT 10 #define PASSWORD_BUFFER 127 #if defined OSF1 || defined ULTRIX struct timeval timeout = {0, 0}; struct timeval zerotime = {0, 0}; #else /* OSF1 || ULTRIX */ struct timeval timeout; struct timeval zerotime; #endif /* OSF1 || ULTRIX */ #define SALT "3C" /* XXX Crappy */ struct stat ttystat; long nexttime; mode_t ttymode; char *ttynam; /* Function prototypes */ void lockTerm(char *ap, char *password, int timeAway, int extendedCommands, int printBanner); char *getPassword(); void usage(char *progName); void quit(); int hi(); void printHeader(int extendedCommands, int printBanner); void print_version_info(void); struct gone_commands commands[] = { "w", "Print a summary of current system activity", 1, "finger", "Display user information", 1, "whoami", "Display the the locking user's name", 1, "help", "Print this message", 0, "date", "Display the date and time", 1, "status", "Display the lock timeout", 0, "cls", "Clear the screen, and display this message", 0 }; #if defined(ULTRIX) extern char *optarg; extern int optind, opterr; #endif /* ULTRIX */ main(int argc, char *argv[]) { extern int errno; char *ap; char buffer[PASSWORD_BUFFER]; char *cryptBuffer; char *cryptRetypeBuffer; char enteredPass[PASSWORD_BUFFER]; struct timeval timval; struct itimerval ntimer, otimer; struct tm *timp; int goneTime; int ch; int i; int mesgOff = 1; int useSysPasswd = 0; int extendedCommands = 1; int printBanner = 1; char *sysPass; struct passwd *pw; goneTime = TIMEOUT; #if defined(OSF1) && defined(EN_SEC) && defined(SETUID) set_auth_parameters(); while ((ch = getopt(argc, argv, "bvpxynt:")) != -1) #elif defined(SETUID) while ((ch = getopt(argc, argv, "bvpxynt:")) != -1) #else /* OSF1 && EN_SEC && SETUID */ while ((ch = getopt(argc, argv, "bvyxnt:")) != -1) #endif /* OSF1 && EN_SEC && SETUID */ switch((char)ch) { case 'b': printBanner = 0; break; case 'v': print_version_info(); exit(0); #if defined(OSF1) && defined(EN_SEC) && defined(SETUID) case 'p': if (getespwuid(getuid()) == NULL) { printf("Error getting your password from the system.\n"); useSysPasswd = 0; } else { sysPass = getespwuid(getuid())->ufld->fd_encrypt; useSysPasswd = 1; } break; #elif defined(SETUID) case 'p': if (!(pw = getpwuid(getuid()))) { printf("Error getting your password from the system.\n"); useSysPasswd = 0; } else { sysPass = pw->pw_passwd; useSysPasswd = 1; } break; #endif /* OSF1 && EN_SEC && SETUID */ case 'n': case 'x': extendedCommands = 0; break; case 'y': mesgOff = 0; break; case 't': if ((goneTime = atoi(optarg)) < 0) { /* If goneTime == 0, then lock the terminal indifinitely. */ fprintf(stderr, "Illegal timeout value.\n"); exit(1); } break; default: usage(argv[0]); } setuid(getuid()); /* reset uid permissions */ putenv("PATH=/bin:/usr/bin:/usr/bsd:/usr/ucb"); if (!(ttynam = ttyname(STDIN_FILENO))) { /* check to see if stdin is a tty */ printf("Not a terminal\n"); exit(1); } stat(ttynam, &ttystat); /* save current tty permissions */ ttymode = ttystat.st_mode; if (mesgOff == 1) { chmod(ttynam, 00600); /* chmod the tty so only the owner can read and write to it */ } else { #ifdef IRIX /* Dumb IRIX "security" */ chmod(ttynam, 00622); #else /* IRIX */ chmod(ttynam, 00620); #endif /* IRIX */ } timeout.tv_sec = goneTime * 60; if (gettimeofday(&timval,(struct timezone *)NULL)) { exit(1); } nexttime = timval.tv_sec + (goneTime * 60); timp = localtime((time_t *)&timval.tv_sec); ap = asctime(timp); ap[strlen(ap)-1] = '\0'; ntimer.it_interval = zerotime; ntimer.it_value = timeout; if ( goneTime != 0 ) { /* Allow for the terminal to be locked forever. */ setitimer(ITIMER_REAL, &ntimer, &otimer); } if (gettimeofday(&timval,(struct timezone *)NULL)) { exit(1); } nexttime = timval.tv_sec + (goneTime * 60); timp = localtime((time_t *)&timval.tv_sec); ap = asctime(timp); ap[strlen(ap)-1] = '\0'; ntimer.it_interval = zerotime; ntimer.it_value = timeout; if ( goneTime != 0 ) { /* Allow for the terminal to be locked forever. */ setitimer(ITIMER_REAL, &ntimer, &otimer); } if (useSysPasswd) { strcpy(enteredPass,sysPass); } else { strcpy(buffer, getpass("Password: ")); if (*buffer == NULL) { printf("Null passwords are not allowed!\n"); exit(1); } cryptBuffer = (char *)crypt(buffer, SALT); strcpy(enteredPass, cryptBuffer); for(i = 0; i < sizeof(buffer)/sizeof(buffer[0]);i++) buffer[i] = '\0'; strcpy(buffer, getpass("Retype: ")); cryptRetypeBuffer = (char *)crypt(buffer, SALT); for(i = 0; i < PASSWORD_BUFFER; i++) { buffer[i] = '\0'; } fflush(stdin); if (strcmp(enteredPass, cryptRetypeBuffer)) { printf("Passwords did not match!\n"); exit(1); } } /* set signal handlers */ signal(SIGINT, (void (*)(int))hi); signal(SIGQUIT, (void (*)(int))hi); signal(SIGTSTP, (void (*)(int))hi); signal(SIGALRM, (void (*)(int))quit); signal(SIGHUP, (void (*)(int))quit); lockTerm(ap, enteredPass, goneTime, extendedCommands, printBanner); return 0; } void lockTerm(char *ap, char *password, int timeAway, int extendedCommands, int printBanner) { char key[PASSWORD_BUFFER]; char *cryptKey; char cmd[BUFSIZ]; int badPass = 1; int goodCommand; int i; if ( timeAway == 0 ) { printf("Terminal locked at %s indefinitely.\n", ap); } else { printf("Terminal locked at %s for %d minutes(s).\n", ap, timeAway); } printHeader(extendedCommands, printBanner); fflush(stdin); printf("> "); while(badPass) { fflush(stdin); if (!fgets(cmd, sizeof(cmd), stdin)) { clearerr(stdin); continue; } goodCommand = 0; cmd[strlen(cmd) - 1] = '\0'; if (!strncmp(cmd, "help",strlen(cmd)) && cmd[0] != '\0') { printHeader(extendedCommands, printBanner); } else if (!strncmp(cmd, "cls", strlen(cmd)) && cmd[0] != '\0') { system("clear"); printHeader(extendedCommands, printBanner); } else if (!strncmp(cmd, "status", strlen(cmd)) && cmd[0] != '\0') { hi(); } else if (!strncmp(cmd, "finger", strlen(cmd)) && extendedCommands && cmd[0] != '\0') { char fingerCommand[BUFSIZ] = "finger "; char hostname[BUFSIZ] = "\0"; char parsedHostname[BUFSIZ] = "\0"; printf("Enter parameters: "); if (!fgets(hostname, sizeof(hostname), stdin)) { clearerr(stdin); continue; } hostname[strlen(hostname) - 1] = '\0'; if (hostname != NULL) { sscanf(hostname, "%[^|!`<>*&$;,]", parsedHostname); } strcat(fingerCommand, parsedHostname); system(fingerCommand); } else { for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { if (!strncmp(cmd, commands[i].command, strlen(cmd)) && extendedCommands && cmd[0] != '\0') { system(commands[i].command); goodCommand = 1; } } } if (!goodCommand && strncmp(cmd, "unlock",strlen(cmd)) && strcmp(cmd, "") && strncmp(cmd, "help",strlen(cmd)) && strncmp(cmd, "cls",strlen(cmd)) && (!extendedCommands || strncmp(cmd, "finger",strlen(cmd))) && strncmp(cmd, "status", strlen(cmd))) { printf("%s: command not allowed in lock mode\n", cmd); printf("Type 'help' for a list of commands.\n"); } if (strncmp(cmd, "unlock",strlen(cmd)) || cmd[0] == '\0') printf("> "); else { strcpy(key, getpass("Enter password: ")); #if defined(OSF1) && defined(EN_SEC) && defined(SETUID) cryptKey = (char *)bigcrypt(key, password); #else /* OSF1 && EN_SEC && SETUID */ cryptKey = (char *)crypt(key, password); #endif /* OSF1 && EN_SEC && SETUID */ if (strcmp(cryptKey, password)) printf("Incorrect password!\n> "); else { chmod(ttynam, ttymode); /* reset tty permissions */ badPass = 0; } } } exit(0); } void usage(char *progName) { #ifdef SETUID printf("Usage: %s [-v] [-p] [-x] [-y] [-t timeout] [Gone message]\n", progName); #else /* SETUID */ printf("Usage: %s [-v] [-x] [-y] [-t timeout] [Gone message]\n", progName); #endif /* SETUID */ exit(1); } void quit() { /* log users out by killing their shell */ kill(getppid(), SIGKILL); exit(0); } void printHeader(int extendedCommands, int printBanner) { int i; if (printBanner) { printf("\n\n\n"); printf(" XXXXX XX X X X XXXXX XXXXX\n"); printf(" X X X X X X X X\n"); printf(" X X X X X X XXXXX XXX\n"); printf(" X X X X X X X X\n"); printf(" XXXXX X XX XXXXXX XXXXX XXXXX\n"); } printf("\n"); printf("Available commands: \n"); for(i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { if (extendedCommands || !commands[i].extended) { printf("\t%-8s : %s\n", commands[i].command, commands[i].help_str); } } printf("\n\tType unlock to unlock the terminal\n\n"); } hi() { struct timeval timval; #ifdef IRIX signal(SIGINT, (void (*)(int))hi); signal(SIGQUIT, (void (*)(int))hi); signal(SIGTSTP, (void (*)(int))hi); signal(SIGALRM, (void (*)(int))quit); signal(SIGHUP, (void (*)(int))quit); #endif /* IRIX */ if (!gettimeofday(&timval,(struct timezone *)NULL)) { printf("\nTerminal locked!\nType 'help' for a list of commands\n\n"); if ( nexttime - timval.tv_sec >= 0 ) { printf("Timeout in %ld minutes and %ld seconds\n", (nexttime - timval.tv_sec)/60, (nexttime - timval.tv_sec)%60); } else { printf("Terminal locked indefinitely.\n"); printf("Terminal has been locked for %ld minutes and %ld seconds.\n", (timval.tv_sec - nexttime)/60, (timval.tv_sec - nexttime)%60); } } return 0; } void print_version_info(void) { printf("Gone version %s by Joe \"Marcus\" Clarke.\n", VERSION); printf("\t* Gone compiled on %s at %s for %s.\n", __DATE__, __TIME__, OSTYPE); #if defined(SETUID) printf("\t* Gone was installed setuid to root.\n"); #endif /* SETUID */ #if defined(OSF1) && (EN_SEC) printf("\t* Gone is OSF/1 Enhanced Security-aware.\n"); #endif /* OSF1 && EN_SEC */ printf("\t* Gone copyright MarcusCom 1998-2003.\n"); }