*/
#include "includes.h"
-RCSID("$OpenBSD: clientloop.c,v 1.124 2004/06/14 01:44:38 djm Exp $");
+RCSID("$OpenBSD: clientloop.c,v 1.128 2004/06/18 11:11:54 djm Exp $");
#include "ssh.h"
#include "ssh1.h"
Buffer cmd;
char *term;
struct termios tio;
+ char **env;
};
/*XXX*/
leave_non_blocking(void)
{
if (in_non_blocking_mode) {
- (void) fcntl(fileno(stdin), F_SETFL, 0);
+ unset_nonblock(fileno(stdin));
in_non_blocking_mode = 0;
}
}
{
struct confirm_ctx *cctx = arg;
Channel *c;
+ int i;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
fatal("%s: no channel for id %d", __func__, id);
client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
- cctx->term, &cctx->tio, c->rfd, &cctx->cmd,
+ cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
client_subsystem_reply);
-
+
c->confirm_ctx = NULL;
buffer_free(&cctx->cmd);
- free(cctx->term);
- free(cctx);
+ xfree(cctx->term);
+ if (cctx->env != NULL) {
+ for (i = 0; cctx->env[i] != NULL; i++)
+ xfree(cctx->env[i]);
+ xfree(cctx->env);
+ }
+ xfree(cctx);
}
static void
{
Buffer m;
Channel *c;
- int client_fd, new_fd[3], ver;
+ int client_fd, new_fd[3], ver, i, allowed;
socklen_t addrlen;
struct sockaddr_storage addr;
struct confirm_ctx *cctx;
char *cmd;
- u_int len;
+ u_int len, env_len;
uid_t euid;
gid_t egid;
close(client_fd);
return;
}
- /* XXX: implement use of ssh-askpass to confirm additional channels */
+
+ allowed = 1;
+ if (options.control_master == 2) {
+ char *p, prompt[1024];
+
+ allowed = 0;
+ snprintf(prompt, sizeof(prompt),
+ "Allow shared connection to %s? ", host);
+ p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
+ if (p != NULL) {
+ /*
+ * Accept empty responses and responses consisting
+ * of the word "yes" as affirmative.
+ */
+ if (*p == '\0' || *p == '\n' ||
+ strcasecmp(p, "yes") == 0)
+ allowed = 1;
+ xfree(p);
+ }
+ }
unset_nonblock(client_fd);
buffer_init(&m);
+ buffer_put_int(&m, allowed);
buffer_put_int(&m, getpid());
if (ssh_msg_send(client_fd, /* version */0, &m) == -1) {
error("%s: client msg_send failed", __func__);
close(client_fd);
+ buffer_free(&m);
return;
}
buffer_clear(&m);
+ if (!allowed) {
+ error("Refused control connection");
+ close(client_fd);
+ buffer_free(&m);
+ return;
+ }
+
if (ssh_msg_recv(client_fd, &m) == -1) {
error("%s: client msg_recv failed", __func__);
close(client_fd);
+ buffer_free(&m);
return;
}
buffer_init(&cctx->cmd);
buffer_append(&cctx->cmd, cmd, strlen(cmd));
+ env_len = buffer_get_int(&m);
+ env_len = MIN(env_len, 4096);
+ debug3("%s: receiving %d env vars", __func__, env_len);
+ if (env_len != 0) {
+ cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1));
+ for (i = 0; i < env_len; i++)
+ cctx->env[i] = buffer_get_string(&m, &len);
+ cctx->env[i] = NULL;
+ }
+
debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
cctx->want_tty, cctx->want_subsys, cmd);
close(new_fd[0]);
close(new_fd[1]);
close(new_fd[2]);
+ buffer_free(&m);
return;
}
buffer_free(&m);
debug("client_input_channel_req: channel %d rtype %s reply %d",
id, rtype, reply);
- c = channel_lookup(id);
- if (c == NULL) {
+ if (id == -1) {
+ error("client_input_channel_req: request for channel -1");
+ } else if ((c = channel_lookup(id)) == NULL) {
error("client_input_channel_req: channel %d: unknown channel", id);
} else if (strcmp(rtype, "exit-status") == 0) {
exitval = packet_get_int();
if (reply) {
packet_start(success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
+ packet_put_int(id);
packet_send();
}
xfree(rtype);
void
client_session2_setup(int id, int want_tty, int want_subsystem,
- const char *term, struct termios *tiop, int in_fd, Buffer *cmd,
+ const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
dispatch_fn *subsys_repl)
{
int len;
}
/* Transfer any environment variables from client to server */
- if (options.num_send_env != 0) {
+ if (options.num_send_env != 0 && env != NULL) {
int i, j, matched;
- extern char **environ;
char *name, *val;
debug("Sending environment.");
- for (i = 0; environ && environ[i] != NULL; i++) {
+ for (i = 0; env[i] != NULL; i++) {
/* Split */
- name = xstrdup(environ[i]);
+ name = xstrdup(env[i]);
if ((val = strchr(name, '=')) == NULL) {
free(name);
continue;