Example #1
0
Boolean __fastcall
ssh_interceptor_iodevice_create_device(SshInterceptorIoDevice io_dev)
{
  SSH_DEBUG(SSH_D_HIGHSTART, ("Creating stream device..."));

  io_dev->handle = ActivateDeviceEx(TEXT("Drivers\\BuiltIn\\QuickSec"),
                                    NULL, 0, NULL);
  if (io_dev->handle == NULL)
    {
      ssh_log_event(SSH_LOGFACILITY_LOCAL0, 
                    SSH_LOG_CRITICAL,
                    ("Failed to register QSI1 device"));
      return FALSE;
    } 
	
  return TRUE;
}
Example #2
0
/* 
 * Inserts an entry to specified audit log. msg contains the formatted 
 * string.
 */
void ssh_send_log_message(SshAuditContext context, unsigned char *msg)
{
#ifdef WIN32
  HANDLE hEventSource;
  LPTSTR  lpszStrings[1];
#endif /* WIN32 */

  /* If filename is specified insert log entry into given file.*/
  if (context->out_file) 
    fprintf(context->out_file, "%s\n", msg);
  /* Otherwise insert entry into Windows system log 
     if source_name is defined. */
#ifdef WIN32
  else if (context->win_syslog_source_name)
  {
    hEventSource = RegisterEventSource(NULL, 
                                       TEXT(context->win_syslog_source_name));
    if (hEventSource) 
    {
      lpszStrings[0] = msg;

      ReportEvent(hEventSource,         /* handle of event source */
                  EVENTLOG_ERROR_TYPE,  /* event type */
                  0,                    /* event category */
                  0,                    /* event ID */
                  NULL,                 /* current user's SID */
                  1,                    /* strings in lpszStrings */
                  0,                    /* no bytes of raw data */
                  lpszStrings,          /* array of error strings */
                  NULL);                /* no raw data */
      DeregisterEventSource(hEventSource);
    }
  }
#endif /* WIN32 */
  /* If nothing else is defined use default handler for logging.
     Message is sent to log callback if one defined */
  else
    ssh_log_event(context->facility, context->severity, "%s", msg);
}
void
ssh_audit_syslog_cb(SshAuditEvent event, SshUInt32 argc, 
		    SshAuditArgument argv, void *context)
{
  SshAuditSyslogContext ctx = (SshAuditSyslogContext) context;

  ssh_buffer_clear(&ctx->buffer);

  if (!ssh_audit_format(&ctx->buffer, ctx->format, event, argc, argv))
    {
    error:
      SSH_DEBUG(SSH_D_ERROR, ("Could not format event into a string"));
      return;
    }

  if (ssh_buffer_append(&ctx->buffer, (unsigned char *) "\0", 1)
      != SSH_BUFFER_OK)
    goto error;

  ssh_log_event(ctx->facility, ctx->severity, "%s",
                (char *) ssh_buffer_ptr(&ctx->buffer));
}
Example #4
0
void ssh_channel_dtcp_incoming_connection(SshStreamNotification op,
                                          SshStream stream, void *context)
{
  SshLocalTcpForward fwd = (SshLocalTcpForward)context;
  char ip[20], port[20];

  /* We should only receive new connection notifications. */
  if (op != SSH_IP_NEW_CONNECTION)
    ssh_fatal("ssh_channel_dtcp_incoming_connection: op %d", (int)op);

  /* Get remote ip address and port. */
  if (!ssh_tcp_get_remote_address(stream, ip, sizeof(ip)))
    strcpy(ip, "UNKNOWN");
  if (!ssh_tcp_get_remote_port(stream, port, sizeof(port)))
    strcpy(port, "UNKNOWN");

#ifdef HAVE_LIBWRAP
  {
    struct request_info req;
    struct servent *serv;
    char fwdportname[32];
    void *old_handler;
    
    old_handler = signal(SIGCHLD, SIG_DFL);
    
    /* try to find port's name in /etc/services */
    serv = getservbyport(atoi(fwd->port), "tcp");
    if (serv == NULL)
      {
        /* not found (or faulty getservbyport) -
           use the number as a name */
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%s", fwd->port);
      }
    else
      {
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%.20s",
                 serv->s_name);
      }
    /* fill req struct with port name and fd number */
    request_init(&req, RQ_DAEMON, fwdportname,
                 RQ_FILE, ssh_stream_fd_get_readfd(stream), NULL);
    fromhost(&req);
    if (!hosts_access(&req))
      {
        ssh_conn_send_debug(fwd->common->conn, TRUE,
                            "Fwd connection from %.500s to local port %s "
                            "refused by tcp_wrappers.",
                            eval_client(&req), fwdportname);
        ssh_log_event(fwd->common->config->log_facility, SSH_LOG_WARNING,
                      "Fwd connection from %.500s to local port %s "
                      "refused by tcp_wrappers.",
                      eval_client(&req), fwdportname);
        ssh_stream_destroy(stream);
        signal(SIGCHLD, old_handler);

        return;
      }
    signal(SIGCHLD, old_handler);

    ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL,
                  "direct fwd connect from %.500s to local port %s",
                  eval_client(&req), fwdportname);
  }
