util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* login: PAM-only, login.defs, -H
@ 2011-10-17 11:02 Karel Zak
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
  2011-11-17 10:31 ` login: PAM-only, login.defs, -H Thorsten Kukuk
  0 siblings, 2 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:02 UTC (permalink / raw)
  To: util-linux; +Cc: Ludwig Nussel, Thorsten Kukuk


 I did some changes to login(1) in last weeks. The goal is to have one PAM-only
 login(1) for all mainstream distributions. 

 The code is based on the original util-linux login(1) and pam_login-4.0
 package from Suse.

 Git tree: https://karelzak@github.com/karelzak/util-linux.git branch 'login'.
 URL: https://github.com/karelzak/util-linux/tree/login

 Changes:

 - remove kerberos specific code
 - remove non-PAM code
 - remove checktty stuff
 - remove ugly macros (e.g. PAM_END)
 - add syslog LOG_ERR on failed tty ch{mod,own} (based on Suse version)
 - move all important/global variables to 'struct login_context'
 - indent to Linux coding style
 - use xalloc.h functions
 - lastlog, utmp, btmp, audit and syslog code refactoring

 - don't log unknown usernames to system log files (may be a security issue if
   an user enter her password instead of her login name) -- controlled by
   LOG_UNKFAIL_ENAB login.defs variable

 - support /etc/login.defs, supported variables:

     name               default
     ------------------------------
     DEFAULT_HOME       yes (means chdir("/") if pwd->pw_dir does not exist)  
     ENV_PATH           "/usr/local/bin:/bin:/usr/bin"
     ENV_{ROOT,SU}PATH  "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
     FAIL_DELAY		5s
     HUSHLOGIN_FILE     /etc/hushlogins and ~/.hushlog
     LOGIN_TIMEOUT      60s
     LOG_UNKFAIL_ENAB	yes
     MOTD_FILE          /etc/motd
     TTYGROUP           'tty' (otherwise pwd->pw_gid is used)
     TTYPERM            0620 (or 0600 for --disable-use-tty-group)
    
   Note that Suse version does not use any defaults for *_FILE and TTYGROUP.

 - print hostname in the login prompt, for example:

     "foo login: "

   Note that Suse version uses hostname with domain (e.g. foo.example.com), our
   goal is to be compatible with the default agetty behavior. 
  
 - add new -H option to suppress hostname in the login prompt (already in Suse
   version)
   
 - call setgroups(0, NULL) rather than initgroups() for root user
   (this avoids the need to step through the whole group file, which can cause
    problems if NIS, NIS+, LDAP or something similar is used and the machine 
    has network problems)

 - improve hushed mode (moslty based on Suse version)
   * accepts HUSHLOGIN_FILE from /etc/login.defs
   * empty /etc/hushlogins file enables hushed mode for all accounts
     (this new feature is necessary if you want to use PAM for motd and last 
      login messages)

 Comments?

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 00/49] login refactoring
  2011-10-17 11:02 login: PAM-only, login.defs, -H Karel Zak
@ 2011-10-17 11:14 ` Karel Zak
  2011-10-17 11:14   ` [PATCH 01/49] login: remove kerberos specific code Karel Zak
                     ` (48 more replies)
  2011-11-17 10:31 ` login: PAM-only, login.defs, -H Thorsten Kukuk
  1 sibling, 49 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

git://github.com/karelzak/util-linux.git login

Karel Zak (49):
  login: remove kerberos specific code
  login: remove dead code and comments
  login: move _PATH_BTMP to pathnames.h
  login: remove non-PAM code
  build-sys: require PAM for login-utils
  login: remove PAM_FAIL_CHECK and PAM_END macros
  lib: cleanup setproctitle.c
  login: cleanup begin of the login.c file
  login: remove obsolete code, clean up macros names
  login: indent -linux
  login: add struct login_context, consolidate tty code
  login: add hostname to login_context struct
  login: add pid to login_context struct
  login: add username to login_context struct
  login: use login_context struct in audit stuff
  login: lastlog code refactoring
  login: utmp code refactoring
  login: use getpwnam_r() rather than manually copy passwd struct
  login: tty chown.chmod refactoring
  login: use setgroups(0, NULL) for root
  login: improve hushed mode (merge suse changes)
  login: remove unused code and tests
  login: PAM initialization refactoring
  login: PAM auth refactoring
  login: PAM account checks refactoring
  login: PAM session initialization refactoring
  login: remove pam_handle_t from main()
  login: fork & session initialization refactoring
  login: env initialization refactoring
  login: use xalloc.h
  login: log good logins refactoring
  login: move signal stuff to the one place
  login: remove unnecessary variables
  login: host{name,address} initialization refactoring
  tests: cleanup islocal test
  login: add login.defs code and tests
  tests: remove obsolete checktty test
  login: remove obsolete info from man page
  login: rewrite motd(), use MOTD_FILE from login.defs
  login: use LOGIN_TIMEOUT from login.defs
  login: use FAIL_DELAY from login.defs
  login: use TTYPERM from login.defs
  login:  use TTYGROUP from login.defs
  login:  use HUSHLOGIN_FILE from login.defs
  login: use DEFAULT_HOME from login.defs
  login: use LOG_UNKFAIL_ENAB from login.defs, improve logging
  login: add -H option for compatibility with Suse
  login: use ENV_PATH and ENV_{ROOT,SU}PATH from login.defs
  login: cosmetic changes in docs

 configure.ac                   |   16 +-
 include/pathnames.h            |    7 +
 include/setproctitle.h         |   10 +-
 lib/setproctitle.c             |   75 +-
 login-utils/.gitignore         |    4 +-
 login-utils/Makefile.am        |   20 +-
 login-utils/checktty.c         |  585 ----------
 login-utils/islocal.c          |    6 +-
 login-utils/login.1            |  375 +++----
 login-utils/login.c            | 2413 +++++++++++++++++++---------------------
 login-utils/login.h            |    9 -
 login-utils/logindefs.c        |  246 ++++
 login-utils/logindefs.h        |    9 +
 tests/commands.sh.in           |    5 +-
 tests/expected/login/checktty  |    8 -
 tests/expected/login/logindefs |   14 +
 tests/ts/login/checktty        |   26 -
 tests/ts/login/islocal         |    2 +-
 tests/ts/login/logindefs       |   24 +
 tests/ts/login/logindefs.data  |   16 +
 20 files changed, 1676 insertions(+), 2194 deletions(-)
 delete mode 100644 login-utils/checktty.c
 delete mode 100644 login-utils/login.h
 create mode 100644 login-utils/logindefs.c
 create mode 100644 login-utils/logindefs.h
 delete mode 100644 tests/expected/login/checktty
 create mode 100644 tests/expected/login/logindefs
 delete mode 100755 tests/ts/login/checktty
 create mode 100755 tests/ts/login/logindefs
 create mode 100644 tests/ts/login/logindefs.data

-- 
1.7.6.4

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 01/49] login: remove kerberos specific code
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 02/49] login: remove dead code and comments Karel Zak
                     ` (47 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

The code has not been used ever. If you want to use kerberos then us
PAM...

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   24 ------------------------
 1 files changed, 0 insertions(+), 24 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 9662336..c02ce3b 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -842,30 +842,6 @@ main(int argc, char **argv)
 	p = crypt(pp, salt);
 	setpriority(PRIO_PROCESS, 0, 0);
 
-#  ifdef KERBEROS
-	/*
-	 * If not present in pw file, act as we normally would.
-	 * If we aren't Kerberos-authenticated, try the normal
-	 * pw file for a password.  If that's ok, log the user
-	 * in without issueing any tickets.
-	 */
-
-	if (pwd && !krb_get_lrealm(realm,1)) {
-	    /*
-	     * get TGT for local realm; be careful about uid's
-	     * here for ticket file ownership
-	     */
-	    setreuid(geteuid(),pwd->pw_uid);
-	    kerror = krb_get_pw_in_tkt(pwd->pw_name, "", realm,
-				       "krbtgt", realm, DEFAULT_TKT_LIFE, pp);
-	    setuid(0);
-	    if (kerror == INTK_OK) {
-		memset(pp, 0, strlen(pp));
-		notickets = 0;	/* user got ticket */
-		break;
-	    }
-	}
-#  endif /* KERBEROS */
 	memset(pp, 0, strlen(pp));
 
 	if (pwd && !strcmp(p, pwd->pw_passwd))
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 02/49] login: remove dead code and comments
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
  2011-10-17 11:14   ` [PATCH 01/49] login: remove kerberos specific code Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 03/49] login: move _PATH_BTMP to pathnames.h Karel Zak
                     ` (46 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 4589 bytes --]

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  103 ++++----------------------------------------------
 1 files changed, 9 insertions(+), 94 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index c02ce3b..118bda9 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1,60 +1,13 @@
-/* This program is derived from 4.3 BSD software and is
-   subject to the copyright notice below.
-
-   The port to HP-UX has been motivated by the incapability
-   of 'rlogin'/'rlogind' as per HP-UX 6.5 (and 7.0) to transfer window sizes.
-
-   Changes:
-
-   - General HP-UX portation. Use of facilities not available
-     in HP-UX (e.g. setpriority) has been eliminated.
-     Utmp/wtmp handling has been ported.
-
-   - The program uses BSD command line options to be used
-     in connection with e.g. 'rlogind' i.e. 'new login'.
-
-   - HP features left out:	    password expiry
-				    '*' as login shell, add it if you need it
-
-   - BSD features left out:         quota checks
-   	                            password expiry
-				    analysis of terminal type (tset feature)
-
-   - BSD features thrown in:        Security logging to syslogd.
-                                    This requires you to have a (ported) syslog
-				    system -- 7.0 comes with syslog
-
-				    'Lastlog' feature.
-
-   - A lot of nitty gritty details have been adjusted in favour of
-     HP-UX, e.g. /etc/securetty, default paths and the environment
-     variables assigned by 'login'.
-
-   - We do *nothing* to setup/alter tty state, under HP-UX this is
-     to be done by getty/rlogind/telnetd/some one else.
-
-   Michael Glad (glad@daimi.dk)
-   Computer Science Department
-   Aarhus University
-   Denmark
-
-   1990-07-04
-
-   1991-09-24 glad@daimi.aau.dk: HP-UX 8.0 port:
-   - now explictly sets non-blocking mode on descriptors
-   - strcasecmp is now part of HP-UX
-
-   1992-02-05 poe@daimi.aau.dk: Ported the stuff to Linux 0.12
-   From 1992 till now (1997) this code for Linux has been maintained at
-   ftp.daimi.aau.dk:/pub/linux/poe/
-
-   1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
-    - added Native Language Support
-   Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-    - fixed strerr(errno) in gettext calls
- */
-
 /*
+ * login(1)
+ *
+ * This program is derived from 4.3 BSD software and is subject to the
+ * copyright notice below.
+ *
+ * Michael Glad (glad@daimi.dk)
+ * Computer Science Department, Aarhus University, Denmark
+ * 1990-07-04
+ *
  * Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
  * All rights reserved.
  *
@@ -70,15 +23,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
-
-/*
- * login [ name ]
- * login -h hostname	(for telnetd, etc.)
- * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
- */
-
 #include <sys/param.h>
-
 #include <stdio.h>
 #include <ctype.h>
 #include <unistd.h>
@@ -91,8 +36,6 @@
 #include <sys/file.h>
 #include <termios.h>
 #include <string.h>
-#define index strchr
-#define rindex strrchr
 #include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <signal.h>
@@ -567,12 +510,6 @@ main(int argc, char **argv)
 
     openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
 
-#if 0
-    /* other than iso-8859-1 */
-    printf("\033(K");
-    fprintf(stderr,"\033(K");
-#endif
-
 #ifdef HAVE_SECURITY_PAM_MISC_H
     /*
      * username is initialized to NULL
@@ -603,15 +540,6 @@ main(int argc, char **argv)
     retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
     PAM_FAIL_CHECK;
 
-#if 0
-    /*
-     * other than iso-8859-1
-     * one more time due to reset tty by PAM
-     */
-    printf("\033(K");
-    fprintf(stderr,"\033(K");
-#endif
-
     if (username) {
 	/* we need't the original username. We have to follow PAM. */
 	free(username);
@@ -963,18 +891,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
 #if HAVE_UPDWTMP
 	updwtmp(_PATH_WTMP, &ut);
 #else
-#if 0
-	/* The O_APPEND open() flag should be enough to guarantee
-	   atomic writes at end of file. */
-	{
-	    int wtmp;
-
-	    if((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
-		write(wtmp, (char *)&ut, sizeof(ut));
-		close(wtmp);
-	    }
-	}
-#else
 	/* Probably all this locking below is just nonsense,
 	   and the short version is OK as well. */
 	{
@@ -990,7 +906,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
 	    }
 	}
 #endif
-#endif
     }
 
     logaudit(tty_name, username, hostname, pwd, 1);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/49] login: move _PATH_BTMP to pathnames.h
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
  2011-10-17 11:14   ` [PATCH 01/49] login: remove kerberos specific code Karel Zak
  2011-10-17 11:14   ` [PATCH 02/49] login: remove dead code and comments Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 04/49] login: remove non-PAM code Karel Zak
                     ` (45 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 include/pathnames.h |    4 ++++
 login-utils/login.c |    1 -
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/include/pathnames.h b/include/pathnames.h
index d7d2a14..025e4af 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -135,5 +135,9 @@
 # define _PATH_RTC_DEV		"/dev/rtc"
 #endif
 
+#ifndef _PATH_BTMP
+#define _PATH_BTMP		"/var/log/btmp"
+#endif
+
 #endif /* PATHNAMES_H */
 
diff --git a/login-utils/login.c b/login-utils/login.c
index 118bda9..bcac52d 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -206,7 +206,6 @@ consoletty(int fd) {
  * Must be called only with username the name of an actual user.
  * The most common login failure is to give password instead of username.
  */
-#define	_PATH_BTMP	"/var/log/btmp"
 static void
 logbtmp(const char *line, const char *username, const char *hostname) {
 	struct utmp ut;
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/49] login: remove non-PAM code
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (2 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 03/49] login: move _PATH_BTMP to pathnames.h Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 05/49] build-sys: require PAM for login-utils Karel Zak
                     ` (44 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 24686 bytes --]

If you need non-PAM login(1) then use shadow-utils or busybox.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/.gitignore  |    1 -
 login-utils/Makefile.am |   11 +-
 login-utils/checktty.c  |  585 -----------------------------------------------
 login-utils/login.c     |  240 +-------------------
 4 files changed, 6 insertions(+), 831 deletions(-)
 delete mode 100644 login-utils/checktty.c

diff --git a/login-utils/.gitignore b/login-utils/.gitignore
index 4d01927..31af9d4 100644
--- a/login-utils/.gitignore
+++ b/login-utils/.gitignore
@@ -1,4 +1,3 @@
-checktty_test
 islocal_test
 chfn
 chsh
diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index f009f2d..7866f7b 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -42,14 +42,7 @@ chfn_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
 chsh_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
 newgrp_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
 
-if HAVE_PAM
 login_ldadd_common += -lpam -lpam_misc
-else
-if NEED_LIBCRYPT
-login_ldadd_common += -lcrypt
-endif
-login_SOURCES += checktty.c
-endif #! HAVE_PAM
 
 if NEED_LIBCRYPT
 newgrp_LDADD += -lcrypt
@@ -72,9 +65,7 @@ install-exec-hook::
 
 endif
 
-noinst_PROGRAMS = checktty_test islocal_test
-checktty_test_SOURCES = checktty.c login.h
-checktty_test_CPPFLAGS = -DMAIN_TEST_CHECKTTY $(AM_CPPFLAGS)
+noinst_PROGRAMS = islocal_test
 islocal_test_SOURCES = islocal.c
 islocal_test_CPPFLAGS = -DMAIN_TEST_ISLOCAL $(AM_CPPFLAGS)
 
diff --git a/login-utils/checktty.c b/login-utils/checktty.c
deleted file mode 100644
index 14f3ee1..0000000
--- a/login-utils/checktty.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/* checktty.c - linked into login, checks user against /etc/usertty
-   Created 25-Aug-95 by Peter Orbaek <poe@daimi.aau.dk>
-   Fixed by JDS June 1996 to clear lists and close files
-
-   1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
-   - added Native Language Support
-
-*/
-
-#include <sys/param.h>
-
-#include <pwd.h>
-#include <grp.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <netdb.h>
-#include <syslog.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <ctype.h>
-#include <limits.h>
-#include <netinet/in.h>
-#include "nls.h"
-
-#include <sys/sysmacros.h>
-#ifdef HAVE_LINUX_MAJOR_H
-#include <linux/major.h>
-#endif
-
-#include "pathnames.h"
-#include "login.h"
-#include "strutils.h"
-
-#ifndef TTY_MAJOR
-#define TTY_MAJOR 4
-#endif
-
-static gid_t mygroups[NGROUPS_MAX];
-static int   num_groups;
-
-#define NAMELEN 128
-
-/* linked list of names */
-struct grplist {
-    struct grplist *next;
-    char name[NAMELEN];
-};
-        
-enum State { StateUsers, StateGroups, StateClasses };
-
-#define CLASSNAMELEN 32
-
-struct ttyclass {
-    struct grplist *first;
-    struct ttyclass *next;
-    char classname[CLASSNAMELEN];
-};
-
-struct ttyclass *ttyclasses = NULL;
-
-static int
-am_in_group(char *group)
-{
-	struct group *g;
-	gid_t *ge;
-	
-	g = getgrnam(group);
-	if (g) {
-		for (ge = mygroups; ge < mygroups + num_groups; ge++) {
-			if (g->gr_gid== *ge) return 1;
-		}
-	}
-    	return 0;
-}
-
-static void
-find_groups()
-{
-	num_groups = getgroups(NGROUPS_MAX, mygroups);
-}
-
-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;
-    xstrncpy(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;
-    xstrncpy(ge->name, tty, NAMELEN);
-    tc->first = ge;
-}
-
-
-/* return true if tty is a pty. Very linux dependent */
-static int
-isapty(const char *tty)
-{
-#ifdef __linux__
-    char devname[100];
-    struct stat stb;
-
-    /* avoid snprintf - old systems do not have it */
-    if (strlen(tty) + 6 > sizeof(devname))
-	    return 0;
-    sprintf(devname, "/dev/%s", tty);
-
-    if((stat(devname, &stb) >= 0) && S_ISCHR(stb.st_mode)) {
-	    int majordev = major(stb.st_rdev);
-
-	    /* this is for linux versions before 1.3: use major 4 */
-	    if(majordev == TTY_MAJOR && minor(stb.st_rdev) >= 192)
-		    return 1;
-
-#if defined(PTY_SLAVE_MAJOR)
-	    /* this is for linux 1.3 and newer: use major 3 */
-	    if(majordev == PTY_SLAVE_MAJOR)
-		    return 1;
-#endif
-
-#if defined(UNIX98_PTY_SLAVE_MAJOR) && defined(UNIX98_PTY_MAJOR_COUNT)
-	    /* this is for linux 2.1.116 and newer: use majors 136-143 */
-	    if(majordev >= UNIX98_PTY_SLAVE_MAJOR &&
-	       majordev < UNIX98_PTY_SLAVE_MAJOR + UNIX98_PTY_MAJOR_COUNT)
-		    return 1;
-#endif
-
-    }
-#endif	/* __linux__ */
-    return 0;
-}
-
-
-/* IPv4 -- pattern is x.x.x.x/y.y.y.y (net/mask)*/
-static int
-hnmatch_ip4(const char *pat)
-{
-	int x1, x2, x3, x4, y1, y2, y3, y4;
-	unsigned long p, mask, a;
-	unsigned char *ha;
-
-	/* pattern is an IP QUAD address and a mask x.x.x.x/y.y.y.y */
-	if (sscanf(pat, "%d.%d.%d.%d/%d.%d.%d.%d",
-			&x1, &x2, &x3, &x4, &y1, &y2, &y3, &y4) < 8)
-		return 0;
-
-	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[0] == 0)
-		return 0;
-
-	ha = (unsigned char *)hostaddress;
-	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));
-}
-
-/* IPv6 -- pattern is [hex:hex:....]/number ([net]/mask) */
-static int
-hnmatch_ip6(const char *pat)
-{
-	char *patnet;
-	char *patmask;
-	struct in6_addr addr;
-	struct addrinfo hints, *res;
-	struct sockaddr_in6 net;
-	int mask_len, i = 0;
-	char *p;
-
-	if (pat == NULL || *pat != '[')
-		return 0;
-
-	memcpy(&addr, hostaddress, sizeof(addr));
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = AF_INET6;
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
-
-	patnet = strdup(pat);
-
-	/* match IPv6 address against [netnumber]/prefixlen */
-	if (!(p = strchr(patnet, ']')))
-		goto mismatch;
-
-	*p++ = '\0';
-
-	if (! (*p == '/' && isdigit((unsigned char) *(p + 1))))
-		goto mismatch;
-
-	patmask = p + 1;
-
-	/* prepare net address */
-	if (getaddrinfo(patnet + 1, NULL, &hints, &res) != 0)
-		goto mismatch;
-
-	memcpy(&net, res->ai_addr, sizeof(net));
-	freeaddrinfo(res);
-
-	/* convert mask to number */
-	if ((mask_len = atoi(patmask)) < 0 || mask_len > 128)
-		goto mismatch;
-
-	/* compare */
-	while (mask_len > 0) {
-		if (mask_len < 32) {
-			uint32_t mask = htonl(~(0xffffffff >> mask_len));
-
-			if ((*(uint32_t *)&addr.s6_addr[i] & mask) !=
-			    (*(uint32_t *)&net.sin6_addr.s6_addr[i] & mask))
-				goto mismatch;
-			break;
-		}
-		if (*(uint32_t *)&addr.s6_addr[i] !=
-		    *(uint32_t *)&net.sin6_addr.s6_addr[i])
-			goto mismatch;
-		i += 4;
-		mask_len -= 32;
-	}
-
-	free(patnet);
-	return 1;
-
-mismatch:
-	free(patnet);
-	return 0;
-}
-
-/* match the hostname hn against the pattern pat */
-static int
-hnmatch(const char *hn, const char *pat)
-{
-
-	if ((hn == NULL) && (strcmp(pat, "localhost") == 0))
-		return 1;
-	if ((hn == NULL) || *hn == '\0')
-		return 0;
-
-	if (*pat >= '0' && *pat <= '9')
-		return hostfamily == AF_INET ? hnmatch_ip4(pat) : 0;
-	else if (*pat == '[')
-		return hostfamily == AF_INET6 ? hnmatch_ip6(pat) : 0;
-	else {
-		/* pattern is a suffix of a FQDN */
-		int 	n = strlen(pat),
-			m = strlen(hn);
-
-		if (n > m)
-			return 0;
-		return (strcasecmp(pat, hn + m - n) == 0);
-	}
-}
-
-#ifdef MAIN_TEST_CHECKTTY
-
-char	hostaddress[16];
-sa_family_t hostfamily;
-char	*hostname;
-
-void sleepexit(int eval __attribute__ ((__unused__)))
-{
-	/* dummy for this test */
-}
-
-void badlogin(const char *s __attribute__ ((__unused__)))
-{
-	/* dummy for this test */
-}
-
-int
-main(int argc __attribute__ ((__unused__)),
-     char **argv __attribute__ ((__unused__)))
-{
-	struct addrinfo hints, *info = NULL;
-	struct addrexp {
-		const char *range;
-		const char *ip;
-	} alist[] = {
-		{ "130.225.16.0/255.255.254.0",	"130.225.16.1" },
-		{ "130.225.16.0/255.255.254.0",	"10.20.30.1" },
-		{ "130.225.0.0/255.254.0.0",	"130.225.16.1" },
-		{ "130.225.0.0/255.254.0.0",	"130.225.17.1" },
-		{ "130.225.0.0/255.254.0.0",	"150.160.170.180" },
-		{ "[3ffe:505:2:1::]/64",	"3ffe:505:2:1::" },
-		{ "[3ffe:505:2:1::]/64",	"3ffe:505:2:2::" },
-		{ "[3ffe:505:2:1::]/64",	"3ffe:505:2:1:ffff:ffff::" },
-		{ NULL, NULL }
-	}, *item;
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_flags = AI_NUMERICHOST |  AI_PASSIVE | AI_ADDRCONFIG;
-	hints.ai_socktype = SOCK_STREAM;
-
-	for (item = alist; item->range; item++) {
-
-		printf("hnmatch() on %-30s <-- %-15s: ", item->range, item->ip);
-
-		if (getaddrinfo(item->ip, NULL, &hints, &info)==0 && info) {
-			if (info->ai_family == AF_INET)	{
-			    struct sockaddr_in *sa =
-					(struct sockaddr_in *) info->ai_addr;
-			    memcpy(hostaddress, &(sa->sin_addr),
-					sizeof(sa->sin_addr));
-			}
-			else if (info->ai_family == AF_INET6) {
-			    struct sockaddr_in6 *sa =
-					(struct sockaddr_in6 *) info->ai_addr;
-			    memcpy(hostaddress, &(sa->sin6_addr),
-					sizeof(sa->sin6_addr));
-			}
-			hostfamily = info->ai_family;
-			freeaddrinfo(info);
-			printf("%s\n", hnmatch("dummy", item->range) ?
-						"match" : "mismatch");
-		}
-		else
-			printf("getaddrinfo() failed\n");
-
-	}
-	return EXIT_SUCCESS;
-}
-#endif /* MAIN_TEST_CHECKTTY */
-
-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(const 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;
-	    xstrncpy(timespec, class+1, sizeof(timespec));
-	    *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;
-			xstrncpy(timespec, n+1, sizeof(timespec));
-			*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;
-}
-
-/* start JDS - SBA */
-static void 
-free_group(struct grplist *ge)
-{
-    if (ge) {
-	memset(ge->name, 0, NAMELEN);
-	free_group(ge->next);
-	free(ge->next);
-	ge->next = NULL;
-    }
-}
-
-static void 
-free_class(struct ttyclass *tc)
-{
-    if (tc) {
-	memset(tc->classname, 0, CLASSNAMELEN);
-	free_group(tc->first);
-	tc->first = NULL;
-	free_class(tc->next);
-	free(tc->next);
-	tc->next = NULL;
-    }
-}
-
-static void 
-free_all(void)
-{
-    free_class(ttyclasses);
-    ttyclasses = NULL;
-}
-/* end JDS - SBA */
-
-void
-checktty(const char *user, const 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 */
-    if (!(f = fopen(_PATH_USERTTY, "r"))) return;
-
-    if (pwd == NULL) {
-	fclose(f);
-	return;  /* misspelled username handled elsewhere */
-    }
-
-    find_groups();
-
-    defaultbuf[0] = 0;
-    while(fgets(buf, 255, f)) {
-
-	/* strip comments */
-	for(ptr = buf; ptr < buf + 256; ptr++) 
-	  if(*ptr == '#') *ptr = 0;
-
-	if (buf[0] == '*') {
-	    xstrncpy(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);
-		    free_all(); /* JDS */
-		    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)) {
-		free_all(); /* JDS */
-		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(EXIT_FAILURE);
-    }
-
-    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(EXIT_FAILURE);
-    }
-
-    /* users not matched in /etc/usertty are by default allowed access
-       on all tty's */
-    free_all(); /* JDS */
-}
diff --git a/login-utils/login.c b/login-utils/login.c
index bcac52d..a7d6b02 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -64,21 +64,19 @@
 #include "xalloc.h"
 #include "c.h"
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
-#  include <security/pam_appl.h>
-#  include <security/pam_misc.h>
-#  define PAM_MAX_LOGIN_TRIES	3
-#  define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#define PAM_MAX_LOGIN_TRIES	3
+#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
        fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
        syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
        pam_end(pamh, retcode); exit(EXIT_FAILURE); \
    }
-#  define PAM_END { \
+#define PAM_END { \
 	pam_setcred(pamh, PAM_DELETE_CRED); \
 	retcode = pam_close_session(pamh,0); \
 	pam_end(pamh,retcode); \
 }
-#endif
 
 #include <lastlog.h>
 
@@ -116,9 +114,7 @@ int     timeout = 60;
 
 struct passwd *pwd;
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
 static struct passwd pwdcopy;
-#endif
 char    hostaddress[16];	/* used in checktty.c */
 sa_family_t hostfamily;		/* used in checktty.c */
 char	*hostname;		/* idem */
@@ -200,7 +196,6 @@ consoletty(int fd) {
 }
 #endif
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
 /*
  * Log failed login attempts in _PATH_BTMP if that exists.
  * Must be called only with username the name of an actual user.
@@ -266,8 +261,6 @@ sig_handler(int signal)
 		kill(-child_pid, SIGHUP); /* because the shell often ignores SIGTERM */
 }
 
-#endif	/* HAVE_SECURITY_PAM_MISC_H */
-
 #ifdef HAVE_LIBAUDIT
 static void
 logaudit(const char *tty, const char *username, const char *hostname,
@@ -291,7 +284,6 @@ logaudit(const char *tty, const char *username, const char *hostname,
 # define logaudit(tty, username, hostname, pwd, status)
 #endif /* HAVE_LIBAUDIT */
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
 /* encapsulate stupid "void **" pam_get_item() API */
 int
 get_pam_username(pam_handle_t *pamh, char **name)
@@ -302,7 +294,6 @@ get_pam_username(pam_handle_t *pamh, char **name)
 	*name = (char *) item;
 	return rc;
 }
-#endif
 
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
@@ -335,15 +326,10 @@ main(int argc, char **argv)
     char *childArgv[10];
     char *buff;
     int childArgc = 0;
-#ifdef HAVE_SECURITY_PAM_MISC_H
     int retcode;
     pam_handle_t *pamh = NULL;
     struct pam_conv conv = { misc_conv, NULL };
     struct sigaction sa, oldsa_hup, oldsa_term;
-#else
-    int ask;
-    char *salt, *pp;
-#endif
 #ifdef LOGIN_CHOWN_VCS
     char vcsn[20], vcsan[20];
 #endif
@@ -435,10 +421,6 @@ main(int argc, char **argv)
     argc -= optind;
     argv += optind;
 
-#ifndef HAVE_SECURITY_PAM_MISC_H
-    ask = *argv ? 0 : 1;		/* Do we need ask for login name? */
-#endif
-
     if (*argv) {
 	char *p = *argv;
 	username = strdup(p);
@@ -509,7 +491,6 @@ main(int argc, char **argv)
 
     openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
     /*
      * username is initialized to NULL
      * and if specified on the command line it is set.
@@ -676,118 +657,6 @@ main(int argc, char **argv)
 	    pam_close_session(pamh, 0);
     PAM_FAIL_CHECK;
 
-#else /* ! HAVE_SECURITY_PAM_MISC_H */
-
-    for (cnt = 0;; ask = 1) {
-
-	if (ask) {
-	    fflag = 0;
-	    getloginname();
-	}
-
-	/* 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(EXIT_FAILURE);
-	}
-
-	/* (void)strcpy(tbuf, username); why was this here? */
-	if ((pwd = getpwnam(username))) {
-#  ifdef SHADOW_PWD
-	    struct spwd *sp;
-
-	    if ((sp = getspnam(username)))
-	      pwd->pw_passwd = sp->sp_pwdp;
-#  endif
-	    salt = pwd->pw_passwd;
-	} else
-	  salt = "xx";
-
-	if (pwd) {
-	    initgroups(username, pwd->pw_gid);
-	    checktty(username, tty_name, pwd); /* in checktty.c */
-	}
-
-	/* if user not super-user, check for disabled logins */
-	if (pwd == NULL || pwd->pw_uid)
-	  checknologin();
-
-	/*
-	 * Disallow automatic login to root; if not invoked by
-	 * root, disallow if the uid's differ.
-	 */
-	if (fflag && pwd) {
-	    int uid = getuid();
-
-	    passwd_req = pwd->pw_uid == 0 ||
-	      (uid && uid != pwd->pw_uid);
-	}
-
-	/*
-	 * If trying to log in as root, but with insecure terminal,
-	 * refuse the login attempt.
-	 */
-	if (pwd && pwd->pw_uid == 0 && !rootterm(tty_name)) {
-	    warnx(_("%s login refused on this terminal."),
-		    pwd->pw_name);
-
-	    if (hostname)
-	      syslog(LOG_NOTICE,
-		     _("LOGIN %s REFUSED FROM %s ON TTY %s"),
-		     pwd->pw_name, hostname, tty_name);
-	    else
-	      syslog(LOG_NOTICE,
-		     _("LOGIN %s REFUSED ON TTY %s"),
-		     pwd->pw_name, tty_name);
-	    logaudit(tty_name, pwd->pw_name, hostname, pwd, 0);
-	    continue;
-	}
-
-	/*
-	 * If no pre-authentication and a password exists
-	 * for this user, prompt for one and verify it.
-	 */
-	if (!passwd_req || (pwd && !*pwd->pw_passwd))
-	  break;
-
-	setpriority(PRIO_PROCESS, 0, -4);
-	pp = getpass(_("Password: "));
-
-#  ifdef CRYPTOCARD
-	if (strncmp(pp, "CRYPTO", 6) == 0) {
-	    if (pwd && cryptocard()) break;
-	}
-#  endif /* CRYPTOCARD */
-
-	p = crypt(pp, salt);
-	setpriority(PRIO_PROCESS, 0, 0);
-
-	memset(pp, 0, strlen(pp));
-
-	if (pwd && !strcmp(p, pwd->pw_passwd))
-	  break;
-
-	printf(_("Login incorrect\n"));
-	badlogin(username); /* log ALL bad logins */
-	failures++;
-
-	/* we allow 10 tries, but after 3 we start backing off */
-	if (++cnt > 3) {
-	    if (cnt >= 10) {
-		sleepexit(EXIT_FAILURE);
-	    }
-	    sleep((unsigned int)((cnt - 3) * 5));
-	}
-    }
-#endif /* !HAVE_SECURITY_PAM_MISC_H */
-
     /* committed to login -- turn off timeout */
     alarm((unsigned int)0);
 
@@ -979,7 +848,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
        */
     setenv("LOGNAME", pwd->pw_name, 1);
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
     {
 	int i;
 	char ** env = pam_getenvlist(pamh);
@@ -991,7 +859,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
 	    }
 	}
     }
-#endif
 
     setproctitle("login", username);
 
@@ -1045,8 +912,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
     signal(SIGQUIT, SIG_DFL);
     signal(SIGTSTP, SIG_IGN);
 
-#ifdef HAVE_SECURITY_PAM_MISC_H
-
     memset(&sa, 0, sizeof(sa));
     sa.sa_handler = SIG_IGN;
     sigaction(SIGINT, &sa, NULL);
@@ -1126,7 +991,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
      */
     if (ioctl(0, TIOCSCTTY, 1))
 	    syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
-#endif
     signal(SIGINT, SIG_DFL);
 
     /* discard permissions last so can't get killed and drop core */
@@ -1176,50 +1040,6 @@ Michael Riepe <michael@stud.uni-hannover.de>
     exit(EXIT_SUCCESS);
 }
 
-#ifndef HAVE_SECURITY_PAM_MISC_H
-static void
-getloginname(void) {
-    int ch, cnt, cnt2;
-    char *p;
-    static char nbuf[UT_NAMESIZE + 1];
-
-    cnt2 = 0;
-    for (;;) {
-	cnt = 0;
-	printf(_("\n%s login: "), thishost); fflush(stdout);
-	for (p = nbuf; (ch = getchar()) != '\n'; ) {
-	    if (ch == EOF) {
-		badlogin("EOF");
-		exit(EXIT_FAILURE);
-	    }
-	    if (p < nbuf + UT_NAMESIZE)
-	      *p++ = ch;
-
-	    cnt++;
-	    if (cnt > UT_NAMESIZE + 20) {
-		badlogin(_("NAME too long"));
-		errx(EXIT_FAILURE, _("login name much too long."));
-	    }
-	}
-	if (p > nbuf) {
-	  if (nbuf[0] == '-')
-	     warnx(_("login names may not start with '-'."));
-	  else {
-	      *p = '\0';
-	      username = nbuf;
-	      break;
-	  }
-	}
-
-	cnt2++;
-	if (cnt2 > 50) {
-	    badlogin(_("EXCESSIVE linefeeds"));
-	    errx(EXIT_FAILURE, _("too many bare linefeeds."));
-	}
-    }
-}
-#endif
-
 /*
  * Robert Ambrose writes:
  * A couple of my users have a problem with login processes hanging around
@@ -1252,38 +1072,6 @@ timedout(int sig __attribute__((__unused__))) {
 	timedout2(0);
 }
 
-#ifndef HAVE_SECURITY_PAM_MISC_H
-int
-rootterm(char * ttyn)
-{
-    int fd;
-    char buf[100],*p;
-    int cnt, more = 0;
-
-    fd = open(_PATH_SECURETTY, O_RDONLY);
-    if(fd < 0) return 1;
-
-    /* read each line in /etc/securetty, if a line matches our ttyline
-       then root is allowed to login on this tty, and we should return
-       true. */
-    for(;;) {
-	p = buf; cnt = 100;
-	while(--cnt >= 0 && (more = read(fd, p, 1)) == 1 && *p != '\n') p++;
-	if(more && *p == '\n') {
-	    *p = '\0';
-	    if(!strcmp(buf, ttyn)) {
-		close(fd);
-		return 1;
-	    } else
-	      continue;
-	} else {
-	    close(fd);
-	    return 0;
-	}
-    }
-}
-#endif /* !HAVE_SECURITY_PAM_MISC_H */
-
 jmp_buf motdinterrupt;
 
 void
@@ -1310,24 +1098,6 @@ sigint(int sig  __attribute__((__unused__))) {
     longjmp(motdinterrupt, 1);
 }
 
