예제 #1
0
파일: cl_ssh.cpp 프로젝트: eranif/codelite
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;
}
예제 #2
0
int verify_knownhost(ssh_session session){
  char *hexa;
  int state;
  char buf[10];
  unsigned char *hash = NULL;
  int hlen;

  state=ssh_is_server_known(session);

  hlen = ssh_get_pubkey_hash(session, &hash);
  if (hlen < 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);
      free(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);
      free(hexa);
      fgets(buf,sizeof(buf),stdin);
      if(strncasecmp(buf,"yes",3)!=0){
        return -1;
      }
      fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
      fgets(buf,sizeof(buf),stdin);
      if(strncasecmp(buf,"yes",3)==0){
        if (ssh_write_knownhost(session) < 0) {
          free(hash);
          fprintf(stderr, "error %s\n", strerror(errno));
          return -1;
        }
      }

      break;
    case SSH_SERVER_ERROR:
      free(hash);
      fprintf(stderr,"%s",ssh_get_error(session));
      return -1;
  }
  free(hash);
  return 0;
}
예제 #3
0
/**
 * Check if the host doesn't change
 * @return  bool                  true if it's ok, false else
 */
bool Kssh::check_known_host()
{
    QString error, server_public_key;
    int state, hlen;
    unsigned char *hash = NULL;

    // get the public key of the server
    state = ssh_is_server_known(this->m_session);
    hlen = ssh_get_pubkey_hash(this->m_session, &hash);

    if (hlen < 0) {
#ifdef DEBUG
        Klog::debug("no public key for this server");
#endif
        return false;
    }

    server_public_key = QString(ssh_get_hexa(hash, hlen));

    delete[] hash;

    switch (state) {
        case SSH_SERVER_KNOWN_OK:
            break;

        case SSH_SERVER_KNOWN_CHANGED:
            Klog::warning(QString("Host key for server changed, now it's : ") + server_public_key);
            return false;

        case SSH_SERVER_FOUND_OTHER:
            error = "The host key for this server was not found but an other type of key exists.\n"
                    "into thinking the key does not exist.\n";
            Klog::warning(error);
            return false;

        case SSH_SERVER_FILE_NOT_FOUND:
            Klog::warning("Could not find known host file. This file will be automatically created.");
            if (ssh_write_knownhost(this->m_session) < 0) {
#ifdef DEBUG
                Klog::debug("impossible to write the knowhosts");
#endif
            }
            break;

        case SSH_SERVER_NOT_KNOWN:
            Klog::warning("The server is unknown. This new key will be written on disk for further usage.");
            if (ssh_write_knownhost(this->m_session) < 0) {
#ifdef DEBUG
                Klog::debug("impossible to write the knowhosts");
#endif
            }
            break;

        case SSH_SERVER_ERROR:
            Klog::error(QString("Error while check the knowhosts : ") + QString(ssh_get_error(this->m_session)));
            return false;
      }

    return true;
}
예제 #4
0
파일: dh.c 프로젝트: mwgoldsmith/ssh
/**
 * @brief Print a buffer as colon separated hex string.
 *
 * @param  descr        Description printed in front of the hex string.
 *
 * @param  what         What should be converted to a hex string.
 *
 * @param  len          Length of the buffer to convert.
 */