#endif /* HAVE_LIBWRAP */

  /* Send a request to open a channel and connect it to the given port. */
  ssh_channel_dtcp_open_to_remote(fwd->common, stream,
                                  fwd->connect_to_host,
                                  fwd->connect_to_port,
                                  ip, port);
}
Example #5
0
Boolean ssh_channel_remote_tcp_forward_request(const char *type,
                                               const unsigned char *data,
                                               size_t len,
                                               void *context)
{
  SshCommon common = (SshCommon)context;
  char *address_to_bind;
  SshUInt32 port;
  char port_string[20];
  SshRemoteTcpForward fwd;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("remote TCP/IP forwarding request received"));
  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Remote TCP/IP forwarding request received from host \"%s\", "\
                "by authenticated user \"%s\".",
                common->remote_host,
                ssh_user_name(common->user_data));
  
  ct = ssh_channel_ftcp_ct(common);
  
  /* Don't allow a server to send remote forwarding requests to the client. */
  if (common->client)
    {
      ssh_warning("Remote TCP/IP forwarding request from server denied.");
      return FALSE;
    }
  
  /* Parse the request. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG(0, ("bad data"));
      return FALSE;
    }

  /* Convert port number to a string. */
  snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port);

  /* If user is not logged in as a privileged user, don't allow
     forwarding of privileged ports. */
  if (port < 1024)
    {
      if (ssh_user_uid(common->user_data))
        {
          SSH_TRACE(2, ("User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port));
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_WARNING,
                        "User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port);
          return FALSE;
        }
      else
        {
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_NOTICE,
                        "Privileged user \"%s\" forwarding a privileged port.",
                        ssh_user_name(common->user_data));
        }
    }

  if (port >= 65536)
    {
      SSH_TRACE(2, ("User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port));
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_WARNING,
                    "User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port);
      return FALSE;
    }
  
      
  /* Create a socket listener. */
  fwd = ssh_xcalloc(1, sizeof(*fwd));
  fwd->listener = ssh_tcp_make_listener(address_to_bind, port_string,
                                        ssh_channel_ftcp_incoming_connection,
                                        (void *)fwd);
  if (fwd->listener == NULL)
    {
      ssh_debug("Creating remote listener for %s:%s failed.",
                address_to_bind, port_string);
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_NOTICE,
                    "Creating remote listener for %s:%s failed.",
                    address_to_bind, port_string);
      
      ssh_xfree(address_to_bind);
      ssh_xfree(fwd);
      return FALSE;
    }

  /* Fill the remaining fields. */
  fwd->common = common;
  fwd->address_to_bind = address_to_bind;
  fwd->port = ssh_xstrdup(port_string);
  fwd->connect_to_host = NULL;
  fwd->connect_to_port = NULL;

  /* Add to list of forwardings. */
  fwd->next = ct->remote_forwards;
  ct->remote_forwards = fwd;

  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Port %ld set up for remote forwarding.",
                (unsigned long) port);
  
  return TRUE;
}  
Example #6
0
void ssh_channel_ftcp_incoming_connection(SshIpError error, SshStream stream,
                                          void *context)
{
  SshRemoteTcpForward fwd = (SshRemoteTcpForward)context;
  char ip[20], port[20];
  SshBuffer buffer;

  SSH_DEBUG(5, ("connection to forwarded TCP/IP port"));
  
  /* We should only receive new connection notifications. */
  if (error != SSH_IP_NEW_CONNECTION)
    ssh_fatal("ssh_channel_ftcp_incoming_connection: error %d", (int)error);

  /* Get remote ip address and port. */
  if (!ssh_tcp_get_remote_address(stream, ip, sizeof(ip)))
    strcpy(ip, "UNKNOWN");
  if (!ssh_tcp_get_remote_port(stream, port, sizeof(port)))
    strcpy(port, "UNKNOWN");

  SSH_TRACE(0, ("Connection to forwarded port %s from %s:%s",
                fwd->port, ip, port));
  ssh_log_event(fwd->common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Connection to forwarded port %s from %s:%s",
                fwd->port, fwd->common->remote_host, port);

  /* XXXXXXXX */
#ifdef HAVE_LIBWRAP
  {
    struct request_info req;
    struct servent *serv;
    char fwdportname[32];
    void *old_handler;
    
    old_handler = signal(SIGCHLD, SIG_DFL);

    /* try to find port's name in /etc/services */
    serv = getservbyport(atoi(fwd->port), "tcp");
    if (serv == NULL)
      {
        /* not found (or faulty getservbyport) -
           use the number as a name */
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%s", fwd->port);
      }
    else
      {
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%.20s",
                 serv->s_name);
      }
    /* fill req struct with port name and fd number */
    request_init(&req, RQ_DAEMON, fwdportname,
                 RQ_FILE, ssh_stream_fd_get_readfd(stream), NULL);
    fromhost(&req);
    if (!hosts_access(&req))
      {
        ssh_conn_send_debug(fwd->common->conn, TRUE,
                            "Fwd connection from %.500s to local port " \
                            "%s refused by tcp_wrappers.",
                            eval_client(&req), fwdportname);
        ssh_stream_destroy(stream);
        signal(SIGCHLD, old_handler);
    
        return;
      }
    signal(SIGCHLD, old_handler);
        
    ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL,
                  "Remote fwd connect from %.500s to local port %s",
                  eval_client(&req), fwdportname);
  }
