static int
auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
    const char *ipaddr)
{
	char buf[1024];
	struct stat st;
	static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
	u_int rhosts_file_index;

	debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
	    client_user, hostname, ipaddr);

	/* Switch to the user's uid. */
	temporarily_use_uid(pw);
	/*
	 * Quick check: if the user has no .shosts or .rhosts files, return
	 * failure immediately without doing costly lookups from name
	 * servers.
	 */
	for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
	    rhosts_file_index++) {
		/* Check users .rhosts or .shosts. */
		snprintf(buf, sizeof buf, "%.500s/%.100s",
			 pw->pw_dir, rhosts_files[rhosts_file_index]);
		if (stat(buf, &st) >= 0)
			break;
	}
	/* Switch back to privileged uid. */
	restore_uid();

	/* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
	if (!rhosts_files[rhosts_file_index] &&
	    stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
	    stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
		return 0;

	/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
	if (pw->pw_uid != 0) {
		if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
		    client_user, pw->pw_name)) {
			auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
			    hostname, ipaddr);
			return 1;
		}
		if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
		    client_user, pw->pw_name)) {
			auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
			    hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
			return 1;
		}
	}
	/*
	 * Check that the home directory is owned by root or the user, and is
	 * not group or world writable.
	 */
	if (stat(pw->pw_dir, &st) < 0) {
		logit("Rhosts authentication refused for %.100s: "
		    "no home directory %.200s", pw->pw_name, pw->pw_dir);
		auth_debug_add("Rhosts authentication refused for %.100s: "
		    "no home directory %.200s", pw->pw_name, pw->pw_dir);
		return 0;
	}
	if (options.strict_modes &&
	    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
	    (st.st_mode & 022) != 0)) {
		logit("Rhosts authentication refused for %.100s: "
		    "bad ownership or modes for home directory.", pw->pw_name);
		auth_debug_add("Rhosts authentication refused for %.100s: "
		    "bad ownership or modes for home directory.", pw->pw_name);
		return 0;
	}
	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	/* Check all .rhosts files (currently .shosts and .rhosts). */
	for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
	    rhosts_file_index++) {
		/* Check users .rhosts or .shosts. */
		snprintf(buf, sizeof buf, "%.500s/%.100s",
			 pw->pw_dir, rhosts_files[rhosts_file_index]);
		if (stat(buf, &st) < 0)
			continue;

		/*
		 * Make sure that the file is either owned by the user or by
		 * root, and make sure it is not writable by anyone but the
		 * owner.  This is to help avoid novices accidentally
		 * allowing access to their account by anyone.
		 */
		if (options.strict_modes &&
		    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
		    (st.st_mode & 022) != 0)) {
			logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
			    pw->pw_name, buf);
			auth_debug_add("Bad file modes for %.200s", buf);
			continue;
		}
		/* Check if we have been configured to ignore .rhosts and .shosts files. */
		if (options.ignore_rhosts) {
			auth_debug_add("Server has been configured to ignore %.100s.",
			    rhosts_files[rhosts_file_index]);
			continue;
		}
		/* Check if authentication is permitted by the file. */
		if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
			auth_debug_add("Accepted by %.100s.",
			    rhosts_files[rhosts_file_index]);
			/* Restore the privileged uid. */
			restore_uid();
			auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
				hostname, ipaddr, client_user, pw->pw_name);
			return 1;
		}
	}

	/* Restore the privileged uid. */
	restore_uid();
	return 0;
}
Beispiel #2
0
/* Tries to authenticate the user using the .shosts or .rhosts file.
   Returns true if authentication succeeds.  If config->ignore_rhosts
   is true, only /etc/hosts.equiv will be considered (.rhosts and
   .shosts are ignored), unless the user is root and
   config->ignore_root_rhosts isn't true. */
