11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi>
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *                    All rights reserved
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Rhosts authentication.  This file contains code to check whether to admit
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the login based on rhosts authentication.  This file also processes
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * /etc/hosts.equiv.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h>
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_NETGROUP_H
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <netgroup.h>
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "uidswap.h"
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "pathnames.h"
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h"
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import */
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options;
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int use_privsep;
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This function processes an rhosts-style file (.rhosts, .shosts, or
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * /etc/hosts.equiv).  This returns true if authentication can be granted
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * based on the file, and returns zero otherwise.
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcheck_rhosts_file(const char *filename, const char *hostname,
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		  const char *ipaddr, const char *client_user,
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		  const char *server_user)
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	FILE *f;
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[1024];	/* Must not be larger than host, user, dummy below. */
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fd;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Open the .rhosts file, deny if unreadable */
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1)
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fstat(fd, &st) == -1) {
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!S_ISREG(st.st_mode)) {
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("User %s hosts file %s is not a regular file",
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    server_user, filename);
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	unset_nonblock(fd);
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((f = fdopen(fd, "r")) == NULL) {
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (fgets(buf, sizeof(buf), f)) {
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* All three must be at least as big as buf to avoid overflows. */
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		int negated;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			;
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '#' || *cp == '\n' || !*cp)
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * NO_PLUS is supported at least on OSF/1.  We skip it (we
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * don't ever support the plus syntax).
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncmp(cp, "NO_PLUS", 7) == 0)
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * This should be safe because each buffer is as big as the
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * whole string, and thus cannot be overwritten.
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf,
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    dummy)) {
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 0:
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Found empty line in %.100s.", filename);
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 1:
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Host name only. */
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(userbuf, server_user, sizeof(userbuf));
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 2:
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Got both host and user name. */
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 3:
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Found garbage in %.100s.", filename);
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Weird... */
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		host = hostbuf;
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		user = userbuf;
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		negated = 0;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Process negated host names, or positive netgroups. */
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (host[0] == '-') {
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			negated = 1;
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			host++;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (host[0] == '+')
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			host++;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (user[0] == '-') {
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			negated = 1;
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			user++;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (user[0] == '+')
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			user++;
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check for empty host/user names (particularly '+'). */
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!host[0] || !user[0]) {
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* We come here if either was '+' or '-'. */
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Ignoring wild host/user names in %.100s.",
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    filename);
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Verify that host name matches. */
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (host[0] == '@') {
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!innetgr(host + 1, hostname, NULL, NULL) &&
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    !innetgr(host + 1, ipaddr, NULL, NULL))
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;	/* Different hostname. */
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Verify that user name matches. */
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (user[0] == '@') {
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!innetgr(user + 1, NULL, client_user, NULL))
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strcmp(user, client_user) != 0)
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;	/* Different username. */
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Found the user and host. */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fclose(f);
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* If the entry was negated, deny access. */
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (negated) {
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Matched negative entry in %.100s.",
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    filename);
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Accept authentication. */
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Authentication using this file denied. */
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fclose(f);
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Tries to authenticate the user using the .shosts or .rhosts file. Returns
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * true if authentication succeeds.  If ignore_rhosts is true, only
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_rhosts(struct passwd *pw, const char *client_user)
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *hostname, *ipaddr;
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	hostname = get_canonical_hostname(options.use_dns);
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ipaddr = get_remote_ipaddr();
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return auth_rhosts2(pw, client_user, hostname, ipaddr);
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const char *ipaddr)
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[1024];
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int rhosts_file_index;
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    client_user, hostname, ipaddr);
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Switch to the user's uid. */
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	temporarily_use_uid(pw);
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Quick check: if the user has no .shosts or .rhosts files, return
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * failure immediately without doing costly lookups from name
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * servers.
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    rhosts_file_index++) {
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check users .rhosts or .shosts. */
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf, "%.500s/%.100s",
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 pw->pw_dir, rhosts_files[rhosts_file_index]);
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (stat(buf, &st) >= 0)
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Switch back to privileged uid. */
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	restore_uid();
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!rhosts_files[rhosts_file_index] &&
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pw->pw_uid != 0) {
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    client_user, pw->pw_name)) {
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    hostname, ipaddr);
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 1;
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    client_user, pw->pw_name)) {
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 1;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Check that the home directory is owned by root or the user, and is
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * not group or world writable.
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(pw->pw_dir, &st) < 0) {
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Rhosts authentication refused for %.100s: "
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "no home directory %.200s", pw->pw_name, pw->pw_dir);
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		auth_debug_add("Rhosts authentication refused for %.100s: "
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "no home directory %.200s", pw->pw_name, pw->pw_dir);
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.strict_modes &&
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (st.st_mode & 022) != 0)) {
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Rhosts authentication refused for %.100s: "
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "bad ownership or modes for home directory.", pw->pw_name);
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		auth_debug_add("Rhosts authentication refused for %.100s: "
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "bad ownership or modes for home directory.", pw->pw_name);
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Temporarily use the user's uid. */
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	temporarily_use_uid(pw);
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Check all .rhosts files (currently .shosts and .rhosts). */
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    rhosts_file_index++) {
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check users .rhosts or .shosts. */
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(buf, sizeof buf, "%.500s/%.100s",
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 pw->pw_dir, rhosts_files[rhosts_file_index]);
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (stat(buf, &st) < 0)
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * Make sure that the file is either owned by the user or by
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * root, and make sure it is not writable by anyone but the
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * owner.  This is to help avoid novices accidentally
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * allowing access to their account by anyone.
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.strict_modes &&
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (st.st_mode & 022) != 0)) {
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    pw->pw_name, buf);
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Bad file modes for %.200s", buf);
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check if we have been configured to ignore .rhosts and .shosts files. */
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.ignore_rhosts) {
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Server has been configured to ignore %.100s.",
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    rhosts_files[rhosts_file_index]);
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Check if authentication is permitted by the file. */
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Accepted by %.100s.",
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    rhosts_files[rhosts_file_index]);
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Restore the privileged uid. */
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			restore_uid();
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				hostname, ipaddr, client_user, pw->pw_name);
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 1;
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Restore the privileged uid. */
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	restore_uid();
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const char *ipaddr)
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood       return auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
322