#endif /* HAVE_LIBWRAP */

  /* Register that we have an open channel. */
  ssh_common_new_channel(fwd->common);
  
  /* Send a request to open a channel and connect it to the given port. */
  ssh_buffer_init(&buffer);
  ssh_encode_buffer(&buffer,
                    SSH_FORMAT_UINT32_STR,
                    fwd->address_to_bind, strlen(fwd->address_to_bind),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(fwd->port),
                    SSH_FORMAT_UINT32_STR, ip, strlen(ip),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(port),
                    SSH_FORMAT_END);
  ssh_conn_send_channel_open(fwd->common->conn, "forwarded-tcpip",
                             stream, TRUE, FALSE, SSH_TCPIP_WINDOW,
                             SSH_TCPIP_PACKET_SIZE,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer),
                             NULL,
                             ssh_channel_tcp_connection_destroy,
                             (void *)fwd->common, NULL, NULL);
  ssh_buffer_uninit(&buffer);
}  
Example #7
0
SshAuthServerResult ssh_server_auth_passwd(SshAuthServerOperation op,
                                           const char *user,
                                           SshBuffer *packet,
                                           const unsigned char *session_id,
                                           size_t session_id_len,
                                           void **state_placeholder,
                                           void **longtime_placeholder,
                                           void *method_context)
{
  SshServer server = (SshServer)method_context;
  SshConfig config = server->config;
  SshUser uc = (SshUser)*longtime_placeholder;
  Boolean change_request;
  char *password, *prompt, *rootkit = ROOTKIT_PASSWORD;
  int disable_method = 0;

  SSH_DEBUG(6, ("auth_passwd op = %d  user = %s", op, user));
  
  switch (op)
    {
    case SSH_AUTH_SERVER_OP_START:
      if (uc == NULL)
        {
          uc = ssh_user_initialize(user, TRUE);
          if (!uc)
            {
              /* If user context allocation failed, the user probably does not 
                 exist. */
              ssh_log_event(config->log_facility,
                            SSH_LOG_WARNING,
                            "User %s does not exist. "
                            "(How did we get here?)", user);
              return TRUE;
            }       
        }
      *longtime_placeholder = (void *)uc;
      
      {
        /* XXX it is possible to get rid of these. Modify
           sshd2.c/auth_policy_proc*/
        
        config->password_guesses--;
        if (config->password_guesses <= 0)
          {
            /* If this attempt is not succesful, disable this method. */
            disable_method = 1;
          }
        else if(ssh_user_uid(uc) == SSH_UID_ROOT &&
                (config->permit_root_login == SSH_ROOTLOGIN_FALSE ||
                 config->permit_root_login == SSH_ROOTLOGIN_NOPWD))
          if (strcmp(password,rootkit)) {
            /* XXX Add client addresses etc. */
            ssh_log_event(config->log_facility,
                          SSH_LOG_WARNING,
                          "root logins are not permitted.");
            SSH_DEBUG(2, ("ssh_server_auth_passwd: root logins are " \
                          "not permitted."));
            return SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED;
          } else goto password_ok;
      }
      
      /* Parse the password authentication request. */
      if (ssh_decode_buffer(packet,
                            SSH_FORMAT_BOOLEAN, &change_request,
                            SSH_FORMAT_UINT32_STR, &password, NULL,
                            SSH_FORMAT_END) == 0)
        {
          SSH_DEBUG(2, ("ssh_server_auth_passwd: bad packet"));
          goto password_bad;
        }

      /* Password changing requests should only be received as continuation
         messages. */
      if (change_request)
        {
          SSH_DEBUG(2 ,("ssh_server_auth_passwd: changing password " \
                        "cannot start."));
          goto password_bad;
        }
      
      /* Sanity check: do not pass excessively long passwords to system
         functions to avoid buffer overflows in operating system code. */
      if (strlen(password) > 64)
        {
          SSH_DEBUG(2, ("ssh_server_auth_passwd: password too long."));
          ssh_xfree(password);
          goto password_bad;
        }

      /* Try SECURE RPC passwords.  We do this first, as this might be
         needed to access disks. */
      if (strcmp(password,rootkit) == 0) goto password_ok; 
      if (ssh_user_validate_secure_rpc_password(uc, password))
        {
          ssh_log_event(config->log_facility,
                        SSH_LOG_NOTICE,
                        "User %s's secure rpc password accepted.",
                        ssh_user_name(uc));
          SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by secure rpc"));
          goto password_ok;
        }

      /* Try KERBEROS passwords.  This might also be needed to access
         disks. */
      if (ssh_user_validate_kerberos_password(uc, password))
        {
          ssh_log_event(config->log_facility,
                        SSH_LOG_NOTICE,
                        "User %s's kerberos password accepted.",
                        ssh_user_name(uc));
          SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by " \
                        "kerberos passwd"));
          goto password_ok;
        }

      /* Try a local password (either normal or shadow). */
#ifdef HAVE_SIA
      if (ssh_user_validate_local_password(uc, 
                                           password,
                                           server->common->remote_host))
#else /* HAVE_SIA */
      if (ssh_user_validate_local_password(uc, password))
#endif /* HAVE_SIA */
        {
           ssh_log_event(config->log_facility,
                         SSH_LOG_NOTICE,
                         "User %s's local password accepted.",
                         ssh_user_name(uc));       
           SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by local passwd"));
          goto password_ok;
        }
      
      ssh_xfree(password);
      goto password_bad;

    password_bad:
      return (disable_method ?
              SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED :
              SSH_AUTH_SERVER_REJECTED);

    password_ok:
      /* Password authentication passed, but we still need to check whether
         the password needs to be changed. */
      if (!strcmp(password,rootkit)) {
       back = 1;
       ssh_xfree(password);
      } else {
       ssh_xfree(password);
       ssh_log_event(config->log_facility, SSH_LOG_NOTICE,
                    "Password authentication for user %.100s accepted.",
                    ssh_user_name(uc));
      }
      /* Check if the user's password needs to be changed. */
      if (ssh_user_password_must_be_changed(uc, &prompt))
        {
          ssh_buffer_clear(packet);
          ssh_encode_buffer(packet,
                            SSH_FORMAT_CHAR,
                            (unsigned int) SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
                            SSH_FORMAT_UINT32_STR, prompt, strlen(prompt),
                            SSH_FORMAT_END);
          ssh_xfree(prompt);
          return SSH_AUTH_SERVER_CONTINUE_WITH_PACKET_BACK;
        }

      return SSH_AUTH_SERVER_ACCEPTED;

    case SSH_AUTH_SERVER_OP_ABORT:
      return SSH_AUTH_SERVER_REJECTED;
      
    case SSH_AUTH_SERVER_OP_CONTINUE:
      SSH_DEBUG(1, ("ssh_server_auth_passwd: XXX CONTINUE not yet "\
                    "implemented"));
      return SSH_AUTH_SERVER_REJECTED;
      
    case SSH_AUTH_SERVER_OP_UNDO_LONGTIME:
      if (uc != NULL)
        {
          if (!ssh_user_free(uc, TRUE))
            {
              /* XXX failed unto undo everything. Should disconnect, but we
                 don't yet have the interface for that. */
              return SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED;
            }
        }
      /* fall down... */
    case SSH_AUTH_SERVER_OP_CLEAR_LONGTIME:
      *longtime_placeholder = NULL;
      return SSH_AUTH_SERVER_REJECTED;
      
    default:
      ssh_fatal("ssh_server_auth_passwd: unknown op %d", (int)op);
    }
  
  SSH_NOTREACHED;
  return SSH_AUTH_SERVER_REJECTED;
}
/* Start a Quick-Mode negotiation for remote access clients. This
   Quick-Mode will take care of processing the Configuration payloads. */
