[Pkg-shadow-commits] r2737 - in upstream/trunk: . lib libmisc src
Nicolas FRANÇOIS
nekral-guest at alioth.debian.org
Tue Apr 21 22:39:14 UTC 2009
Author: nekral-guest
Date: 2009-04-21 22:39:14 +0000 (Tue, 21 Apr 2009)
New Revision: 2737
Modified:
upstream/trunk/configure.in
upstream/trunk/lib/prototypes.h
upstream/trunk/libmisc/utmp.c
upstream/trunk/src/login.c
Log:
* libmisc/utmp.c: Reworked. Get rid of Linux specific stuff. Get rid
of global utent/utxent variables. Only reuse the ut_id and maybe
the ut_host fields from utmp.
* lib/prototypes.h, libmisc/utmp.c: Removed checkutmp(),
setutmp(), setutmpx().
* lib/prototypes.h, libmisc/utmp.c: Added get_current_utmp(),
prepare_utmp(), prepare_utmpx(), setutmp(), setutmpx().
* libmisc/utmp.c (is_my_tty): Only compare the name of the utmp
line with ttyname(). (No stat of the two terminals to compare the
devices).
* libmisc/utmp.c: Use getaddrinfo() to get the address of the
host.
* configure.in: Check for getaddrinfo().
* configure.in: Use AC_CHECK_MEMBERS to check for the existence of
fields in the utmp/utmpx structures.
* configure.in: Reject systems with utmpx support but no ut_id
field in utmp. This could be fixed later if needed.
* src/login.c: Use the new utmp functions. This also simplifies
the failtmp() handling.
* src/login.c: passwd_free() renamed to pw_free() and
shadow_free() renamed to spw_free()
Modified: upstream/trunk/configure.in
===================================================================
--- upstream/trunk/configure.in 2009-04-21 22:22:08 UTC (rev 2736)
+++ upstream/trunk/configure.in 2009-04-21 22:39:14 UTC (rev 2737)
@@ -41,7 +41,7 @@
AC_CHECK_FUNCS(l64a fchmod fchown fsync futimes getgroups gethostname getspnam \
gettimeofday getusershell getutent initgroups lchown lckpwdf lstat \
lutimes memcpy memset setgroups sigaction strchr updwtmp updwtmpx innetgr \
- getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
+ getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo)
AC_SYS_LARGEFILE
dnl Checks for typedefs, structures, and compiler characteristics.
@@ -59,38 +59,32 @@
AC_HEADER_TIME
AC_STRUCT_TM
-if test "$ac_cv_header_utmp_h" = "yes"; then
- AC_CACHE_CHECK(for ut_host in struct utmp,
- ac_cv_struct_utmp_ut_host,
- AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([#include <utmp.h>],
- [struct utmp ut; char *cp = ut.ut_host;]
- )],
- [ac_cv_struct_utmp_ut_host=yes],
- [ac_cv_struct_utmp_ut_host=no]
- )
- )
-
- if test "$ac_cv_struct_utmp_ut_host" = "yes"; then
- AC_DEFINE(UT_HOST, 1, [Define if you have ut_host in struct utmp.])
- fi
-
- AC_CACHE_CHECK(for ut_user in struct utmp,
- ac_cv_struct_utmp_ut_user,
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <utmp.h>],
- [struct utmp ut; char *cp = ut.ut_user;]
- )],
- [ac_cv_struct_utmp_ut_user=yes],
- [ac_cv_struct_utmp_ut_user=no]
- )
- )
-
- if test "$ac_cv_struct_utmp_ut_user" = "no"; then
- AC_DEFINE(ut_user, ut_name,
- [Define to ut_name if struct utmp has ut_name (not ut_user).])
- fi
+AC_CHECK_MEMBERS([struct utmp.ut_type,
+ struct utmp.ut_id,
+ struct utmp.ut_name,
+ struct utmp.ut_user,
+ struct utmp.ut_host,
+ struct utmp.ut_syslen,
+ struct utmp.ut_addr,
+ struct utmp.ut_addr_v6,
+ struct utmp.ut_time,
+ struct utmp.ut_xtime,
+ struct utmp.ut_tv],,,[[#include <utmp.h>]])
+dnl There are dependencies:
+dnl If UTMPX has to be used, the utmp structure shall have a ut_id field.
+if test "$ac_cv_header_utmpx_h" = "yes" &&
+ test "$ac_cv_member_struct_utmp_ut_id" != "yes"; then
+ AC_MSG_ERROR(Systems with UTMPX and no ut_id field in the utmp structure are not supported)
fi
+AC_CHECK_MEMBERS([struct utmpx.ut_name,
+ struct utmpx.ut_host,
+ struct utmpx.ut_syslen,
+ struct utmpx.ut_addr,
+ struct utmpx.ut_addr_v6,
+ struct utmpx.ut_time,
+ struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
+
if test "$ac_cv_header_lastlog_h" = "yes"; then
AC_CACHE_CHECK(for ll_host in struct lastlog,
ac_cv_struct_lastlog_ll_host,
Modified: upstream/trunk/lib/prototypes.h
===================================================================
--- upstream/trunk/lib/prototypes.h 2009-04-21 22:22:08 UTC (rev 2736)
+++ upstream/trunk/lib/prototypes.h 2009-04-21 22:39:14 UTC (rev 2737)
@@ -345,8 +345,19 @@
extern int set_filesize_limit (int blocks);
/* utmp.c */
-extern void checkutmp (bool picky);
-extern int setutmp (const char *, const char *, const char *);
+extern struct utmp *get_current_utmp (void);
+extern struct utmp *prepare_utmp (const char *name,
+ const char *line,
+ const char *host,
+ struct utmp *ut);
+extern int setutmp (struct utmp *ut);
+#ifdef HAVE_UTMPX_H
+extern struct utmpx *prepare_utmpx (const char *name,
+ const char *line,
+ const char *host,
+ struct utmp *ut);
+extern int setutmpx (struct utmpx *utx);
+#endif
/* valid.c */
extern bool valid (const char *, const struct passwd *);
Modified: upstream/trunk/libmisc/utmp.c
===================================================================
--- upstream/trunk/libmisc/utmp.c 2009-04-21 22:22:08 UTC (rev 2736)
+++ upstream/trunk/libmisc/utmp.c 2009-04-21 22:39:14 UTC (rev 2737)
@@ -2,7 +2,7 @@
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 1999, Marek Michałkiewicz
* Copyright (c) 2001 - 2005, Tomasz Kłoczko
- * Copyright (c) 2008 , Nicolas François
+ * Copyright (c) 2008 - 2009, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,44 +37,41 @@
#include <utmp.h>
+// FIXME: disable UTMPX on Linux in configure.in
+// Maybe define an intermediate USE_UTMPX to replace HAVE_UTMPX_H,
+// which would be defined if HAVE_UTMPX_H is defined on non-Linux.
#if HAVE_UTMPX_H
#include <utmpx.h>
#endif
-#include <fcntl.h>
+#include <assert.h>
+#include <netdb.h>
#include <stdio.h>
#ident "$Id$"
-#if HAVE_UTMPX_H
-struct utmpx utxent;
-#endif
-struct utmp utent;
-#define NO_UTENT \
- _("No utmp entry. You must exec \"login\" from the lowest level \"sh\"")
-#define NO_TTY \
- _("Unable to determine your tty name.")
-
/*
* is_my_tty -- determine if "tty" is the same TTY stdin is using
*/
static bool is_my_tty (const char *tty)
{
char full_tty[200];
- struct stat by_name, by_fd;
+ static const char *tmptty = NULL;
if ('/' != *tty) {
snprintf (full_tty, sizeof full_tty, "/dev/%s", tty);
tty = full_tty;
}
- if ( (stat (tty, &by_name) != 0)
- || (fstat (STDIN_FILENO, &by_fd) != 0)) {
- return false;
+ if (NULL == tmptty) {
+ tmptty = ttyname (STDIN_FILENO);
}
- if (by_name.st_rdev != by_fd.st_rdev) {
+ if (NULL == tmptty) {
+ (void) puts (_("Unable to determine your tty name."));
+ exit (EXIT_FAILURE);
+ } else if (strcmp (tty, tmptty) != 0) {
return false;
} else {
return true;
@@ -82,36 +79,36 @@
}
/*
- * checkutmp - see if utmp file is correct for this process
+ * get_current_utmp - return the most probable utmp entry for the current
+ * session
*
- * System V is very picky about the contents of the utmp file
- * and requires that a slot for the current process exist.
- * The utmp file is scanned for an entry with the same process
- * ID. If no entry exists the process exits with a message.
+ * The utmp file is scanned for an entry with the same process ID.
+ * The line enterred by the *getty / telnetd, etc. should also match
+ * the current terminal.
*
- * The "picky" flag is for network and other logins that may
- * use special flags. It allows the pid checks to be overridden.
- * This means that getty should never invoke login with any
- * command line flags.
+ * When an entry is returned by get_current_utmp, and if the utmp
+ * structure has a ut_id field, this field should be used to update
+ * the entry information.
+ *
+ * Return NULL if no entries exist in utmp for the current process.
*/
-
-#if defined(__linux__) /* XXX */
-
-void checkutmp (bool picky)
+struct utmp *get_current_utmp (void)
{
- char *line;
struct utmp *ut;
- pid_t pid = getpid ();
+ struct utmp *ret = NULL;
setutent ();
/* First, try to find a valid utmp entry for this process. */
while ((ut = getutent ()) != NULL) {
- if ( (ut->ut_pid == pid)
- && ('\0' != ut->ut_line[0])
+ if ( (ut->ut_pid == getpid ())
+#ifdef HAVE_STRUCT_UTMP_UT_ID
&& ('\0' != ut->ut_id[0])
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
&& ( (LOGIN_PROCESS == ut->ut_type)
|| (USER_PROCESS == ut->ut_type))
+#endif
/* A process may have failed to close an entry
* Check if this entry refers to the current tty */
&& is_my_tty (ut->ut_line)) {
@@ -119,173 +116,20 @@
}
}
- /* We cannot trust the ut_line field. Prepare the new value. */
- line = ttyname (0);
- if (NULL == line) {
- (void) puts (NO_TTY);
- exit (EXIT_FAILURE);
- }
- if (strncmp (line, "/dev/", 5) == 0) {
- line += 5;
- }
-
- /* If there is one, just use it, otherwise create a new one. */
if (NULL != ut) {
- utent = *ut;
- } else {
- if (picky) {
- (void) puts (NO_UTENT);
- exit (EXIT_FAILURE);
- }
- memset ((void *) &utent, 0, sizeof utent);
- utent.ut_type = LOGIN_PROCESS;
- utent.ut_pid = pid;
- /* XXX - assumes /dev/tty?? or /dev/pts/?? */
- strncpy (utent.ut_id, line + 3, sizeof utent.ut_id);
- strcpy (utent.ut_user, "LOGIN");
- utent.ut_time = time (NULL);
+ ret = malloc (sizeof (*ret));
+ memcpy (ret, ut, sizeof (*ret));
}
- /* Sanitize / set the ut_line field */
- strncpy (utent.ut_line, line, sizeof utent.ut_line);
-
endutent ();
-}
-#elif defined(LOGIN_PROCESS)
-
-void checkutmp (bool picky)
-{
- char *line;
- struct utmp *ut;
-
-#if HAVE_UTMPX_H
- struct utmpx *utx;
-#endif
- pid_t pid = getpid ();
-
-#if HAVE_UTMPX_H
- setutxent ();
-#endif
- setutent ();
-
- if (picky) {
-#if HAVE_UTMPX_H
- while ((utx = getutxent ()) != NULL) {
- if (utx->ut_pid == pid) {
- break;
- }
- }
-
- if (NULL != utx) {
- utxent = *utx;
- }
-#endif
- while ((ut = getutent ()) != NULL) {
- if (ut->ut_pid == pid) {
- break;
- }
- }
-
- if (NULL != ut) {
- utent = *ut;
- }
-
-#if HAVE_UTMPX_H
- endutxent ();
-#endif
- endutent ();
-
- if (NULL == ut) {
- (void) puts (NO_UTENT);
- exit (EXIT_FAILURE);
- }
-#ifndef UNIXPC
-
- /*
- * If there is no ut_line value in this record, fill
- * it in by getting the TTY name and stuffing it in
- * the structure. The UNIX/PC is broken in this regard
- * and needs help ...
- */
- /* XXX: The ut_line may not match with the current tty.
- * ut_line will be set by setutmp anyway, but ut_id
- * will not be set, and the wrong utmp entry may be
- * updated. -- nekral */
-
- if (utent.ut_line[0] == '\0')
-#endif /* !UNIXPC */
- {
- line = ttyname (0);
- if (NULL == line) {
- (void) puts (NO_TTY);
- exit (EXIT_FAILURE);
- }
- if (strncmp (line, "/dev/", 5) == 0) {
- line += 5;
- }
- strncpy (utent.ut_line, line, sizeof utent.ut_line);
-#if HAVE_UTMPX_H
- strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
-#endif
- }
- } else {
- line = ttyname (0);
- if (NULL == line) {
- (void) puts (NO_TTY);
- exit (EXIT_FAILURE);
- }
- if (strncmp (line, "/dev/", 5) == 0) {
- line += 5;
- }
-
- strncpy (utent.ut_line, line, sizeof utent.ut_line);
- ut = getutline (&utent);
- if (NULL != ut) {
- strncpy (utent.ut_id, ut->ut_id, sizeof ut->ut_id);
- }
-
- strcpy (utent.ut_user, "LOGIN");
- utent.ut_pid = getpid ();
- utent.ut_type = LOGIN_PROCESS;
- utent.ut_time = time (NULL);
-#if HAVE_UTMPX_H
- strncpy (utxent.ut_line, line, sizeof utxent.ut_line);
- utx = getutxline (&utxent);
- if (NULL != utx) {
- strncpy (utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
- }
-
- strcpy (utxent.ut_user, "LOGIN");
- utxent.ut_pid = utent.ut_pid;
- utxent.ut_type = utent.ut_type;
- if (sizeof (utxent.ut_tv) == sizeof (struct timeval)) {
- gettimeofday ((struct timeval *) &utxent.ut_tv, NULL);
- } else {
- struct timeval tv;
-
- gettimeofday (&tv, NULL);
- utxent.ut_tv.tv_sec = tv.tv_sec;
- utxent.ut_tv.tv_usec = tv.tv_usec;
- }
- utent.ut_time = utxent.ut_tv.tv_sec;
-#endif
- }
-
-#if HAVE_UTMPX_H
- endutxent ();
-#endif
- endutent ();
+ return ret;
}
-#endif
-
-
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
- * don't, so we re-implement these functions if necessary. --marekm
+ * don't, so we re-implement these functions if necessary.
*/
-
#ifndef HAVE_UPDWTMP
static void updwtmp (const char *filename, const struct utmp *ut)
{
@@ -319,140 +163,293 @@
* setutmp - put a USER_PROCESS entry in the utmp file
*
* setutmp changes the type of the current utmp entry to
- * USER_PROCESS. the wtmp file will be updated as well.
+ * USER_PROCESS.
+ * The wtmp file will be updated as well.
+ *
+ * ut, as returned by get_current_utmp
+ *
+ * We reuse the ut_id and ut_host fields
+ *
+ * The returned structure shall be freed by the caller.
*/
-#if defined(__linux__) /* XXX */
-
-int setutmp (const char *name, const char unused(*line), const char unused(*host))
+/*
+ * prepare_utmp - prepare an utmp entry so that it can be logged in a
+ * utmp/wtmp file.
+ *
+ * It requires an utmp entry in input (ut) to return an entry with
+ * the right ut_id. This is typically an entry returned by
+ * get_current_utmp
+ *
+ * The ut_host field of the input structure may also be kept, and to
+ * define the ut_addr/ut_addr_v6 fields. (if these fields exist)
+ *
+ * Other fields are discarded and filed with new values (if they
+ * exist).
+ *
+ * The returned structure shall be freed by the caller.
+ */
+struct utmp *prepare_utmp (const char *name,
+ const char *line,
+ const char *host,
+ struct utmp *ut)
{
- int err = 0;
- utent.ut_type = USER_PROCESS;
- strncpy (utent.ut_user, name, sizeof utent.ut_user);
- utent.ut_time = time (NULL);
- /* other fields already filled in by checkutmp above */
- setutent ();
- if (pututline (&utent) == NULL) {
- err = 1;
- }
- endutent ();
- updwtmp (_WTMP_FILE, &utent);
+ struct timeval tv;
+ char *hostname = NULL;
+ struct utmp *utent;
- return err;
-}
+ assert (NULL != name);
+ assert (NULL != line);
+ assert (NULL != ut);
-#elif HAVE_UTMPX_H
-int setutmp (const char *name, const char *line, const char *host)
-{
- struct utmp *utmp, utline;
- struct utmpx *utmpx, utxline;
- pid_t pid = getpid ();
- bool found_utmpx = false;
- bool found_utmp = false;
- int err = 0;
- /*
- * The canonical device name doesn't include "/dev/"; skip it
- * if it is already there.
- */
+ if ( (NULL != host)
+ && ('\0' != host)) {
+ hostname = (char *) xmalloc (strlen (host) + 1);
+ strcpy (hostname, host);
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ } else if ( (NULL != ut->ut_host)
+ && ('\0' != ut->ut_host[0])) {
+ hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
+ strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
+ hostname[sizeof (ut->ut_host)] = '\0';
+#endif /* HAVE_STRUCT_UTMP_UT_HOST */
+ }
- if (strncmp (line, "/dev/", 5) == 0) {
+ if (strncmp(line, "/dev/", 5) == 0) {
line += 5;
}
- /*
- * Update utmpx. We create an empty entry in case there is
- * no matching entry in the utmpx file.
- */
- setutxent ();
- setutent ();
+ utent = (struct utmp *) xmalloc (sizeof (*utent));
+ memzero (utent, sizeof (*utent));
- while ((utmpx = getutxent ()) != NULL) {
- if (utmpx->ut_pid == pid) {
- found_utmpx = true;
- break;
+
+
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ utent->ut_type = USER_PROCESS;
+#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
+ utent->ut_pid = getpid ();
+ strncpy (utent->ut_line, line, sizeof (utent->ut_line));
+#ifdef HAVE_STRUCT_UTMP_UT_ID
+ strncpy (utent->ut_id, ut->ut_id, sizeof (utent->ut_id));
+#endif /* HAVE_STRUCT_UTMP_UT_ID */
+#ifdef HAVE_STRUCT_UTMP_UT_NAME
+ strncpy (utent->ut_name, name, sizeof (utent->ut_name));
+#endif /* HAVE_STRUCT_UTMP_UT_NAME */
+#ifdef HAVE_STRUCT_UTMP_UT_USER
+ strncpy (utent->ut_user, name, sizeof (utent->ut_user));
+#endif /* HAVE_STRUCT_UTMP_UT_USER */
+ if (NULL != hostname) {
+ struct addrinfo *info = NULL;
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy (utent->ut_host, hostname, sizeof (utent->ut_host));
+#endif /* HAVE_STRUCT_UTMP_UT_HOST */
+#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
+ utent->ut_syslen = MIN (strlen (hostname),
+ sizeof (utent->ut_host));
+#endif /* HAVE_STRUCT_UTMP_UT_SYSLEN */
+#if defined(HAVE_STRUCT_UTMP_UT_ADDR) || defined(HAVE_STRUCT_UTMP_UT_ADDR_V6)
+ if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
+ /* getaddrinfo might not be reliable.
+ * Just try to log what may be useful.
+ */
+ if (info->ai_family == AF_INET) {
+ struct sockaddr_in *sa =
+ (struct sockaddr_in *) info->ai_addr;
+#ifdef HAVE_STRUCT_UTMP_UT_ADDR
+ memcpy (&(utent->ut_addr),
+ &(sa->sin_addr),
+ MIN (sizeof (utent->ut_addr),
+ sizeof (sa->sin_addr)));
+#endif /* HAVE_STRUCT_UTMP_UT_ADDR */
+#ifdef HAVE_STRUCT_UTMP_UT_ADDR_V6
+ memcpy (utent->ut_addr_v6,
+ &(sa->sin_addr),
+ MIN (sizeof (utent->ut_addr_v6),
+ sizeof (sa->sin_addr)));
+ } else if (info->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sa =
+ (struct sockaddr_in6 *) info->ai_addr;
+ memcpy (utent->ut_addr_v6,
+ &(sa->sin6_addr),
+ MIN (sizeof (utent->ut_addr_v6),
+ sizeof (sa->sin6_addr)));
+#endif /* HAVE_STRUCT_UTMP_UT_ADDR_V6 */
+ }
+ freeaddrinfo (info);
}
+#endif /* HAVE_STRUCT_UTMP_UT_ADDR || HAVE_STRUCT_UTMP_UT_ADDR_V6 */
+ free (hostname);
}
- while ((utmp = getutent ()) != NULL) {
- if (utmp->ut_pid == pid) {
- found_utmp = true;
- break;
- }
- }
+ /* ut_exit is only for DEAD_PROCESS */
+ utent->ut_session = getsid (0);
+ gettimeofday (&tv, NULL);
+#ifdef HAVE_STRUCT_UTMP_UT_TIME
+ utent->ut_time = tv.tv_sec;
+#endif /* HAVE_STRUCT_UTMP_UT_TIME */
+#ifdef HAVE_STRUCT_UTMP_UT_XTIME
+ utent->ut_xtime = tv.tv_usec;
+#endif /* HAVE_STRUCT_UTMP_UT_XTIME */
+#ifdef HAVE_STRUCT_UTMP_UT_TV
+ utent->ut_tv.tv_sec = tv.tv_sec;
+ utent->ut_tv.tv_usec = tv.tv_usec;
+#endif /* HAVE_STRUCT_UTMP_UT_TV */
- /*
- * If the entry matching `pid' cannot be found, create a new
- * entry with the device name in it.
- */
+ return utent;
+}
- if (!found_utmpx) {
- memset ((void *) &utxline, 0, sizeof utxline);
- strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
- utxline.ut_pid = getpid ();
- } else {
- utxline = *utmpx;
- if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
- memmove (utxline.ut_line, utxline.ut_line + 5,
- sizeof utxline.ut_line - 5);
- utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
- }
+/*
+ * setutmp - Update an entry in utmp and log an entry in wtmp
+ *
+ * Return 1 on failure and 0 on success.
+ */
+int setutmp (struct utmp *ut)
+{
+ int err = 0;
+
+ assert (NULL != ut);
+
+ setutent ();
+ if (pututline (ut) == NULL) {
+ err = 1;
}
- if (!found_utmp) {
- memset ((void *) &utline, 0, sizeof utline);
- strncpy (utline.ut_line, utxline.ut_line,
- sizeof utline.ut_line);
- utline.ut_pid = utxline.ut_pid;
- } else {
- utline = *utmp;
- if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
- memmove (utline.ut_line, utline.ut_line + 5,
- sizeof utline.ut_line - 5);
- utline.ut_line[sizeof utline.ut_line - 5] = '\0';
- }
- }
+ endutent ();
- /*
- * Fill in the fields in the utmpx entry and write it out. Do
- * the utmp entry at the same time to make sure things don't
- * get messed up.
- */
+ updwtmp (_WTMP_FILE, ut);
- strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
- strncpy (utline.ut_user, name, sizeof utline.ut_user);
+ return err;
+}
- utline.ut_type = utxline.ut_type = USER_PROCESS;
+#ifdef HAVE_UTMPX_H
+/*
+ * prepare_utmpx - the UTMPX version for prepare_utmp
+ */
+struct utmpx *prepare_utmpx (const char *name,
+ const char *line,
+ const char *host,
+ struct utmp *ut)
+{
+ struct timeval tv;
+ char *hostname = NULL;
+ struct utmpx *utxent;
- if (sizeof (utxline.ut_tv) == sizeof (struct timeval)) {
- gettimeofday ((struct timeval *) &utxline.ut_tv, NULL);
- } else {
- struct timeval tv;
+ assert (NULL != name);
+ assert (NULL != line);
+ assert (NULL != ut);
- gettimeofday (&tv, NULL);
- utxline.ut_tv.tv_sec = tv.tv_sec;
- utxline.ut_tv.tv_usec = tv.tv_usec;
+
+
+ if ( (NULL != host)
+ && ('\0' != host)) {
+ hostname = (char *) xmalloc (strlen (host) + 1);
+ strcpy (hostname, host);
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ } else if ( (NULL != ut->ut_host)
+ && ('\0' != ut->ut_host[0])) {
+ hostname = (char *) xmalloc (sizeof (ut->ut_host) + 1);
+ strncpy (hostname, ut->ut_host, sizeof (ut->ut_host));
+ hostname[sizeof (ut->ut_host)] = '\0';
+#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
}
- utline.ut_time = utxline.ut_tv.tv_sec;
- strncpy (utxline.ut_host, (NULL != host) ? host : "",
- sizeof utxline.ut_host);
+ if (strncmp(line, "/dev/", 5) == 0) {
+ line += 5;
+ }
- if ( (pututxline (&utxline) == NULL)
- || (pututline (&utline) == NULL)) {
- err = 1;
+ utxent = (struct utmpx *) xmalloc (sizeof (*utxent));
+ memzero (utxent, sizeof (*utxent));
+
+
+
+ utxent->ut_type = USER_PROCESS;
+ utxent->ut_pid = getpid ();
+ strncpy (utxent->ut_line, line, sizeof (utxent->ut_line));
+#ifndef HAVE_STRUCT_UTMP_UT_ID
+// FIXME: move to configure.in
+# error "No support for systems with utmpx and no ut_id field in utmp"
+#endif /* !HAVE_STRUCT_UTMP_UT_ID */
+ strncpy (utxent->ut_id, ut->ut_id, sizeof (utxent->ut_id));
+#ifdef HAVE_STRUCT_UTMPX_UT_NAME
+ strncpy (utxent->ut_name, name, sizeof (utxent->ut_name));
+#endif /* HAVE_STRUCT_UTMPX_UT_NAME */
+ strncpy (utxent->ut_user, name, sizeof (utxent->ut_user));
+ if (NULL != hostname) {
+ struct addrinfo *info = NULL;
+#ifdef HAVE_STRUCT_UTMPX_UT_HOST
+ strncpy (utxent->ut_host, hostname, sizeof (utxent->ut_host));
+#endif /* HAVE_STRUCT_UTMPX_UT_HOST */
+#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
+ utxent->ut_syslen = MIN (strlen (hostname),
+ sizeof (utxent->ut_host));
+#endif /* HAVE_STRUCT_UTMPX_UT_SYSLEN */
+#if defined(HAVE_STRUCT_UTMPX_UT_ADDR) || defined(HAVE_STRUCT_UTMPX_UT_ADDR_V6)
+ if (getaddrinfo (hostname, NULL, NULL, &info) == 0) {
+ /* getaddrinfo might not be reliable.
+ * Just try to log what may be useful.
+ */
+ if (info->ai_family == AF_INET) {
+ struct sockaddr_in *sa =
+ (struct sockaddr_in *) info->ai_addr;
+#ifdef HAVE_STRUCT_UTMPX_UT_ADDR
+ memcpy (utxent->ut_addr,
+ &(sa->sin_addr),
+ MIN (sizeof (utxent->ut_addr),
+ sizeof (sa->sin_addr)));
+#endif /* HAVE_STRUCT_UTMPX_UT_ADDR */
+#ifdef HAVE_STRUCT_UTMPX_UT_ADDR_V6
+ memcpy (utxent->ut_addr_v6,
+ &(sa->sin_addr),
+ MIN (sizeof (utxent->ut_addr_v6),
+ sizeof (sa->sin_addr)));
+ } else if (info->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sa =
+ (struct sockaddr_in6 *) info->ai_addr;
+ memcpy (utxent->ut_addr_v6,
+ &(sa->sin6_addr),
+ MIN (sizeof (utxent->ut_addr_v6),
+ sizeof (sa->sin6_addr)));
+#endif /* HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
+ }
+ freeaddrinfo (info);
+ }
+#endif /* HAVE_STRUCT_UTMPX_UT_ADDR || HAVE_STRUCT_UTMPX_UT_ADDR_V6 */
+ free (hostname);
}
+ /* ut_exit is only for DEAD_PROCESS */
+ utxent->ut_session = getsid (0);
+ gettimeofday (&tv, NULL);
+#ifdef HAVE_STRUCT_UTMPX_UT_TIME
+ utxent->ut_time = tv.tv_sec;
+#endif /* HAVE_STRUCT_UTMPX_UT_TIME */
+#ifdef HAVE_STRUCT_UTMPX_UT_XTIME
+ utxent->ut_xtime = tv.tv_usec;
+#endif /* HAVE_STRUCT_UTMPX_UT_XTIME */
+ utxent->ut_tv.tv_sec = tv.tv_sec;
+ utxent->ut_tv.tv_usec = tv.tv_usec;
- updwtmpx (_WTMP_FILE "x", &utxline);
- updwtmp (_WTMP_FILE, &utline);
+ return utxent;
+}
- utxent = utxline;
- utent = utline;
+/*
+ * setutmpx - the UTMPX version for setutmp
+ */
+int setutmpx (struct utmpx *utx)
+{
+ int err = 0;
+ assert (NULL != utx);
+
+ setutxent ();
+ if (pututxline (utx) == NULL) {
+ err = 1;
+ }
endutxent ();
- endutent ();
+ updwtmpx (_WTMP_FILE "x", utx);
+
return err;
}
+#endif /* HAVE_UTMPX_H */
-#endif
Modified: upstream/trunk/src/login.c
===================================================================
--- upstream/trunk/src/login.c 2009-04-21 22:22:08 UTC (rev 2736)
+++ upstream/trunk/src/login.c 2009-04-21 22:39:14 UTC (rev 2737)
@@ -85,14 +85,6 @@
static char *username = NULL;
static int reason = PW_LOGIN;
-#if HAVE_UTMPX_H
-extern struct utmpx utxent;
-struct utmpx failent;
-#else
-struct utmp failent;
-#endif
-extern struct utmp utent;
-
struct lastlog lastlog;
static bool pflg = false;
static bool fflg = false;
@@ -128,7 +120,7 @@
static void usage (void);
static void setup_tty (void);
static void process_flags (int, char *const *);
-static const char *get_failent_user (const char *user)
+static const char *get_failent_user (const char *user);
#ifndef USE_PAM
static struct faillog faillog;
@@ -494,6 +486,7 @@
static char temp_shell[] = "/bin/sh";
#endif
const char *failent_user;
+ struct utmp *utent;
#ifdef USE_PAM
int retcode;
@@ -523,6 +516,7 @@
exit (1); /* must be a terminal */
}
+ utent = get_current_utmp ();
/*
* Be picky if run by normal users (possible if installed setuid
* root), but not if run by root. This way it still allows logins
@@ -530,7 +524,10 @@
* but users must "exec login" which will use the existing utmp
* entry (will not overwrite remote hostname). --marekm
*/
- checkutmp (!amroot);
+ if (!amroot && (NULL == utent)) {
+ (void) puts (_("No utmp entry. You must exec \"login\" from the lowest level \"sh\""));
+ exit (1);
+ }
tmptty = ttyname (0);
if (NULL == tmptty) {
@@ -543,44 +540,12 @@
#endif
if (rflg || hflg) {
-#ifdef UT_ADDR
- struct hostent *he;
-
/*
- * Fill in the ut_addr field (remote login IP address). XXX
- * - login from util-linux does it, but this is not the
- * right place to do it. The program that starts login
- * (telnetd, rlogind) knows the IP address, so it should
- * create the utmp entry and fill in ut_addr.
- * gethostbyname() is not 100% reliable (the remote host may
- * be unknown, etc.). --marekm
- */
- he = gethostbyname (hostname);
- if (NULL != he) {
- utent.ut_addr = *((int32_t *) (he->h_addr_list[0]));
- }
-#endif
-#ifdef UT_HOST
- strncpy (utent.ut_host, hostname, sizeof (utent.ut_host));
-#endif
-#if HAVE_UTMPX_H
- strncpy (utxent.ut_host, hostname, sizeof (utxent.ut_host));
-#endif
- /*
* Add remote hostname to the environment. I think
* (not sure) I saw it once on Irix. --marekm
*/
addenv ("REMOTEHOST", hostname);
}
-#ifdef __linux__
- /*
- * workaround for init/getty leaving junk in ut_host at least in
- * some version of RedHat. --marekm
- */
- else if (amroot) {
- memzero (utent.ut_host, sizeof utent.ut_host);
- }
-#endif
if (fflg) {
preauth_flag = true;
}
@@ -656,18 +621,11 @@
if (rflg || hflg) {
cp = hostname;
} else {
- /* FIXME: What is the priority:
- * UT_HOST or HAVE_UTMPX_H? */
-#ifdef UT_HOST
- if ('\0' != utent.ut_host[0]) {
- cp = utent.ut_host;
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ if ('\0' != utent->ut_host[0]) {
+ cp = utent->ut_host;
} else
-#endif
-#if HAVE_UTMPX_H
- if ('\0' != utxent.ut_host[0]) {
- cp = utxent.ut_host;
- } else
-#endif
+#endif /* HAVE_STRUCT_UTMP_UT_HOST */
{
cp = "";
}
@@ -888,17 +846,17 @@
while (true) { /* repeatedly get login/password pairs */
/* user_passwd is always a pointer to this constant string
* or a passwd or shadow password that will be memzero by
- * passwd_free / shadow_free.
+ * pw_free / spw_free.
* Do not free() user_passwd. */
const char *user_passwd = "!";
/* Do some cleanup to avoid keeping entries we do not need
* anymore. */
if (NULL != pwd) {
- passwd_free (pwd);
+ pw_free (pwd);
}
if (NULL != spwd) {
- shadow_free (spwd);
+ spw_free (spwd);
spwd = NULL;
}
@@ -1007,26 +965,21 @@
failure (pwd->pw_uid, tty, &faillog);
}
if (getdef_str ("FTMP_FILE") != NULL) {
-#if HAVE_UTMPX_H
- failent = utxent;
- if (sizeof (failent.ut_tv) == sizeof (struct timeval)) {
- gettimeofday ((struct timeval *) &failent.ut_tv,
- NULL);
- } else {
- struct timeval tv;
-
- gettimeofday (&tv, NULL);
- failent.ut_tv.tv_sec = tv.tv_sec;
- failent.ut_tv.tv_usec = tv.tv_usec;
- }
+#ifdef HAVE_UTMPX_H
+ struct utmpx *failent =
+ prepare_utmpx (failent_user,
+ tty,
+ /* FIXME: or fromhost? */hostname,
+ utent);
#else
- failent = utent;
- failent.ut_time = time (NULL);
+ struct utmp *failent =
+ prepare_utmp (failent_user,
+ tty,
+ hostname,
+ utent);
#endif
- strncpy (failent.ut_user, failent_user,
- sizeof (failent.ut_user));
- failent.ut_type = USER_PROCESS;
- failtmp (failent_user, &failent);
+ failtmp (failent_user, failent);
+ free (failent);
}
retries--;
@@ -1096,7 +1049,15 @@
addenv ("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
}
- setutmp (username, tty, hostname); /* make entry in utmp & wtmp files */
+ struct utmp *ut = prepare_utmp (username, tty, hostname, utent);
+ (void) setutmp (ut); /* make entry in the utmp & wtmp files */
+ free (ut);
+#ifdef HAVE_UTMPX_H
+ struct utmpx *utx = prepare_utmpx (username, tty, hostname, utent);
+ (void) setutmpx (utx); /* make entry in the utmpx & wtmpx files */
+ free (utx);
+#endif /* HAVE_UTMPX_H */
+
if (pwd->pw_shell[0] == '*') { /* subsystem root */
pwd->pw_shell++; /* skip the '*' */
subsystem (pwd); /* figure out what to execute */
@@ -1144,7 +1105,7 @@
* entry for a long time, and there might be other
* getxxyy in between.
*/
- passwd_free (pwd);
+ pw_free (pwd);
pwd = xgetpwnam (username);
if (NULL == pwd) {
SYSLOG ((LOG_ERR,
@@ -1152,7 +1113,7 @@
username));
exit (1);
}
- shadow_free (spwd);
+ spw_free (spwd);
spwd = xgetspnam (username);
}
}
More information about the Pkg-shadow-commits
mailing list