Boolean ssh_server_auth_hostbased_rhosts(SshUser user_data,
                                         const char *client_user,
                                         void *context)
{
  char buf[1024];
  const char *hostname, *ipaddr;
  struct stat st;
  static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
  unsigned int rhosts_file_index;
  SshConfig config;
  SshServer server = (SshServer) context;
  SshUser effective_user_data =
    ssh_user_initialize_with_uid(geteuid(), FALSE);
  
  config = server->config;

  ssh_userfile_init(ssh_user_name(user_data), ssh_user_uid(user_data),
                    ssh_user_gid(user_data), NULL, NULL);

  /* Get the name, address, and port of the remote host.  */
  hostname = server->common->remote_host;
  ipaddr = server->common->remote_ip;

  /* Quick check: if the user has no .shosts or .rhosts files, return failure
     immediately without doing costly lookups from name servers. */
  for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
       rhosts_file_index++)
    {
      /* Check users .rhosts or .shosts. */
      snprintf(buf, sizeof(buf), "%.500s/%.100s", 
              ssh_user_dir(user_data), rhosts_files[rhosts_file_index]);
      if (ssh_userfile_stat(ssh_user_uid(user_data), buf, &st) >= 0)
        break;
    }

  if (!rhosts_files[rhosts_file_index] && 
      ssh_userfile_stat(ssh_user_uid(user_data), "/etc/hosts.equiv", &st) < 0 &&
      ssh_userfile_stat(ssh_user_uid(user_data), SSH_HOSTS_EQUIV, &st) < 0)
    return FALSE; /* The user has no .shosts or .rhosts file and there are no
                 system-wide files. */
  
  /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
  if (ssh_user_uid(user_data) != UID_ROOT)
    {
      if (check_rhosts_file(ssh_user_uid(effective_user_data), 
                            "/etc/hosts.equiv", hostname, ipaddr, client_user,
                            ssh_user_name(user_data), server))
        {
          SSH_TRACE(2, ("Accepted for %.100s [%.100s] by " \
                        "/etc/hosts.equiv.", hostname, ipaddr));
          return TRUE;
        }
      if (check_rhosts_file(ssh_user_uid(effective_user_data),
                            SSH_HOSTS_EQUIV, hostname, ipaddr, client_user,
                            ssh_user_name(user_data), server))
        {
          SSH_TRACE(2, ("Accepted for %.100s [%.100s] by %.100s.",  \
                            hostname, ipaddr, SSH_HOSTS_EQUIV));
          return TRUE;
        }
    }

  /* Check that the home directory is owned by root or the user, and is not 
     group or world writable. */
  if (ssh_userfile_stat(ssh_user_uid(user_data), ssh_user_dir(user_data),
                    &st) < 0)
    {
      ssh_log_event(config->log_facility, SSH_LOG_WARNING,
                    "hostbased-authentication (rhosts) refused for " \
                    "%.100: no home directory %.200s",
                    ssh_user_name(user_data),
                    ssh_user_dir(user_data));
      SSH_TRACE(2, ("hostbased-authentication (rhosts) refused for " \
                    "%.100: no home directory %.200s", \
                    ssh_user_name(user_data), ssh_user_dir(user_data)));
      return FALSE;
    }
  
  if (config->strict_modes && 
      ((st.st_uid != UID_ROOT && st.st_uid != ssh_user_uid(user_data)) ||
#ifdef ALLOW_GROUP_WRITEABILITY
       (st.st_mode & 002) != 0)
#else
       (st.st_mode & 022) != 0)
#endif
      )
    {
      ssh_log_event(config->log_facility, SSH_LOG_WARNING,
                    "hostbased-authentication (rhosts) refused for " \
                    "%.100s: bad ownership or modes for home directory.",
                    ssh_user_name(user_data));
      SSH_TRACE(2, ("hostbased-authentication (rhosts) refused for " \
                    "%.100s: bad ownership or modes for home directory.", \
                    ssh_user_name(user_data)));
      return FALSE;
    }
  
  /* Check all .rhosts files (currently .shosts and .rhosts). */
  for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
       rhosts_file_index++)
    {
      /* Check users .rhosts or .shosts. */
      snprintf(buf, sizeof(buf), "%.500s/%.100s", 
              ssh_user_dir(user_data), rhosts_files[rhosts_file_index]);
      if (ssh_userfile_stat(ssh_user_uid(user_data), buf, &st) < 0)
        continue; /* No such file. */

      /* Make sure that the file is either owned by the user or by root,
         and make sure it is not writable by anyone but the owner.  This is
         to help avoid novices accidentally allowing access to their account
         by anyone. */
      if (config->strict_modes &&
          ((st.st_uid != UID_ROOT && st.st_uid != ssh_user_uid(user_data)) ||
           (st.st_mode & 022) != 0))
        {
          ssh_log_event(config->log_facility, SSH_LOG_WARNING,
                        "hostbased-authentication (rhosts) refused for " \
                        "%.100s: bad modes for %.200s",
                        ssh_user_name(user_data), buf);
          SSH_TRACE(2, ("hostbased-authentication (rhosts) refused for " \
                        "%.100s: bad modes for %.200s", \
                        ssh_user_name(user_data), buf));
          continue;
        }

      /* Check if we have been configured to ignore .rhosts and .shosts 
         files.  If root, check ignore_root_rhosts first. */
      if ((ssh_user_uid(user_data) == UID_ROOT &&
           config->ignore_root_rhosts) ||
          (ssh_user_uid(user_data) != UID_ROOT &&
           config->ignore_rhosts))
        {
          SSH_TRACE(2, ("Server has been configured to ignore %.100s.", \
                        rhosts_files[rhosts_file_index]));
          continue;
        }

      /* Check if authentication is permitted by the file. */
      if (check_rhosts_file(ssh_user_uid(user_data), buf, hostname,
                            ipaddr, client_user, ssh_user_name(user_data),
                            server))
        {
          SSH_TRACE(2, ("Accepted by %.100s.", \
                        rhosts_files[rhosts_file_index]));
          return TRUE;
        }
    }

  /* Rhosts authentication denied. */
  SSH_TRACE(2, ("hostbased-authentication (rhosts) refused: client " \
                "user '%.100s', server user '%.100s', " \
                "client host '%.200s'.", \
                client_user, ssh_user_name(user_data), hostname));

  ssh_log_event(config->log_facility, SSH_LOG_WARNING,
                "hostbased-authentication (rhosts) refused: client " \
                "user '%.100s', server user '%.100s', " \
                "client host '%.200s'.", \
                client_user, ssh_user_name(user_data), hostname);

  return FALSE;
}