-#ifndef HAVE_SECURITY_PAM_MISC_H			/* PAM takes care of this */
-void
-checknologin(void) {
-    int fd, nchars;
-    char tbuf[8192];
-
-    if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
-	while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
-	  if (write(fileno(stdout), tbuf, nchars)) {
-		;	/* glibc warn_unused_result */
-	  }
-	}
-	close(fd);
-	sleepexit(EXIT_SUCCESS);
-    }
-}
-#endif
-
 void
 dolastlog(int quiet) {
     struct lastlog ll;
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 05/49] build-sys: require PAM for login-utils
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (3 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 04/49] login: remove non-PAM code Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 06/49] login: remove PAM_FAIL_CHECK and PAM_END macros Karel Zak
                     ` (43 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 configure.ac |   15 ++++-----------
 1 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/configure.ac b/configure.ac
index 88aced9..66d0794 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1099,19 +1099,12 @@ AC_ARG_ENABLE([login-utils],
 )
 AM_CONDITIONAL(BUILD_LOGIN_UTILS, test "x$enable_login_utils" = xyes)
 
-AC_ARG_WITH([pam],
-  [AS_HELP_STRING([--without-pam], [compile login-utils without PAM support])])
-
-AM_CONDITIONAL(HAVE_PAM, false)
-if test "x$enable_login_utils" = xyes && test "x$with_pam" != xno; then
-  AC_CHECK_HEADERS([security/pam_misc.h],
-    [AM_CONDITIONAL(HAVE_PAM, true)],
-    [if test "x$with_pam" = xyes; then
-	AC_MSG_ERROR([PAM selected but security/pam_misc.h not found])
-     fi
-    ])
+if test "x$enable_login_utils" = xyes; then
+  AC_CHECK_HEADERS([security/pam_misc.h], [],
+    [AC_MSG_ERROR([login-utils enabled, but security/pam_misc.h not found])])
 fi
 
+
 AC_ARG_WITH([selinux],
   AS_HELP_STRING([--with-selinux], [compile with SELinux support]),
   [], with_selinux=no
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 06/49] login: remove PAM_FAIL_CHECK and PAM_END macros
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (4 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 05/49] build-sys: require PAM for login-utils Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 07/49] lib: cleanup setproctitle.c Karel Zak
                     ` (42 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

 * use function rather than horrible macros
 * rename get_pam_username -> loginpam_get_username

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   80 +++++++++++++++++++++++++++++---------------------
 1 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index a7d6b02..8ef12af 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -49,10 +49,11 @@
 #include <sys/sysmacros.h>
 #include <linux/major.h>
 #include <netdb.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
 #ifdef HAVE_LIBAUDIT
 # include <libaudit.h>
 #endif
-
 #ifdef HAVE_CRYPT_H
 #include <crypt.h>
 #endif
@@ -64,19 +65,8 @@
 #include "xalloc.h"
 #include "c.h"
 
-#include <security/pam_appl.h>
-#include <security/pam_misc.h>
 #define PAM_MAX_LOGIN_TRIES	3
-#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \
-       fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \
-       syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \
-       pam_end(pamh, retcode); exit(EXIT_FAILURE); \
-   }
-#define PAM_END { \
-	pam_setcred(pamh, PAM_DELETE_CRED); \
-	retcode = pam_close_session(pamh,0); \
-	pam_end(pamh,retcode); \
-}
+#define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
 #include <lastlog.h>
 
@@ -285,8 +275,7 @@ logaudit(const char *tty, const char *username, const char *hostname,
 #endif /* HAVE_LIBAUDIT */
 
 /* encapsulate stupid "void **" pam_get_item() API */
-int
-get_pam_username(pam_handle_t *pamh, char **name)
+static int loginpam_get_username(pam_handle_t *pamh, char **name)
 {
 	const void *item = (void *) *name;
 	int rc;
@@ -295,6 +284,19 @@ get_pam_username(pam_handle_t *pamh, char **name)
 	return rc;
 }
 
+static int loginpam_err(pam_handle_t *pamh, int retcode)
+{
+	const char *msg = pam_strerror(pamh, retcode);
+
+	if (msg) {
+		fprintf(stderr, "\n%s\n", msg);
+		syslog(LOG_ERR, "%s", msg);
+	}
+	pam_end(pamh, retcode);
+	exit(EXIT_FAILURE);
+
+}
+
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
  * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID.
@@ -504,12 +506,17 @@ main(int argc, char **argv)
 	       pam_strerror(pamh, retcode));
 	exit(EXIT_FAILURE);
     }
+
     /* hostname & tty are either set to NULL or their correct values,
-       depending on how much we know */
+     * depending on how much we know
+     */
     retcode = pam_set_item(pamh, PAM_RHOST, hostname);
-    PAM_FAIL_CHECK;
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
+
     retcode = pam_set_item(pamh, PAM_TTY, tty_name);
-    PAM_FAIL_CHECK;
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
 
     /*
      * Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
@@ -518,7 +525,8 @@ main(int argc, char **argv)
      * (yet).
      */
     retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
-    PAM_FAIL_CHECK;
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
 
     if (username) {
 	/* we need't the original username. We have to follow PAM. */
@@ -536,7 +544,7 @@ main(int argc, char **argv)
 	int failcount=0;
 
 	/* if we didn't get a user on the command line, set it to NULL */
-	get_pam_username(pamh, &username);
+	loginpam_get_username(pamh, &username);
 
 	/* there may be better ways to deal with some of these
 	   conditions, but at least this way I don't think we'll
@@ -550,7 +558,7 @@ main(int argc, char **argv)
 	       (retcode == PAM_USER_UNKNOWN) ||
 	       (retcode == PAM_CRED_INSUFFICIENT) ||
 	       (retcode == PAM_AUTHINFO_UNAVAIL))) {
-	    get_pam_username(pamh, &username);
+	    loginpam_get_username(pamh, &username);
 
 	    syslog(LOG_NOTICE,_("FAILED LOGIN %d FROM %s FOR %s, %s"),
 		   failcount, hostname, username, pam_strerror(pamh, retcode));
@@ -562,8 +570,8 @@ main(int argc, char **argv)
 	    retcode = pam_authenticate(pamh, 0);
 	}
 
-	if (retcode != PAM_SUCCESS) {
-	    get_pam_username(pamh, &username);
+	if (is_pam_failure(retcode)) {
+	    loginpam_get_username(pamh, &username);
 
 	    if (retcode == PAM_MAXTRIES)
 		syslog(LOG_NOTICE,_("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
@@ -589,18 +597,18 @@ main(int argc, char **argv)
      */
     retcode = pam_acct_mgmt(pamh, 0);
 
-    if(retcode == PAM_NEW_AUTHTOK_REQD) {
+    if (retcode == PAM_NEW_AUTHTOK_REQD)
         retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
-    }
-
-    PAM_FAIL_CHECK;
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
 
     /*
      * Grab the user information out of the password file for future usage
      * First get the username that we are actually using, though.
      */
-    retcode = get_pam_username(pamh, &username);
-    PAM_FAIL_CHECK;
+    retcode = loginpam_get_username(pamh, &username);
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
 
     if (!username || !*username) {
 	    warnx(_("\nSession setup problem, abort."));
@@ -650,12 +658,14 @@ main(int argc, char **argv)
     }
 
     retcode = pam_open_session(pamh, 0);
-    PAM_FAIL_CHECK;
+    if (is_pam_failure(retcode))
+	loginpam_err(pamh, retcode);
 
     retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
-    if (retcode != PAM_SUCCESS)
+    if (is_pam_failure(retcode)) {
 	    pam_close_session(pamh, 0);
-    PAM_FAIL_CHECK;
+	    loginpam_err(pamh, retcode);
+    }
 
     /* committed to login -- turn off timeout */
     alarm((unsigned int)0);
@@ -944,7 +954,8 @@ Michael Riepe <michael@stud.uni-hannover.de>
     if (child_pid < 0) {
        /* error in fork() */
        warn(_("failure forking"));
-       PAM_END;
+       pam_setcred(pamh, PAM_DELETE_CRED);
+       pam_end(pamh, pam_close_session(pamh, 0));
        exit(EXIT_FAILURE);
     }
 
@@ -961,7 +972,8 @@ Michael Riepe <michael@stud.uni-hannover.de>
        while(wait(NULL) == -1 && errno == EINTR)
 	       ;
        openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
-       PAM_END;
+       pam_setcred(pamh, PAM_DELETE_CRED);
+       pam_end(pamh, pam_close_session(pamh, 0));
        exit(EXIT_SUCCESS);
     }
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 07/49] lib: cleanup setproctitle.c
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (5 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 06/49] login: remove PAM_FAIL_CHECK and PAM_END macros Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 08/49] login: cleanup begin of the login.c file Karel Zak
                     ` (41 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 include/setproctitle.h |   10 +++---
 lib/setproctitle.c     |   75 +++++++++++++-----------------------------------
 2 files changed, 25 insertions(+), 60 deletions(-)

diff --git a/include/setproctitle.h b/include/setproctitle.h
index d57abda..70a9efa 100644
--- a/include/setproctitle.h
+++ b/include/setproctitle.h
@@ -1,7 +1,7 @@
+#ifndef UTIL_LINUX_SETPROCTITLE_H
+#define UTIL_LINUX_SETPROCTITLE_H
+
+extern void initproctitle (int argc, char **argv);
+extern void setproctitle (const char *prog, const char *txt);
 
-void initproctitle (int argc, char **argv);
-#if 0
-void setproctitle (const char *fmt, ...);
-#else
-void setproctitle (const char *prog, const char *txt);
 #endif
diff --git a/lib/setproctitle.c b/lib/setproctitle.c
index 319bc6a..4bcf8c8 100644
--- a/lib/setproctitle.c
+++ b/lib/setproctitle.c
@@ -1,36 +1,26 @@
-/* proctitle code - we know this to work only on linux... */
-
 /*
-**  SETPROCTITLE -- set process title for ps (from sendmail)
-**
-**      Parameters:
-**              fmt -- a printf style format string.
-**
-**      Returns:
-**              none.
-**
-**      Side Effects:
-**              Clobbers argv of our main procedure so ps(1) will
-**              display the title.
-*/
-
+ *  set process title for ps (from sendmail)
+ *
+ *  Clobbers argv of our main procedure so ps(1) will display the title.
+ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+
 #include "setproctitle.h"
 
 #ifndef SPT_BUFSIZE
-#define SPT_BUFSIZE     2048
+# define SPT_BUFSIZE     2048
 #endif
 
-extern char** environ;
+extern char **environ;
 
-static char** argv0;
+static char **argv0;
 static int argv_lth;
 
-void
-initproctitle (int argc, char **argv) {
+void initproctitle (int argc, char **argv)
+{
 	int i;
 	char **envp = environ;
 
@@ -42,9 +32,11 @@ initproctitle (int argc, char **argv) {
 	 */
 	for (i = 0; envp[i] != NULL; i++)
 		continue;
+
 	environ = (char **) malloc(sizeof(char *) * (i + 1));
 	if (environ == NULL)
 		return;
+
 	for (i = 0; envp[i] != NULL; i++)
 		if ((environ[i] = strdup(envp[i])) == NULL)
 			return;
@@ -55,38 +47,12 @@ initproctitle (int argc, char **argv) {
 		argv_lth = envp[i-1] + strlen(envp[i-1]) - argv0[0];
 	else
 		argv_lth = argv0[argc-1] + strlen(argv0[argc-1]) - argv0[0];
-}	
-
-#if 0
-/* Nice code, but many places do not know about vsnprintf ... */
-void
-setproctitle (const char *fmt,...) {
-	int        i;
-	char       buf[SPT_BUFSIZE];
-	va_list    ap;
-
-	if (!argv0)
-		return;
-
-	va_start(ap, fmt);
-	(void) vsnprintf(buf, SPT_BUFSIZE, fmt, ap);
-	va_end(ap);
-
-	i = strlen (buf);
-	if (i > argv_lth - 2) {
-		i = argv_lth - 2;
-		buf[i] = '\0';
-	}
-	memset(argv0[0], '\0', argv_lth);       /* clear the memory area */
-	(void) strcpy (argv0[0], buf);
-
-	argv0[1] = NULL;
 }
-#else
-void
-setproctitle (const char *prog, const char *txt) {
-        int        i;
-        char       buf[SPT_BUFSIZE];
+
+void setproctitle (const char *prog, const char *txt)
+{
+        int i;
+        char buf[SPT_BUFSIZE];
 
         if (!argv0)
                 return;
@@ -94,16 +60,15 @@ setproctitle (const char *prog, const char *txt) {
 	if (strlen(prog) + strlen(txt) + 5 > SPT_BUFSIZE)
 		return;
 
-        (void) sprintf(buf, "%s -- %s", prog, txt);
+	sprintf(buf, "%s -- %s", prog, txt);
 
-        i = strlen (buf);
+        i = strlen(buf);
         if (i > argv_lth - 2) {
                 i = argv_lth - 2;
                 buf[i] = '\0';
         }
 	memset(argv0[0], '\0', argv_lth);       /* clear the memory area */
-        (void) strcpy (argv0[0], buf);
+        strcpy(argv0[0], buf);
 
         argv0[1] = NULL;
 }
-#endif
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 08/49] login: cleanup begin of the login.c file
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (6 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 07/49] lib: cleanup setproctitle.c Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 09/49] login: remove obsolete code, clean up macros names Karel Zak
                     ` (40 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   27 ++++++++++-----------------
 1 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 8ef12af..1bbcddd 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -49,6 +49,7 @@
 #include <sys/sysmacros.h>
 #include <linux/major.h>
 #include <netdb.h>
+#include <lastlog.h>
 #include <security/pam_appl.h>
 #include <security/pam_misc.h>
 #ifdef HAVE_LIBAUDIT
@@ -58,32 +59,19 @@
 #include <crypt.h>
 #endif
 
+#include "c.h"
+#include "setproctitle.h"
 #include "pathnames.h"
 #include "login.h"
 #include "strutils.h"
 #include "nls.h"
 #include "xalloc.h"
-#include "c.h"
 
 #define PAM_MAX_LOGIN_TRIES	3
 #define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
-#include <lastlog.h>
-
 #define SLEEP_EXIT_TIMEOUT 5
 
-#include "setproctitle.h"
-
-#ifndef HAVE_SECURITY_PAM_MISC_H
-static void getloginname (void);
-static void checknologin (void);
-static int rootterm (char *ttyn);
-#endif
-static void timedout (int);
-static void sigint (int);
-static void motd (void);
-static void dolastlog (int quiet);
-
 #ifdef USE_TTY_GROUP
 #  define TTY_MODE 0620
 #else
@@ -100,12 +88,12 @@ static void dolastlog (int quiet);
  * This bounds the time given to login.  Not a define so it can
  * be patched on machines where it's too small.
  */
-int     timeout = 60;
+int timeout = 60;
 
 struct passwd *pwd;
 
 static struct passwd pwdcopy;
-char    hostaddress[16];	/* used in checktty.c */
+char hostaddress[16];	/* used in checktty.c */
 sa_family_t hostfamily;		/* used in checktty.c */
 char	*hostname;		/* idem */
 static char	*username, *tty_name, *tty_number;
@@ -113,6 +101,11 @@ static char	thishost[100];
 static int	failures = 1;
 static pid_t	pid;
 
+static void timedout (int);
+static void sigint (int);
+static void motd (void);
+static void dolastlog (int quiet);
+
 /* Nice and simple code provided by Linus Torvalds 16-Feb-93 */
 /* Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
    He writes: "Login performs open() on a tty in a blocking mode.
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 09/49] login: remove obsolete code, clean up macros names
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (7 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 08/49] login: cleanup begin of the login.c file Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 10/49] login: indent -linux Karel Zak
                     ` (39 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   50 +++++++++++---------------------------------------
 1 files changed, 11 insertions(+), 39 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 1bbcddd..4ed1da3 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -67,10 +67,11 @@
 #include "nls.h"
 #include "xalloc.h"
 
-#define PAM_MAX_LOGIN_TRIES	3
 #define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
-#define SLEEP_EXIT_TIMEOUT 5
+#define LOGIN_MAX_TRIES        3
+#define LOGIN_EXIT_TIMEOUT     5
+#define LOGIN_TIMEOUT          60
 
 #ifdef USE_TTY_GROUP
 #  define TTY_MODE 0620
@@ -80,25 +81,18 @@
 
 #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
 
-#ifndef MAXPATHLEN
-#  define MAXPATHLEN 1024
-#endif
-
 /*
  * This bounds the time given to login.  Not a define so it can
  * be patched on machines where it's too small.
  */
-int timeout = 60;
+int timeout = LOGIN_TIMEOUT;
 
 struct passwd *pwd;
 
 static struct passwd pwdcopy;
 char hostaddress[16];	/* used in checktty.c */
-sa_family_t hostfamily;		/* used in checktty.c */
 char	*hostname;		/* idem */
 static char	*username, *tty_name, *tty_number;
-static char	thishost[100];
-static int	failures = 1;
 static pid_t	pid;
 
 static void timedout (int);
@@ -316,7 +310,7 @@ main(int argc, char **argv)
     int fflag, hflag, pflag, cnt;
     int quietlog, passwd_req;
     char *domain, *ttyn;
-    char tbuf[MAXPATHLEN + 2];
+    char tbuf[PATH_MAX + 2];
     char *termenv;
     char *childArgv[10];
     char *buff;
@@ -351,7 +345,6 @@ main(int argc, char **argv)
      *    host to login so that it may be placed in utmp and wtmp
      */
     gethostname(tbuf, sizeof(tbuf));
-    xstrncpy(thishost, tbuf, sizeof(thishost));
     domain = strchr(tbuf, '.');
 
     username = tty_name = hostname = NULL;
@@ -397,7 +390,6 @@ main(int argc, char **argv)
 			    memcpy(hostaddress, &(sa->sin6_addr),
 					sizeof(sa->sin6_addr));
 			}
-			hostfamily = info->ai_family;
 			freeaddrinfo(info);
 		}
 	  }
@@ -546,7 +538,7 @@ main(int argc, char **argv)
 	   pay attention to failure count and get rid of MAX_LOGIN_TRIES? */
 
 	retcode = pam_authenticate(pamh, 0);
