*/
#include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.106 2001/04/05 21:05:24 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.117 2001/04/30 11:18:52 markus Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
#include "misc.h"
#include "kex.h"
#include "mac.h"
+#include "sshtty.h"
#ifdef HAVE___PROGNAME
extern char *__progname;
*/
volatile int received_window_change_signal = 0;
-/* Host private key. */
-Key *host_private_key = NULL;
+/* Private host keys. */
+struct {
+ Key **keys;
+ int nkeys;
+} sensitive_data;
/* Original real UID. */
uid_t original_real_uid;
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, " -s Invoke command (mandatory) as SSH2 subsystem.\n");
+ fprintf(stderr, " -b Local IP address.\n");
exit(1);
}
fatal("setrlimit failed: %.100s", strerror(errno));
}
#endif
+ /* Get user data. */
+ pw = getpwuid(original_real_uid);
+ if (!pw) {
+ log("You don't exist, go away!");
+ exit(1);
+ }
+ /* Take a copy of the returned structure. */
+ pw = pwcopy(pw);
+
/*
* Use uid-swapping to give up root privileges for the duration of
* option processing. We will re-instantiate the rights when we are
* them when the port has been created (actually, when the connection
* has been made, as we may need to create the port several times).
*/
- temporarily_use_uid(original_real_uid);
+ temporarily_use_uid(pw);
/*
* Set our umask to something reasonable, as some files are created
opt = av[optind][1];
if (!opt)
usage();
- if (strchr("eilcmpLRo", opt)) { /* options with arguments */
+ if (strchr("eilcmpbLRDo", opt)) { /* options with arguments */
optarg = av[optind] + 2;
if (strcmp(optarg, "") == 0) {
if (optind >= ac - 1)
}
break;
case 'p':
- options.port = atoi(optarg);
+ options.port = a2port(optarg);
+ if (options.port == 0) {
+ fprintf(stderr, "Bad port '%s'\n", optarg);
+ exit(1);
+ }
break;
case 'l':
options.user = optarg;
}
add_local_forward(&options, fwd_port, buf, fwd_host_port);
break;
+
+ case 'D':
+ fwd_port = a2port(optarg);
+ if (fwd_port == 0) {
+ fprintf(stderr, "Bad dynamic port '%s'\n", optarg);
+ exit(1);
+ }
+ add_local_forward(&options, fwd_port, "socks4", 0);
+ break;
+
case 'C':
options.compression = 1;
break;
case 's':
subsystem_flag = 1;
break;
+ case 'b':
+ options.bind_address = optarg;
+ break;
default:
usage();
}
/* No command specified - execute shell on a tty. */
tty_flag = 1;
if (subsystem_flag) {
- fprintf(stderr, "You must specify a subsystem to invoke.");
+ fprintf(stderr, "You must specify a subsystem to invoke.\n");
usage();
}
} else {
tty_flag = 0;
}
- /* Get user data. */
- pw = getpwuid(original_real_uid);
- if (!pw) {
- log("You don't exist, go away!");
- exit(1);
- }
- /* Take a copy of the returned structure. */
- pw = pwcopy(pw);
-
/*
* Initialize "log" output. Since we are the client all output
* actually goes to stderr.
*/
- log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
+ log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
+ SYSLOG_FACILITY_USER, 1);
/* Read per-user configuration file. */
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE);
"originating port will not be trusted.");
options.rhosts_authentication = 0;
}
+
/*
* If using rsh has been selected, exec it now (without trying
* anything else). Note that we must release privileges first.
restore_uid();
/* Switch to the original uid permanently. */
- permanently_set_uid(original_real_uid);
+ permanently_set_uid(pw);
/* Execute rsh. */
rsh_connect(host, options.user, &command);
ok = ssh_connect(host, &hostaddr, options.port,
options.connection_attempts,
original_effective_uid != 0 || !options.use_privileged_port,
- original_real_uid,
- options.proxy_command);
+ pw, options.proxy_command);
/*
* If we successfully made the connection, load the host private key
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
*/
- if (ok && (options.protocol & SSH_PROTO_1)) {
- host_private_key = key_load_private_type(KEY_RSA1,
+ sensitive_data.nkeys = 0;
+ sensitive_data.keys = NULL;
+ if (ok && (options.rhosts_rsa_authentication ||
+ options.hostbased_authentication)) {
+ sensitive_data.nkeys = 3;
+ sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
+ sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
_PATH_HOST_KEY_FILE, "", NULL);
+ sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
+ _PATH_HOST_DSA_KEY_FILE, "", NULL);
+ sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
+ _PATH_HOST_RSA_KEY_FILE, "", NULL);
}
/*
* Get rid of any extra privileges that we may have. We will no
* process, read the private hostkey and impersonate the host.
* OpenBSD does not allow ptracing of setuid processes.
*/
- permanently_set_uid(original_real_uid);
+ permanently_set_uid(pw);
/*
* Now that we are back to our own permissions, create ~/.ssh
tilde_expand_filename(options.user_hostfile2, original_real_uid);
/* Log into the remote system. This never returns if the login fails. */
- ssh_login(host_private_key, host, (struct sockaddr *)&hostaddr,
- original_real_uid);
-
- /* We no longer need the host private key. Clear it now. */
- if (host_private_key != NULL)
- key_free(host_private_key); /* Destroys contents safely */
+ ssh_login(sensitive_data.keys, sensitive_data.nkeys,
+ host, (struct sockaddr *)&hostaddr, pw);
+
+ /* We no longer need the private host keys. Clear them now. */
+ if (sensitive_data.nkeys != 0) {
+ for (i = 0; i < sensitive_data.nkeys; i++) {
+ if (sensitive_data.keys[i] != NULL) {
+ /* Destroys contents safely */
+ debug3("clear hostkey %d", i);
+ key_free(sensitive_data.keys[i]);
+ sensitive_data.keys[i] = NULL;
+ }
+ }
+ xfree(sensitive_data.keys);
+ }
exit_status = compat20 ? ssh_session2() : ssh_session();
packet_close();
packet_put_int(ws.ws_ypixel);
/* Store tty modes in the packet. */
- tty_make_modes(fileno(stdin));
+ tty_make_modes(fileno(stdin), NULL);
/* Send the packet, and wait for it to leave. */
packet_send();
{
int len;
int interactive = 0;
+ struct termios tio;
debug("client_init id %d arg %ld", id, (long)arg);
packet_put_int(ws.ws_row);
packet_put_int(ws.ws_xpixel);
packet_put_int(ws.ws_ypixel);
- packet_put_cstring(""); /* XXX: encode terminal modes */
+ tio = get_saved_tio();
+ tty_make_modes(/*ignored*/ 0, &tio);
packet_send();
interactive = 1;
/* XXX wait for reply */