1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Author: Tatu Ylonen <ylo@cs.hut.fi> 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * All rights reserved 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Rhosts authentication. This file contains code to check whether to admit 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * the login based on rhosts authentication. This file also processes 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * /etc/hosts.equiv. 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * As far as I am concerned, the code I have written for this software 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * can be used freely for any purpose. Any derived versions of this 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * software must be clearly marked as such, and if the derived work is 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * incompatible with the protocol description in the RFC file, it must be 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * called by a name other than "ssh" or "Secure Shell". 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/stat.h> 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_NETGROUP_H 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <netgroup.h> 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <pwd.h> 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "packet.h" 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "buffer.h" 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "uidswap.h" 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "pathnames.h" 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 37d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "misc.h" 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "servconf.h" 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "canohost.h" 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "key.h" 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "hostfile.h" 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "auth.h" 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* import */ 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern ServerOptions options; 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern int use_privsep; 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This function processes an rhosts-style file (.rhosts, .shosts, or 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * /etc/hosts.equiv). This returns true if authentication can be granted 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * based on the file, and returns zero otherwise. 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancheck_rhosts_file(const char *filename, const char *hostname, 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *ipaddr, const char *client_user, 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *server_user) 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FILE *f; 60d059297112922cabb0c674840589be8db821fd9aAdam Langley#define RBUFLN 1024 61d059297112922cabb0c674840589be8db821fd9aAdam Langley char buf[RBUFLN];/* Must not be larger than host, user, dummy below. */ 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int fd; 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat st; 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Open the .rhosts file, deny if unreadable */ 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1) 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fstat(fd, &st) == -1) { 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!S_ISREG(st.st_mode)) { 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("User %s hosts file %s is not a regular file", 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman server_user, filename); 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman unset_nonblock(fd); 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((f = fdopen(fd, "r")) == NULL) { 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (fgets(buf, sizeof(buf), f)) { 84d059297112922cabb0c674840589be8db821fd9aAdam Langley /* All three must have length >= buf to avoid overflows. */ 85d059297112922cabb0c674840589be8db821fd9aAdam Langley char hostbuf[RBUFLN], userbuf[RBUFLN], dummy[RBUFLN]; 86d059297112922cabb0c674840589be8db821fd9aAdam Langley char *host, *user, *cp; 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int negated; 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ; 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == '#' || *cp == '\n' || !*cp) 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NO_PLUS is supported at least on OSF/1. We skip it (we 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * don't ever support the plus syntax). 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strncmp(cp, "NO_PLUS", 7) == 0) 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This should be safe because each buffer is as big as the 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * whole string, and thus cannot be overwritten. 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf, 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dummy)) { 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 0: 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Found empty line in %.100s.", filename); 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 1: 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Host name only. */ 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strlcpy(userbuf, server_user, sizeof(userbuf)); 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 2: 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Got both host and user name. */ 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 3: 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Found garbage in %.100s.", filename); 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Weird... */ 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = hostbuf; 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman user = userbuf; 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman negated = 0; 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Process negated host names, or positive netgroups. */ 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (host[0] == '-') { 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman negated = 1; 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host++; 133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (host[0] == '+') 134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host++; 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (user[0] == '-') { 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman negated = 1; 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman user++; 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (user[0] == '+') 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman user++; 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Check for empty host/user names (particularly '+'). */ 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!host[0] || !user[0]) { 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* We come here if either was '+' or '-'. */ 145d059297112922cabb0c674840589be8db821fd9aAdam Langley auth_debug_add("Ignoring wild host/user names " 146d059297112922cabb0c674840589be8db821fd9aAdam Langley "in %.100s.", filename); 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Verify that host name matches. */ 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (host[0] == '@') { 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!innetgr(host + 1, hostname, NULL, NULL) && 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman !innetgr(host + 1, ipaddr, NULL, NULL)) 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 154d059297112922cabb0c674840589be8db821fd9aAdam Langley } else if (strcasecmp(host, hostname) && 155d059297112922cabb0c674840589be8db821fd9aAdam Langley strcmp(host, ipaddr) != 0) 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; /* Different hostname. */ 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Verify that user name matches. */ 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (user[0] == '@') { 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!innetgr(user + 1, NULL, client_user, NULL)) 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (strcmp(user, client_user) != 0) 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; /* Different username. */ 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Found the user and host. */ 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fclose(f); 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* If the entry was negated, deny access. */ 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (negated) { 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Matched negative entry in %.100s.", 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman filename); 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Accept authentication. */ 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Authentication using this file denied. */ 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fclose(f); 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Tries to authenticate the user using the .shosts or .rhosts file. Returns 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * true if authentication succeeds. If ignore_rhosts is true, only 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored). 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanauth_rhosts(struct passwd *pw, const char *client_user) 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *hostname, *ipaddr; 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman hostname = get_canonical_hostname(options.use_dns); 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ipaddr = get_remote_ipaddr(); 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return auth_rhosts2(pw, client_user, hostname, ipaddr); 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanauth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname, 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *ipaddr) 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char buf[1024]; 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat st; 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static const char *rhosts_files[] = {".shosts", ".rhosts", NULL}; 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int rhosts_file_index; 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s", 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman client_user, hostname, ipaddr); 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Switch to the user's uid. */ 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman temporarily_use_uid(pw); 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 214d059297112922cabb0c674840589be8db821fd9aAdam Langley * Quick check: if the user has no .shosts or .rhosts files and 215d059297112922cabb0c674840589be8db821fd9aAdam Langley * no system hosts.equiv/shosts.equiv files exist then return 216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * failure immediately without doing costly lookups from name 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * servers. 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rhosts_file_index++) { 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Check users .rhosts or .shosts. */ 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(buf, sizeof buf, "%.500s/%.100s", 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pw->pw_dir, rhosts_files[rhosts_file_index]); 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (stat(buf, &st) >= 0) 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Switch back to privileged uid. */ 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman restore_uid(); 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 230d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 231d059297112922cabb0c674840589be8db821fd9aAdam Langley * Deny if The user has no .shosts or .rhosts file and there 232d059297112922cabb0c674840589be8db821fd9aAdam Langley * are no system-wide files. 233d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!rhosts_files[rhosts_file_index] && 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman stat(_PATH_RHOSTS_EQUIV, &st) < 0 && 236d059297112922cabb0c674840589be8db821fd9aAdam Langley stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) { 237d059297112922cabb0c674840589be8db821fd9aAdam Langley debug3("%s: no hosts access files exist", __func__); 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 239d059297112922cabb0c674840589be8db821fd9aAdam Langley } 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 241d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 242d059297112922cabb0c674840589be8db821fd9aAdam Langley * If not logging in as superuser, try /etc/hosts.equiv and 243d059297112922cabb0c674840589be8db821fd9aAdam Langley * shosts.equiv. 244d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 245d059297112922cabb0c674840589be8db821fd9aAdam Langley if (pw->pw_uid == 0) 246d059297112922cabb0c674840589be8db821fd9aAdam Langley debug3("%s: root user, ignoring system hosts files", __func__); 247d059297112922cabb0c674840589be8db821fd9aAdam Langley else { 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman client_user, pw->pw_name)) { 250d059297112922cabb0c674840589be8db821fd9aAdam Langley auth_debug_add("Accepted for %.100s [%.100s] by " 251d059297112922cabb0c674840589be8db821fd9aAdam Langley "/etc/hosts.equiv.", hostname, ipaddr); 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman client_user, pw->pw_name)) { 256d059297112922cabb0c674840589be8db821fd9aAdam Langley auth_debug_add("Accepted for %.100s [%.100s] by " 257d059297112922cabb0c674840589be8db821fd9aAdam Langley "%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 261d059297112922cabb0c674840589be8db821fd9aAdam Langley 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Check that the home directory is owned by root or the user, and is 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * not group or world writable. 265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (stat(pw->pw_dir, &st) < 0) { 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("Rhosts authentication refused for %.100s: " 268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "no home directory %.200s", pw->pw_name, pw->pw_dir); 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Rhosts authentication refused for %.100s: " 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "no home directory %.200s", pw->pw_name, pw->pw_dir); 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (options.strict_modes && 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (st.st_mode & 022) != 0)) { 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("Rhosts authentication refused for %.100s: " 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "bad ownership or modes for home directory.", pw->pw_name); 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Rhosts authentication refused for %.100s: " 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "bad ownership or modes for home directory.", pw->pw_name); 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Temporarily use the user's uid. */ 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman temporarily_use_uid(pw); 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Check all .rhosts files (currently .shosts and .rhosts). */ 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rhosts_file_index++) { 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Check users .rhosts or .shosts. */ 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(buf, sizeof buf, "%.500s/%.100s", 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pw->pw_dir, rhosts_files[rhosts_file_index]); 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (stat(buf, &st) < 0) 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Make sure that the file is either owned by the user or by 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * root, and make sure it is not writable by anyone but the 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * owner. This is to help avoid novices accidentally 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * allowing access to their account by anyone. 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (options.strict_modes && 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (st.st_mode & 022) != 0)) { 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman logit("Rhosts authentication refused for %.100s: bad modes for %.200s", 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pw->pw_name, buf); 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Bad file modes for %.200s", buf); 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 308d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 309d059297112922cabb0c674840589be8db821fd9aAdam Langley * Check if we have been configured to ignore .rhosts 310d059297112922cabb0c674840589be8db821fd9aAdam Langley * and .shosts files. 311d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (options.ignore_rhosts) { 313d059297112922cabb0c674840589be8db821fd9aAdam Langley auth_debug_add("Server has been configured to " 314d059297112922cabb0c674840589be8db821fd9aAdam Langley "ignore %.100s.", rhosts_files[rhosts_file_index]); 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Check if authentication is permitted by the file. */ 318d059297112922cabb0c674840589be8db821fd9aAdam Langley if (check_rhosts_file(buf, hostname, ipaddr, 319d059297112922cabb0c674840589be8db821fd9aAdam Langley client_user, pw->pw_name)) { 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman auth_debug_add("Accepted by %.100s.", 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rhosts_files[rhosts_file_index]); 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Restore the privileged uid. */ 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman restore_uid(); 324d059297112922cabb0c674840589be8db821fd9aAdam Langley auth_debug_add("Accepted host %s ip %s client_user " 325d059297112922cabb0c674840589be8db821fd9aAdam Langley "%s server_user %s", hostname, ipaddr, 326d059297112922cabb0c674840589be8db821fd9aAdam Langley client_user, pw->pw_name); 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Restore the privileged uid. */ 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman restore_uid(); 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanauth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *ipaddr) 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return auth_rhosts2_raw(pw, client_user, hostname, ipaddr); 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 342