From ac006e744bcd8c4f300fd62d06173643bae44c3d Mon Sep 17 00:00:00 2001 From: Marcin Krol Date: Wed, 5 Feb 2014 12:58:43 +0000 Subject: [PATCH] - from PLD --- ldap-helper-sigpipe.patch | 94 + ldap.conf.patch | 56 + openssh-5.2p1-hpn13v6.diff | 3695 +++++++++++++++++++ openssh-5.8p1-authorized-keys-command.patch | 447 +++ openssh-bind.patch | 11 + openssh-blacklist.diff | 984 +++++ openssh-chroot.patch | 157 + openssh-config.patch | 108 + openssh-disable_ldap.patch | 23 + openssh-include.patch | 11 + openssh-kuserok.patch | 167 + openssh-ldap-fixes.patch | 25 + openssh-ldap.patch | 2609 +++++++++++++ openssh-lpk.schema | 19 + openssh-no_libnsl.patch | 23 + openssh-pam_misc.patch | 12 + openssh-sigpipe.patch | 95 + openssh.spec | 867 +++++ openssh.sysconfig | 7 + opensshd.init | 178 + opensshd.pamd | 12 + opensshd.upstart | 36 + ssh-agent.conf | 19 + ssh-agent.sh | 28 + sshd-keygen | 28 + sshd.service | 14 + sshd.socket | 10 + sshd@.service | 9 + 28 files changed, 9744 insertions(+) create mode 100644 ldap-helper-sigpipe.patch create mode 100644 ldap.conf.patch create mode 100644 openssh-5.2p1-hpn13v6.diff create mode 100644 openssh-5.8p1-authorized-keys-command.patch create mode 100644 openssh-bind.patch create mode 100644 openssh-blacklist.diff create mode 100644 openssh-chroot.patch create mode 100644 openssh-config.patch create mode 100644 openssh-disable_ldap.patch create mode 100644 openssh-include.patch create mode 100644 openssh-kuserok.patch create mode 100644 openssh-ldap-fixes.patch create mode 100644 openssh-ldap.patch create mode 100644 openssh-lpk.schema create mode 100644 openssh-no_libnsl.patch create mode 100644 openssh-pam_misc.patch create mode 100644 openssh-sigpipe.patch create mode 100644 openssh.spec create mode 100644 openssh.sysconfig create mode 100755 opensshd.init create mode 100644 opensshd.pamd create mode 100644 opensshd.upstart create mode 100644 ssh-agent.conf create mode 100644 ssh-agent.sh create mode 100644 sshd-keygen create mode 100644 sshd.service create mode 100644 sshd.socket create mode 100644 sshd@.service diff --git a/ldap-helper-sigpipe.patch b/ldap-helper-sigpipe.patch new file mode 100644 index 0000000..7c51100 --- /dev/null +++ b/ldap-helper-sigpipe.patch @@ -0,0 +1,94 @@ +ignore SIGPIPE from ldap-helper. ssh server does not read whole input if matching key is found + +with latest ldap patch from fedora openssh package repo +(84822b5decc2ddd8415a3167b9ff9f0a368929a3), i encountered bug that if there are +lots of keys for user and matching key is found near the beginning, the +ssh-ldap-helper gets sigpipe because apparently sshd server does not read out +whole output. and that killed by signal is propagated so that whole key auth +fails. + +i'm not sure in which side the fixing should be made, should ldap-helper ignore +SIGPIPE? should ssh authorizedkeyscommand always read up whole input? + +in my case user had only 51 keys outputing ~35k of text: +# /usr/lib/openssh/ssh-ldap-helper -s git | wc + 51 251 35685 + +i think it's quite easy to reproduce: +- print out matchin key early +- produce more lines of output + +so, here's strace of ssh-ldap-helper being called from ssh-ldap-wrapper: + +execve("/usr/lib/openssh/ssh-ldap-helper", ["/usr/lib/openssh/ssh-ldap-helper", "-s", "git"], [/* 13 vars */]) = 0 +access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 +open("/usr/lib/libldap-2.4.so.2", O_RDONLY|O_CLOEXEC) = 3 +open("/usr/lib/liblber-2.4.so.2", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 +open("/usr/lib/libsasl2.so.3", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libssl.so.1.0.0", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libcrypt.so.1", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libpam.so.0", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libaudit.so.1", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3 +open("/lib/libfreebl3.so", O_RDONLY|O_CLOEXEC) = 3 +open("/dev/null", O_RDWR|O_LARGEFILE) = 4 +open("/etc/ldap.conf", O_RDONLY|O_LARGEFILE) = 4 +open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4 +open("/lib/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/openldap/ldap.conf", O_RDONLY) = -1 ENOENT (No such file or directory) +open("/tmp/ldaprc", O_RDONLY) = -1 ENOENT (No such file or directory) +open("/tmp/.ldaprc", O_RDONLY) = -1 ENOENT (No such file or directory) +stat64("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=247, ...}) = 0 +open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 4 +open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4 +open("/lib/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 4 +--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=615, si_uid=99} --- ++++ killed by SIGPIPE +++ + +at the same time in the log: + +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: matching key found: file /usr/lib/openssh/ssh-ldap-wrapper, line 1 DSA 96:a8:6c:5b:42:ad:b4:f3:01:fc:19:38:da:63:0b:37 +Nov 2 18:20:44 gitolite3 sshd[605]: error: AuthorizedKeysCommand /usr/lib/openssh/ssh-ldap-wrapper returned status 141 +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: restore_uid: 0/0 +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: temporarily_use_uid: 264/264 (e=0/0) +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: trying public key file /home/services/git/.ssh/authorized_keys +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: fd 8 clearing O_NONBLOCK +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: restore_uid: 0/0 +Nov 2 18:20:44 gitolite3 sshd[605]: Failed publickey for git from 127.0.0.1 port 34574 ssh2: DSA 96:a8:6c:5b:42:ad:b4:f3:01:fc:19:38:da:63:0b:37 +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: userauth-request for user git service ssh-connection method keyboard-interactive [preauth] +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: attempt 2 failures 1 [preauth] +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: keyboard-interactive devs [preauth] +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: auth2_challenge: user=git devs= [preauth] +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: kbdint_alloc: devices 'pam' [preauth] +Nov 2 18:20:44 gitolite3 sshd[605]: debug1: auth2_challenge_start: trying authentication method 'pam' [preauth] + +there's quick workaround too (without patching), +instead of "exec ssh-ldap-helper", run it, and "exit 0" from the wrapper +script. i don't like this solution, but it makes the problem go away: + +# cat /usr/lib/openssh/ssh-ldap-wrapper +#!/bin/sh +/usr/lib/openssh/ssh-ldap-helper -s "$1" +exit 0 + +--- openssh-6.3p1/ldap-helper.c~ 2013-11-02 17:14:48.000000000 +0200 ++++ openssh-6.3p1/ldap-helper.c 2013-11-02 18:39:15.740402594 +0200 +@@ -137,6 +137,8 @@ + ldap_checkconfig(); + ldap_do_connect(); + ++ signal(SIGPIPE, SIG_IGN); ++ + if (config_single_user) { + process_user (config_single_user, outfile); + } else { diff --git a/ldap.conf.patch b/ldap.conf.patch new file mode 100644 index 0000000..6584785 --- /dev/null +++ b/ldap.conf.patch @@ -0,0 +1,56 @@ +--- openssh-5.9p1/./ldap-helper.c~ 2011-09-29 00:38:28.000000000 +0300 ++++ openssh-5.9p1/./ldap-helper.c 2011-09-29 00:54:04.004223268 +0300 +@@ -34,7 +34,7 @@ + + static int config_debug = 0; + int config_exclusive_config_file = 0; +-static char *config_file_name = "/etc/ssh/ldap.conf"; ++static char *config_file_name = "/etc/ldap.conf"; + static char *config_single_user = NULL; + static int config_verbose = SYSLOG_LEVEL_VERBOSE; + int config_warning_config_file = 0; +@@ -48,7 +48,7 @@ + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -d Output the log messages to stderr.\n"); + fprintf(stderr, " -e Check the config file for unknown commands.\n"); +- fprintf(stderr, " -f file Use alternate config file (default is /etc/ssh/ldap.conf).\n"); ++ fprintf(stderr, " -f file Use alternate config file (default is /etc/ldap.conf).\n"); + fprintf(stderr, " -s user Do not demonize, send the user's key to stdout.\n"); + fprintf(stderr, " -v Increase verbosity of the debug output (implies -d).\n"); + fprintf(stderr, " -w Warn on unknown commands in the config file.\n"); +--- openssh-5.9p1/./ssh-ldap-helper.8~ 2011-09-29 00:38:28.000000000 +0300 ++++ openssh-5.9p1/./ssh-ldap-helper.8 2011-09-29 00:54:14.308032118 +0300 +@@ -56,7 +56,7 @@ + halts if it encounters an unknown item in the ldap.conf file. + .It Fl f + .Nm +-uses this file as the ldap configuration file instead of /etc/ssh/ldap.conf (default). ++uses this file as the ldap configuration file instead of /etc/ldap.conf (default). + .It Fl s + .Nm + prints out the user's keys to stdout and exits. +--- openssh-5.9p1/./ssh-ldap.conf.5~ 2011-09-29 00:38:28.000000000 +0300 ++++ openssh-5.9p1/./ssh-ldap.conf.5 2011-09-29 00:54:40.285897653 +0300 +@@ -21,11 +21,11 @@ + .Nm ssh-ldap.conf + .Nd configuration file for ssh-ldap-helper + .Sh SYNOPSIS +-.Nm /etc/ssh/ldap.conf ++.Nm /etc/ldap.conf + .Sh DESCRIPTION + .Xr ssh-ldap-helper 8 + reads configuration data from +-.Pa /etc/ssh/ldap.conf ++.Pa /etc/ldap.conf + (or the file specified with + .Fl f + on the command line). +@@ -361,7 +361,7 @@ + .El + .Sh FILES + .Bl -tag -width Ds +-.It Pa /etc/ssh/ldap.conf ++.It Pa /etc/ldap.conf + Ldap configuration file for + .Xr ssh-ldap-helper 8 . + .El diff --git a/openssh-5.2p1-hpn13v6.diff b/openssh-5.2p1-hpn13v6.diff new file mode 100644 index 0000000..3c64d2a --- /dev/null +++ b/openssh-5.2p1-hpn13v6.diff @@ -0,0 +1,3695 @@ +diff -NupwB openssh-5.2p1-canonical/auth2.c openssh-5.2p1-hpn13v6/auth2.c +--- openssh-5.2p1-canonical/auth2.c 2008-11-05 00:20:46.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/auth2.c 2009-05-14 12:36:10.000000000 -0400 +@@ -49,6 +49,7 @@ + #include "dispatch.h" + #include "pathnames.h" + #include "buffer.h" ++#include "canohost.h" + + #ifdef GSSAPI + #include "ssh-gss.h" +@@ -75,6 +76,9 @@ extern Authmethod method_gssapi; + extern Authmethod method_jpake; + #endif + ++static int log_flag = 0; ++ ++ + Authmethod *authmethods[] = { + &method_none, + &method_pubkey, +@@ -225,6 +229,11 @@ input_userauth_request(int type, u_int32 + service = packet_get_string(NULL); + method = packet_get_string(NULL); + debug("userauth-request for user %s service %s method %s", user, service, method); ++ if (!log_flag) { ++ logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", ++ get_remote_ipaddr(), get_remote_port(), user); ++ log_flag = 1; ++ } + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + + if ((style = strchr(user, ':')) != NULL) +diff -NupwB openssh-5.2p1-canonical/buffer.c openssh-5.2p1-hpn13v6/buffer.c +--- openssh-5.2p1-canonical/buffer.c 2006-08-04 22:39:39.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/buffer.c 2009-05-14 12:36:10.000000000 -0400 +@@ -127,7 +127,7 @@ restart: + + /* Increase the size of the buffer and retry. */ + newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ); +- if (newlen > BUFFER_MAX_LEN) ++ if (newlen > BUFFER_MAX_LEN_HPN) + fatal("buffer_append_space: alloc %u not supported", + newlen); + buffer->buf = xrealloc(buffer->buf, 1, newlen); +diff -NupwB openssh-5.2p1-canonical/buffer.h openssh-5.2p1-hpn13v6/buffer.h +--- openssh-5.2p1-canonical/buffer.h 2008-05-19 00:59:37.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/buffer.h 2009-05-14 12:36:10.000000000 -0400 +@@ -16,6 +16,9 @@ + #ifndef BUFFER_H + #define BUFFER_H + ++/* move the following to a more appropriate place and name */ ++#define BUFFER_MAX_LEN_HPN 0x4000000 /* 64MB */ ++ + typedef struct { + u_char *buf; /* Buffer for data. */ + u_int alloc; /* Number of bytes allocated for data. */ +diff -NupwB openssh-5.2p1-canonical/channels.c openssh-5.2p1-hpn13v6/channels.c +--- openssh-5.2p1-canonical/channels.c 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/channels.c 2009-05-14 12:36:10.000000000 -0400 +@@ -169,8 +169,14 @@ static void port_open_helper(Channel *c, + static int connect_next(struct channel_connect *); + static void channel_connect_ctx_free(struct channel_connect *); + ++ ++static int hpn_disabled = 0; ++static int hpn_buffer_size = 2 * 1024 * 1024; ++ + /* -- channel core */ + ++ ++ + Channel * + channel_by_id(int id) + { +@@ -308,6 +314,7 @@ channel_new(char *ctype, int type, int r + c->local_window_max = window; + c->local_consumed = 0; + c->local_maxpacket = maxpack; ++ c->dynamic_window = 0; + c->remote_id = -1; + c->remote_name = xstrdup(remote_name); + c->remote_window = 0; +@@ -798,11 +805,35 @@ channel_pre_open_13(Channel *c, fd_set * + FD_SET(c->sock, writeset); + } + ++int channel_tcpwinsz () { ++ u_int32_t tcpwinsz = 0; ++ socklen_t optsz = sizeof(tcpwinsz); ++ int ret = -1; ++ ++ /* if we aren't on a socket return 128KB*/ ++ if(!packet_connection_is_on_socket()) ++ return(128*1024); ++ ret = getsockopt(packet_get_connection_in(), ++ SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); ++ /* return no more than 64MB */ ++ if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN) ++ tcpwinsz = BUFFER_MAX_LEN_HPN; ++ debug2("tcpwinsz: %d for connection: %d", tcpwinsz, ++ packet_get_connection_in()); ++ return(tcpwinsz); ++} ++ + static void + channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) + { + u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); + ++ /* check buffer limits */ ++ if ((!c->tcpwinsz) || (c->dynamic_window > 0)) ++ c->tcpwinsz = channel_tcpwinsz(); ++ ++ limit = MIN(limit, 2 * c->tcpwinsz); ++ + if (c->istate == CHAN_INPUT_OPEN && + limit > 0 && + buffer_len(&c->input) < limit && +@@ -1759,14 +1790,21 @@ channel_check_window(Channel *c) + c->local_maxpacket*3) || + c->local_window < c->local_window_max/2) && + c->local_consumed > 0) { ++ u_int addition = 0; ++ /* adjust max window size if we are in a dynamic environment */ ++ if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { ++ /* grow the window somewhat aggressively to maintain pressure */ ++ addition = 1.5*(c->tcpwinsz - c->local_window_max); ++ c->local_window_max += addition; ++ } + packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); + packet_put_int(c->remote_id); +- packet_put_int(c->local_consumed); ++ packet_put_int(c->local_consumed + addition); + packet_send(); + debug2("channel %d: window %d sent adjust %d", + c->self, c->local_window, + c->local_consumed); +- c->local_window += c->local_consumed; ++ c->local_window += c->local_consumed + addition; + c->local_consumed = 0; + } + return 1; +@@ -1969,11 +2007,12 @@ channel_after_select(fd_set *readset, fd + + + /* If there is data to send to the connection, enqueue some of it now. */ +-void ++int + channel_output_poll(void) + { + Channel *c; + u_int i, len; ++ int packet_length = 0; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; +@@ -2013,7 +2052,7 @@ channel_output_poll(void) + packet_start(SSH2_MSG_CHANNEL_DATA); + packet_put_int(c->remote_id); + packet_put_string(data, dlen); +- packet_send(); ++ packet_length = packet_send(); + c->remote_window -= dlen + 4; + free(data); + } +@@ -2043,7 +2082,7 @@ channel_output_poll(void) + SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); + packet_put_int(c->remote_id); + packet_put_string(buffer_ptr(&c->input), len); +- packet_send(); ++ packet_length = packet_send(); + buffer_consume(&c->input, len); + c->remote_window -= len; + } +@@ -2078,12 +2117,13 @@ channel_output_poll(void) + packet_put_int(c->remote_id); + packet_put_int(SSH2_EXTENDED_DATA_STDERR); + packet_put_string(buffer_ptr(&c->extended), len); +- packet_send(); ++ packet_length = packet_send(); + buffer_consume(&c->extended, len); + c->remote_window -= len; + debug2("channel %d: sent ext data %d", c->self, len); + } + } ++ return (packet_length); + } + + +@@ -2459,6 +2499,15 @@ channel_set_af(int af) + IPv4or6 = af; + } + ++ ++void ++channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size) ++{ ++ hpn_disabled = external_hpn_disabled; ++ hpn_buffer_size = external_hpn_buffer_size; ++ debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size); ++} ++ + static int + channel_setup_fwd_listener(int type, const char *listen_addr, + u_short listen_port, int *allocated_listen_port, +@@ -2610,9 +2659,15 @@ channel_setup_fwd_listener(int type, con + } + + /* Allocate a channel number for the socket. */ ++ /* explicitly test for hpn disabled option. if true use smaller window size */ ++ if (hpn_disabled) + c = channel_new("port listener", type, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); ++ else ++ c = channel_new("port listener", type, sock, sock, -1, ++ hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, ++ 0, "port listener", 1); + c->path = xstrdup(host); + c->host_port = port_to_connect; + c->listening_port = listen_port; +@@ -3151,10 +3206,17 @@ x11_create_display_inet(int x11_display_ + *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); + for (n = 0; n < num_socks; n++) { + sock = socks[n]; ++ /* Is this really necassary? */ ++ if (hpn_disabled) + nc = channel_new("x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, "X11 inet listener", 1); ++ else ++ nc = channel_new("x11 listener", ++ SSH_CHANNEL_X11_LISTENER, sock, sock, -1, ++ hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, ++ 0, "X11 inet listener", 1); + nc->single_connection = single_connection; + (*chanids)[n] = nc->self; + } +diff -NupwB openssh-5.2p1-canonical/channels.h openssh-5.2p1-hpn13v6/channels.h +--- openssh-5.2p1-canonical/channels.h 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/channels.h 2009-05-14 12:36:10.000000000 -0400 +@@ -115,8 +115,10 @@ struct Channel { + u_int local_window_max; + u_int local_consumed; + u_int local_maxpacket; ++ int dynamic_window; + int extended_usage; + int single_connection; ++ u_int tcpwinsz; + + char *ctype; /* type */ + +@@ -146,9 +148,11 @@ struct Channel { + + /* default window/packet sizes for tcp/x11-fwd-channel */ + #define CHAN_SES_PACKET_DEFAULT (32*1024) +-#define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) ++#define CHAN_SES_WINDOW_DEFAULT (4*CHAN_SES_PACKET_DEFAULT) ++ + #define CHAN_TCP_PACKET_DEFAULT (32*1024) +-#define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) ++#define CHAN_TCP_WINDOW_DEFAULT (4*CHAN_TCP_PACKET_DEFAULT) ++ + #define CHAN_X11_PACKET_DEFAULT (16*1024) + #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) + +@@ -221,7 +225,7 @@ void channel_input_status_confirm(int, + + void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int); + void channel_after_select(fd_set *, fd_set *); +-void channel_output_poll(void); ++int channel_output_poll(void); + + int channel_not_very_much_buffered_data(void); + void channel_close_all(void); +@@ -277,4 +281,7 @@ void chan_rcvd_ieof(Channel *); + void chan_write_failed(Channel *); + void chan_obuf_empty(Channel *); + ++/* hpn handler */ ++void channel_set_hpn(int, int); ++ + #endif +diff -NupwB openssh-5.2p1-canonical/cipher.c openssh-5.2p1-hpn13v6/cipher.c +--- openssh-5.2p1-canonical/cipher.c 2009-01-28 00:38:41.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/cipher.c 2009-05-14 12:36:10.000000000 -0400 +@@ -55,6 +55,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(voi + extern const EVP_CIPHER *evp_ssh1_3des(void); + extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); + extern const EVP_CIPHER *evp_aes_128_ctr(void); ++extern const EVP_CIPHER *evp_aes_ctr_mt(void); + extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); + + struct Cipher { +@@ -82,9 +83,9 @@ struct Cipher { + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, + { "rijndael-cbc@lysator.liu.se", + 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 }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_ctr_mt }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_ctr_mt }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_ctr_mt }, + #ifdef USE_CIPHER_ACSS + { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss }, + #endif +@@ -163,7 +164,8 @@ ciphers_valid(const char *names) + for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; + (p = strsep(&cp, CIPHER_SEP))) { + c = cipher_by_name(p); +- if (c == NULL || c->number != SSH_CIPHER_SSH2) { ++ if (c == NULL || (c->number != SSH_CIPHER_SSH2 && ++c->number != SSH_CIPHER_NONE)) { + debug("bad cipher %s [%s]", p, names); + free(cipher_list); + return 0; +@@ -337,6 +339,7 @@ cipher_get_keyiv(CipherContext *cc, u_ch + int evplen; + + switch (c->number) { ++ case SSH_CIPHER_NONE: + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: +@@ -371,6 +374,7 @@ cipher_set_keyiv(CipherContext *cc, u_ch + int evplen = 0; + + switch (c->number) { ++ case SSH_CIPHER_NONE: + case SSH_CIPHER_SSH2: + case SSH_CIPHER_DES: + case SSH_CIPHER_BLOWFISH: +diff -NupwB openssh-5.2p1-canonical/cipher-ctr-mt.c openssh-5.2p1-hpn13v6/cipher-ctr-mt.c +--- openssh-5.2p1-canonical/cipher-ctr-mt.c 1969-12-31 19:00:00.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/cipher-ctr-mt.c 2009-05-14 12:36:10.000000000 -0400 +@@ -0,0 +1,473 @@ ++/* ++ * OpenSSH Multi-threaded AES-CTR Cipher ++ * ++ * Author: Benjamin Bennett ++ * Copyright (c) 2008 Pittsburgh Supercomputing Center. All rights reserved. ++ * ++ * Based on original OpenSSH AES-CTR cipher. Small portions remain unchanged, ++ * Copyright (c) 2003 Markus Friedl ++ * ++ * 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. ++ */ ++#include "includes.h" ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "log.h" ++ ++/* compatibility with old or broken OpenSSL versions */ ++#include "openbsd-compat/openssl-compat.h" ++ ++#ifndef USE_BUILTIN_RIJNDAEL ++#include ++#endif ++ ++#include ++ ++/*-------------------- TUNABLES --------------------*/ ++/* Number of pregen threads to use */ ++#define CIPHER_THREADS 2 ++ ++/* Number of keystream queues */ ++#define NUMKQ (CIPHER_THREADS + 2) ++ ++/* Length of a keystream queue */ ++#define KQLEN 4096 ++ ++/* Processor cacheline length */ ++#define CACHELINE_LEN 64 ++ ++/* Collect thread stats and print at cancellation when in debug mode */ ++/* #define CIPHER_THREAD_STATS */ ++ ++/* Use single-byte XOR instead of 8-byte XOR */ ++/* #define CIPHER_BYTE_XOR */ ++/*-------------------- END TUNABLES --------------------*/ ++ ++ ++const EVP_CIPHER *evp_aes_ctr_mt(void); ++ ++#ifdef CIPHER_THREAD_STATS ++/* ++ * Struct to collect thread stats ++ */ ++struct thread_stats { ++ u_int fills; ++ u_int skips; ++ u_int waits; ++ u_int drains; ++}; ++ ++/* ++ * Debug print the thread stats ++ * Use with pthread_cleanup_push for displaying at thread cancellation ++ */ ++static void ++thread_loop_stats(void *x) ++{ ++ struct thread_stats *s = x; ++ ++ debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(), ++ s->fills, s->skips, s->waits); ++} ++ ++ #define STATS_STRUCT(s) struct thread_stats s ++ #define STATS_INIT(s) { memset(&s, 0, sizeof(s)); } ++ #define STATS_FILL(s) { s.fills++; } ++ #define STATS_SKIP(s) { s.skips++; } ++ #define STATS_WAIT(s) { s.waits++; } ++ #define STATS_DRAIN(s) { s.drains++; } ++#else ++ #define STATS_STRUCT(s) ++ #define STATS_INIT(s) ++ #define STATS_FILL(s) ++ #define STATS_SKIP(s) ++ #define STATS_WAIT(s) ++ #define STATS_DRAIN(s) ++#endif ++ ++/* Keystream Queue state */ ++enum { ++ KQINIT, ++ KQEMPTY, ++ KQFILLING, ++ KQFULL, ++ KQDRAINING ++}; ++ ++/* Keystream Queue struct */ ++struct kq { ++ u_char keys[KQLEN][AES_BLOCK_SIZE]; ++ u_char ctr[AES_BLOCK_SIZE]; ++ u_char pad0[CACHELINE_LEN]; ++ volatile int qstate; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ u_char pad1[CACHELINE_LEN]; ++}; ++ ++/* Context struct */ ++struct ssh_aes_ctr_ctx ++{ ++ struct kq q[NUMKQ]; ++ AES_KEY aes_ctx; ++ STATS_STRUCT(stats); ++ u_char aes_counter[AES_BLOCK_SIZE]; ++ pthread_t tid[CIPHER_THREADS]; ++ int state; ++ int qidx; ++ int ridx; ++}; ++ ++/* ++ * increment counter 'ctr', ++ * the counter is of size 'len' bytes and stored in network-byte-order. ++ * (LSB at ctr[len-1], MSB at ctr[0]) ++ */ ++static void ++ssh_ctr_inc(u_char *ctr, u_int len) ++{ ++ int i; ++ ++ for (i = len - 1; i >= 0; i--) ++ if (++ctr[i]) /* continue on overflow */ ++ return; ++} ++ ++/* ++ * Add num to counter 'ctr' ++ */ ++static void ++ssh_ctr_add(u_char *ctr, uint32_t num, u_int len) ++{ ++ int i; ++ uint16_t n; ++ ++ for (n = 0, i = len - 1; i >= 0 && (num || n); i--) { ++ n = ctr[i] + (num & 0xff) + n; ++ num >>= 8; ++ ctr[i] = n & 0xff; ++ n >>= 8; ++ } ++} ++ ++/* ++ * Threads may be cancelled in a pthread_cond_wait, we must free the mutex ++ */ ++static void ++thread_loop_cleanup(void *x) ++{ ++ pthread_mutex_unlock((pthread_mutex_t *)x); ++} ++ ++/* ++ * The life of a pregen thread: ++ * Find empty keystream queues and fill them using their counter. ++ * When done, update counter for the next fill. ++ */ ++static void * ++thread_loop(void *x) ++{ ++ AES_KEY key; ++ STATS_STRUCT(stats); ++ struct ssh_aes_ctr_ctx *c = x; ++ struct kq *q; ++ int i; ++ int qidx; ++ ++ /* Threads stats on cancellation */ ++ STATS_INIT(stats); ++#ifdef CIPHER_THREAD_STATS ++ pthread_cleanup_push(thread_loop_stats, &stats); ++#endif ++ ++ /* Thread local copy of AES key */ ++ memcpy(&key, &c->aes_ctx, sizeof(key)); ++ ++ /* ++ * Handle the special case of startup, one thread must fill ++ * the first KQ then mark it as draining. Lock held throughout. ++ */ ++ if (pthread_equal(pthread_self(), c->tid[0])) { ++ q = &c->q[0]; ++ pthread_mutex_lock(&q->lock); ++ if (q->qstate == KQINIT) { ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); ++ q->qstate = KQDRAINING; ++ STATS_FILL(stats); ++ pthread_cond_broadcast(&q->cond); ++ } ++ pthread_mutex_unlock(&q->lock); ++ } ++ else ++ STATS_SKIP(stats); ++ ++ /* ++ * Normal case is to find empty queues and fill them, skipping over ++ * queues already filled by other threads and stopping to wait for ++ * a draining queue to become empty. ++ * ++ * Multiple threads may be waiting on a draining queue and awoken ++ * when empty. The first thread to wake will mark it as filling, ++ * others will move on to fill, skip, or wait on the next queue. ++ */ ++ for (qidx = 1;; qidx = (qidx + 1) % NUMKQ) { ++ /* Check if I was cancelled, also checked in cond_wait */ ++ pthread_testcancel(); ++ ++ /* Lock queue and block if its draining */ ++ q = &c->q[qidx]; ++ pthread_mutex_lock(&q->lock); ++ pthread_cleanup_push(thread_loop_cleanup, &q->lock); ++ while (q->qstate == KQDRAINING || q->qstate == KQINIT) { ++ STATS_WAIT(stats); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ pthread_cleanup_pop(0); ++ ++ /* If filling or full, somebody else got it, skip */ ++ if (q->qstate != KQEMPTY) { ++ pthread_mutex_unlock(&q->lock); ++ STATS_SKIP(stats); ++ continue; ++ } ++ ++ /* ++ * Empty, let's fill it. ++ * Queue lock is relinquished while we do this so others ++ * can see that it's being filled. ++ */ ++ q->qstate = KQFILLING; ++ pthread_mutex_unlock(&q->lock); ++ for (i = 0; i < KQLEN; i++) { ++ AES_encrypt(q->ctr, q->keys[i], &key); ++ ssh_ctr_inc(q->ctr, AES_BLOCK_SIZE); ++ } ++ ++ /* Re-lock, mark full and signal consumer */ ++ pthread_mutex_lock(&q->lock); ++ ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE); ++ q->qstate = KQFULL; ++ STATS_FILL(stats); ++ pthread_cond_signal(&q->cond); ++ pthread_mutex_unlock(&q->lock); ++ } ++ ++#ifdef CIPHER_THREAD_STATS ++ /* Stats */ ++ pthread_cleanup_pop(1); ++#endif ++ ++ return NULL; ++} ++ ++static int ++ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, ++ u_int len) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ struct kq *q, *oldq; ++ int ridx; ++ u_char *buf; ++ ++ if (len == 0) ++ return (1); ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) ++ return (0); ++ ++ q = &c->q[c->qidx]; ++ ridx = c->ridx; ++ ++ /* src already padded to block multiple */ ++ while (len > 0) { ++ buf = q->keys[ridx]; ++ ++#ifdef CIPHER_BYTE_XOR ++ dest[0] = src[0] ^ buf[0]; ++ dest[1] = src[1] ^ buf[1]; ++ dest[2] = src[2] ^ buf[2]; ++ dest[3] = src[3] ^ buf[3]; ++ dest[4] = src[4] ^ buf[4]; ++ dest[5] = src[5] ^ buf[5]; ++ dest[6] = src[6] ^ buf[6]; ++ dest[7] = src[7] ^ buf[7]; ++ dest[8] = src[8] ^ buf[8]; ++ dest[9] = src[9] ^ buf[9]; ++ dest[10] = src[10] ^ buf[10]; ++ dest[11] = src[11] ^ buf[11]; ++ dest[12] = src[12] ^ buf[12]; ++ dest[13] = src[13] ^ buf[13]; ++ dest[14] = src[14] ^ buf[14]; ++ dest[15] = src[15] ^ buf[15]; ++#else ++ *(uint64_t *)dest = *(uint64_t *)src ^ *(uint64_t *)buf; ++ *(uint64_t *)(dest + 8) = *(uint64_t *)(src + 8) ^ ++ *(uint64_t *)(buf + 8); ++#endif ++ ++ dest += 16; ++ src += 16; ++ len -= 16; ++ ssh_ctr_inc(ctx->iv, AES_BLOCK_SIZE); ++ ++ /* Increment read index, switch queues on rollover */ ++ if ((ridx = (ridx + 1) % KQLEN) == 0) { ++ oldq = q; ++ ++ /* Mark next queue draining, may need to wait */ ++ c->qidx = (c->qidx + 1) % NUMKQ; ++ q = &c->q[c->qidx]; ++ pthread_mutex_lock(&q->lock); ++ while (q->qstate != KQFULL) { ++ STATS_WAIT(c->stats); ++ pthread_cond_wait(&q->cond, &q->lock); ++ } ++ q->qstate = KQDRAINING; ++ pthread_mutex_unlock(&q->lock); ++ ++ /* Mark consumed queue empty and signal producers */ ++ pthread_mutex_lock(&oldq->lock); ++ oldq->qstate = KQEMPTY; ++ STATS_DRAIN(c->stats); ++ pthread_cond_broadcast(&oldq->cond); ++ pthread_mutex_unlock(&oldq->lock); ++ } ++ } ++ c->ridx = ridx; ++ return (1); ++} ++ ++#define HAVE_NONE 0 ++#define HAVE_KEY 1 ++#define HAVE_IV 2 ++static int ++ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, ++ int enc) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ int i; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { ++ c = xmalloc(sizeof(*c)); ++ ++ c->state = HAVE_NONE; ++ for (i = 0; i < NUMKQ; i++) { ++ pthread_mutex_init(&c->q[i].lock, NULL); ++ pthread_cond_init(&c->q[i].cond, NULL); ++ } ++ ++ STATS_INIT(c->stats); ++ ++ EVP_CIPHER_CTX_set_app_data(ctx, c); ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* Cancel pregen threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_cancel(c->tid[i]); ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_join(c->tid[i], NULL); ++ /* Start over getting key & iv */ ++ c->state = HAVE_NONE; ++ } ++ ++ if (key != NULL) { ++ AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, ++ &c->aes_ctx); ++ c->state |= HAVE_KEY; ++ } ++ ++ if (iv != NULL) { ++ memcpy(ctx->iv, iv, AES_BLOCK_SIZE); ++ c->state |= HAVE_IV; ++ } ++ ++ if (c->state == (HAVE_KEY | HAVE_IV)) { ++ /* Clear queues */ ++ memcpy(c->q[0].ctr, ctx->iv, AES_BLOCK_SIZE); ++ c->q[0].qstate = KQINIT; ++ for (i = 1; i < NUMKQ; i++) { ++ memcpy(c->q[i].ctr, ctx->iv, AES_BLOCK_SIZE); ++ ssh_ctr_add(c->q[i].ctr, i * KQLEN, AES_BLOCK_SIZE); ++ c->q[i].qstate = KQEMPTY; ++ } ++ c->qidx = 0; ++ c->ridx = 0; ++ ++ /* Start threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) { ++ pthread_create(&c->tid[i], NULL, thread_loop, c); ++ } ++ pthread_mutex_lock(&c->q[0].lock); ++ while (c->q[0].qstate != KQDRAINING) ++ pthread_cond_wait(&c->q[0].cond, &c->q[0].lock); ++ pthread_mutex_unlock(&c->q[0].lock); ++ ++ } ++ return (1); ++} ++ ++static int ++ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) ++{ ++ struct ssh_aes_ctr_ctx *c; ++ int i; ++ ++ if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { ++#ifdef CIPHER_THREAD_STATS ++ debug("main thread: %u drains, %u waits", c->stats.drains, ++ c->stats.waits); ++#endif ++ /* Cancel pregen threads */ ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_cancel(c->tid[i]); ++ for (i = 0; i < CIPHER_THREADS; i++) ++ pthread_join(c->tid[i], NULL); ++ ++ memset(c, 0, sizeof(*c)); ++ free(c); ++ EVP_CIPHER_CTX_set_app_data(ctx, NULL); ++ } ++ return (1); ++} ++ ++/* */ ++const EVP_CIPHER * ++evp_aes_ctr_mt(void) ++{ ++ static EVP_CIPHER aes_ctr; ++ ++ memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); ++ aes_ctr.nid = NID_undef; ++ aes_ctr.block_size = AES_BLOCK_SIZE; ++ aes_ctr.iv_len = AES_BLOCK_SIZE; ++ aes_ctr.key_len = 16; ++ aes_ctr.init = ssh_aes_ctr_init; ++ aes_ctr.cleanup = ssh_aes_ctr_cleanup; ++ aes_ctr.do_cipher = ssh_aes_ctr; ++#ifndef SSH_OLD_EVP ++ aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++#endif ++ return (&aes_ctr); ++} +diff -NupwB openssh-5.2p1-canonical/clientloop.c openssh-5.2p1-hpn13v6/clientloop.c +--- openssh-5.2p1-canonical/clientloop.c 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/clientloop.c 2009-05-14 12:36:10.000000000 -0400 +@@ -1688,9 +1688,15 @@ client_request_x11(const char *request_t + sock = x11_connect_display(); + if (sock < 0) + return NULL; ++ /* again is this really necessary for X11? */ ++ if (options.hpn_disabled) + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); ++ else ++ c = channel_new("x11", ++ SSH_CHANNEL_X11_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + c->force_drain = 1; + return c; + } +@@ -1710,9 +1716,15 @@ client_request_agent(const char *request + sock = ssh_get_authentication_socket(); + if (sock < 0) + return NULL; ++ if (options.hpn_disabled) + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, +- CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, ++ CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, ++ "authentication agent connection", 1); ++ else ++ c = channel_new("authentication agent connection", ++ SSH_CHANNEL_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, options.hpn_buffer_size, 0, + "authentication agent connection", 1); + c->force_drain = 1; + return c; +@@ -1740,10 +1752,18 @@ client_request_tun_fwd(int tun_mode, int + return -1; + } + ++ if(options.hpn_disabled) ++ c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, ++ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, ++ 0, "tun", 1); ++ else + c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, +- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, ++ 0, "tun", 1); + c->datagram = 1; + ++ ++ + #if defined(SSH_TUN_FILTER) + if (options.tun_open == SSH_TUNMODE_POINTOPOINT) + channel_register_filter(c->self, sys_tun_infilter, +diff -NupwB openssh-5.2p1-canonical/compat.c openssh-5.2p1-hpn13v6/compat.c +--- openssh-5.2p1-canonical/compat.c 2008-11-03 03:20:14.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/compat.c 2009-05-14 12:36:10.000000000 -0400 +@@ -170,6 +170,15 @@ compat_datafellows(const char *version) + strlen(check[i].pat), 0) == 1) { + debug("match: %s pat %s", version, check[i].pat); + datafellows = check[i].bugs; ++ /* Check to see if the remote side is OpenSSH and not HPN */ ++ if(strstr(version,"OpenSSH") != NULL) ++ { ++ if (strstr(version,"hpn") == NULL) ++ { ++ datafellows |= SSH_BUG_LARGEWINDOW; ++ debug("Remote is NON-HPN aware"); ++ } ++ } + return; + } + } +diff -NupwB openssh-5.2p1-canonical/compat.h openssh-5.2p1-hpn13v6/compat.h +--- openssh-5.2p1-canonical/compat.h 2008-11-03 03:20:14.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/compat.h 2009-05-14 12:36:10.000000000 -0400 +@@ -58,6 +58,7 @@ + #define SSH_OLD_FORWARD_ADDR 0x01000000 + #define SSH_BUG_RFWD_ADDR 0x02000000 + #define SSH_NEW_OPENSSH 0x04000000 ++#define SSH_BUG_LARGEWINDOW 0x08000000 + + void enable_compat13(void); + void enable_compat20(void); +Common subdirectories: openssh-5.2p1-canonical/contrib and openssh-5.2p1-hpn13v6/contrib +diff -NupwB openssh-5.2p1-canonical/HPN-README openssh-5.2p1-hpn13v6/HPN-README +--- openssh-5.2p1-canonical/HPN-README 1969-12-31 19:00:00.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/HPN-README 2009-05-14 12:36:10.000000000 -0400 +@@ -0,0 +1,128 @@ ++Notes: ++ ++MULTI-THREADED CIPHER: ++The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations ++on hosts with multiple cores to use more than one processing core during encryption. ++Tests have show significant throughput performance increases when using MTR-AES-CTR up ++to and including a full gigabit per second on quad core systems. It should be possible to ++achieve full line rate on dual core systems but OS and data management overhead makes this ++more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single ++thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal ++performance requires the MTR-AES-CTR mode be enabled on both ends of the connection. ++The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same ++nomenclature. ++Use examples: ssh -caes128-ctr you@host.com ++ scp -oCipher=aes256-ctr file you@host.com:~/file ++ ++NONE CIPHER: ++To use the NONE option you must have the NoneEnabled switch set on the server and ++you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE ++feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not ++spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will ++be disabled. ++ ++The performance increase will only be as good as the network and TCP stack tuning ++on the reciever side of the connection allows. As a rule of thumb a user will need ++at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The ++HPN-SSH home page describes this in greater detail. ++ ++http://www.psc.edu/networking/projects/hpn-ssh ++ ++BUFFER SIZES: ++ ++If HPN is disabled the receive buffer size will be set to the ++OpenSSH default of 64K. ++ ++If an HPN system connects to a nonHPN system the receive buffer will ++be set to the HPNBufferSize value. The default is 2MB but user adjustable. ++ ++If an HPN to HPN connection is established a number of different things might ++happen based on the user options and conditions. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = up to 64MB ++This is the default state. The HPN buffer size will grow to a maximum of 64MB ++as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is ++geared towards 10GigE transcontinental connections. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = TCP receive buffer value. ++Users on non-autotuning systesm should disable TCPRcvBufPoll in the ++ssh_cofig and sshd_config ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set ++HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. ++This would be the system defined TCP receive buffer (RWIN). ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET ++HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set ++HPN Buffer Size = grows to HPNBufferSize ++The buffer will grow up to the maximum size specified here. ++ ++Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. ++Generally there is no need to set both of these, especially on autotuning ++systems. However, if the users wishes to override the autotuning this would be ++one way to do it. ++ ++Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET ++HPN Buffer Size = TCPRcvBuf. ++This will override autotuning and set the TCP recieve buffer to the user defined ++value. ++ ++ ++HPN Specific Configuration options ++ ++TcpRcvBuf=[int]KB client ++ set the TCP socket receive buffer to n Kilobytes. It can be set up to the ++maximum socket size allowed by the system. This is useful in situations where ++the tcp receive window is set low but the maximum buffer size is set ++higher (as is typical). This works on a per TCP connection basis. You can also ++use this to artifically limit the transfer rate of the connection. In these ++cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. ++Default is the current system wide tcp receive buffer size. ++ ++TcpRcvBufPoll=[yes/no] client/server ++ enable of disable the polling of the tcp receive buffer through the life ++of the connection. You would want to make sure that this option is enabled ++for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) ++default is yes. ++ ++NoneEnabled=[yes/no] client/server ++ enable or disable the use of the None cipher. Care must always be used ++when enabling this as it will allow users to send data in the clear. However, ++it is important to note that authentication information remains encrypted ++even if this option is enabled. Set to no by default. ++ ++NoneSwitch=[yes/no] client ++ Switch the encryption cipher being used to the None cipher after ++authentication takes place. NoneEnabled must be enabled on both the client ++and server side of the connection. When the connection switches to the NONE ++cipher a warning is sent to STDERR. The connection attempt will fail with an ++error if a client requests a NoneSwitch from the server that does not explicitly ++have NoneEnabled set to yes. Note: The NONE cipher cannot be used in ++interactive (shell) sessions and it will fail silently. Set to no by default. ++ ++HPNDisabled=[yes/no] client/server ++ In some situations, such as transfers on a local area network, the impact ++of the HPN code produces a net decrease in performance. In these cases it is ++helpful to disable the HPN functionality. By default HPNDisabled is set to no. ++ ++HPNBufferSize=[int]KB client/server ++ This is the default buffer size the HPN functionality uses when interacting ++with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf ++option as applied to the internal SSH flow control. This value can range from ++1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance ++problems depending on the length of the network path. The default size of this buffer ++is 2MB. ++ ++ ++Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu) ++ The majority of the actual coding for versions up to HPN12v1 was performed ++ by Michael Stevens (mstevens@andrew.cmu.edu). The MT-AES-CTR cipher was ++ implemented by Ben Bennet (ben@psc.edu). This work was financed, in part, ++ by Cisco System, Inc., the National Library of Medicine, ++ and the National Science Foundation. +diff -NupwB openssh-5.2p1-canonical/kex.c openssh-5.2p1-hpn13v6/kex.c +--- openssh-5.2p1-canonical/kex.c 2008-11-03 03:19:12.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/kex.c 2009-05-14 12:36:10.000000000 -0400 +@@ -48,6 +48,7 @@ + #include "match.h" + #include "dispatch.h" + #include "monitor.h" ++#include "canohost.h" + + #define KEX_COOKIE_LEN 16 + +@@ -64,7 +65,8 @@ static void kex_kexinit_finish(Kex *); + static void kex_choose_conf(Kex *); + + /* put algorithm proposal into buffer */ +-static void ++/* used in sshconnect.c as well as kex.c */ ++void + kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) + { + u_int i; +@@ -376,6 +378,13 @@ kex_choose_conf(Kex *kex) + int nenc, nmac, ncomp; + u_int mode, ctos, need; + int first_kex_follows, type; ++ int log_flag = 0; ++ ++ int auth_flag; ++ ++ auth_flag = packet_authentication_state(); ++ ++ debug ("AUTH STATE IS %d", auth_flag); + + my = kex_buf2prop(&kex->my, NULL); + peer = kex_buf2prop(&kex->peer, &first_kex_follows); +@@ -400,11 +409,34 @@ kex_choose_conf(Kex *kex) + choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); + choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); + choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); ++ debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); ++ if (strcmp(newkeys->enc.name, "none") == 0) { ++ debug("Requesting NONE. Authflag is %d", auth_flag); ++ if (auth_flag == 1) { ++ debug("None requested post authentication."); ++ } else { ++ fatal("Pre-authentication none cipher requests are not allowed."); ++ } ++ } + debug("kex: %s %s %s %s", + ctos ? "client->server" : "server->client", + newkeys->enc.name, + newkeys->mac.name, + newkeys->comp.name); ++ /* client starts withctos = 0 && log flag = 0 and no log*/ ++ /* 2nd client pass ctos=1 and flag = 1 so no log*/ ++ /* server starts with ctos =1 && log_flag = 0 so log */ ++ /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ ++ /* -cjr*/ ++ if (ctos && !log_flag) { ++ logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", ++ get_remote_ipaddr(), ++ get_remote_port(), ++ newkeys->enc.name, ++ newkeys->mac.name, ++ newkeys->comp.name); ++ } ++ log_flag = 1; + } + choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); + choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], +diff -NupwB openssh-5.2p1-canonical/kex.h openssh-5.2p1-hpn13v6/kex.h +--- openssh-5.2p1-canonical/kex.h 2007-06-11 00:01:42.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/kex.h 2009-05-14 12:36:10.000000000 -0400 +@@ -127,6 +127,8 @@ struct Kex { + void (*kex[KEX_MAX])(Kex *); + }; + ++void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]); ++ + Kex *kex_setup(char *[PROPOSAL_MAX]); + void kex_finish(Kex *); + +diff -NupwB openssh-5.2p1-canonical/Makefile.in openssh-5.2p1-hpn13v6/Makefile.in +--- openssh-5.2p1-canonical/Makefile.in 2008-11-05 00:20:46.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/Makefile.in 2009-05-14 12:36:10.000000000 -0400 +@@ -43,7 +43,7 @@ CC=@CC@ + LD=@LD@ + CFLAGS=@CFLAGS@ + CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +-LIBS=@LIBS@ ++LIBS=@LIBS@ -lpthread + SSHDLIBS=@SSHDLIBS@ + LIBEDIT=@LIBEDIT@ + AR=@AR@ +@@ -64,7 +64,7 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-a + + LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ +- cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ ++ cipher-bf1.o cipher-ctr.o cipher-ctr-mt.o cipher-3des1.o cleanup.o \ + compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ + log.o match.o md-sha256.o moduli.o nchan.o packet.o \ + readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ +diff -NupwB openssh-5.2p1-canonical/myproposal.h openssh-5.2p1-hpn13v6/myproposal.h +--- openssh-5.2p1-canonical/myproposal.h 2009-01-28 00:33:31.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/myproposal.h 2009-05-14 12:36:10.000000000 -0400 +@@ -47,6 +47,8 @@ + "arcfour256,arcfour128," \ + "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ + "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" ++#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \ ++ ",none" + #define KEX_DEFAULT_MAC \ + "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \ + "hmac-ripemd160@openssh.com," \ +Common subdirectories: openssh-5.2p1-canonical/openbsd-compat and openssh-5.2p1-hpn13v6/openbsd-compat +diff -NupwB openssh-5.2p1-canonical/packet.c openssh-5.2p1-hpn13v6/packet.c +--- openssh-5.2p1-canonical/packet.c 2009-02-14 00:35:01.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/packet.c 2009-05-14 12:36:10.000000000 -0400 +@@ -775,7 +775,7 @@ packet_enable_delayed_compress(void) + /* + * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) + */ +-static void ++static int + packet_send2_wrapped(void) + { + u_char type, *cp, *macbuf = NULL; +@@ -888,11 +888,13 @@ packet_send2_wrapped(void) + set_newkeys(MODE_OUT); + else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) + packet_enable_delayed_compress(); ++ return(packet_length); + } + +-static void ++static int + packet_send2(void) + { ++ static int packet_length = 0; + static int rekeying = 0; + struct packet *p; + u_char type, *cp; +@@ -910,7 +912,7 @@ packet_send2(void) + memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); + buffer_init(&outgoing_packet); + TAILQ_INSERT_TAIL(&outgoing, p, next); +- return; ++ return(sizeof(Buffer)); + } + } + +@@ -918,7 +920,7 @@ packet_send2(void) + if (type == SSH2_MSG_KEXINIT) + rekeying = 1; + +- packet_send2_wrapped(); ++ packet_length = packet_send2_wrapped(); + + /* after a NEWKEYS message we can send the complete queue */ + if (type == SSH2_MSG_NEWKEYS) { +@@ -931,19 +933,22 @@ packet_send2(void) + sizeof(Buffer)); + TAILQ_REMOVE(&outgoing, p, next); + free(p); +- packet_send2_wrapped(); ++ packet_length += packet_send2_wrapped(); + } + } ++ return(packet_length); + } + +-void ++int + packet_send(void) + { ++ int packet_len = 0; + if (compat20) +- packet_send2(); ++ packet_len = packet_send2(); + else + packet_send1(); + DBG(debug("packet_send done")); ++ return(packet_len); + } + + /* +@@ -1544,23 +1549,25 @@ packet_disconnect(const char *fmt,...) + + /* Checks if there is any buffered output, and tries to write some of the output. */ + +-void ++int + packet_write_poll(void) + { +- int len = buffer_len(&output); ++ int len = 0; ++ len = buffer_len(&output); + + if (len > 0) { + len = write(connection_out, buffer_ptr(&output), len); + if (len == -1) { + if (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK) +- return; ++ return (0); + fatal("Write failed: %.100s", strerror(errno)); + } + if (len == 0) + fatal("Write connection closed"); + buffer_consume(&output, len); + } ++ return(len); + } + + +@@ -1569,16 +1576,17 @@ packet_write_poll(void) + * written. + */ + +-void ++int + packet_write_wait(void) + { + fd_set *setp; + int ret, ms_remain; + struct timeval start, timeout, *timeoutp = NULL; ++ u_int bytes_sent = 0; + + setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), + sizeof(fd_mask)); +- packet_write_poll(); ++ bytes_sent += packet_write_poll(); + while (packet_have_data_to_write()) { + memset(setp, 0, howmany(connection_out + 1, NFDBITS) * + sizeof(fd_mask)); +@@ -1612,7 +1620,7 @@ packet_write_wait(void) + "waiting to write", get_remote_ipaddr()); + cleanup_exit(255); + } +- packet_write_poll(); ++ bytes_sent += packet_write_poll(); + } + free(setp); + } +@@ -1736,12 +1744,24 @@ packet_send_ignore(int nbytes) + } + } + ++int rekey_requested = 0; ++void ++packet_request_rekeying(void) ++{ ++ rekey_requested = 1; ++} ++ + #define MAX_PACKETS (1U<<31) + int + packet_need_rekeying(void) + { + if (datafellows & SSH_BUG_NOREKEY) + return 0; ++ if (rekey_requested == 1) ++ { ++ rekey_requested = 0; ++ return 1; ++ } + return + (p_send.packets > MAX_PACKETS) || + (p_read.packets > MAX_PACKETS) || +@@ -1766,3 +1786,9 @@ packet_set_authenticated(void) + { + after_authentication = 1; + } ++ ++int ++packet_authentication_state(void) ++{ ++ return(after_authentication); ++} +diff -NupwB openssh-5.2p1-canonical/packet.h openssh-5.2p1-hpn13v6/packet.h +--- openssh-5.2p1-canonical/packet.h 2008-07-11 03:36:48.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/packet.h 2009-05-14 12:36:10.000000000 -0400 +@@ -20,6 +20,9 @@ + + #include + ++void ++packet_request_rekeying(void); ++ + void packet_set_connection(int, int); + void packet_set_timeout(int, int); + void packet_set_nonblocking(void); +@@ -35,6 +38,7 @@ void packet_set_interactive(int); + int packet_is_interactive(void); + void packet_set_server(void); + void packet_set_authenticated(void); ++int packet_authentication_state(void); + + void packet_start(u_char); + void packet_put_char(int ch); +@@ -44,7 +48,7 @@ void packet_put_bignum2(BIGNUM * val + void packet_put_string(const void *buf, u_int len); + void packet_put_cstring(const char *str); + void packet_put_raw(const void *buf, u_int len); +-void packet_send(void); ++int packet_send(void); + + int packet_read(void); + void packet_read_expect(int type); +@@ -73,8 +77,8 @@ void packet_set_state(int, u_int32_t, u + int packet_get_ssh1_cipher(void); + void packet_set_iv(int, u_char *); + +-void packet_write_poll(void); +-void packet_write_wait(void); ++int packet_write_poll(void); ++int packet_write_wait(void); + int packet_have_data_to_write(void); + int packet_not_very_much_data_to_write(void); + +diff -NupwB openssh-5.2p1-canonical/progressmeter.c openssh-5.2p1-hpn13v6/progressmeter.c +--- openssh-5.2p1-canonical/progressmeter.c 2006-08-04 22:39:40.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/progressmeter.c 2009-05-14 12:36:10.000000000 -0400 +@@ -68,6 +68,8 @@ static time_t last_update; /* last progr + static char *file; /* name of the file being transferred */ + static off_t end_pos; /* ending position of transfer */ + static off_t cur_pos; /* transfer position as of last refresh */ ++static off_t last_pos; ++static off_t max_delta_pos = 0; + static volatile off_t *counter; /* progress counter */ + static long stalled; /* how long we have been stalled */ + static int bytes_per_second; /* current speed in bytes per second */ +@@ -128,12 +130,17 @@ refresh_progress_meter(void) + int hours, minutes, seconds; + int i, len; + int file_len; ++ off_t delta_pos; + + transferred = *counter - cur_pos; + cur_pos = *counter; + now = time(NULL); + bytes_left = end_pos - cur_pos; + ++ delta_pos = cur_pos - last_pos; ++ if (delta_pos > max_delta_pos) ++ max_delta_pos = delta_pos; ++ + if (bytes_left > 0) + elapsed = now - last_update; + else { +@@ -158,7 +165,7 @@ refresh_progress_meter(void) + + /* filename */ + buf[0] = '\0'; +- file_len = win_size - 35; ++ file_len = win_size - 45; + if (file_len > 0) { + len = snprintf(buf, file_len + 1, "\r%s", file); + if (len < 0) +@@ -175,7 +182,8 @@ refresh_progress_meter(void) + percent = ((float)cur_pos / end_pos) * 100; + else + percent = 100; +- snprintf(buf + strlen(buf), win_size - strlen(buf), ++ ++ snprintf(buf + strlen(buf), win_size - strlen(buf-8), + " %3d%% ", percent); + + /* amount transferred */ +@@ -188,6 +196,15 @@ refresh_progress_meter(void) + (off_t)bytes_per_second); + strlcat(buf, "/s ", win_size); + ++ /* instantaneous rate */ ++ if (bytes_left > 0) ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ delta_pos); ++ else ++ format_rate(buf + strlen(buf), win_size - strlen(buf), ++ max_delta_pos); ++ strlcat(buf, "/s ", win_size); ++ + /* ETA */ + if (!transferred) + stalled += elapsed; +@@ -224,6 +241,7 @@ refresh_progress_meter(void) + + atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); + last_update = now; ++ last_pos = cur_pos; + } + + /*ARGSUSED*/ +diff -NupwB openssh-5.2p1-canonical/readconf.c openssh-5.2p1-hpn13v6/readconf.c +--- openssh-5.2p1-canonical/readconf.c 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/readconf.c 2009-05-14 12:36:10.000000000 -0400 +@@ -131,6 +131,8 @@ typedef enum { + oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, + oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oVisualHostKey, oZeroKnowledgePasswordAuthentication, ++ oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled, ++ oHPNBufferSize, + oDeprecated, oUnsupported + } OpCodes; + +@@ -234,6 +236,12 @@ static struct { + #else + { "zeroknowledgepasswordauthentication", oUnsupported }, + #endif ++ { "noneenabled", oNoneEnabled }, ++ { "tcprcvbufpoll", oTcpRcvBufPoll }, ++ { "tcprcvbuf", oTcpRcvBuf }, ++ { "noneswitch", oNoneSwitch }, ++ { "hpndisabled", oHPNDisabled }, ++ { "hpnbuffersize", oHPNBufferSize }, + + { NULL, oBadOption } + }; +@@ -465,6 +473,37 @@ parse_flag: + intptr = &options->check_host_ip; + goto parse_flag; + ++ case oNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ /* we check to see if the command comes from the */ ++ /* command line or not. If it does then enable it */ ++ /* otherwise fail. NONE should never be a default configuration */ ++ case oNoneSwitch: ++ if(strcmp(filename,"command-line")==0) ++ { ++ intptr = &options->none_switch; ++ goto parse_flag; ++ } else { ++ error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename); ++ error("Continuing..."); ++ debug("NoneSwitch directive found in %.200s.", filename); ++ return 0; ++ } ++ ++ case oHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case oHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ ++ case oTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ + case oVerifyHostKeyDNS: + intptr = &options->verify_host_key_dns; + goto parse_yesnoask; +@@ -643,6 +682,10 @@ parse_int: + intptr = &options->connection_attempts; + goto parse_int; + ++ case oTcpRcvBuf: ++ intptr = &options->tcp_rcv_buf; ++ goto parse_int; ++ + case oCipher: + intptr = &options->cipher; + arg = strdelim(&s); +@@ -1065,6 +1108,12 @@ initialize_options(Options * options) + options->permit_local_command = -1; + options->visual_host_key = -1; + options->zero_knowledge_password_authentication = -1; ++ options->none_switch = -1; ++ options->none_enabled = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->tcp_rcv_buf = -1; + } + + /* +@@ -1187,6 +1236,29 @@ fill_default_options(Options * options) + options->server_alive_interval = 0; + if (options->server_alive_count_max == -1) + options->server_alive_count_max = 3; ++ if (options->none_switch == -1) ++ options->none_switch = 0; ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ if (options->hpn_buffer_size > -1) ++ { ++ /* if a user tries to set the size to 0 set it to 1KB */ ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1024; ++ /*limit the buffer to 64MB*/ ++ if (options->hpn_buffer_size > 65536) ++ { ++ options->hpn_buffer_size = 65536*1024; ++ debug("User requested buffer larger than 64MB. Request reverted to 64MB"); ++ } ++ debug("hpn_buffer_size set to %d", options->hpn_buffer_size); ++ } ++ if (options->tcp_rcv_buf == 0) ++ options->tcp_rcv_buf = 1; ++ if (options->tcp_rcv_buf > -1) ++ options->tcp_rcv_buf *=1024; ++ if (options->tcp_rcv_buf_poll == -1) ++ options->tcp_rcv_buf_poll = 1; + if (options->control_master == -1) + options->control_master = 0; + if (options->hash_known_hosts == -1) +diff -NupwB openssh-5.2p1-canonical/readconf.c.orig openssh-5.2p1-hpn13v6/readconf.c.orig +--- openssh-5.2p1-canonical/readconf.c.orig 1969-12-31 19:00:00.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/readconf.c.orig 2009-02-14 00:28:21.000000000 -0500 +@@ -0,0 +1,1310 @@ ++/* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */ ++/* ++ * Author: Tatu Ylonen ++ * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland ++ * All rights reserved ++ * Functions for reading the configuration files. ++ * ++ * As far as I am concerned, the code I have written for this software ++ * can be used freely for any purpose. Any derived versions of this ++ * software must be clearly marked as such, and if the derived work is ++ * incompatible with the protocol description in the RFC file, it must be ++ * called by a name other than "ssh" or "Secure Shell". ++ */ ++ ++#include "includes.h" ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xmalloc.h" ++#include "ssh.h" ++#include "compat.h" ++#include "cipher.h" ++#include "pathnames.h" ++#include "log.h" ++#include "key.h" ++#include "readconf.h" ++#include "match.h" ++#include "misc.h" ++#include "buffer.h" ++#include "kex.h" ++#include "mac.h" ++ ++/* Format of the configuration file: ++ ++ # Configuration data is parsed as follows: ++ # 1. command line options ++ # 2. user-specific file ++ # 3. system-wide file ++ # Any configuration value is only changed the first time it is set. ++ # Thus, host-specific definitions should be at the beginning of the ++ # configuration file, and defaults at the end. ++ ++ # Host-specific declarations. These may override anything above. A single ++ # host may match multiple declarations; these are processed in the order ++ # that they are given in. ++ ++ Host *.ngs.fi ngs.fi ++ User foo ++ ++ Host fake.com ++ HostName another.host.name.real.org ++ User blaah ++ Port 34289 ++ ForwardX11 no ++ ForwardAgent no ++ ++ Host books.com ++ RemoteForward 9999 shadows.cs.hut.fi:9999 ++ Cipher 3des ++ ++ Host fascist.blob.com ++ Port 23123 ++ User tylonen ++ PasswordAuthentication no ++ ++ Host puukko.hut.fi ++ User t35124p ++ ProxyCommand ssh-proxy %h %p ++ ++ Host *.fr ++ PublicKeyAuthentication no ++ ++ Host *.su ++ Cipher none ++ PasswordAuthentication no ++ ++ Host vpn.fake.com ++ Tunnel yes ++ TunnelDevice 3 ++ ++ # Defaults for various options ++ Host * ++ ForwardAgent no ++ ForwardX11 no ++ PasswordAuthentication yes ++ RSAAuthentication yes ++ RhostsRSAAuthentication yes ++ StrictHostKeyChecking yes ++ TcpKeepAlive no ++ IdentityFile ~/.ssh/identity ++ Port 22 ++ EscapeChar ~ ++ ++*/ ++ ++/* Keyword tokens. */ ++ ++typedef enum { ++ oBadOption, ++ oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, ++ oExitOnForwardFailure, ++ oPasswordAuthentication, oRSAAuthentication, ++ oChallengeResponseAuthentication, oXAuthLocation, ++ oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, ++ oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, ++ oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, ++ oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, ++ oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, ++ oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, ++ oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, ++ oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, ++ oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, ++ oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, ++ oClearAllForwardings, oNoHostAuthenticationForLocalhost, ++ oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, ++ oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, ++ oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, ++ oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, ++ oVisualHostKey, oZeroKnowledgePasswordAuthentication, ++ oDeprecated, oUnsupported ++} OpCodes; ++ ++/* Textual representations of the tokens. */ ++ ++static struct { ++ const char *name; ++ OpCodes opcode; ++} keywords[] = { ++ { "forwardagent", oForwardAgent }, ++ { "forwardx11", oForwardX11 }, ++ { "forwardx11trusted", oForwardX11Trusted }, ++ { "exitonforwardfailure", oExitOnForwardFailure }, ++ { "xauthlocation", oXAuthLocation }, ++ { "gatewayports", oGatewayPorts }, ++ { "useprivilegedport", oUsePrivilegedPort }, ++ { "rhostsauthentication", oDeprecated }, ++ { "passwordauthentication", oPasswordAuthentication }, ++ { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, ++ { "kbdinteractivedevices", oKbdInteractiveDevices }, ++ { "rsaauthentication", oRSAAuthentication }, ++ { "pubkeyauthentication", oPubkeyAuthentication }, ++ { "dsaauthentication", oPubkeyAuthentication }, /* alias */ ++ { "rhostsrsaauthentication", oRhostsRSAAuthentication }, ++ { "hostbasedauthentication", oHostbasedAuthentication }, ++ { "challengeresponseauthentication", oChallengeResponseAuthentication }, ++ { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ ++ { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ ++ { "kerberosauthentication", oUnsupported }, ++ { "kerberostgtpassing", oUnsupported }, ++ { "afstokenpassing", oUnsupported }, ++#if defined(GSSAPI) ++ { "gssapiauthentication", oGssAuthentication }, ++ { "gssapidelegatecredentials", oGssDelegateCreds }, ++#else ++ { "gssapiauthentication", oUnsupported }, ++ { "gssapidelegatecredentials", oUnsupported }, ++#endif ++ { "fallbacktorsh", oDeprecated }, ++ { "usersh", oDeprecated }, ++ { "identityfile", oIdentityFile }, ++ { "identityfile2", oIdentityFile }, /* obsolete */ ++ { "identitiesonly", oIdentitiesOnly }, ++ { "hostname", oHostName }, ++ { "hostkeyalias", oHostKeyAlias }, ++ { "proxycommand", oProxyCommand }, ++ { "port", oPort }, ++ { "cipher", oCipher }, ++ { "ciphers", oCiphers }, ++ { "macs", oMacs }, ++ { "protocol", oProtocol }, ++ { "remoteforward", oRemoteForward }, ++ { "localforward", oLocalForward }, ++ { "user", oUser }, ++ { "host", oHost }, ++ { "escapechar", oEscapeChar }, ++ { "globalknownhostsfile", oGlobalKnownHostsFile }, ++ { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, /* obsolete */ ++ { "userknownhostsfile", oUserKnownHostsFile }, ++ { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */ ++ { "connectionattempts", oConnectionAttempts }, ++ { "batchmode", oBatchMode }, ++ { "checkhostip", oCheckHostIP }, ++ { "stricthostkeychecking", oStrictHostKeyChecking }, ++ { "compression", oCompression }, ++ { "compressionlevel", oCompressionLevel }, ++ { "tcpkeepalive", oTCPKeepAlive }, ++ { "keepalive", oTCPKeepAlive }, /* obsolete */ ++ { "numberofpasswordprompts", oNumberOfPasswordPrompts }, ++ { "loglevel", oLogLevel }, ++ { "dynamicforward", oDynamicForward }, ++ { "preferredauthentications", oPreferredAuthentications }, ++ { "hostkeyalgorithms", oHostKeyAlgorithms }, ++ { "bindaddress", oBindAddress }, ++#ifdef SMARTCARD ++ { "smartcarddevice", oSmartcardDevice }, ++#else ++ { "smartcarddevice", oUnsupported }, ++#endif ++ { "clearallforwardings", oClearAllForwardings }, ++ { "enablesshkeysign", oEnableSSHKeysign }, ++ { "verifyhostkeydns", oVerifyHostKeyDNS }, ++ { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, ++ { "rekeylimit", oRekeyLimit }, ++ { "connecttimeout", oConnectTimeout }, ++ { "addressfamily", oAddressFamily }, ++ { "serveraliveinterval", oServerAliveInterval }, ++ { "serveralivecountmax", oServerAliveCountMax }, ++ { "sendenv", oSendEnv }, ++ { "controlpath", oControlPath }, ++ { "controlmaster", oControlMaster }, ++ { "hashknownhosts", oHashKnownHosts }, ++ { "tunnel", oTunnel }, ++ { "tunneldevice", oTunnelDevice }, ++ { "localcommand", oLocalCommand }, ++ { "permitlocalcommand", oPermitLocalCommand }, ++ { "visualhostkey", oVisualHostKey }, ++#ifdef JPAKE ++ { "zeroknowledgepasswordauthentication", ++ oZeroKnowledgePasswordAuthentication }, ++#else ++ { "zeroknowledgepasswordauthentication", oUnsupported }, ++#endif ++ ++ { NULL, oBadOption } ++}; ++ ++/* ++ * Adds a local TCP/IP port forward to options. Never returns if there is an ++ * error. ++ */ ++ ++void ++add_local_forward(Options *options, const Forward *newfwd) ++{ ++ Forward *fwd; ++#ifndef NO_IPPORT_RESERVED_CONCEPT ++ extern uid_t original_real_uid; ++ if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) ++ fatal("Privileged ports can only be forwarded by root."); ++#endif ++ if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) ++ 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; ++ fwd->listen_port = newfwd->listen_port; ++ fwd->connect_host = newfwd->connect_host; ++ fwd->connect_port = newfwd->connect_port; ++} ++ ++/* ++ * Adds a remote TCP/IP port forward to options. Never returns if there is ++ * an error. ++ */ ++ ++void ++add_remote_forward(Options *options, const Forward *newfwd) ++{ ++ Forward *fwd; ++ if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) ++ fatal("Too many remote forwards (max %d).", ++ SSH_MAX_FORWARDS_PER_DIRECTION); ++ fwd = &options->remote_forwards[options->num_remote_forwards++]; ++ ++ fwd->listen_host = newfwd->listen_host; ++ fwd->listen_port = newfwd->listen_port; ++ fwd->connect_host = newfwd->connect_host; ++ fwd->connect_port = newfwd->connect_port; ++} ++ ++static void ++clear_forwardings(Options *options) ++{ ++ int i; ++ ++ for (i = 0; i < options->num_local_forwards; i++) { ++ if (options->local_forwards[i].listen_host != NULL) ++ free(options->local_forwards[i].listen_host); ++ free(options->local_forwards[i].connect_host); ++ } ++ options->num_local_forwards = 0; ++ for (i = 0; i < options->num_remote_forwards; i++) { ++ if (options->remote_forwards[i].listen_host != NULL) ++ free(options->remote_forwards[i].listen_host); ++ free(options->remote_forwards[i].connect_host); ++ } ++ options->num_remote_forwards = 0; ++ options->tun_open = SSH_TUNMODE_NO; ++} ++ ++/* ++ * Returns the number of the token pointed to by cp or oBadOption. ++ */ ++ ++static OpCodes ++parse_token(const char *cp, const char *filename, int linenum) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name; i++) ++ if (strcasecmp(cp, keywords[i].name) == 0) ++ return keywords[i].opcode; ++ ++ error("%s: line %d: Bad configuration option: %s", ++ filename, linenum, cp); ++ return oBadOption; ++} ++ ++/* ++ * Processes a single option line as used in the configuration files. This ++ * only sets those values that have not already been set. ++ */ ++#define WHITESPACE " \t\r\n" ++ ++int ++process_config_line(Options *options, const char *host, ++ char *line, const char *filename, int linenum, ++ int *activep) ++{ ++ char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; ++ int opcode, *intptr, value, value2, scale; ++ LogLevel *log_level_ptr; ++ long long orig, val64; ++ size_t len; ++ Forward fwd; ++ ++ /* Strip trailing whitespace */ ++ for (len = strlen(line) - 1; len > 0; len--) { ++ if (strchr(WHITESPACE, line[len]) == NULL) ++ break; ++ line[len] = '\0'; ++ } ++ ++ s = line; ++ /* Get the keyword. (Each line is supposed to begin with a keyword). */ ++ if ((keyword = strdelim(&s)) == NULL) ++ return 0; ++ /* Ignore leading whitespace. */ ++ if (*keyword == '\0') ++ keyword = strdelim(&s); ++ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') ++ return 0; ++ ++ opcode = parse_token(keyword, filename, linenum); ++ ++ switch (opcode) { ++ case oBadOption: ++ /* don't panic, but count bad options */ ++ return -1; ++ /* NOTREACHED */ ++ case oConnectTimeout: ++ intptr = &options->connection_timeout; ++parse_time: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing time value.", ++ filename, linenum); ++ if ((value = convtime(arg)) == -1) ++ fatal("%s line %d: invalid time value.", ++ filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oForwardAgent: ++ intptr = &options->forward_agent; ++parse_flag: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oForwardX11: ++ intptr = &options->forward_x11; ++ goto parse_flag; ++ ++ case oForwardX11Trusted: ++ intptr = &options->forward_x11_trusted; ++ goto parse_flag; ++ ++ case oGatewayPorts: ++ intptr = &options->gateway_ports; ++ goto parse_flag; ++ ++ case oExitOnForwardFailure: ++ intptr = &options->exit_on_forward_failure; ++ goto parse_flag; ++ ++ case oUsePrivilegedPort: ++ intptr = &options->use_privileged_port; ++ goto parse_flag; ++ ++ case oPasswordAuthentication: ++ 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; ++ ++ case oKbdInteractiveDevices: ++ charptr = &options->kbd_interactive_devices; ++ goto parse_string; ++ ++ case oPubkeyAuthentication: ++ intptr = &options->pubkey_authentication; ++ goto parse_flag; ++ ++ case oRSAAuthentication: ++ intptr = &options->rsa_authentication; ++ goto parse_flag; ++ ++ case oRhostsRSAAuthentication: ++ intptr = &options->rhosts_rsa_authentication; ++ goto parse_flag; ++ ++ case oHostbasedAuthentication: ++ intptr = &options->hostbased_authentication; ++ goto parse_flag; ++ ++ case oChallengeResponseAuthentication: ++ intptr = &options->challenge_response_authentication; ++ goto parse_flag; ++ ++ case oGssAuthentication: ++ intptr = &options->gss_authentication; ++ goto parse_flag; ++ ++ case oGssDelegateCreds: ++ intptr = &options->gss_deleg_creds; ++ goto parse_flag; ++ ++ case oBatchMode: ++ intptr = &options->batch_mode; ++ goto parse_flag; ++ ++ case oCheckHostIP: ++ intptr = &options->check_host_ip; ++ goto parse_flag; ++ ++ case oVerifyHostKeyDNS: ++ intptr = &options->verify_host_key_dns; ++ goto parse_yesnoask; ++ ++ case oStrictHostKeyChecking: ++ intptr = &options->strict_host_key_checking; ++parse_yesnoask: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no/ask argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = 1; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = 0; ++ else if (strcmp(arg, "ask") == 0) ++ value = 2; ++ else ++ fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oCompression: ++ intptr = &options->compression; ++ goto parse_flag; ++ ++ case oTCPKeepAlive: ++ intptr = &options->tcp_keep_alive; ++ goto parse_flag; ++ ++ case oNoHostAuthenticationForLocalhost: ++ intptr = &options->no_host_authentication_for_localhost; ++ goto parse_flag; ++ ++ case oNumberOfPasswordPrompts: ++ intptr = &options->number_of_password_prompts; ++ goto parse_int; ++ ++ case oCompressionLevel: ++ intptr = &options->compression_level; ++ goto parse_int; ++ ++ case oRekeyLimit: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ orig = val64 = strtoll(arg, &endofnumber, 10); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ switch (toupper(*endofnumber)) { ++ case '\0': ++ scale = 1; ++ break; ++ case 'K': ++ scale = 1<<10; ++ break; ++ case 'M': ++ scale = 1<<20; ++ break; ++ case 'G': ++ scale = 1<<30; ++ break; ++ default: ++ fatal("%.200s line %d: Invalid RekeyLimit suffix", ++ filename, linenum); ++ } ++ val64 *= scale; ++ /* detect integer wrap and too-large limits */ ++ if ((val64 / scale) != orig || val64 > UINT_MAX) ++ fatal("%.200s line %d: RekeyLimit too large", ++ filename, linenum); ++ if (val64 < 16) ++ fatal("%.200s line %d: RekeyLimit too small", ++ filename, linenum); ++ if (*activep && options->rekey_limit == -1) ++ options->rekey_limit = (u_int32_t)val64; ++ break; ++ ++ case oIdentityFile: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*activep) { ++ intptr = &options->num_identity_files; ++ if (*intptr >= SSH_MAX_IDENTITY_FILES) ++ fatal("%.200s line %d: Too many identity files specified (max %d).", ++ filename, linenum, SSH_MAX_IDENTITY_FILES); ++ charptr = &options->identity_files[*intptr]; ++ *charptr = xstrdup(arg); ++ *intptr = *intptr + 1; ++ } ++ break; ++ ++ case oXAuthLocation: ++ charptr=&options->xauth_location; ++ goto parse_string; ++ ++ case oUser: ++ charptr = &options->user; ++parse_string: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case oGlobalKnownHostsFile: ++ charptr = &options->system_hostfile; ++ goto parse_string; ++ ++ case oUserKnownHostsFile: ++ charptr = &options->user_hostfile; ++ goto parse_string; ++ ++ case oGlobalKnownHostsFile2: ++ charptr = &options->system_hostfile2; ++ goto parse_string; ++ ++ case oUserKnownHostsFile2: ++ charptr = &options->user_hostfile2; ++ goto parse_string; ++ ++ case oHostName: ++ charptr = &options->hostname; ++ goto parse_string; ++ ++ case oHostKeyAlias: ++ charptr = &options->host_key_alias; ++ goto parse_string; ++ ++ case oPreferredAuthentications: ++ charptr = &options->preferred_authentications; ++ goto parse_string; ++ ++ case oBindAddress: ++ charptr = &options->bind_address; ++ goto parse_string; ++ ++ case oSmartcardDevice: ++ charptr = &options->smartcard_device; ++ goto parse_string; ++ ++ case oProxyCommand: ++ charptr = &options->proxy_command; ++parse_command: ++ if (s == NULL) ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ len = strspn(s, WHITESPACE "="); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(s + len); ++ return 0; ++ ++ case oPort: ++ intptr = &options->port; ++parse_int: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ ++ /* Octal, decimal, or hex format? */ ++ value = strtol(arg, &endofnumber, 0); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oConnectionAttempts: ++ intptr = &options->connection_attempts; ++ goto parse_int; ++ ++ case oCipher: ++ intptr = &options->cipher; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = cipher_number(arg); ++ if (value == -1) ++ fatal("%.200s line %d: Bad cipher '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oCiphers: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (!ciphers_valid(arg)) ++ fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->ciphers == NULL) ++ options->ciphers = xstrdup(arg); ++ break; ++ ++ case oMacs: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (!mac_valid(arg)) ++ fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->macs == NULL) ++ options->macs = xstrdup(arg); ++ break; ++ ++ case oHostKeyAlgorithms: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (!key_names_valid2(arg)) ++ fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->hostkeyalgorithms == NULL) ++ options->hostkeyalgorithms = xstrdup(arg); ++ break; ++ ++ case oProtocol: ++ intptr = &options->protocol; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = proto_spec(arg); ++ if (value == SSH_PROTO_UNKNOWN) ++ fatal("%.200s line %d: Bad protocol spec '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *intptr == SSH_PROTO_UNKNOWN) ++ *intptr = value; ++ break; ++ ++ case oLogLevel: ++ log_level_ptr = &options->log_level; ++ arg = strdelim(&s); ++ value = log_level_number(arg); ++ if (value == SYSLOG_LEVEL_NOT_SET) ++ fatal("%.200s line %d: unsupported log level '%s'", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) ++ *log_level_ptr = (LogLevel) value; ++ break; ++ ++ case oLocalForward: ++ case oRemoteForward: ++ case oDynamicForward: ++ arg = strdelim(&s); ++ if (arg == NULL || *arg == '\0') ++ fatal("%.200s line %d: Missing port argument.", ++ filename, linenum); ++ ++ 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, ++ opcode == oDynamicForward ? 1 : 0, ++ opcode == oRemoteForward ? 1 : 0) == 0) ++ fatal("%.200s line %d: Bad forwarding specification.", ++ filename, linenum); ++ ++ if (*activep) { ++ if (opcode == oLocalForward || ++ opcode == oDynamicForward) ++ add_local_forward(options, &fwd); ++ else if (opcode == oRemoteForward) ++ add_remote_forward(options, &fwd); ++ } ++ break; ++ ++ case oClearAllForwardings: ++ intptr = &options->clear_forwardings; ++ goto parse_flag; ++ ++ case oHost: ++ *activep = 0; ++ while ((arg = strdelim(&s)) != NULL && *arg != '\0') ++ if (match_pattern(host, arg)) { ++ debug("Applying options for %.100s", arg); ++ *activep = 1; ++ break; ++ } ++ /* Avoid garbage check below, as strdelim is done. */ ++ return 0; ++ ++ case oEscapeChar: ++ intptr = &options->escape_char; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] == '^' && arg[2] == 0 && ++ (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) ++ value = (u_char) arg[1] & 31; ++ else if (strlen(arg) == 1) ++ value = (u_char) arg[0]; ++ else if (strcmp(arg, "none") == 0) ++ value = SSH_ESCAPECHAR_NONE; ++ else { ++ fatal("%.200s line %d: Bad escape character.", ++ filename, linenum); ++ /* NOTREACHED */ ++ value = 0; /* Avoid compiler warning. */ ++ } ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oAddressFamily: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing address family.", ++ filename, linenum); ++ intptr = &options->address_family; ++ if (strcasecmp(arg, "inet") == 0) ++ value = AF_INET; ++ else if (strcasecmp(arg, "inet6") == 0) ++ value = AF_INET6; ++ else if (strcasecmp(arg, "any") == 0) ++ value = AF_UNSPEC; ++ else ++ fatal("Unsupported AddressFamily \"%s\"", arg); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oEnableSSHKeysign: ++ intptr = &options->enable_ssh_keysign; ++ goto parse_flag; ++ ++ case oIdentitiesOnly: ++ intptr = &options->identities_only; ++ goto parse_flag; ++ ++ case oServerAliveInterval: ++ intptr = &options->server_alive_interval; ++ goto parse_time; ++ ++ case oServerAliveCountMax: ++ intptr = &options->server_alive_count_max; ++ goto parse_int; ++ ++ case oSendEnv: ++ while ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ if (strchr(arg, '=') != NULL) ++ fatal("%s line %d: Invalid environment name.", ++ filename, linenum); ++ if (!*activep) ++ continue; ++ if (options->num_send_env >= MAX_SEND_ENV) ++ fatal("%s line %d: too many send env.", ++ filename, linenum); ++ options->send_env[options->num_send_env++] = ++ xstrdup(arg); ++ } ++ break; ++ ++ case oControlPath: ++ charptr = &options->control_path; ++ goto parse_string; ++ ++ case oControlMaster: ++ intptr = &options->control_master; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing ControlMaster argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) ++ value = SSHCTL_MASTER_YES; ++ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) ++ value = SSHCTL_MASTER_NO; ++ else if (strcmp(arg, "auto") == 0) ++ value = SSHCTL_MASTER_AUTO; ++ else if (strcmp(arg, "ask") == 0) ++ value = SSHCTL_MASTER_ASK; ++ else if (strcmp(arg, "autoask") == 0) ++ value = SSHCTL_MASTER_AUTO_ASK; ++ else ++ fatal("%.200s line %d: Bad ControlMaster argument.", ++ filename, linenum); ++ if (*activep && *intptr == -1) ++ *intptr = value; ++ break; ++ ++ case oHashKnownHosts: ++ intptr = &options->hash_known_hosts; ++ goto parse_flag; ++ ++ case oTunnel: ++ intptr = &options->tun_open; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: Missing yes/point-to-point/" ++ "ethernet/no argument.", filename, linenum); ++ value = 0; /* silence compiler */ ++ if (strcasecmp(arg, "ethernet") == 0) ++ value = SSH_TUNMODE_ETHERNET; ++ else if (strcasecmp(arg, "point-to-point") == 0) ++ value = SSH_TUNMODE_POINTOPOINT; ++ else if (strcasecmp(arg, "yes") == 0) ++ value = SSH_TUNMODE_DEFAULT; ++ else if (strcasecmp(arg, "no") == 0) ++ value = SSH_TUNMODE_NO; ++ else ++ fatal("%s line %d: Bad yes/point-to-point/ethernet/" ++ "no argument: %s", filename, linenum, arg); ++ if (*activep) ++ *intptr = value; ++ break; ++ ++ case oTunnelDevice: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ value = a2tun(arg, &value2); ++ if (value == SSH_TUNID_ERR) ++ fatal("%.200s line %d: Bad tun device.", filename, linenum); ++ if (*activep) { ++ options->tun_local = value; ++ options->tun_remote = value2; ++ } ++ break; ++ ++ case oLocalCommand: ++ charptr = &options->local_command; ++ goto parse_command; ++ ++ case oPermitLocalCommand: ++ intptr = &options->permit_local_command; ++ goto parse_flag; ++ ++ case oVisualHostKey: ++ intptr = &options->visual_host_key; ++ goto parse_flag; ++ ++ case oDeprecated: ++ debug("%s line %d: Deprecated option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ case oUnsupported: ++ error("%s line %d: Unsupported option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ default: ++ fatal("process_config_line: Unimplemented opcode %d", opcode); ++ } ++ ++ /* Check that there is no garbage at end of line. */ ++ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ fatal("%.200s line %d: garbage at end of line; \"%.200s\".", ++ filename, linenum, arg); ++ } ++ return 0; ++} ++ ++ ++/* ++ * Reads the config file and modifies the options accordingly. Options ++ * should already be initialized before this call. This never returns if ++ * there is an error. If the file does not exist, this returns 0. ++ */ ++ ++int ++read_config_file(const char *filename, const char *host, Options *options, ++ int checkperm) ++{ ++ FILE *f; ++ char line[1024]; ++ int active, linenum; ++ int bad_options = 0; ++ ++ if ((f = fopen(filename, "r")) == NULL) ++ return 0; ++ ++ if (checkperm) { ++ struct stat sb; ++ ++ if (fstat(fileno(f), &sb) == -1) ++ fatal("fstat %s: %s", filename, strerror(errno)); ++ if (((sb.st_uid != 0 && sb.st_uid != getuid()) || ++ (sb.st_mode & 022) != 0)) ++ fatal("Bad owner or permissions on %s", filename); ++ } ++ ++ debug("Reading configuration data %.200s", filename); ++ ++ /* ++ * Mark that we are now processing the options. This flag is turned ++ * on/off by Host specifications. ++ */ ++ active = 1; ++ linenum = 0; ++ while (fgets(line, sizeof(line), f)) { ++ /* Update line number counter. */ ++ linenum++; ++ if (process_config_line(options, host, line, filename, linenum, &active) != 0) ++ bad_options++; ++ } ++ fclose(f); ++ if (bad_options > 0) ++ fatal("%s: terminating, %d bad configuration options", ++ filename, bad_options); ++ return 1; ++} ++ ++/* ++ * Initializes options to special values that indicate that they have not yet ++ * been set. Read_config_file will only set options with this value. Options ++ * are processed in the following order: command line, user config file, ++ * system config file. Last, fill_default_options is called. ++ */ ++ ++void ++initialize_options(Options * options) ++{ ++ memset(options, 'X', sizeof(*options)); ++ options->forward_agent = -1; ++ options->forward_x11 = -1; ++ options->forward_x11_trusted = -1; ++ options->exit_on_forward_failure = -1; ++ options->xauth_location = NULL; ++ options->gateway_ports = -1; ++ options->use_privileged_port = -1; ++ options->rsa_authentication = -1; ++ options->pubkey_authentication = -1; ++ options->challenge_response_authentication = -1; ++ options->gss_authentication = -1; ++ options->gss_deleg_creds = -1; ++ options->password_authentication = -1; ++ options->kbd_interactive_authentication = -1; ++ options->kbd_interactive_devices = NULL; ++ options->rhosts_rsa_authentication = -1; ++ options->hostbased_authentication = -1; ++ options->batch_mode = -1; ++ options->check_host_ip = -1; ++ options->strict_host_key_checking = -1; ++ options->compression = -1; ++ options->tcp_keep_alive = -1; ++ options->compression_level = -1; ++ options->port = -1; ++ options->address_family = -1; ++ options->connection_attempts = -1; ++ options->connection_timeout = -1; ++ options->number_of_password_prompts = -1; ++ options->cipher = -1; ++ options->ciphers = NULL; ++ options->macs = NULL; ++ options->hostkeyalgorithms = NULL; ++ options->protocol = SSH_PROTO_UNKNOWN; ++ options->num_identity_files = 0; ++ options->hostname = NULL; ++ options->host_key_alias = NULL; ++ options->proxy_command = NULL; ++ options->user = NULL; ++ options->escape_char = -1; ++ options->system_hostfile = NULL; ++ options->user_hostfile = NULL; ++ options->system_hostfile2 = NULL; ++ options->user_hostfile2 = NULL; ++ options->num_local_forwards = 0; ++ options->num_remote_forwards = 0; ++ options->clear_forwardings = -1; ++ options->log_level = SYSLOG_LEVEL_NOT_SET; ++ options->preferred_authentications = NULL; ++ options->bind_address = NULL; ++ options->smartcard_device = NULL; ++ options->enable_ssh_keysign = - 1; ++ options->no_host_authentication_for_localhost = - 1; ++ options->identities_only = - 1; ++ options->rekey_limit = - 1; ++ options->verify_host_key_dns = -1; ++ options->server_alive_interval = -1; ++ options->server_alive_count_max = -1; ++ options->num_send_env = 0; ++ options->control_path = NULL; ++ options->control_master = -1; ++ options->hash_known_hosts = -1; ++ options->tun_open = -1; ++ options->tun_local = -1; ++ options->tun_remote = -1; ++ options->local_command = NULL; ++ options->permit_local_command = -1; ++ options->visual_host_key = -1; ++ options->zero_knowledge_password_authentication = -1; ++} ++ ++/* ++ * Called after processing other sources of option data, this fills those ++ * options for which no value has been specified with their default values. ++ */ ++ ++void ++fill_default_options(Options * options) ++{ ++ int len; ++ ++ if (options->forward_agent == -1) ++ options->forward_agent = 0; ++ if (options->forward_x11 == -1) ++ options->forward_x11 = 0; ++ if (options->forward_x11_trusted == -1) ++ options->forward_x11_trusted = 0; ++ if (options->exit_on_forward_failure == -1) ++ options->exit_on_forward_failure = 0; ++ if (options->xauth_location == NULL) ++ options->xauth_location = _PATH_XAUTH; ++ if (options->gateway_ports == -1) ++ options->gateway_ports = 0; ++ if (options->use_privileged_port == -1) ++ options->use_privileged_port = 0; ++ if (options->rsa_authentication == -1) ++ options->rsa_authentication = 1; ++ if (options->pubkey_authentication == -1) ++ options->pubkey_authentication = 1; ++ if (options->challenge_response_authentication == -1) ++ options->challenge_response_authentication = 1; ++ if (options->gss_authentication == -1) ++ options->gss_authentication = 0; ++ if (options->gss_deleg_creds == -1) ++ options->gss_deleg_creds = 0; ++ if (options->password_authentication == -1) ++ options->password_authentication = 1; ++ if (options->kbd_interactive_authentication == -1) ++ options->kbd_interactive_authentication = 1; ++ if (options->rhosts_rsa_authentication == -1) ++ options->rhosts_rsa_authentication = 0; ++ if (options->hostbased_authentication == -1) ++ options->hostbased_authentication = 0; ++ if (options->batch_mode == -1) ++ options->batch_mode = 0; ++ if (options->check_host_ip == -1) ++ options->check_host_ip = 1; ++ if (options->strict_host_key_checking == -1) ++ options->strict_host_key_checking = 2; /* 2 is default */ ++ if (options->compression == -1) ++ options->compression = 0; ++ if (options->tcp_keep_alive == -1) ++ options->tcp_keep_alive = 1; ++ if (options->compression_level == -1) ++ options->compression_level = 6; ++ if (options->port == -1) ++ options->port = 0; /* Filled in ssh_connect. */ ++ if (options->address_family == -1) ++ options->address_family = AF_UNSPEC; ++ if (options->connection_attempts == -1) ++ options->connection_attempts = 1; ++ if (options->number_of_password_prompts == -1) ++ options->number_of_password_prompts = 3; ++ /* Selected in ssh_login(). */ ++ if (options->cipher == -1) ++ options->cipher = SSH_CIPHER_NOT_SET; ++ /* options->ciphers, default set in myproposals.h */ ++ /* options->macs, default set in myproposals.h */ ++ /* options->hostkeyalgorithms, default set in myproposals.h */ ++ if (options->protocol == SSH_PROTO_UNKNOWN) ++ options->protocol = SSH_PROTO_1|SSH_PROTO_2; ++ if (options->num_identity_files == 0) { ++ if (options->protocol & SSH_PROTO_1) { ++ len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY); ++ } ++ if (options->protocol & SSH_PROTO_2) { ++ len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA); ++ ++ len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1; ++ options->identity_files[options->num_identity_files] = ++ xmalloc(len); ++ snprintf(options->identity_files[options->num_identity_files++], ++ len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); ++ } ++ } ++ if (options->escape_char == -1) ++ options->escape_char = '~'; ++ if (options->system_hostfile == NULL) ++ options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE; ++ if (options->user_hostfile == NULL) ++ options->user_hostfile = _PATH_SSH_USER_HOSTFILE; ++ if (options->system_hostfile2 == NULL) ++ options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; ++ if (options->user_hostfile2 == NULL) ++ options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; ++ if (options->log_level == SYSLOG_LEVEL_NOT_SET) ++ options->log_level = SYSLOG_LEVEL_INFO; ++ if (options->clear_forwardings == 1) ++ clear_forwardings(options); ++ if (options->no_host_authentication_for_localhost == - 1) ++ options->no_host_authentication_for_localhost = 0; ++ if (options->identities_only == -1) ++ options->identities_only = 0; ++ if (options->enable_ssh_keysign == -1) ++ options->enable_ssh_keysign = 0; ++ if (options->rekey_limit == -1) ++ options->rekey_limit = 0; ++ if (options->verify_host_key_dns == -1) ++ options->verify_host_key_dns = 0; ++ if (options->server_alive_interval == -1) ++ options->server_alive_interval = 0; ++ if (options->server_alive_count_max == -1) ++ options->server_alive_count_max = 3; ++ if (options->control_master == -1) ++ options->control_master = 0; ++ if (options->hash_known_hosts == -1) ++ options->hash_known_hosts = 0; ++ if (options->tun_open == -1) ++ options->tun_open = SSH_TUNMODE_NO; ++ if (options->tun_local == -1) ++ options->tun_local = SSH_TUNID_ANY; ++ if (options->tun_remote == -1) ++ options->tun_remote = SSH_TUNID_ANY; ++ if (options->permit_local_command == -1) ++ 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 */ ++ /* options->hostname will be set in the main program if appropriate */ ++ /* options->host_key_alias should not be set by default */ ++ /* options->preferred_authentications will be set in ssh */ ++} ++ ++/* ++ * 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, int dynamicfwd, int remotefwd) ++{ ++ int i; ++ char *p, *cp, *fwdarg[4]; ++ ++ memset(fwd, '\0', sizeof(*fwd)); ++ ++ cp = p = xstrdup(fwdspec); ++ ++ /* skip leading spaces */ ++ while (isspace(*cp)) ++ cp++; ++ ++ for (i = 0; i < 4; ++i) ++ if ((fwdarg[i] = hpdelim(&cp)) == NULL) ++ break; ++ ++ /* 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]); ++ fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); ++ fwd->connect_port = a2port(fwdarg[2]); ++ break; ++ ++ case 4: ++ fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); ++ fwd->listen_port = a2port(fwdarg[1]); ++ fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); ++ fwd->connect_port = a2port(fwdarg[3]); ++ break; ++ default: ++ i = 0; /* failure */ ++ } ++ ++ free(p); ++ ++ 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) { ++ free(fwd->connect_host); ++ fwd->connect_host = NULL; ++ } ++ if (fwd->listen_host != NULL) { ++ free(fwd->listen_host); ++ fwd->listen_host = NULL; ++ } ++ return (0); ++} +diff -NupwB openssh-5.2p1-canonical/readconf.h openssh-5.2p1-hpn13v6/readconf.h +--- openssh-5.2p1-canonical/readconf.h 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/readconf.h 2009-05-14 12:36:10.000000000 -0400 +@@ -57,6 +57,11 @@ typedef struct { + int compression_level; /* Compression level 1 (fast) to 9 + * (best). */ + int tcp_keep_alive; /* Set SO_KEEPALIVE. */ ++ int tcp_rcv_buf; /* user switch to set tcp recv buffer */ ++ int tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */ ++ int hpn_disabled; /* Switch to disable HPN buffer management */ ++ int hpn_buffer_size; /* User definable size for HPN buffer window */ ++ + LogLevel log_level; /* Level for logging. */ + + int port; /* Port to connect. */ +@@ -102,6 +107,8 @@ typedef struct { + + int enable_ssh_keysign; + int64_t rekey_limit; ++ int none_switch; /* Use none cipher */ ++ int none_enabled; /* Allow none to be used */ + int no_host_authentication_for_localhost; + int identities_only; + int server_alive_interval; +diff -NupwB openssh-5.2p1-canonical/readconf.h.orig openssh-5.2p1-hpn13v6/readconf.h.orig +--- openssh-5.2p1-canonical/readconf.h.orig 1969-12-31 19:00:00.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/readconf.h.orig 2009-02-14 00:28:21.000000000 -0500 +@@ -0,0 +1,145 @@ ++/* $OpenBSD: readconf.h,v 1.78 2009/02/12 03:00:56 djm Exp $ */ ++ ++/* ++ * Author: Tatu Ylonen ++ * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland ++ * All rights reserved ++ * Functions for reading the configuration file. ++ * ++ * As far as I am concerned, the code I have written for this software ++ * can be used freely for any purpose. Any derived versions of this ++ * software must be clearly marked as such, and if the derived work is ++ * incompatible with the protocol description in the RFC file, it must be ++ * called by a name other than "ssh" or "Secure Shell". ++ */ ++ ++#ifndef READCONF_H ++#define READCONF_H ++ ++/* Data structure for representing a forwarding request. */ ++ ++typedef struct { ++ char *listen_host; /* Host (address) to listen on. */ ++ int listen_port; /* Port to forward. */ ++ char *connect_host; /* Host to connect. */ ++ int connect_port; /* Port to connect on connect_host. */ ++} Forward; ++/* Data structure for representing option data. */ ++ ++#define MAX_SEND_ENV 256 ++ ++typedef struct { ++ int forward_agent; /* Forward authentication agent. */ ++ int forward_x11; /* Forward X11 display. */ ++ int forward_x11_trusted; /* Trust Forward X11 display. */ ++ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ ++ char *xauth_location; /* Location for xauth program */ ++ int gateway_ports; /* Allow remote connects to forwarded ports. */ ++ int use_privileged_port; /* Don't use privileged port if false. */ ++ int rhosts_rsa_authentication; /* Try rhosts with RSA ++ * authentication. */ ++ int rsa_authentication; /* Try RSA authentication. */ ++ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ ++ int hostbased_authentication; /* ssh2's rhosts_rsa */ ++ int challenge_response_authentication; ++ /* Try S/Key or TIS, authentication. */ ++ int gss_authentication; /* Try GSS authentication */ ++ int gss_deleg_creds; /* Delegate GSS credentials */ ++ int password_authentication; /* Try password ++ * 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. */ ++ int compression; /* Compress packets in both directions. */ ++ int compression_level; /* Compression level 1 (fast) to 9 ++ * (best). */ ++ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ ++ LogLevel log_level; /* Level for logging. */ ++ ++ int port; /* Port to connect. */ ++ int address_family; ++ int connection_attempts; /* Max attempts (seconds) before ++ * giving up */ ++ int connection_timeout; /* Max time (seconds) before ++ * aborting connection attempt */ ++ int number_of_password_prompts; /* Max number of password ++ * prompts. */ ++ int cipher; /* Cipher to use. */ ++ char *ciphers; /* SSH2 ciphers in order of preference. */ ++ char *macs; /* SSH2 macs in order of preference. */ ++ char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ ++ int protocol; /* Protocol in order of preference. */ ++ char *hostname; /* Real host to connect. */ ++ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ ++ char *proxy_command; /* Proxy command for connecting the host. */ ++ char *user; /* User to log in as. */ ++ int escape_char; /* Escape character; -2 = none */ ++ ++ char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ ++ char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ ++ char *system_hostfile2; ++ char *user_hostfile2; ++ char *preferred_authentications; ++ char *bind_address; /* local socket address for connection to sshd */ ++ char *smartcard_device; /* Smartcard reader device */ ++ int verify_host_key_dns; /* Verify host key using DNS */ ++ ++ int num_identity_files; /* Number of files for RSA/DSA identities. */ ++ char *identity_files[SSH_MAX_IDENTITY_FILES]; ++ Key *identity_keys[SSH_MAX_IDENTITY_FILES]; ++ ++ /* Local TCP/IP forward requests. */ ++ int num_local_forwards; ++ Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; ++ ++ /* Remote TCP/IP forward requests. */ ++ int num_remote_forwards; ++ Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; ++ int clear_forwardings; ++ ++ int enable_ssh_keysign; ++ int64_t rekey_limit; ++ int no_host_authentication_for_localhost; ++ int identities_only; ++ int server_alive_interval; ++ int server_alive_count_max; ++ ++ int num_send_env; ++ char *send_env[MAX_SEND_ENV]; ++ ++ char *control_path; ++ int control_master; ++ ++ int hash_known_hosts; ++ ++ int tun_open; /* tun(4) */ ++ int tun_local; /* force tun device (optional) */ ++ int tun_remote; /* force tun device (optional) */ ++ ++ char *local_command; ++ int permit_local_command; ++ int visual_host_key; ++ ++} Options; ++ ++#define SSHCTL_MASTER_NO 0 ++#define SSHCTL_MASTER_YES 1 ++#define SSHCTL_MASTER_AUTO 2 ++#define SSHCTL_MASTER_ASK 3 ++#define SSHCTL_MASTER_AUTO_ASK 4 ++ ++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, int); ++ ++int ++process_config_line(Options *, const char *, char *, const char *, int, int *); ++ ++void add_local_forward(Options *, const Forward *); ++void add_remote_forward(Options *, const Forward *); ++ ++#endif /* READCONF_H */ +Common subdirectories: openssh-5.2p1-canonical/regress and openssh-5.2p1-hpn13v6/regress +Common subdirectories: openssh-5.2p1-canonical/scard and openssh-5.2p1-hpn13v6/scard +diff -NupwB openssh-5.2p1-canonical/scp.c openssh-5.2p1-hpn13v6/scp.c +--- openssh-5.2p1-canonical/scp.c 2008-11-03 03:23:45.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/scp.c 2009-05-14 12:36:10.000000000 -0400 +@@ -632,7 +632,7 @@ source(int argc, char **argv) + off_t i, statbytes; + size_t amt; + int fd = -1, haderr, indx; +- char *last, *name, buf[2048], encname[MAXPATHLEN]; ++ char *last, *name, buf[16384], encname[MAXPATHLEN]; + int len; + + for (indx = 0; indx < argc; ++indx) { +@@ -868,7 +868,7 @@ sink(int argc, char **argv) + mode_t mode, omode, mask; + off_t size, statbytes; + int setimes, targisdir, wrerrno = 0; +- char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; ++ char ch, *cp, *np, *targ, *why, *vect[1], buf[16384]; + struct timeval tv[2]; + + #define atime tv[0] +diff -NupwB openssh-5.2p1-canonical/servconf.c openssh-5.2p1-hpn13v6/servconf.c +--- openssh-5.2p1-canonical/servconf.c 2009-01-28 00:31:23.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/servconf.c 2009-05-14 12:36:10.000000000 -0400 +@@ -132,6 +132,10 @@ + options->adm_forced_command = NULL; + options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; ++ options->none_enabled = -1; ++ options->tcp_rcv_buf_poll = -1; ++ options->hpn_disabled = -1; ++ options->hpn_buffer_size = -1; + #ifdef WITH_LDAP_PUBKEY + /* XXX dirty */ + options->lpk.ld = NULL; +@@ -156,6 +160,11 @@ + void + fill_default_server_options(ServerOptions *options) + { ++ /* needed for hpn socket tests */ ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); ++ + /* Portable-specific options */ + if (options->use_pam == -1) + options->use_pam = 0; +@@ -262,6 +271,42 @@ fill_default_server_options(ServerOption + if (options->zero_knowledge_password_authentication == -1) + options->zero_knowledge_password_authentication = 0; + ++ if (options->hpn_disabled == -1) ++ options->hpn_disabled = 0; ++ ++ if (options->hpn_buffer_size == -1) { ++ /* option not explicitly set. Now we have to figure out */ ++ /* what value to use */ ++ if (options->hpn_disabled == 1) { ++ options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ } else { ++ /* get the current RCV size and set it to that */ ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ options->hpn_buffer_size = socksize; ++ debug ("HPN Buffer Size: %d", options->hpn_buffer_size); ++ ++ } ++ } else { ++ /* we have to do this incase the user sets both values in a contradictory */ ++ /* manner. hpn_disabled overrrides hpn_buffer_size*/ ++ if (options->hpn_disabled <= 0) { ++ if (options->hpn_buffer_size == 0) ++ options->hpn_buffer_size = 1; ++ /* limit the maximum buffer to 64MB */ ++ if (options->hpn_buffer_size > 64*1024) { ++ options->hpn_buffer_size = 64*1024*1024; ++ } else { ++ options->hpn_buffer_size *= 1024; ++ } ++ } else ++ options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT; ++ } ++ + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = 1; +@@ -306,6 +351,7 @@ typedef enum { + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, ++ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -424,6 +470,10 @@ static struct { + { "permitopen", sPermitOpen, SSHCFG_ALL }, + { "forcecommand", sForceCommand, SSHCFG_ALL }, + { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, ++ { "noneenabled", sNoneEnabled }, ++ { "hpndisabled", sHPNDisabled }, ++ { "hpnbuffersize", sHPNBufferSize }, ++ { "tcprcvbufpoll", sTcpRcvBufPoll }, + { NULL, sBadOption, 0 } + }; + +@@ -450,6 +500,7 @@ parse_token(const char *cp, const char * + + for (i = 0; keywords[i].name; i++) + if (strcasecmp(cp, keywords[i].name) == 0) { ++ debug ("Config token is %s", keywords[i].name); + *flags = keywords[i].flags; + return keywords[i].opcode; + } +@@ -847,6 +898,22 @@ process_server_config_line(ServerOptions + *intptr = value; + break; + ++ case sNoneEnabled: ++ intptr = &options->none_enabled; ++ goto parse_flag; ++ ++ case sTcpRcvBufPoll: ++ intptr = &options->tcp_rcv_buf_poll; ++ goto parse_flag; ++ ++ case sHPNDisabled: ++ intptr = &options->hpn_disabled; ++ goto parse_flag; ++ ++ case sHPNBufferSize: ++ intptr = &options->hpn_buffer_size; ++ goto parse_int; ++ + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; +diff -NupwB openssh-5.2p1-canonical/servconf.h openssh-5.2p1-hpn13v6/servconf.h +--- openssh-5.2p1-canonical/servconf.h 2009-01-28 00:31:23.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/servconf.h 2009-05-14 12:36:10.000000000 -0400 +@@ -145,6 +145,10 @@ typedef struct { + char *adm_forced_command; + + int use_pam; /* Enable auth via PAM */ ++ int none_enabled; /* enable NONE cipher switch */ ++ int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ ++ int hpn_disabled; /* disable hpn functionality. false by default */ ++ int hpn_buffer_size; /* set the hpn buffer size - default 3MB */ + + int permit_tun; + +diff -NupwB openssh-5.2p1-canonical/serverloop.c openssh-5.2p1-hpn13v6/serverloop.c +--- openssh-5.2p1-canonical/serverloop.c 2009-02-14 00:33:09.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/serverloop.c 2009-05-14 12:36:10.000000000 -0400 +@@ -93,10 +93,10 @@ static int fdin; /* Descriptor for stdi + static int fdout; /* Descriptor for stdout (for reading); + May be same number as fdin. */ + static int fderr; /* Descriptor for stderr. May be -1. */ +-static long stdin_bytes = 0; /* Number of bytes written to stdin. */ +-static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ +-static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ +-static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ ++static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */ ++static u_long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ ++static u_long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ ++static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */ + static int stdin_eof = 0; /* EOF message received from client. */ + static int fdout_eof = 0; /* EOF encountered reading from fdout. */ + static int fderr_eof = 0; /* EOF encountered readung from fderr. */ +@@ -121,6 +121,20 @@ static volatile sig_atomic_t received_si + static void server_init_dispatch(void); + + /* ++ * Returns current time in seconds from Jan 1, 1970 with the maximum ++ * available resolution. ++ */ ++ ++static double ++get_current_time(void) ++{ ++ struct timeval tv; ++ gettimeofday(&tv, NULL); ++ return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; ++} ++ ++ ++/* + * we write to this pipe if a SIGCHLD is caught in order to avoid + * the race between select() and child_terminated + */ +@@ -410,6 +424,7 @@ process_input(fd_set *readset) + } else { + /* Buffer any received data. */ + packet_process_incoming(buf, len); ++ fdout_bytes += len; + } + } + if (compat20) +@@ -432,6 +447,7 @@ process_input(fd_set *readset) + } else { + buffer_append(&stdout_buffer, buf, len); + fdout_bytes += len; ++ debug ("FD out now: %ld", fdout_bytes); + } + } + /* Read and buffer any available stderr data from the program. */ +@@ -499,7 +515,7 @@ process_output(fd_set *writeset) + } + /* Send any buffered packet data to the client. */ + if (FD_ISSET(connection_out, writeset)) +- packet_write_poll(); ++ stdin_bytes += packet_write_poll(); + } + + /* +@@ -816,8 +832,10 @@ server_loop2(Authctxt *authctxt) + { + fd_set *readset = NULL, *writeset = NULL; + int rekeying = 0, max_fd, nalloc = 0; ++ double start_time, total_time; + + debug("Entering interactive session for SSH2."); ++ start_time = get_current_time(); + + mysignal(SIGCHLD, sigchld_handler); + child_terminated = 0; +@@ -879,6 +897,11 @@ server_loop2(Authctxt *authctxt) + + /* free remaining sessions, e.g. remove wtmp entries */ + session_destroy_all(NULL); ++ total_time = get_current_time() - start_time; ++ logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", ++ get_remote_ipaddr(), get_remote_port(), ++ stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, ++ fdout_bytes / total_time); + } + + static void +@@ -994,8 +1017,12 @@ server_request_tun(void) + sock = tun_open(tun, mode); + if (sock < 0) + goto done; ++ if (options.hpn_disabled) + c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); ++ else ++ c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, ++ options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + c->datagram = 1; + #if defined(SSH_TUN_FILTER) + if (mode == SSH_TUNMODE_POINTOPOINT) +@@ -1031,6 +1058,8 @@ server_request_session(void) + c = channel_new("session", SSH_CHANNEL_LARVAL, + -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, + 0, "server-session", 1); ++ if ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled)) ++ c->dynamic_window = 1; + if (session_open(the_authctxt, c->self) != 1) { + debug("session open failed, free channel %d", c->self); + channel_free(c); +diff -NupwB openssh-5.2p1-canonical/session.c openssh-5.2p1-hpn13v6/session.c +--- openssh-5.2p1-canonical/session.c 2009-01-28 00:29:49.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/session.c 2009-05-14 12:36:10.000000000 -0400 +@@ -230,6 +230,7 @@ auth_input_request_forwarding(struct pas + } + + /* Allocate a channel for the authentication agent socket. */ ++ /* this shouldn't matter if its hpn or not - cjr */ + nc = channel_new("auth socket", + SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, +@@ -2301,10 +2302,16 @@ session_set_fds(Session *s, int fdin, in + */ + if (s->chanid == -1) + fatal("no channel for session %d", s->self); ++ if (options.hpn_disabled) + channel_set_fds(s->chanid, + fdout, fdin, fderr, + fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, + 1, is_tty, CHAN_SES_WINDOW_DEFAULT); ++ else ++ channel_set_fds(s->chanid, ++ fdout, fdin, fderr, ++ fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, ++ 1, is_tty, options.hpn_buffer_size); + } + + /* +diff -NupwB openssh-5.2p1-canonical/sftp.1 openssh-5.2p1-hpn13v6/sftp.1 +--- openssh-5.2p1-canonical/sftp.1 2009-01-28 00:14:09.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/sftp.1 2009-05-14 12:36:10.000000000 -0400 +@@ -203,7 +203,8 @@ This option may be useful in debugging t + Specify how many requests may be outstanding at any one time. + Increasing this may slightly improve file transfer speed + but will increase memory usage. +-The default is 64 outstanding requests. ++The default is 256 outstanding requests providing for 8MB ++of outstanding data with a 32KB buffer. + .It Fl S Ar program + Name of the + .Ar program +diff -NupwB openssh-5.2p1-canonical/sftp.c openssh-5.2p1-hpn13v6/sftp.c +--- openssh-5.2p1-canonical/sftp.c 2009-02-14 00:26:19.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/sftp.c 2009-05-14 12:36:10.000000000 -0400 +@@ -75,7 +75,7 @@ int batchmode = 0; + size_t copy_buffer_len = 32768; + + /* Number of concurrent outstanding requests */ +-size_t num_requests = 64; ++size_t num_requests = 256; + + /* PID of ssh transport process */ + static pid_t sshpid = -1; +diff -NupwB openssh-5.2p1-canonical/ssh.c openssh-5.2p1-hpn13v6/ssh.c +--- openssh-5.2p1-canonical/ssh.c 2009-02-14 00:28:21.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/ssh.c 2009-05-14 12:36:10.000000000 -0400 +@@ -492,9 +492,6 @@ main(int ac, char **av) + no_shell_flag = 1; + no_tty_flag = 1; + break; +- case 'T': +- no_tty_flag = 1; +- break; + case 'o': + dummy = 1; + line = xstrdup(optarg); +@@ -503,6 +500,13 @@ main(int ac, char **av) + exit(255); + free(line); + break; ++ case 'T': ++ no_tty_flag = 1; ++ /* ensure that the user doesn't try to backdoor a */ ++ /* null cipher switch on an interactive session */ ++ /* so explicitly disable it no matter what */ ++ options.none_switch=0; ++ break; + case 's': + subsystem_flag = 1; + break; +@@ -1142,6 +1146,9 @@ ssh_session2_open(void) + { + Channel *c; + int window, packetmax, in, out, err; ++ int sock; ++ int socksize; ++ int socksizelen = sizeof(int); + + if (stdin_null_flag) { + in = open(_PATH_DEVNULL, O_RDONLY); +@@ -1162,9 +1169,75 @@ ssh_session2_open(void) + if (!isatty(err)) + set_nonblock(err); + +- window = CHAN_SES_WINDOW_DEFAULT; ++ /* we need to check to see if what they want to do about buffer */ ++ /* sizes here. In a hpn to nonhpn connection we want to limit */ ++ /* the window size to something reasonable in case the far side */ ++ /* has the large window bug. In hpn to hpn connection we want to */ ++ /* use the max window size but allow the user to override it */ ++ /* lastly if they disabled hpn then use the ssh std window size */ ++ ++ /* so why don't we just do a getsockopt() here and set the */ ++ /* ssh window to that? In the case of a autotuning receive */ ++ /* window the window would get stuck at the initial buffer */ ++ /* size generally less than 96k. Therefore we need to set the */ ++ /* maximum ssh window size to the maximum hpn buffer size */ ++ /* unless the user has specifically set the tcprcvbufpoll */ ++ /* to no. In which case we *can* just set the window to the */ ++ /* minimum of the hpn buffer size and tcp receive buffer size */ ++ ++ if (tty_flag) ++ options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; ++ else ++ options.hpn_buffer_size = 2*1024*1024; ++ ++ if (datafellows & SSH_BUG_LARGEWINDOW) ++ { ++ debug("HPN to Non-HPN Connection"); ++ } ++ else ++ { ++ if (options.tcp_rcv_buf_poll <= 0) ++ { ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); ++ } ++ else ++ { ++ if (options.tcp_rcv_buf > 0) ++ { ++ /*create a socket but don't connect it */ ++ /* we use that the get the rcv socket size */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ /* if they are using the tcp_rcv_buf option */ ++ /* attempt to set the buffer size to that */ ++ if (options.tcp_rcv_buf) ++ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, ++ sizeof(options.tcp_rcv_buf)); ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ close(sock); ++ debug("socksize %d", socksize); ++ options.hpn_buffer_size = socksize; ++ debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); ++ } ++ } ++ ++ } ++ ++ debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); ++ ++ window = options.hpn_buffer_size; ++ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++ + packetmax = CHAN_SES_PACKET_DEFAULT; + if (tty_flag) { ++ window = 4*CHAN_SES_PACKET_DEFAULT; + window >>= 1; + packetmax >>= 1; + } +@@ -1172,7 +1245,10 @@ ssh_session2_open(void) + "session", SSH_CHANNEL_OPENING, in, out, err, + window, packetmax, CHAN_EXTENDED_WRITE, + "client-session", /*nonblock*/0); +- ++ if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) { ++ c->dynamic_window = 1; ++ debug ("Enabled Dynamic Window Scaling\n"); ++ } + debug3("ssh_session2_open: channel_new: %d", c->self); + + channel_send_open(c->self); +diff -NupwB openssh-5.2p1-canonical/sshconnect2.c openssh-5.2p1-hpn13v6/sshconnect2.c +--- openssh-5.2p1-canonical/sshconnect2.c 2008-11-05 00:20:47.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/sshconnect2.c 2009-05-14 12:36:10.000000000 -0400 +@@ -78,6 +78,12 @@ + extern char *client_version_string; + extern char *server_version_string; + extern Options options; ++extern Kex *xxx_kex; ++ ++/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ ++/* if it is set then prevent the switch to the null cipher */ ++ ++extern int tty_flag; + + /* + * SSH2 key exchange +@@ -350,6 +356,28 @@ ssh_userauth2(const char *local_user, co + pubkey_cleanup(&authctxt); + dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); + ++ /* if the user wants to use the none cipher do it */ ++ /* post authentication and only if the right conditions are met */ ++ /* both of the NONE commands must be true and there must be no */ ++ /* tty allocated */ ++ if ((options.none_switch == 1) && (options.none_enabled == 1)) ++ { ++ if (!tty_flag) /* no null on tty sessions */ ++ { ++ debug("Requesting none rekeying..."); ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = "none"; ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none"; ++ kex_prop2buf(&xxx_kex->my,myproposal); ++ packet_request_rekeying(); ++ fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n"); ++ } ++ else ++ { ++ /* requested NONE cipher when in a tty */ ++ debug("Cannot switch to NONE cipher with tty allocated"); ++ fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n"); ++ } ++ } + debug("Authentication succeeded (%s).", authctxt.method->name); + } + +diff -NupwB openssh-5.2p1-canonical/sshconnect.c openssh-5.2p1-hpn13v6/sshconnect.c +--- openssh-5.2p1-canonical/sshconnect.c 2009-02-01 06:19:54.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/sshconnect.c 2009-05-14 12:36:10.000000000 -0400 +@@ -165,6 +165,31 @@ ssh_proxy_connect(const char *host, u_sh + } + + /* ++ * Set TCP receive buffer if requested. ++ * Note: tuning needs to happen after the socket is ++ * created but before the connection happens ++ * so winscale is negotiated properly -cjr ++ */ ++static void ++ssh_set_socket_recvbuf(int sock) ++{ ++ void *buf = (void *)&options.tcp_rcv_buf; ++ int sz = sizeof(options.tcp_rcv_buf); ++ int socksize; ++ int socksizelen = sizeof(int); ++ ++ debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); ++ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { ++ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); ++ debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); ++ } ++ else ++ error("Couldn't set socket receive buffer to %d: %.100s", ++ options.tcp_rcv_buf, strerror(errno)); ++} ++ ++ ++/* + * Creates a (possibly privileged) socket for use as the ssh connection. + */ + static int +@@ -187,12 +212,18 @@ ssh_create_socket(int privileged, struct + strerror(errno)); + else + debug("Allocated local port %d.", p); ++ ++ if (options.tcp_rcv_buf > 0) ++ ssh_set_socket_recvbuf(sock); + return sock; + } + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) + error("socket: %.100s", strerror(errno)); + ++ if (options.tcp_rcv_buf > 0) ++ ssh_set_socket_recvbuf(sock); ++ + /* Bind the socket to an alternative local IP address */ + if (options.bind_address == NULL) + return sock; +@@ -536,7 +567,7 @@ ssh_exchange_identification(int timeout_ + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", + compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, + compat20 ? PROTOCOL_MINOR_2 : minor1, +- SSH_VERSION, compat20 ? "\r\n" : "\n"); ++ SSH_RELEASE, compat20 ? "\r\n" : "\n"); + if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) + fatal("write: %.100s", strerror(errno)); + client_version_string = xstrdup(buf); +diff -NupwB openssh-5.2p1-canonical/sshd.c openssh-5.2p1-hpn13v6/sshd.c +--- openssh-5.2p1-canonical/sshd.c 2009-01-28 00:31:23.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/sshd.c 2009-05-14 12:36:10.000000000 -0400 +@@ -136,6 +136,9 @@ int deny_severity; + #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) + #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) + ++int myflag = 0; ++ ++ + extern char *__progname; + + /* Server configuration options. */ +@@ -415,7 +418,7 @@ sshd_exchange_identification(int sock_in + minor = PROTOCOL_MINOR_1; + } + snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor, +- SSH_VERSION, newline); ++ SSH_RELEASE, newline); + server_version_string = xstrdup(buf); + + /* Send our protocol version identification. */ +@@ -466,6 +469,9 @@ sshd_exchange_identification(int sock_in + } + debug("Client protocol version %d.%d; client software version %.100s", + remote_major, remote_minor, remote_version); ++ logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s", ++ get_remote_ipaddr(), get_remote_port(), ++ remote_major, remote_minor, remote_version); + + compat_datafellows(remote_version); + +@@ -944,6 +950,8 @@ server_listen(void) + int ret, listen_sock, on = 1; + struct addrinfo *ai; + char ntop[NI_MAXHOST], strport[NI_MAXSERV]; ++ int socksize; ++ int socksizelen = sizeof(int); + + for (ai = options.listen_addrs; ai; ai = ai->ai_next) { + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) +@@ -990,6 +998,11 @@ server_listen(void) + + debug("Bind to port %s on %s.", strport, ntop); + ++ getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, ++ &socksize, &socksizelen); ++ debug("Server TCP RWIN socket size: %d", socksize); ++ debug("HPN Buffer Size: %d", options.hpn_buffer_size); ++ + /* Bind the socket to the desired port. */ + if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { + error("Bind to port %s on %s failed: %.200s.", +@@ -1817,6 +1830,9 @@ main(int ac, char **av) + /* Log the connection. */ + verbose("Connection from %.500s port %d", remote_ip, remote_port); + ++ /* set the HPN options for the child */ ++ channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2171,9 +2187,15 @@ do_ssh2_kex(void) + { + Kex *kex; + ++ myflag++; ++ debug ("MYFLAG IS %d", myflag); + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (options.none_enabled == 1) { ++ debug ("WARNING: None cipher enabled"); ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +diff -NupwB openssh-5.2p1-canonical/sshd_config openssh-5.2p1-hpn13v6/sshd_config +--- openssh-5.2p1-canonical/sshd_config 2008-07-02 08:35:43.000000000 -0400 ++++ openssh-5.2p1-hpn13v6/sshd_config 2009-05-14 12:36:10.000000000 -0400 +@@ -112,6 +112,20 @@ Protocol 2 + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + ++# the following are HPN related configuration options ++# tcp receive buffer polling. disable in non autotuning kernels ++#TcpRcvBufPoll yes ++ ++# allow the use of the none cipher ++#NoneEnabled no ++ ++# disable hpn performance boosts. ++#HPNDisabled no ++ ++# buffer size for hpn to non-hpn connections ++#HPNBufferSize 2048 ++ ++ + # Example of overriding settings on a per-user basis + #Match User anoncvs + # X11Forwarding no +diff -NupwB openssh-5.2p1-canonical/version.h openssh-5.2p1-hpn13v6/version.h +--- openssh-5.2p1-canonical/version.h 2009-02-22 19:09:26.000000000 -0500 ++++ openssh-5.2p1-hpn13v6/version.h 2009-05-14 12:42:05.000000000 -0400 +@@ -3,4 +3,5 @@ + #define SSH_VERSION "OpenSSH_5.2" + + #define SSH_PORTABLE "p1" +-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE ++#define SSH_HPN "-hpn13v6" ++#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN diff --git a/openssh-5.8p1-authorized-keys-command.patch b/openssh-5.8p1-authorized-keys-command.patch new file mode 100644 index 0000000..022f822 --- /dev/null +++ b/openssh-5.8p1-authorized-keys-command.patch @@ -0,0 +1,447 @@ +diff -up openssh-5.8p1/auth2-pubkey.c.akc openssh-5.8p1/auth2-pubkey.c +--- openssh-5.8p1/auth2-pubkey.c.akc 2011-02-10 13:21:27.000000000 +0100 ++++ openssh-5.8p1/auth2-pubkey.c 2011-02-10 13:21:28.000000000 +0100 +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + #include + #include +@@ -268,27 +269,15 @@ match_principals_file(char *file, struct + + /* return 1 if user allows given key */ + static int +-user_key_allowed2(struct passwd *pw, Key *key, char *file) ++user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw) + { + char line[SSH_MAX_PUBKEY_BYTES]; + const char *reason; + int found_key = 0; +- FILE *f; + u_long linenum = 0; + Key *found; + char *fp; + +- /* Temporarily use the user's uid. */ +- temporarily_use_uid(pw); +- +- debug("trying public key file %s", file); +- f = auth_openkeyfile(file, pw, options.strict_modes); +- +- if (!f) { +- restore_uid(); +- return 0; +- } +- + found_key = 0; + found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); + +@@ -381,8 +370,6 @@ user_key_allowed2(struct passwd *pw, Key + break; + } + } +- restore_uid(); +- fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); +@@ -444,13 +431,191 @@ user_cert_trusted_ca(struct passwd *pw, + return ret; + } + +-/* check whether given key is in .ssh/authorized_keys* */ ++/* return 1 if user allows given key */ ++static int ++user_key_allowed2(struct passwd *pw, Key *key, char *file) ++{ ++ FILE *f; ++ int found_key = 0; ++ ++ /* Temporarily use the user's uid. */ ++ temporarily_use_uid(pw); ++ ++ debug("trying public key file %s", file); ++ f = auth_openkeyfile(file, pw, options.strict_modes); ++ ++ if (f) { ++ found_key = user_search_key_in_file (f, file, key, pw); ++ fclose(f); ++ } ++ ++ restore_uid(); ++ return found_key; ++} ++ ++#ifdef WITH_AUTHORIZED_KEYS_COMMAND ++ ++#define WHITESPACE " \t\r\n" ++ ++/* return 1 if user allows given key */ ++static int ++user_key_via_command_allowed2(struct passwd *pw, Key *key) ++{ ++ FILE *f; ++ int found_key = 0; ++ char *progname = NULL; ++ char *cp; ++ struct passwd *runas_pw; ++ struct stat st; ++ int childdescriptors[2], i; ++ pid_t pstat, pid, child; ++ ++ if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/') ++ return -1; ++ ++ /* get the run as identity from config */ ++ runas_pw = (options.authorized_keys_command_runas == NULL)? pw ++ : getpwnam (options.authorized_keys_command_runas); ++ if (!runas_pw) { ++ error("%s: getpwnam(\"%s\"): %s", __func__, ++ options.authorized_keys_command_runas, strerror(errno)); ++ return 0; ++ } ++ ++ /* Temporarily use the specified uid. */ ++ if (runas_pw->pw_uid != 0) ++ temporarily_use_uid(runas_pw); ++ ++ progname = xstrdup(options.authorized_keys_command); ++ ++ debug3("%s: checking program '%s'", __func__, progname); ++ ++ if (stat (progname, &st) < 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for AuthorizedKeysCommand \"%s\"", ++ progname); ++ goto go_away; ++ } ++ ++ if (!S_ISREG(st.st_mode)) { ++ error("AuthorizedKeysCommand \"%s\" is not a regular file", ++ progname); ++ goto go_away; ++ } ++ ++ /* ++ * Descend the path, checking that each component is a ++ * root-owned directory with strict permissions. ++ */ ++ do { ++ if ((cp = strrchr(progname, '/')) == NULL) ++ break; ++ else ++ *cp = '\0'; ++ ++ debug3("%s: checking component '%s'", __func__, (*progname == '\0' ? "/" : progname)); ++ ++ if (stat((*progname == '\0' ? "/" : progname), &st) != 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for AuthorizedKeysCommand path component \"%s\"", ++ progname); ++ goto go_away; ++ } ++ if (!S_ISDIR(st.st_mode)) { ++ error("AuthorizedKeysCommand path component \"%s\" is not a directory", ++ progname); ++ goto go_away; ++ } ++ } while (1); ++ ++ /* open the pipe and read the keys */ ++ if (pipe(childdescriptors)) { ++ error("failed to pipe(2) for AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ goto go_away; ++ } ++ ++ child = fork(); ++ if (child == -1) { ++ error("failed to fork(2) for AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ goto go_away; ++ } else if (child == 0) { ++ /* we're in the child process here -- we should never return from this block. */ ++ /* permanently drop privs in child process */ ++ if (runas_pw->pw_uid != 0) { ++ restore_uid(); ++ permanently_set_uid(runas_pw); ++ } ++ ++ close(childdescriptors[0]); ++ /* put the write end of the pipe on stdout (FD 1) */ ++ if (dup2(childdescriptors[1], 1) == -1) { ++ error("failed to dup2(2) from AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ _exit(127); ++ } ++ ++ debug3("about to execl() AuthorizedKeysCommand: \"%s\" \"%s\"", options.authorized_keys_command, pw->pw_name); ++ /* see session.c:child_close_fds() */ ++ for (i = 3; i < 64; ++i) { ++ close(i); ++ } ++ ++ execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL); ++ ++ /* if we got here, it didn't work */ ++ error("failed to execl AuthorizedKeysCommand: %s", strerror(errno)); /* this won't work because we closed the fds above */ ++ _exit(127); ++ } ++ ++ close(childdescriptors[1]); ++ f = fdopen(childdescriptors[0], "r"); ++ if (!f) { ++ error("%s: could not buffer FDs from AuthorizedKeysCommand (\"%s\", \"r\"): %s", __func__, ++ options.authorized_keys_command, strerror (errno)); ++ goto go_away; ++ } ++ ++ found_key = user_search_key_in_file (f, options.authorized_keys_command, key, pw); ++ fclose (f); ++ do { ++ pid = waitpid(child, &pstat, 0); ++ } while (pid == -1 && errno == EINTR); ++ ++ /* what about the return value from the child process? */ ++go_away: ++ if (progname) ++ free (progname); ++ ++ if (runas_pw->pw_uid != 0) ++ restore_uid(); ++ return found_key; ++} ++#endif ++ ++/* check whether given key is in 0) ++ return success; ++#endif ++ + if (auth_key_is_revoked(key)) + return 0; + if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) +diff -up openssh-5.8p1/configure.ac.akc openssh-5.8p1/configure.ac +--- openssh-5.8p1/configure.ac.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/configure.ac 2011-02-10 13:21:28.000000000 +0100 +@@ -1422,6 +1422,18 @@ AC_ARG_WITH(audit, + esac ] + ) + ++# Check whether user wants AuthorizedKeysCommand support ++AKC_MSG="no" ++AC_ARG_WITH(authorized-keys-command, ++ [ --with-authorized-keys-command Enable AuthorizedKeysCommand support], ++ [ ++ if test "x$withval" != "xno" ; then ++ AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support]) ++ AKC_MSG="yes" ++ fi ++ ] ++) ++ + dnl Checks for library functions. Please keep in alphabetical order + AC_CHECK_FUNCS( \ + arc4random \ +@@ -4325,6 +4337,7 @@ echo " SELinux support + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" ++echo " AuthorizedKeysCommand support: $AKC_MSG" + echo " MD5 password support: $MD5_MSG" + echo " libedit support: $LIBEDIT_MSG" + echo " Solaris process contract support: $SPC_MSG" +diff -up openssh-5.8p1/servconf.c.akc openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-10 13:28:21.000000000 +0100 +@@ -134,6 +134,8 @@ initialize_server_options(ServerOptions + options->num_permitted_opens = -1; + options->adm_forced_command = NULL; + options->chroot_directory = NULL; ++ options->authorized_keys_command = NULL; ++ options->authorized_keys_command_runas = NULL; + options->zero_knowledge_password_authentication = -1; + options->revoked_keys_file = NULL; + options->trusted_user_ca_keys = NULL; +@@ -331,6 +333,7 @@ typedef enum { + sZeroKnowledgePasswordAuthentication, sHostCertificate, + sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sKexAlgorithms, sIPQoS, ++ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -456,6 +459,13 @@ static struct { + { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, + { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, + { "ipqos", sIPQoS, SSHCFG_ALL }, ++#ifdef WITH_AUTHORIZED_KEYS_COMMAND ++ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, ++ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandRunAs, SSHCFG_ALL }, ++#else ++ { "authorizedkeyscommand", sUnsupported, SSHCFG_ALL }, ++ { "authorizedkeyscommandrunas", sUnsupported, SSHCFG_ALL }, ++#endif + { NULL, sBadOption, 0 } + }; + +@@ -1406,6 +1416,20 @@ process_server_config_line(ServerOptions + } + break; + ++ case sAuthorizedKeysCommand: ++ len = strspn(cp, WHITESPACE); ++ if (*activep && options->authorized_keys_command == NULL) ++ options->authorized_keys_command = xstrdup(cp + len); ++ return 0; ++ ++ case sAuthorizedKeysCommandRunAs: ++ charptr = &options->authorized_keys_command_runas; ++ ++ arg = strdelim(&cp); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); +@@ -1499,6 +1523,8 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(gss_authentication); + M_CP_INTOPT(rsa_authentication); + M_CP_INTOPT(pubkey_authentication); ++ M_CP_STROPT(authorized_keys_command); ++ M_CP_STROPT(authorized_keys_command_runas); + M_CP_INTOPT(kerberos_authentication); + M_CP_INTOPT(hostbased_authentication); + M_CP_INTOPT(hostbased_uses_name_from_packet_only); +@@ -1753,6 +1779,8 @@ dump_config(ServerOptions *o) + dump_cfg_string(sRevokedKeys, o->revoked_keys_file); + dump_cfg_string(sAuthorizedPrincipalsFile, + o->authorized_principals_file); ++ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); ++ dump_cfg_string(sAuthorizedKeysCommandRunAs, o->authorized_keys_command_runas); + + /* string arguments requiring a lookup */ + dump_cfg_string(sLogLevel, log_level_name(o->log_level)); +diff -up openssh-5.8p1/servconf.h.akc openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-10 13:21:28.000000000 +0100 +@@ -161,6 +161,8 @@ typedef struct { + char *revoked_keys_file; + char *trusted_user_ca_keys; + char *authorized_principals_file; ++ char *authorized_keys_command; ++ char *authorized_keys_command_runas; + } ServerOptions; + + void initialize_server_options(ServerOptions *); +diff -up openssh-5.8p1/sshd_config.0.akc openssh-5.8p1/sshd_config.0 +--- openssh-5.8p1/sshd_config.0.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config.0 2011-02-10 13:21:28.000000000 +0100 +@@ -71,6 +71,23 @@ DESCRIPTION + + See PATTERNS in ssh_config(5) for more information on patterns. + ++ AuthorizedKeysCommand ++ ++ Specifies a program to be used for lookup of the user's ++ public keys. The program will be invoked with its first ++ argument the name of the user being authorized, and should produce ++ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS ++ in sshd(8)). By default (or when set to the empty string) there is no ++ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully ++ authorize the user, authorization falls through to the ++ AuthorizedKeysFile. Note that this option has an effect ++ only with PubkeyAuthentication turned on. ++ ++ AuthorizedKeysCommandRunAs ++ Specifies the user under whose account the AuthorizedKeysCommand is run. ++ Empty string (the default value) means the user being authorized ++ is used. ++ + AuthorizedKeysFile + Specifies the file that contains the public keys that can be used + for user authentication. The format is described in the +@@ -398,7 +415,8 @@ DESCRIPTION + + Only a subset of keywords may be used on the lines following a + Match keyword. Available keywords are AllowAgentForwarding, +- AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile, ++ AllowTcpForwarding, AuthorizedKeysFile, AuthorizedKeysCommand, ++ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, + Banner, ChrootDirectory, ForceCommand, GatewayPorts, + GSSAPIAuthentication, HostbasedAuthentication, + HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication, +diff -up openssh-5.8p1/sshd_config.5.akc openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-10 13:21:28.000000000 +0100 +@@ -703,6 +703,8 @@ Available keywords are + .Cm AllowAgentForwarding , + .Cm AllowTcpForwarding , + .Cm AuthorizedKeysFile , ++.Cm AuthorizedKeysCommand , ++.Cm AuthorizedKeysCommandRunAs , + .Cm AuthorizedPrincipalsFile , + .Cm Banner , + .Cm ChrootDirectory , +@@ -715,6 +717,7 @@ Available keywords are + .Cm KerberosAuthentication , + .Cm MaxAuthTries , + .Cm MaxSessions , ++.Cm PubkeyAuthentication , + .Cm PasswordAuthentication , + .Cm PermitEmptyPasswords , + .Cm PermitOpen , +@@ -917,6 +920,20 @@ Specifies a list of revoked public keys. + Keys listed in this file will be refused for public key authentication. + Note that if this file is not readable, then public key authentication will + be refused for all users. ++.It Cm AuthorizedKeysCommand ++Specifies a program to be used for lookup of the user's ++public keys. The program will be invoked with its first ++argument the name of the user being authorized, and should produce ++on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS ++in sshd(8)). By default (or when set to the empty string) there is no ++AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully ++authorize the user, authorization falls through to the ++AuthorizedKeysFile. Note that this option has an effect ++only with PubkeyAuthentication turned on. ++.It Cm AuthorizedKeysCommandRunAs ++Specifies the user under whose account the AuthorizedKeysCommand is run. Empty ++string (the default value) means the user being authorized is used. ++.Dq + .It Cm RhostsRSAAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful RSA host authentication is allowed. +diff -up openssh-5.8p1/sshd_config.akc openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-10 13:21:28.000000000 +0100 +@@ -46,6 +46,8 @@ SyslogFacility AUTHPRIV + #RSAAuthentication yes + #PubkeyAuthentication yes + #AuthorizedKeysFile .ssh/authorized_keys ++#AuthorizedKeysCommand none ++#AuthorizedKeysCommandRunAs nobody + + # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts + #RhostsRSAAuthentication no diff --git a/openssh-bind.patch b/openssh-bind.patch new file mode 100644 index 0000000..718caa6 --- /dev/null +++ b/openssh-bind.patch @@ -0,0 +1,11 @@ +--- openssh-5.9p1/channels.c~ 2011-06-23 00:31:57.000000000 +0200 ++++ openssh-5.9p1/channels.c 2011-11-12 11:37:15.242015675 +0100 +@@ -3301,6 +3301,8 @@ + if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + debug2("bind port %d: %.100s", port, strerror(errno)); + close(sock); ++ if (errno == EADDRNOTAVAIL) ++ continue; + + for (n = 0; n < num_socks; n++) { + close(socks[n]); diff --git a/openssh-blacklist.diff b/openssh-blacklist.diff new file mode 100644 index 0000000..5de3dca --- /dev/null +++ b/openssh-blacklist.diff @@ -0,0 +1,984 @@ +This patch is against OpenSSH 4.7p1, although should apply to other versions +without too much difficulty. It makes the following changes: + + * Add key blacklisting support. Keys listed in + /etc/ssh/blacklist.TYPE-LENGTH will be rejected for authentication by + sshd, unless "PermitBlacklistedKeys yes" is set in /etc/ssh/sshd_config. + + * Add a new program, ssh-vulnkey, which can be used to check keys against + these blacklists. + +This patch is up to date with respect to Debian openssh 1:4.7p1-10. + +--- openssh-4.7p1.orig/sshd_config.5 ++++ openssh-4.7p1/sshd_config.5 +@@ -615,6 +615,20 @@ + Specifies whether password authentication is allowed. + The default is + .Dq yes . ++.It Cm PermitBlacklistedKeys ++Specifies whether ++.Xr sshd 8 ++should allow keys recorded in its blacklist of known-compromised keys (see ++.Xr ssh-vulnkey 1 ) . ++If ++.Dq yes , ++then attempts to authenticate with compromised keys will be logged but ++accepted. ++If ++.Dq no , ++then attempts to authenticate with compromised keys will be rejected. ++The default is ++.Dq no . + .It Cm PermitEmptyPasswords + When password authentication is allowed, it specifies whether the + server allows login to accounts with empty password strings. +--- openssh-4.7p1.orig/sshd.c ++++ openssh-4.7p1/sshd.c +@@ -1466,6 +1466,21 @@ + + for (i = 0; i < options.num_host_key_files; i++) { + key = key_load_private(options.host_key_files[i], "", NULL); ++ if (key && blacklisted_key(key)) { ++ char *fp; ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (options.permit_blacklisted_keys) ++ error("Host key %s blacklisted (see " ++ "ssh-vulnkey(1)); continuing anyway", fp); ++ else ++ error("Host key %s blacklisted (see " ++ "ssh-vulnkey(1))", fp); ++ free(fp); ++ if (!options.permit_blacklisted_keys) { ++ sensitive_data.host_keys[i] = NULL; ++ continue; ++ } ++ } + pubkey = key_load_public(options.host_key_files[i], NULL); + sensitive_data.host_keys[i] = key; + sensitive_data.host_pubkeys[i] = pubkey; +--- openssh-4.7p1.orig/servconf.c ++++ openssh-4.7p1/servconf.c +@@ -96,6 +96,7 @@ + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->challenge_response_authentication = -1; ++ options->permit_blacklisted_keys = -1; + options->permit_empty_passwd = -1; + options->permit_user_env = -1; + options->use_login = -1; +@@ -218,6 +219,8 @@ + options->kbd_interactive_authentication = 0; + if (options->challenge_response_authentication == -1) + options->challenge_response_authentication = 1; ++ if (options->permit_blacklisted_keys == -1) ++ options->permit_blacklisted_keys = 0; + if (options->permit_empty_passwd == -1) + options->permit_empty_passwd = 0; + if (options->permit_user_env == -1) +@@ -287,7 +290,7 @@ + sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, +- sStrictModes, sEmptyPasswd, sTCPKeepAlive, ++ sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive, + sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, + sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, + sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, +@@ -387,6 +390,7 @@ + { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, + { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, + { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, ++ { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL }, + { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, + { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, + { "uselogin", sUseLogin, SSHCFG_GLOBAL }, +@@ -943,6 +947,10 @@ + intptr = &options->tcp_keep_alive; + goto parse_flag; + ++ case sPermitBlacklistedKeys: ++ intptr = &options->permit_blacklisted_keys; ++ goto parse_flag; ++ + case sEmptyPasswd: + intptr = &options->permit_empty_passwd; + goto parse_flag; +--- openssh-4.7p1.orig/servconf.h ++++ openssh-4.7p1/servconf.h +@@ -94,6 +94,7 @@ + * authentication. / + int kbd_interactive_authentication; /* If true, permit */ + int challenge_response_authentication; ++ int permit_blacklisted_keys; /* If true, permit */ + int zero_knowledge_password_authentication; + /* If true, permit jpake auth */ + int permit_empty_passwd; /* If false, do not permit empty +--- openssh-4.7p1.orig/Makefile.in ++++ openssh-4.7p1/Makefile.in +@@ -62,7 +62,7 @@ + INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ + INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-vulnkey$(EXEEXT) + + LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ +@@ -93,8 +93,8 @@ + audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \ + roaming_common.o roaming_serv.o ldapauth.o + +-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 ++MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out ssh-vulnkey.1.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 ssh-vulnkey.1 + MANTYPE = @MANTYPE@ + + CONFIGFILES=sshd_config.out ssh_config.out moduli.out +@@ -165,6 +165,9 @@ + ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o + $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + ++ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o ++ $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ + # test driver for the loginrec code - not built by default + logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o + $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) +@@ -271,6 +274,7 @@ + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) ++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 +@@ -289,6 +293,7 @@ + $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 + $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 ++ $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1 + $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + -rm -f $(DESTDIR)$(bindir)/slogin + ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin +@@ -361,6 +366,7 @@ + -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) ++ -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT) + -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) + -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) + -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) +@@ -373,6 +379,7 @@ + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 ++ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 +--- openssh-4.7p1.orig/auth-rh-rsa.c ++++ openssh-4.7p1/auth-rh-rsa.c +@@ -20,6 +20,7 @@ + #include + #include + ++#include "xmalloc.h" + #include "packet.h" + #include "uidswap.h" + #include "log.h" +@@ -27,6 +28,7 @@ + #include "servconf.h" + #include "key.h" + #include "hostfile.h" ++#include "authfile.h" + #include "pathnames.h" + #include "auth.h" + #include "canohost.h" +@@ -42,8 +44,22 @@ + auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost, + Key *client_host_key) + { ++ char *fp; + HostStatus host_status; + ++ if (blacklisted_key(client_host_key)) { ++ fp = key_fingerprint(client_host_key, SSH_FP_MD5, SSH_FP_HEX); ++ if (options.permit_blacklisted_keys) ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1)); continuing anyway", fp); ++ else ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1))", fp); ++ free(fp); ++ if (!options.permit_blacklisted_keys) ++ return 0; ++ } ++ + if (auth_key_is_revoked(client_host_key)) + return 0; + +--- openssh-4.7p1.orig/authfile.h ++++ openssh-4.7p1/authfile.h +@@ -23,4 +23,7 @@ + Key *key_load_private_pem(int, int, const char *, char **); + int key_perm_ok(int, const char *); + ++char *blacklist_filename(const Key *key); ++int blacklisted_key(const Key *key); ++ + #endif +--- openssh-4.7p1.orig/ssh-vulnkey.1 ++++ openssh-4.7p1/ssh-vulnkey.1 +@@ -0,0 +1,187 @@ ++.\" Copyright (c) 2008 Canonical Ltd. All rights reserved. ++.\" ++.\" Redistribution and use in source and binary forms, with or without ++.\" modification, are permitted provided that the following conditions ++.\" are met: ++.\" 1. Redistributions of source code must retain the above copyright ++.\" notice, this list of conditions and the following disclaimer. ++.\" 2. Redistributions in binary form must reproduce the above copyright ++.\" notice, this list of conditions and the following disclaimer in the ++.\" documentation and/or other materials provided with the distribution. ++.\" ++.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++.\" (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: May 12 2008 $ ++.Dt SSH-VULNKEY 1 ++.Os ++.Sh NAME ++.Nm ssh-vulnkey ++.Nd check blacklist of compromised keys ++.Sh SYNOPSIS ++.Nm ++.Op Fl q ++.Ar file ... ++.Nm ++.Fl a ++.Sh DESCRIPTION ++.Nm ++checks a key against a blacklist of compromised keys. ++.Pp ++A substantial number of keys are known to have been generated using a broken ++version of OpenSSL distributed by Debian which failed to seed its random ++number generator correctly. ++Keys generated using these OpenSSL versions should be assumed to be ++compromised. ++This tool may be useful in checking for such keys. ++.Pp ++Keys that are compromised cannot be repaired; replacements must be generated ++using ++.Xr ssh-keygen 1 . ++Make sure to update ++.Pa authorized_keys ++files on all systems where compromised keys were permitted to authenticate. ++.Pp ++The argument list will be interpreted as a list of paths to public key files ++or ++.Pa authorized_keys ++files. ++If no suitable file is found at a given path, ++.Nm ++will append ++.Pa .pub ++and retry, in case it was given a private key file. ++If no files are given as arguments, ++.Nm ++will check ++.Pa ~/.ssh/id_rsa , ++.Pa ~/.ssh/id_dsa , ++.Pa ~/.ssh/identity , ++.Pa ~/.ssh/authorized_keys ++and ++.Pa ~/.ssh/authorized_keys2 , ++as well as the system's host keys if readable. ++.Pp ++If ++.Dq - ++is given as an argument, ++.Nm ++will read from standard input. ++This can be used to process output from ++.Xr ssh-keyscan 1 , ++for example: ++.Pp ++.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey - ++.Pp ++.Nm ++will exit zero if any of the given keys were in the compromised list, ++otherwise non-zero. ++.Pp ++Unless the ++.Cm PermitBlacklistedKeys ++option is used, ++.Xr sshd 8 ++will reject attempts to authenticate with keys in the compromised list. ++.Pp ++The options are as follows: ++.Bl -tag -width Ds ++.It Fl a ++Check keys of all users on the system. ++You will typically need to run ++.Nm ++as root to use this option. ++For each user, ++.Nm ++will check ++.Pa ~/.ssh/id_rsa , ++.Pa ~/.ssh/id_dsa , ++.Pa ~/.ssh/identity , ++.Pa ~/.ssh/authorized_keys ++and ++.Pa ~/.ssh/authorized_keys2 . ++It will also check the system's host keys. ++.It Fl q ++Quiet mode. ++Normally, ++.Nm ++outputs the fingerprint of each key scanned, with a description of its ++status. ++This option suppresses that output. ++.El ++.Sh BLACKLIST FILE FORMAT ++The blacklist file may start with comments, on lines starting with ++.Dq # . ++After these initial comments, it must follow a strict format: ++.Pp ++.Bl -bullet -offset indent -compact ++.It ++All the lines must be exactly the same length (20 characters followed by a ++newline) and must be in sorted order. ++.It ++Each line must consist of the lower-case hexadecimal MD5 key fingerprint, ++without colons, and with the first 12 characters removed (that is, the least ++significant 80 bits of the fingerprint). ++.El ++.Pp ++The key fingerprint may be generated using ++.Xr ssh-keygen 1 : ++.Pp ++.Dl $ ssh-keygen -l -f /path/to/key ++.Pp ++This strict format is necessary to allow the blacklist file to be checked ++quickly, using a binary-search algorithm. ++.Sh FILES ++.Bl -tag -width Ds ++.It Pa ~/.ssh/id_rsa ++If present, contains the protocol version 2 RSA authentication identity of ++the user. ++.It Pa ~/.ssh/id_dsa ++If present, contains the protocol version 2 DSA authentication identity of ++the user. ++.It Pa ~/.ssh/identity ++If present, contains the protocol version 1 RSA authentication identity of ++the user. ++.It Pa ~/.ssh/authorized_keys ++If present, lists the public keys (RSA/DSA) that can be used for logging in ++as this user. ++.It Pa ~/.ssh/authorized_keys2 ++Obsolete name for ++.Pa ~/.ssh/authorized_keys . ++This file may still be present on some old systems, but should not be ++created if it is missing. ++.It Pa /etc/ssh/ssh_host_rsa_key ++If present, contains the protocol version 2 RSA identity of the system. ++.It Pa /etc/ssh/ssh_host_dsa_key ++If present, contains the protocol version 2 DSA identity of the system. ++.It Pa /etc/ssh/ssh_host_key ++If present, contains the protocol version 1 RSA identity of the system. ++.It Pa /etc/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH ++If present, lists the blacklisted keys of type ++.Ar TYPE ++.Pf ( Dq RSA1 , ++.Dq RSA , ++or ++.Dq DSA ) ++and bit length ++.Ar LENGTH . ++The format of this file is described above. ++.El ++.Sh SEE ALSO ++.Xr ssh-keygen 1 , ++.Xr sshd 8 ++.Sh AUTHORS ++.An -nosplit ++.An Colin Watson Aq cjwatson@ubuntu.com ++.Pp ++Florian Weimer suggested the option to check keys of all users, and the idea ++of processing ++.Xr ssh-keyscan 1 ++output. +--- openssh-5.6p1/auth2-hostbased.c~ 2010-08-24 14:10:03.000000000 +0300 ++++ openssh-5.6p1/auth2-hostbased.c 2010-08-24 14:12:10.632553591 +0300 +@@ -40,6 +40,7 @@ + #include "compat.h" + #include "key.h" + #include "hostfile.h" ++#include "authfile.h" + #include "auth.h" + #include "canohost.h" + #ifdef GSSAPI +@@ -147,6 +148,19 @@ + int len; + char *fp; + ++ if (blacklisted_key(key)) { ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (options.permit_blacklisted_keys) ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1)); continuing anyway", fp); ++ else ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1))", fp); ++ free(fp); ++ if (!options.permit_blacklisted_keys) ++ return 0; ++ } ++ + if (auth_key_is_revoked(key)) + return 0; + +--- openssh-4.7p1.orig/authfile.c ++++ openssh-4.7p1/authfile.c +@@ -65,6 +65,7 @@ + #include "rsa.h" + #include "misc.h" + #include "atomicio.h" ++#include "pathnames.h" + + /* Version identification string for SSH v1 identity files. */ + static const char authfile_id_string[] = +@@ -677,3 +678,113 @@ + return ret; + } + ++ ++char * ++blacklist_filename(const Key *key) ++{ ++ char *name; ++ ++ xasprintf(&name, "%s.%s-%u", ++ _PATH_BLACKLIST, key_type(key), key_size(key)); ++ return name; ++} ++ ++/* Scan a blacklist of known-vulnerable keys. */ ++int ++blacklisted_key(const Key *key) ++{ ++ char *blacklist_file; ++ int fd = -1; ++ char *dgst_hex = NULL; ++ char *dgst_packed = NULL, *p; ++ int i; ++ size_t line_len; ++ struct stat st; ++ char buf[256]; ++ off_t start, lower, upper; ++ int ret = 0; ++ ++ blacklist_file = blacklist_filename(key); ++ debug("Checking blacklist file %s", blacklist_file); ++ fd = open(blacklist_file, O_RDONLY); ++ if (fd < 0) ++ goto out; ++ ++ dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ /* Remove all colons */ ++ dgst_packed = xcalloc(1, strlen(dgst_hex) + 1); ++ for (i = 0, p = dgst_packed; dgst_hex[i]; i++) ++ if (dgst_hex[i] != ':') ++ *p++ = dgst_hex[i]; ++ /* Only compare least-significant 80 bits (to keep the blacklist ++ * size down) ++ */ ++ line_len = strlen(dgst_packed + 12); ++ if (line_len > 32) ++ goto out; ++ ++ /* Skip leading comments */ ++ start = 0; ++ for (;;) { ++ ssize_t r; ++ char *newline; ++ ++ r = atomicio(read, fd, buf, 256); ++ if (r <= 0) ++ goto out; ++ if (buf[0] != '#') ++ break; ++ ++ newline = memchr(buf, '\n', 256); ++ if (!newline) ++ goto out; ++ start += newline + 1 - buf; ++ if (lseek(fd, start, SEEK_SET) < 0) ++ goto out; ++ } ++ ++ /* Initialise binary search record numbers */ ++ if (fstat(fd, &st) < 0) ++ goto out; ++ lower = 0; ++ upper = (st.st_size - start) / (line_len + 1); ++ ++ while (lower != upper) { ++ off_t cur; ++ char buf[32]; ++ int cmp; ++ ++ cur = lower + (upper - lower) / 2; ++ ++ /* Read this line and compare to digest; this is ++ * overflow-safe since cur < max(off_t) / (line_len + 1) */ ++ if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0) ++ break; ++ if (atomicio(read, fd, buf, line_len) != line_len) ++ break; ++ cmp = memcmp(buf, dgst_packed + 12, line_len); ++ if (cmp < 0) { ++ if (cur == lower) ++ break; ++ lower = cur; ++ } else if (cmp > 0) { ++ if (cur == upper) ++ break; ++ upper = cur; ++ } else { ++ debug("Found %s in blacklist", dgst_hex); ++ ret = 1; ++ break; ++ } ++ } ++ ++out: ++ if (dgst_packed) ++ free(dgst_packed); ++ if (dgst_hex) ++ free(dgst_hex); ++ if (fd >= 0) ++ close(fd); ++ free(blacklist_file); ++ return ret; ++} +--- openssh-4.7p1.orig/ssh-vulnkey.c ++++ openssh-4.7p1/ssh-vulnkey.c +@@ -0,0 +1,325 @@ ++/* ++ * Copyright (c) 2008 Canonical Ltd. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "includes.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "ssh.h" ++#include "log.h" ++#include "key.h" ++#include "authfile.h" ++#include "pathnames.h" ++#include "misc.h" ++ ++extern char *__progname; ++ ++/* Default files to check */ ++static char *default_host_files[] = { ++ _PATH_HOST_RSA_KEY_FILE, ++ _PATH_HOST_DSA_KEY_FILE, ++ _PATH_HOST_KEY_FILE, ++ NULL ++}; ++static char *default_files[] = { ++ _PATH_SSH_CLIENT_ID_RSA, ++ _PATH_SSH_CLIENT_ID_DSA, ++ _PATH_SSH_CLIENT_IDENTITY, ++ _PATH_SSH_USER_PERMITTED_KEYS, ++ _PATH_SSH_USER_PERMITTED_KEYS2, ++ NULL ++}; ++ ++static int quiet = 0; ++ ++static void ++usage(void) ++{ ++ fprintf(stderr, "usage: %s [-aq] [file ...]\n", __progname); ++ fprintf(stderr, "Options:\n"); ++ fprintf(stderr, " -a Check keys of all users.\n"); ++ fprintf(stderr, " -q Quiet mode.\n"); ++ exit(1); ++} ++ ++void ++describe_key(const char *msg, const Key *key, const char *comment) ++{ ++ char *fp; ++ ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (!quiet) ++ printf("%s: %u %s %s\n", msg, key_size(key), fp, comment); ++ free(fp); ++} ++ ++int ++do_key(const Key *key, const char *comment) ++{ ++ char *blacklist_file; ++ struct stat st; ++ int ret = 1; ++ ++ blacklist_file = blacklist_filename(key); ++ if (stat(blacklist_file, &st) < 0) ++ describe_key("Unknown (no blacklist information)", ++ key, comment); ++ else if (blacklisted_key(key)) { ++ describe_key("COMPROMISED", key, comment); ++ ret = 0; ++ } else ++ describe_key("Not blacklisted", key, comment); ++ free(blacklist_file); ++ ++ return ret; ++} ++ ++int ++do_filename(const char *filename, int quiet_open) ++{ ++ FILE *f; ++ char line[SSH_MAX_PUBKEY_BYTES]; ++ char *cp; ++ u_long linenum = 0; ++ Key *key; ++ char *comment = NULL; ++ int found = 0, ret = 1; ++ ++ /* Copy much of key_load_public's logic here so that we can read ++ * several keys from a single file (e.g. authorized_keys). ++ */ ++ ++ if (strcmp(filename, "-") != 0) { ++ f = fopen(filename, "r"); ++ if (!f) { ++ char pubfile[MAXPATHLEN]; ++ if (strlcpy(pubfile, filename, sizeof pubfile) < ++ sizeof(pubfile) && ++ strlcat(pubfile, ".pub", sizeof pubfile) < ++ sizeof(pubfile)) ++ f = fopen(pubfile, "r"); ++ } ++ if (!f) { ++ if (!quiet_open) ++ perror(filename); ++ return -1; ++ } ++ } else ++ f = stdin; ++ while (read_keyfile_line(f, filename, line, sizeof(line), ++ &linenum) != -1) { ++ int i; ++ char *space; ++ int type; ++ ++ /* Chop trailing newline. */ ++ i = strlen(line) - 1; ++ if (line[i] == '\n') ++ line[i] = '\0'; ++ ++ /* Skip leading whitespace, empty and comment lines. */ ++ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ++ ; ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ /* Cope with ssh-keyscan output and options in ++ * authorized_keys files. ++ */ ++ space = strchr(cp, ' '); ++ if (!space) ++ continue; ++ *space = '\0'; ++ type = key_type_from_name(cp); ++ *space = ' '; ++ /* Leading number (RSA1) or valid type (RSA/DSA) indicates ++ * that we have no host name or options to skip. ++ */ ++ if (atoi(cp) == 0 && type == KEY_UNSPEC) { ++ int quoted = 0; ++ ++ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { ++ if (*cp == '\\' && cp[1] == '"') ++ cp++; /* Skip both */ ++ else if (*cp == '"') ++ quoted = !quoted; ++ } ++ /* Skip remaining whitespace. */ ++ for (; *cp == ' ' || *cp == '\t'; cp++) ++ ; ++ if (!*cp) ++ continue; ++ } ++ ++ /* Read and process the key itself. */ ++ key = key_new(KEY_RSA1); ++ if (key_read(key, &cp) == 1) { ++ while (*cp == ' ' || *cp == '\t') ++ cp++; ++ if (!do_key(key, *cp ? cp : filename)) ++ ret = 0; ++ found = 1; ++ } else { ++ key_free(key); ++ key = key_new(KEY_UNSPEC); ++ if (key_read(key, &cp) == 1) { ++ while (*cp == ' ' || *cp == '\t') ++ cp++; ++ if (!do_key(key, *cp ? cp : filename)) ++ ret = 0; ++ found = 1; ++ } ++ } ++ key_free(key); ++ } ++ if (f != stdin) ++ fclose(f); ++ ++ if (!found && filename) { ++ key = key_load_public(filename, &comment); ++ if (key) { ++ if (!do_key(key, comment)) ++ ret = 0; ++ found = 1; ++ } ++ if (comment) ++ free(comment); ++ } ++ ++ return ret; ++} ++ ++int ++do_host(void) ++{ ++ int i; ++ struct stat st; ++ int ret = 1; ++ ++ for (i = 0; default_host_files[i]; i++) { ++ if (stat(default_host_files[i], &st) < 0) ++ continue; ++ if (!do_filename(default_host_files[i], 1)) ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++int ++do_user(const char *dir) ++{ ++ int i; ++ char buf[MAXPATHLEN]; ++ struct stat st; ++ int ret = 1; ++ ++ for (i = 0; default_files[i]; i++) { ++ snprintf(buf, sizeof(buf), "%s/%s", dir, default_files[i]); ++ if (stat(buf, &st) < 0) ++ continue; ++ if (!do_filename(buf, 0)) ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++int ++main(int argc, char **argv) ++{ ++ int opt, all_users = 0; ++ int ret = 1; ++ extern int optind; ++ ++ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ ++ sanitise_stdfd(); ++ ++ __progname = ssh_get_progname(argv[0]); ++ ++ SSLeay_add_all_algorithms(); ++ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); ++ ++ /* We don't need the RNG ourselves, but symbol references here allow ++ * ld to link us properly. ++ */ ++ //init_rng(); ++ //seed_rng(); ++ ++ while ((opt = getopt(argc, argv, "ahq")) != -1) { ++ switch (opt) { ++ case 'a': ++ all_users = 1; ++ break; ++ case 'q': ++ quiet = 1; ++ break; ++ case 'h': ++ default: ++ usage(); ++ } ++ } ++ ++ if (all_users) { ++ struct passwd *pw; ++ ++ if (!do_host()) ++ ret = 0; ++ ++ while ((pw = getpwent()) != NULL) { ++ if (pw->pw_dir) { ++ if (!do_user(pw->pw_dir)) ++ ret = 0; ++ } ++ } ++ } else if (optind == argc) { ++ struct passwd *pw; ++ ++ if (!do_host()) ++ ret = 0; ++ ++ if ((pw = getpwuid(getuid())) == NULL) ++ fprintf(stderr, "No user found with uid %u\n", ++ (u_int)getuid()); ++ else { ++ if (!do_user(pw->pw_dir)) ++ ret = 0; ++ } ++ } else { ++ while (optind < argc) ++ if (!do_filename(argv[optind++], 0)) ++ ret = 0; ++ } ++ ++ return ret; ++} +--- openssh-4.7p1.orig/auth-rsa.c ++++ openssh-4.7p1/auth-rsa.c +@@ -40,6 +40,7 @@ + #include "servconf.h" + #include "key.h" + #include "hostfile.h" ++#include "authfile.h" + #include "auth.h" + #ifdef GSSAPI + #include "ssh-gss.h" +@@ -221,6 +222,7 @@ + char *cp; + char *key_options; + int keybits; ++ char *fp; + + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) +@@ -265,6 +267,19 @@ + "actual %d vs. announced %d.", + file, linenum, BN_num_bits(key->rsa->n), bits); + ++ if (blacklisted_key(key)) { ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (options.permit_blacklisted_keys) ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1)); continuing anyway", fp); ++ else ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1))", fp); ++ free(fp); ++ if (!options.permit_blacklisted_keys) ++ continue; ++ } ++ + /* We have found the desired key. */ + /* + * If our options do not allow this key to be used, +--- openssh-4.7p1.orig/pathnames.h ++++ openssh-4.7p1/pathnames.h +@@ -43,6 +43,8 @@ + /* Backwards compatibility */ + #define _PATH_DH_PRIMES SSHDIR "/primes" + ++#define _PATH_BLACKLIST SSHDIR "/blacklist" ++ + #ifndef _PATH_SSH_PROGRAM + #define _PATH_SSH_PROGRAM "/usr/bin/ssh" + #endif +--- openssh-5.9p1/auth2-pubkey.c~ 2011-09-29 00:36:17.000000000 +0300 ++++ openssh-5.9p1/auth2-pubkey.c 2011-09-29 00:37:17.847762648 +0300 +@@ -42,6 +42,7 @@ + #include "compat.h" + #include "key.h" + #include "hostfile.h" ++#include "authfile.h" + #include "auth.h" + #include "pathnames.h" + #include "uidswap.h" +@@ -608,6 +609,20 @@ + { + u_int success, i; + char *file; ++ char *fp; ++ ++ if (blacklisted_key(key)) { ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (options.permit_blacklisted_keys) ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1)); continuing anyway", fp); ++ else ++ logit("Public key %s blacklisted (see " ++ "ssh-vulnkey(1))", fp); ++ free(fp); ++ if (!options.permit_blacklisted_keys) ++ return 0; ++ } + + if (auth_key_is_revoked(key)) + return 0; + diff --git a/openssh-chroot.patch b/openssh-chroot.patch new file mode 100644 index 0000000..5dda773 --- /dev/null +++ b/openssh-chroot.patch @@ -0,0 +1,157 @@ +--- openssh-4.4p1/servconf.c.orig 2006-08-18 16:23:15.000000000 +0200 ++++ openssh-4.4p1/servconf.c 2006-10-05 10:11:17.065971000 +0200 +@@ -56,7 +56,9 @@ + + /* Portable-specific options */ + options->use_pam = -1; +- ++ ++ options->use_chroot = -1; ++ + /* Standard Options */ + options->num_ports = 0; + options->ports_from_cmdline = 0; +@@ -131,6 +133,9 @@ + if (options->use_pam == -1) + options->use_pam = 0; + ++ if (options->use_chroot == -1) ++ options->use_chroot = 0; ++ + /* Standard Options */ + if (options->protocol == SSH_PROTO_UNKNOWN) + options->protocol = SSH_PROTO_1|SSH_PROTO_2; +@@ -270,6 +275,7 @@ + sBadOption, /* == unknown option */ + /* Portable-specific options */ + sUsePAM, ++ sUseChroot, + /* Standard Options */ + sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, + sPermitRootLogin, sLogFacility, sLogLevel, +@@ -312,6 +318,11 @@ + #else + { "usepam", sUnsupported, SSHCFG_GLOBAL }, + #endif ++#ifdef CHROOT ++ { "usechroot", sUseChroot, SSHCFG_GLOBAL }, ++#else ++ { "usechroot", sUnsupported, SSHCFG_GLOBAL }, ++#endif /* CHROOT */ + { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, + /* Standard Options */ + { "port", sPort, SSHCFG_GLOBAL }, +@@ -662,6 +673,10 @@ + intptr = &options->use_pam; + goto parse_flag; + ++ case sUseChroot: ++ intptr = &options->use_chroot; ++ goto parse_flag; ++ + /* Standard Options */ + case sBadOption: + return -1; +--- openssh-3.7.1p2/servconf.h 2003-09-02 14:58:22.000000000 +0200 ++++ openssh-3.7.1p2.pius/servconf.h 2003-10-07 20:49:08.000000000 +0200 +@@ -109,6 +109,7 @@ + int max_startups_rate; + int max_startups; + char *banner; /* SSH-2 banner message */ ++ int use_chroot; /* Enable chrooted enviroment support */ + int use_dns; + int client_alive_interval; /* + * poke the client this often to +--- ./session.c.org 2008-05-05 16:22:11.935003283 +0200 ++++ ./session.c 2008-05-05 16:32:50.025507650 +0200 +@@ -1345,6 +1345,10 @@ void + do_setusercontext(struct passwd *pw) + { + char *chroot_path, *tmp; ++#ifdef CHROOT ++ char *user_dir; ++ char *new_root; ++#endif /* CHROOT */ + + #ifdef WITH_SELINUX + /* Cache selinux status for later use */ +@@ -1425,8 +1429,28 @@ do_setusercontext(struct passwd *pw) + /* Make sure we don't attempt to chroot again */ + free(options.chroot_directory); + options.chroot_directory = NULL; ++#ifdef CHROOT ++ } else if (options.use_chroot) { ++ user_dir = xstrdup(pw->pw_dir); ++ new_root = user_dir + 1; ++ ++ while((new_root = strchr(new_root, '.')) != NULL) { ++ new_root--; ++ if(strncmp(new_root, "/./", 3) == 0) { ++ *new_root = '\0'; ++ new_root += 2; ++ ++ if(chroot(user_dir) != 0) ++ fatal("Couldn't chroot to user directory %s", user_dir); ++ pw->pw_dir = new_root; ++ break; ++ } ++ new_root += 2; ++ } ++#endif /* CHROOT */ + } + ++ + #ifdef HAVE_LOGIN_CAP + if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) { + perror("unable to set user context (setuser)"); +--- openssh-3.7.1p2/sshd_config 2003-09-02 14:51:18.000000000 +0200 ++++ openssh-3.7.1p2.pius/sshd_config 2003-10-07 20:49:08.000000000 +0200 +@@ -91,6 +91,10 @@ + # and ChallengeResponseAuthentication to 'no'. + UsePAM yes + ++# Set this to 'yes' to enable support for chrooted user environment. ++# You must create such environment before you can use this feature. ++#UseChroot yes ++ + #AllowAgentForwarding yes + # Security advisory: + # http://securitytracker.com/alerts/2004/Sep/1011143.html +--- openssh-4.4p1/sshd_config.0.orig 2006-09-26 13:03:48.000000000 +0200 ++++ openssh-4.4p1/sshd_config.0 2006-10-05 10:11:41.615971000 +0200 +@@ -451,6 +451,16 @@ + To disable TCP keepalive messages, the value should be set to + ``no''. + ++ UseChroot ++ Specifies whether to use chroot-jail environment with ssh/sftp, ++ i.e. restrict users to a particular area in the filesystem. This ++ is done by setting user home directory to, for example, ++ /path/to/chroot/./home/username. sshd looks for a '.' in the ++ users home directory, then calls chroot(2) to whatever directory ++ was before the . and continues with the normal ssh functionality. ++ For this to work properly you have to create special chroot-jail ++ environment in a /path/to/chroot directory. ++ + UseDNS Specifies whether sshd(8) should look up the remote host name and + check that the resolved host name for the remote IP address maps + back to the very same IP address. The default is ``yes''. +--- openssh-3.8p1/sshd_config.5.orig 2004-02-18 04:31:24.000000000 +0100 ++++ openssh-3.8p1/sshd_config.5 2004-02-25 21:17:23.000000000 +0100 +@@ -552,6 +552,16 @@ + The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, + LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. + The default is AUTH. ++.It Cm UseChroot ++Specifies whether to use chroot-jail environment with ssh/sftp, i.e. restrict ++users to a particular area in the filesystem. This is done by setting user ++home directory to, for example, /path/to/chroot/./home/username. ++.Nm sshd ++looks for a '.' in the users home directory, then calls ++.Xr chroot 2 ++to whatever directory was before the . and continues with the normal ssh ++functionality. For this to work properly you have to create special chroot-jail ++environment in a /path/to/chroot directory. + .It Cm TCPKeepAlive + Specifies whether the system should send TCP keepalive messages to the + other side. diff --git a/openssh-config.patch b/openssh-config.patch new file mode 100644 index 0000000..80c4995 --- /dev/null +++ b/openssh-config.patch @@ -0,0 +1,108 @@ +--- openssh-4.6p1/sshd_config~ 2007-10-13 01:37:17.000000000 +0200 ++++ openssh-4.6p1/sshd_config 2007-10-13 01:47:12.000000000 +0200 +@@ -34,6 +35,7 @@ + + #LoginGraceTime 2m + #PermitRootLogin yes ++PermitRootLogin no + #StrictModes yes + #MaxAuthTries 6 + +@@ -50,10 +51,13 @@ + #IgnoreUserKnownHosts no + # Don't read the user's ~/.rhosts and ~/.shosts files + #IgnoreRhosts yes ++IgnoreRhosts yes + + # To disable tunneled clear text passwords, change to no here! + #PasswordAuthentication yes + #PermitEmptyPasswords no ++PasswordAuthentication yes ++PermitEmptyPasswords no + + # Change to no to disable s/key passwords + #ChallengeResponseAuthentication yes +@@ -66,6 +67,8 @@ + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++GSSAPIAuthentication yes ++GSSAPICleanupCredentials yes + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +@@ -89,10 +89,12 @@ + # If you just want the PAM account and session checks to run without + # PAM authentication, then enable this but set PasswordAuthentication + # and ChallengeResponseAuthentication to 'no'. +-#UsePAM no ++UsePAM yes + + #AllowAgentForwarding yes +-#AllowTcpForwarding yes ++# Security advisory: ++# http://securitytracker.com/alerts/2004/Sep/1011143.html ++AllowTcpForwarding no + #GatewayPorts no + #X11Forwarding no + #X11DisplayOffset 10 +@@ -106,6 +109,9 @@ + # no default banner path + #Banner /some/path + ++# Accept locale-related environment variables, also accept some GIT vars ++AcceptEnv LANG LC_* LANGUAGE XMODIFIERS TZ GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL ++ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + +@@ -119,6 +130,10 @@ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + ++# Uncomment this if you want to use .local domain ++#Host *.local ++# CheckHostIP no ++ + # Example of overriding settings on a per-user basis + #Match User anoncvs + # X11Forwarding no +--- openssh-4.6p1/ssh_config~ 2006-06-13 05:01:10.000000000 +0200 ++++ openssh-4.6p1/ssh_config 2007-10-13 02:00:16.000000000 +0200 +@@ -20,12 +20,15 @@ + # Host * + # ForwardAgent no + # ForwardX11 no ++# ForwardX11Trusted yes + # RhostsRSAAuthentication no + # RSAAuthentication yes + # PasswordAuthentication yes + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +@@ -42,3 +45,19 @@ + # VisualHostKey no + # ProxyCommand ssh -q -W %h:%p gateway.example.com + # RekeyLimit 1G 1h ++ ++Host * ++ GSSAPIAuthentication yes ++ GSSAPIDelegateCredentials no ++ ForwardAgent no ++ ForwardX11 no ++# If this option is set to yes then remote X11 clients will have full access ++# to the original X11 display. As virtually no X11 client supports the untrusted ++# mode correctly we set this to yes. ++ ForwardX11Trusted yes ++ StrictHostKeyChecking no ++ ServerAliveInterval 60 ++ ServerAliveCountMax 10 ++ TCPKeepAlive no ++# Send locale-related environment variables, also pass some GIT vars ++ SendEnv LANG LC_* LANGUAGE XMODIFIERS TZ GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL ++ HashKnownHosts yes diff --git a/openssh-disable_ldap.patch b/openssh-disable_ldap.patch new file mode 100644 index 0000000..1b0ffae --- /dev/null +++ b/openssh-disable_ldap.patch @@ -0,0 +1,23 @@ +diff -dur -x '*~' openssh-6.1p1.orig/Makefile.in openssh-6.1p1/Makefile.in +--- openssh-6.1p1.orig/Makefile.in 2012-10-29 11:25:43.000000000 +0100 ++++ openssh-6.1p1/Makefile.in 2012-10-29 14:48:34.336371687 +0100 +@@ -62,7 +62,7 @@ + MANFMT=@MANFMT@ + INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-vulnkey$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT) + + LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ +@@ -96,8 +96,8 @@ + sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ + sandbox-seccomp-filter.o + +-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out ssh-vulnkey.1.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 ssh-vulnkey.1 ++MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out ssh-vulnkey.1.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ssh-vulnkey.1 + MANTYPE = @MANTYPE@ + + CONFIGFILES=sshd_config.out ssh_config.out moduli.out diff --git a/openssh-include.patch b/openssh-include.patch new file mode 100644 index 0000000..801c681 --- /dev/null +++ b/openssh-include.patch @@ -0,0 +1,11 @@ +--- openssh-5.9p1/configure.ac~ 2011-09-06 19:31:16.000000000 +0200 ++++ openssh-5.9p1/configure.ac 2011-09-06 19:31:55.291791679 +0200 +@@ -1076,6 +1076,7 @@ + + AC_MSG_CHECKING([for possibly buggy zlib]) + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ ++#include + #include + #include + ]], + diff --git a/openssh-kuserok.patch b/openssh-kuserok.patch new file mode 100644 index 0000000..4d5388b --- /dev/null +++ b/openssh-kuserok.patch @@ -0,0 +1,167 @@ +diff -up openssh-5.8p1/auth-krb5.c.kuserok openssh-5.8p1/auth-krb5.c +--- openssh-5.8p1/auth-krb5.c.kuserok 2009-12-21 00:49:22.000000000 +0100 ++++ openssh-5.8p1/auth-krb5.c 2011-02-14 09:15:12.000000000 +0100 +@@ -54,6 +54,20 @@ + + extern ServerOptions options; + ++int ++ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client) ++{ ++ if (options.use_kuserok) ++ return krb5_kuserok(krb5_ctx, krb5_user, client); ++ else { ++ char kuser[65]; ++ ++ if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser)) ++ return 0; ++ return strcmp(kuser, client) == 0; ++ } ++} ++ + static int + krb5_init(void *context) + { +@@ -146,7 +160,7 @@ auth_krb5_password(Authctxt *authctxt, c + if (problem) + goto out; + +- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { ++ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { + problem = -1; + goto out; + } +diff -up openssh-5.8p1/gss-serv-krb5.c.kuserok openssh-5.8p1/gss-serv-krb5.c +--- openssh-5.8p1/gss-serv-krb5.c.kuserok 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-5.8p1/gss-serv-krb5.c 2011-02-14 09:15:12.000000000 +0100 +@@ -57,6 +57,7 @@ extern ServerOptions options; + #endif + + static krb5_context krb_context = NULL; ++extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *); + + /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ + +@@ -97,7 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + krb5_get_err_text(krb_context, retval)); + return 0; + } +- if (krb5_kuserok(krb_context, princ, name)) { ++ if (ssh_krb5_kuserok(krb_context, princ, name)) { + retval = 1; + logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", + name, (char *)client->displayname.value); +diff -up openssh-5.8p1/servconf.c.kuserok openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-14 09:20:22.000000000 +0100 +@@ -133,6 +133,7 @@ + options->num_accept_env = 0; + options->permit_tun = -1; + options->num_permitted_opens = -1; ++ options->use_kuserok = -1; + options->adm_forced_command = NULL; + options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; +@@ -291,6 +292,8 @@ fill_default_server_options(ServerOption + if (use_privsep == -1) + use_privsep = 1; + ++ if (options->use_kuserok == -1) ++ options->use_kuserok = 1; + #ifndef HAVE_MMAP + if (use_privsep && options->compression == 1) { + error("This platform does not support both privilege " +@@ -312,7 +315,7 @@ typedef enum { + sPermitRootLogin, sLogFacility, sLogLevel, + sRhostsRSAAuthentication, sRSAAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, ++ sKerberosGetAFSToken, sKerberosUseKuserok, + sKerberosTgtPassing, sChallengeResponseAuthentication, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, +@@ -381,11 +384,13 @@ static struct { + #else + { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, + #endif ++ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL }, + #else + { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, + { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, ++ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL }, + #endif + { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, + { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, +@@ -1341,6 +1346,10 @@ process_server_config_line(ServerOptions + *activep = value; + break; + ++ case sKerberosUseKuserok: ++ intptr = &options->use_kuserok; ++ goto parse_flag; ++ + case sPermitOpen: + arg = strdelim(&cp); + if (!arg || *arg == '\0') +@@ -1544,6 +1553,7 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(ip_qos_bulk); + M_CP_INTOPT(rekey_limit); + M_CP_INTOPT(rekey_interval); ++ M_CP_INTOPT(use_kuserok); + + M_CP_STROPT(banner); + if (preauth) +@@ -1764,6 +1774,7 @@ dump_config(ServerOptions *o) + dump_cfg_fmtint(sUseDNS, o->use_dns); + dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); + dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); ++ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); + + /* string arguments */ + dump_cfg_string(sPidFile, o->pid_file); +diff -up openssh-5.8p1/servconf.h.kuserok openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-14 09:15:12.000000000 +0100 +@@ -157,6 +157,7 @@ typedef struct { + + int num_permitted_opens; + ++ int use_kuserok; + char *chroot_directory; + char *revoked_keys_file; + char *trusted_user_ca_keys; +diff -up openssh-5.8p1/sshd_config.5.kuserok openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-14 09:17:11.000000000 +0100 +@@ -574,6 +574,10 @@ Specifies whether to automatically destr + file on logout. + The default is + .Dq yes . ++.It Cm KerberosUseKuserok ++Specifies whether to look at .k5login file for user's aliases. ++The default is ++.Dq yes . + .It Cm KexAlgorithms + Specifies the available KEX (Key Exchange) algorithms. + Multiple algorithms must be comma-separated. +@@ -715,6 +719,7 @@ Available keywords are + .Cm HostbasedUsesNameFromPacketOnly , + .Cm KbdInteractiveAuthentication , + .Cm KerberosAuthentication , ++.Cm KerberosUseKuserok , + .Cm MaxAuthTries , + .Cm MaxSessions , + .Cm PubkeyAuthentication , +diff -up openssh-5.8p1/sshd_config.kuserok openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-14 09:15:12.000000000 +0100 +@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no ++#KerberosUseKuserok yes + + # GSSAPI options + #GSSAPIAuthentication no diff --git a/openssh-ldap-fixes.patch b/openssh-ldap-fixes.patch new file mode 100644 index 0000000..19feca6 --- /dev/null +++ b/openssh-ldap-fixes.patch @@ -0,0 +1,25 @@ +diff -ur openssh-5.9p1.org/ldap-helper.c openssh-5.9p1/ldap-helper.c +--- openssh-5.9p1.org/ldap-helper.c 2011-09-11 08:44:20.526555802 +0200 ++++ openssh-5.9p1/ldap-helper.c 2011-09-11 08:43:11.328426660 +0200 +@@ -62,6 +62,8 @@ + int + main(int ac, char **av) + { ++ extern char *optarg; ++ extern int optind; + int opt; + FILE *outfile = NULL; + +diff -ur openssh-5.9p1.org/Makefile.in openssh-5.9p1/Makefile.in +--- openssh-5.9p1.org/Makefile.in 2011-09-11 08:44:20.543222823 +0200 ++++ openssh-5.9p1/Makefile.in 2011-09-11 08:43:11.348427083 +0200 +@@ -165,7 +165,7 @@ + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lssh -lopenbsd-compat $(LIBS) + + ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o +- $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) ++ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o + $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + diff --git a/openssh-ldap.patch b/openssh-ldap.patch new file mode 100644 index 0000000..994ef59 --- /dev/null +++ b/openssh-ldap.patch @@ -0,0 +1,2609 @@ +diff -up openssh-6.2p1/configure.ac.ldap openssh-6.2p1/configure.ac +--- openssh-6.2p1/configure.ac.ldap 2013-03-20 02:55:15.000000000 +0100 ++++ openssh-6.2p1/configure.ac 2013-03-25 21:27:15.888248071 +0100 +@@ -1509,6 +1509,106 @@ AC_ARG_WITH([audit], + esac ] + ) + ++# Check whether user wants LDAP support ++LDAP_MSG="no" ++INSTALL_SSH_LDAP_HELPER="" ++AC_ARG_WITH(ldap, ++ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], ++ [ ++ if test "x$withval" != "xno" ; then ++ ++ INSTALL_SSH_LDAP_HELPER="yes" ++ CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED" ++ ++ if test "x$withval" != "xyes" ; then ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ LDFLAGS="$LDFLAGS -L${withval}/lib" ++ fi ++ ++ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support]) ++ LDAP_MSG="yes" ++ ++ AC_CHECK_HEADERS(lber.h) ++ AC_CHECK_HEADERS(ldap.h, , AC_MSG_ERROR(could not locate )) ++ AC_CHECK_HEADERS(ldap_ssl.h) ++ ++ AC_ARG_WITH(ldap-lib, ++ [ --with-ldap-lib=type select ldap library [auto|netscape5|netscape4|netscape3|umich|openldap]]) ++ ++ if test -z "$with_ldap_lib"; then ++ with_ldap_lib=auto ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = umich -o $with_ldap_lib = openldap \); then ++ AC_CHECK_LIB(lber, main, LIBS="-llber $LIBS" found_ldap_lib=yes) ++ AC_CHECK_LIB(ldap, main, LIBS="-lldap $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape5 \); then ++ AC_CHECK_LIB(ldap50, main, LIBS="-lldap50 -lssldap50 -lssl3 -lnss3 -lnspr4 -lprldap50 -lplc4 -lplds4 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape4 \); then ++ AC_CHECK_LIB(ldapssl41, main, LIBS="-lldapssl41 -lplc3 -lplds3 -lnspr3 $LIBS" found_ldap_lib=yes) ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldapssl40, main, LIBS="-lldapssl40 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap41, main, LIBS="-lldap41 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap40, main, LIBS="-lldap40 $LIBS" found_ldap_lib=yes) ++ fi ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape3 \); then ++ AC_CHECK_LIB(ldapssl30, main, LIBS="-lldapssl30 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib"; then ++ AC_MSG_ERROR(could not locate a valid LDAP library) ++ fi ++ ++ AC_MSG_CHECKING([for working LDAP support]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [(void)ldap_init(0, 0);], ++ [AC_MSG_RESULT(yes)], ++ [ ++ AC_MSG_RESULT(no) ++ AC_MSG_ERROR([** Incomplete or missing ldap libraries **]) ++ ]) ++ AC_CHECK_FUNCS( \ ++ ldap_init \ ++ ldap_get_lderrno \ ++ ldap_set_lderrno \ ++ ldap_parse_result \ ++ ldap_memfree \ ++ ldap_controls_free \ ++ ldap_set_option \ ++ ldap_get_option \ ++ ldapssl_init \ ++ ldap_start_tls_s \ ++ ldap_pvt_tls_set_option \ ++ ldap_initialize \ ++ ) ++ AC_CHECK_FUNCS(ldap_set_rebind_proc, ++ AC_MSG_CHECKING([number arguments of ldap_set_rebind_proc]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [ldap_set_rebind_proc(0, 0, 0);], ++ [ac_cv_ldap_set_rebind_proc=3], ++ [ac_cv_ldap_set_rebind_proc=2]) ++ AC_MSG_RESULT($ac_cv_ldap_set_rebind_proc) ++ AC_DEFINE(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc]) ++ ) ++ fi ++ ] ++) ++AC_SUBST(INSTALL_SSH_LDAP_HELPER) ++ + dnl Checks for library functions. Please keep in alphabetical order + AC_CHECK_FUNCS([ \ + arc4random \ +diff -up openssh-6.2p1/HOWTO.ldap-keys.ldap openssh-6.2p1/HOWTO.ldap-keys +--- openssh-6.2p1/HOWTO.ldap-keys.ldap 2013-03-25 21:27:15.889248078 +0100 ++++ openssh-6.2p1/HOWTO.ldap-keys 2013-03-25 21:27:15.889248078 +0100 +@@ -0,0 +1,108 @@ ++ ++HOW TO START ++ ++1) configure LDAP server ++ * Use LDAP server documentation ++2) add appropriate LDAP schema ++ * For OpenLDAP or SunONE Use attached schema, otherwise you have to create it. ++ * LDAP user entry ++ User entry: ++ - attached to the 'ldapPublicKey' objectclass ++ - attached to the 'posixAccount' objectclass ++ - with a filled 'sshPublicKey' attribute ++3) insert users into LDAP ++ * Use LDAP Tree management tool as useful ++ * Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema and the additionnal lpk.schema. ++ * Example: ++ dn: uid=captain,ou=commanders,dc=enterprise,dc=universe ++ objectclass: top ++ objectclass: person ++ objectclass: organizationalPerson ++ objectclass: posixAccount ++ objectclass: ldapPublicKey ++ description: Jonathan Archer ++ userPassword: Porthos ++ cn: onathan Archer ++ sn: onathan Archer ++ uid: captain ++ uidNumber: 1001 ++ gidNumber: 1001 ++ homeDirectory: /home/captain ++ sshPublicKey: ssh-rss AAAAB3.... =captain@universe ++ sshPublicKey: command="kill -9 1" ssh-rss AAAAM5... ++4) on the ssh side set in sshd_config ++ * Set up the backend ++ AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper ++ AuthorizedKeysCommandUser ++ * Do not forget to set ++ PubkeyAuthentication yes ++ * Swith off unnecessary auth methods ++5) confugure ldap.conf ++ * Default ldap.conf is placed in /etc/ssh ++ * The configuration style is the same as other ldap based aplications ++6) if necessary edit ssh-ldap-wrapper ++ * There is a possibility to change ldap.conf location ++ * There are some debug options ++ * Example ++ /usr/libexec/openssh -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt ++ ++HOW TO MIGRATE FROM LPK ++ ++1) goto HOW TO START 4) .... the ldap schema is the same ++ ++2) convert the group requests to the appropriate LDAP requests ++ ++HOW TO SOLVE PROBLEMS ++ ++1) use debug in sshd ++ * /usr/sbin/sshd -d -d -d -d ++2) use debug in ssh-ldap-helper ++ * ssh-ldap-helper -d -d -d -d -s ++3) use tcpdump ... other ldap client etc. ++ ++ADVANTAGES ++ ++1) Blocking an user account can be done directly from LDAP (if sshd is using PubkeyAuthentication + AuthorizedKeysCommand with ldap only). ++ ++DISADVANTAGES ++ ++1) LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP ++ allows write to users dn, somebody could replace some user's public key by his own and impersonate some ++ of your users in all your server farm -- be VERY CAREFUL. ++2) With incomplete PKI the MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login ++ as the impersonated user. ++3) If LDAP server is down there may be no fallback on passwd auth. ++ ++MISC. ++ ++1) todo ++ * Possibility to reuse the ssh-ldap-helper. ++ * Tune the LDAP part to accept all possible LDAP configurations. ++ ++2) differences from original lpk ++ * No LDAP code in sshd. ++ * Support for various LDAP platforms and configurations. ++ * LDAP is configured in separate ldap.conf file. ++ ++3) docs/link ++ * http://pacsec.jp/core05/psj05-barisani-en.pdf ++ * http://fritz.potsdam.edu/projects/openssh-lpk/ ++ * http://fritz.potsdam.edu/projects/sshgate/ ++ * http://dev.inversepath.com/trac/openssh-lpk ++ * http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm ) ++ ++4) contributors/ideas/greets ++ - Eric AUGE ++ - Andrea Barisani ++ - Falk Siemonsmeier. ++ - Jacob Rief. ++ - Michael Durchgraf. ++ - frederic peters. ++ - Finlay dobbie. ++ - Stefan Fisher. ++ - Robin H. Johnson. ++ - Adrian Bridgett. ++ ++5) Author ++ Jan F. Chadima ++ +diff -up openssh-6.2p1/ldapbody.c.ldap openssh-6.2p1/ldapbody.c +--- openssh-6.2p1/ldapbody.c.ldap 2013-03-25 21:27:15.889248078 +0100 ++++ openssh-6.2p1/ldapbody.c 2013-03-25 21:27:15.889248078 +0100 +@@ -0,0 +1,494 @@ ++/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "log.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapmisc.h" ++#include "ldapbody.h" ++#include ++#include ++ ++#define LDAPSEARCH_FORMAT "(&(objectclass=%s)(objectclass=ldapPublicKey)(uid=%s)%s)" ++#define PUBKEYATTR "sshPublicKey" ++#define LDAP_LOGFILE "%s/ldap.%d" ++ ++static FILE *logfile = NULL; ++static LDAP *ld; ++ ++static char *attrs[] = { ++ PUBKEYATTR, ++ NULL ++}; ++ ++void ++ldap_checkconfig (void) ++{ ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.host == NULL && options.uri == NULL) ++#else ++ if (options.host == NULL) ++#endif ++ fatal ("missing \"host\" in config file"); ++} ++ ++#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) ++static int ++_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid) ++{ ++ struct timeval timeout; ++ int rc; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ LDAPMessage *result; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug2 ("Doing LDAP rebind to %s", options.binddn); ++ if (options.ssl == SSL_START_TLS) { ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) { ++ error ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ } ++ ++#if !defined(HAVE_LDAP_PARSE_RESULT) || !defined(HAVE_LDAP_CONTROLS_FREE) ++ return ldap_simple_bind_s (ld, options.binddn, options.bindpw); ++#else ++ if (ldap_simple_bind(ld, options.binddn, options.bindpw) < 0) ++ fatal ("ldap_simple_bind %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ result = NULL; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ error ("ldap_result %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ldap_msgfree (result); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ debug3 ("LDAP rebind to %s succesfull", options.binddn); ++ return rc; ++#endif ++} ++#else ++ ++static int ++_rebind_proc (LDAP * ld, char **whop, char **credp, int *methodp, int freeit) ++{ ++ if (freeit) ++ return LDAP_SUCCESS; ++ ++ *whop = strdup (options.binddn); ++ *credp = strdup (options.bindpw); ++ *methodp = LDAP_AUTH_SIMPLE; ++ debug2 ("Doing LDAP rebind for %s", *whop); ++ return LDAP_SUCCESS; ++} ++#endif ++ ++void ++ldap_do_connect(void) ++{ ++ int rc, msgid, ld_errno = 0; ++ struct timeval timeout; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ int parserc; ++ LDAPMessage *result; ++ LDAPControl **controls; ++ int reconnect = 0; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug ("LDAP do connect"); ++ ++retry: ++ if (reconnect) { ++ debug3 ("Reconnecting with ld_errno %d", ld_errno); ++ if (options.bind_policy == 0 || ++ (ld_errno != LDAP_SERVER_DOWN && ld_errno != LDAP_TIMEOUT) || ++ reconnect > 5) ++ fatal ("Cannot connect to LDAP server"); ++ ++ if (reconnect > 1) ++ sleep (reconnect - 1); ++ ++ if (ld != NULL) { ++ ldap_unbind (ld); ++ ld = NULL; ++ } ++ logit("reconnecting to LDAP server..."); ++ } ++ ++ if (ld == NULL) { ++ int rc; ++ struct timeval tv; ++ ++#ifdef HAVE_LDAP_SET_OPTION ++ if (options.debug > 0) { ++#ifdef LBER_OPT_LOG_PRINT_FILE ++ if (options.logdir) { ++ char *logfilename; ++ int logfilenamelen; ++ ++ logfilenamelen = strlen (LDAP_LOGFILE) + strlen ("000000") + strlen (options.logdir); ++ logfilename = xmalloc (logfilenamelen); ++ snprintf (logfilename, logfilenamelen, LDAP_LOGFILE, options.logdir, (int) getpid ()); ++ logfilename[logfilenamelen - 1] = 0; ++ if ((logfile = fopen (logfilename, "a")) == NULL) ++ fatal ("cannot append to %s: %s", logfilename, strerror (errno)); ++ debug3 ("LDAP debug into %s", logfilename); ++ free (logfilename); ++ ber_set_option (NULL, LBER_OPT_LOG_PRINT_FILE, logfile); ++ } ++#endif ++ if (options.debug) { ++#ifdef LBER_OPT_DEBUG_LEVEL ++ ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LBER_OPT_DEBUG_LEVEL */ ++#ifdef LDAP_OPT_DEBUG_LEVEL ++ (void) ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LDAP_OPT_DEBUG_LEVEL */ ++ debug3 ("Set LDAP debug to %d", options.debug); ++ } ++ } ++#endif /* HAVE_LDAP_SET_OPTION */ ++ ++ ld = NULL; ++#ifdef HAVE_LDAPSSL_INIT ++ if (options.host != NULL) { ++ if (options.ssl_on == SSL_LDAPS) { ++ if ((rc = ldapssl_client_init (options.sslpath, NULL)) != LDAP_SUCCESS) ++ fatal ("ldapssl_client_init %s", ldap_err2string (rc)); ++ debug3 ("LDAPssl client init"); ++ } ++ ++ if (options.ssl_on != SSL_OFF) { ++ if ((ld = ldapssl_init (options.host, options.port, TRUE)) == NULL) ++ fatal ("ldapssl_init failed"); ++ debug3 ("LDAPssl init"); ++ } ++ } ++#endif /* HAVE_LDAPSSL_INIT */ ++ ++ /* continue with opening */ ++ if (ld == NULL) { ++#if defined (HAVE_LDAP_START_TLS_S) || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) ++ /* Some global TLS-specific options need to be set before we create our ++ * session context, so we set them here. */ ++ ++#ifdef LDAP_OPT_X_TLS_RANDOM_FILE ++ /* rand file */ ++ if (options.tls_randfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, ++ options.tls_randfile)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS random file %s", options.tls_randfile); ++ } ++#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ ++ ++ /* ca cert file */ ++ if (options.tls_cacertfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, ++ options.tls_cacertfile)) != LDAP_SUCCESS) ++ error ("ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert file %s ", options.tls_cacertfile); ++ } ++ ++ /* ca cert directory */ ++ if (options.tls_cacertdir != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, ++ options.tls_cacertdir)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert dir %s ", options.tls_cacertdir); ++ } ++ ++ /* require cert? */ ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, ++ &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS check peer to %d ", options.tls_checkpeer); ++ ++ /* set cipher suite, certificate and private key: */ ++ if (options.tls_ciphers != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, ++ options.tls_ciphers)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS ciphers to %s ", options.tls_ciphers); ++ } ++ ++ /* cert file */ ++ if (options.tls_cert != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, ++ options.tls_cert)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS cert file %s ", options.tls_cert); ++ } ++ ++ /* key file */ ++ if (options.tls_key != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, ++ options.tls_key)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_KEYFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS key file %s ", options.tls_key); ++ } ++#endif ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.uri != NULL) { ++ if ((rc = ldap_initialize (&ld, options.uri)) != LDAP_SUCCESS) ++ fatal ("ldap_initialize %s", ldap_err2string (rc)); ++ debug3 ("LDAP initialize %s", options.uri); ++ } ++ } ++#endif /* HAVE_LDAP_INTITIALIZE */ ++ ++ /* continue with opening */ ++ if ((ld == NULL) && (options.host != NULL)) { ++#ifdef HAVE_LDAP_INIT ++ if ((ld = ldap_init (options.host, options.port)) == NULL) ++ fatal ("ldap_init failed"); ++ debug3 ("LDAP init %s:%d", options.host, options.port); ++#else ++ if ((ld = ldap_open (options.host, options.port)) == NULL) ++ fatal ("ldap_open failed"); ++ debug3 ("LDAP open %s:%d", options.host, options.port); ++#endif /* HAVE_LDAP_INIT */ ++ } ++ ++ if (ld == NULL) ++ fatal ("no way to open ldap"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) ++ if (options.ssl == SSL_LDAPS) { ++ if ((rc = ldap_set_option (ld, LDAP_OPT_X_TLS, &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS) %s", ldap_err2string (rc)); ++ debug3 ("LDAP set LDAP_OPT_X_TLS_%d", options.tls_checkpeer); ++ } ++#endif /* LDAP_OPT_X_TLS */ ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &options.ldap_version); ++#else ++ ld->ld_version = options.ldap_version; ++#endif ++ debug3 ("LDAP set version to %d", options.ldap_version); ++ ++#if LDAP_SET_REBIND_PROC_ARGS == 3 ++ ldap_set_rebind_proc (ld, _rebind_proc, NULL); ++#elif LDAP_SET_REBIND_PROC_ARGS == 2 ++ ldap_set_rebind_proc (ld, _rebind_proc); ++#else ++#warning unknown LDAP_SET_REBIND_PROC_ARGS ++#endif ++ debug3 ("LDAP set rebind proc"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_DEREF) ++ (void) ldap_set_option (ld, LDAP_OPT_DEREF, &options.deref); ++#else ++ ld->ld_deref = options.deref; ++#endif ++ debug3 ("LDAP set deref to %d", options.deref); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_TIMELIMIT) ++ (void) ldap_set_option (ld, LDAP_OPT_TIMELIMIT, ++ &options.timelimit); ++#else ++ ld->ld_timelimit = options.timelimit; ++#endif ++ debug3 ("LDAP set timelimit to %d", options.timelimit); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_X_OPT_CONNECT_TIMEOUT) ++ /* ++ * This is a new option in the Netscape SDK which sets ++ * the TCP connect timeout. For want of a better value, ++ * we use the bind_timelimit to control this. ++ */ ++ timeout = options.bind_timelimit * 1000; ++ (void) ldap_set_option (ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout); ++ debug3 ("LDAP set opt connect timeout to %d", timeout); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) ++ tv.tv_sec = options.bind_timelimit; ++ tv.tv_usec = 0; ++ (void) ldap_set_option (ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); ++ debug3 ("LDAP set opt network timeout to %ld.0", tv.tv_sec); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_REFERRALS) ++ (void) ldap_set_option (ld, LDAP_OPT_REFERRALS, ++ options.referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set referrals to %d", options.referrals); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_RESTART) ++ (void) ldap_set_option (ld, LDAP_OPT_RESTART, ++ options.restart ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set restart to %d", options.restart); ++#endif ++ ++#ifdef HAVE_LDAP_START_TLS_S ++ if (options.ssl == SSL_START_TLS) { ++ int version; ++ ++ if (ldap_get_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version) ++ == LDAP_SUCCESS) { ++ if (version < LDAP_VERSION3) { ++ version = LDAP_VERSION3; ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &version); ++ debug3 ("LDAP set version to %d", version); ++ } ++ } ++ ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ debug3 ("LDAP start TLS"); ++ } ++#endif /* HAVE_LDAP_START_TLS_S */ ++ } ++ ++ if ((msgid = ldap_simple_bind (ld, options.binddn, ++ options.bindpw)) == -1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_simple_bind %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP simple bind (%s)", options.binddn); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_result %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP result in time"); ++ ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ controls = NULL; ++ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, TRUE)) != LDAP_SUCCESS) ++ fatal ("ldap_parse_result %s", ldap_err2string (parserc)); ++ debug3 ("LDAP parse result OK"); ++ ++ if (controls != NULL) { ++ ldap_controls_free (controls); ++ } ++#else ++ rc = ldap_result2error (session->ld, result, TRUE); ++#endif ++ if (rc != LDAP_SUCCESS) ++ fatal ("error trying to bind as user \"%s\" (%s)", ++ options.binddn, ldap_err2string (rc)); ++ ++ debug2 ("LDAP do connect OK"); ++} ++ ++void ++process_user (const char *user, FILE *output) ++{ ++ LDAPMessage *res, *e; ++ char *buffer; ++ int bufflen, rc, i; ++ struct timeval timeout; ++ ++ debug ("LDAP process user"); ++ ++ /* quick check for attempts to be evil */ ++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || ++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) { ++ logit ("illegal user name %s not processed", user); ++ return; ++ } ++ ++ /* build filter for LDAP request */ ++ bufflen = strlen (LDAPSEARCH_FORMAT) + strlen(options.account_class) + strlen (user); ++ if (options.ssh_filter != NULL) ++ bufflen += strlen (options.ssh_filter); ++ buffer = xmalloc (bufflen); ++ snprintf(buffer, bufflen, LDAPSEARCH_FORMAT, options.account_class, user, (options.ssh_filter != NULL) ? options.ssh_filter : NULL); ++ buffer[bufflen - 1] = 0; ++ ++ debug3 ("LDAP search scope = %d %s", options.scope, buffer); ++ ++ timeout.tv_sec = options.timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_search_st(ld, options.base, options.scope, buffer, attrs, 0, &timeout, &res)) != LDAP_SUCCESS) { ++ error ("ldap_search_st(): %s", ldap_err2string (rc)); ++ free (buffer); ++ return; ++ } ++ ++ /* free */ ++ free (buffer); ++ ++ for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) { ++ int num; ++ struct berval **keys; ++ ++ keys = ldap_get_values_len(ld, e, PUBKEYATTR); ++ num = ldap_count_values_len(keys); ++ for (i = 0 ; i < num ; i++) { ++ char *cp; //, *options = NULL; ++ ++ for (cp = keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++); ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ /* We have found the desired key. */ ++ fprintf (output, "%s\n", keys[i]->bv_val); ++ } ++ ++ ldap_value_free_len(keys); ++ } ++ ++ ldap_msgfree(res); ++ debug2 ("LDAP process user finished"); ++} ++ ++void ++ldap_do_close(void) ++{ ++ int rc; ++ ++ debug ("LDAP do close"); ++ if ((rc = ldap_unbind_ext(ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_unbind_ext: %s", ++ ldap_err2string (rc)); ++ ++ ld = NULL; ++ debug2 ("LDAP do close OK"); ++ return; ++} ++ +diff -up openssh-6.2p1/ldapbody.h.ldap openssh-6.2p1/ldapbody.h +--- openssh-6.2p1/ldapbody.h.ldap 2013-03-25 21:27:15.889248078 +0100 ++++ openssh-6.2p1/ldapbody.h 2013-03-25 21:27:15.889248078 +0100 +@@ -0,0 +1,37 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPBODY_H ++#define LDAPBODY_H ++ ++#include ++ ++void ldap_checkconfig(void); ++void ldap_do_connect(void); ++void process_user(const char *, FILE *); ++void ldap_do_close(void); ++ ++#endif /* LDAPBODY_H */ ++ +diff -up openssh-6.2p2/ldapconf.c.ldap openssh-6.2p2/ldapconf.c +--- openssh-6.2p2/ldapconf.c.ldap 2013-06-07 15:10:05.601942693 +0200 ++++ openssh-6.2p2/ldapconf.c 2013-06-07 15:10:24.928857566 +0200 +@@ -0,0 +1,691 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "ldap-helper.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include ++#include ++ ++/* Keyword tokens. */ ++ ++typedef enum { ++ lBadOption, ++ lHost, lURI, lBase, lBindDN, lBindPW, lRootBindDN, ++ lScope, lDeref, lPort, lTimeLimit, lBind_TimeLimit, ++ lLdap_Version, lBind_Policy, lSSLPath, lSSL, lReferrals, ++ lRestart, lTLS_CheckPeer, lTLS_CaCertFile, ++ lTLS_CaCertDir, lTLS_Ciphers, lTLS_Cert, lTLS_Key, ++ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter, ++ lAccountClass, lDeprecated, lUnsupported ++} OpCodes; ++ ++/* Textual representations of the tokens. */ ++ ++static struct { ++ const char *name; ++ OpCodes opcode; ++} keywords[] = { ++ { "URI", lURI }, ++ { "Base", lBase }, ++ { "BindDN", lBindDN }, ++ { "BindPW", lBindPW }, ++ { "RootBindDN", lRootBindDN }, ++ { "Host", lHost }, ++ { "Port", lPort }, ++ { "Scope", lScope }, ++ { "Deref", lDeref }, ++ { "TimeLimit", lTimeLimit }, ++ { "TimeOut", lTimeLimit }, ++ { "Bind_Timelimit", lBind_TimeLimit }, ++ { "Network_TimeOut", lBind_TimeLimit }, ++/* ++ * Todo ++ * SIZELIMIT ++ */ ++ { "Ldap_Version", lLdap_Version }, ++ { "Version", lLdap_Version }, ++ { "Bind_Policy", lBind_Policy }, ++ { "SSLPath", lSSLPath }, ++ { "SSL", lSSL }, ++ { "Referrals", lReferrals }, ++ { "Restart", lRestart }, ++ { "TLS_CheckPeer", lTLS_CheckPeer }, ++ { "TLS_ReqCert", lTLS_CheckPeer }, ++ { "TLS_CaCertFile", lTLS_CaCertFile }, ++ { "TLS_CaCert", lTLS_CaCertFile }, ++ { "TLS_CaCertDir", lTLS_CaCertDir }, ++ { "TLS_Ciphers", lTLS_Ciphers }, ++ { "TLS_Cipher_Suite", lTLS_Ciphers }, ++ { "TLS_Cert", lTLS_Cert }, ++ { "TLS_Certificate", lTLS_Cert }, ++ { "TLS_Key", lTLS_Key }, ++ { "TLS_RandFile", lTLS_RandFile }, ++/* ++ * Todo ++ * TLS_CRLCHECK ++ * TLS_CRLFILE ++ */ ++ { "LogDir", lLogDir }, ++ { "Debug", lDebug }, ++ { "SSH_Filter", lSSH_Filter }, ++ { "AccountClass", lAccountClass }, ++ { NULL, lBadOption } ++}; ++ ++/* Configuration ptions. */ ++ ++Options options; ++ ++/* ++ * Returns the number of the token pointed to by cp or oBadOption. ++ */ ++ ++static OpCodes ++parse_token(const char *cp, const char *filename, int linenum) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name; i++) ++ if (strcasecmp(cp, keywords[i].name) == 0) ++ return keywords[i].opcode; ++ ++ if (config_warning_config_file) ++ logit("%s: line %d: Bad configuration option: %s", ++ filename, linenum, cp); ++ return lBadOption; ++} ++ ++/* ++ * Processes a single option line as used in the configuration files. This ++ * only sets those values that have not already been set. ++ */ ++#define WHITESPACE " \t\r\n" ++ ++static int ++process_config_line(char *line, const char *filename, int linenum) ++{ ++ char *s, **charptr, **xstringptr, *endofnumber, *keyword, *arg; ++ char *rootbinddn = NULL; ++ int opcode, *intptr, value; ++ size_t len; ++ ++ /* Strip trailing whitespace */ ++ for (len = strlen(line) - 1; len > 0; len--) { ++ if (strchr(WHITESPACE, line[len]) == NULL) ++ break; ++ line[len] = '\0'; ++ } ++ ++ s = line; ++ /* Get the keyword. (Each line is supposed to begin with a keyword). */ ++ if ((keyword = strdelim(&s)) == NULL) ++ return 0; ++ /* Ignore leading whitespace. */ ++ if (*keyword == '\0') ++ keyword = strdelim(&s); ++ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') ++ return 0; ++ ++ opcode = parse_token(keyword, filename, linenum); ++ ++ switch (opcode) { ++ case lBadOption: ++ /* don't panic, but count bad options */ ++ return -1; ++ /* NOTREACHED */ ++ ++ case lHost: ++ xstringptr = &options.host; ++parse_xstring: ++ if (!s || *s == '\0') ++ fatal("%s line %d: missing dn",filename,linenum); ++ if (*xstringptr == NULL) ++ *xstringptr = xstrdup(s); ++ return 0; ++ ++ case lURI: ++ xstringptr = &options.uri; ++ goto parse_xstring; ++ ++ case lBase: ++ xstringptr = &options.base; ++ goto parse_xstring; ++ ++ case lBindDN: ++ xstringptr = &options.binddn; ++ goto parse_xstring; ++ ++ case lBindPW: ++ charptr = &options.bindpw; ++parse_string: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case lRootBindDN: ++ xstringptr = &rootbinddn; ++ goto parse_xstring; ++ ++ case lScope: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing sub/one/base argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp (arg, "sub") == 0 || strcasecmp (arg, "subtree") == 0) ++ value = LDAP_SCOPE_SUBTREE; ++ else if (strcasecmp (arg, "one") == 0) ++ value = LDAP_SCOPE_ONELEVEL; ++ else if (strcasecmp (arg, "base") == 0) ++ value = LDAP_SCOPE_BASE; ++ else ++ fatal("%.200s line %d: Bad sub/one/base argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lDeref: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/searching/finding/always argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (!strcasecmp (arg, "never")) ++ value = LDAP_DEREF_NEVER; ++ else if (!strcasecmp (arg, "searching")) ++ value = LDAP_DEREF_SEARCHING; ++ else if (!strcasecmp (arg, "finding")) ++ value = LDAP_DEREF_FINDING; ++ else if (!strcasecmp (arg, "always")) ++ value = LDAP_DEREF_ALWAYS; ++ else ++ fatal("%.200s line %d: Bad never/searching/finding/always argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lPort: ++ intptr = &options.port; ++parse_int: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ ++ /* Octal, decimal, or hex format? */ ++ value = strtol(arg, &endofnumber, 0); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lTimeLimit: ++ intptr = &options.timelimit; ++parse_time: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing time value.", ++ filename, linenum); ++ if ((value = convtime(arg)) == -1) ++ fatal("%s line %d: invalid time value.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lBind_TimeLimit: ++ intptr = &options.bind_timelimit; ++ goto parse_time; ++ ++ case lLdap_Version: ++ intptr = &options.ldap_version; ++ goto parse_int; ++ ++ case lBind_Policy: ++ intptr = &options.bind_policy; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing soft/hard argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "hard") == 0 || strcasecmp(arg, "hard_open") == 0 || strcasecmp(arg, "hard_init") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "soft") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad soft/hard argument.", filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lSSLPath: ++ charptr = &options.sslpath; ++ goto parse_string; ++ ++ case lSSL: ++ intptr = &options.ssl; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no/start_tls argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) ++ value = SSL_LDAPS; ++ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) ++ value = SSL_OFF; ++ else if (!strcasecmp (arg, "start_tls")) ++ value = SSL_START_TLS; ++ else ++ fatal("%.200s line %d: Bad yes/no/start_tls argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lReferrals: ++ intptr = &options.referrals; ++parse_flag: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lRestart: ++ intptr = &options.restart; ++ goto parse_flag; ++ ++ case lTLS_CheckPeer: ++ intptr = &options.tls_checkpeer; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/hard/demand/alow/try argument.", filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "never") == 0 || strcasecmp(arg, "no") == 0 || strcasecmp(arg, "false") == 0 || strcasecmp(arg, "off") == 0) ++ value = LDAP_OPT_X_TLS_NEVER; ++ else if (strcasecmp(arg, "hard") == 0 || strcasecmp(arg, "yes") == 0 || strcasecmp(arg, "true") == 0 || strcasecmp(arg, "on") == 0) ++ value = LDAP_OPT_X_TLS_HARD; ++ else if (strcasecmp(arg, "demand") == 0) ++ value = LDAP_OPT_X_TLS_DEMAND; ++ else if (strcasecmp(arg, "allow") == 0) ++ value = LDAP_OPT_X_TLS_ALLOW; ++ else if (strcasecmp(arg, "try") == 0) ++ value = LDAP_OPT_X_TLS_TRY; ++ else ++ fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lTLS_CaCertFile: ++ charptr = &options.tls_cacertfile; ++ goto parse_string; ++ ++ case lTLS_CaCertDir: ++ charptr = &options.tls_cacertdir; ++ goto parse_string; ++ ++ case lTLS_Ciphers: ++ xstringptr = &options.tls_ciphers; ++ goto parse_xstring; ++ ++ case lTLS_Cert: ++ charptr = &options.tls_cert; ++ goto parse_string; ++ ++ case lTLS_Key: ++ charptr = &options.tls_key; ++ goto parse_string; ++ ++ case lTLS_RandFile: ++ charptr = &options.tls_randfile; ++ goto parse_string; ++ ++ case lLogDir: ++ charptr = &options.logdir; ++ goto parse_string; ++ ++ case lDebug: ++ intptr = &options.debug; ++ goto parse_int; ++ ++ case lSSH_Filter: ++ xstringptr = &options.ssh_filter; ++ goto parse_xstring; ++ ++ case lAccountClass: ++ charptr = &options.account_class; ++ goto parse_string; ++ ++ case lDeprecated: ++ debug("%s line %d: Deprecated option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ case lUnsupported: ++ error("%s line %d: Unsupported option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ default: ++ fatal("process_config_line: Unimplemented opcode %d", opcode); ++ } ++ ++ /* Check that there is no garbage at end of line. */ ++ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ fatal("%.200s line %d: garbage at end of line; \"%.200s\".", ++ filename, linenum, arg); ++ } ++ return 0; ++} ++ ++/* ++ * Reads the config file and modifies the options accordingly. Options ++ * should already be initialized before this call. This never returns if ++ * there is an error. If the file does not exist, this returns 0. ++ */ ++ ++void ++read_config_file(const char *filename) ++{ ++ FILE *f; ++ char line[1024]; ++ int active, linenum; ++ int bad_options = 0; ++ struct stat sb; ++ ++ if ((f = fopen(filename, "r")) == NULL) ++ fatal("fopen %s: %s", filename, strerror(errno)); ++ ++ if (fstat(fileno(f), &sb) == -1) ++ fatal("fstat %s: %s", filename, strerror(errno)); ++ if (((sb.st_uid != 0 && sb.st_uid != getuid()) || ++ (sb.st_mode & 022) != 0)) ++ fatal("Bad owner or permissions on %s", filename); ++ ++ debug("Reading configuration data %.200s", filename); ++ ++ /* ++ * Mark that we are now processing the options. This flag is turned ++ * on/off by Host specifications. ++ */ ++ active = 1; ++ linenum = 0; ++ while (fgets(line, sizeof(line), f)) { ++ /* Update line number counter. */ ++ linenum++; ++ if (process_config_line(line, filename, linenum) != 0) ++ bad_options++; ++ } ++ fclose(f); ++ if ((bad_options > 0) && config_exclusive_config_file) ++ fatal("%s: terminating, %d bad configuration options", ++ filename, bad_options); ++} ++ ++/* ++ * Initializes options to special values that indicate that they have not yet ++ * been set. Read_config_file will only set options with this value. Options ++ * are processed in the following order: command line, user config file, ++ * system config file. Last, fill_default_options is called. ++ */ ++ ++void ++initialize_options(void) ++{ ++ memset(&options, 'X', sizeof(options)); ++ options.host = NULL; ++ options.uri = NULL; ++ options.base = NULL; ++ options.binddn = NULL; ++ options.bindpw = NULL; ++ options.scope = -1; ++ options.deref = -1; ++ options.port = -1; ++ options.timelimit = -1; ++ options.bind_timelimit = -1; ++ options.ldap_version = -1; ++ options.bind_policy = -1; ++ options.sslpath = NULL; ++ options.ssl = -1; ++ options.referrals = -1; ++ options.restart = -1; ++ options.tls_checkpeer = -1; ++ options.tls_cacertfile = NULL; ++ options.tls_cacertdir = NULL; ++ options.tls_ciphers = NULL; ++ options.tls_cert = NULL; ++ options.tls_key = NULL; ++ options.tls_randfile = NULL; ++ options.logdir = NULL; ++ options.debug = -1; ++ options.ssh_filter = NULL; ++ options.account_class = NULL; ++} ++ ++/* ++ * Called after processing other sources of option data, this fills those ++ * options for which no value has been specified with their default values. ++ */ ++ ++void ++fill_default_options(void) ++{ ++ if (options.uri != NULL) { ++ LDAPURLDesc *ludp; ++ ++ if (ldap_url_parse(options.uri, &ludp) == LDAP_SUCCESS) { ++ if (options.ssl == -1) { ++ if (strcmp (ludp->lud_scheme, "ldap") == 0) ++ options.ssl = 2; ++ if (strcmp (ludp->lud_scheme, "ldapi") == 0) ++ options.ssl = 0; ++ else if (strcmp (ludp->lud_scheme, "ldaps") == 0) ++ options.ssl = 1; ++ } ++ if (options.host == NULL) ++ options.host = xstrdup (ludp->lud_host); ++ if (options.port == -1) ++ options.port = ludp->lud_port; ++ ++ ldap_free_urldesc (ludp); ++ } ++ } ++ if (options.ssl == -1) ++ options.ssl = SSL_START_TLS; ++ if (options.port == -1) ++ options.port = (options.ssl == 0) ? 389 : 636; ++ if (options.uri == NULL) { ++ int len; ++#define MAXURILEN 4096 ++ ++ options.uri = xmalloc (MAXURILEN); ++ len = snprintf (options.uri, MAXURILEN, "ldap%s://%s:%d", ++ (options.ssl == 0) ? "" : "s", options.host, options.port); ++ options.uri[MAXURILEN - 1] = 0; ++ options.uri = xrealloc (options.uri, len + 1, 1); ++ } ++ if (options.binddn == NULL) ++ options.binddn = ""; ++ if (options.bindpw == NULL) ++ options.bindpw = ""; ++ if (options.scope == -1) ++ options.scope = LDAP_SCOPE_SUBTREE; ++ if (options.deref == -1) ++ options.deref = LDAP_DEREF_NEVER; ++ if (options.timelimit == -1) ++ options.timelimit = 10; ++ if (options.bind_timelimit == -1) ++ options.bind_timelimit = 10; ++ if (options.ldap_version == -1) ++ options.ldap_version = 3; ++ if (options.bind_policy == -1) ++ options.bind_policy = 1; ++ if (options.referrals == -1) ++ options.referrals = 1; ++ if (options.restart == -1) ++ options.restart = 1; ++ if (options.tls_checkpeer == -1) ++ options.tls_checkpeer = LDAP_OPT_X_TLS_HARD; ++ if (options.debug == -1) ++ options.debug = 0; ++ if (options.ssh_filter == NULL) ++ options.ssh_filter = ""; ++ if (options.account_class == NULL) ++ options.account_class = "posixAccount"; ++} ++ ++static const char * ++lookup_opcode_name(OpCodes code) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name != NULL; i++) ++ if (keywords[i].opcode == code) ++ return(keywords[i].name); ++ return "UNKNOWN"; ++} ++ ++static void ++dump_cfg_string(OpCodes code, const char *val) ++{ ++ if (val == NULL) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %s", lookup_opcode_name(code), val); ++} ++ ++static void ++dump_cfg_int(OpCodes code, int val) ++{ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %d", lookup_opcode_name(code), val); ++} ++ ++struct names { ++ int value; ++ char *name; ++}; ++ ++static void ++dump_cfg_namedint(OpCodes code, int val, struct names *names) ++{ ++ u_int i; ++ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else { ++ for (i = 0; names[i].value != -1; i++) ++ if (names[i].value == val) { ++ debug3("%s %s", lookup_opcode_name(code), names[i].name); ++ return; ++ } ++ debug3("%s unknown: %d", lookup_opcode_name(code), val); ++ } ++} ++ ++static struct names _yesnotls[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { 2, "Start_TLS" }, ++ { -1, NULL }}; ++ ++static struct names _scope[] = { ++ { LDAP_SCOPE_BASE, "Base" }, ++ { LDAP_SCOPE_ONELEVEL, "One" }, ++ { LDAP_SCOPE_SUBTREE, "Sub"}, ++ { -1, NULL }}; ++ ++static struct names _deref[] = { ++ { LDAP_DEREF_NEVER, "Never" }, ++ { LDAP_DEREF_SEARCHING, "Searching" }, ++ { LDAP_DEREF_FINDING, "Finding" }, ++ { LDAP_DEREF_ALWAYS, "Always" }, ++ { -1, NULL }}; ++ ++static struct names _yesno[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { -1, NULL }}; ++ ++static struct names _bindpolicy[] = { ++ { 0, "Soft" }, ++ { 1, "Hard" }, ++ { -1, NULL }}; ++ ++static struct names _checkpeer[] = { ++ { LDAP_OPT_X_TLS_NEVER, "Never" }, ++ { LDAP_OPT_X_TLS_HARD, "Hard" }, ++ { LDAP_OPT_X_TLS_DEMAND, "Demand" }, ++ { LDAP_OPT_X_TLS_ALLOW, "Allow" }, ++ { LDAP_OPT_X_TLS_TRY, "TRY" }, ++ { -1, NULL }}; ++ ++void ++dump_config(void) ++{ ++ dump_cfg_string(lURI, options.uri); ++ dump_cfg_string(lHost, options.host); ++ dump_cfg_int(lPort, options.port); ++ dump_cfg_namedint(lSSL, options.ssl, _yesnotls); ++ dump_cfg_int(lLdap_Version, options.ldap_version); ++ dump_cfg_int(lTimeLimit, options.timelimit); ++ dump_cfg_int(lBind_TimeLimit, options.bind_timelimit); ++ dump_cfg_string(lBase, options.base); ++ dump_cfg_string(lBindDN, options.binddn); ++ dump_cfg_string(lBindPW, options.bindpw); ++ dump_cfg_namedint(lScope, options.scope, _scope); ++ dump_cfg_namedint(lDeref, options.deref, _deref); ++ dump_cfg_namedint(lReferrals, options.referrals, _yesno); ++ dump_cfg_namedint(lRestart, options.restart, _yesno); ++ dump_cfg_namedint(lBind_Policy, options.bind_policy, _bindpolicy); ++ dump_cfg_string(lSSLPath, options.sslpath); ++ dump_cfg_namedint(lTLS_CheckPeer, options.tls_checkpeer, _checkpeer); ++ dump_cfg_string(lTLS_CaCertFile, options.tls_cacertfile); ++ dump_cfg_string(lTLS_CaCertDir, options.tls_cacertdir); ++ dump_cfg_string(lTLS_Ciphers, options.tls_ciphers); ++ dump_cfg_string(lTLS_Cert, options.tls_cert); ++ dump_cfg_string(lTLS_Key, options.tls_key); ++ dump_cfg_string(lTLS_RandFile, options.tls_randfile); ++ dump_cfg_string(lLogDir, options.logdir); ++ dump_cfg_int(lDebug, options.debug); ++ dump_cfg_string(lSSH_Filter, options.ssh_filter); ++ dump_cfg_string(lAccountClass, options.logdir); ++} ++ +diff -up openssh-6.2p2/ldapconf.h.ldap openssh-6.2p2/ldapconf.h +--- openssh-6.2p2/ldapconf.h.ldap 2013-06-07 15:10:05.602942689 +0200 ++++ openssh-6.2p2/ldapconf.h 2013-06-07 15:10:24.928857566 +0200 +@@ -0,0 +1,72 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPCONF_H ++#define LDAPCONF_H ++ ++#define SSL_OFF 0 ++#define SSL_LDAPS 1 ++#define SSL_START_TLS 2 ++ ++/* Data structure for representing option data. */ ++ ++typedef struct { ++ char *host; ++ char *uri; ++ char *base; ++ char *binddn; ++ char *bindpw; ++ int scope; ++ int deref; ++ int port; ++ int timelimit; ++ int bind_timelimit; ++ int ldap_version; ++ int bind_policy; ++ char *sslpath; ++ int ssl; ++ int referrals; ++ int restart; ++ int tls_checkpeer; ++ char *tls_cacertfile; ++ char *tls_cacertdir; ++ char *tls_ciphers; ++ char *tls_cert; ++ char *tls_key; ++ char *tls_randfile; ++ char *logdir; ++ int debug; ++ char *ssh_filter; ++ char *account_class; ++} Options; ++ ++extern Options options; ++ ++void read_config_file(const char *); ++void initialize_options(void); ++void fill_default_options(void); ++void dump_config(void); ++ ++#endif /* LDAPCONF_H */ +diff -up openssh-6.2p1/ldap.conf.ldap openssh-6.2p1/ldap.conf +--- openssh-6.2p1/ldap.conf.ldap 2013-03-25 21:27:15.891248091 +0100 ++++ openssh-6.2p1/ldap.conf 2013-03-25 21:27:15.891248091 +0100 +@@ -0,0 +1,88 @@ ++# $Id: openssh-5.5p1-ldap.patch,v 1.3 2010/07/07 13:48:36 jfch2222 Exp $ ++# ++# This is the example configuration file for the OpenSSH ++# LDAP backend ++# ++# see ssh-ldap.conf(5) ++# ++ ++# URI with your LDAP server name. This allows to use ++# Unix Domain Sockets to connect to a local LDAP Server. ++#uri ldap://127.0.0.1/ ++#uri ldaps://127.0.0.1/ ++#uri ldapi://%2fvar%2frun%2fldapi_sock/ ++# Note: %2f encodes the '/' used as directory separator ++ ++# Another way to specify your LDAP server is to provide an ++# host name and the port of our LDAP server. Host name ++# must be resolvable without using LDAP. ++# Multiple hosts may be specified, each separated by a ++# space. How long nss_ldap takes to failover depends on ++# whether your LDAP client library supports configurable ++# network or connect timeouts (see bind_timelimit). ++#host 127.0.0.1 ++ ++# The port. ++# Optional: default is 389. ++#port 389 ++ ++# The distinguished name to bind to the server with. ++# Optional: default is to bind anonymously. ++#binddn cn=openssh_keys,dc=example,dc=org ++ ++# The credentials to bind with. ++# Optional: default is no credential. ++#bindpw TopSecret ++ ++# The distinguished name of the search base. ++#base dc=example,dc=org ++ ++# The LDAP version to use (defaults to 3 ++# if supported by client library) ++#ldap_version 3 ++ ++# The search scope. ++#scope sub ++#scope one ++#scope base ++ ++# Search timelimit ++#timelimit 30 ++ ++# Bind/connect timelimit ++#bind_timelimit 30 ++ ++# Reconnect policy: hard (default) will retry connecting to ++# the software with exponential backoff, soft will fail ++# immediately. ++#bind_policy hard ++ ++# SSL setup, may be implied by URI also. ++#ssl no ++#ssl on ++#ssl start_tls ++ ++# OpenLDAP SSL options ++# Require and verify server certificate (yes/no) ++# Default is to use libldap's default behavior, which can be configured in ++# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for ++# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes". ++#tls_checkpeer hard ++ ++# CA certificates for server certificate verification ++# At least one of these are required if tls_checkpeer is "yes" ++#tls_cacertfile /etc/ssl/ca.cert ++#tls_cacertdir /etc/pki/tls/certs ++ ++# Seed the PRNG if /dev/urandom is not provided ++#tls_randfile /var/run/egd-pool ++ ++# SSL cipher suite ++# See man ciphers for syntax ++#tls_ciphers TLSv1 ++ ++# Client certificate and key ++# Use these, if your server requires client authentication. ++#tls_cert ++#tls_key ++ +diff -up openssh-6.2p1/ldap-helper.c.ldap openssh-6.2p1/ldap-helper.c +--- openssh-6.2p1/ldap-helper.c.ldap 2013-03-25 21:27:15.892248097 +0100 ++++ openssh-6.2p1/ldap-helper.c 2013-03-25 21:27:15.892248097 +0100 +@@ -0,0 +1,155 @@ ++/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "ldapincludes.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapbody.h" ++#include ++#include ++ ++static int config_debug = 0; ++int config_exclusive_config_file = 0; ++static char *config_file_name = "/etc/ssh/ldap.conf"; ++static char *config_single_user = NULL; ++static int config_verbose = SYSLOG_LEVEL_VERBOSE; ++int config_warning_config_file = 0; ++extern char *__progname; ++ ++static void ++usage(void) ++{ ++ fprintf(stderr, "usage: %s [options]\n", ++ __progname); ++ fprintf(stderr, "Options:\n"); ++ fprintf(stderr, " -d Output the log messages to stderr.\n"); ++ fprintf(stderr, " -e Check the config file for unknown commands.\n"); ++ fprintf(stderr, " -f file Use alternate config file (default is /etc/ssh/ldap.conf).\n"); ++ fprintf(stderr, " -s user Do not demonize, send the user's key to stdout.\n"); ++ fprintf(stderr, " -v Increase verbosity of the debug output (implies -d).\n"); ++ fprintf(stderr, " -w Warn on unknown commands in the config file.\n"); ++ exit(1); ++} ++ ++/* ++ * Main program for the ssh pka ldap agent. ++ */ ++ ++int ++main(int ac, char **av) ++{ ++ int opt; ++ FILE *outfile = NULL; ++ ++ __progname = ssh_get_progname(av[0]); ++ ++ log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); ++ ++ /* ++ * Initialize option structure to indicate that no values have been ++ * set. ++ */ ++ initialize_options(); ++ ++ /* Parse command-line arguments. */ ++ while ((opt = getopt(ac, av, "def:s:vw")) != -1) { ++ switch (opt) { ++ case 'd': ++ config_debug = 1; ++ break; ++ ++ case 'e': ++ config_exclusive_config_file = 1; ++ config_warning_config_file = 1; ++ break; ++ ++ case 'f': ++ config_file_name = optarg; ++ break; ++ ++ case 's': ++ config_single_user = optarg; ++ outfile = fdopen (dup (fileno (stdout)), "w"); ++ break; ++ ++ case 'v': ++ config_debug = 1; ++ if (config_verbose < SYSLOG_LEVEL_DEBUG3) ++ config_verbose++; ++ break; ++ ++ case 'w': ++ config_warning_config_file = 1; ++ break; ++ ++ case '?': ++ default: ++ usage(); ++ break; ++ } ++ } ++ ++ /* Initialize loging */ ++ log_init(__progname, config_verbose, SYSLOG_FACILITY_AUTH, config_debug); ++ ++ if (ac != optind) ++ fatal ("illegal extra parameter %s", av[1]); ++ ++ /* Ensure that fds 0 and 2 are open or directed to /dev/null */ ++ if (config_debug == 0) ++ sanitise_stdfd(); ++ ++ /* Read config file */ ++ read_config_file(config_file_name); ++ fill_default_options(); ++ if (config_verbose == SYSLOG_LEVEL_DEBUG3) { ++ debug3 ("=== Configuration ==="); ++ dump_config(); ++ debug3 ("=== *** ==="); ++ } ++ ++ ldap_checkconfig(); ++ ldap_do_connect(); ++ ++ if (config_single_user) { ++ process_user (config_single_user, outfile); ++ } else { ++ usage(); ++ fatal ("Not yet implemented"); ++/* TODO ++ * open unix socket a run the loop on it ++ */ ++ } ++ ++ ldap_do_close(); ++ return 0; ++} ++ ++/* Ugly hack */ ++void *buffer_get_string(Buffer *b, u_int *l) { return NULL; } ++void buffer_put_string(Buffer *b, const void *f, u_int l) {} ++ +diff -up openssh-6.2p1/ldap-helper.h.ldap openssh-6.2p1/ldap-helper.h +--- openssh-6.2p1/ldap-helper.h.ldap 2013-03-25 21:27:15.892248097 +0100 ++++ openssh-6.2p1/ldap-helper.h 2013-03-25 21:27:15.892248097 +0100 +@@ -0,0 +1,32 @@ ++/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAP_HELPER_H ++#define LDAP_HELPER_H ++ ++extern int config_exclusive_config_file; ++extern int config_warning_config_file; ++ ++#endif /* LDAP_HELPER_H */ +diff -up openssh-6.2p1/ldapincludes.h.ldap openssh-6.2p1/ldapincludes.h +--- openssh-6.2p1/ldapincludes.h.ldap 2013-03-25 21:27:15.892248097 +0100 ++++ openssh-6.2p1/ldapincludes.h 2013-03-25 21:27:15.892248097 +0100 +@@ -0,0 +1,41 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPINCLUDES_H ++#define LDAPINCLUDES_H ++ ++#include "includes.h" ++ ++#ifdef HAVE_LBER_H ++#include ++#endif ++#ifdef HAVE_LDAP_H ++#include ++#endif ++#ifdef HAVE_LDAP_SSL_H ++#include ++#endif ++ ++#endif /* LDAPINCLUDES_H */ +diff -up openssh-6.2p1/ldapmisc.c.ldap openssh-6.2p1/ldapmisc.c +--- openssh-6.2p1/ldapmisc.c.ldap 2013-03-25 21:27:15.893248104 +0100 ++++ openssh-6.2p1/ldapmisc.c 2013-03-25 21:27:15.893248104 +0100 +@@ -0,0 +1,79 @@ ++ ++#include "ldapincludes.h" ++#include "ldapmisc.h" ++ ++#ifndef HAVE_LDAP_GET_LDERRNO ++int ++ldap_get_lderrno (LDAP * ld, char **m, char **s) ++{ ++#ifdef HAVE_LDAP_GET_OPTION ++ int rc; ++#endif ++ int lderrno; ++ ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ lderrno = ld->ld_errno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *s = ld->ld_error; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *m = ld->ld_matched; ++#endif ++ } ++ ++ return lderrno; ++} ++#endif ++ ++#ifndef HAVE_LDAP_SET_LDERRNO ++int ++ldap_set_lderrno (LDAP * ld, int lderrno, const char *m, const char *s) ++{ ++#ifdef HAVE_LDAP_SET_OPTION ++ int rc; ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_errno = lderrno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_error = s; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_matched = m; ++#endif ++ } ++ ++ return LDAP_SUCCESS; ++} ++#endif ++ +diff -up openssh-6.2p1/ldapmisc.h.ldap openssh-6.2p1/ldapmisc.h +--- openssh-6.2p1/ldapmisc.h.ldap 2013-03-25 21:27:15.893248104 +0100 ++++ openssh-6.2p1/ldapmisc.h 2013-03-25 21:27:15.893248104 +0100 +@@ -0,0 +1,35 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef LDAPMISC_H ++#define LDAPMISC_H ++ ++#include "ldapincludes.h" ++ ++int ldap_get_lderrno (LDAP *, char **, char **); ++int ldap_set_lderrno (LDAP *, int, const char *, const char *); ++ ++#endif /* LDAPMISC_H */ ++ +diff -up openssh-6.2p1/Makefile.in.ldap openssh-6.2p1/Makefile.in +--- openssh-6.2p1/Makefile.in.ldap 2013-03-25 21:27:15.850247822 +0100 ++++ openssh-6.2p1/Makefile.in 2013-03-25 21:27:57.356518817 +0100 +@@ -25,6 +25,8 @@ SSH_PROGRAM=@bindir@/ssh + ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass + SFTP_SERVER=$(libexecdir)/sftp-server + SSH_KEYSIGN=$(libexecdir)/ssh-keysign ++SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper ++SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ +@@ -60,8 +62,9 @@ XAUTH_PATH=@XAUTH_PATH@ + LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ + EXEEXT=@EXEEXT@ + MANFMT=@MANFMT@ ++INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) + + LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-aes.o \ +@@ -95,8 +98,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ + sandbox-seccomp-filter.o + +-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ++MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 + MANTYPE = @MANTYPE@ + + CONFIGFILES=sshd_config.out ssh_config.out moduli.out +@@ -164,6 +167,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss + ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + ++ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o ++ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) ++ + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o + $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + +@@ -266,6 +272,10 @@ install-files: + $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ ++ $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ ++ fi + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 +@@ -282,6 +292,10 @@ install-files: + $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 644 ssh-ldap-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 ; \ ++ $(INSTALL) -m 644 ssh-ldap.conf.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh-ldap.conf.5 ; \ ++ fi + -rm -f $(DESTDIR)$(bindir)/slogin + ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 +@@ -311,6 +325,13 @@ install-sysconf: + else \ + echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ + fi ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ if [ ! -f $(DESTDIR)$(sysconfdir)/ldap.conf ]; then \ ++ $(INSTALL) -m 644 ldap.conf $(DESTDIR)$(sysconfdir)/ldap.conf; \ ++ else \ ++ echo "$(DESTDIR)$(sysconfdir)/ldap.conf already exists, install will not overwrite"; \ ++ fi ; \ ++ fi + + host-key: ssh-keygen$(EXEEXT) + @if [ -z "$(DESTDIR)" ] ; then \ +@@ -368,6 +389,8 @@ uninstall: + -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) ++ -rm -f $(DESTDIR)$(SSH_LDAP_HELPER)$(EXEEXT) ++ -rm -f $(DESTDIR)$(SSH_LDAP_WRAPPER)$(EXEEXT) + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 +@@ -379,6 +402,7 @@ uninstall: + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 ++ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 + + regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c +diff -up openssh-6.2p1/openssh-lpk-openldap.schema.ldap openssh-6.2p1/openssh-lpk-openldap.schema +--- openssh-6.2p1/openssh-lpk-openldap.schema.ldap 2013-03-25 21:27:15.894248110 +0100 ++++ openssh-6.2p1/openssh-lpk-openldap.schema 2013-03-25 21:27:15.894248110 +0100 +@@ -0,0 +1,21 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# Author: Eric AUGE ++# ++# Based on the proposal of : Mark Ruijter ++# ++ ++ ++# octetString SYNTAX ++attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +diff -up openssh-6.2p1/openssh-lpk-sun.schema.ldap openssh-6.2p1/openssh-lpk-sun.schema +--- openssh-6.2p1/openssh-lpk-sun.schema.ldap 2013-03-25 21:27:15.894248110 +0100 ++++ openssh-6.2p1/openssh-lpk-sun.schema 2013-03-25 21:27:15.894248110 +0100 +@@ -0,0 +1,23 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# Author: Eric AUGE ++# ++# Schema for Sun Directory Server. ++# Based on the original schema, modified by Stefan Fischer. ++# ++ ++dn: cn=schema ++ ++# octetString SYNTAX ++attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +diff -up openssh-6.2p2/ssh-ldap.conf.5.ldap openssh-6.2p2/ssh-ldap.conf.5 +--- openssh-6.2p2/ssh-ldap.conf.5.ldap 2013-06-07 15:10:05.604942680 +0200 ++++ openssh-6.2p2/ssh-ldap.conf.5 2013-06-07 15:10:24.928857566 +0200 +@@ -0,0 +1,379 @@ ++.\" $OpenBSD: ssh-ldap.conf.5,v 1.1 2010/02/10 23:20:38 markus Exp $ ++.\" ++.\" Copyright (c) 2010 Jan F. Chadima. 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. ++.\" ++.Dd $Mdocdate: may 12 2010 $ ++.Dt SSH-LDAP.CONF 5 ++.Os ++.Sh NAME ++.Nm ssh-ldap.conf ++.Nd configuration file for ssh-ldap-helper ++.Sh SYNOPSIS ++.Nm /etc/ssh/ldap.conf ++.Sh DESCRIPTION ++.Xr ssh-ldap-helper 8 ++reads configuration data from ++.Pa /etc/ssh/ldap.conf ++(or the file specified with ++.Fl f ++on the command line). ++The file contains keyword-argument pairs, one per line. ++Lines starting with ++.Ql # ++and empty lines are interpreted as comments. ++.Pp ++The value starts with the first non-blank character after ++the keyword's name, and terminates at the end of the line, ++or at the last sequence of blanks before the end of the line. ++Quoting values that contain blanks ++may be incorrect, as the quotes would become part of the value. ++The possible keywords and their meanings are as follows (note that ++keywords are case-insensitive, and arguments, on a case by case basis, may be case-sensitive). ++.Bl -tag -width Ds ++.It Cm URI ++The argument(s) are in the form ++.Pa ldap[si]://[name[:port]] ++and specify the URI(s) of an LDAP server(s) to which the ++.Xr ssh-ldap-helper 8 ++should connect. The URI scheme may be any of ++.Dq ldap , ++.Dq ldaps ++or ++.Dq ldapi , ++which refer to LDAP over TCP, LDAP over SSL (TLS) and LDAP ++over IPC (UNIX domain sockets), respectively. ++Each server's name can be specified as a ++domain-style name or an IP address literal. Optionally, the ++server's name can followed by a ':' and the port number the LDAP ++server is listening on. If no port number is provided, the default ++port for the scheme is used (389 for ldap://, 636 for ldaps://). ++For LDAP over IPC, name is the name of the socket, and no port ++is required, nor allowed; note that directory separators must be ++URL-encoded, like any other characters that are special to URLs; ++A space separated list of URIs may be provided. ++There is no default. ++.It Cm Base ++Specifies the default base Distinguished Name (DN) to use when performing ldap operations. ++The base must be specified as a DN in LDAP format. ++There is no default. ++.It Cm BindDN ++Specifies the default BIND DN to use when connecting to the ldap server. ++The bind DN must be specified as a Distinguished Name in LDAP format. ++There is no default. ++.It Cm BindPW ++Specifies the default password to use when connecting to the ldap server via ++.Cm BindDN . ++There is no default. ++.It Cm RootBindDN ++Intentionaly does nothing. Recognized for compatibility reasons. ++.It Cm Host ++The argument(s) specifies the name(s) of an LDAP server(s) to which the ++.Xr ssh-ldap-helper 8 ++should connect. Each server's name can be specified as a ++domain-style name or an IP address and optionally followed by a ':' and ++the port number the ldap server is listening on. A space-separated ++list of hosts may be provided. ++There is no default. ++.Cm Host ++is deprecated in favor of ++.Cm URI . ++.It Cm Port ++Specifies the default port used when connecting to LDAP servers(s). ++The port may be specified as a number. ++The default port is 389 for ldap:// or 636 for ldaps:// respectively. ++.Cm Port ++is deprecated in favor of ++.Cm URI . ++.It Cm Scope ++Specifies the starting point of an LDAP search and the depth from the base DN to which the search should descend. ++There are three options (values) that can be assigned to the ++.Cm Scope parameter: ++.Dq base , ++.Dq one ++and ++.Dq subtree . ++Alias for the subtree is ++.Dq sub . ++The value ++.Dq base ++is used to indicate searching only the entry at the base DN, resulting in only that entry being returned (keeping in mind that it also has to meet the search filter criteria!). ++The value ++.Dq one ++is used to indicate searching all entries one level under the base DN, but not including the base DN and not including any entries under that one level under the base DN. ++The value ++.Dq subtree ++is used to indicate searching of all entries at all levels under and including the specified base DN. ++The default is ++.Dq subtree . ++.It Cm Deref ++Specifies how alias dereferencing is done when performing a search. There are four ++possible values that can be assigned to the ++.Cm Deref ++parameter: ++.Dq never , ++.Dq searching , ++.Dq finding , ++and ++.Dq always . ++The value ++.Dq never ++means that the aliases are never dereferenced. ++The value ++.Dq searching ++means that the aliases are dereferenced in subordinates of the base object, but ++not in locating the base object of the search. ++The value ++.Dq finding ++means that the aliases are only dereferenced when locating the base object of the search. ++The value ++.Dq always ++means that the aliases are dereferenced both in searching and in locating the base object ++of the search. ++The default is ++.Dq never . ++.It Cm TimeLimit ++Specifies a time limit (in seconds) to use when performing searches. ++The number should be a non-negative integer. A ++.Cm TimeLimit ++of zero (0) specifies that the search time is unlimited. Please note that the server ++may still apply any server-side limit on the duration of a search operation. ++The default value is 10. ++.It Cm TimeOut ++Is an aliast to ++.Cm TimeLimit . ++.It Cm Bind_TimeLimit ++Specifies the timeout (in seconds) after which the poll(2)/select(2) ++following a connect(2) returns in case of no activity. ++The default value is 10. ++.It Cm Network_TimeOut ++Is an alias to ++.Cm Bind_TimeLimit . ++.It Cm Ldap_Version ++Specifies what version of the LDAP protocol should be used. ++The allowed values are 2 or 3. The default is 3. ++.It Cm Version ++Is an alias to ++.Cm Ldap_Version . ++.It Cm Bind_Policy ++Specifies the policy to use for reconnecting to an unavailable LDAP server. There are 2 available values: ++.Dq hard ++and ++.Dq soft. ++.Dq hard has 2 aliases ++.Dq hard_open ++and ++.Dq hard_init . ++The value ++.Dq hard ++means that reconects that the ++.Xr ssh-ldap-helper 8 ++tries to reconnect to the LDAP server 5 times before failure. There is exponential backoff before retrying. ++The value ++.Dq soft ++means that ++.Xr ssh-ldap-helper 8 ++fails immediately when it cannot connect to the LDAP seerver. ++The deault is ++.Dq hard . ++.It Cm SSLPath ++Specifies the path to the X.509 certificate database. ++There is no default. ++.It Cm SSL ++Specifies whether to use SSL/TLS or not. ++There are three allowed values: ++.Dq yes , ++.Dq no ++and ++.Dq start_tls ++Both ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++If ++.Dq start_tls ++is specified then StartTLS is used rather than raw LDAP over SSL. ++The default for ldap:// is ++.Dq start_tls , ++for ldaps:// ++.Dq yes ++and ++.Dq no ++for the ldapi:// . ++In case of host based configuration the default is ++.Dq start_tls . ++.It Cm Referrals ++Specifies if the client should automatically follow referrals returned ++by LDAP servers. ++The value can be or ++.Dq yes ++or ++.Dq no . ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++The default is yes. ++.It Cm Restart ++Specifies whether the LDAP client library should restart the select(2) system call when interrupted. ++The value can be or ++.Dq yes ++or ++.Dq no . ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++The default is yes. ++.It Cm TLS_CheckPeer ++Specifies what checks to perform on server certificates in a TLS session, ++if any. The value ++can be specified as one of the following keywords: ++.Dq never , ++.Dq hard , ++.Dq demand , ++.Dq allow ++and ++.Dq try . ++.Dq true , ++.Dq on ++and ++.Dq yes ++are aliases for ++.Dq hard . ++.Dq false , ++.Dq off ++and ++.Dq no ++are the aliases for ++.Dq never . ++The value ++.Dq never ++means that the client will not request or check any server certificate. ++The value ++.Dq allow ++means that the server certificate is requested. If no certificate is provided, ++the session proceeds normally. If a bad certificate is provided, it will ++be ignored and the session proceeds normally. ++The value ++.Dq try ++means that the server certificate is requested. If no certificate is provided, ++the session proceeds normally. If a bad certificate is provided, ++the session is immediately terminated. ++The value ++.Dq demand ++means that the server certificate is requested. If no ++certificate is provided, or a bad certificate is provided, the session ++is immediately terminated. ++The value ++.Dq hard ++is the same as ++.Dq demand . ++It requires an SSL connection. In the case of the plain conection the ++session is immediately terminated. ++The default is ++.Dq hard . ++.It Cm TLS_ReqCert ++Is an alias for ++.Cm TLS_CheckPeer . ++.It Cm TLS_CACertFile ++Specifies the file that contains certificates for all of the Certificate ++Authorities the client will recognize. ++There is no default. ++.It Cm TLS_CACert ++Is an alias for ++.Cm TLS_CACertFile . ++.It Cm TLS_CACertDIR ++Specifies the path of a directory that contains Certificate Authority ++certificates in separate individual files. The ++.Cm TLS_CACert ++is always used before ++.Cm TLS_CACertDir . ++The specified directory must be managed with the OpenSSL c_rehash utility. ++There is no default. ++.It Cm TLS_Ciphers ++Specifies acceptable cipher suite and preference order. ++The value should be a cipher specification for OpenSSL, ++e.g., ++.Dq HIGH:MEDIUM:+SSLv2 . ++The default is ++.Dq ALL . ++.It Cm TLS_Cipher_Suite ++Is an alias for ++.Cm TLS_Ciphers . ++.It Cm TLS_Cert ++Specifies the file that contains the client certificate. ++There is no default. ++.It Cm TLS_Certificate ++Is an alias for ++.Cm TLS_Cert . ++.It Cm TLS_Key ++Specifies the file that contains the private key that matches the certificate ++stored in the ++.Cm TLS_Cert ++file. Currently, the private key must not be protected with a password, so ++it is of critical importance that the key file is protected carefully. ++There is no default. ++.It Cm TLS_RandFile ++Specifies the file to obtain random bits from when /dev/[u]random is ++not available. Generally set to the name of the EGD/PRNGD socket. ++The environment variable RANDFILE can also be used to specify the filename. ++There is no default. ++.It Cm LogDir ++Specifies the directory used for logging by the LDAP client library. ++There is no default. ++.It Cm Debug ++Specifies the debug level used for logging by the LDAP client library. ++There is no default. ++.It Cm SSH_Filter ++Specifies the user filter applied on the LDAP serch. ++The default is no filter. ++.It Cm AccountClass ++Specifies the LDAP class used to find user accounts. ++The default is posixAccount. ++.El ++.Sh FILES ++.Bl -tag -width Ds ++.It Pa /etc/ssh/ldap.conf ++Ldap configuration file for ++.Xr ssh-ldap-helper 8 . ++.El ++.Sh "SEE ALSO" ++.Xr ldap.conf 5 , ++.Xr ssh-ldap-helper 8 ++.Sh HISTORY ++.Nm ++first appeared in ++OpenSSH 5.5 + PKA-LDAP . ++.Sh AUTHORS ++.An Jan F. Chadima Aq jchadima@redhat.com +diff -up openssh-6.2p1/ssh-ldap-helper.8.ldap openssh-6.2p1/ssh-ldap-helper.8 +--- openssh-6.2p1/ssh-ldap-helper.8.ldap 2013-03-25 21:27:15.895248117 +0100 ++++ openssh-6.2p1/ssh-ldap-helper.8 2013-03-25 21:27:15.895248117 +0100 +@@ -0,0 +1,79 @@ ++.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ ++.\" ++.\" Copyright (c) 2010 Jan F. Chadima. 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. ++.\" ++.Dd $Mdocdate: April 29 2010 $ ++.Dt SSH-LDAP-HELPER 8 ++.Os ++.Sh NAME ++.Nm ssh-ldap-helper ++.Nd sshd helper program for ldap support ++.Sh SYNOPSIS ++.Nm ssh-ldap-helper ++.Op Fl devw ++.Op Fl f Ar file ++.Op Fl s Ar user ++.Sh DESCRIPTION ++.Nm ++is used by ++.Xr sshd 1 ++to access keys provided by an LDAP. ++.Nm ++is disabled by default and can only be enabled in the ++sshd configuration file ++.Pa /etc/ssh/sshd_config ++by setting ++.Cm AuthorizedKeysCommand ++to ++.Dq /usr/libexec/ssh-ldap-wrapper . ++.Pp ++.Nm ++is not intended to be invoked by the user, but from ++.Xr sshd 8 via ++.Xr ssh-ldap-wrapper . ++.Pp ++The options are as follows: ++.Bl -tag -width Ds ++.It Fl d ++Set the debug mode; ++.Nm ++prints all logs to stderr instead of syslog. ++.It Fl e ++Implies \-w; ++.Nm ++halts if it encounters an unknown item in the ldap.conf file. ++.It Fl f ++.Nm ++uses this file as the ldap configuration file instead of /etc/ssh/ldap.conf (default). ++.It Fl s ++.Nm ++prints out the user's keys to stdout and exits. ++.It Fl v ++Implies \-d; ++increases verbosity. ++.It Fl w ++.Nm ++writes warnings about unknown items in the ldap.conf configuration file. ++.El ++.Sh SEE ALSO ++.Xr sshd 8 , ++.Xr sshd_config 5 , ++.Xr ssh-ldap.conf 5 , ++.Sh HISTORY ++.Nm ++first appeared in ++OpenSSH 5.5 + PKA-LDAP . ++.Sh AUTHORS ++.An Jan F. Chadima Aq jchadima@redhat.com +diff -up openssh-6.2p1/ssh-ldap-wrapper.ldap openssh-6.2p1/ssh-ldap-wrapper +--- openssh-6.2p1/ssh-ldap-wrapper.ldap 2013-03-25 21:27:15.896248124 +0100 ++++ openssh-6.2p1/ssh-ldap-wrapper 2013-03-25 21:27:15.896248124 +0100 +@@ -0,0 +1,4 @@ ++#!/bin/sh ++ ++exec /usr/libexec/openssh/ssh-ldap-helper -s "$1" ++ diff --git a/openssh-lpk.schema b/openssh-lpk.schema new file mode 100644 index 0000000..4691fa0 --- /dev/null +++ b/openssh-lpk.schema @@ -0,0 +1,19 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey +# Author: Eric AUGE +# +# Based on the proposal of : Mark Ruijter +# + + +# octetString SYNTAX +attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' + DESC 'MANDATORY: OpenSSH Public key' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + +# printableString SYNTAX yes|no +objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY + DESC 'MANDATORY: OpenSSH LPK objectclass' + MAY ( sshPublicKey $ uid ) + ) diff --git a/openssh-no_libnsl.patch b/openssh-no_libnsl.patch new file mode 100644 index 0000000..c8fbdd4 --- /dev/null +++ b/openssh-no_libnsl.patch @@ -0,0 +1,23 @@ +diff -urN openssh-3.0p1.orig/configure.ac openssh-3.0p1/configure.ac +--- openssh-3.0p1.orig/configure.ac Sat Nov 3 20:09:33 2001 ++++ openssh-3.0p1/configure.ac Wed Nov 7 16:22:54 2001 +@@ -123,6 +123,8 @@ + AC_DEFINE(LOCKED_PASSWD_PREFIX, "!!") + AC_DEFINE(SPT_TYPE,SPT_REUSEARGV) + inet6_default_4in6=yes ++ no_libnsl=1 ++ no_libsocket=1 + case `uname -r` in + 1.*|2.0.*) + AC_DEFINE(BROKEN_CMSG_TYPE) +--- openssh-5.9p1/configure.ac~ 2011-09-06 19:01:09.000000000 +0200 ++++ openssh-5.9p1/configure.ac 2011-09-06 19:02:14.816070290 +0200 +@@ -972,7 +972,6 @@ + + dnl Checks for header files. + # Checks for libraries. +-AC_CHECK_FUNC([yp_match], , [AC_CHECK_LIB([nsl], [yp_match])]) + AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])]) + + dnl IRIX and Solaris 2.5.1 have dirname() in libgen + diff --git a/openssh-pam_misc.patch b/openssh-pam_misc.patch new file mode 100644 index 0000000..c05a1b6 --- /dev/null +++ b/openssh-pam_misc.patch @@ -0,0 +1,12 @@ +--- openssh-5.9p1/configure.ac~ 2011-09-06 19:02:28.000000000 +0200 ++++ openssh-5.9p1/configure.ac 2011-09-06 19:03:14.340571364 +0200 +@@ -2419,7 +2419,7 @@ + + PAM_MSG="yes" + +- SSHDLIBS="$SSHDLIBS -lpam" ++ SSHDLIBS="$SSHDLIBS -lpam -lpam_misc" + AC_DEFINE([USE_PAM], [1], + [Define if you want to enable PAM support]) + + diff --git a/openssh-sigpipe.patch b/openssh-sigpipe.patch new file mode 100644 index 0000000..67631f7 --- /dev/null +++ b/openssh-sigpipe.patch @@ -0,0 +1,95 @@ +--- openssh-4.0p1/clientloop.c.orig 2005-03-01 11:24:33.000000000 +0100 ++++ openssh-4.0p1/clientloop.c 2005-03-10 15:10:05.000000000 +0100 +@@ -104,6 +104,9 @@ + */ + extern char *host; + ++/* if we process SIGPIPE */ ++extern int enable_sigpipe; ++ + /* + * Flag to indicate that we have received a window change signal which has + * not yet been processed. This will cause a message indicating the new +@@ -1236,6 +1239,8 @@ + signal(SIGQUIT, signal_handler); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, signal_handler); ++ if (enable_sigpipe) ++ signal(SIGPIPE, signal_handler); + signal(SIGWINCH, window_change_handler); + + if (have_pty) +diff -urN openssh-3.9p1.org/ssh.0 openssh-3.9p1/ssh.0 +--- openssh-3.9p1.org/ssh.0 2004-08-17 19:03:29.327565840 +0200 ++++ openssh-3.9p1/ssh.0 2004-08-17 19:03:41.809668272 +0200 +@@ -235,6 +235,8 @@ + that enable them to authenticate using the identities loaded into + the agent. + ++ -B Enable SIGPIPE processing. ++ + -a Disables forwarding of the authentication agent connection. + + -b bind_address +--- openssh-5.6p1/ssh.1~ 2010-08-24 14:05:48.000000000 +0300 ++++ openssh-5.6p1/ssh.1 2010-08-24 14:06:57.879253682 +0300 +@@ -44,7 +44,7 @@ + .Sh SYNOPSIS + .Nm ssh + .Bk -words +-.Op Fl 1246AaCfgKkMNnqsTtVvXxYy ++.Op Fl 1246AaBCfgKkMNnqsTtVvXxYy + .Op Fl b Ar bind_address + .Op Fl c Ar cipher_spec + .Op Fl D Oo Ar bind_address : Oc Ns Ar port +@@ -425,6 +425,10 @@ + on the local machine as the source address + of the connection. + Only useful on systems with more than one address. ++.It Fl B ++Enables processing of SIGPIPE. Useful when using ssh output as input for ++another process, for example in a shell script. Be careful - it may break ++port/X11 forwarding when used. + .It Fl C + Requests compression of all data (including stdin, stdout, stderr, and + data for forwarded X11 and TCP/IP connections). +--- openssh-4.0p1/ssh.c.orig 2005-03-02 02:04:33.000000000 +0100 ++++ openssh-4.0p1/ssh.c 2005-03-10 15:11:10.000000000 +0100 +@@ -135,6 +135,9 @@ + /* Should we execute a command or invoke a subsystem? */ + int subsystem_flag = 0; + ++/* Enable sigpipe */ ++int enable_sigpipe = 0; ++ + /* # of replies received for global requests */ + static int client_global_request_id = 0; + +@@ -199,7 +199,7 @@ static void + usage(void) + { + fprintf(stderr, +-"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" ++"usage: ssh [-1246AaBCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" + " [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" + " [-F configfile] [-I pkcs11] [-i identity_file]\n" + " [-L [bind_address:]port:host:hostport] [-Q protocol_feature]\n" +@@ -330,7 +330,7 @@ main(int ac, char **av) + + again: + while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" +- "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { ++ "ABCD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { + switch (opt) { + case '1': + options.protocol = SSH_PROTO_1; +@@ -291,6 +294,9 @@ + case 'A': + options.forward_agent = 1; + break; ++ case 'B': ++ enable_sigpipe = 1; ++ break; + case 'k': + options.gss_deleg_creds = 0; + break; diff --git a/openssh.spec b/openssh.spec new file mode 100644 index 0000000..efd5688 --- /dev/null +++ b/openssh.spec @@ -0,0 +1,867 @@ +# TODO: +# - add trigger to enable this: +# * sshd(8): This release turns on pre-auth sandboxing sshd by default for +# new installs, by setting UsePrivilegeSeparation=sandbox in sshd_config. +# +# Conditional build: +%bcond_without audit # sshd audit support +%bcond_with gnome # with gnome-askpass (GNOME 1.x) utility +%bcond_without gtk # without GTK+ (2.x) +%bcond_without ldap # with ldap support +%bcond_without libedit # without libedit (editline/history support in sftp client) +%bcond_without kerberos5 # without kerberos5 support +%bcond_without selinux # build without SELinux support +%bcond_with hpn # High Performance SSH/SCP - HPN-SSH including Cipher NONE (broken too often) +%bcond_without tests + +# gtk2-based gnome-askpass means no gnome1-based +%{?with_gtk:%undefine with_gnome} + +%if "%{pld_release}" == "ac" +%define pam_ver 0.79.0 +%else +%define pam_ver 1:1.1.5-5 +%endif +Summary: OpenSSH free Secure Shell (SSH) implementation +Summary(de.UTF-8): OpenSSH - freie Implementation der Secure Shell (SSH) +Summary(es.UTF-8): Implementación libre de SSH +Summary(fr.UTF-8): Implémentation libre du shell sécurisé OpenSSH (SSH) +Summary(it.UTF-8): Implementazione gratuita OpenSSH della Secure Shell +Summary(pl.UTF-8): Publicznie dostępna implementacja bezpiecznego shella (SSH) +Summary(pt.UTF-8): Implementação livre OpenSSH do protocolo 'Secure Shell' (SSH) +Summary(pt_BR.UTF-8): Implementação livre do SSH +Summary(ru.UTF-8): OpenSSH - свободная реализация протокола Secure Shell (SSH) +Summary(uk.UTF-8): OpenSSH - вільна реалізація протоколу Secure Shell (SSH) +Name: openssh +Version: 6.5p1 +Release: 0.1 +Epoch: 2 +License: BSD +Group: Applications/Networking +Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{name}-%{version}.tar.gz +# Source0-md5: a084e7272b8cbd25afe0f5dce4802fef +Source1: http://www.mif.pg.gda.pl/homepages/ankry/man-PLD/%{name}-non-english-man-pages.tar.bz2 +# Source1-md5: 66943d481cc422512b537bcc2c7400d1 +Source2: %{name}d.init +Source3: %{name}d.pamd +Source4: %{name}.sysconfig +Source5: ssh-agent.sh +Source6: ssh-agent.conf +Source7: %{name}-lpk.schema +Source8: %{name}d.upstart +Source9: sshd.service +Source10: sshd-keygen +Source11: sshd.socket +Source12: sshd@.service +Patch0: %{name}-no_libnsl.patch +Patch2: %{name}-pam_misc.patch +Patch3: %{name}-sigpipe.patch +# http://pkgs.fedoraproject.org/gitweb/?p=openssh.git;a=tree +Patch4: %{name}-ldap.patch +Patch5: %{name}-ldap-fixes.patch +Patch8: ldap.conf.patch +Patch6: %{name}-config.patch +Patch7: ldap-helper-sigpipe.patch + +# High Performance SSH/SCP - HPN-SSH - http://www.psc.edu/networking/projects/hpn-ssh/ +# http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.2p1-hpn13v6.diff.gz +Patch9: %{name}-5.2p1-hpn13v6.diff +Patch10: %{name}-include.patch +Patch11: %{name}-chroot.patch +# http://people.debian.org/~cjwatson/%{name}-blacklist.diff +Patch12: %{name}-blacklist.diff +Patch13: %{name}-kuserok.patch +Patch14: %{name}-bind.patch +Patch15: %{name}-disable_ldap.patch +URL: http://www.openssh.com/portable.html +BuildRequires: %{__perl} +%{?with_tests:BuildRequires: %{name}-server} +%{?with_audit:BuildRequires: audit-libs-devel} +BuildRequires: autoconf >= 2.50 +BuildRequires: automake +%{?with_gnome:BuildRequires: gnome-libs-devel} +%{?with_gtk:BuildRequires: gtk+2-devel} +%{?with_kerberos5:BuildRequires: heimdal-devel >= 0.7} +%{?with_libedit:BuildRequires: libedit-devel} +%{?with_selinux:BuildRequires: libselinux-devel} +BuildRequires: libwrap-devel +%{?with_ldap:BuildRequires: openldap-devel} +BuildRequires: openssl-devel >= 0.9.7d +BuildRequires: pam-devel +%{?with_gtk:BuildRequires: pkgconfig} +BuildRequires: rpm >= 4.4.9-56 +BuildRequires: rpmbuild(macros) >= 1.627 +BuildRequires: sed >= 4.0 +BuildRequires: zlib-devel >= 1.2.3 +Requires: zlib >= 1.2.3 +%if "%{pld_release}" == "ac" +Requires: filesystem >= 2.0-1 +Requires: pam >= 0.79.0 +%else +Requires: filesystem >= 3.0-11 +Requires: pam >= %{pam_ver} +Suggests: openssh-blacklist +Suggests: xorg-app-xauth +%endif +Obsoletes: ssh +BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n) + +%define _sysconfdir /etc/ssh +%define _libexecdir %{_libdir}/%{name} +%define _privsepdir /usr/share/empty +%define schemadir /usr/share/openldap/schema + +%description +Ssh (Secure Shell) a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. X11 connections and +arbitrary TCP/IP ports can also be forwarded over the secure channel. + +OpenSSH is OpenBSD's rework of the last free version of SSH, bringing +it up to date in terms of security and features, as well as removing +all patented algorithms to seperate libraries (OpenSSL). + +This package includes the core files necessary for both the OpenSSH +client and server. To make this package useful, you should also +install openssh-clients, openssh-server, or both. + +%if %{with hpn} +This release includes High Performance SSH/SCP patches from +http://www.psc.edu/networking/projects/hpn-ssh/ which are supposed to +increase throughput on fast connections with high RTT (20-150 msec). +See the website for '-w' values for your connection and /proc/sys TCP +values. BTW. in a LAN you have got generally RTT < 1 msec. +%endif + +%description -l de.UTF-8 +OpenSSH (Secure Shell) stellt den Zugang zu anderen Rechnern her. Es +ersetzt telnet, rlogin, rexec und rsh und stellt eine sichere, +verschlüsselte Verbindung zwischen zwei nicht vertrauenswürdigen Hosts +über eine unsicheres Netzwerk her. X11 Verbindungen und beliebige +andere TCP/IP Ports können ebenso über den sicheren Channel +weitergeleitet werden. + +%description -l es.UTF-8 +SSH es un programa para accesar y ejecutar órdenes en computadores +remotos. Sustituye rlogin y rsh, y suministra un canal de comunicación +seguro entre dos servidores en una red insegura. Conexiones X11 y +puertas TCP/IP arbitrárias también pueden ser usadas por el canal +seguro. + +OpenSSH es el resultado del trabajo del equipo de OpenBSD para +continuar la última versión gratuita de SSH, actualizándolo en +términos de seguridad y recursos,así también eliminando todos los +algoritmos patentados y colocándolos en bibliotecas separadas +(OpenSSL). + +Este paquete contiene "port" para Linux de OpenSSH. Se debe instalar +también el paquete openssh-clients u openssh-server o ambos. + +%description -l fr.UTF-8 +OpenSSH (Secure Shell) fournit un accès à un système distant. Il +remplace telnet, rlogin, rexec et rsh, tout en assurant des +communications cryptées securisées entre deux hôtes non fiabilisés sur +un réseau non sécurisé. Des connexions X11 et des ports TCP/IP +arbitraires peuvent également être transmis sur le canal sécurisé. + +%description -l it.UTF-8 +OpenSSH (Secure Shell) fornisce l'accesso ad un sistema remoto. +Sostituisce telnet, rlogin, rexec, e rsh, e fornisce comunicazioni +sicure e crittate tra due host non fidati su una rete non sicura. Le +connessioni X11 ad una porta TCP/IP arbitraria possono essere +inoltrate attraverso un canale sicuro. + +%description -l pl.UTF-8 +Ssh (Secure Shell) to program służący do logowania się na zdalną +maszynę i uruchamiania na niej aplikacji. W zamierzeniu openssh ma +zastąpić rlogin, rsh i dostarczyć bezpieczne, szyfrowane połączenie +pomiędzy dwoma hostami. + +Ten pakiet zawiera podstawowe pliki potrzebne zarówno po stronie +klienta jak i serwera OpenSSH. Aby był użyteczny, trzeba zainstalować +co najmniej jeden z pakietów: openssh-clients lub openssh-server. + +%if %{with hpn} +Ta wersja zawiera łaty z projektu High Performance SSH/SCP +http://www.psc.edu/networking/projects/hpn-ssh/, które mają na celu +zwiększenie przepustowości transmisji dla szybkich połączeń z dużym +RTT (20-150 msec). Na stronie projektu znaleźć można odpowednie dla +danego połączenia wartości parametru '-w' oraz opcje /proc/sys dla +TCP. Nawiasem mówiąc w sieciach LAN RTT < 1 msec. +%endif + +%description -l pt.UTF-8 +OpenSSH (Secure Shell) fornece acesso a um sistema remoto. Substitui o +telnet, rlogin, rexec, e o rsh e fornece comunicações seguras e +cifradas entre duas máquinas sem confiança mútua sobre uma rede +insegura. Ligações X11 e portos TCP/IP arbitrários também poder ser +reenviados pelo canal seguro. + +%description -l pt_BR.UTF-8 +SSH é um programa para acessar e executar comandos em máquinas +remotas. Ele substitui rlogin e rsh, e provem um canal de comunicação +seguro entre dois hosts em uma rede insegura. Conexões X11 e portas +TCP/IP arbitrárias também podem ser usadas pelo canal seguro. + +OpenSSH é o resultado do trabalho da equipe do OpenBSD em continuar a +última versão gratuita do SSH, atualizando-o em termos de segurança e +recursos, assim como removendo todos os algoritmos patenteados e +colocando-os em bibliotecas separadas (OpenSSL). + +Esse pacote contém o "port" pra Linux do OpenSSH. Você deve instalar +também ou o pacote openssh-clients, ou o openssh-server, ou ambos. + +%description -l ru.UTF-8 +Ssh (Secure Shell) - это программа для "захода" (login) на удаленную +машину и для выполнения команд на удаленной машине. Она предназначена +для замены rlogin и rsh и обеспечивает безопасную шифрованную +коммуникацию между двумя хостами в сети, являющейся небезопасной. +Соединения X11 и любые порты TCP/IP могут также быть проведены через +безопасный канал. + +OpenSSH - это переделка командой разработчиков OpenBSD последней +свободной версии SSH, доведенная до современного состояния в терминах +уровня безопасности и поддерживаемых возможностей. Все патентованные +алгоритмы вынесены в отдельные библиотеки (OpenSSL). + +Этот пакет содержит файлы, необходимые как для клиента, так и для +сервера OpenSSH. Вам нужно будет установить еще openssh-clients, +openssh-server, или оба пакета. + +%description -l uk.UTF-8 +Ssh (Secure Shell) - це програма для "заходу" (login) до віддаленої +машини та для виконання команд на віддаленій машині. Вона призначена +для заміни rlogin та rsh і забезпечує безпечну шифровану комунікацію +між двома хостами в мережі, яка не є безпечною. З'єднання X11 та +довільні порти TCP/IP можуть також бути проведені через безпечний +канал. + +OpenSSH - це переробка командою розробників OpenBSD останньої вільної +версії SSH, доведена до сучасного стану в термінах рівня безпеки та +підтримуваних можливостей. Всі патентовані алгоритми винесені до +окремих бібліотек (OpenSSL). + +Цей пакет містить файли, необхідні як для клієнта, так і для сервера +OpenSSH. Вам потрібно буде ще встановити openssh-clients, +openssh-server, чи обидва пакети. + +%package clients +Summary: OpenSSH Secure Shell protocol clients +Summary(es.UTF-8): Clientes de OpenSSH +Summary(pl.UTF-8): Klienci protokołu Secure Shell +Summary(pt_BR.UTF-8): Clientes do OpenSSH +Summary(ru.UTF-8): OpenSSH - клиенты протокола Secure Shell +Summary(uk.UTF-8): OpenSSH - клієнти протоколу Secure Shell +Group: Applications/Networking +Requires: %{name} +Provides: ssh-clients +Obsoletes: ssh-clients +%requires_eq_to openssl openssl-devel + +%description clients +Ssh (Secure Shell) a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. X11 connections and +arbitrary TCP/IP ports can also be forwarded over the secure channel. + +OpenSSH is OpenBSD's rework of the last free version of SSH, bringing +it up to date in terms of security and features, as well as removing +all patented algorithms to seperate libraries (OpenSSL). + +This package includes the clients necessary to make encrypted +connections to SSH servers. + +%description clients -l es.UTF-8 +Este paquete incluye los clientes que se necesitan para hacer +conexiones codificadas con servidores SSH. + +%description clients -l pl.UTF-8 +Ssh (Secure Shell) to program służący do logowania się na zdalną +maszynę i uruchamiania na niej aplikacji. W zamierzeniu openssh ma +zastąpić rlogin, rsh i dostarczyć bezpieczne, szyfrowane połączenie +pomiędzy dwoma hostami. + +Ten pakiet zawiera klientów służących do łączenia się z serwerami SSH. + +%description clients -l pt_BR.UTF-8 +Esse pacote inclui os clientes necessários para fazer conexões +encriptadas com servidores SSH. + +%description clients -l ru.UTF-8 +Ssh (Secure Shell) - это программа для "захода" (login) на удаленную +машину и для выполнения команд на удаленной машине. + +Этот пакет содержит программы-клиенты, необходимые для установления +зашифрованных соединений с серверами SSH. + +%description clients -l uk.UTF-8 +Ssh (Secure Shell) - це програма для "заходу" (login) до віддаленої +машини та для виконання команд на віддаленій машині. + +Цей пакет містить програми-клієнти, необхідні для встановлення +зашифрованих з'єднань з серверами SSH. + +%package clients-agent-profile_d +Summary: OpenSSH Secure Shell agent init script +Summary(pl.UTF-8): Skrypt startowy agenta OpenSSH +Group: Applications/Networking +Requires: %{name}-clients = %{epoch}:%{version}-%{release} + +%description clients-agent-profile_d +profile.d scripts for starting SSH agent. + +%description clients-agent-profile_d -l pl.UTF-8 +Skrypty profile.d do uruchamiania agenta SSH. + +%package clients-agent-xinitrc +Summary: OpenSSH Secure Shell agent init script +Summary(pl.UTF-8): Skrypt inicjujący agenta ssh przez xinitrc +Group: Applications/Networking +Requires: %{name}-clients-agent-profile_d = %{epoch}:%{version}-%{release} +Requires: xinitrc + +%description clients-agent-xinitrc +xinitrc scripts for starting SSH agent. + +%description clients-agent-xinitrc -l pl.UTF-8 +Skrypty xinitrc do uruchamiania agenta SSH. + +%package server +Summary: OpenSSH Secure Shell protocol server (sshd) +Summary(de.UTF-8): OpenSSH Secure Shell Protocol-Server (sshd) +Summary(es.UTF-8): Servidor OpenSSH para comunicaciones codificadas +Summary(fr.UTF-8): Serveur de protocole du shell sécurisé OpenSSH (sshd) +Summary(it.UTF-8): Server OpenSSH per il protocollo Secure Shell (sshd) +Summary(pl.UTF-8): Serwer protokołu Secure Shell (sshd) +Summary(pt.UTF-8): Servidor do protocolo 'Secure Shell' OpenSSH (sshd) +Summary(pt_BR.UTF-8): Servidor OpenSSH para comunicações encriptadas +Summary(ru.UTF-8): OpenSSH - сервер протокола Secure Shell (sshd) +Summary(uk.UTF-8): OpenSSH - сервер протоколу Secure Shell (sshd) +Group: Networking/Daemons +Requires(post): /sbin/chkconfig +Requires(post): grep +Requires(post,preun): /sbin/chkconfig +Requires(postun): /usr/sbin/userdel +Requires(pre): /bin/id +Requires(pre): /usr/sbin/useradd +Requires(post,preun,postun): systemd-units >= 38 +Requires: %{name} = %{epoch}:%{version}-%{release} +Requires: pam >= %{pam_ver} +Requires: rc-scripts >= 0.4.3.0 +Requires: systemd-units >= 38 +Requires: util-linux +%{?with_ldap:Suggests: %{name}-server-ldap} +Suggests: /bin/login +Suggests: xorg-app-xauth +Provides: ssh-server +Provides: user(sshd) +%requires_eq_to openssl openssl-devel + +%description server +Ssh (Secure Shell) a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. X11 connections and +arbitrary TCP/IP ports can also be forwarded over the secure channel. + +OpenSSH is OpenBSD's rework of the last free version of SSH, bringing +it up to date in terms of security and features, as well as removing +all patented algorithms to seperate libraries (OpenSSL). + +This package contains the secure shell daemon. The sshd is the server +part of the secure shell protocol and allows ssh clients to connect to +your host. + +%description server -l de.UTF-8 +Dieses Paket installiert den sshd, den Server-Teil der OpenSSH. + +%description server -l es.UTF-8 +Este paquete contiene el servidor SSH. sshd es la parte servidor del +protocolo secure shell y permite que clientes ssh se conecten a su +servidor. + +%description server -l fr.UTF-8 +Ce paquetage installe le 'sshd', partie serveur de OpenSSH. + +%description server -l it.UTF-8 +Questo pacchetto installa sshd, il server di OpenSSH. + +%description server -l pl.UTF-8 +Ssh (Secure Shell) to program służący do logowania się na zdalną +maszynę i uruchamiania na niej aplikacji. W zamierzeniu openssh ma +zastąpić rlogin, rsh i dostarczyć bezpieczne, szyfrowane połączenie +pomiędzy dwoma hostami. + +Ten pakiet zawiera serwer sshd (do którego mogą łączyć się klienci +ssh). + +%description server -l pt.UTF-8 +Este pacote intala o sshd, o servidor do OpenSSH. + +%description server -l pt_BR.UTF-8 +Esse pacote contém o servidor SSH. O sshd é a parte servidor do +protocolo secure shell e permite que clientes ssh se conectem ao seu +host. + +%description server -l ru.UTF-8 +Ssh (Secure Shell) - это программа для "захода" (login) на удаленную +машину и для выполнения команд на удаленной машине. + +Этот пакет содержит sshd - "демон" Secure Shell. sshd - это серверная +часть протокола Secure Shell, позволяющая клиентам ssh соединяться с +вашим хостом. + +%description server -l uk.UTF-8 +Ssh (Secure Shell) - це програма для "заходу" (login) до віддаленої +машини та для виконання команд на віддаленій машині. + +Цей пакет містить sshd - "демон" Secure Shell. sshd - це серверна +частина протоколу Secure Shell, яка дозволяє клієнтам ssh зв'язуватись +з вашим хостом. + +%package server-ldap +Summary: A LDAP support for open source SSH server daemon +Summary(pl.UTF-8): Wsparcie LDAP dla serwera OpenSSH +Group: Daemons +Requires: %{name} = %{epoch}:%{version}-%{release} +Requires: openldap-nss-config + +%description server-ldap +OpenSSH LDAP backend is a way how to distribute the authorized tokens +among the servers in the network. + +%description server-ldap -l pl.UTF-8 +Backend LDAP dla OpenSSH to metoda rozprowadzania autoryzowanych +tokenów między serwerami w sieci. + +%package server-upstart +Summary: Upstart job description for OpenSSH server +Summary(pl.UTF-8): Opis zadania Upstart dla serwera OpenSSH +Group: Daemons +Requires: %{name}-server = %{epoch}:%{version}-%{release} +Requires: upstart >= 0.6 +Conflicts: syslog-ng < 3.2.4-1 + +%description server-upstart +Upstart job description for OpenSSH. + +%description server-upstart -l pl.UTF-8 +Opis zadania Upstart dla OpenSSH. + +%package gnome-askpass +Summary: OpenSSH GNOME passphrase dialog +Summary(de.UTF-8): OpenSSH GNOME Passwort-Dialog +Summary(es.UTF-8): Diálogo para introducción de passphrase para GNOME +Summary(fr.UTF-8): Dialogue pass-phrase GNOME d'OpenSSH +Summary(it.UTF-8): Finestra di dialogo GNOME per la frase segreta di OpenSSH +Summary(pl.UTF-8): Odpytywacz hasła OpenSSH dla GNOME +Summary(pt.UTF-8): Diálogo de pedido de senha para GNOME do OpenSSH +Summary(pt_BR.UTF-8): Diálogo para entrada de passphrase para GNOME +Summary(ru.UTF-8): OpenSSH - диалог ввода ключевой фразы (passphrase) для GNOME +Summary(uk.UTF-8): OpenSSH - діалог вводу ключової фрази (passphrase) для GNOME +Group: Applications/Networking +Requires: %{name} = %{epoch}:%{version}-%{release} +Obsoletes: openssh-askpass +Obsoletes: ssh-askpass +Obsoletes: ssh-extras + +%description gnome-askpass +Ssh (Secure Shell) a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. X11 connections and +arbitrary TCP/IP ports can also be forwarded over the secure channel. + +OpenSSH is OpenBSD's rework of the last free version of SSH, bringing +it up to date in terms of security and features, as well as removing +all patented algorithms to seperate libraries (OpenSSL). + +This package contains the GNOME passphrase dialog. + +%description gnome-askpass -l es.UTF-8 +Este paquete contiene un programa que abre una caja de diálogo para +entrada de passphrase en GNOME. + +%description gnome-askpass -l pl.UTF-8 +Ssh (Secure Shell) to program służący do logowania się na zdalną +maszynę i uruchamiania na niej aplikacji. W zamierzeniu openssh ma +zastąpić rlogin, rsh i dostarczyć bezpieczne, szyfrowane połączenie +pomiędzy dwoma hostami. + +Ten pakiet zawiera ,,odpytywacz hasła'' dla GNOME. + +%description gnome-askpass -l pt_BR.UTF-8 +Esse pacote contém um programa que abre uma caixa de diálogo para +entrada de passphrase no GNOME. + +%description gnome-askpass -l ru.UTF-8 +Ssh (Secure Shell) - это программа для "захода" (login) на удаленную +машину и для выполнения команд на удаленной машине. + +Этот пакет содержит диалог ввода ключевой фразы для использования под +GNOME. + +%description gnome-askpass -l uk.UTF-8 +Ssh (Secure Shell) - це програма для "заходу" (login) до віддаленої +машини та для виконання команд на віддаленій машині. + +Цей пакет містить діалог вводу ключової фрази для використання під +GNOME. + +%package -n openldap-schema-openssh-lpk +Summary: OpenSSH LDAP Public Key schema +Summary(pl.UTF-8): Schemat klucza publicznego LDAP dla OpenSSH +Group: Networking/Daemons +Requires(post,postun): sed >= 4.0 +Requires: openldap-servers +%if "%{_rpmversion}" >= "5" +BuildArch: noarch +%endif + +%description -n openldap-schema-openssh-lpk +This package contains OpenSSH LDAP Public Key schema for openldap. + +%description -n openldap-schema-openssh-lpk -l pl.UTF-8 +Ten pakiet zawiera schemat klucza publicznego LDAP dla OpenSSH dla +openldap-a. + +%prep +%setup -q +%patch0 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch8 -p1 +%patch6 -p1 +%patch7 -p1 + +%{?with_hpn:%patch9 -p1} +%patch10 -p1 +%patch11 -p1 +# do we really need to drag this old/obsolete patch? +#%patch12 -p1 +# code changed in upstream, needs baggins verification +#%patch13 -p1 +%patch14 -p1 +%{!?with_ldap:%patch15 -p1} + +%if "%{pld_release}" == "ac" +# fix for missing x11.pc +%{__sed} -i -e '/pkg-config/s/ x11//' contrib/Makefile +%endif + +# hack since arc4random from openbsd-compat needs symbols from libssh and vice versa +sed -i -e 's#-lssh -lopenbsd-compat#-lssh -lopenbsd-compat -lssh#g' Makefile* + +grep -rl /usr/libexec/openssh/ssh-ldap-helper . | xargs \ +%{__sed} -i -e 's,/usr/libexec/openssh/ssh-ldap-helper,%{_libexecdir}/ssh-ldap-helper,' + +%build +cp /usr/share/automake/config.sub . +%{__aclocal} +%{__autoconf} +%{__autoheader} +CPPFLAGS="-DCHROOT" +%configure \ + PERL=%{__perl} \ + --disable-strip \ + --enable-utmpx \ + --enable-wtmpx \ + --with-4in6 \ + %{?with_audit:--with-audit=linux} \ + --with-ipaddr-display \ + %{?with_kerberos5:--with-kerberos5=/usr} \ + --with-ldap%{!?with_ldap:=no} \ + %{?with_libedit:--with-libedit} \ + --with-mantype=man \ + --with-md5-passwords \ + --with-pam \ + --with-pid-dir=%{_localstatedir}/run \ + --with-privsep-path=%{_privsepdir} \ + --with-sandbox=seccomp_filter \ + %{?with_selinux:--with-selinux} \ + --with-tcp-wrappers \ +%if "%{pld_release}" == "ac" + --with-xauth=/usr/X11R6/bin/xauth +%else + --with-xauth=%{_bindir}/xauth +%endif + +echo '#define LOGIN_PROGRAM "/bin/login"' >>config.h + +%{__make} + +%{?with_tests:%{__make} tests} + +cd contrib +%if %{with gnome} +%{__make} gnome-ssh-askpass1 \ + CC="%{__cc} %{rpmldflags} %{rpmcflags}" +%endif +%if %{with gtk} +%{__make} gnome-ssh-askpass2 \ + CC="%{__cc} %{rpmldflags} %{rpmcflags}" +%endif + +%install +rm -rf $RPM_BUILD_ROOT +install -d $RPM_BUILD_ROOT{%{_sysconfdir},/etc/{init,pam.d,rc.d/init.d,sysconfig,security,env.d}} \ + $RPM_BUILD_ROOT{%{_libexecdir}/ssh,%{schemadir},%{systemdunitdir}} +install -d $RPM_BUILD_ROOT/etc/{profile.d,X11/xinit/xinitrc.d} + +%{__make} install \ + DESTDIR=$RPM_BUILD_ROOT + +bzip2 -dc %{SOURCE1} | tar xf - -C $RPM_BUILD_ROOT%{_mandir} + +cp -p %{SOURCE3} sshd.pam +install -p %{SOURCE2} sshd.init + +%if "%{pld_release}" == "ac" +# not present in ac, no point searching it +%{__sed} -i -e '/pam_keyinit.so/d' sshd.pam +# openssl on ac does not have OPENSSL_HAS_ECC +%{__sed} -i -e '/ecdsa/d' sshd.init +%endif + +%if %{without audit} +# remove recording user's login uid to the process attribute +%{__sed} -i -e '/pam_loginuid.so/d' sshd.pam +%endif + +install -p sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd +cp -p sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd +cp -p %{SOURCE4} $RPM_BUILD_ROOT/etc/sysconfig/sshd +cp -p %{SOURCE5} $RPM_BUILD_ROOT/etc/profile.d +ln -sf /etc/profile.d/ssh-agent.sh $RPM_BUILD_ROOT/etc/X11/xinit/xinitrc.d/ssh-agent.sh +cp -p %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir} +cp -p %{SOURCE7} $RPM_BUILD_ROOT%{schemadir} +cp -p %{SOURCE8} $RPM_BUILD_ROOT/etc/init/sshd.conf + +%{__sed} -e 's|@@LIBEXECDIR@@|%{_libexecdir}|g' %{SOURCE9} >$RPM_BUILD_ROOT%{systemdunitdir}/sshd.service +cp -p %{SOURCE10} $RPM_BUILD_ROOT%{_libexecdir}/sshd-keygen + +cp -p %{SOURCE11} $RPM_BUILD_ROOT%{systemdunitdir} +cp -p %{SOURCE12} $RPM_BUILD_ROOT%{systemdunitdir} + +%if %{with gnome} +install -p contrib/gnome-ssh-askpass1 $RPM_BUILD_ROOT%{_libexecdir}/ssh/ssh-askpass +%endif +%if %{with gtk} +install -p contrib/gnome-ssh-askpass2 $RPM_BUILD_ROOT%{_libexecdir}/ssh/ssh-askpass +%endif +%if %{with gnome} || %{with gtk} +cat << 'EOF' >$RPM_BUILD_ROOT/etc/env.d/GNOME_SSH_ASKPASS_GRAB_SERVER +#GNOME_SSH_ASKPASS_GRAB_SERVER="true" +EOF +cat << 'EOF' >$RPM_BUILD_ROOT/etc/env.d/GNOME_SSH_ASKPASS_GRAB_POINTER +#GNOME_SSH_ASKPASS_GRAB_POINTER="true" +EOF +ln -s %{_libexecdir}/ssh/ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/ssh-askpass +%endif + +install -p contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir} +cp -p contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1 + +%{__rm} $RPM_BUILD_ROOT%{_mandir}/man1/slogin.1 +echo ".so ssh.1" > $RPM_BUILD_ROOT%{_mandir}/man1/slogin.1 + +touch $RPM_BUILD_ROOT/etc/security/blacklist.sshd + +cat << 'EOF' > $RPM_BUILD_ROOT/etc/env.d/SSH_ASKPASS +#SSH_ASKPASS="%{_libexecdir}/ssh-askpass" +EOF + +%{__rm} $RPM_BUILD_ROOT%{_mandir}/README.openssh-non-english-man-pages +%{?with_ldap:%{__rm} $RPM_BUILD_ROOT%{_sysconfdir}/ldap.conf} + +%clean +rm -rf $RPM_BUILD_ROOT + +%post clients +%env_update + +%postun clients +%env_update + +%post gnome-askpass +%env_update + +%postun gnome-askpass +%env_update + +%pre server +%useradd -P %{name}-server -u 40 -d %{_privsepdir} -s /bin/false -c "OpenSSH PrivSep User" -g nobody sshd + +%post server +/sbin/chkconfig --add sshd +%service sshd reload "OpenSSH Daemon" +NORESTART=1 +%systemd_post sshd.service + +%preun server +if [ "$1" = "0" ]; then + %service sshd stop + /sbin/chkconfig --del sshd +fi +%systemd_preun sshd.service + +%postun server +if [ "$1" = "0" ]; then + %userremove sshd +fi +%systemd_reload + +%triggerpostun server -- %{name}-server < 6.2p1-1 +cp -f %{_sysconfdir}/sshd_config{,.rpmorig} +sed -i -e 's#AuthorizedKeysCommandRunAs#AuthorizedKeysCommandUser##g' %{_sysconfdir}/sshd_config + +%triggerpostun server -- %{name}-server < 2:5.9p1-8 +# lpk.patch to ldap.patch +if grep -qE '^(UseLPK|Lpk)' %{_sysconfdir}/sshd_config; then + echo >&2 "Migrating LPK patch to LDAP patch" + cp -f %{_sysconfdir}/sshd_config{,.rpmorig} + %{__sed} -i -e ' + # disable old configs + # just UseLPK/LkpLdapConf supported for now + s/^\s*UseLPK/## Obsolete &/ + s/^\s*Lpk/## Obsolete &/ + # Enable new ones, assumes /etc/ldap.conf defaults, see HOWTO.ldap-keys + /UseLPK/iAuthorizedKeysCommand %{_libexecdir}/ssh-ldap-wrapper + ' %{_sysconfdir}/sshd_config + if [ ! -x /bin/systemd_booted ] || ! /bin/systemd_booted; then + /bin/systemctl try-restart sshd.service || : + else + %service -q sshd reload + fi +fi +%systemd_trigger sshd.service +if [ -x /bin/systemd_booted ] && /bin/systemd_booted; then +%banner %{name}-server -e << EOF +!!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!! +! Native systemd support for sshd has been installed. ! +! Restarting sshd.service with systemctl WILL kill all ! +! active ssh sessions (daemon as such will be started). ! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +EOF +fi + +%post server-upstart +%upstart_post sshd + +%postun server-upstart +%upstart_postun sshd + +%post -n openldap-schema-openssh-lpk +%openldap_schema_register %{schemadir}/openssh-lpk.schema +%service -q ldap restart + +%postun -n openldap-schema-openssh-lpk +if [ "$1" = "0" ]; then + %openldap_schema_unregister %{schemadir}/openssh-lpk.schema + %service -q ldap restart +fi + +%files +%defattr(644,root,root,755) +%doc TODO README OVERVIEW CREDITS Change* +%attr(755,root,root) %{_bindir}/ssh-key* +#%attr(755,root,root) %{_bindir}/ssh-vulnkey* +%{_mandir}/man1/ssh-key*.1* +#%{_mandir}/man1/ssh-vulnkey*.1* +%dir %{_sysconfdir} +%dir %{_libexecdir} + +%files clients +%defattr(644,root,root,755) +%attr(755,root,root) %{_bindir}/ssh +%attr(755,root,root) %{_bindir}/slogin +%attr(755,root,root) %{_bindir}/sftp +%attr(755,root,root) %{_bindir}/ssh-agent +%attr(755,root,root) %{_bindir}/ssh-add +%attr(755,root,root) %{_bindir}/ssh-copy-id +%attr(755,root,root) %{_bindir}/scp +%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/ssh_config +%config(noreplace,missingok) %verify(not md5 mtime size) /etc/env.d/SSH_ASKPASS +%{_mandir}/man1/scp.1* +%{_mandir}/man1/ssh.1* +%{_mandir}/man1/slogin.1* +%{_mandir}/man1/sftp.1* +%{_mandir}/man1/ssh-agent.1* +%{_mandir}/man1/ssh-add.1* +%{_mandir}/man1/ssh-copy-id.1* +%{_mandir}/man5/ssh_config.5* +%lang(it) %{_mandir}/it/man1/ssh.1* +%lang(it) %{_mandir}/it/man5/ssh_config.5* +%lang(pl) %{_mandir}/pl/man1/scp.1* +%lang(zh_CN) %{_mandir}/zh_CN/man1/scp.1* + +# for host-based auth (suid required for accessing private host key) +#%attr(4755,root,root) %{_libexecdir}/ssh-keysign +#%{_mandir}/man8/ssh-keysign.8* + +%files clients-agent-profile_d +%defattr(644,root,root,755) +%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/ssh-agent.conf +%attr(755,root,root) /etc/profile.d/ssh-agent.sh + +%files clients-agent-xinitrc +%defattr(644,root,root,755) +%attr(755,root,root) /etc/X11/xinit/xinitrc.d/ssh-agent.sh + +%files server +%defattr(644,root,root,755) +%attr(755,root,root) %{_sbindir}/sshd +%attr(755,root,root) %{_libexecdir}/sftp-server +%attr(755,root,root) %{_libexecdir}/ssh-keysign +%attr(755,root,root) %{_libexecdir}/ssh-pkcs11-helper +%attr(755,root,root) %{_libexecdir}/sshd-keygen +%{_mandir}/man8/sshd.8* +%{_mandir}/man8/sftp-server.8* +%{_mandir}/man8/ssh-keysign.8* +%{_mandir}/man8/ssh-pkcs11-helper.8* +%{_mandir}/man5/sshd_config.5* +%{_mandir}/man5/moduli.5* +%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/sshd_config +%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/pam.d/sshd +%attr(640,root,root) %{_sysconfdir}/moduli +%attr(754,root,root) /etc/rc.d/init.d/sshd +%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/sysconfig/sshd +%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/security/blacklist.sshd +%{systemdunitdir}/sshd.service +%{systemdunitdir}/sshd.socket +%{systemdunitdir}/sshd@.service + +%if %{with ldap} +%files server-ldap +%defattr(644,root,root,755) +%doc HOWTO.ldap-keys ldap.conf +%attr(755,root,root) %{_libexecdir}/ssh-ldap-helper +%attr(755,root,root) %{_libexecdir}/ssh-ldap-wrapper +%{_mandir}/man5/ssh-ldap.conf.5* +%{_mandir}/man8/ssh-ldap-helper.8* +%endif + +%if %{with gnome} || %{with gtk} +%files gnome-askpass +%defattr(644,root,root,755) +%config(noreplace,missingok) %verify(not md5 mtime size) /etc/env.d/GNOME_SSH_ASKPASS* +%dir %{_libexecdir}/ssh +%attr(755,root,root) %{_libexecdir}/ssh/ssh-askpass +%attr(755,root,root) %{_libexecdir}/ssh-askpass +%endif + +%if %{with ldap} +%files -n openldap-schema-openssh-lpk +%defattr(644,root,root,755) +%{schemadir}/openssh-lpk.schema +%endif + +%if "%{pld_release}" != "ti" +%files server-upstart +%defattr(644,root,root,755) +%config(noreplace) %verify(not md5 mtime size) /etc/init/sshd.conf +%endif diff --git a/openssh.sysconfig b/openssh.sysconfig new file mode 100644 index 0000000..2fad1f0 --- /dev/null +++ b/openssh.sysconfig @@ -0,0 +1,7 @@ +# Customized setings for ssh + +# Leave -u (max user processes) as ulimited to avoid nasty suprise +SERVICE_LIMITS="-u unlimited -Sc 0" + +# Define nice level for ssh +SERVICE_RUN_NICE_LEVEL="+0" diff --git a/opensshd.init b/opensshd.init new file mode 100755 index 0000000..ab59061 --- /dev/null +++ b/opensshd.init @@ -0,0 +1,178 @@ +#!/bin/sh +# +# sshd sshd (secure shell daemon) +# +# chkconfig: 345 22 88 +# +# description: sshd (secure shell daemon) is a server part of the ssh suite. \ +# Ssh can be used for remote login, remote file copying, TCP port \ +# forwarding etc. Ssh offers strong encryption and authentication. + +# Source function library +. /etc/rc.d/init.d/functions + +upstart_controlled --except init configtest + +# Get network config +. /etc/sysconfig/network + +SSHD_OOM_ADJUST=-1000 +PIDFILE=/var/run/sshd.pid + +# Get service config +[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd + +# Check that networking is up. +if is_yes "${NETWORKING}"; then + if [ ! -f /var/lock/subsys/network -a "$1" != stop -a "$1" != status -a "$1" != init ]; then + msg_network_down "OpenSSH" + exit 1 + fi +else + exit 0 +fi + +adjust_oom() { + if [ -e $PIDFILE ]; then + for pid in $(cat $PIDFILE); do + echo "$SSHD_OOM_ADJUST" 2>/dev/null > /proc/$pid/oom_score_adj + done + fi +} + +checkconfig() { + ssh_gen_keys + /usr/sbin/sshd -t || exit 1 +} + +ssh_gen_keys() { + # generate new keys with empty passwords if they do not exist + if [ ! -f /etc/ssh/ssh_host_key -o ! -s /etc/ssh/ssh_host_key ]; then + /usr/bin/ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_key + fi + if [ ! -f /etc/ssh/ssh_host_rsa_key -o ! -s /etc/ssh/ssh_host_rsa_key ]; then + /usr/bin/ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_rsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_rsa_key + fi + if [ ! -f /etc/ssh/ssh_host_dsa_key -o ! -s /etc/ssh/ssh_host_dsa_key ]; then + /usr/bin/ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_dsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_dsa_key + fi + if [ ! -f /etc/ssh/ssh_host_ecdsa_key -o ! -s /etc/ssh/ssh_host_ecdsa_key ]; then + /usr/bin/ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_ecdsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_ecdsa_key + fi # ecdsa +} + +start() { + # Check if the service is already running? + if [ -f /var/lock/subsys/sshd ]; then + msg_already_running "OpenSSH" + return + fi + + checkconfig + + if [ ! -s /etc/ssh/ssh_host_key ]; then + msg_not_running "OpenSSH" + nls "No SSH host key found! You must run \"%s init\" first." "$0" + exit 1 + fi + + if is_yes "$IPV4_NETWORKING" && is_no "$IPV6_NETWORKING"; then + OPTIONS="$OPTIONS -4" + fi + if is_yes "$IPV6_NETWORKING" && is_no "$IPV4_NETWORKING"; then + OPTIONS="$OPTIONS -6" + fi + + msg_starting "OpenSSH" + daemon --pidfile $PIDFILE /usr/sbin/sshd $OPTIONS + RETVAL=$? + adjust_oom + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/sshd +} + +stop() { + if [ ! -f /var/lock/subsys/sshd ]; then + msg_not_running "OpenSSH" + return + fi + + msg_stopping "OpenSSH" + # we use start-stop-daemon to stop sshd, as it is unacceptable for such + # critical service as sshd to kill it by procname, but unfortunately + # rc-scripts does not provide way to kill *only* by pidfile + start-stop-daemon --stop --quiet --pidfile $PIDFILE && ok || fail + rm -f /var/lock/subsys/sshd >/dev/null 2>&1 +} + +reload() { + if [ ! -f /var/lock/subsys/sshd ]; then + msg_not_running "OpenSSH" + RETVAL=7 + return + fi + + checkconfig + msg_reloading "OpenSSH" + killproc sshd -HUP + RETVAL=$? +} + +condrestart() { + if [ ! -f /var/lock/subsys/sshd ]; then + msg_not_running "OpenSSH" + RETVAL=$1 + return + fi + + checkconfig + stop + start +} + +RETVAL=0 +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + checkconfig + stop + start + ;; + try-restart) + condrestart 0 + ;; + reload|force-reload) + reload + ;; + configtest) + checkconfig + ;; + init) + nls "Now the SSH host key will be generated. Please note, that if you" + nls "will use password for the key, you will need to type it on each" + nls "reboot." + ssh_gen_keys + ;; + status) + status --pidfile $PIDFILE sshd + exit $? + ;; + *) + msg_usage "$0 {start|stop|restart|try-restart|reload|force-reload|configtest|init|status}" + exit 3 +esac + +exit $RETVAL diff --git a/opensshd.pamd b/opensshd.pamd new file mode 100644 index 0000000..1dd3461 --- /dev/null +++ b/opensshd.pamd @@ -0,0 +1,12 @@ +#%PAM-1.0 +auth required pam_listfile.so item=user sense=deny file=/etc/security/blacklist.sshd onerr=succeed +auth include system-auth +account required pam_shells.so +account required pam_nologin.so +account required pam_access.so +account include system-auth +password include system-auth +session required pam_loginuid.so +session optional pam_keyinit.so force revoke +session include system-auth +session optional pam_mail.so diff --git a/opensshd.upstart b/opensshd.upstart new file mode 100644 index 0000000..7836e17 --- /dev/null +++ b/opensshd.upstart @@ -0,0 +1,36 @@ + +start on pld.network-started and started SERVICE_syslog=y and started random +stop on pld.shutdown-started + +respawn +respawn limit 10 5 +console output +oom never + +pre-start script + test -x /usr/sbin/sshd || { stop; exit 0; } + test -c /dev/null || { stop; exit 0; } + + if [ ! -s /etc/ssh/ssh_host_key \ + -o ! -s /etc/ssh/ssh_host_rsa_key \ + -o ! -s /etc/ssh/ssh_host_dsa_key \ + -o ! -s /etc/ssh/ssh_host_ecdsa_key \ + ]; then + # call gen keys if any of the files above is missing or empty + /etc/rc.d/init.d/sshd ssh_gen_keys + fi +end script + +script + . /etc/rc.d/init.d/functions + . /etc/sysconfig/network + + if is_yes "$IPV4_NETWORKING" && is_no "$IPV6_NETWORKING"; then + OPTIONS="$OPTIONS -4" + fi + if is_yes "$IPV6_NETWORKING" && is_no "$IPV4_NETWORKING"; then + OPTIONS="$OPTIONS -6" + fi + + exec /usr/sbin/sshd -D $OPTIONS +end script diff --git a/ssh-agent.conf b/ssh-agent.conf new file mode 100644 index 0000000..7d52259 --- /dev/null +++ b/ssh-agent.conf @@ -0,0 +1,19 @@ +# This is configuration file for /etc/profile.d/ssh-agent.sh script +# which allows to run exactly one copy of ssh-agent per user and +# propagate SSH_AGENT_PID and SSH_AUTH_SOCK environment variables +# on all login sessions. +# For system-wide configuration you can put this file +# in /etc/ssh/ssh-agent.conf. +# For per-user configuration you can put this +# in $HOME/.ssh/ssh-agent.conf . +# Per-user configuration override system-wide settings. +# This file must have valid shell syntax (see sh(1)). + +# Run ssh-agent at first user login: +# ssh_agent_enable=yes +ssh_agent_enable=no + +# Pass to ssh-agent commandline options +# ssh_agent_flags="-t 3600" +# For valid options see ssh-agent(1). Options must be quoted. +ssh_agent_flags= diff --git a/ssh-agent.sh b/ssh-agent.sh new file mode 100644 index 0000000..623c581 --- /dev/null +++ b/ssh-agent.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# ssh-agent.sh is a sh/bash/zsh compatible script sourced from /etc/profile.d/ +# at user login. It reads configuration from /etc/ssh/ssh-agent.conf +# or ~/.ssh/ssh-agent.conf if any exist and, depending on settings +# in configuration file, runs ssh-agent with given options at first user login, +# exports SSH_AGENT_PID SSH_AUTH_SOCK environment variables to all login +# sessions. If ssh-agent is already started for given user, script exports only +# SSH_AGENT_PID SSH_AUTH_SOCK to new user's login session. + +[ -f /etc/ssh/ssh-agent.conf ] && SSH_AGENT_CONF="/etc/ssh/ssh-agent.conf" +[ -f "${HOME}/.ssh/ssh-agent.conf" ] && SSH_AGENT_CONF="${HOME}/.ssh/ssh-agent.conf" +if [ -s "$SSH_AGENT_CONF" ] ; then + . "$SSH_AGENT_CONF" || : + if [ "$ssh_agent_enable" = "yes" -o "$ssh_agent_enable" = "YES" ] ; then + SSH_AGENT_DATA="${HOME}/.ssh/SSH-AGENT-DATA" + if [ -s "$SSH_AGENT_DATA" ] ; then + . "$SSH_AGENT_DATA" > /dev/null + if [ "$(ps uhp "$SSH_AGENT_PID" 2>/dev/null | awk '$1 ~ ENVIRON["USER"] {print $11}')" != "ssh-agent" ] ; then + ssh-agent $ssh_agent_flags > "$SSH_AGENT_DATA" + . "$SSH_AGENT_DATA" > /dev/null + fi + else + ssh-agent $ssh_agent_flags > "$SSH_AGENT_DATA" + . "$SSH_AGENT_DATA" > /dev/null + fi + fi +fi + diff --git a/sshd-keygen b/sshd-keygen new file mode 100644 index 0000000..94ac509 --- /dev/null +++ b/sshd-keygen @@ -0,0 +1,28 @@ +#!/bin/sh + +# Get service config +[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd + +# generate new keys with empty passwords if they do not exist +if [ ! -f /etc/ssh/ssh_host_key -o ! -s /etc/ssh/ssh_host_key ]; then + /usr/bin/ssh-keygen -t rsa1 -f /etc/ssh/ssh_host_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_key +fi +if [ ! -f /etc/ssh/ssh_host_rsa_key -o ! -s /etc/ssh/ssh_host_rsa_key ]; then + /usr/bin/ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_rsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_rsa_key +fi +if [ ! -f /etc/ssh/ssh_host_dsa_key -o ! -s /etc/ssh/ssh_host_dsa_key ]; then + /usr/bin/ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_dsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_dsa_key +fi +if [ ! -f /etc/ssh/ssh_host_ecdsa_key -o ! -s /etc/ssh/ssh_host_ecdsa_key ]; then + /usr/bin/ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N '' >&2 + chmod 600 /etc/ssh/ssh_host_ecdsa_key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/ssh/ssh_host_ecdsa_key +fi # ecdsa + +exit 0 diff --git a/sshd.service b/sshd.service new file mode 100644 index 0000000..04e4505 --- /dev/null +++ b/sshd.service @@ -0,0 +1,14 @@ +[Unit] +Description=OpenSSH server daemon +After=syslog.target network.target auditd.service + +[Service] +EnvironmentFile=-/etc/sysconfig/sshd +ExecStartPre=@@LIBEXECDIR@@/sshd-keygen +ExecStart=/usr/sbin/sshd -D $OPTIONS +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/sshd.socket b/sshd.socket new file mode 100644 index 0000000..94b9533 --- /dev/null +++ b/sshd.socket @@ -0,0 +1,10 @@ +[Unit] +Description=OpenSSH Server Socket +Conflicts=sshd.service + +[Socket] +ListenStream=22 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/sshd@.service b/sshd@.service new file mode 100644 index 0000000..7a8db43 --- /dev/null +++ b/sshd@.service @@ -0,0 +1,9 @@ +[Unit] +Description=OpenSSH per-connection server daemon +After=syslog.target auditd.service + +[Service] +EnvironmentFile=/etc/sysconfig/sshd +ExecStartPre=/usr/sbin/sshd-keygen +ExecStart=-/usr/sbin/sshd -i $OPTIONS +StandardInput=socket -- 2.52.0