-	while((failcount++ < PAM_MAX_LOGIN_TRIES) &&
+	while((failcount++ < LOGIN_MAX_TRIES) &&
 	      ((retcode == PAM_AUTH_ERR) ||
 	       (retcode == PAM_USER_UNKNOWN) ||
 	       (retcode == PAM_CRED_INSUFFICIENT) ||
@@ -672,15 +664,14 @@ main(int argc, char **argv)
 
        A portable solution would require a fork(), but we rely on Linux
        having the BSD setreuid() */
-
     {
-	char tmpstr[MAXPATHLEN];
+	char tmpstr[PATH_MAX];
 	uid_t ruid = getuid();
 	gid_t egid = getegid();
 
 	/* avoid snprintf - old systems do not have it, or worse,
 	   have a libc in which snprintf is the same as sprintf */
-	if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 > MAXPATHLEN)
+	if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 > PATH_MAX)
 		quietlog = 0;
 	else {
 		sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
@@ -838,9 +829,9 @@ Michael Riepe <michael@stud.uni-hannover.de>
 
     /* mailx will give a funny error msg if you forget this one */
     {
-      char tmp[MAXPATHLEN];
+      char tmp[PATH_MAX];
       /* avoid snprintf */
-      if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < MAXPATHLEN) {
+      if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < PATH_MAX) {
 	      sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
 	      setenv("MAIL",tmp,0);
       }
@@ -1145,28 +1136,9 @@ dolastlog(int quiet) {
     }
 }
 
-void
-badlogin(const char *name) {
-    if (failures == 1) {
-	if (hostname)
-	  syslog(LOG_NOTICE, _("LOGIN FAILURE FROM %s, %s"),
-		 hostname, name);
-	else
-	  syslog(LOG_NOTICE, _("LOGIN FAILURE ON %s, %s"),
-		 tty_name, name);
-    } else {
-	if (hostname)
-	  syslog(LOG_NOTICE, _("%d LOGIN FAILURES FROM %s, %s"),
-		 failures, hostname, name);
-	else
-	  syslog(LOG_NOTICE, _("%d LOGIN FAILURES ON %s, %s"),
-		 failures, tty_name, name);
-    }
-}
-
 /* Should not be called from PAM code... */
 void
 sleepexit(int eval) {
-    sleep(SLEEP_EXIT_TIMEOUT);
+    sleep(LOGIN_EXIT_TIMEOUT);
     exit(eval);
 }
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 10/49] login: indent -linux
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (8 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 09/49] login: remove obsolete code, clean up macros names Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 11/49] login: add struct login_context, consolidate tty code Karel Zak
                     ` (38 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Yeah, this patch is horrible, but necessary before a real changes to
the code...

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c | 1591 ++++++++++++++++++++++++++-------------------------
 1 files changed, 806 insertions(+), 785 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 4ed1da3..9528908 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -52,11 +52,12 @@
 #include <lastlog.h>
 #include <security/pam_appl.h>
 #include <security/pam_misc.h>
+
 #ifdef HAVE_LIBAUDIT
 # include <libaudit.h>
 #endif
 #ifdef HAVE_CRYPT_H
-#include <crypt.h>
+# include <crypt.h>
 #endif
 
 #include "c.h"
@@ -74,12 +75,12 @@
 #define LOGIN_TIMEOUT          60
 
 #ifdef USE_TTY_GROUP
-#  define TTY_MODE 0620
+# define TTY_MODE 0620
 #else
-#  define TTY_MODE 0600
+# define TTY_MODE 0600
 #endif
 
-#define	TTYGRPNAME	"tty"		/* name of group to own ttys */
+#define	TTYGRPNAME	"tty"	/* name of group to own ttys */
 
 /*
  * This bounds the time given to login.  Not a define so it can
@@ -90,15 +91,15 @@ int timeout = LOGIN_TIMEOUT;
 struct passwd *pwd;
 
 static struct passwd pwdcopy;
-char hostaddress[16];	/* used in checktty.c */
-char	*hostname;		/* idem */
-static char	*username, *tty_name, *tty_number;
-static pid_t	pid;
+char hostaddress[16];		/* used in checktty.c */
+char *hostname;			/* idem */
+static char *username, *tty_name, *tty_number;
+static pid_t pid;
 
-static void timedout (int);
-static void sigint (int);
-static void motd (void);
-static void dolastlog (int quiet);
+static void timedout(int);
+static void sigint(int);
+static void motd(void);
+static void dolastlog(int quiet);
 
 /* Nice and simple code provided by Linus Torvalds 16-Feb-93 */
 /* Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
@@ -108,8 +109,8 @@ static void dolastlog (int quiet);
    connection. I believe login should open the line in the non-blocking mode
    leaving the decision to make a connection to getty (where it actually
    belongs). */
-static void
-opentty(const char * tty) {
+static void opentty(const char *tty)
+{
 	int i, fd, flags;
 
 	fd = open(tty, O_RDWR | O_NONBLOCK);
@@ -142,8 +143,8 @@ opentty(const char * tty) {
 /* More precisely, the problem is  ttyn := ttyname(0); ...; chown(ttyn);
    here ttyname() might return "/tmp/x", a hardlink to a pseudotty. */
 /* All of this is a problem only when login is suid, which it isnt. */
-static void
-check_ttyname(char *ttyn) {
+static void check_ttyname(char *ttyn)
+{
 	struct stat statbuf;
 
 	if (ttyn == NULL
@@ -160,16 +161,16 @@ check_ttyname(char *ttyn) {
 
 #ifdef LOGIN_CHOWN_VCS
 /* true if the filedescriptor fd is a console tty, very Linux specific */
-static int
-consoletty(int fd) {
-    struct stat stb;
-
-    if ((fstat(fd, &stb) >= 0)
-	&& (major(stb.st_rdev) == TTY_MAJOR)
-	&& (minor(stb.st_rdev) < 64)) {
-	return 1;
-    }
-    return 0;
+static int consoletty(int fd)
+{
+	struct stat stb;
+
+	if ((fstat(fd, &stb) >= 0)
+	    && (major(stb.st_rdev) == TTY_MAJOR)
+	    && (minor(stb.st_rdev) < 64)) {
+		return 1;
+	}
+	return 0;
 }
 #endif
 
@@ -179,7 +180,8 @@ consoletty(int fd) {
  * The most common login failure is to give password instead of username.
  */
 static void
-logbtmp(const char *line, const char *username, const char *hostname) {
+logbtmp(const char *line, const char *username, const char *hostname)
+{
 	struct utmp ut;
 	struct timeval tv;
 
@@ -191,7 +193,7 @@ logbtmp(const char *line, const char *username, const char *hostname) {
 	strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
 	xstrncpy(ut.ut_line, line, sizeof(ut.ut_line));
 
-#if defined(_HAVE_UT_TV)	    /* in <utmpbits.h> included by <utmp.h> */
+#if defined(_HAVE_UT_TV)	/* in <utmpbits.h> included by <utmp.h> */
 	gettimeofday(&tv, NULL);
 	ut.ut_tv.tv_sec = tv.tv_sec;
 	ut.ut_tv.tv_usec = tv.tv_usec;
@@ -199,23 +201,23 @@ logbtmp(const char *line, const char *username, const char *hostname) {
 	{
 		time_t t;
 		time(&t);
-		ut.ut_time = t;	    /* ut_time is not always a time_t */
+		ut.ut_time = t;	/* ut_time is not always a time_t */
 	}
 #endif
 
-	ut.ut_type = LOGIN_PROCESS; /* XXX doesn't matter */
+	ut.ut_type = LOGIN_PROCESS;	/* XXX doesn't matter */
 	ut.ut_pid = pid;
 	if (hostname) {
 		xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
 		if (hostaddress[0])
-			memcpy(&ut.ut_addr_v6, hostaddress, sizeof(ut.ut_addr_v6));
+			memcpy(&ut.ut_addr_v6, hostaddress,
+			       sizeof(ut.ut_addr_v6));
 	}
 #if HAVE_UPDWTMP		/* bad luck for ancient systems */
 	updwtmp(_PATH_BTMP, &ut);
 #endif
 }
 
-
 static int child_pid = 0;
 static volatile int got_sig = 0;
 
@@ -227,21 +229,20 @@ static volatile int got_sig = 0;
  * Also, parent who is session leader is able (before setsid() in child) to
  * inform child when controlling tty goes away (e.g. modem hangup, SIGHUP).
  */
-static void
-sig_handler(int signal)
+static void sig_handler(int signal)
 {
-	if(child_pid)
+	if (child_pid)
 		kill(-child_pid, signal);
 	else
 		got_sig = 1;
-	if(signal == SIGTERM)
-		kill(-child_pid, SIGHUP); /* because the shell often ignores SIGTERM */
+	if (signal == SIGTERM)
+		kill(-child_pid, SIGHUP);	/* because the shell often ignores SIGTERM */
 }
 
 #ifdef HAVE_LIBAUDIT
 static void
 logaudit(const char *tty, const char *username, const char *hostname,
-					struct passwd *pwd, int status)
+	 struct passwd *pwd, int status)
 {
 	int audit_fd;
 
@@ -252,26 +253,27 @@ logaudit(const char *tty, const char *username, const char *hostname,
 		pwd = getpwnam(username);
 
 	audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
-		NULL, "login", username ? username : "(unknown)",
-		pwd ? pwd->pw_uid : (unsigned int) -1, hostname, NULL, tty, status);
+			       NULL, "login", username ? username : "(unknown)",
+			       pwd ? pwd->pw_uid : (unsigned int)-1, hostname,
+			       NULL, tty, status);
 
 	close(audit_fd);
 }
-#else /* ! HAVE_LIBAUDIT */
-# define logaudit(tty, username, hostname, pwd, status)
-#endif /* HAVE_LIBAUDIT */
+#else				/* ! HAVE_LIBAUDIT */
+#define logaudit(tty, username, hostname, pwd, status)
+#endif				/* HAVE_LIBAUDIT */
 
 /* encapsulate stupid "void **" pam_get_item() API */
-static int loginpam_get_username(pam_handle_t *pamh, char **name)
+static int loginpam_get_username(pam_handle_t * pamh, char **name)
 {
-	const void *item = (void *) *name;
+	const void *item = (void *)*name;
 	int rc;
 	rc = pam_get_item(pamh, PAM_USER, &item);
-	*name = (char *) item;
+	*name = (char *)item;
 	return rc;
 }
 
-static int loginpam_err(pam_handle_t *pamh, int retcode)
+static int loginpam_err(pam_handle_t * pamh, int retcode)
 {
 	const char *msg = pam_strerror(pamh, retcode);
 
@@ -290,8 +292,7 @@ static int loginpam_err(pam_handle_t *pamh, int retcode)
  * The open(2) seems as the surest solution.
  * -- kzak@redhat.com (10-Apr-2009)
  */
-int
-effective_access(const char *path, int mode)
+int effective_access(const char *path, int mode)
 {
 	int fd = open(path, mode);
 	if (fd != -1)
@@ -299,741 +300,759 @@ effective_access(const char *path, int mode)
 	return fd == -1 ? -1 : 0;
 }
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
-    extern int optind;
-    extern char *optarg, **environ;
-    struct group *gr;
-    register int ch;
-    register char *p;
-    int fflag, hflag, pflag, cnt;
-    int quietlog, passwd_req;
-    char *domain, *ttyn;
-    char tbuf[PATH_MAX + 2];
-    char *termenv;
-    char *childArgv[10];
-    char *buff;
-    int childArgc = 0;
-    int retcode;
-    pam_handle_t *pamh = NULL;
-    struct pam_conv conv = { misc_conv, NULL };
-    struct sigaction sa, oldsa_hup, oldsa_term;
+	extern int optind;
+	extern char *optarg, **environ;
+	struct group *gr;
+	register int ch;
+	register char *p;
+	int fflag, hflag, pflag, cnt;
+	int quietlog, passwd_req;
+	char *domain, *ttyn;
+	char tbuf[PATH_MAX + 2];
+	char *termenv;
+	char *childArgv[10];
+	char *buff;
+	int childArgc = 0;
+	int retcode;
+	pam_handle_t *pamh = NULL;
+	struct pam_conv conv = { misc_conv, NULL };
+	struct sigaction sa, oldsa_hup, oldsa_term;
 #ifdef LOGIN_CHOWN_VCS
-    char vcsn[20], vcsan[20];
+	char vcsn[20], vcsan[20];
 #endif
 
-    pid = getpid();
-
-    signal(SIGALRM, timedout);
-    siginterrupt(SIGALRM,1);           /* we have to interrupt syscalls like ioclt() */
-    alarm((unsigned int)timeout);
-    signal(SIGQUIT, SIG_IGN);
-    signal(SIGINT, SIG_IGN);
-
-    setlocale(LC_ALL, "");
-    bindtextdomain(PACKAGE, LOCALEDIR);
-    textdomain(PACKAGE);
-
-    setpriority(PRIO_PROCESS, 0, 0);
-    initproctitle(argc, argv);
-
-    /*
-     * -p is used by getty to tell login not to destroy the environment
-     * -f is used to skip a second login authentication
-     * -h is used by other servers to pass the name of the remote
-     *    host to login so that it may be placed in utmp and wtmp
-     */
-    gethostname(tbuf, sizeof(tbuf));
-    domain = strchr(tbuf, '.');
-
-    username = tty_name = hostname = NULL;
-    fflag = hflag = pflag = 0;
-    passwd_req = 1;
-
-    while ((ch = getopt(argc, argv, "fh:p")) != -1)
-      switch (ch) {
-	case 'f':
-	  fflag = 1;
-	  break;
-
-	case 'h':
-	  if (getuid()) {
-	      fprintf(stderr,
-		      _("login: -h for super-user only.\n"));
-	      exit(EXIT_FAILURE);
-	  }
-	  hflag = 1;
-	  if (domain && (p = strchr(optarg, '.')) &&
-	      strcasecmp(p, domain) == 0)
-	    *p = 0;
-
-	  hostname = strdup(optarg); 	/* strdup: Ambrose C. Li */
-	  {
-		struct addrinfo hints, *info = NULL;
-
-		memset(&hints, 0, sizeof(hints));
-		hints.ai_flags = AI_ADDRCONFIG;
-
-		hostaddress[0] = 0;
-
-		if (getaddrinfo(hostname, NULL, &hints, &info)==0 && info) {
-			if (info->ai_family == AF_INET) {
-			    struct sockaddr_in *sa =
-					(struct sockaddr_in *) info->ai_addr;
-			    memcpy(hostaddress, &(sa->sin_addr),
-					sizeof(sa->sin_addr));
+	pid = getpid();
+
+	signal(SIGALRM, timedout);
+	siginterrupt(SIGALRM, 1);	/* we have to interrupt syscalls like ioclt() */
+	alarm((unsigned int)timeout);
+	signal(SIGQUIT, SIG_IGN);
+	signal(SIGINT, SIG_IGN);
+
+	setlocale(LC_ALL, "");
+	bindtextdomain(PACKAGE, LOCALEDIR);
+	textdomain(PACKAGE);
+
+	setpriority(PRIO_PROCESS, 0, 0);
+	initproctitle(argc, argv);
+
+	/*
+	 * -p is used by getty to tell login not to destroy the environment
+	 * -f is used to skip a second login authentication
+	 * -h is used by other servers to pass the name of the remote
+	 *    host to login so that it may be placed in utmp and wtmp
+	 */
+	gethostname(tbuf, sizeof(tbuf));
+	domain = strchr(tbuf, '.');
+
+	username = tty_name = hostname = NULL;
+	fflag = hflag = pflag = 0;
+	passwd_req = 1;
+
+	while ((ch = getopt(argc, argv, "fh:p")) != -1)
+		switch (ch) {
+		case 'f':
+			fflag = 1;
+			break;
+
+		case 'h':
+			if (getuid()) {
+				fprintf(stderr,
+					_("login: -h for super-user only.\n"));
+				exit(EXIT_FAILURE);
 			}
-			else if (info->ai_family == AF_INET6) {
-			    struct sockaddr_in6 *sa =
-					(struct sockaddr_in6 *) info->ai_addr;
-			    memcpy(hostaddress, &(sa->sin6_addr),
-					sizeof(sa->sin6_addr));
+			hflag = 1;
+			if (domain && (p = strchr(optarg, '.')) &&
+			    strcasecmp(p, domain) == 0)
+				*p = 0;
+
+			hostname = strdup(optarg);	/* strdup: Ambrose C. Li */
+			{
+				struct addrinfo hints, *info = NULL;
+
+				memset(&hints, 0, sizeof(hints));
+				hints.ai_flags = AI_ADDRCONFIG;
+
+				hostaddress[0] = 0;
+
+				if (getaddrinfo(hostname, NULL, &hints, &info)
+				    == 0 && info) {
+					if (info->ai_family == AF_INET) {
+						struct sockaddr_in *sa =
+						    (struct sockaddr_in *)info->
+						    ai_addr;
+						memcpy(hostaddress,
+						       &(sa->sin_addr),
+						       sizeof(sa->sin_addr));
+					} else if (info->ai_family == AF_INET6) {
+						struct sockaddr_in6 *sa =
+						    (struct sockaddr_in6 *)
+						    info->ai_addr;
+						memcpy(hostaddress,
+						       &(sa->sin6_addr),
+						       sizeof(sa->sin6_addr));
+					}
+					freeaddrinfo(info);
+				}
 			}
-			freeaddrinfo(info);
+			break;
+
+		case 'p':
+			pflag = 1;
+			break;
+
+		case '?':
+		default:
+			fprintf(stderr, _("usage: login [-fp] [username]\n"));
+			exit(EXIT_FAILURE);
 		}
-	  }
-	  break;
-
-	case 'p':
-	  pflag = 1;
-	  break;
-
-	case '?':
-	default:
-	  fprintf(stderr,
-		  _("usage: login [-fp] [username]\n"));
-	  exit(EXIT_FAILURE);
-      }
-    argc -= optind;
-    argv += optind;
-
-    if (*argv) {
-	char *p = *argv;
-	username = strdup(p);
-
-	/* wipe name - some people mistype their password here */
-	/* (of course we are too late, but perhaps this helps a little ..) */
-	while(*p)
-	    *p++ = ' ';
-    }
-
-    for (cnt = getdtablesize(); cnt > 2; cnt--)
-      close(cnt);
-
-    /* note that libc checks that the file descriptor is a terminal, so we don't
-     * have to call isatty() here */
-    ttyn = ttyname(0);
-    check_ttyname(ttyn);
-
-    if (strncmp(ttyn, "/dev/", 5) == 0)
-	tty_name = ttyn+5;
-    else
-	tty_name = ttyn;
-
-    if (strncmp(ttyn, "/dev/tty", 8) == 0)
-	tty_number = ttyn+8;
-    else {
-	char *p = ttyn;
-	while (*p && !isdigit(*p)) p++;
-	tty_number = p;
-    }
+	argc -= optind;
+	argv += optind;
+
+	if (*argv) {
+		char *p = *argv;
+		username = strdup(p);
+
+		/* wipe name - some people mistype their password here */
+		/* (of course we are too late, but perhaps this helps a little ..) */
+		while (*p)
+			*p++ = ' ';
+	}
+
+	for (cnt = getdtablesize(); cnt > 2; cnt--)
+		close(cnt);
+
+	/* note that libc checks that the file descriptor is a terminal, so we don't
+	 * have to call isatty() here */
+	ttyn = ttyname(0);
+	check_ttyname(ttyn);
+
+	if (strncmp(ttyn, "/dev/", 5) == 0)
+		tty_name = ttyn + 5;
+	else
+		tty_name = ttyn;
+
+	if (strncmp(ttyn, "/dev/tty", 8) == 0)
+		tty_number = ttyn + 8;
+	else {
+		char *p = ttyn;
+		while (*p && !isdigit(*p))
+			p++;
+		tty_number = p;
+	}
 
 #ifdef LOGIN_CHOWN_VCS
-    /* find names of Virtual Console devices, for later mode change */
-    snprintf(vcsn, sizeof(vcsn), "/dev/vcs%s", tty_number);
-    snprintf(vcsan, sizeof(vcsan), "/dev/vcsa%s", tty_number);
+	/* find names of Virtual Console devices, for later mode change */
+	snprintf(vcsn, sizeof(vcsn), "/dev/vcs%s", tty_number);
+	snprintf(vcsan, sizeof(vcsan), "/dev/vcsa%s", tty_number);
 #endif
 
-    /* set pgid to pid */
-    setpgrp();
-    /* this means that setsid() will fail */
+	/* set pgid to pid */
+	setpgrp();
+	/* this means that setsid() will fail */
 
-    {
-	struct termios tt, ttt;
+	{
+		struct termios tt, ttt;
 
-	tcgetattr(0, &tt);
-	ttt = tt;
-	ttt.c_cflag &= ~HUPCL;
+		tcgetattr(0, &tt);
+		ttt = tt;
+		ttt.c_cflag &= ~HUPCL;
 
-	/* These can fail, e.g. with ttyn on a read-only filesystem */
-	if (fchown(0, 0, 0)) {
-		; /* glibc warn_unused_result */
+		/* These can fail, e.g. with ttyn on a read-only filesystem */
+		if (fchown(0, 0, 0)) {
+			;	/* glibc warn_unused_result */
+		}
+
+		fchmod(0, TTY_MODE);
+
+		/* Kill processes left on this tty */
+		tcsetattr(0, TCSAFLUSH, &ttt);
+		signal(SIGHUP, SIG_IGN);	/* so vhangup() wont kill us */
+		vhangup();
+		signal(SIGHUP, SIG_DFL);
+
+		/* open stdin,stdout,stderr to the tty */
+		opentty(ttyn);
+
+		/* restore tty modes */
+		tcsetattr(0, TCSAFLUSH, &tt);
 	}
 
-	fchmod(0, TTY_MODE);
+	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
 
-	/* Kill processes left on this tty */
-	tcsetattr(0,TCSAFLUSH,&ttt);
-	signal(SIGHUP, SIG_IGN); /* so vhangup() wont kill us */
-	vhangup();
-	signal(SIGHUP, SIG_DFL);
+	/*
+	 * username is initialized to NULL
+	 * and if specified on the command line it is set.
+	 * Therefore, we are safe not setting it to anything
+	 */
 
-	/* open stdin,stdout,stderr to the tty */
-	opentty(ttyn);
+	retcode = pam_start(hflag ? "remote" : "login", username, &conv, &pamh);
+	if (retcode != PAM_SUCCESS) {
+		warnx(_("PAM failure, aborting: %s"),
+		      pam_strerror(pamh, retcode));
+		syslog(LOG_ERR, _("Couldn't initialize PAM: %s"),
+		       pam_strerror(pamh, retcode));
+		exit(EXIT_FAILURE);
+	}
 
-	/* restore tty modes */
-	tcsetattr(0,TCSAFLUSH,&tt);
-    }
+	/* hostname & tty are either set to NULL or their correct values,
+	 * depending on how much we know
+	 */
+	retcode = pam_set_item(pamh, PAM_RHOST, hostname);
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
 
-    openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
+	retcode = pam_set_item(pamh, PAM_TTY, tty_name);
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
 
-    /*
-     * username is initialized to NULL
-     * and if specified on the command line it is set.
-     * Therefore, we are safe not setting it to anything
-     */
+	/*
+	 * Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
+	 * so that the "login: " prompt gets localized. Unfortunately,
+	 * PAM doesn't have an interface to specify the "Password: " string
+	 * (yet).
+	 */
+	retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
+
+	if (username) {
+		/* we need't the original username. We have to follow PAM. */
+		free(username);
+		username = NULL;
+	}
 
-    retcode = pam_start(hflag?"remote":"login",username, &conv, &pamh);
-    if(retcode != PAM_SUCCESS) {
-	warnx(_("PAM failure, aborting: %s"), pam_strerror(pamh, retcode));
-	syslog(LOG_ERR, _("Couldn't initialize PAM: %s"),
-	       pam_strerror(pamh, retcode));
-	exit(EXIT_FAILURE);
-    }
-
-    /* hostname & tty are either set to NULL or their correct values,
-     * depending on how much we know
-     */
-    retcode = pam_set_item(pamh, PAM_RHOST, hostname);
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    retcode = pam_set_item(pamh, PAM_TTY, tty_name);
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    /*
-     * Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
-     * so that the "login: " prompt gets localized. Unfortunately,
-     * PAM doesn't have an interface to specify the "Password: " string
-     * (yet).
-     */
-    retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    if (username) {
-	/* we need't the original username. We have to follow PAM. */
-	free(username);
-	username = NULL;
-    }
-
-    /* if fflag == 1, then the user has already been authenticated */
-    if (fflag && (getuid() == 0))
-	passwd_req = 0;
-    else
-	passwd_req = 1;
+	/* if fflag == 1, then the user has already been authenticated */
+	if (fflag && (getuid() == 0))
+		passwd_req = 0;
+	else
+		passwd_req = 1;
+
+	if (passwd_req == 1) {
+		int failcount = 0;
+
+		/* if we didn't get a user on the command line, set it to NULL */
+		loginpam_get_username(pamh, &username);
+
+		/* there may be better ways to deal with some of these
+		   conditions, but at least this way I don't think we'll
+		   be giving away information... */
+		/* Perhaps someday we can trust that all PAM modules will
+		   pay attention to failure count and get rid of MAX_LOGIN_TRIES? */
+
+		retcode = pam_authenticate(pamh, 0);
+		while ((failcount++ < LOGIN_MAX_TRIES) &&
+		       ((retcode == PAM_AUTH_ERR) ||
+			(retcode == PAM_USER_UNKNOWN) ||
+			(retcode == PAM_CRED_INSUFFICIENT) ||
+			(retcode == PAM_AUTHINFO_UNAVAIL))) {
+			loginpam_get_username(pamh, &username);
+
+			syslog(LOG_NOTICE,
+			       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
+			       failcount, hostname, username, pam_strerror(pamh,
+									   retcode));
+			logbtmp(tty_name, username, hostname);
+			logaudit(tty_name, username, hostname, NULL, 0);
+
+			fprintf(stderr, _("Login incorrect\n\n"));
+			pam_set_item(pamh, PAM_USER, NULL);
+			retcode = pam_authenticate(pamh, 0);
+		}
 
-    if(passwd_req == 1) {
-	int failcount=0;
-
-	/* if we didn't get a user on the command line, set it to NULL */
-	loginpam_get_username(pamh, &username);
-
-	/* there may be better ways to deal with some of these
-	   conditions, but at least this way I don't think we'll
-	   be giving away information... */
-	/* Perhaps someday we can trust that all PAM modules will
-	   pay attention to failure count and get rid of MAX_LOGIN_TRIES? */
-
-	retcode = pam_authenticate(pamh, 0);
-	while((failcount++ < LOGIN_MAX_TRIES) &&
-	      ((retcode == PAM_AUTH_ERR) ||
-	       (retcode == PAM_USER_UNKNOWN) ||
-	       (retcode == PAM_CRED_INSUFFICIENT) ||
-	       (retcode == PAM_AUTHINFO_UNAVAIL))) {
-	    loginpam_get_username(pamh, &username);
-
-	    syslog(LOG_NOTICE,_("FAILED LOGIN %d FROM %s FOR %s, %s"),
-		   failcount, hostname, username, pam_strerror(pamh, retcode));
-	    logbtmp(tty_name, username, hostname);
-	    logaudit(tty_name, username, hostname, NULL, 0);
-
-	    fprintf(stderr,_("Login incorrect\n\n"));
-	    pam_set_item(pamh,PAM_USER,NULL);
-	    retcode = pam_authenticate(pamh, 0);
+		if (is_pam_failure(retcode)) {
+			loginpam_get_username(pamh, &username);
+
+			if (retcode == PAM_MAXTRIES)
+				syslog(LOG_NOTICE,
+				       _
+				       ("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
+					"%s, %s"), failcount, hostname,
+				       username, pam_strerror(pamh, retcode));
+			else
+				syslog(LOG_NOTICE,
+				       _
+				       ("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
+				       hostname, username, pam_strerror(pamh,
+									retcode));
+			logbtmp(tty_name, username, hostname);
+			logaudit(tty_name, username, hostname, NULL, 0);
+
+			fprintf(stderr, _("\nLogin incorrect\n"));
+			pam_end(pamh, retcode);
+			exit(EXIT_SUCCESS);
+		}
 	}
 
-	if (is_pam_failure(retcode)) {
-	    loginpam_get_username(pamh, &username);
-
-	    if (retcode == PAM_MAXTRIES)
-		syslog(LOG_NOTICE,_("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
-			"%s, %s"), failcount, hostname, username,
-			 pam_strerror(pamh, retcode));
-	    else
-		syslog(LOG_NOTICE,_("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
-			hostname, username, pam_strerror(pamh, retcode));
-	    logbtmp(tty_name, username, hostname);
-	    logaudit(tty_name, username, hostname, NULL, 0);
-
-	    fprintf(stderr,_("\nLogin incorrect\n"));
-	    pam_end(pamh, retcode);
-	    exit(EXIT_SUCCESS);
+	/*
+	 * Authentication may be skipped (for example, during krlogin, rlogin, etc...),
+	 * but it doesn't mean that we can skip other account checks. The account
+	 * could be disabled or password expired (althought kerberos ticket is valid).
+	 * -- kzak@redhat.com (22-Feb-2006)
+	 */
+	retcode = pam_acct_mgmt(pamh, 0);
+
+	if (retcode == PAM_NEW_AUTHTOK_REQD)
+		retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
+
+	/*
+	 * Grab the user information out of the password file for future usage
+	 * First get the username that we are actually using, though.
+	 */
+	retcode = loginpam_get_username(pamh, &username);
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
+
+	if (!username || !*username) {
+		warnx(_("\nSession setup problem, abort."));
+		syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
+		       __FUNCTION__, __LINE__);
+		pam_end(pamh, PAM_SYSTEM_ERR);
+		exit(EXIT_FAILURE);
 	}
-    }
-
-    /*
-     * Authentication may be skipped (for example, during krlogin, rlogin, etc...),
-     * but it doesn't mean that we can skip other account checks. The account
-     * could be disabled or password expired (althought kerberos ticket is valid).
-     * -- kzak@redhat.com (22-Feb-2006)
-     */
-    retcode = pam_acct_mgmt(pamh, 0);
-
-    if (retcode == PAM_NEW_AUTHTOK_REQD)
-        retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    /*
-     * Grab the user information out of the password file for future usage
-     * First get the username that we are actually using, though.
-     */
-    retcode = loginpam_get_username(pamh, &username);
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    if (!username || !*username) {
-	    warnx(_("\nSession setup problem, abort."));
-	    syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
-		   __FUNCTION__, __LINE__);
-	    pam_end(pamh, PAM_SYSTEM_ERR);
-	    exit(EXIT_FAILURE);
-    }
-    if (!(pwd = getpwnam(username))) {
-	    warnx(_("\nSession setup problem, abort."));
-	    syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
-		   username, __FUNCTION__, __LINE__);
-	    pam_end(pamh, PAM_SYSTEM_ERR);
-	    exit(EXIT_FAILURE);
-    }
-
-    /*
-     * Create a copy of the pwd struct - otherwise it may get
-     * clobbered by PAM
-     */
-    memcpy(&pwdcopy, pwd, sizeof(*pwd));
-    pwd = &pwdcopy;
-    pwd->pw_name   = strdup(pwd->pw_name);
-    pwd->pw_passwd = strdup(pwd->pw_passwd);
-    pwd->pw_gecos  = strdup(pwd->pw_gecos);
-    pwd->pw_dir    = strdup(pwd->pw_dir);
-    pwd->pw_shell  = strdup(pwd->pw_shell);
-    if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
-	!pwd->pw_dir || !pwd->pw_shell) {
-	    warnx(_("out of memory"));
-	    syslog(LOG_ERR, "Out of memory");
-	    pam_end(pamh, PAM_SYSTEM_ERR);
-	    exit(EXIT_FAILURE);
-    }
-    username = pwd->pw_name;
-
-    /*
-     * Initialize the supplementary group list.
-     * This should be done before pam_setcred because
-     * the PAM modules might add groups during pam_setcred.
-     */
-    if (initgroups(username, pwd->pw_gid) < 0) {
-	    syslog(LOG_ERR, "initgroups: %m");
-	    warnx(_("\nSession setup problem, abort."));
-	    pam_end(pamh, PAM_SYSTEM_ERR);
-	    exit(EXIT_FAILURE);
-    }
-
-    retcode = pam_open_session(pamh, 0);
-    if (is_pam_failure(retcode))
-	loginpam_err(pamh, retcode);
-
-    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
-    if (is_pam_failure(retcode)) {
-	    pam_close_session(pamh, 0);
-	    loginpam_err(pamh, retcode);
-    }
-
-    /* committed to login -- turn off timeout */
-    alarm((unsigned int)0);
-
-    endpwent();
-
-    /* This requires some explanation: As root we may not be able to
-       read the directory of the user if it is on an NFS mounted
-       filesystem. We temporarily set our effective uid to the user-uid
-       making sure that we keep root privs. in the real uid.
-
-       A portable solution would require a fork(), but we rely on Linux
-       having the BSD setreuid() */
-    {
-	char tmpstr[PATH_MAX];
-	uid_t ruid = getuid();
-	gid_t egid = getegid();
-
-	/* avoid snprintf - old systems do not have it, or worse,
-	   have a libc in which snprintf is the same as sprintf */
-	if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 > PATH_MAX)
-		quietlog = 0;
-	else {
-		sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
-		setregid(-1, pwd->pw_gid);
-		setreuid(0, pwd->pw_uid);
-		quietlog = (effective_access(tmpstr, O_RDONLY) == 0);
-		setuid(0); /* setreuid doesn't do it alone! */
-		setreuid(ruid, 0);
-		setregid(-1, egid);
+	if (!(pwd = getpwnam(username))) {
+		warnx(_("\nSession setup problem, abort."));
+		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
+		       username, __FUNCTION__, __LINE__);
+		pam_end(pamh, PAM_SYSTEM_ERR);
+		exit(EXIT_FAILURE);
 	}
-    }
 
-    /* for linux, write entries in utmp and wtmp */
-    {
-	struct utmp ut;
-	struct utmp *utp;
-	struct timeval tv;
+	/*
+	 * Create a copy of the pwd struct - otherwise it may get
+	 * clobbered by PAM
+	 */
+	memcpy(&pwdcopy, pwd, sizeof(*pwd));
+	pwd = &pwdcopy;
+	pwd->pw_name = strdup(pwd->pw_name);
+	pwd->pw_passwd = strdup(pwd->pw_passwd);
+	pwd->pw_gecos = strdup(pwd->pw_gecos);
+	pwd->pw_dir = strdup(pwd->pw_dir);
+	pwd->pw_shell = strdup(pwd->pw_shell);
+	if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
+	    !pwd->pw_dir || !pwd->pw_shell) {
+		warnx(_("out of memory"));
+		syslog(LOG_ERR, "Out of memory");
+		pam_end(pamh, PAM_SYSTEM_ERR);
+		exit(EXIT_FAILURE);
+	}
+	username = pwd->pw_name;
 
-	utmpname(_PATH_UTMP);
-	setutent();
-
-	/* Find pid in utmp.
-login sometimes overwrites the runlevel entry in /var/run/utmp,
-confusing sysvinit. I added a test for the entry type, and the problem
-was gone. (In a runlevel entry, st_pid is not really a pid but some number
-calculated from the previous and current runlevel).
-Michael Riepe <michael@stud.uni-hannover.de>
-	*/
-	while ((utp = getutent()))
-		if (utp->ut_pid == pid
-		    && utp->ut_type >= INIT_PROCESS
-		    && utp->ut_type <= DEAD_PROCESS)
-			break;
+	/*
+	 * Initialize the supplementary group list.
+	 * This should be done before pam_setcred because
+	 * the PAM modules might add groups during pam_setcred.
+	 */
+	if (initgroups(username, pwd->pw_gid) < 0) {
+		syslog(LOG_ERR, "initgroups: %m");
+		warnx(_("\nSession setup problem, abort."));
+		pam_end(pamh, PAM_SYSTEM_ERR);
+		exit(EXIT_FAILURE);
+	}
+
+	retcode = pam_open_session(pamh, 0);
+	if (is_pam_failure(retcode))
+		loginpam_err(pamh, retcode);
 
-	/* If we can't find a pre-existing entry by pid, try by line.
-	   BSD network daemons may rely on this. (anonymous) */
-	if (utp == NULL) {
-	     setutent();
-	     ut.ut_type = LOGIN_PROCESS;
-	     strncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
-	     utp = getutline(&ut);
+	retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+	if (is_pam_failure(retcode)) {
+		pam_close_session(pamh, 0);
+		loginpam_err(pamh, retcode);
 	}
 
-	if (utp) {
-	    memcpy(&ut, utp, sizeof(ut));
-	} else {
-	    /* some gettys/telnetds don't initialize utmp... */
-	    memset(&ut, 0, sizeof(ut));
+	/* committed to login -- turn off timeout */
+	alarm((unsigned int)0);
+
+	endpwent();
+
+	{
+		/*
+		 * Check per accout setting.
+		 *
+		 * This requires some explanation: As root we may not be able to
+		 * read the directory of the user if it is on an NFS mounted
+		 * filesystem. We temporarily set our effective uid to the user-uid
+		 * making sure that we keep root privs. in the real uid.
+		 *
+		 * A portable solution would require a fork(), but we rely on Linux
+		 * having the BSD setreuid()
+		 */
+		char tmpstr[PATH_MAX];
+		uid_t ruid = getuid();
+		gid_t egid = getegid();
+
+		/* avoid snprintf - old systems do not have it, or worse,
+		   have a libc in which snprintf is the same as sprintf */
+		if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 >
+		    PATH_MAX)
+			quietlog = 0;
+		else {
+			sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
+			setregid(-1, pwd->pw_gid);
+			setreuid(0, pwd->pw_uid);
+			quietlog = (effective_access(tmpstr, O_RDONLY) == 0);
+			setuid(0);	/* setreuid doesn't do it alone! */
+			setreuid(ruid, 0);
+			setregid(-1, egid);
+		}
 	}
 
-	if (ut.ut_id[0] == 0)
-	  strncpy(ut.ut_id, tty_number, sizeof(ut.ut_id));
+	/* for linux, write entries in utmp and wtmp */
+	{
+		struct utmp ut;
+		struct utmp *utp;
+		struct timeval tv;
+
+		utmpname(_PATH_UTMP);
+		setutent();
+
+		/* Find pid in utmp.
+		   login sometimes overwrites the runlevel entry in /var/run/utmp,
+		   confusing sysvinit. I added a test for the entry type, and the problem
+		   was gone. (In a runlevel entry, st_pid is not really a pid but some number
+		   calculated from the previous and current runlevel).
+		   Michael Riepe <michael@stud.uni-hannover.de>
+		 */
+		while ((utp = getutent()))
+			if (utp->ut_pid == pid
+			    && utp->ut_type >= INIT_PROCESS
+			    && utp->ut_type <= DEAD_PROCESS)
+				break;
+
+		/* If we can't find a pre-existing entry by pid, try by line.
+		   BSD network daemons may rely on this. (anonymous) */
+		if (utp == NULL) {
+			setutent();
+			ut.ut_type = LOGIN_PROCESS;
+			strncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+			utp = getutline(&ut);
+		}
 
-	strncpy(ut.ut_user, username, sizeof(ut.ut_user));
-	xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+		if (utp) {
+			memcpy(&ut, utp, sizeof(ut));
+		} else {
+			/* some gettys/telnetds don't initialize utmp... */
+			memset(&ut, 0, sizeof(ut));
+		}
+
+		if (ut.ut_id[0] == 0)
+			strncpy(ut.ut_id, tty_number, sizeof(ut.ut_id));
+
+		strncpy(ut.ut_user, username, sizeof(ut.ut_user));
+		xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
 #ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
-	gettimeofday(&tv, NULL);
-	ut.ut_tv.tv_sec = tv.tv_sec;
-	ut.ut_tv.tv_usec = tv.tv_usec;
+		gettimeofday(&tv, NULL);
+		ut.ut_tv.tv_sec = tv.tv_sec;
+		ut.ut_tv.tv_usec = tv.tv_usec;
 #else
-	{
-	    time_t t;
-	    time(&t);
-	    ut.ut_time = t;	/* ut_time is not always a time_t */
-				/* glibc2 #defines it as ut_tv.tv_sec */
-	}
+		{
+			time_t t;
+			time(&t);
+			ut.ut_time = t;	/* ut_time is not always a time_t */
+			/* glibc2 #defines it as ut_tv.tv_sec */
+		}
 #endif
-	ut.ut_type = USER_PROCESS;
-	ut.ut_pid = pid;
-	if (hostname) {
-		xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
-		if (hostaddress[0])
-			memcpy(&ut.ut_addr_v6, hostaddress, sizeof(ut.ut_addr_v6));
-	}
+		ut.ut_type = USER_PROCESS;
+		ut.ut_pid = pid;
+		if (hostname) {
+			xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
+			if (hostaddress[0])
+				memcpy(&ut.ut_addr_v6, hostaddress,
+				       sizeof(ut.ut_addr_v6));
+		}
 
-	pututline(&ut);
-	endutent();
+		pututline(&ut);
+		endutent();
 
 #if HAVE_UPDWTMP
-	updwtmp(_PATH_WTMP, &ut);
+		updwtmp(_PATH_WTMP, &ut);
 #else
-	/* Probably all this locking below is just nonsense,
-	   and the short version is OK as well. */
-	{
-	    int lf, wtmp;
-	    if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) {
-		flock(lf, LOCK_EX);
-		if ((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
-		    write(wtmp, (char *)&ut, sizeof(ut));
-		    close(wtmp);
+		/* Probably all this locking below is just nonsense,
+		   and the short version is OK as well. */
+		{
+			int lf, wtmp;
+			if ((lf =
+			     open(_PATH_WTMPLOCK, O_CREAT | O_WRONLY,
+				  0660)) >= 0) {
+				flock(lf, LOCK_EX);
+				if ((wtmp =
+				     open(_PATH_WTMP,
+					  O_APPEND | O_WRONLY)) >= 0) {
+					write(wtmp, (char *)&ut, sizeof(ut));
+					close(wtmp);
+				}
+				flock(lf, LOCK_UN);
+				close(lf);
+			}
 		}
-		flock(lf, LOCK_UN);
-		close(lf);
-	    }
-	}
 #endif
-    }
+	}
 
-    logaudit(tty_name, username, hostname, pwd, 1);
-    dolastlog(quietlog);
+	logaudit(tty_name, username, hostname, pwd, 1);
+	dolastlog(quietlog);
 
-    if (fchown(0, pwd->pw_uid,
-	  (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
-        warn(_("change terminal owner failed"));
+	if (fchown(0, pwd->pw_uid,
+		   (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
+		warn(_("change terminal owner failed"));
 
-    fchmod(0, TTY_MODE);
+	fchmod(0, TTY_MODE);
 
 #ifdef LOGIN_CHOWN_VCS
-    /* if tty is one of the VC's then change owner and mode of the
-       special /dev/vcs devices as well */
-    if (consoletty(0)) {
-
-	if (chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
-	    warn(_("change terminal owner failed"));
-	if (chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
-	    warn(_("change terminal owner failed"));
-
-	chmod(vcsn, TTY_MODE);
-	chmod(vcsan, TTY_MODE);
-    }
+	/* if tty is one of the VC's then change owner and mode of the
+	   special /dev/vcs devices as well */
+	if (consoletty(0)) {
+
+		if (chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
+			warn(_("change terminal owner failed"));
+		if (chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
+			warn(_("change terminal owner failed"));
+
+		chmod(vcsn, TTY_MODE);
+		chmod(vcsan, TTY_MODE);
+	}
 #endif
 
-    if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
-	syslog(LOG_ALERT, _("setgid() failed"));
-	exit(EXIT_FAILURE);
-    }
-
-
-    if (*pwd->pw_shell == '\0')
-      pwd->pw_shell = _PATH_BSHELL;
-
-    /* preserve TERM even without -p flag */
-    {
-	char *ep;
-
-	if(!((ep = getenv("TERM")) && (termenv = strdup(ep))))
-	  termenv = "dumb";
-    }
-
-    /* destroy environment unless user has requested preservation */
-    if (!pflag)
-      {
-          environ = (char**)malloc(sizeof(char*));
-	  memset(environ, 0, sizeof(char*));
-      }
-
-    setenv("HOME", pwd->pw_dir, 0);      /* legal to override */
-    if(pwd->pw_uid)
-      setenv("PATH", _PATH_DEFPATH, 1);
-    else
-      setenv("PATH", _PATH_DEFPATH_ROOT, 1);
-
-    setenv("SHELL", pwd->pw_shell, 1);
-    setenv("TERM", termenv, 1);
-
-    /* mailx will give a funny error msg if you forget this one */
-    {
-      char tmp[PATH_MAX];
-      /* avoid snprintf */
-      if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < PATH_MAX) {
-	      sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
-	      setenv("MAIL",tmp,0);
-      }
-    }
-
-    /* LOGNAME is not documented in login(1) but
-       HP-UX 6.5 does it. We'll not allow modifying it.
-       */
-    setenv("LOGNAME", pwd->pw_name, 1);
-
-    {
-	int i;
-	char ** env = pam_getenvlist(pamh);
-
-	if (env != NULL) {
-	    for (i=0; env[i]; i++) {
-		putenv(env[i]);
-		/* D(("env[%d] = %s", i,env[i])); */
-	    }
+	if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
+		syslog(LOG_ALERT, _("setgid() failed"));
+		exit(EXIT_FAILURE);
 	}
-    }
 
-    setproctitle("login", username);
+	if (*pwd->pw_shell == '\0')
+		pwd->pw_shell = _PATH_BSHELL;
 
-    if (!strncmp(tty_name, "ttyS", 4))
-      syslog(LOG_INFO, _("DIALUP AT %s BY %s"), tty_name, pwd->pw_name);
+	/* preserve TERM even without -p flag */
+	{
+		char *ep;
 
-    /* allow tracking of good logins.
-       -steve philp (sphilp@mail.alliance.net) */
+		if (!((ep = getenv("TERM")) && (termenv = strdup(ep))))
+			termenv = "dumb";
+	}
 
-    if (pwd->pw_uid == 0) {
-	if (hostname)
-	  syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
-		 tty_name, hostname);
-	else
-	  syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), tty_name);
-    } else {
-	if (hostname)
-	  syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"), tty_name,
-		 pwd->pw_name, hostname);
+	/* destroy environment unless user has requested preservation */
+	if (!pflag) {
+		environ = (char **)malloc(sizeof(char *));
+		memset(environ, 0, sizeof(char *));
+	}
+
+	setenv("HOME", pwd->pw_dir, 0);	/* legal to override */
+	if (pwd->pw_uid)
+		setenv("PATH", _PATH_DEFPATH, 1);
 	else
-	  syslog(LOG_INFO, _("LOGIN ON %s BY %s"), tty_name,
-		 pwd->pw_name);
-    }
+		setenv("PATH", _PATH_DEFPATH_ROOT, 1);
 
-    if (!quietlog) {
-	motd();
+	setenv("SHELL", pwd->pw_shell, 1);
+	setenv("TERM", termenv, 1);
 
-#ifdef LOGIN_STAT_MAIL
-	/*
-	 * This turns out to be a bad idea: when the mail spool
-	 * is NFS mounted, and the NFS connection hangs, the
-	 * login hangs, even root cannot login.
-	 * Checking for mail should be done from the shell.
+	/* mailx will give a funny error msg if you forget this one */
+	{
+		char tmp[PATH_MAX];
+		/* avoid snprintf */
+		if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < PATH_MAX) {
+			sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+			setenv("MAIL", tmp, 0);
+		}
+	}
+
+	/* LOGNAME is not documented in login(1) but
+	   HP-UX 6.5 does it. We'll not allow modifying it.
 	 */
+	setenv("LOGNAME", pwd->pw_name, 1);
+
 	{
-	    struct stat st;
-	    char *mail;
+		int i;
+		char **env = pam_getenvlist(pamh);
+
+		if (env != NULL) {
+			for (i = 0; env[i]; i++) {
+				putenv(env[i]);
+				/* D(("env[%d] = %s", i,env[i])); */
+			}
+		}
+	}
+
+	setproctitle("login", username);
+
+	if (!strncmp(tty_name, "ttyS", 4))
+		syslog(LOG_INFO, _("DIALUP AT %s BY %s"), tty_name,
+		       pwd->pw_name);
+
+	/* allow tracking of good logins.
+	   -steve philp (sphilp@mail.alliance.net) */
 
-	    mail = getenv("MAIL");
-	    if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
-		if (st.st_mtime > st.st_atime)
-			printf(_("You have new mail.\n"));
+	if (pwd->pw_uid == 0) {
+		if (hostname)
+			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
+			       tty_name, hostname);
 		else
-			printf(_("You have mail.\n"));
-	    }
+			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), tty_name);
+	} else {
+		if (hostname)
+			syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"),
+			       tty_name, pwd->pw_name, hostname);
+		else
+			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), tty_name,
+			       pwd->pw_name);
 	}
+
+	if (!quietlog) {
+		motd();
+
+#ifdef LOGIN_STAT_MAIL
+		/*
+		 * This turns out to be a bad idea: when the mail spool
+		 * is NFS mounted, and the NFS connection hangs, the
+		 * login hangs, even root cannot login.
+		 * Checking for mail should be done from the shell.
+		 */
+		{
+			struct stat st;
+			char *mail;
+
+			mail = getenv("MAIL");
+			if (mail && stat(mail, &st) == 0 && st.st_size != 0) {
+				if (st.st_mtime > st.st_atime)
+					printf(_("You have new mail.\n"));
+				else
+					printf(_("You have mail.\n"));
+			}
+		}
 #endif
-    }
-
-    signal(SIGALRM, SIG_DFL);
-    signal(SIGQUIT, SIG_DFL);
-    signal(SIGTSTP, SIG_IGN);
-
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_handler = SIG_IGN;
-    sigaction(SIGINT, &sa, NULL);
-
-    sigaction(SIGHUP, &sa, &oldsa_hup); /* ignore when TIOCNOTTY */
-
-    /*
-     * detach the controlling tty
-     * -- we needn't the tty in parent who waits for child only.
-     *    The child calls setsid() that detach from the tty as well.
-     */
-    ioctl(0, TIOCNOTTY, NULL);
-
-    /*
-     * We have care about SIGTERM, because leave PAM session without
-     * pam_close_session() is pretty bad thing.
-     */
-    sa.sa_handler = sig_handler;
-    sigaction(SIGHUP, &sa, NULL);
-    sigaction(SIGTERM, &sa, &oldsa_term);
-
-    closelog();
-
-    /*
-     * We must fork before setuid() because we need to call
-     * pam_close_session() as root.
-     */
-
-    child_pid = fork();
-    if (child_pid < 0) {
-       /* error in fork() */
-       warn(_("failure forking"));
-       pam_setcred(pamh, PAM_DELETE_CRED);
-       pam_end(pamh, pam_close_session(pamh, 0));
-       exit(EXIT_FAILURE);
-    }
-
-    if (child_pid) {
-       /* parent - wait for child to finish, then cleanup session */
-       close(0);
-       close(1);
-       close(2);
-       sa.sa_handler = SIG_IGN;
-       sigaction(SIGQUIT, &sa, NULL);
-       sigaction(SIGINT, &sa, NULL);
-
-       /* wait as long as any child is there */
-       while(wait(NULL) == -1 && errno == EINTR)
-	       ;
-       openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
-       pam_setcred(pamh, PAM_DELETE_CRED);
-       pam_end(pamh, pam_close_session(pamh, 0));
-       exit(EXIT_SUCCESS);
-    }
-
-    /* child */
-
-    /* restore to old state */
-    sigaction(SIGHUP, &oldsa_hup, NULL);
-    sigaction(SIGTERM, &oldsa_term, NULL);
-    if(got_sig)
-	    exit(EXIT_FAILURE);
-
-    /*
-     * Problem: if the user's shell is a shell like ash that doesnt do
-     * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
-     * process in the pgrp, will kill us.
-     */
-
-    /* start new session */
-    setsid();
-
-    /* make sure we have a controlling tty */
-    opentty(ttyn);
-    openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
-
-    /*
-     * TIOCSCTTY: steal tty from other process group.
-     */
-    if (ioctl(0, TIOCSCTTY, 1))
-	    syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
-    signal(SIGINT, SIG_DFL);
-
-    /* discard permissions last so can't get killed and drop core */
-    if(setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
-	syslog(LOG_ALERT, _("setuid() failed"));
-	exit(EXIT_FAILURE);
-    }
-
-    /* wait until here to change directory! */
-    if (chdir(pwd->pw_dir) < 0) {
-	warn(_("%s: change directory failed"), pwd->pw_dir);
-	if (chdir("/"))
-	  exit(EXIT_FAILURE);
-	pwd->pw_dir = "/";
-	printf(_("Logging in with home = \"/\".\n"));
-    }
-
-    /* if the shell field has a space: treat it like a shell script */
-    if (strchr(pwd->pw_shell, ' ')) {
-	buff = xmalloc(strlen(pwd->pw_shell) + 6);
-
-	strcpy(buff, "exec ");
-	strcat(buff, pwd->pw_shell);
-	childArgv[childArgc++] = "/bin/sh";
-	childArgv[childArgc++] = "-sh";
-	childArgv[childArgc++] = "-c";
-	childArgv[childArgc++] = buff;
-    } else {
-	tbuf[0] = '-';
-	xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
-			   p + 1 : pwd->pw_shell),
-		sizeof(tbuf)-1);
-
-	childArgv[childArgc++] = pwd->pw_shell;
-	childArgv[childArgc++] = tbuf;
-    }
-
-    childArgv[childArgc++] = NULL;
-
-    execvp(childArgv[0], childArgv + 1);
-
-    if (!strcmp(childArgv[0], "/bin/sh"))
-	warn(_("couldn't exec shell script"));
-    else
-	warn(_("no shell"));
-
-    exit(EXIT_SUCCESS);
+	}
+
+	signal(SIGALRM, SIG_DFL);
+	signal(SIGQUIT, SIG_DFL);
+	signal(SIGTSTP, SIG_IGN);
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGINT, &sa, NULL);
+
+	sigaction(SIGHUP, &sa, &oldsa_hup);	/* ignore when TIOCNOTTY */
+
+	/*
+	 * detach the controlling tty
+	 * -- we needn't the tty in parent who waits for child only.
+	 *    The child calls setsid() that detach from the tty as well.
+	 */
+	ioctl(0, TIOCNOTTY, NULL);
+
+	/*
+	 * We have care about SIGTERM, because leave PAM session without
+	 * pam_close_session() is pretty bad thing.
+	 */
+	sa.sa_handler = sig_handler;
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGTERM, &sa, &oldsa_term);
+
+	closelog();
+
+	/*
+	 * We must fork before setuid() because we need to call
+	 * pam_close_session() as root.
+	 */
+
+	child_pid = fork();
+	if (child_pid < 0) {
+		/* error in fork() */
+		warn(_("failure forking"));
+		pam_setcred(pamh, PAM_DELETE_CRED);
+		pam_end(pamh, pam_close_session(pamh, 0));
+		exit(EXIT_FAILURE);
+	}
+
+	if (child_pid) {
+		/* parent - wait for child to finish, then cleanup session */
+		close(0);
+		close(1);
+		close(2);
+		sa.sa_handler = SIG_IGN;
+		sigaction(SIGQUIT, &sa, NULL);
+		sigaction(SIGINT, &sa, NULL);
+
+		/* wait as long as any child is there */
+		while (wait(NULL) == -1 && errno == EINTR) ;
+		openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
+		pam_setcred(pamh, PAM_DELETE_CRED);
+		pam_end(pamh, pam_close_session(pamh, 0));
+		exit(EXIT_SUCCESS);
+	}
+
+	/* child */
+
+	/* restore to old state */
+	sigaction(SIGHUP, &oldsa_hup, NULL);
+	sigaction(SIGTERM, &oldsa_term, NULL);
+	if (got_sig)
+		exit(EXIT_FAILURE);
+
+	/*
+	 * Problem: if the user's shell is a shell like ash that doesnt do
+	 * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
+	 * process in the pgrp, will kill us.
+	 */
+
+	/* start new session */
+	setsid();
+
+	/* make sure we have a controlling tty */
+	opentty(ttyn);
+	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
+
+	/*
+	 * TIOCSCTTY: steal tty from other process group.
+	 */
+	if (ioctl(0, TIOCSCTTY, 1))
+		syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
+	signal(SIGINT, SIG_DFL);
+
+	/* discard permissions last so can't get killed and drop core */
+	if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
+		syslog(LOG_ALERT, _("setuid() failed"));
+		exit(EXIT_FAILURE);
+	}
+
+	/* wait until here to change directory! */
+	if (chdir(pwd->pw_dir) < 0) {
+		warn(_("%s: change directory failed"), pwd->pw_dir);
+		if (chdir("/"))
+			exit(EXIT_FAILURE);
+		pwd->pw_dir = "/";
+		printf(_("Logging in with home = \"/\".\n"));
+	}
+
+	/* if the shell field has a space: treat it like a shell script */
+	if (strchr(pwd->pw_shell, ' ')) {
+		buff = xmalloc(strlen(pwd->pw_shell) + 6);
+
+		strcpy(buff, "exec ");
+		strcat(buff, pwd->pw_shell);
+		childArgv[childArgc++] = "/bin/sh";
+		childArgv[childArgc++] = "-sh";
+		childArgv[childArgc++] = "-c";
+		childArgv[childArgc++] = buff;
+	} else {
+		tbuf[0] = '-';
+		xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
+				    p + 1 : pwd->pw_shell), sizeof(tbuf) - 1);
+
+		childArgv[childArgc++] = pwd->pw_shell;
+		childArgv[childArgc++] = tbuf;
+	}
+
+	childArgv[childArgc++] = NULL;
+
+	execvp(childArgv[0], childArgv + 1);
+
+	if (!strcmp(childArgv[0], "/bin/sh"))
+		warn(_("couldn't exec shell script"));
+	else
+		warn(_("no shell"));
+
+	exit(EXIT_SUCCESS);
 }
 
 /*
@@ -1046,19 +1065,19 @@ Michael Riepe <michael@stud.uni-hannover.de>
  * the process just exits if the second timeout expires.
  */
 
-static void
-timedout2(int sig __attribute__((__unused__))) {
+static void timedout2(int sig __attribute__ ((__unused__)))
+{
 	struct termios ti;
 
 	/* reset echo */
 	tcgetattr(0, &ti);
 	ti.c_lflag |= ECHO;
 	tcsetattr(0, TCSANOW, &ti);
-	exit(EXIT_SUCCESS);			/* %% */
+	exit(EXIT_SUCCESS);	/* %% */
 }
 
-static void
-timedout(int sig __attribute__((__unused__))) {
+static void timedout(int sig __attribute__ ((__unused__)))
+{
 	signal(SIGALRM, timedout2);
 	alarm(10);
 	/* TRANSLATORS: The standard value for %d is 60. */
@@ -1070,75 +1089,77 @@ timedout(int sig __attribute__((__unused__))) {
 
 jmp_buf motdinterrupt;
 
-void
-motd(void) {
-    int fd, nchars;
-    void (*oldint)(int);
-    char tbuf[8192];
-
-    if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
-      return;
-    oldint = signal(SIGINT, sigint);
-    if (setjmp(motdinterrupt) == 0)
-      while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
-	if (write(fileno(stdout), tbuf, nchars)) {
-		;	/* glibc warn_unused_result */
-	}
-      }
-    signal(SIGINT, oldint);
-    close(fd);
+void motd(void)
+{
+	int fd, nchars;
+	void (*oldint) (int);
+	char tbuf[8192];
+
+	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+		return;
+	oldint = signal(SIGINT, sigint);
+	if (setjmp(motdinterrupt) == 0)
+		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
+			if (write(fileno(stdout), tbuf, nchars)) {
+				;	/* glibc warn_unused_result */
+			}
+		}
+	signal(SIGINT, oldint);
+	close(fd);
 }
 
-void
-sigint(int sig  __attribute__((__unused__))) {
-    longjmp(motdinterrupt, 1);
+void sigint(int sig __attribute__ ((__unused__)))
+{
+	longjmp(motdinterrupt, 1);
 }
 
-void
-dolastlog(int quiet) {
-    struct lastlog ll;
-    int fd;
-
-    if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
-	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) {
-		    time_t ll_time = (time_t) ll.ll_time;
-
-		    printf(_("Last login: %.*s "),
-			   24-5, ctime(&ll_time));
-
-		    if (*ll.ll_host != '\0')
-			    printf(_("from %.*s\n"),
-				   (int)sizeof(ll.ll_host), ll.ll_host);
-		    else
-			    printf(_("on %.*s\n"),
-				   (int)sizeof(ll.ll_line), ll.ll_line);
-	    }
-	    lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
-	}
-	memset((char *)&ll, 0, sizeof(ll));
+void dolastlog(int quiet)
+{
+	struct lastlog ll;
+	int fd;
+
+	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
+		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) {
+				time_t ll_time = (time_t) ll.ll_time;
+
+				printf(_("Last login: %.*s "),
+				       24 - 5, ctime(&ll_time));
+
+				if (*ll.ll_host != '\0')
+					printf(_("from %.*s\n"),
+					       (int)sizeof(ll.ll_host),
+					       ll.ll_host);
+				else
+					printf(_("on %.*s\n"),
+					       (int)sizeof(ll.ll_line),
+					       ll.ll_line);
+			}
+			lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+		}
+		memset((char *)&ll, 0, sizeof(ll));
 
-	{
-		time_t t;
-		time(&t);
-		ll.ll_time = t; /* ll_time is always 32bit */
-	}
+		{
+			time_t t;
+			time(&t);
+			ll.ll_time = t;	/* ll_time is always 32bit */
+		}
 
-	xstrncpy(ll.ll_line, tty_name, sizeof(ll.ll_line));
-	if (hostname)
-	    xstrncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+		xstrncpy(ll.ll_line, tty_name, sizeof(ll.ll_line));
+		if (hostname)
+			xstrncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
 
-	if (write(fd, (char *)&ll, sizeof(ll)) < 0)
-	    warn(_("write lastlog failed"));
-	close(fd);
-    }
+		if (write(fd, (char *)&ll, sizeof(ll)) < 0)
+			warn(_("write lastlog failed"));
+		close(fd);
+	}
 }
 
 /* Should not be called from PAM code... */
-void
-sleepexit(int eval) {
-    sleep(LOGIN_EXIT_TIMEOUT);
-    exit(eval);
+void sleepexit(int eval)
+{
+	sleep(LOGIN_EXIT_TIMEOUT);
+	exit(eval);
 }
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 11/49] login: add struct login_context, consolidate tty code
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (9 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 10/49] login: indent -linux Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 12/49] login: add hostname to login_context struct Karel Zak
                     ` (37 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

 - move all tty_* variables to struct login_context

 - move all tty initialization code to init_tty()

 - LOG_ERR on failed tty ch{mod,own}
   [based on SUSE pam_login - note that we don't write any this error to stderr]

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  228 +++++++++++++++++++++++++++------------------------
 1 files changed, 122 insertions(+), 106 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 9528908..e1bf81c 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -81,6 +81,21 @@
 #endif
 
 #define	TTYGRPNAME	"tty"	/* name of group to own ttys */
+#define VCS_PATH_MAX	64
+
+/*
+ * Login control struct
+ */
+struct login_context {
+	const char	*tty_path;	/* ttyname() return value */
+	const char	*tty_name;	/* tty_path without /dev prefix */
+	const char	*tty_number;	/* end of the tty_path */
+
+#ifdef LOGIN_CHOWN_VCS
+	char		vcsn[VCS_PATH_MAX];	/* virtual console name */
+	char		vcsan[VCS_PATH_MAX];
+#endif
+};
 
 /*
  * This bounds the time given to login.  Not a define so it can
@@ -93,23 +108,26 @@ struct passwd *pwd;
 static struct passwd pwdcopy;
 char hostaddress[16];		/* used in checktty.c */
 char *hostname;			/* idem */
-static char *username, *tty_name, *tty_number;
+static char *username;
 static pid_t pid;
 
 static void timedout(int);
 static void sigint(int);
 static void motd(void);
-static void dolastlog(int quiet);
-
-/* Nice and simple code provided by Linus Torvalds 16-Feb-93 */
-/* Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
-   He writes: "Login performs open() on a tty in a blocking mode.
-   In some cases it may make login wait in open() for carrier infinitely,
-   for example if the line is a simplistic case of a three-wire serial
-   connection. I believe login should open the line in the non-blocking mode
-   leaving the decision to make a connection to getty (where it actually
-   belongs). */
-static void opentty(const char *tty)
+static void dolastlog(struct login_context *cxt, int quiet);
+
+/*
+ * Nice and simple code provided by Linus Torvalds 16-Feb-93
+ * Nonblocking stuff by Maciej W. Rozycki, macro@ds2.pg.gda.pl, 1999.
+ *
+ * He writes: "Login performs open() on a tty in a blocking mode.
+ * In some cases it may make login wait in open() for carrier infinitely,
+ * for example if the line is a simplistic case of a three-wire serial
+ * connection. I believe login should open the line in the non-blocking mode
+ * leaving the decision to make a connection to getty (where it actually
+ * belongs).
+ */
+static void open_tty(const char *tty)
 {
 	int i, fd, flags;
 
@@ -138,30 +156,81 @@ static void opentty(const char *tty)
 		close(fd);
 }
 
-/* In case login is suid it was possible to use a hardlink as stdin
-   and exploit races for a local root exploit. (Wojciech Purczynski). */
-/* More precisely, the problem is  ttyn := ttyname(0); ...; chown(ttyn);
-   here ttyname() might return "/tmp/x", a hardlink to a pseudotty. */
-/* All of this is a problem only when login is suid, which it isnt. */
-static void check_ttyname(char *ttyn)
+/*
+ * Reads the currect terminal path and initialize cxt->tty_* variables.
+ */
+static void init_tty(struct login_context *cxt)
 {
-	struct stat statbuf;
+	const char *p;
+	struct stat st;
+	struct termios tt, ttt;
+
+	cxt->tty_path = ttyname(0);		/* libc calls istty() here */
 
-	if (ttyn == NULL
-	    || *ttyn == '\0'
-	    || lstat(ttyn, &statbuf)
-	    || !S_ISCHR(statbuf.st_mode)
-	    || (statbuf.st_nlink > 1 && strncmp(ttyn, "/dev/", 5))
-	    || (access(ttyn, R_OK | W_OK) != 0)) {
+	/*
+	 * In case login is suid it was possible to use a hardlink as stdin
+	 * and exploit races for a local root exploit. (Wojciech Purczynski).
+	 *
+	 * More precisely, the problem is  ttyn := ttyname(0); ...; chown(ttyn);
+	 * here ttyname() might return "/tmp/x", a hardlink to a pseudotty.
+	 * All of this is a problem only when login is suid, which it isnt.
+	 */
+	if (!cxt->tty_path || !*cxt->tty_path ||
+	    lstat(cxt->tty_path, &st) != 0 || !S_ISCHR(st.st_mode) ||
+	    (st.st_nlink > 1 && strncmp(cxt->tty_path, "/dev/", 5)) ||
+	    access(cxt->tty_path, R_OK | W_OK) != 0) {
 
 		syslog(LOG_ERR, _("FATAL: bad tty"));
 		sleepexit(EXIT_FAILURE);
 	}
+
+	if (strncmp(cxt->tty_path, "/dev/", 5) == 0)
+		cxt->tty_name = cxt->tty_path + 5;
+	else
+		cxt->tty_name = cxt->tty_path;
+
+	for (p = cxt->tty_name; p && *p; p++) {
+		if (isdigit(*p)) {
+			cxt->tty_number = p;
+			break;
+		}
+	}
+
+#ifdef LOGIN_CHOWN_VCS
+	/* find names of Virtual Console devices, for later mode change */
+	snprintf(cxt->vcsn, sizeof(cxt->vcsn), "/dev/vcs%s", cxt->tty_number);
+	snprintf(cxt->vcsan, sizeof(cxt->vcsan), "/dev/vcsa%s", cxt->tty_number);
+#endif
+
+	tcgetattr(0, &tt);
+	ttt = tt;
+	ttt.c_cflag &= ~HUPCL;
+
+	if ((fchown(0, 0, 0) || fchmod(0, TTY_MODE)) && errno != EROFS) {
+
+		syslog(LOG_ERR, _("FATAL: %s: change permissions failed: %m"),
+				cxt->tty_path);
+		sleepexit(EXIT_FAILURE);
+	}
+
+	/* Kill processes left on this tty */
+	tcsetattr(0, TCSAFLUSH, &ttt);
+
+	signal(SIGHUP, SIG_IGN);	/* so vhangup() wont kill us */
+	vhangup();
+	signal(SIGHUP, SIG_DFL);
+
+	/* open stdin,stdout,stderr to the tty */
+	open_tty(cxt->tty_path);
+
+	/* restore tty modes */
+	tcsetattr(0, TCSAFLUSH, &tt);
 }
 
+
 #ifdef LOGIN_CHOWN_VCS
 /* true if the filedescriptor fd is a console tty, very Linux specific */
-static int consoletty(int fd)
+static int is_consoletty(int fd)
 {
 	struct stat stb;
 
@@ -309,7 +378,7 @@ int main(int argc, char **argv)
 	register char *p;
 	int fflag, hflag, pflag, cnt;
 	int quietlog, passwd_req;
-	char *domain, *ttyn;
+	char *domain;
 	char tbuf[PATH_MAX + 2];
 	char *termenv;
 	char *childArgv[10];
@@ -319,10 +388,9 @@ int main(int argc, char **argv)
 	pam_handle_t *pamh = NULL;
 	struct pam_conv conv = { misc_conv, NULL };
 	struct sigaction sa, oldsa_hup, oldsa_term;
-#ifdef LOGIN_CHOWN_VCS
-	char vcsn[20], vcsan[20];
-#endif
+	struct login_context cxt;
 
+	memset(&cxt, 0, sizeof(cxt));
 	pid = getpid();
 
 	signal(SIGALRM, timedout);
@@ -347,7 +415,7 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	username = tty_name = hostname = NULL;
+	username = hostname = NULL;
 	fflag = hflag = pflag = 0;
 	passwd_req = 1;
 
@@ -424,64 +492,12 @@ int main(int argc, char **argv)
 	for (cnt = getdtablesize(); cnt > 2; cnt--)
 		close(cnt);
 
-	/* note that libc checks that the file descriptor is a terminal, so we don't
-	 * have to call isatty() here */
-	ttyn = ttyname(0);
-	check_ttyname(ttyn);
-
-	if (strncmp(ttyn, "/dev/", 5) == 0)
-		tty_name = ttyn + 5;
-	else
-		tty_name = ttyn;
-
-	if (strncmp(ttyn, "/dev/tty", 8) == 0)
-		tty_number = ttyn + 8;
-	else {
-		char *p = ttyn;
-		while (*p && !isdigit(*p))
-			p++;
-		tty_number = p;
-	}
-
-#ifdef LOGIN_CHOWN_VCS
-	/* find names of Virtual Console devices, for later mode change */
-	snprintf(vcsn, sizeof(vcsn), "/dev/vcs%s", tty_number);
-	snprintf(vcsan, sizeof(vcsan), "/dev/vcsa%s", tty_number);
-#endif
-
-	/* set pgid to pid */
-	setpgrp();
-	/* this means that setsid() will fail */
-
-	{
-		struct termios tt, ttt;
-
-		tcgetattr(0, &tt);
-		ttt = tt;
-		ttt.c_cflag &= ~HUPCL;
-
-		/* These can fail, e.g. with ttyn on a read-only filesystem */
-		if (fchown(0, 0, 0)) {
-			;	/* glibc warn_unused_result */
-		}
-
-		fchmod(0, TTY_MODE);
-
-		/* Kill processes left on this tty */
-		tcsetattr(0, TCSAFLUSH, &ttt);
-		signal(SIGHUP, SIG_IGN);	/* so vhangup() wont kill us */
-		vhangup();
-		signal(SIGHUP, SIG_DFL);
-
-		/* open stdin,stdout,stderr to the tty */
-		opentty(ttyn);
-
-		/* restore tty modes */
-		tcsetattr(0, TCSAFLUSH, &tt);
-	}
+	setpgrp();	 /* set pgid to pid this means that setsid() will fail */
 
 	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
 
+	init_tty(&cxt);
+
 	/*
 	 * username is initialized to NULL
 	 * and if specified on the command line it is set.
@@ -504,7 +520,7 @@ int main(int argc, char **argv)
 	if (is_pam_failure(retcode))
 		loginpam_err(pamh, retcode);
 
-	retcode = pam_set_item(pamh, PAM_TTY, tty_name);
+	retcode = pam_set_item(pamh, PAM_TTY, cxt.tty_name);
 	if (is_pam_failure(retcode))
 		loginpam_err(pamh, retcode);
 
@@ -554,8 +570,8 @@ int main(int argc, char **argv)
 			       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
 			       failcount, hostname, username, pam_strerror(pamh,
 									   retcode));
-			logbtmp(tty_name, username, hostname);
-			logaudit(tty_name, username, hostname, NULL, 0);
+			logbtmp(cxt.tty_name, username, hostname);
+			logaudit(cxt.tty_name, username, hostname, NULL, 0);
 
 			fprintf(stderr, _("Login incorrect\n\n"));
 			pam_set_item(pamh, PAM_USER, NULL);
@@ -577,8 +593,8 @@ int main(int argc, char **argv)
 				       ("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
 				       hostname, username, pam_strerror(pamh,
 									retcode));
-			logbtmp(tty_name, username, hostname);
-			logaudit(tty_name, username, hostname, NULL, 0);
+			logbtmp(cxt.tty_name, username, hostname);
+			logaudit(cxt.tty_name, username, hostname, NULL, 0);
 
 			fprintf(stderr, _("\nLogin incorrect\n"));
 			pam_end(pamh, retcode);
@@ -728,7 +744,7 @@ int main(int argc, char **argv)
 		if (utp == NULL) {
 			setutent();
 			ut.ut_type = LOGIN_PROCESS;
-			strncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+			strncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line));
 			utp = getutline(&ut);
 		}
 
@@ -740,10 +756,10 @@ int main(int argc, char **argv)
 		}
 
 		if (ut.ut_id[0] == 0)
-			strncpy(ut.ut_id, tty_number, sizeof(ut.ut_id));
+			strncpy(ut.ut_id, cxt.tty_number, sizeof(ut.ut_id));
 
 		strncpy(ut.ut_user, username, sizeof(ut.ut_user));
-		xstrncpy(ut.ut_line, tty_name, sizeof(ut.ut_line));
+		xstrncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line));
 #ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
 		gettimeofday(&tv, NULL);
 		ut.ut_tv.tv_sec = tv.tv_sec;
@@ -792,8 +808,8 @@ int main(int argc, char **argv)
 #endif
 	}
 
-	logaudit(tty_name, username, hostname, pwd, 1);
-	dolastlog(quietlog);
+	logaudit(cxt.tty_name, username, hostname, pwd, 1);
+	dolastlog(&cxt, quietlog);
 
 	if (fchown(0, pwd->pw_uid,
 		   (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
@@ -804,7 +820,7 @@ int main(int argc, char **argv)
 #ifdef LOGIN_CHOWN_VCS
 	/* if tty is one of the VC's then change owner and mode of the
 	   special /dev/vcs devices as well */
-	if (consoletty(0)) {
+	if (is_consoletty(0)) {
 
 		if (chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
 			warn(_("change terminal owner failed"));
@@ -876,8 +892,8 @@ int main(int argc, char **argv)
 
 	setproctitle("login", username);
 
-	if (!strncmp(tty_name, "ttyS", 4))
-		syslog(LOG_INFO, _("DIALUP AT %s BY %s"), tty_name,
+	if (!strncmp(cxt.tty_name, "ttyS", 4))
+		syslog(LOG_INFO, _("DIALUP AT %s BY %s"), cxt.tty_name,
 		       pwd->pw_name);
 
 	/* allow tracking of good logins.
@@ -886,15 +902,15 @@ int main(int argc, char **argv)
 	if (pwd->pw_uid == 0) {
 		if (hostname)
 			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
-			       tty_name, hostname);
+			       cxt.tty_name, hostname);
 		else
-			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), tty_name);
+			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), cxt.tty_name);
 	} else {
 		if (hostname)
 			syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"),
-			       tty_name, pwd->pw_name, hostname);
+			       cxt.tty_name, pwd->pw_name, hostname);
 		else
-			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), tty_name,
+			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), cxt.tty_name,
 			       pwd->pw_name);
 	}
 
@@ -999,7 +1015,7 @@ int main(int argc, char **argv)
 	setsid();
 
 	/* make sure we have a controlling tty */
-	opentty(ttyn);
+	open_tty(cxt.tty_path);
 	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
 
 	/*
@@ -1113,7 +1129,7 @@ void sigint(int sig __attribute__ ((__unused__)))
 	longjmp(motdinterrupt, 1);
 }
 
-void dolastlog(int quiet)
+void dolastlog(struct login_context *cxt, int quiet)
 {
 	struct lastlog ll;
 	int fd;
@@ -1147,7 +1163,7 @@ void dolastlog(int quiet)
 			ll.ll_time = t;	/* ll_time is always 32bit */
 		}
 
-		xstrncpy(ll.ll_line, tty_name, sizeof(ll.ll_line));
+		xstrncpy(ll.ll_line, cxt->tty_name, sizeof(ll.ll_line));
 		if (hostname)
 			xstrncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 12/49] login: add hostname to login_context struct
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (10 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 11/49] login: add struct login_context, consolidate tty code Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 13/49] login: add pid " Karel Zak
                     ` (36 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   71 ++++++++++++++++++++++++++------------------------
 1 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index e1bf81c..c4ef30a 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -95,6 +95,9 @@ struct login_context {
 	char		vcsn[VCS_PATH_MAX];	/* virtual console name */
 	char		vcsan[VCS_PATH_MAX];
 #endif
+
+	char		*hostname;
+	char		hostaddress[16];
 };
 
 /*
@@ -106,8 +109,6 @@ int timeout = LOGIN_TIMEOUT;
 struct passwd *pwd;
 
 static struct passwd pwdcopy;
-char hostaddress[16];		/* used in checktty.c */
-char *hostname;			/* idem */
 static char *username;
 static pid_t pid;
 
@@ -249,7 +250,7 @@ static int is_consoletty(int fd)
  * The most common login failure is to give password instead of username.
  */
 static void
-logbtmp(const char *line, const char *username, const char *hostname)
+logbtmp(struct login_context *cxt, const char *username)
 {
 	struct utmp ut;
 	struct timeval tv;
@@ -259,8 +260,10 @@ logbtmp(const char *line, const char *username, const char *hostname)
 	strncpy(ut.ut_user, username ? username : "(unknown)",
 		sizeof(ut.ut_user));
 
-	strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
-	xstrncpy(ut.ut_line, line, sizeof(ut.ut_line));
+	if (cxt->tty_number)
+		strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id));
+	if (cxt->tty_name)
+		xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line));
 
 #if defined(_HAVE_UT_TV)	/* in <utmpbits.h> included by <utmp.h> */
 	gettimeofday(&tv, NULL);
@@ -276,10 +279,10 @@ logbtmp(const char *line, const char *username, const char *hostname)
 
 	ut.ut_type = LOGIN_PROCESS;	/* XXX doesn't matter */
 	ut.ut_pid = pid;
-	if (hostname) {
-		xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
-		if (hostaddress[0])
-			memcpy(&ut.ut_addr_v6, hostaddress,
+	if (cxt->hostname) {
+		xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host));
+		if (cxt->hostaddress && *cxt->hostaddress)
+			memcpy(&ut.ut_addr_v6, cxt->hostaddress,
 			       sizeof(ut.ut_addr_v6));
 	}
 #if HAVE_UPDWTMP		/* bad luck for ancient systems */
@@ -415,7 +418,7 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	username = hostname = NULL;
+	username = NULL;
 	fflag = hflag = pflag = 0;
 	passwd_req = 1;
 
@@ -436,29 +439,29 @@ int main(int argc, char **argv)
 			    strcasecmp(p, domain) == 0)
 				*p = 0;
 
-			hostname = strdup(optarg);	/* strdup: Ambrose C. Li */
+			cxt.hostname = strdup(optarg);
 			{
 				struct addrinfo hints, *info = NULL;
 
 				memset(&hints, 0, sizeof(hints));
 				hints.ai_flags = AI_ADDRCONFIG;
 
-				hostaddress[0] = 0;
+				cxt.hostaddress[0] = 0;
 
-				if (getaddrinfo(hostname, NULL, &hints, &info)
+				if (getaddrinfo(cxt.hostname, NULL, &hints, &info)
 				    == 0 && info) {
 					if (info->ai_family == AF_INET) {
 						struct sockaddr_in *sa =
 						    (struct sockaddr_in *)info->
 						    ai_addr;
-						memcpy(hostaddress,
+						memcpy(cxt.hostaddress,
 						       &(sa->sin_addr),
 						       sizeof(sa->sin_addr));
 					} else if (info->ai_family == AF_INET6) {
 						struct sockaddr_in6 *sa =
 						    (struct sockaddr_in6 *)
 						    info->ai_addr;
-						memcpy(hostaddress,
+						memcpy(cxt.hostaddress,
 						       &(sa->sin6_addr),
 						       sizeof(sa->sin6_addr));
 					}
@@ -516,7 +519,7 @@ int main(int argc, char **argv)
 	/* hostname & tty are either set to NULL or their correct values,
 	 * depending on how much we know
 	 */
-	retcode = pam_set_item(pamh, PAM_RHOST, hostname);
+	retcode = pam_set_item(pamh, PAM_RHOST, cxt.hostname);
 	if (is_pam_failure(retcode))
 		loginpam_err(pamh, retcode);
 
@@ -568,10 +571,10 @@ int main(int argc, char **argv)
 
 			syslog(LOG_NOTICE,
 			       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
-			       failcount, hostname, username, pam_strerror(pamh,
+			       failcount, cxt.hostname, username, pam_strerror(pamh,
 									   retcode));
-			logbtmp(cxt.tty_name, username, hostname);
-			logaudit(cxt.tty_name, username, hostname, NULL, 0);
+			logbtmp(&cxt, username);
+			logaudit(cxt.tty_name, username, cxt.hostname, NULL, 0);
 
 			fprintf(stderr, _("Login incorrect\n\n"));
 			pam_set_item(pamh, PAM_USER, NULL);
@@ -585,16 +588,16 @@ int main(int argc, char **argv)
 				syslog(LOG_NOTICE,
 				       _
 				       ("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
-					"%s, %s"), failcount, hostname,
+					"%s, %s"), failcount, cxt.hostname,
 				       username, pam_strerror(pamh, retcode));
 			else
 				syslog(LOG_NOTICE,
 				       _
 				       ("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
-				       hostname, username, pam_strerror(pamh,
+				       cxt.hostname, username, pam_strerror(pamh,
 									retcode));
-			logbtmp(cxt.tty_name, username, hostname);
-			logaudit(cxt.tty_name, username, hostname, NULL, 0);
+			logbtmp(&cxt, username);
+			logaudit(cxt.tty_name, username, cxt.hostname, NULL, 0);
 
 			fprintf(stderr, _("\nLogin incorrect\n"));
 			pam_end(pamh, retcode);
@@ -774,10 +777,10 @@ int main(int argc, char **argv)
 #endif
 		ut.ut_type = USER_PROCESS;
 		ut.ut_pid = pid;
-		if (hostname) {
-			xstrncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
-			if (hostaddress[0])
-				memcpy(&ut.ut_addr_v6, hostaddress,
+		if (cxt.hostname) {
+			xstrncpy(ut.ut_host, cxt.hostname, sizeof(ut.ut_host));
+			if (cxt.hostaddress[0])
+				memcpy(&ut.ut_addr_v6, cxt.hostaddress,
 				       sizeof(ut.ut_addr_v6));
 		}
 
@@ -808,7 +811,7 @@ int main(int argc, char **argv)
 #endif
 	}
 
-	logaudit(cxt.tty_name, username, hostname, pwd, 1);
+	logaudit(cxt.tty_name, username, cxt.hostname, pwd, 1);
 	dolastlog(&cxt, quietlog);
 
 	if (fchown(0, pwd->pw_uid,
@@ -900,15 +903,15 @@ int main(int argc, char **argv)
 	   -steve philp (sphilp@mail.alliance.net) */
 
 	if (pwd->pw_uid == 0) {
-		if (hostname)
+		if (cxt.hostname)
 			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
-			       cxt.tty_name, hostname);
+			       cxt.tty_name, cxt.hostname);
 		else
 			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), cxt.tty_name);
 	} else {
-		if (hostname)
+		if (cxt.hostname)
 			syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"),
-			       cxt.tty_name, pwd->pw_name, hostname);
+			       cxt.tty_name, pwd->pw_name, cxt.hostname);
 		else
 			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), cxt.tty_name,
 			       pwd->pw_name);
@@ -1164,8 +1167,8 @@ void dolastlog(struct login_context *cxt, int quiet)
 		}
 
 		xstrncpy(ll.ll_line, cxt->tty_name, sizeof(ll.ll_line));
-		if (hostname)
-			xstrncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+		if (cxt->hostname)
+			xstrncpy(ll.ll_host, cxt->hostname, sizeof(ll.ll_host));
 
 		if (write(fd, (char *)&ll, sizeof(ll)) < 0)
 			warn(_("write lastlog failed"));
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 13/49] login: add pid to login_context struct
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (11 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 12/49] login: add hostname to login_context struct Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 14/49] login: add username " Karel Zak
                     ` (35 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index c4ef30a..9299e5c 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -98,6 +98,8 @@ struct login_context {
 
 	char		*hostname;
 	char		hostaddress[16];
+
+	pid_t		pid;
 };
 
 /*
@@ -110,7 +112,6 @@ struct passwd *pwd;
 
 static struct passwd pwdcopy;
 static char *username;
-static pid_t pid;
 
 static void timedout(int);
 static void sigint(int);
@@ -278,7 +279,7 @@ logbtmp(struct login_context *cxt, const char *username)
 #endif
 
 	ut.ut_type = LOGIN_PROCESS;	/* XXX doesn't matter */
-	ut.ut_pid = pid;
+	ut.ut_pid = cxt->pid;
 	if (cxt->hostname) {
 		xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host));
 		if (cxt->hostaddress && *cxt->hostaddress)
@@ -391,10 +392,10 @@ int main(int argc, char **argv)
 	pam_handle_t *pamh = NULL;
 	struct pam_conv conv = { misc_conv, NULL };
 	struct sigaction sa, oldsa_hup, oldsa_term;
-	struct login_context cxt;
 
-	memset(&cxt, 0, sizeof(cxt));
-	pid = getpid();
+	struct login_context cxt = {
+		.pid = getpid()
+	};
 
 	signal(SIGALRM, timedout);
 	siginterrupt(SIGALRM, 1);	/* we have to interrupt syscalls like ioclt() */
@@ -737,7 +738,7 @@ int main(int argc, char **argv)
 		   Michael Riepe <michael@stud.uni-hannover.de>
 		 */
 		while ((utp = getutent()))
-			if (utp->ut_pid == pid
+			if (utp->ut_pid == cxt.pid
 			    && utp->ut_type >= INIT_PROCESS
 			    && utp->ut_type <= DEAD_PROCESS)
 				break;
@@ -776,7 +777,7 @@ int main(int argc, char **argv)
 		}
 #endif
 		ut.ut_type = USER_PROCESS;
-		ut.ut_pid = pid;
+		ut.ut_pid = cxt.pid;
 		if (cxt.hostname) {
 			xstrncpy(ut.ut_host, cxt.hostname, sizeof(ut.ut_host));
 			if (cxt.hostaddress[0])
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 14/49] login: add username to login_context struct
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (12 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 13/49] login: add pid " Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 15/49] login: use login_context struct in audit stuff Karel Zak
                     ` (34 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   59 +++++++++++++++++++++++++--------------------------
 1 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 9299e5c..a794d18 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -91,6 +91,8 @@ struct login_context {
 	const char	*tty_name;	/* tty_path without /dev prefix */
 	const char	*tty_number;	/* end of the tty_path */
 
+	char		*username;	/* from command line or PAM */
+
 #ifdef LOGIN_CHOWN_VCS
 	char		vcsn[VCS_PATH_MAX];	/* virtual console name */
 	char		vcsan[VCS_PATH_MAX];
@@ -111,7 +113,6 @@ int timeout = LOGIN_TIMEOUT;
 struct passwd *pwd;
 
 static struct passwd pwdcopy;
-static char *username;
 
 static void timedout(int);
 static void sigint(int);
@@ -251,14 +252,15 @@ static int is_consoletty(int fd)
  * The most common login failure is to give password instead of username.
  */
 static void
-logbtmp(struct login_context *cxt, const char *username)
+logbtmp(struct login_context *cxt)
 {
 	struct utmp ut;
 	struct timeval tv;
 
 	memset(&ut, 0, sizeof(ut));
 
-	strncpy(ut.ut_user, username ? username : "(unknown)",
+	strncpy(ut.ut_user,
+		cxt->username ? cxt->username : "(unknown)",
 		sizeof(ut.ut_user));
 
 	if (cxt->tty_number)
@@ -419,7 +421,6 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	username = NULL;
 	fflag = hflag = pflag = 0;
 	passwd_req = 1;
 
@@ -485,7 +486,7 @@ int main(int argc, char **argv)
 
 	if (*argv) {
 		char *p = *argv;
-		username = strdup(p);
+		cxt.username = strdup(p);
 
 		/* wipe name - some people mistype their password here */
 		/* (of course we are too late, but perhaps this helps a little ..) */
@@ -508,7 +509,7 @@ int main(int argc, char **argv)
 	 * Therefore, we are safe not setting it to anything
 	 */
 
-	retcode = pam_start(hflag ? "remote" : "login", username, &conv, &pamh);
+	retcode = pam_start(hflag ? "remote" : "login", cxt.username, &conv, &pamh);
 	if (retcode != PAM_SUCCESS) {
 		warnx(_("PAM failure, aborting: %s"),
 		      pam_strerror(pamh, retcode));
@@ -538,11 +539,9 @@ int main(int argc, char **argv)
 	if (is_pam_failure(retcode))
 		loginpam_err(pamh, retcode);
 
-	if (username) {
-		/* we need't the original username. We have to follow PAM. */
-		free(username);
-		username = NULL;
-	}
+	/* we need't the original username. We have to follow PAM. */
+	free(cxt.username);
+	cxt.username = NULL;
 
 	/* if fflag == 1, then the user has already been authenticated */
 	if (fflag && (getuid() == 0))
@@ -554,7 +553,7 @@ int main(int argc, char **argv)
 		int failcount = 0;
 
 		/* if we didn't get a user on the command line, set it to NULL */
-		loginpam_get_username(pamh, &username);
+		loginpam_get_username(pamh, &cxt.username);
 
 		/* there may be better ways to deal with some of these
 		   conditions, but at least this way I don't think we'll
@@ -568,14 +567,14 @@ int main(int argc, char **argv)
 			(retcode == PAM_USER_UNKNOWN) ||
 			(retcode == PAM_CRED_INSUFFICIENT) ||
 			(retcode == PAM_AUTHINFO_UNAVAIL))) {
-			loginpam_get_username(pamh, &username);
+			loginpam_get_username(pamh, &cxt.username);
 
 			syslog(LOG_NOTICE,
 			       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
-			       failcount, cxt.hostname, username, pam_strerror(pamh,
+			       failcount, cxt.hostname, cxt.username, pam_strerror(pamh,
 									   retcode));
-			logbtmp(&cxt, username);
-			logaudit(cxt.tty_name, username, cxt.hostname, NULL, 0);
+			logbtmp(&cxt);
+			logaudit(cxt.tty_name, cxt.username, cxt.hostname, NULL, 0);
 
 			fprintf(stderr, _("Login incorrect\n\n"));
 			pam_set_item(pamh, PAM_USER, NULL);
@@ -583,22 +582,22 @@ int main(int argc, char **argv)
 		}
 
 		if (is_pam_failure(retcode)) {
-			loginpam_get_username(pamh, &username);
+			loginpam_get_username(pamh, &cxt.username);
 
 			if (retcode == PAM_MAXTRIES)
 				syslog(LOG_NOTICE,
 				       _
 				       ("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
 					"%s, %s"), failcount, cxt.hostname,
-				       username, pam_strerror(pamh, retcode));
+				       cxt.username, pam_strerror(pamh, retcode));
 			else
 				syslog(LOG_NOTICE,
 				       _
 				       ("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
-				       cxt.hostname, username, pam_strerror(pamh,
+				       cxt.hostname, cxt.username, pam_strerror(pamh,
 									retcode));
-			logbtmp(&cxt, username);
-			logaudit(cxt.tty_name, username, cxt.hostname, NULL, 0);
+			logbtmp(&cxt);
+			logaudit(cxt.tty_name, cxt.username, cxt.hostname, NULL, 0);
 
 			fprintf(stderr, _("\nLogin incorrect\n"));
 			pam_end(pamh, retcode);
@@ -623,21 +622,21 @@ int main(int argc, char **argv)
 	 * Grab the user information out of the password file for future usage
 	 * First get the username that we are actually using, though.
 	 */
-	retcode = loginpam_get_username(pamh, &username);
+	retcode = loginpam_get_username(pamh, &cxt.username);
 	if (is_pam_failure(retcode))
 		loginpam_err(pamh, retcode);
 
-	if (!username || !*username) {
+	if (!cxt.username || !*cxt.username) {
 		warnx(_("\nSession setup problem, abort."));
 		syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
 		       __FUNCTION__, __LINE__);
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
-	if (!(pwd = getpwnam(username))) {
+	if (!(pwd = getpwnam(cxt.username))) {
 		warnx(_("\nSession setup problem, abort."));
 		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
-		       username, __FUNCTION__, __LINE__);
+		       cxt.username, __FUNCTION__, __LINE__);
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
@@ -660,14 +659,14 @@ int main(int argc, char **argv)
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
-	username = pwd->pw_name;
+	cxt.username = pwd->pw_name;
 
 	/*
 	 * Initialize the supplementary group list.
 	 * This should be done before pam_setcred because
 	 * the PAM modules might add groups during pam_setcred.
 	 */
-	if (initgroups(username, pwd->pw_gid) < 0) {
+	if (initgroups(cxt.username, pwd->pw_gid) < 0) {
 		syslog(LOG_ERR, "initgroups: %m");
 		warnx(_("\nSession setup problem, abort."));
 		pam_end(pamh, PAM_SYSTEM_ERR);
@@ -762,7 +761,7 @@ int main(int argc, char **argv)
 		if (ut.ut_id[0] == 0)
 			strncpy(ut.ut_id, cxt.tty_number, sizeof(ut.ut_id));
 
-		strncpy(ut.ut_user, username, sizeof(ut.ut_user));
+		strncpy(ut.ut_user, cxt.username, sizeof(ut.ut_user));
 		xstrncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line));
 #ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
 		gettimeofday(&tv, NULL);
@@ -812,7 +811,7 @@ int main(int argc, char **argv)
 #endif
 	}
 
-	logaudit(cxt.tty_name, username, cxt.hostname, pwd, 1);
+	logaudit(cxt.tty_name, cxt.username, cxt.hostname, pwd, 1);
 	dolastlog(&cxt, quietlog);
 
 	if (fchown(0, pwd->pw_uid,
@@ -894,7 +893,7 @@ int main(int argc, char **argv)
 		}
 	}
 
-	setproctitle("login", username);
+	setproctitle("login", cxt.username);
 
 	if (!strncmp(cxt.tty_name, "ttyS", 4))
 		syslog(LOG_INFO, _("DIALUP AT %s BY %s"), cxt.tty_name,
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 15/49] login: use login_context struct in audit stuff
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (13 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 14/49] login: add username " Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 16/49] login: lastlog code refactoring Karel Zak
                     ` (33 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   36 ++++++++++++++++++++----------------
 1 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index a794d18..e29fb43 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -251,8 +251,7 @@ static int is_consoletty(int fd)
  * Must be called only with username the name of an actual user.
  * The most common login failure is to give password instead of username.
  */
-static void
-logbtmp(struct login_context *cxt)
+static void logbtmp(struct login_context *cxt)
 {
 	struct utmp ut;
 	struct timeval tv;
@@ -282,6 +281,7 @@ logbtmp(struct login_context *cxt)
 
 	ut.ut_type = LOGIN_PROCESS;	/* XXX doesn't matter */
 	ut.ut_pid = cxt->pid;
+
 	if (cxt->hostname) {
 		xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host));
 		if (cxt->hostaddress && *cxt->hostaddress)
@@ -315,27 +315,31 @@ static void sig_handler(int signal)
 }
 
 #ifdef HAVE_LIBAUDIT
-static void
-logaudit(const char *tty, const char *username, const char *hostname,
-	 struct passwd *pwd, int status)
+static void log_audit(struct login_context *cxt, struct passwd *pwd, int status)
 {
 	int audit_fd;
 
 	audit_fd = audit_open();
 	if (audit_fd == -1)
 		return;
-	if (!pwd && username)
-		pwd = getpwnam(username);
-
-	audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
-			       NULL, "login", username ? username : "(unknown)",
-			       pwd ? pwd->pw_uid : (unsigned int)-1, hostname,
-			       NULL, tty, status);
+	if (!pwd && cxt->username)
+		pwd = getpwnam(cxt->username);
+
+	audit_log_acct_message(audit_fd,
+			       AUDIT_USER_LOGIN,
+			       NULL,
+			       "login",
+			       cxt->username ? cxt->username : "(unknown)",
+			       pwd ? pwd->pw_uid : (unsigned int) -1,
+			       cxt->hostname,
+			       NULL,
+			       cxt->tty_name,
+			       status);
 
 	close(audit_fd);
 }
 #else				/* ! HAVE_LIBAUDIT */
-#define logaudit(tty, username, hostname, pwd, status)
+#define log_audit(cxt, pwd, status)
 #endif				/* HAVE_LIBAUDIT */
 
 /* encapsulate stupid "void **" pam_get_item() API */
@@ -574,7 +578,7 @@ int main(int argc, char **argv)
 			       failcount, cxt.hostname, cxt.username, pam_strerror(pamh,
 									   retcode));
 			logbtmp(&cxt);
-			logaudit(cxt.tty_name, cxt.username, cxt.hostname, NULL, 0);
+			log_audit(&cxt, NULL, 0);
 
 			fprintf(stderr, _("Login incorrect\n\n"));
 			pam_set_item(pamh, PAM_USER, NULL);
@@ -597,7 +601,7 @@ int main(int argc, char **argv)
 				       cxt.hostname, cxt.username, pam_strerror(pamh,
 									retcode));
 			logbtmp(&cxt);
-			logaudit(cxt.tty_name, cxt.username, cxt.hostname, NULL, 0);
+			log_audit(&cxt, NULL, 0);
 
 			fprintf(stderr, _("\nLogin incorrect\n"));
 			pam_end(pamh, retcode);
@@ -811,7 +815,7 @@ int main(int argc, char **argv)
 #endif
 	}
 
-	logaudit(cxt.tty_name, cxt.username, cxt.hostname, pwd, 1);
+	log_audit(&cxt, pwd, 1);
 	dolastlog(&cxt, quietlog);
 
 	if (fchown(0, pwd->pw_uid,
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 16/49] login: lastlog code refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (14 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 15/49] login: use login_context struct in audit stuff Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 17/49] login: utmp " Karel Zak
                     ` (32 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  103 ++++++++++++++++++++++++++------------------------
 1 files changed, 54 insertions(+), 49 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index e29fb43..91f5b81 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -67,6 +67,7 @@
 #include "strutils.h"
 #include "nls.h"
 #include "xalloc.h"
+#include "writeall.h"
 
 #define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
@@ -102,6 +103,7 @@ struct login_context {
 	char		hostaddress[16];
 
 	pid_t		pid;
+	int		quiet;		/* 1 is hush file exists */
 };
 
 /*
@@ -117,7 +119,6 @@ static struct passwd pwdcopy;
 static void timedout(int);
 static void sigint(int);
 static void motd(void);
-static void dolastlog(struct login_context *cxt, int quiet);
 
 /*
  * Nice and simple code provided by Linus Torvalds 16-Feb-93
@@ -342,6 +343,53 @@ static void log_audit(struct login_context *cxt, struct passwd *pwd, int status)
 #define log_audit(cxt, pwd, status)
 #endif				/* HAVE_LIBAUDIT */
 
+static void log_lastlog(struct login_context *cxt)
+{
+	struct lastlog ll;
+	time_t t;
+	int fd;
+
+	fd = open(_PATH_LASTLOG, O_RDWR, 0);
+	if (fd < 0)
+		return;
+
+	lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+
+	/*
+	 * Print last log message
+	 */
+	if (!cxt->quiet) {
+		if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
+							ll.ll_time != 0) {
+			time_t ll_time = (time_t) ll.ll_time;
+
+			printf(_("Last login: %.*s "), 24 - 5, ctime(&ll_time));
+			if (*ll.ll_host != '\0')
+				printf(_("from %.*s\n"),
+				       (int)sizeof(ll.ll_host), ll.ll_host);
+			else
+				printf(_("on %.*s\n"),
+				       (int)sizeof(ll.ll_line), ll.ll_line);
+		}
+		lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+	}
+
+	memset((char *)&ll, 0, sizeof(ll));
+
+	time(&t);
+	ll.ll_time = t;		/* ll_time is always 32bit */
+
+	if (cxt->tty_name)
+		xstrncpy(ll.ll_line, cxt->tty_name, sizeof(ll.ll_line));
+	if (cxt->hostname)
+		xstrncpy(ll.ll_host, cxt->hostname, sizeof(ll.ll_host));
+
+	if (write_all(fd, (char *)&ll, sizeof(ll)))
+		warn(_("write lastlog failed"));
+
+	close(fd);
+}
+
 /* encapsulate stupid "void **" pam_get_item() API */
 static int loginpam_get_username(pam_handle_t * pamh, char **name)
 {
@@ -387,7 +435,7 @@ int main(int argc, char **argv)
 	register int ch;
 	register char *p;
 	int fflag, hflag, pflag, cnt;
-	int quietlog, passwd_req;
+	int passwd_req;
 	char *domain;
 	char tbuf[PATH_MAX + 2];
 	char *termenv;
@@ -712,12 +760,12 @@ int main(int argc, char **argv)
 		   have a libc in which snprintf is the same as sprintf */
 		if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 >
 		    PATH_MAX)
-			quietlog = 0;
+			cxt.quiet = 0;
 		else {
 			sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
 			setregid(-1, pwd->pw_gid);
 			setreuid(0, pwd->pw_uid);
-			quietlog = (effective_access(tmpstr, O_RDONLY) == 0);
+			cxt.quiet = (effective_access(tmpstr, O_RDONLY) == 0);
 			setuid(0);	/* setreuid doesn't do it alone! */
 			setreuid(ruid, 0);
 			setregid(-1, egid);
@@ -816,7 +864,7 @@ int main(int argc, char **argv)
 	}
 
 	log_audit(&cxt, pwd, 1);
-	dolastlog(&cxt, quietlog);
+	log_lastlog(&cxt);
 
 	if (fchown(0, pwd->pw_uid,
 		   (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
@@ -921,7 +969,7 @@ int main(int argc, char **argv)
 			       pwd->pw_name);
 	}
 
-	if (!quietlog) {
+	if (!cxt.quiet) {
 		motd();
 
 #ifdef LOGIN_STAT_MAIL
@@ -1136,49 +1184,6 @@ void sigint(int sig __attribute__ ((__unused__)))
 	longjmp(motdinterrupt, 1);
 }
 
-void dolastlog(struct login_context *cxt, int quiet)
-{
-	struct lastlog ll;
-	int fd;
-
-	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
-		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) {
-				time_t ll_time = (time_t) ll.ll_time;
-
-				printf(_("Last login: %.*s "),
-				       24 - 5, ctime(&ll_time));
-
-				if (*ll.ll_host != '\0')
-					printf(_("from %.*s\n"),
-					       (int)sizeof(ll.ll_host),
-					       ll.ll_host);
-				else
-					printf(_("on %.*s\n"),
-					       (int)sizeof(ll.ll_line),
-					       ll.ll_line);
-			}
-			lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
-		}
-		memset((char *)&ll, 0, sizeof(ll));
-
-		{
-			time_t t;
-			time(&t);
-			ll.ll_time = t;	/* ll_time is always 32bit */
-		}
-
-		xstrncpy(ll.ll_line, cxt->tty_name, sizeof(ll.ll_line));
-		if (cxt->hostname)
-			xstrncpy(ll.ll_host, cxt->hostname, sizeof(ll.ll_host));
-
-		if (write(fd, (char *)&ll, sizeof(ll)) < 0)
-			warn(_("write lastlog failed"));
-		close(fd);
-	}
-}
 
 /* Should not be called from PAM code... */
 void sleepexit(int eval)
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 17/49] login: utmp code refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (15 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 16/49] login: lastlog code refactoring Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 18/49] login: use getpwnam_r() rather than manually copy passwd struct Karel Zak
                     ` (31 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 configure.ac        |    1 -
 login-utils/login.c |  170 +++++++++++++++++++++++----------------------------
 2 files changed, 77 insertions(+), 94 deletions(-)

diff --git a/configure.ac b/configure.ac
index 66d0794..0baff21 100644
--- a/configure.ac
+++ b/configure.ac
@@ -194,7 +194,6 @@ AC_CHECK_FUNCS(
 	usleep \
 	nanosleep \
 	personality \
-	updwtmp \
 	jrand48 \
 	lchown \
 	llseek \
diff --git a/login-utils/login.c b/login-utils/login.c
index 91f5b81..c4f3d9c 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -289,9 +289,8 @@ static void logbtmp(struct login_context *cxt)
 			memcpy(&ut.ut_addr_v6, cxt->hostaddress,
 			       sizeof(ut.ut_addr_v6));
 	}
-#if HAVE_UPDWTMP		/* bad luck for ancient systems */
+
 	updwtmp(_PATH_BTMP, &ut);
-#endif
 }
 
 static int child_pid = 0;
@@ -390,6 +389,81 @@ static void log_lastlog(struct login_context *cxt)
 	close(fd);
 }
 