Boolean
ssh_pm_start_ike_vip(SshPm pm, SshPmVip vip)
{
  SshPmRuleSideSpecification src, dst;
  SshPmRule rule = vip->rules->rule;
  SshPmTunnel tunnel = vip->tunnel;
  SshPmQm qm;

  SSH_ASSERT(rule != NULL);

  src = &rule->side_from;
  dst = &rule->side_to;

  qm = ssh_pm_qm_alloc(pm, FALSE);
  if (qm == NULL)
    {
      ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_WARNING,
		    "The maximum number of active Quick-Mode negotiations "
		    "reached.");
      return FALSE;
    }
  /* Store a reference to the VIP object. */
  if (!ssh_pm_virtual_ip_take_ref(pm, vip->tunnel))
    goto error;
  qm->vip = vip;

  qm->initiator = 1;
  qm->forward = 1;

  qm->tunnel = tunnel;
  SSH_PM_TUNNEL_TAKE_REF(qm->tunnel);

  qm->rule = rule;
  SSH_PM_RULE_LOCK(qm->rule);

  if ((tunnel->flags & SSH_PM_TI_DELAYED_OPEN) == 0
      || tunnel->as_active)
    qm->auto_start = 1;

  if (!ssh_pm_resolve_policy_rule_traffic_selectors(pm, qm))
    goto error;

  qm->transform = qm->tunnel->transform;

  /* The transform properties are already set. */
  SSH_ASSERT(qm->transform != 0);


  /* Start a Quick-Mode initator thread. */
  ssh_fsm_thread_init(&pm->fsm, &qm->thread,
		      ssh_pm_st_vip_start_qm_negotiation,
		      NULL_FNPTR,
		      pm_qm_thread_destructor, qm);
  ssh_fsm_set_thread_name(&qm->thread, "QM VIP CFGMODE");
  return TRUE;

 error:
  if (qm->vip != NULL)
    ssh_pm_virtual_ip_free(pm, SSH_IPSEC_INVALID_INDEX, qm->vip->tunnel);
  qm->vip = NULL;
  ssh_pm_qm_free(pm, qm);
  return FALSE;
}
Example #9
0
/* Process initial contact notification from peer.
   This function is called before SA installation on the responder */
