home *** CD-ROM | disk | FTP | other *** search
- /* CAP - Console Access Protection */
- /* This provides security from phsyical access to your conoles. */
- /* When you run this program, it will clear the screen and prompt */
- /* for a password. After so many failed attempts it will lock the */
- /* tty and not allow them to try anymore. While this program is */
- /* running, they can't abort this program, and they can not switch */
- /* consoles either. The only only way around this is to reboot the */
- /* computer, in which case it will be obvious that someone tried to */
- /* access your server's consoles. This will log the date and time */
- /* the person tried to get access into your console. */
- /* */
- /* Compile: [g]cc -o CAP CAP.c -ltermcap */
- /* If you have shadow passwords compile with -DUSESHADOW. */
- /* To compile in debug (or testing) mode, compile with -DDEBUG. */
- /* */
- /* Shok (Matt Conover), shok@dataforce.net */
-
- #include <pwd.h>
- #include <term.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <syslog.h>
- #include <shadow.h>
- #include <linux/vt.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
-
- #define ERROR -1
- #define SAME 0
- #define LOCKOUT 3 /* How long in minutes to lock out of the console. */
- #define MAXFAIL 3 /* Number of times they can enter an invalid password. */
- /* before being locked out for LOCKOUT minutes. */
-
- /* Used to disable switching consoles. */
- #define LOCKVT(x) if ((ioctl(fd, VT_LOCKSWITCH, 1)) == ERROR) { \
- perror("locking console (/dev/tty/)"); \
- exit(ERROR); \
- }
-
- /* Used to reenable ability to switch consoles. */
- #define UNLOCKVT(x) if ((ioctl(fd, VT_UNLOCKSWITCH, 1)) == ERROR) { \
- perror("locking console (/dev/tty/)"); \
- exit(ERROR); \
- }
-
-
- int fd; /* Console fd. */
-
- char *strip(char *str); /* Used to strip newlines from ctime(). */
- #ifdef DEBUG
- void sighandler(int signum);
- #endif DEBUG
-
- void main()
- {
- int uid;
- int failed = 0; /* Number of failed attempts out of MAXFAIL. */
- int totfailed = 0; /* Number of total failed attempts (not reseted). */
-
- time_t tm;
-
- char curtime[64];
-
- /* Don't change passwd or realpasswd's length. This is the maximum */
- /* password length allow from getpass(). Any smaller can overflow. */
- char *pass, passwd[128], realpasswd[128];
-
- struct passwd *pwd;
- #ifdef USESHADOW
- struct spwd *spwd;
- #endif
-
- if ((fd = open("/dev/tty", O_RDWR)) == ERROR) {
- perror("opening console (/dev/tty)");
- exit(ERROR);
- }
-
- /* Disable signals (so attackers can't abort program). */
-
- #ifndef DEBUG
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
- signal(SIGTERM, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTSTP, SIG_IGN);
- #else
- signal(SIGINT, sighandler);
- signal(SIGTERM, sighandler);
- signal(SIGQUIT, sighandler);
- signal(SIGTSTP, sighandler);
- signal(SIGSEGV, sighandler);
- #endif
-
- LOCKVT(fd); /* Lock the VT. It can no longer switch. */
-
- uid = getuid();
- pwd = getpwuid(uid);
- #ifdef USESHADOW
- if ((spwd = getspnam(pwd->pw_name)) == NULL) {
- perror("getspnam");
- exit(ERROR);
- }
-
- strncpy(realpasswd, spwd->sp_pwdp, sizeof(realpasswd));
- #else
- strncpy(realpasswd, pwd->pw_passwd, sizeof(realpasswd));
- #endif
-
- clr();
- printf("w00w00!\n");
- printf("Console is now locked.\n");
- getchar();
-
- /* Used to log invalid password attempts. */
- openlog("CAP/conprot", LOG_CONS, LOG_AUTHPRIV);
-
- while (1) {
- /* Get the password from the user. */
-
- /* For some reason I get warnings without the typecast (broken
- prototype?). */
- pass = getpass("Enter password: ");
-
-
- /* Encrypt the password from getpass().
- /* Note, we are using realpasswd for our salt. This is to allow a */
- /* salt of any size. This also saving us the trouble of getting */
- /* the salt ourselves. */
- strncpy(passwd, crypt(pass, realpasswd), sizeof(passwd));
-
- passwd[128] = '\0'; /* NULL terminate passwd just to be safe. */
-
- #ifdef DEBUG
- printf("Encrypted password from user: %s\n", passwd);
- printf("The real encrypted password: %s\n", realpasswd);
- #endif
-
- if ((strcmp(passwd, realpasswd)) == SAME) {
- /* Unlock the console, to allow it to switch. */
- UNLOCKVT(fd);
-
- closelog(); /* Close logging. */
-
- clr();
-
- printf("Everything is now restored.\n");
-
- if (totfailed == 0) printf("No one tried to access the console.\n");
- else printf("Total number of failed attempts to unlock console: %d\n",
- totfailed);
-
- exit(0);
- } else {
- failed++, totfailed++; /* Increase number of failed attempts. */
-
- /* Log bad attempts to syslog. */
- tm = time(NULL);
-
- snprintf(curtime, sizeof(curtime), (char *)ctime(&tm));
- strip(curtime); /* Strip new lines out of the time. */
- syslog(LOG_WARNING, "Failed access attempt on: %s", curtime);
-
- printf("Invalid password.\n");
-
- if (failed >= MAXFAIL) {
- printf("Maximum number of failed attempts.\n"
- "Now locking for %d minutes.\n", LOCKOUT);
-
- sleep(LOCKOUT * 60); /* Convert the minutes to seconds. */
- failed = 0; /* Reset the number of failed attempts. */
- }
- }
- }
- }
-
- char *strip(char *str)
- {
- register int i;
-
- for (i = 0; str[i]; i++)
- /* Strip newline out of string. */
- /* We do this because syslog appends the newline itself. */
- if (str[i] == '\n') str[i] = '\0';
-
- return str;
- }
-
- #ifdef DEBUG
- void sighandler(int signum)
- {
- if (signum == 11) printf("Received SIGSEGV.\n");
- printf("\nAborting and unlocking console.\n");
-
- UNLOCKVT(fd);
-
- if (signum == 11) kill(getpid(), 11);
- exit(0);
- }
- #endif
-
- clr()
- {
- char *clear;
- char clbuf[1024], *clbp = clbuf;
-
- if (tgetent(clbuf, getenv("TERM")) == ERROR) {
- perror("tgetent");
- system("clear");
- return;
- }
-
- if ((clear = tgetstr("cl", &clbp)) == NULL) {
- perror("tgetent");
- system("clear");
- return;
- }
-
- if (clear)
- tputs(clear, tgetnum("li"), putchar);
- }
-