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

📄 loginrec.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 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. * * 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. *//* * The btmp logging code is derived from login.c from util-linux and is under * the the following license: * * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. *//** ** 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! */#include "includes.h"#include "ssh.h"#include "xmalloc.h"#include "loginrec.h"#include "log.h"#include "atomicio.h"#include "packet.h"#include "canohost.h"#include "auth.h"#include "buffer.h"#ifdef HAVE_UTIL_H# include <util.h>#endif#ifdef HAVE_LIBUTIL_H# include <libutil.h>#endifRCSID("$Id: loginrec.c,v 1.67 2005/02/15 11:19:28 dtucker Exp $");/** ** 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);extern Buffer loginmsg;/* 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("%s: Cannot find account for uid %i", __func__, uid);	/* No MIN_SIZEOF here - we absolutely *must not* truncate the	 * username (XXX - so check for trunc!) */	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 = xmalloc(sizeof(*newli));	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("%s: Cannot find user \"%s\"", __func__, 			    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(&li->hostaddr.sa, sa, bufsize);}/** ** login_write: Call low-level recording functions based on autoconf ** results **/intlogin_write(struct logininfo *li){#ifndef HAVE_CYGWIN	if (geteuid() != 0) {		logit("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#ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN	if (li->type == LTYPE_LOGIN && 	   !sys_auth_record_login(li->username,li->hostname,li->line, &loginmsg))		logit("Writing login record failed for %s", li->username);#endif#ifdef SSH_AUDIT_EVENTS	if (li->type == LTYPE_LOGIN)		audit_session_open(li->line);	else if (li->type == LTYPE_LOGOUT)		audit_session_close(li->line);#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 */#if defined(DISABLE_LASTLOG)	/* On some systems we shouldn't even try to obtain last login	 * time, e.g. AIX */	return (0);# elif defined(USE_WTMP) && \    (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP))	/* retrieve last login time from utmp */	return (wtmp_get_entry(li));# elif defined(USE_WTMPX) && \    (defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX))	/* If wtmp isn't available, try wtmpx */	return (wtmpx_get_entry(li));# else	/* Give up: No means of retrieving last login time */	return (0);# endif /* DISABLE_LASTLOG */#endif /* USE_LASTLOG */}/* * 'line' string utility functions * * These functions process the 'line' string into one of three forms: * * 1. The full filename (including '/dev') * 2. The stripped name (excluding '/dev') * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 *                               /dev/pts/1  -> ts/1 ) * * Form 3 is used on some systems to identify a .tmp.? entry when * attempting to remove it. Typically both addition and removal is * performed by one application - say, sshd - so as long as the choice * uniquely identifies a terminal it's ok. *//* * line_fullname(): add the leading '/dev/' if it doesn't exist make * sure dst has enough space, if not just copy src (ugh) */char *line_fullname(char *dst, const char *src, int dstsize){	memset(dst, '\0', dstsize);	if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5)))		strlcpy(dst, src, dstsize);	else {		strlcpy(dst, "/dev/", dstsize);		strlcat(dst, src, dstsize);	}	return (dst);}/* line_stripname(): strip the leading '/dev' if it exists, return dst */char *line_stripname(char *dst, const char *src, int dstsize){	memset(dst, '\0', dstsize);	if (strncmp(src, "/dev/", 5) == 0)		strlcpy(dst, src + 5, dstsize);	else		strlcpy(dst, src, dstsize);	return (dst);}

⌨️ 快捷键说明

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