Module Name:    src
Committed By:   christos
Date:           Tue Dec 29 19:26:13 UTC 2009

Modified Files:
        src/usr.bin/login: Makefile login.c login_pam.c
Added Files:
        src/usr.bin/login: common.c common.h

Log Message:
PR/42540: Ed Ravin: /usr/bin/login does not log normal logins, and does not
log ip addresses.
- Factor out the common code in login.c and login_pam.c into common.c
- Always log a login event
- Check passed in sockaddr against the one from getpeername(2).


To generate a diff of this commit:
cvs rdiff -u -r1.50 -r1.51 src/usr.bin/login/Makefile
cvs rdiff -u -r0 -r1.1 src/usr.bin/login/common.c src/usr.bin/login/common.h
cvs rdiff -u -r1.96 -r1.97 src/usr.bin/login/login.c
cvs rdiff -u -r1.19 -r1.20 src/usr.bin/login/login_pam.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/login/Makefile
diff -u src/usr.bin/login/Makefile:1.50 src/usr.bin/login/Makefile:1.51
--- src/usr.bin/login/Makefile:1.50	Tue Apr 14 18:15:22 2009
+++ src/usr.bin/login/Makefile	Tue Dec 29 14:26:13 2009
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.50 2009/04/14 22:15:22 lukem Exp $
+#	$NetBSD: Makefile,v 1.51 2009/12/29 19:26:13 christos Exp $
 #	@(#)Makefile	8.1 (Berkeley) 7/19/93
 
 WARNS?=	2	# XXX -Wcast-qual issues
@@ -13,6 +13,7 @@
 BINOWN=	root
 BINMODE=4555
 
+SRCS+=	common.c
 .if (${USE_PAM} != "no")
 SRCS+=	login_pam.c
 LDADD+=	-lpam ${PAM_STATIC_LDADD}

Index: src/usr.bin/login/login.c
diff -u src/usr.bin/login/login.c:1.96 src/usr.bin/login/login.c:1.97
--- src/usr.bin/login/login.c:1.96	Mon Jul 21 10:19:23 2008
+++ src/usr.bin/login/login.c	Tue Dec 29 14:26:13 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: login.c,v 1.96 2008/07/21 14:19:23 lukem Exp $	*/
+/*	$NetBSD: login.c,v 1.97 2009/12/29 19:26:13 christos Exp $	*/
 
 /*-
  * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)login.c	8.4 (Berkeley) 4/2/94";
 #endif
-__RCSID("$NetBSD: login.c,v 1.96 2008/07/21 14:19:23 lukem Exp $");
+__RCSID("$NetBSD: login.c,v 1.97 2009/12/29 19:26:13 christos Exp $");
 #endif /* not lint */
 
 /*
@@ -91,31 +91,15 @@
 #include <vis.h>
 
 #include "pathnames.h"
+#include "common.h"
 
 #ifdef KERBEROS5
-int login_krb5_get_tickets = 1;
 int login_krb5_forwardable_tgt = 0;
-int login_krb5_retain_ccache = 0;
+static int login_krb5_get_tickets = 1;
+static int login_krb5_retain_ccache = 0;
 #endif
 
-void	 badlogin(char *);
-void	 checknologin(char *);
-#ifdef SUPPORT_UTMP
-static void	 doutmp(void);
-static void	 dolastlog(int);
-#endif
-#ifdef SUPPORT_UTMPX
-static void	 doutmpx(void);
-static void	 dolastlogx(int);
-#endif
-static void	 update_db(int);
-void	 getloginname(void);
-void	 motd(char *);
-int	 rootterm(char *);
-void	 sigint(int);
-void	 sleepexit(int);
-const	 char *stypeof(const char *);
-void	 timedout(int);
+static void	 checknologin(char *);
 #ifdef KERBEROS5
 int	 k5login(struct passwd *, char *, char *, char *);
 void	 k5destroy(void);
@@ -123,26 +107,19 @@
 int	 k5_write_creds(void);
 #endif
 #if defined(KERBEROS5)
-void	 dofork(void);
+static void	 dofork(void);
 #endif
-void	 decode_ss(const char *);
-void	 usage(void);
+static void	 usage(void);
 
 #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
 
 #define DEFAULT_BACKOFF 3
 #define DEFAULT_RETRIES 10
 
-/*
- * This bounds the time given to login.  Not a define so it can
- * be patched on machines where it's too small.
- */
-u_int	timeout = 300;
-
 #if defined(KERBEROS5)