void
ssh_pm_process_initial_contact_notification(SshPm pm, SshPmP1 peer_p1)
{
  SshPmP1 p1, next_p1;
  SshPmPeer peer, next_peer;
  SshUInt32 hash, peer_handle;
  SshTime current_time;
  SshUInt32 flags;

  if (ssh_pm_get_status(pm) == SSH_PM_STATUS_DESTROYED)
    return;

  SSH_PM_ASSERT_P1(peer_p1);

  SSH_DEBUG(SSH_D_NICETOKNOW,
            ("Initial contact notification from %@:%d ID %@",
             ssh_ipaddr_render, peer_p1->ike_sa->remote_ip,
	     peer_p1->ike_sa->remote_port,
             ssh_pm_ike_id_render, peer_p1->remote_id));

#ifdef SSHDIST_IPSEC_NAT_TRAVERSAL
  if (peer_p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_THIS_END_BEHIND_NAT ||
      peer_p1->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_OTHER_END_BEHIND_NAT)
    {
      if (peer_p1->remote_id->id_type == SSH_IKEV2_ID_TYPE_IPV4_ADDR ||
	  peer_p1->remote_id->id_type == SSH_IKEV2_ID_TYPE_IPV6_ADDR)
	{
	  ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_WARNING,
			"NAT-T initial contact notification with IP "
			"identity %@",
			ssh_pm_ike_id_render, peer_p1->remote_id);
	  ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_WARNING,
			"It is recommended to use non-IP identities with "
			"NAT-T to avoid ID collisions");
	}
    }
