/* (c) 1993, 1994, 1995 Julian Assage (proff@suburbia.apana.org.au) all rights reserved. This software may only be used freely by non-profit non-governmental non-comercial organizations. If your not in this category then you MUST purchase a site license from me. Write to the above address for more information. */ #define VERSION "0.98" #ifdef linux # define _USE_BSD # define POSIX_SIGNALS #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef NOTAP # include #endif #include "hutmp.h" extern int chalace (char *); #ifndef INSTALL # define DEBUG #endif #ifndef BOOL # define BOOL int #endif #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #ifndef ULONG # define ULONG unsigned long int #endif #ifndef USHORT # define USHORT unsigned short #endif #define PATH_LEN 256 #define VVSIZE 1024 #ifdef DEBUG # define CONFIG "/etc/hidleho.cnf" # define USER_BASE "/usr/hidleho" # define INVOKENAME "a.out" #else # define CONFIG "/etc/hidleho.cnf" # define USER_BASE "/usr/hidleho" # define INVOKENAME "-hidleho" #endif #define MAXTTYS 64 #define UID "hidleho" #define DEFAULT "default:" #define SLEEPTIME 60 #define FUSER "/bin/fuser" #define DEVS "/dev/" /* must have a trailing solidus */ #define TERMTYPE ".termtype" #define HUSHLOGIN ".hushlogin" #define SECRET ".secret" #define DEFTERM "vt100" #define STTY "/bin/stty" struct stat st; char *argvv[VVSIZE]; int argcc = 0; char *argv0; char username[NAME_LEN]; char host[HOST_LEN] = ""; char rfc931host[HOST_LEN] = "=unknown="; char remotehost[HOST_LEN] = "=unknown="; char utremotehost[HOST_LEN] = "=unknown="; char remotehostlocal[HOST_LEN] = "=unknown="; char rhostip[16] = "255.255.255.255"; ULONG rhost_addr = 0xffffffff; char denyhost[HOST_LEN]; char shell[PATH_LEN]; struct passwd *pw; char sflags[FLAGS_LEN]; char flags[FLAGS_LEN]; struct hutmp ht, *ht2; int hutmp_pos; int hfd; struct termios term; struct winsize ws; char term_cnf[TT_LEN] = "vt100"; char *termp; char sttya[1024] = ""; BOOL f_stty = FALSE; char tty[TTY_LEN]; char *ttys[MAXTTYS]; /* max number of ttys: defs */ int tty_max = 0; /* max entry+1 in ttys */ int tty_ent; float weights[MAXTTYS]; int weights_ent = 0; int tty_speeds[] = {0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200}; int speed; int ttyfd; FILE *ttyout; #ifdef F_TAPON int tap_fdo=-1; #endif #define PIDMAX 128 pid_t pid; pid_t pids[PIDMAX]; int pid_x = 0; pid_t child; pid_t wpid; int wstatus = 0; uid_t ouid; uid_t oeuid; uid_t uid; uid_t tty_uid; char uid_name[NAME_LEN] = "hidleho"; char tty_uid_name[NAME_LEN] = "root"; gid_t *gids; char **gnames; int gr_x = 0;; struct lim { int resource; char *key; int val; }; struct lim limits[] = { {RLIMIT_CPU, "cpu", -1}, {RLIMIT_FSIZE, "fsize", -1}, {RLIMIT_DATA, "data", -1}, {RLIMIT_STACK, "stack", -1}, {RLIMIT_CORE, "core", -1}, {RLIMIT_RSS, "rss", -1}, #ifdef RLIMIT_MEMLOCK {RLIMIT_MEMLOCK, "memlock", -1}, #endif {RLIMIT_NPROC, "nproc", -1}, {RLIMIT_NOFILE, "nofile", -1}, {0, NULL, 0} }; char cwd[PATH_LEN]; char user_base[PATH_LEN] = USER_BASE; char group_base[PATH_LEN] = USER_BASE; char DeniedMsg[PATH_LEN] = "/etc/hidlho.denied"; char bin_sh[PATH_LEN] = "/bin/sh"; char bigsys[PATH_LEN * 4] = ""; char fname[PATH_LEN] = ""; #ifdef F_TAPON char LDir[PATH_LEN] = "/usr/log/packages"; #endif BOOL f_gotsighup = FALSE; BOOL f_gotsigchld = FALSE; BOOL f_onBorrow = FALSE; BOOL f_freetty = FALSE; BOOL f_onconftty = FALSE; BOOL f_weighted = FALSE; BOOL f_deny = FALSE; BOOL f_exclude = FALSE; BOOL f_remotehostlocal = FALSE; BOOL f_hushlogin = FALSE; BOOL f_chalaced = FALSE; int sleeptime = SLEEPTIME; struct utimbuf ut; secs idle_a; secs idle_m; time_t starttime; time_t currenttime; time_t borrowstart = 0; time_t borrowend = 0; time_t lastlogout = 0; time_t lastlogin = 0; secs timeleft = 0; secs timeleftatlogin = 0; secs totaltime = 0; secs totaltimesaved = 0; long int numlogins = 0; secs borrow_grace = 2 * 60; secs intimeout = 10 * 60; secs outtimeout = 10 * 60; secs timepercall = 3600; secs timelim = 0 * 60; secs timeper = 0 * 60; secs excludetime = 0 * 60; secs warningst[] = {10 * 60, 2 * 60, 1 * 60, 0, 0, 0, 0, 0, 0, 0, 0}; secs *wt = &warningst[0]; int warn_t_ent = 0; secs warningsi[] = {3 * 60, 2 * 60, 1 * 60, 0, 0, 0, 0, 0, 0, 0, 0}; secs *wi = &warningsi[0]; int warn_i_ent = 0; BOOL f_Warn = TRUE; BOOL f_Inform = TRUE; BOOL f_Kill = TRUE; BOOL f_AskTerm = TRUE; BOOL f_Borrow = TRUE; BOOL f_TimeUser = TRUE; BOOL f_Disable = FALSE; BOOL f_ConfTtyOnly = TRUE; BOOL f_StrictIdle = FALSE; BOOL f_Exclusive = FALSE; BOOL f_Unlimited = FALSE; BOOL f_Negative = FALSE; BOOL f_Debug = FALSE; #ifdef F_TAPON BOOL f_Log = FALSE; #endif void *Smalloc (); void Super () { if (!getuid () && geteuid ()) setreuid (geteuid (), getuid ()); setuid (0); } void Be (uid_t uid) { Super (); setreuid (0, uid); } void fatal (int ret) { Super (); setuid (ouid); exit (ret); } void fatal_ (int ret) { Super (); setuid (ouid); _exit (ret); } char * trimS (str) char *str; { char *np; if ((str == NULL) || !*str) return NULL; np = Smalloc (strlen (str) + 1); strcpy (np, str); return np; } int ttyf (char *fmt,...) { va_list argp; struct stat ttyst; struct utimbuf tty_ut; pid_t suid; pid_t seuid; suid = getuid (); seuid = geteuid (); if (fstat (ttyfd, &ttyst) < 0) return -1; if (!(ttyst.st_mode & 022)) return 0; va_start (argp, fmt); vfprintf (ttyout, fmt, argp); va_end (argp); fflush (ttyout); tty_ut.modtime = ttyst.st_mtime; tty_ut.actime = ttyst.st_atime; Super (); utime (tty, &tty_ut); setreuid (suid, seuid); return 0; } char * ltime (time_t *tim) { char *p; p=ctime(tim); p[strlen(p)-1]='\0'; return p; } int ttymsg (char *fmt,...) { va_list argp; struct stat ttyst; struct utimbuf tty_ut; pid_t suid; pid_t seuid; if (f_hushlogin) return 0; suid = getuid (); seuid = geteuid (); if (fstat (ttyfd, &ttyst) < 0) return -1; (void) time (¤ttime); fprintf (ttyout, "\7\n\r\n\rMessage from hidleho@%s on \ %s at %s\n\r", host, strrchr (tty, '/') + 1, ltime(¤ttime)); va_start (argp, fmt); vfprintf (ttyout, fmt, argp); va_end (argp); fprintf (ttyout, "\n\rEOF\n\r"); tty_ut.modtime = ttyst.st_mtime; tty_ut.actime = ttyst.st_atime; Super (); utime (tty, &tty_ut); setreuid (suid, seuid); return 0; } void err (char *fmt,...) { va_list argp; register int x, n; register char c, pc; char *sbuf; char sbuf2[1024]; char *serr = strerror (errno); if (fmt == NULL) return; sbuf = (char *) Smalloc (strlen (serr) + strlen (fmt) + 1); for (pc = n = x = 0; (c = fmt[n]); n++, x++) { if (pc == '%') { if (c == 'm') { if (serr == NULL) continue; sbuf[--x] = 0; strcat (sbuf, serr); x = strlen (sbuf) - 1; pc = c; continue; } else if (c == '%') { pc = 0; sbuf[x] = c; continue; } } sbuf[x] = c; pc = c; } va_start (argp, fmt); vsprintf (sbuf2, sbuf, argp); va_end (argp); syslog (LOG_ERR, "%s", sbuf2); ttyf ("\n\rhidleho error: %s\n\r", sbuf2); } char from_cntl (char c) { if (c == 0x7f) return 0x3f; return c + 0x40; } void * Smalloc (int bytes) { void *p; while ((p = (void *) malloc (bytes)) == NULL) { write (ttyfd, "\n\rSmalloc, sleeping 10 seconds\n\r", 31); sleep (20); continue; } return p; } int argvvcc (char *str) { int n; int f_esc = 0; BOOL f_dquote = FALSE; BOOL f_squote = FALSE; char *p; char *endp; char t[1024]; char *tp; char c; char pc; int slen; for (n = 1; (n < VVSIZE) && (n < argcc); n++) if (argvv[argcc] != NULL) free (argvv[argcc]); argvv[0] = str; argvv[1] = NULL; argcc = 1; if (!str || !*str) return 0; slen = strlen (str); for (c = ' ', tp = t, p = str, endp = p + slen + 1; p < endp; p++) { pc = c; c = *p; if (f_esc) f_esc--; switch (c) { case '\\': if (f_esc) f_esc = 0; else { f_esc = 2; continue; } break; case '"': if (f_esc || f_squote) break; f_dquote = !f_dquote; continue; case '\'': if (f_esc || f_dquote) break; f_squote = !f_squote; continue; case 'n': if (f_esc) c = '\n'; break; case 'r': if (f_esc) c = '\r'; break; case 't': if (f_esc) c = '\t'; break; case '\n': case ' ': case '\t': if (f_esc || f_squote || f_dquote) break; if (isspace (pc)) continue; case '\0': *tp = '\0'; tp = t; if (argcc + 1 >= VVSIZE) { err ("argument limit [%d] exceeded %s", argcc, str); argvv[VVSIZE] = NULL; return argcc; } argvv[argcc++] = trimS (t); if (c) continue; argvv[argcc] = NULL; return argcc; default: break; } *tp = c; if ((++tp - t) >= sizeof (t)) { --tp; *tp = 0; err ("argument [%s] too long", t); return argcc; } } return argcc; } void printfile (char *f) { int fdi; int cc; char buf[256]; if ((fdi = open (f, O_RDONLY)) < 0) { err ("%s on %s couldn't open %s: %m", username, tty, f); return; } while ((cc = read (fdi, buf, sizeof (buf))) > 0) write (ttyfd, buf, cc); close (fdi); } void handalrm () { ttymsg ("Disconnected due to inactivity."); sleep (1); fatal (1); } BOOL freetty () { static struct stat ttyst; int x; for (x = 0; x < tty_max; x++) { if (stat (ttys[x], &ttyst)) continue; if (ttyst.st_uid != tty_uid) continue; return TRUE; } return FALSE; } BOOL ingroup (grp) char *grp; { int n; int t; t = strlen (grp); if (grp[t - 1] != '+') return FALSE; for (n = 0; n < gr_x; n++) if (!strncmp (grp, gnames[n], t - 1)) return TRUE; return FALSE; } char * itod (secs id) { char tmp[40]; char *rv = Smalloc (20);/* whats a few bytes between friends? */ *rv = 0; if (id < 0) strcpy (rv, "-"); id = labs (id); if (id > 86400) { sprintf (tmp, "%ldd", id / (86400)); strcat (rv, tmp); if (!(id % 86400)) return rv; } if ((id %= 86400) / 3600) { sprintf (tmp, "%ldh", id / 3600); strcat (rv, tmp); if (!(id % 3600)) return rv; } if ((id %= 3600) / 60) { sprintf (tmp, "%ldm", id / 60); strcat (rv, tmp); if (!(id % 60)) return rv; } sprintf (tmp, "%lds", id % 60); strcat (rv, tmp); return rv; } secs dtoi (char *s, secs def) { long rv = 0; long nv; int ns, nd; int s_len = strlen (s); char c = 0; char digits[s_len]; if (s[0] == '*') return def; for (nd = ns = 0; ns <= s_len; ns++) { c = s[ns]; if (c>='0' && c<='9') { digits[nd++] = s[ns]; continue; } digits[nd] = '\0'; if (!digits[0] || (sscanf (digits, "%ld", &nv) != 1)) return def; switch (c) { case 'w': nv *= 604800; break; case 'd': nv *= 86400; break; case 'h': nv *= 3600; break; case 'm': case '\0': nv *= 60; break; case 's': break; default: err ("%s on %s, invalid time specifier in \"%s\"", username, tty, s); } rv += nv; if (!c || !s[ns + 1]) break; nd = 0; } return rv; } int Cscanf (char *s, char *keyword, int limit, char *fmt,...) { va_list argp; int rv; char s1[32] = ""; char s2[2] = ""; char *p; if (!s || !keyword) return 0; if (sscanf (s, "%31s %1s", s1, s2) != 2) return 0; if (strcasecmp (s1, keyword)) return 0; p = strpbrk (s, " \t"); va_start (argp, fmt); rv = vsscanf (p, fmt, argp); va_end (argp); if (rv != limit) { err ("%s on %s error in %s invalid number/type of \ arguments \"%s = %s\"", username, tty, CONFIG, keyword, s); return 0; } return rv; } void checklocaldomain () { int n1, n2; char *p; n1 = strlen (host) - 1; n2 = strlen (remotehost) - 1; for (; n1 && n2 && (host[n1] == remotehost[n2]); n1--, n2--); if (!(p = strchr (remotehost + n2, '.'))) return; strncpy (remotehostlocal, remotehost, p - remotehost); f_remotehostlocal++; } int hutmp_open () { int fd; if ((fd = open (PATH_HUTMP, O_RDWR | O_CREAT, 0644)) < 0) { err ("couldn't open %s: %m"); fatal (1); } flock (fd, LOCK_EX); return fd; } void hutmp_close (int fd) { close (fd); flock (fd, LOCK_UN); } void hutmp_update () { hfd = hutmp_open (); lseek (hfd, hutmp_pos, SEEK_SET); write (hfd, &ht, sizeof (ht)); hutmp_close (hfd); } void do_utmp () { struct in_addr in; struct hostent *hp; struct utmp ut; int fd; if ((fd = open (_PATH_UTMP, O_RDONLY)) < 0) { err ("%s on %s unable to open %s : %m", username, tty, _PATH_UTMP); return; } while (read (fd, &ut, sizeof (ut)) > 0) { if ((ut.ut_type == DEAD_PROCESS) || strncmp (ut.ut_line, strchr (tty + 1, '/') + 1, sizeof (ut.ut_line))) continue; strncpy (utremotehost, ut.ut_host, sizeof (utremotehost)); rhost_addr = (ULONG) ut.ut_addr; if (ut.ut_addr && (ut.ut_addr != INADDR_NONE)) { in.s_addr = ut.ut_addr; hp = gethostbyaddr ((char *) &in, sizeof (in), AF_INET); if (hp) { strcpy (remotehost, hp->h_name); strcpy (rhostip, inet_ntoa (in)); checklocaldomain (); } else { char *p; in.s_addr = ut.ut_addr; p = inet_ntoa (in); strcpy (rhostip, p); strcpy (remotehost, p); } close (fd); return; } break; } gethostname (remotehost, sizeof (remotehost)); close (fd); return; } void deny () { ttymsg ("\ You are not permitted to login from %s.", denyhost); syslog (LOG_INFO, "%s on %s from %s LOGIN DENIED (%s)", username, tty, rfc931host, denyhost); fatal (1); } void config () { FILE *fh; int line_no; int n; char line[1024]; char arg1[32]; char *linep; char temp[1024]; char *tempp; char sshell[PATH_LEN]; BOOL f_gotuser = FALSE; char s_tt[20] = ""; char s_it[20] = ""; char s_ot[20] = ""; char s_tl[20] = ""; char s_tp[20] = ""; char s_et[20] = ""; for (n = 0; n < MAXTTYS; weights[n++] = 1); Be (uid); if ((fh = fopen (CONFIG, "r")) == NULL) { err ("couldn't open %s: %m", CONFIG); fatal (1); } Be (ouid); for (line_no = 1; fgets (line, sizeof (line), fh) != NULL; line_no++) { if (!line[0] || (line[0] == '#')) continue; if (sscanf (line, "%31s", arg1) != 1) continue; if (Cscanf (line, "Uid", 1, "%16s", uid_name)) continue; if (Cscanf (line, "TtyUid", 1, "%16s", tty_uid_name)) continue; if (Cscanf (line, "Term", 1, "%16s", term_cnf)) continue; if (Cscanf (line, "UserBase", 1, "%127s", user_base)) continue; if (Cscanf (line, "GroupBase", 1, "%127s", group_base)) continue; if (Cscanf (line, "DeniedMsg", 1, "%127s", DeniedMsg)) continue; if (Cscanf (line, "LDir", 1, "%127s", LDir)) continue; if (Cscanf (line, "BorrowGrace", 1, "%s", temp)) { borrow_grace = dtoi (temp, borrow_grace); continue; } if (Cscanf (line, "weights", 1, "%f", &weights[0])) { linep = strpbrk (line, " \t") + 1; while (*linep) { for (; *linep && isspace (*linep); linep++); if (!*linep) break; for (tempp = temp; *linep && !isspace (*linep); linep++) *(tempp++) = *linep; *tempp = '\0'; weights[weights_ent] = (float) atof (temp); if (++weights_ent > MAXTTYS) { err ("%s on %s config err, MAXTTYS (%d)\ exceeded \"%s\"", username, tty, MAXTTYS, line); n--; break; } } continue; } if (Cscanf (line, "ttys", 1, "%s", temp)) { linep = strpbrk (line, " \t") + 1; while (*linep) { for (; *linep && isspace (*linep); linep++); if (!*linep) break; for (tempp = temp; *linep && !isspace (*linep); linep++) *(tempp++) = *linep; *tempp = '\0'; ttys[tty_max] = Smalloc (strlen (temp) + strlen (DEVS) + 1); strcpy (ttys[tty_max], DEVS); strcat (ttys[tty_max], temp); if (++tty_max > MAXTTYS) { err ("%s on %s config err, MAXTTYS (%d)\ exceeded \"%s\"", username, tty, MAXTTYS, line); tty_max--; break; } } continue; } if (Cscanf (line, "warn_t", 1, "%ld", &warningst[0])) { linep = strpbrk (line, " \t") + 1; while (*linep) { for (; *linep && isspace (*linep); linep++); if (!*linep) break; for (tempp = temp; *linep && !isspace (*linep); linep++) *(tempp++) = *linep; *tempp = '\0'; warningst[warn_t_ent] = dtoi (temp, 0); if (++warn_t_ent > sizeof (warningst)) { err ("%s on %s config err, warningst[] (%d)\ exceeded \"%s\"", username, tty, sizeof (warningst), line); n--; break; } } continue; } if (Cscanf (line, "warn_i", 1, "%ld", &warningsi[0])) { linep = strpbrk (line, " \t") + 1; while (*linep) { for (; *linep && isspace (*linep); linep++); if (!*linep) break; for (tempp = temp; *linep && !isspace (*linep); linep++) *(tempp++) = *linep; *tempp = '\0'; warningsi[warn_i_ent] = dtoi (temp, 0); if (++warn_i_ent > sizeof (warningsi)) { err ("%s on %s config err, warningsi[] (%d)\ exceeded \"%s\"", username, tty, sizeof (warningsi), line); n--; break; } } continue; } if ((f_gotuser = !strcmp (arg1, username)) || !strcmp (arg1, DEFAULT) || ingroup (arg1)) { int n; int flen; if (sscanf (line, "%*s %19s %19s %19s %19s %19s %19s \ %19s %254s", s_tt, s_it, s_ot, s_tl, s_tp, s_et, sflags, sshell) != 8) syslog (LOG_ERR, "invalid number of arguments:\ %s", line); timepercall = dtoi (s_tt, timepercall); intimeout = dtoi (s_it, intimeout); outtimeout = dtoi (s_ot, outtimeout); timelim = dtoi (s_tl, timelim); timeper = dtoi (s_tp, timeper); excludetime = dtoi (s_et, excludetime); if (strcmp (sshell, "*")) strcpy (shell, sshell); flen = strlen (sflags); for (n = 0; n < flen; n++) { switch (sflags[n]) { case '*': break; case 'i': f_Inform = FALSE; break; case 'I': f_Inform = TRUE; break; case 'w': f_Warn = FALSE; break; case 'W': f_Warn = TRUE; break; case 'k': f_Kill = FALSE; break; case 'K': f_Kill = TRUE; break; case 'A': f_AskTerm = TRUE; break; case 'a': f_AskTerm = FALSE; break; case 'B': f_Borrow = TRUE; break; case 'b': f_Borrow = FALSE; break; case 'C': f_ConfTtyOnly = TRUE; break; case 'c': f_ConfTtyOnly = FALSE; break; case '-': f_Disable = TRUE; break; case '+': f_Disable = FALSE; break; case 'T': f_TimeUser = TRUE; break; case 't': f_TimeUser = FALSE; break; case 'E': f_Exclusive = TRUE; break; case 'e': f_Exclusive = FALSE; break; case 'N': f_Negative = TRUE; break; case 'n': f_Negative = FALSE; break; case 'U': f_Unlimited = TRUE; break; case 'u': f_Unlimited = FALSE; break; case 'D': f_Debug = TRUE; break; case 'd': f_Debug = FALSE; break; #ifdef F_TAPON case 'L': f_Log = TRUE; break; case 'l': f_Log = FALSE; break; #endif default: err ("WARNING: \ invalid flag '%c' in %s on line %d:\ -> %s", sflags[n], CONFIG, line_no, line); } } if (f_gotuser) break; } } fclose (fh); } void calcflags () { char *flags_p = flags; int *fla[] = {&f_Inform, &f_Warn, &f_Kill, &f_AskTerm, &f_Borrow, &f_ConfTtyOnly, &f_TimeUser, &f_Disable, &f_Exclusive, &f_Negative, &f_Unlimited, &f_Debug, &f_Log, (int *) 0}; char flac[] = {'I', 'W', 'K', 'A', 'B', 'C', 'T', '-', 'E', 'N', 'U', 'D', 'L'}; int n; for (n = 0; fla[n] != NULL; n++) if (*fla[n] == TRUE) *(flags_p++) = flac[n]; *flags_p = '\0'; } void alrmhand () { static int alarm_c = 0; #ifdef POSIX_SIGNALS signal (SIGALRM, alrmhand); #endif alarm_c++; } void huphand () { #ifdef POSIX_SIGNALS signal (SIGHUP, huphand); #endif f_gotsighup++; } void chldhand () { #ifdef POSIX_SIGNALS signal (SIGCHLD, chldhand); #endif f_gotsigchld++; } void segvhand () { err ("Killed by a SIGSEGV!"); fatal (1); } BOOL isconftty (t) char *t; { for (tty_ent = 0; tty_ent < tty_max; tty_ent++) if (!strcmp (t, ttys[tty_ent])) return TRUE; return FALSE; } #ifdef FUSER void killpids (sig) int sig; { int n; for (n = 0; n < pid_x; n++) if (pids[n] != pid) kill (pids[n], sig); } #endif void dogroups () { int n; char numbuf[8]; struct group *gr_p; if ((gr_x = getgroups (0, gids)) == -1) { err ("There was a problem reading groups from /etc/group: %m"); fatal (1); } gids = (gid_t *) Smalloc (sizeof (gid_t) * (int) (gr_x + 1)); gnames = (char **) Smalloc (sizeof (char *) * (int) (gr_x + 1)); if (getgroups (gr_x, gids) == -1) { err ("There was a problem reading groups from /etc/group: %m"); fatal (1); } for (n = 0; n < gr_x; n++) { gr_p = getgrgid (gids[n]); if (!gr_p) { sprintf (numbuf, "%d", gids[n]); gnames[n] = (char *) Smalloc (strlen (numbuf) + 1); strcpy (gnames[n], numbuf); continue; } gnames[n] = (char *) Smalloc (strlen (gr_p->gr_name) + 1); strcpy (gnames[n], gr_p->gr_name); } } void user_conf_write (BOOL f_group) { FILE *fout, *fin; time(¤ttime); if ((fout = fopen ("lastlogout", "w")) != NULL) { flock (fileno (fout), LOCK_EX); fprintf (fout, "%s\t%s\t%lu\t%s\n", username, tty, currenttime, ltime (¤ttime)); fflush (fout); flock (fileno (fout), LOCK_UN); fclose (fout); } if ((fin = fopen ("totaltime", "r")) != NULL) { flock (fileno (fin), LOCK_EX); if (fscanf (fin, "%ld", &totaltimesaved) != 1) totaltimesaved = 0; flock (fileno (fin), LOCK_UN); fclose (fin); } else totaltimesaved = 0; if ((fout = fopen ("totaltime", "w")) != NULL) { secs t = totaltimesaved + (currenttime - starttime); flock (fileno (fout), LOCK_EX); fprintf (fout, "%ld\t%s\n", t, itod (t)); fflush (fout); flock (fileno (fout), LOCK_UN); fclose (fout); } if (timelim && (!f_ConfTtyOnly || f_onconftty) && !f_group) { secs timesaved; if ((fin = fdopen (open("timeleft", O_RDWR|O_CREAT, 0666), "r+")) != NULL) { flock (fileno (fin), LOCK_EX); if (fscanf (fin, "%ld", ×aved) != 1) timesaved = timelim; rewind(fin); if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s timesaved (w) = %d", username, tty, rfc931host, timesaved); timesaved -= (currenttime - starttime) / (f_weighted ? weights[tty_ent] : 1); if (!f_Unlimited && ((timesaved + timelim) < 0)) timesaved = -timelim; if (!f_Negative && (timesaved < 0)) timesaved = 0; fprintf (fin, "%ld\t%s\n", timesaved, itod (timesaved)); fflush (fin); if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s timesaved#2 (w) = %ld", username, tty, rfc931host, timesaved); flock (fileno (fin), LOCK_UN); fclose (fin); } } } void killup (BOOL forced) { pid_t cpid; int n; closelog (); Be (uid); time (¤ttime); sprintf (fname, "%s/%s", group_base, DEFAULT); if (!chdir (fname)) user_conf_write (TRUE); for (n = 0; n < gr_x; n++) { sprintf (fname, "%s/%s+", group_base, gnames[n]); if (!chdir (fname)) user_conf_write (TRUE); } sprintf (fname, "%s/%s", user_base, username); if (!chdir (fname)) user_conf_write (FALSE); ht.ht_type = HT_EMPTY; hutmp_update (); if (fork ()) { fatal_ (0); /* free init */ } tcgetattr (0, &term); term.c_line = B0; tcsetattr (0, TCSANOW, &term); Super (); #ifdef F_TAPON fcntl(tap_fdo, F_TAPOFF, 1); #endif if (f_Kill && ouid) { if (!(cpid = fork ())) { setuid (ouid); kill (-1, SIGHUP); _exit (0); } while (cpid > 0 && wait (&wstatus) != cpid); } else { #ifdef FUSER static int p[2]; FILE *pf; pipe ((void *) &p); if (!fork ()) { close (p[0]); dup2 (p[1], 1); dup2 (p[1], 2); execl (FUSER, FUSER, tty, (char *) 0); syslog (LOG_ERR, "%s: %m:", FUSER); _exit (1); } close (p[1]); pf = fdopen (p[0], "r"); fscanf (pf, "%*s"); for (pid_x = 0; pid_x < PIDMAX && (fscanf (pf, "%d", &pids[pid_x]) == 1); pid_x++); fclose (pf); #endif killpg (child, SIGHUP); kill (child, SIGHUP); #ifdef FUSER killpids (SIGHUP); #endif } vhangup (); for (n = 0; n < 256; close (n++)); sleep (15); if (f_Kill && ouid) { if (!(cpid = fork ())) { setuid (ouid); kill (-1, SIGKILL); _exit (0); } while (cpid > 0 && wait (&wstatus) != cpid); } else { #ifdef FUSER killpids (SIGKILL); #endif killpg (child, SIGKILL); kill (child, SIGKILL); } fatal (0); } void retire_idleness () { if (f_Warn) ttymsg ("\ * DISCONNECT: Your terminal has been idle for %s.", itod ((idle_a > idle_m) ? idle_m : idle_a)); sleep (2); syslog (LOG_INFO, "%s on %s from %s killed for idleness", username, tty, rfc931host); killup (TRUE); } void retire_oldage () { if (f_Warn) { char s[512]; char st[256]; sprintf (s, "\n\r\ * DISCONNECT: Your terminal has been on line for %s.\n\r\ * DISCONNECT: To upgrade your account, login as `credit'.", itod (currenttime - starttime)); if (excludetime) { sprintf (st, "\n\r\ * DISCONNECT: You may not logon for another %s.", itod (excludetime)); strcat (s, st); } ttymsg (s); } sleep (2); syslog (LOG_INFO, "%s on %s from %s timelimit%s", username, tty, rfc931host, (borrowstart || borrowend) ? " (borrow)" : ""); killup (TRUE); } BOOL borrow () { if (f_freetty) { if (!borrowstart && f_Warn) { ttymsg ("\n\ * WARNING: You are now on borrowed time, if all lines become allocated\n\r\ * WARNING: during this session, you will have %ld:%02.2d minutes to logoff.", borrow_grace / 60, borrow_grace % 60); } borrowstart = currenttime; borrowend = 0; ht.ht_status |= HT_BORROW; hutmp_update (); return TRUE; } if (!borrowend) { borrowend = currenttime; borrowstart = 0; } if (currenttime < (borrowend + borrow_grace)) { if (f_Warn) { ttymsg ("\ * WARNING: All lines are full, you have only %ld:%02.2d minutes left\n\r\ * WARNING: to forced logout, unless someone else logs out before then.", (borrow_grace + borrowend - currenttime) / 60, (borrow_grace + borrowend - currenttime) % 60); } ht.ht_status |= HT_BORROW_DIE; hutmp_update (); return TRUE; } retire_oldage (); return 0; /* kill a warning */ } void warning_disconnect () { if (f_Warn) { if (f_Borrow && f_onconftty && f_freetty) { ttymsg ("\ * WARNING: borrowed time mode will activate in %ld:%-02.2d minutes.", (totaltime - currenttime + starttime) / 60, (totaltime - currenttime + starttime) % 60); } else { ttymsg ("\ * WARNING: Your terminal will be disconnected in %ld:%-02.2d minutes.", (totaltime - currenttime + starttime) / 60, (totaltime - currenttime + starttime) % 60); } } sleeptime = totaltime + starttime - currenttime; if (sleeptime > 60) sleeptime = 60; else if (sleeptime < 1) retire_oldage (); } void warning_idleness () { if (f_Warn) { ttymsg ("\ * WARNING: Your terminal appears to have been idle for %ld:%-02.2d minutes.\n\r\ * WARNING: Rectify this, or you will be disconnected in %ld:%-02.2d minutes.", (idle_a > idle_m) ? idle_a / 60 : idle_m / 60, (idle_a > idle_m) ? idle_a % 60 : idle_m % 60, (idle_a > idle_m) ? (outtimeout - idle_a) / 60 : (intimeout - idle_m) / 60, (idle_a > idle_m) ? (outtimeout - idle_a) % 60 : (intimeout - idle_m) % 60); } sleeptime = (idle_a < idle_m) ? outtimeout - idle_m : intimeout - idle_a; if (sleeptime < 1) retire_idleness (); else if (sleeptime > 60) sleeptime = 60; } void addscript (char *st, char *fn) { char sys[PATH_LEN]; char tcwd[PATH_LEN]; if (access (fn, R_OK) == 0) { getcwd (tcwd, sizeof (tcwd)); sprintf (sys, ". \"%s/%s\";", tcwd, fn); strcat (st, sys); } } void permit (char *fname) { FILE *fin; if ((fin = fopen (fname, "r")) != NULL) { char buf[HOST_LEN]; char *p = buf; while (fscanf (fin, "%128s", p) == 1) { if (p[0] == '-') p++; if (!fnmatch (p, remotehost, FNM_CASEFOLD) || (f_remotehostlocal && !fnmatch (p, remotehostlocal, FNM_CASEFOLD)) || !fnmatch (p, rhostip, 0) || !fnmatch (p, tty, 0) || !fnmatch (p, rfc931host, FNM_CASEFOLD) || !fnmatch (p, strchr (tty + 1, '/') + 1, 0)) if ((f_deny = (buf[0] == '-'))) strcpy (denyhost, p); p = buf; } fclose (fin); } } void setlimits() { int n; struct rlimit ru; for (n=0; limits[n].key; n++) { int t=limits[n].val; if (t==-1) continue; ru.rlim_cur=ru.rlim_max=t? t: RLIM_INFINITY; setrlimit(limits[n].resource, &ru); } } void getlimits(FILE *in) { int n; char line[64]; while (fgets(line, sizeof(line), in)) { for (n=0; limits[n].key; n++) if (Cscanf (line, limits[n].key, 1, "%d", &(limits[n].val))) goto cont; err("invalid limit line: `%s'", line); cont: } } void user_conf (BOOL f_group) { FILE *fin, *fout; Super (); Be (uid); time (¤ttime); if (!f_group) { if ((fin = fopen ("lastlogin", "r")) != NULL) { flock (fileno (fin), LOCK_EX); if ((fscanf (fin, "%*s %*s %lu", &lastlogin) < 1) || (lastlogin > currenttime)) lastlogin = 0; flock (fileno (fin), LOCK_UN); } else lastlogin = 0; if ((fin = fopen ("lastlogout", "r")) != NULL) { flock (fileno (fin), LOCK_EX); if ((fscanf (fin, "%*s %*s %lu", &lastlogout) < 1) || (lastlogout > currenttime) || (lastlogout < lastlogin)) lastlogout = currenttime - excludetime - 1; flock (fileno (fin), LOCK_UN); fclose (fin); } else lastlogout = currenttime - excludetime - 1; if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s lastlogout = %lu = %s", username, tty, rfc931host, lastlogout, ltime(&lastlogout)); if ((fin = fopen ("totaltime", "r")) != NULL) { flock (fileno (fin), LOCK_EX); if (fscanf (fin, "%ld", &totaltimesaved) != 1) totaltimesaved = 0; flock (fileno (fin), LOCK_UN); fclose (fin); } else totaltimesaved = 0; if (timelim) { BOOL f_open_t = FALSE; if ((fin = fdopen (open("timeleft", O_RDWR|O_CREAT, 0666), "r+")) != NULL) { f_open_t=TRUE; flock (fileno (fin), LOCK_EX); if (fscanf (fin, "%ld", &timeleft) != 1) timeleft = timelim; } else timeleft = timelim; if (!lastlogin) timeleft = timelim; timeleftatlogin = timeleft; if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s timeleft#1 = %ld", username, tty, rfc931host, timeleft); if (!f_Unlimited && ((timeleft + timelim) < 0)) timeleft = -timelim; if (!f_Negative && (timeleft < 0)) timeleft = 0; if (timeper) timeleft += ((float)timelim * (currenttime - lastlogin)) / (float)timeper; if (timeleft > timelim) timeleft = timelim; if (f_open_t) { rewind(fin); fprintf (fin, "%ld\t%s\n", timeleft, itod (timeleft)); fflush(fin); flock(fileno(fin), LOCK_UN); fclose(fin); } if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s timeleft#2 = %ld", username, tty, rfc931host, timeleft); } } if ((fin = fopen ("numlogins", "r")) != NULL) { flock (fileno (fin), LOCK_EX); if (fscanf (fin, "%ld", &numlogins) != 1) numlogins = 0; flock (fileno (fin), LOCK_UN); fclose (fin); } else numlogins = 0; if ((fout = fopen ("numlogins", "w")) != NULL) { flock (fileno (fout), LOCK_EX); fprintf (fout, "%ld\n", ++numlogins); fflush (fout); flock (fileno (fout), LOCK_UN); fclose (fout); } if ((fout = fopen ("lastlogin", "w")) != NULL) { flock (fileno (fout), LOCK_EX); fprintf (fout, "%s\t%s\t%lu\t%s\n", username, tty, currenttime, ltime (¤ttime)); fflush (fout); flock (fileno (fout), LOCK_UN); fclose (fout); } if ((fin = fopen ("nologin", "r")) != NULL) { fclose (fin); printfile ("nologin"); syslog (LOG_INFO, "%s on %s from %s [%s] LOGIN DISABLED", username, tty, rfc931host, flags); sleep (2); fatal (0); } if ((fin = fopen ("limits", "r")) != NULL) { getlimits(fin); fclose(fin); } permit ("permitdeny"); addscript (bigsys, "environ"); addscript (bigsys, "login"); } void call_chalace (char *fname) { int res; res = chalace (fname); switch (res) { case FALSE: syslog (LOG_INFO, "CHALACE_INVALID %s on %s from %s [%s]", username, tty, rfc931host, flags); fatal (1); case -TRUE: syslog (LOG_INFO, "CHALACE_TIMEOUT %s on %s from %s [%s]", username, tty, rfc931host, flags); fatal (1); } syslog (LOG_INFO, "CHALACE_VALID %s on %s from %s [%s]", username, tty, rfc931host, flags); f_chalaced = TRUE; } int main (int argc, char **argv) { struct hostent *hp; int n; char *p; if (getenv("HFINT")) { char c; f_Debug=1; printf("hidleho: debug mode on (press return)"); fflush(stdout); while (read(0, &c, 1)==1 && c!='\n'); } signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); signal (SIGSEGV, segvhand); umask (022); unsetenv ("TZ"); tzset (); bzero (&ht, sizeof (ht)); ht.ht_time = time (&starttime); openlog ("hidleho", LOG_NDELAY | LOG_PID, LOG_AUTH); strncpy (tty, (char *) (p=ttyname (0))? p: "NOTTY", sizeof (tty)); if (p && (ttyfd = open (tty, O_NOCTTY | O_WRONLY | O_NONBLOCK)) < 0) { syslog (LOG_INFO, "COULDN'T-OPEN-TTY %s: %m", tty); fatal (1); } if (!p) ttyfd=1; if ((ttyout = fdopen (ttyfd, "w")) == NULL) { syslog (LOG_INFO, "COULDN'T-OPEN-TTY %s: %m", tty); fatal (1); } ht.ht_pid = pid = getpid (); ht.ht_uid = ouid = getuid (); ht.ht_gid = getgid (); oeuid = geteuid (); setgid (getgid ()); if ((pw = getpwuid (ouid)) == NULL) { err ("uid %d - go away, you don't exist!", ouid); fatal (1); } strncpy (ht.ht_user, getlogin()? getlogin(): ":INVALID", sizeof (ht.ht_user)); strcpy (username, pw->pw_name); if ((pw = getpwnam (uid_name)) == NULL) { err ("%s couldn't find uid %s", username, uid_name); fatal (1); } uid = pw->pw_uid; if ((pw = getpwnam (tty_uid_name)) == NULL) { err ("%s couldn't locate uid %s", username, tty_uid_name); fatal (1); } tty_uid = pw->pw_uid; argv0 = argv[0]; gethostname (host, sizeof (host)); if ((hp = gethostbyname (host))) strcpy (host, hp->h_name); getcwd (cwd, sizeof (cwd)); Be (uid); if (isatty (0)) { strncpy (ht.ht_tty, tty, sizeof (ht.ht_tty)); do_utmp (); } if (!(termp = (char *) getenv ("TERM"))) termp=""; if ((p=getenv("RFC931")) && strlen(p)>2 ) strncpy(rfc931host, p, sizeof(rfc931host)); else sprintf(rfc931host, p, "=unknown=@%s", remotehost); strncpy (ht.ht_host, rfc931host, sizeof (ht.ht_host)); strncpy (ht.ht_uthost, utremotehost, sizeof (ht.ht_host)); ht.ht_addr = rhost_addr; dogroups (); config (); calcflags (); strncpy (ht.ht_flags, flags, sizeof (ht.ht_flags)); if (f_Debug) { char c; printf("hidleho: debug mode on (press return)"); fflush(stdout); while (read(0, &c, 1)==1 && c!='\n'); } setenv ("SHELL", shell, 1); #ifdef F_TAPON if (f_Log) { char s[PATH_LEN]; struct tm *tm=localtime(&starttime); sprintf(s, "%s/%s.%02d.%02d.%02d.%02d.%02d.%02d", LDir, username, tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); Super (); if ((tap_fdo=open(s, O_WRONLY|O_CREAT, 0600))!=-1) { fcntl(tap_fdo, F_SETFD, 1); if (fcntl(tap_fdo, F_TAPON, 1)<0) syslog (LOG_ERR, "%s: %m", s); } Be (uid); } #endif if (!getenv("HFINT") && (!isatty (0) || strncmp (argv[0], INVOKENAME, strlen(INVOKENAME)-1))) { syslog (LOG_INFO, "EXEC %s on %s from %s [%s]", username, tty, rfc931host, flags); argv[0] = shell; Super (); setlimits(); setuid (ouid); signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGSEGV, SIG_DFL); close (ttyfd); execv (shell, argv); err ("couldn't execute shell %s: %m", shell); exit (1); } Be (uid); sprintf (fname, "%s/%s", user_base, DEFAULT); mkdir (fname, 0755); if (!chdir (fname)) user_conf (TRUE); for (n = gr_x; n--;) { sprintf (fname, "%s/%s+", group_base, gnames[n]); mkdir (fname, 0755); if (!chdir (fname)) user_conf (TRUE); } sprintf (fname, "%s/%s", user_base, username); mkdir (fname, 0755); if (!chdir (fname)) user_conf (FALSE); Be (ouid); chdir (cwd); if (!f_deny) permit (".permitdeny"); if (f_deny) deny (); currenttime = time (NULL); f_onconftty = isconftty (tty); if (f_Borrow) f_freetty = freetty (); totaltime = (timelim && (timeleft < timepercall)) ? timeleft : timepercall; if (totaltime < 0) totaltime = 0; if (f_onconftty && weights[tty_ent] != 1.0) { totaltime = rint (totaltime * weights[tty_ent]); f_weighted++; } if (f_Debug) syslog (LOG_DEBUG, "%s on %s from %s totaltime = %ld", username, tty, rfc931host, totaltime); Be (uid); if (f_Disable) { printfile (DeniedMsg); syslog (LOG_INFO, "%s on %s from %s [%s] LOGIN DISABLED", username, tty, rfc931host, flags); sleep (2); fatal (1); } sprintf (fname, "%s/%s/secret", user_base, username); if (!stat (fname, &st)) call_chalace (fname); Be (ouid); if (!stat (HUSHLOGIN, &st)) f_hushlogin = TRUE; if (!stat (SECRET, &st)) call_chalace (SECRET); Be (uid); ht.ht_status |= HT_CHALACED; ht.ht_timeleft_l = timeleftatlogin; ht.ht_timeleft_c = timeleft; ht.ht_timeleft_p = timepercall; strncpy (ht.ht_term, termp, sizeof (ht.ht_term)); hfd = hutmp_open (); ht2 = (struct hutmp *) Smalloc (sizeof (struct hutmp)); while (read (hfd, ht2, sizeof (struct hutmp)) > 0) { if ((ht2->ht_type != HT_EMPTY) && (!kill (ht2->ht_pid, 0) || (errno != ESRCH))) continue; lseek (hfd, -sizeof (struct hutmp), SEEK_CUR); break; } hutmp_pos = lseek (hfd, 0, SEEK_CUR); free (ht2); ht.ht_type = HT_USER; write (hfd, &ht, sizeof (ht)); hutmp_close (hfd); Be (uid); if ((termp == NULL) || !*termp || !strcasecmp (termp, "dumb") || !strcasecmp (termp, "none") || !strcasecmp (termp, "unknown")) unsetenv ("TERM"); { FILE *termfh; Be (ouid); if ((termfh = fopen (TERMTYPE, "r")) != NULL) { char s[sizeof (sttya) - 32] = ""; char *sttyp; static char s2[TT_LEN]; if (fgets (s, sizeof (s), termfh) != NULL) { ioctl (0, TIOCGWINSZ, &ws); if (((getenv ("TERM") == NULL) || !ws.ws_row) && (sttyp = strpbrk (s, " \t")) != NULL) { sttyp++; sttyp[strlen (sttyp) - 1] = 0; strncpy (sttya, sttyp, sizeof (sttya) - 1); f_stty = TRUE; } strcpy (s2, term_cnf); /* not as dumb as it looks */ sscanf (s, "%15s", s2); setenv ("TERM", s2, 0); } fclose (termfh); } else setenv ("TERM", term_cnf, 1); } Be (uid); if (!ws.ws_row) ws.ws_row = 24; if (!ws.ws_col) ws.ws_col = 80; ioctl (0, TIOCSWINSZ, &ws); tcgetattr (0, &term); if (!term.c_cc[VERASE]) { term.c_cc[VERASE] = 8; /* ctrl-h */ tcsetattr (0, TCSADRAIN, &term); } if (strstr (sttya, "rows") == NULL) { char s[32]; if (!isspace (sttya[strlen (sttya) - 1])) strcat (sttya, " "); sprintf (s, "rows %d", ws.ws_row); strcat (sttya, s); } if (strstr (sttya, "cols") == NULL) { char s[32]; if (!isspace (sttya[strlen (sttya) - 1])) strcat (sttya, " "); sprintf (s, "cols %d", ws.ws_col); strcat (sttya, s); } if (strstr (sttya, "erase") == NULL) { char s[32]; if (!isspace (sttya[strlen (sttya) - 1])) strcat (sttya, " "); sprintf (s, "erase ^%c", from_cntl (term.c_cc[VERASE])); strcat (sttya, s); } if (f_AskTerm && !f_hushlogin) { char temp[255]; char *tp; while (1) { signal (SIGALRM, handalrm); alarm (intimeout); ttyf ("\nEnter terminal type [%s %s]: ", getenv ("TERM"), sttya); for (tp = temp; (read (0, tp, 1) == 1) && (*tp != '\n'); ((tp - temp) < sizeof (temp) - 1) ? tp++ : 0); *tp = '\0'; if (temp[0]) { int ac; char junk[2]; ac = sscanf (temp, "%16s%1s", term_cnf, junk); setenv ("TERM", term_cnf, 1); if (ac == 2) { strcat (sttya, strstr (temp, term_cnf) + strlen (term_cnf)); f_stty = TRUE; } } alarm (0L); signal (SIGALRM, SIG_DFL); break; } } strncpy (ht.ht_term, getenv ("TERM"), sizeof (ht.ht_term)); hutmp_update (); if (f_stty) { pid_t child; if (!(child = fork ())) { if (argvvcc (sttya) < 1) _exit (1); /* save mem, malloc in child */ argvv[0] = STTY; Super (); setuid (ouid); execv (STTY, argvv); err ("%s couldn't execv %s", username, STTY); _exit (1); } while (wait (&wstatus) != child); } tcgetattr (0, &term); speed = cfgetospeed (&term); if (speed < 50) speed = tty_speeds[speed]; ht.ht_speed = speed; if ((labs (currenttime - lastlogout) < excludetime) /* && (!f_Borrow || !f_freetty) && (!f_ConfTtyOnly || f_onconftty) */ ) { f_exclude = TRUE; syslog (LOG_INFO, "EXCLUDE %s on %s from %s [%s] %d", username, tty, rfc931host, flags, speed); } else syslog (LOG_INFO, "%s %s on %s from %s [%s] %d", f_TimeUser ? "TIMED" : "UNTIMED", username, tty, rfc931host, flags, speed); if (f_exclude) { time_t t = lastlogout + excludetime; time(¤ttime); ttymsg ("\ You are excluded from %s for the next %ld:%-02.2d minutes,\n\r\ in order to allow other users a chance to connect to the machine.\n\r\ Please call back after %s\n\r", host, (t - currenttime) / 60, (t - currenttime) % 60, ltime (&t)); sleep (2); fatal (0); } if (f_Inform && !f_hushlogin) { int n; char s1[20]; char *s2; if (timelim) sprintf (s1, "%s/%s", itod (timelim), itod (timeper)); else strcpy (s1, "each call"); if (!(n = totaltimesaved / numlogins)) s2 = "unknown"; else s2 = itod (n); ttyf ("\n\r* HidleHo (v%s) (c) 1993, 1994, 1995 Julian Assange (%s) *\n\n\r\ Username: %16s Hostname: %21s\n\r\ Time this call:%15s Remote: %23s\n\r\ Time granted: %16s Time Left: %20s\n\r\ Tty weighting:%16.2f Time per call: %16s\n\r\ Input Idle: %16s Output Idle: %18s\n\r\ In/Out Warn: %16s Total Warn: %19s\n\r\ Exclude time: %16s Logins: %16ld\n\r\ Total use: %16s Average call: %17s\n\r\ User ID: %16d Group ID: %16ld\n\r\ Tty-line: %18s Tty-speed: %16d\n\r\ Terminal: %18s Shell: %24s\n\n\r\ Flags = Information, %sWarnings, %s-Kill, %sAskTerm, %sBorrowTime, \ %sTimeAllTtys,\n\r %sExclusiveIdle, Timer%sActive.\n\r", VERSION, __DATE__, username, host, (f_ConfTtyOnly && !f_onconftty) ? "unlimited" : itod (totaltime), remotehost, s1, (timelim) ? itod (timeleft) : itod (totaltime), f_weighted ? weights[tty_ent] : 1, itod (timepercall), itod (intimeout), itod (outtimeout), itod (warningsi[0]), itod (warningst[0]), excludetime ? itod (excludetime) : "none", numlogins, itod (totaltimesaved), s2, ouid, getgid (), strrchr (tty, '/') + 1, speed, getenv ("TERM"), shell, f_Warn ? "" : "!", f_Kill ? "Full" : "TTY", f_AskTerm ? "" : "!", f_Borrow ? "" : "!", f_ConfTtyOnly ? "!" : "", f_Exclusive ? "" : "!", f_TimeUser ? "" : "In"); ttyf ("Groups = "); for (n = 0; n < gr_x; n++) { ttyf ("%s%s", gnames[n], (n < (gr_x - 1)) ? ", " : ".\n\n\r"); } } #if 0 if (f_Inform && !f_hushlogin) { char c; signal (SIGALRM, handalrm); alarm (intimeout); ttyf ("Press return to continue: "); while ((read (0, &c, 1) == 1) && (c != '\n')); alarm (0L); signal (SIGALRM, SIG_DFL); } #endif signal (SIGHUP, huphand); signal (SIGTERM, huphand); signal (SIGCHLD, chldhand); if (!f_TimeUser) ht.ht_type = HT_EMPTY; hutmp_update (); if (!f_TimeUser || !(child = fork ())) { signal (SIGINT, SIG_DFL); signal (SIGQUIT, SIG_DFL); signal (SIGHUP, SIG_DFL); signal (SIGTERM, SIG_DFL); signal (SIGCHLD, SIG_DFL); signal (SIGSEGV, SIG_DFL); strcat (bigsys, "exec /etc/execas "); strcat (bigsys, shell); strcat (bigsys, " '"); shell[0] = '-'; strcat (bigsys, shell); strcat (bigsys, "'"); Super (); setlimits(); setuid (ouid); close (ttyfd); execl ("/bin/sh", "sh", "-c", bigsys, (char *) 0); syslog (LOG_INFO, "couldn't execute shell: %m"); term.c_line = B0; tcsetattr (0, TCSANOW, &term); fatal (1); } signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); signal (SIGABRT, SIG_IGN); signal (SIGSTOP, SIG_IGN); signal (SIGTSTP, SIG_IGN); signal (SIGTTOU, SIG_IGN); signal (SIGTTIN, SIG_IGN); pid = getpid (); sleep (1); /* close(0); */ close (1); close (2); Super (); /* if (open(tty, O_RDONLY|O_NONBLOCK)<0) { err("couldn't open tty: %m"); exit(1); } */ Be (uid); dup2 (open ("/dev/null", O_WRONLY | O_NONBLOCK), 1); dup2 (1, 2); while (1) { signal (SIGALRM, alrmhand); alarm (sleeptime); #if 1 wpid = waitpid (child, &wstatus, 0 /*WNOHANG*/ ); #else pause (); #endif alarm (0L); sleeptime = SLEEPTIME; if (f_gotsighup || f_gotsigchld || ((wpid < 1) && (errno == ECHILD)) || ((wpid == child) && (WIFEXITED (wstatus) || WIFSIGNALED (wstatus) ) ) ) { time (¤ttime); stat (tty, &st); if (f_gotsighup) syslog (LOG_INFO, "%s on %s from %s SIGHUP (hangup)", username, tty, rfc931host); else { if (WIFSIGNALED (wstatus)) syslog (LOG_INFO, "%s on %s from %s %s \ (child_died)", username, tty, rfc931host, strsignal (WTERMSIG (wstatus))); else syslog (LOG_INFO, "%s on %s from %s \ child_exit(%d)", username, tty, rfc931host, WEXITSTATUS (wstatus)); } killup (FALSE); } stat (tty, &st); time (¤ttime); if (f_Borrow) f_freetty = freetty (); idle_a = (secs) (currenttime - st.st_atime); idle_m = (secs) (currenttime - st.st_mtime); if (f_Exclusive ? ((idle_a >= intimeout) || (idle_m >= outtimeout)) : ((idle_a >= intimeout) && (idle_m >= outtimeout))) retire_idleness (); if (f_Exclusive ? ((idle_a >= labs (intimeout - *wi)) || (idle_m >= labs (outtimeout - *wi))) : ((idle_a >= labs (intimeout - *wi)) && (idle_m >= labs (outtimeout - *wi)))) { if (*wi) wi++; warning_idleness (); } else wi = &warningsi[0]; if (f_ConfTtyOnly && !f_onconftty) continue; if ((currenttime - starttime) >= totaltime) { if (f_Borrow && f_onconftty && borrow ()) continue; retire_oldage (); } if ((currenttime - starttime) >= labs (totaltime - *wt)) { if (*wt) wt++; warning_disconnect (); } } }