-int	notickets = 1;
-char	*instance;
 int	has_ccache = 0;
+static int	notickets = 1;
+static char	*instance;
 extern krb5_context kcontext;
 extern int	have_forward;
 extern char	*krb5tkfile_env;
@@ -153,18 +130,11 @@
 #define	KERBEROS_CONFIGURED	krb5_configured
 #endif
 
-struct	passwd *pwd;
-int	failures, have_ss;
-char	term[64], *envinit[1], *hostname, *username, *tty, *nested;
-struct timeval now;
-struct sockaddr_storage ss;
-
-extern const char copyrightstr[];
+extern char **environ;
 
 int
 main(int argc, char *argv[])
 {
-	extern char **environ;
 	struct group *gr;
 	struct stat st;
 	int ask, ch, cnt, fflag, hflag, pflag, sflag, quietlog, rootlogin, rval;
@@ -577,7 +547,7 @@
 
 	}
 	/* Nothing else left to fail -- really log in. */
-	update_db(quietlog);
+	update_db(quietlog, rootlogin, fflag);
 
 	(void)chown(ttyn, pwd->pw_uid,
 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
@@ -748,17 +718,11 @@
 }
 
 #if defined(KERBEROS5)
-#define	NBUFSIZ		(MAXLOGNAME + 1 + 5)	/* .root suffix */
-#else
-#define	NBUFSIZ		(MAXLOGNAME + 1)
-#endif
-
-#if defined(KERBEROS5)
 /*
  * This routine handles cleanup stuff, and the like.
  * It exists only in the child process.
  */
-void
+static void
 dofork(void)
 {
 	pid_t child, wchild;
@@ -795,81 +759,7 @@
 }
 #endif
 
-void
-getloginname(void)
-{
-	int ch;
-	char *p;
-	static char nbuf[NBUFSIZ];
-
-	for (;;) {
-		(void)printf("login: ");
-		for (p = nbuf; (ch = getchar()) != '\n'; ) {
-			if (ch == EOF) {
-				badlogin(username);
-				exit(EXIT_FAILURE);
-			}
-			if (p < nbuf + (NBUFSIZ - 1))
-				*p++ = ch;
-		}
-		if (p > nbuf) {
-			if (nbuf[0] == '-')
-				(void)fprintf(stderr,
-				    "login names may not start with '-'.\n");
-			else {
-				*p = '\0';
-				username = nbuf;
-				break;
-			}
-		}
-	}
-}
-
-int
-rootterm(char *ttyn)
-{
-	struct ttyent *t;
-
-	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
-}
-
-jmp_buf motdinterrupt;
-
-void
-motd(char *fname)
-{
-	int fd, nchars;
-	sig_t oldint;
-	char tbuf[8192];
-
-	if ((fd = open(fname ? fname : _PATH_MOTDFILE, O_RDONLY, 0)) < 0)
-		return;
-	oldint = signal(SIGINT, sigint);
-	if (setjmp(motdinterrupt) == 0)
-		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-			(void)write(fileno(stdout), tbuf, nchars);
-	(void)signal(SIGINT, oldint);
-	(void)close(fd);
-}
-
-/* ARGSUSED */
-void
-sigint(int signo)
-{
-
-	longjmp(motdinterrupt, 1);
-}
-
-/* ARGSUSED */
-void
-timedout(int signo)
-{
-
-	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
-	exit(EXIT_FAILURE);
-}
-
-void
+static void
 checknologin(char *fname)
 {
 	int fd, nchars;
@@ -883,202 +773,6 @@
 }
 
 static void