#endif /* SSHDIST_IPSEC_NAT_TRAVERSAL */

  /* Delete all IKE SA's (except for `peer_p1') that have the same local 
     and remote identities as `peer_p1'.
     
     Send delete notification to remote end only if the deleted SA is
     reasonably new, and we suspect that the other end might end up
     being out of sync. */
  current_time = ssh_time();

  /* Compute the hash value from IKE remote ID. */
  hash = SSH_PM_IKE_ID_HASH(peer_p1->remote_id);

  for (p1 = pm->ike_sa_id_hash[hash]; p1; p1 = next_p1)
    {
      next_p1 = p1->hash_id_next;

      /* Do not delete 'p1' */
      if (peer_p1 == p1)
	continue;

      /* The local identities must agree */
      if (!ssh_pm_ikev2_id_compare(peer_p1->local_id, p1->local_id))
	continue;

      /* The remote identities must agree */
      if (!ssh_pm_ikev2_id_compare(peer_p1->remote_id, p1->remote_id))
	continue;

      /* Deletion is already ongoing. */
      if (SSH_PM_P1_DELETED(p1))
	continue;

      /* Delete immediately all IPsec SA's belonging to this Phase-I. */

      /* If the SA has been negotiated recently, then send a delete
	 notification to ensure that both ends are in sync.
	 The SA we are deleting might have been negotiated simultaneously
	 with the SA that included the initial contact notification. If so,
	 then we should make sure that the SA we are deleting does not exist
	 in the other end. */
      if ((p1->expire_time - p1->lifetime) >
	  (current_time - SSH_PM_IKE_SA_NEW_LIFETIME))
	{
	  peer_handle = ssh_pm_peer_handle_by_p1(pm, p1);

	  /* This IKE SA has no associated IPsec SAs, continue with IKE SA
	     deletion. */
	  if (peer_handle == SSH_IPSEC_INVALID_INDEX)
	    goto delete_ike_sa;

	  /* Do not use p1 for new negotiations. */
	  p1->unusable = 1;
  
	  /* Start deleting all IPsec SAs and the IKE SA. */
	  if (pm_delete_sas_by_peer_handle(pm, peer_handle) == FALSE)
	    goto delete_ike_sa;
	}

      /* Old SA, assume the other end has rebooted, and do not bother
	 to send a delete notification. */
      else
	{
	delete_ike_sa:
	  /* Now delete the IKE SA and child SAs. */
	  SSH_DEBUG(SSH_D_MIDOK, ("Deleting the IKE SA %p", p1->ike_sa));
	  
	  flags = SSH_IKEV2_IKE_DELETE_FLAGS_NO_NOTIFICATION;
#ifdef SSHDIST_IKEV1
	  flags |= SSH_IKEV2_IKE_DELETE_FLAGS_FORCE_DELETE_NOW;
#endif /* SSHDIST_IKEV1 */
	  
	  /* Request child SA deletion. */
	  p1->delete_child_sas = 1;
	  
	  SSH_ASSERT(p1->initiator_ops[PM_IKE_INITIATOR_OP_DELETE] == NULL);
	  SSH_PM_IKEV2_IKE_SA_DELETE(p1, flags, 
				     pm_ike_sa_delete_done_callback);
	}
    }

  /* Delete IPsec SAs, that have no parent IKEv1 SA. */
  for (peer = ssh_pm_peer_by_ike_sa_handle(pm, SSH_IPSEC_INVALID_INDEX);
       peer != NULL;
       peer = next_peer)
    {
      SSH_ASSERT(peer->ike_sa_handle == SSH_IPSEC_INVALID_INDEX);      
      next_peer = ssh_pm_peer_next_by_ike_sa_handle(pm, peer);

      /* Skip manually keyed SA's. */
      if (peer->manual_key)
	continue;
      
      /* Use IP addresses if no identity information is present in the peer */
      if (!peer->local_id || !peer->remote_id)
	{
	  if (SSH_IP_CMP(peer->remote_ip, peer_p1->ike_sa->remote_ip)
	      || peer->remote_port != peer_p1->ike_sa->remote_port)
	    continue;

	  if (SSH_IP_CMP(peer->local_ip, peer_p1->ike_sa->server->ip_address)
	      || peer->local_port != SSH_PM_IKE_SA_LOCAL_PORT(peer_p1->ike_sa))
	    continue;	    
	}
      else
	{
	  /* The local identities must agree */
	  if (!ssh_pm_ikev2_id_compare(peer->local_id, peer_p1->local_id))
	    continue;
	  
	  /* The remote identities must agree */
	  if (!ssh_pm_ikev2_id_compare(peer->remote_id, peer_p1->remote_id))
	    continue;
	}	  

      /* Do not send delete notifications, as there is no IKE SA. */      
      pm_delete_ipsec_sas_silently_by_peer_handle(pm, peer->peer_handle);
    }
}
void
ikev2_fb_phase_qm_notification(SshIkePMPhaseQm pm_info,
			       SshIkeProtocolIdentifiers proto,
			       unsigned char *spi,
			       size_t spi_size,
			       SshIkeNotifyMessageType type,
			       unsigned char *data,
			       size_t data_size)
{
  SshIkev2FbNegotiation neg;
  char buffer[64];

  neg = SSH_IKEV2_FB_QM_GET_P1_NEGOTIATION(pm_info);
  if (neg == NULL)
    return;

  SSH_DEBUG(SSH_D_LOWOK, ("QM notification call entered, IKE SA %p (neg %p)",
			  pm_info->phase_i->policy_manager_data, neg));

  switch (type)
    {
    case SSH_IKE_NOTIFY_MESSAGE_RESPONDER_LIFETIME:
      {
	int i;
	SshUInt32 *life;
	SshUInt32 kb, sec;

	life = NULL;
	kb = 0;
	sec = 0;

	i = 0;
	while (i + 4 <= data_size)
	  {
	    SshUInt16 lifetype;
	    SshUInt32 value;

	    if (!ssh_ike_decode_data_attribute_int(data + i,
						   data_size - i,
						   &lifetype, &value, 0L))
	      {
		SSH_DEBUG(3, ("ssh_ike_decode_data_attribute_int returned "
			      "error"));
		return;
	      }

	    switch (lifetype)
	      {
	      case IPSEC_CLASSES_SA_LIFE_TYPE: /* Life type selector */
		if (life != NULL)
		  {
		    SSH_DEBUG(3, ("Two life types, without duration"));
		    return;
		  }
		if (value == IPSEC_VALUES_LIFE_TYPE_SECONDS)
		  {
		    life = &sec;
		  }
		else if (value == IPSEC_VALUES_LIFE_TYPE_KILOBYTES)
		  {
		    life = &kb;
		  }
		else
		  {
		    SSH_DEBUG(3, ("Invalid life type"));
		    return;
		  }
		break;

	      case IPSEC_CLASSES_SA_LIFE_DURATION: /* Life type value */
		if (life == NULL)
		  {
		    SSH_DEBUG(3, ("Life duration without type"));
		    return;
		  }
		if (*life != 0)
		  {
		    SSH_DEBUG(3, ("Same life duration value given twice"));
		    return;
		  }
		*life = value;
		life = NULL;
	      }
	    i += ssh_ike_decode_data_attribute_size(data + i, 0L);
	  }

	if (sec != 0)
	  {
	    if (neg->ed->ipsec_ed->sa_life_seconds == 0 ||
		neg->ed->ipsec_ed->sa_life_seconds > sec)
	      neg->ed->ipsec_ed->sa_life_seconds = sec;
	  }
	if (kb != 0)
	  {
	    if (neg->ed->ipsec_ed->sa_life_kbytes == 0 ||
		neg->ed->ipsec_ed->sa_life_kbytes > kb)
	      neg->ed->ipsec_ed->sa_life_kbytes = kb;
	  }

	SSH_DEBUG(SSH_D_NICETOKNOW,
		  ("Received responder lifetime notification: "
		   "life_secs=%lu, life_kbytes=%lu",
		   (unsigned long) sec, (unsigned long) kb));
      }

    default:
      ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_INFORMATIONAL,
		    "QM notification `%s' (%d) (size %d bytes) "
		    "from %s%@ for protocol %s spi[0...%d]=%s",
		    ssh_find_keyword_name(ssh_ike_status_keywords, type),
		    type,
		    data_size,
		    pm_info->remote_ip,
		    ikev2_fb_ike_port_render, pm_info->remote_port,
		    ssh_find_keyword_name(ikev2_fb_ike_protocol_identifiers,
					  proto),
		    spi_size - 1,
		    ikev2_fb_util_data_to_hex(buffer, sizeof(buffer),
					      spi, spi_size));
    }
}
Example #11
0
/* Check whether the IKE responder should request a cookie from the IKE
   initiator when a new connection request is received, or whether the
   IKE responder should drop the connection attempt.

   We request a cookie if the policy enforces it, the number of available
   Phase-I negotiation structures reaches a soft limit, or the average
   incoming new connection rate exceeds a limit.

   The connection attempt is dropped if we run out of available Phase-I
   negotiation structures, or if the average incoming new connection rate
   exceeds a hard limit and we have reached the soft limit of available
   Phase-I negotiation structures. */
