summaryrefslogtreecommitdiffstats
path: root/login-utils
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:33 +0100
committerKarel Zak2006-12-07 00:25:33 +0100
commit726f69e29ca9d4842f3acb20fffd2466fda62c09 (patch)
treeabbc1b6e9bfb0dfe32e81a83648e261ccb2d5a5f /login-utils
parentImported from util-linux-2.2 tarball. (diff)
downloadkernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.gz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.tar.xz
kernel-qcow2-util-linux-726f69e29ca9d4842f3acb20fffd2466fda62c09.zip
Imported from util-linux-2.5 tarball.
Diffstat (limited to 'login-utils')
-rw-r--r--login-utils/Makefile162
-rw-r--r--login-utils/README.admutil50
-rw-r--r--login-utils/README.poeigl73
-rw-r--r--login-utils/agetty.822
-rw-r--r--login-utils/agetty.c126
-rw-r--r--login-utils/checktty.c423
-rw-r--r--login-utils/chfn.16
-rw-r--r--login-utils/chfn.c38
-rw-r--r--login-utils/chsh.16
-rw-r--r--login-utils/chsh.c69
-rw-r--r--login-utils/last.14
-rw-r--r--login-utils/last.1.orig49
-rw-r--r--login-utils/last.c1
-rw-r--r--login-utils/last.c.orig381
-rw-r--r--login-utils/login.1181
-rw-r--r--login-utils/login.c185
-rw-r--r--login-utils/mesg.1116
-rw-r--r--login-utils/mesg.c138
-rw-r--r--login-utils/newgrp.16
-rw-r--r--login-utils/passwd.131
-rw-r--r--login-utils/passwd.c318
-rw-r--r--login-utils/setpwnam.c104
-rw-r--r--login-utils/shutdown.89
-rw-r--r--login-utils/shutdown.c56
-rw-r--r--login-utils/simpleinit.c8
-rw-r--r--login-utils/ttymsg.c50
-rw-r--r--login-utils/vipw.82
-rw-r--r--login-utils/vipw.c16
-rw-r--r--login-utils/wall.c60
29 files changed, 2188 insertions, 502 deletions
diff --git a/login-utils/Makefile b/login-utils/Makefile
index 88e0b8220..35c8125a2 100644
--- a/login-utils/Makefile
+++ b/login-utils/Makefile
@@ -1,6 +1,6 @@
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Wed Feb 22 16:09:31 1995 by faith@cs.unc.edu
+# Revised: Thu Oct 12 10:10:32 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
# Suggested changed from Bauke Jan Douma <bjdouma@xs4all.nl> have been
@@ -10,46 +10,64 @@ include ../MCONFIG
# Where to put man pages?
-MAN1= last.1 mesg.1 wall.1
+MAN1.MISC= last.1 mesg.1 wall.1
-MAN1.NONSHADOW= chfn.1 chsh.1 login.1 newgrp.1 passwd.1
+MAN1.PUTILS= chfn.1 chsh.1 login.1 newgrp.1
+MAN1.PASSWD= passwd.1
-MAN8= agetty.8 fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 \
- shutdown.8
+MAN8.GETTY= agetty.8
-MAN8.NONSHADOW= vipw.8
+MAN8.INIT= fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 shutdown.8
+
+MAN8.PUTILS= vipw.8
# Where to put binaries?
# See the "install" rule for the links. . .
-SBIN= agetty simpleinit shutdown
+SBIN.GETTY= agetty
-BIN.NONSHADOW= login
+SBIN.INIT= simpleinit shutdown
-USRBIN= last mesg wall
+BIN.PUTILS= login
-USRBIN.NONSHADOW= chfn chsh newgrp passwd
+USRBIN.MISC= last mesg wall
-USRSBIN.NONSHADOW= vipw
+USRBIN.PUTILS= chfn chsh newgrp
+USRBIN.PASSWD= passwd
-PASSWDDIR= /usr/bin
+USRSBIN.PUTILS= vipw
ifeq "$(HAVE_SHADOW)" "no"
-WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-nonshadow
-WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-nonshadow
+ifeq "$(HAVE_PASSWD)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-passwd all-putils
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-passwd install-putils
+else
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-putils
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-putils
+endif
endif
ifeq "$(HAVE_SYSVINIT)" "no"
-WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-nonsysvinit
-WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-nonsysvinit
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-init
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-init
endif
-all: $(WHAT_TO_BUILD)
-all-nonshadow: $(BIN.NONSHADOW) $(USRBIN.NONSHADOW) $(USRSBIN.NONSHADOW)
-all-nonsysvinit: $(USRBIN) $(SBIN)
+ifeq "$(HAVE_SYSVINIT_UTILS)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-misc
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-misc
+endif
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
+ifeq "$(HAVE_GETTY)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-getty
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-getty
+endif
+
+all: $(WHAT_TO_BUILD)
+all-passwd: $(USRBIN.PASSWD)
+all-putils: $(BIN.PUTILS) $(USRBIN.PUTILS) $(USRSBIN.PUTILS)
+all-init: $(SBIN.INIT)
+all-getty: $(SBIN.GETTY)
+all-misc: $(USRBIN.MISC)
# Rules for everything else
@@ -59,12 +77,11 @@ chfn: chfn.o setpwnam.o
chsh: chsh.o setpwnam.o
last.o: $(BSD)/pathnames.h
last: last.o $(BSD)/getopt.o
-login.o: $(BSD)/pathnames.h
-login: login.o
-mesg: mesg.o
+login: login.o checktty.o
+mesg: mesg.o $(BSD)/getopt.o $(BSD)/err.o
newgrp.o: $(BSD)/pathnames.h
newgrp: newgrp.o
-passwd: passwd.o islocal.o
+setpwnam.o: $(BSD)/pathnames.h
shutdown.o: $(BSD)/pathnames.h
shutdown: shutdown.o
simpleinit.o: $(BSD)/pathnames.h
@@ -73,40 +90,81 @@ vipw.o: $(BSD)/pathnames.h
vipw: vipw.o
wall: wall.o ttymsg.o
+ifeq "$(USE_TTY_GROUP)" "yes"
+login.o: login.c $(BSD)/pathnames.h
+ $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP login.c
+mesg.o: mesg.c $(BSD)/err.h
+ $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c
+else
+login.o: $(BSD)/pathnames.h
+mesg.o: $(BSD)/err.h
+endif
+
+passwd: passwd.o islocal.o setpwnam.o
+passwd.o: passwd.c
+ $(CC) -c $(CFLAGS) -DUSE_SETPWNAM passwd.c
+
+ifeq "$(REQUIRE_PASSWORD)" "yes"
+CHSH_FLAGS:=$(CHSH_FLAGS) -DREQUIRE_PASSWORD
+endif
+
+ifeq "$(ONLY_LISTED_SHELLS)" "yes"
+CHSH_FLAGS:=$(CHSH_FLAGS) -DONLY_LISTED_SHELLS
+endif
+
+chsh.o: chsh.c
+ $(CC) -c $(CFLAGS) $(CHSH_FLAGS) chsh.c
+
+chfn.o: chfn.c
+ $(CC) -c $(CFLAGS) $(CHSH_FLAGS) chfn.c
+
install: all $(WHAT_TO_INSTALL)
-install-nonshadow:
- $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR)
- $(INSTALLBIN) $(BIN.NONSHADOW) $(BINDIR)
- $(INSTALLBIN) $(USRBIN.NONSHADOW) $(USRBINDIR)
- $(INSTALLBIN) $(USRSBIN.NONSHADOW) $(USRSBINDIR)
+install-putils: $(BIN.PUTILS) $(USRBIN.PUTILS) $(USRSBIN.PUTILS)
+ $(INSTALLDIR) $(BINDIR) $(USRBINDIR) $(USRSBINDIR)
+ $(INSTALLSUID) $(BIN.PUTILS) $(BINDIR)
+ $(INSTALLSUID) $(USRBIN.PUTILS) $(USRBINDIR)
+ $(INSTALLBIN) $(USRSBIN.PUTILS) $(USRSBINDIR)
$(INSTALLDIR) $(MAN1DIR) $(MAN8DIR)
- $(INSTALLMAN) $(MAN1.NONSHADOW) $(MAN1DIR)
- $(INSTALLMAN) $(MAN8.NONSHADOW) $(MAN8DIR)
- chown root $(USRBINDIR)/chsh
- chmod u+s $(USRBINDIR)/chsh
- chown root $(USRBINDIR)/chfn
- chmod u+s $(USRBINDIR)/chfn
- chown root $(USRBINDIR)/newgrp
- chmod u+s $(USRBINDIR)/newgrp
- chown root $(PASSWDDIR)/passwd
- chmod u+s $(PASSWDDIR)/passwd
- chown root $(BINDIR)/login
- chmod u+s $(BINDIR)/login
-
-install-nonsysvinit:
- $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR)
- $(INSTALLBIN) $(SBIN) $(SBINDIR)
+ $(INSTALLMAN) $(MAN1.PUTILS) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN8.PUTILS) $(MAN8DIR)
+
+install-passwd: $(USRBIN.PASSWD)
+ $(INSTALLDIR) $(USRBINDIR)
+ $(INSTALLSUID) $(USRBIN.PASSWD) $(USRBINDIR)
+ $(INSTALLDIR) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN1.PASSWD) $(MAN1DIR)
+
+install-init: $(SBIN.INIT)
+ $(INSTALLDIR) $(SBINDIR)
+ $(INSTALLBIN) $(SBIN.INIT) $(SBINDIR)
+ $(INSTALLDIR) $(MAN8DIR)
+ $(INSTALLMAN) $(MAN8.INIT) $(MAN8DIR)
+ # Make *relative* links for these
(cd $(SHUTDOWNDIR); ln -sf shutdown reboot)
(cd $(SHUTDOWNDIR); ln -sf shutdown fastboot)
(cd $(SHUTDOWNDIR); ln -sf shutdown halt)
(cd $(SHUTDOWNDIR); ln -sf shutdown fasthalt)
- $(INSTALLBIN) $(USRBIN) $(USRBINDIR)
- $(INSTALLDIR) $(MAN1DIR) $(MAN8DIR)
- $(INSTALLMAN) $(MAN1) $(MAN1DIR)
- $(INSTALLMAN) $(MAN8) $(MAN8DIR)
+
+
+install-getty: $(SBIN.GETTY)
+ $(INSTALLDIR) $(SBINDIR)
+ $(INSTALLBIN) $(SBIN.GETTY) $(SBINDIR)
+ $(INSTALLDIR) $(MAN8DIR)
+ $(INSTALLMAN) $(MAN8.GETTY) $(MAN8DIR)
+
+install-misc: $(USRBIN.MISC)
+ $(INSTALLDIR) $(USRBINDIR)
+ $(INSTALLBIN) $(USRBIN.MISC) $(USRBINDIR)
+ $(INSTALLDIR) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN1.MISC) $(MAN1DIR)
+ifeq "$(USE_TTY_GROUP)" "yes"
+ chgrp tty $(USRBINDIR)/wall
+ chmod g+s $(USRBINDIR)/wall
+endif
.PHONY: clean
clean:
- -rm -f *.o *~ core $(SBIN) $(BIN) $(BIN.NONSHADOW) $(USRBIN) \
- $(USRBIN.NONSHADOW) $(USRSBIN.NONSHADOW)
+ -rm -f *.o *~ core $(BIN.PASSWD) $(SBIN.GETTY) $(SBIN.INIT) \
+ $(USRBIN.MISC) $(USRBIN.PASSWD) $(USRBIN.PUTILS) \
+ $(USRSBIN.PUTILS) $(BIN.PUTILS)
diff --git a/login-utils/README.admutil b/login-utils/README.admutil
index 789252d10..3e25e84e7 100644
--- a/login-utils/README.admutil
+++ b/login-utils/README.admutil
@@ -1,4 +1,4 @@
-README file for the admutils V1.14 for Linux.
+README file for the admutils V1.16 for Linux.
See installation instructions at the bottom. Currently the latest versions
of this software is maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/
@@ -7,6 +7,54 @@ LICENSE:
This software is distributed as is without any warranty what so ever.
With respect to copyrights it is covered by the GNU Public License.
+Version 1.17 (7-Oct-95):
+ Added setrlimit() calls to passwd.c and chsh.c to fix security hole
+ caused by resource limitations. Inspired by Zefram
+ <A.Main@dcs.warwick.ac.uk>. Also beefed up the ptmp locking in
+ chsh.c.
+ Added swap_off() function to shutdown.c by baekgrd@ibm.net
+ (Anders Baekgaard).
+ Bugfix in shutdown.c that makes sure wtmp gets closed. By
+ Alexandre Julliard <julliard@sunsite.unc.edu>.
+ Fixed bug in passwd.c that made it impossible to change from having
+ no password into having one.
+
+Version 1.16 (18-Sep-95):
+ Added feature to passwd.c by Arpad Magossanyi (mag@tas.vein.hu),
+ so root can give a password for a user on the command line. This
+ might be useful in a shell script autogenerating passwords for
+ new users.
+
+ Added and updated manual pages for all commands by Rick Faith.
+
+Version 1.15d (21-Aug-95):
+ Fixed minor nit with salt generation in passwd.c
+ By Steven Reisman <sar@beehive.mn.org>.
+
+Version 1.15c (5-Jul-95):
+ passwd does not allow reuse of the old password when changing.
+ passwd returns 1 if the password is not changed. This was
+ suggested by Anibal Jodorcovsky <anibal@ee.mcgill.ca> who
+ also fixed my initial bug in this feature.
+
+ passwd uses O_EXCL for opening /etc/ptmp instead of access/fopen.
+ This was suggested by jorge@un1.satlink.com (Jorge).
+
+Version 1.15a (12-Jun-95):
+ Fix in last.c so it does not print wtmp entries marked DEAD_PROCESS.
+ By Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+Version 1.15 (5-Jun-95):
+ Man-page fixes, fixes in pathnames.h to adhere to the FSSTND.
+ Fix by Rickard Faith <faith@cs.unc.edu> to passwd.c, so sanity
+ checks come before the second entry of the new password.
+ This is for Linux 1.2, GCC 2.6.2 or later.
+
+Version 1.14a (12-Mar-95):
+ Fixed passwd and chsh so a username that is a prefix of another
+ doesn't affect the other's password. After suggested patch
+ by Valtteri J. Karu <vatekaru@tuug.utu.fi>, but differently!
+
Version 1.14 (12-Feb-95):
Added options -l, -y, -i to last.c. See last.man
diff --git a/login-utils/README.poeigl b/login-utils/README.poeigl
index f6f8933c4..5b6fac3f4 100644
--- a/login-utils/README.poeigl
+++ b/login-utils/README.poeigl
@@ -1,6 +1,6 @@
README for init/getty/login, by poe@daimi.aau.dk
-This package contains init, getty, and login programs for Linux.
+This package contains simpleinit, agetty, and login programs for Linux.
Additional utilities included are: hostname, who, write, wall, users
domainname, hostid, cage and mesg.
@@ -9,12 +9,81 @@ ported the things to Linux.
About installation: See the bottom of this file. Check the Makefile!
Be sure you know what you are doing! You may well be able to lock
-yourself out from your machine.
+yourself out from your machine. Especially: The init provided here
+(simpleinit) is NOT a SYSV compatible init and the inittab format
+is different.
If you are uncertain whether you got the latest version, check out
ftp://ftp.daimi.aau.dk:/pub/linux/poe/
+Version 1.37 (15-Sep-95):
+ Added -I <initstring> and -w options to agetty.c for those that
+ use agetty with modems.
+
+Version 1.36 (25-Aug-95):
+ Enhanced /etc/usertty features with group support. Moved this part
+ of login.c to checktty.c. One can now define classes of hosts and
+ ttys and do access checking based on unix-group membership. See
+ login.1. Also time ranges for logins can be specified, for example
+ writing the line
+
+ joe [mon:tue:wed:thu:fri:8-16]@barracuda [mon:tue:wed:thu:fri:0-7:17-23]@joes.pc.at.home [sat:sun:0-23]@joes.pc.at.home
+
+ says that during working hours, Joe may rlogin from the host
+ barracuda, whereas outside working hours and in weekends Joe may
+ rlogin from his networked PC at home.
+
+ login.c: failures was not properly initialized, it now is. Also
+ made sure ALL failures are really logged to syslog.
+
+Version 1.35 (7-Aug-95):
+ login.c: Much improved features for the usertty file, allows
+ access control based on both hostnames/addresses and line. See the
+ about.usertty file and the man-page.
+
+ Fixed agetty so it doesn't fiddle with the ut_id field in the
+ utmp record, this should prevent growing utmps on systems with
+ more than 10 login lines. Fix suggested and checked by Alan Wendt
+ <alan@ezlink.com> in his agetty.1.9.1a.
+
+ Agetty now installs as agetty again, not as getty.
+ Updated man-page for login(1) to document /etc/usertty changes.
+
+ This has been tested on Linux 1.2.5 with GCC 2.5.8 and libc 4.5.26.
+
+Version 1.33a (20-Jun-95):
+ rchatfie@cavern.nmsu.edu ("rc.") suggested that I should remove
+ the #ifndef linux around the special logging of dial-up
+ logins. This is now done, so each login via a serial port
+ generates a separate DIALUP syslog entry.
+
+Version 1.33 (5-Jun-95):
+ Patch by Ron Sommeling <sommel@sci.kun.nl> and
+ jlaiho@ichaos.nullnet.fi (Juha Laiho) for agetty.c, used
+ to return a pointer to an automatic variable in get_logname().
+ Many patches from or via Rickard Faith <faith@cs.unc.edu>, fixing
+ man-pages etc, now defaults to using /var/log/wtmp and /var/run/utmp
+ according to the new FSSTND.
+
+ Fix in login.c for CPU eating bug when a remote telnet client dies
+ while logging in.
+
+ This is for Linux 1.2, GCC 2.6.2 or later.
+
+Version 1.32b (12-Mar-95):
+ Login now sets the tty group to "tty" instead of "other". Depending
+ on compile-time define USE_TTY_GROUP the tty mode is set to 0620 or
+ 0600 instead of 0622. All as per suggestion by Rik Faith and the
+ linux-security list.
+ Write/wall now strips control chars except BEL (\007). Again after
+ suggestion by Rik Faith.
+
+Version 1.32a
+ Urgent security patch from Alvaro M. Echevarria incorporated into
+ login.c. This is really needed on machines running YP until
+ the libraries are fixed.
+
Version 1.32
Login now logs the ip-address of the connecting host to utmp as it
should.
diff --git a/login-utils/agetty.8 b/login-utils/agetty.8
index 3f3cf6ada..f6a59909c 100644
--- a/login-utils/agetty.8
+++ b/login-utils/agetty.8
@@ -6,8 +6,8 @@ agetty \- alternative Linux getty
.SH SYNOPSIS
.na
.nf
-agetty [-ihL] [-l login_program] [-m] [-t timeout] port baud_rate,... [term]
-agetty [-ihL] [-l login_program] [-m] [-t timeout] baud_rate,... port [term]
+agetty [-ihLmw] [-l login_program] [-I init] [-t timeout] port baud_rate,... [term]
+agetty [-ihLmw] [-l login_program] [-I init] [-t timeout] baud_rate,... port [term]
.SH DESCRIPTION
.ad
.fi
@@ -85,6 +85,14 @@ login prompt. Terminals or communications hardware may become confused
when receiving lots of text at the wrong baud rate; dial-up scripts
may fail if the login prompt is preceded by too much text.
.TP
+-I initstring
+Set an initial string to be sent to the tty or modem before sending
+anything else. This may be used to initialize a modem. Non printable
+characters may be sent by writing their octal code preceded by a
+backslash (\\). For example to send a linefeed character (ASCII 10,
+octal 012) write \\012.
+.PP
+.TP
-l login_program
Invoke the specified \fIlogin_program\fP instead of /bin/login.
This allows the use of a non-standard login program (for example,
@@ -112,7 +120,11 @@ lines.
Force the line to be local line with no need for carrier detect. This can
be useful when you have locally attached terminal where the serial line
does not set the carrier detect signal.
-
+.TP
+-w
+Wait for the user or the modem to send a carriage-return or a linefeed
+character before sending the /etc/issue file and the login prompt.
+.PP
.SH EXAMPLES
.na
.nf
@@ -190,7 +202,7 @@ This is thingol.orcan.dk (Linux i386 1.1.9) 18:29:30
.SH FILES
.na
.nf
-/etc/utmp, the system status file (System V only).
+/var/run/utmp, the system status file.
/etc/issue, printed before the login prompt (System V only).
/dev/console, problem reports (if syslog(3) is not used).
/etc/inittab (Linux simpleinit(8) configuration file).
@@ -214,7 +226,7 @@ the modem emits its status message \fIafter\fP raising the DCD line.
Depending on how the program was configured, all diagnostics are
written to the console device or reported via the syslog(3) facility.
Error messages are produced if the \fIport\fP argument does not
-specify a terminal device; if there is no /etc/utmp entry for the
+specify a terminal device; if there is no utmp entry for the
current process (System V only); and so on.
.SH AUTHOR(S)
.na
diff --git a/login-utils/agetty.c b/login-utils/agetty.c
index a8cd45db8..c7595bf37 100644
--- a/login-utils/agetty.c
+++ b/login-utils/agetty.c
@@ -132,12 +132,15 @@ struct options {
int numspeed; /* number of baud rates to try */
int speeds[MAX_SPEED]; /* baud rates to be tried */
char *tty; /* name of tty */
+ char *initstring; /* modem init string */
};
#define F_PARSE (1<<0) /* process modem status messages */
#define F_ISSUE (1<<1) /* display /etc/issue */
#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */
#define F_LOCAL (1<<3) /* force local */
+#define F_INITSTRING (1<<4) /* initstring is set */
+#define F_WAITCRLF (1<<5) /* wait for CR or LF */
/* Storage for things detected while the login name was read. */
@@ -194,7 +197,6 @@ main(argc, argv)
char **argv;
{
char *logname; /* login name, given to /bin/login */
- char *get_logname();
struct chardata chardata; /* set by get_logname() */
struct termio termio; /* terminal mode bits */
static struct options options = {
@@ -251,7 +253,13 @@ main(argc, argv)
/* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */
termio_init(&termio, options.speeds[FIRST_SPEED], options.flags & F_LOCAL);
-
+
+ /* write the modem init string and flush the buffers */
+ if (options.flags & F_INITSTRING) {
+ write(1, options.initstring, strlen(options.initstring));
+ ioctl(1, TCFLSH, 2);
+ }
+
/* Optionally detect the baud rate from the modem status message. */
if (options.flags & F_PARSE)
@@ -262,6 +270,16 @@ main(argc, argv)
if (options.timeout)
(void) alarm((unsigned) options.timeout);
+ /* optionally wait for CR or LF before writing /etc/issue */
+ if (options.flags & F_WAITCRLF) {
+ char ch;
+
+ while(read(0, &ch, 1) == 1) {
+ ch &= 0x7f; /* strip "parity bit" */
+ if (ch == '\n' || ch == '\r') break;
+ }
+ }
+
/* Read the login name. */
while ((logname = get_logname(&options, &chardata, &termio)) == 0)
@@ -299,8 +317,48 @@ parse_args(argc, argv, op)
extern int optind; /* getopt */
int c;
- while (isascii(c = getopt(argc, argv, "Lhil:mt:"))) {
+ while (isascii(c = getopt(argc, argv, "I:Lhil:mt:w"))) {
switch (c) {
+ case 'I':
+ if (!(op->initstring = malloc(strlen(optarg)))) {
+ error("can't malloc initstring");
+ break;
+ }
+ {
+ char ch, *p, *q;
+ int i;
+
+ /* copy optarg into op->initstring decoding \ddd
+ octal codes into chars */
+ q = op->initstring;
+ p = optarg;
+ while (*p) {
+ if (*p == '\\') { /* know \\ means \ */
+ p++;
+ if (*p == '\\') {
+ ch = '\\';
+ p++;
+ } else { /* handle \000 - \177 */
+ ch = 0;
+ for (i = 1; i <= 3; i++) {
+ if (*p >= '0' && *p <= '7') {
+ ch <<= 3;
+ ch += *p - '0';
+ p++;
+ } else
+ break;
+ }
+ }
+ *q++ = ch;
+ } else {
+ *q++ = *p++;
+ }
+ }
+ *q = '\0';
+ }
+ op->flags |= F_INITSTRING;
+ break;
+
case 'L': /* force local */
op->flags |= F_LOCAL;
break;
@@ -320,6 +378,9 @@ parse_args(argc, argv, op)
if ((op->timeout = atoi(optarg)) <= 0)
error("bad timeout value: %s", optarg);
break;
+ case 'w':
+ op->flags |= F_WAITCRLF;
+ break;
default:
usage();
}
@@ -379,10 +440,11 @@ update_utmp(line)
long time();
long lseek();
char *strncpy();
+ struct utmp *utp;
/*
* The utmp file holds miscellaneous information about things started by
- * /etc/init and other system-related events. Our purpose is to update
+ * /sbin/init and other system-related events. Our purpose is to update
* the utmp entry for the current process, in particular the process type
* and the tty line we are listening to. Return successfully only if the
* utmp file can be opened for update, and if we are able to find our
@@ -390,24 +452,36 @@ update_utmp(line)
*/
#ifdef linux
- utmpname(_PATH_UTMP);
- memset(&ut, 0, sizeof(ut));
- (void) strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
- (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- (void) strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
- (void) time(&ut.ut_time);
- ut.ut_type = LOGIN_PROCESS;
- ut.ut_pid = mypid;
-
- pututline(&ut);
- endutent();
-
- if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
- flock(ut_fd, LOCK_EX);
- write(ut_fd, &ut, sizeof(ut));
- flock(ut_fd, LOCK_UN);
- close(ut_fd);
- }
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_type == INIT_PROCESS
+ && utp->ut_pid == mypid)) /* nothing */;
+
+ if (utp) {
+ memcpy(&ut, utp, sizeof(ut));
+ } else {
+ /* some inits don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+ }
+ endutent();
+
+ strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = LOGIN_PROCESS;
+ ut.ut_pid = mypid;
+
+ pututline(&ut);
+ endutent();
+
+ if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
+ flock(ut_fd, LOCK_EX);
+ write(ut_fd, &ut, sizeof(ut));
+ flock(ut_fd, LOCK_UN);
+ close(ut_fd);
+ }
#else
if ((ut_fd = open(UTMP_FILE, 2)) < 0) {
error("%s: open for update: %m", UTMP_FILE);
@@ -592,7 +666,7 @@ auto_baud(tp)
buf[nread] = '\0';
for (bp = buf; bp < buf + nread; bp++) {
if (isascii(*bp) && isdigit(*bp)) {
- if (speed = bcode(bp)) {
+ if ((speed = bcode(bp))) {
tp->c_cflag &= ~CBAUD;
tp->c_cflag |= speed;
}
@@ -709,7 +783,7 @@ do_prompt(op, tp)
int users = 0;
struct utmp *ut;
setutent();
- while (ut = getutent())
+ while ((ut = getutent()))
if (ut->ut_type == USER_PROCESS)
users++;
endutent();
@@ -764,7 +838,7 @@ char *get_logname(op, cp, tp)
struct chardata *cp;
struct termio *tp;
{
- char logname[BUFSIZ];
+ static char logname[BUFSIZ];
char *bp;
char c; /* input character, full eight bits */
char ascval; /* low 7 bits of input character */
@@ -860,7 +934,7 @@ char *get_logname(op, cp, tp)
}
/* Handle names with upper case and no lower case. */
- if (cp->capslock = caps_lock(logname)) {
+ if ((cp->capslock = caps_lock(logname))) {
for (bp = logname; *bp; bp++)
if (isupper(*bp))
*bp = tolower(*bp); /* map name to lower case */
diff --git a/login-utils/checktty.c b/login-utils/checktty.c
new file mode 100644
index 000000000..8daa17204
--- /dev/null
+++ b/login-utils/checktty.c
@@ -0,0 +1,423 @@
+/* checktty.c - linked into login, checks user against /etc/usertty
+ Created 25-Aug-95 by Peter Orbaek <poe@daimi.aau.dk>
+*/
+
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <netdb.h>
+#include <sys/syslog.h>
+
+#ifdef linux
+# include <sys/sysmacros.h>
+# include <linux/major.h>
+#endif
+
+#include "pathnames.h"
+
+/* functions in login.c */
+void badlogin(char *s);
+void sleepexit(int);
+extern struct hostent hostaddress;
+extern char *hostname;
+
+#ifdef TESTING
+struct hostent hostaddress;
+char *hostname;
+
+void
+badlogin(char *s)
+{
+ printf("badlogin: %s\n", s);
+}
+
+void
+sleepexit(int x)
+{
+ printf("sleepexit %d\n", x);
+ exit(1);
+}
+#endif
+
+#define NAMELEN 128
+
+/* linked list of names */
+struct grplist {
+ struct grplist *next;
+ char name[NAMELEN];
+};
+
+struct grplist *mygroups = NULL;
+
+enum State { StateUsers, StateGroups, StateClasses };
+
+#define CLASSNAMELEN 32
+
+struct ttyclass {
+ struct grplist *first;
+ struct ttyclass *next;
+ char classname[CLASSNAMELEN];
+};
+
+struct ttyclass *ttyclasses = NULL;
+
+static void
+add_group(char *group)
+{
+ struct grplist *ge;
+
+ ge = (struct grplist *)malloc(sizeof(struct grplist));
+
+ /* we can't just bail out at this stage! */
+ if (!ge) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc grplist");
+ return;
+ }
+
+ ge->next = mygroups;
+ strncpy(ge->name, group, NAMELEN);
+ mygroups = ge;
+}
+
+static int
+am_in_group(char *group)
+{
+ struct grplist *ge;
+
+ for (ge = mygroups; ge; ge = ge->next) {
+ if (strcmp(ge->name, group) == 0) return 1;
+ }
+ return 0;
+}
+
+static void
+find_groups(gid_t defgrp, char *user)
+{
+ struct group *gp;
+ char **p;
+
+ setgrent();
+ while ((gp = getgrent())) {
+ if (gp->gr_gid == defgrp) {
+ add_group(gp->gr_name);
+ } else {
+ for(p = gp->gr_mem; *p; p++) {
+ if (strcmp(user, *p) == 0) {
+ add_group(gp->gr_name);
+ break;
+ }
+ }
+ }
+
+ }
+ endgrent();
+}
+
+static struct ttyclass *
+new_class(char *class)
+{
+ struct ttyclass *tc;
+
+ tc = (struct ttyclass *)malloc(sizeof(struct ttyclass));
+ if (tc == NULL) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc for ttyclass");
+ return NULL;
+ }
+
+ tc->next = ttyclasses;
+ tc->first = NULL;
+ strncpy(tc->classname, class, CLASSNAMELEN);
+ ttyclasses = tc;
+ return tc;
+}
+
+static void
+add_to_class(struct ttyclass *tc, char *tty)
+{
+ struct grplist *ge;
+
+ if (tc == NULL) return;
+
+ ge = (struct grplist *)malloc(sizeof(struct grplist));
+ if (ge == NULL) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc for grplist");
+ return;
+ }
+
+ ge->next = tc->first;
+ strncpy(ge->name, tty, NAMELEN);
+ tc->first = ge;
+}
+
+
+/* return true if tty is a pty. Very linux dependent */
+static int
+isapty(tty)
+ char *tty;
+{
+ char devname[100];
+ struct stat stb;
+
+#ifdef linux
+ strcpy(devname, "/dev/");
+ strncat(devname, tty, 80);
+ if((stat(devname, &stb) >= 0)
+ && major(stb.st_rdev) == TTY_MAJOR
+ && minor(stb.st_rdev) >= 192) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/* match the hostname hn against the pattern pat */
+static int
+hnmatch(hn, pat)
+ char *hn;
+ char *pat;
+{
+ int x1, x2, x3, x4, y1, y2, y3, y4;
+ unsigned long p, mask, a;
+ unsigned char *ha;
+ int n, m;
+
+ if ((hn == NULL) && (strcmp(pat, "localhost") == 0)) return 1;
+ if ((hn == NULL) || hn[0] == 0) return 0;
+
+ if (pat[0] >= '0' && pat[0] <= '9') {
+ /* pattern is an IP QUAD address and a mask x.x.x.x/y.y.y.y */
+ sscanf(pat, "%d.%d.%d.%d/%d.%d.%d.%d", &x1, &x2, &x3, &x4,
+ &y1, &y2, &y3, &y4);
+ p = (((unsigned long)x1<<24)+((unsigned long)x2<<16)
+ +((unsigned long)x3<<8)+((unsigned long)x4));
+ mask = (((unsigned long)y1<<24)+((unsigned long)y2<<16)
+ +((unsigned long)y3<<8)+((unsigned long)y4));
+
+ if (!hostaddress.h_addr_list || !hostaddress.h_addr_list[0])
+ return 0;
+
+ ha = (unsigned char *)hostaddress.h_addr_list[0];
+ a = (((unsigned long)ha[0]<<24)+((unsigned long)ha[1]<<16)
+ +((unsigned long)ha[2]<<8)+((unsigned long)ha[3]));
+ return ((p & mask) == (a & mask));
+ } else {
+ /* pattern is a suffix of a FQDN */
+ n = strlen(pat);
+ m = strlen(hn);
+ if (n > m) return 0;
+ return (strcasecmp(pat, hn + m - n) == 0);
+ }
+}
+
+static char *wdays[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
+
+/* example timespecs:
+
+ mon:tue:wed:8-17
+
+ meaning monday, tuesday or wednesday between 8:00 and 17:59
+
+ 4:5:13:fri
+
+ meaning fridays from 4:00 to 5:59 and from 13:00 to 13:59
+*/
+static int
+timeok(struct tm *t, char *spec)
+{
+ char *p, *q;
+ int dayok = 0;
+ int hourok = 0;
+ int h, h2;
+ char *sp;
+
+ sp = spec;
+ while ((p = strsep(&sp, ":"))) {
+ if (*p >= '0' && *p <= '9') {
+ h = atoi(p);
+ if (h == t->tm_hour) hourok = 1;
+ if ((q = strchr(p, '-')) && (q[1] >= '0' && q[1] <= '9')) {
+ h2 = atoi(q+1);
+ if (h <= t->tm_hour && t->tm_hour <= h2) hourok = 1;
+ }
+ } else if (strcasecmp(wdays[t->tm_wday], p) == 0) {
+ dayok = 1;
+ }
+ }
+
+ return (dayok && hourok);
+}
+
+/* return true if tty equals class or is in the class defined by class.
+ Also return true if hostname matches the hostname pattern, class
+ or a pattern in the class named by class. */
+static int
+in_class(char *tty, char *class)
+{
+ struct ttyclass *tc;
+ struct grplist *ge;
+ time_t t;
+ char *p;
+ char timespec[256];
+ struct tm *tm;
+ char *n;
+
+ time(&t);
+ tm = localtime(&t);
+
+ if (class[0] == '[') {
+ if ((p = strchr(class, ']'))) {
+ *p = 0;
+ strcpy(timespec, class+1);
+ *p = ']';
+ if(!timeok(tm, timespec)) return 0;
+ class = p+1;
+ }
+ /* really ought to warn about syntax error */
+ }
+
+ if (strcmp(tty, class) == 0) return 1;
+
+ if ((class[0] == '@') && isapty(tty)
+ && hnmatch(hostname, class+1)) return 1;
+
+ for (tc = ttyclasses; tc; tc = tc->next) {
+ if (strcmp(tc->classname, class) == 0) {
+ for (ge = tc->first; ge; ge = ge->next) {
+
+ n = ge->name;
+ if (n[0] == '[') {
+ if ((p = strchr(n, ']'))) {
+ *p = 0;
+ strcpy(timespec, n+1);
+ *p = ']';
+ if(!timeok(tm, timespec)) continue;
+ n = p+1;
+ }
+ /* really ought to warn about syntax error */
+ }
+
+ if (strcmp(n, tty) == 0) return 1;
+
+ if ((n[0] == '@') && isapty(tty)
+ && hnmatch(hostname, n+1)) return 1;
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+void
+checktty(user, tty, pwd)
+ char *user;
+ char *tty;
+ struct passwd *pwd;
+{
+ FILE *f;
+ char buf[256], defaultbuf[256];
+ char *ptr;
+ enum State state = StateUsers;
+ int found_match = 0;
+
+ /* no /etc/usertty, default to allow access */
+#ifdef TESTING
+ if (!(f = fopen("usertty", "r"))) return;
+#else
+ if (!(f = fopen(_PATH_USERTTY, "r"))) return;
+#endif
+
+ if (pwd == NULL) return; /* misspelled username handled elsewhere */
+
+ find_groups(pwd->pw_gid, user);
+
+ defaultbuf[0] = 0;
+ while(fgets(buf, 255, f)) {
+
+ /* strip comments */
+ for(ptr = buf; ptr < buf + 256; ptr++)
+ if(*ptr == '#') *ptr = 0;
+
+ if (buf[0] == '*') {
+ strncpy(defaultbuf, buf, 256);
+ continue;
+ }
+
+ if (strncmp("GROUPS", buf, 6) == 0) {
+ state = StateGroups;
+ continue;
+ } else if (strncmp("USERS", buf, 5) == 0) {
+ state = StateUsers;
+ continue;
+ } else if (strncmp("CLASSES", buf, 7) == 0) {
+ state = StateClasses;
+ continue;
+ }
+
+ strtok(buf, " \t");
+ if((state == StateUsers && (strncmp(user, buf, 8) == 0))
+ || (state == StateGroups && am_in_group(buf))) {
+ found_match = 1; /* we found a line matching the user */
+ while((ptr = strtok(NULL, "\t\n "))) {
+ if (in_class(tty, ptr)) {
+ fclose(f);
+ return;
+ }
+ }
+ } else if (state == StateClasses) {
+ /* define a new tty/host class */
+ struct ttyclass *tc = new_class(buf);
+
+ while ((ptr = strtok(NULL, "\t\n "))) {
+ add_to_class(tc, ptr);
+ }
+ }
+ }
+ fclose(f);
+
+ /* user is not explicitly mentioned in /etc/usertty, if there was
+ a default rule, use that */
+ if (defaultbuf[0]) {
+ strtok(defaultbuf, " \t");
+ while((ptr = strtok(NULL, "\t\n "))) {
+ if (in_class(tty, ptr)) return;
+ }
+
+ /* there was a default rule, but user didn't match, reject! */
+ printf("Login on %s from %s denied by default.\n", tty, hostname);
+ badlogin(user);
+ sleepexit(1);
+ }
+
+ if (found_match) {
+ /* if we get here, /etc/usertty exists, there's a line
+ matching our username, but it doesn't contain the
+ name of the tty where the user is trying to log in.
+ So deny access! */
+
+ printf("Login on %s from %s denied.\n", tty, hostname);
+ badlogin(user);
+ sleepexit(1);
+ }
+
+ /* users not matched in /etc/usertty are by default allowed access
+ on all tty's */
+}
+
+#ifdef TESTING
+main(int argc, char *argv[])
+{
+ struct passwd *pw;
+
+ pw = getpwnam(argv[1]);
+ checktty(argv[1], argv[2], pw);
+}
+#endif
diff --git a/login-utils/chfn.1 b/login-utils/chfn.1
index 9be9fff0a..5e8369ba6 100644
--- a/login-utils/chfn.1
+++ b/login-utils/chfn.1
@@ -6,9 +6,9 @@
.\" modify it under the terms of the gnu general public license.
.\" there is no warranty.
.\"
-.\" faith
-.\" 1.1.1.1
-.\" 1995/02/22 19:09:24
+.\" $Author: faith $
+.\" $Revision: 1.1 $
+.\" $Date: 1995/03/12 01:29:16 $
.\"
.TH CHFN 1 "October 13 1994" "chfn" "Linux Reference Manual"
.SH NAME
diff --git a/login-utils/chfn.c b/login-utils/chfn.c
index 2effa85d2..207bcb254 100644
--- a/login-utils/chfn.c
+++ b/login-utils/chfn.c
@@ -6,13 +6,16 @@
* modify it under the terms of the gnu general public license.
* there is no warranty.
*
- * faith
- * 1.1.1.1
- * 1995/02/22 19:09:24
+ * $Author: faith $
+ * $Revision: 1.8 $
+ * $Date: 1995/10/12 14:46:35 $
+ *
+ * Updated Thu Oct 12 09:19:26 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
*
*/
-#define _POSIX_SOURCE 1
+static char rcsId[] = "$Version: $Id: chfn.c,v 1.8 1995/10/12 14:46:35 faith Exp $ $";
#include <sys/types.h>
#include <stdio.h>
@@ -35,7 +38,7 @@ typedef unsigned char boolean;
#define false 0
#define true 1
-static char *version_string = "chfn 0.9 beta";
+static char *version_string = "chfn 0.9a beta";
static char *whoami;
static char buf[1024];
@@ -59,15 +62,17 @@ static int check_gecos_string P((char *msg, char *gecos));
static boolean set_changed_data P((struct finfo *oldfp, struct finfo *newfp));
static int save_new_data P((struct finfo *pinfo));
static void *xmalloc P((int bytes));
+#if 0
extern int strcasecmp P((char *, char *));
extern int setpwnam P((struct passwd *pwd));
+#endif
#define memzero(ptr, size) memset((char *) ptr, 0, size)
int main (argc, argv)
int argc;
char *argv[];
{
- char *cp;
+ char *cp, *pwdstr;
uid_t uid;
struct finfo oldf, newf;
boolean interactive;
@@ -80,8 +85,6 @@ int main (argc, argv)
for (cp = whoami; *cp; cp++)
if (*cp == '/') whoami = cp + 1;
- umask (022);
-
/*
* "oldf" contains the users original finger information.
* "newf" contains the changed finger information, and contains NULL
@@ -117,7 +120,22 @@ int main (argc, argv)
perror (whoami);
return (-1);
}
-
+
+ printf ("Changing finger information for %s.\n", oldf.username);
+
+#if REQUIRE_PASSWORD
+ /* require password, unless root */
+ if(uid != 0 && oldf.pw->pw_passwd && oldf.pw->pw_passwd[0]) {
+ pwdstr = getpass("Password: ");
+ if(strncmp(oldf.pw->pw_passwd,
+ crypt(pwdstr, oldf.pw->pw_passwd), 13)) {
+ puts("Incorrect password.");
+ exit(1);
+ }
+ }
+#endif
+
+
if (interactive) ask_info (&oldf, &newf);
if (! set_changed_data (&oldf, &newf)) {
@@ -268,7 +286,6 @@ static void ask_info (oldfp, newfp)
struct finfo *oldfp;
struct finfo *newfp;
{
- printf ("Changing finger information for %s.\n", oldfp->username);
newfp->full_name = prompt ("Name", oldfp->full_name);
newfp->office = prompt ("Office", oldfp->office);
newfp->office_phone = prompt ("Office Phone", oldfp->office_phone);
@@ -391,6 +408,7 @@ static int save_new_data (pinfo)
pinfo->pw->pw_gecos = gecos;
if (setpwnam (pinfo->pw) < 0) {
perror ("setpwnam");
+ printf( "Finger information *NOT* changed. Try again later.\n" );
return (-1);
}
printf ("Finger information changed.\n");
diff --git a/login-utils/chsh.1 b/login-utils/chsh.1
index ec278fb4f..57ded2902 100644
--- a/login-utils/chsh.1
+++ b/login-utils/chsh.1
@@ -6,9 +6,9 @@
.\" modify it under the terms of the gnu general public license.
.\" there is no warranty.
.\"
-.\" faith
-.\" 1.1.1.1
-.\" 1995/02/22 19:09:23
+.\" $Author: faith $
+.\" $Revision: 1.1 $
+.\" $Date: 1995/03/12 01:28:58 $
.\"
.TH CHSH 1 "October 13 1994" "chsh" "Linux Reference Manual"
.SH NAME
diff --git a/login-utils/chsh.c b/login-utils/chsh.c
index 9a9a52e85..9ffd81b2f 100644
--- a/login-utils/chsh.c
+++ b/login-utils/chsh.c
@@ -6,13 +6,20 @@
* modify it under the terms of the gnu general public license.
* there is no warranty.
*
- * faith
- * 1.1.1.1
- * 1995/02/22 19:09:23
+ * $Author: faith $
+ * $Revision: 1.8 $
+ * $Date: 1995/10/12 14:46:35 $
+ *
+ * Updated Thu Oct 12 09:33:15 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
*
*/
+static char rcsId[] = "$Version: $Id: chsh.c,v 1.8 1995/10/12 14:46:35 faith Exp $ $";
+
+#if 0
#define _POSIX_SOURCE 1
+#endif
#include <sys/types.h>
#include <stdio.h>
@@ -35,7 +42,7 @@ typedef unsigned char boolean;
#define false 0
#define true 1
-static char *version_string = "chsh 0.9 beta";
+static char *version_string = "chsh 0.9a beta";
static char *whoami;
static char buf[FILENAME_MAX];
@@ -58,7 +65,7 @@ int main (argc, argv)
int argc;
char *argv[];
{
- char *cp, *shell;
+ char *cp, *shell, *oldshell, *pwdstr;
uid_t uid;
struct sinfo info;
struct passwd *pw;
@@ -70,8 +77,6 @@ int main (argc, argv)
for (cp = whoami; *cp; cp++)
if (*cp == '/') whoami = cp + 1;
- umask (022);
-
uid = getuid ();
memzero (&info, sizeof (info));
@@ -91,28 +96,55 @@ int main (argc, argv)
return (-1); }
}
+ oldshell = pw->pw_shell;
+ if (!oldshell[0]) oldshell = "/bin/sh";
+
/* reality check */
+#if 0
+ /* Require current shell to be in list.
+ This is not a reasonable expectation on
+ most Linux systems, and the error is
+ confusing. */
+ if (uid != 0 && (uid != pw->pw_uid || !get_shell_list(oldshell))) {
+#else
if (uid != 0 && uid != pw->pw_uid) {
+#endif
errno = EACCES;
perror (whoami);
return (-1);
}
shell = info.shell;
+
+ printf( "Changing shell for %s.\n", pw->pw_name );
+
+#ifdef REQUIRE_PASSWORD
+ /* require password, unless root */
+ if(uid != 0 && pw->pw_passwd && pw->pw_passwd[0]) {
+ pwdstr = getpass("Password: ");
+ if(strncmp(pw->pw_passwd, crypt(pwdstr, pw->pw_passwd), 13)) {
+ puts("Incorrect password.");
+ exit(1);
+ }
+ }
+#endif
+
if (! shell) {
- printf ("Changing shell for %s.\n", pw->pw_name);
- shell = prompt ("New shell", pw->pw_shell);
+ shell = prompt ("New shell", oldshell);
if (! shell) return 0;
}
+
if (check_shell (shell) < 0) return (-1);
if (! strcmp (pw->pw_shell, shell)) {
printf ("Shell not changed.\n");
return 0;
}
+ if (!strcmp(shell, "/bin/sh")) shell = "";
pw->pw_shell = shell;
if (setpwnam (pw) < 0) {
perror ("setpwnam");
+ printf( "Shell *NOT* changed. Try again later.\n" );
return (-1);
}
printf ("Shell changed.\n");
@@ -252,8 +284,23 @@ static int check_shell (shell)
return (-1);
}
}
- if (! get_shell_list (shell))
- printf ("warning: \"%s\" is not listed as a valid shell.\n", shell);
+#if ONLY_LISTED_SHELLS
+ if (! get_shell_list (shell)) {
+ if (!getuid())
+ printf ("Warning: \"%s\" is not listed as a valid shell.\n", shell);
+ else {
+ printf ("%s: \"%s\" is not listed as a valid shell.\n",
+ whoami, shell);
+ printf( "%s: use -l option to see list\n" );
+ exit(1);
+ }
+ }
+#else
+ if (! get_shell_list (shell)) {
+ printf ("Warning: \"%s\" is not listed as a valid shell.\n", shell);
+ printf( "Use %s -l to see list.\n", whoami );
+ }
+#endif
return 0;
}
diff --git a/login-utils/last.1 b/login-utils/last.1
index 44e6b8270..f2c1d1d2b 100644
--- a/login-utils/last.1
+++ b/login-utils/last.1
@@ -44,7 +44,7 @@ continues.
limit the number of entries displayed to that specified by \fInumber\fP.
.IP "\fB\-f\fP \fIfilename\fP"
Use \fIfilename\fP as the name of the accounting file instead of
-.BR /etc/wtmp .
+.BR /var/log/wtmp .
.IP "\fB\-h\fP \fIhostname\fP"
List only logins from \fIhostname\fP.
.IP "\fB\-i\fP \fIIP address\fP""
@@ -56,4 +56,4 @@ List only logins on \fItty\fP.
.IP "\fB\-y\fP"
Also report year of dates.
.SH FILES
-/usr/adm/wtmp \(em login data base
+/var/log/wtmp \(em login data base
diff --git a/login-utils/last.1.orig b/login-utils/last.1.orig
new file mode 100644
index 000000000..4d0deb882
--- /dev/null
+++ b/login-utils/last.1.orig
@@ -0,0 +1,49 @@
+.TH LAST 1 "20 March 1992"
+.SH NAME
+last \(em indicate last logins by user or terminal
+.SH SYNOPSIS
+.ad l
+.B last
+.RB [ \-\fP\fInumber\fP ]
+.RB [ \-f
+.IR filename ]
+.RB [ \-t
+.IR tty ]
+.RB [ \-h
+.IR hostname ]
+.RI [ name ...]
+.ad b
+.SH DESCRIPTION
+\fBLast\fP looks back in the \fBwtmp\fP file which records all logins
+and logouts for information about a user, a teletype or any group of
+users and teletypes. Arguments specify names of users or teletypes of
+interest. If multiple arguments are given, the information which
+applies to any of the arguments is printed. For example ``\fBlast root
+console\fP'' would list all of root's sessions as well as all sessions
+on the console terminal. \fBLast\fP displays the sessions of the
+specified users and teletypes, most recent first, indicating the times
+at which the session began, the duration of the session, and the
+teletype which the session took place on. If the session is still
+continuing or was cut short by a reboot, \fBlast\fP so indicates.
+.LP
+The pseudo-user \fBreboot\fP logs in at reboots of the system.
+.LP
+\fBLast\fP with no arguments displays a record of all logins and
+logouts, in reverse order.
+.LP
+If \fBlast\fP is interrupted, it indicates how far the search has
+progressed in \fBwtmp\fP. If interrupted with a quit signal \fBlast\fP
+indicates how far the search has progressed so far, and the search
+continues.
+.SH OPTIONS
+.IP \fB\-\fP\fInumber\fP
+limit the number of entries displayed to that specified by \fInumber\fP.
+.IP "\fB\-\fP \fIfilename\fP"
+Use \fIfilename\fP as the name of the accounting file instead of
+.BR /etc/wtmp .
+.IP "\fB\-t\fP \fItty\fP"
+List only logins on \fItty\fP.
+.IP "\fB\-h\fP \fIhostname\fP"
+List only logins from \fhostname\fP.
+.SH FILES
+/etc/wtmp \(em login data base
diff --git a/login-utils/last.c b/login-utils/last.c
index c00808c2e..bc8294978 100644
--- a/login-utils/last.c
+++ b/login-utils/last.c
@@ -242,6 +242,7 @@ wtmp()
break;
}
if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS
+ && bp->ut_type != DEAD_PROCESS
&& want(bp, YES)) {
print_partial_line(bp);
diff --git a/login-utils/last.c.orig b/login-utils/last.c.orig
new file mode 100644
index 000000000..788aa66a0
--- /dev/null
+++ b/login-utils/last.c.orig
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1987 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)last.c 5.11 (Berkeley) 6/29/88";
+#endif /* not lint */
+
+/*
+ * last
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <utmp.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pathnames.h"
+
+#define SECDAY (24*60*60) /* seconds in a day */
+#define NO 0 /* false/no */
+#define YES 1 /* true/yes */
+
+static struct utmp buf[1024]; /* utmp read buffer */
+
+#define HMAX (int)sizeof(buf[0].ut_host) /* size of utmp host field */
+#define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */
+#define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */
+
+typedef struct arg {
+ char *name; /* argument */
+#define HOST_TYPE -2
+#define TTY_TYPE -3
+#define USER_TYPE -4
+ int type; /* type of arg */
+ struct arg *next; /* linked list pointer */
+} ARG;
+ARG *arglist; /* head of linked list */
+
+typedef struct ttytab {
+ long logout; /* log out time */
+ char tty[LMAX + 1]; /* terminal name */
+ struct ttytab *next; /* linked list pointer */
+} TTY;
+TTY *ttylist; /* head of linked list */
+
+static long currentout, /* current logout value */
+ maxrec; /* records to display */
+static char *file = _PATH_WTMP; /* wtmp file */
+
+static void wtmp(), addarg(), hostconv();
+static int want();
+TTY *addtty();
+static char *ttyconv();
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int optind;
+ extern char *optarg;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
+ switch((char)ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /*
+ * kludge: last was originally designed to take
+ * a number after a dash.
+ */
+ if (!maxrec)
+ maxrec = atol(argv[optind - 1] + 1);
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ case 'h':
+ hostconv(optarg);
+ addarg(HOST_TYPE, optarg);
+ break;
+ case 't':
+ addarg(TTY_TYPE, ttyconv(optarg));
+ break;
+ case '?':
+ default:
+ fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr);
+ exit(1);
+ }
+ for (argv += optind; *argv; ++argv) {
+#define COMPATIBILITY
+#ifdef COMPATIBILITY
+ /* code to allow "last p5" to work */
+ addarg(TTY_TYPE, ttyconv(*argv));
+#endif
+ addarg(USER_TYPE, *argv);
+ }
+ wtmp();
+ exit(0);
+}
+
+/*
+ * wtmp --
+ * read through the wtmp file
+ */
+static void
+wtmp()
+{
+ register struct utmp *bp; /* current structure */
+ register TTY *T; /* tty list entry */
+ struct stat stb; /* stat of file for size */
+ long bl, delta, /* time difference */
+ lseek(), time();
+ int bytes, wfd;
+ void onintr();
+ char *ct, *crmsg;
+
+ if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) {
+ perror(file);
+ exit(1);
+ }
+ bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
+
+ (void)time(&buf[0].ut_time);
+ (void)signal(SIGINT, onintr);
+ (void)signal(SIGQUIT, onintr);
+
+ while (--bl >= 0) {
+ if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 ||
+ (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) {
+ fprintf(stderr, "last: %s: ", file);
+ perror((char *)NULL);
+ exit(1);
+ }
+ for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
+ /*
+ * if the terminal line is '~', the machine stopped.
+ * see utmp(5) for more info.
+ */
+ if (!strncmp(bp->ut_line, "~", LMAX)) {
+ /* everybody just logged out */
+ for (T = ttylist; T; T = T->next)
+ T->logout = -bp->ut_time;
+ currentout = -bp->ut_time;
+ crmsg = strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down ";
+ if (!bp->ut_name[0])
+ (void)strcpy(bp->ut_name, "reboot");
+ if (want(bp, NO)) {
+ ct = ctime(&bp->ut_time);
+ if(bp->ut_type != LOGIN_PROCESS)
+ printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
+ if (maxrec && !--maxrec)
+ return;
+ }
+ continue;
+ }
+ /* find associated tty */
+ for (T = ttylist;; T = T->next) {
+ if (!T) {
+ /* add new one */
+ T = addtty(bp->ut_line);
+ break;
+ }
+ if (!strncmp(T->tty, bp->ut_line, LMAX))
+ break;
+ }
+ if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS
+ && want(bp, YES)) {
+ ct = ctime(&bp->ut_time);
+ printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
+ if (!T->logout)
+ puts(" still logged in");
+ else {
+ if (T->logout < 0) {
+ T->logout = -T->logout;
+ printf("- %s", crmsg);
+ }
+ else
+ printf("- %5.5s", ctime(&T->logout)+11);
+ delta = T->logout - bp->ut_time;
+ if (delta < SECDAY)
+ printf(" (%5.5s)\n", asctime(gmtime(&delta))+11);
+ else
+ printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11);
+ }
+ if (maxrec != -1 && !--maxrec)
+ return;
+ }
+ T->logout = bp->ut_time;
+ }
+ }
+ ct = ctime(&buf[0].ut_time);
+ printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
+}
+
+/*
+ * want --
+ * see if want this entry
+ */
+static int
+want(bp, check)
+ register struct utmp *bp;
+ int check;
+{
+ register ARG *step;
+
+ if (check)
+ /*
+ * when uucp and ftp log in over a network, the entry in
+ * the utmp file is the name plus their process id. See
+ * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
+ */
+ if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
+ bp->ut_line[3] = '\0';
+ else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
+ bp->ut_line[4] = '\0';
+ if (!arglist)
+ return(YES);
+
+ for (step = arglist; step; step = step->next)
+ switch(step->type) {
+ case HOST_TYPE:
+ if (!strncmp(step->name, bp->ut_host, HMAX))
+ return(YES);
+ break;
+ case TTY_TYPE:
+ if (!strncmp(step->name, bp->ut_line, LMAX))
+ return(YES);
+ break;
+ case USER_TYPE:
+ if (!strncmp(step->name, bp->ut_name, NMAX))
+ return(YES);
+ break;
+ }
+ return(NO);
+}
+
+/*
+ * addarg --
+ * add an entry to a linked list of arguments
+ */
+static void
+addarg(type, arg)
+ int type;
+ char *arg;
+{
+ register ARG *cur;
+
+ if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ cur->next = arglist;
+ cur->type = type;
+ cur->name = arg;
+ arglist = cur;
+}
+
+/*
+ * addtty --
+ * add an entry to a linked list of ttys
+ */
+TTY *
+addtty(ttyname)
+ char *ttyname;
+{
+ register TTY *cur;
+
+ if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ cur->next = ttylist;
+ cur->logout = currentout;
+ memcpy(cur->tty, ttyname, LMAX);
+ return(ttylist = cur);
+}
+
+/*
+ * hostconv --
+ * convert the hostname to search pattern; if the supplied host name
+ * has a domain attached that is the same as the current domain, rip
+ * off the domain suffix since that's what login(1) does.
+ */
+static void
+hostconv(arg)
+ char *arg;
+{
+ static int first = 1;
+ static char *hostdot,
+ name[MAXHOSTNAMELEN];
+ char *argdot;
+
+ if (!(argdot = strchr(arg, '.')))
+ return;
+ if (first) {
+ first = 0;
+ if (gethostname(name, sizeof(name))) {
+ perror("last: gethostname");
+ exit(1);
+ }
+ hostdot = strchr(name, '.');
+ }
+ if (hostdot && !strcmp(hostdot, argdot))
+ *argdot = '\0';
+}
+
+/*
+ * ttyconv --
+ * convert tty to correct name.
+ */
+static char *
+ttyconv(arg)
+ char *arg;
+{
+ char *mval;
+
+ /*
+ * kludge -- we assume that all tty's end with
+ * a two character suffix.
+ */
+ if (strlen(arg) == 2) {
+ /* either 6 for "ttyxx" or 8 for "console" */
+ if (!(mval = malloc((unsigned int)8))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ if (!strcmp(arg, "co"))
+ (void)strcpy(mval, "console");
+ else {
+ (void)strcpy(mval, "tty");
+ (void)strcpy(mval + 3, arg);
+ }
+ return(mval);
+ }
+ if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1))
+ return(arg + 5);
+ return(arg);
+}
+
+/*
+ * onintr --
+ * on interrupt, we inform the user how far we've gotten
+ */
+void
+onintr(signo)
+ int signo;
+{
+ char *ct;
+
+ ct = ctime(&buf[0].ut_time);
+ printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
+ if (signo == SIGINT)
+ exit(1);
+ (void)fflush(stdout); /* fix required for rsh */
+}
diff --git a/login-utils/login.1 b/login-utils/login.1
index e6e30d82a..0e1f5eff8 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -29,6 +29,12 @@ exists, the contents of of this file are printed to the screen, and the
login is terminated. This is typically used to prevent logins when the
system is being taken down.
+If special access restrictions are specified for the user in
+.IR /etc/usertty ,
+these must be met, or the log in attempt will be denied and a
+.B syslog
+message will be generated. See the section on "Special Access Restrictions".
+
If the user is root, then the login must be occuring on a tty listed in
.IR /etc/securetty .
Failures will be logged with the
@@ -49,7 +55,7 @@ If the file
exists, then a "quiet" login is performed (this disables the checking of
the checking of mail and the printing of the last login time and message of
the day). Otherwise, if
-.I /var/adm/lastlog
+.I /var/log/lastlog
exists, the last login time is printed (and the current login is recorded).
Random administrative things, such as setting the UID and GID of the tty
@@ -98,14 +104,183 @@ to pass the name of the remote host to
.B login
so that it may be placed in utmp and wtmp. Only the superuser may use this
option.
+
+.SH "SPECIAL ACCESS RESTRICTIONS"
+The file
+.I /etc/securetty
+lists the names of the ttys where root is allowed to log in. One name of
+a tty device without the /dev/ prefix must be specified on each line.
+If the file does not exist, root is allowed to log in on any tty.
+.PP
+The file
+.I /etc/usertty
+specifies additional access restrictions for specific users. If this file
+does not exist, no additional access restrictions are imposed. The file
+consists of a sequence of sections. There are three possible section
+types: CLASSES, GROUPS and USERS. A CLASSES section defines classes of
+ttys and hostname patterns, A GROUPS section defines allowed ttys and
+hosts on a per group basis, and a USERS section defines allowed ttys
+and hosts on a per user basis.
+.PP
+Each line in this file in may be no longer than 255 characters. Comments
+start with # character and extend to the end of the line.
+.PP
+.SS "The CLASSES Section"
+A CLASSES section begins with the word CLASSES at the start of a line in all
+upper case. Each following line until the start of a new section or the
+end of the file consists of a sequence of words separated by tabs or
+spaces. Each line defines a class of ttys and host patterns.
+.PP
+The word at
+the beginning of a line becomes defined as a collective name for the
+ttys and host patterns specified at the rest of the line. This collective
+name can be used in any subsequent GROUPS or USERS section. No such class
+name must occur as part of the definition of a class in order to avoid
+problems with recursive classes.
+.PP
+An example CLASSES section:
+.PP
+.nf
+.in +.5
+CLASSES
+myclass1 tty1 tty2
+myclass2 tty3 @.foo.com
+.in -.5
+.fi
+.PP
+This defines the classes
+.I myclass1
+and
+.I myclass2
+as the corresponding right hand sides.
+.PP
+
+.SS "The GROUPS Section
+A GROUPS section defines allowed ttys and hosts on a per Unix group basis. If
+a user is a member of a Unix group according to
+.I /etc/passwd
+and
+.I /etc/group
+and such a group is mentioned in a GROUPS section in
+.I /etc/usertty
+then the user is granted access if the group is.
+.PP
+A GROUPS section starts with the word GROUPS in all upper case at the start of
+a line, and each following line is a sequence of words separated by spaces
+or tabs. The first word on a line is the name of the group and the rest
+of the words on the line specifies the ttys and hosts where members of that
+group are allowed access. These specifications may involve the use of
+classes defined in previous CLASSES sections.
+.PP
+An example GROUPS section.
+.PP
+.nf
+.in +0.5
+GROUPS
+sys tty1 @.bar.edu
+stud myclass1 tty4
+.in -0.5
+.fi
+.PP
+This example specifies that members of group
+.I sys
+may log in on tty1 and from hosts in the bar.edu domain. Users in group
+.I stud
+may log in from hosts/ttys specified in the class myclass1 or from tty4.
+.PP
+
+.SS "The USERS Section"
+A USERS section starts with the word USERS in all upper case at the
+start of a line, and each following line is a sequence of words
+separated by spaces or tabs. The first word on a line is a username
+and that user is allowed to log in on the ttys and from the hosts
+mentioned on the rest of the line. These specifications may involve
+classes defined in previous CLASSES sections. If no section header is
+specified at the top of the file, the first section defaults to be a
+USERS section.
+.PP
+An example USERS section:
+.PP
+.nf
+.in +0.5
+USERS
+zacho tty1 @130.225.16.0/255.255.255.0
+blue tty3 myclass2
+.in -0.5
+.fi
+.PP
+This lets the user zacho login only on tty1 and from hosts with IP addreses
+in the range 130.225.16.0 \- 130.225.16.255, and user blue is allowed to
+log in from tty3 and whatever is specified in the class myclass2.
+.PP
+There may be a line in a USERS section starting with a username of *. This
+is a default rule and it will be applied to any user not matching any other
+line.
+.PP
+If both a USERS line and GROUPS line match a user then the user is allowed
+access from the union of all the ttys/hosts mentioned in these specifications.
+
+.SS Origins
+The tty and host pattern specifications used in the specification of classes,
+group and user access are called origins. An origin string may have
+one of these formats:
+.IP o
+The name of a tty device without the /dev/ prefix, for example tty1 or
+ttyS0.
+.PP
+.IP o
+The string @localhost, meaning that the user is allowed to telnet/rlogin
+from the local host to the same host. This also allows the user to for
+example run the command: xterm -e /bin/login.
+.PP
+.IP o
+A domain name suffix such as @.some.dom, meaning that the user may
+rlogin/telnet from any host whose domain name has the suffix .some.dom.
+.PP
+.IP o
+A range of IPv4 addresses, written @x.x.x.x/y.y.y.y where x.x.x.x
+is the IP address in the usual dotted quad decimal notation, and
+y.y.y.y is a bitmask in the same notation specifying which bits in the
+address to compare with the IP address of the remote host. For example
+@130.225.16.0/255.255.254.0 means that the user may rlogin/telnet from
+any host whose IP address is in the range 130.225.16.0 \- 130.225.17.255.
+.PP
+Any of the above origins may be prefixed by a time specification according
+to the syntax:
+.PP
+.nf
+timespec ::= '[' <day-or-hour> [':' <day-or-hour>]* ']'
+day ::= 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun'
+hour ::= '0' | '1' | ... | '23'
+hourspec ::= <hour> | <hour> '\-' <hour>
+day-or-hour ::= <day> | <hourspec>
+.fi
+.PP
+For example, the origin [mon:tue:wed:thu:fri:8\-17]tty3 means that log in is
+allowed on mondays through fridays between 8:00 and 17:59 (5:59 pm) on tty3.
+This also shows that an hour range a\-b includes all moments between a:00 and
+b:59. A single hour specification (such as 10) means the time span between
+10:00 and 10:59.
+.PP
+Not specifying any time prefix for a tty or host means log in from that origin
+is allowed any time. If you give a time prefix be sure to specify both a set
+of days and one or more hours or hour ranges. A time specification may
+not include any white space.
+.PP
+If no default rule is given then users not matching any line
+.I /etc/usertty
+are allowed to log in from anywhere as is standard behavior.
+.PP
.SH FILES
.nf
-.I /etc/utmp
-.I /etc/wtmp
+.I /var/run/utmp
+.I /var/log/wtmp
+.I /var/log/lastlog
.I /usr/spool/mail/*
.I /etc/motd
.I /etc/passwd
.I /etc/nologin
+.I /etc/usertty
.I .hushlogin
.fi
.SH "SEE ALSO"
diff --git a/login-utils/login.c b/login-utils/login.c
index f0130f8ed..33a0b03e7 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -130,8 +130,11 @@ static char sccsid[] = "@(#)login.c 5.40 (Berkeley) 5/9/89";
#ifndef linux
#include <tzfile.h>
+#endif
#include <lastlog.h>
-#else
+
+#if 0
+/* from before we had a lastlog.h file in linux */
struct lastlog
{ long ll_time;
char ll_line[12];
@@ -152,7 +155,7 @@ void checknologin P_((void));
void dolastlog P_((int quiet));
void badlogin P_((char *name));
char *stypeof P_((char *ttyid));
-void checktty P_((char *user, char *tty));
+void checktty P_((char *user, char *tty, struct passwd *pwd));
void getstr P_((char *buf, int cnt, char *err));
void sleepexit P_((int eval));
#undef P_
@@ -164,13 +167,11 @@ char realm[REALM_SZ];
int kerror = KSUCCESS, notickets = 1;
#endif
-#ifndef linux
#define TTYGRPNAME "tty" /* name of group to own ttys */
-#else
-# define TTYGRPNAME "other"
-# ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-# endif
+/**# define TTYGRPNAME "other" **/
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
#endif
/*
@@ -184,9 +185,9 @@ int timeout = 60;
#endif
struct passwd *pwd;
-int failures;
+int failures = 1;
char term[64], *hostname, *username, *tty;
-
+struct hostent hostaddress;
char thishost[100];
#ifndef linux
@@ -265,6 +266,7 @@ main(argc, argv)
(void)strncpy(thishost, tbuf, sizeof(thishost)-1);
domain = index(tbuf, '.');
+ hostname = NULL;
fflag = hflag = pflag = 0;
passwd_req = 1;
while ((ch = getopt(argc, argv, "fh:p")) != EOF)
@@ -284,6 +286,14 @@ main(argc, argv)
strcasecmp(p, domain) == 0)
*p = 0;
hostname = optarg;
+ {
+ struct hostent *he = gethostbyname(hostname);
+ if (he) {
+ memcpy(&hostaddress, he, sizeof(hostaddress));
+ } else {
+ memset(&hostaddress, 0, sizeof(hostaddress));
+ }
+ }
break;
case 'p':
@@ -357,7 +367,7 @@ main(argc, argv)
tcsetattr(0,TCSAFLUSH,&tt);
}
- if (tty = rindex(ttyn, '/'))
+ if ((tty = rindex(ttyn, '/')))
++tty;
else
tty = ttyn;
@@ -375,14 +385,27 @@ main(argc, argv)
getloginname();
}
- checktty(username, tty);
+ /* Dirty patch to fix a gigantic security hole when using
+ yellow pages. This problem should be solved by the
+ libraries, and not by programs, but this must be fixed
+ urgently! If the first char of the username is '+', we
+ avoid login success.
+ Feb 95 <alvaro@etsit.upm.es> */
+
+ if (username[0] == '+') {
+ puts("Illegal username");
+ badlogin(username);
+ sleepexit(1);
+ }
(void)strcpy(tbuf, username);
- if (pwd = getpwnam(username))
+ if ((pwd = getpwnam(username)))
salt = pwd->pw_passwd;
else
salt = "xx";
+ checktty(username, tty, pwd); /* in checktty.c */
+
/* if user not super-user, check for disabled logins */
if (pwd == NULL || pwd->pw_uid)
checknologin();
@@ -566,30 +589,38 @@ main(argc, argv)
/* for linux, write entries in utmp and wtmp */
{
struct utmp ut;
- char *ttyabbrev;
int wtmp;
-
- memset((char *)&ut, 0, sizeof(ut));
- ut.ut_type = USER_PROCESS;
- ut.ut_pid = getpid();
- strncpy(ut.ut_line, ttyn + sizeof("/dev/")-1, sizeof(ut.ut_line));
- ttyabbrev = ttyn + sizeof("/dev/tty") - 1;
- strncpy(ut.ut_id, ttyabbrev, sizeof(ut.ut_id));
- (void)time(&ut.ut_time);
+ struct utmp *utp;
+ pid_t mypid = getpid();
+
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_pid == mypid)) /* nothing */;
+
+ if (utp) {
+ memcpy(&ut, utp, sizeof(ut));
+ } else {
+ /* some gettys/telnetds don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ }
+ endutent();
+
+ if (ut.ut_id[0] == 0)
+ strncpy(ut.ut_id, ttyn + 8, sizeof(ut.ut_id));
+
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
-
- /* fill in host and ip-addr fields when we get networking */
+ strncpy(ut.ut_line, ttyn + 5, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = USER_PROCESS;
+ ut.ut_pid = mypid;
if (hostname) {
- struct hostent *he;
-
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
- if ((he = gethostbyname(hostname)))
- memcpy(&ut.ut_addr, he->h_addr_list[0],
+ if (hostaddress.h_addr_list)
+ memcpy(&ut.ut_addr, hostaddress.h_addr_list[0],
sizeof(ut.ut_addr));
}
-
- utmpname(_PATH_UTMP);
- setutent();
+
pututline(&ut);
endutent();
@@ -600,7 +631,6 @@ main(argc, argv)
close(wtmp);
}
}
- /* fix_utmp_type_and_user(username, ttyn, LOGIN_PROCESS); */
#endif
dolastlog(quietlog);
@@ -615,9 +645,13 @@ main(argc, argv)
(void)chown(ttyn, pwd->pw_uid,
(gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
- (void)chmod(ttyn, 0622);
- (void)setgid(pwd->pw_gid);
+#ifdef USE_TTY_GROUP
+ chmod(ttyn, 0620);
+#else
+ chmod(ttyn, 0600);
+#endif
+ setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
#ifdef HAVE_QUOTA
@@ -676,10 +710,9 @@ main(argc, argv)
(void)setenv("LOGNAME", pwd->pw_name, 1);
#endif
-#ifndef linux
- if (tty[sizeof("tty")-1] == 'd')
+ if (tty[sizeof("tty")-1] == 'S')
syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
-#endif
+
if (pwd->pw_uid == 0)
if (hostname)
syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s",
@@ -748,16 +781,26 @@ getloginname()
register int ch;
register char *p;
static char nbuf[UT_NAMESIZE + 1];
+ int cnt, cnt2;
+ cnt2 = 0;
for (;;) {
+ cnt = 0;
(void)printf("\n%s login: ", thishost); fflush(stdout);
for (p = nbuf; (ch = getchar()) != '\n'; ) {
if (ch == EOF) {
- badlogin(username);
+ badlogin("EOF");
exit(0);
}
if (p < nbuf + UT_NAMESIZE)
*p++ = ch;
+
+ cnt++;
+ if (cnt > UT_NAMESIZE + 20) {
+ fprintf(stderr, "login name much too long.\n");
+ badlogin("NAME too long");
+ exit(0);
+ }
}
if (p > nbuf)
if (nbuf[0] == '-')
@@ -768,6 +811,13 @@ getloginname()
username = nbuf;
break;
}
+
+ cnt2++;
+ if (cnt2 > 50) {
+ fprintf(stderr, "too many bare linefeeds.\n");
+ badlogin("EXCESSIVE linefeeds");
+ exit(0);
+ }
}
}
@@ -898,9 +948,6 @@ void
badlogin(name)
char *name;
{
- if (failures == 0)
- return;
-
if (hostname)
syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s",
failures, failures > 1 ? "S" : "", hostname, name);
@@ -924,62 +971,6 @@ stypeof(ttyid)
#endif
void
-checktty(user, tty)
- char *user;
- char *tty;
-{
- FILE *f;
- char buf[256];
- char *ptr;
- char devname[50];
- struct stat stb;
-
- /* no /etc/usertty, default to allow access */
- if(!(f = fopen(_PATH_USERTTY, "r"))) return;
-
- while(fgets(buf, 255, f)) {
-
- /* strip comments */
- for(ptr = buf; ptr < buf + 256; ptr++)
- if(*ptr == '#') *ptr = 0;
-
- strtok(buf, " \t");
- if(strncmp(user, buf, 8) == 0) {
- while((ptr = strtok(NULL, "\t\n "))) {
- if(strncmp(tty, ptr, 10) == 0) {
- fclose(f);
- return;
- }
- if(strcmp("PTY", ptr) == 0) {
-#ifdef linux
- sprintf(devname, "/dev/%s", ptr);
- /* VERY linux dependent, recognize PTY as alias
- for all pseudo tty's */
- if((stat(devname, &stb) >= 0)
- && major(stb.st_rdev) == 4
- && minor(stb.st_rdev) >= 192) {
- fclose(f);
- return;
- }
-#endif
- }
- }
- /* if we get here, /etc/usertty exists, there's a line
- beginning with our username, but it doesn't contain the
- name of the tty where the user is trying to log in.
- So deny access! */
- fclose(f);
- printf("Login on %s denied.\n", tty);
- badlogin(user);
- sleepexit(1);
- }
- }
- fclose(f);
- /* users not mentioned in /etc/usertty are by default allowed access
- on all tty's */
-}
-
-void
getstr(buf, cnt, err)
char *buf, *err;
int cnt;
diff --git a/login-utils/mesg.1 b/login-utils/mesg.1
index 81932dfd9..4a9f3c9b1 100644
--- a/login-utils/mesg.1
+++ b/login-utils/mesg.1
@@ -1,24 +1,98 @@
-.\" Original author: Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
-.\" Updated by faith@cs.unc.edu, Fri Oct 29 23:22:16 1993
-.TH MESG 1 "29 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.\" Copyright (c) 1987, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)mesg.1 8.1 (Berkeley) 6/6/93
+.\"
+.\" Fri Mar 10 20:31:02 1995, modified for standard man macros,
+.\" faith@cs.unc.edu
+.\"
+.\"
+.\" "
+.TH MESG 1 "10 March 1995" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
-mesg \- control write access to your terminal
+mesg \- display (do not display) messages from other users
.SH SYNOPSIS
-.B mesg
-.RB [y|n]
-.br
+.B mesg [ n ] [ y ]
.SH DESCRIPTION
-.B Mesg
-controls the access to your terminal by others. It's typically used
-to allow/disallow others users to \fBwrite(1)\fP to your terminal.
-.SH FLAGS
-.IP y
-Allow write access to your terminal.
-.IP n
-Disallow write access to your terminal.
-.IP [none]
-Prints out the current access state of your terminal.
-.SH SEE ALSO
-.BR write (1), wall (1)
-.SH AUTHOR
-Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
+The
+.B mesg
+utility is invoked by a users to control write access others have to the
+terminal device associated with the standard error output. If write access
+is allowed, then programs such as
+.BR talk (1)
+and
+.BR write (1)
+may display messages on the terminal.
+.PP
+Traditionally, write access is allowed by default. However, as users
+become more conscious of various security risks, there is a trend to remove
+write access by default, at least for the primary login shell. To make
+sure your ttys are set the way you want them to be set,
+.B mesg
+should be executed in your login scripts.
+.PP
+Options available:
+.TP
+.B n
+Disallows messages.
+.TP
+.B y
+Permits messages to be displayed.
+.PP
+If no arguments are given,
+.B mesg
+displays the present message status to the standard error output.
+.PP
+The
+.B mesg
+utility exits with one of the following values:
+.TP
+.I "\ 0"
+Messages are allowed.
+.TP
+.I "\ 1"
+Messages are not allowed.
+.TP
+.I "\>1"
+An error has occurred.
+.SH FILES
+.I /dev/[pt]ty[pq]?
+.SH "SEE ALSO"
+.BR biff (1),
+.BR talk (1),
+.BR write (1),
+.BR wall (1),
+.BR login (1),
+.BR xterm (1)
+.SH HISTORY
+A
+.B mesg
+command appeared in Version 6 AT&T UNIX.
diff --git a/login-utils/mesg.c b/login-utils/mesg.c
index 07c5fad1f..79d3ef21e 100644
--- a/login-utils/mesg.c
+++ b/login-utils/mesg.c
@@ -1,44 +1,112 @@
/*
- * mesg.c The "mesg" utility. Gives / restrict access to
- * your terminal by others.
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
*
- * Usage: mesg [y|n].
- * Without arguments prints out the current settings.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * Modified Fri Mar 10 20:27:19 1995, faith@cs.unc.edu, for Linux
+ *
*/
-#include <stdio.h>
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mesg.c 8.2 (Berkeley) 1/21/94";
+#endif /* not lint */
+
+#include <sys/types.h>
#include <sys/stat.h>
-#include <stdlib.h>
+
+#include <err.h>
#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-char *Version = "@(#) mesg 1.0 08-12-92 MvS";
-
-int main(int argc, char **argv)
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
{
- struct stat st;
-
- if (!isatty(0)) {
- /* Or should we look in /etc/utmp? */
- fprintf(stderr, "stdin: is not a tty");
- return(1);
- }
-
- if (fstat(0, &st) < 0) {
- perror("fstat");
- return(1);
- }
- if (argc < 2) {
- printf("Is %s\n", ((st.st_mode & 022) == 022) ? "y" : "n");
- return(0);
- }
- if (argc > 2 || (argv[1][0] != 'y' && argv[1][0] != 'n')) {
- fprintf(stderr, "Usage: mesg [y|n]\n");
- return(1);
- }
- if (argv[1][0] == 'y')
- st.st_mode |= 022;
- else
- st.st_mode &= ~022;
- fchmod(0, st.st_mode);
- return(0);
+ struct stat sb;
+ char *tty;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch (ch) {
+ case '?':
+ default:
+ goto usage;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((tty = ttyname(STDERR_FILENO)) == NULL)
+ err(1, "ttyname");
+ if (stat(tty, &sb) < 0)
+ err(1, "%s", tty);
+
+ if (*argv == NULL) {
+ if (sb.st_mode & (S_IWGRP | S_IWOTH)) {
+ (void)fprintf(stderr, "is y\n");
+ exit(0);
+ }
+ (void)fprintf(stderr, "is n\n");
+ exit(1);
+ }
+
+ switch (*argv[0]) {
+ case 'y':
+#ifdef USE_TTY_GROUP
+ if (chmod(tty, sb.st_mode | S_IWGRP) < 0)
+ err(1, "%s", tty);
+#else
+ if (chmod(tty, sb.st_mode | S_IWGRP | S_IWOTH) < 0)
+ err(1, "%s", tty);
+#endif
+ exit(0);
+ case 'n':
+ if (chmod(tty, sb.st_mode & ~(S_IWGRP|S_IWOTH)) < 0)
+ err(1, "%s", tty);
+ exit(1);
+ }
+
+usage: (void)fprintf(stderr, "usage: mesg [y | n]\n");
+ exit(2);
}
diff --git a/login-utils/newgrp.1 b/login-utils/newgrp.1
index 032a5d5aa..de420ecfb 100644
--- a/login-utils/newgrp.1
+++ b/login-utils/newgrp.1
@@ -1,6 +1,6 @@
.\" Original author unknown. This man page is in the public domain.
.\" Modified Sat Oct 9 17:46:48 1993 by faith@cs.unc.edu
-.TH NEWGRP 1 "9 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH NEWGRP 1 "9 October 1993" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
newgrp \- log in to a new group
.SH SYNOPSIS
@@ -22,3 +22,7 @@ If no group is specified, the GID is changed to the login GID.
.SH "SEE ALSO"
.BR login "(1), " group (5)
+
+.SH AUTHOR
+Originally by Michael Haardt. Currently maintained by
+Peter Orbaek (poe@daimi.aau.dk).
diff --git a/login-utils/passwd.1 b/login-utils/passwd.1
index d22c458fa..f2bf9de90 100644
--- a/login-utils/passwd.1
+++ b/login-utils/passwd.1
@@ -1,20 +1,33 @@
.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH PASSWD 1 "22 June 1994" "Linux 1.0" "Linux Programmer's Manual"
+.TH PASSWD 1 "22 June 1994" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
passwd \- change password
.SH SYNOPSIS
-.BR "passwd [ " name " ]"
+.BR "passwd [ " name " [ " password " ] ]"
.SH DESCRIPTION
+Without arguments
.B passwd
-will change the specified user's password. Only the superuser is allowed
-to change other user's passwords. If the user is not root, then the old
-password is prompted for and verified.
+will change the password for the current user. First the user is asked for
+the old password, then prompted twice for the new password in order to
+catch typing errors. The new password must be at least six characters long,
+and have both upper and lower case letters or non-letters. The new password
+must not be equal to the old password, and it must not match the username.
+
+The one and two argument forms may only be used by the superuser. Using the
+one argument form, the superuser may change the password for that user.
+The superuser is not asked for the users old password, and the rules
+for proper passwords are not applied since the superuser may have legitimate
+reasons to choose a non-conformant password.
+
+The two argument form gives the
+.I user
+the password stated as the second argument. This may be useful when
+giving many users an initial generated password.
+
+Giving an empty string as the second argument erases the password for the
+user.
-A new password is prompted for twice, to avoid typing mistakes. Unless the
-user is the superuser, the new password must have more than six characters,
-and must have either both upper and lower case letters, or non-letters.
-Some passwords which are similar to the user's name are not allowed.
.SH FILES
.I /etc/passwd
.br
diff --git a/login-utils/passwd.c b/login-utils/passwd.c
index 5bd6d3abd..1c786e94e 100644
--- a/login-utils/passwd.c
+++ b/login-utils/passwd.c
@@ -5,16 +5,26 @@
/* Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es,
to allow peaceful coexistence with yp. Nov 94. */
+/* Hacked to allow root to set passwd from command line.
+ by Arpad Magossanyi (mag@tas.vein.hu) */
+/*
+ * Usage: passwd [username [password]]
+ * Only root may use the one and two argument forms.
+ */
+
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
+#include <fcntl.h>
#include <pwd.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
+#include <errno.h>
+#include <sys/resource.h>
extern int is_local(char *);
@@ -23,171 +33,225 @@ extern int is_local(char *);
#define MAX_LENGTH 1024
+static void
+pexit(str)
+ char *str;
+{
+ perror(str);
+ exit(1);
+}
+
int
main(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- struct passwd *pe;
- uid_t gotuid = getuid();
- char *pwdstr, *cryptstr;
- char pwdstr1[10];
- int ucase, lcase, other;
- char *p, *q, *user;
- time_t tm;
- char salt[2];
- FILE *fd_in, *fd_out;
- char line[MAX_LENGTH];
- int error=0;
- int r;
-
- umask(022);
+ struct passwd *pe;
+ uid_t gotuid = getuid();
+ char *pwdstr = NULL, *cryptstr, *oldstr;
+ char pwdstr1[10];
+ int ucase, lcase, other;
+ char *p, *q, *user;
+ time_t tm;
+ char salt[2];
+ FILE *fd_in, *fd_out;
+ char line[MAX_LENGTH];
+ char colonuser[16];
+ int error=0;
+ int r;
+ int ptmp;
+#ifndef USE_SETPWNAM
+ struct rlimit rlim;
+#endif
- if(argc > 2) {
- puts("Too many arguments");
- exit(1);
- } else if(argc == 2) {
- if(gotuid) {
- puts("Only root can change the password for others");
- exit(1);
- }
- user = argv[1];
- } else {
- if (!(user = getlogin())) {
- if (!(pe = getpwuid( getuid() ))) {
- puts("Cannot find login name");
- exit(1);
- } else
- user = pe->pw_name;
- }
+ if(argc > 3) {
+ puts("Too many arguments");
+ exit(1);
+ } else if(argc >= 2) {
+ if(gotuid) {
+ puts("Only root can change the password for others");
+ exit(1);
}
-
- if(!(pe = getpwnam(user))) {
- puts("Can't find username anywhere. Are you really a user?");
- exit(1);
+ user = argv[1];
+
+ if (argc == 3) pwdstr = argv[2];
+
+ } else {
+ if (!(user = getlogin())) {
+ if (!(pe = getpwuid( getuid() ))) {
+ pexit("Cannot find login name");
+ } else
+ user = pe->pw_name;
}
+ }
- if (!(is_local(user))) {
- puts("Sorry, I can only change local passwords. Use yppasswd instead.");
- exit(1);
- }
+#ifndef USE_SETPWNAM
+ umask(022);
- /* if somebody got into changing utmp... */
- if(gotuid && gotuid != pe->pw_uid) {
- puts("UID and username does not match, imposter!");
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_CPU, &rlim);
+ setrlimit(RLIMIT_FSIZE, &rlim);
+ setrlimit(RLIMIT_STACK, &rlim);
+ setrlimit(RLIMIT_DATA, &rlim);
+ setrlimit(RLIMIT_RSS, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+#endif
+
+ if(!(pe = getpwnam(user))) {
+ pexit("Can't find username anywhere. Are you really a user?");
+ }
+
+ if (!(is_local(user))) {
+ puts("Sorry, I can only change local passwords. Use yppasswd instead.");
+ exit(1);
+ }
+
+ /* if somebody got into changing utmp... */
+ if(gotuid && gotuid != pe->pw_uid) {
+ puts("UID and username does not match, imposter!");
+ exit(1);
+ }
+
+ printf( "Changing password for %s\n", user );
+
+ if(gotuid && pe->pw_passwd && pe->pw_passwd[0]) {
+ oldstr = getpass("Enter old password: ");
+ if(strncmp(pe->pw_passwd, crypt(oldstr, pe->pw_passwd), 13)) {
+ puts("Illegal password, imposter.");
exit(1);
}
+ }
- printf( "Changing password for %s\n", user );
-
- if(gotuid && pe->pw_passwd && pe->pw_passwd[0]) {
- pwdstr = getpass("Enter old password: ");
- if(strncmp(pe->pw_passwd, crypt(pwdstr, pe->pw_passwd), 13)) {
- puts("Illegal password, imposter.");
- exit(1);
- }
- }
+ if (!pwdstr) {
+ /* password not set on command line by root, ask for it ... */
-redo_it:
+ redo_it:
pwdstr = getpass("Enter new password: ");
- strncpy(pwdstr1, pwdstr, 9);
- pwdstr = getpass("Re-type new password: ");
-
- if(strncmp(pwdstr, pwdstr1, 8)) {
- puts("You misspelled it. Password not changed.");
- exit(0);
+ if (pwdstr[0] == '\0') {
+ puts("Password not changed.");
+ exit(1);
}
if((strlen(pwdstr) < 6) && gotuid) {
- puts("The password must have at least 6 characters, try again.");
- goto redo_it;
+ puts("The password must have at least 6 characters, try again.");
+ goto redo_it;
}
other = ucase = lcase = 0;
for(p = pwdstr; *p; p++) {
- ucase = ucase || isupper(*p);
- lcase = lcase || islower(*p);
- other = other || !isalpha(*p);
+ ucase = ucase || isupper(*p);
+ lcase = lcase || islower(*p);
+ other = other || !isalpha(*p);
}
if((!ucase || !lcase) && !other && gotuid) {
- puts("The password must have both upper- and lowercase");
- puts("letters, or non-letters; try again.");
- goto redo_it;
+ puts("The password must have both upper- and lowercase");
+ puts("letters, or non-letters; try again.");
+ goto redo_it;
+ }
+
+ if (pe->pw_passwd[0]
+ && !strncmp(pe->pw_passwd, crypt(pwdstr, pe->pw_passwd), 13)
+ && gotuid) {
+ puts("You cannot reuse the old password.");
+ goto redo_it;
}
r = 0;
for(p = pwdstr, q = pe->pw_name; *q && *p; q++, p++) {
- if(tolower(*p) != tolower(*q)) {
- r = 1;
- break;
- }
+ if(tolower(*p) != tolower(*q)) {
+ r = 1;
+ break;
+ }
}
-
+
for(p = pwdstr + strlen(pwdstr)-1, q = pe->pw_name;
*q && p >= pwdstr; q++, p--) {
- if(tolower(*p) != tolower(*q)) {
- r += 2;
- break;
- }
+ if(tolower(*p) != tolower(*q)) {
+ r += 2;
+ break;
+ }
}
-
+
if(gotuid && r != 3) {
- puts("Please don't use something like your username as password!");
- goto redo_it;
+ puts("Please don't use something like your username as password!");
+ goto redo_it;
}
-
+
/* do various other checks for stupid passwords here... */
-
- time(&tm);
- salt[0] = bin_to_ascii(tm & 0x3f);
- salt[1] = bin_to_ascii((tm >> 5) & 0x3f);
- cryptstr = crypt(pwdstr, salt);
- if(access("/etc/ptmp", F_OK) == 0) {
- puts("/etc/ptmp exists, can't change password");
- exit(1);
- }
+ strncpy(pwdstr1, pwdstr, 9);
+ pwdstr = getpass("Re-type new password: ");
- if(!(fd_out = fopen("/etc/ptmp", "w"))) {
- puts("Can't open /etc/ptmp, can't update password");
- exit(1);
+ if(strncmp(pwdstr, pwdstr1, 8)) {
+ puts("You misspelled it. Password not changed.");
+ exit(1);
}
+ } /* pwdstr != argv[2] i.e. password set on command line */
+
+ time(&tm);
+ salt[0] = bin_to_ascii(tm & 0x3f);
+ salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
+ cryptstr = crypt(pwdstr, salt);
+
+ if (pwdstr[0] == 0) cryptstr = "";
- if(!(fd_in = fopen("/etc/passwd", "r"))) {
- puts("Can't read /etc/passwd, can't update password");
- exit(1);
+#ifdef USE_SETPWNAM
+ pe->pw_passwd = cryptstr;
+ if (setpwnam( pe ) < 0) {
+ perror( "setpwnam" );
+ printf( "Password *NOT* changed. Try again later.\n" );
+ exit( 1 );
+ }
+#else
+ if ((ptmp = open("/etc/ptmp", O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) {
+ pexit("Can't exclusively open /etc/ptmp, can't update password");
+ }
+ fd_out = fdopen(ptmp, "w");
+
+ if(!(fd_in = fopen("/etc/passwd", "r"))) {
+ pexit("Can't read /etc/passwd, can't update password");
+ }
+
+ strcpy(colonuser, user);
+ strcat(colonuser, ":");
+ while(fgets(line, sizeof(line), fd_in)) {
+ if(!strncmp(line,colonuser,strlen(colonuser))) {
+ pe->pw_passwd = cryptstr;
+ if(putpwent(pe, fd_out) < 0) {
+ error = 1;
+ }
+ } else {
+ if(fputs(line,fd_out) < 0) {
+ error = 1;
+ }
}
- while(fgets(line, sizeof(line), fd_in)) {
- if(!strncmp(line,user,strlen(user))) {
- pe->pw_passwd = cryptstr;
- if(putpwent(pe, fd_out) < 0) {
- error = 1;
- }
- } else {
- if(fputs(line,fd_out) < 0) {
- error = 1;
- }
- }
- if(error) {
- puts("Error while writing new password file, password not changed.");
- fclose(fd_out);
- endpwent();
- unlink("/etc/ptmp");
- exit(1);
- }
+ if(error) {
+ puts("Error while writing new password file, password not changed.");
+ fclose(fd_out);
+ endpwent();
+ unlink("/etc/ptmp");
+ exit(1);
}
- fclose(fd_in);
- fclose(fd_out);
-
- unlink("/etc/passwd.OLD");
- link("/etc/passwd", "/etc/passwd.OLD");
- unlink("/etc/passwd");
- link("/etc/ptmp", "/etc/passwd");
- unlink("/etc/ptmp");
- chmod("/etc/passwd", 0644);
- chown("/etc/passwd", 0, 0);
-
- puts("Password changed.");
- exit(0);
+ }
+ fclose(fd_in);
+ fclose(fd_out);
+
+ unlink("/etc/passwd.OLD"); /* passwd.OLD not required */
+ if (link("/etc/passwd", "/etc/passwd.OLD"))
+ pexit("link(/etc/passwd, /etc/passwd.OLD) failed: no change");
+ if (unlink("/etc/passwd") < 0)
+ pexit("unlink(/etc/passwd) failed: no change");
+ if (link("/etc/ptmp", "/etc/passwd") < 0)
+ pexit("link(/etc/ptmp, /etc/passwd) failed: PASSWD file DROPPED!!");
+ if (unlink("/etc/ptmp") < 0)
+ pexit("unlink(/etc/ptmp) failed: /etc/ptmp still exists");
+
+ chmod("/etc/passwd", 0644);
+ chown("/etc/passwd", 0, 0);
+#endif
+
+ puts("Password changed.");
+ exit(0);
}
diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c
index f7e6eb312..8a01c6ec5 100644
--- a/login-utils/setpwnam.c
+++ b/login-utils/setpwnam.c
@@ -23,12 +23,12 @@
*
* Thanks to "two guys named Ian".
*/
-/* faith
- * 1.1.1.1
- * 1995/02/22 19:09:24
+/* $Author: faith $
+ * $Revision: 1.5 $
+ * $Date: 1995/10/12 14:46:36 $
*/
-#define DEBUG 0
+#undef DEBUG
/* because I use getpwent(), putpwent(), etc... */
#define _SVID_SOURCE
@@ -41,9 +41,14 @@
#include <fcntl.h>
#include <pwd.h>
#include <errno.h>
+#include <signal.h>
+#include <sys/resource.h>
#ifdef BSD43
#include <sys/file.h>
#endif
+#include <paths.h>
+
+#include "pathnames.h"
extern int errno;
@@ -52,15 +57,18 @@ typedef int boolean;
#define true 1
#ifndef DEBUG
-#define PASSWD_FILE "/etc/passwd"
-#define PTMP_FILE "/etc/ptmp"
+#define PASSWD_FILE _PATH_PASSWD
+#define PTMP_FILE _PATH_PTMP
+#define PTMPTMP_FILE _PATH_PTMPTMP
#else
#define PASSWD_FILE "/tmp/passwd"
#define PTMP_FILE "/tmp/ptmp"
+#define PTMPTMP_FILE "/tmp/ptmptmp"
#endif
static int copy_pwd (struct passwd *src, struct passwd *dest);
static char *xstrdup (char *str);
+static void pw_init(void);
/*
* setpwnam () --
@@ -70,14 +78,12 @@ static char *xstrdup (char *str);
*/
int setpwnam (struct passwd *pwd)
{
- char *passwd = PASSWD_FILE;
- char *ptmp = PTMP_FILE;
FILE *fp;
- int x, save_errno, fd;
+ int x, save_errno, fd, ret;
struct passwd *entry;
boolean found;
- char buf[50];
struct passwd spwd;
+ int oldumask;
/* getpwent() returns a pointer to a static buffer.
* "pwd" might have some from getpwent(), so we have to copy it to
@@ -86,16 +92,31 @@ int setpwnam (struct passwd *pwd)
if (copy_pwd (pwd, &spwd) < 0)
return (-1);
+ oldumask = umask(0); /* Create with exact permissions */
+ pw_init();
+
/* sanity check */
for (x = 0; x < 3; x++) {
if (x > 0) sleep (1);
- fd = open (ptmp, O_WRONLY|O_CREAT|O_EXCL, 00644);
- if (fd >= 0) break;
+ fd = open (PTMPTMP_FILE, O_WRONLY|O_CREAT, 0644);
+ if(fd == -1) {
+ perror(PTMPTMP_FILE);
+ umask(oldumask);
+ return (-1);
+ }
+ ret = link(PTMPTMP_FILE, PTMP_FILE);
+ unlink(PTMPTMP_FILE);
+ if(ret == -1)
+ close(fd);
+ else
+ break;
}
- if (fd < 0) return (-1);
+
+ umask(oldumask);
+ if (ret == -1) return (-1);
/* ptmp should be owned by root.root or root.wheel */
- if (chown (ptmp, (uid_t) 0, (gid_t) 0) < 0)
+ if (chown (PTMP_FILE, (uid_t) 0, (gid_t) 0) < 0)
perror ("chown");
/* open ptmp for writing and passwd for reading */
@@ -122,25 +143,13 @@ int setpwnam (struct passwd *pwd)
goto fail;
}
- strcpy (buf, passwd);
- strcat (buf, "~");
/* we don't care if we can't remove the backup file */
- remove (buf);
+ unlink (PASSWD_FILE".OLD");
/* we don't care if we can't create the backup file */
- link (passwd, buf);
- /* we DO care if we can't erase the passwd file */
- if (remove (passwd) < 0) {
- /* if the file is still there, fail */
- if (access (passwd, F_OK) == 0) goto fail;
- }
- /* if we can't link ptmp to passwd, all is lost */
- if (link (ptmp, passwd) < 0) {
- /* reinstall_system (); */
- return (-1);
- }
- /* if we can't erase the ptmp file, we simply lose */
- if (remove (ptmp) < 0)
- return (-1);
+ link (PASSWD_FILE, PASSWD_FILE".OLD");
+ /* we DO care if we can't rename to the passwd file */
+ if (rename (PTMP_FILE, PASSWD_FILE) < 0)
+ goto fail;
/* finally: success */
return 0;
@@ -149,7 +158,7 @@ int setpwnam (struct passwd *pwd)
if (fp) fclose (fp);
if (fd >= 0) close (fd);
endpwent ();
- remove (ptmp);
+ unlink (PTMP_FILE);
errno = save_errno;
return (-1);
}
@@ -207,3 +216,34 @@ int putpwent (const struct passwd *p, FILE *stream)
}
#endif
+
+static void
+pw_init()
+{
+ struct rlimit rlim;
+
+ /* Unlimited resource limits. */
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ (void)setrlimit(RLIMIT_CPU, &rlim);
+ (void)setrlimit(RLIMIT_FSIZE, &rlim);
+ (void)setrlimit(RLIMIT_STACK, &rlim);
+ (void)setrlimit(RLIMIT_DATA, &rlim);
+ (void)setrlimit(RLIMIT_RSS, &rlim);
+
+ /* Don't drop core (not really necessary, but GP's). */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ (void)setrlimit(RLIMIT_CORE, &rlim);
+
+ /* Turn off signals. */
+ (void)signal(SIGALRM, SIG_IGN);
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGPIPE, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
+ (void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGTSTP, SIG_IGN);
+ (void)signal(SIGTTOU, SIG_IGN);
+
+ /* Create with exact permissions. */
+ (void)umask(0);
+}
diff --git a/login-utils/shutdown.8 b/login-utils/shutdown.8
index 78eb984b0..21b384124 100644
--- a/login-utils/shutdown.8
+++ b/login-utils/shutdown.8
@@ -1,6 +1,6 @@
.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH SHUTDOWN 8 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH SHUTDOWN 8 "20 November 1993" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
shutdown \- close down the system
.SH SYNOPSIS
@@ -53,7 +53,7 @@ notifies all users, tells
not to spawn more
.BR getty (8)'s,
writes the shutdown time into the
-.I /var/adm/wtmp
+.I /var/log/wtmp
file, kills all other processes on the system,
.BR sync (2)'s,
unmounts all the disks,
@@ -93,7 +93,7 @@ detects (and deletes).
.I /fastboot
.I /etc/singleboot
.I /etc/nologin
-.I /var/adm/wtmp
+.I /var/log/wtmp
.fi
.SH "SEE ALSO"
.BR umount (8),
@@ -106,7 +106,8 @@ Unlike the BSD
.BR shutdown ,
users are notified of shutdown only once or twice, instead of many times,
and at shorter and shorter intervals as "apocalypse approaches."
+Some would construe this as a feature.
.SH AUTHOR
-poe@daimi.aau.dk
+Peter Orbaek (poe@daimi.aau.dk)
.br
Modified by jrs@world.std.com
diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c
index 0ca303988..155154c21 100644
--- a/login-utils/shutdown.c
+++ b/login-utils/shutdown.c
@@ -46,6 +46,7 @@
void usage(), int_handler(), write_user(struct utmp *);
void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves();
+void swap_off();
char *prog; /* name of the program */
int opt_reboot; /* true if -r option or reboot command */
@@ -88,14 +89,14 @@ main(argc, argv)
#ifndef DEBUGGING
if(geteuid()) {
- fprintf(stderr, "Only root can shut a system down.\n");
+ fprintf(stderr, "%s: Only root can shut a system down.\n", argv[0]);
exit(1);
}
#endif
if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */
prog = argv[0];
- if(ptr = strrchr(argv[0], '/')) prog = ++ptr;
+ if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;
if(!strcmp("halt", prog)) {
opt_reboot = 0;
@@ -163,7 +164,7 @@ main(argc, argv)
struct tm *tt;
int now, then;
- if(colon = strchr(argv[c], ':')) {
+ if((colon = strchr(argv[c], ':'))) {
*colon = '\0';
hour = atoi(argv[c]);
minute = atoi(++colon);
@@ -276,6 +277,9 @@ main(argc, argv)
sync();
sleep(2);
+ /* remove swap files and partitions using swapoff */
+ swap_off();
+
/* unmount disks... */
unmount_disks();
sync();
@@ -339,7 +343,7 @@ wall()
utmpname(_PATH_UTMP);
setutent();
- while(ut = getutent()) {
+ while((ut = getutent())) {
if(ut->ut_type == USER_PROCESS)
write_user(ut);
}
@@ -360,13 +364,42 @@ write_wtmp()
time(&ut.ut_time);
ut.ut_type = BOOT_TIME;
- if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) > 0) {
+ if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
write(fd, (char *)&ut, sizeof(ut));
close(fd);
}
}
void
+swap_off()
+{
+ /* swapoff esp. swap FILES so the underlying partition can be
+ unmounted. It you don't have swapoff(1) or use mount to
+ add swapspace, this may not be necessary, but I guess it
+ won't hurt */
+
+ int pid;
+ int result;
+ int status;
+
+ sync();
+ if ((pid = fork()) < 0) {
+ printf("Cannot fork for swapoff. Shrug!\n");
+ return;
+ }
+ if (!pid) {
+ execl("/sbin/swapoff", SWAPOFF_ARGS, NULL);
+ execl("/etc/swapoff", SWAPOFF_ARGS, NULL);
+ execl("/bin/swapoff", SWAPOFF_ARGS, NULL);
+ execlp("swapoff", SWAPOFF_ARGS, NULL);
+ puts("Cannot exec swapoff, hoping umount will do the trick.");
+ exit(0);
+ }
+ while ((result = wait(&status)) != -1 && result != pid)
+ ;
+}
+
+void
unmount_disks()
{
/* better to use umount directly because it may be smarter than us */
@@ -385,16 +418,13 @@ unmount_disks()
execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL);
printf("Cannot exec %s, trying umount.\n", _PATH_UMOUNT);
execlp("umount", UMOUNT_ARGS, NULL);
- printf("Cannot exec umount, trying manually.\n");
- unmount_disks_ourselves();
+ puts("Cannot exec umount, giving up on umount.");
exit(0);
}
while ((result = wait(&status)) != -1 && result != pid)
;
- if (result == -1 || status) {
- printf("Running umount failed, trying manually.\n");
- unmount_disks_ourselves();
- }
+ puts("Unmounting any remaining filesystems...");
+ unmount_disks_ourselves();
}
void
@@ -411,7 +441,7 @@ unmount_disks_ourselves()
sync();
if (!(mtab = setmntent(_PATH_MTAB, "r"))) {
- printf("Cannot open %s.\n", _PATH_MTAB);
+ printf("shutdown: Cannot open %s.\n", _PATH_MTAB);
return;
}
n = 0;
@@ -429,7 +459,7 @@ unmount_disks_ourselves()
printf("umount %s\n", filesys);
#else
if (umount(mntlist[i]) < 0)
- printf("Couldn't umount %s\n", filesys);
+ printf("shutdown: Couldn't umount %s\n", filesys);
#endif
}
}
diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c
index 9b31c15e4..3a39dcd45 100644
--- a/login-utils/simpleinit.c
+++ b/login-utils/simpleinit.c
@@ -144,7 +144,7 @@ int main(int argc, char *argv[])
utmpname(_PATH_UTMP);
setutent();
- while(ut = getutent()) {
+ while((ut = getutent())) {
if(ut->ut_pid == pid) {
time(&ut->ut_time);
memset(&ut->ut_user, 0, UT_NAMESIZE);
@@ -265,7 +265,9 @@ void spawn(int i)
} else {
/* this is the child */
char term[40];
+#ifdef SET_TZ
char tz[CMDSIZ];
+#endif
char *env[3];
setsid();
@@ -294,8 +296,10 @@ void read_inittab()
char buf[CMDSIZ];
int i,j,k;
char *ptr, *getty;
+#ifdef SPECIAL_CONSOLE_TERM
char tty[50];
struct stat stb;
+#endif
char *termenv, *getenv();
termenv = getenv("TERM"); /* set by kernel */
@@ -332,7 +336,7 @@ void read_inittab()
(void) strtok(getty, " \t\n");
inittab[i].toks[0] = getty;
j = 1;
- while(ptr = strtok((char *)0, " \t\n"))
+ while((ptr = strtok((char *)0, " \t\n")))
inittab[i].toks[j++] = ptr;
inittab[i].toks[j] = (char *)0;
diff --git a/login-utils/ttymsg.c b/login-utils/ttymsg.c
index 40c178df2..e6aa39615 100644
--- a/login-utils/ttymsg.c
+++ b/login-utils/ttymsg.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,13 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Modified for Linux (which doesn\'t have snprintf()) by faith@cs.unc.edu
- * on Sun Mar 7 16:14:18 1993.
+ * Modified Sun Mar 12 10:39:22 1995, faith@cs.unc.edu for Linux
*
*/
#ifndef lint
-static char sccsid[] = "@(#)ttymsg.c 5.8 (Berkeley) 7/1/91";
+static char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93";
#endif /* not lint */
#include <sys/types.h>
@@ -51,18 +50,23 @@ static char sccsid[] = "@(#)ttymsg.c 5.8 (Berkeley) 7/1/91";
#include <string.h>
#include <stdlib.h>
+#ifdef __linux__
+#include "pathnames.h"
+#endif
+
/*
- * Display the contents of a uio structure on a terminal. Used by wall(1)
- * and syslogd(8). Forks and finishes in child if write would block, waiting
- * at most five minutes. Returns pointer to error string on unexpected error;
- * string is not newline-terminated. Various "normal" errors are ignored
- * (exclusive-use, lack of permission, etc.).
+ * Display the contents of a uio structure on a terminal. Used by wall(1),
+ * syslogd(8), and talkd(8). Forks and finishes in child if write would block,
+ * waiting up to tmout seconds. Returns pointer to error string on unexpected
+ * error; string is not newline-terminated. Various "normal" errors are
+ * ignored (exclusive-use, lack of permission, etc.).
*/
char *
-ttymsg(iov, iovcnt, line)
+ttymsg(iov, iovcnt, line, tmout)
struct iovec *iov;
int iovcnt;
char *line;
+ int tmout;
{
static char device[MAXNAMLEN] = _PATH_DEV;
static char errbuf[1024];
@@ -70,13 +74,25 @@ ttymsg(iov, iovcnt, line)
struct iovec localiov[6];
int forked = 0;
- if (iovcnt > 6)
+ if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
return ("too many iov's (change code in wall/ttymsg.c)");
+
+ (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
+ if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
+ /* A slash is an attempt to break security... */
+#ifdef __linux__
+ (void) sprintf(errbuf, "'/' in \"%s\"", device);
+#else
+ (void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
+ device);
+#endif
+ return (errbuf);
+ }
+
/*
* open will fail on slip lines or exclusive-use lines
* if not running as root; not an error.
*/
- (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
if (errno == EBUSY || errno == EACCES)
return (NULL);
@@ -100,7 +116,7 @@ ttymsg(iov, iovcnt, line)
if (wret >= 0) {
left -= wret;
if (iov != localiov) {
- bcopy(iov, localiov,
+ bcopy(iov, localiov,
iovcnt * sizeof(struct iovec));
iov = localiov;
}
@@ -139,14 +155,14 @@ ttymsg(iov, iovcnt, line)
return (NULL);
}
forked++;
- /* wait at most 5 minutes */
+ /* wait at most tmout seconds */
(void) signal(SIGALRM, SIG_DFL);
(void) signal(SIGTERM, SIG_DFL); /* XXX */
(void) sigsetmask(0);
- (void) alarm((u_int)(60 * 5));
+ (void) alarm((u_int)tmout);
(void) fcntl(fd, O_NONBLOCK, &off);
continue;
- }
+ }
/*
* We get ENODEV on a slip line if we're running as root,
* and EIO if the line just went away.
diff --git a/login-utils/vipw.8 b/login-utils/vipw.8
index 23d84ad69..b2786d0e5 100644
--- a/login-utils/vipw.8
+++ b/login-utils/vipw.8
@@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" from: @(#)vipw.8 6.7 (Berkeley) 3/16/91
-.\" vipw.8,v 1.1.1.1 1995/02/22 19:09:25 faith Exp
+.\" $Id: vipw.8,v 1.2 1995/03/12 01:33:13 faith Exp $
.\"
.Dd March 16, 1991
.Dt VIPW 8
diff --git a/login-utils/vipw.c b/login-utils/vipw.c
index f36df5f2e..681d9a658 100644
--- a/login-utils/vipw.c
+++ b/login-utils/vipw.c
@@ -29,6 +29,10 @@
* 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.
+ *
+ * Updated Thu Oct 12 09:56:55 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
+ *
*/
#ifndef lint
@@ -39,7 +43,7 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)vipw.c 5.16 (Berkeley) 3/3/91";*/
-static char rcsid[] = "vipw.c,v 1.1.1.1 1995/02/22 19:09:25 faith Exp";
+static char rcsid[] = "$Id: vipw.c,v 1.4 1995/10/12 14:46:36 faith Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -115,7 +119,6 @@ pw_init()
int
pw_lock()
{
- static char path[MAXPATHLEN] = _PATH_PTMP;
int lockfd, fd, ret;
char *p;
@@ -131,11 +134,13 @@ pw_lock()
progname, _PATH_PASSWD, strerror(errno));
exit(1);
}
+#if 0 /* flock()ing is superfluous here, with the ptmp/ptmptmp system. */
if (flock(lockfd, LOCK_EX|LOCK_NB)) {
(void)fprintf(stderr,
"%s: the password file is busy.\n", progname);
exit(1);
}
+#endif
if ((fd = open(_PATH_PTMPTMP, O_WRONLY|O_CREAT, 0644)) == -1) {
(void)fprintf(stderr,
@@ -162,8 +167,9 @@ pw_lock()
void
pw_unlock()
{
- (void)unlink(_PATH_PASSWD);
- if (link(_PATH_PTMP, _PATH_PASSWD) == -1) {
+ unlink(_PATH_PASSWD ".OLD");
+ link(_PATH_PASSWD, _PATH_PASSWD ".OLD" );
+ if (rename(_PATH_PTMP, _PATH_PASSWD) == -1) {
(void)fprintf(stderr,
"%s: can't unlock %s: %s (your changes are still in %s)\n",
progname, _PATH_PASSWD, strerror(errno), _PATH_PTMP);
@@ -183,7 +189,7 @@ pw_edit(notsetuid)
if (!(editor = getenv("EDITOR")))
editor = _PATH_VI;
- if ((p = strrchr(editor, '/')) != NULL)
+ if ((p = strrchr(strtok(editor," \t"), '/')) != NULL)
++p;
else
p = editor;
diff --git a/login-utils/wall.c b/login-utils/wall.c
index b10badbac..7f3e61235 100644
--- a/login-utils/wall.c
+++ b/login-utils/wall.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1988, 1990 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,17 +30,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Modified for Linux, Mon Mar 8 18:08:30 1993, faith@cs.unc.edu
+ * Modified Sun Mar 12 10:34:34 1995, faith@cs.unc.edu, for Linux
*/
#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)wall.c 5.14 (Berkeley) 3/2/91";
+static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93";
#endif /* not lint */
/*
@@ -52,11 +52,20 @@ static char sccsid[] = "@(#)wall.c 5.14 (Berkeley) 3/2/91";
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
-#include <utmp.h>
+
+#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#ifdef __linux__
+#include <locale.h>
+#include "pathnames.h"
+#endif
+
+void makemsg __P((char *));
#define IGNOREUSER "sleeper"
@@ -65,6 +74,7 @@ int mbufsize;
char *mbuf;
/* ARGSUSED */
+int
main(argc, argv)
int argc;
char **argv;
@@ -75,7 +85,12 @@ main(argc, argv)
struct utmp utmp;
FILE *fp;
char *p, *ttymsg();
+ char line[sizeof(utmp.ut_line) + 1];
+#ifdef __linux__
+ setlocale(LC_CTYPE,"");
+#endif
+
while ((ch = getopt(argc, argv, "n")) != EOF)
switch (ch) {
case 'n':
@@ -94,11 +109,6 @@ usage:
if (argc > 1)
goto usage;
-#ifdef __linux__
- if (argc != 1)
- makemsg("");
- else
-#endif
makemsg(*argv);
if (!(fp = fopen(_PATH_UTMP, "r"))) {
@@ -114,14 +124,17 @@ usage:
continue;
#ifdef __linux__
if (utmp.ut_type != USER_PROCESS)
- continue;
+ continue;
#endif
- if (p = ttymsg(&iov, 1, utmp.ut_line))
+ strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
+ line[sizeof(utmp.ut_line)] = '\0';
+ if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
(void)fprintf(stderr, "wall: %s\n", p);
}
exit(0);
}
+void
makemsg(fname)
char *fname;
{
@@ -167,20 +180,27 @@ makemsg(fname)
}
(void)fprintf(fp, "%79s\r\n", " ");
- if (*fname && !(freopen(fname, "r", stdin))) {
+ if (fname && !(freopen(fname, "r", stdin))) {
(void)fprintf(stderr, "wall: can't read %s.\n", fname);
exit(1);
}
while (fgets(lbuf, sizeof(lbuf), stdin))
- for (cnt = 0, p = lbuf; ch = *p; ++p, ++cnt) {
+ for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
if (cnt == 79 || ch == '\n') {
for (; cnt < 79; ++cnt)
putc(' ', fp);
putc('\r', fp);
putc('\n', fp);
cnt = 0;
- } else
- putc(ch, fp);
+ } else {
+ /* Test for control chars added Fri Mar 10
+ 19:49:30 1995, faith@cs.unc.edu */
+ if (!isprint(ch) && !isspace(ch) && ch != '\007') {
+ putc('^', fp);
+ putc(ch^0x40,fp); /* DEL to ?, others to alpha */
+ } else
+ putc(ch, fp);
+ }
}
(void)fprintf(fp, "%79s\r\n", " ");
rewind(fp);