+/*
+ * Update wtmp and utmp logs
+ */
+static void log_utmp(struct login_context *cxt)
+{
+	struct utmp ut;
+	struct utmp *utp;
+	struct timeval tv;
+
+	utmpname(_PATH_UTMP);
+	setutent();
+
+	/* Find pid in utmp.
+	 *
+	 * login sometimes overwrites the runlevel entry in /var/run/utmp,
+	 * confusing sysvinit. I added a test for the entry type, and the
+	 * problem was gone. (In a runlevel entry, st_pid is not really a pid
+	 * but some number calculated from the previous and current runlevel).
+	 * -- Michael Riepe <michael@stud.uni-hannover.de>
+	 */
+	while ((utp = getutent()))
+		if (utp->ut_pid == cxt->pid
+		    && utp->ut_type >= INIT_PROCESS
+		    && utp->ut_type <= DEAD_PROCESS)
+			break;
+
+	/* If we can't find a pre-existing entry by pid, try by line.
+	 * BSD network daemons may rely on this.
+	 */
+	if (utp == NULL) {
+		setutent();
+		ut.ut_type = LOGIN_PROCESS;
+		strncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line));
+		utp = getutline(&ut);
+	}
+
+	if (utp)
+		memcpy(&ut, utp, sizeof(ut));
+	else
+		/* some gettys/telnetds don't initialize utmp... */
+		memset(&ut, 0, sizeof(ut));
+
+	if (ut.ut_id[0] == 0)
+		strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id));
+
+	strncpy(ut.ut_user, cxt->username, sizeof(ut.ut_user));
+	xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line));
+
+#ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
+	gettimeofday(&tv, NULL);
+	ut.ut_tv.tv_sec = tv.tv_sec;
+	ut.ut_tv.tv_usec = tv.tv_usec;
+#else
+	{
+		time_t t;
+		time(&t);
+		ut.ut_time = t;	/* ut_time is not always a time_t */
+				/* glibc2 #defines it as ut_tv.tv_sec */
+	}
+#endif
+	ut.ut_type = USER_PROCESS;
+	ut.ut_pid = cxt->pid;
+	if (cxt->hostname) {
+		xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host));
+		if (cxt->hostaddress && *cxt->hostaddress)
+			memcpy(&ut.ut_addr_v6, cxt->hostaddress,
+			       sizeof(ut.ut_addr_v6));
+	}
+
+	pututline(&ut);
+	endutent();
+
+	updwtmp(_PATH_WTMP, &ut);
+}
+
 /* encapsulate stupid "void **" pam_get_item() API */
 static int loginpam_get_username(pam_handle_t * pamh, char **name)
 {
@@ -772,97 +846,7 @@ int main(int argc, char **argv)
 		}
 	}
 
