/**
 * @brief tests the privatekey_from_file function with passphrase
 */
static void torture_privatekey_from_file_passphrase(void **state) {
    ssh_session session = *state;
    ssh_private_key key = NULL;

    key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, SSH_KEYTYPE_RSA, LIBSSH_PASSPHRASE);
    assert_true(key != NULL);
    if (key != NULL) {
        privatekey_free(key);
        key = NULL;
    }

    key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, SSH_KEYTYPE_DSS, LIBSSH_PASSPHRASE);
    assert_true(key != NULL);
    if (key != NULL) {
        privatekey_free(key);
        key = NULL;
    }

    /* Test the automatic type discovery */
    key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, LIBSSH_PASSPHRASE);
    assert_true(key != NULL);
    if (key != NULL) {
        privatekey_free(key);
        key = NULL;
    }

    key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, 0, LIBSSH_PASSPHRASE);
    assert_true(key != NULL);
    if (key != NULL) {
        privatekey_free(key);
        key = NULL;
    }
}
/**
 * Authenticate in the SSH server with key
 * @param   QString private_key   the private key to use for connect in the SSH server
 * @param   QString password      the password to use for connect in the SSH server (passphrase of the private key)
 * @return  bool                  true if it's ok, false else
 * @todo    test with a private key with passphrase
 */