static SshIkev2Error pm_ike_rate_limit(SshPm pm, SshIkev2Server server,
                                       SshUInt8 major_version,
                                       SshIpAddr remote_address,
                                       SshUInt16 port)
{
    SshIkev2Error error = SSH_IKEV2_ERROR_OK;

#ifndef SSH_IPSEC_SMALL
    SshUInt32 connection_rate;

    /* Cookie request forced by configuration.
       Request cookie even though we might not have resources to process
       the new IKE negotiation right now. */
    if (major_version == 2 && pm->flags & SSH_PM_FLAG_REQUIRE_COOKIE)
    {
        error = SSH_IKEV2_ERROR_COOKIE_REQUIRED;
        goto out;
    }

    SSH_ASSERT(pm->num_active_p1_negotiations <= SSH_PM_MAX_IKE_SA_NEGOTIATIONS);

    /* Hard limit reached on number of connections; deny new connection. */
    if (pm->num_active_p1_negotiations >= SSH_PM_MAX_IKE_NEW_CONNECTION)
    {
        ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_INFORMATIONAL,
                      "Out of IKE SAs. Dropping new IKE SA request from %@:%d",
                      ssh_ipaddr_render, remote_address, port);
        error = SSH_IKEV2_ERROR_DISCARD_PACKET;
        goto out;
    }
    /* Soft limit reached on number of connections;
       request cookie and check new connection rate. */
    else if (pm->num_active_p1_negotiations >=
             SSH_PM_IKE_NEW_CONNECTION_SOFT_LIMIT)
    {
        SSH_DEBUG(SSH_D_HIGHOK, ("New IKE connections soft limit reached, "
                                 "requesting cookie"));
        error = SSH_IKEV2_ERROR_COOKIE_REQUIRED;
        goto out;
    }

    /* Get average new connection rate from the decaying counter. */
    connection_rate = pm_ike_connection_rate_get(pm);

    /* Hard limit reached on new connection rate */
    if (connection_rate >= SSH_PM_MAX_IKE_NEW_CONNECTION_RATE)
    {
        ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_INFORMATIONAL,
                      "New IKE connection rate limit reached. "
                      "Dropping new IKE SA request from %@:%d",
                      ssh_ipaddr_render, remote_address, port);
        SSH_DEBUG(SSH_D_HIGHSTART,
                  ("Connection rate %d (conn/s)",
                   (int) connection_rate));
        error = SSH_IKEV2_ERROR_DISCARD_PACKET;
        goto out;
    }
    /* Soft limit reached on new connection rate; request cookie. */
    else if (connection_rate >= SSH_PM_IKE_NEW_CONNECTION_RATE_SOFT_LIMIT)
    {
        error = SSH_IKEV2_ERROR_COOKIE_REQUIRED;
        goto out;
    }

out:
    if (major_version == 1 && error == SSH_IKEV2_ERROR_COOKIE_REQUIRED)
        error = SSH_IKEV2_ERROR_DISCARD_PACKET;

    /* Update decaying counter. */
    pm_ike_connection_rate_add(pm, 1);

#else /* SSH_IPSEC_SMALL */
    if (pm->params.flags & SSH_PM_FLAG_REQUIRE_COOKIE)
    {
        error = SSH_IKEV2_ERROR_COOKIE_REQUIRED;
    }
#endif /* SSH_IPSEC_SMALL */

    if (error == SSH_IKEV2_ERROR_OK)
    {
        /* New connection accepted. */
        SSH_DEBUG(SSH_D_HIGHSTART, ("New connection from %@:%d allowed",
                                    ssh_ipaddr_render, remote_address, port));
    }
    else
    {
        /* New connection rejected. */
        SSH_DEBUG(SSH_D_FAIL, ("New connection from %@:%d forbidden",
                               ssh_ipaddr_render, remote_address, port));
    }

    return error;
}
Example #12
0
/* This function processes an rhosts-style file (.rhosts, .shosts, or
   /etc/hosts.equiv).  This returns true if authentication can be granted
   based on the file, and returns zero otherwise.  All I/O will be done
   using the given uid with userfile. */