-update_db(int quietlog)
-{
-	if (nested != NULL) {
-		if (hostname != NULL)
-			syslog(LOG_NOTICE, "%s to %s on tty %s from %s",
-			    nested, pwd->pw_name, tty, hostname);
-		else
-			syslog(LOG_NOTICE, "%s to %s on tty %s", nested,
-			    pwd->pw_name, tty);
-
-		return;
-	}
-	if (hostname != NULL && have_ss == 0) {
-		socklen_t len = sizeof(ss);
-		have_ss = getpeername(STDIN_FILENO, (struct sockaddr *)&ss,
-		    &len) != -1;
-	}
-	(void)gettimeofday(&now, NULL);
-#ifdef SUPPORT_UTMPX
-	doutmpx();
-	dolastlogx(quietlog);
-	quietlog = 1;
-#endif	
-#ifdef SUPPORT_UTMP
-	doutmp();
-	dolastlog(quietlog);
-#endif
-}
-
-#ifdef SUPPORT_UTMPX
-static void
-doutmpx(void)
-{
-	struct utmpx utmpx;
-	char *t;
-
-	memset((void *)&utmpx, 0, sizeof(utmpx));
-	utmpx.ut_tv = now;
-	(void)strncpy(utmpx.ut_name, username, sizeof(utmpx.ut_name));
-	if (hostname) {
-		(void)strncpy(utmpx.ut_host, hostname, sizeof(utmpx.ut_host));
-		utmpx.ut_ss = ss;
-	}
-	(void)strncpy(utmpx.ut_line, tty, sizeof(utmpx.ut_line));
-	utmpx.ut_type = USER_PROCESS;
-	utmpx.ut_pid = getpid();
-	t = tty + strlen(tty);
-	if (t - tty >= sizeof(utmpx.ut_id)) {
-	    (void)strncpy(utmpx.ut_id, t - sizeof(utmpx.ut_id),
-		sizeof(utmpx.ut_id));
-	} else {
-	    (void)strncpy(utmpx.ut_id, tty, sizeof(utmpx.ut_id));
-	}
-	if (pututxline(&utmpx) == NULL)
-		syslog(LOG_NOTICE, "Cannot update utmpx: %m");
-	endutxent();
-	if (updwtmpx(_PATH_WTMPX, &utmpx) != 0)
-		syslog(LOG_NOTICE, "Cannot update wtmpx: %m");
-}
-
-static void
-dolastlogx(int quiet)
-{
-	struct lastlogx ll;
-	if (!quiet && getlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != NULL) {
-		time_t t = (time_t)ll.ll_tv.tv_sec;
-		(void)printf("Last login: %.24s ", ctime(&t));
-		if (*ll.ll_host != '\0')
-			(void)printf("from %.*s ",
-			    (int)sizeof(ll.ll_host),
-			    ll.ll_host);
-		(void)printf("on %.*s\n",
-		    (int)sizeof(ll.ll_line),
-		    ll.ll_line);
-	}
-	ll.ll_tv = now;
-	(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
-	if (hostname)
-		(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
-	else
-		(void)memset(ll.ll_host, '\0', sizeof(ll.ll_host));
-	if (have_ss)
-		ll.ll_ss = ss;
-	else
-		(void)memset(&ll.ll_ss, 0, sizeof(ll.ll_ss));
-	if (updlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != 0)
-		syslog(LOG_NOTICE, "Cannot update lastlogx: %m");
-}
-#endif
-
-#ifdef SUPPORT_UTMP
-static void
-doutmp(void)
-{
-	struct utmp utmp;
-
-	(void)memset((void *)&utmp, 0, sizeof(utmp));
-	utmp.ut_time = now.tv_sec;
-	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
-	if (hostname)
-		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
-	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
-	login(&utmp);
-}
-
-static void
-dolastlog(int quiet)
-{
-	struct lastlog ll;
-	int fd;
-
-	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
-		(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), SEEK_SET);
-		if (!quiet) {
-			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
-			    ll.ll_time != 0) {
-				(void)printf("Last login: %.24s ",
-				    ctime(&ll.ll_time));
-				if (*ll.ll_host != '\0')
-					(void)printf("from %.*s ",
-					    (int)sizeof(ll.ll_host),
-					    ll.ll_host);
-				(void)printf("on %.*s\n",
-				    (int)sizeof(ll.ll_line), ll.ll_line);
-			}
-			(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)),
-			    SEEK_SET);
-		}
-		memset((void *)&ll, 0, sizeof(ll));
-		ll.ll_time = now.tv_sec;
-		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
-		if (hostname)
-			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
-		(void)write(fd, (char *)&ll, sizeof(ll));
-		(void)close(fd);
-	}
-}
-#endif
-
-void
-badlogin(char *name)
-{
-
-	if (failures == 0)
-		return;
-	if (hostname) {
-		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
-		    failures, failures > 1 ? "S" : "", hostname);
-		syslog(LOG_AUTHPRIV|LOG_NOTICE,
-		    "%d LOGIN FAILURE%s FROM %s, %s",
-		    failures, failures > 1 ? "S" : "", hostname, name);
-	} else {
-		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
-		    failures, failures > 1 ? "S" : "", tty);
-		syslog(LOG_AUTHPRIV|LOG_NOTICE,
-		    "%d LOGIN FAILURE%s ON %s, %s",
-		    failures, failures > 1 ? "S" : "", tty, name);
-	}
-}
-
-const char *
-stypeof(const char *ttyid)
-{
-	struct ttyent *t;
-
-	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL);
-}
-
-void
-sleepexit(int eval)
-{
-
-	(void)sleep(5);
-	exit(eval);
-}
-
-void
-decode_ss(const char *arg)
-{
-	struct sockaddr_storage *ssp;
-	size_t len = strlen(arg);
-	
-	if (len > sizeof(*ssp) * 4 + 1 || len < sizeof(*ssp))
-		errx(EXIT_FAILURE, "Bad argument");
-
-	if ((ssp = malloc(len)) == NULL)
-		err(EXIT_FAILURE, NULL);
-
-	if (strunvis((char *)ssp, arg) != sizeof(*ssp))
-		errx(EXIT_FAILURE, "Decoding error");
-
-	(void)memcpy(&ss, ssp, sizeof(ss));
-	have_ss = 1;
-}
-
-void
 usage(void)
 {
 	(void)fprintf(stderr,

Index: src/usr.bin/login/login_pam.c
diff -u src/usr.bin/login/login_pam.c:1.19 src/usr.bin/login/login_pam.c:1.20
--- src/usr.bin/login/login_pam.c:1.19	Mon Jul 21 10:19:23 2008
+++ src/usr.bin/login/login_pam.c	Tue Dec 29 14:26:13 2009
@@ -1,4 +1,4 @@
-/*     $NetBSD: login_pam.c,v 1.19 2008/07/21 14:19:23 lukem Exp $       */
+/*     $NetBSD: login_pam.c,v 1.20 2009/12/29 19:26:13 christos Exp $       */
 
 /*-
  * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)login.c	8.4 (Berkeley) 4/2/94";
 #endif
-__RCSID("$NetBSD: login_pam.c,v 1.19 2008/07/21 14:19:23 lukem Exp $");
+__RCSID("$NetBSD: login_pam.c,v 1.20 2009/12/29 19:26:13 christos Exp $");
 #endif /* not lint */
 
 /*
@@ -78,19 +78,12 @@
 #include <security/openpam.h>
 
 #include "pathnames.h"
+#include "common.h"
 
-void	 badlogin (char *);
-static void	 update_db (int);
-void	 getloginname (void);
-int	 main (int, char *[]);
-void	 motd (char *);
-int	 rootterm (char *);
-void	 sigint (int);
-void	 sleepexit (int);
-const	 char *stypeof (const char *);
-void	 timedout (int);
-void	 decode_ss (const char *);
-void	 usage (void);
+#if 0
+static int	 rootterm(char *);
+#endif
+static void	 usage(void) __attribute__((__noreturn__));
 
 static struct pam_conv pamc = { openpam_ttyconv, NULL };
 
@@ -99,27 +92,15 @@
 #define DEFAULT_BACKOFF 3
 #define DEFAULT_RETRIES 10
 
-/*
- * This bounds the time given to login.  Not a define so it can
- * be patched on machines where it's too small.
- */
-u_int	timeout = 300;
-
-struct	passwd *pwd, pwres;
-char	pwbuf[1024];
-struct	group grs, *grp;
-char	grbuf[1024];
-int	failures, have_ss;
-char	term[64], *envinit[1], *hostname, *username, *tty, *nested;
-struct timeval now;
-struct sockaddr_storage ss;
-
-extern const char copyrightstr[];
+static struct	passwd pwres;
+static char	pwbuf[1024];
+static struct	group grs, *grp;
+static char	grbuf[1024];
+extern char **environ;
 
 int
 main(int argc, char *argv[])
 {
-	extern char **environ;
 	struct stat st;
 	int ask, ch, cnt, fflag, pflag, quietlog, rootlogin;
 	int auth_passed;
@@ -185,10 +166,6 @@
 				err(EXIT_FAILURE, "-a option");
 			}
 			decode_ss(optarg);
-#ifdef notdef
-			(void)sockaddr_snprintf(optarg,
-			    sizeof(struct sockaddr_storage), "%a", (void *)&ss);
-#endif
 			break;
 		case 'f':
 			fflag = 1;
@@ -486,7 +463,7 @@
 		(void)printf("Warning: ttyaction failed.\n");
 
 	/* Nothing else left to fail -- really log in. */
-        update_db(quietlog);
+        update_db(quietlog, rootlogin, fflag);
 
 	if (nested == NULL && setusercontext(lc, pwd, pwd->pw_uid,
 	    LOGIN_SETLOGIN) != 0) {
@@ -498,15 +475,6 @@
 	if (tty[sizeof("tty")-1] == 'd')
 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
 
-	/* If fflag is on, assume caller/authenticator has logged root login. */
-	if (rootlogin && fflag == 0) {
-		if (hostname)
-			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
-			    username, tty, hostname);
-		else
-			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s",
-			    username, tty);
-	}
 
 	/*
 	 * Establish groups
@@ -687,165 +655,21 @@
 	err(EXIT_FAILURE, "%s", pwd->pw_shell);
 }
 
-#define	NBUFSIZ		(MAXLOGNAME + 1)
-
-
-void
-getloginname(void)
+static void
+usage(void)
 {
-	int ch;
-	char *p;
-	static char nbuf[NBUFSIZ];
-
-	for (;;) {
-		(void)printf("login: ");
-		for (p = nbuf; (ch = getchar()) != '\n'; ) {
-			if (ch == EOF) {
-				badlogin(username);
-				exit(EXIT_FAILURE);
-			}
-			if (p < nbuf + (NBUFSIZ - 1))
-				*p++ = ch;
-		}
-		if (p > nbuf) {
-			if (nbuf[0] == '-')
-				(void)fprintf(stderr,
-				    "login names may not start with '-'.\n");
-			else {
-				*p = '\0';
-				username = nbuf;
-				break;
-			}
-		}
-	}
+	(void)fprintf(stderr,
+	    "Usage: %s [-fp] [-a address] [-h hostname] [username]\n",
+	    getprogname());
+	exit(EXIT_FAILURE);
 }
 
-int
+#if 0
+static int
 rootterm(char *ttyn)
 {
 	struct ttyent *t;
 
 	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
 }
-
-jmp_buf motdinterrupt;
-
-void
-motd(char *fname)
-{
-	int fd, nchars;
-	sig_t oldint;
-	char tbuf[8192];
-
-	if ((fd = open(fname ? fname : _PATH_MOTDFILE, O_RDONLY, 0)) < 0)
-		return;
-	oldint = signal(SIGINT, sigint);
-	if (setjmp(motdinterrupt) == 0)
-		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
-			(void)write(fileno(stdout), tbuf, nchars);
-	(void)signal(SIGINT, oldint);
-	(void)close(fd);
-}
-
-/* ARGSUSED */
-void
-sigint(int signo)
-{
-
-	longjmp(motdinterrupt, 1);
-}
-
-/* ARGSUSED */
-void
-timedout(int signo)
-{
-
-	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
-	exit(EXIT_FAILURE);
-}
-
-static void
-update_db(int quietlog)
-{
-	if (nested != NULL) {
-		if (hostname != NULL)
-			syslog(LOG_NOTICE, "%s to %s on tty %s from %s",
-			    nested, pwd->pw_name, tty, hostname);
-		else
-			syslog(LOG_NOTICE, "%s to %s on tty %s", nested,
-			    pwd->pw_name, tty);
-
-	}
-	if (hostname != NULL && have_ss == 0) {
-		socklen_t len = sizeof(ss);
-		have_ss = getpeername(STDIN_FILENO, (struct sockaddr *)&ss,
-		    &len) != -1;
-	}
-	(void)gettimeofday(&now, NULL);
-}
-
-void
-badlogin(char *name)
-{
-
-	if (failures == 0)
-		return;
-	if (hostname) {
-		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
-		    failures, failures > 1 ? "S" : "", hostname);
-		syslog(LOG_AUTHPRIV|LOG_NOTICE,
-		    "%d LOGIN FAILURE%s FROM %s, %s",
-		    failures, failures > 1 ? "S" : "", hostname, name);
-	} else {
-		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
-		    failures, failures > 1 ? "S" : "", tty);
-		syslog(LOG_AUTHPRIV|LOG_NOTICE,
-		    "%d LOGIN FAILURE%s ON %s, %s",
-		    failures, failures > 1 ? "S" : "", tty, name);
-	}
-}
-
-const char *
-stypeof(const char *ttyid)
-{
-	struct ttyent *t;
-
-	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL);
-}
-
-void
-sleepexit(int eval)
-{
-
-	(void)sleep(5);
-	exit(eval);
-}
-
-void
-decode_ss(const char *arg)
-{
-	struct sockaddr_storage *ssp;
-	size_t len = strlen(arg);
-	
-	if (len > sizeof(*ssp) * 4 + 1 || len < sizeof(*ssp))
-		errx(EXIT_FAILURE, "Bad argument");
-
-	if ((ssp = malloc(len)) == NULL)
-		err(EXIT_FAILURE, NULL);
-
-	if (strunvis((char *)ssp, arg) != sizeof(*ssp))
-		errx(EXIT_FAILURE, "Decoding error");
-
-	(void)memcpy(&ss, ssp, sizeof(ss));
-	have_ss = 1;
-	free(ssp);
-}
-
-void
-usage(void)
-{
-	(void)fprintf(stderr,
-	    "Usage: %s [-fp] [-a address] [-h hostname] [username]\n",
-	    getprogname());
-	exit(EXIT_FAILURE);
-}
+#endif

