* [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