From b1715dc0cf5ea91707b437310f63b17bed2dc7a6 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 30 May 2000 13:44:51 +1000 Subject: [PATCH] - OpenBSD CVS updates: - markus@cvs.openbsd.org [session.c] make x11-fwd work w/ localhost (xauth add host/unix:11) [cipher.c compat.c readconf.c servconf.c] check strtok() != NULL; ok niels@ [key.c] fix key_read() for uuencoded keys w/o '=' [serverloop.c] group ssh1 vs. ssh2 in serverloop [kex.c kex.h myproposal.h sshconnect2.c sshd.c] split kexinit/kexdh, factor out common code [readconf.c ssh.1 ssh.c] forwardagent defaults to no, add ssh -A - theo@cvs.openbsd.org [session.c] just some line shortening --- ChangeLog | 17 +++++++ cipher.c | 6 ++- compat.c | 8 +-- kex.c | 96 +++++++++++++++++++++++++---------- kex.h | 13 +++-- key.c | 18 ++++--- myproposal.h | 2 +- readconf.c | 10 +++- servconf.c | 6 ++- serverloop.c | 51 ++++++++++--------- session.c | 34 +++++++++---- ssh.1 | 12 +++-- ssh.c | 6 ++- sshconnect2.c | 137 +++++++++++++++++++++----------------------------- sshd.c | 47 +++-------------- 15 files changed, 256 insertions(+), 207 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3037eac38..f8dcd9ce9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,23 @@ - Define atexit for old Solaris - Fix buffer overrun in login.c for systems which use syslen in utmpx. patch from YOSHIFUJI Hideaki + - OpenBSD CVS updates: + - markus@cvs.openbsd.org + [session.c] + make x11-fwd work w/ localhost (xauth add host/unix:11) + [cipher.c compat.c readconf.c servconf.c] + check strtok() != NULL; ok niels@ + [key.c] + fix key_read() for uuencoded keys w/o '=' + [serverloop.c] + group ssh1 vs. ssh2 in serverloop + [kex.c kex.h myproposal.h sshconnect2.c sshd.c] + split kexinit/kexdh, factor out common code + [readconf.c ssh.1 ssh.c] + forwardagent defaults to no, add ssh -A + - theo@cvs.openbsd.org + [session.c] + just some line shortening 20000520 - Xauth fix from Markus Friedl diff --git a/cipher.c b/cipher.c index 639c1abbd..4117cb772 100644 --- a/cipher.c +++ b/cipher.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$Id: cipher.c,v 1.20 2000/04/16 02:31:50 damien Exp $"); +RCSID("$Id: cipher.c,v 1.21 2000/05/30 03:44:52 damien Exp $"); #include "ssh.h" #include "cipher.h" @@ -178,7 +178,7 @@ ciphers_valid(const char *names) char *p; int i; - if (strcmp(names, "") == 0) + if (names == NULL || strcmp(names, "") == 0) return 0; ciphers = xstrdup(names); for ((p = strtok(ciphers, CIPHER_SEP)); p; (p = strtok(NULL, CIPHER_SEP))) { @@ -201,6 +201,8 @@ int cipher_number(const char *name) { int i; + if (name == NULL) + return -1; for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++) if (strcmp(cipher_names[i], name) == 0 && (cipher_mask() & (1 << i))) diff --git a/compat.c b/compat.c index 00f031b8b..967e0b6b8 100644 --- a/compat.c +++ b/compat.c @@ -28,7 +28,7 @@ */ #include "includes.h" -RCSID("$Id: compat.c,v 1.10 2000/05/09 01:03:00 damien Exp $"); +RCSID("$Id: compat.c,v 1.11 2000/05/30 03:44:53 damien Exp $"); #include "ssh.h" #include "packet.h" @@ -80,10 +80,12 @@ compat_datafellows(const char *version) int proto_spec(const char *spec) { - char *s = xstrdup(spec); - char *p; + char *s, *p; int ret = SSH_PROTO_UNKNOWN; + if (spec == NULL) + return ret; + s = xstrdup(spec); for ((p = strtok(s, SEP)); p; (p = strtok(NULL, SEP))) { switch(atoi(p)) { case 1: diff --git a/kex.c b/kex.c index 221e03041..199e04264 100644 --- a/kex.c +++ b/kex.c @@ -28,13 +28,14 @@ */ #include "includes.h" -RCSID("$Id: kex.c,v 1.8 2000/05/09 01:03:01 damien Exp $"); +RCSID("$Id: kex.c,v 1.9 2000/05/30 03:44:53 damien Exp $"); #include "ssh.h" #include "ssh2.h" #include "xmalloc.h" #include "buffer.h" #include "bufaux.h" +#include "packet.h" #include "cipher.h" #include "compat.h" @@ -49,15 +50,17 @@ RCSID("$Id: kex.c,v 1.8 2000/05/09 01:03:01 damien Exp $"); #include "kex.h" +#define KEX_COOKIE_LEN 16 + Buffer * kex_init(char *myproposal[PROPOSAL_MAX]) { - char c = 0; - unsigned char cookie[16]; + int first_kex_packet_follows = 0; + unsigned char cookie[KEX_COOKIE_LEN]; u_int32_t rand = 0; int i; Buffer *ki = xmalloc(sizeof(*ki)); - for (i = 0; i < 16; i++) { + for (i = 0; i < KEX_COOKIE_LEN; i++) { if (i % 4 == 0) rand = arc4random(); cookie[i] = rand & 0xff; @@ -67,11 +70,55 @@ kex_init(char *myproposal[PROPOSAL_MAX]) buffer_append(ki, (char *)cookie, sizeof cookie); for (i = 0; i < PROPOSAL_MAX; i++) buffer_put_cstring(ki, myproposal[i]); - buffer_append(ki, &c, 1); /* boolean first_kex_packet_follows */ - buffer_put_int(ki, 0); /* uint32 0 (reserved for future extension) */ + buffer_put_char(ki, first_kex_packet_follows); + buffer_put_int(ki, 0); /* uint32 reserved */ return ki; } +/* send kexinit, parse and save reply */ +void +kex_exchange_kexinit( + Buffer *my_kexinit, Buffer *peer_kexint, + char *peer_proposal[PROPOSAL_MAX]) +{ + int i; + char *ptr; + int plen; + + debug("send KEXINIT"); + packet_start(SSH2_MSG_KEXINIT); + packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit)); + packet_send(); + packet_write_wait(); + debug("done"); + + /* + * read and save raw KEXINIT payload in buffer. this is used during + * computation of the session_id and the session keys. + */ + debug("wait KEXINIT"); + packet_read_expect(&plen, SSH2_MSG_KEXINIT); + ptr = packet_get_raw(&plen); + buffer_append(peer_kexint, ptr, plen); + + /* parse packet and save algorithm proposal */ + /* skip cookie */ + for (i = 0; i < KEX_COOKIE_LEN; i++) + packet_get_char(); + /* extract kex init proposal strings */ + for (i = 0; i < PROPOSAL_MAX; i++) { + peer_proposal[i] = packet_get_string(NULL); + debug("got kexinit: %s", peer_proposal[i]); + } + /* first kex follow / reserved */ + i = packet_get_char(); + debug("first kex follow: %d ", i); + i = packet_get_int(); + debug("reserved: %d ", i); + packet_done(); + debug("done"); +} + /* diffie-hellman-group1-sha1 */ int @@ -133,12 +180,6 @@ dh_new_group1() return dh; } -void -bignum_print(BIGNUM *b) -{ - BN_print_fp(stderr,b); -} - void dump_digest(unsigned char *digest, int len) { @@ -246,10 +287,13 @@ char * get_match(char *client, char *server) { char *sproposals[MAX_PROP]; - char *p; + char *c, *s, *p, *ret; int i, j, nproposals; - for ((p = strtok(server, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { + c = xstrdup(client); + s = xstrdup(server); + + for ((p = strtok(s, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { if (i < MAX_PROP) sproposals[i] = p; else @@ -257,11 +301,18 @@ get_match(char *client, char *server) } nproposals = i; - for ((p = strtok(client, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { - for (j = 0; j < nproposals; j++) - if (strcmp(p, sproposals[j]) == 0) - return xstrdup(p); + for ((p = strtok(c, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { + for (j = 0; j < nproposals; j++) { + if (strcmp(p, sproposals[j]) == 0) { + ret = xstrdup(p); + xfree(c); + xfree(s); + return ret; + } + } } + xfree(c); + xfree(s); return NULL; } void @@ -355,7 +406,6 @@ choose_hostkeyalg(Kex *k, char *client, char *server) Kex * kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server) { - int i; int mode; int ctos; /* direction: if true client-to-server */ int need; @@ -383,10 +433,6 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); - for (i = 0; i < PROPOSAL_MAX; i++) { - xfree(cprop[i]); - xfree(sprop[i]); - } need = 0; for (mode = 0; mode < MODE_MAX; mode++) { if (need < k->enc[mode].key_len) @@ -396,9 +442,7 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server if (need < k->mac[mode].key_len) need = k->mac[mode].key_len; } - /* need runden? */ -#define WE_NEED 32 - k->we_need = WE_NEED; + /* XXX need runden? */ k->we_need = need; return k; } diff --git a/kex.h b/kex.h index 5395ebc3f..7e5c67024 100644 --- a/kex.h +++ b/kex.h @@ -91,12 +91,17 @@ struct Kex { }; Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); +void +kex_exchange_kexinit( + Buffer *my_kexinit, Buffer *peer_kexint, + char *peer_proposal[PROPOSAL_MAX]); +Kex * +kex_choose_conf(char *cprop[PROPOSAL_MAX], + char *sprop[PROPOSAL_MAX], int server); +int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); +void packet_set_kex(Kex *k); int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); DH *dh_new_group1(); -Kex *kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server); -int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); -void bignum_print(BIGNUM *b); -void packet_set_kex(Kex *k); unsigned char * kex_hash( diff --git a/key.c b/key.c index ae355a3fc..d474f85c6 100644 --- a/key.c +++ b/key.c @@ -256,12 +256,14 @@ key_read(Key *ret, char **cpp) blob = xmalloc(len); n = uudecode(cp, blob, len); if (n < 0) { - error("uudecode %s failed", cp); + error("key_read: uudecode %s failed", cp); return 0; } k = dsa_key_from_blob(blob, n); - if (k == NULL) - return 0; + if (k == NULL) { + error("key_read: dsa_key_from_blob %s failed", cp); + return 0; + } xfree(blob); if (ret->dsa != NULL) DSA_free(ret->dsa); @@ -269,10 +271,12 @@ key_read(Key *ret, char **cpp) k->dsa = NULL; key_free(k); bits = BN_num_bits(ret->dsa->p); - cp = strchr(cp, '='); - if (cp == NULL) - return 0; - *cpp = cp + 1; + /* advance cp: skip whitespace and data */ + while (*cp == ' ' || *cp == '\t') + cp++; + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cpp = cp; break; default: fatal("key_read: bad key type: %d", ret->type); diff --git a/myproposal.h b/myproposal.h index 8b2417972..9611d8951 100644 --- a/myproposal.h +++ b/myproposal.h @@ -6,7 +6,7 @@ #define KEX_DEFAULT_LANG "" -static const char *myproposal[PROPOSAL_MAX] = { +static char *myproposal[PROPOSAL_MAX] = { KEX_DEFAULT_KEX, KEX_DEFAULT_PK_ALG, KEX_DEFAULT_ENCRYPT, diff --git a/readconf.c b/readconf.c index 9c5638b07..d7011d7f7 100644 --- a/readconf.c +++ b/readconf.c @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$Id: readconf.c,v 1.14 2000/05/09 01:03:01 damien Exp $"); +RCSID("$Id: readconf.c,v 1.15 2000/05/30 03:44:53 damien Exp $"); #include "ssh.h" #include "cipher.h" @@ -464,6 +464,8 @@ parse_int: case oCipher: intptr = &options->cipher; cp = strtok(NULL, WHITESPACE); + if (!cp) + fatal("%.200s line %d: Missing argument.", filename, linenum); value = cipher_number(cp); if (value == -1) fatal("%.200s line %d: Bad cipher '%s'.", @@ -474,6 +476,8 @@ parse_int: case oCiphers: cp = strtok(NULL, WHITESPACE); + if (!cp) + fatal("%.200s line %d: Missing argument.", filename, linenum); if (!ciphers_valid(cp)) fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, cp ? cp : ""); @@ -484,6 +488,8 @@ parse_int: case oProtocol: intptr = &options->protocol; cp = strtok(NULL, WHITESPACE); + if (!cp) + fatal("%.200s line %d: Missing argument.", filename, linenum); value = proto_spec(cp); if (value == SSH_PROTO_UNKNOWN) fatal("%.200s line %d: Bad protocol spec '%s'.", @@ -691,7 +697,7 @@ void fill_default_options(Options * options) { if (options->forward_agent == -1) - options->forward_agent = 1; + options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; if (options->gateway_ports == -1) diff --git a/servconf.c b/servconf.c index 05630c766..1aa4fe06d 100644 --- a/servconf.c +++ b/servconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$Id: servconf.c,v 1.16 2000/05/09 01:03:01 damien Exp $"); +RCSID("$Id: servconf.c,v 1.17 2000/05/30 03:44:53 damien Exp $"); #include "ssh.h" #include "servconf.h" @@ -588,6 +588,8 @@ parse_flag: case sCiphers: cp = strtok(NULL, WHITESPACE); + if (!cp) + fatal("%s line %d: Missing argument.", filename, linenum); if (!ciphers_valid(cp)) fatal("%s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, cp ? cp : ""); @@ -598,6 +600,8 @@ parse_flag: case sProtocol: intptr = &options->protocol; cp = strtok(NULL, WHITESPACE); + if (!cp) + fatal("%s line %d: Missing argument.", filename, linenum); value = proto_spec(cp); if (value == SSH_PROTO_UNKNOWN) fatal("%s line %d: Bad protocol spec '%s'.", diff --git a/serverloop.c b/serverloop.c index 977ed41f6..b08fcfd92 100644 --- a/serverloop.c +++ b/serverloop.c @@ -164,33 +164,37 @@ retry_select: /* Initialize select() masks. */ FD_ZERO(readset); + FD_ZERO(writeset); - /* - * Read packets from the client unless we have too much buffered - * stdin or channel data. - */ if (compat20) { /* wrong: bad condition XXX */ if (channel_not_very_much_buffered_data()) FD_SET(connection_in, readset); } else { - if (buffer_len(&stdin_buffer) < 4096 && + /* + * Read packets from the client unless we have too much + * buffered stdin or channel data. + */ + if (buffer_len(&stdin_buffer) < buffer_high && channel_not_very_much_buffered_data()) FD_SET(connection_in, readset); + /* + * If there is not too much data already buffered going to + * the client, try to get some more data from the program. + */ + if (packet_not_very_much_data_to_write()) { + if (!fdout_eof) + FD_SET(fdout, readset); + if (!fderr_eof) + FD_SET(fderr, readset); + } + /* + * If we have buffered data, try to write some of that data + * to the program. + */ + if (fdin != -1 && buffer_len(&stdin_buffer) > 0) + FD_SET(fdin, writeset); } - - /* - * If there is not too much data already buffered going to the - * client, try to get some more data from the program. - */ - if (!compat20 && packet_not_very_much_data_to_write()) { - if (!fdout_eof) - FD_SET(fdout, readset); - if (!fderr_eof) - FD_SET(fderr, readset); - } - FD_ZERO(writeset); - /* Set masks for channel descriptors. */ channel_prepare_select(readset, writeset); @@ -201,11 +205,6 @@ retry_select: if (packet_have_data_to_write()) FD_SET(connection_out, writeset); - /* If we have buffered data, try to write some of that data to the - program. */ - if (!compat20 && fdin != -1 && buffer_len(&stdin_buffer) > 0) - FD_SET(fdin, writeset); - /* Update the maximum descriptor number if appropriate. */ if (channel_max_fd() > max_fd) max_fd = channel_max_fd(); @@ -377,6 +376,7 @@ process_buffered_input_packets() void server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) { + fd_set readset, writeset; int wait_status; /* Status returned by wait(). */ pid_t wait_pid; /* pid returned by wait(). */ int waiting_termination = 0; /* Have displayed waiting close message. */ @@ -445,7 +445,6 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) /* Main loop of the server for the interactive session mode. */ for (;;) { - fd_set readset, writeset; /* Process buffered packets from the client. */ process_buffered_input_packets(); @@ -717,6 +716,9 @@ input_direct_tcpip(void) originator = packet_get_string(NULL); originator_port = packet_get_int(); packet_done(); + + debug("open direct-tcpip: from %s port %d to %s port %d", + originator, originator_port, target, target_port); /* XXX check permission */ sock = channel_connect_to(target, target_port); xfree(target); @@ -768,7 +770,6 @@ server_input_channel_open(int type, int plen) channel_free(id); } } else if (strcmp(ctype, "direct-tcpip") == 0) { - debug("open direct-tcpip"); id = input_direct_tcpip(); if (id >= 0) c = channel_lookup(id); diff --git a/session.c b/session.c index 4b7404f73..4791857c0 100644 --- a/session.c +++ b/session.c @@ -8,7 +8,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.12 2000/05/03 18:03:07 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.14 2000/05/25 03:10:18 deraadt Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -645,7 +645,8 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) } #endif /* Do common processing for the child, such as execing the command. */ - do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty); + do_child(command, pw, s->term, s->display, s->auth_proto, + s->auth_data, s->tty); /* NOTREACHED */ } if (pid < 0) @@ -749,7 +750,10 @@ read_environment_file(char ***env, unsigned int *envsize, fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf); continue; } - /* Replace the equals sign by nul, and advance value to the value string. */ + /* + * Replace the equals sign by nul, and advance value to + * the value string. + */ *value = '\0'; value++; child_set_env(env, envsize, cp, value); @@ -948,7 +952,8 @@ do_child(const char *command, struct passwd * pw, const char *term, /* read $HOME/.ssh/environment. */ if (!options.use_login) { - snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir); + snprintf(buf, sizeof buf, "%.200s/.ssh/environment", + pw->pw_dir); read_environment_file(&env, &envsize, buf); } if (debug_flag) { @@ -1037,21 +1042,27 @@ do_child(const char *command, struct passwd * pw, const char *term, if (auth_proto != NULL && auth_data != NULL) { char *screen = strchr(display, ':'); if (debug_flag) { - fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n", + fprintf(stderr, + "Running %.100s add %.100s %.100s %.100s\n", XAUTH_PATH, display, auth_proto, auth_data); if (screen != NULL) - fprintf(stderr, "Adding %.*s/unix%s %s %s\n", - screen-display, display, screen, auth_proto, auth_data); + fprintf(stderr, + "Adding %.*s/unix%s %s %s\n", + screen-display, display, + screen, auth_proto, auth_data); } f = popen(XAUTH_PATH " -q -", "w"); if (f) { - fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data); + fprintf(f, "add %s %s %s\n", display, + auth_proto, auth_data); if (screen != NULL) fprintf(f, "add %.*s/unix%s %s %s\n", - screen-display, display, screen, auth_proto, auth_data); + screen-display, display, + screen, auth_proto, auth_data); pclose(f); } else - fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH); + fprintf(stderr, "Could not run %s -q -\n", + XAUTH_PATH); } } #endif /* XAUTH_PATH */ @@ -1081,7 +1092,8 @@ do_child(const char *command, struct passwd * pw, const char *term, struct stat mailstat; mailbox = getenv("MAIL"); if (mailbox != NULL) { - if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0) + if (stat(mailbox, &mailstat) != 0 || + mailstat.st_size == 0) printf("No mail.\n"); else if (mailstat.st_mtime < mailstat.st_atime) printf("You have mail.\n"); diff --git a/ssh.1 b/ssh.1 index d8e9eb0b9..6c1d3763e 100644 --- a/ssh.1 +++ b/ssh.1 @@ -9,7 +9,7 @@ .\" .\" Created: Sat Apr 22 21:55:14 1995 ylo .\" -.\" $Id: ssh.1,v 1.26 2000/05/17 12:34:24 damien Exp $ +.\" $Id: ssh.1,v 1.27 2000/05/30 03:44:54 damien Exp $ .\" .Dd September 25, 1999 .Dt SSH 1 @@ -24,7 +24,7 @@ .Op Ar command .Pp .Nm ssh -.Op Fl afgknqtvxCNPTX246 +.Op Fl afgknqtvxACNPTX246 .Op Fl c Ar cipher_spec .Op Fl e Ar escape_char .Op Fl i Ar identity_file @@ -332,7 +332,9 @@ host key is not known or has changed. .Bl -tag -width Ds .It Fl a Disables forwarding of the authentication agent connection. -This may also be specified on a per-host basis in the configuration file. +.It Fl A +Enables forwarding of the authentication agent connection. +This can also be specified on a per-host basis in a configuration file. .It Fl c Ar blowfish|3des Selects the cipher to use for encrypting the session. .Ar 3des @@ -460,9 +462,9 @@ The verbose mode is also used to display challenges, if the user entered "s/key" as password. .It Fl x Disables X11 forwarding. -This can also be specified on a per-host basis in a configuration file. .It Fl X Enables X11 forwarding. +This can also be specified on a per-host basis in a configuration file. .It Fl C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11 and TCP/IP connections). @@ -671,6 +673,8 @@ The argument must be .Dq yes or .Dq no . +The default is +.Dq no . .It Cm ForwardX11 Specifies whether X11 connections will be automatically redirected over the secure channel and diff --git a/ssh.c b/ssh.c index 1cc8dbbf3..2934c3a4a 100644 --- a/ssh.c +++ b/ssh.c @@ -11,7 +11,7 @@ */ #include "includes.h" -RCSID("$Id: ssh.c,v 1.32 2000/05/20 05:22:37 damien Exp $"); +RCSID("$Id: ssh.c,v 1.33 2000/05/30 03:44:54 damien Exp $"); #include #include @@ -116,6 +116,7 @@ usage() fprintf(stderr, "Options:\n"); fprintf(stderr, " -l user Log in using this user name.\n"); fprintf(stderr, " -n Redirect input from /dev/null.\n"); + fprintf(stderr, " -A Enable authentication agent forwarding.\n"); fprintf(stderr, " -a Disable authentication agent forwarding.\n"); #ifdef AFS fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n"); @@ -315,6 +316,9 @@ main(int ac, char **av) case 'a': options.forward_agent = 0; break; + case 'A': + options.forward_agent = 1; + break; #ifdef AFS case 'k': options.kerberos_tgt_passing = 0; diff --git a/sshconnect2.c b/sshconnect2.c index 99ffb2c47..0abcf89a0 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -28,7 +28,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.10 2000/05/08 17:42:25 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.11 2000/05/25 20:45:20 markus Exp $"); #include #include @@ -68,16 +68,12 @@ unsigned char *session_id2 = NULL; int session_id2_len = 0; void -ssh_kex2(char *host, struct sockaddr *hostaddr) +ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, + Buffer *client_kexinit, Buffer *server_kexinit) { - Kex *kex; - char *cprop[PROPOSAL_MAX]; - char *sprop[PROPOSAL_MAX]; - Buffer *client_kexinit; - Buffer *server_kexinit; - int payload_len, dlen; + int i; + int plen, dlen; unsigned int klen, kout; - char *ptr; char *signature = NULL; unsigned int slen; char *server_host_key_blob = NULL; @@ -86,72 +82,10 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) DH *dh; BIGNUM *dh_server_pub = 0; BIGNUM *shared_secret = 0; - int i; unsigned char *kbuf; unsigned char *hash; -/* KEXINIT */ - - debug("Sending KEX init."); - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } else if (options.cipher == SSH_CIPHER_3DES) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = - cipher_name(SSH_CIPHER_3DES_CBC); - } else if (options.cipher == SSH_CIPHER_BLOWFISH) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = - cipher_name(SSH_CIPHER_BLOWFISH_CBC); - } - if (options.compression) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib"; - myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib"; - } else { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none"; - myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; - } - for (i = 0; i < PROPOSAL_MAX; i++) - cprop[i] = xstrdup(myproposal[i]); - - client_kexinit = kex_init(cprop); - packet_start(SSH2_MSG_KEXINIT); - packet_put_raw(buffer_ptr(client_kexinit), buffer_len(client_kexinit)); - packet_send(); - packet_write_wait(); - - debug("done"); - - packet_read_expect(&payload_len, SSH2_MSG_KEXINIT); - - /* save payload for session_id */ - server_kexinit = xmalloc(sizeof(*server_kexinit)); - buffer_init(server_kexinit); - ptr = packet_get_raw(&payload_len); - buffer_append(server_kexinit, ptr, payload_len); - - /* skip cookie */ - for (i = 0; i < 16; i++) - (void) packet_get_char(); - /* kex init proposal strings */ - for (i = 0; i < PROPOSAL_MAX; i++) { - sprop[i] = packet_get_string(NULL); - debug("got kexinit string: %s", sprop[i]); - } - i = (int) packet_get_char(); - debug("first kex follow == %d", i); - i = packet_get_int(); - debug("reserved == %d", i); - packet_done(); - - debug("done read kexinit"); - kex = kex_choose_conf(cprop, sprop, 0); - -/* KEXDH */ - debug("Sending SSH2_MSG_KEXDH_INIT."); - /* generate and send 'e', client DH public key */ dh = dh_new_group1(); packet_start(SSH2_MSG_KEXDH_INIT); @@ -172,7 +106,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) debug("Wait SSH2_MSG_KEXDH_REPLY."); - packet_read_expect(&payload_len, SSH2_MSG_KEXDH_REPLY); + packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY); debug("Got SSH2_MSG_KEXDH_REPLY."); @@ -233,10 +167,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) shared_secret ); xfree(server_host_key_blob); - buffer_free(client_kexinit); - buffer_free(server_kexinit); - xfree(client_kexinit); - xfree(server_kexinit); + DH_free(dh); #ifdef DEBUG_KEXDH fprintf(stderr, "hash == "); for (i = 0; i< 20; i++) @@ -250,16 +181,61 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) kex_derive_keys(kex, hash, shared_secret); packet_set_kex(kex); - /* have keys, free DH */ - DH_free(dh); - /* save session id */ session_id2_len = 20; session_id2 = xmalloc(session_id2_len); memcpy(session_id2, hash, session_id2_len); +} + +void +ssh_kex2(char *host, struct sockaddr *hostaddr) +{ + int i, plen; + Kex *kex; + Buffer *client_kexinit, *server_kexinit; + char *sprop[PROPOSAL_MAX]; + + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; + } else if (options.cipher == SSH_CIPHER_3DES) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = + (char *) cipher_name(SSH_CIPHER_3DES_CBC); + } else if (options.cipher == SSH_CIPHER_BLOWFISH) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = + (char *) cipher_name(SSH_CIPHER_BLOWFISH_CBC); + } + if (options.compression) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib"; + myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib"; + } else { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none"; + myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; + } + + /* buffers with raw kexinit messages */ + server_kexinit = xmalloc(sizeof(*server_kexinit)); + buffer_init(server_kexinit); + client_kexinit = kex_init(myproposal); + + /* algorithm negotiation */ + kex_exchange_kexinit(client_kexinit, server_kexinit, sprop); + kex = kex_choose_conf(myproposal, sprop, 0); + for (i = 0; i < PROPOSAL_MAX; i++) + xfree(sprop[i]); + + /* server authentication and session key agreement */ + ssh_kex_dh(kex, host, hostaddr, client_kexinit, server_kexinit); + + buffer_free(client_kexinit); + buffer_free(server_kexinit); + xfree(client_kexinit); + xfree(server_kexinit); debug("Wait SSH2_MSG_NEWKEYS."); - packet_read_expect(&payload_len, SSH2_MSG_NEWKEYS); + packet_read_expect(&plen, SSH2_MSG_NEWKEYS); packet_done(); debug("GOT SSH2_MSG_NEWKEYS."); @@ -278,6 +254,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) #endif debug("done: KEX2."); } + /* * Authenticate user */ diff --git a/sshd.c b/sshd.c index 39fbcba40..ec860024b 100644 --- a/sshd.c +++ b/sshd.c @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.117 2000/05/18 13:27:36 djm Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.118 2000/05/25 20:45:20 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -1159,7 +1159,6 @@ do_ssh2_kex() int payload_len, dlen; int slen; unsigned int klen, kout; - char *ptr; unsigned char *signature = NULL; unsigned char *server_host_key_blob = NULL; unsigned int sbloblen; @@ -1171,7 +1170,6 @@ do_ssh2_kex() unsigned char *hash; Kex *kex; char *cprop[PROPOSAL_MAX]; - char *sprop[PROPOSAL_MAX]; /* KEXINIT */ @@ -1179,46 +1177,15 @@ do_ssh2_kex() myproposal[PROPOSAL_ENC_ALGS_CTOS] = myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; } - - debug("Sending KEX init."); - - for (i = 0; i < PROPOSAL_MAX; i++) - sprop[i] = xstrdup(myproposal[i]); - server_kexinit = kex_init(sprop); - packet_start(SSH2_MSG_KEXINIT); - packet_put_raw(buffer_ptr(server_kexinit), buffer_len(server_kexinit)); - packet_send(); - packet_write_wait(); - - debug("done"); - - packet_read_expect(&payload_len, SSH2_MSG_KEXINIT); - - /* - * save raw KEXINIT payload in buffer. this is used during - * computation of the session_id and the session keys. - */ + server_kexinit = kex_init(myproposal); client_kexinit = xmalloc(sizeof(*client_kexinit)); buffer_init(client_kexinit); - ptr = packet_get_raw(&payload_len); - buffer_append(client_kexinit, ptr, payload_len); - /* skip cookie */ - for (i = 0; i < 16; i++) - (void) packet_get_char(); - /* save kex init proposal strings */ - for (i = 0; i < PROPOSAL_MAX; i++) { - cprop[i] = packet_get_string(NULL); - debug("got kexinit string: %s", cprop[i]); - } - - i = (int) packet_get_char(); - debug("first kex follow == %d", i); - i = packet_get_int(); - debug("reserved == %d", i); - - debug("done read kexinit"); - kex = kex_choose_conf(cprop, sprop, 1); + /* algorithm negotiation */ + kex_exchange_kexinit(server_kexinit, client_kexinit, cprop); + kex = kex_choose_conf(cprop, myproposal, 1); + for (i = 0; i < PROPOSAL_MAX; i++) + xfree(cprop[i]); /* KEXDH */