bool Kssh::authenticateKey(QString private_key, QString password)
{
    ssh_string public_key_to_use;
    ssh_private_key private_key_to_use;
    int auth;

    private_key_to_use = privatekey_from_file(this->m_session, private_key.toStdString().c_str(), 0, password.toStdString().c_str());
    if (private_key_to_use == NULL) {
        Klog::error(QString("Fatal error while get the private key : ") + QString(ssh_get_error(this->m_session)));
        return false;
    }

    // get the public key
    public_key_to_use = publickey_to_string(publickey_from_privatekey(private_key_to_use));

    // try to authenticate
    auth = ssh_userauth_pubkey(this->m_session, NULL, public_key_to_use, private_key_to_use);

    if (auth == SSH_AUTH_SUCCESS) {
        // clear the keys of the memory
        privatekey_free(private_key_to_use);
        string_free(public_key_to_use);

        // it's ok
        return true;
    } else if (auth == SSH_AUTH_DENIED || auth == SSH_AUTH_PARTIAL) {
        Klog::warning(QString("Authenticated denied with this key"));
        return false;
    } else if (auth == SSH_AUTH_ERROR) {
        Klog::error(QString("Fatal error in authenticated with key : ") + QString(ssh_get_error(this->m_session)));
        return false;
    }

    return false;
}
static void torture_pubkey_generate_from_privkey(void **state) {
    ssh_session session = *state;
    ssh_private_key privkey = NULL;
    ssh_public_key pubkey = NULL;
    ssh_string pubkey_orig = NULL;
    ssh_string pubkey_new = NULL;
    char pubkey_line_orig[512] = {0};
    char pubkey_line_new[512] = {0};
    int type_orig = 0;
    int type_new = 0;
    int rc;

    /* read the publickey */
    rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey_orig,
        &type_orig);
    assert_true(rc == 0);
    assert_true(pubkey_orig != NULL);

    rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_orig,
        sizeof(pubkey_line_orig));
    assert_true(rc == 0);

    /* remove the public key, generate it from the private key and write it. */
    unlink(LIBSSH_RSA_TESTKEY ".pub");

    privkey = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL);
    assert_true(privkey != NULL);

    pubkey = publickey_from_privatekey(privkey);
    assert_true(pubkey != NULL);
    type_new = privkey->type;
    privatekey_free(privkey);

    pubkey_new = publickey_to_string(pubkey);
    publickey_free(pubkey);

    assert_true(pubkey_new != NULL);

    assert_true(ssh_string_len(pubkey_orig) == ssh_string_len(pubkey_new));
    assert_memory_equal(ssh_string_data(pubkey_orig),
                        ssh_string_data(pubkey_new),
                        ssh_string_len(pubkey_orig));

    rc = ssh_publickey_to_file(session, LIBSSH_RSA_TESTKEY ".pub", pubkey_new, type_new);
    assert_true(rc == 0);

    rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_new,
        sizeof(pubkey_line_new));
    assert_true(rc == 0);

    assert_string_equal(pubkey_line_orig, pubkey_line_new);

    ssh_string_free(pubkey_orig);
    ssh_string_free(pubkey_new);
}
Exemple #4
0
// Connect to a SSH server.
// When the connection is established, read data from stdin and send it to the server.
void client_pipe(char *host, int port)
{
    ssh_session s = ssh_new();
    ssh_options_set(s, SSH_OPTIONS_HOST, host);
    ssh_options_set(s, SSH_OPTIONS_PORT, &port);
    ssh_options_set(s, SSH_OPTIONS_USER, "xya");
    //ssh_options_set(s, SSH_OPTIONS_LOG_VERBOSITY_STR, "5");
    if(ssh_connect(s) != SSH_OK)
        return session_error(s, "connect");
    
    char *hash = pubkey_hash(ssh_get_pubkey(s));
    if(authenticate(hash, 0))
    {
        session_event(s, "authenticated", hash);
        free(hash);
    }
    else
    {
        free(hash);
        exit(1);
    }
    
    int keytype;
    ssh_string pub = publickey_from_file(s, "test-client-key.pub", &keytype);
    if(!pub)
        session_error(s, "open-public-key");
    if(SSH_AUTH_SUCCESS != ssh_userauth_offer_pubkey(s, NULL, keytype, pub))
        session_error(s, "offer-public-key");
    
    ssh_private_key priv = privatekey_from_file(s, "test-client-key", keytype, NULL);
    if(!priv)
        session_error(s, "open-private-key");
    if(SSH_AUTH_SUCCESS != ssh_userauth_pubkey(s, NULL, pub, priv))
        session_error(s, "user-auth");
    string_free(pub);
    privatekey_free(priv);
    
    ssh_channel chan = channel_new(s);
    if(!chan)
        session_error(s, "create-channel");
    if(channel_open_session(chan) < 0)
        session_error(s, "open-channel");
    session_event(s, "channel-opened", NULL);
    channel_from_file(chan, 0);
    channel_free(chan);
    ssh_disconnect(s);
    ssh_finalize();
}
Exemple #5
0
gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file,
		RemminaNXPassphraseCallback passphrase_func, gpointer userdata)
{
	gint ret;
	ssh_private_key privkey;
	ssh_public_key pubkey;
	ssh_string pubkeystr;
	gint keytype;
	gboolean encrypted;
	gchar *passphrase = NULL;
	gchar tmpfile[L_tmpnam + 1];

nx	->session = ssh_new();
	ssh_options_set(nx->session, SSH_OPTIONS_HOST, server);
	ssh_options_set(nx->session, SSH_OPTIONS_PORT, &port);
	ssh_options_set(nx->session, SSH_OPTIONS_USER, "nx");

	if (private_key_file && private_key_file[0])
	{
		if (!remmina_get_keytype(private_key_file, &keytype, &encrypted))
		{
			remmina_nx_session_set_application_error(nx, "Invalid private key file.");
			return FALSE;
		}
		if (encrypted && !passphrase_func(&passphrase, userdata))
		{
			return FALSE;
		}
		privkey = privatekey_from_file(nx->session, private_key_file, keytype, (passphrase ? passphrase : ""));
		g_free(passphrase);
	}
	else
	{
		/* Use NoMachine's default nx private key */
		if ((tmpnam(tmpfile)) == NULL || !g_file_set_contents(tmpfile, nx_default_private_key, -1, NULL))
		{
			remmina_nx_session_set_application_error(nx, "Failed to create temporary private key file.");
			return FALSE;
		}
		privkey = privatekey_from_file(nx->session, tmpfile, REMMINA_SSH_TYPE_DSS, "");
		g_unlink(tmpfile);
	}

	if (privkey == NULL)
	{
		remmina_nx_session_set_error(nx, "Invalid private key file: %s");
		return FALSE;
	}
	pubkey = publickey_from_privatekey(privkey);
	pubkeystr = publickey_to_string(pubkey);
	publickey_free(pubkey);

	if (ssh_connect(nx->session))
	{
		string_free(pubkeystr);
		privatekey_free(privkey);
		remmina_nx_session_set_error(nx, "Failed to startup SSH session: %s");
		return FALSE;
	}

	ret = ssh_userauth_pubkey(nx->session, NULL, pubkeystr, privkey);
	string_free(pubkeystr);
	privatekey_free(privkey);

	if (ret != SSH_AUTH_SUCCESS)
	{
		remmina_nx_session_set_error(nx, "NX SSH authentication failed: %s");
		return FALSE;
	}

	if ((nx->channel = channel_new(nx->session)) == NULL || channel_open_session(nx->channel))
	{
		return FALSE;
	}

	if (channel_request_shell(nx->channel))
	{
		return FALSE;
	}

	/* NX server starts the session with an initial 105 status */
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	/* Say hello to the NX server */
	remmina_nx_session_send_command(nx, "HELLO NXCLIENT - Version %s", nx->version);
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	/* Set the NX session environment */
	remmina_nx_session_send_command(nx, "SET SHELL_MODE SHELL");
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;
	remmina_nx_session_send_command(nx, "SET AUTH_MODE PASSWORD");
	if (!remmina_nx_session_expect_status(nx, 105))
		return FALSE;

	nx->server = g_strdup(server);

	return TRUE;
}
Exemple #6
0
static int dh_handshake_server(ssh_session session) {
  ssh_string f;
  ssh_string pubkey;
  ssh_string sign;
  ssh_public_key pub;
  ssh_private_key prv;

  if (dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  switch(session->hostkeys){
    case SSH_KEYTYPE_DSS:
      prv = session->dsa_key;
      break;
    case SSH_KEYTYPE_RSA:
      prv = session->rsa_key;
      break;
    default:
      prv = NULL;
  }

  pub = publickey_from_privatekey(prv);
  if (pub == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Could not get the public key from the private key");
    ssh_string_free(f);
    return -1;
  }
  pubkey = publickey_to_string(pub);
  publickey_free(pub);
  if (pubkey == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    ssh_string_free(f);
    return -1;
  }

  dh_import_pubkey(session, pubkey);
  if (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    ssh_string_free(f);
    return -1;
  }

  if (make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    ssh_string_free(f);
    return -1;
  }

  sign = ssh_sign_session_id(session, prv);
  if (sign == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    ssh_string_free(f);
    return -1;
  }

  /* Free private keys as they should not be readable after this point */
  if (session->rsa_key) {
    privatekey_free(session->rsa_key);
    session->rsa_key = NULL;
  }
  if (session->dsa_key) {
    privatekey_free(session->dsa_key);
    session->dsa_key = NULL;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 ||
      buffer_add_ssh_string(session->out_buffer, pubkey) < 0 ||
      buffer_add_ssh_string(session->out_buffer, f) < 0 ||
      buffer_add_ssh_string(session->out_buffer, sign) < 0) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    buffer_reinit(session->out_buffer);
    ssh_string_free(f);
    ssh_string_free(sign);
    return -1;
  }
  ssh_string_free(f);
  ssh_string_free(sign);
  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    buffer_reinit(session->out_buffer);
    return -1;
  }

  if (packet_send(session) == SSH_ERROR) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
  session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;

  return 0;
}
Exemple #7
0
static int dh_handshake_server(SSH_SESSION *session) {
  STRING *e;
  STRING *f;
  STRING *pubkey;
  STRING *sign;
  PUBLIC_KEY *pub;
  PRIVATE_KEY *prv;

  if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) {
    return -1;
  }

  e = buffer_get_ssh_string(session->in_buffer);
  if (e == NULL) {
    ssh_set_error(session, SSH_FATAL, "No e number in client request");
    return -1;
  }
  if (dh_import_e(session, e) < 0) {
    ssh_set_error(session, SSH_FATAL, "Cannot import e number");
    string_free(e);
    return -1;
  }
  string_free(e);

  if (dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  switch(session->hostkeys){
    case TYPE_DSS:
      prv = session->dsa_key;
      break;
    case TYPE_RSA:
      prv = session->rsa_key;
      break;
    default:
      prv = NULL;
  }

  pub = publickey_from_privatekey(prv);
  if (pub == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Could not get the public key from the private key");
    string_free(f);
    return -1;
  }
  pubkey = publickey_to_string(pub);
  publickey_free(pub);
  if (pubkey == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    string_free(f);
    return -1;
  }

  dh_import_pubkey(session, pubkey);
  if (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    string_free(f);
    return -1;
  }

  if (make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    string_free(f);
    return -1;
  }

  sign = ssh_sign_session_id(session, prv);
  if (sign == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    string_free(f);
    return -1;
  }

  /* Free private keys as they should not be readable after this point */
  if (session->rsa_key) {
    privatekey_free(session->rsa_key);
    session->rsa_key = NULL;
  }
  if (session->dsa_key) {
    privatekey_free(session->dsa_key);
    session->dsa_key = NULL;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 ||
      buffer_add_ssh_string(session->out_buffer, pubkey) < 0 ||
      buffer_add_ssh_string(session->out_buffer, f) < 0 ||
      buffer_add_ssh_string(session->out_buffer, sign) < 0) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    buffer_free(session->out_buffer);
    string_free(f);
    string_free(sign);
    return -1;
  }
  string_free(f);
  string_free(sign);

  if (packet_send(session) != SSH_OK) {
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    buffer_free(session->out_buffer);
    return -1;
  }

  if (packet_send(session) != SSH_OK) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");

  if (packet_wait(session, SSH2_MSG_NEWKEYS, 1) != SSH_OK) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "Got SSH_MSG_NEWKEYS");

  if (generate_session_keys(session) < 0) {
    return -1;
  }

  /*
   * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
   * current_crypto
   */
  if (session->current_crypto) {
    crypto_free(session->current_crypto);
  }

  /* FIXME TODO later, include a function to change keys */
  session->current_crypto = session->next_crypto;
  session->next_crypto = crypto_new();
  if (session->next_crypto == NULL) {
    return -1;
  }

  return 0;
}
Exemple #8
0
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind) {
  SSH_SESSION *session;
  PRIVATE_KEY *dsa = NULL;
  PRIVATE_KEY *rsa = NULL;
  int fd = -1;

  if (ssh_bind->bindfd < 0) {
    ssh_set_error(ssh_bind, SSH_FATAL,
        "Can't accept new clients on a not bound socket.");
    return NULL;
  }

  if (ssh_bind->options->dsakey == NULL || ssh_bind->options->rsakey == NULL) {
    ssh_set_error(ssh_bind, SSH_FATAL,
        "DSA or RSA host key file must be set before accept()");
    return NULL;
  }

  if (ssh_bind->options->dsakey) {
    dsa = _privatekey_from_file(ssh_bind, ssh_bind->options->dsakey, TYPE_DSS);
    if (dsa == NULL) {
      return NULL;
    }
  }

  if (ssh_bind->options->rsakey) {
    rsa = _privatekey_from_file(ssh_bind, ssh_bind->options->rsakey, TYPE_RSA);
    if (rsa == NULL) {
      privatekey_free(dsa);
      return NULL;
    }
  }

  fd = accept(ssh_bind->bindfd, NULL, NULL);
  if (fd < 0) {
    ssh_set_error(ssh_bind, SSH_FATAL,
        "Accepting a new connection: %s",
        strerror(errno));
    privatekey_free(dsa);
    privatekey_free(rsa);
    return NULL;
  }

  session = ssh_new();
  if (session == NULL) {
    ssh_set_error(ssh_bind, SSH_FATAL, "Not enough space");
    privatekey_free(dsa);
    privatekey_free(rsa);
    return NULL;
  }
  session->server = 1;
  session->version = 2;
  session->options = ssh_options_copy(ssh_bind->options);
  if (session->options == NULL) {
    ssh_set_error(ssh_bind, SSH_FATAL, "No space left");
    privatekey_free(dsa);
    privatekey_free(rsa);
    ssh_cleanup(session);
    return NULL;
  }

  ssh_socket_free(session->socket);
  session->socket = ssh_socket_new(session);
  if (session->socket == NULL) {
    privatekey_free(dsa);
    privatekey_free(rsa);
    ssh_cleanup(session);
    return NULL;
  }
  ssh_socket_set_fd(session->socket,fd);
  session->dsa_key = dsa;
  session->rsa_key = rsa;

  return session;
}
Exemple #9
0
int ssh_bind_listen(ssh_bind sshbind) {
  const char *host;
  socket_t fd;

  sshbind->dsa = NULL;
  sshbind->rsa = NULL;

  if (ssh_init() < 0) {
    ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
    return -1;
  }

  if (sshbind->dsakey) {
    if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
      ssh_set_error(sshbind, SSH_FATAL,
        "DSA or RSA host key file must be set before listen()");
      return SSH_ERROR;
    }
    sshbind->dsa = _privatekey_from_file(
      sshbind, sshbind->dsakey, SSH_KEYTYPE_DSS
    );
    if (sshbind->dsa == NULL) {
      return -1;
    }
  }

  if (sshbind->rsakey) {
    sshbind->rsa = _privatekey_from_file(
      sshbind, sshbind->rsakey, SSH_KEYTYPE_RSA
    );
    if (sshbind->rsa == NULL) {
      privatekey_free(sshbind->dsa);
      return -1;
    }
  }

  host = sshbind->bindaddr;
  if (host == NULL) {
    host = "0.0.0.0";
  }

  fd = bind_socket(sshbind, host, sshbind->bindport);
  if (fd == SSH_INVALID_SOCKET) {
    privatekey_free(sshbind->dsa);
    privatekey_free(sshbind->rsa);
    return -1;
  }
  sshbind->bindfd = fd;

  if (listen(fd, 10) < 0) {
    ssh_set_error(sshbind, SSH_FATAL,
        "Listening to socket %d: %s",
        fd, strerror(errno));
    close(fd);
    privatekey_free(sshbind->dsa);
    privatekey_free(sshbind->rsa);
    return -1;
  }

  return 0;
}
Exemple #10
0
/**
 * @brief Tries to automaticaly authenticate with public key and "none"
 *
 * It may fail, for instance it doesn't ask for a password and uses a default
 * asker for passphrases (in case the private key is encrypted).
 *
 * @param session       The ssh session to authenticate with.
 *
 * @param passphrase    Use this passphrase to unlock the privatekey. Use NULL
 *                      if you don't want to use a passphrase or the user
 *                      should be asked.
 *
 * @returns SSH_AUTH_ERROR:   A serious error happened\n
 *          SSH_AUTH_DENIED:  Authentication failed: use another method\n
 *          SSH_AUTH_PARTIAL: You've been partially authenticated, you still
 *                            have to use another method\n
 *          SSH_AUTH_SUCCESS: Authentication success
 *
 * @see ssh_userauth_kbdint()
 * @see ssh_userauth_password()
 */
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
  struct ssh_iterator *it;
  ssh_private_key privkey;
  ssh_public_key pubkey;
  ssh_string pubkey_string;
  int type = 0;
  int rc;

  enter_function();

  /* Always test none authentication */
  rc = ssh_userauth_none(session, NULL);
  if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_SUCCESS) {
    leave_function();
    return rc;
  }

  /* Try authentication with ssh-agent first */
