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

📄 loginrec.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 3 页
字号:
 * leave all fields set, but change the ut_type field to DEAD_PROCESS. * * Since we're only looking for logins here, we know that the username * must be set correctly. On systems that leave it in, we check for * ut_type==USER_PROCESS (indicating a login.) * * Portability: Some systems may set something other than USER_PROCESS * to indicate a login process. I don't know of any as I write. Also, * it's possible that some systems may both leave the username in * place and not have ut_type. *//* return true if this wtmp entry indicates a login */static intwtmp_islogin(struct logininfo *li, struct utmp *ut){	if (strncmp(li->username, ut->ut_name,	    MIN_SIZEOF(li->username, ut->ut_name)) == 0) {# ifdef HAVE_TYPE_IN_UTMP		if (ut->ut_type & USER_PROCESS)			return (1);# else		return (1);# endif	}	return (0);}intwtmp_get_entry(struct logininfo *li){	struct stat st;	struct utmp ut;	int fd, found = 0;	/* Clear the time entries in our logininfo */	li->tv_sec = li->tv_usec = 0;	if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) {		logit("%s: problem opening %s: %s", __func__, 		    WTMP_FILE, strerror(errno));		return (0);	}	if (fstat(fd, &st) != 0) {		logit("%s: couldn't stat %s: %s", __func__, 		    WTMP_FILE, strerror(errno));		close(fd);		return (0);	}	/* Seek to the start of the last struct utmp */	if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) {		/* Looks like we've got a fresh wtmp file */		close(fd);		return (0);	}	while (!found) {		if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) {			logit("%s: read of %s failed: %s", __func__, 			    WTMP_FILE, strerror(errno));			close (fd);			return (0);		}		if ( wtmp_islogin(li, &ut) ) {			found = 1;			/*			 * We've already checked for a time in struct			 * utmp, in login_getlast()			 */# ifdef HAVE_TIME_IN_UTMP			li->tv_sec = ut.ut_time;# else#  if HAVE_TV_IN_UTMP			li->tv_sec = ut.ut_tv.tv_sec;#  endif# endif			line_fullname(li->line, ut.ut_line,			    MIN_SIZEOF(li->line, ut.ut_line));# ifdef HAVE_HOST_IN_UTMP			strlcpy(li->hostname, ut.ut_host,			    MIN_SIZEOF(li->hostname, ut.ut_host));# endif			continue;		}		/* Seek back 2 x struct utmp */		if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) {			/* We've found the start of the file, so quit */			close(fd);			return (0);		}	}	/* We found an entry. Tidy up and return */	close(fd);	return (1);}# endif /* USE_WTMP *//** ** Low-level wtmpx functions **/#ifdef USE_WTMPX/* * Write a wtmpx entry direct to the end of the file * This is a slight modification of code in OpenBSD's logwtmp.c */static intwtmpx_write(struct logininfo *li, struct utmpx *utx){#ifndef HAVE_UPDWTMPX	struct stat buf;	int fd, ret = 1;	if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) {		logit("%s: problem opening %s: %s", __func__, 		    WTMPX_FILE, strerror(errno));		return (0);	}	if (fstat(fd, &buf) == 0)		if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) {			ftruncate(fd, buf.st_size);			logit("%s: problem writing %s: %s", __func__,			    WTMPX_FILE, strerror(errno));			ret = 0;		}	close(fd);	return (ret);#else	updwtmpx(WTMPX_FILE, utx);	return (1);#endif}static intwtmpx_perform_login(struct logininfo *li){	struct utmpx utx;	construct_utmpx(li, &utx);	return (wtmpx_write(li, &utx));}static intwtmpx_perform_logout(struct logininfo *li){	struct utmpx utx;	construct_utmpx(li, &utx);	return (wtmpx_write(li, &utx));}intwtmpx_write_entry(struct logininfo *li){	switch(li->type) {	case LTYPE_LOGIN:		return (wtmpx_perform_login(li));	case LTYPE_LOGOUT:		return (wtmpx_perform_logout(li));	default:		logit("%s: invalid type field", __func__);		return (0);	}}/* Please see the notes above wtmp_islogin() for information about the   next two functions *//* Return true if this wtmpx entry indicates a login */static intwtmpx_islogin(struct logininfo *li, struct utmpx *utx){	if (strncmp(li->username, utx->ut_name,	    MIN_SIZEOF(li->username, utx->ut_name)) == 0 ) {# ifdef HAVE_TYPE_IN_UTMPX		if (utx->ut_type == USER_PROCESS)			return (1);# else		return (1);# endif	}	return (0);}intwtmpx_get_entry(struct logininfo *li){	struct stat st;	struct utmpx utx;	int fd, found=0;	/* Clear the time entries */	li->tv_sec = li->tv_usec = 0;	if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) {		logit("%s: problem opening %s: %s", __func__, 		    WTMPX_FILE, strerror(errno));		return (0);	}	if (fstat(fd, &st) != 0) {		logit("%s: couldn't stat %s: %s", __func__, 		    WTMPX_FILE, strerror(errno));		close(fd);		return (0);	}	/* Seek to the start of the last struct utmpx */	if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) {		/* probably a newly rotated wtmpx file */		close(fd);		return (0);	}	while (!found) {		if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) {			logit("%s: read of %s failed: %s", __func__, 			    WTMPX_FILE, strerror(errno));			close (fd);			return (0);		}		/*		 * Logouts are recorded as a blank username on a particular 		 * line. So, we just need to find the username in struct utmpx		 */		if (wtmpx_islogin(li, &utx)) {			found = 1;# if defined(HAVE_TV_IN_UTMPX)			li->tv_sec = utx.ut_tv.tv_sec;# elif defined(HAVE_TIME_IN_UTMPX)			li->tv_sec = utx.ut_time;# endif			line_fullname(li->line, utx.ut_line, sizeof(li->line));# if defined(HAVE_HOST_IN_UTMPX)			strlcpy(li->hostname, utx.ut_host,			    MIN_SIZEOF(li->hostname, utx.ut_host));# endif			continue;		}		if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) {			close(fd);			return (0);		}	}	close(fd);	return (1);}#endif /* USE_WTMPX *//** ** Low-level libutil login() functions **/#ifdef USE_LOGINstatic intsyslogin_perform_login(struct logininfo *li){	struct utmp *ut;	ut = xmalloc(sizeof(*ut));	construct_utmp(li, ut);	login(ut);	free(ut);	return (1);}static intsyslogin_perform_logout(struct logininfo *li){# ifdef HAVE_LOGOUT	char line[UT_LINESIZE];	(void)line_stripname(line, li->line, sizeof(line));	if (!logout(line))		logit("%s: logout() returned an error", __func__);#  ifdef HAVE_LOGWTMP	else		logwtmp(line, "", "");#  endif	/* FIXME: (ATL - if the need arises) What to do if we have	 * login, but no logout?  what if logout but no logwtmp? All	 * routines are in libutil so they should all be there,	 * but... */# endif	return (1);}intsyslogin_write_entry(struct logininfo *li){	switch (li->type) {	case LTYPE_LOGIN:		return (syslogin_perform_login(li));	case LTYPE_LOGOUT:		return (syslogin_perform_logout(li));	default:		logit("%s: Invalid type field", __func__);		return (0);	}}#endif /* USE_LOGIN *//* end of file log-syslogin.c *//** ** Low-level lastlog functions **/#ifdef USE_LASTLOG#define LL_FILE 1#define LL_DIR 2#define LL_OTHER 3static voidlastlog_construct(struct logininfo *li, struct lastlog *last){	/* clear the structure */	memset(last, '\0', sizeof(*last));	line_stripname(last->ll_line, li->line, sizeof(last->ll_line));	strlcpy(last->ll_host, li->hostname,		MIN_SIZEOF(last->ll_host, li->hostname));	last->ll_time = li->tv_sec;}static intlastlog_filetype(char *filename){	struct stat st;	if (stat(LASTLOG_FILE, &st) != 0) {		logit("%s: Couldn't stat %s: %s", __func__,		    LASTLOG_FILE, strerror(errno));		return (0);	}	if (S_ISDIR(st.st_mode))		return (LL_DIR);	else if (S_ISREG(st.st_mode))		return (LL_FILE);	else		return (LL_OTHER);}/* open the file (using filemode) and seek to the login entry */static intlastlog_openseek(struct logininfo *li, int *fd, int filemode){	off_t offset;	int type;	char lastlog_file[1024];	type = lastlog_filetype(LASTLOG_FILE);	switch (type) {	case LL_FILE:		strlcpy(lastlog_file, LASTLOG_FILE,		    sizeof(lastlog_file));		break;	case LL_DIR:		snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s",		    LASTLOG_FILE, li->username);		break;	default:		logit("%s: %.100s is not a file or directory!", __func__,		    LASTLOG_FILE);		return (0);	}	*fd = open(lastlog_file, filemode, 0600);	if (*fd < 0) {		debug("%s: Couldn't open %s: %s", __func__,		    lastlog_file, strerror(errno));		return (0);	}	if (type == LL_FILE) {		/* find this uid's offset in the lastlog file */		offset = (off_t) ((long)li->uid * sizeof(struct lastlog));		if (lseek(*fd, offset, SEEK_SET) != offset) {			logit("%s: %s->lseek(): %s", __func__,			    lastlog_file, strerror(errno));			return (0);		}	}	return (1);}static intlastlog_perform_login(struct logininfo *li){	struct lastlog last;	int fd;	/* create our struct lastlog */	lastlog_construct(li, &last);	if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))		return (0);	/* write the entry */	if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {		close(fd);		logit("%s: Error writing to %s: %s", __func__,		    LASTLOG_FILE, strerror(errno));		return (0);	}	close(fd);	return (1);}intlastlog_write_entry(struct logininfo *li){	switch(li->type) {	case LTYPE_LOGIN:		return (lastlog_perform_login(li));	default:		logit("%s: Invalid type field", __func__);		return (0);	}}static voidlastlog_populate_entry(struct logininfo *li, struct lastlog *last){	line_fullname(li->line, last->ll_line, sizeof(li->line));	strlcpy(li->hostname, last->ll_host,	    MIN_SIZEOF(li->hostname, last->ll_host));	li->tv_sec = last->ll_time;}intlastlog_get_entry(struct logininfo *li){	struct lastlog last;	int fd, ret;	if (!lastlog_openseek(li, &fd, O_RDONLY))		return (0);	ret = atomicio(read, fd, &last, sizeof(last));	close(fd);	switch (ret) {	case 0:		memset(&last, '\0', sizeof(last));		/* FALLTHRU */	case sizeof(last):		lastlog_populate_entry(li, &last);		return (1);	case -1:		error("%s: Error reading from %s: %s", __func__,		    LASTLOG_FILE, strerror(errno));		return (0);	default:		error("%s: Error reading from %s: Expecting %d, got %d",		    __func__, LASTLOG_FILE, sizeof(last), ret);		return (0);	}	/* NOTREACHED */	return (0);}#endif /* USE_LASTLOG */#ifdef USE_BTMP  /*   * Logs failed login attempts in _PATH_BTMP if that exists.   * The most common login failure is to give password instead of username.   * So the _PATH_BTMP file checked for the correct permission, so that   * only root can read it.   */voidrecord_failed_login(const char *username, const char *hostname,    const char *ttyn){	int fd;	struct utmp ut;	struct sockaddr_storage from;	size_t fromlen = sizeof(from);	struct sockaddr_in *a4;	struct sockaddr_in6 *a6;	time_t t;	struct stat fst;	if (geteuid() != 0)		return;	if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) {		debug("Unable to open the btmp file %s: %s", _PATH_BTMP,		    strerror(errno));		return;	}	if (fstat(fd, &fst) < 0) {		logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP,		    strerror(errno));		goto out;	}	if((fst.st_mode & (S_IRWXG | S_IRWXO)) || (fst.st_uid != 0)){		logit("Excess permission or bad ownership on file %s",		    _PATH_BTMP);		goto out;	}	memset(&ut, 0, sizeof(ut));	/* strncpy because we don't necessarily want nul termination */	strncpy(ut.ut_user, username, sizeof(ut.ut_user));	strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line));	time(&t);	ut.ut_time = t;     /* ut_time is not always a time_t */	ut.ut_type = LOGIN_PROCESS;	ut.ut_pid = getpid();	/* strncpy because we don't necessarily want nul termination */	strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));	if (packet_connection_is_on_socket() &&	    getpeername(packet_get_connection_in(),	    (struct sockaddr *)&from, &fromlen) == 0) {		ipv64_normalise_mapped(&from, &fromlen);		if (from.ss_family == AF_INET) {			a4 = (struct sockaddr_in *)&from;			memcpy(&ut.ut_addr, &(a4->sin_addr),			    MIN_SIZEOF(ut.ut_addr, a4->sin_addr));		}#ifdef HAVE_ADDR_V6_IN_UTMP		if (from.ss_family == AF_INET6) {			a6 = (struct sockaddr_in6 *)&from;			memcpy(&ut.ut_addr_v6, &(a6->sin6_addr),			    MIN_SIZEOF(ut.ut_addr_v6, a6->sin6_addr));		}#endif	}	if (atomicio(vwrite, fd, &ut, sizeof(ut)) != sizeof(ut))		error("Failed to write to %s: %s", _PATH_BTMP,		    strerror(errno));out:	close(fd);}#endif	/* USE_BTMP */

⌨️ 快捷键说明

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