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

📄 loginrec.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * line_abbrevname(): Return the abbreviated (usually four-character) * form of the line (Just use the last <dstsize> characters of the * full name.) * * NOTE: use strncpy because we do NOT necessarily want zero * termination */char *line_abbrevname(char *dst, const char *src, int dstsize){	size_t len;	memset(dst, '\0', dstsize);	/* Always skip prefix if present */	if (strncmp(src, "/dev/", 5) == 0)		src += 5;#ifdef WITH_ABBREV_NO_TTY	if (strncmp(src, "tty", 3) == 0)		src += 3;#endif	len = strlen(src);	if (len > 0) {		if (((int)len - dstsize) > 0)			src +=  ((int)len - dstsize);		/* note: _don't_ change this to strlcpy */		strncpy(dst, src, (size_t)dstsize);	}	return (dst);}/** ** utmp utility functions ** ** These functions manipulate struct utmp, taking system differences ** into account. **/#if defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN)/* build the utmp structure */voidset_utmp_time(struct logininfo *li, struct utmp *ut){# if defined(HAVE_TV_IN_UTMP)	ut->ut_tv.tv_sec = li->tv_sec;	ut->ut_tv.tv_usec = li->tv_usec;# elif defined(HAVE_TIME_IN_UTMP)	ut->ut_time = li->tv_sec;# endif}voidconstruct_utmp(struct logininfo *li,		    struct utmp *ut){# ifdef HAVE_ADDR_V6_IN_UTMP	struct sockaddr_in6 *sa6;# endif	memset(ut, '\0', sizeof(*ut));	/* First fill out fields used for both logins and logouts */# ifdef HAVE_ID_IN_UTMP	line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id));# endif# ifdef HAVE_TYPE_IN_UTMP	/* This is done here to keep utmp constants out of struct logininfo */	switch (li->type) {	case LTYPE_LOGIN:		ut->ut_type = USER_PROCESS;#ifdef _UNICOS		cray_set_tmpdir(ut);#endif		break;	case LTYPE_LOGOUT:		ut->ut_type = DEAD_PROCESS;#ifdef _UNICOS		cray_retain_utmp(ut, li->pid);#endif		break;	}# endif	set_utmp_time(li, ut);	line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line));# ifdef HAVE_PID_IN_UTMP	ut->ut_pid = li->pid;# endif	/* If we're logging out, leave all other fields blank */	if (li->type == LTYPE_LOGOUT)		return;	/*	 * These fields are only used when logging in, and are blank	 * for logouts.	 */	/* Use strncpy because we don't necessarily want null termination */	strncpy(ut->ut_name, li->username,	    MIN_SIZEOF(ut->ut_name, li->username));# ifdef HAVE_HOST_IN_UTMP	strncpy(ut->ut_host, li->hostname,	    MIN_SIZEOF(ut->ut_host, li->hostname));# endif# ifdef HAVE_ADDR_IN_UTMP	/* this is just a 32-bit IP address */	if (li->hostaddr.sa.sa_family == AF_INET)		ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;# endif# ifdef HAVE_ADDR_V6_IN_UTMP	/* this is just a 128-bit IPv6 address */	if (li->hostaddr.sa.sa_family == AF_INET6) {		sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa);		memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16);		if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {			ut->ut_addr_v6[0] = ut->ut_addr_v6[3];			ut->ut_addr_v6[1] = 0;			ut->ut_addr_v6[2] = 0;			ut->ut_addr_v6[3] = 0;		}	}# endif}#endif /* USE_UTMP || USE_WTMP || USE_LOGIN *//** ** utmpx utility functions ** ** These functions manipulate struct utmpx, accounting for system ** variations. **/#if defined(USE_UTMPX) || defined (USE_WTMPX)/* build the utmpx structure */voidset_utmpx_time(struct logininfo *li, struct utmpx *utx){# if defined(HAVE_TV_IN_UTMPX)	utx->ut_tv.tv_sec = li->tv_sec;	utx->ut_tv.tv_usec = li->tv_usec;# elif defined(HAVE_TIME_IN_UTMPX)	utx->ut_time = li->tv_sec;# endif}voidconstruct_utmpx(struct logininfo *li, struct utmpx *utx){# ifdef HAVE_ADDR_V6_IN_UTMP	struct sockaddr_in6 *sa6;#  endif	memset(utx, '\0', sizeof(*utx));# ifdef HAVE_ID_IN_UTMPX	line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id));# endif	/* this is done here to keep utmp constants out of loginrec.h */	switch (li->type) {	case LTYPE_LOGIN:		utx->ut_type = USER_PROCESS;		break;	case LTYPE_LOGOUT:		utx->ut_type = DEAD_PROCESS;		break;	}	line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line));	set_utmpx_time(li, utx);	utx->ut_pid = li->pid;	/* strncpy(): Don't necessarily want null termination */	strncpy(utx->ut_name, li->username,	    MIN_SIZEOF(utx->ut_name, li->username));	if (li->type == LTYPE_LOGOUT)		return;	/*	 * These fields are only used when logging in, and are blank	 * for logouts.	 */# ifdef HAVE_HOST_IN_UTMPX	strncpy(utx->ut_host, li->hostname,	    MIN_SIZEOF(utx->ut_host, li->hostname));# endif# ifdef HAVE_ADDR_IN_UTMPX	/* this is just a 32-bit IP address */	if (li->hostaddr.sa.sa_family == AF_INET)		utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;# endif# ifdef HAVE_ADDR_V6_IN_UTMP	/* this is just a 128-bit IPv6 address */	if (li->hostaddr.sa.sa_family == AF_INET6) {		sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa);		memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16);		if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {			ut->ut_addr_v6[0] = ut->ut_addr_v6[3];			ut->ut_addr_v6[1] = 0;			ut->ut_addr_v6[2] = 0;			ut->ut_addr_v6[3] = 0;		}	}# endif# ifdef HAVE_SYSLEN_IN_UTMPX	/* ut_syslen is the length of the utx_host string */	utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host));# endif}#endif /* USE_UTMPX || USE_WTMPX *//** ** Low-level utmp functions **//* FIXME: (ATL) utmp_write_direct needs testing */#ifdef USE_UTMP/* if we can, use pututline() etc. */# if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \	defined(HAVE_PUTUTLINE)#  define UTMP_USE_LIBRARY# endif/* write a utmp entry with the system's help (pututline() and pals) */# ifdef UTMP_USE_LIBRARYstatic intutmp_write_library(struct logininfo *li, struct utmp *ut){	setutent();	pututline(ut);#  ifdef HAVE_ENDUTENT	endutent();#  endif	return (1);}# else /* UTMP_USE_LIBRARY *//*  * Write a utmp entry direct to the file * This is a slightly modification of code in OpenBSD's login.c */static intutmp_write_direct(struct logininfo *li, struct utmp *ut){	struct utmp old_ut;	register int fd;	int tty;	/* FIXME: (ATL) ttyslot() needs local implementation */#if defined(HAVE_GETTTYENT)	struct ttyent *ty;	tty=0;	setttyent();	while (NULL != (ty = getttyent())) {		tty++;		if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line)))			break;	}	endttyent();	if (NULL == ty) {		logit("%s: tty not found", __func__);		return (0);	}#else /* FIXME */	tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */#endif /* HAVE_GETTTYENT */	if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) {		off_t pos, ret;		pos = (off_t)tty * sizeof(struct utmp);		if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {			logit("%s: lseek: %s", __func__, strerror(errno));			return (0);		}		if (ret != pos) {			logit("%s: Couldn't seek to tty %d slot in %s", 			    __func__, tty, UTMP_FILE);			return (0);		}		/*		 * Prevent luser from zero'ing out ut_host.		 * If the new ut_line is empty but the old one is not		 * and ut_line and ut_name match, preserve the old ut_line.		 */		if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) &&		    (ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') &&		    (strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) &&		    (strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0))			memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host));		if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {			logit("%s: lseek: %s", __func__, strerror(errno));			return (0);		}		if (ret != pos) {			logit("%s: Couldn't seek to tty %d slot in %s",			    __func__, tty, UTMP_FILE);			return (0);		}		if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {			logit("%s: error writing %s: %s", __func__,			    UTMP_FILE, strerror(errno));		}		close(fd);		return (1);	} else {		return (0);	}}# endif /* UTMP_USE_LIBRARY */static intutmp_perform_login(struct logininfo *li){	struct utmp ut;	construct_utmp(li, &ut);# ifdef UTMP_USE_LIBRARY	if (!utmp_write_library(li, &ut)) {		logit("%s: utmp_write_library() failed", __func__);		return (0);	}# else	if (!utmp_write_direct(li, &ut)) {		logit("%s: utmp_write_direct() failed", __func__);		return (0);	}# endif	return (1);}static intutmp_perform_logout(struct logininfo *li){	struct utmp ut;	construct_utmp(li, &ut);# ifdef UTMP_USE_LIBRARY	if (!utmp_write_library(li, &ut)) {		logit("%s: utmp_write_library() failed", __func__);		return (0);	}# else	if (!utmp_write_direct(li, &ut)) {		logit("%s: utmp_write_direct() failed", __func__);		return (0);	}# endif	return (1);}intutmp_write_entry(struct logininfo *li){	switch(li->type) {	case LTYPE_LOGIN:		return (utmp_perform_login(li));	case LTYPE_LOGOUT:		return (utmp_perform_logout(li));	default:		logit("%s: invalid type field", __func__);		return (0);	}}#endif /* USE_UTMP *//** ** Low-level utmpx functions **//* not much point if we don't want utmpx entries */#ifdef USE_UTMPX/* if we have the wherewithall, use pututxline etc. */# if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \	defined(HAVE_PUTUTXLINE)#  define UTMPX_USE_LIBRARY# endif/* write a utmpx entry with the system's help (pututxline() and pals) */# ifdef UTMPX_USE_LIBRARYstatic intutmpx_write_library(struct logininfo *li, struct utmpx *utx){	setutxent();	pututxline(utx);#  ifdef HAVE_ENDUTXENT	endutxent();#  endif	return (1);}# else /* UTMPX_USE_LIBRARY *//* write a utmp entry direct to the file */static intutmpx_write_direct(struct logininfo *li, struct utmpx *utx){	logit("%s: not implemented!", __func__);	return (0);}# endif /* UTMPX_USE_LIBRARY */static intutmpx_perform_login(struct logininfo *li){	struct utmpx utx;	construct_utmpx(li, &utx);# ifdef UTMPX_USE_LIBRARY	if (!utmpx_write_library(li, &utx)) {		logit("%s: utmp_write_library() failed", __func__);		return (0);	}# else	if (!utmpx_write_direct(li, &ut)) {		logit("%s: utmp_write_direct() failed", __func__);		return (0);	}# endif	return (1);}static intutmpx_perform_logout(struct logininfo *li){	struct utmpx utx;	construct_utmpx(li, &utx);# ifdef HAVE_ID_IN_UTMPX	line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id));# endif# ifdef HAVE_TYPE_IN_UTMPX	utx.ut_type = DEAD_PROCESS;# endif# ifdef UTMPX_USE_LIBRARY	utmpx_write_library(li, &utx);# else	utmpx_write_direct(li, &utx);# endif	return (1);}intutmpx_write_entry(struct logininfo *li){	switch(li->type) {	case LTYPE_LOGIN:		return (utmpx_perform_login(li));	case LTYPE_LOGOUT:		return (utmpx_perform_logout(li));	default:		logit("%s: invalid type field", __func__);		return (0);	}}#endif /* USE_UTMPX *//** ** Low-level wtmp functions **/#ifdef USE_WTMP/*  * Write a wtmp entry direct to the end of the file * This is a slight modification of code in OpenBSD's logwtmp.c */static intwtmp_write(struct logininfo *li, struct utmp *ut){	struct stat buf;	int fd, ret = 1;	if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) {		logit("%s: problem writing %s: %s", __func__,		    WTMP_FILE, strerror(errno));		return (0);	}	if (fstat(fd, &buf) == 0)		if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {			ftruncate(fd, buf.st_size);			logit("%s: problem writing %s: %s", __func__,			    WTMP_FILE, strerror(errno));			ret = 0;		}	close(fd);	return (ret);}static intwtmp_perform_login(struct logininfo *li){	struct utmp ut;	construct_utmp(li, &ut);	return (wtmp_write(li, &ut));}static intwtmp_perform_logout(struct logininfo *li){	struct utmp ut;	construct_utmp(li, &ut);	return (wtmp_write(li, &ut));}intwtmp_write_entry(struct logininfo *li){	switch(li->type) {	case LTYPE_LOGIN:		return (wtmp_perform_login(li));	case LTYPE_LOGOUT:		return (wtmp_perform_logout(li));	default:		logit("%s: invalid type field", __func__);		return (0);	}}/*  * Notes on fetching login data from wtmp/wtmpx * * Logouts are usually recorded with (amongst other things) a blank * username on a given tty line.  However, some systems (HP-UX is one)

⌨️ 快捷键说明

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