diff options
author | Damien Miller <djm@mindrot.org> | 2000-04-06 12:32:37 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-04-06 12:32:37 +1000 |
commit | 1383bd8eb91a8ec9c8d283679faec5925b0ccc42 (patch) | |
tree | f71278df6c50983ea3dad850ae79c45c340d9362 | |
parent | 74a333bbe11f67c59c559e0f424d5945eb438577 (diff) |
- OpenBSD CVS update:
- [channels.c]
close efd on eof
- [clientloop.c compat.c ssh.c sshconnect.c myproposal.h]
ssh2 client implementation, interops w/ ssh.com and lsh servers.
- [sshconnect.c]
missing free.
- [authfile.c cipher.c cipher.h packet.c sshconnect.c sshd.c]
remove unused argument, split cipher_mask()
- [clientloop.c]
re-order: group ssh1 vs. ssh2
- Make Redhat spec require openssl >= 0.9.5a
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | authfile.c | 8 | ||||
-rw-r--r-- | channels.c | 10 | ||||
-rw-r--r-- | cipher.c | 24 | ||||
-rw-r--r-- | cipher.h | 8 | ||||
-rw-r--r-- | clientloop.c | 210 | ||||
-rw-r--r-- | compat.c | 6 | ||||
-rw-r--r-- | contrib/redhat/openssh.spec | 4 | ||||
-rw-r--r-- | kex.h | 11 | ||||
-rw-r--r-- | myproposal.h | 20 | ||||
-rw-r--r-- | packet.c | 32 | ||||
-rw-r--r-- | packet.h | 4 | ||||
-rw-r--r-- | ssh.c | 162 | ||||
-rw-r--r-- | sshconnect.c | 350 | ||||
-rw-r--r-- | sshd.c | 4 |
15 files changed, 737 insertions, 130 deletions
@@ -1,3 +1,17 @@ +20000406 + - OpenBSD CVS update: + - [channels.c] + close efd on eof + - [clientloop.c compat.c ssh.c sshconnect.c myproposal.h] + ssh2 client implementation, interops w/ ssh.com and lsh servers. + - [sshconnect.c] + missing free. + - [authfile.c cipher.c cipher.h packet.c sshconnect.c sshd.c] + remove unused argument, split cipher_mask() + - [clientloop.c] + re-order: group ssh1 vs. ssh2 + - Make Redhat spec require openssl >= 0.9.5a + 20000404 - Add tests for RAND_add function when searching for OpenSSL - OpenBSD CVS update: @@ -15,7 +15,7 @@ */ #include "includes.h" -RCSID("$Id: authfile.c,v 1.7 2000/03/02 12:57:18 damien Exp $"); +RCSID("$Id: authfile.c,v 1.8 2000/04/06 02:32:38 damien Exp $"); #ifdef HAVE_OPENSSL #include <openssl/bn.h> @@ -107,7 +107,7 @@ save_private_key(const char *filename, const char *passphrase, /* Allocate space for the private part of the key in the buffer. */ buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); - cipher_set_key_string(&cipher, cipher_type, passphrase, 1); + cipher_set_key_string(&cipher, cipher_type, passphrase); cipher_encrypt(&cipher, (unsigned char *) cp, (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer)); @@ -286,7 +286,7 @@ load_private_key(const char *filename, const char *passphrase, xfree(buffer_get_string(&buffer, NULL)); /* Check that it is a supported cipher. */ - if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & + if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & (1 << cipher_type)) == 0) { debug("Unsupported cipher %.100s used in key file %.200s.", cipher_name(cipher_type), filename); @@ -298,7 +298,7 @@ load_private_key(const char *filename, const char *passphrase, buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - cipher_set_key_string(&cipher, cipher_type, passphrase, 0); + cipher_set_key_string(&cipher, cipher_type, passphrase); cipher_decrypt(&cipher, (unsigned char *) cp, (unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer)); @@ -17,7 +17,7 @@ */ #include "includes.h" -RCSID("$Id: channels.c,v 1.21 2000/04/04 04:39:00 damien Exp $"); +RCSID("$Id: channels.c,v 1.22 2000/04/06 02:32:38 damien Exp $"); #include "ssh.h" #include "packet.h" @@ -642,6 +642,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) char buf[16*1024]; int len; +/** XXX handle drain efd, too */ if (c->efd != -1) { if (c->extended_usage == CHAN_EXTENDED_WRITE && FD_ISSET(c->efd, writeset) && @@ -659,7 +660,12 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) len = read(c->efd, buf, sizeof(buf)); debug("channel %d: read %d from efd %d", c->self, len, c->efd); - if (len > 0) + if (len == 0) { + debug("channel %d: closing efd %d", + c->self, c->efd); + close(c->efd); + c->efd = -1; + } else if (len > 0) buffer_append(&c->extended, buf, len); } } @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$Id: cipher.c,v 1.15 2000/04/01 01:09:23 damien Exp $"); +RCSID("$Id: cipher.c,v 1.16 2000/04/06 02:32:39 damien Exp $"); #include "ssh.h" #include "cipher.h" @@ -137,17 +137,28 @@ static char *cipher_names[] = */ unsigned int -cipher_mask() +cipher_mask1() { unsigned int mask = 0; mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ mask |= 1 << SSH_CIPHER_BLOWFISH; + return mask; +} +unsigned int +cipher_mask2() +{ + unsigned int mask = 0; mask |= 1 << SSH_CIPHER_BLOWFISH_CBC; mask |= 1 << SSH_CIPHER_3DES_CBC; mask |= 1 << SSH_CIPHER_ARCFOUR; mask |= 1 << SSH_CIPHER_CAST128_CBC; return mask; } +unsigned int +cipher_mask() +{ + return cipher_mask1() | cipher_mask2(); +} /* Returns the name of the cipher. */ @@ -182,8 +193,7 @@ cipher_number(const char *name) */ void -cipher_set_key_string(CipherContext *context, int cipher, - const char *passphrase, int for_encryption) +cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase) { MD5_CTX md; unsigned char digest[16]; @@ -192,7 +202,7 @@ cipher_set_key_string(CipherContext *context, int cipher, MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase)); MD5_Final(digest, &md); - cipher_set_key(context, cipher, digest, 16, for_encryption); + cipher_set_key(context, cipher, digest, 16); memset(digest, 0, sizeof(digest)); memset(&md, 0, sizeof(md)); @@ -201,8 +211,8 @@ cipher_set_key_string(CipherContext *context, int cipher, /* Selects the cipher to use and sets the key. */ void -cipher_set_key(CipherContext *context, int cipher, - const unsigned char *key, int keylen, int for_encryption) +cipher_set_key(CipherContext *context, int cipher, const unsigned char *key, + int keylen) { unsigned char padded[32]; @@ -11,7 +11,7 @@ * */ -/* RCSID("$Id: cipher.h,v 1.7 2000/04/01 01:09:23 damien Exp $"); */ +/* RCSID("$Id: cipher.h,v 1.8 2000/04/06 02:32:39 damien Exp $"); */ #ifndef CIPHER_H #define CIPHER_H @@ -76,6 +76,8 @@ typedef struct { * supported cipher. */ unsigned int cipher_mask(); +unsigned int cipher_mask1(); +unsigned int cipher_mask2(); /* Returns the name of the cipher. */ const char *cipher_name(int cipher); @@ -92,7 +94,7 @@ int cipher_number(const char *name); */ void cipher_set_key(CipherContext * context, int cipher, - const unsigned char *key, int keylen, int for_encryption); + const unsigned char *key, int keylen); void cipher_set_key_iv(CipherContext * context, int cipher, const unsigned char *key, int keylen, @@ -104,7 +106,7 @@ cipher_set_key_iv(CipherContext * context, int cipher, */ void cipher_set_key_string(CipherContext * context, int cipher, - const char *passphrase, int for_encryption); + const char *passphrase); /* Encrypts data using the cipher. */ void diff --git a/clientloop.c b/clientloop.c index 1bc6d7e6..4f2e5037 100644 --- a/clientloop.c +++ b/clientloop.c @@ -12,10 +12,11 @@ * * The main loop for the interactive session (client side). * + * SSH2 support added by Markus Friedl. */ #include "includes.h" -RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $"); +RCSID("$Id: clientloop.c,v 1.9 2000/04/06 02:32:39 damien Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -24,6 +25,7 @@ RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $"); #include "authfd.h" #include "readconf.h" +#include "ssh2.h" #include "compat.h" #include "channels.h" #include "dispatch.h" @@ -75,6 +77,10 @@ static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; static int quit_pending; /* Set to non-zero to quit the client loop. */ static int escape_char; /* Escape character. */ + +void client_init_dispatch(void); +int session_ident = -1; + /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ void @@ -273,23 +279,32 @@ client_make_packets_from_stdin_data() void client_check_window_change() { - /* Send possible window change message to the server. */ - if (received_window_change_signal) { - struct winsize ws; - - /* Clear the window change indicator. */ - received_window_change_signal = 0; - - /* Read new window size. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) { - /* Successful, send the packet now. */ - packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int(ws.ws_row); - packet_put_int(ws.ws_col); - packet_put_int(ws.ws_xpixel); - packet_put_int(ws.ws_ypixel); - packet_send(); - } + struct winsize ws; + + if (! received_window_change_signal) + return; + /** XXX race */ + received_window_change_signal = 0; + + if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) + return; + + debug("client_check_window_change: changed"); + + if (compat20) { + channel_request_start(session_ident, "window-change", 0); + packet_put_int(ws.ws_col); + packet_put_int(ws.ws_row); + packet_put_int(ws.ws_xpixel); + packet_put_int(ws.ws_ypixel); + packet_send(); + } else { + packet_start(SSH_CMSG_WINDOW_SIZE); + packet_put_int(ws.ws_row); + packet_put_int(ws.ws_col); + packet_put_int(ws.ws_xpixel); + packet_put_int(ws.ws_ypixel); + packet_send(); } } @@ -301,23 +316,33 @@ client_check_window_change() void client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) { + /*debug("client_wait_until_can_do_something"); */ + /* Initialize select masks. */ FD_ZERO(readset); + FD_ZERO(writeset); - /* Read from the connection, unless our buffers are full. */ - if (buffer_len(&stdout_buffer) < buffer_high && - buffer_len(&stderr_buffer) < buffer_high && - channel_not_very_much_buffered_data()) + if (!compat20) { + /* Read from the connection, unless our buffers are full. */ + if (buffer_len(&stdout_buffer) < buffer_high && + buffer_len(&stderr_buffer) < buffer_high && + channel_not_very_much_buffered_data()) + FD_SET(connection_in, readset); + /* + * Read from stdin, unless we have seen EOF or have very much + * buffered data to send to the server. + */ + if (!stdin_eof && packet_not_very_much_data_to_write()) + FD_SET(fileno(stdin), readset); + + /* Select stdout/stderr if have data in buffer. */ + if (buffer_len(&stdout_buffer) > 0) + FD_SET(fileno(stdout), writeset); + if (buffer_len(&stderr_buffer) > 0) + FD_SET(fileno(stderr), writeset); + } else { FD_SET(connection_in, readset); - - /* - * Read from stdin, unless we have seen EOF or have very much - * buffered data to send to the server. - */ - if (!stdin_eof && packet_not_very_much_data_to_write()) - FD_SET(fileno(stdin), readset); - - FD_ZERO(writeset); + } /* Add any selections by the channel mechanism. */ channel_prepare_select(readset, writeset); @@ -326,14 +351,7 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) if (packet_have_data_to_write()) FD_SET(connection_out, writeset); - /* Select stdout if have data in buffer. */ - if (buffer_len(&stdout_buffer) > 0) - FD_SET(fileno(stdout), writeset); - - /* Select stderr if have data in buffer. */ - if (buffer_len(&stderr_buffer) > 0) - FD_SET(fileno(stderr), writeset); - +/* move UP XXX */ /* Update maximum file descriptor number, if appropriate. */ if (channel_max_fd() > max_fd) max_fd = channel_max_fd(); @@ -408,10 +426,10 @@ client_suspend_self() } void -client_process_input(fd_set * readset) +client_process_net_input(fd_set * readset) { - int len, pid; - char buf[8192], *s; + int len; + char buf[8192]; /* * Read input from the server, and add any such data to the buffer of @@ -420,6 +438,7 @@ client_process_input(fd_set * readset) if (FD_ISSET(connection_in, readset)) { /* Read as much as possible. */ len = read(connection_in, buf, sizeof(buf)); +/*debug("read connection_in len %d", len); XXX */ if (len == 0) { /* Received EOF. The remote host has closed the connection. */ snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", @@ -447,6 +466,14 @@ client_process_input(fd_set * readset) } packet_process_incoming(buf, len); } +} + +void +client_process_input(fd_set * readset) +{ + int len, pid; + char buf[8192], *s; + /* Read input from stdin. */ if (FD_ISSET(fileno(stdin), readset)) { /* Read as much as possible. */ @@ -703,8 +730,6 @@ client_process_buffered_input_packets() * character for terminating or suspending the session. */ -void client_init_dispatch(void); - int client_loop(int have_pty, int escape_char_arg) { @@ -753,7 +778,8 @@ client_loop(int have_pty, int escape_char_arg) enter_raw_mode(); /* Check if we should immediately send of on stdin. */ - client_check_initial_eof_on_stdin(); + if (!compat20) + client_check_initial_eof_on_stdin(); /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { @@ -762,11 +788,17 @@ client_loop(int have_pty, int escape_char_arg) /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(); + if (compat20 && !channel_still_open()) { + debug("!channel_still_open."); + break; + } + /* * Make packets of buffered stdin data, and buffer them for * sending to the server. */ - client_make_packets_from_stdin_data(); + if (!compat20) + client_make_packets_from_stdin_data(); /* * Make packets from buffered channel data, and buffer them @@ -796,17 +828,21 @@ client_loop(int have_pty, int escape_char_arg) /* Do channel operations. */ channel_after_select(&readset, &writeset); - /* - * Process input from the connection and from stdin. Buffer - * any data that is available. - */ - client_process_input(&readset); + /* Buffer input from the connection. */ + client_process_net_input(&readset); - /* - * Process output to stdout and stderr. Output to the - * connection is processed elsewhere (above). - */ - client_process_output(&writeset); + if (quit_pending) + break; + + if (!compat20) { + /* Buffer data from stdin */ + client_process_input(&readset); + /* + * Process output to stdout and stderr. Output to + * the connection is processed elsewhere (above). + */ + client_process_output(&writeset); + } /* Send as much buffered packet data as possible to the sender. */ if (FD_ISSET(connection_out, &writeset)) @@ -918,6 +954,19 @@ client_input_exit_status(int type, int plen) } void +client_init_dispatch_20() +{ + dispatch_init(&dispatch_protocol_error); + dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); + dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); + dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); + dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); + dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); + dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); + dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); + dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); +} +void client_init_dispatch_13() { dispatch_init(NULL); @@ -944,8 +993,55 @@ client_init_dispatch_15() void client_init_dispatch() { - if (compat13) + if (compat20) + client_init_dispatch_20(); + else if (compat13) client_init_dispatch_13(); else client_init_dispatch_15(); } + +void +client_input_channel_req(int id, void *arg) +{ + Channel *c = NULL; + unsigned int len; + int success = 0; + int reply; + char *rtype; + + rtype = packet_get_string(&len); + reply = packet_get_char(); + + log("session_input_channel_req: rtype %s reply %d", rtype, reply); + + c = channel_lookup(id); + if (c == NULL) + fatal("session_input_channel_req: channel %d: bad channel", id); + + if (session_ident == -1) { + error("client_input_channel_req: no channel %d", id); + } else if (id != session_ident) { + error("client_input_channel_req: bad channel %d != %d", + id, session_ident); + } else if (strcmp(rtype, "exit-status") == 0) { + success = 1; + exit_status = packet_get_int(); + } + if (reply) { + packet_start(success ? + SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); + packet_put_int(c->remote_id); + packet_send(); + } + xfree(rtype); +} + +void +client_set_session_ident(int id) +{ + debug("client_set_session_ident: id %d", id); + session_ident = id; + channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST, + client_input_channel_req, (void *)0); +} @@ -28,7 +28,7 @@ */ #include "includes.h" -RCSID("$Id: compat.c,v 1.4 2000/04/04 04:39:01 damien Exp $"); +RCSID("$Id: compat.c,v 1.5 2000/04/06 02:32:39 damien Exp $"); #include "ssh.h" #include "packet.h" @@ -40,7 +40,9 @@ int datafellows = 0; void enable_compat20(void) { - fatal("protocol 2.0 not implemented"); + verbose("Enabling compatibility mode for protocol 2.0"); + compat20 = 1; + packet_set_ssh2_format(); } void enable_compat13(void) diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 24f0e428..35affbaa 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -15,8 +15,8 @@ Copyright: BSD Group: Applications/Internet BuildRoot: /tmp/openssh-%{version}-buildroot Obsoletes: ssh -PreReq: openssl -Requires: openssl +PreReq: openssl >= 0.9.5a +Requires: openssl >= 0.9.5a BuildPreReq: perl BuildPreReq: openssl-devel BuildPreReq: tcp_wrappers @@ -29,6 +29,17 @@ #ifndef KEX_H #define KEX_H +#include "config.h" + +#ifdef HAVE_OPENSSL +# include <openssl/bn.h> +# include <openssl/evp.h> +#endif +#ifdef HAVE_SSL +# include <ssl/bn.h> +# include <ssl/evp.h> +#endif + #define KEX_DH1 "diffie-hellman-group1-sha1" #define KEX_DSS "ssh-dss" diff --git a/myproposal.h b/myproposal.h new file mode 100644 index 00000000..7e4baff9 --- /dev/null +++ b/myproposal.h @@ -0,0 +1,20 @@ +#define KEX_DEFAULT_KEX "diffie-hellman-group1-sha1" +#define KEX_DEFAULT_PK_ALG "ssh-dss" +#define KEX_DEFAULT_ENCRYPT "blowfish-cbc,3des-cbc,arcfour,cast128-cbc" +#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com" +#define KEX_DEFAULT_COMP "zlib,none" +#define KEX_DEFAULT_LANG "" + + +static const char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, + KEX_DEFAULT_PK_ALG, + KEX_DEFAULT_ENCRYPT, + KEX_DEFAULT_ENCRYPT, + KEX_DEFAULT_MAC, + KEX_DEFAULT_MAC, + KEX_DEFAULT_COMP, + KEX_DEFAULT_COMP, + KEX_DEFAULT_LANG, + KEX_DEFAULT_LANG +}; @@ -17,7 +17,18 @@ */ #include "includes.h" -RCSID("$Id: packet.c,v 1.15 2000/04/04 04:57:08 damien Exp $"); +RCSID("$Id: packet.c,v 1.16 2000/04/06 02:32:40 damien Exp $"); + +#ifdef HAVE_OPENSSL +# include <openssl/bn.h> +# include <openssl/dh.h> +# include <openssl/hmac.h> +#endif /* HAVE_OPENSSL */ +#ifdef HAVE_SSL +# include <ssl/bn.h> +# include <ssl/dh.h> +# include <ssl/hmac.h> +#endif /* HAVE_SSL */ #include "xmalloc.h" #include "buffer.h" @@ -35,17 +46,6 @@ RCSID("$Id: packet.c,v 1.15 2000/04/04 04:57:08 damien Exp $"); #include "compat.h" #include "ssh2.h" -#ifdef HAVE_OPENSSL -# include <openssl/bn.h> -# include <openssl/dh.h> -# include <openssl/hmac.h> -#endif /* HAVE_OPENSSL */ -#ifdef HAVE_SSL -# include <ssl/bn.h> -# include <ssl/dh.h> -# include <ssl/hmac.h> -#endif /* HAVE_SSL */ - #include "buffer.h" #include "kex.h" #include "hmac.h" @@ -152,8 +152,8 @@ packet_set_connection(int fd_in, int fd_out) connection_in = fd_in; connection_out = fd_out; cipher_type = SSH_CIPHER_NONE; - cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 1); - cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0, 0); + cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *) "", 0); + cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *) "", 0); if (!initialized) { initialized = 1; buffer_init(&input); @@ -352,8 +352,8 @@ packet_set_encryption_key(const unsigned char *key, unsigned int keylen, fatal("keylen too small: %d", keylen); /* All other ciphers use the same key in both directions for now. */ - cipher_set_key(&receive_context, cipher, key, keylen, 0); - cipher_set_key(&send_context, cipher, key, keylen, 1); + cipher_set_key(&receive_context, cipher, key, keylen); + cipher_set_key(&send_context, cipher, key, keylen); } /* Starts constructing a packet to send. */ @@ -13,13 +13,11 @@ * */ -/* RCSID("$Id: packet.h,v 1.11 2000/04/04 04:39:03 damien Exp $"); */ +/* RCSID("$Id: packet.h,v 1.12 2000/04/06 02:32:40 damien Exp $"); */ #ifndef PACKET_H #define PACKET_H -#include "config.h" - #ifdef HAVE_OPENSSL #include <openssl/bn.h> #endif @@ -11,7 +11,7 @@ */ #include "includes.h" -RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $"); +RCSID("$Id: ssh.c,v 1.24 2000/04/06 02:32:40 damien Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -20,6 +20,9 @@ RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $"); #include "authfd.h" #include "readconf.h" #include "uidswap.h" + +#include "ssh2.h" +#include "compat.h" #include "channels.h" #ifdef HAVE___PROGNAME @@ -41,6 +44,10 @@ int debug_flag = 0; int tty_flag = 0; +/* don't exec a shell */ +int no_shell_flag = 0; +int no_tty_flag = 0; + /* * Flag indicating that nothing should be read from stdin. This can be set * on the command line. @@ -90,6 +97,9 @@ RSA *host_private_key = NULL; /* Original real UID. */ uid_t original_real_uid; +/* command to be executed */ +Buffer command; + /* Prints a help message to the user. This function never returns. */ void @@ -104,9 +114,9 @@ usage() fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); #endif /* AFS */ fprintf(stderr, " -x Disable X11 connection forwarding.\n"); - fprintf(stderr, " -X Enable X11 connection forwarding.\n"); fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\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, " -v Verbose; display verbose debugging messages.\n"); fprintf(stderr, " -V Display version number only.\n"); fprintf(stderr, " -P Don't allocate a privileged port.\n"); @@ -123,6 +133,7 @@ usage() fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0); fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); fprintf(stderr, " -C Enable compression.\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, " -4 Use IPv4 only.\n"); fprintf(stderr, " -6 Use IPv6 only.\n"); @@ -168,23 +179,22 @@ rsh_connect(char *host, char *user, Buffer * command) exit(1); } +int ssh_session(void); +int ssh_session2(void); + /* * Main program for the ssh client. */ int main(int ac, char **av) { - int i, opt, optind, type, exit_status, ok, authfd; + int i, opt, optind, exit_status, ok; u_short fwd_port, fwd_host_port; char *optarg, *cp, buf[256]; - Buffer command; - struct winsize ws; struct stat st; struct passwd *pw, pwcopy; - int interactive = 0, dummy; - int have_pty = 0; + int dummy; uid_t original_effective_uid; - int plen; /* * Save the original real uid. It will be needed later (uid-swapping @@ -328,7 +338,7 @@ main(int ac, char **av) case 'V': fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n", SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR); - fprintf(stderr, "Compiled with SSL.\n"); + fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay()); if (opt == 'V') exit(0); debug_flag = 1; @@ -397,6 +407,15 @@ main(int ac, char **av) options.compression = 1; break; + case 'N': + no_shell_flag = 1; + no_tty_flag = 1; + break; + + case 'T': + no_tty_flag = 1; + break; + case 'o': dummy = 1; if (process_config_line(&options, host ? host : "", optarg, @@ -455,6 +474,10 @@ main(int ac, char **av) fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n"); tty_flag = 0; } + /* force */ + if (no_tty_flag) + tty_flag = 0; + /* Get user data. */ pw = getpwuid(original_real_uid); if (!pw) { @@ -620,6 +643,23 @@ main(int ac, char **av) if (host_private_key_loaded) RSA_free(host_private_key); /* Destroys contents safely */ + exit_status = compat20 ? ssh_session2() : ssh_session(); + packet_close(); + return exit_status; +} + +int +ssh_session(void) +{ + int type; + int i; + int plen; + int interactive = 0; + int have_tty = 0; + struct winsize ws; + int authfd; + char *cp; + /* Enable compression if requested. */ if (options.compression) { debug("Requesting compression at level %d.", options.compression_level); @@ -673,7 +713,7 @@ main(int ac, char **av) type = packet_read(&plen); if (type == SSH_SMSG_SUCCESS) { interactive = 1; - have_pty = 1; + have_tty = 1; } else if (type == SSH_SMSG_FAILURE) log("Warning: Remote host failed or refused to allocate a pseudo tty."); else @@ -802,11 +842,103 @@ main(int ac, char **av) } /* Enter the interactive session. */ - exit_status = client_loop(have_pty, tty_flag ? options.escape_char : -1); + return client_loop(have_tty, tty_flag ? options.escape_char : -1); +} - /* Close the connection to the remote host. */ - packet_close(); +void +init_local_fwd(void) +{ + int i; + /* Initiate local TCP/IP port forwardings. */ + for (i = 0; i < options.num_local_forwards; i++) { + debug("Connections to local port %d forwarded to remote address %.200s:%d", + options.local_forwards[i].port, + options.local_forwards[i].host, + options.local_forwards[i].host_port); + channel_request_local_forwarding(options.local_forwards[i].port, + options.local_forwards[i].host, + options.local_forwards[i].host_port, + options.gateway_ports); + } +} + +extern void client_set_session_ident(int id); + +void +client_init(int id, void *arg) +{ + int len; + debug("client_init id %d arg %d", id, (int)arg); + + if (no_shell_flag) + goto done; + + if (tty_flag) { + struct winsize ws; + char *cp; + cp = getenv("TERM"); + if (!cp) + cp = ""; + /* Store window size in the packet. */ + if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) + memset(&ws, 0, sizeof(ws)); + + channel_request_start(id, "pty-req", 0); + packet_put_cstring(cp); + packet_put_int(ws.ws_col); + 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 */ + packet_send(); + /* XXX wait for reply */ + } + len = buffer_len(&command); + if (len > 0) { + if (len > 900) + len = 900; + debug("Sending command: %.*s", len, buffer_ptr(&command)); + channel_request_start(id, "exec", 0); + packet_put_string(buffer_ptr(&command), len); + packet_send(); + } else { + channel_request(id, "shell", 0); + } + /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */ +done: + /* register different callback, etc. XXX */ + client_set_session_ident(id); +} + +int +ssh_session2(void) +{ + int window, packetmax, id; + int in = dup(STDIN_FILENO); + int out = dup(STDOUT_FILENO); + int err = dup(STDERR_FILENO); + + if (in < 0 || out < 0 || err < 0) + fat |