diff --git a/ChangeLog b/ChangeLog index a20e9ad54..b6f22341d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,32 @@ - (djm) NeXT patch from Ben Lindstrom - (djm) Use printf %lld instead of %qd in sftp-server.c. Fix from Michael Stone + - (djm) OpenBSD CVS sync: + - markus@cvs.openbsd.org 2000/09/17 09:38:59 + [sshconnect2.c sshd.c] + fix DEBUG_KEXDH + - markus@cvs.openbsd.org 2000/09/17 09:52:51 + [sshconnect.c] + yes no; ok niels@ + - markus@cvs.openbsd.org 2000/09/21 04:55:11 + [sshd.8] + typo + - markus@cvs.openbsd.org 2000/09/21 05:03:54 + [serverloop.c] + typo + - markus@cvs.openbsd.org 2000/09/21 05:11:42 + scp.c + utime() to utimes(); mouring@pconline.com + - markus@cvs.openbsd.org 2000/09/21 05:25:08 + sshconnect2.c + change login logic in ssh2, allows plugin of other auth methods + - markus@cvs.openbsd.org 2000/09/21 05:25:35 + [auth2.c channels.c channels.h clientloop.c dispatch.c dispatch.h] + [serverloop.c] + add context to dispatch_run + - markus@cvs.openbsd.org 2000/09/21 05:07:52 + authfd.c authfd.h ssh-agent.c + bug compat for old ssh.com software 20000920 - (djm) Fix bad path substitution. Report from Andrew Miner diff --git a/auth2.c b/auth2.c index 8b0a4bc6a..6ac5d2527 100644 --- a/auth2.c +++ b/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.14 2000/09/07 20:27:49 deraadt Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.15 2000/09/21 11:25:32 markus Exp $"); #include #include @@ -64,9 +64,9 @@ extern int session_id2_len; /* protocol */ -void input_service_request(int type, int plen); -void input_userauth_request(int type, int plen); -void protocol_error(int type, int plen); +void input_service_request(int type, int plen, void *ctxt); +void input_userauth_request(int type, int plen, void *ctxt); +void protocol_error(int type, int plen, void *ctxt); /* auth */ int ssh2_auth_none(struct passwd *pw); @@ -104,12 +104,12 @@ do_authentication2() dispatch_init(&protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); - dispatch_run(DISPATCH_BLOCK, &userauth_success); + dispatch_run(DISPATCH_BLOCK, &userauth_success, NULL); do_authenticated2(); } void -protocol_error(int type, int plen) +protocol_error(int type, int plen, void *ctxt) { log("auth: protocol error: type %d plen %d", type, plen); packet_start(SSH2_MSG_UNIMPLEMENTED); @@ -119,7 +119,7 @@ protocol_error(int type, int plen) } void -input_service_request(int type, int plen) +input_service_request(int type, int plen, void *ctxt) { unsigned int len; int accept = 0; @@ -148,7 +148,7 @@ input_service_request(int type, int plen) } void -input_userauth_request(int type, int plen) +input_userauth_request(int type, int plen, void *ctxt) { static void (*authlog) (const char *fmt,...) = verbose; static int attempt = 0; diff --git a/authfd.c b/authfd.c index 89fa2afad..433623ef7 100644 --- a/authfd.c +++ b/authfd.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $"); +RCSID("$OpenBSD: authfd.c,v 1.28 2000/09/21 11:07:50 markus Exp $"); #include "ssh.h" #include "rsa.h" @@ -51,6 +51,7 @@ RCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $"); #include "authfd.h" #include "kex.h" #include "dsa.h" +#include "compat.h" /* helper */ int decode_reply(int type); @@ -364,20 +365,24 @@ ssh_agent_sign(AuthenticationConnection *auth, unsigned char **sigp, int *lenp, unsigned char *data, int datalen) { + extern int datafellows; Buffer msg; unsigned char *blob; unsigned int blen; - int type; + int type, flags = 0; int ret = -1; if (dsa_make_key_blob(key, &blob, &blen) == 0) return -1; + if (datafellows & SSH_BUG_SIGBLOB) + flags = SSH_AGENT_OLD_SIGNATURE; + buffer_init(&msg); buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); buffer_put_string(&msg, blob, blen); buffer_put_string(&msg, data, datalen); - buffer_put_int(&msg, 0); /* flags, unused */ + buffer_put_int(&msg, flags); xfree(blob); if (ssh_request_reply(auth, &msg, &msg) == 0) { diff --git a/authfd.h b/authfd.h index b7a137d99..808575cd8 100644 --- a/authfd.h +++ b/authfd.h @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: authfd.h,v 1.11 2000/09/07 20:27:49 deraadt Exp $"); */ +/* RCSID("$OpenBSD: authfd.h,v 1.12 2000/09/21 11:07:51 markus Exp $"); */ #ifndef AUTHFD_H #define AUTHFD_H @@ -37,6 +37,9 @@ #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 +#define SSH_AGENT_OLD_SIGNATURE 0x01 + + typedef struct { int fd; Buffer identities; diff --git a/channels.c b/channels.c index 48479c456..287e16d10 100644 --- a/channels.c +++ b/channels.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.68 2000/09/07 20:40:29 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.69 2000/09/21 11:25:33 markus Exp $"); #include "ssh.h" #include "packet.h" @@ -998,7 +998,7 @@ channel_output_poll() */ void -channel_input_data(int type, int plen) +channel_input_data(int type, int plen, void *ctxt) { int id; char *data; @@ -1043,7 +1043,7 @@ channel_input_data(int type, int plen) xfree(data); } void -channel_input_extended_data(int type, int plen) +channel_input_extended_data(int type, int plen, void *ctxt) { int id; int tcode; @@ -1113,7 +1113,7 @@ channel_not_very_much_buffered_data() } void -channel_input_ieof(int type, int plen) +channel_input_ieof(int type, int plen, void *ctxt) { int id; Channel *c; @@ -1128,7 +1128,7 @@ channel_input_ieof(int type, int plen) } void -channel_input_close(int type, int plen) +channel_input_close(int type, int plen, void *ctxt) { int id; Channel *c; @@ -1167,7 +1167,7 @@ channel_input_close(int type, int plen) /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ void -channel_input_oclose(int type, int plen) +channel_input_oclose(int type, int plen, void *ctxt) { int id = packet_get_int(); Channel *c = channel_lookup(id); @@ -1178,7 +1178,7 @@ channel_input_oclose(int type, int plen) } void -channel_input_close_confirmation(int type, int plen) +channel_input_close_confirmation(int type, int plen, void *ctxt) { int id = packet_get_int(); Channel *c = channel_lookup(id); @@ -1194,7 +1194,7 @@ channel_input_close_confirmation(int type, int plen) } void -channel_input_open_confirmation(int type, int plen) +channel_input_open_confirmation(int type, int plen, void *ctxt) { int id, remote_id; Channel *c; @@ -1228,7 +1228,7 @@ channel_input_open_confirmation(int type, int plen) } void -channel_input_open_failure(int type, int plen) +channel_input_open_failure(int type, int plen, void *ctxt) { int id; Channel *c; @@ -1256,7 +1256,7 @@ channel_input_open_failure(int type, int plen) } void -channel_input_channel_request(int type, int plen) +channel_input_channel_request(int type, int plen, void *ctxt) { int id; Channel *c; @@ -1281,7 +1281,7 @@ debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event); } void -channel_input_window_adjust(int type, int plen) +channel_input_window_adjust(int type, int plen, void *ctxt) { Channel *c; int id, adjust; @@ -1659,7 +1659,7 @@ channel_connect_to(const char *host, u_short host_port) */ void -channel_input_port_open(int type, int plen) +channel_input_port_open(int type, int plen, void *ctxt) { u_short host_port; char *host, *originator_string; @@ -2000,7 +2000,7 @@ x11_connect_display(void) */ void -x11_input_open(int type, int plen) +x11_input_open(int type, int plen, void *ctxt) { int remote_channel, sock = 0, newch; char *remote_host; @@ -2215,7 +2215,7 @@ auth_input_request_forwarding(struct passwd * pw) /* This is called to process an SSH_SMSG_AGENT_OPEN message. */ void -auth_input_open_request(int type, int plen) +auth_input_open_request(int type, int plen, void *ctxt) { int remch, sock, newch; char *dummyname; diff --git a/channels.h b/channels.h index c0d60199c..a74f59261 100644 --- a/channels.h +++ b/channels.h @@ -32,7 +32,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: channels.h,v 1.19 2000/09/07 21:13:37 markus Exp $"); */ +/* RCSID("$OpenBSD: channels.h,v 1.20 2000/09/21 11:25:33 markus Exp $"); */ #ifndef CHANNELS_H #define CHANNELS_H @@ -131,18 +131,18 @@ int channel_new(char *ctype, int type, int rfd, int wfd, int efd, int window, int maxpack, int extended_usage, char *remote_name); -void channel_input_channel_request(int type, int plen); -void channel_input_close(int type, int plen); -void channel_input_close_confirmation(int type, int plen); -void channel_input_data(int type, int plen); -void channel_input_extended_data(int type, int plen); -void channel_input_ieof(int type, int plen); -void channel_input_oclose(int type, int plen); -void channel_input_open_confirmation(int type, int plen); -void channel_input_open_failure(int type, int plen); -void channel_input_port_open(int type, int plen); -void channel_input_window_adjust(int type, int plen); -void channel_input_open(int type, int plen); +void channel_input_channel_request(int type, int plen, void *ctxt); +void channel_input_close(int type, int plen, void *ctxt); +void channel_input_close_confirmation(int type, int plen, void *ctxt); +void channel_input_data(int type, int plen, void *ctxt); +void channel_input_extended_data(int type, int plen, void *ctxt); +void channel_input_ieof(int type, int plen, void *ctxt); +void channel_input_oclose(int type, int plen, void *ctxt); +void channel_input_open_confirmation(int type, int plen, void *ctxt); +void channel_input_open_failure(int type, int plen, void *ctxt); +void channel_input_port_open(int type, int plen, void *ctxt); +void channel_input_window_adjust(int type, int plen, void *ctxt); +void channel_input_open(int type, int plen, void *ctxt); /* Sets specific protocol options. */ void channel_set_options(int hostname_in_open); @@ -246,7 +246,7 @@ char *x11_create_display_inet(int screen, int x11_display_offset); * the remote channel number. We should do whatever we want, and respond * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */ -void x11_input_open(int type, int plen); +void x11_input_open(int type, int plen, void *ctxt); /* * Requests forwarding of X11 connections. This should be called on the @@ -279,7 +279,7 @@ char *auth_get_socket_name(void); int auth_input_request_forwarding(struct passwd * pw); /* This is called to process an SSH_SMSG_AGENT_OPEN message. */ -void auth_input_open_request(int type, int plen); +void auth_input_open_request(int type, int plen, void *ctxt); /* XXX */ int channel_connect_to(const char *host, u_short host_port); diff --git a/clientloop.c b/clientloop.c index 7400a17a6..845307eba 100644 --- a/clientloop.c +++ b/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.35 2000/09/14 20:25:14 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.36 2000/09/21 11:25:33 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -771,7 +771,7 @@ client_process_output(fd_set * writeset) void client_process_buffered_input_packets() { - dispatch_run(DISPATCH_NONBLOCK, &quit_pending); + dispatch_run(DISPATCH_NONBLOCK, &quit_pending, NULL); } /* scan buf[] for '~' before sending data to the peer */ @@ -978,7 +978,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /*********/ void -client_input_stdout_data(int type, int plen) +client_input_stdout_data(int type, int plen, void *ctxt) { unsigned int data_len; char *data = packet_get_string(&data_len); @@ -989,7 +989,7 @@ client_input_stdout_data(int type, int plen) xfree(data); } void -client_input_stderr_data(int type, int plen) +client_input_stderr_data(int type, int plen, void *ctxt) { unsigned int data_len; char *data = packet_get_string(&data_len); @@ -1000,7 +1000,7 @@ client_input_stderr_data(int type, int plen) xfree(data); } void -client_input_exit_status(int type, int plen) +client_input_exit_status(int type, int plen, void *ctxt) { packet_integrity_check(plen, 4, type); exit_status = packet_get_int(); @@ -1018,7 +1018,7 @@ client_input_exit_status(int type, int plen) /* XXXX move to generic input handler */ void -client_input_channel_open(int type, int plen) +client_input_channel_open(int type, int plen, void *ctxt) { Channel *c = NULL; char *ctype; diff --git a/dispatch.c b/dispatch.c index 3daac2022..db8951c1b 100644 --- a/dispatch.c +++ b/dispatch.c @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: dispatch.c,v 1.4 2000/09/07 20:27:51 deraadt Exp $"); +RCSID("$OpenBSD: dispatch.c,v 1.5 2000/09/21 11:25:34 markus Exp $"); #include "ssh.h" #include "dispatch.h" #include "packet.h" @@ -33,7 +33,7 @@ RCSID("$OpenBSD: dispatch.c,v 1.4 2000/09/07 20:27:51 deraadt Exp $"); dispatch_fn *dispatch[DISPATCH_MAX]; void -dispatch_protocol_error(int type, int plen) +dispatch_protocol_error(int type, int plen, void *ctxt) { error("Hm, dispatch protocol error: type %d plen %d", type, plen); } @@ -50,7 +50,7 @@ dispatch_set(int type, dispatch_fn *fn) dispatch[type] = fn; } void -dispatch_run(int mode, int *done) +dispatch_run(int mode, int *done, void *ctxt) { for (;;) { int plen; @@ -64,7 +64,7 @@ dispatch_run(int mode, int *done) return; } if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL) - (*dispatch[type])(type, plen); + (*dispatch[type])(type, plen, ctxt); else packet_disconnect("protocol error: rcvd type %d", type); if (done != NULL && *done) diff --git a/dispatch.h b/dispatch.h index dc9d3dd4e..e60174c20 100644 --- a/dispatch.h +++ b/dispatch.h @@ -26,9 +26,9 @@ enum { DISPATCH_NONBLOCK }; -typedef void dispatch_fn(int type, int plen); +typedef void dispatch_fn(int type, int plen, void *ctxt); void dispatch_init(dispatch_fn *dflt); void dispatch_set(int type, dispatch_fn *fn); -void dispatch_run(int mode, int *done); -void dispatch_protocol_error(int type, int plen); +void dispatch_run(int mode, int *done, void *ctxt); +void dispatch_protocol_error(int type, int plen, void *ctxt); diff --git a/scp.c b/scp.c index 79c310c5e..72949d0ec 100644 --- a/scp.c +++ b/scp.c @@ -75,11 +75,10 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.39 2000/09/07 20:53:00 markus Exp $"); +RCSID("$OpenBSD: scp.c,v 1.40 2000/09/21 11:11:42 markus Exp $"); #include "ssh.h" #include "xmalloc.h" -#include #define _PATH_CP "cp" @@ -711,8 +710,8 @@ sink(argc, argv) off_t size; int setimes, targisdir, wrerrno = 0; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; - struct utimbuf ut; int dummy_usec; + struct timeval tv[2]; #define SCREWUP(str) { why = str; goto screwup; } @@ -766,16 +765,18 @@ sink(argc, argv) if (*cp == 'T') { setimes++; cp++; - getnum(ut.modtime); + getnum(tv[1].tv_sec); if (*cp++ != ' ') SCREWUP("mtime.sec not delimited"); getnum(dummy_usec); + tv[1].tv_usec = 0; if (*cp++ != ' ') SCREWUP("mtime.usec not delimited"); - getnum(ut.actime); + getnum(tv[0].tv_sec); if (*cp++ != ' ') SCREWUP("atime.sec not delimited"); getnum(dummy_usec); + tv[0].tv_usec = 0; if (*cp++ != '\0') SCREWUP("atime.usec not delimited"); (void) atomicio(write, remout, "", 1); @@ -843,7 +844,7 @@ sink(argc, argv) sink(1, vect); if (setimes) { setimes = 0; - if (utime(np, &ut) < 0) + if (utimes(np, tv) < 0) run_err("%s: set times: %s", np, strerror(errno)); } @@ -930,7 +931,7 @@ bad: run_err("%s: %s", np, strerror(errno)); (void) response(); if (setimes && wrerr == NO) { setimes = 0; - if (utime(np, &ut) < 0) { + if (utimes(np, tv) < 0) { run_err("%s: set times: %s", np, strerror(errno)); wrerr = DISPLAYED; diff --git a/serverloop.c b/serverloop.c index c2b2d0222..be9edfafc 100644 --- a/serverloop.c +++ b/serverloop.c @@ -389,7 +389,7 @@ drain_output() void process_buffered_input_packets() { - dispatch_run(DISPATCH_NONBLOCK, NULL); + dispatch_run(DISPATCH_NONBLOCK, NULL, NULL); } /* @@ -689,7 +689,7 @@ server_loop2(void) } void -server_input_stdin_data(int type, int plen) +server_input_stdin_data(int type, int plen, void *ctxt) { char *data; unsigned int data_len; @@ -706,7 +706,7 @@ server_input_stdin_data(int type, int plen) } void -server_input_eof(int type, int plen) +server_input_eof(int type, int plen, void *ctxt) { /* * Eof from the client. The stdin descriptor to the @@ -719,7 +719,7 @@ server_input_eof(int type, int plen) } void -server_input_window_size(int type, int plen) +server_input_window_size(int type, int plen, void *ctxt) { int row = packet_get_int(); int col = packet_get_int(); @@ -765,7 +765,7 @@ input_direct_tcpip(void) } void -server_input_channel_open(int type, int plen) +server_input_channel_open(int type, int plen, void *ctxt) { Channel *c = NULL; char *ctype; @@ -780,7 +780,7 @@ server_input_channel_open(int type, int plen) rwindow = packet_get_int(); rmaxpack = packet_get_int(); - debug("channel_input_open: ctype %s rchan %d win %d max %d", + debug("server_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { diff --git a/ssh-agent.c b/ssh-agent.c index f7be488f8..e6fb336ed 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.36 2000/09/15 07:13:49 deraadt Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */ /* * Author: Tatu Ylonen @@ -37,7 +37,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-agent.c,v 1.36 2000/09/15 07:13:49 deraadt Exp $"); +RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $"); #include "ssh.h" #include "rsa.h" @@ -56,6 +56,7 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.36 2000/09/15 07:13:49 deraadt Exp $"); #include "authfd.h" #include "dsa.h" #include "kex.h" +#include "compat.h" typedef struct { int fd; @@ -237,6 +238,7 @@ process_sign_request2(SocketEntry *e) Key *key, *private; unsigned char *blob, *data, *signature = NULL; unsigned int blen, dlen, slen = 0; + int flags; Buffer msg; int ok = -1; @@ -244,7 +246,10 @@ process_sign_request2(SocketEntry *e) blob = buffer_get_string(&e->input, &blen); data = buffer_get_string(&e->input, &dlen); - buffer_get_int(&e->input); /* flags, unused */ + + flags = buffer_get_int(&e->input); + if (flags & SSH_AGENT_OLD_SIGNATURE) + datafellows = SSH_BUG_SIGBLOB; key = dsa_key_from_blob(blob, blen); if (key != NULL) { diff --git a/sshconnect.c b/sshconnect.c index 7144040ef..d6072b36c 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -13,7 +13,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.78 2000/09/07 20:27:54 deraadt Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $"); #include #include @@ -444,8 +444,10 @@ read_yes_or_no(const char *prompt, int defval) retval = defval; if (strcmp(buf, "yes") == 0) retval = 1; - if (strcmp(buf, "no") == 0) + else if (strcmp(buf, "no") == 0) retval = 0; + else + fprintf(stderr, "Please type 'yes' or 'no'.\n"); if (retval != -1) { if (f != stdin) diff --git a/sshconnect2.c b/sshconnect2.c index d225359d0..855833c06 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.18 2000/09/07 20:27:55 deraadt Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.20 2000/09/21 11:25:07 markus Exp $"); #include #include @@ -49,6 +49,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.18 2000/09/07 20:27:55 deraadt Exp $"); #include "dsa.h" #include "sshconnect.h" #include "authfile.h" +#include "dispatch.h" #include "authfd.h" /* import */ @@ -67,6 +68,9 @@ void ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, Buffer *client_kexinit, Buffer *server_kexinit) { +#ifdef DEBUG_KEXDH + int i; +#endif int plen, dlen; unsigned int klen, kout; char *signature = NULL; @@ -90,11 +94,11 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, #ifdef DEBUG_KEXDH fprintf(stderr, "\np= "); - bignum_print(dh->p); + BN_print_fp(stderr, dh->p); fprintf(stderr, "\ng= "); - bignum_print(dh->g); + BN_print_fp(stderr, dh->g); fprintf(stderr, "\npub= "); - bignum_print(dh->pub_key); + BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); DHparams_print_fp(stderr, dh); #endif @@ -122,7 +126,7 @@ ssh_kex_dh(Kex *kex, char *host, struct sockaddr *hostaddr, #ifdef DEBUG_KEXDH fprintf(stderr, "\ndh_server_pub= "); - bignum_print(dh_server_pub); + BN_print_fp(stderr, dh_server_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_server_pub)); #endif @@ -253,8 +257,156 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) /* * Authenticate user */ + +typedef struct Authctxt Authctxt; +typedef struct Authmethod Authmethod; + +typedef int sign_cb_fn( + Authctxt *authctxt, Key *key, + unsigned char **sigp, int *lenp, unsigned char *data, int datalen); + +struct Authctxt { + const char *server_user; + const char *host; + const char *service; + AuthenticationConnection *agent; + int success; + Authmethod *method; +}; +struct Authmethod { + char *name; /* string to compare against server's list */ + int (*userauth)(Authctxt *authctxt); + int *enabled; /* flag in option struct that enables method */ + int *batch_flag; /* flag in option struct that disables method */ +}; + +void input_userauth_success(int type, int plen, void *ctxt); +void input_userauth_failure(int type, int plen, void *ctxt); +void input_userauth_error(int type, int plen, void *ctxt); +int userauth_pubkey(Authctxt *authctxt); +int userauth_passwd(Authctxt *authctxt); + +void authmethod_clear(); +Authmethod *authmethod_get(char *auth_list); + +Authmethod authmethods[] = { + {"publickey", + userauth_pubkey, + &options.dsa_authentication, + NULL}, + {"password", + userauth_passwd, + &options.password_authentication, + &options.batch_mode}, + {NULL, NULL, NULL, NULL} +}; + +void +ssh_userauth2(const char *server_user, char *host) +{ + Authctxt authctxt; + int type; + int plen; + + debug("send SSH2_MSG_SERVICE_REQUEST"); + packet_start(SSH2_MSG_SERVICE_REQUEST); + packet_put_cstring("ssh-userauth"); + packet_send(); + packet_write_wait(); + type = packet_read(&plen); + if (type != SSH2_MSG_SERVICE_ACCEPT) { + fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type); + } + if (packet_remaining() > 0) { + char *reply = packet_get_string(&plen); + debug("service_accept: %s", reply); + xfree(reply); + packet_done(); + } else { + debug("buggy server: service_accept w/o service"); + } + packet_done(); + debug("got SSH2_MSG_SERVICE_ACCEPT"); + + /* setup authentication context */ + authctxt.agent = ssh_get_authentication_connection(); + authctxt.server_user = server_user; + authctxt.host = host; + authctxt.service = "ssh-connection"; /* service name */ + authctxt.success = 0; + authctxt.method = NULL; + + /* initial userauth request */ + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt.server_user); + packet_put_cstring(authctxt.service); + packet_put_cstring("none"); + packet_send(); + packet_write_wait(); + + authmethod_clear(); + + dispatch_init(&input_userauth_error); + dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); + dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); + dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ + + if (authctxt.agent != NULL) + ssh_close_authentication_connection(authctxt.agent); + + debug("ssh-userauth2 successfull"); +} +void +input_userauth_error(int type, int plen, void *ctxt) +{ + fatal("input_userauth_error: bad message during authentication"); +} +void +input_userauth_success(int type, int plen, void *ctxt) +{ + Authctxt *authctxt = ctxt; + if (authctxt == NULL) + fatal("input_userauth_success: no authentication context"); + authctxt->success = 1; /* break out */ +} +void +input_userauth_failure(int type, int plen, void *ctxt) +{ + Authmethod *method = NULL; + Authctxt *authctxt = ctxt; + char *authlist = NULL; + int partial; + int dlen; + + if (authctxt == NULL) + fatal("input_userauth_failure: no authentication context"); + + authlist = packet_get_string(&dlen); + partial = packet_get_char(); + packet_done(); + + if (partial != 0) + debug("partial success"); + debug("authentications that can continue: %s", authlist); + + for (;;) { + /* try old method or get next method */ + method = authmethod_get(authlist); + if (method == NULL) + fatal("Unable to find an authentication method"); + if (method->userauth(authctxt) != 0) { + debug2("we sent a packet, wait for reply"); + break; + } else { + debug2("we did not send a packet, disable method"); + method->enabled = NULL; + } + } + xfree(authlist); +} + int -ssh2_try_passwd(const char *server_user, const char *host, const char *service) +userauth_passwd(Authctxt *authctxt) { static int attempt = 0; char prompt[80]; @@ -267,11 +419,11 @@ ssh2_try_passwd(const char *server_user, const char *host, const char *service) error("Permission denied, please try again."); snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ", - server_user, host); + authctxt->server_user, authctxt->host); password = read_passphrase(prompt, 0); packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(server_user); - packet_put_cstring(service); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); packet_put_cstring("password"); packet_put_char(0); packet_put_cstring(password); @@ -282,14 +434,8 @@ ssh2_try_passwd(const char *server_user, const char *host, const char *service) return 1; } -typedef int sign_fn( - Key *key, - unsigned char **sigp, int *lenp, - unsigned char *data, int datalen); - int -ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, - const char *server_user, const char *host, const char *service) +sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) { Buffer b; unsigned char *blob, *signature; @@ -309,18 +455,18 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, skip = session_id2_len; } buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, server_user); + buffer_put_cstring(&b, authctxt->server_user); buffer_put_cstring(&b, datafellows & SSH_BUG_PUBKEYAUTH ? "ssh-userauth" : - service); + authctxt->service); buffer_put_cstring(&b, "publickey"); buffer_put_char(&b, 1); buffer_put_cstring(&b, KEX_DSS); buffer_put_string(&b, blob, bloblen); /* generate signature */ - ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); + ret = (*sign_callback)(authctxt, k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); if (ret == -1) { xfree(blob); buffer_free(&b); @@ -333,8 +479,8 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, buffer_clear(&b); buffer_append(&b, session_id2, session_id2_len); buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, server_user); - buffer_put_cstring(&b, service); + buffer_put_cstring(&b, authctxt->server_user); + buffer_put_cstring(&b, authctxt->service); buffer_put_cstring(&b, "publickey"); buffer_put_char(&b, 1); buffer_put_cstring(&b, KEX_DSS); @@ -347,7 +493,7 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, /* skip session id and packet type */ if (buffer_len(&b) < skip + 1) - fatal("ssh2_try_pubkey: internal error"); + fatal("userauth_pubkey: internal error"); buffer_consume(&b, skip + 1); /* put remaining data from buffer into packet */ @@ -362,12 +508,18 @@ ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign, return 1; } +/* sign callback */ +int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp, + unsigned char *data, int datalen) +{ + return dsa_sign(key, sigp, lenp, data, datalen); +} + int -ssh2_try_pubkey(char *filename, - const char *server_user, const char *host, const char *service) +userauth_pubkey_identity(Authctxt *authctxt, char *filename) { Key *k; - int ret = 0; + int i, ret, try_next; struct stat st; if (stat(filename, &st) != 0) { @@ -384,37 +536,40 @@ ssh2_try_pubkey(char *filename, snprintf(prompt, sizeof prompt, "Enter passphrase for DSA key '%.100s': ", filename); - passphrase = read_passphrase(prompt, 0); - success = load_private_key(filename, passphrase, k, NULL); - memset(passphrase, 0, strlen(passphrase)); - xfree(passphrase); + for (i = 0; i < options.number_of_password_prompts; i++) { + passphrase = read_passphrase(prompt, 0); + if (strcmp(passphrase, "") != 0) { + success = load_private_key(filename, passphrase, k, NULL); + try_next = 0; + } else { + debug2("no passphrase given, try next key"); + try_next = 1; + } + memset(passphrase, 0, strlen(passphrase)); + xfree(passphrase); + if (success || try_next) + break; + debug2("bad passphrase given, try again..."); + } if (!success) { key_free(k); return 0; } } - ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service); + ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb); key_free(k); return ret; } -int agent_sign( - Key *key, - unsigned char **sigp, int *lenp, +/* sign callback */ +int agent_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp, unsigned char *data, int datalen) { - int ret = -1; - AuthenticationConnection *ac = ssh_get_authentication_connection(); - if (ac != NULL) { - ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen); - ssh_close_authentication_connection(ac); - } - return ret; + return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen); } int -ssh2_try_agent(AuthenticationConnection *ac, - const char *server_user, const char *host, const char *service) +userauth_pubkey_agent(Authctxt *authctxt) { static int called = 0; char *comment; @@ -422,104 +577,151 @@ ssh2_try_agent(AuthenticationConnection *ac, int ret; if (called == 0) { - k = ssh_get_first_identity(ac, &comment, 2); - called ++; + k = ssh_get_first_identity(authctxt->agent, &comment, 2); + called = 1; } else { - k = ssh_get_next_identity(ac, &comment, 2); + k = ssh_get_next_identity(authctxt->agent, &comment, 2); } - if (k == NULL) + if (k == NULL) { + debug2("no more DSA keys from agent"); return 0; + } debug("trying DSA agent key %s", comment); xfree(comment); - ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service); + ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb); key_free(k); return ret; } -void -ssh_userauth2(const char *server_user, char *host) +int +userauth_pubkey(Authctxt *authctxt) { - AuthenticationConnection *ac = ssh_get_authentication_connection(); - int type; - int plen; - int sent; - unsigned int dlen; - int partial; - int i = 0; - char *auths; - char *service = "ssh-connection"; /* service name */ + static int idx = 0; + int sent = 0; - debug("send SSH2_MSG_SERVICE_REQUEST"); - packet_start(SSH2_MSG_SERVICE_REQUEST); - packet_put_cstring("ssh-userauth"); - packet_send(); - packet_write_wait(); - - type = packet_read(&plen); - if (type != SSH2_MSG_SERVICE_ACCEPT) { - fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type); - } - if (packet_remaining() > 0) { - char *reply = packet_get_string(&plen); - debug("service_accept: %s", reply); - xfree(reply); - } else { - /* payload empty for ssh-2.0.13 ?? */ - debug("buggy server: service_accept w/o service"); - } - packet_done(); - debug("got SSH2_MSG_SERVICE_ACCEPT"); - - /* INITIAL request for auth */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(server_user); - packet_put_cstring(service); - packet_put_cstring("none"); - packet_send(); - packet_write_wait(); - - for (;;) { - sent = 0; - type = packet_read(&plen); - if (type == SSH2_MSG_USERAUTH_SUCCESS) - break; - if (type != SSH2_MSG_USERAUTH_FAILURE) - fatal("access denied: %d", type); - /* SSH2_MSG_USERAUTH_FAILURE means: try again */ - auths = packet_get_string(&dlen); - debug("authentications that can continue: %s", auths); - partial = packet_get_char(); - packet_done(); - if (partial) - debug("partial success"); - if (options.dsa_authentication && - strstr(auths, "publickey") != NULL) { - if (ac != NULL) - sent = ssh2_try_agent(ac, - server_user, host, service); - if (!sent) { - while (i < options.num_identity_files2) { - sent = ssh2_try_pubkey( - options.identity_files2[i++], - server_user, host, service); - if (sent) - break; - } - } - } - if (!sent) { - if (options.password_authentication && - !options.batch_mode && - strstr(auths, "password") != NULL) { - sent = ssh2_try_passwd(server_user, host, service); - } - } - if (!sent) - fatal("Permission denied (%s).", auths); - xfree(auths); - } - if (ac != NULL) - ssh_close_authentication_connection(ac); - packet_done(); - debug("ssh-userauth2 successfull"); + if (authctxt->agent != NULL) + sent = userauth_pubkey_agent(authctxt); + while (sent == 0 && idx < options.num_identity_files2) + sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]); + return sent; +} + + +/* find auth method */ + +#define DELIM "," + +static char *def_authlist = "publickey,password"; +static char *authlist_current = NULL; /* clean copy used for comparison */ +static char *authname_current = NULL; /* last used auth method */ +static char *authlist_working = NULL; /* copy that gets modified by strtok_r() */ +static char *authlist_state = NULL; /* state variable for strtok_r() */ + +/* + * Before starting to use a new authentication method list sent by the + * server, reset internal variables. This should also be called when + * finished processing server list to free resources. + */ +void +authmethod_clear() +{ + if (authlist_current != NULL) { + xfree(authlist_current); + authlist_current = NULL; + } + if (authlist_working != NULL) { + xfree(authlist_working); + authlist_working = NULL; + } + if (authname_current != NULL) { + xfree(authname_current); + authlist_state = NULL; + } + if (authlist_state != NULL) + authlist_state = NULL; + return; +} + +/* + * given auth method name, if configurable options permit this method fill + * in auth_ident field and return true, otherwise return false. + */ +int +authmethod_is_enabled(Authmethod *method) +{ + if (method == NULL) + return 0; + /* return false if options indicate this method is disabled */ + if (method->enabled == NULL || *method->enabled == 0) + return 0; + /* return false if batch mode is enabled but method needs interactive mode */ + if (method->batch_flag != NULL && *method->batch_flag != 0) + return 0; + return 1; +} + +Authmethod * +authmethod_lookup(const char *name) +{ + Authmethod *method = NULL; + if (name != NULL) + for (method = authmethods; method->name != NULL; method++) + if (strcmp(name, method->name) == 0) + return method; + debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); + return NULL; +} + +/* + * Given the authentication method list sent by the server, return the + * next method we should try. If the server initially sends a nil list, + * use a built-in default list. If the server sends a nil list after + * previously sending a valid list, continue using the list originally + * sent. + */ + +Authmethod * +authmethod_get(char *authlist) +{ + char *name = NULL; + Authmethod *method = NULL; + + /* Use a suitable default if we're passed a nil list. */ + if (authlist == NULL || strlen(authlist) == 0) + authlist = def_authlist; + + if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) { + /* start over if passed a different list */ + authmethod_clear(); + authlist_current = xstrdup(authlist); + authlist_working = xstrdup(authlist); + name = strtok_r(authlist_working, DELIM, &authlist_state); + } else { + /* + * try to use previously used authentication method + * or continue to use previously passed list + */ + name = (authname_current != NULL) ? + authname_current : strtok_r(NULL, DELIM, &authlist_state); + } + + while (name != NULL) { + method = authmethod_lookup(name); + if (method != NULL && authmethod_is_enabled(method)) + break; + name = strtok_r(NULL, DELIM, &authlist_state); + } + + if (authname_current != NULL) + xfree(authname_current); + + if (name != NULL) { + debug("next auth method to try is %s", name); + authname_current = xstrdup(name); + return method; + } else { + debug("no more auth methods to try"); + authname_current = NULL; + return NULL; + } } diff --git a/sshd.8 b/sshd.8 index 6c08a377e..cd2a8e962 100644 --- a/sshd.8 +++ b/sshd.8 @@ -432,8 +432,7 @@ Default is If set then if password authentication through Kerberos fails then the password will be validated via any additional local mechanism such as -.Pa /etc/passwd -or SecurID. +.Pa /etc/passwd . Default is .Dq yes . .It Cm KerberosTgtPassing diff --git a/sshd.c b/sshd.c index e94b5d11d..c11a89609 100644 --- a/sshd.c +++ b/sshd.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.127 2000/09/12 20:53:10 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -1336,7 +1336,7 @@ do_ssh2_kex() #ifdef DEBUG_KEXDH fprintf(stderr, "\ndh_client_pub= "); - bignum_print(dh_client_pub); + BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif @@ -1346,12 +1346,13 @@ do_ssh2_kex() #ifdef DEBUG_KEXDH fprintf(stderr, "\np= "); - bignum_print(dh->p); + BN_print_fp(stderr, dh->p); fprintf(stderr, "\ng= "); - bignum_print(dh->g); + bn_print(dh->g); fprintf(stderr, "\npub= "); - bignum_print(dh->pub_key); + BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); + DHparams_print_fp(stderr, dh); #endif if (!dh_pub_is_valid(dh, dh_client_pub)) packet_disconnect("bad client public DH value");