Esempio n. 1
0
/*
 * Returns the local/remote IP-address/hostname of socket as a string.
 * The returned string must be freed.
 */
static char *
get_socket_address(int sock, int remote, int flags)
{
	struct sockaddr_storage addr;
	socklen_t addrlen;
	char ntop[NI_MAXHOST];
	int r;

	/* Get IP address of client. */
	addrlen = sizeof(addr);
	memset(&addr, 0, sizeof(addr));

	if (remote) {
		if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
		    < 0)
			return NULL;
	} else {
		if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
		    < 0)
			return NULL;
	}

	/* Work around Linux IPv6 weirdness */
	if (addr.ss_family == AF_INET6) {
		addrlen = sizeof(struct sockaddr_in6);
		ipv64_normalise_mapped(&addr, &addrlen);
	}

	switch (addr.ss_family) {
	case AF_INET:
	case AF_INET6:
		/* Get the address in ascii. */
		if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
		    sizeof(ntop), NULL, 0, flags)) != 0) {
			error("get_socket_address: getnameinfo %d failed: %s",
			    flags, ssh_gai_strerror(r));
			return NULL;
		}
		return xstrdup(ntop);
	case AF_UNIX:
		/* Get the Unix domain socket path. */
		return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
	default:
		/* We can't look up remote Unix domain sockets. */
		return NULL;
	}
}
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);
}
Esempio n. 3
0
static char *
get_remote_hostname(int sock, int use_dns)
{
	struct sockaddr_storage from;
	int i;
	socklen_t fromlen;
	struct addrinfo hints, *ai, *aitop;
	char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];

	/* Get IP address of client. */
	fromlen = sizeof(from);
	memset(&from, 0, sizeof(from));
	if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
		debug("getpeername failed: %.100s", strerror(errno));
		cleanup_exit(255);
	}

	if (from.ss_family == AF_INET)
		check_ip_options(sock, ntop);

	ipv64_normalise_mapped(&from, &fromlen);

	if (from.ss_family == AF_INET6)
		fromlen = sizeof(struct sockaddr_in6);

	if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
	    NULL, 0, NI_NUMERICHOST) != 0)
		fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");

	if (!use_dns)
		return xstrdup(ntop);

	debug3("Trying to reverse map address %.100s.", ntop);
	/* Map the IP address to a host name. */
	if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
	    NULL, 0, NI_NAMEREQD) != 0) {
		/* Host name not found.  Use ip address. */
		return xstrdup(ntop);
	}

	/*
	 * if reverse lookup result looks like a numeric hostname,
	 * someone is trying to trick us by PTR record like following:
	 *	1.1.1.10.in-addr.arpa.	IN PTR	2.3.4.5
	 */
	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
	hints.ai_flags = AI_NUMERICHOST;
	if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
		logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
		    name, ntop);
		freeaddrinfo(ai);
		return xstrdup(ntop);
	}

	/*
	 * Convert it to all lowercase (which is expected by the rest
	 * of this software).
	 */
	for (i = 0; name[i]; i++)
		if (isupper(name[i]))
			name[i] = (char)tolower(name[i]);
	/*
	 * Map it back to an IP address and check that the given
	 * address actually is an address of this host.  This is
	 * necessary because anyone with access to a name server can
	 * define arbitrary names for an IP address. Mapping from
	 * name to IP address can be trusted better (but can still be
	 * fooled if the intruder has access to the name server of
	 * the domain).
	 */
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = from.ss_family;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
		logit("reverse mapping checking getaddrinfo for %.700s "
		    "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
		return xstrdup(ntop);
	}
	/* Look for the address from the list of addresses. */
	for (ai = aitop; ai; ai = ai->ai_next) {
		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
		    sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
		    (strcmp(ntop, ntop2) == 0))
				break;
	}
	freeaddrinfo(aitop);
	/* If we reached the end of the list, the address was not there. */
	if (!ai) {
		/* Address not found for the host name. */
		logit("Address %.100s maps to %.600s, but this does not "
		    "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
		    ntop, name);
		return xstrdup(ntop);
	}
	return xstrdup(name);
}