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

📄 loginrec.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
	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:		log("wtmp_write_entry: invalid type field");		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) * 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) {		log("wtmp_get_entry: problem opening %s: %s",		    WTMP_FILE, strerror(errno));		return 0;	}	if (fstat(fd, &st) != 0) {		log("wtmp_get_entry: couldn't stat %s: %s",		    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)) {			log("wtmp_get_entry: read of %s failed: %s",			    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){	struct stat buf;	int fd, ret = 1;	if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) {		log("wtmpx_write: problem opening %s: %s",		    WTMPX_FILE, strerror(errno));		return 0;	}	if (fstat(fd, &buf) == 0)		if (atomicio(write, fd, utx, sizeof(*utx)) != sizeof(*utx)) {			ftruncate(fd, buf.st_size);			log("wtmpx_write: problem writing %s: %s",			    WTMPX_FILE, strerror(errno));			ret = 0;		}	(void)close(fd);	return ret;}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:		log("wtmpx_write_entry: invalid type field");		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) {		log("wtmpx_get_entry: problem opening %s: %s",		    WTMPX_FILE, strerror(errno));		return 0;	}	if (fstat(fd, &st) != 0) {		log("wtmpx_get_entry: couldn't stat %s: %s",		    WTMP_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)) {			log("wtmpx_get_entry: read of %s failed: %s",			    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) ) {# ifdef HAVE_TV_IN_UTMPX			li->tv_sec = utx.ut_tv.tv_sec;# else#  ifdef HAVE_TIME_IN_UTMPX			li->tv_sec = utx.ut_time;#  endif# endif			line_fullname(li->line, utx.ut_line, sizeof(li->line));# ifdef 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;	if (! (ut = (struct utmp *)malloc(sizeof(*ut)))) {		log("syslogin_perform_login: couldn't malloc()");		return 0;	}	construct_utmp(li, ut);	login(ut);	return 1;}static intsyslogin_perform_logout(struct logininfo *li){# ifdef HAVE_LOGOUT	char line[8];	(void)line_stripname(line, li->line, sizeof(line));	if (!logout(line)) {		log("syslogin_perform_logout: logout() returned an error");#  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:		log("syslogin_write_entry: Invalid type field");		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));	(void)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) {		log("lastlog_perform_login: Couldn't stat %s: %s", 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:			log("lastlog_openseek: %.100s is not a file or directory!",			    LASTLOG_FILE);			return 0;	}	*fd = open(lastlog_file, filemode);	if ( *fd < 0) {		debug("lastlog_openseek: Couldn't open %s: %s",		    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 ) {			log("lastlog_openseek: %s->lseek(): %s",			 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(write, fd, &last, sizeof(last)) != sizeof(last)) {		close(fd);		log("lastlog_write_filemode: Error writing to %s: %s",		    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:		log("lastlog_write_entry: Invalid type field");		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;	if (!lastlog_openseek(li, &fd, O_RDONLY))		return 0;	if (atomicio(read, fd, &last, sizeof(last)) != sizeof(last)) {		close(fd);		log("lastlog_get_entry: Error reading from %s: %s",		    LASTLOG_FILE, strerror(errno));		return 0;	}	close(fd);	lastlog_populate_entry(li, &last);	return 1;}#endif /* USE_LASTLOG */

⌨️ 快捷键说明

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