void
construct_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
}
Esempio n. 2
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);
	default:
		logit("%s: Invalid type field", __func__);
		return (0);
	}
}
#endif /* LASTLOG_WRITE_PUTUTXLINE */

#ifdef HAVE_GETLASTLOGXBYNAME
int
lastlog_get_entry(struct logininfo *li)
{
	struct lastlogx l, *ll;

	if ((ll = getlastlogxbyname(li->username, &l)) == NULL) {
		memset(&l, '\0', sizeof(l));
		ll = &l;
	}
	line_fullname(li->line, ll->ll_line, sizeof(li->line));
	strlcpy(li->hostname, ll->ll_host,
		MIN_SIZEOF(li->hostname, ll->ll_host));
	li->tv_sec = ll->ll_tv.tv_sec;
	li->tv_usec = ll->ll_tv.tv_usec;
	return (1);
}
#else /* HAVE_GETLASTLOGXBYNAME */
int
lastlog_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):
		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;
		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, (int)sizeof(last), ret);
		return (0);
	}

	/* NOTREACHED */
	return (0);
}
Esempio n. 3
0
		/* 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);
}
#endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */

#ifdef LASTLOG_WRITE_PUTUTXLINE
int
lastlog_write_entry(struct logininfo *li)
{
	switch(li->type) {
	case LTYPE_LOGIN:
		return 1; /* lastlog written by pututxline */
	default:
		logit("lastlog_write_entry: Invalid type field");
		return 0;
	}
}
#else /* LASTLOG_WRITE_PUTUTXLINE */
int
lastlog_write_entry(struct logininfo *li)
{
	struct lastlog last;
	int fd;

	switch(li->type) {
	case LTYPE_LOGIN:
		/* create our struct lastlog */
		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;
	
		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);
	default:
		logit("%s: Invalid type field", __func__);
		return (0);
	}
}
static void
lastlog_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;
}
static void
lastlog_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;
}
Esempio n. 6
0
int
utmpx_get_entry(struct logininfo *li)
{
	struct utmpx *utx;

	if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0)
		return (0);
	utx = getutxuser(li->username);
	if (utx == NULL) {
		endutxent();
		return (0);
	}

	line_fullname(li->line, utx->ut_line,
	    MIN_SIZEOF(li->line, utx->ut_line));
	strlcpy(li->hostname, utx->ut_host,
	    MIN_SIZEOF(li->hostname, utx->ut_host));
	li->tv_sec = utx->ut_tv.tv_sec;
	li->tv_usec = utx->ut_tv.tv_usec;
	endutxent();
	return (1);
}
/* Return true if this wtmpx entry indicates a login */
static int
wtmpx_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;
}
/* return true if this wtmp entry indicates a login */
static int
wtmp_islogin(struct logininfo *li, struct utmp *ut)
{
	if (strncmp(li->username, ut->ut_name,
		MIN_SIZEOF(li->username, ut->ut_name)) == 0) {
# ifdef HAVE_STRUCT_UTMP_UT_TYPE
		if (ut->ut_type & USER_PROCESS)
			return 1;
# else
		return 1;
# endif
	}
	return 0;
}
Esempio n. 9
0
int
lastlog_get_entry(struct logininfo *li)
{
	struct lastlogx l, *ll;

	if ((ll = getlastlogxbyname(li->username, &l)) == NULL) {
		memset(&l, '\0', sizeof(l));
		ll = &l;
	}
	line_fullname(li->line, ll->ll_line, sizeof(li->line));
	strlcpy(li->hostname, ll->ll_host,
		MIN_SIZEOF(li->hostname, ll->ll_host));
	li->tv_sec = ll->ll_tv.tv_sec;
	li->tv_usec = ll->ll_tv.tv_usec;
	return (1);
}
void
construct_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
}
void
record_failed_login(const char *username, const char *hostname,
    const char *ttyn)
{
	int fd;
	struct utmp ut;
	struct sockaddr_storage from;
	socklen_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_IXGRP | 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);
}
int
wtmpx_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("wtmpx_get_entry: problem opening %s: %s",
		    WTMPX_FILE, strerror(errno));
		return 0;
	}
	if (fstat(fd, &st) != 0) {
		logit("wtmpx_get_entry: couldn't stat %s: %s",
		    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("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) ) {
			found = 1;
# 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;
}
int
wtmp_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("wtmp_get_entry: problem opening %s: %s",
		    WTMP_FILE, strerror(errno));
		return 0;
	}
	if (fstat(fd, &st) != 0) {
		logit("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)) {
			logit("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;
}