Exemplo n.º 1
0
int buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
    unsigned int len;
    unsigned char *bin;

    if ((bin = (unsigned char *)buffer_get_string_ret(buffer, &len)) == NULL)
    {
        return (-1);
    }
    if (len > 0 && (bin[0] & 0x80))
    {
        free(bin);
        return (-1);
    }
    if (len > 8 * 1024)
    {
        free(bin);
        return (-1);
    }
    if (BN_bin2bn(bin, len, value) == NULL)
    {
        free(bin);
        return (-1);
    }
    free(bin);
    return (0);
}
Exemplo n.º 2
0
int
buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
{
	u_int len;
	u_char *bin;

	if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
		error("buffer_get_bignum2_ret: invalid bignum");
		return (-1);
	}

	if (len > 0 && (bin[0] & 0x80)) {
		error("buffer_get_bignum2_ret: negative numbers not supported");
		free(bin);
		return (-1);
	}
	if (len > 8 * 1024) {
		error("buffer_get_bignum2_ret: cannot handle BN of size %d",
		    len);
		free(bin);
		return (-1);
	}
	if (BN_bin2bn(bin, len, value) == NULL) {
		error("buffer_get_bignum2_ret: BN_bin2bn failed");
		free(bin);
		return (-1);
	}
	free(bin);
	return (0);
}
Exemplo n.º 3
0
void *
buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
{
	u_int len;
	u_char *bin, *p, *ret;

	if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
		error("%s: invalid bignum", __func__);
		return NULL;
	}

	if (len > 0 && (bin[0] & 0x80)) {
		error("%s: negative numbers not supported", __func__);
		free(bin);
		return NULL;
	}
	if (len > 8 * 1024) {
		error("%s: cannot handle BN of size %d", __func__, len);
		free(bin);
		return NULL;
	}
	/* Skip zero prefix on numbers with the MSB set */
	if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
		p++;
		len--;
	}
	ret = xmalloc(len);
	memcpy(ret, p, len);
	memset(p, '\0', len);
	free(bin);
	return ret;
}
Exemplo n.º 4
0
void *
buffer_get_string(Buffer *buffer, u_int *length_ptr)
{
	void *ret;

	if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
		fatal("%s: buffer error", __func__);
	return (ret);
}
Exemplo n.º 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;
}
Exemplo n.º 6
0
void
rexec_recv_rng_seed(Buffer *m)
{
	u_char *buf;
	u_int len;

	buf = buffer_get_string_ret(m, &len);
	if (buf != NULL) {
		debug3("rexec_recv_rng_seed: seeding rng with %u bytes", len);
		RAND_add(buf, len, len);
	}
}
Exemplo n.º 7
0
int
buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
    EC_POINT *point)
{
	u_char *buf;
	u_int len;
	BN_CTX *bnctx;
	int ret = -1;

	if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
		error("%s: invalid point", __func__);
		return -1;
	}
	if ((bnctx = BN_CTX_new()) == NULL)
		fatal("%s: BN_CTX_new failed", __func__);
	if (len > BUFFER_MAX_ECPOINT_LEN) {
		error("%s: EC_POINT too long: %u > max %u", __func__,
		    len, BUFFER_MAX_ECPOINT_LEN);
		goto out;
	}
	if (len == 0) {
		error("%s: EC_POINT buffer is empty", __func__);
		goto out;
	}
	if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
		error("%s: EC_POINT is in an incorrect form: "
		    "0x%02x (want 0x%02x)", __func__, buf[0],
		    POINT_CONVERSION_UNCOMPRESSED);
		goto out;
	}
	if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
		error("buffer_get_bignum2_ret: BN_bin2bn failed");
		goto out;
	}
	/* EC_POINT_oct2point verifies that the point is on the curve for us */
	ret = 0;
 out:
	BN_CTX_free(bnctx);
	bzero(buf, len);
	xfree(buf);
	return ret;
}
Exemplo n.º 8
0
char *
buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
{
	u_int length;
	char *cp, *ret = buffer_get_string_ret(buffer, &length);

	if (ret == NULL)
		return NULL;
	if ((cp = memchr(ret, '\0', length)) != NULL) {
		/* XXX allow \0 at end-of-string for a while, remove later */
		if (cp == ret + length - 1)
			error("buffer_get_cstring_ret: string contains \\0");
		else {
			bzero(ret, length);
			free(ret);
			return NULL;
		}
	}
	if (length_ptr != NULL)
		*length_ptr = length;
	return ret;
}
Exemplo n.º 9
0
static int
parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
    u_int which, int crit,
    int *cert_no_port_forwarding_flag,
    int *cert_no_agent_forwarding_flag,
    int *cert_no_x11_forwarding_flag,
    int *cert_no_pty_flag,
    int *cert_no_user_rc,
    char **cert_forced_command,
    int *cert_source_address_done)
{
	char *command, *allowed;
	const char *remote_ip;
	u_char *name = NULL, *data_blob = NULL;
	u_int nlen, dlen, clen;
	Buffer c, data;
	int ret = -1, found;

	buffer_init(&data);

	/* Make copy to avoid altering original */
	buffer_init(&c);
	buffer_append(&c, optblob, optblob_len);

	while (buffer_len(&c) > 0) {
		if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
		    (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
			error("Certificate options corrupt");
			goto out;
		}
		buffer_append(&data, data_blob, dlen);
		debug3("found certificate option \"%.100s\" len %u",
		    name, dlen);
		if (strlen(name) != nlen) {
			error("Certificate constraint name contains \\0");
			goto out;
		}
		found = 0;
		if ((which & OPTIONS_EXTENSIONS) != 0) {
			if (strcmp(name, "permit-X11-forwarding") == 0) {
				*cert_no_x11_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name,
			    "permit-agent-forwarding") == 0) {
				*cert_no_agent_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name,
			    "permit-port-forwarding") == 0) {
				*cert_no_port_forwarding_flag = 0;
				found = 1;
			} else if (strcmp(name, "permit-pty") == 0) {
				*cert_no_pty_flag = 0;
				found = 1;
			} else if (strcmp(name, "permit-user-rc") == 0) {
				*cert_no_user_rc = 0;
				found = 1;
			}
		}
		if (!found && (which & OPTIONS_CRITICAL) != 0) {
			if (strcmp(name, "force-command") == 0) {
				if ((command = buffer_get_cstring_ret(&data,
				    &clen)) == NULL) {
					error("Certificate constraint \"%s\" "
					    "corrupt", name);
					goto out;
				}
				if (strlen(command) != clen) {
					error("force-command constraint "
					    "contains \\0");
					goto out;
				}
				if (*cert_forced_command != NULL) {
					error("Certificate has multiple "
					    "force-command options");
					xfree(command);
					goto out;
				}
				*cert_forced_command = command;
				found = 1;
			}
			if (strcmp(name, "source-address") == 0) {
				if ((allowed = buffer_get_cstring_ret(&data,
				    &clen)) == NULL) {
					error("Certificate constraint "
					    "\"%s\" corrupt", name);
					goto out;
				}
				if (strlen(allowed) != clen) {
					error("source-address constraint "
					    "contains \\0");
					goto out;
				}
				if ((*cert_source_address_done)++) {
					error("Certificate has multiple "
					    "source-address options");
					xfree(allowed);
					goto out;
				}
				remote_ip = get_remote_ipaddr();
				switch (addr_match_cidr_list(remote_ip,
				    allowed)) {
				case 1:
					/* accepted */
					xfree(allowed);
					break;
				case 0:
					/* no match */
					logit("Authentication tried for %.100s "
					    "with valid certificate but not "
					    "from a permitted host "
					    "(ip=%.200s).", pw->pw_name,
					    remote_ip);
					auth_debug_add("Your address '%.200s' "
					    "is not permitted to use this "
					    "certificate for login.",
					    remote_ip);
					xfree(allowed);
					goto out;
				case -1:
					error("Certificate source-address "
					    "contents invalid");
					xfree(allowed);
					goto out;
				}
				found = 1;
			}
		}

		if (!found) {
			if (crit) {
				error("Certificate critical option \"%s\" "
				    "is not supported", name);
				goto out;
			} else {
				logit("Certificate extension \"%s\" "
				    "is not supported", name);
			}
		} else if (buffer_len(&data) != 0) {
			error("Certificate option \"%s\" corrupt "
			    "(extra data)", name);
			goto out;
		}
		buffer_clear(&data);
		xfree(name);
		xfree(data_blob);
		name = data_blob = NULL;
	}
	/* successfully parsed all options */
	ret = 0;

 out:
	if (ret != 0 &&
	    cert_forced_command != NULL &&
	    *cert_forced_command != NULL) {
		xfree(*cert_forced_command);
		*cert_forced_command = NULL;
	}
	if (name != NULL)
		xfree(name);
	if (data_blob != NULL)
		xfree(data_blob);
	buffer_free(&data);
	buffer_free(&c);
	return ret;
}
Exemplo n.º 10
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;
	}