Пример #1
0
/*
 * Returns an arbitrary binary string from the buffer.  The string cannot
 * be longer than 256k.  The returned value points to memory allocated
 * with xmalloc; it is the responsibility of the calling function to free
 * the data.  If length_ptr is non-NULL, the length of the returned data
 * will be stored there.  A null character will be automatically appended
 * to the returned string, and is not counted in length.
 */
void *
buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
{
	u_char *value;
	u_int len;

	/* Get the length. */
	if (buffer_get_int_ret(&len, buffer) != 0) {
		error("buffer_get_string_ret: cannot extract length");
		return (NULL);
	}
	if (len > 256 * 1024) {
		error("buffer_get_string_ret: bad string length %u", len);
		return (NULL);
	}
	/* Allocate space for the string.  Add one byte for a null character. */
	value = xmalloc(len + 1);
	/* Get the string. */
	if (buffer_get_ret(buffer, value, len) == -1) {
		error("buffer_get_string_ret: buffer_get failed");
		free(value);
		return (NULL);
	}
	/* Append a null character to make processing easier. */
	value[len] = '\0';
	/* Optionally return the length of the string. */
	if (length_ptr)
		*length_ptr = len;
	return (value);
}
Пример #2
0
u_int
buffer_get_int(Buffer *buffer)
{
	u_int ret = 0;		/* XXX: GCC */

	if (buffer_get_int_ret(&ret, buffer) == -1)
		fatal("%s: buffer error", __func__);

	return (ret);
}
Пример #3
0
u_int
buffer_get_int(Buffer *buffer)
{
	u_int ret;

	if (buffer_get_int_ret(&ret, buffer) == -1)
		fatal("buffer_get_int: buffer error");

	return (ret);
}
Пример #4
0
void *
buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
{
	void *ptr;
	u_int len;

	if (buffer_get_int_ret(&len, buffer) != 0)
		return NULL;
	if (len > 256 * 1024) {
		error("buffer_get_string_ptr: bad string length %u", len);
		return NULL;
	}
	ptr = buffer_ptr(buffer);
	buffer_consume(buffer, len);
	if (length_ptr)
		*length_ptr = len;
	return (ptr);
}
Пример #5
0
static int
process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
{
	u_int ver;
	struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;

	if (state == NULL)
		fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
	if (state->hello_rcvd) {
		error("%s: HELLO received twice", __func__);
		return -1;
	}
	if (buffer_get_int_ret(&ver, m) != 0) {
 malf:
		error("%s: malformed message", __func__);
		return -1;
	}
	if (ver != SSHMUX_VER) {
		error("Unsupported multiplexing protocol version %d "
		    "(expected %d)", ver, SSHMUX_VER);
		return -1;
	}
	debug2("%s: channel %d slave version %u", __func__, c->self, ver);

	/* No extensions are presently defined */
	while (buffer_len(m) > 0) {
		char *name = buffer_get_string_ret(m, NULL);
		char *value = buffer_get_string_ret(m, NULL);

		if (name == NULL || value == NULL) {
			if (name != NULL)
				xfree(name);
			goto malf;
		}
		debug2("Unrecognised slave extension \"%s\"", name);
		xfree(name);
		xfree(value);
	}
	state->hello_rcvd = 1;
	return 0;
}
Пример #6
0
static int
process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
{
	Channel *nc;
	struct mux_session_confirm_ctx *cctx;
	char *reserved, *cmd, *cp;
	u_int i, j, len, env_len, escape_char, window, packetmax;
	int new_fd[3];

	/* Reply for SSHMUX_COMMAND_OPEN */
	cctx = xcalloc(1, sizeof(*cctx));
	cctx->term = NULL;
	cmd = reserved = NULL;
	if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
	    buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
	    buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
	    buffer_get_int_ret(&cctx->want_agent_fwd, m) != 0 ||
	    buffer_get_int_ret(&cctx->want_subsys, m) != 0 ||
	    buffer_get_int_ret(&escape_char, m) != 0 ||
	    (cctx->term = buffer_get_string_ret(m, &len)) == NULL ||
	    (cmd = buffer_get_string_ret(m, &len)) == NULL) {
 malf:
		if (cmd != NULL)
			xfree(cmd);
		if (reserved != NULL)
			xfree(reserved);
		if (cctx->term != NULL)
			xfree(cctx->term);
		error("%s: malformed message", __func__);
		return -1;
	}
	xfree(reserved);
	reserved = NULL;

	cctx->env = NULL;
	env_len = 0;
	while (buffer_len(m) > 0) {
#define MUX_MAX_ENV_VARS	4096
		if ((cp = buffer_get_string_ret(m, &len)) == NULL) {
			xfree(cmd);
			goto malf;
		}
		if (!env_permitted(cp)) {
			xfree(cp);
			continue;
		}
		cctx->env = xrealloc(cctx->env, env_len + 2,
		    sizeof(*cctx->env));
		cctx->env[env_len++] = cp;
		cctx->env[env_len] = NULL;
		if (env_len > MUX_MAX_ENV_VARS) {
			error(">%d environment variables received, ignoring "
			    "additional", MUX_MAX_ENV_VARS);
			break;
		}
	}

	debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
	    "term \"%s\", cmd \"%s\", env %u", __func__, c->self,
	    cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
	    cctx->want_subsys, cctx->term, cmd, env_len);

	buffer_init(&cctx->cmd);
	buffer_append(&cctx->cmd, cmd, strlen(cmd));
	xfree(cmd);
	cmd = NULL;

	/* Gather fds from client */
	for(i = 0; i < 3; i++) {
		if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
			error("%s: failed to receive fd %d from slave",
			    __func__, i);
			for (j = 0; j < i; j++)
				close(new_fd[j]);
			for (j = 0; j < env_len; j++)
				xfree(cctx->env[j]);
			if (env_len > 0)
				xfree(cctx->env);
			xfree(cctx->term);
			buffer_free(&cctx->cmd);
			xfree(cctx);

			/* prepare reply */
			buffer_put_int(r, MUX_S_FAILURE);
			buffer_put_int(r, rid);
			buffer_put_cstring(r,
			    "did not receive file descriptors");
			return -1;
		}
	}

	debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
	    new_fd[0], new_fd[1], new_fd[2]);

	/* XXX support multiple child sessions in future */
	if (c->remote_id != -1) {
		debug2("%s: session already open", __func__);
		/* prepare reply */
		buffer_put_int(r, MUX_S_FAILURE);
		buffer_put_int(r, rid);
		buffer_put_cstring(r, "Multiple sessions not supported");
 cleanup:
		close(new_fd[0]);
		close(new_fd[1]);
		close(new_fd[2]);
		xfree(cctx->term);
		if (env_len != 0) {
			for (i = 0; i < env_len; i++)
				xfree(cctx->env[i]);
			xfree(cctx->env);
		}
		buffer_free(&cctx->cmd);
		return 0;
	}

	if (options.control_master == SSHCTL_MASTER_ASK ||
	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
		if (!ask_permission("Allow shared connection to %s? ", host)) {
			debug2("%s: session refused by user", __func__);
			/* prepare reply */
			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
			buffer_put_int(r, rid);
			buffer_put_cstring(r, "Permission denied");
			goto cleanup;
		}
	}

	/* Try to pick up ttymodes from client before it goes raw */
	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
		error("%s: tcgetattr: %s", __func__, strerror(errno));

	/* enable nonblocking unless tty */
	if (!isatty(new_fd[0]))
		set_nonblock(new_fd[0]);
	if (!isatty(new_fd[1]))
		set_nonblock(new_fd[1]);
	if (!isatty(new_fd[2]))
		set_nonblock(new_fd[2]);

	window = CHAN_SES_WINDOW_DEFAULT;
	packetmax = CHAN_SES_PACKET_DEFAULT;
	if (cctx->want_tty) {
		window >>= 1;
		packetmax >>= 1;
	}