int main(int ac, char **av)
{
  int opt, i;
  DIR *ssh2dir = NULL;
  char *ssh2dirname;
  Boolean dynamic_array = FALSE;
  struct dirent * cand;

  /* Save program name. */
  if (strchr(av[0], '/'))
    av0 = strrchr(av[0], '/') + 1;
  else
    av0 = av[0];

  user = ssh_user_initialize(NULL, FALSE);

#ifdef WITH_PGP
  pgp_keyring = ssh_xstrdup(SSH_PGP_SECRET_KEY_FILE);
#endif /* WITH_PGP */

  action = ADD;
  while ((opt = ssh_getopt(ac, av, "ldDput:f:F:1LUNPI", NULL)) != EOF)
    {
      if (!ssh_optval)
        {
          usage();
          exit(EXIT_STATUS_ERROR);
        }
      switch (opt)
        {
        case 'N':
#ifdef WITH_PGP
          pgp_mode = PGP_KEY_NAME;
#else /* WITH_PGP */
          fprintf(stderr, "%s: PGP keys not supported.\n", av0);
          exit(EXIT_STATUS_ERROR);
#endif /* WITH_PGP */
          break;

        case 'P':
#ifdef WITH_PGP
          pgp_mode = PGP_KEY_FINGERPRINT;
#else /* WITH_PGP */
          fprintf(stderr, "%s: PGP keys not supported.\n", av0);
          exit(EXIT_STATUS_ERROR);
#endif /* WITH_PGP */
          break;

        case 'I':
#ifdef WITH_PGP
          pgp_mode = PGP_KEY_ID;
#else /* WITH_PGP */
          fprintf(stderr, "%s: PGP keys not supported.\n", av0);
          exit(EXIT_STATUS_ERROR);
#endif /* WITH_PGP */
          break;

        case 'R':
#ifdef WITH_PGP
          ssh_xfree(pgp_keyring);
          pgp_keyring = ssh_xstrdup(ssh_optarg);
#else /* WITH_PGP */
          fprintf(stderr, "%s: PGP keys not supported.\n", av0);
          exit(EXIT_STATUS_ERROR);
#endif /* WITH_PGP */
          break;

        case 'l':
          action = LIST;
          break;

        case 'p':
          use_stdin = TRUE;
          break;

        case 'd':
          if (action == ADD_URL)
            action = DELETE_URL;
          else
            action = DELETE;
          break;

        case 'D':
          action = DELETE_ALL;
          break;

        case 't':
          if (ssh_optargnum)
            {
              key_timeout = (SshTime)(ssh_optargval * 60);
            }
          else
            {
              usage();
              exit(EXIT_STATUS_ERROR);
            }
          have_attrs = TRUE;
          break;

        case 'f':
          if (ssh_optargnum)
            {
              path_limit = (SshUInt32)ssh_optargval;
            }
          else
            {
              usage();
              exit(EXIT_STATUS_ERROR);
            }
          have_attrs = TRUE;
          break;

        case 'F':
          path_constraint = ssh_xstrdup(ssh_optarg);
          have_attrs = TRUE;
          break;

        case '1':
          forbid_compat = TRUE;
          have_attrs = TRUE;
          break;

        case 'u':
          if (action == DELETE)
            action = DELETE_URL;
          else
            action = ADD_URL;
          break;

        case 'L':
          action = LOCK;
          break;

        case 'U':
          action = UNLOCK;
          break;

        default:
          usage();
          exit(EXIT_STATUS_ERROR);
        }
    }

#ifdef WITH_PGP
  if (pgp_keyring[0] != '/')
    {
      char buf[1024];
      snprintf(buf, sizeof (buf), "%s/%s/%s", 
               ssh_user_dir(user), 
               SSH_USER_DIR,
               pgp_keyring);
      ssh_xfree(pgp_keyring);
      pgp_keyring = ssh_xstrdup(buf);
    }
#endif /* WITH_PGP */

  files = &av[ssh_optind];
  num_files = ac - ssh_optind;

  /* Fetch default from ~/.ssh2/id_* (the first that we happen to get) */

#define ID_PREFIX "id"
  
  if (num_files == 0 && action != LIST && action != DELETE_ALL &&
      action != LOCK && action != UNLOCK)
    {
#ifdef WITH_PGP
      if (pgp_mode != PGP_KEY_NONE)
        {
          fprintf(stderr, "%s: Nothing to do!\n",  av0);
          exit(EXIT_STATUS_ERROR);
        }
#endif /* WITH_PGP */
      ssh_dsprintf(&ssh2dirname, "%s/%s", ssh_user_dir(user), SSH_USER_DIR);
      ssh2dir = opendir(ssh2dirname);

      if (!ssh2dir)
        {
          fprintf(stderr, "%s: Can't open directory \"%s\"", av0, ssh2dirname);
          exit(EXIT_STATUS_ERROR);
        }
          
      while ((cand = readdir(ssh2dir)) != NULL)
        {
          if ((strlen(cand->d_name) > strlen(ID_PREFIX)) &&
              (strncmp(cand->d_name, ID_PREFIX, strlen(ID_PREFIX)) == 0) &&
              ((strlen(cand->d_name) < 4) ||
               (strcmp(cand->d_name + strlen(cand->d_name) - 4,
                       ".pub") != 0)) &&
              ((((cand->d_name)[strlen(ID_PREFIX)]) == '_') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '-') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '.') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '(') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '[') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '<') ||
               (((cand->d_name)[strlen(ID_PREFIX)]) == '>')))
            {
              files = ssh_xcalloc(2, sizeof(char *));
              ssh_dsprintf(&files[0], "%s/%s", ssh2dirname, cand->d_name);
              ssh_xfree(ssh2dirname);
              num_files++;
              dynamic_array = TRUE;
              break;
            }
        }
      (void)closedir(ssh2dir);
    }
  
  signal(SIGPIPE, SIG_IGN);
  
  ssh_event_loop_initialize();
  
  ssh_agent_open(agent_open_callback, NULL);

  ssh_event_loop_run();
  ssh_event_loop_uninitialize();

  if (dynamic_array)
    {
      for(i = 0; i < num_files ; i++)
        {
          ssh_xfree(files[i]);
        }
      ssh_xfree(files);
    }
  
  ssh_user_free(user, FALSE);
  exit(EXIT_STATUS_OK);
}
示例#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;
}