void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) {
    char *hexa = ssh_get_hexa(what, len);

    if (hexa == NULL) {
      return;
    }
    printf("%s: %s\n", descr, hexa);

    free(hexa);
}
예제 #5
0
파일: full.c 프로젝트: birdatdotty/webutils
int verify_knownhost(ssh_session session) {

  int state, hlen;
  unsigned char *hash = NULL;
  char *hexa;
  char buf[10];

  state = ssh_is_server_known(session);
  hlen = ssh_get_pubkey_hash(session, &hash);

  if (hlen < 0)
    return -1;
  switch (state)

  {
    case SSH_SERVER_KNOWN_OK:
      break; /* ok */
    case SSH_SERVER_KNOWN_CHANGED:
      fprintf(stderr, "Host key for server changed: it is now:\n");
      ssh_print_hexa("Public key hash", hash, hlen);
      fprintf(stderr, "For security reasons, connection will be stopped\n");
      free(hash);
      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");
      free(hash);
      return -1;
    case SSH_SERVER_FILE_NOT_FOUND:
      fprintf(stderr, "Could not find known host file.\n");
      fprintf(stderr, "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);
      fprintf(stderr,"The server is unknown. Do you trust the host key [yes/no]?\n");
      fprintf(stderr, "Public key hash: %s\n", hexa);
      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)
      {
        fprintf(stderr, "Error %s\n", strerror(errno));
        free(hash);
        return -1;
      }
      break;
    case SSH_SERVER_ERROR:
      fprintf(stderr, "Error %s", ssh_get_error(session));
      free(hash);
      return -1;
  }

  free(hash);
  return 0;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
0
/**
    Verifying the target host.

    @param session is the created ssh session
    @return the server status 
*/
int SSHSession::verifyKnownHost(ssh_session session) {
  unsigned char *hash = NULL;
  auto state = ssh_is_server_known(session);
  auto hlen = ssh_get_pubkey_hash(session, &hash);
  char buf[10];  
  char *hexa;

  if (hlen < 0)
    return -1;
  
  switch (state) {
    case SSH_SERVER_KNOWN_OK:
      return 1; // 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);
      delete 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; 
      delete 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; 
      delete hash;
      return -1;

    case SSH_SERVER_NOT_KNOWN:
      hexa = ssh_get_hexa(hash, hlen);
      std::cout << "The server is unknown. Do you trust the host key?" << std::endl;
      std::cout << "Public key hash: " << hexa << std::endl;
      delete hexa;
      if (fgets(buf, sizeof(buf), stdin) == NULL) {
        delete hash;
        return -1;
      }
      
      if (strncasecmp(buf, "yes", 3) != 0) {
        delete hash;
        return -1;
      }
   
      if (ssh_write_knownhost(session) < 0) {
        std::cout << "Error" << std::endl;
        delete hash;
        return -1;
      }
      break;

    case SSH_SERVER_ERROR:
      std::cout << "Error" << ssh_get_error(session) << std::endl;
      delete hash;
      return -1;
  }

  delete hash;
  return 0;  
}
예제 #9
0
static int _sftp_connect(const char *uri) {
  char *scheme = NULL;
  char *user = NULL;
  char *passwd = NULL;
  char *host = NULL;
  unsigned int port = 0;
  char *path = NULL;
  unsigned char *hash = NULL;
  int hlen;
  int rc = -1;
  int state = SSH_SERVER_ERROR;
  int timeout = 10;
  int method;
  char *verbosity;

  if (_connected) {
    return 0;
  }

  rc = c_parse_uri(uri, &scheme, &user, &passwd, &host, &port, &path);
  if (rc < 0) {
    goto out;
  }

  DEBUG_SFTP(("csync_sftp - conntecting to: %s\n", host));

  /* create the session */
  _ssh_session = ssh_new();
  if (_ssh_session == NULL) {
    fprintf(stderr, "csync_sftp - error creating new connection: %s\n",
        strerror(errno));
    rc = -1;
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_TIMEOUT, &timeout);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_COMPRESSION_C_S, "none");
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  rc = ssh_options_set(_ssh_session, SSH_OPTIONS_COMPRESSION_S_C, "none");
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  ssh_options_set(_ssh_session, SSH_OPTIONS_HOST, host);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error setting options: %s\n",
        strerror(errno));
    goto out;
  }

  if (port) {
    ssh_options_set(_ssh_session, SSH_OPTIONS_PORT, &port);
    if (rc < 0) {
      fprintf(stderr, "csync_sftp - error setting options: %s\n",
          strerror(errno));
      goto out;
    }
    DEBUG_SFTP(("csync_sftp - port set to: %d\n", port));
  }

  if (user && *user) {
    ssh_options_set(_ssh_session, SSH_OPTIONS_USER, user);
    if (rc < 0) {
      fprintf(stderr, "csync_sftp - error setting options: %s\n",
          strerror(errno));
      goto out;
    }
    DEBUG_SFTP(("csync_sftp - username set to: %s\n", user));
  }

  verbosity = getenv("CSYNC_SFTP_LOG_VERBOSITY");
  if (verbosity) {
    rc = ssh_options_set(_ssh_session, SSH_OPTIONS_LOG_VERBOSITY_STR, verbosity);
    if (rc < 0) {
      goto out;
    }
  }

  /* read ~/.ssh/config */
  rc = ssh_options_parse_config(_ssh_session, NULL);
  if (rc < 0) {
    goto out;
  }

  _ssh_callbacks = (ssh_callbacks) c_malloc(sizeof(struct ssh_callbacks_struct));
  if (_ssh_callbacks == NULL) {
    rc = -1;
    goto out;
  }
  ZERO_STRUCTP(_ssh_callbacks);

  _ssh_callbacks->userdata = _userdata;
  _ssh_callbacks->auth_function = _ssh_auth_callback;

  ssh_callbacks_init(_ssh_callbacks);

  ssh_set_callbacks(_ssh_session, _ssh_callbacks);

  rc = ssh_connect(_ssh_session);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error connecting to the server: %s\n", ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    goto out;
  }

  hlen = ssh_get_pubkey_hash(_ssh_session, &hash);
  if (hlen < 0) {
    fprintf(stderr, "csync_sftp - error connecting to the server: %s\n",
        ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    goto out;
  }

  /* check the server public key hash */
  state = ssh_is_server_known(_ssh_session);
  switch (state) {
    case SSH_SERVER_KNOWN_OK:
      break;
    case SSH_SERVER_KNOWN_CHANGED:
      fprintf(stderr, "csync_sftp - 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"
            "Please contact your system administrator.\n"
            "%s\n", ssh_get_error(_ssh_session));
      ssh_print_hexa("csync_sftp - public key hash", hash, hlen);

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_FOUND_OTHER:
      fprintf(stderr, "csync_sftp - the host key for this server was not "
          "found but an other type of key exists.\n");
      fprintf(stderr, "csync_sftp - an attacker might change the default "
          "server key to confuse your client into thinking the key does not "
          "exist\n");
      fprintf(stderr, "The host key for the server %s has changed.\n"
          "This could either mean that DNS SPOOFING is happening or the IP "
          "address for the host and its host key have changed at the same time.\n"
          "The fingerprint for the key sent by the remote host is:\n", host);
          ssh_print_hexa("", hash, hlen);
          fprintf(stderr, "Please contact your system administrator.\n"
          "%s\n", ssh_get_error(_ssh_session));

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_NOT_KNOWN:
      if (_authcb) {
        char *hexa;
        char *prompt;
        char buf[4] = {0};

        hexa = ssh_get_hexa(hash, hlen);
        if (hexa == NULL) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        if (asprintf(&prompt,
              "The authenticity of host '%s' can't be established.\n"
              "RSA key fingerprint is %s.\n"
              "Are you sure you want to continue connecting (yes/no)?",
              host, hexa) < 0 ) {
          free(hexa);
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        free(hexa);

        if ((*_authcb)(prompt, buf, sizeof(buf), 1, 0, _userdata) < 0) {
          free(prompt);
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        free(prompt);

        if (strncasecmp(buf, "yes", 3) != 0) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }

        if (ssh_write_knownhost(_ssh_session) < 0) {
          ssh_disconnect(_ssh_session);
          _ssh_session = NULL;
          ssh_finalize();
          rc = -1;
          goto out;
        }
      } else {
        fprintf(stderr,"csync_sftp - the server is unknown. Connect manually to "
            "the host to retrieve the public key hash, then try again.\n");
      }
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    case SSH_SERVER_ERROR:
      fprintf(stderr, "%s\n", ssh_get_error(_ssh_session));

      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
      break;
    default:
      break;
  }

  /* Try to authenticate */
  rc = ssh_userauth_none(_ssh_session, NULL);
  if (rc == SSH_AUTH_ERROR) {
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
  }

#if 0
  /* authenticate with the server */
  if (passwd && *passwd) {
    DEBUG_SFTP(("csync_sftp - authenticating with user/password\n"));
    /*
     * This is tunneled cleartext password authentication and possibly needs
     * to be allowed by the ssh server. Set 'PasswordAuthentication yes'
     */
    auth = ssh_userauth_password(_ssh_session, user, passwd);
  } else {
    DEBUG_SFTP(("csync_sftp - authenticating with pubkey\n"));
    auth = ssh_userauth_autopubkey(_ssh_session, NULL);
  }

  if (auth == SSH_AUTH_ERROR) {
    fprintf(stderr, "csync_sftp - authenticating with pubkey: %s\n",
        ssh_get_error(_ssh_session));
    ssh_disconnect(_ssh_session);
    _ssh_session = NULL;
    ssh_finalize();
    rc = -1;
    goto out;
  }

  if (auth != SSH_AUTH_SUCCESS) {
    if (_authcb != NULL) {
      auth = auth_kbdint(_ssh_session);
      if (auth == SSH_AUTH_ERROR) {
        fprintf(stderr,"csync_sftp - authentication failed: %s\n",
            ssh_get_error(_ssh_session));
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      }
    } else {
      ssh_disconnect(_ssh_session);
      _ssh_session = NULL;
      ssh_finalize();
      rc = -1;
      goto out;
    }
  }


#endif
  method = ssh_auth_list(_ssh_session);

  while (rc != SSH_AUTH_SUCCESS) {
    /* Try to authenticate with public key first */
    if (method & SSH_AUTH_METHOD_PUBLICKEY) {
      rc = ssh_userauth_autopubkey(_ssh_session, NULL);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }

    /* Try to authenticate with keyboard interactive */
    if (method & SSH_AUTH_METHOD_INTERACTIVE) {
      rc = auth_kbdint(_ssh_session, user, passwd);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }

    /* Try to authenticate with password */
    if ((method & SSH_AUTH_METHOD_PASSWORD) && passwd && *passwd) {
      rc = ssh_userauth_password(_ssh_session, user, passwd);
      if (rc == SSH_AUTH_ERROR) {
        ssh_disconnect(_ssh_session);
        _ssh_session = NULL;
        ssh_finalize();
        rc = -1;
        goto out;
      } else if (rc == SSH_AUTH_SUCCESS) {
        break;
      }
    }
  }

  DEBUG_SFTP(("csync_sftp - creating sftp channel...\n"));
  /* start the sftp session */
  _sftp_session = sftp_new(_ssh_session);
  if (_sftp_session == NULL) {
    fprintf(stderr, "csync_sftp - sftp error initialising channel: %s\n", ssh_get_error(_ssh_session));
    rc = -1;
    goto out;
  }

  rc = sftp_init(_sftp_session);
  if (rc < 0) {
    fprintf(stderr, "csync_sftp - error initialising sftp: %s\n", ssh_get_error(_ssh_session));
    goto out;
  }

  DEBUG_SFTP(("csync_sftp - connection established...\n"));
  _connected = 1;
  rc = 0;
out:
  SAFE_FREE(scheme);
  SAFE_FREE(user);
  SAFE_FREE(passwd);
  SAFE_FREE(host);
  SAFE_FREE(path);
  SAFE_FREE(hash);

  return rc;
}
예제 #10
0
int
ssh_connect_p (char *haddr, int hport, char *remote_version, char * remote_fingerprint)
{
	struct timeval tv;
	double elapsed_time;

	ssh_session my_ssh_session;
	int  version;
	int myversion;
	int hlen;
	int rc;
	int state;
	int i;
	unsigned char *hash = NULL;
	char *  fingerprint;
	int in_known_host;

	int sshv1,sshv2,sshv3;

	gettimeofday(&tv, NULL);

	my_ssh_session = ssh_new();

	if (my_ssh_session == NULL)
		return STATE_CRITICAL;

	ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, haddr);
	ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &hport);
	rc = ssh_connect(my_ssh_session);
	if (rc != SSH_OK) {
		printf ("Connect to Server failed\n");
		exit (STATE_CRITICAL);
	}
	in_known_host=-1;
	state = ssh_is_server_known(my_ssh_session);
	hlen = ssh_get_pubkey_hash(my_ssh_session, &hash);

	/* Get the finger print as a string */
	fingerprint = ssh_get_hexa(hash, hlen);
	if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") == NULL) {
		if(state != SSH_SERVER_KNOWN_OK) {
			printf ("SSH CRITICAL - Fingerprint (%s) checked in known_hosts failed\n", remote_fingerprint,fingerprint);
			exit(STATE_CRITICAL);
		} else {
			in_known_host=1;
		}
	}

	/* FIXME: This alwats eval to false... */
	if(remote_fingerprint && strcmp(remote_fingerprint, "known_host") && strcmp(remote_fingerprint, fingerprint)) {
		printf ("SSH CRITICAL - Fingerprint (%s) mismatched %s\n", remote_fingerprint,fingerprint);
		free(fingerprint);
		exit(STATE_CRITICAL);
	}

	version = ssh_get_openssh_version(my_ssh_session);
	if(remote_version && sscanf(remote_version, "%d.%d.%d", &sshv1, &sshv2, &sshv3)) {
		myversion = SSH_VERSION_INT(sshv1, sshv2, sshv3);
		if(version < myversion) {
			printf ("SSH WARNING version on server is below %s\n", remote_version);
			exit(STATE_CRITICAL);
		}
	}

	elapsed_time = (double)deltime(tv) / 1.0e6;

	printf (_("SSH OK - fingerprint: %s (Version %d) known_host_check:%d | %s\n"),
	        fingerprint, version,in_known_host, fperfdata("time", elapsed_time, "s",
	        FALSE, 0, FALSE, 0, TRUE, 0, TRUE, (int)socket_timeout));
	free(fingerprint);
	ssh_disconnect(my_ssh_session);
	ssh_free(my_ssh_session);
	exit(STATE_OK);

}
예제 #11
0
파일: sshclient.cpp 프로젝트: aopui/gnash
bool
SSHClient::sshConnect(int /* fd */, std::string &hostname)
{
//     GNASH_REPORT_FUNCTION;
    char *password;
    char *banner;
    char *hexa;

    // We always need a hostname to connect to
    if (ssh_options_set(_session, SSH_OPTIONS_HOST, hostname.c_str()) < 0) {
	log_error(_("Couldn't set hostname option"));
	return false;
    }

    // We always need a user name for the connection
    if (_user.empty()) {
	if (ssh_options_set(_session, SSH_OPTIONS_USER, _user.c_str()) < 0) {
	    log_error(_("Couldn't set user name option"));
	    return false;
	}
    }
    
    // Start a new session
    _session = ssh_new();
    if(ssh_connect(_session)){
        log_error(_("Connection failed : %s\n"), ssh_get_error(_session));
	sshShutdown();
        return false;
    }

    _state = ssh_is_server_known(_session);

    unsigned char *hash = 0;
    int hlen = ssh_get_pubkey_hash(_session, &hash);
    if (hlen < 0) {
	sshShutdown();
	return false;
    }
    switch(_state){
      case SSH_SERVER_KNOWN_OK:	// ok
	  log_debug(_("SSH Server is currently known: %d"), _state);
	  break; 
      case SSH_SERVER_KNOWN_CHANGED:
	  log_error(_("Host key for server changed : server's one is now: "));
	  ssh_print_hexa(_("Public key hash"), hash, hlen);
	  free(hash);
	  log_error(_("For security reason, connection will be stopped"));
	  sshShutdown();
	  return false;;
      case SSH_SERVER_FOUND_OTHER:
	  log_error(_("The host key for this server was not found but an other type of key exists."));
	  log_error(_("An attacker might change the default server key to confuse your client"
		    " into thinking the key does not exist"
		      "We advise you to rerun the client with -d or -r for more safety."));
	  sshShutdown();
	  return false;;
      case SSH_SERVER_NOT_KNOWN:
	  hexa = ssh_get_hexa(hash, hlen);
	  free(hash);
	  // FIXME: for now, accecpt all new keys, and update the 
	  // $HOME/.ssh/know_hosts file.
#if 0
	  log_error(_("The server is unknown. Do you trust the host key ? (yes,no)"));
	  log_error(_("Public key hash: %s"), hexa);
	  free(hexa);
	  fgets(buf, sizeof(buf), stdin);
	  if(strncasecmp(buf, "yes", 3) != 0){
	      sshShutdown();
	      return false;
	  }
	  log_error(_("This new key will be written on disk for further usage. do you agree? (yes,no) "));
	  fgets(buf, sizeof(buf), stdin);
	  if(strncasecmp(buf, "yes", 3)==0){
	      if(ssh_write_knownhost(_session))
		  log_error(ssh_get_error(_session));
	  }
#else
	  if(ssh_write_knownhost(_session)) {
	      log_error(ssh_get_error(_session));
	  }
#endif  
	  break;
      case SSH_SERVER_ERROR:
	  free(hash);
	  log_error(ssh_get_error(_session));
	  sshShutdown();
	  return false;
    }
    
    free(hash);
    
    ssh_userauth_none(_session, NULL);
    
    int auth = ssh_auth_list(_session);

//    log_debug("auth: 0x%04x", auth);
    log_debug(_("supported auth methods: "));
    if (auth & SSH_AUTH_METHOD_PUBLICKEY) {
	log_debug(_("\tpublickey"));
    }
    if (auth & SSH_AUTH_METHOD_INTERACTIVE) {
	log_debug(_("\tkeyboard-interactive"));
    }

    /* no ? you should :) */
    auth=ssh_userauth_autopubkey(_session, NULL);
    if(auth == SSH_AUTH_ERROR){
        log_debug(_("Authenticating with pubkey: %s"), ssh_get_error(_session));
	ssh_finalize();
        return false;
    }
    banner = ssh_get_issue_banner(_session);
    if(banner){
        log_debug(banner);
        free(banner);
    }
    if(auth != SSH_AUTH_SUCCESS){
        auth = authKbdint(_session);
        if(auth == SSH_AUTH_ERROR){
            log_error(_("authenticating with keyb-interactive: %s"),
		      ssh_get_error(_session));
	    ssh_finalize();
            return false;
        }
    }
    if(auth != SSH_AUTH_SUCCESS){
        password = getpass("Password: "******"Authentication failed: %s"), ssh_get_error(_session));
            ssh_disconnect(_session);
                ssh_finalize();
            return false;
        }
        memset(password, 0, strlen(password));
    }
    ssh_log(_session, SSH_LOG_FUNCTIONS, "Authentication success");

