Ejemplo n.º 1
0
  /**
   *  Blocks until the result code of the process has been returned.
   */
  int process::result() {
    if (!my->return_code && !my->return_signal) {
      // we don't have any cached exit status, so wait and obtain the values now
      my->sshc->my->call_ssh2_function(boost::bind(libssh2_channel_wait_eof, my->chan));
      my->sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_wait_closed, my->chan),
                                                        "Error waiting on socket to close: ${message}");

      char* exit_signal;
      char* error_message;
      libssh2_channel_get_exit_signal(my->chan, &exit_signal, NULL, &error_message, NULL, NULL, NULL);
      if (exit_signal) {
        // process terminated with a signal
        my->return_signal = exit_signal;
        libssh2_free(my->chan->session, exit_signal);
        if (error_message) {
          my->return_signal_message = error_message;
          libssh2_free(my->chan->session, error_message);
        }
      } else
        my->return_code = libssh2_channel_get_exit_status(my->chan);
    }
    if (my->return_signal)
      FC_THROW("process terminated with signal ${signal}: ${signal_message}", ("signal", *my->return_signal)
                                                                              ("signal_message", my->return_signal_message ? *my->return_signal_message : ""));
    else
      return *my->return_code;
  }
Ejemplo n.º 2
0
static int
ssh_client_profile_init(obfsproxyssh_client_t *client)
{
	obfsproxyssh_t *state = client->state;
	LIBSSH2_SESSION *session;
	struct bstrList *pmethods;
	const char **methods;
	bstring s;
	int i, j, k, found, rval;

	/*
	 * Determine the OS and select a "likely" fingerprint.
	 *
	 * Note:
	 * Every single asshat out there that compiles OpenSSH seems to end up
	 * tacking on additional information as the banner comment (Eg:
	 * SSH-2.0-OpenSSH_6.1p1 Debian-4)
	 *
	 * Picking the "right" OpenSSH is tricky because of this, and opens up
	 * the potential for an active attacker to attempt to probe the client
	 * and see if the ssh version running matches what we claim to be.
	 *
	 * In theory we *COULD* just claim to be PuTTY since every single OS
	 * that we vaguely care about can run PuTTY, but no one that's in their
	 * right mind would use it for ssh on OSX or U*IX.
	 *
	 * That said, it's plausible that real OSes (and OSX) can be running NAT
	 * for a Windows box, so acting like Putty for now is probably fine.
	 */

	/* NOTYET */
/*	ssh_client_profile_current = &ssh_client_profile_putty; */
	ssh_client_profile_current = &ssh_client_profile_putty_insecure;
#if 0
	if (ssh_client_profile_current == &ssh_client_profile_putty)
		return 0;
#endif

	/*
	 * So, libssh2 doesn't like to actually return anything that resembles
	 * an error code when it is asked to use unsupported algorithms.
	 *
	 * Instead it tries to ignore unsupported algorithms and only returns
	 * an error from libssh2_session_method_pref when there are no
	 * algorithms at all that are supported.
	 *
	 * Since it's vital that our behavior matches the emulated real client
	 * exactly, ensure that all the algorithms in a given profile are
	 * actually supported by libssh2.
	 *
	 * There's no way to get the algorithms that will be sent in a KEX
	 * without reaching into libssh2 internals either, so this is the best
	 * that can be done).
	 *
	 * On failure should I fail hard, or continue as a "generic libssh2
	 * application"?
	 */

	session = libssh2_session_init();
	if (NULL == session) {
		log_f(state, "SSH: Error: Failed to make temporary libssh2 session");
		return -1;
	}

	libssh2_session_flag(session, LIBSSH2_FLAG_COMPRESS,
			ssh_client_profile_current->enable_compression);

	for (i = 0; i <= LIBSSH2_METHOD_LANG_SC; i++) {
		if (NULL == ssh_client_profile_current->kex_methods[i])
			continue;

		s = bfromcstr(ssh_client_profile_current->kex_methods[i]);
		pmethods = bsplit(s,',');
		bdestroy(s);
		if (NULL == pmethods) {
			log_f(state, "SSH: Error: Out of memory verifying libssh2 settings");
			libssh2_session_free(session);
			return -1;
		}

		methods = NULL;
		rval = libssh2_session_supported_algs(session, i, &methods);
		if (0 > rval) {
			log_f(state, "SSH: Error: Out of memory verifying libssh2 settings");
out_free:
			if (NULL != methods)
				libssh2_free(session, methods);
			bstrListDestroy(pmethods);
			libssh2_session_free(session);
			return -1;
		}

		/* This is slow, but at least it's only done once */
		for (j = 0; j < pmethods->qty; j++) {
			found = 0;
			for (k = 0; k < rval; k++) {
				if (1 == biseqcstr(pmethods->entry[j],
							methods[k])) {
					found = 1;
					break;
				}
			}

			if (0 == found) {
				log_f(state, "SSH: Error: Unsupported Algorithm: [%d]: %s",
						i, bdata(pmethods->entry[j]));
				goto out_free;
			}
		}

		bstrListDestroy(pmethods);
		if (NULL != methods)
			libssh2_free(session, methods);
	}

	libssh2_session_free(session);

	return 0;
}