diff -rc2P rungetty-1.1.0/CHANGELOG rungetty-1.2/CHANGELOG *** rungetty-1.1.0/CHANGELOG Wed Dec 30 10:15:43 1998 --- rungetty-1.2/CHANGELOG Thu Feb 4 10:05:36 1999 *************** *** 1,4 **** --- 1,7 ---- rungetty + Version 1.2 - 04 February 1999 + Added -g group option to fix a potential security hole + Version 1.1.0 - 30 December 1998 Added diffs from Aaron Tiensivu (tiensivu@pilot.msu.edu) for nice level and path diff -rc2P rungetty-1.1.0/Makefile rungetty-1.2/Makefile *** rungetty-1.1.0/Makefile Fri Aug 14 08:16:20 1998 --- rungetty-1.2/Makefile Thu Feb 4 10:21:04 1999 *************** *** 7,12 **** install: all ! install -s -m 0755 -o root -g root rungetty /sbin/ ! install -m 0644 -o root -g root rungetty.8 /usr/man/man8/ rungetty: rungetty.o --- 7,14 ---- install: all ! mkdir -p $(ROOT)/sbin ! mkdir -p $(ROOT)/usr/man/man8 ! install -s -m 0755 -o root -g root rungetty $(ROOT)/sbin/ ! install -m 0644 -o root -g root rungetty.8 $(ROOT)/usr/man/man8/ rungetty: rungetty.o diff -rc2P rungetty-1.1.0/README rungetty-1.2/README *** rungetty-1.1.0/README Wed Dec 30 10:19:53 1998 --- rungetty-1.2/README Thu Feb 4 10:04:41 1999 *************** *** 1,3 **** ! This is rungetty version 1.1.0. rungetty takes command of a virtual console and runs any program on it. By default, it runs login. If a program is passed as a paramater to rungetty from inittab, it will run that program. For example: --- 1,3 ---- ! This is rungetty version 1.2. rungetty takes command of a virtual console and runs any program on it. By default, it runs login. If a program is passed as a paramater to rungetty from inittab, it will run that program. For example: diff -rc2P rungetty-1.1.0/rungetty.8 rungetty-1.2/rungetty.8 *** rungetty-1.1.0/rungetty.8 Wed Dec 30 10:17:51 1998 --- rungetty-1.2/rungetty.8 Thu Feb 4 10:02:13 1999 *************** *** 1,3 **** ! .TH RUNGETTY 8 "20 November 1998" " Jakob 'sparky' Kaivo " "Linux Programmer's Manual" .SH NAME rungetty \- a minimal console getty that can run any process --- 1,3 ---- ! .TH RUNGETTY 8 "04 February 1999" " Jakob 'sparky' Kaivo " "Linux Programmer's Manual" .SH NAME rungetty \- a minimal console getty that can run any process *************** *** 6,9 **** --- 6,11 ---- [\-\-noclear] [\-\-long\-hostname] [\-u .IR username ] + [\-g + .IR group ] [\-w .IR path ] *************** *** 34,41 **** for that. It is useful, though, for keeping programs such as, say, .BR telnet (1), ! running at all times. When running a program other than login, it is executed as the user .BR nobody , or the user specified by ! .IR username . .PP .SH OPTIONS --- 36,45 ---- for that. It is useful, though, for keeping programs such as, say, .BR telnet (1), ! running at all times. When running a program other than login, it is executed as the user and group .BR nobody , or the user specified by ! .I username ! and group specified by ! .IR group . .PP .SH OPTIONS *************** *** 54,57 **** --- 58,65 ---- .IR username . .TP + .B \-g group + By default, rungetty runs as the group nobody. This option allows you to tell rungetty to run programs as the group + .IR group . + .TP .B \-\-prompt [=string] This option causes rungetty to wait until user input (usually an 'Enter') *************** *** 211,213 **** .PP .SH AUTHOR ! Copyright \(co 1998 Jakob Kaivo . --- 219,221 ---- .PP .SH AUTHOR ! Copyright \(co 1999 Jakob Kaivo . diff -rc2P rungetty-1.1.0/rungetty.c rungetty-1.2/rungetty.c *** rungetty-1.1.0/rungetty.c Wed Dec 30 10:18:32 1998 --- rungetty-1.2/rungetty.c Thu Feb 4 10:04:02 1999 *************** *** 1,5 **** /******************************************************************************* * rungetty.c ! * Copyright (C) 1998 Jakob 'sparky' Kaivo * jake@nodomainname.net * --- 1,8 ---- /******************************************************************************* * rungetty.c ! * This is rungetty, a small console getty that allows for execution of ! * arbitrary programs. ! * ! * Copyright (C) 1999 Jakob 'sparky' Kaivo * jake@nodomainname.net * *************** *** 24,27 **** --- 27,31 ---- #include #include + #include #include #include *************** *** 88,91 **** --- 92,98 ---- static struct passwd *user; + /* The group */ + static struct group *u_group; + /* set to wait for return before doing anything */ static int prompt_return = 0; *************** *** 109,113 **** * output error messages */ ! static void error (const char *fmt,...) { --- 116,120 ---- * output error messages */ ! static void error (const char *fmt,...) { *************** *** 136,143 **** #else /* !USE_SYSLOG */ strcat (bp, "\r\n"); ! if ((fd = open ("/dev/console", 1)) >= 0) { ! write (fd, buf, strlen (buf)); ! close (fd); ! } #endif /* USE_SYSLOG */ exit (1); --- 143,151 ---- #else /* !USE_SYSLOG */ strcat (bp, "\r\n"); ! if ((fd = open ("/dev/console", 1)) >= 0) ! { ! write (fd, buf, strlen (buf)); ! close (fd); ! } #endif /* USE_SYSLOG */ exit (1); *************** *** 154,158 **** * our entry in the utmp file. */ ! static void update_utmp (void) { --- 162,166 ---- * our entry in the utmp file. */ ! static void update_utmp (void) { *************** *** 168,180 **** break; ! if (utp) { ! memcpy (&ut, utp, sizeof (ut)); ! } ! else { ! /* some inits don't initialize utmp... */ ! /* XXX we should print out a warning message */ ! memset (&ut, 0, sizeof (ut)); ! strncpy (ut.ut_id, tty + 3, sizeof (ut.ut_id)); ! } endutent (); --- 176,190 ---- break; ! if (utp) ! { ! memcpy (&ut, utp, sizeof (ut)); ! } ! else ! { ! /* some inits don't initialize utmp... */ ! /* XXX we should print out a warning message */ ! memset (&ut, 0, sizeof (ut)); ! strncpy (ut.ut_id, tty + 3, sizeof (ut.ut_id)); ! } endutent (); *************** *** 188,264 **** endutent (); ! if ((ut_fd = open (_PATH_WTMP, O_APPEND | O_WRONLY)) >= 0) { ! (void) signal (SIGALRM, locktimeout); ! (void) alarm (3); ! flock (ut_fd, LOCK_EX); ! (void) alarm (0); ! write (ut_fd, &ut, sizeof (ut)); ! flock (ut_fd, LOCK_UN); ! close (ut_fd); ! } } ! static void output_special_char (unsigned char c) { ! switch (c) { ! case 's': ! printf ("%s", uts.sysname); ! break; ! case 'n': ! printf ("%s", uts.nodename); ! break; ! case 'r': ! printf ("%s", uts.release); ! break; ! case 'v': ! printf ("%s", uts.version); ! break; ! case 'm': ! printf ("%s", uts.machine); ! break; ! case 'o': #ifdef __USE_GNU ! printf ("%s", uts.domainname); #else ! printf ("%s", uts.__domainname); #endif - break; - case 'd': - case 't': - { - char buff[20]; - struct tm *tm = localtime (&cur_time); - - strftime (buff, sizeof (buff), c == 'd' ? "%a %b %d %Y" : "%X", tm); - fputs (buff, stdout); break; ! } ! case 'l': ! printf ("%s", tty); ! break; ! case 'u': ! case 'U': ! { ! int users = 0; ! struct utmp *ut; ! ! setutent (); ! while ((ut = getutent ())) ! if (ut->ut_type == USER_PROCESS) ! users++; ! endutent (); ! printf ("%d", users); ! if (c == 'U') ! printf (" user%s", users == 1 ? "" : "s"); break; } - default: - putchar (c); - } } /* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ ! static void do_prompt (void) { --- 198,276 ---- endutent (); ! if ((ut_fd = open (_PATH_WTMP, O_APPEND | O_WRONLY)) >= 0) ! { ! (void) signal (SIGALRM, locktimeout); ! (void) alarm (3); ! flock (ut_fd, LOCK_EX); ! (void) alarm (0); ! write (ut_fd, &ut, sizeof (ut)); ! flock (ut_fd, LOCK_UN); ! close (ut_fd); ! } } ! static void output_special_char (unsigned char c) { ! switch (c) ! { ! case 's': ! printf ("%s", uts.sysname); ! break; ! case 'n': ! printf ("%s", uts.nodename); ! break; ! case 'r': ! printf ("%s", uts.release); ! break; ! case 'v': ! printf ("%s", uts.version); ! break; ! case 'm': ! printf ("%s", uts.machine); ! break; ! case 'o': #ifdef __USE_GNU ! printf ("%s", uts.domainname); #else ! printf ("%s", uts.__domainname); #endif break; ! case 'd': ! case 't': ! { ! char buff[20]; ! struct tm *tm = localtime (&cur_time); ! ! strftime (buff, sizeof (buff), c == 'd' ? "%a %b %d %Y" : "%X", tm); ! fputs (buff, stdout); ! break; ! } ! case 'l': ! printf ("%s", tty); break; + case 'u': + case 'U': + { + int users = 0; + struct utmp *ut; + + setutent (); + while ((ut = getutent ())) + if (ut->ut_type == USER_PROCESS) + users++; + endutent (); + printf ("%d", users); + if (c == 'U') + printf (" user%s", users == 1 ? "" : "s"); + break; + } + default: + putchar (c); } } /* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ ! static void do_prompt (void) { *************** *** 267,280 **** write (1, "\n", 1); /* start a new line */ ! if ((fd = fopen (ISSUE, "r"))) { ! while ((c = getc (fd)) != EOF) { ! if (c == '\\') ! output_special_char (getc (fd)); ! else ! putchar (c); ! } ! fflush (stdout); ! fclose (fd); ! } write (1, hn, strlen (hn)); write (1, LOGIN, sizeof (LOGIN) - 1); --- 279,294 ---- write (1, "\n", 1); /* start a new line */ ! if ((fd = fopen (ISSUE, "r"))) ! { ! while ((c = getc (fd)) != EOF) ! { ! if (c == '\\') ! output_special_char (getc (fd)); ! else ! putchar (c); ! } ! fflush (stdout); ! fclose (fd); ! } write (1, hn, strlen (hn)); write (1, LOGIN, sizeof (LOGIN) - 1); *************** *** 291,314 **** ioctl (0, TCFLSH, 0); /* flush pending input */ ! for (*logname = 0; *logname == 0;) { ! do_prompt (); ! for (bp = logname;;) { ! if (read (0, &c, 1) < 1) { ! if (errno == EINTR || errno == EIO || errno == ENOENT) ! exit (0); ! error ("%s: read: %s", tty, sys_errlist[errno]); ! } ! if (c == '\n' || c == '\r') { ! *bp = 0; ! break; ! } ! else if (!isprint (c)) ! error ("%s: invalid character %c in login name", tty, c); ! else if (bp - logname >= sizeof (logname) - 1) ! error ("%s: too long login name", tty); ! else ! *bp++ = c; } - } return logname; } --- 305,332 ---- ioctl (0, TCFLSH, 0); /* flush pending input */ ! for (*logname = 0; *logname == 0;) ! { ! do_prompt (); ! for (bp = logname;;) ! { ! if (read (0, &c, 1) < 1) ! { ! if (errno == EINTR || errno == EIO || errno == ENOENT) ! exit (0); ! error ("%s: read: %s", tty, sys_errlist[errno]); ! } ! if (c == '\n' || c == '\r') ! { ! *bp = 0; ! break; ! } ! else if (!isprint (c)) ! error ("%s: invalid character %c in login name", tty, c); ! else if (bp - logname >= sizeof (logname) - 1) ! error ("%s: too long login name", tty); ! else ! *bp++ = c; ! } } return logname; } *************** *** 325,329 **** }; ! void locktimeout (int dummy) { --- 343,347 ---- }; ! void locktimeout (int dummy) { *************** *** 336,343 **** char buf[] = "Lock failed on wtmp\n"; ! if ((fd = open ("/dev/console", 1)) >= 0) { ! write (fd, buf, strlen (buf)); ! close (fd); ! } #endif } --- 354,362 ---- char buf[] = "Lock failed on wtmp\n"; ! if ((fd = open ("/dev/console", 1)) >= 0) ! { ! write (fd, buf, strlen (buf)); ! close (fd); ! } #endif } *************** *** 351,355 **** * return 0 otherwise. */ ! static int autologin_ok (void) { --- 370,374 ---- * return 0 otherwise. */ ! static int autologin_ok (void) { *************** *** 400,413 **** } ! void mingetty_login (char *logname, char *tty) { ! if (autologin_ok ()) { ! execl (_PATH_LOGIN, _PATH_LOGIN, "-f", autologin_name, NULL); ! } ! else { ! while ((logname = get_logname ()) == 0); ! execl (_PATH_LOGIN, _PATH_LOGIN, "--", logname, NULL); ! } error ("%s: can't exec " _PATH_LOGIN ": %s", tty, sys_errlist[errno]); exit (0); --- 419,434 ---- } ! void mingetty_login (char *logname, char *tty) { ! if (autologin_ok ()) ! { ! execl (_PATH_LOGIN, _PATH_LOGIN, "-f", autologin_name, NULL); ! } ! else ! { ! while ((logname = get_logname ()) == 0); ! execl (_PATH_LOGIN, _PATH_LOGIN, "--", logname, NULL); ! } error ("%s: can't exec " _PATH_LOGIN ": %s", tty, sys_errlist[errno]); exit (0); *************** *** 415,419 **** /* open_tty - set up tty as standard { input, output, error } */ ! static void open_tty (void) { --- 436,440 ---- /* open_tty - set up tty as standard { input, output, error } */ ! static void open_tty (void) { *************** *** 471,484 **** sigaction (SIGHUP, &sa, NULL); ! if (prompt_return) { ! write (1, prompt, strlen (prompt)); ! if (program_run) { ! write (1, "`", 1); ! write (1, program_run, strlen (program_run)); ! write (1, "'", 1); ! } ! write (1, "\n", 1); ! read (0, buf, 1); ! } #if DEBUG_THIS --- 492,507 ---- sigaction (SIGHUP, &sa, NULL); ! if (prompt_return) ! { ! write (1, prompt, strlen (prompt)); ! if (program_run) ! { ! write (1, "`", 1); ! write (1, program_run, strlen (program_run)); ! write (1, "'", 1); ! } ! write (1, "\n", 1); ! read (0, buf, 1); ! } #if DEBUG_THIS *************** *** 487,491 **** } ! static void usage (void) { --- 510,514 ---- } ! static void usage (void) { *************** *** 497,501 **** * main program */ ! int main (int argc, char **argv) { --- 520,524 ---- * main program */ ! int main (int argc, char **argv) { *************** *** 509,546 **** pid = getpid (); time (&cur_time); ! while ((c = getopt_long (argc, argv, "d:n:u:w:", long_options, (int *) 0)) != EOF) { ! switch (c) { ! case 0: ! break; ! case 'a': ! autologin_name = optarg; ! break; ! case 'd': ! delay = atoi (optarg); ! break; ! case 'n': ! priority = atoi (optarg); ! break; ! case 'p': ! if (optarg) ! prompt = optarg; ! else ! prompt = PROMPT_RETURN; ! prompt_return = 1; ! break; ! case 'u': ! user = getpwnam (optarg); ! break; ! case 'w': ! progpath = optarg; ! break; ! default: ! usage (); } - } if (!longhostname && (s = strchr (hn, '.'))) *s = '\0'; if (!user) user = getpwnam ("nobody"); tty = argv[optind]; if (!tty) --- 532,576 ---- pid = getpid (); time (&cur_time); ! while ((c = getopt_long (argc, argv, "d:n:u:w:g:", long_options, (int *) 0)) != EOF) ! { ! switch (c) ! { ! case 0: ! break; ! case 'a': ! autologin_name = optarg; ! break; ! case 'd': ! delay = atoi (optarg); ! break; ! case 'g': ! u_group = getgrnam (optarg); ! break; ! case 'n': ! priority = atoi (optarg); ! break; ! case 'p': ! if (optarg) ! prompt = optarg; ! else ! prompt = PROMPT_RETURN; ! prompt_return = 1; ! break; ! case 'u': ! user = getpwnam (optarg); ! break; ! case 'w': ! progpath = optarg; ! break; ! default: ! usage (); ! } } if (!longhostname && (s = strchr (hn, '.'))) *s = '\0'; if (!user) user = getpwnam ("nobody"); + if (!u_group) + u_group = getgrnam ("nobody"); tty = argv[optind]; if (!tty) *************** *** 567,570 **** --- 597,601 ---- mingetty_login (logname, tty); + setgid (u_group->gr_gid); setuid (user->pw_uid);