Ejemplo n.º 1
0
bool clSSH::AuthenticateServer(wxString& message)
{
    int state;
    unsigned char* hash = NULL;
    char* hexa = NULL;

    message.Clear();
    state = ssh_is_server_known(m_session);

#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 6, 1)
    int hlen = 0;
    hlen = ssh_get_pubkey_hash(m_session, &hash);
    if(hlen < 0) { throw clException("Unable to obtain server public key!"); }
#else
    size_t hlen = 0;
    ssh_key key = NULL;
    ssh_get_publickey(m_session, &key);
    ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen);
    if(hlen == 0) { throw clException("Unable to obtain server public key!"); }
#endif

    switch(state) {
    case SSH_SERVER_KNOWN_OK:
        free(hash);
        return true;

    case SSH_SERVER_KNOWN_CHANGED:
        hexa = ssh_get_hexa(hash, hlen);
        message << _("Host key for server changed: it is now:\n") << hexa << "\n" << _("Accept server authentication?");
        free(hexa);
        free(hash);
        return false;

    case SSH_SERVER_FOUND_OTHER:
        message << _("The host key for this server was not found but another type of key exists.\n")
                << _("An attacker might change the default server key to confuse your client into thinking the key "
                     "does not exist\n")
                << _("Accept server authentication?");
        free(hash);
        return false;

    case SSH_SERVER_FILE_NOT_FOUND:
        message << _("Could not find known host file.\n")
                << _("If you accept the host key here, the file will be automatically created.\n");
    /* fallback to SSH_SERVER_NOT_KNOWN behavior */
    case SSH_SERVER_NOT_KNOWN:
        hexa = ssh_get_hexa(hash, hlen);
        message << _("The server is unknown. Do you trust the host key?\n") << _("Public key hash: ") << hexa << "\n"
                << _("Accept server authentication?");
        free(hexa);
        free(hash);
        return false;

    default:
    case SSH_SERVER_ERROR:
        throw clException(wxString() << "An error occurred: " << ssh_get_error(m_session));
    }
    return false;
}
Ejemplo n.º 2
0
static const gchar *
verify_knownhost (CockpitSshData *data)
{
  const gchar *ret = "unknown-hostkey";
  ssh_key key = NULL;
  unsigned char *hash = NULL;
  const char *type = NULL;
  int state;
  gsize len;

  data->host_key = get_knownhosts_line (data->session);
  if (data->host_key == NULL)
    {
      ret = "internal-error";
      goto done;
    }

  if (ssh_get_publickey (data->session, &key) != SSH_OK)
    {
      g_warning ("Couldn't look up ssh host key");
      ret = "internal-error";
      goto done;
    }

  type = ssh_key_type_to_char (ssh_key_type (key));
  if (type == NULL)
    {
      g_warning ("Couldn't lookup host key type");
      ret = "internal-error";
      goto done;
    }

  if (ssh_get_publickey_hash (key, SSH_PUBLICKEY_HASH_MD5, &hash, &len) < 0)
    {
      g_warning ("Couldn't hash ssh public key");
      ret = "internal-error";
      goto done;
    }
  else
    {
      data->host_fingerprint = ssh_get_hexa (hash, len);
      ssh_clean_pubkey_hash (&hash);
    }

  if (data->expect_key)
    {
      /* Only check that the host key matches this specifically */
      if (g_str_equal (data->host_key, data->expect_key))
        {
          g_debug ("%s: host key matched expected", data->logname);
          ret = NULL; /* success */
        }
      else
        {
          /* A empty expect_key is used by the frontend to force
             failure.  Don't warn about it.
          */
          if (data->expect_key[0])
            g_message ("%s: host key did not match expected", data->logname);
        }
    }
  else
    {
      if (ssh_options_set (data->session, SSH_OPTIONS_KNOWNHOSTS, data->knownhosts_file) != SSH_OK)
        {
          g_warning ("Couldn't set knownhosts file location");
          ret = "internal-error";
          goto done;
        }

      state = ssh_is_server_known (data->session);
      if (state == SSH_SERVER_KNOWN_OK)
        {
          g_debug ("%s: verified host key", data->logname);
          ret = NULL; /* success */
          goto done;
        }
      else if (state == SSH_SERVER_ERROR)
        {
          if (g_atomic_int_get (data->connecting))
            g_warning ("%s: couldn't check host key: %s", data->logname,
                       ssh_get_error (data->session));
          ret = "internal-error";
          goto done;
        }

      switch (state)
        {
        case SSH_SERVER_KNOWN_OK:
        case SSH_SERVER_ERROR:
          g_assert_not_reached ();
          break;
        case SSH_SERVER_KNOWN_CHANGED:
          g_message ("%s: %s host key for server has changed to: %s",
                     data->logname, type, data->host_fingerprint);
          break;
        case SSH_SERVER_FOUND_OTHER:
          g_message ("%s: host key for this server changed key type: %s",
                     data->logname, type);
          break;
        case SSH_SERVER_FILE_NOT_FOUND:
          g_debug ("Couldn't find the known hosts file");
          /* fall through */
        case SSH_SERVER_NOT_KNOWN:
          g_message ("%s: %s host key for server is not known: %s",
                     data->logname, type, data->host_fingerprint);
          break;
        }
    }

done:
  if (key)
    ssh_key_free (key);
  return ret;
}
Ejemplo n.º 3
0
gint
remmina_ssh_auth_gui (RemminaSSH *ssh, RemminaInitDialog *dialog, gboolean threaded)
{
	gchar *tips;
	gchar *keyname;
	gint ret;
	size_t len;
	guchar *pubkey;
	ssh_key server_pubkey;

	/* Check if the server's public key is known */
	ret = ssh_is_server_known (ssh->session);
	switch (ret)
	{
		case SSH_SERVER_KNOWN_OK:
			break;

		case SSH_SERVER_NOT_KNOWN:
		case SSH_SERVER_FILE_NOT_FOUND:
		case SSH_SERVER_KNOWN_CHANGED:
		case SSH_SERVER_FOUND_OTHER:
			if ( ssh_get_publickey(ssh->session, &server_pubkey) != SSH_OK )
			{
				remmina_ssh_set_error(ssh, "ssh_get_publickey() has failed: %s");
				return 0;
			}
			if ( ssh_get_publickey_hash(server_pubkey, SSH_PUBLICKEY_HASH_MD5, &pubkey, &len) != 0 ) {
				ssh_key_free(server_pubkey);
				remmina_ssh_set_error(ssh, "ssh_get_publickey_hash() has failed: %s");
				return 0;
			}
			ssh_key_free(server_pubkey);
			keyname = ssh_get_hexa (pubkey, len);

			if (threaded) gdk_threads_enter();
			if (ret == SSH_SERVER_NOT_KNOWN || ret == SSH_SERVER_FILE_NOT_FOUND)
			{
				ret = remmina_init_dialog_serverkey_unknown (dialog, keyname);
			}
			else
			{
				ret = remmina_init_dialog_serverkey_changed (dialog, keyname);
			}
			if (threaded)
			{	gdk_flush();gdk_threads_leave();}

			ssh_string_free_char(keyname);
			ssh_clean_pubkey_hash (&pubkey);
			if (ret != GTK_RESPONSE_OK) return -1;
			ssh_write_knownhost (ssh->session);
			break;
		case SSH_SERVER_ERROR:
		default:
			remmina_ssh_set_error (ssh, "SSH known host checking failed: %s");
		return 0;
	}

	/* Try empty password or existing password first */
	ret = remmina_ssh_auth (ssh, NULL);
	if (ret > 0) return 1;

	/* Requested for a non-empty password */
	if (ret < 0)
	{
		if (!dialog) return -1;

		switch (ssh->auth)
		{
			case SSH_AUTH_PASSWORD:
			tips = _("Authenticating %s's password to SSH server %s...");
			keyname = _("SSH password");
			break;
			case SSH_AUTH_PUBLICKEY:
			tips = _("Authenticating %s's identity to SSH server %s...");
			keyname = _("SSH private key passphrase");
			break;
			default:
			return FALSE;
		}

		if (ssh->auth != SSH_AUTH_AUTO_PUBLICKEY)
		{
			if (threaded) gdk_threads_enter();
			remmina_init_dialog_set_status (dialog, tips, ssh->user, ssh->server);

			ret = remmina_init_dialog_authpwd (dialog, keyname, FALSE);
			if (threaded)
			{	gdk_flush();gdk_threads_leave();}

			if (ret != GTK_RESPONSE_OK) return -1;
		}
		ret = remmina_ssh_auth (ssh, dialog->password);
	}

	if (ret <= 0)
	{
		return 0;
	}

	return 1;
}
Ejemplo n.º 4
0
// Verify if Server is a known host.
int SSH_Socket::verify_knownhost()
{
    int state;
    size_t hlen;
    unsigned char *hash = nullptr;
    char *hexa;

    state = ssh_is_server_known(session);
    ssh_key srv_pubkey;
    int rc;

    rc = ssh_get_publickey(session, &srv_pubkey);
    if(rc < 0)
    {
        return -1;
    }

    rc = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen);
    ssh_key_free(srv_pubkey);
    if(rc < 0)
    {
        return -1;
    }

    switch(state)
    {
        case SSH_SERVER_KNOWN_OK:
            break; /* ok */

        case SSH_SERVER_KNOWN_CHANGED:
            std::cout << "Host key for server changed: it is now" << std::endl;
            ssh_print_hexa("Public key hash", hash, hlen);
            std::cout << "For security reasons, connection will be stopped" << std::endl;
            free(hash);
            return -1;

        case SSH_SERVER_FOUND_OTHER:
            std::cout << "The host key for this server was not found but an other"
                      << "type of key exists." << std::endl;
            std::cout << "An attacker might change the default server key to"
                      << "confuse your client into thinking the key does not exist" << std::endl;
            free(hash);
            return -1;

        case SSH_SERVER_FILE_NOT_FOUND:
            std::cout << "Could not find known host file." << std::endl;
            std::cout << "If you accept the host key here, the file will be"
                      << "automatically created." << std::endl;

            /* fallback to SSH_SERVER_NOT_KNOWN behavior */
        case SSH_SERVER_NOT_KNOWN:
            hexa = ssh_get_hexa(hash, hlen);
            //Do you trust the host key?\n");
            std::cout << "The server is unknown. Adding Key." << std::endl;
            std::cout << "Public key hash: " << hexa << std::endl;
            free(hexa);

            /*
            if (fgets(buf, sizeof(buf), stdin) == NULL)
            {
                free(hash);
                return -1;
            }
            if (strncasecmp(buf, "yes", 3) != 0)
            {
                free(hash);
                return -1;
            }
            */
            if(ssh_write_knownhost(session) < 0)
            {
                std::cout << "Error: " << strerror(errno) << std::endl;
                free(hash);
                return -1;
            }
            break;

        case SSH_SERVER_ERROR:
            std::cout << "Error: " << ssh_get_error(session) << std::endl;
            free(hash);
            return -1;
    }
    free(hash);
    return 0;
}
Ejemplo n.º 5
0
int knownhost_verify(ssh_session_t *session){
  char *hexa;
  int state;
  char buf[10];
  unsigned char *hash = NULL;
  size_t hlen;
  ssh_key_t *srv_pubkey;
  int rc;

  state=ssh_is_server_known(session);

  rc = ssh_get_publickey(session, &srv_pubkey);
  if (rc < 0) {
      return -1;
  }

  rc = ssh_get_publickey_hash(srv_pubkey,
                              SSH_PUBLICKEY_HASH_SHA1,
                              &hash,
                              &hlen);
  ssh_key_free(srv_pubkey);
  if (rc < 0) {
      return -1;
  }

  switch(state){
    case SSH_SERVER_KNOWN_OK:
      break; /* ok */
    case SSH_SERVER_KNOWN_CHANGED:
      fprintf(stderr,"Host key for server changed : server's one is now :\n");
      ssh_print_hexa("Public key hash",hash, hlen);
      ssh_clean_pubkey_hash(&hash);
      fprintf(stderr,"For security reason, connection will be stopped\n");
      return -1;
    case SSH_SERVER_FOUND_OTHER:
      fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
      fprintf(stderr,"An attacker might change the default server key to confuse your client"
          "into thinking the key does not exist\n"
          "We advise you to rerun the client with -d or -r for more safety.\n");
      return -1;
    case SSH_SERVER_FILE_NOT_FOUND:
      fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
      fprintf(stderr,"the file will be automatically created.\n");
      /* fallback to SSH_SERVER_NOT_KNOWN behavior */
    case SSH_SERVER_NOT_KNOWN:
      hexa = ssh_get_hexa(hash, hlen);
      fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
      fprintf(stderr, "Public key hash: %s\n", hexa);
      ssh_string_free_char(hexa);
      if (fgets(buf, sizeof(buf), stdin) == NULL) {
	    ssh_clean_pubkey_hash(&hash);
        return -1;
      }
      if(strncasecmp(buf,"yes",3)!=0){
	    ssh_clean_pubkey_hash(&hash);
        return -1;
      }
      fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
      if (fgets(buf, sizeof(buf), stdin) == NULL) {
	    ssh_clean_pubkey_hash(&hash);
        return -1;
      }
      if(strncasecmp(buf,"yes",3)==0){
        if (ssh_write_knownhost(session) < 0) {
          ssh_clean_pubkey_hash(&hash);
          fprintf(stderr, "error %s\n", strerror(errno));
          return -1;
        }
      }

      break;
    case SSH_SERVER_ERROR:
      ssh_clean_pubkey_hash(&hash);
      fprintf(stderr,"%s",ssh_get_error(session));
      return -1;
  }
  ssh_clean_pubkey_hash(&hash);
  return 0;
}