-	/* for linux, write entries in utmp and wtmp */
-	{
-		struct utmp ut;
-		struct utmp *utp;
-		struct timeval tv;
-
-		utmpname(_PATH_UTMP);
-		setutent();
-
-		/* Find pid in utmp.
-		   login sometimes overwrites the runlevel entry in /var/run/utmp,
-		   confusing sysvinit. I added a test for the entry type, and the problem
-		   was gone. (In a runlevel entry, st_pid is not really a pid but some number
-		   calculated from the previous and current runlevel).
-		   Michael Riepe <michael@stud.uni-hannover.de>
-		 */
-		while ((utp = getutent()))
-			if (utp->ut_pid == cxt.pid
-			    && utp->ut_type >= INIT_PROCESS
-			    && utp->ut_type <= DEAD_PROCESS)
-				break;
-
-		/* If we can't find a pre-existing entry by pid, try by line.
-		   BSD network daemons may rely on this. (anonymous) */
-		if (utp == NULL) {
-			setutent();
-			ut.ut_type = LOGIN_PROCESS;
-			strncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line));
-			utp = getutline(&ut);
-		}
-
-		if (utp) {
-			memcpy(&ut, utp, sizeof(ut));
-		} else {
-			/* some gettys/telnetds don't initialize utmp... */
-			memset(&ut, 0, sizeof(ut));
-		}
-
-		if (ut.ut_id[0] == 0)
-			strncpy(ut.ut_id, cxt.tty_number, sizeof(ut.ut_id));
-
-		strncpy(ut.ut_user, cxt.username, sizeof(ut.ut_user));
-		xstrncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line));
-#ifdef _HAVE_UT_TV		/* in <utmpbits.h> included by <utmp.h> */
-		gettimeofday(&tv, NULL);
-		ut.ut_tv.tv_sec = tv.tv_sec;
-		ut.ut_tv.tv_usec = tv.tv_usec;
-#else
-		{
-			time_t t;
-			time(&t);
-			ut.ut_time = t;	/* ut_time is not always a time_t */
-			/* glibc2 #defines it as ut_tv.tv_sec */
-		}
-#endif
-		ut.ut_type = USER_PROCESS;
-		ut.ut_pid = cxt.pid;
-		if (cxt.hostname) {
-			xstrncpy(ut.ut_host, cxt.hostname, sizeof(ut.ut_host));
-			if (cxt.hostaddress[0])
-				memcpy(&ut.ut_addr_v6, cxt.hostaddress,
-				       sizeof(ut.ut_addr_v6));
-		}
-
-		pututline(&ut);
-		endutent();
-
-#if HAVE_UPDWTMP
-		updwtmp(_PATH_WTMP, &ut);
-#else
-		/* Probably all this locking below is just nonsense,
-		   and the short version is OK as well. */
-		{
-			int lf, wtmp;
-			if ((lf =
-			     open(_PATH_WTMPLOCK, O_CREAT | O_WRONLY,
-				  0660)) >= 0) {
-				flock(lf, LOCK_EX);
-				if ((wtmp =
-				     open(_PATH_WTMP,
-					  O_APPEND | O_WRONLY)) >= 0) {
-					write(wtmp, (char *)&ut, sizeof(ut));
-					close(wtmp);
-				}
-				flock(lf, LOCK_UN);
-				close(lf);
-			}
-		}
-#endif
-	}
-
+	log_utmp(&cxt);
 	log_audit(&cxt, pwd, 1);
 	log_lastlog(&cxt);
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 18/49] login: use getpwnam_r() rather than manually copy passwd struct
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (16 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 17/49] login: utmp " Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 19/49] login: tty chown.chmod refactoring Karel Zak
                     ` (30 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   80 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index c4f3d9c..8b724ec 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -94,6 +94,8 @@ struct login_context {
 
 	char		*username;	/* from command line or PAM */
 
+	struct passwd	*pwd;		/* user info */
+
 #ifdef LOGIN_CHOWN_VCS
 	char		vcsn[VCS_PATH_MAX];	/* virtual console name */
 	char		vcsan[VCS_PATH_MAX];
@@ -112,10 +114,6 @@ struct login_context {
  */
 int timeout = LOGIN_TIMEOUT;
 
-struct passwd *pwd;
-
-static struct passwd pwdcopy;
-
 static void timedout(int);
 static void sigint(int);
 static void motd(void);
@@ -315,9 +313,10 @@ static void sig_handler(int signal)
 }
 
 #ifdef HAVE_LIBAUDIT
-static void log_audit(struct login_context *cxt, struct passwd *pwd, int status)
+static void log_audit(struct login_context *cxt, int status)
 {
 	int audit_fd;
+	struct passwd *pwd = cxt->pwd;
 
 	audit_fd = audit_open();
 	if (audit_fd == -1)
@@ -348,11 +347,14 @@ static void log_lastlog(struct login_context *cxt)
 	time_t t;
 	int fd;
 
+	if (!cxt->pwd)
+		return;
+
 	fd = open(_PATH_LASTLOG, O_RDWR, 0);
 	if (fd < 0)
 		return;
 
-	lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+	lseek(fd, (off_t) cxt->pwd->pw_uid * sizeof(ll), SEEK_SET);
 
 	/*
 	 * Print last log message
@@ -370,7 +372,7 @@ static void log_lastlog(struct login_context *cxt)
 				printf(_("on %.*s\n"),
 				       (int)sizeof(ll.ll_line), ll.ll_line);
 		}
-		lseek(fd, (off_t) pwd->pw_uid * sizeof(ll), SEEK_SET);
+		lseek(fd, (off_t) cxt->pwd->pw_uid * sizeof(ll), SEEK_SET);
 	}
 
 	memset((char *)&ll, 0, sizeof(ll));
@@ -464,6 +466,40 @@ static void log_utmp(struct login_context *cxt)
 	updwtmp(_PATH_WTMP, &ut);
 }
 
+static struct passwd *get_passwd_entry(const char *username,
+					 char **pwdbuf,
+					 struct passwd *pwd)
+{
+	struct passwd *res = NULL;
+	size_t sz;
+	char *tmp;
+	int x;
+
+	if (!pwdbuf || !username)
+		return NULL;
+
+#ifdef _SC_GETPW_R_SIZE_MAX
+	sz = sysconf(_SC_GETPW_R_SIZE_MAX);
+	if (sz <= 0)
+#endif
+		sz = 16384;
+
+	tmp = realloc(*pwdbuf, sz);
+	if (!tmp) {
+		free(*pwdbuf);
+		*pwdbuf = NULL;
+		return NULL;
+	}
+	*pwdbuf = tmp;
+
+	x = getpwnam_r(username, pwd, *pwdbuf, sz, &res);
+	if (!res) {
+		errno = x;
+		return NULL;
+	}
+	return res;
+}
+
 /* encapsulate stupid "void **" pam_get_item() API */
 static int loginpam_get_username(pam_handle_t * pamh, char **name)
 {
@@ -521,6 +557,9 @@ int main(int argc, char **argv)
 	struct pam_conv conv = { misc_conv, NULL };
 	struct sigaction sa, oldsa_hup, oldsa_term;
 
+	char *pwdbuf = NULL;
+	struct passwd *pwd = NULL, _pwd;
+
 	struct login_context cxt = {
 		.pid = getpid()
 	};
@@ -700,7 +739,7 @@ int main(int argc, char **argv)
 			       failcount, cxt.hostname, cxt.username, pam_strerror(pamh,
 									   retcode));
 			logbtmp(&cxt);
-			log_audit(&cxt, NULL, 0);
+			log_audit(&cxt, 0);
 
 			fprintf(stderr, _("Login incorrect\n\n"));
 			pam_set_item(pamh, PAM_USER, NULL);
@@ -723,7 +762,7 @@ int main(int argc, char **argv)
 				       cxt.hostname, cxt.username, pam_strerror(pamh,
 									retcode));
 			logbtmp(&cxt);
-			log_audit(&cxt, NULL, 0);
+			log_audit(&cxt, 0);
 
 			fprintf(stderr, _("\nLogin incorrect\n"));
 			pam_end(pamh, retcode);
@@ -759,7 +798,7 @@ int main(int argc, char **argv)
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
-	if (!(pwd = getpwnam(cxt.username))) {
+	if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
 		warnx(_("\nSession setup problem, abort."));
 		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
 		       cxt.username, __FUNCTION__, __LINE__);
@@ -767,24 +806,7 @@ int main(int argc, char **argv)
 		exit(EXIT_FAILURE);
 	}
 
-	/*
-	 * Create a copy of the pwd struct - otherwise it may get
-	 * clobbered by PAM
-	 */
-	memcpy(&pwdcopy, pwd, sizeof(*pwd));
-	pwd = &pwdcopy;
-	pwd->pw_name = strdup(pwd->pw_name);
-	pwd->pw_passwd = strdup(pwd->pw_passwd);
-	pwd->pw_gecos = strdup(pwd->pw_gecos);
-	pwd->pw_dir = strdup(pwd->pw_dir);
-	pwd->pw_shell = strdup(pwd->pw_shell);
-	if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos ||
-	    !pwd->pw_dir || !pwd->pw_shell) {
-		warnx(_("out of memory"));
-		syslog(LOG_ERR, "Out of memory");
-		pam_end(pamh, PAM_SYSTEM_ERR);
-		exit(EXIT_FAILURE);
-	}
+	pwd = cxt.pwd;
 	cxt.username = pwd->pw_name;
 
 	/*
@@ -847,7 +869,7 @@ int main(int argc, char **argv)
 	}
 
 	log_utmp(&cxt);
-	log_audit(&cxt, pwd, 1);
+	log_audit(&cxt, 1);
 	log_lastlog(&cxt);
 
 	if (fchown(0, pwd->pw_uid,
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 19/49] login: tty chown.chmod refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (17 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 18/49] login: use getpwnam_r() rather than manually copy passwd struct Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:14   ` [PATCH 20/49] login: use setgroups(0, NULL) for root Karel Zak
                     ` (29 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   58 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 8b724ec..3a74abe 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -158,6 +158,43 @@ static void open_tty(const char *tty)
 		close(fd);
 }
 
+#define chown_err(_what, _uid, _gid) \
+		syslog(LOG_ERR, _("chown (%s, %lu, %lu) failed: %m"), \
+			(_what), (unsigned long) (_uid), (unsigned long) (_gid))
+
+#define chmod_err(_what, _mode) \
+		syslog(LOG_ERR, _("chmod (%s, %u) failed: %m"), (_what), (_mode))
+
+static void chown_tty(struct login_context *cxt)
+{
+	struct group *gr;
+	uid_t uid = cxt->pwd->pw_uid;
+	gid_t gid = cxt->pwd->pw_gid;
+
+	gr = getgrnam(TTYGRPNAME);
+	if (gr)
+		gid = gr->gr_gid;
+
+	if (fchown(0, uid, gid))				/* tty */
+		chown_err(cxt->tty_name, uid, gid);
+	if (fchmod(0, TTY_MODE))
+		chmod_err(cxt->tty_name, TTY_MODE);
+
+#ifdef LOGIN_CHOWN_VCS
+	if (is_consoletty(0)) {
+		if (chown(cxt->vcs, uid, gid))			/* vcs */
+			chown_err(cxt->vcs, uid, gid);
+		if (chmod(cxt->vcs, TTY_MODE))
+			chmod_err(cxt->vcs, TTY_MODE);
+
+		if (chown(cxt->vcsa, uid, gid))			/* vcsa */
+			chown_err(cxt->vcsa, uid, gid);
+		if (chmod(cxt->vcsa, TTY_MODE))
+			chmod_err(cxt->vcsa, TTY_MODE);
+	}
+#endif
+}
+
 /*
  * Reads the currect terminal path and initialize cxt->tty_* variables.
  */
@@ -541,7 +578,6 @@ int main(int argc, char **argv)
 {
 	extern int optind;
 	extern char *optarg, **environ;
-	struct group *gr;
 	register int ch;
 	register char *p;
 	int fflag, hflag, pflag, cnt;
@@ -872,26 +908,8 @@ int main(int argc, char **argv)
 	log_audit(&cxt, 1);
 	log_lastlog(&cxt);
 
-	if (fchown(0, pwd->pw_uid,
-		   (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
-		warn(_("change terminal owner failed"));
-
-	fchmod(0, TTY_MODE);
-
-#ifdef LOGIN_CHOWN_VCS
-	/* if tty is one of the VC's then change owner and mode of the
-	   special /dev/vcs devices as well */
-	if (is_consoletty(0)) {
-
-		if (chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
-			warn(_("change terminal owner failed"));
-		if (chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)))
-			warn(_("change terminal owner failed"));
+	chown_tty(&cxt);
 
-		chmod(vcsn, TTY_MODE);
-		chmod(vcsan, TTY_MODE);
-	}
-#endif
 
 	if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
 		syslog(LOG_ALERT, _("setgid() failed"));
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 20/49] login: use setgroups(0, NULL) for root
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (18 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 19/49] login: tty chown.chmod refactoring Karel Zak
@ 2011-10-17 11:14   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 21/49] login: improve hushed mode (merge suse changes) Karel Zak
                     ` (28 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:14 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 3a74abe..1adf330 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -709,7 +709,6 @@ int main(int argc, char **argv)
 	 * and if specified on the command line it is set.
 	 * Therefore, we are safe not setting it to anything
 	 */
-
 	retcode = pam_start(hflag ? "remote" : "login", cxt.username, &conv, &pamh);
 	if (retcode != PAM_SUCCESS) {
 		warnx(_("PAM failure, aborting: %s"),
@@ -834,6 +833,7 @@ int main(int argc, char **argv)
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
+
 	if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
 		warnx(_("\nSession setup problem, abort."));
 		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
@@ -846,12 +846,19 @@ int main(int argc, char **argv)
 	cxt.username = pwd->pw_name;
 
 	/*
-	 * Initialize the supplementary group list.
-	 * This should be done before pam_setcred because
-	 * the PAM modules might add groups during pam_setcred.
+	 * Initialize the supplementary group list. This should be done before
+	 * pam_setcred because the PAM modules might add groups during
+	 * pam_setcred.
+	 *
+         * For root we don't call initgroups, instead we call setgroups with
+	 * group 0. This avoids the need to step through the whole group file,
+	 * which can cause problems if NIS, NIS+, LDAP or something similar
+	 * is used and the machine has network problems.
 	 */
-	if (initgroups(cxt.username, pwd->pw_gid) < 0) {
-		syslog(LOG_ERR, "initgroups: %m");
+	retcode = pwd->pw_uid ? initgroups(cxt.username, pwd->pw_gid) :	/* user */
+			        setgroups(0, NULL);			/* root */
+	if (retcode < 0) {
+		syslog(LOG_ERR, _("groups initialization failed: %m"));
 		warnx(_("\nSession setup problem, abort."));
 		pam_end(pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 21/49] login: improve hushed mode (merge suse changes)
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (19 preceding siblings ...)
  2011-10-17 11:14   ` [PATCH 20/49] login: use setgroups(0, NULL) for root Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 22/49] login: remove unused code and tests Karel Zak
                     ` (27 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 include/pathnames.h |    1 +
 login-utils/login.c |  122 +++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 91 insertions(+), 32 deletions(-)

diff --git a/include/pathnames.h b/include/pathnames.h
index 025e4af..1a54a03 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -29,6 +29,7 @@
 #define _PATH_WTMPLOCK		"/etc/wtmplock"
 
 #define	_PATH_HUSHLOGIN		".hushlogin"
+#define	_PATH_HUSHLOGINS	"/etc/hushlogins"
 
 #ifndef _PATH_MAILDIR
 #define	_PATH_MAILDIR		"/var/spool/mail"
diff --git a/login-utils/login.c b/login-utils/login.c
index 1adf330..7f6048c 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -566,7 +566,7 @@ static int loginpam_err(pam_handle_t * pamh, int retcode)
  * The open(2) seems as the surest solution.
  * -- kzak@redhat.com (10-Apr-2009)
  */
-int effective_access(const char *path, int mode)
+static int effective_access(const char *path, int mode)
 {
 	int fd = open(path, mode);
 	if (fd != -1)
@@ -574,6 +574,94 @@ int effective_access(const char *path, int mode)
 	return fd == -1 ? -1 : 0;
 }
 
+/*
+ * Check per accout or global hush-login setting.
+ *
+ * Hushed mode is enabled:
+ *
+ * a) if global (e.g. /etc/hushlogins) hush file exists:
+ *     1) for ALL ACCOUNTS if the file is empty
+ *     2) for the current user if the username or shell are found in the file
+ *
+ * b) if ~/.hushlogin file exists
+ *
+ * The ~/.hushlogin is ignored if the global hush file exists.
+ *
+ * Note that shadow-utils login(1) does not support "a1)". The "a1)" is
+ * necessary if you want to use PAM for "Last login" message.
+ *
+ * -- Karel Zak <kzak@redhat.com> (26-Aug-2011)
+ *
+ *
+ * Per-account check requires some explanation: As root we may not be able to
+ * read the directory of the user if it is on an NFS mounted filesystem. We
+ * temporarily set our effective uid to the user-uid making sure that we keep
+ * root privs. in the real uid.
+ *
+ * A portable solution would require a fork(), but we rely on Linux having the
+ * BSD setreuid()
+ */
+static int get_hushlogin_status(struct passwd *pwd)
+{
+	const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL };
+	char buf[BUFSIZ];
+	int i;
+
+	for (i = 0; files[i]; i++) {
+		const char *file = files[i];
+		int ok = 0;
+
+		/* Global hush-file*/
+		if (*file == '/') {
+			struct stat st;
+			FILE *f;
+
+			if (stat(file, &st) != 0)
+				continue;	/* file does not exist */
+
+			if (st.st_size == 0)
+				return 1;	/* for all accounts */
+
+			f = fopen(file, "r");
+			if (!f)
+				continue;	/* ignore errors... */
+
+			while (ok == 0 && fgets(buf, sizeof(buf), f)) {
+				buf[strlen(buf) - 1] = '\0';
+				ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell :
+								pwd->pw_name);
+			}
+			fclose(f);
+			if (ok)
+				return 1;	/* found username/shell */
+
+			return 0;		/* ignore per-account files */
+		}
+
+		/* Per-account setting */
+		if (strlen(pwd->pw_dir) + sizeof(file) + 2 > sizeof(buf))
+			continue;
+		else {
+			uid_t ruid = getuid();
+			gid_t egid = getegid();
+
+			sprintf(buf, "%s/%s", pwd->pw_dir, file);
+			setregid(-1, pwd->pw_gid);
+			setreuid(0, pwd->pw_uid);
+			ok = effective_access(buf, O_RDONLY) == 0;
+			setuid(0);	/* setreuid doesn't do it alone! */
+			setreuid(ruid, 0);
+			setregid(-1, egid);
+
+			if (ok)
+				return 1;	/* enabled by user */
+		}
+	}
+
+	return 0;
+}
+
+
 int main(int argc, char **argv)
 {
 	extern int optind;
@@ -879,37 +967,7 @@ int main(int argc, char **argv)
 
 	endpwent();
 
-	{
-		/*
-		 * Check per accout setting.
-		 *
-		 * This requires some explanation: As root we may not be able to
-		 * read the directory of the user if it is on an NFS mounted
-		 * filesystem. We temporarily set our effective uid to the user-uid
-		 * making sure that we keep root privs. in the real uid.
-		 *
-		 * A portable solution would require a fork(), but we rely on Linux
-		 * having the BSD setreuid()
-		 */
-		char tmpstr[PATH_MAX];
-		uid_t ruid = getuid();
-		gid_t egid = getegid();
-
-		/* avoid snprintf - old systems do not have it, or worse,
-		   have a libc in which snprintf is the same as sprintf */
-		if (strlen(pwd->pw_dir) + sizeof(_PATH_HUSHLOGIN) + 2 >
-		    PATH_MAX)
-			cxt.quiet = 0;
-		else {
-			sprintf(tmpstr, "%s/%s", pwd->pw_dir, _PATH_HUSHLOGIN);
-			setregid(-1, pwd->pw_gid);
-			setreuid(0, pwd->pw_uid);
-			cxt.quiet = (effective_access(tmpstr, O_RDONLY) == 0);
-			setuid(0);	/* setreuid doesn't do it alone! */
-			setreuid(ruid, 0);
-			setregid(-1, egid);
-		}
-	}
+	cxt.quiet = get_hushlogin_status(pwd);
 
 	log_utmp(&cxt);
 	log_audit(&cxt, 1);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 22/49] login: remove unused code and tests
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (20 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 21/49] login: improve hushed mode (merge suse changes) Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 23/49] login: PAM initialization refactoring Karel Zak
                     ` (26 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/Makefile.am |    2 +-
 login-utils/login.c     |   10 ++++------
 login-utils/login.h     |    9 ---------
 tests/commands.sh.in    |    1 -
 tests/ts/login/checktty |   26 --------------------------
 5 files changed, 5 insertions(+), 43 deletions(-)
 delete mode 100644 login-utils/login.h
 delete mode 100755 tests/ts/login/checktty

diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index 7866f7b..a07279e 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -25,7 +25,7 @@ chfn_SOURCES = chfn.c $(chfn_chsh_common)
 chsh_SOURCES = chsh.c $(chfn_chsh_common)
 chfn_chsh_common = islocal.c setpwnam.c islocal.h setpwnam.h \
 	$(top_srcdir)/lib/env.c
-login_SOURCES = login.c login.h $(top_srcdir)/lib/setproctitle.c
+login_SOURCES = login.c $(top_srcdir)/lib/setproctitle.c
 vipw_SOURCES = vipw.c setpwnam.h
 
 chfn_LDADD = $(login_ldadd_common)
diff --git a/login-utils/login.c b/login-utils/login.c
index 7f6048c..fa28c1b 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -63,7 +63,6 @@
 #include "c.h"
 #include "setproctitle.h"
 #include "pathnames.h"
-#include "login.h"
 #include "strutils.h"
 #include "nls.h"
 #include "xalloc.h"
@@ -117,6 +116,7 @@ int timeout = LOGIN_TIMEOUT;
 static void timedout(int);
 static void sigint(int);
 static void motd(void);
+static void sleepexit(int eval);
 
 /*
  * Nice and simple code provided by Linus Torvalds 16-Feb-93
@@ -661,7 +661,6 @@ static int get_hushlogin_status(struct passwd *pwd)
 	return 0;
 }
 
-
 int main(int argc, char **argv)
 {
 	extern int optind;
@@ -1224,7 +1223,6 @@ int main(int argc, char **argv)
  * What I did was add a second timeout while trying to write the message so
  * the process just exits if the second timeout expires.
  */
-
 static void timedout2(int sig __attribute__ ((__unused__)))
 {
 	struct termios ti;
@@ -1249,7 +1247,7 @@ static void timedout(int sig __attribute__ ((__unused__)))
 
 jmp_buf motdinterrupt;
 
-void motd(void)
+static void motd(void)
 {
 	int fd, nchars;
 	void (*oldint) (int);
@@ -1268,14 +1266,14 @@ void motd(void)
 	close(fd);
 }
 
-void sigint(int sig __attribute__ ((__unused__)))
+static void sigint(int sig __attribute__ ((__unused__)))
 {
 	longjmp(motdinterrupt, 1);
 }
 
 
 /* Should not be called from PAM code... */
-void sleepexit(int eval)
+static void sleepexit(int eval)
 {
 	sleep(LOGIN_EXIT_TIMEOUT);
 	exit(eval);
diff --git a/login-utils/login.h b/login-utils/login.h
deleted file mode 100644
index 92b94b9..0000000
--- a/login-utils/login.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* defined in login.c */
-extern void badlogin(const char *s);
-extern void sleepexit(int);
-extern char hostaddress[16];
-extern char *hostname;
-extern sa_family_t hostfamily;
-
-/* defined in checktty.c */
-extern void checktty(const char *user, const char *tty, struct passwd *pwd);
diff --git a/tests/commands.sh.in b/tests/commands.sh.in
index 4f70da7..462a4f5 100644
--- a/tests/commands.sh.in
+++ b/tests/commands.sh.in
@@ -55,7 +55,6 @@ TS_CMD_LOOK=${TS_CMD_LOOK-"$top_builddir/misc-utils/look"}
 TS_CMD_CAL=${TS_CMD_CAL-"$top_builddir/misc-utils/cal"}
 TS_CMD_SCRIPT=${TS_CMD_SCRIPT-"$top_builddir/term-utils/script"}
 
-TS_CMD_CHECKTTY=${TS_CMD_CHECKTTY-"$top_builddir/login-utils/checktty_test"}
 TS_CMD_ISLOCAL=${TS_CMD_ISLOCAL-"$top_builddir/login-utils/islocal_test"}
 
 TS_CMD_HWCLOCK=${TS_CMD_HWCLOCK-"$top_builddir/hwclock/hwclock"}
diff --git a/tests/ts/login/checktty b/tests/ts/login/checktty
deleted file mode 100755
index 9917d63..0000000
--- a/tests/ts/login/checktty
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-#
-# Copyright (C) 2007 Karel Zak <kzak@redhat.com>
-#
-# This file is part of util-linux.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This file is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-TS_TOPDIR="$(dirname $0)/../.."
-TS_DESC="checktty"
-
-. $TS_TOPDIR/functions.sh
-ts_init "$*"
-
-$TS_CMD_CHECKTTY  >> $TS_OUTPUT
-ts_finalize
-
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 23/49] login: PAM initialization refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (21 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 22/49] login: remove unused code and tests Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 24/49] login: PAM auth refactoring Karel Zak
                     ` (25 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  106 +++++++++++++++++++++++++++++----------------------
 1 files changed, 60 insertions(+), 46 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index fa28c1b..1e69afd 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -95,6 +95,9 @@ struct login_context {
 
 	struct passwd	*pwd;		/* user info */
 
+	pam_handle_t	*pamh;		/* PAM handler */
+	struct pam_conv	conv;		/* PAM conversation */
+
 #ifdef LOGIN_CHOWN_VCS
 	char		vcsn[VCS_PATH_MAX];	/* virtual console name */
 	char		vcsan[VCS_PATH_MAX];
@@ -105,6 +108,8 @@ struct login_context {
 
 	pid_t		pid;
 	int		quiet;		/* 1 is hush file exists */
+
+	unsigned int	remote:1;	/* login -h */
 };
 
 /*
@@ -538,7 +543,7 @@ static struct passwd *get_passwd_entry(const char *username,
 }
 
 /* encapsulate stupid "void **" pam_get_item() API */
-static int loginpam_get_username(pam_handle_t * pamh, char **name)
+static int loginpam_get_username(pam_handle_t *pamh, char **name)
 {
 	const void *item = (void *)*name;
 	int rc;
@@ -547,7 +552,7 @@ static int loginpam_get_username(pam_handle_t * pamh, char **name)
 	return rc;
 }
 
-static int loginpam_err(pam_handle_t * pamh, int retcode)
+static int loginpam_err(pam_handle_t *pamh, int retcode)
 {
 	const char *msg = pam_strerror(pamh, retcode);
 
@@ -560,6 +565,52 @@ static int loginpam_err(pam_handle_t * pamh, int retcode)
 
 }
 
+static pam_handle_t *init_loginpam(struct login_context *cxt)
+{
+	pam_handle_t *pamh = NULL;
+	int rc;
+
+	/*
+	 * username is initialized to NULL and if specified on the command line
+	 * it is set.  Therefore, we are safe not setting it to anything
+	 */
+	rc = pam_start(cxt->remote ? "remote" : "login",
+		       cxt->username, &cxt->conv, &pamh);
+	if (rc != PAM_SUCCESS) {
+		warnx(_("PAM failure, aborting: %s"), pam_strerror(pamh, rc));
+		syslog(LOG_ERR, _("Couldn't initialize PAM: %s"),
+		       pam_strerror(pamh, rc));
+		exit(EXIT_FAILURE);
+	}
+
+	/* hostname & tty are either set to NULL or their correct values,
+	 * depending on how much we know
+	 */
+	rc = pam_set_item(pamh, PAM_RHOST, cxt->hostname);
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	rc = pam_set_item(pamh, PAM_TTY, cxt->tty_name);
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	/*
+	 * Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM so that
+	 * the "login: " prompt gets localized. Unfortunately, PAM doesn't have
+	 * an interface to specify the "Password: " string (yet).
+	 */
+	rc = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	/* we need't the original username. We have to follow PAM. */
+	free(cxt->username);
+	cxt->username = NULL;
+	cxt->pamh = pamh;
+
+	return pamh;
+}
+
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
  * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID.
@@ -667,7 +718,7 @@ int main(int argc, char **argv)
 	extern char *optarg, **environ;
 	register int ch;
 	register char *p;
-	int fflag, hflag, pflag, cnt;
+	int fflag, pflag, cnt;
 	int passwd_req;
 	char *domain;
 	char tbuf[PATH_MAX + 2];
@@ -676,15 +727,15 @@ int main(int argc, char **argv)
 	char *buff;
 	int childArgc = 0;
 	int retcode;
-	pam_handle_t *pamh = NULL;
-	struct pam_conv conv = { misc_conv, NULL };
 	struct sigaction sa, oldsa_hup, oldsa_term;
 
 	char *pwdbuf = NULL;
 	struct passwd *pwd = NULL, _pwd;
+	pam_handle_t *pamh;
 
 	struct login_context cxt = {
-		.pid = getpid()
+		.pid = getpid(),		/* PID */
+		.conv = { misc_conv, NULL }	/* PAM conversation function */
 	};
 
 	signal(SIGALRM, timedout);
@@ -709,7 +760,7 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	fflag = hflag = pflag = 0;
+	fflag = pflag = 0;
 	passwd_req = 1;
 
 	while ((ch = getopt(argc, argv, "fh:p")) != -1)
@@ -724,7 +775,7 @@ int main(int argc, char **argv)
 					_("login: -h for super-user only.\n"));
 				exit(EXIT_FAILURE);
 			}
-			hflag = 1;
+			cxt.remote = 1;
 			if (domain && (p = strchr(optarg, '.')) &&
 			    strcasecmp(p, domain) == 0)
 				*p = 0;
@@ -791,44 +842,7 @@ int main(int argc, char **argv)
 
 	init_tty(&cxt);
 
-	/*
-	 * username is initialized to NULL
-	 * and if specified on the command line it is set.
-	 * Therefore, we are safe not setting it to anything
-	 */
-	retcode = pam_start(hflag ? "remote" : "login", cxt.username, &conv, &pamh);
-	if (retcode != PAM_SUCCESS) {
-		warnx(_("PAM failure, aborting: %s"),
-		      pam_strerror(pamh, retcode));
-		syslog(LOG_ERR, _("Couldn't initialize PAM: %s"),
-		       pam_strerror(pamh, retcode));
-		exit(EXIT_FAILURE);
-	}
-
-	/* hostname & tty are either set to NULL or their correct values,
-	 * depending on how much we know
-	 */
-	retcode = pam_set_item(pamh, PAM_RHOST, cxt.hostname);
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	retcode = pam_set_item(pamh, PAM_TTY, cxt.tty_name);
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	/*
-	 * Andrew.Taylor@cal.montage.ca: Provide a user prompt to PAM
-	 * so that the "login: " prompt gets localized. Unfortunately,
-	 * PAM doesn't have an interface to specify the "Password: " string
-	 * (yet).
-	 */
-	retcode = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	/* we need't the original username. We have to follow PAM. */
-	free(cxt.username);
-	cxt.username = NULL;
+	pamh = init_loginpam(&cxt);
 
 	/* if fflag == 1, then the user has already been authenticated */
 	if (fflag && (getuid() == 0))
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 24/49] login: PAM auth refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (22 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 23/49] login: PAM initialization refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 25/49] login: PAM account checks refactoring Karel Zak
                     ` (24 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  140 ++++++++++++++++++++++++++------------------------
 1 files changed, 73 insertions(+), 67 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 1e69afd..03335c4 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -109,7 +109,8 @@ struct login_context {
 	pid_t		pid;
 	int		quiet;		/* 1 is hush file exists */
 
-	unsigned int	remote:1;	/* login -h */
+	unsigned int	remote:1,	/* login -h */
+			noauth:1;	/* login -f */
 };
 
 /*
@@ -292,7 +293,7 @@ static int is_consoletty(int fd)
  * Must be called only with username the name of an actual user.
  * The most common login failure is to give password instead of username.
  */
-static void logbtmp(struct login_context *cxt)
+static void log_btmp(struct login_context *cxt)
 {
 	struct utmp ut;
 	struct timeval tv;
@@ -611,6 +612,69 @@ static pam_handle_t *init_loginpam(struct login_context *cxt)
 	return pamh;
 }
 
+static void loginpam_auth(struct login_context *cxt)
+{
+	int rc, failcount = 0;
+	pam_handle_t *pamh = cxt->pamh;
+
+	/* if we didn't get a user on the command line, set it to NULL */
+	loginpam_get_username(pamh, &cxt->username);
+
+	/*
+	 * There may be better ways to deal with some of these conditions, but
+	 * at least this way I don't think we'll be giving away information...
+	 *
+	 * Perhaps someday we can trust that all PAM modules will pay attention
+	 * to failure count and get rid of MAX_LOGIN_TRIES?
+	 */
+	rc = pam_authenticate(pamh, 0);
+
+	while ((failcount++ < LOGIN_MAX_TRIES) &&
+	       ((rc == PAM_AUTH_ERR) ||
+		(rc == PAM_USER_UNKNOWN) ||
+		(rc == PAM_CRED_INSUFFICIENT) ||
+		(rc == PAM_AUTHINFO_UNAVAIL))) {
+
+		loginpam_get_username(pamh, &cxt->username);
+
+		syslog(LOG_NOTICE,
+		       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
+		       failcount, cxt->hostname, cxt->username,
+		       pam_strerror(pamh, rc));
+
+		log_btmp(cxt);
+		log_audit(cxt, 0);
+
+		fprintf(stderr, _("Login incorrect\n\n"));
+
+		pam_set_item(pamh, PAM_USER, NULL);
+		rc = pam_authenticate(pamh, 0);
+	}
+
+	if (is_pam_failure(rc)) {
+
+		loginpam_get_username(pamh, &cxt->username);
+
+		if (rc == PAM_MAXTRIES)
+			syslog(LOG_NOTICE,
+			       _("TOO MANY LOGIN TRIES (%d) FROM %s FOR %s, %s"),
+			       failcount, cxt->hostname, cxt->username,
+			       pam_strerror(pamh, rc));
+		else
+			syslog(LOG_NOTICE,
+			       _("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
+			       cxt->hostname, cxt->username,
+			       pam_strerror(pamh, rc));
+
+		log_btmp(cxt);
+		log_audit(cxt, 0);
+
+		fprintf(stderr, _("\nLogin incorrect\n"));
+		pam_end(pamh, rc);
+		exit(EXIT_SUCCESS);
+	}
+}
+
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
  * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID.
@@ -718,8 +782,7 @@ int main(int argc, char **argv)
 	extern char *optarg, **environ;
 	register int ch;
 	register char *p;
-	int fflag, pflag, cnt;
-	int passwd_req;
+	int pflag, cnt;
 	char *domain;
 	char tbuf[PATH_MAX + 2];
 	char *termenv;
@@ -760,13 +823,12 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	fflag = pflag = 0;
-	passwd_req = 1;
+	pflag = 0;
 
 	while ((ch = getopt(argc, argv, "fh:p")) != -1)
 		switch (ch) {
 		case 'f':
-			fflag = 1;
+			cxt.noauth = 1;
 			break;
 
 		case 'h':
@@ -844,67 +906,11 @@ int main(int argc, char **argv)
 
 	pamh = init_loginpam(&cxt);
 
-	/* if fflag == 1, then the user has already been authenticated */
-	if (fflag && (getuid() == 0))
-		passwd_req = 0;
-	else
-		passwd_req = 1;
-
-	if (passwd_req == 1) {
-		int failcount = 0;
-
-		/* if we didn't get a user on the command line, set it to NULL */
-		loginpam_get_username(pamh, &cxt.username);
+	/* login -f, then the user has already been authenticated */
+	cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0;
 
-		/* there may be better ways to deal with some of these
-		   conditions, but at least this way I don't think we'll
-		   be giving away information... */
-		/* Perhaps someday we can trust that all PAM modules will
-		   pay attention to failure count and get rid of MAX_LOGIN_TRIES? */
-
-		retcode = pam_authenticate(pamh, 0);
-		while ((failcount++ < LOGIN_MAX_TRIES) &&
-		       ((retcode == PAM_AUTH_ERR) ||
-			(retcode == PAM_USER_UNKNOWN) ||
-			(retcode == PAM_CRED_INSUFFICIENT) ||
-			(retcode == PAM_AUTHINFO_UNAVAIL))) {
-			loginpam_get_username(pamh, &cxt.username);
-
-			syslog(LOG_NOTICE,
-			       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
-			       failcount, cxt.hostname, cxt.username, pam_strerror(pamh,
-									   retcode));
-			logbtmp(&cxt);
-			log_audit(&cxt, 0);
-
-			fprintf(stderr, _("Login incorrect\n\n"));
-			pam_set_item(pamh, PAM_USER, NULL);
-			retcode = pam_authenticate(pamh, 0);
-		}
-
-		if (is_pam_failure(retcode)) {
-			loginpam_get_username(pamh, &cxt.username);
-
-			if (retcode == PAM_MAXTRIES)
-				syslog(LOG_NOTICE,
-				       _
-				       ("TOO MANY LOGIN TRIES (%d) FROM %s FOR "
-					"%s, %s"), failcount, cxt.hostname,
-				       cxt.username, pam_strerror(pamh, retcode));
-			else
-				syslog(LOG_NOTICE,
-				       _
-				       ("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
-				       cxt.hostname, cxt.username, pam_strerror(pamh,
-									retcode));
-			logbtmp(&cxt);
-			log_audit(&cxt, 0);
-
-			fprintf(stderr, _("\nLogin incorrect\n"));
-			pam_end(pamh, retcode);
-			exit(EXIT_SUCCESS);
-		}
-	}
+	if (!cxt.noauth)
+		loginpam_auth(&cxt);
 
 	/*
 	 * Authentication may be skipped (for example, during krlogin, rlogin, etc...),
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 25/49] login: PAM account checks refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (23 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 24/49] login: PAM auth refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 26/49] login: PAM session initialization refactoring Karel Zak
                     ` (23 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   61 +++++++++++++++++++++++++++++---------------------
 1 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 03335c4..0c53d5f 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -675,6 +675,36 @@ static void loginpam_auth(struct login_context *cxt)
 	}
 }
 