#if 0
    if(strstr(argv[0],"sftp")){
        sftp = 1;
        ssh_log(_session, SSH_LOG_FUNCTIONS, "Doing sftp instead");
    }
    if(!sftp){
        if(!cmds[0])
            shell(_session);
        else
            batch_shell(_session);
    }
    else
        do_sftp(_session);
    if(!sftp && !cmds[0])
        do_cleanup(0);
#endif
    
    return true;
}
예제 #12
0
파일: gssapi.c 프로젝트: Distrotech/libssh
/** @brief returns the OIDs of the mechs that have usable credentials
 */
static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids)
{
    OM_uint32 maj_stat, min_stat, lifetime;
    gss_OID_set actual_mechs;
    gss_buffer_desc namebuf;
    gss_name_t client_id = GSS_C_NO_NAME;
    gss_OID oid;
    unsigned int i;
    char *ptr;
    int ret;

    if (session->gssapi->client.client_deleg_creds == NULL) {
        if (session->opts.gss_client_identity != NULL) {
            namebuf.value = (void *)session->opts.gss_client_identity;
            namebuf.length = strlen(session->opts.gss_client_identity);

            maj_stat = gss_import_name(&min_stat, &namebuf,
                                       GSS_C_NT_USER_NAME, &client_id);
            if (GSS_ERROR(maj_stat)) {
                ret = SSH_ERROR;
                goto end;
            }
        }

        maj_stat = gss_acquire_cred(&min_stat, client_id, GSS_C_INDEFINITE,
                                    GSS_C_NO_OID_SET, GSS_C_INITIATE,
                                    &session->gssapi->client.creds,
                                    &actual_mechs, NULL);
        if (GSS_ERROR(maj_stat)) {
            ret = SSH_ERROR;
            goto end;
        }
    } else {
        session->gssapi->client.creds =
                                    session->gssapi->client.client_deleg_creds;

        maj_stat = gss_inquire_cred(&min_stat, session->gssapi->client.creds,
                                    &client_id, NULL, NULL, &actual_mechs);
        if (GSS_ERROR(maj_stat)) {
            ret = SSH_ERROR;
            goto end;
        }
    }

    gss_create_empty_oid_set(&min_stat, valid_oids);

    /* double check each single cred */
    for (i = 0; i < actual_mechs->count; i++) {
        /* check lifetime is not 0 or skip */
        lifetime = 0;
        oid = &actual_mechs->elements[i];
        maj_stat = gss_inquire_cred_by_mech(&min_stat,
                                            session->gssapi->client.creds,
                                            oid, NULL, &lifetime, NULL, NULL);
        if (maj_stat == GSS_S_COMPLETE && lifetime > 0) {
            gss_add_oid_set_member(&min_stat, oid, valid_oids);
            ptr = ssh_get_hexa(oid->elements, oid->length);
            SSH_LOG(SSH_LOG_DEBUG, "GSSAPI valid oid %d : %s\n", i, ptr);
            SAFE_FREE(ptr);
        }
    }

    ret = SSH_OK;

end:
    gss_release_name(&min_stat, &client_id);
    return ret;
}
예제 #13
0
파일: gssapi.c 프로젝트: Distrotech/libssh
/** @internal
 * @brief handles an user authentication using GSSAPI
 */
