⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loginrec.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2000 Andre Lucas.  All rights reserved. * Portions copyright (c) 1998 Todd C. Miller * Portions copyright (c) 1996 Jason Downs * Portions copyright (c) 1996 Theo de Raadt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by Markus Friedl. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//** ** loginrec.c:  platform-independent login recording and lastlog retrieval **//*  The new login code explained  ============================  This code attempts to provide a common interface to login recording  (utmp and friends) and last login time retrieval.  Its primary means of achieving this is to use 'struct logininfo', a  union of all the useful fields in the various different types of  system login record structures one finds on UNIX variants.  We depend on autoconf to define which recording methods are to be  used, and which fields are contained in the relevant data structures  on the local system. Many C preprocessor symbols affect which code  gets compiled here.  The code is designed to make it easy to modify a particular  recording method, without affecting other methods nor requiring so  many nested conditional compilation blocks as were commonplace in  the old code.  For login recording, we try to use the local system's libraries as  these are clearly most likely to work correctly. For utmp systems  this usually means login() and logout() or setutent() etc., probably  in libutil, along with logwtmp() etc. On these systems, we fall back  to writing the files directly if we have to, though this method  requires very thorough testing so we do not corrupt local auditing  information. These files and their access methods are very system  specific indeed.  For utmpx systems, the corresponding library functions are  setutxent() etc. To the author's knowledge, all utmpx systems have  these library functions and so no direct write is attempted. If such  a system exists and needs support, direct analogues of the [uw]tmp  code should suffice.  Retrieving the time of last login ('lastlog') is in some ways even  more problemmatic than login recording. Some systems provide a  simple table of all users which we seek based on uid and retrieve a  relatively standard structure. Others record the same information in  a directory with a separate file, and others don't record the  information separately at all. For systems in the latter category,  we look backwards in the wtmp or wtmpx file for the last login entry  for our user. Naturally this is slower and on busy systems could  incur a significant performance penalty.  Calling the new code  --------------------  In OpenSSH all login recording and retrieval is performed in  login.c. Here you'll find working examples. Also, in the logintest.c  program there are more examples.  Internal handler calling method  -------------------------------  When a call is made to login_login() or login_logout(), both  routines set a struct logininfo flag defining which action (log in,  or log out) is to be taken. They both then call login_write(), which  calls whichever of the many structure-specific handlers autoconf  selects for the local system.  The handlers themselves handle system data structure specifics. Both  struct utmp and struct utmpx have utility functions (see  construct_utmp*()) to try to make it simpler to add extra systems  that introduce new features to either structure.  While it may seem terribly wasteful to replicate so much similar  code for each method, experience has shown that maintaining code to  write both struct utmp and utmpx in one function, whilst maintaining  support for all systems whether they have library support or not, is  a difficult and time-consuming task.  Lastlog support proceeds similarly. Functions login_get_lastlog()  (and its OpenSSH-tuned friend login_get_lastlog_time()) call  getlast_entry(), which tries one of three methods to find the last  login time. It uses local system lastlog support if it can,  otherwise it tries wtmp or wtmpx before giving up and returning 0,  meaning "tilt".  Maintenance  -----------  In many cases it's possible to tweak autoconf to select the correct  methods for a particular platform, either by improving the detection  code (best), or by presetting DISABLE_<method> or CONF_<method>_FILE  symbols for the platform.  Use logintest to check which symbols are defined before modifying  configure.ac and loginrec.c. (You have to build logintest yourself  with 'make logintest' as it's not built by default.)  Otherwise, patches to the specific method(s) are very helpful!*//** ** TODO: **   homegrown ttyslot() **   test, test, test ** ** Platform status: ** ---------------- ** ** Known good: **   Linux (Redhat 6.2, Debian) **   Solaris **   HP-UX 10.20 (gcc only) **   IRIX **   NeXT - M68k/HPPA/Sparc (4.2/3.3) ** ** Testing required: Please send reports! **   NetBSD **   HP-UX 11 **   AIX ** ** Platforms with known problems: **   Some variants of Slackware Linux ** **/#include "includes.h"#include "ssh.h"#include "xmalloc.h"#include "loginrec.h"#include "log.h"#include "atomicio.h"RCSID("$Id: loginrec.c,v 1.40 2002/04/23 13:09:19 djm Exp $");#ifdef HAVE_UTIL_H#  include <util.h>#endif#ifdef HAVE_LIBUTIL_H#   include <libutil.h>#endif/** ** prototypes for helper functions in this file **/#if HAVE_UTMP_Hvoid set_utmp_time(struct logininfo *li, struct utmp *ut);void construct_utmp(struct logininfo *li, struct utmp *ut);#endif#ifdef HAVE_UTMPX_Hvoid set_utmpx_time(struct logininfo *li, struct utmpx *ut);void construct_utmpx(struct logininfo *li, struct utmpx *ut);#endifint utmp_write_entry(struct logininfo *li);int utmpx_write_entry(struct logininfo *li);int wtmp_write_entry(struct logininfo *li);int wtmpx_write_entry(struct logininfo *li);int lastlog_write_entry(struct logininfo *li);int syslogin_write_entry(struct logininfo *li);int getlast_entry(struct logininfo *li);int lastlog_get_entry(struct logininfo *li);int wtmp_get_entry(struct logininfo *li);int wtmpx_get_entry(struct logininfo *li);/* pick the shortest string */#define MIN_SIZEOF(s1,s2) ( sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2) )/** ** platform-independent login functions **//* login_login(struct logininfo *)     -Record a login * * Call with a pointer to a struct logininfo initialised with * login_init_entry() or login_alloc_entry() * * Returns: *  >0 if successful *  0  on failure (will use OpenSSH's logging facilities for diagnostics) */intlogin_login (struct logininfo *li){	li->type = LTYPE_LOGIN;	return login_write(li);}/* login_logout(struct logininfo *)     - Record a logout * * Call as with login_login() * * Returns: *  >0 if successful *  0  on failure (will use OpenSSH's logging facilities for diagnostics) */intlogin_logout(struct logininfo *li){	li->type = LTYPE_LOGOUT;	return login_write(li);}/* login_get_lastlog_time(int)           - Retrieve the last login time * * Retrieve the last login time for the given uid. Will try to use the * system lastlog facilities if they are available, but will fall back * to looking in wtmp/wtmpx if necessary * * Returns: *   0 on failure, or if user has never logged in *   Time in seconds from the epoch if successful * * Useful preprocessor symbols: *   DISABLE_LASTLOG: If set, *never* even try to retrieve lastlog *                    info *   USE_LASTLOG: If set, indicates the presence of system lastlog *                facilities. If this and DISABLE_LASTLOG are not set, *                try to retrieve lastlog information from wtmp/wtmpx. */unsigned intlogin_get_lastlog_time(const int uid){	struct logininfo li;	if (login_get_lastlog(&li, uid))		return li.tv_sec;	else		return 0;}/* login_get_lastlog(struct logininfo *, int)   - Retrieve a lastlog entry * * Retrieve a logininfo structure populated (only partially) with * information from the system lastlog data, or from wtmp/wtmpx if no * system lastlog information exists. * * Note this routine must be given a pre-allocated logininfo. * * Returns: *  >0: A pointer to your struct logininfo if successful *  0  on failure (will use OpenSSH's logging facilities for diagnostics) * */struct logininfo *login_get_lastlog(struct logininfo *li, const int uid){	struct passwd *pw;	memset(li, '\0', sizeof(*li));	li->uid = uid;	/*	 * If we don't have a 'real' lastlog, we need the username to	 * reliably search wtmp(x) for the last login (see	 * wtmp_get_entry().)	 */	pw = getpwuid(uid);	if (pw == NULL)		fatal("login_get_lastlog: Cannot find account for uid %i", uid);	/* No MIN_SIZEOF here - we absolutely *must not* truncate the	 * username */	strlcpy(li->username, pw->pw_name, sizeof(li->username));	if (getlast_entry(li))		return li;	else		return NULL;}/* login_alloc_entry(int, char*, char*, char*)    - Allocate and initialise *                                                  a logininfo structure * * This function creates a new struct logininfo, a data structure * meant to carry the information required to portably record login info. * * Returns a pointer to a newly created struct logininfo. If memory * allocation fails, the program halts. */structlogininfo *login_alloc_entry(int pid, const char *username,			     const char *hostname, const char *line){	struct logininfo *newli;	newli = (struct logininfo *) xmalloc (sizeof(*newli));	(void)login_init_entry(newli, pid, username, hostname, line);	return newli;}/* login_free_entry(struct logininfo *)    - free struct memory */voidlogin_free_entry(struct logininfo *li){	xfree(li);}/* login_init_entry(struct logininfo *, int, char*, char*, char*) *                                        - initialise a struct logininfo * * Populates a new struct logininfo, a data structure meant to carry * the information required to portably record login info. * * Returns: 1 */intlogin_init_entry(struct logininfo *li, int pid, const char *username,		 const char *hostname, const char *line){	struct passwd *pw;	memset(li, 0, sizeof(*li));	li->pid = pid;	/* set the line information */	if (line)		line_fullname(li->line, line, sizeof(li->line));	if (username) {		strlcpy(li->username, username, sizeof(li->username));		pw = getpwnam(li->username);		if (pw == NULL)			fatal("login_init_entry: Cannot find user \"%s\"", li->username);		li->uid = pw->pw_uid;	}	if (hostname)		strlcpy(li->hostname, hostname, sizeof(li->hostname));	return 1;}/* login_set_current_time(struct logininfo *)    - set the current time * * Set the current time in a logininfo structure. This function is * meant to eliminate the need to deal with system dependencies for * time handling. */voidlogin_set_current_time(struct logininfo *li){	struct timeval tv;	gettimeofday(&tv, NULL);	li->tv_sec = tv.tv_sec;	li->tv_usec = tv.tv_usec;}/* copy a sockaddr_* into our logininfo */voidlogin_set_addr(struct logininfo *li, const struct sockaddr *sa,	       const unsigned int sa_size){	unsigned int bufsize = sa_size;	/* make sure we don't overrun our union */	if (sizeof(li->hostaddr) < sa_size)		bufsize = sizeof(li->hostaddr);	memcpy((void *)&(li->hostaddr.sa), (const void *)sa, bufsize);}/** ** login_write: Call low-level recording functions based on autoconf ** results **/intlogin_write (struct logininfo *li){#ifndef HAVE_CYGWIN	if ((int)geteuid() != 0) {	  log("Attempt to write login records by non-root user (aborting)");	  return 1;	}#endif	/* set the timestamp */	login_set_current_time(li);#ifdef USE_LOGIN	syslogin_write_entry(li);#endif#ifdef USE_LASTLOG	if (li->type == LTYPE_LOGIN) {		lastlog_write_entry(li);	}#endif#ifdef USE_UTMP	utmp_write_entry(li);#endif#ifdef USE_WTMP	wtmp_write_entry(li);#endif#ifdef USE_UTMPX	utmpx_write_entry(li);#endif#ifdef USE_WTMPX	wtmpx_write_entry(li);#endif	return 0;}#ifdef LOGIN_NEEDS_UTMPXintlogin_utmp_only(struct logininfo *li){	li->type = LTYPE_LOGIN; 	login_set_current_time(li);# ifdef USE_UTMP	utmp_write_entry(li);# endif# ifdef USE_WTMP	wtmp_write_entry(li);# endif# ifdef USE_UTMPX	utmpx_write_entry(li);# endif# ifdef USE_WTMPX	wtmpx_write_entry(li);# endif	return 0;}#endif/** ** getlast_entry: Call low-level functions to retrieve the last login **                time. **//* take the uid in li and return the last login time */intgetlast_entry(struct logininfo *li){#ifdef USE_LASTLOG	return(lastlog_get_entry(li));#else /* !USE_LASTLOG */#ifdef DISABLE_LASTLOG	/* On some systems we shouldn't even try to obtain last login	 * time, e.g. AIX */	return 0;# else /* DISABLE_LASTLOG */	/* Try to retrieve the last login time from wtmp */#  if defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP))	/* retrieve last login time from utmp */	return (wtmp_get_entry(li));#  else /* defined(USE_WTMP) && (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) */	/* If wtmp isn't available, try wtmpx */#   if defined(USE_WTMPX) && (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX))	/* retrieve last login time from utmpx */	return (wtmpx_get_entry(li));#   else	/* Give up: No means of retrieving last login time */	return 0;#   endif /* USE_WTMPX && (HAVE_TIME_IN_UTMPX || HAVE_TV_IN_UTMPX) */#  endif /* USE_WTMP && (HAVE_TIME_IN_UTMP || HAVE_TV_IN_UTMP) */# endif /* DISABLE_LASTLOG */#endif /* USE_LASTLOG */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -