Example #1
0
static void handle_sigchld(__unused int sig)
{
	int status;
	pid_t pid;

	while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
		if (WIFEXITED(status))
			tmate_info("Child %d exited (%d)", pid, WEXITSTATUS(status));
		if (WIFSIGNALED(status))
			tmate_info("Child %d killed (%d)", pid, WTERMSIG(status));
		if (WIFSTOPPED(status))
			tmate_info("Child %d stopped (%d)", pid, WSTOPSIG(status));
	}
}
Example #2
0
static void handle_sigsegv(__unused int sig)
{
	/* TODO send stack trace to server */
	tmate_info("CRASH, printing stack trace");
	tmate_print_stack_trace();
	tmate_fatal("CRASHED");
}
Example #3
0
void tmate_print_trace(void)
{
    void *array[20];
    size_t size;
    char **strings;
    size_t i;

    size = backtrace(array, 20);
    strings = backtrace_symbols(array, size);

    tmate_info("============ %zd stack frames ============", size);

    for (i = 1; i < size; i++) {
#if DEBUG
        if (print_resolved_stack_frame(strings[i]) < 0)
#endif
            tmate_info("%s", strings[i]);
    }

    free(strings);
}
Example #4
0
static void handle_sigchld(__unused int sig)
{
	int status;
	pid_t pid;

	while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
		/*
		 * It's not safe to call indirectly malloc() here, because
		 * of potential deadlocks with ssh_bind_accept() which also
		 * calls malloc(). (And we can't even block singals because
		 * the accept() call is blocking.
		 */
#if 0
		if (WIFEXITED(status))
			tmate_info("Child %d exited (%d)", pid, WEXITSTATUS(status));
		if (WIFSIGNALED(status))
			tmate_info("Child %d killed (%d)", pid, WTERMSIG(status));
		if (WIFSTOPPED(status))
			tmate_info("Child %d stopped (%d)", pid, WSTOPSIG(status));
#endif
	}
}
Example #5
0
void tmate_ssh_server_main(struct tmate_session *session,
			   const char *keys_dir, int port)
{
	sigset_t sigchld_set;
	struct tmate_ssh_client *client = &session->ssh_client;
	ssh_bind bind;
	pid_t pid;

	signal(SIGSEGV, handle_sigsegv);
	signal(SIGCHLD, handle_sigchld);

	sigemptyset(&sigchld_set);
	sigaddset(&sigchld_set, SIGCHLD);
	sigprocmask(SIG_BLOCK, &sigchld_set, NULL);

	bind = prepare_ssh(keys_dir, port);

	for (;;) {
		client->session = ssh_new();
		client->channel = NULL;
		client->winsize_pty.ws_col = 80;
		client->winsize_pty.ws_row = 24;

		if (!client->session)
			tmate_fatal("Cannot initialize session");

		sigprocmask(SIG_UNBLOCK, &sigchld_set, NULL);
		if (ssh_bind_accept(bind, client->session) < 0)
			tmate_fatal("Error accepting connection: %s", ssh_get_error(bind));
		sigprocmask(SIG_BLOCK, &sigchld_set, NULL);

		if (get_ip(ssh_get_fd(client->session),
			   client->ip_address, sizeof(client->ip_address)) < 0)
			tmate_fatal("Error getting IP address from connection");

		if ((pid = fork()) < 0)
			tmate_fatal("Can't fork");

		if (pid) {
			tmate_info("Child spawned pid=%d, ip=%s",
				    pid, client->ip_address);
			ssh_free(client->session);
		} else {
			ssh_bind_free(bind);
			session->session_token = "init";
			client_bootstrap(session);
		}
	}
}
Example #6
0
void tmate_dispatch_slave_message(struct tmate_session *session,
				  struct tmate_unpacker *uk)
{
	int cmd = unpack_int(uk);
	switch (cmd) {
#define dispatch(c, f) case c: f(session, uk); break
	dispatch(TMATE_IN_NOTIFY,		handle_notify);
	dispatch(TMATE_IN_LEGACY_PANE_KEY,	handle_legacy_pane_key);
	dispatch(TMATE_IN_RESIZE,		handle_resize);
	dispatch(TMATE_IN_EXEC_CMD_STR,		handle_exec_cmd_str);
	dispatch(TMATE_IN_SET_ENV,		handle_set_env);
	dispatch(TMATE_IN_READY,		handle_ready);
	dispatch(TMATE_IN_PANE_KEY,		handle_pane_key);
	dispatch(TMATE_IN_EXEC_CMD,		handle_exec_cmd);
	default: tmate_info("Bad message type: %d", cmd);
	}
}
Example #7
0
static int print_resolved_stack_frame(const char *frame)
{
    char file[100];
    char cmd[200];
    char output[300];
    char address[20];
    char *line;
    FILE *ps;

    static regex_t _regex;
    static regex_t *regex;
    regmatch_t matches[3];

    if (!regex) {
        if (regcomp(&_regex, "(.+)\\(\\) \\[([^]]+)\\]", REG_EXTENDED))
            return -1;
        regex = &_regex;
    }

    if (regexec(regex, frame, 3, matches, 0))
        return -1;

    memcpy(file, &frame[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so);
    file[matches[1].rm_eo - matches[1].rm_so] = 0;

    memcpy(address, &frame[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so);
    address[matches[2].rm_eo - matches[2].rm_so] = 0;

    sprintf(cmd, "addr2line -e %s %s -f -p -s", file, address);

    ps = popen(cmd, "r");
    if (!ps)
        return -1;

    line = fgets(output, sizeof(output), ps);
    pclose(ps);

    if (!line)
        return -1;

    line[strlen(line)-1] = 0; /* remove \n */
    tmate_info("%s(%s) [%s]", file, line, address);
    return 0;
}
Example #8
0
static void lookup_and_connect(void)
{
	struct evutil_addrinfo hints;

	if (!ev_dnsbase)
		ev_dnsbase = evdns_base_new(ev_base, 1);
	if (!ev_dnsbase)
		tmate_fatal("Cannot initialize the DNS lookup service");

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_flags = 0;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	tmate_info("Looking up %s...", TMATE_HOST);
	(void)evdns_getaddrinfo(ev_dnsbase, TMATE_HOST, NULL,
				&hints, dns_cb, NULL);
}
static void lookup_and_connect(void)
{
	struct evutil_addrinfo hints;
	const char *tmate_server_host;

	if (!tmate_session.ev_dnsbase)
		tmate_session.ev_dnsbase = evdns_base_new(tmate_session.ev_base, 1);
	if (!tmate_session.ev_dnsbase)
		tmate_fatal("Cannot initialize the DNS lookup service");

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_flags = EVUTIL_AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	tmate_server_host = options_get_string(global_options,
					       "tmate-server-host");
	tmate_info("Looking up %s...", tmate_server_host);
	(void)evdns_getaddrinfo(tmate_session.ev_dnsbase, tmate_server_host, NULL,
				&hints, dns_cb, (void *)tmate_server_host);
}
Example #10
0
static void handle_sigsegv(__unused int sig)
{
	tmate_info("CRASH, printing stack trace");
	tmate_print_stack_trace();
	tmate_fatal("CRASHED");
}
Example #11
0
static void client_bootstrap(struct tmate_session *_session)
{
	struct tmate_ssh_client *client = &_session->ssh_client;
	int grace_period = TMATE_SSH_GRACE_PERIOD;
	ssh_event mainloop;
	ssh_session session = client->session;

	tmate_notice("Bootstrapping ssh client ip=%s", client->ip_address);

	_session->ev_base = osdep_event_init();

	/* new process group, we don't want to die with our parent (upstart) */
	setpgid(0, 0);

	{
	int flag = 1;
	setsockopt(ssh_get_fd(session), IPPROTO_TCP, TCP_NODELAY,
		   &flag, sizeof(flag));
	}

	signal(SIGALRM, handle_sigalrm);
	alarm(grace_period);

	/*
	 * We should die early if we can't connect to proxy. This way the
	 * tmate daemon will pick another server to work on.
	 */
	_session->proxy_fd = -1;
	if (tmate_has_proxy())
		_session->proxy_fd = tmate_connect_to_proxy();

	ssh_server_cb.userdata = client;
	ssh_callbacks_init(&ssh_server_cb);
	ssh_set_server_callbacks(client->session, &ssh_server_cb);

	ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &grace_period);
	ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes");

	ssh_set_auth_methods(client->session, SSH_AUTH_METHOD_PUBLICKEY);

	tmate_info("Exchanging DH keys");
	if (ssh_handle_key_exchange(session) < 0)
		tmate_fatal("Error doing the key exchange: %s",
				    ssh_get_error(session));

	mainloop = ssh_event_new();
	ssh_event_add_session(mainloop, session);

	while (!client->role) {
		if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR)
			tmate_fatal("Error polling ssh socket: %s", ssh_get_error(session));
	}

	alarm(0);

	/* The latency is callback set later */
	tmate_start_ssh_latency_probes(client, &ssh_server_cb, TMATE_SSH_KEEPALIVE * 1000);
	register_on_ssh_read(client);

	tmate_spawn(_session);
	/* never reached */
}
Example #12
0
static void ssh_log_function(int priority, const char *function,
			     const char *buffer, __unused void *userdata)
{
	tmate_info("[%d] [%s] %s", priority, function, buffer);
}