version 1.116, 2001/04/17 12:55:04 |
version 1.116.2.2, 2001/11/15 00:15:19 |
|
|
#include "mac.h" |
#include "mac.h" |
#include "sshtty.h" |
#include "sshtty.h" |
|
|
|
#ifdef SMARTCARD |
|
#include <openssl/engine.h> |
|
#include "scard.h" |
|
#endif |
|
|
extern char *__progname; |
extern char *__progname; |
|
|
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. |
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. |
|
|
*/ |
*/ |
Options options; |
Options options; |
|
|
|
/* optional user configfile */ |
|
char *config = NULL; |
|
|
/* |
/* |
* Name of the host we are connecting to. This is the name given on the |
* Name of the host we are connecting to. This is the name given on the |
* command line, or the HostName specified for the user-supplied name in a |
* command line, or the HostName specified for the user-supplied name in a |
|
|
|
|
/* Prints a help message to the user. This function never returns. */ |
/* Prints a help message to the user. This function never returns. */ |
|
|
void |
static void |
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, "Usage: %s [options] host [command]\n", __progname); |
fprintf(stderr, "Usage: %s [options] host [command]\n", __progname); |
fprintf(stderr, "Options:\n"); |
fprintf(stderr, "Options:\n"); |
fprintf(stderr, " -l user Log in using this user name.\n"); |
fprintf(stderr, " -l user Log in using this user name.\n"); |
fprintf(stderr, " -n Redirect input from " _PATH_DEVNULL ".\n"); |
fprintf(stderr, " -n Redirect input from " _PATH_DEVNULL ".\n"); |
|
fprintf(stderr, " -F config Config file (default: ~/%s).\n", |
|
_PATH_SSH_USER_CONFFILE); |
fprintf(stderr, " -A Enable authentication agent forwarding.\n"); |
fprintf(stderr, " -A Enable authentication agent forwarding.\n"); |
fprintf(stderr, " -a Disable authentication agent forwarding.\n"); |
fprintf(stderr, " -a Disable authentication agent forwarding (default).\n"); |
#ifdef AFS |
#ifdef AFS |
fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); |
fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); |
#endif /* AFS */ |
#endif /* AFS */ |
fprintf(stderr, " -X Enable X11 connection forwarding.\n"); |
fprintf(stderr, " -X Enable X11 connection forwarding.\n"); |
fprintf(stderr, " -x Disable X11 connection forwarding.\n"); |
fprintf(stderr, " -x Disable X11 connection forwarding (default).\n"); |
fprintf(stderr, " -i file Identity for public key authentication " |
fprintf(stderr, " -i file Identity for public key authentication " |
"(default: ~/.ssh/identity)\n"); |
"(default: ~/.ssh/identity)\n"); |
|
#ifdef SMARTCARD |
|
fprintf(stderr, " -I reader Set smartcard reader.\n"); |
|
#endif |
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n"); |
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n"); |
fprintf(stderr, " -T Do not allocate a tty.\n"); |
fprintf(stderr, " -T Do not allocate a tty.\n"); |
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); |
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n"); |
|
|
fprintf(stderr, " -f Fork into background after authentication.\n"); |
fprintf(stderr, " -f Fork into background after authentication.\n"); |
fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n"); |
fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n"); |
|
|
fprintf(stderr, " -c cipher Select encryption algorithm: " |
fprintf(stderr, " -c cipher Select encryption algorithm\n"); |
"``3des'', ``blowfish''\n"); |
|
fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\n"); |
fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\n"); |
fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n"); |
fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n"); |
fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n"); |
fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n"); |
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); |
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); |
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname); |
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname); |
fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); |
fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); |
|
fprintf(stderr, " -D port Enable dynamic application-level port forwarding.\n"); |
fprintf(stderr, " -C Enable compression.\n"); |
fprintf(stderr, " -C Enable compression.\n"); |
fprintf(stderr, " -N Do not execute a shell or command.\n"); |
fprintf(stderr, " -N Do not execute a shell or command.\n"); |
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); |
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n"); |
|
|
fprintf(stderr, " -6 Use IPv6 only.\n"); |
fprintf(stderr, " -6 Use IPv6 only.\n"); |
fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n"); |
fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n"); |
fprintf(stderr, " -s Invoke command (mandatory) as SSH2 subsystem.\n"); |
fprintf(stderr, " -s Invoke command (mandatory) as SSH2 subsystem.\n"); |
|
fprintf(stderr, " -b addr Local IP address.\n"); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
* Connects to the given host using rsh (or prints an error message and exits |
* Connects to the given host using rsh (or prints an error message and exits |
* if rsh is not available). This function never returns. |
* if rsh is not available). This function never returns. |
*/ |
*/ |
void |
static void |
rsh_connect(char *host, char *user, Buffer * command) |
rsh_connect(char *host, char *user, Buffer * command) |
{ |
{ |
char *args[10]; |
char *args[10]; |
|
|
exit(1); |
exit(1); |
} |
} |
|
|
int ssh_session(void); |
static int ssh_session(void); |
int ssh_session2(void); |
static int ssh_session2(void); |
void load_public_identity_files(void); |
static void load_public_identity_files(void); |
|
|
/* |
/* |
* Main program for the ssh client. |
* Main program for the ssh client. |
|
|
int |
int |
main(int ac, char **av) |
main(int ac, char **av) |
{ |
{ |
int i, opt, optind, exit_status, ok; |
int i, opt, exit_status, cerr; |
u_short fwd_port, fwd_host_port; |
u_short fwd_port, fwd_host_port; |
char *optarg, *cp, buf[256]; |
char sfwd_port[6], sfwd_host_port[6]; |
|
char *p, *cp, buf[256]; |
struct stat st; |
struct stat st; |
struct passwd *pw; |
struct passwd *pw; |
int dummy; |
int dummy; |
uid_t original_effective_uid; |
uid_t original_effective_uid; |
|
extern int optind, optreset; |
|
extern char *optarg; |
|
|
/* |
/* |
* Save the original real uid. It will be needed later (uid-swapping |
* Save the original real uid. It will be needed later (uid-swapping |
|
|
/* Parse command-line arguments. */ |
/* Parse command-line arguments. */ |
host = NULL; |
host = NULL; |
|
|
for (optind = 1; optind < ac; optind++) { |
again: |
if (av[optind][0] != '-') { |
while ((opt = getopt(ac, av, |
if (host) |
"1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) { |
break; |
|
if ((cp = strchr(av[optind], '@'))) { |
|
if(cp == av[optind]) |
|
usage(); |
|
options.user = av[optind]; |
|
*cp = '\0'; |
|
host = ++cp; |
|
} else |
|
host = av[optind]; |
|
continue; |
|
} |
|
opt = av[optind][1]; |
|
if (!opt) |
|
usage(); |
|
if (strchr("eilcmpLRDo", opt)) { /* options with arguments */ |
|
optarg = av[optind] + 2; |
|
if (strcmp(optarg, "") == 0) { |
|
if (optind >= ac - 1) |
|
usage(); |
|
optarg = av[++optind]; |
|
} |
|
} else { |
|
if (av[optind][2]) |
|
usage(); |
|
optarg = NULL; |
|
} |
|
switch (opt) { |
switch (opt) { |
case '1': |
case '1': |
options.protocol = SSH_PROTO_1; |
options.protocol = SSH_PROTO_1; |
|
|
#endif |
#endif |
case 'i': |
case 'i': |
if (stat(optarg, &st) < 0) { |
if (stat(optarg, &st) < 0) { |
fprintf(stderr, "Warning: Identity file %s does not exist.\n", |
fprintf(stderr, "Warning: Identity file %s " |
optarg); |
"does not exist.\n", optarg); |
break; |
break; |
} |
} |
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) |
if (options.num_identity_files >= |
fatal("Too many identity files specified (max %d)", |
SSH_MAX_IDENTITY_FILES) |
SSH_MAX_IDENTITY_FILES); |
fatal("Too many identity files specified " |
options.identity_files[options.num_identity_files++] = xstrdup(optarg); |
"(max %d)", SSH_MAX_IDENTITY_FILES); |
|
options.identity_files[options.num_identity_files++] = |
|
xstrdup(optarg); |
break; |
break; |
|
case 'I': |
|
#ifdef SMARTCARD |
|
options.smartcard_device = xstrdup(optarg); |
|
#else |
|
fprintf(stderr, "no support for smartcards.\n"); |
|
#endif |
|
break; |
case 't': |
case 't': |
if (tty_flag) |
if (tty_flag) |
force_tty_flag = 1; |
force_tty_flag = 1; |
|
|
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { |
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { |
options.log_level++; |
options.log_level++; |
break; |
break; |
} else { |
} else |
fatal("Too high debugging level."); |
fatal("Too high debugging level."); |
} |
|
/* fallthrough */ |
/* fallthrough */ |
case 'V': |
case 'V': |
fprintf(stderr, |
fprintf(stderr, |
|
|
break; |
break; |
case 'e': |
case 'e': |
if (optarg[0] == '^' && optarg[2] == 0 && |
if (optarg[0] == '^' && optarg[2] == 0 && |
(u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128) |
(u_char) optarg[1] >= 64 && |
|
(u_char) optarg[1] < 128) |
options.escape_char = (u_char) optarg[1] & 31; |
options.escape_char = (u_char) optarg[1] & 31; |
else if (strlen(optarg) == 1) |
else if (strlen(optarg) == 1) |
options.escape_char = (u_char) optarg[0]; |
options.escape_char = (u_char) optarg[0]; |
else if (strcmp(optarg, "none") == 0) |
else if (strcmp(optarg, "none") == 0) |
options.escape_char = -2; |
options.escape_char = SSH_ESCAPECHAR_NONE; |
else { |
else { |
fprintf(stderr, "Bad escape character '%s'.\n", optarg); |
fprintf(stderr, "Bad escape character '%s'.\n", |
|
optarg); |
exit(1); |
exit(1); |
} |
} |
break; |
break; |
|
|
/* SSH1 only */ |
/* SSH1 only */ |
options.cipher = cipher_number(optarg); |
options.cipher = cipher_number(optarg); |
if (options.cipher == -1) { |
if (options.cipher == -1) { |
fprintf(stderr, "Unknown cipher type '%s'\n", optarg); |
fprintf(stderr, |
|
"Unknown cipher type '%s'\n", |
|
optarg); |
exit(1); |
exit(1); |
} |
} |
if (options.cipher == SSH_CIPHER_3DES) { |
if (options.cipher == SSH_CIPHER_3DES) |
options.ciphers = "3des-cbc"; |
options.ciphers = "3des-cbc"; |
} else if (options.cipher == SSH_CIPHER_BLOWFISH) { |
else if (options.cipher == SSH_CIPHER_BLOWFISH) |
options.ciphers = "blowfish-cbc"; |
options.ciphers = "blowfish-cbc"; |
} else { |
else |
options.ciphers = (char *)-1; |
options.ciphers = (char *)-1; |
} |
|
} |
} |
break; |
break; |
case 'm': |
case 'm': |
if (mac_valid(optarg)) |
if (mac_valid(optarg)) |
options.macs = xstrdup(optarg); |
options.macs = xstrdup(optarg); |
else { |
else { |
fprintf(stderr, "Unknown mac type '%s'\n", optarg); |
fprintf(stderr, "Unknown mac type '%s'\n", |
|
optarg); |
exit(1); |
exit(1); |
} |
} |
break; |
break; |
|
|
case 'l': |
case 'l': |
options.user = optarg; |
options.user = optarg; |
break; |
break; |
|
|
|
case 'L': |
case 'R': |
case 'R': |
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf, |
if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]", |
&fwd_host_port) != 3 && |
sfwd_port, buf, sfwd_host_port) != 3 && |
sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, |
sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]", |
&fwd_host_port) != 3) { |
sfwd_port, buf, sfwd_host_port) != 3) { |
fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); |
fprintf(stderr, |
|
"Bad forwarding specification '%s'\n", |
|
optarg); |
usage(); |
usage(); |
/* NOTREACHED */ |
/* NOTREACHED */ |
} |
} |
add_remote_forward(&options, fwd_port, buf, fwd_host_port); |
if ((fwd_port = a2port(sfwd_port)) == 0 || |
break; |
(fwd_host_port = a2port(sfwd_host_port)) == 0) { |
case 'L': |
fprintf(stderr, |
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf, |
"Bad forwarding port(s) '%s'\n", optarg); |
&fwd_host_port) != 3 && |
exit(1); |
sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf, |
|
&fwd_host_port) != 3) { |
|
fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg); |
|
usage(); |
|
/* NOTREACHED */ |
|
} |
} |
add_local_forward(&options, fwd_port, buf, fwd_host_port); |
if (opt == 'L') |
|
add_local_forward(&options, fwd_port, buf, |
|
fwd_host_port); |
|
else if (opt == 'R') |
|
add_remote_forward(&options, fwd_port, buf, |
|
fwd_host_port); |
break; |
break; |
|
|
case 'D': |
case 'D': |
fwd_port = a2port(optarg); |
fwd_port = a2port(optarg); |
if (fwd_port == 0) { |
if (fwd_port == 0) { |
fprintf(stderr, "Bad dynamic port '%s'\n", optarg); |
fprintf(stderr, "Bad dynamic port '%s'\n", |
|
optarg); |
exit(1); |
exit(1); |
} |
} |
add_local_forward(&options, fwd_port, "socks4", 0); |
add_local_forward(&options, fwd_port, "socks4", 0); |
|
|
break; |
break; |
case 'o': |
case 'o': |
dummy = 1; |
dummy = 1; |
if (process_config_line(&options, host ? host : "", optarg, |
if (process_config_line(&options, host ? host : "", |
"command-line", 0, &dummy) != 0) |
optarg, "command-line", 0, &dummy) != 0) |
exit(1); |
exit(1); |
break; |
break; |
case 's': |
case 's': |
subsystem_flag = 1; |
subsystem_flag = 1; |
break; |
break; |
|
case 'b': |
|
options.bind_address = optarg; |
|
break; |
|
case 'F': |
|
config = optarg; |
|
break; |
default: |
default: |
usage(); |
usage(); |
} |
} |
} |
} |
|
|
|
ac -= optind; |
|
av += optind; |
|
|
|
if (ac > 0 && !host && **av != '-') { |
|
if (strchr(*av, '@')) { |
|
p = xstrdup(*av); |
|
cp = strchr(p, '@'); |
|
if (cp == NULL || cp == p) |
|
usage(); |
|
options.user = p; |
|
*cp = '\0'; |
|
host = ++cp; |
|
} else |
|
host = *av; |
|
ac--, av++; |
|
if (ac > 0) { |
|
optind = 0; |
|
optreset = 1; |
|
goto again; |
|
} |
|
} |
|
|
/* Check that we got a host name. */ |
/* Check that we got a host name. */ |
if (!host) |
if (!host) |
usage(); |
usage(); |
|
|
SSLeay_add_all_algorithms(); |
SSLeay_add_all_algorithms(); |
ERR_load_crypto_strings(); |
ERR_load_crypto_strings(); |
|
channel_set_af(IPv4or6); |
|
|
/* Initialize the command to execute on remote host. */ |
/* Initialize the command to execute on remote host. */ |
buffer_init(&command); |
buffer_init(&command); |
|
|
* is no limit on the length of the command, except by the maximum |
* is no limit on the length of the command, except by the maximum |
* packet size. Also sets the tty flag if there is no command. |
* packet size. Also sets the tty flag if there is no command. |
*/ |
*/ |
if (optind == ac) { |
if (!ac) { |
/* No command specified - execute shell on a tty. */ |
/* No command specified - execute shell on a tty. */ |
tty_flag = 1; |
tty_flag = 1; |
if (subsystem_flag) { |
if (subsystem_flag) { |
fprintf(stderr, "You must specify a subsystem to invoke.\n"); |
fprintf(stderr, |
|
"You must specify a subsystem to invoke.\n"); |
usage(); |
usage(); |
} |
} |
} else { |
} else { |
/* A command has been specified. Store it into the |
/* A command has been specified. Store it into the buffer. */ |
buffer. */ |
for (i = 0; i < ac; i++) { |
for (i = optind; i < ac; i++) { |
if (i) |
if (i > optind) |
|
buffer_append(&command, " ", 1); |
buffer_append(&command, " ", 1); |
buffer_append(&command, av[i], strlen(av[i])); |
buffer_append(&command, av[i], strlen(av[i])); |
} |
} |
|
|
log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, |
log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, |
SYSLOG_FACILITY_USER, 1); |
SYSLOG_FACILITY_USER, 1); |
|
|
/* Read per-user configuration file. */ |
/* |
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); |
* Read per-user configuration file. Ignore the system wide config |
read_config_file(buf, host, &options); |
* file if the user specifies a config file on the command line. |
|
*/ |
|
if (config != NULL) { |
|
if (!read_config_file(config, host, &options)) |
|
fatal("Can't open user config file %.100s: " |
|
"%.100s", config, strerror(errno)); |
|
} else { |
|
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, |
|
_PATH_SSH_USER_CONFFILE); |
|
(void)read_config_file(buf, host, &options); |
|
|
/* Read systemwide configuration file. */ |
/* Read systemwide configuration file after use config. */ |
read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); |
(void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); |
|
} |
|
|
/* Fill configuration defaults. */ |
/* Fill configuration defaults. */ |
fill_default_options(&options); |
fill_default_options(&options); |
|
|
|
|
/* Open a connection to the remote host. */ |
/* Open a connection to the remote host. */ |
|
|
ok = ssh_connect(host, &hostaddr, options.port, |
cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6, |
options.connection_attempts, |
options.connection_attempts, |
original_effective_uid != 0 || !options.use_privileged_port, |
original_effective_uid != 0 || !options.use_privileged_port, |
pw, options.proxy_command); |
pw, options.proxy_command); |
|
|
*/ |
*/ |
sensitive_data.nkeys = 0; |
sensitive_data.nkeys = 0; |
sensitive_data.keys = NULL; |
sensitive_data.keys = NULL; |
if (ok && (options.rhosts_rsa_authentication || |
if (!cerr && (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*sizeof(Key)); |
sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key)); |
|
|
* 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/%.100s", 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) |
if (mkdir(buf, 0700) < 0) |
if (mkdir(buf, 0700) < 0) |
error("Could not create directory '%.200s'.", buf); |
error("Could not create directory '%.200s'.", buf); |
|
|
/* Check if the connection failed, and try "rsh" if appropriate. */ |
/* Check if the connection failed, and try "rsh" if appropriate. */ |
if (!ok) { |
if (cerr) { |
|
if (!options.fallback_to_rsh) |
|
exit(1); |
if (options.port != 0) |
if (options.port != 0) |
log("Secure connection to %.100s on port %hu refused%.100s.", |
log("Secure connection to %.100s on port %hu refused; " |
host, options.port, |
"reverting to insecure method", |
options.fallback_to_rsh ? "; reverting to insecure method" : ""); |
host, options.port); |
else |
else |
log("Secure connection to %.100s refused%.100s.", host, |
log("Secure connection to %.100s refused; " |
options.fallback_to_rsh ? "; reverting to insecure method" : ""); |
"reverting to insecure method.", host); |
|
|
if (options.fallback_to_rsh) { |
rsh_connect(host, options.user, &command); |
rsh_connect(host, options.user, &command); |
fatal("rsh_connect returned"); |
fatal("rsh_connect returned"); |
|
} |
|
exit(1); |
|
} |
} |
/* load options.identity_files */ |
/* load options.identity_files */ |
load_public_identity_files(); |
load_public_identity_files(); |
|
|
} |
} |
xfree(sensitive_data.keys); |
xfree(sensitive_data.keys); |
} |
} |
|
for (i = 0; i < options.num_identity_files; i++) { |
|
if (options.identity_files[i]) { |
|
xfree(options.identity_files[i]); |
|
options.identity_files[i] = NULL; |
|
} |
|
if (options.identity_keys[i]) { |
|
key_free(options.identity_keys[i]); |
|
options.identity_keys[i] = NULL; |
|
} |
|
} |
|
|
exit_status = compat20 ? ssh_session2() : ssh_session(); |
exit_status = compat20 ? ssh_session2() : ssh_session(); |
packet_close(); |
packet_close(); |
return exit_status; |
return exit_status; |
} |
} |
|
|
void |
static void |
x11_get_proto(char *proto, int proto_len, char *data, int data_len) |
x11_get_proto(char *proto, int proto_len, char *data, int data_len) |
{ |
{ |
char line[512]; |
char line[512]; |
|
|
} |
} |
} |
} |
|
|
void |
static void |
ssh_init_forwarding(void) |
ssh_init_forwarding(void) |
{ |
{ |
int success = 0; |
int success = 0; |
|
|
} |
} |
} |
} |
|
|
void |
static void |
check_agent_present(void) |
check_agent_present(void) |
{ |
{ |
if (options.forward_agent) { |
if (options.forward_agent) { |
|
|
} |
} |
} |
} |
|
|
int |
static int |
ssh_session(void) |
ssh_session(void) |
{ |
{ |
int type; |
int type; |
|
|
cp = getenv("TERM"); |
cp = getenv("TERM"); |
if (!cp) |
if (!cp) |
cp = ""; |
cp = ""; |
packet_put_string(cp, strlen(cp)); |
packet_put_cstring(cp); |
|
|
/* 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) |
|
|
} |
} |
|
|
/* Enter the interactive session. */ |
/* Enter the interactive session. */ |
return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); |
return client_loop(have_tty, tty_flag ? |
|
options.escape_char : SSH_ESCAPECHAR_NONE, 0); |
} |
} |
|
|
void |
static void |
client_subsystem_reply(int type, int plen, void *ctxt) |
client_subsystem_reply(int type, int plen, void *ctxt) |
{ |
{ |
int id, len; |
int id, len; |
|
|
len, buffer_ptr(&command), id); |
len, buffer_ptr(&command), id); |
} |
} |
|
|
void |
/* request pty/x11/agent/tcpfwd/shell for channel */ |
ssh_session2_callback(int id, void *arg) |
static void |
|
ssh_session2_setup(int id, void *arg) |
{ |
{ |
int len; |
int len; |
int interactive = 0; |
int interactive = 0; |
struct termios tio; |
struct termios tio; |
|
|
debug("client_init id %d arg %ld", id, (long)arg); |
debug("ssh_session2_setup: id %d", id); |
|
|
if (tty_flag) { |
if (tty_flag) { |
struct winsize ws; |
struct winsize ws; |
|
|
packet_set_interactive(interactive); |
packet_set_interactive(interactive); |
} |
} |
|
|
int |
/* open new channel for a session */ |
ssh_session2_command(void) |
static int |
|
ssh_session2_open(void) |
{ |
{ |
int id, window, packetmax; |
Channel *c; |
int in, out, err; |
int window, packetmax, in, out, err; |
|
|
if (stdin_null_flag) { |
if (stdin_null_flag) { |
in = open(_PATH_DEVNULL, O_RDONLY); |
in = open(_PATH_DEVNULL, O_RDONLY); |
|
|
window *= 2; |
window *= 2; |
packetmax *=2; |
packetmax *=2; |
} |
} |
id = channel_new( |
c = channel_new( |
"session", SSH_CHANNEL_OPENING, in, out, err, |
"session", SSH_CHANNEL_OPENING, in, out, err, |
window, packetmax, CHAN_EXTENDED_WRITE, |
window, packetmax, CHAN_EXTENDED_WRITE, |
xstrdup("client-session"), /*nonblock*/0); |
xstrdup("client-session"), /*nonblock*/0); |
|
if (c == NULL) |
|
fatal("ssh_session2_open: channel_new failed"); |
|
|
debug("channel_new: %d", id); |
debug3("ssh_session2_open: channel_new: %d", c->self); |
|
|
channel_open(id); |
channel_send_open(c->self); |
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, |
if (!no_shell_flag) |
ssh_session2_callback, (void *)0); |
channel_register_callback(c->self, |
|
SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, |
|
ssh_session2_setup, (void *)0); |
|
|
return id; |
return c->self; |
} |
} |
|
|
int |
static int |
ssh_session2(void) |
ssh_session2(void) |
{ |
{ |
int id; |
int id = -1; |
|
|
/* XXX should be pre-session */ |
/* XXX should be pre-session */ |
ssh_init_forwarding(); |
ssh_init_forwarding(); |
|
|
id = no_shell_flag ? -1 : ssh_session2_command(); |
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
|
id = ssh_session2_open(); |
|
|
/* 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) |
fatal("daemon() failed: %.200s", strerror(errno)); |
fatal("daemon() failed: %.200s", strerror(errno)); |
|
|
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); |
return client_loop(tty_flag, tty_flag ? |
|
options.escape_char : SSH_ESCAPECHAR_NONE, id); |
} |
} |
|
|
void |
static void |
load_public_identity_files(void) |
load_public_identity_files(void) |
{ |
{ |
char *filename; |
char *filename; |
Key *public; |
Key *public; |
int i; |
int i = 0; |
|
|
for (i = 0; i < options.num_identity_files; i++) { |
#ifdef SMARTCARD |
|
if (options.smartcard_device != NULL && |
|
options.num_identity_files + 1 < SSH_MAX_IDENTITY_FILES && |
|
(public = sc_get_key(options.smartcard_device)) != NULL ) { |
|
Key *new; |
|
|
|
if (options.num_identity_files + 2 > SSH_MAX_IDENTITY_FILES) |
|
options.num_identity_files = SSH_MAX_IDENTITY_FILES - 2; |
|
memmove(&options.identity_files[2], &options.identity_files[0], |
|
sizeof(char *) * options.num_identity_files); |
|
options.num_identity_files += 2; |
|
i = 2; |
|
|
|
/* XXX ssh1 vs ssh2 */ |
|
new = key_new(KEY_RSA); |
|
new->flags = KEY_FLAG_EXT; |
|
BN_copy(new->rsa->n, public->rsa->n); |
|
BN_copy(new->rsa->e, public->rsa->e); |
|
RSA_set_method(new->rsa, sc_get_engine()); |
|
options.identity_keys[0] = new; |
|
options.identity_files[0] = xstrdup("smartcard rsa key");; |
|
|
|
new = key_new(KEY_RSA1); |
|
new->flags = KEY_FLAG_EXT; |
|
BN_copy(new->rsa->n, public->rsa->n); |
|
BN_copy(new->rsa->e, public->rsa->e); |
|
RSA_set_method(new->rsa, sc_get_engine()); |
|
options.identity_keys[1] = new; |
|
options.identity_files[1] = xstrdup("smartcard rsa1 key"); |
|
|
|
key_free(public); |
|
} |
|
#endif /* SMARTCARD */ |
|
for (; i < options.num_identity_files; i++) { |
filename = tilde_expand_filename(options.identity_files[i], |
filename = tilde_expand_filename(options.identity_files[i], |
original_real_uid); |
original_real_uid); |
public = key_load_public(filename, NULL); |
public = key_load_public(filename, NULL); |