int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids){
    char service_name[]="host";
    gss_buffer_desc name_buf;
    gss_name_t server_name; /* local server fqdn */
    OM_uint32 maj_stat, min_stat;
    unsigned int i;
    char *ptr;
    gss_OID_set supported; /* oids supported by server */
    gss_OID_set both_supported; /* oids supported by both client and server */
    gss_OID_set selected; /* oid selected for authentication */
    int present=0;
    int oid_count=0;
    struct gss_OID_desc_struct oid;
    int rc;

    if (ssh_callbacks_exists(session->server_callbacks, gssapi_select_oid_function)){
        ssh_string oid_s = session->server_callbacks->gssapi_select_oid_function(session,
                user, n_oid, oids,
                session->server_callbacks->userdata);
        if (oid_s != NULL){
            if (ssh_gssapi_init(session) == SSH_ERROR)
                return SSH_ERROR;
            session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN;
            rc = ssh_gssapi_send_response(session, oid_s);
            ssh_string_free(oid_s);
            return rc;
        } else {
            return ssh_auth_reply_default(session,0);
        }
    }
    gss_create_empty_oid_set(&min_stat, &both_supported);

    maj_stat = gss_indicate_mechs(&min_stat, &supported);
    for (i=0; i < supported->count; ++i){
        ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
        SSH_LOG(SSH_LOG_DEBUG, "Supported mech %d: %s\n", i, ptr);
        free(ptr);
    }

    for (i=0 ; i< n_oid ; ++i){
        unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
        size_t len = ssh_string_len(oids[i]);
        if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
            SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
            continue;
        }
        oid.elements = &oid_s[2];
        oid.length = len - 2;
        gss_test_oid_set_member(&min_stat,&oid,supported,&present);
        if(present){
            gss_add_oid_set_member(&min_stat,&oid,&both_supported);
            oid_count++;
        }
    }
    gss_release_oid_set(&min_stat, &supported);
    if (oid_count == 0){
        SSH_LOG(SSH_LOG_PROTOCOL,"GSSAPI: no OID match");
        ssh_auth_reply_default(session, 0);
        gss_release_oid_set(&min_stat, &both_supported);
        return SSH_OK;
    }
    /* from now we have room for context */
    if (ssh_gssapi_init(session) == SSH_ERROR)
        return SSH_ERROR;

    name_buf.value = service_name;
    name_buf.length = strlen(name_buf.value) + 1;
    maj_stat = gss_import_name(&min_stat, &name_buf,
            (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat);
        return -1;
    }

    maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
            both_supported, GSS_C_ACCEPT,
            &session->gssapi->server_creds, &selected, NULL);
    gss_release_name(&min_stat, &server_name);
    gss_release_oid_set(&min_stat, &both_supported);

    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_WARNING, "acquiring creds", maj_stat);
        ssh_auth_reply_default(session,0);
        return SSH_ERROR;
    }

    SSH_LOG(SSH_LOG_PROTOCOL, "acquiring credentials %d, %d", maj_stat, min_stat);

    /* finding which OID from client we selected */
    for (i=0 ; i< n_oid ; ++i){
        unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]);
        size_t len = ssh_string_len(oids[i]);
        if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){
            SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID");
            continue;
        }
        oid.elements = &oid_s[2];
        oid.length = len - 2;
        gss_test_oid_set_member(&min_stat,&oid,selected,&present);
        if(present){
            SSH_LOG(SSH_LOG_PACKET, "Selected oid %d", i);
            break;
        }
    }
    session->gssapi->mech.length = oid.length;
    session->gssapi->mech.elements = malloc(oid.length);
    if (session->gssapi->mech.elements == NULL){
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    memcpy(session->gssapi->mech.elements, oid.elements, oid.length);
    gss_release_oid_set(&min_stat, &selected);
    session->gssapi->user = strdup(user);
    session->gssapi->service = service_name;
    session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN;
    return ssh_gssapi_send_response(session, oids[i]);
}
예제 #14
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;
}
예제 #15
0
파일: gssapi.c 프로젝트: alexislitool/tmate
/** @brief returns the OIDs of the mechs that work with both
 * hostname and username
 */