+static void loginpam_acct(struct login_context *cxt)
+{
+	int rc;
+	pam_handle_t *pamh = cxt->pamh;
+
+	rc = pam_acct_mgmt(pamh, 0);
+
+	if (rc == PAM_NEW_AUTHTOK_REQD)
+		rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	/*
+	 * Grab the user information out of the password file for future usage
+	 * First get the username that we are actually using, though.
+	 */
+	rc = loginpam_get_username(pamh, &cxt->username);
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	if (!cxt->username || !*cxt->username) {
+		warnx(_("\nSession setup problem, abort."));
+		syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
+		       __FUNCTION__, __LINE__);
+		pam_end(pamh, PAM_SYSTEM_ERR);
+		exit(EXIT_FAILURE);
+	}
+}
+
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
  * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID.
@@ -913,33 +943,12 @@ int main(int argc, char **argv)
 		loginpam_auth(&cxt);
 
 	/*
-	 * Authentication may be skipped (for example, during krlogin, rlogin, etc...),
-	 * but it doesn't mean that we can skip other account checks. The account
-	 * could be disabled or password expired (althought kerberos ticket is valid).
-	 * -- kzak@redhat.com (22-Feb-2006)
-	 */
-	retcode = pam_acct_mgmt(pamh, 0);
-
-	if (retcode == PAM_NEW_AUTHTOK_REQD)
-		retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	/*
-	 * Grab the user information out of the password file for future usage
-	 * First get the username that we are actually using, though.
+	 * Authentication may be skipped (for example, during krlogin, rlogin,
+	 * etc...), but it doesn't mean that we can skip other account checks.
+	 * The account could be disabled or password expired (althought
+	 * kerberos ticket is valid).         -- kzak@redhat.com (22-Feb-2006)
 	 */
-	retcode = loginpam_get_username(pamh, &cxt.username);
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	if (!cxt.username || !*cxt.username) {
-		warnx(_("\nSession setup problem, abort."));
-		syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."),
-		       __FUNCTION__, __LINE__);
-		pam_end(pamh, PAM_SYSTEM_ERR);
-		exit(EXIT_FAILURE);
-	}
+	loginpam_acct(&cxt);
 
 	if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
 		warnx(_("\nSession setup problem, abort."));
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 26/49] login: PAM session initialization refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (24 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 25/49] login: PAM account checks refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 27/49] login: remove pam_handle_t from main() Karel Zak
                     ` (22 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   29 ++++++++++++++++++++---------
 1 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 0c53d5f..49c8aab 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -705,6 +705,22 @@ static void loginpam_acct(struct login_context *cxt)
 	}
 }
 
+static void loginpam_session(struct login_context *cxt)
+{
+	int rc;
+	pam_handle_t *pamh = cxt->pamh;
+
+	rc = pam_open_session(pamh, 0);
+	if (is_pam_failure(rc))
+		loginpam_err(pamh, rc);
+
+	rc = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+	if (is_pam_failure(rc)) {
+		pam_close_session(pamh, 0);
+		loginpam_err(pamh, rc);
+	}
+}
+
 /*
  * We need to check effective UID/GID. For example $HOME could be on root
  * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID.
@@ -980,15 +996,10 @@ int main(int argc, char **argv)
 		exit(EXIT_FAILURE);
 	}
 
-	retcode = pam_open_session(pamh, 0);
-	if (is_pam_failure(retcode))
-		loginpam_err(pamh, retcode);
-
-	retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
-	if (is_pam_failure(retcode)) {
-		pam_close_session(pamh, 0);
-		loginpam_err(pamh, retcode);
-	}
+	/*
+	 * Open PAM session (after successful authentication and account check)
+	 */
+	loginpam_session(&cxt);
 
 	/* committed to login -- turn off timeout */
 	alarm((unsigned int)0);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 27/49] login: remove pam_handle_t from main()
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (25 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 26/49] login: PAM session initialization refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 28/49] login: fork & session initialization refactoring Karel Zak
                     ` (21 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   30 +++++++++++++++++-------------
 1 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 49c8aab..950af99 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -840,7 +840,6 @@ int main(int argc, char **argv)
 
 	char *pwdbuf = NULL;
 	struct passwd *pwd = NULL, _pwd;
-	pam_handle_t *pamh;
 
 	struct login_context cxt = {
 		.pid = getpid(),		/* PID */
@@ -949,8 +948,7 @@ int main(int argc, char **argv)
 	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
 
 	init_tty(&cxt);
-
-	pamh = init_loginpam(&cxt);
+	init_loginpam(&cxt);
 
 	/* login -f, then the user has already been authenticated */
 	cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0;
@@ -970,7 +968,7 @@ int main(int argc, char **argv)
 		warnx(_("\nSession setup problem, abort."));
 		syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
 		       cxt.username, __FUNCTION__, __LINE__);
-		pam_end(pamh, PAM_SYSTEM_ERR);
+		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
 
@@ -992,7 +990,7 @@ int main(int argc, char **argv)
 	if (retcode < 0) {
 		syslog(LOG_ERR, _("groups initialization failed: %m"));
 		warnx(_("\nSession setup problem, abort."));
-		pam_end(pamh, PAM_SYSTEM_ERR);
+		pam_end(cxt.pamh, PAM_SYSTEM_ERR);
 		exit(EXIT_FAILURE);
 	}
 
@@ -1063,7 +1061,7 @@ int main(int argc, char **argv)
 
 	{
 		int i;
-		char **env = pam_getenvlist(pamh);
+		char **env = pam_getenvlist(cxt.pamh);
 
 		if (env != NULL) {
 			for (i = 0; env[i]; i++) {
@@ -1156,15 +1154,20 @@ int main(int argc, char **argv)
 
 	child_pid = fork();
 	if (child_pid < 0) {
-		/* error in fork() */
-		warn(_("failure forking"));
-		pam_setcred(pamh, PAM_DELETE_CRED);
-		pam_end(pamh, pam_close_session(pamh, 0));
+		/*
+		 * fork() error
+		 */
+		warn(_("fork failed"));
+
+		pam_setcred(cxt.pamh, PAM_DELETE_CRED);
+		pam_end(cxt.pamh, pam_close_session(cxt.pamh, 0));
 		exit(EXIT_FAILURE);
 	}
 
 	if (child_pid) {
-		/* parent - wait for child to finish, then cleanup session */
+		/*
+		 * parent - wait for child to finish, then cleanup session
+		 */
 		close(0);
 		close(1);
 		close(2);
@@ -1175,8 +1178,9 @@ int main(int argc, char **argv)
 		/* wait as long as any child is there */
 		while (wait(NULL) == -1 && errno == EINTR) ;
 		openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
-		pam_setcred(pamh, PAM_DELETE_CRED);
-		pam_end(pamh, pam_close_session(pamh, 0));
+
+		pam_setcred(cxt.pamh, PAM_DELETE_CRED);
+		pam_end(cxt.pamh, pam_close_session(cxt.pamh, 0));
 		exit(EXIT_SUCCESS);
 	}
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 28/49] login: fork & session initialization refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (26 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 27/49] login: remove pam_handle_t from main() Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 29/49] login: env " Karel Zak
                     ` (20 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  200 +++++++++++++++++++++++++++------------------------
 1 files changed, 106 insertions(+), 94 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 950af99..1011206 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -117,7 +117,9 @@ struct login_context {
  * This bounds the time given to login.  Not a define so it can
  * be patched on machines where it's too small.
  */
-int timeout = LOGIN_TIMEOUT;
+static int timeout = LOGIN_TIMEOUT;
+static int child_pid = 0;
+static volatile int got_sig = 0;
 
 static void timedout(int);
 static void sigint(int);
@@ -334,9 +336,6 @@ static void log_btmp(struct login_context *cxt)
 	updwtmp(_PATH_BTMP, &ut);
 }
 
-static int child_pid = 0;
-static volatile int got_sig = 0;
-
 /*
  * This handler allows to inform a shell about signals to login. If you have
  * (root) permissions you can kill all login childrent by one signal to login
@@ -822,6 +821,106 @@ static int get_hushlogin_status(struct passwd *pwd)
 	return 0;
 }
 
+/*
+ * Detach the controlling terminal, fork, restore syslog stuff and create a new
+ * session.
+ */
+static void fork_session(struct login_context *cxt)
+{
+	struct sigaction sa, oldsa_hup, oldsa_term;
+
+	signal(SIGALRM, SIG_DFL);
+	signal(SIGQUIT, SIG_DFL);
+	signal(SIGTSTP, SIG_IGN);
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = SIG_IGN;
+	sigaction(SIGINT, &sa, NULL);
+
+	sigaction(SIGHUP, &sa, &oldsa_hup);	/* ignore when TIOCNOTTY */
+
+	/*
+	 * detach the controlling tty
+	 * -- we needn't the tty in parent who waits for child only.
+	 *    The child calls setsid() that detach from the tty as well.
+	 */
+	ioctl(0, TIOCNOTTY, NULL);
+
+	/*
+	 * We have care about SIGTERM, because leave PAM session without
+	 * pam_close_session() is pretty bad thing.
+	 */
+	sa.sa_handler = sig_handler;
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGTERM, &sa, &oldsa_term);
+
+	closelog();
+
+	/*
+	 * We must fork before setuid() because we need to call
+	 * pam_close_session() as root.
+	 */
+	child_pid = fork();
+	if (child_pid < 0) {
+		/*
+		 * fork() error
+		 */
+		warn(_("fork failed"));
+
+		pam_setcred(cxt->pamh, PAM_DELETE_CRED);
+		pam_end(cxt->pamh, pam_close_session(cxt->pamh, 0));
+		exit(EXIT_FAILURE);
+	}
+
+	if (child_pid) {
+		/*
+		 * parent - wait for child to finish, then cleanup session
+		 */
+		close(0);
+		close(1);
+		close(2);
+		sa.sa_handler = SIG_IGN;
+		sigaction(SIGQUIT, &sa, NULL);
+		sigaction(SIGINT, &sa, NULL);
+
+		/* wait as long as any child is there */
+		while (wait(NULL) == -1 && errno == EINTR) ;
+		openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
+
+		pam_setcred(cxt->pamh, PAM_DELETE_CRED);
+		pam_end(cxt->pamh, pam_close_session(cxt->pamh, 0));
+		exit(EXIT_SUCCESS);
+	}
+
+	/*
+	 * child
+	 */
+	sigaction(SIGHUP, &oldsa_hup, NULL);		/* restore old state */
+	sigaction(SIGTERM, &oldsa_term, NULL);
+	if (got_sig)
+		exit(EXIT_FAILURE);
+
+	/*
+	 * Problem: if the user's shell is a shell like ash that doesnt do
+	 * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
+	 * process in the pgrp, will kill us.
+	 */
+
+	/* start new session */
+	setsid();
+
+	/* make sure we have a controlling tty */
+	open_tty(cxt->tty_path);
+	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
+
+	/*
+	 * TIOCSCTTY: steal tty from other process group.
+	 */
+	if (ioctl(0, TIOCSCTTY, 1))
+		syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
+	signal(SIGINT, SIG_DFL);
+}
+
 int main(int argc, char **argv)
 {
 	extern int optind;
@@ -836,7 +935,6 @@ int main(int argc, char **argv)
 	char *buff;
 	int childArgc = 0;
 	int retcode;
-	struct sigaction sa, oldsa_hup, oldsa_term;
 
 	char *pwdbuf = NULL;
 	struct passwd *pwd = NULL, _pwd;
@@ -1120,97 +1218,11 @@ int main(int argc, char **argv)
 #endif
 	}
 
-	signal(SIGALRM, SIG_DFL);
-	signal(SIGQUIT, SIG_DFL);
-	signal(SIGTSTP, SIG_IGN);
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_IGN;
-	sigaction(SIGINT, &sa, NULL);
-
-	sigaction(SIGHUP, &sa, &oldsa_hup);	/* ignore when TIOCNOTTY */
-
 	/*
-	 * detach the controlling tty
-	 * -- we needn't the tty in parent who waits for child only.
-	 *    The child calls setsid() that detach from the tty as well.
+	 * Detach the controlling terminal, fork() and create, new session
+	 * and reinilizalize syslog stuff.
 	 */
-	ioctl(0, TIOCNOTTY, NULL);
-
-	/*
-	 * We have care about SIGTERM, because leave PAM session without
-	 * pam_close_session() is pretty bad thing.
-	 */
-	sa.sa_handler = sig_handler;
-	sigaction(SIGHUP, &sa, NULL);
-	sigaction(SIGTERM, &sa, &oldsa_term);
-
-	closelog();
-
-	/*
-	 * We must fork before setuid() because we need to call
-	 * pam_close_session() as root.
-	 */
-
-	child_pid = fork();
-	if (child_pid < 0) {
-		/*
-		 * fork() error
-		 */
-		warn(_("fork failed"));
-
-		pam_setcred(cxt.pamh, PAM_DELETE_CRED);
-		pam_end(cxt.pamh, pam_close_session(cxt.pamh, 0));
-		exit(EXIT_FAILURE);
-	}
-
-	if (child_pid) {
-		/*
-		 * parent - wait for child to finish, then cleanup session
-		 */
-		close(0);
-		close(1);
-		close(2);
-		sa.sa_handler = SIG_IGN;
-		sigaction(SIGQUIT, &sa, NULL);
-		sigaction(SIGINT, &sa, NULL);
-
-		/* wait as long as any child is there */
-		while (wait(NULL) == -1 && errno == EINTR) ;
-		openlog("login", LOG_ODELAY, LOG_AUTHPRIV);
-
-		pam_setcred(cxt.pamh, PAM_DELETE_CRED);
-		pam_end(cxt.pamh, pam_close_session(cxt.pamh, 0));
-		exit(EXIT_SUCCESS);
-	}
-
-	/* child */
-
-	/* restore to old state */
-	sigaction(SIGHUP, &oldsa_hup, NULL);
-	sigaction(SIGTERM, &oldsa_term, NULL);
-	if (got_sig)
-		exit(EXIT_FAILURE);
-
-	/*
-	 * Problem: if the user's shell is a shell like ash that doesnt do
-	 * setsid() or setpgrp(), then a ctrl-\, sending SIGQUIT to every
-	 * process in the pgrp, will kill us.
-	 */
-
-	/* start new session */
-	setsid();
-
-	/* make sure we have a controlling tty */
-	open_tty(cxt.tty_path);
-	openlog("login", LOG_ODELAY, LOG_AUTHPRIV);	/* reopen */
-
-	/*
-	 * TIOCSCTTY: steal tty from other process group.
-	 */
-	if (ioctl(0, TIOCSCTTY, 1))
-		syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
-	signal(SIGINT, SIG_DFL);
+	fork_session(&cxt);
 
 	/* discard permissions last so can't get killed and drop core */
 	if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) {
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 29/49] login: env initialization refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (27 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 28/49] login: fork & session initialization refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 30/49] login: use xalloc.h Karel Zak
                     ` (19 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   98 +++++++++++++++++++++++----------------------------
 1 files changed, 44 insertions(+), 54 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 1011206..c875181 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -110,7 +110,8 @@ struct login_context {
 	int		quiet;		/* 1 is hush file exists */
 
 	unsigned int	remote:1,	/* login -h */
-			noauth:1;	/* login -f */
+			noauth:1,	/* login -f */
+			keep_env:1;	/* login -p */
 };
 
 /*
@@ -921,16 +922,54 @@ static void fork_session(struct login_context *cxt)
 	signal(SIGINT, SIG_DFL);
 }
 
+/*
+ * Initialize $TERM, $HOME, ...
+ */
+static void init_environ(struct login_context *cxt)
+{
+	struct passwd *pwd = cxt->pwd;
+	char *termenv = NULL, **env;
+	char tmp[PATH_MAX];
+	int len, i;
+
+	termenv = getenv("TERM");
+	termenv = termenv ? strdup(termenv) : "dumb";
+
+	/* destroy environment unless user has requested preservation (-p) */
+	if (!cxt->keep_env) {
+		environ = (char **) malloc(sizeof(char *));
+		memset(environ, 0, sizeof(char *));
+	}
+
+	setenv("HOME", pwd->pw_dir, 0);	/* legal to override */
+	setenv("PATH", pwd->pw_uid ? _PATH_DEFPATH : _PATH_DEFPATH_ROOT, 1);
+	setenv("SHELL", pwd->pw_shell, 1);
+	setenv("TERM", termenv, 1);
+
+	/* mailx will give a funny error msg if you forget this one */
+	len = snprintf(tmp, sizeof(tmp), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+	if (len > 0 && (size_t) len + 1 <= sizeof(tmp))
+		setenv("MAIL", tmp, 0);
+
+	/* LOGNAME is not documented in login(1) but HP-UX 6.5 does it. We'll
+	 * not allow modifying it.
+	 */
+	setenv("LOGNAME", pwd->pw_name, 1);
+
+	env = pam_getenvlist(cxt->pamh);
+	for (i = 0; env && env[i]; i++)
+		putenv(env[i]);
+}
+
 int main(int argc, char **argv)
 {
 	extern int optind;
 	extern char *optarg, **environ;
 	register int ch;
 	register char *p;
-	int pflag, cnt;
+	int cnt;
 	char *domain;
 	char tbuf[PATH_MAX + 2];
-	char *termenv;
 	char *childArgv[10];
 	char *buff;
 	int childArgc = 0;
@@ -966,8 +1005,6 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	pflag = 0;
-
 	while ((ch = getopt(argc, argv, "fh:p")) != -1)
 		switch (ch) {
 		case 'f':
@@ -1017,7 +1054,7 @@ int main(int argc, char **argv)
 			break;
 
 		case 'p':
-			pflag = 1;
+			cxt.keep_env = 1;
 			break;
 
 		case '?':
@@ -1119,55 +1156,8 @@ int main(int argc, char **argv)
 	if (*pwd->pw_shell == '\0')
 		pwd->pw_shell = _PATH_BSHELL;
 
-	/* preserve TERM even without -p flag */
-	{
-		char *ep;
-
-		if (!((ep = getenv("TERM")) && (termenv = strdup(ep))))
-			termenv = "dumb";
-	}
-
-	/* destroy environment unless user has requested preservation */
-	if (!pflag) {
-		environ = (char **)malloc(sizeof(char *));
-		memset(environ, 0, sizeof(char *));
-	}
-
-	setenv("HOME", pwd->pw_dir, 0);	/* legal to override */
-	if (pwd->pw_uid)
-		setenv("PATH", _PATH_DEFPATH, 1);
-	else
-		setenv("PATH", _PATH_DEFPATH_ROOT, 1);
-
-	setenv("SHELL", pwd->pw_shell, 1);
-	setenv("TERM", termenv, 1);
+	init_environ(&cxt);
 
-	/* mailx will give a funny error msg if you forget this one */
-	{
-		char tmp[PATH_MAX];
-		/* avoid snprintf */
-		if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < PATH_MAX) {
-			sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
-			setenv("MAIL", tmp, 0);
-		}
-	}
-
-	/* LOGNAME is not documented in login(1) but
-	   HP-UX 6.5 does it. We'll not allow modifying it.
-	 */
-	setenv("LOGNAME", pwd->pw_name, 1);
-
-	{
-		int i;
-		char **env = pam_getenvlist(cxt.pamh);
-
-		if (env != NULL) {
-			for (i = 0; env[i]; i++) {
-				putenv(env[i]);
-				/* D(("env[%d] = %s", i,env[i])); */
-			}
-		}
-	}
 
 	setproctitle("login", cxt.username);
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 30/49] login: use xalloc.h
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (28 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 29/49] login: env " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 31/49] login: log good logins refactoring Karel Zak
                     ` (18 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   17 +++++------------
 1 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index c875181..d87a632 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -515,7 +515,6 @@ static struct passwd *get_passwd_entry(const char *username,
 {
 	struct passwd *res = NULL;
 	size_t sz;
-	char *tmp;
 	int x;
 
 	if (!pwdbuf || !username)
@@ -527,13 +526,7 @@ static struct passwd *get_passwd_entry(const char *username,
 #endif
 		sz = 16384;
 
-	tmp = realloc(*pwdbuf, sz);
-	if (!tmp) {
-		free(*pwdbuf);
-		*pwdbuf = NULL;
-		return NULL;
-	}
-	*pwdbuf = tmp;
+	*pwdbuf = xrealloc(*pwdbuf, sz);
 
 	x = getpwnam_r(username, pwd, *pwdbuf, sz, &res);
 	if (!res) {
@@ -933,11 +926,11 @@ static void init_environ(struct login_context *cxt)
 	int len, i;
 
 	termenv = getenv("TERM");
-	termenv = termenv ? strdup(termenv) : "dumb";
+	termenv = termenv ? xstrdup(termenv) : "dumb";
 
 	/* destroy environment unless user has requested preservation (-p) */
 	if (!cxt->keep_env) {
-		environ = (char **) malloc(sizeof(char *));
+		environ = (char **) xmalloc(sizeof(char *));
 		memset(environ, 0, sizeof(char *));
 	}
 
@@ -1022,7 +1015,7 @@ int main(int argc, char **argv)
 			    strcasecmp(p, domain) == 0)
 				*p = 0;
 
-			cxt.hostname = strdup(optarg);
+			cxt.hostname = xstrdup(optarg);
 			{
 				struct addrinfo hints, *info = NULL;
 
@@ -1067,7 +1060,7 @@ int main(int argc, char **argv)
 
 	if (*argv) {
 		char *p = *argv;
-		cxt.username = strdup(p);
+		cxt.username = xstrdup(p);
 
 		/* wipe name - some people mistype their password here */
 		/* (of course we are too late, but perhaps this helps a little ..) */
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 31/49] login: log good logins refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (29 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 30/49] login: use xalloc.h Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 32/49] login: move signal stuff to the one place Karel Zak
                     ` (17 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   50 ++++++++++++++++++++++++++------------------------
 1 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index d87a632..52598f4 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -509,6 +509,30 @@ static void log_utmp(struct login_context *cxt)
 	updwtmp(_PATH_WTMP, &ut);
 }
 
+static void log_syslog(struct login_context *cxt)
+{
+	struct passwd *pwd = cxt->pwd;
+
+	if (!strncmp(cxt->tty_name, "ttyS", 4))
+		syslog(LOG_INFO, _("DIALUP AT %s BY %s"),
+		       cxt->tty_name, pwd->pw_name);
+
+	if (!pwd->pw_uid) {
+		if (cxt->hostname)
+			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
+			       cxt->tty_name, cxt->hostname);
+		else
+			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), cxt->tty_name);
+	} else {
+		if (cxt->hostname)
+			syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"),
+			       cxt->tty_name, pwd->pw_name, cxt->hostname);
+		else
+			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), cxt->tty_name,
+			       pwd->pw_name);
+	}
+}
+
 static struct passwd *get_passwd_entry(const char *username,
 					 char **pwdbuf,
 					 struct passwd *pwd)
@@ -1140,7 +1164,6 @@ int main(int argc, char **argv)
 
 	chown_tty(&cxt);
 