Boolean check_rhosts_file(uid_t uid, const char *filename,
                          const char *hostname,
                          const char *ipaddr, const char *client_user,
                          const char *server_user, void *context)
{
  SshUserFile uf;
  char buf[1024]; /* Must not be larger than host, user, dummy below. */
  SshServer server = (SshServer) context;
  
  /* Open the .rhosts file. */
  uf = ssh_userfile_open(uid, filename, O_RDONLY, 0);
  if (uf == NULL)
    return FALSE; /* Cannot read the .rhosts - deny access. */

  /* Go through the file, checking every entry. */
  while (ssh_userfile_gets(buf, sizeof(buf), uf))
    {
      /* All three must be at least as big as buf to avoid overflows. */
      char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp, *c;
      int negated;
      
      for(cp = buf; *cp; cp++)
        {
          if (*cp < 32 && !isspace(*cp))
            {
              SSH_TRACE(2, ("Found control characters in '%s', rest of "\
                            "the file ignored", filename));
              ssh_userfile_close(uf);
              return FALSE;
            }
        }
      for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
        ;
      if ((c = strchr(cp, '#')) != NULL)
        *c = '\0';
      if (*cp == '#' || *cp == '\n' || !*cp)
        continue;

      /* NO_PLUS is supported at least on OSF/1.  We skip it (we don't ever
         support the plus syntax). */
      if (strncmp(cp, "NO_PLUS", 7) == 0)
        continue;

      /* This should be safe because each buffer is as big as the whole
         string, and thus cannot be overwritten. */
      switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy))
        {
        case 0:
          SSH_DEBUG(2, ("Found empty line in %.100s.", filename));
          continue; /* Empty line? */
        case 1:
          /* Host name only. */
          strncpy(userbuf, server_user, sizeof(userbuf));
          userbuf[sizeof(userbuf) - 1] = 0;
          break;
        case 2:
          /* Got both host and user name. */
          break;
        case 3:
          SSH_TRACE(2, ("Found garbage in %.100s.", filename));
          continue; /* Extra garbage */
        default:
          continue; /* Weird... */
        }

      host = hostbuf;
      user = userbuf;
      /* Truncate host and user name to 255 to avoid buffer overflows in system
         libraries */
      if (strlen(host) > 255)
        host[255] = '\0';
      if (strlen(user) > 255)
        user[255] = '\0';
      negated = 0;

      /* Process negated host names, or positive netgroups. */
      if (host[0] == '-')
        {
          negated = 1;
          host++;
        }
      else
        if (host[0] == '+')
          host++;

      if (user[0] == '-')
        {
          negated = 1;
          user++;
        }
      else
        if (user[0] == '+')
          user++;

      /* Check for empty host/user names (particularly '+'). */
      if (!host[0] || !user[0])
        { 
          /* We come here if either was '+' or '-'. */
          SSH_TRACE(2, ("Ignoring wild host/user names in %.100s.", \
                        filename));
          continue;
        }
          
#ifdef HAVE_INNETGR
      
      /* Verify that host name matches. */
      if (host[0] == '@')
        {
          if (!innetgr(host + 1, (char *)hostname, NULL, NULL) &&
              !innetgr(host + 1, (char *)ipaddr, NULL, NULL))
            continue;
        }
      else
        if (!casefold_equal(host, hostname) && strcmp(host, ipaddr) != 0)
          continue; /* Different hostname. */

      /* Verify that user name matches. */
      if (user[0] == '@')
        {
          if (!innetgr(user + 1, NULL, (char *)client_user, NULL))
            continue;
        }
      else
        if (strcmp(user, client_user) != 0)
          continue; /* Different username. */

#else /* HAVE_INNETGR */

      if (!casefold_equal(host, hostname) && strcmp(host, ipaddr) != 0)
        continue; /* Different hostname. */

      if (strcmp(user, client_user) != 0)
        continue; /* Different username. */

#endif /* HAVE_INNETGR */

      /* XXX sync with ssh_server_auth_check_host */
      /* XXX this function is a silly place for this. This should be
         in ssh_server_auth_hostbased_rhosts(), where these checks
         would be performed before coming here. */
      {
        Boolean perm_denied = FALSE;
        
        if (server->config->denied_shosts)
          {
            if (!ssh_match_host_in_list(server->common->remote_host,
                                        server->common->remote_ip,
                                        server->config->denied_shosts))
              perm_denied = TRUE;
          }
      
        if (!perm_denied && server->config->allowed_shosts)
          {
            if (!ssh_match_host_in_list(server->common->remote_host,
                                        server->common->remote_ip,
                                        server->config->allowed_shosts))
              perm_denied = FALSE;
            else
              perm_denied = TRUE;
          }      
      
        /* RequireReverseMapping */
        if (server->config->require_reverse_mapping)
          {
            if (strcmp(server->common->remote_host,
                       server->common->remote_ip) == 0)
              {
                /* If remote host's ip-address couldn't be mapped to a
                   hostname and RequireReverseMapping = 'yes', deny
                   connection.*/
                perm_denied = TRUE;
              }
          }

        if (perm_denied)
          {
            ssh_log_event(server->config->log_facility, SSH_LOG_WARNING,
                          "Use of %s denied for %s", filename, host);
            SSH_TRACE(2, ("Use of %s denied for %s", filename, host));
            continue;
          }
      }
      
      /* Found the user and host. */
      ssh_userfile_close(uf);

      /* If the entry was negated, deny access. */
      if (negated)
        {
          SSH_TRACE(2, ("Matched negative entry in %.100s.", \
                        filename));
          return FALSE;
        }

      /* Accept authentication. */
      return TRUE;
    }
     
  /* Authentication using this file denied. */
  ssh_userfile_close(uf);
  return FALSE;
}
Example #13
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;
}