static int ssh_gssapi_match(ssh_session session, char *hostname, char *username, gss_OID_set *valid_oids, int deleg){
    gss_buffer_desc host_namebuf, user_namebuf;
    gss_name_t host_name, user_name;
    OM_uint32 maj_stat, min_stat;
    gss_OID_set supported;
    gss_OID oid;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
    gss_cred_id_t client_creds = GSS_C_NO_CREDENTIAL;
    unsigned int i;
    char *ptr;
    char hostname_buf[256];


    gss_create_empty_oid_set(&min_stat, valid_oids);
    maj_stat = gss_indicate_mechs(&min_stat, &supported);
    for (i=0; i < supported->count; ++i){
        ptr=ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
        SSH_LOG(SSH_LOG_DEBUG, "GSSAPI oid supported %d : %s\n",i, ptr);
        SAFE_FREE(ptr);
    }

    user_namebuf.value = username;
    user_namebuf.length = strlen(username) + 1;
    maj_stat = gss_import_name(&min_stat, &user_namebuf,
            (gss_OID) GSS_C_NT_USER_NAME, &user_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(SSH_LOG_DEBUG, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(SSH_LOG_DEBUG, "importing name", maj_stat);
        return -1;
    }

    snprintf(hostname_buf, sizeof(hostname_buf),"host@%s", hostname);
    host_namebuf.value = hostname_buf;
    host_namebuf.length = strlen(hostname_buf) + 1;
    maj_stat = gss_import_name(&min_stat, &host_namebuf,
            (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &host_name);
    if (maj_stat != GSS_S_COMPLETE) {
        SSH_LOG(0, "importing name %d, %d", maj_stat, min_stat);
        ssh_gssapi_log_error(0, "importing name", maj_stat);
        return -1;
    }

    ssh_gssapi_init(session);
    session->gssapi->client_name = user_name;
    session->gssapi->client.server_name = host_name;
    session->gssapi->user = strdup(username);
    for (i=0; i<supported->count; ++i){
        oid = &supported->elements[i];
        maj_stat = gss_init_sec_context(&min_stat,
                session->gssapi->client.client_deleg_creds, &ctx, host_name, oid,
                GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | (deleg ? GSS_C_DELEG_FLAG : 0),
                0, NULL, &input_token, NULL, &output_token, NULL, NULL);
        if (!GSS_ERROR(maj_stat)){
            gss_OID_set tmp;
            if (session->gssapi->client.client_deleg_creds != GSS_C_NO_CREDENTIAL){
                /* we know the oid is ok since init_sec_context worked */
                gss_add_oid_set_member(&min_stat, oid, valid_oids);
                SSH_LOG(SSH_LOG_PROTOCOL, "Matched oid %u for server (with forwarding)", i);
            } else {
                gss_create_empty_oid_set(&min_stat, &tmp);
                gss_add_oid_set_member(&min_stat, oid, &tmp);
                maj_stat = gss_acquire_cred(&min_stat, user_name, 0,
                        tmp, GSS_C_INITIATE,
                        &client_creds, NULL, NULL);
                gss_release_oid_set(&min_stat, &tmp);
                if (!GSS_ERROR(maj_stat)){
                    gss_release_cred(&min_stat, &client_creds);
                    gss_add_oid_set_member(&min_stat,oid,valid_oids);
                    SSH_LOG(SSH_LOG_PROTOCOL, "Matched oid %u for server", i);
                }
            }
        }
        gss_delete_sec_context(&min_stat,&ctx, &output_token);
        ctx = GSS_C_NO_CONTEXT;
    }

    return SSH_OK;
}