version 1.249, 2005/07/30 01:26:16 |
version 1.249.2.3, 2006/11/08 00:44:05 |
|
|
|
/* $OpenBSD$ */ |
/* |
/* |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
#include "includes.h" |
#include <sys/types.h> |
RCSID("$OpenBSD$"); |
#include <sys/time.h> |
|
#include <sys/resource.h> |
|
#include <sys/ioctl.h> |
|
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
#include <sys/un.h> |
|
#include <sys/stat.h> |
|
|
|
#include <ctype.h> |
|
#include <errno.h> |
|
#include <fcntl.h> |
|
#include <netdb.h> |
|
#include <paths.h> |
|
#include <pwd.h> |
|
#include <signal.h> |
|
#include <stddef.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
|
#include <openssl/evp.h> |
#include <openssl/evp.h> |
#include <openssl/err.h> |
#include <openssl/err.h> |
|
|
|
#include "xmalloc.h" |
#include "ssh.h" |
#include "ssh.h" |
#include "ssh1.h" |
#include "ssh1.h" |
#include "ssh2.h" |
#include "ssh2.h" |
#include "compat.h" |
#include "compat.h" |
#include "cipher.h" |
#include "cipher.h" |
#include "xmalloc.h" |
|
#include "packet.h" |
#include "packet.h" |
#include "buffer.h" |
#include "buffer.h" |
#include "bufaux.h" |
|
#include "channels.h" |
#include "channels.h" |
#include "key.h" |
#include "key.h" |
#include "authfd.h" |
#include "authfd.h" |
|
|
#include "msg.h" |
#include "msg.h" |
#include "monitor_fdpass.h" |
#include "monitor_fdpass.h" |
#include "uidswap.h" |
#include "uidswap.h" |
|
#include "version.h" |
|
|
#ifdef SMARTCARD |
#ifdef SMARTCARD |
#include "scard.h" |
#include "scard.h" |
|
|
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" |
"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" |
" [-D port] [-e escape_char] [-F configfile]\n" |
" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" |
" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" |
" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" |
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" |
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" |
" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" |
" [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" |
" [user@]hostname [command]\n" |
" [-w local_tun[:remote_tun]] [user@]hostname [command]\n" |
); |
); |
exit(1); |
exit(255); |
} |
} |
|
|
static int ssh_session(void); |
static int ssh_session(void); |
|
|
struct servent *sp; |
struct servent *sp; |
Forward fwd; |
Forward fwd; |
|
|
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
|
sanitise_stdfd(); |
|
|
/* |
/* |
* Save the original real uid. It will be needed later (uid-swapping |
* Save the original real uid. It will be needed later (uid-swapping |
* may clobber the real uid). |
* may clobber the real uid). |
|
|
pw = getpwuid(original_real_uid); |
pw = getpwuid(original_real_uid); |
if (!pw) { |
if (!pw) { |
logit("You don't exist, go away!"); |
logit("You don't exist, go away!"); |
exit(1); |
exit(255); |
} |
} |
/* Take a copy of the returned structure. */ |
/* Take a copy of the returned structure. */ |
pw = pwcopy(pw); |
pw = pwcopy(pw); |
|
|
/* Parse command-line arguments. */ |
/* Parse command-line arguments. */ |
host = NULL; |
host = NULL; |
|
|
again: |
again: |
while ((opt = getopt(ac, av, |
while ((opt = getopt(ac, av, |
"1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) { |
"1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XY")) != -1) { |
switch (opt) { |
switch (opt) { |
case '1': |
case '1': |
options.protocol = SSH_PROTO_1; |
options.protocol = SSH_PROTO_1; |
|
|
if (opt == 'V') |
if (opt == 'V') |
exit(0); |
exit(0); |
break; |
break; |
|
case 'w': |
|
if (options.tun_open == -1) |
|
options.tun_open = SSH_TUNMODE_DEFAULT; |
|
options.tun_local = a2tun(optarg, &options.tun_remote); |
|
if (options.tun_local == SSH_TUNID_ERR) { |
|
fprintf(stderr, "Bad tun device '%s'\n", optarg); |
|
exit(255); |
|
} |
|
break; |
case 'q': |
case 'q': |
options.log_level = SYSLOG_LEVEL_QUIET; |
options.log_level = SYSLOG_LEVEL_QUIET; |
break; |
break; |
|
|
else { |
else { |
fprintf(stderr, "Bad escape character '%s'.\n", |
fprintf(stderr, "Bad escape character '%s'.\n", |
optarg); |
optarg); |
exit(1); |
exit(255); |
} |
} |
break; |
break; |
case 'c': |
case 'c': |
|
|
fprintf(stderr, |
fprintf(stderr, |
"Unknown cipher type '%s'\n", |
"Unknown cipher type '%s'\n", |
optarg); |
optarg); |
exit(1); |
exit(255); |
} |
} |
if (options.cipher == SSH_CIPHER_3DES) |
if (options.cipher == SSH_CIPHER_3DES) |
options.ciphers = "3des-cbc"; |
options.ciphers = "3des-cbc"; |
|
|
else { |
else { |
fprintf(stderr, "Unknown mac type '%s'\n", |
fprintf(stderr, "Unknown mac type '%s'\n", |
optarg); |
optarg); |
exit(1); |
exit(255); |
} |
} |
break; |
break; |
case 'M': |
case 'M': |
|
|
options.port = a2port(optarg); |
options.port = a2port(optarg); |
if (options.port == 0) { |
if (options.port == 0) { |
fprintf(stderr, "Bad port '%s'\n", optarg); |
fprintf(stderr, "Bad port '%s'\n", optarg); |
exit(1); |
exit(255); |
} |
} |
break; |
break; |
case 'l': |
case 'l': |
|
|
fprintf(stderr, |
fprintf(stderr, |
"Bad local forwarding specification '%s'\n", |
"Bad local forwarding specification '%s'\n", |
optarg); |
optarg); |
exit(1); |
exit(255); |
} |
} |
break; |
break; |
|
|
|
|
fprintf(stderr, |
fprintf(stderr, |
"Bad remote forwarding specification " |
"Bad remote forwarding specification " |
"'%s'\n", optarg); |
"'%s'\n", optarg); |
exit(1); |
exit(255); |
} |
} |
break; |
break; |
|
|
|
|
if ((fwd.listen_host = hpdelim(&cp)) == NULL) { |
if ((fwd.listen_host = hpdelim(&cp)) == NULL) { |
fprintf(stderr, "Bad dynamic forwarding " |
fprintf(stderr, "Bad dynamic forwarding " |
"specification '%.100s'\n", optarg); |
"specification '%.100s'\n", optarg); |
exit(1); |
exit(255); |
} |
} |
if (cp != NULL) { |
if (cp != NULL) { |
fwd.listen_port = a2port(cp); |
fwd.listen_port = a2port(cp); |
|
|
if (fwd.listen_port == 0) { |
if (fwd.listen_port == 0) { |
fprintf(stderr, "Bad dynamic port '%s'\n", |
fprintf(stderr, "Bad dynamic port '%s'\n", |
optarg); |
optarg); |
exit(1); |
exit(255); |
} |
} |
add_local_forward(&options, &fwd); |
add_local_forward(&options, &fwd); |
xfree(p); |
xfree(p); |
|
|
line = xstrdup(optarg); |
line = xstrdup(optarg); |
if (process_config_line(&options, host ? host : "", |
if (process_config_line(&options, host ? host : "", |
line, "command-line", 0, &dummy) != 0) |
line, "command-line", 0, &dummy) != 0) |
exit(1); |
exit(255); |
xfree(line); |
xfree(line); |
break; |
break; |
case 's': |
case 's': |
|
|
if (options.host_key_alias != NULL) { |
if (options.host_key_alias != NULL) { |
for (p = options.host_key_alias; *p; p++) |
for (p = options.host_key_alias; *p; p++) |
if (isupper(*p)) |
if (isupper(*p)) |
*p = tolower(*p); |
*p = (char)tolower(*p); |
} |
} |
|
|
/* Get default port if port has not been set. */ |
/* Get default port if port has not been set. */ |
|
|
options.control_path = NULL; |
options.control_path = NULL; |
|
|
if (options.control_path != NULL) { |
if (options.control_path != NULL) { |
|
char thishost[NI_MAXHOST]; |
|
|
|
if (gethostname(thishost, sizeof(thishost)) == -1) |
|
fatal("gethostname: %s", strerror(errno)); |
snprintf(buf, sizeof(buf), "%d", options.port); |
snprintf(buf, sizeof(buf), "%d", options.port); |
cp = tilde_expand_filename(options.control_path, |
cp = tilde_expand_filename(options.control_path, |
original_real_uid); |
original_real_uid); |
options.control_path = percent_expand(cp, "p", buf, "h", host, |
options.control_path = percent_expand(cp, "p", buf, "h", host, |
"r", options.user, (char *)NULL); |
"r", options.user, "l", thishost, (char *)NULL); |
xfree(cp); |
xfree(cp); |
} |
} |
if (mux_command != 0 && options.control_path == NULL) |
if (mux_command != 0 && options.control_path == NULL) |
|
|
options.address_family, options.connection_attempts, |
options.address_family, options.connection_attempts, |
original_effective_uid == 0 && options.use_privileged_port, |
original_effective_uid == 0 && options.use_privileged_port, |
options.proxy_command) != 0) |
options.proxy_command) != 0) |
exit(1); |
exit(255); |
|
|
/* |
/* |
* If we successfully made the connection, load the host private key |
* If we successfully made the connection, load the host private key |
|
|
if (options.rhosts_rsa_authentication || |
if (options.rhosts_rsa_authentication || |
options.hostbased_authentication) { |
options.hostbased_authentication) { |
sensitive_data.nkeys = 3; |
sensitive_data.nkeys = 3; |
sensitive_data.keys = xmalloc(sensitive_data.nkeys * |
sensitive_data.keys = xcalloc(sensitive_data.nkeys, |
sizeof(Key)); |
sizeof(Key)); |
|
|
PRIV_START; |
PRIV_START; |
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, |
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, |
_PATH_HOST_KEY_FILE, "", NULL); |
_PATH_HOST_KEY_FILE, "", NULL, NULL); |
sensitive_data.keys[1] = key_load_private_type(KEY_DSA, |
sensitive_data.keys[1] = key_load_private_type(KEY_DSA, |
_PATH_HOST_DSA_KEY_FILE, "", NULL); |
_PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); |
sensitive_data.keys[2] = key_load_private_type(KEY_RSA, |
sensitive_data.keys[2] = key_load_private_type(KEY_RSA, |
_PATH_HOST_RSA_KEY_FILE, "", NULL); |
_PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); |
PRIV_END; |
PRIV_END; |
|
|
if (options.hostbased_authentication == 1 && |
if (options.hostbased_authentication == 1 && |
|
|
|
|
/* |
/* |
* Now that we are back to our own permissions, create ~/.ssh |
* Now that we are back to our own permissions, create ~/.ssh |
* directory if it doesn\'t already exist. |
* directory if it doesn't already exist. |
*/ |
*/ |
snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); |
if (stat(buf, &st) < 0) |
if (stat(buf, &st) < 0) |
|
|
options.local_forwards[i].connect_port, |
options.local_forwards[i].connect_port, |
options.gateway_ports); |
options.gateway_ports); |
} |
} |
|
if (i > 0 && success != i && options.exit_on_forward_failure) |
|
fatal("Could not request local forwarding."); |
if (i > 0 && success == 0) |
if (i > 0 && success == 0) |
error("Could not request local forwarding."); |
error("Could not request local forwarding."); |
|
|
|
|
debug("Remote connections from %.200s:%d forwarded to " |
debug("Remote connections from %.200s:%d forwarded to " |
"local address %.200s:%d", |
"local address %.200s:%d", |
(options.remote_forwards[i].listen_host == NULL) ? |
(options.remote_forwards[i].listen_host == NULL) ? |
(options.gateway_ports ? "*" : "LOCALHOST") : |
"LOCALHOST" : options.remote_forwards[i].listen_host, |
options.remote_forwards[i].listen_host, |
|
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_port); |
options.remote_forwards[i].connect_port); |
channel_request_remote_forwarding( |
if (channel_request_remote_forwarding( |
options.remote_forwards[i].listen_host, |
options.remote_forwards[i].listen_host, |
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_port); |
options.remote_forwards[i].connect_port) < 0) { |
|
if (options.exit_on_forward_failure) |
|
fatal("Could not request remote forwarding."); |
|
else |
|
logit("Warning: Could not request remote " |
|
"forwarding."); |
|
} |
} |
} |
} |
} |
|
|
|
|
check_agent_present(void) |
check_agent_present(void) |
{ |
{ |
if (options.forward_agent) { |
if (options.forward_agent) { |
/* Clear agent forwarding if we don\'t have an agent. */ |
/* Clear agent forwarding if we don't have an agent. */ |
if (!ssh_agent_present()) |
if (!ssh_agent_present()) |
options.forward_agent = 0; |
options.forward_agent = 0; |
} |
} |
|
|
/* Store window size in the packet. */ |
/* Store window size in the packet. */ |
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) |
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) |
memset(&ws, 0, sizeof(ws)); |
memset(&ws, 0, sizeof(ws)); |
packet_put_int(ws.ws_row); |
packet_put_int((u_int)ws.ws_row); |
packet_put_int(ws.ws_col); |
packet_put_int((u_int)ws.ws_col); |
packet_put_int(ws.ws_xpixel); |
packet_put_int((u_int)ws.ws_xpixel); |
packet_put_int(ws.ws_ypixel); |
packet_put_int((u_int)ws.ws_ypixel); |
|
|
/* Store tty modes in the packet. */ |
/* Store tty modes in the packet. */ |
tty_make_modes(fileno(stdin), NULL); |
tty_make_modes(fileno(stdin), NULL); |
|
|
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].listen_port, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_host, |
options.remote_forwards[i].connect_port); |
options.remote_forwards[i].connect_port); |
if (type == SSH2_MSG_REQUEST_FAILURE) |
if (type == SSH2_MSG_REQUEST_FAILURE) { |
logit("Warning: remote port forwarding failed for listen " |
if (options.exit_on_forward_failure) |
"port %d", options.remote_forwards[i].listen_port); |
fatal("Error: remote port forwarding failed for " |
|
"listen port %d", |
|
options.remote_forwards[i].listen_port); |
|
else |
|
logit("Warning: remote port forwarding failed for " |
|
"listen port %d", |
|
options.remote_forwards[i].listen_port); |
|
} |
} |
} |
|
|
static void |
static void |
|
|
fatal("ControlPath too long"); |
fatal("ControlPath too long"); |
|
|
if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
if ((control_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
fatal("%s socket(): %s\n", __func__, strerror(errno)); |
fatal("%s socket(): %s", __func__, strerror(errno)); |
|
|
old_umask = umask(0177); |
old_umask = umask(0177); |
if (bind(control_fd, (struct sockaddr*)&addr, addr.sun_len) == -1) { |
if (bind(control_fd, (struct sockaddr *)&addr, addr.sun_len) == -1) { |
control_fd = -1; |
control_fd = -1; |
if (errno == EINVAL || errno == EADDRINUSE) |
if (errno == EINVAL || errno == EADDRINUSE) |
fatal("ControlSocket %s already exists", |
fatal("ControlSocket %s already exists", |
options.control_path); |
options.control_path); |
else |
else |
fatal("%s bind(): %s\n", __func__, strerror(errno)); |
fatal("%s bind(): %s", __func__, strerror(errno)); |
} |
} |
umask(old_umask); |
umask(old_umask); |
|
|
if (listen(control_fd, 64) == -1) |
if (listen(control_fd, 64) == -1) |
fatal("%s listen(): %s\n", __func__, strerror(errno)); |
fatal("%s listen(): %s", __func__, strerror(errno)); |
|
|
set_nonblock(control_fd); |
set_nonblock(control_fd); |
} |
} |
|
|
packet_send(); |
packet_send(); |
} |
} |
|
|
|
if (options.tun_open != SSH_TUNMODE_NO) { |
|
Channel *c; |
|
int fd; |
|
|
|
debug("Requesting tun."); |
|
if ((fd = tun_open(options.tun_local, |
|
options.tun_open)) >= 0) { |
|
c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
|
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
|
0, "tun", 1); |
|
c->datagram = 1; |
|
packet_start(SSH2_MSG_CHANNEL_OPEN); |
|
packet_put_cstring("tun@openssh.com"); |
|
packet_put_int(c->self); |
|
packet_put_int(c->local_window_max); |
|
packet_put_int(c->local_maxpacket); |
|
packet_put_int(options.tun_open); |
|
packet_put_int(options.tun_remote); |
|
packet_send(); |
|
} |
|
} |
|
|
client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), |
client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), |
NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); |
NULL, fileno(stdin), &command, environ, &ssh_subsystem_reply); |
|
|
|
|
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
id = ssh_session2_open(); |
id = ssh_session2_open(); |
|
|
|
/* Execute a local command */ |
|
if (options.local_command != NULL && |
|
options.permit_local_command) |
|
ssh_local_cmd(options.local_command); |
|
|
/* If requested, let ssh continue in the background. */ |
/* If requested, let ssh continue in the background. */ |
if (fork_after_authentication_flag) |
if (fork_after_authentication_flag) |
if (daemon(1, 1) < 0) |
if (daemon(1, 1) < 0) |
|
|
static void |
static void |
load_public_identity_files(void) |
load_public_identity_files(void) |
{ |
{ |
char *filename; |
char *filename, *cp, thishost[NI_MAXHOST]; |
int i = 0; |
int i = 0; |
Key *public; |
Key *public; |
|
struct passwd *pw; |
#ifdef SMARTCARD |
#ifdef SMARTCARD |
Key **keys; |
Key **keys; |
|
|
if (options.smartcard_device != NULL && |
if (options.smartcard_device != NULL && |
options.num_identity_files < SSH_MAX_IDENTITY_FILES && |
options.num_identity_files < SSH_MAX_IDENTITY_FILES && |
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) { |
(keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) { |
int count = 0; |
int count = 0; |
for (i = 0; keys[i] != NULL; i++) { |
for (i = 0; keys[i] != NULL; i++) { |
count++; |
count++; |
|
|
xfree(keys); |
xfree(keys); |
} |
} |
#endif /* SMARTCARD */ |
#endif /* SMARTCARD */ |
|
if ((pw = getpwuid(original_real_uid)) == NULL) |
|
fatal("load_public_identity_files: getpwuid failed"); |
|
if (gethostname(thishost, sizeof(thishost)) == -1) |
|
fatal("load_public_identity_files: gethostname: %s", |
|
strerror(errno)); |
for (; i < options.num_identity_files; i++) { |
for (; i < options.num_identity_files; i++) { |
filename = tilde_expand_filename(options.identity_files[i], |
cp = tilde_expand_filename(options.identity_files[i], |
original_real_uid); |
original_real_uid); |
|
filename = percent_expand(cp, "d", pw->pw_dir, |
|
"u", pw->pw_name, "l", thishost, "h", host, |
|
"r", options.user, (char *)NULL); |
|
xfree(cp); |
public = key_load_public(filename, NULL); |
public = key_load_public(filename, NULL); |
debug("identity file %s type %d", filename, |
debug("identity file %s type %d", filename, |
public ? public->type : -1); |
public ? public->type : -1); |
|
|
static int |
static int |
env_permitted(char *env) |
env_permitted(char *env) |
{ |
{ |
int i; |
int i, ret; |
char name[1024], *cp; |
char name[1024], *cp; |
|
|
strlcpy(name, env, sizeof(name)); |
if ((cp = strchr(env, '=')) == NULL || cp == env) |
if ((cp = strchr(name, '=')) == NULL) |
|
return (0); |
return (0); |
|
ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env); |
|
if (ret <= 0 || (size_t)ret >= sizeof(name)) |
|
fatal("env_permitted: name '%.100s...' too long", env); |
|
|
*cp = '\0'; |
|
|
|
for (i = 0; i < options.num_send_env; i++) |
for (i = 0; i < options.num_send_env; i++) |
if (match_pattern(name, options.send_env[i])) |
if (match_pattern(name, options.send_env[i])) |
return (1); |
return (1); |
|
|
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
fatal("%s socket(): %s", __func__, strerror(errno)); |
fatal("%s socket(): %s", __func__, strerror(errno)); |
|
|
if (connect(sock, (struct sockaddr*)&addr, addr.sun_len) == -1) { |
if (connect(sock, (struct sockaddr *)&addr, addr.sun_len) == -1) { |
if (mux_command != SSHMUX_COMMAND_OPEN) { |
if (mux_command != SSHMUX_COMMAND_OPEN) { |
fatal("Control socket connect(%.100s): %s", path, |
fatal("Control socket connect(%.100s): %s", path, |
strerror(errno)); |
strerror(errno)); |
} |
} |
if (errno == ENOENT) |
if (errno == ENOENT) |
debug("Control socket \"%.100s\" does not exist", path); |
debug("Control socket \"%.100s\" does not exist", path); |
else { |
else { |
error("Control socket connect(%.100s): %s", path, |
error("Control socket connect(%.100s): %s", path, |
strerror(errno)); |
strerror(errno)); |
} |
} |
close(sock); |
close(sock); |
return; |
return; |
} |
} |
|
|
if (stdin_null_flag) { |
if (stdin_null_flag) { |
if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) |
if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) |
fatal("open(/dev/null): %s", strerror(errno)); |
fatal("open(/dev/null): %s", strerror(errno)); |
if (dup2(fd, STDIN_FILENO) == -1) |
if (dup2(fd, STDIN_FILENO) == -1) |
fatal("dup2: %s", strerror(errno)); |
fatal("dup2: %s", strerror(errno)); |
if (fd > STDERR_FILENO) |
if (fd > STDERR_FILENO) |
close(fd); |
close(fd); |
} |
} |
|
|
term = getenv("TERM"); |
term = getenv("TERM"); |
|
|