#ifndef _WIN32
  if (agent_is_running(session)) {
    char *privkey_file = NULL;

    ssh_log(session, SSH_LOG_RARE,
        "Trying to authenticate with SSH agent keys as user: %s",
        session->username);

    for (pubkey = agent_get_first_ident(session, &privkey_file);
        pubkey != NULL;
        pubkey = agent_get_next_ident(session, &privkey_file)) {

      ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file);

      pubkey_string = publickey_to_string(pubkey);
      if (pubkey_string) {
        rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
        string_free(pubkey_string);
        if (rc == SSH_AUTH_ERROR) {
          SAFE_FREE(privkey_file);
          publickey_free(pubkey);
          leave_function();

          return rc;
        } else if (rc != SSH_AUTH_SUCCESS) {
          ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
          SAFE_FREE(privkey_file);
          publickey_free(pubkey);
          continue;
        }
        ssh_log(session, SSH_LOG_RARE, "Public key accepted");
        /* pubkey accepted by server ! */
        rc = ssh_userauth_agent_pubkey(session, NULL, pubkey);
        if (rc == SSH_AUTH_ERROR) {
          SAFE_FREE(privkey_file);
          publickey_free(pubkey);
          leave_function();

          return rc;
        } else if (rc != SSH_AUTH_SUCCESS) {
          ssh_log(session, SSH_LOG_RARE,
              "Server accepted public key but refused the signature ;"
              " It might be a bug of libssh");
          SAFE_FREE(privkey_file);
          publickey_free(pubkey);
          continue;
        }
        /* auth success */
        ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
            privkey_file);
        SAFE_FREE(privkey_file);
        publickey_free(pubkey);

        leave_function();

        return SSH_AUTH_SUCCESS;
      } /* if pubkey */
      SAFE_FREE(privkey_file);
      publickey_free(pubkey);
    } /* for each privkey */
  } /* if agent is running */