Added files:

Index: src/usr.bin/login/common.c
diff -u /dev/null src/usr.bin/login/common.c:1.1
--- /dev/null	Tue Dec 29 14:26:13 2009
+++ src/usr.bin/login/common.c	Tue Dec 29 14:26:13 2009
@@ -0,0 +1,393 @@
+/*	$NetBSD: common.c,v 1.1 2009/12/29 19:26:13 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
+ *	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. 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.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: common.c,v 1.1 2009/12/29 19:26:13 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <ttyent.h>
+#include <setjmp.h>
+#include <time.h>
+#include <pwd.h>
+#include <err.h>
+#include <vis.h>
+#include <util.h>
+
+#include "pathnames.h"
+#include "common.h"
+
+#if defined(KERBEROS5)
+#define	NBUFSIZ		(MAXLOGNAME + 1 + 5)	/* .root suffix */
+#else
+#define	NBUFSIZ		(MAXLOGNAME + 1)
+#endif
+
+#ifdef SUPPORT_UTMP
+#include <utmp.h>
+static void	 doutmp(void);
+static void	 dolastlog(int);
+#endif
+#ifdef SUPPORT_UTMPX
+#include <utmpx.h>
+static void	 doutmpx(void);
+static void	 dolastlogx(int);
+#endif
+
+/*
+ * This bounds the time given to login.  Not a define so it can
+ * be patched on machines where it's too small.
+ */
+u_int	timeout = 300;
+
+void	 decode_ss(const char *);
+struct	passwd *pwd;
+int	failures, have_ss;
+char	term[64], *envinit[1], *hostname, *username, *tty, *nested;
+struct timeval now;
+struct sockaddr_storage ss;
+
+void
+getloginname(void)
+{
+	int ch;
+	char *p;
+	static char nbuf[NBUFSIZ];
+
+	for (;;) {
+		(void)printf("login: ");
+		for (p = nbuf; (ch = getchar()) != '\n'; ) {
+			if (ch == EOF) {
+				badlogin(username);
+				exit(EXIT_FAILURE);
+			}
+			if (p < nbuf + (NBUFSIZ - 1))
+				*p++ = ch;
+		}
+		if (p > nbuf) {
+			if (nbuf[0] == '-')
+				(void)fprintf(stderr,
+				    "login names may not start with '-'.\n");
+			else {
+				*p = '\0';
+				username = nbuf;
+				break;
+			}
+		}
+	}
+}
+
+int
+rootterm(char *ttyn)
+{
+	struct ttyent *t;
+
+	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+}
+
+static jmp_buf motdinterrupt;
+
+void
+motd(char *fname)
+{
+	int fd, nchars;
+	sig_t oldint;
+	char tbuf[8192];
+
+	if ((fd = open(fname ? fname : _PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+		return;
+	oldint = signal(SIGINT, sigint);
+	if (setjmp(motdinterrupt) == 0)
+		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+			(void)write(fileno(stdout), tbuf, nchars);
+	(void)signal(SIGINT, oldint);
+	(void)close(fd);
+}
+
+/* ARGSUSED */
+void
+sigint(int signo)
+{
+
+	longjmp(motdinterrupt, 1);
+}
+
+/* ARGSUSED */
+void
+timedout(int signo)
+{
+
+	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
+	exit(EXIT_FAILURE);
+}
+
+void
+update_db(int quietlog, int rootlogin, int fflag)
+{
+	struct sockaddr_storage ass;
+	char assbuf[1024];
+	socklen_t alen;
+	const char *hname;
+	int remote;
+
+	hname = (hostname == NULL) ? "?" : hostname;
+	if (getpeername(STDIN_FILENO, (struct sockaddr *)&ass, &alen) != -1) {
+		(void)sockaddr_snprintf(assbuf,
+		    sizeof(assbuf), "%A (%a)", (void *)&ass);
+		if (have_ss) {
+			char ssbuf[1024];
+			(void)sockaddr_snprintf(ssbuf,
+			    sizeof(ssbuf), "%A (%a)", (void *)&ss);
+			 if (memcmp(&ass, &ss, alen) != 0)
+				syslog(LOG_NOTICE,
+				    "login %s on tty %s address mismatch "
+				    "passed %s != actual %s", username, tty,
+				    ssbuf, assbuf);
+		} else
+			ss = ass;
+		remote = 1;
+	} else if (have_ss) {
+		(void)sockaddr_snprintf(assbuf,
+		    sizeof(assbuf), "%A (%a)", (void *)&ss);
+		remote = 1;
+	} else if (hostname) {
+		(void)snprintf(assbuf, sizeof(assbuf), "? ?");
+		remote = 1;
+	} else
+		remote = 0;
+
+	/* If fflag is on, assume caller/authenticator has logged root login. */
+	if (rootlogin && fflag == 0) {
+		if (remote)
+			syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s from %s /"
+			    " %s", username, tty, hname, assbuf);
+		else
+			syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s",
+			    username, tty);
+	} else if (nested != NULL) {
+		if (remote)
+			syslog(LOG_NOTICE, "login %s to %s on tty %s from %s / "
+			    "%s", nested, pwd->pw_name, tty, hname, assbuf);
+		else
+			syslog(LOG_NOTICE, "login %s to %s on tty %s", nested,
+			    pwd->pw_name, tty);
+	} else {
+		if (remote)
+			syslog(LOG_NOTICE, "login %s on tty %s from %s / %s",
+			    pwd->pw_name, tty, hname, assbuf);
+		else
+			syslog(LOG_NOTICE, "login %s on tty %s", 
+			    pwd->pw_name, tty);
+	}
+	(void)gettimeofday(&now, NULL);
+#ifdef SUPPORT_UTMPX
+	doutmpx();
+	dolastlogx(quietlog);
+	quietlog = 1;
+#endif	
+#ifdef SUPPORT_UTMP
+	doutmp();
+	dolastlog(quietlog);
+#endif
+}
+
+#ifdef SUPPORT_UTMPX
+static void
+doutmpx(void)
+{
+	struct utmpx utmpx;
+	char *t;
+
+	memset((void *)&utmpx, 0, sizeof(utmpx));
+	utmpx.ut_tv = now;
+	(void)strncpy(utmpx.ut_name, username, sizeof(utmpx.ut_name));
+	if (hostname) {
+		(void)strncpy(utmpx.ut_host, hostname, sizeof(utmpx.ut_host));
+		utmpx.ut_ss = ss;
+	}
+	(void)strncpy(utmpx.ut_line, tty, sizeof(utmpx.ut_line));
+	utmpx.ut_type = USER_PROCESS;
+	utmpx.ut_pid = getpid();
+	t = tty + strlen(tty);
+	if (t - tty >= sizeof(utmpx.ut_id)) {
+	    (void)strncpy(utmpx.ut_id, t - sizeof(utmpx.ut_id),
+		sizeof(utmpx.ut_id));
+	} else {
+	    (void)strncpy(utmpx.ut_id, tty, sizeof(utmpx.ut_id));
+	}
+	if (pututxline(&utmpx) == NULL)
+		syslog(LOG_NOTICE, "Cannot update utmpx: %m");
+	endutxent();
+	if (updwtmpx(_PATH_WTMPX, &utmpx) != 0)
+		syslog(LOG_NOTICE, "Cannot update wtmpx: %m");
+}
+
+static void
+dolastlogx(int quiet)
+{
+	struct lastlogx ll;
+	if (!quiet && getlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != NULL) {
+		time_t t = (time_t)ll.ll_tv.tv_sec;
+		(void)printf("Last login: %.24s ", ctime(&t));
+		if (*ll.ll_host != '\0')
+			(void)printf("from %.*s ",
+			    (int)sizeof(ll.ll_host),
+			    ll.ll_host);
+		(void)printf("on %.*s\n",
+		    (int)sizeof(ll.ll_line),
+		    ll.ll_line);
+	}
+	ll.ll_tv = now;
+	(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+	if (hostname)
+		(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+	else
+		(void)memset(ll.ll_host, '\0', sizeof(ll.ll_host));
+	if (have_ss)
+		ll.ll_ss = ss;
+	else
+		(void)memset(&ll.ll_ss, 0, sizeof(ll.ll_ss));
+	if (updlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != 0)
+		syslog(LOG_NOTICE, "Cannot update lastlogx: %m");
+}
+#endif
+
+#ifdef SUPPORT_UTMP
+static void
+doutmp(void)
+{
+	struct utmp utmp;
+
+	(void)memset((void *)&utmp, 0, sizeof(utmp));
+	utmp.ut_time = now.tv_sec;
+	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
+	if (hostname)
+		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
+	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
+	login(&utmp);
+}
+
+static void
+dolastlog(int quiet)
+{
+	struct lastlog ll;
+	int fd;
+
+	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
+		(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), SEEK_SET);
+		if (!quiet) {
+			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
+			    ll.ll_time != 0) {
+				(void)printf("Last login: %.24s ",
+				    ctime(&ll.ll_time));
+				if (*ll.ll_host != '\0')
+					(void)printf("from %.*s ",
+					    (int)sizeof(ll.ll_host),
+					    ll.ll_host);
+				(void)printf("on %.*s\n",
+				    (int)sizeof(ll.ll_line), ll.ll_line);
+			}
+			(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)),
+			    SEEK_SET);
+		}
+		memset((void *)&ll, 0, sizeof(ll));
+		ll.ll_time = now.tv_sec;
+		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+		if (hostname)
+			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+		(void)write(fd, (char *)&ll, sizeof(ll));
+		(void)close(fd);
+	}
+}
+#endif
+
+void
+badlogin(const char *name)
+{
+
+	if (failures == 0)
+		return;
+	if (hostname) {
+		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
+		    failures, failures > 1 ? "S" : "", hostname);
+		syslog(LOG_AUTHPRIV|LOG_NOTICE,
+		    "%d LOGIN FAILURE%s FROM %s, %s",
+		    failures, failures > 1 ? "S" : "", hostname, name);
+	} else {
+		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
+		    failures, failures > 1 ? "S" : "", tty);
+		syslog(LOG_AUTHPRIV|LOG_NOTICE,
+		    "%d LOGIN FAILURE%s ON %s, %s",
+		    failures, failures > 1 ? "S" : "", tty, name);
+	}
+}
+
+const char *
+stypeof(const char *ttyid)
+{
+	struct ttyent *t;
+
+	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL);
+}
+
+void
+sleepexit(int eval)
+{
+
+	(void)sleep(5);
+	exit(eval);
+}
+
+void
+decode_ss(const char *arg)
+{
+	struct sockaddr_storage *ssp;
+	size_t len = strlen(arg);
+	
+	if (len > sizeof(*ssp) * 4 + 1 || len < sizeof(*ssp))
+		errx(EXIT_FAILURE, "Bad argument");
+
+	if ((ssp = malloc(len)) == NULL)
+		err(EXIT_FAILURE, NULL);
+
+	if (strunvis((char *)ssp, arg) != sizeof(*ssp))
+		errx(EXIT_FAILURE, "Decoding error");
+
+	(void)memcpy(&ss, ssp, sizeof(ss));
+	free(ssp);
+	have_ss = 1;
+}
Index: src/usr.bin/login/common.h
diff -u /dev/null src/usr.bin/login/common.h:1.1
--- /dev/null	Tue Dec 29 14:26:13 2009
+++ src/usr.bin/login/common.h	Tue Dec 29 14:26:13 2009
@@ -0,0 +1,53 @@
+/*	$NetBSD: common.h,v 1.1 2009/12/29 19:26:13 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
+ *	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. 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.
+ */
+
+__BEGIN_DECLS
+
+void	 badlogin(const char *);
+void	 update_db(int, int, int);
+void	 getloginname(void);
+void	 motd(char *);
+int	 rootterm(char *);
+void	 sigint(int);
+void	 sleepexit(int);
+const	 char *stypeof(const char *);
+void	 timedout(int);
+void	 decode_ss(const char *);
+
+extern u_int	timeout;
+extern struct	passwd *pwd;
+extern int	failures, have_ss;
+extern char	term[64], *envinit[1], *hostname, *username, *tty, *nested;
+extern struct timeval now;
+extern struct sockaddr_storage ss;
+extern const char copyrightstr[];
+
+__END_DECLS

Reply via email to