- Buffer m;
- Channel *c;
- int client_fd, new_fd[3], ver, allowed;
- socklen_t addrlen;
- struct sockaddr_storage addr;
- struct confirm_ctx *cctx;
- char *cmd;
- u_int i, len, env_len, command, flags;
- uid_t euid;
- gid_t egid;
- int listen_port = 0;
- int connect_port = 0;
- char * listen_host = NULL;
- char * connect_host = NULL;
-
- /*
- * Accept connection on control socket
- */
- if (control_fd == -1 || !FD_ISSET(control_fd, readset))
- return;
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
- if ((client_fd = accept(control_fd,
- (struct sockaddr*)&addr, &addrlen)) == -1) {
- error("%s accept: %s", __func__, strerror(errno));
- return;
- }
-
- if (getpeereid(client_fd, &euid, &egid) < 0) {
- error("%s getpeereid failed: %s", __func__, strerror(errno));
- close(client_fd);
- return;
- }
- if ((euid != 0) && (getuid() != euid)) {
- error("control mode uid mismatch: peer euid %u != uid %u",
- (u_int) euid, (u_int) getuid());
- close(client_fd);
- return;
- }
-
- unset_nonblock(client_fd);
-
- /* Read command */
- buffer_init(&m);
- if (ssh_msg_recv(client_fd, &m) == -1) {
- error("%s: client msg_recv failed", __func__);
- close(client_fd);
- buffer_free(&m);
- return;
- }
- if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
- error("%s: wrong client version %d", __func__, ver);
- buffer_free(&m);
- close(client_fd);
- return;
- }
-
- allowed = 1;
- command = buffer_get_int(&m);
- flags = buffer_get_int(&m);
-
- if (SSHMUX_FLAG_PORTFORWARD & flags)
- {
- listen_host = buffer_get_string(&m,NULL);
- listen_port = buffer_get_int(&m);
- connect_host = buffer_get_string(&m,NULL);
- connect_port = buffer_get_int(&m);
- }
- buffer_clear(&m);
-
- switch (command) {
- case SSHMUX_COMMAND_OPEN:
- if (options.control_master == SSHCTL_MASTER_ASK ||
- options.control_master == SSHCTL_MASTER_AUTO_ASK)
- allowed = ask_permission("Allow shared connection "
- "to %s? ", host);
- /* continue below */
- break;
- case SSHMUX_COMMAND_TERMINATE:
- if (options.control_master == SSHCTL_MASTER_ASK ||
- options.control_master == SSHCTL_MASTER_AUTO_ASK)
- allowed = ask_permission("Terminate shared connection "
- "to %s? ", host);
- if (allowed)
- quit_pending = 1;
- /* FALLTHROUGH */
- case SSHMUX_COMMAND_ALIVE_CHECK:
- /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
- buffer_clear(&m);
- buffer_put_int(&m, allowed);
- buffer_put_int(&m, getpid());
- if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
- error("%s: client msg_send failed", __func__);
- close(client_fd);
- buffer_free(&m);
- return;
- }
- buffer_free(&m);
- close(client_fd);
- return;
- default:
- error("Unsupported command %d", command);
- buffer_free(&m);
- close(client_fd);
- return;
- }
-
- if (allowed && (SSHMUX_FLAG_PORTFORWARD & flags) && listen_host && connect_host)
- {
- int ret;
- Forward * fwd;
-
- fwd = &options.local_forwards[options.num_local_forwards++];
- fwd->listen_host = xstrdup(listen_host);
- fwd->listen_port = listen_port;
- fwd->connect_host = xstrdup(connect_host);
- fwd->connect_port = connect_port;
- ret = channel_setup_local_fwd_listener(
- options.local_forwards[options.num_local_forwards-1].listen_host,
- options.local_forwards[options.num_local_forwards-1].listen_port,
- options.local_forwards[options.num_local_forwards-1].connect_host,
- options.local_forwards[options.num_local_forwards-1].connect_port,
- options.gateway_ports, options.hpn_disabled, options.hpn_buffer_size);
-
- }