#endif


  for (it = ssh_list_get_iterator(session->identity);
       it != NULL;
       it = it->next) {
    const char *privkey_file = it->data;
    int privkey_open = 0;

    privkey = NULL;

    ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);

    rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
    if (rc == 1) {
      char *publickey_file;
      size_t len;

      privkey = privatekey_from_file(session, privkey_file, type, passphrase);
      if (privkey == NULL) {
        ssh_log(session, SSH_LOG_RARE,
          "Reading private key %s failed (bad passphrase ?)",
          privkey_file);
        leave_function();
        return SSH_AUTH_ERROR;
      }
      privkey_open = 1;

      pubkey = publickey_from_privatekey(privkey);
      if (pubkey == NULL) {
        privatekey_free(privkey);
        ssh_set_error_oom(session);
        leave_function();
        return SSH_AUTH_ERROR;
      }

      pubkey_string = publickey_to_string(pubkey);
      type = pubkey->type;
      publickey_free(pubkey);
      if (pubkey_string == NULL) {
        ssh_set_error_oom(session);
        leave_function();
        return SSH_AUTH_ERROR;
      }

      len = strlen(privkey_file) + 5;
      publickey_file = malloc(len);
      if (publickey_file == NULL) {
        ssh_set_error_oom(session);
        leave_function();
        return SSH_AUTH_ERROR;
      }
      snprintf(publickey_file, len, "%s.pub", privkey_file);
      rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type);
      if (rc < 0) {
        ssh_log(session, SSH_LOG_PACKET,
            "Could not write public key to file: %s", publickey_file);
      }
      SAFE_FREE(publickey_file);
    } else if (rc < 0) {
      continue;
    }

    rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string);
    if (rc == SSH_AUTH_ERROR){
      string_free(pubkey_string);
      ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
      leave_function();
      return rc;
    } else {
      if (rc != SSH_AUTH_SUCCESS){
        ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
        string_free(pubkey_string);
        continue;
      }
    }

    /* Public key accepted by server! */
    if (!privkey_open) {
      ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
          privkey_file);
      privkey = privatekey_from_file(session, privkey_file, type, passphrase);
      if (privkey == NULL) {
        ssh_log(session, SSH_LOG_RARE,
            "Reading private key %s failed (bad passphrase ?)",
            privkey_file);
        string_free(pubkey_string);
        continue; /* continue the loop with other pubkey */
      }
    }

    rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey);
    if (rc == SSH_AUTH_ERROR) {
      string_free(pubkey_string);
      privatekey_free(privkey);
      leave_function();
      return rc;
    } else {
      if (rc != SSH_AUTH_SUCCESS){
        ssh_log(session, SSH_LOG_FUNCTIONS,
            "The server accepted the public key but refused the signature");
        string_free(pubkey_string);
        privatekey_free(privkey);
        continue;
      }
    }

    /* auth success */
    ssh_log(session, SSH_LOG_PROTOCOL,
        "Successfully authenticated using %s", privkey_file);
    string_free(pubkey_string);
    privatekey_free(privkey);

    leave_function();
    return SSH_AUTH_SUCCESS;
  }

  /* at this point, pubkey is NULL and so is privkeyfile */
  ssh_log(session, SSH_LOG_FUNCTIONS,
      "Tried every public key, none matched");
  ssh_set_error(session,SSH_NO_ERROR,"No public key matched");

  leave_function();
  return SSH_AUTH_DENIED;
}
Exemple #11
0
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
  ssh_private_key dsa = NULL;
  ssh_private_key rsa = NULL;
  socket_t fd = SSH_INVALID_SOCKET;
  int i;

  if (sshbind->bindfd == SSH_INVALID_SOCKET) {
    ssh_set_error(sshbind, SSH_FATAL,
        "Can't accept new clients on a not bound socket.");
    return SSH_ERROR;
  }
  if(session == NULL){
  	ssh_set_error(sshbind, SSH_FATAL,"session is null");
  	return SSH_ERROR;
  }
  if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) {
    ssh_set_error(sshbind, SSH_FATAL,
        "DSA or RSA host key file must be set before accept()");
    return SSH_ERROR;
  }

  if (sshbind->dsakey) {
    dsa = _privatekey_from_file(sshbind, sshbind->dsakey, SSH_KEYTYPE_DSS);
    if (dsa == NULL) {
      return SSH_ERROR;
    }
  }

  if (sshbind->rsakey) {
    rsa = _privatekey_from_file(sshbind, sshbind->rsakey, SSH_KEYTYPE_RSA);
    if (rsa == NULL) {
      privatekey_free(dsa);
      return SSH_ERROR;
    }
  }

  fd = accept(sshbind->bindfd, NULL, NULL);
  if (fd == SSH_INVALID_SOCKET) {
    ssh_set_error(sshbind, SSH_FATAL,
        "Accepting a new connection: %s",
        strerror(errno));
    privatekey_free(dsa);
    privatekey_free(rsa);
    return SSH_ERROR;
  }

  session->server = 1;
  session->version = 2;

  /* copy options */
  for (i = 0; i < 10; ++i) {
    if (sshbind->wanted_methods[i]) {
      session->wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
      if (session->wanted_methods[i] == NULL) {
        privatekey_free(dsa);
        privatekey_free(rsa);
        return SSH_ERROR;
      }
    }
  }

  if (sshbind->bindaddr == NULL)
    session->bindaddr = NULL;
  else {
    SAFE_FREE(session->bindaddr);
    session->bindaddr = strdup(sshbind->bindaddr);
    if (session->bindaddr == NULL) {
      privatekey_free(dsa);
      privatekey_free(rsa);
      return SSH_ERROR;
    }
  }

  session->log_verbosity = sshbind->log_verbosity;

  ssh_socket_free(session->socket);
  session->socket = ssh_socket_new(session);
  if (session->socket == NULL) {
    /* perhaps it may be better to copy the error from session to sshbind */
    ssh_set_error_oom(sshbind);
    privatekey_free(dsa);
    privatekey_free(rsa);
    return SSH_ERROR;
  }
  ssh_socket_set_fd(session->socket, fd);
  ssh_socket_get_poll_handle_out(session->socket);
  session->dsa_key = dsa;
  session->rsa_key = rsa;

return SSH_OK;
}