-
 	if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) {
 		syslog(LOG_ALERT, _("setgid() failed"));
 		exit(EXIT_FAILURE);
@@ -1149,32 +1172,11 @@ int main(int argc, char **argv)
 	if (*pwd->pw_shell == '\0')
 		pwd->pw_shell = _PATH_BSHELL;
 
-	init_environ(&cxt);
-
+	init_environ(&cxt);		/* init $HOME, $TERM ... */
 
 	setproctitle("login", cxt.username);
 
-	if (!strncmp(cxt.tty_name, "ttyS", 4))
-		syslog(LOG_INFO, _("DIALUP AT %s BY %s"), cxt.tty_name,
-		       pwd->pw_name);
-
-	/* allow tracking of good logins.
-	   -steve philp (sphilp@mail.alliance.net) */
-
-	if (pwd->pw_uid == 0) {
-		if (cxt.hostname)
-			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s FROM %s"),
-			       cxt.tty_name, cxt.hostname);
-		else
-			syslog(LOG_NOTICE, _("ROOT LOGIN ON %s"), cxt.tty_name);
-	} else {
-		if (cxt.hostname)
-			syslog(LOG_INFO, _("LOGIN ON %s BY %s FROM %s"),
-			       cxt.tty_name, pwd->pw_name, cxt.hostname);
-		else
-			syslog(LOG_INFO, _("LOGIN ON %s BY %s"), cxt.tty_name,
-			       pwd->pw_name);
-	}
+	log_syslog(&cxt);
 
 	if (!cxt.quiet) {
 		motd();
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 32/49] login: move signal stuff to the one place
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (30 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 31/49] login: log good logins refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 33/49] login: remove unnecessary variables Karel Zak
                     ` (16 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |  166 +++++++++++++++++++++++++--------------------------
 1 files changed, 82 insertions(+), 84 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 52598f4..ffde1af 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -122,10 +122,88 @@ static int timeout = LOGIN_TIMEOUT;
 static int child_pid = 0;
 static volatile int got_sig = 0;
 
-static void timedout(int);
-static void sigint(int);
-static void motd(void);
-static void sleepexit(int eval);
+jmp_buf motdinterrupt;
+
+/*
+ * Robert Ambrose writes:
+ * A couple of my users have a problem with login processes hanging around
+ * soaking up pts's.  What they seem to hung up on is trying to write out the
+ * message 'Login timed out after %d seconds' when the connection has already
+ * been dropped.
+ * What I did was add a second timeout while trying to write the message so
+ * the process just exits if the second timeout expires.
+ */
+static void timedout2(int sig __attribute__ ((__unused__)))
+{
+	struct termios ti;
+
+	/* reset echo */
+	tcgetattr(0, &ti);
+	ti.c_lflag |= ECHO;
+	tcsetattr(0, TCSANOW, &ti);
+	exit(EXIT_SUCCESS);	/* %% */
+}
+
+static void timedout(int sig __attribute__ ((__unused__)))
+{
+	signal(SIGALRM, timedout2);
+	alarm(10);
+	/* TRANSLATORS: The standard value for %d is 60. */
+	warnx(_("timed out after %d seconds"), timeout);
+	signal(SIGALRM, SIG_IGN);
+	alarm(0);
+	timedout2(0);
+}
+
+/*
+ * This handler allows to inform a shell about signals to login. If you have
+ * (root) permissions you can kill all login childrent by one signal to login
+ * process.
+ *
+ * Also, parent who is session leader is able (before setsid() in child) to
+ * inform child when controlling tty goes away (e.g. modem hangup, SIGHUP).
+ */
+static void sig_handler(int signal)
+{
+	if (child_pid)
+		kill(-child_pid, signal);
+	else
+		got_sig = 1;
+	if (signal == SIGTERM)
+		kill(-child_pid, SIGHUP);	/* because the shell often ignores SIGTERM */
+}
+
+static void sigint(int sig __attribute__ ((__unused__)))
+{
+	longjmp(motdinterrupt, 1);
+}
+
+
+/* Should not be called from PAM code... */
+static void sleepexit(int eval)
+{
+	sleep(LOGIN_EXIT_TIMEOUT);
+	exit(eval);
+}
+
+static void motd(void)
+{
+	int fd, nchars;
+	void (*oldint) (int);
+	char tbuf[8192];
+
+	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+		return;
+	oldint = signal(SIGINT, sigint);
+	if (setjmp(motdinterrupt) == 0)
+		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
+			if (write(fileno(stdout), tbuf, nchars)) {
+				;	/* glibc warn_unused_result */
+			}
+		}
+	signal(SIGINT, oldint);
+	close(fd);
+}
 
 /*
  * Nice and simple code provided by Linus Torvalds 16-Feb-93
@@ -337,23 +415,6 @@ static void log_btmp(struct login_context *cxt)
 	updwtmp(_PATH_BTMP, &ut);
 }
 
-/*
- * This handler allows to inform a shell about signals to login. If you have
- * (root) permissions you can kill all login childrent by one signal to login
- * process.
- *
- * Also, parent who is session leader is able (before setsid() in child) to
- * inform child when controlling tty goes away (e.g. modem hangup, SIGHUP).
- */
-static void sig_handler(int signal)
-{
-	if (child_pid)
-		kill(-child_pid, signal);
-	else
-		got_sig = 1;
-	if (signal == SIGTERM)
-		kill(-child_pid, SIGHUP);	/* because the shell often ignores SIGTERM */
-}
 
 #ifdef HAVE_LIBAUDIT
 static void log_audit(struct login_context *cxt, int status)
@@ -1255,67 +1316,4 @@ int main(int argc, char **argv)
 	exit(EXIT_SUCCESS);
 }
 
-/*
- * Robert Ambrose writes:
- * A couple of my users have a problem with login processes hanging around
- * soaking up pts's.  What they seem to hung up on is trying to write out the
- * message 'Login timed out after %d seconds' when the connection has already
- * been dropped.
- * What I did was add a second timeout while trying to write the message so
- * the process just exits if the second timeout expires.
- */
-static void timedout2(int sig __attribute__ ((__unused__)))
-{
-	struct termios ti;
-
-	/* reset echo */
-	tcgetattr(0, &ti);
-	ti.c_lflag |= ECHO;
-	tcsetattr(0, TCSANOW, &ti);
-	exit(EXIT_SUCCESS);	/* %% */
-}
 
-static void timedout(int sig __attribute__ ((__unused__)))
-{
-	signal(SIGALRM, timedout2);
-	alarm(10);
-	/* TRANSLATORS: The standard value for %d is 60. */
-	warnx(_("timed out after %d seconds"), timeout);
-	signal(SIGALRM, SIG_IGN);
-	alarm(0);
-	timedout2(0);
-}
-
-jmp_buf motdinterrupt;
-
-static void motd(void)
-{
-	int fd, nchars;
-	void (*oldint) (int);
-	char tbuf[8192];
-
-	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
-		return;
-	oldint = signal(SIGINT, sigint);
-	if (setjmp(motdinterrupt) == 0)
-		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
-			if (write(fileno(stdout), tbuf, nchars)) {
-				;	/* glibc warn_unused_result */
-			}
-		}
-	signal(SIGINT, oldint);
-	close(fd);
-}
-
-static void sigint(int sig __attribute__ ((__unused__)))
-{
-	longjmp(motdinterrupt, 1);
-}
-
-
-/* Should not be called from PAM code... */
-static void sleepexit(int eval)
-{
-	sleep(LOGIN_EXIT_TIMEOUT);
-	exit(eval);
-}
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 33/49] login: remove unnecessary variables
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (31 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 32/49] login: move signal stuff to the one place Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 34/49] login: host{name,address} initialization refactoring Karel Zak
                     ` (15 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index ffde1af..fba8fdd 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1041,10 +1041,8 @@ static void init_environ(struct login_context *cxt)
 
 int main(int argc, char **argv)
 {
-	extern int optind;
-	extern char *optarg, **environ;
-	register int ch;
-	register char *p;
+	int c;
+	char *p;
 	int cnt;
 	char *domain;
 	char tbuf[PATH_MAX + 2];
@@ -1083,8 +1081,8 @@ int main(int argc, char **argv)
 	gethostname(tbuf, sizeof(tbuf));
 	domain = strchr(tbuf, '.');
 
-	while ((ch = getopt(argc, argv, "fh:p")) != -1)
-		switch (ch) {
+	while ((c = getopt(argc, argv, "fh:p")) != -1)
+		switch (c) {
 		case 'f':
 			cxt.noauth = 1;
 			break;
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 34/49] login: host{name,address} initialization refactoring
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (32 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 33/49] login: remove unnecessary variables Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 35/49] tests: cleanup islocal test Karel Zak
                     ` (14 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   83 ++++++++++++++++++++++++++------------------------
 1 files changed, 43 insertions(+), 40 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index fba8fdd..5f5313f 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1039,13 +1039,50 @@ static void init_environ(struct login_context *cxt)
 		putenv(env[i]);
 }
 
+/*
+ * Called for -h option, initialize cxt->{hostname,hostaddress}
+ */
+static void init_remote_info(struct login_context *cxt, char *remotehost)
+{
+	char host[MAXHOSTNAMELEN + 1];
+	char *domain = NULL, *p;
+	struct addrinfo hints, *info = NULL;
+
+	cxt->remote = 1;
+
+	if (gethostname(host, sizeof(host)) == 0)
+		domain = strchr(host, '.');
+
+	if (domain && (p = strchr(remotehost, '.')) && strcasecmp(p, domain) == 0)
+		*p = '\0';
+
+	cxt->hostname = xstrdup(remotehost);
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_ADDRCONFIG;
+	cxt->hostaddress[0] = 0;
+
+	if (getaddrinfo(cxt->hostname, NULL, &hints, &info) == 0 && info) {
+		if (info->ai_family == AF_INET) {
+			struct sockaddr_in *sa =
+				    (struct sockaddr_in *) info->ai_addr;
+
+			memcpy(cxt->hostaddress, &(sa->sin_addr), sizeof(sa->sin_addr));
+
+		} else if (info->ai_family == AF_INET6) {
+			struct sockaddr_in6 *sa =
+				     (struct sockaddr_in6 *) info->ai_addr;
+
+			memcpy(cxt->hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr));
+		}
+		freeaddrinfo(info);
+	}
+}
+
 int main(int argc, char **argv)
 {
 	int c;
-	char *p;
 	int cnt;
-	char *domain;
-	char tbuf[PATH_MAX + 2];
 	char *childArgv[10];
 	char *buff;
 	int childArgc = 0;
@@ -1078,9 +1115,6 @@ int main(int argc, char **argv)
 	 * -h is used by other servers to pass the name of the remote
 	 *    host to login so that it may be placed in utmp and wtmp
 	 */
-	gethostname(tbuf, sizeof(tbuf));
-	domain = strchr(tbuf, '.');
-
 	while ((c = getopt(argc, argv, "fh:p")) != -1)
 		switch (c) {
 		case 'f':
@@ -1093,40 +1127,7 @@ int main(int argc, char **argv)
 					_("login: -h for super-user only.\n"));
 				exit(EXIT_FAILURE);
 			}
-			cxt.remote = 1;
-			if (domain && (p = strchr(optarg, '.')) &&
-			    strcasecmp(p, domain) == 0)
-				*p = 0;
-
-			cxt.hostname = xstrdup(optarg);
-			{
-				struct addrinfo hints, *info = NULL;
-
-				memset(&hints, 0, sizeof(hints));
-				hints.ai_flags = AI_ADDRCONFIG;
-
-				cxt.hostaddress[0] = 0;
-
-				if (getaddrinfo(cxt.hostname, NULL, &hints, &info)
-				    == 0 && info) {
-					if (info->ai_family == AF_INET) {
-						struct sockaddr_in *sa =
-						    (struct sockaddr_in *)info->
-						    ai_addr;
-						memcpy(cxt.hostaddress,
-						       &(sa->sin_addr),
-						       sizeof(sa->sin_addr));
-					} else if (info->ai_family == AF_INET6) {
-						struct sockaddr_in6 *sa =
-						    (struct sockaddr_in6 *)
-						    info->ai_addr;
-						memcpy(cxt.hostaddress,
-						       &(sa->sin6_addr),
-						       sizeof(sa->sin6_addr));
-					}
-					freeaddrinfo(info);
-				}
-			}
+			init_remote_info(&cxt, optarg);
 			break;
 
 		case 'p':
@@ -1294,6 +1295,8 @@ int main(int argc, char **argv)
 		childArgv[childArgc++] = "-c";
 		childArgv[childArgc++] = buff;
 	} else {
+		char tbuf[PATH_MAX + 2], *p;
+
 		tbuf[0] = '-';
 		xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ?
 				    p + 1 : pwd->pw_shell), sizeof(tbuf) - 1);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 35/49] tests: cleanup islocal test
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (33 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 34/49] login: host{name,address} initialization refactoring Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 36/49] login: add login.defs code and tests Karel Zak
                     ` (13 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/.gitignore  |    2 +-
 login-utils/Makefile.am |    7 +++----
 login-utils/islocal.c   |    6 +++---
 tests/commands.sh.in    |    3 ++-
 tests/ts/login/islocal  |    2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/login-utils/.gitignore b/login-utils/.gitignore
index 31af9d4..17b6f09 100644
--- a/login-utils/.gitignore
+++ b/login-utils/.gitignore
@@ -1,4 +1,4 @@
-islocal_test
+test_islocal
 chfn
 chsh
 login
diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index a07279e..a5909a6 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -65,7 +65,6 @@ install-exec-hook::
 
 endif
 
-noinst_PROGRAMS = islocal_test
-islocal_test_SOURCES = islocal.c
-islocal_test_CPPFLAGS = -DMAIN_TEST_ISLOCAL $(AM_CPPFLAGS)
-
+noinst_PROGRAMS = test_islocal
+test_islocal_SOURCES = islocal.c
+test_islocal_CPPFLAGS = -DTEST_PROGRAM $(AM_CPPFLAGS)
diff --git a/login-utils/islocal.c b/login-utils/islocal.c
index 39a74c6..e0a3d76 100644
--- a/login-utils/islocal.c
+++ b/login-utils/islocal.c
@@ -92,12 +92,12 @@ is_local(const char *user)
 	}
 }
 
-#if MAIN_TEST_ISLOCAL
+#ifdef TEST_PROGRAM
 int
 main (int argc, char *argv[])
 {
-	if (argc < 2) {
-		fprintf(stderr, "No test passwd file was specified.\n");
+	if (argc <= 2) {
+		fprintf(stderr, "usage: %s <passwdfile> <username> [...]\n", argv[0]);
 		return 1;
 	} else {
 		int i;
diff --git a/tests/commands.sh.in b/tests/commands.sh.in
index 462a4f5..63c146f 100644
--- a/tests/commands.sh.in
+++ b/tests/commands.sh.in
@@ -24,6 +24,8 @@ TS_HELPER_LIBMOUNT_UPDATE="$top_builddir/libmount/src/test_tab_update"
 TS_HELPER_LIBMOUNT_CONTEXT="$top_builddir/libmount/src/test_context"
 TS_HELPER_LIBMOUNT_TABDIFF="$top_builddir/libmount/src/test_tab_diff"
 
+TS_HELPER_ISLOCAL="$top_builddir/login-utils/test_islocal"
+
 # TODO: use partx
 TS_HELPER_PARTITIONS="$top_builddir/libblkid/samples/partitions"
 
@@ -55,7 +57,6 @@ TS_CMD_LOOK=${TS_CMD_LOOK-"$top_builddir/misc-utils/look"}
 TS_CMD_CAL=${TS_CMD_CAL-"$top_builddir/misc-utils/cal"}
 TS_CMD_SCRIPT=${TS_CMD_SCRIPT-"$top_builddir/term-utils/script"}
 
-TS_CMD_ISLOCAL=${TS_CMD_ISLOCAL-"$top_builddir/login-utils/islocal_test"}
 
 TS_CMD_HWCLOCK=${TS_CMD_HWCLOCK-"$top_builddir/hwclock/hwclock"}
 TS_CMD_LSCPU=${TS_CMD_LSCPU-"$top_builddir/sys-utils/lscpu"}
diff --git a/tests/ts/login/islocal b/tests/ts/login/islocal
index ba23857..c25da6a 100755
--- a/tests/ts/login/islocal
+++ b/tests/ts/login/islocal
@@ -21,7 +21,7 @@ TS_DESC="islocal"
 . $TS_TOPDIR/functions.sh
 ts_init "$*"
 
-$TS_CMD_ISLOCAL "$TS_SELF/islocal.data" root nobody "" youngman youngman2 \
+$TS_HELPER_ISLOCAL "$TS_SELF/islocal.data" root nobody "" youngman youngman2 \
     abcdefghx nobo long rot al malformed \
     nonl znobody >> $TS_OUTPUT
 ts_finalize
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 36/49] login: add login.defs code and tests
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (34 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 35/49] tests: cleanup islocal test Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 37/49] tests: remove obsolete checktty test Karel Zak
                     ` (12 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

The new logindefs.c file contains /etc/login.defs parser and functions
for searching in the list of the login default variables. The patch
also contains a new regression test for the code.

Based on pam_login-4.0 from Suse.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 include/pathnames.h            |    2 +
 login-utils/.gitignore         |    1 +
 login-utils/Makefile.am        |    5 +-
 login-utils/logindefs.c        |  246 ++++++++++++++++++++++++++++++++++++++++
 login-utils/logindefs.h        |    9 ++
 tests/commands.sh.in           |    1 +
 tests/expected/login/logindefs |   14 +++
 tests/ts/login/logindefs       |   24 ++++
 tests/ts/login/logindefs.data  |   16 +++
 9 files changed, 317 insertions(+), 1 deletions(-)
 create mode 100644 login-utils/logindefs.c
 create mode 100644 login-utils/logindefs.h
 create mode 100644 tests/expected/login/logindefs
 create mode 100755 tests/ts/login/logindefs
 create mode 100644 tests/ts/login/logindefs.data

diff --git a/include/pathnames.h b/include/pathnames.h
index 1a54a03..07912bc 100644
--- a/include/pathnames.h
+++ b/include/pathnames.h
@@ -72,6 +72,8 @@
 /* used in term-utils/agetty.c */
 #define _PATH_ISSUE		"/etc/issue"
 
+#define _PATH_LOGINDEFS		"/etc/login.defs"
+
 /* used in misc-utils/look.c */
 #define _PATH_WORDS             "/usr/share/dict/words"
 #define _PATH_WORDS_ALT         "/usr/share/dict/web2"
diff --git a/login-utils/.gitignore b/login-utils/.gitignore
index 17b6f09..d3093bf 100644
--- a/login-utils/.gitignore
+++ b/login-utils/.gitignore
@@ -1,4 +1,5 @@
 test_islocal
+test_logindefs
 chfn
 chsh
 login
diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index a5909a6..84036fc 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -65,6 +65,9 @@ install-exec-hook::
 
 endif
 
-noinst_PROGRAMS = test_islocal
+noinst_PROGRAMS = test_islocal test_logindefs
 test_islocal_SOURCES = islocal.c
 test_islocal_CPPFLAGS = -DTEST_PROGRAM $(AM_CPPFLAGS)
+
+test_logindefs_SOURCES = logindefs.c logindefs.h
+test_logindefs_CPPFLAGS = -DTEST_PROGRAM $(AM_CPPFLAGS)
diff --git a/login-utils/logindefs.c b/login-utils/logindefs.c
new file mode 100644
index 0000000..27017c4
--- /dev/null
+++ b/login-utils/logindefs.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
+ * Author: Thorsten Kukuk <kukuk@suse.de>
+ *
+ * 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 any existing copyright
+ *    notice, and this entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ *
+ * 2. Redistributions in binary form must reproduce all prior and current
+ *    copyright notices, this list of conditions, and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *
+ * 3. The name of any author may not be used to endorse or promote
+ *    products derived from this software without their specific prior
+ *   written permission.
+ */
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <sys/syslog.h>
+
+#include "c.h"
+#include "nls.h"
+#include "xalloc.h"
+#include "pathnames.h"
+#include "logindefs.h"
+
+struct item {
+	char *name;		/* name of the option.  */
+	char *value;		/* value of the option.  */
+	char *path;		/* name of config file for this option.  */
+
+	struct item *next;	/* pointer to next option.  */
+};
+
+static struct item *list = NULL;
+
+void free_getlogindefs_data(void)
+{
+	struct item *ptr;
+
+	ptr = list;
+	while (ptr) {
+		struct item *tmp = ptr->next;
+
+		free(ptr->path);
+		free(ptr->name);
+		free(ptr->value);
+		free(ptr);
+		ptr = tmp;
+	}
+
+	list = NULL;
+}
+
+static void store(const char *name, const char *value, const char *path)
+{
+	struct item *new = xmalloc(sizeof(struct item));
+
+	if (!name)
+		abort();
+
+	new->name = xstrdup(name);
+	new->value = value && *value ? xstrdup(value) : NULL;
+	new->path = xstrdup(path);
+	new->next = list;
+	list = new;
+}
+
+
+static void load_defaults(const char *filename)
+{
+	FILE *f;
+	char buf[BUFSIZ];
+
+	f = fopen(filename, "r");
+	if (!f)
+		return;
+
+	while (fgets(buf, sizeof(buf), f)) {
+
+		char *p, *name, *data = NULL;
+
+		if (*buf == '#' || *buf == '\n')
+			continue;			/* only comment or empty line */
+
+		p = strchr(buf, '#');
+		if (p)
+			*p = '\0';
+		else {
+			size_t n = strlen(buf);
+			if (n && *(buf + n - 1) == '\n')
+				*(buf + n - 1) = '\0';
+		}
+
+		if (!*buf)
+			continue;			/* empty line */
+
+		/* ignore space at begin of the line */
+		name = buf;
+		while (*name && isspace((unsigned) *name))
+			name++;
+
+		/* go to the end of the name */
+		data = name;
+		while (*data && !(isspace((unsigned) *data) || *data == '='))
+			data++;
+		if (data > name && *data)
+			*data++ = '\0';
+
+		if (!*name || data == name)
+			continue;
+
+		/* go to the begin of the value */
+		while (*data && (isspace((unsigned) *data) || *data == '=' || *data == '"'))
+			 data++;
+
+		/* remove space at the end of the value */
+		p = data + strlen(data);
+		if (p > data)
+			p--;
+		while (p > data && (isspace((unsigned) *p) || *p == '"'))
+			*p-- = '\0';
+
+		store(name, data, filename);
+	}
+
+	fclose(f);
+}
+
+static struct item *search(const char *name)
+{
+	struct item *ptr;
+
+	if (!list)
+		load_defaults(_PATH_LOGINDEFS);
+
+	ptr = list;
+	while (ptr != NULL) {
+		if (strcasecmp(name, ptr->name) == 0)
+			return ptr;
+		ptr = ptr->next;
+	}
+
+	return NULL;
+}
+
+static const char *search_config(const char *name)
+{
+	struct item *ptr;
+
+	ptr = list;
+	while (ptr != NULL) {
+		if (strcasecmp(name, ptr->name) == 0)
+			return ptr->path;
+		ptr = ptr->next;
+	}
+
+	return NULL;
+}
+
+int getlogindefs_bool(const char *name, int dflt)
+{
+	struct item *ptr= search(name);
+	return ptr && ptr->value ? (strcasecmp(ptr->value, "yes") == 0) : dflt;
+}
+
+long getlogindefs_num(const char *name, long dflt)
+{
+	struct item *ptr = search(name);
+	char *end = NULL;
+	long retval;
+
+	if (!ptr || !ptr->value)
+		return dflt;
+
+	errno = 0;
+	retval = strtol(ptr->value, &end, 0);
+	if (end && *end == '\0' && !errno)
+		return retval;
+
+	syslog(LOG_NOTICE, _("%s: %s contains invalid numerical value: %s"),
+		search_config(name), name, ptr->value);
+	return dflt;
+}
+
+/*
+ * Returns:
+ *	@dflt		if @name not found
+ *	""		(empty string) if found, but value not defined
+ *	"string"	if found
+ */
+const char *getlogindefs_str(const char *name, const char *dflt)
+{
+	struct item *ptr = search(name);
+
+	if (!ptr)
+		return dflt;
+	if (!ptr->value)
+		return "";
+	return ptr->value;
+}
+
+
+#ifdef TEST_PROGRAM
+int main(int argc, char *argv[])
+{
+	char *name, *type;
+
+	if (argc <= 1)
+		errx(EXIT_FAILURE, "usage: %s <filename> "
+				  "[<str|num|bool> <valname>]", argv[0]);
+
+	load_defaults(argv[1]);
+
+	if (argc != 4) {			/* list all */
+		struct item *ptr;
+
+		for (ptr = list; ptr; ptr = ptr->next)
+			printf("%s: $%s: '%s'\n", ptr->path, ptr->name, ptr->value);
+
+		return EXIT_SUCCESS;
+	}
+
+	type = argv[2];
+	name = argv[3];
+
+	if (strcmp(type, "str") == 0)
+		printf("$%s: '%s'\n", name, getlogindefs_str(name, "DEFAULT"));
+	else if (strcmp(type, "num") == 0)
+		printf("$%s: '%ld'\n", name, getlogindefs_num(name, 0));
+	else if (strcmp(type, "bool") == 0)
+		printf("$%s: '%s'\n", name, getlogindefs_bool(name, 0) ? "Y" : "N");
+
+	return EXIT_SUCCESS;
+}
+#endif
diff --git a/login-utils/logindefs.h b/login-utils/logindefs.h
new file mode 100644
index 0000000..37d19e1
--- /dev/null
+++ b/login-utils/logindefs.h
@@ -0,0 +1,9 @@
+#ifndef UTIL_LINUX_LOGINDEFS_H
+#define UTIL_LINUX_LOGINDEFS_H
+
+extern int getlogindefs_bool(const char *name, int dflt);
+extern long getlogindefs_num(const char *name, long dflt);
+extern const char *getlogindefs_str(const char *name, const char *dflt);
+extern void free_getlogindefs_data(void);
+
+#endif /* UTIL_LINUX_LOGINDEFS_H */
diff --git a/tests/commands.sh.in b/tests/commands.sh.in
index 63c146f..4695e8a 100644
--- a/tests/commands.sh.in
+++ b/tests/commands.sh.in
@@ -25,6 +25,7 @@ TS_HELPER_LIBMOUNT_CONTEXT="$top_builddir/libmount/src/test_context"
 TS_HELPER_LIBMOUNT_TABDIFF="$top_builddir/libmount/src/test_tab_diff"
 
 TS_HELPER_ISLOCAL="$top_builddir/login-utils/test_islocal"
+TS_HELPER_LOGINDEFS="$top_builddir/login-utils/test_logindefs"
 
 # TODO: use partx
 TS_HELPER_PARTITIONS="$top_builddir/libblkid/samples/partitions"
diff --git a/tests/expected/login/logindefs b/tests/expected/login/logindefs
new file mode 100644
index 0000000..aca2a1f
--- /dev/null
+++ b/tests/expected/login/logindefs
@@ -0,0 +1,14 @@
+logindefs.data: $END: 'the is end'
+logindefs.data: $EMPTY: '(null)'
+logindefs.data: $CRAZY3: 'FoooBaaar'
+logindefs.data: $CRAZY2: 'fooBar'
+logindefs.data: $CRAZY1: 'this is crazy format'
+logindefs.data: $BOOLEAN: 'yEs'
+logindefs.data: $NUMBER: '123456'
+logindefs.data: $STRING: 'this_is_string'
+logindefs.data: $HELLO_WORLD: 'hello world!'
+$STRING: 'this_is_string'
+$NUMBER: '123456'
+$BOOLEAN: 'Y'
+$EMPTY: ''
+$UNKNOWN: 'DEFAULT'
diff --git a/tests/ts/login/logindefs b/tests/ts/login/logindefs
new file mode 100755
index 0000000..10caed7
--- /dev/null
+++ b/tests/ts/login/logindefs
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+#
+# This file is part of util-linux.
+#
+TS_TOPDIR="$(dirname $0)/../.."
+TS_DESC="defs"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+# list all items
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" | sed 's:'$TS_SELF'/::g' >> $TS_OUTPUT
+
+# search
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" str STRING >> $TS_OUTPUT
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" num NUMBER >> $TS_OUTPUT
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" bool BOOLEAN >> $TS_OUTPUT
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" str EMPTY >> $TS_OUTPUT
+
+$TS_HELPER_LOGINDEFS "$TS_SELF/logindefs.data" str UNKNOWN >> $TS_OUTPUT
+
+ts_finalize
diff --git a/tests/ts/login/logindefs.data b/tests/ts/login/logindefs.data
new file mode 100644
index 0000000..b899ff7
--- /dev/null
+++ b/tests/ts/login/logindefs.data
@@ -0,0 +1,16 @@
+#
+# this is /etc/login.defs sample
+#
+
+HELLO_WORLD	"hello world!"
+STRING		this_is_string		# another comment
+NUMBER		123456
+BOOLEAN		yEs
+
+CRAZY1 = "this is crazy format"
+CRAZY2=fooBar
+CRAZY3    FoooBaaar
+
+EMPTY
+
+END	"the is end"
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 37/49] tests: remove obsolete checktty test
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (35 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 36/49] login: add login.defs code and tests Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 38/49] login: remove obsolete info from man page Karel Zak
                     ` (11 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 tests/expected/login/checktty |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)
 delete mode 100644 tests/expected/login/checktty

diff --git a/tests/expected/login/checktty b/tests/expected/login/checktty
deleted file mode 100644
index 2e1b2c1..0000000
--- a/tests/expected/login/checktty
+++ /dev/null
@@ -1,8 +0,0 @@
-hnmatch() on 130.225.16.0/255.255.254.0     <-- 130.225.16.1   : match
-hnmatch() on 130.225.16.0/255.255.254.0     <-- 10.20.30.1     : mismatch
-hnmatch() on 130.225.0.0/255.254.0.0        <-- 130.225.16.1   : match
-hnmatch() on 130.225.0.0/255.254.0.0        <-- 130.225.17.1   : match
-hnmatch() on 130.225.0.0/255.254.0.0        <-- 150.160.170.180: mismatch
-hnmatch() on [3ffe:505:2:1::]/64            <-- 3ffe:505:2:1:: : match
-hnmatch() on [3ffe:505:2:1::]/64            <-- 3ffe:505:2:2:: : mismatch
-hnmatch() on [3ffe:505:2:1::]/64            <-- 3ffe:505:2:1:ffff:ffff::: match
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 38/49] login: remove obsolete info from man page
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (36 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 37/49] tests: remove obsolete checktty test Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 39/49] login: rewrite motd(), use MOTD_FILE from login.defs Karel Zak
                     ` (10 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |  301 ++++++++++-----------------------------------------
 1 files changed, 60 insertions(+), 241 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 80fb3b3..50575cc 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -2,76 +2,67 @@
 .\" May be distributed under the GNU General Public License
 .TH LOGIN 1 "March 2009" "util-linux" "User Commands"
 .SH NAME
-login \- sign on
+login \- begin session on the system
 .SH SYNOPSIS
-.BR "login [ " name " ]"
-.br
-.B "login \-p"
-.br
-.BR "login \-h " hostname
-.br
-.BR "login \-f " name
+.B login
+[
+.BR \-p
+] [
+.BR \-h
+.IR host
+] [
+.BR \-f
+.IR username
+|
+.IR username
+]
 .SH DESCRIPTION
 .B login
 is used when signing onto a system.
-
-If an argument is not given,
+If no argument is given,
 .B login
 prompts for the username.
 
-If the user is
-.I not
-root, and if
-.I /etc/nologin
-exists, the contents 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 occurring on a tty listed in
-.IR /etc/securetty .
-Failures will be logged with the
-.B syslog
-facility.
-
-After these conditions have been checked, the password will be requested and
-checked (if a password is required for this username).  Ten attempts
-are allowed before
+The user is then prompted for a password, where approprate.  Echoing is
+disabled to prevent revealing the password. Only a small number of password
+failures are permitted before
 .B login
-dies, but after the first three, the response starts to get very slow.
-Login failures are reported via the
-.B syslog
-facility.  This facility is also used to report any successful root logins.
+exits and the communications link is severed.
 
-If the file
-.I .hushlogin
-exists, then a "quiet" login is performed (this disables the checking
-of mail and the printing of the last login time and message of the day).
-Otherwise, if
-.I /var/log/lastlog
-exists, the last login time is printed (and the current login is
-recorded).
+If password aging has been enabled for the account, the user may be prompted
+for a new password before proceeding. He will be forced to provide his old
+password and the new password before continuing. Please refer to
+.BR passwd (1)
+for more information.
 
-Random administrative things, such as setting the UID and GID of the
-tty are performed.  The TERM environment variable is preserved, if it
-exists (other environment variables are preserved if the
-.B \-p
-option is used).  Then the HOME, PATH, SHELL, TERM, MAIL, and LOGNAME
-environment variables are set.  PATH defaults to
-.I /usr/local/bin:/bin:/usr/bin
+The user and group ID will be set according to their values in the
+.I /etc/passwd
+file. There is one exception if the user ID is zero: in this case,
+only the primary group ID of the account is set. This should prevent
+that the system adminitrator cannot login in case of network problems.
+The value for
+.BR $HOME ,
+.BR $SHELL ,
+.BR $PATH ,
+.BR $LOGNAME ,
+and
+.B $MAIL
+are set according to the appropriate fields in the password entry.
+.B $PATH
+defaults to
+.I /usr/local/bin:/bin:/usr/bin:.
 for normal users, and to
-.I /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-for root.  Last, if this is not a "quiet" login, the message of the
-day is printed and the file with the user's name in
-.I /var/spool/mail
-will be checked, and a message printed if it has non-zero length.
+.I /sbin:/bin:/usr/sbin:/usr/bin
+for root if not other configured.
+
+The environment variable
+.B $TERM
+will be preserved, if it exists (other environment variables are
+preserved if the
+.B \-p
+option is given) or be initialize to the terminal type on your tty
 
-The user's shell is then started.  If no shell is specified for the
+Then the user's shell is started. If no shell is specified for the
 user in
 .BR /etc/passwd ,
 then
@@ -82,7 +73,17 @@ then
 .I /
 is used (the home directory is checked for the
 .I .hushlogin
-file described above).
+file described below).
+
+If the file
+.I .hushlogin
+exists, then a "quiet" login is performed (this disables the checking
+of mail and the printing of the last login time and message of the day).
+Otherwise, if
+.I /var/log/lastlog
+exists, the last login time is printed (and the current login is
+recorded).
+
 .SH OPTIONS
 .TP
 .B \-p
@@ -113,188 +114,6 @@ and
 .I /etc/pam.d/remote
 ).
 
-.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
-On most modern Linux systems PAM (Pluggable Authentication Modules)
-is used. On systems that do not use PAM, 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
-addresses 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
-.IP o
-An range of IPv6 addresses, written @[n:n:n:n:n:n:n:n]/m is interpreted as a
-[net]/prefixlen pair. An IPv6 host address is matched if prefixlen bits of
-net is equal to the prefixlen bits of the address.  For  example, the
-[net]/prefixlen pattern [3ffe:505:2:1::]/64 matches every address in the
-range 3ffe:505:2:1:: through 3ffe:505:2:1:ffff:ffff:ffff:ffff.
-.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 /var/run/utmp
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 39/49] login: rewrite motd(), use MOTD_FILE from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (37 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 38/49] login: remove obsolete info from man page Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 40/49] login: use LOGIN_TIMEOUT " Karel Zak
                     ` (9 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Note that Suse login(1) does not use any default for MOTD_FILE, so
MOTD_FILE item in login.defs is required otherwise nothing is printed.

We use (for backward compatibility) /etc/motd as default.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/Makefile.am |    3 +-
 login-utils/login.1     |   20 +++++++++++++++++
 login-utils/login.c     |   53 +++++++++++++++++++++++++++-------------------
 3 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index 84036fc..ada4555 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -25,7 +25,8 @@ chfn_SOURCES = chfn.c $(chfn_chsh_common)
 chsh_SOURCES = chsh.c $(chfn_chsh_common)
 chfn_chsh_common = islocal.c setpwnam.c islocal.h setpwnam.h \
 	$(top_srcdir)/lib/env.c
-login_SOURCES = login.c $(top_srcdir)/lib/setproctitle.c
+login_SOURCES = login.c logindefs.c logindefs.h \
+		$(top_srcdir)/lib/setproctitle.c
 vipw_SOURCES = vipw.c setpwnam.h
 
 chfn_LDADD = $(login_ldadd_common)
diff --git a/login-utils/login.1 b/login-utils/login.1
index 50575cc..8aba16f 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -114,6 +114,26 @@ and
 .I /etc/pam.d/remote
 ).
 
+
+.SH CONFIG FILE ITEMS
+.B login
+reads the
+.IR /etc/login.defs (5)
+configuration file. Note that the configuration file could be distributed with
+another package (e.g. shadow-utils). The following configuration items are
+relevant for
+.BR login (1):
+.PP
+\fBMOTD_FILE\fR (string)
+.RS 4
+If defined, ":" delimited list of "message of the day" files to be displayed
+upon login. The default value is "/etc/motd". If the \fBMOTD_FILE\fR item is
+empty or "quiet" login is enabled then the message of the day is not displayed.
+Note that the same functionality is also provided by
+.BR pam_motd (8)
+PAM module.
+.RE
+
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 5f5313f..8431af8 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -43,7 +43,6 @@
 #include <grp.h>
 #include <pwd.h>
 #include <utmp.h>
-#include <setjmp.h>
 #include <stdlib.h>
 #include <sys/syslog.h>
 #include <sys/sysmacros.h>
@@ -52,6 +51,7 @@
 #include <lastlog.h>
 #include <security/pam_appl.h>
 #include <security/pam_misc.h>
+#include <sys/sendfile.h>
 
 #ifdef HAVE_LIBAUDIT
 # include <libaudit.h>
@@ -68,6 +68,8 @@
 #include "xalloc.h"
 #include "writeall.h"
 
+#include "logindefs.h"
+
 #define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
 #define LOGIN_MAX_TRIES        3
@@ -122,8 +124,6 @@ static int timeout = LOGIN_TIMEOUT;
 static int child_pid = 0;
 static volatile int got_sig = 0;
 
-jmp_buf motdinterrupt;
-
 /*
  * Robert Ambrose writes:
  * A couple of my users have a problem with login processes hanging around
@@ -173,12 +173,6 @@ static void sig_handler(int signal)
 		kill(-child_pid, SIGHUP);	/* because the shell often ignores SIGTERM */
 }
 
-static void sigint(int sig __attribute__ ((__unused__)))
-{
-	longjmp(motdinterrupt, 1);
-}
-
-
 /* Should not be called from PAM code... */
 static void sleepexit(int eval)
 {
@@ -186,23 +180,38 @@ static void sleepexit(int eval)
 	exit(eval);
 }
 
