From cb5eb4f19f8c9639a3e0859fbc753185d4a75ade Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 20 Jun 2009 08:55:46 -1000 Subject: [PATCH] Upgrade to OpenSSH-5.2p1. Security: * This release changes the default cipher order to prefer the AES CTR modes and the revised "arcfour256" mode to CBC mode ciphers that are susceptible to CPNI-957037 "Plaintext Recovery Attack Against SSH". * This release also adds countermeasures to mitigate CPNI-957037-style attacks against the SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid packet length or Message Authentication Code, ssh/sshd will continue reading up to the maximum supported packet length rather than immediately terminating the connection. This eliminates most of the known differences in behaviour that leaked information about the plaintext of injected data which formed the basis of this attack. We believe that these attacks are rendered infeasible by these changes. New features: * Added a -y option to ssh(1) to force logging to syslog rather than stderr, which is useful when running daemonised (ssh -f) * The sshd_config(5) ForceCommand directive now accepts commandline arguments for the internal-sftp server. * The ssh(1) ~C escape commandline now support runtime creation of dynamic (-D) port forwards. * Support the SOCKS4A protocol in ssh(1) dynamic (-D) forwards. (bz#1482) * Support remote port forwarding with a listen port of '0'. This informs the server that it should dynamically allocate a listen port and report it back to the client. (bz#1003) * sshd(8) now supports setting PermitEmptyPasswords and AllowAgentForwarding in Match blocks Bug and documentation fixes * Repair a ssh(1) crash introduced in openssh-5.1 when the client is sent a zero-length banner (bz#1496) * Due to interoperability problems with certain broken SSH implementations, the eow@openssh.com and no-more-sessions@openssh.com protocol extensions are now only sent to peers that identify themselves as OpenSSH. * Make ssh(1) send the correct channel number for SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to avoid triggering 'Non-public channel' error messages on sshd(8) in openssh-5.1. * Avoid printing 'Non-public channel' warnings in sshd(8), since the ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a behaviour introduced in openssh-5.1). * Avoid double-free in ssh(1) ~C escape -L handler (bz#1539) * Correct fail-on-error behaviour in sftp(1) batchmode for remote stat operations. (bz#1541) * Disable nonfunctional ssh(1) ~C escape handler in multiplex slave connections. (bz#1543) * Avoid hang in ssh(1) when attempting to connect to a server that has MaxSessions=0 set. * Multiple fixes to sshd(8) configuration test (-T) mode * Several core and portable OpenSSH bugs fixed: 1380, 1412, 1418, 1419, 1421, 1490, 1491, 1492, 1514, 1515, 1518, 1520, 1538, 1540 * Many manual page improvements. --- crypto/openssh/PROTOCOL | 13 +- crypto/openssh/README | 4 +- crypto/openssh/README.DELETED | 4 + crypto/openssh/addrmatch.c | 7 +- crypto/openssh/auth-options.c | 6 +- crypto/openssh/auth.c | 2 +- crypto/openssh/auth.h | 6 +- crypto/openssh/auth2-chall.c | 10 +- crypto/openssh/auth2.c | 12 +- crypto/openssh/canohost.c | 4 +- crypto/openssh/canohost.h | 4 +- crypto/openssh/channels.c | 187 ++++++++++++--- crypto/openssh/channels.h | 8 +- crypto/openssh/cipher.c | 49 ++-- crypto/openssh/cipher.h | 3 +- crypto/openssh/clientloop.c | 44 ++-- crypto/openssh/compat.c | 5 +- crypto/openssh/compat.h | 3 +- crypto/openssh/defines.h | 8 +- crypto/openssh/dispatch.c | 3 +- crypto/openssh/jpake.h | 134 +++++++++++ crypto/openssh/kex.c | 2 +- crypto/openssh/kexgexs.c | 27 ++- crypto/openssh/key.c | 7 +- crypto/openssh/loginrec.c | 139 ++++++----- crypto/openssh/misc.c | 27 +-- crypto/openssh/monitor.c | 231 +++++++++++++++++- crypto/openssh/monitor.h | 9 +- crypto/openssh/monitor_fdpass.c | 29 ++- crypto/openssh/monitor_wrap.c | 167 ++++++++++++- crypto/openssh/monitor_wrap.h | 22 +- crypto/openssh/myproposal.h | 9 +- crypto/openssh/nchan.c | 12 +- crypto/openssh/openbsd-compat/xmmap.c | 5 +- crypto/openssh/packet.c | 75 +++++- crypto/openssh/pathnames.h | 10 +- crypto/openssh/readconf.c | 130 +++++++---- crypto/openssh/readconf.h | 9 +- crypto/openssh/scp.c | 4 +- crypto/openssh/servconf.c | 55 +++-- crypto/openssh/servconf.h | 10 +- crypto/openssh/serverloop.c | 18 +- crypto/openssh/session.c | 18 +- crypto/openssh/sftp-server-main.c | 5 +- crypto/openssh/sftp.1 | 15 +- crypto/openssh/sftp.c | 81 +++---- crypto/openssh/ssh-keygen.1 | 5 +- crypto/openssh/ssh-keygen.c | 18 +- crypto/openssh/ssh-keyscan.1 | 8 +- crypto/openssh/ssh-keyscan.c | 9 +- crypto/openssh/ssh.1 | 25 +- crypto/openssh/ssh.c | 58 +++-- crypto/openssh/ssh2.h | 9 +- crypto/openssh/ssh_config | 5 +- crypto/openssh/ssh_config.5 | 28 ++- crypto/openssh/sshconnect.c | 10 +- crypto/openssh/sshconnect2.c | 322 +++++++++++++++++++++++++- crypto/openssh/sshd.8 | 6 +- crypto/openssh/sshd.c | 5 +- crypto/openssh/sshd_config.5 | 14 +- crypto/openssh/sshpty.c | 9 + crypto/openssh/ttymodes.c | 7 +- crypto/openssh/uidswap.c | 10 + 63 files changed, 1686 insertions(+), 494 deletions(-) create mode 100644 crypto/openssh/jpake.h diff --git a/crypto/openssh/PROTOCOL b/crypto/openssh/PROTOCOL index 37fd536d98..5aada630dd 100644 --- a/crypto/openssh/PROTOCOL +++ b/crypto/openssh/PROTOCOL @@ -64,6 +64,12 @@ remain open after a "eow@openssh.com" has been sent and more data may still be sent in the other direction. This message does not consume window space and may be sent even if no window space is available. +NB. due to certain broken SSH implementations aborting upon receipt +of this message (in contravention of RFC4254 section 5.4), this +message is only sent to OpenSSH peers (identified by banner). +Other SSH implementations may be whitelisted to receive this message +upon request. + 4. connection: disallow additional sessions extension "no-more-sessions@openssh.com" @@ -87,6 +93,11 @@ connection. Note that this is not a general defence against compromised clients (that is impossible), but it thwarts a simple attack. +NB. due to certain broken SSH implementations aborting upon receipt +of this message, the no-more-sessions request is only sent to OpenSSH +servers (identified by banner). Other SSH implementations may be +whitelisted to receive this message upon request. + 5. connection: Tunnel forward extension "tun@openssh.com" OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" @@ -240,4 +251,4 @@ The values of the f_flag bitmask are as follows: Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are advertised in the SSH_FXP_VERSION hello with version "2". -$OpenBSD: PROTOCOL,v 1.11 2008/07/05 05:16:01 djm Exp $ +$OpenBSD: PROTOCOL,v 1.12 2009/02/14 06:35:49 djm Exp $ diff --git a/crypto/openssh/README b/crypto/openssh/README index 183d92f70e..9de00c0933 100644 --- a/crypto/openssh/README +++ b/crypto/openssh/README @@ -1,4 +1,4 @@ -See http://www.openssh.com/txt/release-5.1 for the release notes. +See http://www.openssh.com/txt/release-5.2 for the release notes. - A Japanese translation of this document and of the OpenSSH FAQ is - available at http://www.unixuser.org/~haruyama/security/openssh/index.html @@ -62,4 +62,4 @@ References - [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 [7] http://www.openssh.com/faq.html -$Id: README,v 1.69 2008/07/21 08:21:52 djm Exp $ +$Id: README,v 1.70 2009/02/23 00:11:57 djm Exp $ diff --git a/crypto/openssh/README.DELETED b/crypto/openssh/README.DELETED index dcf4caee56..202f8b4986 100644 --- a/crypto/openssh/README.DELETED +++ b/crypto/openssh/README.DELETED @@ -11,6 +11,7 @@ aclocal.m4 auth-shadow.c auth-sia.c auth-sia.h +auth2-jpake.c buildpkg.sh.in config.guess config.h.in @@ -21,6 +22,7 @@ contrib/ fixpaths fixprogs install-sh +jpake.c logintest.c md-sha256.c mdoc2man.awk @@ -32,6 +34,7 @@ openbsd-compat/Makefile.in openbsd-compat/base64.c openbsd-compat/basename.c openbsd-compat/bindresvport.c +openbsd-compat/bsd-arc4random.c openbsd-compat/bsd-asprintf.c openbsd-compat/bsd-closefrom.c openbsd-compat/bsd-cray.c @@ -83,6 +86,7 @@ opensshd.init.in regress/ scard/ scard.h +schnorr.c scp.0 sftp-server.0 sftp.0 diff --git a/crypto/openssh/addrmatch.c b/crypto/openssh/addrmatch.c index 2086afe84f..d39885b7bd 100644 --- a/crypto/openssh/addrmatch.c +++ b/crypto/openssh/addrmatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: addrmatch.c,v 1.3 2008/06/10 23:06:19 djm Exp $ */ +/* $OpenBSD: addrmatch.c,v 1.4 2008/12/10 03:55:20 stevesk Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller @@ -31,6 +31,7 @@ #include "match.h" #include "log.h" +#include "xmalloc.h" struct xaddr { sa_family_t af; @@ -97,7 +98,9 @@ addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) return -1; xa->af = AF_INET6; memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID xa->scope_id = in6->sin6_scope_id; +#endif break; default: return -1; @@ -415,7 +418,7 @@ addr_match_list(const char *addr, const char *_list) goto foundit; } } - free(o); + xfree(o); return ret; } diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c index 25361455e5..ab085c2339 100644 --- a/crypto/openssh/auth-options.c +++ b/crypto/openssh/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.43 2008/06/10 23:06:19 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.44 2009/01/22 10:09:16 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -255,7 +255,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) cp = "permitopen=\""; if (strncasecmp(opts, cp, strlen(cp)) == 0) { char *host, *p; - u_short port; + int port; char *patterns = xmalloc(strlen(opts) + 1); opts += strlen(cp); @@ -293,7 +293,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) goto bad_option; } host = cleanhostname(host); - if (p == NULL || (port = a2port(p)) == 0) { + if (p == NULL || (port = a2port(p)) <= 0) { debug("%.100s, line %lu: Bad permitopen port " "<%.100s>", file, linenum, p ? p : ""); auth_debug_add("%.100s, line %lu: " diff --git a/crypto/openssh/auth.c b/crypto/openssh/auth.c index 2370e5c2c7..3585daadc1 100644 --- a/crypto/openssh/auth.c +++ b/crypto/openssh/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.79 2008/07/02 12:03:51 dtucker Exp $ */ +/* $OpenBSD: auth.c,v 1.80 2008/11/04 07:58:09 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * diff --git a/crypto/openssh/auth.h b/crypto/openssh/auth.h index 6a70f0eb6a..3a70f44213 100644 --- a/crypto/openssh/auth.h +++ b/crypto/openssh/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.61 2008/07/02 12:03:51 dtucker Exp $ */ +/* $OpenBSD: auth.h,v 1.62 2008/11/04 08:22:12 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -59,6 +59,7 @@ struct Authctxt { struct passwd *pw; /* set if 'valid' */ char *style; void *kbdintctxt; + void *jpake_ctx; #ifdef BSD_AUTH auth_session_t *as; #endif @@ -156,6 +157,9 @@ int bsdauth_respond(void *, u_int, char **); int skey_query(void *, char **, char **, u_int *, char ***, u_int **); int skey_respond(void *, u_int, char **); +void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **); +void auth2_jpake_stop(Authctxt *); + int allowed_user(struct passwd *); struct passwd * getpwnamallow(const char *user); diff --git a/crypto/openssh/auth2-chall.c b/crypto/openssh/auth2-chall.c index d816578c62..e6dbffe22b 100644 --- a/crypto/openssh/auth2-chall.c +++ b/crypto/openssh/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.33 2007/09/21 08:15:29 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.34 2008/12/09 04:32:22 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -281,7 +281,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; KbdintAuthctxt *kbdintctxt; - int authenticated = 0, res, len; + int authenticated = 0, res; u_int i, nresp; char **response = NULL, *method; @@ -330,11 +330,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt) break; } - len = strlen("keyboard-interactive") + 2 + - strlen(kbdintctxt->device->name); - method = xmalloc(len); - snprintf(method, len, "keyboard-interactive/%s", - kbdintctxt->device->name); + xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name); if (!authctxt->postponed) { if (authenticated) { diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c index a835abfc6c..ecf8570526 100644 --- a/crypto/openssh/auth2.c +++ b/crypto/openssh/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.119 2008/07/04 23:30:16 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.120 2008/11/04 08:22:12 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -71,12 +71,18 @@ extern Authmethod method_hostbased; #ifdef GSSAPI extern Authmethod method_gssapi; #endif +#ifdef JPAKE +extern Authmethod method_jpake; +#endif Authmethod *authmethods[] = { &method_none, &method_pubkey, #ifdef GSSAPI &method_gssapi, +#endif +#ifdef JPAKE + &method_jpake, #endif &method_passwd, &method_kbdint, @@ -257,8 +263,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } /* reset state */ auth2_challenge_stop(authctxt); +#ifdef JPAKE + auth2_jpake_stop(authctxt); +#endif #ifdef GSSAPI + /* XXX move to auth2_gssapi_stop() */ dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif diff --git a/crypto/openssh/canohost.c b/crypto/openssh/canohost.c index 42011fd0ac..7138f48d0f 100644 --- a/crypto/openssh/canohost.c +++ b/crypto/openssh/canohost.c @@ -1,4 +1,4 @@ -/* $OpenBSD: canohost.c,v 1.63 2008/06/12 00:03:49 dtucker Exp $ */ +/* $OpenBSD: canohost.c,v 1.64 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -342,7 +342,7 @@ get_remote_name_or_ip(u_int utmp_len, int use_dns) /* Returns the local/remote port for the socket. */ -static int +int get_sock_port(int sock, int local) { struct sockaddr_storage from; diff --git a/crypto/openssh/canohost.h b/crypto/openssh/canohost.h index e33e8941b2..d9b41ffe54 100644 --- a/crypto/openssh/canohost.h +++ b/crypto/openssh/canohost.h @@ -1,4 +1,4 @@ -/* $OpenBSD: canohost.h,v 1.9 2006/03/25 22:22:42 djm Exp $ */ +/* $OpenBSD: canohost.h,v 1.10 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen @@ -23,5 +23,7 @@ char *get_local_name(int); int get_remote_port(void); int get_local_port(void); +int get_sock_port(int, int); + void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c index 69c99c9b2f..dea60ba24e 100644 --- a/crypto/openssh/channels.c +++ b/crypto/openssh/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.286 2008/07/16 11:52:19 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.295 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -296,6 +296,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, buffer_init(&c->input); buffer_init(&c->output); buffer_init(&c->extended); + c->path = NULL; c->ostate = CHAN_OUTPUT_OPEN; c->istate = CHAN_INPUT_OPEN; c->flags = 0; @@ -402,6 +403,10 @@ channel_free(Channel *c) xfree(c->remote_name); c->remote_name = NULL; } + if (c->path) { + xfree(c->path); + c->path = NULL; + } while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { if (cc->abandon_cb != NULL) cc->abandon_cb(c, cc->ctx); @@ -691,7 +696,7 @@ channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx) Channel *c = channel_lookup(id); if (c == NULL) { - logit("channel_register_open_comfirm: %d: bad id", id); + logit("channel_register_open_confirm: %d: bad id", id); return; } c->open_confirm = fn; @@ -980,7 +985,7 @@ static int channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) { char *p, *host; - u_int len, have, i, found; + u_int len, have, i, found, need; char username[256]; struct { u_int8_t version; @@ -996,10 +1001,20 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) if (have < len) return 0; p = buffer_ptr(&c->input); + + need = 1; + /* SOCKS4A uses an invalid IP address 0.0.0.x */ + if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) { + debug2("channel %d: socks4a request", c->self); + /* ... and needs an extra string (the hostname) */ + need = 2; + } + /* Check for terminating NUL on the string(s) */ for (found = 0, i = len; i < have; i++) { if (p[i] == '\0') { - found = 1; - break; + found++; + if (found == need) + break; } if (i > 1024) { /* the peer is probably sending garbage */ @@ -1008,7 +1023,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) return -1; } } - if (!found) + if (found < need) return 0; buffer_get(&c->input, (char *)&s4_req.version, 1); buffer_get(&c->input, (char *)&s4_req.command, 1); @@ -1018,23 +1033,46 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) p = buffer_ptr(&c->input); len = strlen(p); debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); + len++; /* trailing '\0' */ if (len > have) fatal("channel %d: decode socks4: len %d > have %d", c->self, len, have); strlcpy(username, p, sizeof(username)); buffer_consume(&c->input, len); - buffer_consume(&c->input, 1); /* trailing '\0' */ - host = inet_ntoa(s4_req.dest_addr); - strlcpy(c->path, host, sizeof(c->path)); + if (c->path != NULL) { + xfree(c->path); + c->path = NULL; + } + if (need == 1) { /* SOCKS4: one string */ + host = inet_ntoa(s4_req.dest_addr); + c->path = xstrdup(host); + } else { /* SOCKS4A: two strings */ + have = buffer_len(&c->input); + p = buffer_ptr(&c->input); + len = strlen(p); + debug2("channel %d: decode socks4a: host %s/%d", + c->self, p, len); + len++; /* trailing '\0' */ + if (len > have) + fatal("channel %d: decode socks4a: len %d > have %d", + c->self, len, have); + if (len > NI_MAXHOST) { + error("channel %d: hostname \"%.100s\" too long", + c->self, p); + return -1; + } + c->path = xstrdup(p); + buffer_consume(&c->input, len); + } c->host_port = ntohs(s4_req.dest_port); debug2("channel %d: dynamic request: socks4 host %s port %u command %u", - c->self, host, c->host_port, s4_req.command); + c->self, c->path, c->host_port, s4_req.command); if (s4_req.command != 1) { - debug("channel %d: cannot handle: socks4 cn %d", - c->self, s4_req.command); + debug("channel %d: cannot handle: %s cn %d", + c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command); return -1; } s4_rsp.version = 0; /* vn: 0 for reply */ @@ -1065,7 +1103,7 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) u_int8_t atyp; } s5_req, s5_rsp; u_int16_t dest_port; - u_char *p, dest_addr[255+1]; + u_char *p, dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; u_int have, need, i, found, nmethods, addrlen, af; debug2("channel %d: decode socks5", c->self); @@ -1138,10 +1176,22 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) buffer_get(&c->input, (char *)&dest_addr, addrlen); buffer_get(&c->input, (char *)&dest_port, 2); dest_addr[addrlen] = '\0'; - if (s5_req.atyp == SSH_SOCKS5_DOMAIN) - strlcpy(c->path, (char *)dest_addr, sizeof(c->path)); - else if (inet_ntop(af, dest_addr, c->path, sizeof(c->path)) == NULL) - return -1; + if (c->path != NULL) { + xfree(c->path); + c->path = NULL; + } + if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { + if (addrlen >= NI_MAXHOST) { + error("channel %d: dynamic request: socks5 hostname " + "\"%.100s\" too long", c->self, dest_addr); + return -1; + } + c->path = xstrdup(dest_addr); + } else { + if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL) + return -1; + c->path = xstrdup(ntop); + } c->host_port = ntohs(dest_port); debug2("channel %d: dynamic request: socks5 host %s port %u command %u", @@ -1370,7 +1420,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) c->local_window_max, c->local_maxpacket, 0, rtype, 1); nc->listening_port = c->listening_port; nc->host_port = c->host_port; - strlcpy(nc->path, c->path, sizeof(nc->path)); + if (c->path != NULL) + nc->path = xstrdup(c->path); if (nextstate == SSH_CHANNEL_DYNAMIC) { /* @@ -2311,8 +2362,8 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) xfree(lang); } packet_check_eom(); - /* Free the channel. This will also close the socket. */ - channel_free(c); + /* Schedule the channel for cleanup/deletion. */ + chan_mark_dead(c); } /* ARGSUSED */ @@ -2377,18 +2428,18 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) { Channel *c; struct channel_confirm *cc; - int remote_id; + int id; /* Reset keepalive timeout */ keep_alive_timeouts = 0; - remote_id = packet_get_int(); + id = packet_get_int(); packet_check_eom(); - debug2("channel_input_confirm: type %d id %d", type, remote_id); + debug2("channel_input_status_confirm: type %d id %d", type, id); - if ((c = channel_lookup(remote_id)) == NULL) { - logit("channel_input_success_failure: %d: unknown", remote_id); + if ((c = channel_lookup(id)) == NULL) { + logit("channel_input_status_confirm: %d: unknown", id); return; } ; @@ -2409,7 +2460,8 @@ channel_set_af(int af) } static int -channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, +channel_setup_fwd_listener(int type, const char *listen_addr, + u_short listen_port, int *allocated_listen_port, const char *host_to_connect, u_short port_to_connect, int gateway_ports) { Channel *c; @@ -2417,6 +2469,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por struct addrinfo hints, *ai, *aitop; const char *host, *addr; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + in_port_t *lport_p; host = (type == SSH_CHANNEL_RPORT_LISTENER) ? listen_addr : host_to_connect; @@ -2426,7 +2479,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por error("No forward host name."); return 0; } - if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { + if (strlen(host) >= NI_MAXHOST) { error("Forward host name too long."); return 0; } @@ -2485,10 +2538,29 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por } return 0; } - + if (allocated_listen_port != NULL) + *allocated_listen_port = 0; for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) + switch (ai->ai_family) { + case AF_INET: + lport_p = &((struct sockaddr_in *)ai->ai_addr)-> + sin_port; + break; + case AF_INET6: + lport_p = &((struct sockaddr_in6 *)ai->ai_addr)-> + sin6_port; + break; + default: continue; + } + /* + * If allocating a port for -R forwards, then use the + * same port for all address families. + */ + if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && + allocated_listen_port != NULL && *allocated_listen_port > 0) + *lport_p = htons(*allocated_listen_port); + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error("channel_setup_fwd_listener: getnameinfo failed"); @@ -2504,7 +2576,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por channel_set_reuseaddr(sock); - debug("Local forwarding listening on %s port %s.", ntop, strport); + debug("Local forwarding listening on %s port %s.", + ntop, strport); /* Bind the socket to the address. */ if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { @@ -2523,11 +2596,24 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por close(sock); continue; } + + /* + * listen_port == 0 requests a dynamically allocated port - + * record what we got. + */ + if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && + allocated_listen_port != NULL && + *allocated_listen_port == 0) { + *allocated_listen_port = get_sock_port(sock, 1); + debug("Allocated listen port %d", + *allocated_listen_port); + } + /* Allocate a channel number for the socket. */ c = channel_new("port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); - strlcpy(c->path, host, sizeof(c->path)); + c->path = xstrdup(host); c->host_port = port_to_connect; c->listening_port = listen_port; success = 1; @@ -2549,8 +2635,7 @@ channel_cancel_rport_listener(const char *host, u_short port) Channel *c = channels[i]; if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && - strncmp(c->path, host, sizeof(c->path)) == 0 && - c->listening_port == port) { + strcmp(c->path, host) == 0 && c->listening_port == port) { debug2("%s: close channel %d", __func__, i); channel_free(c); found = 1; @@ -2566,17 +2651,18 @@ channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, const char *host_to_connect, u_short port_to_connect, int gateway_ports) { return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, - listen_host, listen_port, host_to_connect, port_to_connect, + listen_host, listen_port, NULL, host_to_connect, port_to_connect, gateway_ports); } /* protocol v2 remote port fwd, used by sshd */ int channel_setup_remote_fwd_listener(const char *listen_address, - u_short listen_port, int gateway_ports) + u_short listen_port, int *allocated_listen_port, int gateway_ports) { return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, - listen_address, listen_port, NULL, 0, gateway_ports); + listen_address, listen_port, allocated_listen_port, + NULL, 0, gateway_ports); } /* @@ -2791,10 +2877,16 @@ channel_print_adm_permitted_opens(void) { int i; + printf("permitopen"); + if (num_adm_permitted_opens == 0) { + printf(" any\n"); + return; + } for (i = 0; i < num_adm_permitted_opens; i++) if (permitted_adm_opens[i].host_to_connect != NULL) printf(" %s:%d", permitted_adm_opens[i].host_to_connect, permitted_adm_opens[i].port_to_connect); + printf("\n"); } /* Try to start non-blocking connect to next host in cctx list */ @@ -3074,7 +3166,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, } static int -connect_local_xsocket(u_int dnr) +connect_local_xsocket_path(const char *pathname) { int sock; struct sockaddr_un addr; @@ -3084,7 +3176,7 @@ connect_local_xsocket(u_int dnr) error("socket: %.100s", strerror(errno)); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X, dnr); + strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) return sock; close(sock); @@ -3092,6 +3184,14 @@ connect_local_xsocket(u_int dnr) return -1; } +static int +connect_local_xsocket(u_int dnr) +{ + char buf[1024]; + snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr); + return connect_local_xsocket_path(buf); +} + int x11_connect_display(void) { @@ -3113,6 +3213,17 @@ x11_connect_display(void) * connection to the real X server. */ + /* Check if the display is from launchd. */ +#ifdef __APPLE__ + if (strncmp(display, "/tmp/launch", 11) == 0) { + sock = connect_local_xsocket_path(display); + if (sock < 0) + return -1; + + /* OK, we now have a connection to the display. */ + return sock; + } +#endif /* * Check if it is a unix domain socket. Unix domain displays are in * one of the following formats: unix:d[.s], :d[.s], ::d[.s] diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h index 108b360681..1488ed7e59 100644 --- a/crypto/openssh/channels.h +++ b/crypto/openssh/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.96 2008/06/15 20:06:26 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.98 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen @@ -55,8 +55,6 @@ #define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */ #define SSH_CHANNEL_MAX_TYPE 15 -#define SSH_CHANNEL_PATH_LEN 256 - struct Channel; typedef struct Channel Channel; @@ -105,7 +103,7 @@ struct Channel { Buffer output; /* data received over encrypted connection for * send on socket */ Buffer extended; - char path[SSH_CHANNEL_PATH_LEN]; + char *path; /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ int host_port; /* remote port to connect for forwards */ @@ -247,7 +245,7 @@ int channel_request_remote_forwarding(const char *, u_short, int channel_setup_local_fwd_listener(const char *, u_short, const char *, u_short, int); void channel_request_rforward_cancel(const char *host, u_short port); -int channel_setup_remote_fwd_listener(const char *, u_short, int); +int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); int channel_cancel_rport_listener(const char *, u_short); /* x11 forwarding */ diff --git a/crypto/openssh/cipher.c b/crypto/openssh/cipher.c index b264063c40..bb5c0ac3a2 100644 --- a/crypto/openssh/cipher.c +++ b/crypto/openssh/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.81 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -63,31 +63,32 @@ struct Cipher { u_int block_size; u_int key_len; u_int discard_len; + u_int cbc_mode; const EVP_CIPHER *(*evptype)(void); } ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des }, - { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf }, - - { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc }, - { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc }, - { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc }, - { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4 }, - { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4 }, - { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4 }, - { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc }, - { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc }, - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, + { "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc }, + { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, + { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf }, + + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, + { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc }, + { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc }, + { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 }, + { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 }, + { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 }, + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, { "rijndael-cbc@lysator.liu.se", - SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_128_ctr }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_128_ctr }, + SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, + { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, + { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, + { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, #ifdef USE_CIPHER_ACSS - { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, EVP_acss }, + { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss }, #endif - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, NULL } + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } }; /*--*/ @@ -110,6 +111,12 @@ cipher_get_number(const Cipher *c) return (c->number); } +u_int +cipher_is_cbc(const Cipher *c) +{ + return (c->cbc_mode); +} + u_int cipher_mask_ssh1(int client) { diff --git a/crypto/openssh/cipher.h b/crypto/openssh/cipher.h index 49bbc1682b..3dd2270bbe 100644 --- a/crypto/openssh/cipher.h +++ b/crypto/openssh/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.36 2006/03/25 22:22:42 djm Exp $ */ +/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */ /* * Author: Tatu Ylonen @@ -81,6 +81,7 @@ void cipher_cleanup(CipherContext *); void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); u_int cipher_blocksize(const Cipher *); u_int cipher_keylen(const Cipher *); +u_int cipher_is_cbc(const Cipher *); u_int cipher_get_number(const Cipher *); void cipher_get_keyiv(CipherContext *, u_char *, u_int); diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c index f10fab7698..a2d2d1d074 100644 --- a/crypto/openssh/clientloop.c +++ b/crypto/openssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.201 2008/07/16 11:51:14 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.209 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -107,7 +107,6 @@ #include "atomicio.h" #include "sshpty.h" #include "misc.h" -#include "monitor_fdpass.h" #include "match.h" #include "msg.h" @@ -765,8 +764,8 @@ process_cmdline(void) void (*handler)(int); char *s, *cmd, *cancel_host; int delete = 0; - int local = 0; - u_short cancel_port; + int local = 0, remote = 0, dynamic = 0; + int cancel_port; Forward fwd; bzero(&fwd, sizeof(fwd)); @@ -790,6 +789,8 @@ process_cmdline(void) "Request local forward"); logit(" -R[bind_address:]port:host:hostport " "Request remote forward"); + logit(" -D[bind_address:]port " + "Request dynamic forward"); logit(" -KR[bind_address:]port " "Cancel remote forward"); if (!options.permit_local_command) @@ -809,17 +810,22 @@ process_cmdline(void) delete = 1; s++; } - if (*s != 'L' && *s != 'R') { + if (*s == 'L') + local = 1; + else if (*s == 'R') + remote = 1; + else if (*s == 'D') + dynamic = 1; + else { logit("Invalid command."); goto out; } - if (*s == 'L') - local = 1; - if (local && delete) { + + if ((local || dynamic) && delete) { logit("Not supported."); goto out; } - if ((!local || delete) && !compat20) { + if (remote && delete && !compat20) { logit("Not supported for SSH protocol version 1."); goto out; } @@ -837,17 +843,17 @@ process_cmdline(void) cancel_port = a2port(cancel_host); cancel_host = NULL; } - if (cancel_port == 0) { + if (cancel_port <= 0) { logit("Bad forwarding close port"); goto out; } channel_request_rforward_cancel(cancel_host, cancel_port); } else { - if (!parse_forward(&fwd, s)) { + if (!parse_forward(&fwd, s, dynamic, remote)) { logit("Bad forwarding specification."); goto out; } - if (local) { + if (local || dynamic) { if (channel_setup_local_fwd_listener(fwd.listen_host, fwd.listen_port, fwd.connect_host, fwd.connect_port, options.gateway_ports) < 0) { @@ -1036,7 +1042,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, Supported escape sequences:\r\n\ %c. - terminate session\r\n\ %cB - send a BREAK to the remote system\r\n\ - %cC - open a command line\r\n\ %cR - Request rekey (SSH protocol 2 only)\r\n\ %c# - list forwarded connections\r\n\ %c? - this message\r\n\ @@ -1045,8 +1050,7 @@ Supported escape sequences:\r\n\ escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, - escape_char, escape_char, - escape_char); + escape_char, escape_char); } else { snprintf(string, sizeof string, "%c?\r\n\ @@ -1081,6 +1085,8 @@ Supported escape sequences:\r\n\ continue; case 'C': + if (c && c->ctl_fd != -1) + goto noescape; process_cmdline(); continue; @@ -1632,7 +1638,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) { Channel *c = NULL; char *listen_address, *originator_address; - int listen_port, originator_port; + u_short listen_port, originator_port; /* Get rest of the packet */ listen_address = packet_get_string(NULL); @@ -1658,7 +1664,7 @@ client_request_x11(const char *request_type, int rchan) { Channel *c = NULL; char *originator; - int originator_port; + u_short originator_port; int sock; if (!options.forward_x11) { @@ -1722,7 +1728,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) return 0; if (!compat20) { - error("Tunnel forwarding is not support for protocol 1"); + error("Tunnel forwarding is not supported for protocol 1"); return -1; } @@ -1846,7 +1852,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) if (reply) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(id); + packet_put_int(c->remote_id); packet_send(); } xfree(rtype); diff --git a/crypto/openssh/compat.c b/crypto/openssh/compat.c index bc11315814..df3541df70 100644 --- a/crypto/openssh/compat.c +++ b/crypto/openssh/compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.c,v 1.77 2006/12/12 03:58:42 djm Exp $ */ +/* $OpenBSD: compat.c,v 1.78 2008/09/11 14:22:37 markus Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -91,7 +91,8 @@ compat_datafellows(const char *version) "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR }, { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, - { "OpenSSH*", 0 }, + { "OpenSSH_4*", 0 }, + { "OpenSSH*", SSH_NEW_OPENSSH }, { "*MindTerm*", 0 }, { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| SSH_OLD_SESSIONID|SSH_BUG_DEBUG| diff --git a/crypto/openssh/compat.h b/crypto/openssh/compat.h index 4d8ebc908a..16cf282a7a 100644 --- a/crypto/openssh/compat.h +++ b/crypto/openssh/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.41 2006/12/12 03:58:42 djm Exp $ */ +/* $OpenBSD: compat.h,v 1.42 2008/09/11 14:22:37 markus Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -57,6 +57,7 @@ #define SSH_BUG_FIRSTKEX 0x00800000 #define SSH_OLD_FORWARD_ADDR 0x01000000 #define SSH_BUG_RFWD_ADDR 0x02000000 +#define SSH_NEW_OPENSSH 0x04000000 void enable_compat13(void); void enable_compat20(void); diff --git a/crypto/openssh/defines.h b/crypto/openssh/defines.h index a8203ebbbf..536ec4978b 100644 --- a/crypto/openssh/defines.h +++ b/crypto/openssh/defines.h @@ -25,7 +25,7 @@ #ifndef _DEFINES_H #define _DEFINES_H -/* $Id: defines.h,v 1.151 2008/07/04 13:10:49 djm Exp $ */ +/* $Id: defines.h,v 1.153 2009/02/01 11:19:54 dtucker Exp $ */ /* Constants */ @@ -698,7 +698,7 @@ struct winsize { # define CUSTOM_SYS_AUTH_PASSWD 1 #endif -#if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) +#if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) && !defined(HAVE_SECUREWARE) # define CUSTOM_SYS_AUTH_PASSWD 1 #endif #if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) && !defined(BROKEN_LIBIAF) @@ -738,4 +738,8 @@ struct winsize { # define EWOULDBLOCK EAGAIN #endif +#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ +#define INET6_ADDRSTRLEN 46 +#endif + #endif /* _DEFINES_H */ diff --git a/crypto/openssh/dispatch.c b/crypto/openssh/dispatch.c index d6b63be4b7..64bb809474 100644 --- a/crypto/openssh/dispatch.c +++ b/crypto/openssh/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.21 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: dispatch.c,v 1.22 2008/10/31 15:05:34 stevesk Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -37,7 +37,6 @@ #include "packet.h" #include "compat.h" -#define DISPATCH_MIN 0 #define DISPATCH_MAX 255 dispatch_fn *dispatch[DISPATCH_MAX]; diff --git a/crypto/openssh/jpake.h b/crypto/openssh/jpake.h new file mode 100644 index 0000000000..a3d800cd3c --- /dev/null +++ b/crypto/openssh/jpake.h @@ -0,0 +1,134 @@ +/* $OpenBSD: jpake.h,v 1.1 2008/11/04 08:22:13 djm Exp $ */ +/* + * Copyright (c) 2008 Damien Miller. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef JPAKE_H +#define JPAKE_H + +#include + +#include + +/* Set JPAKE_DEBUG in CFLAGS for privacy-violating debugging */ +#ifndef JPAKE_DEBUG +# define JPAKE_DEBUG_BN(a) +# define JPAKE_DEBUG_BUF(a) +# define JPAKE_DEBUG_CTX(a) +#else +# define JPAKE_DEBUG_BN(a) jpake_debug3_bn a +# define JPAKE_DEBUG_BUF(a) jpake_debug3_buf a +# define JPAKE_DEBUG_CTX(a) jpake_dump a +#endif /* SCHNORR_DEBUG */ + +struct jpake_group { + BIGNUM *p, *q, *g; +}; + +#define KZP_ID_LEN 16 /* Length of client and server IDs */ + +struct jpake_ctx { + /* Parameters */ + struct jpake_group *grp; + + /* Private values shared by client and server */ + BIGNUM *s; /* Secret (salted, crypted password) */ + BIGNUM *k; /* Derived key */ + + /* Client private values (NULL for server) */ + BIGNUM *x1; /* random in Zq */ + BIGNUM *x2; /* random in Z*q */ + + /* Server private values (NULL for server) */ + BIGNUM *x3; /* random in Zq */ + BIGNUM *x4; /* random in Z*q */ + + /* Step 1: C->S */ + u_char *client_id; /* Anti-replay nonce */ + u_int client_id_len; + BIGNUM *g_x1; /* g^x1 */ + BIGNUM *g_x2; /* g^x2 */ + + /* Step 1: S->C */ + u_char *server_id; /* Anti-replay nonce */ + u_int server_id_len; + BIGNUM *g_x3; /* g^x3 */ + BIGNUM *g_x4; /* g^x4 */ + + /* Step 2: C->S */ + BIGNUM *a; /* g^((x1+x3+x4)*x2*s) */ + + /* Step 2: S->C */ + BIGNUM *b; /* g^((x1+x2+x3)*x4*s) */ + + /* Confirmation: C->S */ + u_char *h_k_cid_sessid; /* H(k || client_id || session_id) */ + u_int h_k_cid_sessid_len; + + /* Confirmation: S->C */ + u_char *h_k_sid_sessid; /* H(k || server_id || session_id) */ + u_int h_k_sid_sessid_len; +}; + +/* jpake.c */ +struct jpake_group *jpake_default_group(void); +BIGNUM *bn_rand_range_gt_one(const BIGNUM *high); +int hash_buffer(const u_char *, u_int, const EVP_MD *, u_char **, u_int *); +void jpake_debug3_bn(const BIGNUM *, const char *, ...) + __attribute__((__nonnull__ (2))) + __attribute__((format(printf, 2, 3))); +void jpake_debug3_buf(const u_char *, u_int, const char *, ...) + __attribute__((__nonnull__ (3))) + __attribute__((format(printf, 3, 4))); +void jpake_dump(struct jpake_ctx *, const char *, ...) + __attribute__((__nonnull__ (2))) + __attribute__((format(printf, 2, 3))); +struct jpake_ctx *jpake_new(void); +void jpake_free(struct jpake_ctx *); + +void jpake_step1(struct jpake_group *, u_char **, u_int *, + BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, + u_char **, u_int *, u_char **, u_int *); + +void jpake_step2(struct jpake_group *, BIGNUM *, + BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, + const u_char *, u_int, const u_char *, u_int, + const u_char *, u_int, const u_char *, u_int, + BIGNUM **, u_char **, u_int *); + +void jpake_confirm_hash(const BIGNUM *, + const u_char *, u_int, + const u_char *, u_int, + u_char **, u_int *); + +void jpake_key_confirm(struct jpake_group *, BIGNUM *, BIGNUM *, + BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, + const u_char *, u_int, const u_char *, u_int, + const u_char *, u_int, const u_char *, u_int, + BIGNUM **, u_char **, u_int *); + +int jpake_check_confirm(const BIGNUM *, const u_char *, u_int, + const u_char *, u_int, const u_char *, u_int); + +/* schnorr.c */ +int schnorr_sign(const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, const u_char *, u_int , + u_char **, u_int *); +int schnorr_verify(const BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const u_char *, u_int, + const u_char *, u_int); + +#endif /* JPAKE_H */ + diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c index 332fadf6e2..48b54f5f73 100644 --- a/crypto/openssh/kex.c +++ b/crypto/openssh/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.79 2007/06/05 06:52:37 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.80 2008/09/06 12:24:13 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * diff --git a/crypto/openssh/kexgexs.c b/crypto/openssh/kexgexs.c index a037f57f28..76a0f8ca71 100644 --- a/crypto/openssh/kexgexs.c +++ b/crypto/openssh/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.10 2006/11/06 21:25:28 markus Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.11 2009/01/01 21:17:36 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -56,7 +56,8 @@ kexgex_server(Kex *kex) DH *dh; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int sbloblen, klen, slen, hashlen; - int min = -1, max = -1, nbits = -1, type, kout; + int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1; + int type, kout; if (kex->load_host_key == NULL) fatal("Cannot load hostkey"); @@ -68,27 +69,29 @@ kexgex_server(Kex *kex) switch (type) { case SSH2_MSG_KEX_DH_GEX_REQUEST: debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); - min = packet_get_int(); - nbits = packet_get_int(); - max = packet_get_int(); + omin = min = packet_get_int(); + onbits = nbits = packet_get_int(); + omax = max = packet_get_int(); min = MAX(DH_GRP_MIN, min); max = MIN(DH_GRP_MAX, max); + nbits = MAX(DH_GRP_MIN, nbits); + nbits = MIN(DH_GRP_MAX, nbits); break; case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); - nbits = packet_get_int(); - min = DH_GRP_MIN; - max = DH_GRP_MAX; + onbits = nbits = packet_get_int(); /* unused for old GEX */ + omin = min = DH_GRP_MIN; + omax = max = DH_GRP_MAX; break; default: fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); } packet_check_eom(); - if (max < min || nbits < min || max < nbits) + if (omax < omin || onbits < omin || omax < onbits) fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", - min, nbits, max); + omin, onbits, omax); /* Contact privileged parent */ dh = PRIVSEP(choose_dh(min, nbits, max)); @@ -149,7 +152,7 @@ kexgex_server(Kex *kex) key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) - min = max = -1; + omin = min = omax = max = -1; /* calc H */ kexgex_hash( @@ -159,7 +162,7 @@ kexgex_server(Kex *kex) buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, - min, nbits, max, + omin, onbits, omax, dh->p, dh->g, dh_client_pub, dh->pub_key, diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c index 2ea13d27d1..3e17da6016 100644 --- a/crypto/openssh/key.c +++ b/crypto/openssh/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.78 2008/07/07 23:32:51 stevesk Exp $ */ +/* $OpenBSD: key.c,v 1.80 2008/10/10 05:00:12 stevesk Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -369,7 +369,8 @@ key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) y = MIN(y, FLDSIZE_Y - 1); /* augment the field */ - field[x][y]++; + if (field[x][y] < len - 2) + field[x][y]++; input = input >> 2; } } @@ -427,7 +428,7 @@ key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k); break; default: - fatal("key_fingerprint_ex: bad digest representation %d", + fatal("key_fingerprint: bad digest representation %d", dgst_rep); break; } diff --git a/crypto/openssh/loginrec.c b/crypto/openssh/loginrec.c index b411141987..f4af067360 100644 --- a/crypto/openssh/loginrec.c +++ b/crypto/openssh/loginrec.c @@ -1456,25 +1456,14 @@ syslogin_write_entry(struct logininfo *li) **/ #ifdef USE_LASTLOG -#define LL_FILE 1 -#define LL_DIR 2 -#define LL_OTHER 3 - -static void -lastlog_construct(struct logininfo *li, struct lastlog *last) -{ - /* clear the structure */ - memset(last, '\0', sizeof(*last)); - - line_stripname(last->ll_line, li->line, sizeof(last->ll_line)); - strlcpy(last->ll_host, li->hostname, - MIN_SIZEOF(last->ll_host, li->hostname)); - last->ll_time = li->tv_sec; -} +#if !defined(LASTLOG_WRITE_PUTUTXLINE) || !defined(HAVE_GETLASTLOGXBYNAME) +/* open the file (using filemode) and seek to the login entry */ static int -lastlog_filetype(char *filename) +lastlog_openseek(struct logininfo *li, int *fd, int filemode) { + off_t offset; + char lastlog_file[1024]; struct stat st; if (stat(LASTLOG_FILE, &st) != 0) { @@ -1482,34 +1471,12 @@ lastlog_filetype(char *filename) LASTLOG_FILE, strerror(errno)); return (0); } - if (S_ISDIR(st.st_mode)) - return (LL_DIR); - else if (S_ISREG(st.st_mode)) - return (LL_FILE); - else - return (LL_OTHER); -} - - -/* open the file (using filemode) and seek to the login entry */ -static int -lastlog_openseek(struct logininfo *li, int *fd, int filemode) -{ - off_t offset; - int type; - char lastlog_file[1024]; - - type = lastlog_filetype(LASTLOG_FILE); - switch (type) { - case LL_FILE: - strlcpy(lastlog_file, LASTLOG_FILE, - sizeof(lastlog_file)); - break; - case LL_DIR: + if (S_ISDIR(st.st_mode)) { snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s", LASTLOG_FILE, li->username); - break; - default: + } else if (S_ISREG(st.st_mode)) { + strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); + } else { logit("%s: %.100s is not a file or directory!", __func__, LASTLOG_FILE); return (0); @@ -1522,7 +1489,7 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) return (0); } - if (type == LL_FILE) { + if (S_ISREG(st.st_mode)) { /* find this uid's offset in the lastlog file */ offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); @@ -1535,52 +1502,74 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode) return (1); } +#endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */ -static int -lastlog_perform_login(struct logininfo *li) +#ifdef LASTLOG_WRITE_PUTUTXLINE +int +lastlog_write_entry(struct logininfo *li) { - struct lastlog last; - int fd; - - /* create our struct lastlog */ - lastlog_construct(li, &last); - - if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) - return (0); - - /* write the entry */ - if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { - close(fd); - logit("%s: Error writing to %s: %s", __func__, - LASTLOG_FILE, strerror(errno)); - return (0); + switch(li->type) { + case LTYPE_LOGIN: + return 1; /* lastlog written by pututxline */ + default: + logit("lastlog_write_entry: Invalid type field"); + return 0; } - - close(fd); - return (1); } - +#else /* LASTLOG_WRITE_PUTUTXLINE */ int lastlog_write_entry(struct logininfo *li) { + struct lastlog last; + int fd; + switch(li->type) { case LTYPE_LOGIN: - return (lastlog_perform_login(li)); + /* create our struct lastlog */ + memset(&last, '\0', sizeof(last)); + line_stripname(last.ll_line, li->line, sizeof(last.ll_line)); + strlcpy(last.ll_host, li->hostname, + MIN_SIZEOF(last.ll_host, li->hostname)); + last.ll_time = li->tv_sec; + + if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) + return (0); + + /* write the entry */ + if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { + close(fd); + logit("%s: Error writing to %s: %s", __func__, + LASTLOG_FILE, strerror(errno)); + return (0); + } + + close(fd); + return (1); default: logit("%s: Invalid type field", __func__); return (0); } } +#endif /* LASTLOG_WRITE_PUTUTXLINE */ -static void -lastlog_populate_entry(struct logininfo *li, struct lastlog *last) +#ifdef HAVE_GETLASTLOGXBYNAME +int +lastlog_get_entry(struct logininfo *li) { - line_fullname(li->line, last->ll_line, sizeof(li->line)); - strlcpy(li->hostname, last->ll_host, - MIN_SIZEOF(li->hostname, last->ll_host)); - li->tv_sec = last->ll_time; -} + struct lastlogx l, *ll; + if ((ll = getlastlogxbyname(li->username, &l)) == NULL) { + memset(&l, '\0', sizeof(l)); + ll = &l; + } + line_fullname(li->line, ll->ll_line, sizeof(li->line)); + strlcpy(li->hostname, ll->ll_host, + MIN_SIZEOF(li->hostname, ll->ll_host)); + li->tv_sec = ll->ll_tv.tv_sec; + li->tv_usec = ll->ll_tv.tv_usec; + return (1); +} +#else /* HAVE_GETLASTLOGXBYNAME */ int lastlog_get_entry(struct logininfo *li) { @@ -1598,7 +1587,10 @@ lastlog_get_entry(struct logininfo *li) memset(&last, '\0', sizeof(last)); /* FALLTHRU */ case sizeof(last): - lastlog_populate_entry(li, &last); + line_fullname(li->line, last.ll_line, sizeof(li->line)); + strlcpy(li->hostname, last.ll_host, + MIN_SIZEOF(li->hostname, last.ll_host)); + li->tv_sec = last.ll_time; return (1); case -1: error("%s: Error reading from %s: %s", __func__, @@ -1613,6 +1605,7 @@ lastlog_get_entry(struct logininfo *li) /* NOTREACHED */ return (0); } +#endif /* HAVE_GETLASTLOGXBYNAME */ #endif /* USE_LASTLOG */ #ifdef USE_BTMP diff --git a/crypto/openssh/misc.c b/crypto/openssh/misc.c index 8b303f16f7..143dbf0e2d 100644 --- a/crypto/openssh/misc.c +++ b/crypto/openssh/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.69 2008/06/13 01:38:23 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.71 2009/02/21 19:32:04 tobias Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -221,23 +221,19 @@ pwcopy(struct passwd *pw) /* * Convert ASCII string to TCP/IP port number. - * Port must be >0 and <=65535. - * Return 0 if invalid. + * Port must be >=0 and <=65535. + * Return -1 if invalid. */ int a2port(const char *s) { - long port; - char *endp; - - errno = 0; - port = strtol(s, &endp, 0); - if (s == endp || *endp != '\0' || - (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) || - port <= 0 || port > 65535) - return 0; + long long port; + const char *errstr; - return port; + port = strtonum(s, 0, 65535, &errstr); + if (errstr != NULL) + return -1; + return (int)port; } int @@ -718,7 +714,8 @@ sanitise_stdfd(void) int nullfd, dupfd; if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { - fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); + fprintf(stderr, "Couldn't open /dev/null: %s\n", + strerror(errno)); exit(1); } while (++dupfd <= 2) { @@ -726,7 +723,7 @@ sanitise_stdfd(void) if (fcntl(dupfd, F_GETFL, 0) >= 0) continue; if (dup2(nullfd, dupfd) == -1) { - fprintf(stderr, "dup2: %s", strerror(errno)); + fprintf(stderr, "dup2: %s\n", strerror(errno)); exit(1); } } diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c index 73cf6bc9b9..f57e74ba5c 100644 --- a/crypto/openssh/monitor.c +++ b/crypto/openssh/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.99 2008/07/10 18:08:11 markus Exp $ */ +/* $OpenBSD: monitor.c,v 1.101 2009/02/12 03:26:22 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -87,6 +87,7 @@ #include "misc.h" #include "compat.h" #include "ssh2.h" +#include "jpake.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -149,6 +150,11 @@ int mm_answer_rsa_challenge(int, Buffer *); int mm_answer_rsa_response(int, Buffer *); int mm_answer_sesskey(int, Buffer *); int mm_answer_sessid(int, Buffer *); +int mm_answer_jpake_get_pwdata(int, Buffer *); +int mm_answer_jpake_step1(int, Buffer *); +int mm_answer_jpake_step2(int, Buffer *); +int mm_answer_jpake_key_confirm(int, Buffer *); +int mm_answer_jpake_check_confirm(int, Buffer *); #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); @@ -233,6 +239,13 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, +#endif +#ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, + {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1}, + {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2}, + {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm}, + {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm}, #endif {0, 0, NULL} }; @@ -379,6 +392,15 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) if (!authenticated) authctxt->failures++; } +#ifdef JPAKE + /* Cleanup JPAKE context after authentication */ + if (ent->flags & MON_AUTHDECIDE) { + if (authctxt->jpake_ctx != NULL) { + jpake_free(authctxt->jpake_ctx); + authctxt->jpake_ctx = NULL; + } + } +#endif } if (!authctxt->valid) @@ -1478,7 +1500,9 @@ mm_answer_rsa_challenge(int sock, Buffer *m) fatal("%s: key type mismatch", __func__); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); - + if (key->type != KEY_RSA) + fatal("%s: received bad key type %d", __func__, key->type); + key->type = KEY_RSA1; if (ssh1_challenge) BN_clear_free(ssh1_challenge); ssh1_challenge = auth_rsa_generate_challenge(key); @@ -1969,3 +1993,206 @@ mm_answer_gss_userok(int sock, Buffer *m) return (authenticated); } #endif /* GSSAPI */ + +#ifdef JPAKE +int +mm_answer_jpake_step1(int sock, Buffer *m) +{ + struct jpake_ctx *pctx; + u_char *x3_proof, *x4_proof; + u_int x3_proof_len, x4_proof_len; + + if (!options.zero_knowledge_password_authentication) + fatal("zero_knowledge_password_authentication disabled"); + + if (authctxt->jpake_ctx != NULL) + fatal("%s: authctxt->jpake_ctx already set (%p)", + __func__, authctxt->jpake_ctx); + authctxt->jpake_ctx = pctx = jpake_new(); + + jpake_step1(pctx->grp, + &pctx->server_id, &pctx->server_id_len, + &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4, + &x3_proof, &x3_proof_len, + &x4_proof, &x4_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__)); + + buffer_clear(m); + + buffer_put_string(m, pctx->server_id, pctx->server_id_len); + buffer_put_bignum2(m, pctx->g_x3); + buffer_put_bignum2(m, pctx->g_x4); + buffer_put_string(m, x3_proof, x3_proof_len); + buffer_put_string(m, x4_proof, x4_proof_len); + + debug3("%s: sending step1", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m); + + bzero(x3_proof, x3_proof_len); + bzero(x4_proof, x4_proof_len); + xfree(x3_proof); + xfree(x4_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0); + + return 0; +} + +int +mm_answer_jpake_get_pwdata(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + char *hash_scheme, *salt; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt); + + buffer_clear(m); + /* pctx->s is sensitive, not returned to slave */ + buffer_put_cstring(m, hash_scheme); + buffer_put_cstring(m, salt); + + debug3("%s: sending pwdata", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m); + + bzero(hash_scheme, strlen(hash_scheme)); + bzero(salt, strlen(salt)); + xfree(hash_scheme); + xfree(salt); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1); + + return 0; +} + +int +mm_answer_jpake_step2(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x1_proof, *x2_proof, *x4_s_proof; + u_int x1_proof_len, x2_proof_len, x4_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->g_x1 = BN_new()) == NULL || + (pctx->g_x2 = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->g_x1); + buffer_get_bignum2(m, pctx->g_x2); + pctx->client_id = buffer_get_string(m, &pctx->client_id_len); + x1_proof = buffer_get_string(m, &x1_proof_len); + x2_proof = buffer_get_string(m, &x2_proof_len); + + jpake_step2(pctx->grp, pctx->s, pctx->g_x3, + pctx->g_x1, pctx->g_x2, pctx->x4, + pctx->client_id, pctx->client_id_len, + pctx->server_id, pctx->server_id_len, + x1_proof, x1_proof_len, + x2_proof, x2_proof_len, + &pctx->b, + &x4_s_proof, &x4_s_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__)); + + bzero(x1_proof, x1_proof_len); + bzero(x2_proof, x2_proof_len); + xfree(x1_proof); + xfree(x2_proof); + + buffer_clear(m); + + buffer_put_bignum2(m, pctx->b); + buffer_put_string(m, x4_s_proof, x4_s_proof_len); + + debug3("%s: sending step2", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m); + + bzero(x4_s_proof, x4_s_proof_len); + xfree(x4_s_proof); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_key_confirm(int sock, Buffer *m) +{ + struct jpake_ctx *pctx = authctxt->jpake_ctx; + u_char *x2_s_proof; + u_int x2_s_proof_len; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + if ((pctx->a = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + buffer_get_bignum2(m, pctx->a); + x2_s_proof = buffer_get_string(m, &x2_s_proof_len); + + jpake_key_confirm(pctx->grp, pctx->s, pctx->a, + pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, + pctx->server_id, pctx->server_id_len, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + x2_s_proof, x2_s_proof_len, + &pctx->k, + &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len); + + JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__)); + + bzero(x2_s_proof, x2_s_proof_len); + buffer_clear(m); + + /* pctx->k is sensitive, not sent */ + buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); + + debug3("%s: sending confirmation hash", __func__); + mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1); + + return 0; +} + +int +mm_answer_jpake_check_confirm(int sock, Buffer *m) +{ + int authenticated = 0; + u_char *peer_confirm_hash; + u_int peer_confirm_hash_len; + struct jpake_ctx *pctx = authctxt->jpake_ctx; + + if (pctx == NULL) + fatal("%s: pctx == NULL", __func__); + + peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len); + + authenticated = jpake_check_confirm(pctx->k, + pctx->client_id, pctx->client_id_len, + session_id2, session_id2_len, + peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid; + + JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__)); + + bzero(peer_confirm_hash, peer_confirm_hash_len); + xfree(peer_confirm_hash); + + buffer_clear(m); + buffer_put_int(m, authenticated); + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m); + + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); + + auth_method = "jpake-01@openssh.com"; + return authenticated; +} + +#endif /* JPAKE */ diff --git a/crypto/openssh/monitor.h b/crypto/openssh/monitor.h index 464009ad81..a8a2c0c199 100644 --- a/crypto/openssh/monitor.h +++ b/crypto/openssh/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.14 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: monitor.h,v 1.15 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -60,7 +60,12 @@ enum monitor_reqtype { MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND, MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX, MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND, - MONITOR_REQ_TERM + MONITOR_REQ_TERM, + MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1, + MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA, + MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2, + MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM, + MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, }; struct mm_master; diff --git a/crypto/openssh/monitor_fdpass.c b/crypto/openssh/monitor_fdpass.c index cab538bc90..4b9a066bcf 100644 --- a/crypto/openssh/monitor_fdpass.c +++ b/crypto/openssh/monitor_fdpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_fdpass.c,v 1.17 2008/03/24 16:11:07 deraadt Exp $ */ +/* $OpenBSD: monitor_fdpass.c,v 1.18 2008/11/30 11:59:26 dtucker Exp $ */ /* * Copyright 2001 Niels Provos * All rights reserved. @@ -45,17 +45,16 @@ mm_send_fd(int sock, int fd) { #if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; - struct iovec vec; - char ch = '\0'; - ssize_t n; #ifndef HAVE_ACCRIGHTS_IN_MSGHDR union { struct cmsghdr hdr; - char tmp[CMSG_SPACE(sizeof(int))]; char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; struct cmsghdr *cmsg; #endif + struct iovec vec; + char ch = '\0'; + ssize_t n; memset(&msg, 0, sizeof(msg)); #ifdef HAVE_ACCRIGHTS_IN_MSGHDR @@ -76,7 +75,10 @@ mm_send_fd(int sock, int fd) msg.msg_iov = &vec; msg.msg_iovlen = 1; - if ((n = sendmsg(sock, &msg, 0)) == -1) { + while ((n = sendmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || + errno == EINTR)) + debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno)); + if (n == -1) { error("%s: sendmsg(%d): %s", __func__, fd, strerror(errno)); return -1; @@ -99,10 +101,6 @@ mm_receive_fd(int sock) { #if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR)) struct msghdr msg; - struct iovec vec; - ssize_t n; - char ch; - int fd; #ifndef HAVE_ACCRIGHTS_IN_MSGHDR union { struct cmsghdr hdr; @@ -110,6 +108,10 @@ mm_receive_fd(int sock) } cmsgbuf; struct cmsghdr *cmsg; #endif + struct iovec vec; + ssize_t n; + char ch; + int fd; memset(&msg, 0, sizeof(msg)); vec.iov_base = &ch; @@ -124,10 +126,14 @@ mm_receive_fd(int sock) msg.msg_controllen = sizeof(cmsgbuf.buf); #endif - if ((n = recvmsg(sock, &msg, 0)) == -1) { + while ((n = recvmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || + errno == EINTR)) + debug3("%s: recvmsg: %s", __func__, strerror(errno)); + if (n == -1) { error("%s: recvmsg: %s", __func__, strerror(errno)); return -1; } + if (n != 1) { error("%s: recvmsg: expected received 1 got %ld", __func__, (long)n); @@ -145,6 +151,7 @@ mm_receive_fd(int sock) error("%s: no message header", __func__); return -1; } + #ifndef BROKEN_CMSG_TYPE if (cmsg->cmsg_type != SCM_RIGHTS) { error("%s: expected type %d got %d", __func__, diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c index 40463d0780..0986fc5182 100644 --- a/crypto/openssh/monitor_wrap.c +++ b/crypto/openssh/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.63 2008/07/10 18:08:11 markus Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.64 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -40,6 +40,7 @@ #include #include +#include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -70,7 +71,7 @@ #include "atomicio.h" #include "monitor_fdpass.h" #include "misc.h" -#include "servconf.h" +#include "jpake.h" #include "channels.h" #include "session.h" @@ -1256,3 +1257,165 @@ mm_ssh_gssapi_userok(char *user) return (authenticated); } #endif /* GSSAPI */ + +#ifdef JPAKE +void +mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s, + char **hash_scheme, char **salt) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, + MONITOR_REQ_JPAKE_GET_PWDATA, &m); + + debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_JPAKE_GET_PWDATA, &m); + + *hash_scheme = buffer_get_string(&m, NULL); + *salt = buffer_get_string(&m, NULL); + + buffer_free(&m); +} + +void +mm_jpake_step1(struct jpake_group *grp, + u_char **id, u_int *id_len, + BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, + u_char **priv1_proof, u_int *priv1_proof_len, + u_char **priv2_proof, u_int *priv2_proof_len) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, + MONITOR_REQ_JPAKE_STEP1, &m); + + debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_JPAKE_STEP1, &m); + + if ((*priv1 = BN_new()) == NULL || + (*priv2 = BN_new()) == NULL || + (*g_priv1 = BN_new()) == NULL || + (*g_priv2 = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + + *id = buffer_get_string(&m, id_len); + /* priv1 and priv2 are, well, private */ + buffer_get_bignum2(&m, *g_priv1); + buffer_get_bignum2(&m, *g_priv2); + *priv1_proof = buffer_get_string(&m, priv1_proof_len); + *priv2_proof = buffer_get_string(&m, priv2_proof_len); + + buffer_free(&m); +} + +void +mm_jpake_step2(struct jpake_group *grp, BIGNUM *s, + BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, + const u_char *theirid, u_int theirid_len, + const u_char *myid, u_int myid_len, + const u_char *theirpub1_proof, u_int theirpub1_proof_len, + const u_char *theirpub2_proof, u_int theirpub2_proof_len, + BIGNUM **newpub, + u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + /* monitor already has all bignums except theirpub1, theirpub2 */ + buffer_put_bignum2(&m, theirpub1); + buffer_put_bignum2(&m, theirpub2); + /* monitor already knows our id */ + buffer_put_string(&m, theirid, theirid_len); + buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len); + buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len); + + mm_request_send(pmonitor->m_recvfd, + MONITOR_REQ_JPAKE_STEP2, &m); + + debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_JPAKE_STEP2, &m); + + if ((*newpub = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + + buffer_get_bignum2(&m, *newpub); + *newpub_exponent_proof = buffer_get_string(&m, + newpub_exponent_proof_len); + + buffer_free(&m); +} + +void +mm_jpake_key_confirm(struct jpake_group *grp, BIGNUM *s, BIGNUM *step2_val, + BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, + BIGNUM *theirpub1, BIGNUM *theirpub2, + const u_char *my_id, u_int my_id_len, + const u_char *their_id, u_int their_id_len, + const u_char *sess_id, u_int sess_id_len, + const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len, + BIGNUM **k, + u_char **confirm_hash, u_int *confirm_hash_len) +{ + Buffer m; + + debug3("%s entering", __func__); + + buffer_init(&m); + /* monitor already has all bignums except step2_val */ + buffer_put_bignum2(&m, step2_val); + /* monitor already knows all the ids */ + buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len); + + mm_request_send(pmonitor->m_recvfd, + MONITOR_REQ_JPAKE_KEY_CONFIRM, &m); + + debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_JPAKE_KEY_CONFIRM, &m); + + /* 'k' is sensitive and stays in the monitor */ + *confirm_hash = buffer_get_string(&m, confirm_hash_len); + + buffer_free(&m); +} + +int +mm_jpake_check_confirm(const BIGNUM *k, + const u_char *peer_id, u_int peer_id_len, + const u_char *sess_id, u_int sess_id_len, + const u_char *peer_confirm_hash, u_int peer_confirm_hash_len) +{ + Buffer m; + int success = 0; + + debug3("%s entering", __func__); + + buffer_init(&m); + /* k is dummy in slave, ignored */ + /* monitor knows all the ids */ + buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len); + mm_request_send(pmonitor->m_recvfd, + MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m); + + debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m); + + success = buffer_get_int(&m); + buffer_free(&m); + + debug3("%s: success = %d", __func__, success); + return success; +} +#endif /* JPAKE */ diff --git a/crypto/openssh/monitor_wrap.h b/crypto/openssh/monitor_wrap.h index 329189c2ad..55c4b99f35 100644 --- a/crypto/openssh/monitor_wrap.h +++ b/crypto/openssh/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.20 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.21 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -101,6 +101,26 @@ int mm_bsdauth_respond(void *, u_int, char **); int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_skey_respond(void *, u_int, char **); +/* jpake */ +struct jpake_group; +void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **); +void mm_jpake_step1(struct jpake_group *, u_char **, u_int *, + BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, + u_char **, u_int *, u_char **, u_int *); +void mm_jpake_step2(struct jpake_group *, BIGNUM *, + BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, + const u_char *, u_int, const u_char *, u_int, + const u_char *, u_int, const u_char *, u_int, + BIGNUM **, u_char **, u_int *); +void mm_jpake_key_confirm(struct jpake_group *, BIGNUM *, BIGNUM *, + BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, + const u_char *, u_int, const u_char *, u_int, + const u_char *, u_int, const u_char *, u_int, + BIGNUM **, u_char **, u_int *); +int mm_jpake_check_confirm(const BIGNUM *, + const u_char *, u_int, const u_char *, u_int, const u_char *, u_int); + + /* zlib allocation hooks */ void *mm_zalloc(struct mm_master *, u_int, u_int); diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h index 87a9e58200..7bca3bcae4 100644 --- a/crypto/openssh/myproposal.h +++ b/crypto/openssh/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.22 2007/06/07 19:37:34 pvalchev Exp $ */ +/* $OpenBSD: myproposal.h,v 1.23 2009/01/23 07:58:11 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -41,11 +41,12 @@ #endif #define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" + #define KEX_DEFAULT_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "arcfour256,arcfour128," \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ - "arcfour128,arcfour256,arcfour," \ - "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ - "aes128-ctr,aes192-ctr,aes256-ctr" + "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" #define KEX_DEFAULT_MAC \ "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \ "hmac-ripemd160@openssh.com," \ diff --git a/crypto/openssh/nchan.c b/crypto/openssh/nchan.c index e0ebf43f15..160445e5a2 100644 --- a/crypto/openssh/nchan.c +++ b/crypto/openssh/nchan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nchan.c,v 1.60 2008/06/30 12:16:02 djm Exp $ */ +/* $OpenBSD: nchan.c,v 1.62 2008/11/07 18:50:18 stevesk Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -387,6 +387,8 @@ chan_send_eow2(Channel *c) c->self); return; } + if (!(datafellows & SSH_NEW_OPENSSH)) + return; packet_start(SSH2_MSG_CHANNEL_REQUEST); packet_put_int(c->remote_id); packet_put_cstring("eow@openssh.com"); @@ -484,12 +486,12 @@ chan_shutdown_write(Channel *c) if (c->sock != -1) { if (shutdown(c->sock, SHUT_WR) < 0) debug2("channel %d: chan_shutdown_write: " - "shutdown() failed for fd%d: %.100s", + "shutdown() failed for fd %d: %.100s", c->self, c->sock, strerror(errno)); } else { if (channel_close_fd(&c->wfd) < 0) logit("channel %d: chan_shutdown_write: " - "close() failed for fd%d: %.100s", + "close() failed for fd %d: %.100s", c->self, c->wfd, strerror(errno)); } } @@ -508,13 +510,13 @@ chan_shutdown_read(Channel *c) if (shutdown(c->sock, SHUT_RD) < 0 && errno != ENOTCONN) error("channel %d: chan_shutdown_read: " - "shutdown() failed for fd%d [i%d o%d]: %.100s", + "shutdown() failed for fd %d [i%d o%d]: %.100s", c->self, c->sock, c->istate, c->ostate, strerror(errno)); } else { if (channel_close_fd(&c->rfd) < 0) logit("channel %d: chan_shutdown_read: " - "close() failed for fd%d: %.100s", + "close() failed for fd %d: %.100s", c->self, c->rfd, strerror(errno)); } } diff --git a/crypto/openssh/openbsd-compat/xmmap.c b/crypto/openssh/openbsd-compat/xmmap.c index 23efe38889..04c6babc28 100644 --- a/crypto/openssh/openbsd-compat/xmmap.c +++ b/crypto/openssh/openbsd-compat/xmmap.c @@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: xmmap.c,v 1.14 2007/06/11 02:52:24 djm Exp $ */ +/* $Id: xmmap.c,v 1.15 2009/02/16 04:21:40 djm Exp $ */ #include "includes.h" @@ -71,7 +71,8 @@ xmmap(size_t size) fatal("mkstemp(\"%s\"): %s", MM_SWAP_TEMPLATE, strerror(errno)); unlink(tmpname); - ftruncate(tmpfd, size); + if (ftruncate(tmpfd, size) != 0) + fatal("%s: ftruncate: %s", __func__, strerror(errno)); address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED, tmpfd, (off_t)0); close(tmpfd); diff --git a/crypto/openssh/packet.c b/crypto/openssh/packet.c index 8abd43eb46..5afc84ce0b 100644 --- a/crypto/openssh/packet.c +++ b/crypto/openssh/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */ +/* $OpenBSD: packet.c,v 1.160 2009/02/13 11:50:21 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -84,6 +84,8 @@ #define DBG(x) #endif +#define PACKET_MAX_SIZE (256 * 1024) + /* * This variable contains the file descriptors used for communicating with * the other side. connection_in is used for reading; connection_out for @@ -160,6 +162,10 @@ static u_int ssh1_keylen; /* roundup current message to extra_pad bytes */ static u_char extra_pad = 0; +/* XXX discard incoming data after MAC error */ +static u_int packet_discard = 0; +static Mac *packet_discard_mac = NULL; + struct packet { TAILQ_ENTRY(packet) next; u_char type; @@ -209,6 +215,36 @@ packet_set_timeout(int timeout, int count) packet_timeout_ms = timeout * count * 1000; } +static void +packet_stop_discard(void) +{ + if (packet_discard_mac) { + char buf[1024]; + + memset(buf, 'a', sizeof(buf)); + while (buffer_len(&incoming_packet) < PACKET_MAX_SIZE) + buffer_append(&incoming_packet, buf, sizeof(buf)); + (void) mac_compute(packet_discard_mac, + p_read.seqnr, + buffer_ptr(&incoming_packet), + PACKET_MAX_SIZE); + } + logit("Finished discarding for %.200s", get_remote_ipaddr()); + cleanup_exit(255); +} + +static void +packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) +{ + if (enc == NULL || !cipher_is_cbc(enc->cipher)) + packet_disconnect("Packet corrupt"); + if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) + packet_discard_mac = mac; + if (buffer_len(&input) >= discard) + packet_stop_discard(); + packet_discard = discard - buffer_len(&input); +} + /* Returns 1 if remote host is connected via socket, 0 if not. */ int @@ -1127,6 +1163,9 @@ packet_read_poll2(u_int32_t *seqnr_p) Mac *mac = NULL; Comp *comp = NULL; + if (packet_discard) + return SSH_MSG_NONE; + if (newkeys[MODE_IN] != NULL) { enc = &newkeys[MODE_IN]->enc; mac = &newkeys[MODE_IN]->mac; @@ -1148,11 +1187,14 @@ packet_read_poll2(u_int32_t *seqnr_p) block_size); cp = buffer_ptr(&incoming_packet); packet_length = get_u32(cp); - if (packet_length < 1 + 4 || packet_length > 256 * 1024) { + if (packet_length < 1 + 4 || packet_length > PACKET_MAX_SIZE) { #ifdef PACKET_DEBUG buffer_dump(&incoming_packet); #endif - packet_disconnect("Bad packet length %u.", packet_length); + logit("Bad packet length %u.", packet_length); + packet_start_discard(enc, mac, packet_length, + PACKET_MAX_SIZE); + return SSH_MSG_NONE; } DBG(debug("input: packet len %u", packet_length+4)); buffer_consume(&input, block_size); @@ -1161,9 +1203,13 @@ packet_read_poll2(u_int32_t *seqnr_p) need = 4 + packet_length - block_size; DBG(debug("partial packet %d, need %d, maclen %d", block_size, need, maclen)); - if (need % block_size != 0) - fatal("padding error: need %d block %d mod %d", + if (need % block_size != 0) { + logit("padding error: need %d block %d mod %d", need, block_size, need % block_size); + packet_start_discard(enc, mac, packet_length, + PACKET_MAX_SIZE - block_size); + return SSH_MSG_NONE; + } /* * check if the entire packet has been received and * decrypt into incoming_packet @@ -1185,11 +1231,19 @@ packet_read_poll2(u_int32_t *seqnr_p) macbuf = mac_compute(mac, p_read.seqnr, buffer_ptr(&incoming_packet), buffer_len(&incoming_packet)); - if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) - packet_disconnect("Corrupted MAC on input."); + if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) { + logit("Corrupted MAC on input."); + if (need > PACKET_MAX_SIZE) + fatal("internal error need %d", need); + packet_start_discard(enc, mac, packet_length, + PACKET_MAX_SIZE - need); + return SSH_MSG_NONE; + } + DBG(debug("MAC #%d ok", p_read.seqnr)); buffer_consume(&input, mac->mac_len); } + /* XXX now it's safe to use fatal/packet_disconnect */ if (seqnr_p != NULL) *seqnr_p = p_read.seqnr; if (++p_read.seqnr == 0) @@ -1322,6 +1376,13 @@ packet_read_poll(void) void packet_process_incoming(const char *buf, u_int len) { + if (packet_discard) { + keep_alive_timeouts = 0; /* ?? */ + if (len >= packet_discard) + packet_stop_discard(); + packet_discard -= len; + return; + } buffer_append(&input, buf, len); } diff --git a/crypto/openssh/pathnames.h b/crypto/openssh/pathnames.h index f2571e2749..80c5d9cbb7 100644 --- a/crypto/openssh/pathnames.h +++ b/crypto/openssh/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: pathnames.h,v 1.17 2008/12/29 02:23:26 stevesk Exp $ */ /* * Author: Tatu Ylonen @@ -54,7 +54,7 @@ #define _PATH_SSH_DAEMON_PID_FILE _PATH_SSH_PIDDIR "/sshd.pid" /* - * The directory in user\'s home directory in which the files reside. The + * The directory in user's home directory in which the files reside. The * directory should be world-readable (though not all files are). */ #define _PATH_SSH_USER_DIR ".ssh" @@ -77,9 +77,9 @@ #define _PATH_SSH_CLIENT_ID_RSA ".ssh/id_rsa" /* - * Configuration file in user\'s home directory. This file need not be + * Configuration file in user's home directory. This file need not be * readable by anyone but the user him/herself, but does not contain anything - * particularly secret. If the user\'s home directory resides on an NFS + * particularly secret. If the user's home directory resides on an NFS * volume where root is mapped to nobody, this may need to be world-readable. */ #define _PATH_SSH_USER_CONFFILE ".ssh/config" @@ -87,7 +87,7 @@ /* * File containing a list of those rsa keys that permit logging in as this * user. This file need not be readable by anyone but the user him/herself, - * but does not contain anything particularly secret. If the user\'s home + * but does not contain anything particularly secret. If the user's home * directory resides on an NFS volume where root is mapped to nobody, this * may need to be world-readable. (This file is read by the daemon which is * running as root.) diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c index 73f6eb361e..53fc6c7ba5 100644 --- a/crypto/openssh/readconf.c +++ b/crypto/openssh/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.167 2008/06/26 11:46:31 grunk Exp $ */ +/* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -130,7 +130,7 @@ typedef enum { oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, - oVisualHostKey, + oVisualHostKey, oZeroKnowledgePasswordAuthentication, oDeprecated, oUnsupported } OpCodes; @@ -172,7 +172,7 @@ static struct { { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, { "identityfile", oIdentityFile }, - { "identityfile2", oIdentityFile }, /* alias */ + { "identityfile2", oIdentityFile }, /* obsolete */ { "identitiesonly", oIdentitiesOnly }, { "hostname", oHostName }, { "hostkeyalias", oHostKeyAlias }, @@ -188,8 +188,8 @@ static struct { { "host", oHost }, { "escapechar", oEscapeChar }, { "globalknownhostsfile", oGlobalKnownHostsFile }, - { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */ - { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, + { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */ + { "userknownhostsfile", oUserKnownHostsFile }, { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, @@ -228,6 +228,13 @@ static struct { { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, { "visualhostkey", oVisualHostKey }, +#ifdef JPAKE + { "zeroknowledgepasswordauthentication", + oZeroKnowledgePasswordAuthentication }, +#else + { "zeroknowledgepasswordauthentication", oUnsupported }, +#endif + { NULL, oBadOption } }; @@ -249,10 +256,9 @@ add_local_forward(Options *options, const Forward *newfwd) fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->local_forwards[options->num_local_forwards++]; - fwd->listen_host = (newfwd->listen_host == NULL) ? - NULL : xstrdup(newfwd->listen_host); + fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; - fwd->connect_host = xstrdup(newfwd->connect_host); + fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; } @@ -270,10 +276,9 @@ add_remote_forward(Options *options, const Forward *newfwd) SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->remote_forwards[options->num_remote_forwards++]; - fwd->listen_host = (newfwd->listen_host == NULL) ? - NULL : xstrdup(newfwd->listen_host); + fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; - fwd->connect_host = xstrdup(newfwd->connect_host); + fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; } @@ -412,6 +417,10 @@ parse_flag: intptr = &options->password_authentication; goto parse_flag; + case oZeroKnowledgePasswordAuthentication: + intptr = &options->zero_knowledge_password_authentication; + goto parse_flag; + case oKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; @@ -706,56 +715,40 @@ parse_int: case oLocalForward: case oRemoteForward: + case oDynamicForward: arg = strdelim(&s); if (arg == NULL || *arg == '\0') fatal("%.200s line %d: Missing port argument.", filename, linenum); - arg2 = strdelim(&s); - if (arg2 == NULL || *arg2 == '\0') - fatal("%.200s line %d: Missing target argument.", - filename, linenum); - /* construct a string for parse_forward */ - snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); + if (opcode == oLocalForward || + opcode == oRemoteForward) { + arg2 = strdelim(&s); + if (arg2 == NULL || *arg2 == '\0') + fatal("%.200s line %d: Missing target argument.", + filename, linenum); + + /* construct a string for parse_forward */ + snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); + } else if (opcode == oDynamicForward) { + strlcpy(fwdarg, arg, sizeof(fwdarg)); + } - if (parse_forward(&fwd, fwdarg) == 0) + if (parse_forward(&fwd, fwdarg, + opcode == oDynamicForward ? 1 : 0, + opcode == oRemoteForward ? 1 : 0) == 0) fatal("%.200s line %d: Bad forwarding specification.", filename, linenum); if (*activep) { - if (opcode == oLocalForward) + if (opcode == oLocalForward || + opcode == oDynamicForward) add_local_forward(options, &fwd); else if (opcode == oRemoteForward) add_remote_forward(options, &fwd); } break; - case oDynamicForward: - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing port argument.", - filename, linenum); - memset(&fwd, '\0', sizeof(fwd)); - fwd.connect_host = "socks"; - fwd.listen_host = hpdelim(&arg); - if (fwd.listen_host == NULL || - strlen(fwd.listen_host) >= NI_MAXHOST) - fatal("%.200s line %d: Bad forwarding specification.", - filename, linenum); - if (arg) { - fwd.listen_port = a2port(arg); - fwd.listen_host = cleanhostname(fwd.listen_host); - } else { - fwd.listen_port = a2port(fwd.listen_host); - fwd.listen_host = NULL; - } - if (fwd.listen_port == 0) - fatal("%.200s line %d: Badly formatted port number.", - filename, linenum); - if (*activep) - add_local_forward(options, &fwd); - break; - case oClearAllForwardings: intptr = &options->clear_forwardings; goto parse_flag; @@ -959,7 +952,6 @@ read_config_file(const char *filename, const char *host, Options *options, int active, linenum; int bad_options = 0; - /* Open the file. */ if ((f = fopen(filename, "r")) == NULL) return 0; @@ -1072,6 +1064,7 @@ initialize_options(Options * options) options->local_command = NULL; options->permit_local_command = -1; options->visual_host_key = -1; + options->zero_knowledge_password_authentication = -1; } /* @@ -1208,6 +1201,8 @@ fill_default_options(Options * options) options->permit_local_command = 0; if (options->visual_host_key == -1) options->visual_host_key = 0; + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; /* options->local_command should not be set by default */ /* options->proxy_command should not be set by default */ /* options->user will be set in the main program if appropriate */ @@ -1219,11 +1214,14 @@ fill_default_options(Options * options) /* * parse_forward * parses a string containing a port forwarding specification of the form: + * dynamicfwd == 0 * [listenhost:]listenport:connecthost:connectport + * dynamicfwd == 1 + * [listenhost:]listenport * returns number of arguments parsed or zero on error */ int -parse_forward(Forward *fwd, const char *fwdspec) +parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) { int i; char *p, *cp, *fwdarg[4]; @@ -1240,11 +1238,23 @@ parse_forward(Forward *fwd, const char *fwdspec) if ((fwdarg[i] = hpdelim(&cp)) == NULL) break; - /* Check for trailing garbage in 4-arg case*/ + /* Check for trailing garbage */ if (cp != NULL) i = 0; /* failure */ switch (i) { + case 1: + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdarg[0]); + fwd->connect_host = xstrdup("socks"); + break; + + case 2: + fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); + fwd->listen_port = a2port(fwdarg[1]); + fwd->connect_host = xstrdup("socks"); + break; + case 3: fwd->listen_host = NULL; fwd->listen_port = a2port(fwdarg[0]); @@ -1264,19 +1274,37 @@ parse_forward(Forward *fwd, const char *fwdspec) xfree(p); - if (fwd->listen_port == 0 || fwd->connect_port == 0) + if (dynamicfwd) { + if (!(i == 1 || i == 2)) + goto fail_free; + } else { + if (!(i == 3 || i == 4)) + goto fail_free; + if (fwd->connect_port <= 0) + goto fail_free; + } + + if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) goto fail_free; if (fwd->connect_host != NULL && strlen(fwd->connect_host) >= NI_MAXHOST) goto fail_free; + if (fwd->listen_host != NULL && + strlen(fwd->listen_host) >= NI_MAXHOST) + goto fail_free; + return (i); fail_free: - if (fwd->connect_host != NULL) + if (fwd->connect_host != NULL) { xfree(fwd->connect_host); - if (fwd->listen_host != NULL) + fwd->connect_host = NULL; + } + if (fwd->listen_host != NULL) { xfree(fwd->listen_host); + fwd->listen_host = NULL; + } return (0); } diff --git a/crypto/openssh/readconf.h b/crypto/openssh/readconf.h index 47c7aef4e0..8fb3a85281 100644 --- a/crypto/openssh/readconf.h +++ b/crypto/openssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.74 2008/06/26 11:46:31 grunk Exp $ */ +/* $OpenBSD: readconf.h,v 1.78 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen @@ -20,9 +20,9 @@ typedef struct { char *listen_host; /* Host (address) to listen on. */ - u_short listen_port; /* Port to forward. */ + int listen_port; /* Port to forward. */ char *connect_host; /* Host to connect. */ - u_short connect_port; /* Port to connect on connect_host. */ + int connect_port; /* Port to connect on connect_host. */ } Forward; /* Data structure for representing option data. */ @@ -49,6 +49,7 @@ typedef struct { * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ + int zero_knowledge_password_authentication; /* Try jpake */ int batch_mode; /* Batch mode: do not ask for passwords. */ int check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ @@ -133,7 +134,7 @@ typedef struct { void initialize_options(Options *); void fill_default_options(Options *); int read_config_file(const char *, const char *, Options *, int); -int parse_forward(Forward *, const char *); +int parse_forward(Forward *, const char *, int, int); int process_config_line(Options *, const char *, char *, const char *, int, int *); diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c index 9f8b7a192a..3237478068 100644 --- a/crypto/openssh/scp.c +++ b/crypto/openssh/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.163 2008/06/13 18:55:22 dtucker Exp $ */ +/* $OpenBSD: scp.c,v 1.164 2008/10/10 04:55:16 stevesk Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -434,7 +434,7 @@ main(int argc, char **argv) } /* * Finally check the exit status of the ssh process, if one was forked - * and no error has occured yet + * and no error has occurred yet */ if (do_cmd_pid != -1 && errs == 0) { if (remin != -1) diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 66e22979f9..e7fc2a7812 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.186 2008/07/04 03:44:59 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.194 2009/01/22 10:02:34 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -42,8 +42,8 @@ #include "channels.h" #include "groupaccess.h" -static void add_listen_addr(ServerOptions *, char *, u_short); -static void add_one_listen_addr(ServerOptions *, char *, u_short); +static void add_listen_addr(ServerOptions *, char *, int); +static void add_one_listen_addr(ServerOptions *, char *, int); /* Use of privilege separation or not */ extern int use_privsep; @@ -127,6 +127,7 @@ initialize_server_options(ServerOptions *options) options->num_permitted_opens = -1; options->adm_forced_command = NULL; options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; } void @@ -258,6 +259,8 @@ fill_default_server_options(ServerOptions *options) options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; /* Turn privilege separation on by default */ if (use_privsep == -1) @@ -302,6 +305,7 @@ typedef enum { sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sDeprecated, sUnsupported } ServerOpCodes; @@ -368,6 +372,11 @@ static struct { { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ +#ifdef JPAKE + { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL }, +#else + { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL }, +#endif { "checkmail", sDeprecated, SSHCFG_GLOBAL }, { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, @@ -380,7 +389,7 @@ static struct { { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, - { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL }, + { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, { "uselogin", sUseLogin, SSHCFG_GLOBAL }, { "compression", sCompression, SSHCFG_GLOBAL }, @@ -451,7 +460,7 @@ parse_token(const char *cp, const char *filename, } static void -add_listen_addr(ServerOptions *options, char *addr, u_short port) +add_listen_addr(ServerOptions *options, char *addr, int port) { u_int i; @@ -467,7 +476,7 @@ add_listen_addr(ServerOptions *options, char *addr, u_short port) } static void -add_one_listen_addr(ServerOptions *options, char *addr, u_short port) +add_one_listen_addr(ServerOptions *options, char *addr, int port) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; @@ -477,7 +486,7 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port) hints.ai_family = options->address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; - snprintf(strport, sizeof strport, "%u", port); + snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) fatal("bad addr or host: %s (%s)", addr ? addr : "", @@ -633,7 +642,7 @@ process_server_config_line(ServerOptions *options, char *line, SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; ServerOpCodes opcode; - u_short port; + int port; u_int i, flags = 0; size_t len; @@ -690,7 +699,7 @@ process_server_config_line(ServerOptions *options, char *line, fatal("%s line %d: missing port number.", filename, linenum); options->ports[options->num_ports++] = a2port(arg); - if (options->ports[options->num_ports-1] == 0) + if (options->ports[options->num_ports-1] <= 0) fatal("%s line %d: Badly formatted port number.", filename, linenum); break; @@ -743,7 +752,7 @@ process_server_config_line(ServerOptions *options, char *line, p = cleanhostname(p); if (arg == NULL) port = 0; - else if ((port = a2port(arg)) == 0) + else if ((port = a2port(arg)) <= 0) fatal("%s line %d: bad port number", filename, linenum); add_listen_addr(options, p, port); @@ -890,6 +899,10 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->password_authentication; goto parse_flag; + case sZeroKnowledgePasswordAuthentication: + intptr = &options->zero_knowledge_password_authentication; + goto parse_flag; + case sKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; @@ -1252,7 +1265,7 @@ process_server_config_line(ServerOptions *options, char *line, fatal("%s line %d: missing host in PermitOpen", filename, linenum); p = cleanhostname(p); - if (arg == NULL || (port = a2port(arg)) == 0) + if (arg == NULL || (port = a2port(arg)) <= 0) fatal("%s line %d: bad port number in " "PermitOpen", filename, linenum); if (*activep && n == -1) @@ -1377,7 +1390,9 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(kerberos_authentication); M_CP_INTOPT(hostbased_authentication); M_CP_INTOPT(kbd_interactive_authentication); + M_CP_INTOPT(zero_knowledge_password_authentication); M_CP_INTOPT(permit_root_login); + M_CP_INTOPT(permit_empty_passwd); M_CP_INTOPT(allow_tcp_forwarding); M_CP_INTOPT(allow_agent_forwarding); @@ -1439,7 +1454,7 @@ fmt_intarg(ServerOpCodes code, int val) if (code == sPermitRootLogin) { switch (val) { case PERMIT_NO_PASSWD: - return "without-passord"; + return "without-password"; case PERMIT_FORCED_ONLY: return "forced-commands-only"; case PERMIT_YES: @@ -1544,11 +1559,15 @@ dump_config(ServerOptions *o) } /* integer arguments */ +#ifdef USE_PAM + dump_cfg_int(sUsePAM, o->use_pam); +#endif dump_cfg_int(sServerKeyBits, o->server_key_bits); dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); dump_cfg_int(sMaxAuthTries, o->max_authtries); + dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); @@ -1562,12 +1581,22 @@ dump_config(ServerOptions *o) o->hostbased_uses_name_from_packet_only); dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication); dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); +#ifdef KRB5 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); +# ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); +# endif +#endif +#ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); +#endif +#ifdef JPAKE + dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, + o->zero_knowledge_password_authentication); +#endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, o->kbd_interactive_authentication); @@ -1626,7 +1655,5 @@ dump_config(ServerOptions *o) } dump_cfg_string(sPermitTunnel, s); - printf("permitopen"); channel_print_adm_permitted_opens(); - printf("\n"); } diff --git a/crypto/openssh/servconf.h b/crypto/openssh/servconf.h index 40ac64f135..b3ac7da4b6 100644 --- a/crypto/openssh/servconf.h +++ b/crypto/openssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.85 2008/06/10 04:50:25 dtucker Exp $ */ +/* $OpenBSD: servconf.h,v 1.87 2009/01/22 10:02:34 djm Exp $ */ /* * Author: Tatu Ylonen @@ -41,9 +41,9 @@ #define INTERNAL_SFTP_NAME "internal-sftp" typedef struct { - u_int num_ports; - u_int ports_from_cmdline; - u_short ports[MAX_PORTS]; /* Port number to listen on. */ + u_int num_ports; + u_int ports_from_cmdline; + int ports[MAX_PORTS]; /* Port number to listen on. */ char *listen_addr; /* Address on which the server listens. */ struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ int address_family; /* Address family used by the server. */ @@ -96,6 +96,8 @@ typedef struct { * authentication. */ int kbd_interactive_authentication; /* If true, permit */ int challenge_response_authentication; + int zero_knowledge_password_authentication; + /* If true, permit jpake auth */ int permit_empty_passwd; /* If false, do not permit empty * passwords. */ int permit_user_env; /* If true, read ~/.ssh/environment */ diff --git a/crypto/openssh/serverloop.c b/crypto/openssh/serverloop.c index 77d9dee75c..81cafe6ad5 100644 --- a/crypto/openssh/serverloop.c +++ b/crypto/openssh/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.153 2008/06/30 12:15:39 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.157 2009/02/12 03:16:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -942,7 +942,7 @@ server_request_direct_tcpip(void) { Channel *c; char *target, *originator; - int target_port, originator_port; + u_short target_port, originator_port; target = packet_get_string(NULL); target_port = packet_get_int(); @@ -1095,7 +1095,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) { char *rtype; int want_reply; - int success = 0; + int success = 0, allocated_listen_port = 0; rtype = packet_get_string(NULL); want_reply = packet_get_char(); @@ -1117,7 +1117,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) /* check permissions */ if (!options.allow_tcp_forwarding || - no_port_forwarding_flag + no_port_forwarding_flag || + (!want_reply && listen_port == 0) #ifndef NO_IPPORT_RESERVED_CONCEPT || (listen_port < IPPORT_RESERVED && pw->pw_uid != 0) #endif @@ -1127,7 +1128,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener( - listen_address, listen_port, options.gateway_ports); + listen_address, listen_port, + &allocated_listen_port, options.gateway_ports); } xfree(listen_address); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { @@ -1149,6 +1151,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) if (want_reply) { packet_start(success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); + if (success && allocated_listen_port > 0) + packet_put_int(allocated_listen_port); packet_send(); packet_write_wait(); } @@ -1202,9 +1206,9 @@ server_init_dispatch_20(void) dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); - dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm); - dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm); /* client_alive */ + dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive); + dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive); dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); /* rekeying */ diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c index 93babf9570..f2549e0cd7 100644 --- a/crypto/openssh/session.c +++ b/crypto/openssh/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.241 2008/06/16 13:22:53 dtucker Exp $ */ +/* $OpenBSD: session.c,v 1.245 2009/01/22 09:46:01 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -95,6 +95,12 @@ #include #endif +#define IS_INTERNAL_SFTP(c) \ + (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ + (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ + c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \ + c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t')) + /* func */ Session *session_new(void); @@ -228,7 +234,7 @@ auth_input_request_forwarding(struct passwd * pw) SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "auth socket", 1); - strlcpy(nc->path, auth_sock_name, sizeof(nc->path)); + nc->path = xstrdup(auth_sock_name); return 1; authsock_err: @@ -781,7 +787,7 @@ do_exec(Session *s, const char *command) if (options.adm_forced_command) { original_command = command; command = options.adm_forced_command; - if (strcmp(INTERNAL_SFTP_NAME, command) == 0) + if (IS_INTERNAL_SFTP(command)) s->is_subsystem = SUBSYSTEM_INT_SFTP; else if (s->is_subsystem) s->is_subsystem = SUBSYSTEM_EXT; @@ -789,7 +795,7 @@ do_exec(Session *s, const char *command) } else if (forced_command) { original_command = command; command = forced_command; - if (strcmp(INTERNAL_SFTP_NAME, command) == 0) + if (IS_INTERNAL_SFTP(command)) s->is_subsystem = SUBSYSTEM_INT_SFTP; else if (s->is_subsystem) s->is_subsystem = SUBSYSTEM_EXT; @@ -926,7 +932,7 @@ check_quietlogin(Session *s, const char *command) /* * Sets the value of the given variable in the environment. If the variable - * already exists, its value is overriden. + * already exists, its value is overridden. */ void child_set_env(char ***envp, u_int *envsizep, const char *name, @@ -1789,7 +1795,7 @@ do_child(Session *s, const char *command) char *p, *args; setproctitle("%s@internal-sftp-server", s->pw->pw_name); - args = strdup(command ? command : "sftp-server"); + args = xstrdup(command ? command : "sftp-server"); for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " "))) if (i < ARGV_MAX - 1) argv[i++] = p; diff --git a/crypto/openssh/sftp-server-main.c b/crypto/openssh/sftp-server-main.c index 2b14569e47..7e644ab898 100644 --- a/crypto/openssh/sftp-server-main.c +++ b/crypto/openssh/sftp-server-main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server-main.c,v 1.3 2008/03/26 23:44:41 djm Exp $ */ +/* $OpenBSD: sftp-server-main.c,v 1.4 2009/02/21 19:32:04 tobias Exp $ */ /* * Copyright (c) 2008 Markus Friedl. All rights reserved. * @@ -42,7 +42,8 @@ main(int argc, char **argv) sanitise_stdfd(); if ((user_pw = getpwuid(getuid())) == NULL) { - fprintf(stderr, "No user found for uid %lu", (u_long)getuid()); + fprintf(stderr, "No user found for uid %lu\n", + (u_long)getuid()); return 1; } diff --git a/crypto/openssh/sftp.1 b/crypto/openssh/sftp.1 index b4f9a68845..37ccb3a38b 100644 --- a/crypto/openssh/sftp.1 +++ b/crypto/openssh/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.67 2008/07/15 02:23:14 djm Exp $ +.\" $OpenBSD: sftp.1,v 1.69 2008/12/09 15:35:00 sobrado Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -22,7 +22,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. .\" -.Dd $Mdocdate: July 15 2008 $ +.Dd $Mdocdate: December 9 2008 $ .Dt SFTP 1 .Os .Sh NAME @@ -43,13 +43,12 @@ .Ar host .Ek .Nm sftp -.Oo Oo Ar user Ns @ Oc Ns -.Ar host Ns Oo : Ns Ar file Oo -.Ar file Oc Oc Oc +.Oo Ar user Ns @ Oc Ns +.Ar host Ns Op : Ns Ar .Nm sftp -.Oo Oo Ar user Ns @ Oc Ns +.Oo Ar user Ns @ Oc Ns .Ar host Ns Oo : Ns Ar dir Ns -.Oo Ar / Oc Oc Oc +.Op Ar / Oc .Nm sftp .Fl b Ar batchfile .Oo Ar user Ns @ Oc Ns Ar host @@ -442,7 +441,7 @@ to Display the .Nm protocol version. -.It Ic \&! Ar command +.It Ic \&! Ns Ar command Execute .Ar command in local shell. diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c index e1aa49d0f0..66bd111b12 100644 --- a/crypto/openssh/sftp.c +++ b/crypto/openssh/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.103 2008/07/13 22:16:03 djm Exp $ */ +/* $OpenBSD: sftp.c,v 1.107 2009/02/02 11:15:14 dtucker Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -207,36 +207,37 @@ cmd_interrupt(int signo) static void help(void) { - printf("Available commands:\n"); - printf("cd path Change remote directory to 'path'\n"); - printf("lcd path Change local directory to 'path'\n"); - printf("chgrp grp path Change group of file 'path' to 'grp'\n"); - printf("chmod mode path Change permissions of file 'path' to 'mode'\n"); - printf("chown own path Change owner of file 'path' to 'own'\n"); - printf("df [path] Display statistics for current directory or\n"); - printf(" filesystem containing 'path'\n"); - printf("help Display this help text\n"); - printf("get remote-path [local-path] Download file\n"); - printf("lls [ls-options [path]] Display local directory listing\n"); - printf("ln oldpath newpath Symlink remote file\n"); - printf("lmkdir path Create local directory\n"); - printf("lpwd Print local working directory\n"); - printf("ls [path] Display remote directory listing\n"); - printf("lumask umask Set local umask to 'umask'\n"); - printf("mkdir path Create remote directory\n"); - printf("progress Toggle display of progress meter\n"); - printf("put local-path [remote-path] Upload file\n"); - printf("pwd Display remote working directory\n"); - printf("exit Quit sftp\n"); - printf("quit Quit sftp\n"); - printf("rename oldpath newpath Rename remote file\n"); - printf("rmdir path Remove remote directory\n"); - printf("rm path Delete remote file\n"); - printf("symlink oldpath newpath Symlink remote file\n"); - printf("version Show SFTP version\n"); - printf("!command Execute 'command' in local shell\n"); - printf("! Escape to local shell\n"); - printf("? Synonym for help\n"); + printf("Available commands:\n" + "bye Quit sftp\n" + "cd path Change remote directory to 'path'\n" + "chgrp grp path Change group of file 'path' to 'grp'\n" + "chmod mode path Change permissions of file 'path' to 'mode'\n" + "chown own path Change owner of file 'path' to 'own'\n" + "df [-hi] [path] Display statistics for current directory or\n" + " filesystem containing 'path'\n" + "exit Quit sftp\n" + "get [-P] remote-path [local-path] Download file\n" + "help Display this help text\n" + "lcd path Change local directory to 'path'\n" + "lls [ls-options [path]] Display local directory listing\n" + "lmkdir path Create local directory\n" + "ln oldpath newpath Symlink remote file\n" + "lpwd Print local working directory\n" + "ls [-1aflnrSt] [path] Display remote directory listing\n" + "lumask umask Set local umask to 'umask'\n" + "mkdir path Create remote directory\n" + "progress Toggle display of progress meter\n" + "put [-P] local-path [remote-path] Upload file\n" + "pwd Display remote working directory\n" + "quit Quit sftp\n" + "rename oldpath newpath Rename remote file\n" + "rm path Delete remote file\n" + "rmdir path Remove remote directory\n" + "symlink oldpath newpath Symlink remote file\n" + "version Show SFTP version\n" + "!command Execute 'command' in local shell\n" + "! Escape to local shell\n" + "? Synonym for help\n"); } static void @@ -1234,8 +1235,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, int err_abort) { char *path1, *path2, *tmp; - int pflag, lflag, iflag, hflag, cmdnum, i; - unsigned long n_arg; + int pflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i; + unsigned long n_arg = 0; Attrib a, *aa; char path_buf[MAXPATHLEN]; int err = 0; @@ -1386,17 +1387,19 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { - if (err != 0 && err_abort) + if (err_abort) { + err = -1; break; - else + } else continue; } if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { error("Can't get current ownership of " "remote file \"%s\"", g.gl_pathv[i]); - if (err != 0 && err_abort) + if (err_abort) { + err = -1; break; - else + } else continue; } aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; @@ -1668,8 +1671,8 @@ usage(void) "usage: %s [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config]\n" " [-o ssh_option] [-P sftp_server_path] [-R num_requests]\n" " [-S program] [-s subsystem | sftp_server] host\n" - " %s [[user@]host[:file [file]]]\n" - " %s [[user@]host[:dir[/]]]\n" + " %s [user@]host[:file ...]\n" + " %s [user@]host[:dir[/]]\n" " %s -b batchfile [user@]host\n", __progname, __progname, __progname, __progname); exit(1); } diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1 index 3fff59e770..3596cc1747 100644 --- a/crypto/openssh/ssh-keygen.1 +++ b/crypto/openssh/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.78 2008/06/12 19:10:09 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.79 2008/07/24 23:55:30 sthen Exp $ .\" .\" -*- nroff -*- .\" @@ -37,7 +37,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. .\" -.Dd $Mdocdate: June 12 2008 $ +.Dd $Mdocdate: July 24 2008 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -83,6 +83,7 @@ .Nm ssh-keygen .Fl F Ar hostname .Op Fl f Ar known_hosts_file +.Op Fl l .Nm ssh-keygen .Fl H .Op Fl f Ar known_hosts_file diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c index f7e2840621..5765cff088 100644 --- a/crypto/openssh/ssh-keygen.c +++ b/crypto/openssh/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.171 2008/07/13 21:22:52 sthen Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.173 2009/02/21 19:32:04 tobias Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -135,7 +135,7 @@ ask_filename(struct passwd *pw, const char *prompt) name = _PATH_SSH_CLIENT_ID_RSA; break; default: - fprintf(stderr, "bad key type"); + fprintf(stderr, "bad key type\n"); exit(1); break; } @@ -421,7 +421,7 @@ do_convert_from_ssh2(struct passwd *pw) PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : key_write(k, stdout); if (!ok) { - fprintf(stderr, "key write failed"); + fprintf(stderr, "key write failed\n"); exit(1); } key_free(k); @@ -1015,11 +1015,11 @@ do_change_comment(struct passwd *pw) } f = fdopen(fd, "w"); if (f == NULL) { - printf("fdopen %s failed", identity_file); + printf("fdopen %s failed\n", identity_file); exit(1); } if (!key_write(public, f)) - fprintf(stderr, "write key failed"); + fprintf(stderr, "write key failed\n"); key_free(public); fprintf(f, " %s\n", new_comment); fclose(f); @@ -1366,7 +1366,7 @@ main(int argc, char **argv) printf("Generating public/private %s key pair.\n", key_type_name); private = key_generate(type, bits); if (private == NULL) { - fprintf(stderr, "key_generate failed"); + fprintf(stderr, "key_generate failed\n"); exit(1); } public = key_from_private(private); @@ -1426,7 +1426,7 @@ passphrase_again: if (identity_comment) { strlcpy(comment, identity_comment, sizeof(comment)); } else { - /* Create default commend field for the passphrase. */ + /* Create default comment field for the passphrase. */ snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); } @@ -1456,11 +1456,11 @@ passphrase_again: } f = fdopen(fd, "w"); if (f == NULL) { - printf("fdopen %s failed", identity_file); + printf("fdopen %s failed\n", identity_file); exit(1); } if (!key_write(public, f)) - fprintf(stderr, "write key failed"); + fprintf(stderr, "write key failed\n"); fprintf(f, " %s\n", comment); fclose(f); diff --git a/crypto/openssh/ssh-keyscan.1 b/crypto/openssh/ssh-keyscan.1 index 8a4f3bcba3..4a58645665 100644 --- a/crypto/openssh/ssh-keyscan.1 +++ b/crypto/openssh/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.24 2008/04/30 10:14:03 djm Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.26 2008/12/29 01:12:36 stevesk Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,7 +6,7 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" -.Dd $Mdocdate: April 30 2008 $ +.Dd $Mdocdate: December 29 2008 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME @@ -21,7 +21,7 @@ .Op Fl T Ar timeout .Op Fl t Ar type .Op Ar host | addrlist namelist -.Op Ar ... +.Ar ... .Ek .Sh DESCRIPTION .Nm @@ -137,7 +137,7 @@ or .Pa /etc/ssh/ssh_known_hosts .Sh EXAMPLES Print the -.Pa rsa1 +.Pa rsa host key for machine .Pa hostname : .Bd -literal diff --git a/crypto/openssh/ssh-keyscan.c b/crypto/openssh/ssh-keyscan.c index d810777646..9a91be499e 100644 --- a/crypto/openssh/ssh-keyscan.c +++ b/crypto/openssh/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.76 2008/04/30 10:14:03 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.78 2009/01/22 10:02:34 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -713,8 +713,9 @@ fatal(const char *fmt,...) static void usage(void) { - fprintf(stderr, "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n" - "\t\t [host | addrlist namelist] [...]\n", + fprintf(stderr, + "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n" + "\t\t [host | addrlist namelist] ...\n", __progname); exit(1); } @@ -747,7 +748,7 @@ main(int argc, char **argv) break; case 'p': ssh_port = a2port(optarg); - if (ssh_port == 0) { + if (ssh_port <= 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(1); } diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1 index 1883578f22..421783be36 100644 --- a/crypto/openssh/ssh.1 +++ b/crypto/openssh/ssh.1 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.277 2008/07/02 13:47:39 djm Exp $ -.Dd $Mdocdate: July 2 2008 $ +.\" $OpenBSD: ssh.1,v 1.282 2009/02/12 03:44:25 djm Exp $ +.Dd $Mdocdate: February 12 2009 $ .Dt SSH 1 .Os .Sh NAME @@ -43,7 +43,7 @@ .Nd OpenSSH SSH client (remote login program) .Sh SYNOPSIS .Nm ssh -.Op Fl 1246AaCfgKkMNnqsTtVvXxY +.Op Fl 1246AaCfgKkMNnqsTtVvXxYy .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Oo Fl D\ \& @@ -550,7 +550,7 @@ using an alternative syntax: .Pp By default, the listening socket on the server will be bound to the loopback interface only. -This may be overriden by specifying a +This may be overridden by specifying a .Ar bind_address . An empty .Ar bind_address , @@ -563,6 +563,13 @@ will only succeed if the server's .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . +.Pp +If the +.Ar port +argument is +.Ql 0 , +the listen port will be dynamically allocated on the server and reported +to the client at run time. .It Fl S Ar ctl_path Specifies the location of a control socket for connection sharing. Refer to the description of @@ -658,6 +665,11 @@ Disables X11 forwarding. Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls. +.It Fl y +Send log information using the +.Xr syslog 3 +system module. +By default this information is sent to stderr. .El .Pp .Nm @@ -893,9 +905,10 @@ Send a BREAK to the remote system .It Cm ~C Open command line. Currently this allows the addition of port forwardings using the -.Fl L -and +.Fl L , .Fl R +and +.Fl D options (see above). It also allows the cancellation of existing remote port-forwardings using diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c index e2dd67d688..9d43bb74fc 100644 --- a/crypto/openssh/ssh.c +++ b/crypto/openssh/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.318 2008/07/02 13:47:39 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.324 2009/02/12 03:00:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -179,7 +179,7 @@ static void usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" +"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" " [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" " [-i identity_file] [-L [bind_address:]port:host:hostport]\n" " [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" @@ -203,7 +203,7 @@ void muxserver_listen(void); int main(int ac, char **av) { - int i, opt, exit_status; + int i, opt, exit_status, use_syslog; char *p, *cp, *line, buf[256]; struct stat st; struct passwd *pw; @@ -269,10 +269,11 @@ main(int ac, char **av) /* Parse command-line arguments. */ host = NULL; + use_syslog = 0; again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" - "ACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) { + "ACD:F:I:KL:MNO:PR:S:TVw:XYy")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; @@ -299,6 +300,9 @@ main(int ac, char **av) case 'X': options.forward_x11 = 1; break; + case 'y': + use_syslog = 1; + break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; @@ -439,7 +443,7 @@ main(int ac, char **av) break; case 'p': options.port = a2port(optarg); - if (options.port == 0) { + if (options.port <= 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(255); } @@ -449,7 +453,7 @@ main(int ac, char **av) break; case 'L': - if (parse_forward(&fwd, optarg)) + if (parse_forward(&fwd, optarg, 0, 0)) add_local_forward(&options, &fwd); else { fprintf(stderr, @@ -460,7 +464,7 @@ main(int ac, char **av) break; case 'R': - if (parse_forward(&fwd, optarg)) { + if (parse_forward(&fwd, optarg, 0, 1)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, @@ -471,30 +475,14 @@ main(int ac, char **av) break; case 'D': - cp = p = xstrdup(optarg); - memset(&fwd, '\0', sizeof(fwd)); - fwd.connect_host = "socks"; - if ((fwd.listen_host = hpdelim(&cp)) == NULL) { - fprintf(stderr, "Bad dynamic forwarding " - "specification '%.100s'\n", optarg); - exit(255); - } - if (cp != NULL) { - fwd.listen_port = a2port(cp); - fwd.listen_host = - cleanhostname(fwd.listen_host); + if (parse_forward(&fwd, optarg, 1, 0)) { + add_local_forward(&options, &fwd); } else { - fwd.listen_port = a2port(fwd.listen_host); - fwd.listen_host = NULL; - } - - if (fwd.listen_port == 0) { - fprintf(stderr, "Bad dynamic port '%s'\n", - optarg); + fprintf(stderr, + "Bad dynamic forwarding specification " + "'%s'\n", optarg); exit(255); } - add_local_forward(&options, &fwd); - xfree(p); break; case 'C': @@ -614,7 +602,7 @@ main(int ac, char **av) */ log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, - SYSLOG_FACILITY_USER, 1); + SYSLOG_FACILITY_USER, !use_syslog); /* * Read per-user configuration file. Ignore the system wide config @@ -640,7 +628,7 @@ main(int ac, char **av) channel_set_af(options.address_family); /* reinit */ - log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); + log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, !use_syslog); seed_rng(); @@ -849,9 +837,16 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) { Forward *rfwd = (Forward *)ctxt; + /* XXX verbose() on failure? */ debug("remote forward %s for: listen %d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); + if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) { + logit("Allocated port %u for remote forward to %s:%d", + packet_get_int(), + rfwd->connect_host, rfwd->connect_port); + } + if (type == SSH2_MSG_REQUEST_FAILURE) { if (options.exit_on_forward_failure) fatal("Error: remote port forwarding failed for " @@ -1200,7 +1195,8 @@ ssh_session2(void) id = ssh_session2_open(); /* If we don't expect to open a new session, then disallow it */ - if (options.control_master == SSHCTL_MASTER_NO) { + if (options.control_master == SSHCTL_MASTER_NO && + (datafellows & SSH_NEW_OPENSSH)) { debug("Requesting no-more-sessions@openssh.com"); packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_put_cstring("no-more-sessions@openssh.com"); diff --git a/crypto/openssh/ssh2.h b/crypto/openssh/ssh2.h index cf56bc4ee1..1c33dc268b 100644 --- a/crypto/openssh/ssh2.h +++ b/crypto/openssh/ssh2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh2.h,v 1.10 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: ssh2.h,v 1.11 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -111,6 +111,12 @@ #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 +#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1 60 +#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1 61 +#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2 62 +#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2 63 +#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM 64 +#define SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM 65 /* connection protocol: generic */ @@ -159,3 +165,4 @@ #define SSH2_OPEN_RESOURCE_SHORTAGE 4 #define SSH2_EXTENDED_DATA_STDERR 1 + diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config index 8cb0698a8d..f28d595834 100644 --- a/crypto/openssh/ssh_config +++ b/crypto/openssh/ssh_config @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.23 2007/06/08 04:40:40 pvalchev Exp $ +# $OpenBSD: ssh_config,v 1.25 2009/02/17 01:28:32 djm Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -37,9 +37,10 @@ # Port 22 # Protocol 2,1 # Cipher 3des -# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc +# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc # MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no +# VisualHostKey no diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5 index 85e7ba06d7..ea9a20b23e 100644 --- a/crypto/openssh/ssh_config.5 +++ b/crypto/openssh/ssh_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.111 2008/06/26 11:46:31 grunk Exp $ -.Dd $Mdocdate: June 26 2008 $ +.\" $OpenBSD: ssh_config.5,v 1.119 2009/02/22 23:50:57 djm Exp $ +.Dd $Mdocdate: February 22 2009 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -103,7 +103,7 @@ Restricts the following declarations (up to the next .Cm Host keyword) to be only for those hosts that match one of the patterns given after the keyword. -If more than one pattern is provided, they should be separated by whitepsace. +If more than one pattern is provided, they should be separated by whitespace. A single .Ql * as a pattern can be used to provide global @@ -204,9 +204,9 @@ and .Dq cast128-cbc . The default is: .Bd -literal -offset 3n -aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour128, -arcfour256,arcfour,aes192-cbc,aes256-cbc,aes128-ctr, -aes192-ctr,aes256-ctr +aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, +aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, +aes256-cbc,arcfour .Ed .It Cm ClearAllForwardings Specifies that all local, remote, and dynamic port forwardings @@ -811,7 +811,15 @@ and .Ar host Ns / Ns Ar hostport . Multiple forwardings may be specified, and additional forwardings can be given on the command line. -Only the superuser can forward privileged ports. +Privileged ports can be forwarded only when +logging in as root on the remote machine. +.Pp +If the +.Ar port +argument is +.Ql 0 , +the listen port will be dynamically allocated on the server and reported +to the client at run time. .Pp If the .Ar bind_address @@ -1064,10 +1072,12 @@ in If this flag is set to .Dq yes , an ASCII art representation of the remote host key fingerprint is -printed additionally to the hex fingerprint string. +printed in addition to the hex fingerprint string at login and +for unknown host keys. If this flag is set to .Dq no , -only the hex fingerprint string will be printed. +no fingerprint strings are printed at login and +only the hex fingerprint string will be printed for unknown host keys. The default is .Dq no . .It Cm XAuthLocation diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c index ec8ba33e01..c04aa10571 100644 --- a/crypto/openssh/sshconnect.c +++ b/crypto/openssh/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.211 2008/07/01 07:24:22 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.212 2008/10/14 18:11:33 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -70,10 +70,6 @@ extern uid_t original_real_uid; extern uid_t original_effective_uid; extern pid_t proxy_command_pid; -#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ -#define INET6_ADDRSTRLEN 46 -#endif - static int show_other_keys(const char *, Key *); static void warn_changed_key(Key *); @@ -741,8 +737,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, if (options.host_key_alias == NULL && port != 0 && port != SSH_DEFAULT_PORT) { debug("checking without port identifier"); - if (check_host_key(hostname, hostaddr, 0, host_key, 2, - user_hostfile, system_hostfile) == 0) { + if (check_host_key(hostname, hostaddr, 0, host_key, + ROQUIET, user_hostfile, system_hostfile) == 0) { debug("found matching key w/out port"); break; } diff --git a/crypto/openssh/sshconnect2.c b/crypto/openssh/sshconnect2.c index 389bec9e43..a762eec3bd 100644 --- a/crypto/openssh/sshconnect2.c +++ b/crypto/openssh/sshconnect2.c @@ -1,6 +1,7 @@ -/* $OpenBSD: sshconnect2.c,v 1.166 2008/07/17 08:48:00 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.170 2008/11/04 08:22:13 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -67,6 +68,7 @@ #include "msg.h" #include "pathnames.h" #include "uidswap.h" +#include "jpake.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -201,6 +203,7 @@ struct Authctxt { struct Authmethod { char *name; /* string to compare against server's list */ int (*userauth)(Authctxt *authctxt); + void (*cleanup)(Authctxt *authctxt); int *enabled; /* flag in option struct that enables method */ int *batch_flag; /* flag in option struct that disables method */ }; @@ -212,13 +215,18 @@ void input_userauth_error(int, u_int32_t, void *); void input_userauth_info_req(int, u_int32_t, void *); void input_userauth_pk_ok(int, u_int32_t, void *); void input_userauth_passwd_changereq(int, u_int32_t, void *); +void input_userauth_jpake_server_step1(int, u_int32_t, void *); +void input_userauth_jpake_server_step2(int, u_int32_t, void *); +void input_userauth_jpake_server_confirm(int, u_int32_t, void *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); int userauth_passwd(Authctxt *); int userauth_kbdint(Authctxt *); int userauth_hostbased(Authctxt *); -int userauth_kerberos(Authctxt *); +int userauth_jpake(Authctxt *); + +void userauth_jpake_cleanup(Authctxt *); #ifdef GSSAPI int userauth_gssapi(Authctxt *authctxt); @@ -244,30 +252,43 @@ Authmethod authmethods[] = { #ifdef GSSAPI {"gssapi-with-mic", userauth_gssapi, + NULL, &options.gss_authentication, NULL}, #endif {"hostbased", userauth_hostbased, + NULL, &options.hostbased_authentication, NULL}, {"publickey", userauth_pubkey, + NULL, &options.pubkey_authentication, NULL}, +#ifdef JPAKE + {"jpake-01@openssh.com", + userauth_jpake, + userauth_jpake_cleanup, + &options.zero_knowledge_password_authentication, + &options.batch_mode}, +#endif {"keyboard-interactive", userauth_kbdint, + NULL, &options.kbd_interactive_authentication, &options.batch_mode}, {"password", userauth_passwd, + NULL, &options.password_authentication, &options.batch_mode}, {"none", userauth_none, NULL, + NULL, NULL}, - {NULL, NULL, NULL, NULL} + {NULL, NULL, NULL, NULL, NULL} }; void @@ -335,6 +356,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, void userauth(Authctxt *authctxt, char *authlist) { + if (authctxt->method != NULL && authctxt->method->cleanup != NULL) + authctxt->method->cleanup(authctxt); + if (authctxt->methoddata) { xfree(authctxt->methoddata); authctxt->methoddata = NULL; @@ -367,6 +391,7 @@ userauth(Authctxt *authctxt, char *authlist) } } +/* ARGSUSED */ void input_userauth_error(int type, u_int32_t seq, void *ctxt) { @@ -374,6 +399,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt) "type %d", type); } +/* ARGSUSED */ void input_userauth_banner(int type, u_int32_t seq, void *ctxt) { @@ -383,11 +409,11 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) debug3("input_userauth_banner"); raw = packet_get_string(&len); lang = packet_get_string(NULL); - if (options.log_level >= SYSLOG_LEVEL_INFO) { + if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) { if (len > 65536) len = 65536; - msg = xmalloc(len * 4); /* max expansion from strnvis() */ - strnvis(msg, raw, len * 4, VIS_SAFE|VIS_OCTAL); + msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */ + strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL); fprintf(stderr, "%s", msg); xfree(msg); } @@ -395,6 +421,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) xfree(lang); } +/* ARGSUSED */ void input_userauth_success(int type, u_int32_t seq, void *ctxt) { @@ -412,6 +439,7 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt) authctxt->success = 1; /* break out */ } +/* ARGSUSED */ void input_userauth_failure(int type, u_int32_t seq, void *ctxt) { @@ -432,6 +460,8 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt) userauth(authctxt, authlist); } + +/* ARGSUSED */ void input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) { @@ -614,6 +644,7 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) return status; } +/* ARGSUSED */ void input_gssapi_response(int type, u_int32_t plen, void *ctxt) { @@ -653,6 +684,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) } } +/* ARGSUSED */ void input_gssapi_token(int type, u_int32_t plen, void *ctxt) { @@ -680,6 +712,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) } } +/* ARGSUSED */ void input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) { @@ -709,6 +742,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) /* Server will be returning a failed packet after this one */ } +/* ARGSUSED */ void input_gssapi_error(int type, u_int32_t plen, void *ctxt) { @@ -773,9 +807,11 @@ userauth_passwd(Authctxt *authctxt) return 1; } + /* * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ +/* ARGSUSED */ void input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) { @@ -840,6 +876,209 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) &input_userauth_passwd_changereq); } +#ifdef JPAKE +static char * +pw_encrypt(const char *password, const char *crypt_scheme, const char *salt) +{ + /* OpenBSD crypt(3) handles all of these */ + if (strcmp(crypt_scheme, "crypt") == 0 || + strcmp(crypt_scheme, "bcrypt") == 0 || + strcmp(crypt_scheme, "md5crypt") == 0 || + strcmp(crypt_scheme, "crypt-extended") == 0) + return xstrdup(crypt(password, salt)); + error("%s: unsupported password encryption scheme \"%.100s\"", + __func__, crypt_scheme); + return NULL; +} + +static BIGNUM * +jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme, + const char *salt) +{ + char prompt[256], *password, *crypted; + u_char *secret; + u_int secret_len; + BIGNUM *ret; + + snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ", + authctxt->server_user, authctxt->host); + password = read_passphrase(prompt, 0); + + if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) { + logit("Disabling %s authentication", authctxt->method->name); + authctxt->method->enabled = NULL; + /* Continue with an empty password to fail gracefully */ + crypted = xstrdup(""); + } + +#ifdef JPAKE_DEBUG + debug3("%s: salt = %s", __func__, salt); + debug3("%s: scheme = %s", __func__, crypt_scheme); + debug3("%s: crypted = %s", __func__, crypted); +#endif + + if (hash_buffer(crypted, strlen(crypted), EVP_sha256(), + &secret, &secret_len) != 0) + fatal("%s: hash_buffer", __func__); + + bzero(password, strlen(password)); + bzero(crypted, strlen(crypted)); + xfree(password); + xfree(crypted); + + if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL) + fatal("%s: BN_bin2bn (secret)", __func__); + bzero(secret, secret_len); + xfree(secret); + + return ret; +} + +/* ARGSUSED */ +void +input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt) +{ + Authctxt *authctxt = ctxt; + struct jpake_ctx *pctx = authctxt->methoddata; + u_char *x3_proof, *x4_proof, *x2_s_proof; + u_int x3_proof_len, x4_proof_len, x2_s_proof_len; + char *crypt_scheme, *salt; + + /* Disable this message */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL); + + if ((pctx->g_x3 = BN_new()) == NULL || + (pctx->g_x4 = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + + /* Fetch step 1 values */ + crypt_scheme = packet_get_string(NULL); + salt = packet_get_string(NULL); + pctx->server_id = packet_get_string(&pctx->server_id_len); + packet_get_bignum2(pctx->g_x3); + packet_get_bignum2(pctx->g_x4); + x3_proof = packet_get_string(&x3_proof_len); + x4_proof = packet_get_string(&x4_proof_len); + packet_check_eom(); + + JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__)); + + /* Obtain password and derive secret */ + pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt); + bzero(crypt_scheme, strlen(crypt_scheme)); + bzero(salt, strlen(salt)); + xfree(crypt_scheme); + xfree(salt); + JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__)); + + /* Calculate step 2 values */ + jpake_step2(pctx->grp, pctx->s, pctx->g_x1, + pctx->g_x3, pctx->g_x4, pctx->x2, + pctx->server_id, pctx->server_id_len, + pctx->client_id, pctx->client_id_len, + x3_proof, x3_proof_len, + x4_proof, x4_proof_len, + &pctx->a, + &x2_s_proof, &x2_s_proof_len); + + bzero(x3_proof, x3_proof_len); + bzero(x4_proof, x4_proof_len); + xfree(x3_proof); + xfree(x4_proof); + + JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__)); + + /* Send values for step 2 */ + packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2); + packet_put_bignum2(pctx->a); + packet_put_string(x2_s_proof, x2_s_proof_len); + packet_send(); + + bzero(x2_s_proof, x2_s_proof_len); + xfree(x2_s_proof); + + /* Expect step 2 packet from peer */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, + input_userauth_jpake_server_step2); +} + +/* ARGSUSED */ +void +input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt) +{ + Authctxt *authctxt = ctxt; + struct jpake_ctx *pctx = authctxt->methoddata; + u_char *x4_s_proof; + u_int x4_s_proof_len; + + /* Disable this message */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL); + + if ((pctx->b = BN_new()) == NULL) + fatal("%s: BN_new", __func__); + + /* Fetch step 2 values */ + packet_get_bignum2(pctx->b); + x4_s_proof = packet_get_string(&x4_s_proof_len); + packet_check_eom(); + + JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__)); + + /* Derive shared key and calculate confirmation hash */ + jpake_key_confirm(pctx->grp, pctx->s, pctx->b, + pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4, + pctx->client_id, pctx->client_id_len, + pctx->server_id, pctx->server_id_len, + session_id2, session_id2_len, + x4_s_proof, x4_s_proof_len, + &pctx->k, + &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len); + + bzero(x4_s_proof, x4_s_proof_len); + xfree(x4_s_proof); + + JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__)); + + /* Send key confirmation proof */ + packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM); + packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len); + packet_send(); + + /* Expect confirmation from peer */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, + input_userauth_jpake_server_confirm); +} + +/* ARGSUSED */ +void +input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt) +{ + Authctxt *authctxt = ctxt; + struct jpake_ctx *pctx = authctxt->methoddata; + + /* Disable this message */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL); + + pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len); + packet_check_eom(); + + JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__)); + + /* Verify expected confirmation hash */ + if (jpake_check_confirm(pctx->k, + pctx->server_id, pctx->server_id_len, + session_id2, session_id2_len, + pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1) + debug("%s: %s success", __func__, authctxt->method->name); + else { + debug("%s: confirmation mismatch", __func__); + /* XXX stash this so if auth succeeds then we can warn/kill */ + } + + userauth_jpake_cleanup(authctxt); +} +#endif /* JPAKE */ + static int identity_sign(Identity *id, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) @@ -1414,6 +1653,76 @@ userauth_hostbased(Authctxt *authctxt) return 1; } +#ifdef JPAKE +int +userauth_jpake(Authctxt *authctxt) +{ + struct jpake_ctx *pctx; + u_char *x1_proof, *x2_proof; + u_int x1_proof_len, x2_proof_len; + static int attempt = 0; /* XXX share with userauth_password's? */ + + if (attempt++ >= options.number_of_password_prompts) + return 0; + if (attempt != 1) + error("Permission denied, please try again."); + + if (authctxt->methoddata != NULL) + fatal("%s: authctxt->methoddata already set (%p)", + __func__, authctxt->methoddata); + + authctxt->methoddata = pctx = jpake_new(); + + /* + * Send request immediately, to get the protocol going while + * we do the initial computations. + */ + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_send(); + packet_write_wait(); + + jpake_step1(pctx->grp, + &pctx->client_id, &pctx->client_id_len, + &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2, + &x1_proof, &x1_proof_len, + &x2_proof, &x2_proof_len); + + JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__)); + + packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1); + packet_put_string(pctx->client_id, pctx->client_id_len); + packet_put_bignum2(pctx->g_x1); + packet_put_bignum2(pctx->g_x2); + packet_put_string(x1_proof, x1_proof_len); + packet_put_string(x2_proof, x2_proof_len); + packet_send(); + + bzero(x1_proof, x1_proof_len); + bzero(x2_proof, x2_proof_len); + xfree(x1_proof); + xfree(x2_proof); + + /* Expect step 1 packet from peer */ + dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, + input_userauth_jpake_server_step1); + + return 1; +} + +void +userauth_jpake_cleanup(Authctxt *authctxt) +{ + debug3("%s: clean up", __func__); + if (authctxt->methoddata != NULL) { + jpake_free(authctxt->methoddata); + authctxt->methoddata = NULL; + } +} +#endif /* JPAKE */ + /* find auth method */ /* @@ -1515,3 +1824,4 @@ authmethods_get(void) buffer_free(&b); return list; } + diff --git a/crypto/openssh/sshd.8 b/crypto/openssh/sshd.8 index c4c4181fcd..a4b9e90c71 100644 --- a/crypto/openssh/sshd.8 +++ b/crypto/openssh/sshd.8 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.246 2008/07/02 02:24:18 djm Exp $ -.Dd $Mdocdate: July 2 2008 $ +.\" $OpenBSD: sshd.8,v 1.247 2008/10/03 13:08:12 jmc Exp $ +.Dd $Mdocdate: October 3 2008 $ .Dt SSHD 8 .Os .Sh NAME @@ -741,8 +741,6 @@ will not allow it to be used unless the .Cm StrictModes option has been set to .Dq no . -The recommended permissions can be set by executing -.Dq chmod go-w ~/ ~/.ssh ~/.ssh/authorized_keys . .Pp .It ~/.ssh/environment This file is read into the environment at login (if it exists). diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index 6e5bb5476a..3b5cd3cfd6 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.364 2008/07/10 18:08:11 markus Exp $ */ +/* $OpenBSD: sshd.c,v 1.366 2009/01/22 10:02:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -117,7 +117,6 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" -#include "monitor_fdpass.h" #include "version.h" #ifdef LIBWRAP @@ -1334,7 +1333,7 @@ main(int ac, char **av) exit(1); } options.ports[options.num_ports++] = a2port(optarg); - if (options.ports[options.num_ports-1] == 0) { + if (options.ports[options.num_ports-1] <= 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index 7255b1c226..dfd07b713e 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.96 2008/07/02 02:24:18 djm Exp $ -.Dd $Mdocdate: July 2 2008 $ +.\" $OpenBSD: sshd_config.5,v 1.102 2009/02/22 23:59:25 djm Exp $ +.Dd $Mdocdate: February 22 2009 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -240,9 +240,9 @@ and .Dq cast128-cbc . The default is: .Bd -literal -offset 3n -aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour128, -arcfour256,arcfour,aes192-cbc,aes256-cbc,aes128-ctr, -aes192-ctr,aes256-ctr +aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, +aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, +aes256-cbc,arcfour .Ed .It Cm ClientAliveCountMax Sets the number of client alive messages (see below) which may be @@ -593,6 +593,7 @@ Only a subset of keywords may be used on the lines following a .Cm Match keyword. Available keywords are +.Cm AllowAgentForwarding , .Cm AllowTcpForwarding , .Cm Banner , .Cm ChrootDirectory , @@ -605,12 +606,13 @@ Available keywords are .Cm MaxAuthTries , .Cm MaxSessions , .Cm PasswordAuthentication , +.Cm PermitEmptyPasswords , .Cm PermitOpen , .Cm PermitRootLogin , .Cm RhostsRSAAuthentication , .Cm RSAAuthentication , .Cm X11DisplayOffset , -.Cm X11Forwarding , +.Cm X11Forwarding and .Cm X11UseLocalHost . .It Cm MaxAuthTries diff --git a/crypto/openssh/sshpty.c b/crypto/openssh/sshpty.c index 5a0d1a7adb..bbbc0fefee 100644 --- a/crypto/openssh/sshpty.c +++ b/crypto/openssh/sshpty.c @@ -46,6 +46,13 @@ #define O_NOCTTY 0 #endif +#ifdef __APPLE__ +# include +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) +# define __APPLE_PRIVPTY__ +# endif +#endif + /* * Allocates and opens a pty. Returns 0 if no pty could be allocated, or * nonzero if a pty was successfully allocated. On success, open file @@ -78,10 +85,12 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) void pty_release(const char *tty) { +#ifndef __APPLE_PRIVPTY__ if (chown(tty, (uid_t) 0, (gid_t) 0) < 0) error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno)); if (chmod(tty, (mode_t) 0666) < 0) error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno)); +#endif /* __APPLE_PRIVPTY__ */ } /* Makes the tty the process's controlling tty and sets it to sane modes. */ diff --git a/crypto/openssh/ttymodes.c b/crypto/openssh/ttymodes.c index e116b19990..6f51b8a708 100644 --- a/crypto/openssh/ttymodes.c +++ b/crypto/openssh/ttymodes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ttymodes.c,v 1.28 2008/07/07 00:31:41 stevesk Exp $ */ +/* $OpenBSD: ttymodes.c,v 1.29 2008/11/02 00:16:16 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -311,11 +311,9 @@ tty_make_modes(int fd, struct termios *tiop) /* Store input and output baud rates. */ baud = speed_to_baud(cfgetospeed(&tio)); - debug3("tty_make_modes: ospeed %d", baud); buffer_put_char(&buf, tty_op_ospeed); buffer_put_int(&buf, baud); baud = speed_to_baud(cfgetispeed(&tio)); - debug3("tty_make_modes: ispeed %d", baud); buffer_put_char(&buf, tty_op_ispeed); buffer_put_int(&buf, baud); @@ -359,7 +357,6 @@ tty_parse_modes(int fd, int *n_bytes_ptr) if (compat20) { *n_bytes_ptr = packet_get_int(); - debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); if (*n_bytes_ptr == 0) return; get_arg = packet_get_int; @@ -391,7 +388,6 @@ tty_parse_modes(int fd, int *n_bytes_ptr) case TTY_OP_ISPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - debug3("tty_parse_modes: ispeed %d", baud); if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); @@ -402,7 +398,6 @@ tty_parse_modes(int fd, int *n_bytes_ptr) case TTY_OP_OSPEED_PROTO2: n_bytes += 4; baud = packet_get_int(); - debug3("tty_parse_modes: ospeed %d", baud); if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); diff --git a/crypto/openssh/uidswap.c b/crypto/openssh/uidswap.c index 91d878c30e..8376483967 100644 --- a/crypto/openssh/uidswap.c +++ b/crypto/openssh/uidswap.c @@ -233,6 +233,16 @@ permanently_set_uid(struct passwd *pw) fatal("setgid %u: %.100s", (u_int)pw->pw_gid, strerror(errno)); #endif +#ifdef __APPLE__ + /* + * OS X requires initgroups after setgid to opt back into + * memberd support for >16 supplemental groups. + */ + if (initgroups(pw->pw_name, pw->pw_gid) < 0) + fatal("initgroups %.100s %u: %.100s", + pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); +#endif + #if defined(HAVE_SETRESUID) && !defined(BROKEN_SETRESUID) if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) fatal("setresuid %u: %.100s", (u_int)pw->pw_uid, strerror(errno)); -- 2.41.0