+/*
+ * Output the /etc/motd file
+ *
+ * motd() determines the name of a login announcement file and outputs it to
+ * the user's terminal at login time.  The MOTD_FILE configuration option is a
+ * colon-delimited list of filenames. The empty MOTD_FILE option disables motd
+ * printing at all.
+ */
 static void motd(void)
 {
-	int fd, nchars;
-	void (*oldint) (int);
-	char tbuf[8192];
+	char *motdlist, *motdfile, *cp;
+	const char *mb;
 
-	if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+	mb = getlogindefs_str("MOTD_FILE", _PATH_MOTDFILE);
+	if (!mb || !*mb)
 		return;
-	oldint = signal(SIGINT, sigint);
-	if (setjmp(motdinterrupt) == 0)
-		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) {
-			if (write(fileno(stdout), tbuf, nchars)) {
-				;	/* glibc warn_unused_result */
-			}
-		}
-	signal(SIGINT, oldint);
-	close(fd);
+
+	motdlist = xstrdup(mb);
+
+	for (cp = motdlist; (motdfile = strtok(cp, ":")); cp = NULL) {
+		struct stat st;
+		int fd;
+
+		if (stat(motdfile, &st) || !st.st_size)
+			continue;
+		fd = open(motdfile, O_RDONLY, 0);
+		if (fd < 0)
+			continue;
+
+		sendfile(fileno(stdout), fd, NULL, st.st_size);
+		close(fd);
+	}
 }
 
 /*
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 40/49] login: use LOGIN_TIMEOUT from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (38 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 39/49] login: rewrite motd(), use MOTD_FILE from login.defs Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 41/49] login: use FAIL_DELAY " Karel Zak
                     ` (8 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    5 +++++
 login-utils/login.c |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 8aba16f..ef71539 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -133,6 +133,11 @@ Note that the same functionality is also provided by
 .BR pam_motd (8)
 PAM module.
 .RE
+.PP
+\fBLOGIN_TIMEOUT\fR (number)
+.RS 4
+Max time in seconds for login. The default value is 60.
+.RE
 
 .SH FILES
 .nf
diff --git a/login-utils/login.c b/login-utils/login.c
index 8431af8..9822d9a 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1105,6 +1105,8 @@ int main(int argc, char **argv)
 		.conv = { misc_conv, NULL }	/* PAM conversation function */
 	};
 
+	timeout = getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT);
+
 	signal(SIGALRM, timedout);
 	siginterrupt(SIGALRM, 1);	/* we have to interrupt syscalls like ioclt() */
 	alarm((unsigned int)timeout);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 41/49] login: use FAIL_DELAY from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (39 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 40/49] login: use LOGIN_TIMEOUT " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 42/49] login: use TTYPERM " Karel Zak
                     ` (7 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    7 ++++++-
 login-utils/login.c |    2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index ef71539..8cb2450 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -138,7 +138,12 @@ PAM module.
 .RS 4
 Max time in seconds for login. The default value is 60.
 .RE
-
+.PP
+\fBFAIL_DELAY\fR (number)
+.RS 4
+Delay in seconds before being allowed another attempt after a login failure.
+The default value is 5.
+.RE
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 9822d9a..a70ce56 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -176,7 +176,7 @@ static void sig_handler(int signal)
 /* Should not be called from PAM code... */
 static void sleepexit(int eval)
 {
-	sleep(LOGIN_EXIT_TIMEOUT);
+	sleep(getlogindefs_num("FAIL_DELAY", LOGIN_EXIT_TIMEOUT));
 	exit(eval);
 }
 
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 42/49] login: use TTYPERM from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (40 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 41/49] login: use FAIL_DELAY " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 43/49] login: use TTYGROUP " Karel Zak
                     ` (6 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    6 ++++++
 login-utils/login.c |   18 +++++++++++-------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 8cb2450..1d3ae1a 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -144,6 +144,12 @@ Max time in seconds for login. The default value is 60.
 Delay in seconds before being allowed another attempt after a login failure.
 The default value is 5.
 .RE
+.PP
+\fBTTYPERM\fR (string)
+.RS 4
+The terminal permissions. The default value is 0600.
+.RE
+
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index a70ce56..857240d 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -92,6 +92,7 @@ struct login_context {
 	const char	*tty_path;	/* ttyname() return value */
 	const char	*tty_name;	/* tty_path without /dev prefix */
 	const char	*tty_number;	/* end of the tty_path */
+	mode_t		tty_mode;	/* chmod() mode */
 
 	char		*username;	/* from command line or PAM */
 
@@ -273,20 +274,20 @@ static void chown_tty(struct login_context *cxt)
 
 	if (fchown(0, uid, gid))				/* tty */
 		chown_err(cxt->tty_name, uid, gid);
-	if (fchmod(0, TTY_MODE))
-		chmod_err(cxt->tty_name, TTY_MODE);
+	if (fchmod(0, cxt->tty_mode))
+		chmod_err(cxt->tty_name, cxt->tty_mode);
 
 #ifdef LOGIN_CHOWN_VCS
 	if (is_consoletty(0)) {
 		if (chown(cxt->vcs, uid, gid))			/* vcs */
 			chown_err(cxt->vcs, uid, gid);
-		if (chmod(cxt->vcs, TTY_MODE))
-			chmod_err(cxt->vcs, TTY_MODE);
+		if (chmod(cxt->vcs, cxt->tty_mode))
+			chmod_err(cxt->vcs, cxt->tty_mode);
 
 		if (chown(cxt->vcsa, uid, gid))			/* vcsa */
 			chown_err(cxt->vcsa, uid, gid);
-		if (chmod(cxt->vcsa, TTY_MODE))
-			chmod_err(cxt->vcsa, TTY_MODE);
+		if (chmod(cxt->vcsa, cxt->tty_mode))
+			chmod_err(cxt->vcsa, cxt->tty_mode);
 	}
 #endif
 }
@@ -300,6 +301,8 @@ static void init_tty(struct login_context *cxt)
 	struct stat st;
 	struct termios tt, ttt;
 
+	cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
+
 	cxt->tty_path = ttyname(0);		/* libc calls istty() here */
 
 	/*
@@ -341,7 +344,7 @@ static void init_tty(struct login_context *cxt)
 	ttt = tt;
 	ttt.c_cflag &= ~HUPCL;
 
-	if ((fchown(0, 0, 0) || fchmod(0, TTY_MODE)) && errno != EROFS) {
+	if ((fchown(0, 0, 0) || fchmod(0, cxt->tty_mode)) && errno != EROFS) {
 
 		syslog(LOG_ERR, _("FATAL: %s: change permissions failed: %m"),
 				cxt->tty_path);
@@ -1101,6 +1104,7 @@ int main(int argc, char **argv)
 	struct passwd *pwd = NULL, _pwd;
 
 	struct login_context cxt = {
+		.tty_mode = TTY_MODE,		/* tty chmod() */
 		.pid = getpid(),		/* PID */
 		.conv = { misc_conv, NULL }	/* PAM conversation function */
 	};
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 43/49] login:  use TTYGROUP from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (41 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 42/49] login: use TTYPERM " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 44/49] login: use HUSHLOGIN_FILE " Karel Zak
                     ` (5 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Note that Suse login(1) does not use any default for TTYGROUP, it
means that TTYGROUP has to be explicitly defined otherwise user\'s
primary group is used.

The util-linux login(1) uses 'tty' group name as a default value.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    9 +++++++++
 login-utils/login.c |   15 +++++++++++----
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 1d3ae1a..cce4672 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -149,6 +149,15 @@ The default value is 5.
 .RS 4
 The terminal permissions. The default value is 0600.
 .RE
+.PP
+\fBTTYGROUP\fR (string)
+.RS 4
+The login tty will be owned by the
+\fBTTYGROUP\fR. The default value is 'tty'. If the \fBTTYGROUP\fR does not exist
+then the ownership of the terminal is set to the user\'s primary group.
+.SP
+The \fBTTYGROUP\fR can be either the name of a group or a numeric group identifier.
+.RE
 
 .SH FILES
 .nf
diff --git a/login-utils/login.c b/login-utils/login.c
index 857240d..3d6d73a 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -264,13 +264,20 @@ static void open_tty(const char *tty)
 
 static void chown_tty(struct login_context *cxt)
 {
-	struct group *gr;
+	const char *grname;
 	uid_t uid = cxt->pwd->pw_uid;
 	gid_t gid = cxt->pwd->pw_gid;
 
-	gr = getgrnam(TTYGRPNAME);
-	if (gr)
-		gid = gr->gr_gid;
+	grname = getlogindefs_str("TTYGROUP", TTYGRPNAME);
+	if (grname && *grname) {
+		if (*grname >= 0 && *grname <= 9)		/* group by ID */
+			gid = getlogindefs_num("TTYGROUP", gid);
+		else {						/* group by name */
+			struct group *gr = getgrnam(grname);
+			if (gr)
+				gid = gr->gr_gid;
+		}
+	}
 
 	if (fchown(0, uid, gid))				/* tty */
 		chown_err(cxt->tty_name, uid, gid);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 44/49] login:  use HUSHLOGIN_FILE from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (42 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 43/49] login: use TTYGROUP " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 45/49] login: use DEFAULT_HOME " Karel Zak
                     ` (4 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Note that Suse login(1) does not use any default for HUSHLOGIN_FILE.
We use /etc/hushlogins and ~/.hushlogin as default.

The another difference is that *empty* global (e.g. /etc/hushlogins)
means that hushed mode will be enabled for all accounts.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |   16 ++++++++++++++++
 login-utils/login.c |   15 ++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index cce4672..c72fcfa 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -158,7 +158,23 @@ then the ownership of the terminal is set to the user\'s primary group.
 .SP
 The \fBTTYGROUP\fR can be either the name of a group or a numeric group identifier.
 .RE
+.PP
+\fBHUSHLOGIN_FILE\fR (string)
+.RS 4
+If defined, this file can inhibit all the usual chatter during the login
+sequence.  If a full pathname (e.g. /etc/hushlogins) is specified, then hushed
+mode will be enabled if the user\'s name or shell are found in the file. If
+this global hush login file is empty then the hushed mode will be enabled for
+all users.
+
+If not a full pathname is specified, then hushed mode will be enabled if the
+file exists in the user\'s home directory.
 
+The default is to check "/etc/hushlogins" and if does not exist then
+"~/.hushlogin".
+
+If the \fBHUSHLOGIN_FILE\fR item is empty then all checks are disabled.
+.RE
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 3d6d73a..0464a17 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -845,6 +845,8 @@ static int effective_access(const char *path, int mode)
  *
  * The ~/.hushlogin is ignored if the global hush file exists.
  *
+ * The HUSHLOGIN_FILE login.def variable overwrites the default hush filename.
+ *
  * Note that shadow-utils login(1) does not support "a1)". The "a1)" is
  * necessary if you want to use PAM for "Last login" message.
  *
@@ -862,13 +864,24 @@ static int effective_access(const char *path, int mode)
 static int get_hushlogin_status(struct passwd *pwd)
 {
 	const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL };
+	const char *file;
 	char buf[BUFSIZ];
 	int i;
 
+	file = getlogindefs_str("HUSHLOGIN_FILE", NULL);
+	if (file) {
+		if (!*file)
+			return 0;	/* empty HUSHLOGIN_FILE defined */
+
+		files[0] = file;
+		files[1] = NULL;
+	}
+
 	for (i = 0; files[i]; i++) {
-		const char *file = files[i];
 		int ok = 0;
 
+		file = files[i];
+
 		/* Global hush-file*/
 		if (*file == '/') {
 			struct stat st;
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 45/49] login: use DEFAULT_HOME from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (43 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 44/49] login: use HUSHLOGIN_FILE " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 46/49] login: use LOG_UNKFAIL_ENAB from login.defs, improve logging Karel Zak
                     ` (3 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    8 ++++++++
 login-utils/login.c |    3 +++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index c72fcfa..ca7c4b3 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -175,6 +175,14 @@ The default is to check "/etc/hushlogins" and if does not exist then
 
 If the \fBHUSHLOGIN_FILE\fR item is empty then all checks are disabled.
 .RE
+.PP
+\fBDEFAULT_HOME\fR (boolean)
+.RS 4
+Indicate if login is allowed if we can\'t cd to the home directory. If set to
+\fIyes\fR, the user will login in the root (/) directory if it is not possible
+to cd to her home directory. The default value is 'yes'.
+.RE
+
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 0464a17..0c8cc26 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1313,6 +1313,9 @@ int main(int argc, char **argv)
 	/* wait until here to change directory! */
 	if (chdir(pwd->pw_dir) < 0) {
 		warn(_("%s: change directory failed"), pwd->pw_dir);
+
+		if (!getlogindefs_bool("DEFAULT_HOME", 1))
+			exit(0);
 		if (chdir("/"))
 			exit(EXIT_FAILURE);
 		pwd->pw_dir = "/";
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 46/49] login: use LOG_UNKFAIL_ENAB from login.defs, improve logging
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (44 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 45/49] login: use DEFAULT_HOME " Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 47/49] login: add -H option for compatibility with Suse Karel Zak
                     ` (2 subsequent siblings)
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    9 ++++++++-
 login-utils/login.c |   29 +++++++++++++++++++++++------
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index ca7c4b3..948177c 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -182,7 +182,14 @@ Indicate if login is allowed if we can\'t cd to the home directory. If set to
 \fIyes\fR, the user will login in the root (/) directory if it is not possible
 to cd to her home directory. The default value is 'yes'.
 .RE
-
+.PP
+\fBLOG_UNKFAIL_ENAB\fR (boolean)
+.RS 4
+Enable display of unknown usernames when login failures are recorded\&.
+.sp
+Note that logging unknown usernames may be a security issue if an user enter
+her password instead of her login name.
+.RE
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 0c8cc26..74f5736 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -711,12 +711,16 @@ static pam_handle_t *init_loginpam(struct login_context *cxt)
 
 static void loginpam_auth(struct login_context *cxt)
 {
-	int rc, failcount = 0;
+	int rc, failcount = 0, show_unknown;
+	const char *hostname = cxt->hostname ? cxt->hostname :
+			       cxt->tty_name ? cxt->tty_name : "<unknown>";
 	pam_handle_t *pamh = cxt->pamh;
 
 	/* if we didn't get a user on the command line, set it to NULL */
 	loginpam_get_username(pamh, &cxt->username);
 
+	show_unknown = getlogindefs_bool("LOG_UNKFAIL_ENAB", 0);
+
 	/*
 	 * There may be better ways to deal with some of these conditions, but
 	 * at least this way I don't think we'll be giving away information...
@@ -732,11 +736,19 @@ static void loginpam_auth(struct login_context *cxt)
 		(rc == PAM_CRED_INSUFFICIENT) ||
 		(rc == PAM_AUTHINFO_UNAVAIL))) {
 
-		loginpam_get_username(pamh, &cxt->username);
+		if (rc == PAM_USER_UNKNOWN && !show_unknown)
+			/*
+			 * logging unknown usernames may be a security issue if
+			 * an user enter her password instead of her login name
+			 */
+			cxt->username = NULL;
+		else
+			loginpam_get_username(pamh, &cxt->username);
 
 		syslog(LOG_NOTICE,
 		       _("FAILED LOGIN %d FROM %s FOR %s, %s"),
-		       failcount, cxt->hostname, cxt->username,
+		       failcount, hostname,
+		       cxt->username ? cxt->username : "(unknown)",
 		       pam_strerror(pamh, rc));
 
 		log_btmp(cxt);
@@ -750,17 +762,22 @@ static void loginpam_auth(struct login_context *cxt)
 
 	if (is_pam_failure(rc)) {
 
-		loginpam_get_username(pamh, &cxt->username);
+		if (rc == PAM_USER_UNKNOWN && !show_unknown)
+			cxt->username = NULL;
+		else
+			loginpam_get_username(pamh, &cxt->username);
 
 		if (rc == PAM_MAXTRIES)
 			syslog(LOG_NOTICE,
 			       _("TOO MANY LOGIN TRIES (%d) FROM %s FOR %s, %s"),
-			       failcount, cxt->hostname, cxt->username,
+			       failcount, hostname,
+			       cxt->username ? cxt->username : "(unknown)",
 			       pam_strerror(pamh, rc));
 		else
 			syslog(LOG_NOTICE,
 			       _("FAILED LOGIN SESSION FROM %s FOR %s, %s"),
-			       cxt->hostname, cxt->username,
+			       hostname,
+			       cxt->username ? cxt->username : "(unknown)",
 			       pam_strerror(pamh, rc));
 
 		log_btmp(cxt);
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 47/49] login: add -H option for compatibility with Suse
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (45 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 46/49] login: use LOG_UNKFAIL_ENAB from login.defs, improve logging Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 48/49] login: use ENV_PATH and ENV_{ROOT,SU}PATH from login.defs Karel Zak
  2011-10-17 11:15   ` [PATCH 49/49] login: cosmetic changes in docs Karel Zak
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Note that our login(1) uses hostname without domain, so:

	"foo login: "

this is compatible with the default agetty(8) behavior.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |   10 +++++++-
 login-utils/login.c |   66 +++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 948177c..1f4aa69 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -11,6 +11,8 @@ login \- begin session on the system
 .BR \-h
 .IR host
 ] [
+.BR \-H
+] [
 .BR \-f
 .IR username
 |
@@ -113,7 +115,13 @@ necessary to create a proper PAM config files (e.g.
 and 
 .I /etc/pam.d/remote
 ).
-
+.TP
+.B \-H
+Used by other servers (i.e.,
+.BR telnetd (8))
+to tell
+.B login
+that printing the hostname should be suppressed in the login: prompt.
 
 .SH CONFIG FILE ITEMS
 .B login
diff --git a/login-utils/login.c b/login-utils/login.c
index 74f5736..2d9a847 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -106,13 +106,16 @@ struct login_context {
 	char		vcsan[VCS_PATH_MAX];
 #endif
 
-	char		*hostname;
-	char		hostaddress[16];
+	char		thishost[MAXHOSTNAMELEN + 1];	/* this machine */
+	char		*thisdomain;			/* this machine domain */
+	char		*hostname;			/* remote machine */
+	char		hostaddress[16];		/* remote address */
 
 	pid_t		pid;
 	int		quiet;		/* 1 is hush file exists */
 
 	unsigned int	remote:1,	/* login -h */
+			nohost:1,	/* login -H */
 			noauth:1,	/* login -f */
 			keep_env:1;	/* login -p */
 };
@@ -181,6 +184,25 @@ static void sleepexit(int eval)
 	exit(eval);
 }
 
+const char *get_thishost(struct login_context *cxt, const char **domain)
+{
+	if (!*cxt->thishost) {
+		if (gethostname(cxt->thishost, sizeof(cxt->thishost))) {
+			if (domain)
+				*domain = NULL;
+			return NULL;
+		}
+		cxt->thishost[sizeof(cxt->thishost) -1] = '\0';
+		cxt->thisdomain = strchr(cxt->thishost, '.');
+		if (cxt->thisdomain)
+			*cxt->thisdomain++ = '\0';
+	}
+
+	if (domain)
+		*domain = cxt->thisdomain;
+	return cxt->thishost;
+}
+
 /*
  * Output the /etc/motd file
  *
@@ -663,6 +685,26 @@ static int loginpam_err(pam_handle_t *pamh, int retcode)
 
 }
 
+/*
+ * Composes "<host> login: " string; or returns "login: " is -H is given
+ */
+static const char *loginpam_get_prompt(struct login_context *cxt)
+{
+	const char *host;
+	char *prompt, *dflt_prompt = _("login: ");
+	size_t sz;
+
+	if (cxt->nohost || !(host = get_thishost(cxt, NULL)))
+		return dflt_prompt;
+
+	sz = strlen(host) + 1 + strlen(dflt_prompt) + 1;
+
+	prompt = xmalloc(sz);
+	snprintf(prompt, sz, "%s %s", host, dflt_prompt);
+
+	return prompt;
+}
+
 static pam_handle_t *init_loginpam(struct login_context *cxt)
 {
 	pam_handle_t *pamh = NULL;
@@ -697,7 +739,7 @@ static pam_handle_t *init_loginpam(struct login_context *cxt)
 	 * the "login: " prompt gets localized. Unfortunately, PAM doesn't have
 	 * an interface to specify the "Password: " string (yet).
 	 */
-	rc = pam_set_item(pamh, PAM_USER_PROMPT, _("login: "));
+	rc = pam_set_item(pamh, PAM_USER_PROMPT, loginpam_get_prompt(cxt));
 	if (is_pam_failure(rc))
 		loginpam_err(pamh, rc);
 
@@ -1093,16 +1135,16 @@ static void init_environ(struct login_context *cxt)
  */
 static void init_remote_info(struct login_context *cxt, char *remotehost)
 {
-	char host[MAXHOSTNAMELEN + 1];
-	char *domain = NULL, *p;
+	const char *domain;
+	char *p;
 	struct addrinfo hints, *info = NULL;
 
 	cxt->remote = 1;
 
-	if (gethostname(host, sizeof(host)) == 0)
-		domain = strchr(host, '.');
+	get_thishost(cxt, &domain);
 
-	if (domain && (p = strchr(remotehost, '.')) && strcasecmp(p, domain) == 0)
+	if (domain && (p = strchr(remotehost, '.')) &&
+	    strcasecmp(p + 1, domain) == 0)
 		*p = '\0';
 
 	cxt->hostname = xstrdup(remotehost);
@@ -1167,12 +1209,16 @@ int main(int argc, char **argv)
 	 * -h is used by other servers to pass the name of the remote
 	 *    host to login so that it may be placed in utmp and wtmp
 	 */
-	while ((c = getopt(argc, argv, "fh:p")) != -1)
+	while ((c = getopt(argc, argv, "fHh:p")) != -1)
 		switch (c) {
 		case 'f':
 			cxt.noauth = 1;
 			break;
 
+		case 'H':
+			cxt.nohost = 1;
+			break;
+
 		case 'h':
 			if (getuid()) {
 				fprintf(stderr,
@@ -1188,7 +1234,7 @@ int main(int argc, char **argv)
 
 		case '?':
 		default:
-			fprintf(stderr, _("usage: login [-fp] [username]\n"));
+			fprintf(stderr, _("usage: login [ -p ] [ -h host ] [ -H ] [ -f username | username ]\n"));
 			exit(EXIT_FAILURE);
 		}
 	argc -= optind;
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 48/49] login: use ENV_PATH and ENV_{ROOT,SU}PATH from login.defs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (46 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 47/49] login: add -H option for compatibility with Suse Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  2011-10-17 11:15   ` [PATCH 49/49] login: cosmetic changes in docs Karel Zak
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |   12 ++++++++++++
 login-utils/login.c |   10 +++++++++-
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 1f4aa69..54b7562 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -198,6 +198,18 @@ Enable display of unknown usernames when login failures are recorded\&.
 Note that logging unknown usernames may be a security issue if an user enter
 her password instead of her login name.
 .RE
+.PP
+\fBENV_PATH\fR (string)
+.RS 4
+If set, it will be used to define the PATH environment variable when a regular
+user login. The default value is "/usr/local/bin:/bin:/usr/bin".
+.RE
+.PP
+\fBENV_ROOTPATH\fR (string), \fBENV_SUPATH\fR (string)
+.RS 4
+If set, it will be used to define the PATH environment variable when the superuser
+login. The default value is "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin".
+.RE
 .SH FILES
 .nf
 .I /var/run/utmp
diff --git a/login-utils/login.c b/login-utils/login.c
index 2d9a847..f688307 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1111,10 +1111,18 @@ static void init_environ(struct login_context *cxt)
 	}
 
 	setenv("HOME", pwd->pw_dir, 0);	/* legal to override */
-	setenv("PATH", pwd->pw_uid ? _PATH_DEFPATH : _PATH_DEFPATH_ROOT, 1);
 	setenv("SHELL", pwd->pw_shell, 1);
 	setenv("TERM", termenv, 1);
 
+	if (pwd->pw_uid)
+		setenv("PATH", getlogindefs_str("ENV_PATH", _PATH_DEFPATH), 1);
+	else {
+		const char *x = getlogindefs_str("ENV_ROOTPATH", NULL);
+		if (!x)
+			x = getlogindefs_str("ENV_SUPATH", _PATH_DEFPATH_ROOT);
+		setenv("PATH", x, 1);
+	}
+
 	/* mailx will give a funny error msg if you forget this one */
 	len = snprintf(tmp, sizeof(tmp), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
 	if (len > 0 && (size_t) len + 1 <= sizeof(tmp))
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 49/49] login: cosmetic changes in docs
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
                     ` (47 preceding siblings ...)
  2011-10-17 11:15   ` [PATCH 48/49] login: use ENV_PATH and ENV_{ROOT,SU}PATH from login.defs Karel Zak
@ 2011-10-17 11:15   ` Karel Zak
  48 siblings, 0 replies; 54+ messages in thread
From: Karel Zak @ 2011-10-17 11:15 UTC (permalink / raw)
  To: util-linux; +Cc: Karel Zak

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.1 |    4 +++-
 login-utils/login.c |    3 +++
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/login-utils/login.1 b/login-utils/login.1
index 54b7562..d9d8333 100644
--- a/login-utils/login.1
+++ b/login-utils/login.1
@@ -219,9 +219,9 @@ login. The default value is "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin
 .I /etc/motd
 .I /etc/passwd
 .I /etc/nologin
-.I /etc/usertty
 .I /etc/pam.d/login
 .I /etc/pam.d/remote
+.I /etc/hushlogins
 .I .hushlogin
 .fi
 .SH "SEE ALSO"
@@ -254,6 +254,8 @@ Derived from BSD login 5.40 (5/9/89) by Michael Glad (glad@daimi.dk)
 for HP-UX
 .br
 Ported to Linux 0.12: Peter Orbaek (poe@daimi.aau.dk)
+.br
+Rewritten to PAM-only version by Karel Zak (kzak@redhat.com)
 .SH AVAILABILITY
 The login command is part of the util-linux package and is available from
 ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
diff --git a/login-utils/login.c b/login-utils/login.c
index f688307..afdb32e 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -4,6 +4,9 @@
  * This program is derived from 4.3 BSD software and is subject to the
  * copyright notice below.
  *
+ * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ * Rewritten to PAM-only version.
+ *
  * Michael Glad (glad@daimi.dk)
  * Computer Science Department, Aarhus University, Denmark
  * 1990-07-04
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: login: PAM-only, login.defs, -H
  2011-10-17 11:02 login: PAM-only, login.defs, -H Karel Zak
  2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
@ 2011-11-17 10:31 ` Thorsten Kukuk
  2011-11-18 12:14   ` Karel Zak
  1 sibling, 1 reply; 54+ messages in thread
From: Thorsten Kukuk @ 2011-11-17 10:31 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Ludwig Nussel

On Mon, Oct 17, Karel Zak wrote:

>  Git tree: https://karelzak@github.com/karelzak/util-linux.git branch 'login'.
>  URL: https://github.com/karelzak/util-linux/tree/login

Ok, I found one bug: pam_setcred() is only called after pam_open_session(),
but has to be called before:

--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -868,15 +868,15 @@ static void loginpam_session(struct login_context *cxt)
        int rc;
        pam_handle_t *pamh = cxt->pamh;
 
-       rc = pam_open_session(pamh, 0);
-       if (is_pam_failure(rc))
-               loginpam_err(pamh, rc);
-
        rc = pam_setcred(pamh, PAM_ESTABLISH_CRED);
        if (is_pam_failure(rc)) {
                pam_close_session(pamh, 0);
                loginpam_err(pamh, rc);
        }
+
+       rc = pam_open_session(pamh, 0);
+       if (is_pam_failure(rc))
+               loginpam_err(pamh, rc);
 }
 


Another problem with current git is:
prlimit.c: In function ‘prlimit’:
prlimit.c:142:17: error: ‘SYS_prlimit64’ undeclared (first use in this function)
prlimit.c:142:17: note: each undeclared identifier is reported only once for each function it appears in

  Thorsten

-- 
Thorsten Kukuk, Project Manager/Release Manager SLES
SUSE LINUX Products GmbH, Maxfeldstr. 5, D-90409 Nuernberg
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB 16746 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: login: PAM-only, login.defs, -H
  2011-11-17 10:31 ` login: PAM-only, login.defs, -H Thorsten Kukuk
@ 2011-11-18 12:14   ` Karel Zak
  2011-11-24  9:29     ` Ludwig Nussel
  0 siblings, 1 reply; 54+ messages in thread
From: Karel Zak @ 2011-11-18 12:14 UTC (permalink / raw)
  To: Thorsten Kukuk; +Cc: util-linux, Ludwig Nussel

On Thu, Nov 17, 2011 at 11:31:47AM +0100, Thorsten Kukuk wrote:
> On Mon, Oct 17, Karel Zak wrote:
> 
> >  Git tree: https://karelzak@github.com/karelzak/util-linux.git branch 'login'.
> >  URL: https://github.com/karelzak/util-linux/tree/login
> 
> Ok, I found one bug: pam_setcred() is only called after pam_open_session(),
> but has to be called before:

 Well, this is discussable... login(1) for years called pam_setcred()
 after pam_open_session(), but I agree it's not optional.
 
 After discussion with our PAM maintainer we decided that the best is
 probably to use PAM_ESTABLISH_CRED before and PAM_REINITIALIZE_CRED
 after pam_open_session(). This solution should be probably the most
 robust (it's probably used by openssh). 
 
 For example pam_krb5 should be ready for such usage.

 Please, git pull (or see the patch below) and test it.

> Another problem with current git is:
> prlimit.c: In function ‘prlimit’:
> prlimit.c:142:17: error: ‘SYS_prlimit64’ undeclared (first use in this function)
> prlimit.c:142:17: note: each undeclared identifier is reported only once for each function it appears in

 Fixed.

 Thanks!
    Karel

>From 34f7ea15c10fb72db73257c697156797832337c6 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Fri, 18 Nov 2011 12:26:19 +0100
Subject: [PATCH] login: improve pam_setcred() usage

Reported-by: Thorsten Kukuk <kukuk@suse.de>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/login.c |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/login-utils/login.c b/login-utils/login.c
index 93ed2d6..0d6c390 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -863,16 +863,37 @@ static void loginpam_acct(struct login_context *cxt)
 	}
 }
 
+/*
+ * Note that position of the pam_setcred() call is discussable:
+ *
+ *  - the PAM docs recommends pam_setcred() before pam_open_session()
+ *  - but the original RFC http://www.opengroup.org/rfc/mirror-rfc/rfc86.0.txt
+ *    uses pam_setcred() after pam_open_session()
+ *
+ * The old login versions (before year 2011) followed the RFC. This is probably
+ * not optimal, because there could be dependence between some session modules
+ * and user's credentials.
+ *
+ * The best is probably to follow openssh and call pam_setcred() before and
+ * after pam_open_session().                -- kzak@redhat.com (18-Nov-2011)
+ *
+ */
 static void loginpam_session(struct login_context *cxt)
 {
 	int rc;
 	pam_handle_t *pamh = cxt->pamh;
 
-	rc = pam_open_session(pamh, 0);
+	rc = pam_setcred(pamh, PAM_ESTABLISH_CRED);
 	if (is_pam_failure(rc))
 		loginpam_err(pamh, rc);
 
-	rc = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+	rc = pam_open_session(pamh, 0);
+	if (is_pam_failure(rc)) {
+		pam_setcred(cxt->pamh, PAM_DELETE_CRED);
+		loginpam_err(pamh, rc);
+	}
+
+	rc = pam_setcred(pamh, PAM_REINITIALIZE_CRED);
 	if (is_pam_failure(rc)) {
 		pam_close_session(pamh, 0);
 		loginpam_err(pamh, rc);
-- 
1.7.6.4


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: login: PAM-only, login.defs, -H
  2011-11-18 12:14   ` Karel Zak
@ 2011-11-24  9:29     ` Ludwig Nussel
  0 siblings, 0 replies; 54+ messages in thread
From: Ludwig Nussel @ 2011-11-24  9:29 UTC (permalink / raw)
  To: Karel Zak; +Cc: Thorsten Kukuk, util-linux

Karel Zak wrote:
> On Thu, Nov 17, 2011 at 11:31:47AM +0100, Thorsten Kukuk wrote:
>> On Mon, Oct 17, Karel Zak wrote:
>>
>>>  Git tree: https://karelzak@github.com/karelzak/util-linux.git branch 'login'.
>>>  URL: https://github.com/karelzak/util-linux/tree/login
>>
>> Ok, I found one bug: pam_setcred() is only called after pam_open_session(),
>> but has to be called before:
> 
>  Well, this is discussable... login(1) for years called pam_setcred()
>  after pam_open_session(), but I agree it's not optional.
>  
>  After discussion with our PAM maintainer we decided that the best is
>  probably to use PAM_ESTABLISH_CRED before and PAM_REINITIALIZE_CRED
>  after pam_open_session(). This solution should be probably the most
>  robust (it's probably used by openssh). 

Modules must work with one call before pam_open_session() as that's the
only documented and correct way. So that's what other applications such
as login managers, su etc do. IOW a module that would break due to login
using pam calls in the correct order is quite unlikely to exist at all.

cu
Ludwig

-- 
 (o_   Ludwig Nussel
 //\
 V_/_  http://www.suse.de/
SUSE LINUX Products GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB 16746 (AG Nürnberg) 

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2011-11-24  9:29 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-17 11:02 login: PAM-only, login.defs, -H Karel Zak
2011-10-17 11:14 ` [PATCH 00/49] login refactoring Karel Zak
2011-10-17 11:14   ` [PATCH 01/49] login: remove kerberos specific code Karel Zak
2011-10-17 11:14   ` [PATCH 02/49] login: remove dead code and comments Karel Zak
2011-10-17 11:14   ` [PATCH 03/49] login: move _PATH_BTMP to pathnames.h Karel Zak
2011-10-17 11:14   ` [PATCH 04/49] login: remove non-PAM code Karel Zak
2011-10-17 11:14   ` [PATCH 05/49] build-sys: require PAM for login-utils Karel Zak
2011-10-17 11:14   ` [PATCH 06/49] login: remove PAM_FAIL_CHECK and PAM_END macros Karel Zak
2011-10-17 11:14   ` [PATCH 07/49] lib: cleanup setproctitle.c Karel Zak
2011-10-17 11:14   ` [PATCH 08/49] login: cleanup begin of the login.c file Karel Zak
2011-10-17 11:14   ` [PATCH 09/49] login: remove obsolete code, clean up macros names Karel Zak
2011-10-17 11:14   ` [PATCH 10/49] login: indent -linux Karel Zak
2011-10-17 11:14   ` [PATCH 11/49] login: add struct login_context, consolidate tty code Karel Zak
2011-10-17 11:14   ` [PATCH 12/49] login: add hostname to login_context struct Karel Zak
2011-10-17 11:14   ` [PATCH 13/49] login: add pid " Karel Zak
2011-10-17 11:14   ` [PATCH 14/49] login: add username " Karel Zak
2011-10-17 11:14   ` [PATCH 15/49] login: use login_context struct in audit stuff Karel Zak
2011-10-17 11:14   ` [PATCH 16/49] login: lastlog code refactoring Karel Zak
2011-10-17 11:14   ` [PATCH 17/49] login: utmp " Karel Zak
2011-10-17 11:14   ` [PATCH 18/49] login: use getpwnam_r() rather than manually copy passwd struct Karel Zak
2011-10-17 11:14   ` [PATCH 19/49] login: tty chown.chmod refactoring Karel Zak
2011-10-17 11:14   ` [PATCH 20/49] login: use setgroups(0, NULL) for root Karel Zak
2011-10-17 11:15   ` [PATCH 21/49] login: improve hushed mode (merge suse changes) Karel Zak
2011-10-17 11:15   ` [PATCH 22/49] login: remove unused code and tests Karel Zak
2011-10-17 11:15   ` [PATCH 23/49] login: PAM initialization refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 24/49] login: PAM auth refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 25/49] login: PAM account checks refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 26/49] login: PAM session initialization refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 27/49] login: remove pam_handle_t from main() Karel Zak
2011-10-17 11:15   ` [PATCH 28/49] login: fork & session initialization refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 29/49] login: env " Karel Zak
2011-10-17 11:15   ` [PATCH 30/49] login: use xalloc.h Karel Zak
2011-10-17 11:15   ` [PATCH 31/49] login: log good logins refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 32/49] login: move signal stuff to the one place Karel Zak
2011-10-17 11:15   ` [PATCH 33/49] login: remove unnecessary variables Karel Zak
2011-10-17 11:15   ` [PATCH 34/49] login: host{name,address} initialization refactoring Karel Zak
2011-10-17 11:15   ` [PATCH 35/49] tests: cleanup islocal test Karel Zak
2011-10-17 11:15   ` [PATCH 36/49] login: add login.defs code and tests Karel Zak
2011-10-17 11:15   ` [PATCH 37/49] tests: remove obsolete checktty test Karel Zak
2011-10-17 11:15   ` [PATCH 38/49] login: remove obsolete info from man page Karel Zak
2011-10-17 11:15   ` [PATCH 39/49] login: rewrite motd(), use MOTD_FILE from login.defs Karel Zak
2011-10-17 11:15   ` [PATCH 40/49] login: use LOGIN_TIMEOUT " Karel Zak
2011-10-17 11:15   ` [PATCH 41/49] login: use FAIL_DELAY " Karel Zak
2011-10-17 11:15   ` [PATCH 42/49] login: use TTYPERM " Karel Zak
2011-10-17 11:15   ` [PATCH 43/49] login: use TTYGROUP " Karel Zak
2011-10-17 11:15   ` [PATCH 44/49] login: use HUSHLOGIN_FILE " Karel Zak
2011-10-17 11:15   ` [PATCH 45/49] login: use DEFAULT_HOME " Karel Zak
2011-10-17 11:15   ` [PATCH 46/49] login: use LOG_UNKFAIL_ENAB from login.defs, improve logging Karel Zak
2011-10-17 11:15   ` [PATCH 47/49] login: add -H option for compatibility with Suse Karel Zak
2011-10-17 11:15   ` [PATCH 48/49] login: use ENV_PATH and ENV_{ROOT,SU}PATH from login.defs Karel Zak
2011-10-17 11:15   ` [PATCH 49/49] login: cosmetic changes in docs Karel Zak
2011-11-17 10:31 ` login: PAM-only, login.defs, -H Thorsten Kukuk
2011-11-18 12:14   ` Karel Zak
2011-11-24  9:29     ` Ludwig Nussel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).