diff --git a/openssh-5.9p1-ctr-evp-fast.patch b/openssh-5.9p1-ctr-evp-fast.patch deleted file mode 100644 index 5d17aab..0000000 --- a/openssh-5.9p1-ctr-evp-fast.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c ---- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100 -+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100 -@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in - - struct ssh_aes_ctr_ctx - { -- AES_KEY aes_ctx; -+ EVP_CIPHER_CTX ecbctx; - u_char aes_counter[AES_BLOCK_SIZE]; - }; - -@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char - { - struct ssh_aes_ctr_ctx *c; - size_t n = 0; -- u_char buf[AES_BLOCK_SIZE]; -+ u_char ctrbuf[AES_BLOCK_SIZE*256]; -+ u_char buf[AES_BLOCK_SIZE*256]; - - if (len == 0) - return (1); - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) - return (0); - -- while ((len--) > 0) { -+ for (; len > 0; len -= sizeof(u_int)) { -+ u_int r,a,b; -+ - if (n == 0) { -- AES_encrypt(c->aes_counter, buf, &c->aes_ctx); -- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ int outl, i, buflen; -+ -+ buflen = MIN(len, sizeof(ctrbuf)); -+ -+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) { -+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE); -+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ } -+ -+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl, -+ ctrbuf, buflen); - } -- *(dest++) = *(src++) ^ buf[n]; -- n = (n + 1) % AES_BLOCK_SIZE; -+ -+ memcpy(&a, src, sizeof(a)); -+ memcpy(&b, &buf[n], sizeof(b)); -+ r = a ^ b; -+ memcpy(dest, &r, sizeof(r)); -+ src += sizeof(a); -+ dest += sizeof(r); -+ -+ n = (n + sizeof(b)) % sizeof(buf); - } -+ memset(ctrbuf, '\0', sizeof(ctrbuf)); -+ memset(buf, '\0', sizeof(buf)); - return (1); - } - -@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } -- if (key != NULL) -- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, -- &c->aes_ctx); -+ -+ EVP_CIPHER_CTX_init(&c->ecbctx); -+ -+ if (key != NULL) { -+ const EVP_CIPHER *cipher; -+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) { -+ case 128: -+ cipher = EVP_aes_128_ecb(); -+ break; -+ case 192: -+ cipher = EVP_aes_192_ecb(); -+ break; -+ case 256: -+ cipher = EVP_aes_256_ecb(); -+ break; -+ default: -+ fatal("ssh_aes_ctr_init: wrong aes key length"); -+ } -+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL)) -+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption"); -+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0); -+ } - if (iv != NULL) - memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); - return (1); -@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { -+ EVP_CIPHER_CTX_cleanup(&c->ecbctx); - memset(c, 0, sizeof(*c)); - xfree(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); diff --git a/openssh-6.1p1-privsep-selinux.patch b/openssh-6.1p1-privsep-selinux.patch deleted file mode 100644 index 881c71a..0000000 --- a/openssh-6.1p1-privsep-selinux.patch +++ /dev/null @@ -1,104 +0,0 @@ -diff -up openssh-6.1p1/openbsd-compat/port-linux.c.privsep-selinux openssh-6.1p1/openbsd-compat/port-linux.c ---- openssh-6.1p1/openbsd-compat/port-linux.c.privsep-selinux 2012-11-05 14:46:39.334809203 +0100 -+++ openssh-6.1p1/openbsd-compat/port-linux.c 2012-11-05 14:54:32.614504884 +0100 -@@ -505,6 +505,25 @@ ssh_selinux_change_context(const char *n - xfree(newctx); - } - -+void -+ssh_selinux_copy_context(void) -+{ -+ security_context_t *ctx; -+ -+ if (!ssh_selinux_enabled()) -+ return; -+ -+ if (getexeccon((security_context_t *)&ctx) != 0) { -+ logit("%s: getcon failed with %s", __func__, strerror (errno)); -+ return; -+ } -+ if (ctx != NULL) { -+ if (setcon(ctx) != 0) -+ logit("%s: setcon failed with %s", __func__, strerror (errno)); -+ freecon(ctx); -+ } -+} -+ - #endif /* WITH_SELINUX */ - - #ifdef LINUX_OOM_ADJUST -diff -up openssh-6.1p1/openbsd-compat/port-linux.h.privsep-selinux openssh-6.1p1/openbsd-compat/port-linux.h ---- openssh-6.1p1/openbsd-compat/port-linux.h.privsep-selinux 2011-01-25 02:16:18.000000000 +0100 -+++ openssh-6.1p1/openbsd-compat/port-linux.h 2012-11-05 14:46:39.339809234 +0100 -@@ -24,6 +24,7 @@ int ssh_selinux_enabled(void); - void ssh_selinux_setup_pty(char *, const char *); - void ssh_selinux_setup_exec_context(char *); - void ssh_selinux_change_context(const char *); -+void ssh_selinux_copy_context(void); - void ssh_selinux_setfscreatecon(const char *); - #endif - -diff -up openssh-6.1p1/session.c.privsep-selinux openssh-6.1p1/session.c ---- openssh-6.1p1/session.c.privsep-selinux 2012-12-03 09:43:11.727505761 +0100 -+++ openssh-6.1p1/session.c 2012-12-03 09:54:50.455688902 +0100 -@@ -1519,6 +1519,9 @@ do_setusercontext(struct passwd *pw) - pw->pw_uid); - chroot_path = percent_expand(tmp, "h", pw->pw_dir, - "u", pw->pw_name, (char *)NULL); -+#ifdef WITH_SELINUX -+ ssh_selinux_copy_context(); -+#endif - safely_chroot(chroot_path, pw->pw_uid); - free(tmp); - free(chroot_path); -@@ -1533,6 +1536,12 @@ do_setusercontext(struct passwd *pw) - /* Permanently switch to the desired uid. */ - permanently_set_uid(pw); - #endif -+ -+#ifdef WITH_SELINUX -+ if (options.chroot_directory == NULL || -+ strcasecmp(options.chroot_directory, "none") == 0) -+ ssh_selinux_copy_context(); -+#endif - } - - if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) -@@ -1787,9 +1796,6 @@ do_child(Session *s, const char *command - argv[i] = NULL; - optind = optreset = 1; - __progname = argv[0]; --#ifdef WITH_SELINUX -- ssh_selinux_change_context("sftpd_t"); --#endif - exit(sftp_server_main(i, argv, s->pw)); - } - -diff -up openssh-6.1p1/sshd.c.privsep-selinux openssh-6.1p1/sshd.c ---- openssh-6.1p1/sshd.c.privsep-selinux 2013-02-24 11:29:32.997823377 +0100 -+++ openssh-6.1p1/sshd.c 2013-02-24 11:43:34.171182720 +0100 -@@ -653,6 +653,10 @@ privsep_preauth_child(void) - /* Demote the private keys to public keys. */ - demote_sensitive_data(); - -+#ifdef WITH_SELINUX -+ ssh_selinux_change_context("sshd_net_t"); -+#endif -+ - /* Change our root directory */ - if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) - fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, -@@ -794,6 +798,13 @@ privsep_postauth(Authctxt *authctxt) - do_setusercontext(authctxt->pw); - - skip: -+#ifdef WITH_SELINUX -+ /* switch SELinux content for root too */ -+ if (authctxt->pw->pw_uid == 0) { -+ ssh_selinux_copy_context(); -+ } -+#endif -+ - /* It is safe now to apply the key state */ - monitor_apply_keystate(pmonitor); - diff --git a/openssh-6.1p1-redhat.patch b/openssh-6.1p1-redhat.patch deleted file mode 100644 index a1fa0e5..0000000 --- a/openssh-6.1p1-redhat.patch +++ /dev/null @@ -1,117 +0,0 @@ -diff -up openssh-6.1p1/ssh_config.redhat openssh-6.1p1/ssh_config ---- openssh-6.1p1/ssh_config.redhat 2010-01-12 09:40:27.000000000 +0100 -+++ openssh-6.1p1/ssh_config 2012-10-26 16:28:51.820340584 +0200 -@@ -45,3 +45,14 @@ - # PermitLocalCommand no - # VisualHostKey no - # ProxyCommand ssh -q -W %h:%p gateway.example.com -+Host * -+ GSSAPIAuthentication yes -+# 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 -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+ SendEnv XMODIFIERS -diff -up openssh-6.1p1/sshd_config.0.redhat openssh-6.1p1/sshd_config.0 ---- openssh-6.1p1/sshd_config.0.redhat 2012-10-26 16:28:51.762340584 +0200 -+++ openssh-6.1p1/sshd_config.0 2012-10-26 16:28:51.821340584 +0200 -@@ -583,9 +583,9 @@ DESCRIPTION - - SyslogFacility - Gives the facility code that is used when logging messages from -- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, -- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The -- default is AUTH. -+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, -+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. -+ The default is AUTH. - - TCPKeepAlive - Specifies whether the system should send TCP keepalive messages -diff -up openssh-6.1p1/sshd_config.5.redhat openssh-6.1p1/sshd_config.5 ---- openssh-6.1p1/sshd_config.5.redhat 2012-10-26 16:28:51.763340584 +0200 -+++ openssh-6.1p1/sshd_config.5 2012-10-26 16:28:51.822340584 +0200 -@@ -1015,7 +1015,7 @@ Note that this option applies to protoco - .It Cm SyslogFacility - Gives the facility code that is used when logging messages from - .Xr sshd 8 . --The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, -+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, - LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. - The default is AUTH. - .It Cm TCPKeepAlive -diff -up openssh-6.1p1/sshd_config.redhat openssh-6.1p1/sshd_config ---- openssh-6.1p1/sshd_config.redhat 2012-10-26 16:28:51.819340584 +0200 -+++ openssh-6.1p1/sshd_config 2012-10-26 16:31:44.773340564 +0200 -@@ -10,6 +10,10 @@ - # possible, but leave them commented. Uncommented options override the - # default value. - -+# If you want to change the port on a SELinux system, you have to tell -+# SELinux about this change. -+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER -+# - #Port 22 - #AddressFamily any - #ListenAddress 0.0.0.0 -@@ -32,6 +36,7 @@ - # Logging - # obsoletes QuietMode and FascistLogging - #SyslogFacility AUTH -+SyslogFacility AUTHPRIV - #LogLevel INFO - - # Authentication: -@@ -67,9 +72,11 @@ AuthorizedKeysFile .ssh/authorized_keys - # To disable tunneled clear text passwords, change to no here! - #PasswordAuthentication yes - #PermitEmptyPasswords no -+PasswordAuthentication yes - - # Change to no to disable s/key passwords - #ChallengeResponseAuthentication yes -+ChallengeResponseAuthentication no - - # Kerberos options - #KerberosAuthentication no -@@ -79,7 +86,9 @@ AuthorizedKeysFile .ssh/authorized_keys - - # GSSAPI options - #GSSAPIAuthentication no -+GSSAPIAuthentication yes - #GSSAPICleanupCredentials yes -+GSSAPICleanupCredentials yes - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -@@ -91,11 +100,13 @@ AuthorizedKeysFile .ssh/authorized_keys - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. - #UsePAM no -+UsePAM yes - - #AllowAgentForwarding yes - #AllowTcpForwarding yes - #GatewayPorts no - #X11Forwarding no -+X11Forwarding yes - #X11DisplayOffset 10 - #X11UseLocalhost yes - #PrintMotd yes -@@ -117,6 +128,12 @@ UsePrivilegeSeparation sandbox # Defaul - # no default banner path - #Banner none - -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+AcceptEnv XMODIFIERS -+ - # override default of no subsystems - Subsystem sftp /usr/libexec/sftp-server - diff --git a/openssh-6.2p1-aarch64.patch b/openssh-6.2p1-aarch64.patch deleted file mode 100644 index 5224fbd..0000000 --- a/openssh-6.2p1-aarch64.patch +++ /dev/null @@ -1,1080 +0,0 @@ -diff --git a/config.guess b/config.guess -index 78553c4..b94cde8 100755 ---- a/config.guess -+++ b/config.guess -@@ -2,9 +2,9 @@ - # Attempt to guess a canonical system name. - # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, --# 2011 Free Software Foundation, Inc. -+# 2011, 2012, 2013 Free Software Foundation, Inc. - --timestamp='2011-01-23' -+timestamp='2012-12-23' - - # This file is free software; you can redistribute it and/or modify it - # under the terms of the GNU General Public License as published by -@@ -17,9 +17,7 @@ timestamp='2011-01-23' - # General Public License for more details. - # - # You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA --# 02110-1301, USA. -+# along with this program; if not, see . - # - # As a special exception to the GNU General Public License, if you - # distribute this file as part of a program that contains a -@@ -57,8 +55,8 @@ GNU config.guess ($timestamp) - - Originally written by Per Bothner. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, --2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free --Software Foundation, Inc. -+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -+2012, 2013 Free Software Foundation, Inc. - - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." -@@ -145,7 +143,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or -- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, -+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward -@@ -181,7 +179,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - fi - ;; - *) -- os=netbsd -+ os=netbsd - ;; - esac - # The OS release -@@ -202,6 +200,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; -+ *:Bitrig:*:*) -+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` -+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} -+ exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} -@@ -224,7 +226,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) -- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` -+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on -@@ -299,12 +301,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) -- echo powerpc-ibm-os400 -+ echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; -- arm:riscos:*:*|arm:RISCOS:*:*) -+ arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) -@@ -398,23 +400,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) -- echo m68k-atari-mint${UNAME_RELEASE} -+ echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} -- exit ;; -+ exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) -- echo m68k-atari-mint${UNAME_RELEASE} -+ echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) -- echo m68k-milan-mint${UNAME_RELEASE} -- exit ;; -+ echo m68k-milan-mint${UNAME_RELEASE} -+ exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) -- echo m68k-hades-mint${UNAME_RELEASE} -- exit ;; -+ echo m68k-hades-mint${UNAME_RELEASE} -+ exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) -- echo m68k-unknown-mint${UNAME_RELEASE} -- exit ;; -+ echo m68k-unknown-mint${UNAME_RELEASE} -+ exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; -@@ -484,8 +486,8 @@ EOF - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) -- # DG/UX returns AViiON for all architectures -- UNAME_PROCESSOR=`/usr/bin/uname -p` -+ # DG/UX returns AViiON for all architectures -+ UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ -@@ -498,7 +500,7 @@ EOF - else - echo i586-dg-dgux${UNAME_RELEASE} - fi -- exit ;; -+ exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; -@@ -598,52 +600,52 @@ EOF - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` -- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` -- case "${sc_cpu_version}" in -- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 -- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 -- 532) # CPU_PA_RISC2_0 -- case "${sc_kernel_bits}" in -- 32) HP_ARCH="hppa2.0n" ;; -- 64) HP_ARCH="hppa2.0w" ;; -+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` -+ case "${sc_cpu_version}" in -+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 -+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 -+ 532) # CPU_PA_RISC2_0 -+ case "${sc_kernel_bits}" in -+ 32) HP_ARCH="hppa2.0n" ;; -+ 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 -- esac ;; -- esac -+ esac ;; -+ esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build -- sed 's/^ //' << EOF >$dummy.c -+ sed 's/^ //' << EOF >$dummy.c - -- #define _HPUX_SOURCE -- #include -- #include -+ #define _HPUX_SOURCE -+ #include -+ #include - -- int main () -- { -- #if defined(_SC_KERNEL_BITS) -- long bits = sysconf(_SC_KERNEL_BITS); -- #endif -- long cpu = sysconf (_SC_CPU_VERSION); -+ int main () -+ { -+ #if defined(_SC_KERNEL_BITS) -+ long bits = sysconf(_SC_KERNEL_BITS); -+ #endif -+ long cpu = sysconf (_SC_CPU_VERSION); - -- switch (cpu) -- { -- case CPU_PA_RISC1_0: puts ("hppa1.0"); break; -- case CPU_PA_RISC1_1: puts ("hppa1.1"); break; -- case CPU_PA_RISC2_0: -- #if defined(_SC_KERNEL_BITS) -- switch (bits) -- { -- case 64: puts ("hppa2.0w"); break; -- case 32: puts ("hppa2.0n"); break; -- default: puts ("hppa2.0"); break; -- } break; -- #else /* !defined(_SC_KERNEL_BITS) */ -- puts ("hppa2.0"); break; -- #endif -- default: puts ("hppa1.0"); break; -- } -- exit (0); -- } -+ switch (cpu) -+ { -+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break; -+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break; -+ case CPU_PA_RISC2_0: -+ #if defined(_SC_KERNEL_BITS) -+ switch (bits) -+ { -+ case 64: puts ("hppa2.0w"); break; -+ case 32: puts ("hppa2.0n"); break; -+ default: puts ("hppa2.0"); break; -+ } break; -+ #else /* !defined(_SC_KERNEL_BITS) */ -+ puts ("hppa2.0"); break; -+ #endif -+ default: puts ("hppa1.0"); break; -+ } -+ exit (0); -+ } - EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa -@@ -734,22 +736,22 @@ EOF - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd -- exit ;; -+ exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi -- exit ;; -+ exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd -- exit ;; -+ exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd -- exit ;; -+ exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd -- exit ;; -+ exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; -@@ -773,14 +775,14 @@ EOF - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` -- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` -- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` -- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" -- exit ;; -+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` -+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` -+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" -+ exit ;; - 5000:UNIX_System_V:4.*:*) -- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` -- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` -- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" -+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` -+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` -+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} -@@ -792,30 +794,35 @@ EOF - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) -- case ${UNAME_MACHINE} in -- pc98) -- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; -+ UNAME_PROCESSOR=`/usr/bin/uname -p` -+ case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) -- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; -+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; -+ *:MINGW64*:*) -+ echo ${UNAME_MACHINE}-pc-mingw64 -+ exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; -+ i*:MSYS*:*) -+ echo ${UNAME_MACHINE}-pc-msys -+ exit ;; - i*:windows32*:*) -- # uname -m includes "-pc" on this system. -- echo ${UNAME_MACHINE}-mingw32 -+ # uname -m includes "-pc" on this system. -+ echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) -- case ${UNAME_MACHINE} in -+ case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; -@@ -861,6 +868,13 @@ EOF - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; -+ aarch64:Linux:*:*) -+ echo ${UNAME_MACHINE}-unknown-linux-gnu -+ exit ;; -+ aarch64_be:Linux:*:*) -+ UNAME_MACHINE=aarch64_be -+ echo ${UNAME_MACHINE}-unknown-linux-gnu -+ exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; -@@ -870,7 +884,7 @@ EOF - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; -- esac -+ esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} -@@ -882,20 +896,29 @@ EOF - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else -- echo ${UNAME_MACHINE}-unknown-linux-gnueabi -+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ -+ | grep -q __ARM_PCS_VFP -+ then -+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi -+ else -+ echo ${UNAME_MACHINE}-unknown-linux-gnueabihf -+ fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) -- echo cris-axis-linux-gnu -+ echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) -- echo crisv32-axis-linux-gnu -+ echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - frv:Linux:*:*) -- echo frv-unknown-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu -+ exit ;; -+ hexagon:Linux:*:*) -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu -@@ -937,7 +960,7 @@ EOF - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) -- echo or32-unknown-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu -@@ -963,7 +986,7 @@ EOF - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) -- echo ${UNAME_MACHINE}-unknown-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu -@@ -972,16 +995,16 @@ EOF - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) -- echo ${UNAME_MACHINE}-tilera-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) -- echo x86_64-unknown-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) -- echo ${UNAME_MACHINE}-unknown-linux-gnu -+ echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. -@@ -990,11 +1013,11 @@ EOF - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) -- # Unixware is an offshoot of SVR4, but it has its own version -- # number series starting with 2... -- # I am not positive that other SVR4 systems won't match this, -+ # Unixware is an offshoot of SVR4, but it has its own version -+ # number series starting with 2... -+ # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. -- # Use sysv4.2uw... so that sysv4* matches it. -+ # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) -@@ -1026,7 +1049,7 @@ EOF - fi - exit ;; - i*86:*:5:[678]*) -- # UnixWare 7.x, OpenUNIX and OpenServer 6. -+ # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; -@@ -1054,13 +1077,13 @@ EOF - exit ;; - pc:*:*:*) - # Left here for compatibility: -- # uname -m prints for DJGPP always 'pc', but it prints nothing about -- # the processor, so we play safe by assuming i586. -+ # uname -m prints for DJGPP always 'pc', but it prints nothing about -+ # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp -- exit ;; -+ exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; -@@ -1095,8 +1118,8 @@ EOF - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) -- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ -- && { echo i486-ncr-sysv4; exit; } ;; -+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ -+ && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ -@@ -1139,10 +1162,10 @@ EOF - echo ns32k-sni-sysv - fi - exit ;; -- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort -- # says -- echo i586-unisys-sysv4 -- exit ;; -+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort -+ # says -+ echo i586-unisys-sysv4 -+ exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm -@@ -1168,11 +1191,11 @@ EOF - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then -- echo mips-nec-sysv${UNAME_RELEASE} -+ echo mips-nec-sysv${UNAME_RELEASE} - else -- echo mips-unknown-sysv${UNAME_RELEASE} -+ echo mips-unknown-sysv${UNAME_RELEASE} - fi -- exit ;; -+ exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; -@@ -1185,6 +1208,9 @@ EOF - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; -+ x86_64:Haiku:*:*) -+ echo x86_64-unknown-haiku -+ exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; -@@ -1240,7 +1266,7 @@ EOF - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; -- NSE-?:NONSTOP_KERNEL:*:*) -+ NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) -@@ -1285,13 +1311,13 @@ EOF - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) -- echo mips-sei-seiux${UNAME_RELEASE} -+ echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) -- UNAME_MACHINE=`(uname -p) 2>/dev/null` -+ UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; -@@ -1309,11 +1335,11 @@ EOF - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -+ x86_64:VMkernel:*:*) -+ echo ${UNAME_MACHINE}-unknown-esx -+ exit ;; - esac - --#echo '(No uname command or uname output not recognized.)' 1>&2 --#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 -- - eval $set_cc_for_build - cat >$dummy.c < - printf ("m68k-sony-newsos%s\n", - #ifdef NEWSOS4 -- "4" -+ "4" - #else -- "" -+ "" - #endif -- ); exit (0); -+ ); exit (0); - #endif - #endif - -diff --git a/config.sub b/config.sub -index 2d81696..eee8dcc 100755 ---- a/config.sub -+++ b/config.sub -@@ -2,9 +2,9 @@ - # Configuration validation subroutine script. - # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, --# 2011 Free Software Foundation, Inc. -+# 2011, 2012, 2013 Free Software Foundation, Inc. - --timestamp='2011-01-01' -+timestamp='2012-12-23' - - # This file is (in principle) common to ALL GNU software. - # The presence of a machine in this file suggests that SOME GNU software -@@ -21,9 +21,7 @@ timestamp='2011-01-01' - # GNU General Public License for more details. - # - # You should have received a copy of the GNU General Public License --# along with this program; if not, write to the Free Software --# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA --# 02110-1301, USA. -+# along with this program; if not, see . - # - # As a special exception to the GNU General Public License, if you - # distribute this file as part of a program that contains a -@@ -76,8 +74,8 @@ version="\ - GNU config.sub ($timestamp) - - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, --2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free --Software Foundation, Inc. -+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -+2012, 2013 Free Software Foundation, Inc. - - This is free software; see the source for copying conditions. There is NO - warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." -@@ -125,13 +123,17 @@ esac - maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` - case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ -- linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ -+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; -+ android-linux) -+ os=-linux-android -+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown -+ ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] -@@ -154,12 +156,12 @@ case $os in - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -- -apple | -axis | -knuth | -cray | -microblaze) -+ -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; -- -bluegene*) -- os=-cnk -+ -bluegene*) -+ os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= -@@ -175,10 +177,10 @@ case $os in - os=-chorusos - basic_machine=$1 - ;; -- -chorusrdb) -- os=-chorusrdb -+ -chorusrdb) -+ os=-chorusrdb - basic_machine=$1 -- ;; -+ ;; - -hiux*) - os=-hiuxwe2 - ;; -@@ -223,6 +225,12 @@ case $os in - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; -+ -lynx*178) -+ os=-lynxos178 -+ ;; -+ -lynx*5) -+ os=-lynxos5 -+ ;; - -lynx*) - os=-lynxos - ;; -@@ -247,20 +255,27 @@ case $basic_machine in - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ -+ | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ -- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ -+ | arc \ -+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ -+ | avr | avr32 \ -+ | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ -+ | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ -+ | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ -+ | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ -- | maxq | mb | microblaze | mcore | mep | metag \ -+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ -@@ -286,22 +301,23 @@ case $basic_machine in - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ -+ | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ -- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ -+ | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ -- | rx \ -+ | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ -- | spu | strongarm \ -- | tahoe | thumb | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ -+ | spu \ -+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ -- | v850 | v850e \ -+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ -- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ -+ | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; -@@ -314,8 +330,7 @@ case $basic_machine in - c6x) - basic_machine=tic6x-unknown - ;; -- m6811 | m68hc11 | m6812 | m68hc12 | picochip) -- # Motorola 68HC11/12. -+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; -@@ -325,6 +340,21 @@ case $basic_machine in - basic_machine=mt-unknown - ;; - -+ strongarm | thumb | xscale) -+ basic_machine=arm-unknown -+ ;; -+ xgate) -+ basic_machine=$basic_machine-unknown -+ os=-none -+ ;; -+ xscaleeb) -+ basic_machine=armeb-unknown -+ ;; -+ -+ xscaleel) -+ basic_machine=armel-unknown -+ ;; -+ - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. -@@ -339,11 +369,13 @@ case $basic_machine in - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ -+ | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ -+ | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ -@@ -352,12 +384,15 @@ case $basic_machine in - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ -+ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ -+ | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ -- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ -+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ -+ | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ -@@ -382,24 +417,26 @@ case $basic_machine in - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ -+ | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ -- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ -+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ -- | romp-* | rs6000-* | rx-* \ -+ | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ -- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ -- | tahoe-* | thumb-* \ -+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ -+ | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ -- | tile-* | tilegx-* \ -+ | tile*-* \ - | tron-* \ - | ubicom32-* \ -- | v850-* | v850e-* | vax-* \ -+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ -+ | vax-* \ - | we32k-* \ -- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ -+ | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) -@@ -424,7 +461,7 @@ case $basic_machine in - basic_machine=a29k-amd - os=-udi - ;; -- abacus) -+ abacus) - basic_machine=abacus-unknown - ;; - adobe68k) -@@ -507,7 +544,7 @@ case $basic_machine in - basic_machine=c90-cray - os=-unicos - ;; -- cegcc) -+ cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; -@@ -697,7 +734,6 @@ case $basic_machine in - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; --# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 -@@ -755,9 +791,13 @@ case $basic_machine in - basic_machine=ns32k-utek - os=-sysv - ;; -- microblaze) -+ microblaze*) - basic_machine=microblaze-xilinx - ;; -+ mingw64) -+ basic_machine=x86_64-pc -+ os=-mingw64 -+ ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 -@@ -794,10 +834,18 @@ case $basic_machine in - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; -+ msys) -+ basic_machine=i386-pc -+ os=-msys -+ ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; -+ nacl) -+ basic_machine=le32-unknown -+ os=-nacl -+ ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 -@@ -862,10 +910,10 @@ case $basic_machine in - np1) - basic_machine=np1-gould - ;; -- neo-tandem) -+ neo-tandem) - basic_machine=neo-tandem - ;; -- nse-tandem) -+ nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) -@@ -950,9 +998,10 @@ case $basic_machine in - ;; - power) basic_machine=power-ibm - ;; -- ppc) basic_machine=powerpc-unknown -+ ppc | ppcbe) basic_machine=powerpc-unknown - ;; -- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` -+ ppc-* | ppcbe-*) -+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown -@@ -977,7 +1026,11 @@ case $basic_machine in - basic_machine=i586-unknown - os=-pw32 - ;; -- rdos) -+ rdos | rdos64) -+ basic_machine=x86_64-pc -+ os=-rdos -+ ;; -+ rdos32) - basic_machine=i386-pc - os=-rdos - ;; -@@ -1046,6 +1099,9 @@ case $basic_machine in - basic_machine=i860-stratus - os=-sysv4 - ;; -+ strongarm-* | thumb-*) -+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` -+ ;; - sun2) - basic_machine=m68000-sun - ;; -@@ -1102,13 +1158,8 @@ case $basic_machine in - basic_machine=t90-cray - os=-unicos - ;; -- # This must be matched before tile*. -- tilegx*) -- basic_machine=tilegx-unknown -- os=-linux-gnu -- ;; - tile*) -- basic_machine=tile-unknown -+ basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) -@@ -1178,6 +1229,9 @@ case $basic_machine in - xps | xps100) - basic_machine=xps100-honeywell - ;; -+ xscale-* | xscalee[bl]-*) -+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` -+ ;; - ymp) - basic_machine=ymp-cray - os=-unicos -@@ -1275,11 +1329,11 @@ esac - if [ x"$os" != x"" ] - then - case $os in -- # First match some system type aliases -- # that might get confused with valid system types. -+ # First match some system type aliases -+ # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. -- -auroraux) -- os=-auroraux -+ -auroraux) -+ os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` -@@ -1309,15 +1363,15 @@ case $os in - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ -- | -openbsd* | -solidbsd* \ -+ | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ -- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ -- | -mingw32* | -linux-gnu* | -linux-android* \ -- | -linux-newlib* | -linux-uclibc* \ -+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ -+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ -+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ -@@ -1364,7 +1418,7 @@ case $os in - -opened*) - os=-openedition - ;; -- -os400*) -+ -os400*) - os=-os400 - ;; - -wince*) -@@ -1413,7 +1467,7 @@ case $os in - -sinix*) - os=-sysv4 - ;; -- -tpf*) -+ -tpf*) - os=-tpf - ;; - -triton*) -@@ -1458,8 +1512,8 @@ case $os in - -dicos*) - os=-dicos - ;; -- -nacl*) -- ;; -+ -nacl*) -+ ;; - -none) - ;; - *) -@@ -1482,10 +1536,10 @@ else - # system, and we'll never get to this point. - - case $basic_machine in -- score-*) -+ score-*) - os=-elf - ;; -- spu-*) -+ spu-*) - os=-elf - ;; - *-acorn) -@@ -1497,8 +1551,11 @@ case $basic_machine in - arm*-semi) - os=-aout - ;; -- c4x-* | tic4x-*) -- os=-coff -+ c4x-* | tic4x-*) -+ os=-coff -+ ;; -+ hexagon-*) -+ os=-elf - ;; - tic54x-*) - os=-coff -@@ -1527,14 +1584,11 @@ case $basic_machine in - ;; - m68000-sun) - os=-sunos3 -- # This also exists in the configure program, but was not the -- # default. -- # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; -- mep-*) -+ mep-*) - os=-elf - ;; - mips*-cisco) -@@ -1561,7 +1615,7 @@ case $basic_machine in - *-ibm) - os=-aix - ;; -- *-knuth) -+ *-knuth) - os=-mmixware - ;; - *-wec) diff --git a/openssh-6.2p1-audit.patch b/openssh-6.2p1-audit.patch deleted file mode 100644 index 9a5d23c..0000000 --- a/openssh-6.2p1-audit.patch +++ /dev/null @@ -1,2297 +0,0 @@ -diff --git a/Makefile.in b/Makefile.in -index d327787..85903be 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -73,7 +73,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ -- jpake.o schnorr.o ssh-pkcs11.o krl.o -+ jpake.o schnorr.o ssh-pkcs11.o krl.o auditstub.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ -diff --git a/audit-bsm.c b/audit-bsm.c -index 6135591..5160869 100644 ---- a/audit-bsm.c -+++ b/audit-bsm.c -@@ -375,10 +375,23 @@ audit_connection_from(const char *host, int port) - #endif - } - --void -+int - audit_run_command(const char *command) - { - /* not implemented */ -+ return 0; -+} -+ -+void -+audit_end_command(int handle, const char *command) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_count_session_open(void) -+{ -+ /* not necessary */ - } - - void -@@ -393,6 +406,12 @@ audit_session_close(struct logininfo *li) - /* not implemented */ - } - -+int -+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) -+{ -+ /* not implemented */ -+} -+ - void - audit_event(ssh_audit_event_t event) - { -@@ -454,4 +473,40 @@ audit_event(ssh_audit_event_t event) - debug("%s: unhandled event %d", __func__, event); - } - } -+ -+void -+audit_unsupported_body(int what) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, uid_t uid) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_destroy_sensitive_data(const char *fp) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_generate_ephemeral_server_key(const char *fp) -+{ -+ /* not implemented */ -+} - #endif /* BSM */ -diff --git a/audit-linux.c b/audit-linux.c -index b3ee2f4..43904ee 100644 ---- a/audit-linux.c -+++ b/audit-linux.c -@@ -35,13 +35,24 @@ - - #include "log.h" - #include "audit.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" -+#include "servconf.h" - #include "canohost.h" -+#include "packet.h" -+#include "cipher.h" - -+#define AUDIT_LOG_SIZE 128 -+ -+extern ServerOptions options; -+extern Authctxt *the_authctxt; -+extern u_int utmp_len; - const char* audit_username(void); - --int --linux_audit_record_event(int uid, const char *username, -- const char *hostname, const char *ip, const char *ttyn, int success) -+static void -+linux_audit_user_logxxx(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success, int event) - { - int audit_fd, rc, saved_errno; - -@@ -49,11 +60,11 @@ linux_audit_record_event(int uid, const char *username, - if (audit_fd < 0) { - if (errno == EINVAL || errno == EPROTONOSUPPORT || - errno == EAFNOSUPPORT) -- return 1; /* No audit support in kernel */ -+ return; /* No audit support in kernel */ - else -- return 0; /* Must prevent login */ -+ goto fatal_report; /* Must prevent login */ - } -- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, -+ rc = audit_log_acct_message(audit_fd, event, - NULL, "login", username ? username : "(unknown)", - username == NULL ? uid : -1, hostname, ip, ttyn, success); - saved_errno = errno; -@@ -65,35 +76,150 @@ linux_audit_record_event(int uid, const char *username, - if ((rc == -EPERM) && (geteuid() != 0)) - rc = 0; - errno = saved_errno; -- return (rc >= 0); -+ if (rc < 0) { -+fatal_report: -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ } - } - -+static void -+linux_audit_user_auth(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success, int event) -+{ -+ int audit_fd, rc, saved_errno; -+ static const char *event_name[] = { -+ "maxtries exceeded", -+ "root denied", -+ "success", -+ "none", -+ "password", -+ "challenge-response", -+ "pubkey", -+ "hostbased", -+ "gssapi", -+ "invalid user", -+ "nologin", -+ "connection closed", -+ "connection abandoned", -+ "unknown" -+ }; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return; /* No audit support in kernel */ -+ else -+ goto fatal_report; /* Must prevent login */ -+ } -+ -+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN)) -+ event = SSH_AUDIT_UNKNOWN; -+ -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, -+ NULL, event_name[event], username ? username : "(unknown)", -+ username == NULL ? uid : -1, hostname, ip, ttyn, success); -+ saved_errno = errno; -+ close(audit_fd); -+ /* -+ * Do not report error if the error is EPERM and sshd is run as non -+ * root user. -+ */ -+ if ((rc == -EPERM) && (geteuid() != 0)) -+ rc = 0; -+ errno = saved_errno; -+ if (rc < 0) { -+fatal_report: -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ } -+} -+ -+int -+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, rc, saved_errno; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 1; /* No audit support in kernel */ -+ else -+ return 0; /* Must prevent login */ -+ } -+ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "pubkey" : "hostbased", get_remote_port()); -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, -+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); -+ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) -+ goto out; -+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d", -+ type, bits, key_fingerprint_prefix(), fp, get_remote_port()); -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, -+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); -+out: -+ saved_errno = errno; -+ audit_close(audit_fd); -+ errno = saved_errno; -+ /* do not report error if the error is EPERM and sshd is run as non root user */ -+ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); -+} -+ -+static int user_login_count = 0; -+ - /* Below is the sshd audit API code */ - - void - audit_connection_from(const char *host, int port) - { --} - /* not implemented */ -+} - --void -+int - audit_run_command(const char *command) - { -- /* not implemented */ -+ if (!user_login_count++) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGIN); -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_START); -+ return 0; -+} -+ -+void -+audit_end_command(int handle, const char *command) -+{ -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_END); -+ if (user_login_count && !--user_login_count) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGOUT); -+} -+ -+void -+audit_count_session_open(void) -+{ -+ user_login_count++; - } - - void - audit_session_open(struct logininfo *li) - { -- if (linux_audit_record_event(li->uid, NULL, li->hostname, -- NULL, li->line, 1) == 0) -- fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ if (!user_login_count++) -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_LOGIN); -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_START); - } - - void - audit_session_close(struct logininfo *li) - { -- /* not implemented */ -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_END); -+ if (user_login_count && !--user_login_count) -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_LOGOUT); - } - - void -@@ -101,21 +227,43 @@ audit_event(ssh_audit_event_t event) - { - switch(event) { - case SSH_AUTH_SUCCESS: -- case SSH_CONNECTION_CLOSE: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 1, event); -+ break; -+ - case SSH_NOLOGIN: -- case SSH_LOGIN_EXCEED_MAXTRIES: - case SSH_LOGIN_ROOT_DENIED: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, event); -+ linux_audit_user_logxxx(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); - break; - -+ case SSH_LOGIN_EXCEED_MAXTRIES: - case SSH_AUTH_FAIL_NONE: - case SSH_AUTH_FAIL_PASSWD: - case SSH_AUTH_FAIL_KBDINT: - case SSH_AUTH_FAIL_PUBKEY: - case SSH_AUTH_FAIL_HOSTBASED: - case SSH_AUTH_FAIL_GSSAPI: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, event); -+ break; -+ -+ case SSH_CONNECTION_CLOSE: -+ if (user_login_count) { -+ while (user_login_count--) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_END); -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGOUT); -+ } -+ break; -+ -+ case SSH_CONNECTION_ABANDON: - case SSH_INVALID_USER: -- linux_audit_record_event(-1, audit_username(), NULL, -- get_remote_ipaddr(), "sshd", 0); -+ linux_audit_user_logxxx(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); - break; - - default: -@@ -123,4 +271,135 @@ audit_event(ssh_audit_event_t event) - } - } - -+void -+audit_unsupported_body(int what) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; -+ char *s; -+ int audit_fd; -+ -+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", -+ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), -+ get_local_port()); -+ xfree(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) -+ /* no problem, the next instruction will be fatal() */ -+ return; -+ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, get_remote_ipaddr(), NULL, 0); -+ audit_close(audit_fd); -+#endif -+} -+ -+const static char *direction[] = { "from-server", "from-client", "both" }; -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, -+ uid_t uid) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ Cipher *cipher = cipher_by_name(enc); -+ char *s; -+ -+ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", -+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, -+ (intmax_t)pid, (intmax_t)uid, -+ get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port()); -+ xfree(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return; /* No audit support in kernel */ -+ else -+ fatal("cannot open audit"); /* Must prevent login */ -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, get_remote_ipaddr(), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ fatal("cannot write into audit"); /* Must prevent login */ -+#endif -+} -+ -+void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ char *s; -+ -+ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", -+ direction[ctos], (intmax_t)pid, (intmax_t)uid, -+ get_remote_port(), -+ (s = get_local_ipaddr(packet_get_connection_in())), -+ get_local_port()); -+ xfree(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, get_remote_ipaddr(), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} -+ -+void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ", -+ fp, (intmax_t)pid, (intmax_t)uid); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, -+ listening_for_clients() ? NULL : get_remote_ipaddr(), -+ NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} -+ -+void -+audit_generate_ephemeral_server_key(const char *fp) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "op=create kind=server fp=%s direction=? ", fp); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, 0, NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} - #endif /* USE_LINUX_AUDIT */ -diff --git a/audit.c b/audit.c -index ced57fa..1ccc9e9 100644 ---- a/audit.c -+++ b/audit.c -@@ -28,6 +28,7 @@ - - #include - #include -+#include - - #ifdef SSH_AUDIT_EVENTS - -@@ -36,6 +37,9 @@ - #include "key.h" - #include "hostfile.h" - #include "auth.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" -+#include "xmalloc.h" - - /* - * Care must be taken when using this since it WILL NOT be initialized when -@@ -111,6 +115,40 @@ audit_event_lookup(ssh_audit_event_t ev) - return(event_lookup[i].name); - } - -+void -+audit_key(int host_user, int *rv, const Key *key) -+{ -+ char *fp; -+ const char *crypto_name; -+ -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ if (key->type == KEY_RSA1) -+ crypto_name = "ssh-rsa1"; -+ else -+ crypto_name = key_ssh_name(key); -+ if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0) -+ *rv = 0; -+ xfree(fp); -+} -+ -+void -+audit_unsupported(int what) -+{ -+ PRIVSEP(audit_unsupported_body(what)); -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp) -+{ -+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid())); -+} -+ -+void -+audit_session_key_free(int ctos) -+{ -+ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid())); -+} -+ - # ifndef CUSTOM_SSH_AUDIT_EVENTS - /* - * Null implementations of audit functions. -@@ -140,6 +178,17 @@ audit_event(ssh_audit_event_t event) - } - - /* -+ * Called when a child process has called, or will soon call, -+ * audit_session_open. -+ */ -+void -+audit_count_session_open(void) -+{ -+ debug("audit count session open euid %d user %s", geteuid(), -+ audit_username()); -+} -+ -+/* - * Called when a user session is started. Argument is the tty allocated to - * the session, or NULL if no tty was allocated. - * -@@ -174,13 +223,91 @@ audit_session_close(struct logininfo *li) - /* - * This will be called when a user runs a non-interactive command. Note that - * it may be called multiple times for a single connection since SSH2 allows -- * multiple sessions within a single connection. -+ * multiple sessions within a single connection. Returns a "handle" for -+ * audit_end_command. - */ --void -+int - audit_run_command(const char *command) - { - debug("audit run command euid %d user %s command '%.200s'", geteuid(), - audit_username(), command); -+ return 0; -+} -+ -+/* -+ * This will be called when the non-interactive command finishes. Note that -+ * it may be called multiple times for a single connection since SSH2 allows -+ * multiple sessions within a single connection. "handle" should come from -+ * the corresponding audit_run_command. -+ */ -+void -+audit_end_command(int handle, const char *command) -+{ -+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), -+ audit_username(), command); -+} -+ -+/* -+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. -+ * -+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. -+ */ -+int -+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) -+{ -+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d", -+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits, -+ key_fingerprint_prefix(), fp, rv); -+} -+ -+/* -+ * This will be called when the protocol negotiation fails. -+ */ -+void -+audit_unsupported_body(int what) -+{ -+ debug("audit unsupported protocol euid %d type %d", geteuid(), what); -+} -+ -+/* -+ * This will be called on succesfull protocol negotiation. -+ */ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, -+ uid_t uid) -+{ -+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s from pid %ld uid %u", -+ (unsigned)geteuid(), ctos, enc, mac, compress, (long)pid, -+ (unsigned)uid); -+} -+ -+/* -+ * This will be called on succesfull session key discard -+ */ -+void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+ debug("audit session key discard euid %u direction %d from pid %ld uid %u", -+ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); -+} -+ -+/* -+ * This will be called on destroy private part of the server key -+ */ -+void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) -+{ -+ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", -+ geteuid(), fp, (long)pid, (unsigned)uid); -+} -+ -+/* -+ * This will be called on generation of the ephemeral server key -+ */ -+void -+audit_generate_ephemeral_server_key(const char *) -+{ -+ debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp); - } - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff --git a/audit.h b/audit.h -index 92ede5b..a2dc3ff 100644 ---- a/audit.h -+++ b/audit.h -@@ -28,6 +28,7 @@ - # define _SSH_AUDIT_H - - #include "loginrec.h" -+#include "key.h" - - enum ssh_audit_event_type { - SSH_LOGIN_EXCEED_MAXTRIES, -@@ -47,11 +48,25 @@ enum ssh_audit_event_type { - }; - typedef enum ssh_audit_event_type ssh_audit_event_t; - -+int listening_for_clients(void); -+ - void audit_connection_from(const char *, int); - void audit_event(ssh_audit_event_t); -+void audit_count_session_open(void); - void audit_session_open(struct logininfo *); - void audit_session_close(struct logininfo *); --void audit_run_command(const char *); -+int audit_run_command(const char *); -+void audit_end_command(int, const char *); - ssh_audit_event_t audit_classify_auth(const char *); -+int audit_keyusage(int, const char *, unsigned, char *, int); -+void audit_key(int, int *, const Key *); -+void audit_unsupported(int); -+void audit_kex(int, char *, char *, char *); -+void audit_unsupported_body(int); -+void audit_kex_body(int, char *, char *, char *, pid_t, uid_t); -+void audit_session_key_free(int ctos); -+void audit_session_key_free_body(int ctos, pid_t, uid_t); -+void audit_destroy_sensitive_data(const char *, pid_t, uid_t); -+void audit_generate_ephemeral_server_key(const char *); - - #endif /* _SSH_AUDIT_H */ -diff --git a/auditstub.c b/auditstub.c -new file mode 100644 -index 0000000..45817e0 ---- /dev/null -+++ b/auditstub.c -@@ -0,0 +1,50 @@ -+/* $Id: auditstub.c,v 1.1 jfch Exp $ */ -+ -+/* -+ * Copyright 2010 Red Hat, Inc. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * 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. -+ * -+ * Red Hat author: Jan F. Chadima -+ */ -+ -+#include -+ -+void -+audit_unsupported(int n) -+{ -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp) -+{ -+} -+ -+void -+audit_session_key_free(int ctos) -+{ -+} -+ -+void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+} -diff --git a/auth-rsa.c b/auth-rsa.c -index de7c369..7fdd0ae 100644 ---- a/auth-rsa.c -+++ b/auth-rsa.c -@@ -92,7 +92,10 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) - { - u_char buf[32], mdbuf[16]; - MD5_CTX md; -- int len; -+ int len, rv; -+#ifdef SSH_AUDIT_EVENTS -+ char *fp; -+#endif - - /* don't allow short keys */ - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -@@ -113,12 +116,18 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) - MD5_Final(mdbuf, &md); - - /* Verify that the response is the original challenge. */ -- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { -- /* Wrong answer. */ -- return (0); -+ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; -+ -+#ifdef SSH_AUDIT_EVENTS -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa) * 8, fp, rv) == 0) { -+ debug("unsuccessful audit"); -+ rv = 0; - } -- /* Correct answer. */ -- return (1); -+ xfree(fp); -+#endif -+ -+ return rv; - } - - /* -diff --git a/auth.h b/auth.h -index c6fe847..9ecc405 100644 ---- a/auth.h -+++ b/auth.h -@@ -181,6 +181,7 @@ void abandon_challenge_response(Authctxt *); - - char *expand_authorized_keys(const char *, struct passwd *pw); - char *authorized_principals_file(struct passwd *); -+int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - - FILE *auth_openkeyfile(const char *, struct passwd *, int); - FILE *auth_openprincipals(const char *, struct passwd *, int); -@@ -196,6 +197,7 @@ Key *get_hostkey_public_by_type(int); - Key *get_hostkey_private_by_type(int); - int get_hostkey_index(Key *); - int ssh1_session_key(BIGNUM *); -+int hostbased_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - - /* debug messages during authentication */ - void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); -diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index 69b849b..e535680 100644 ---- a/auth2-hostbased.c -+++ b/auth2-hostbased.c -@@ -119,7 +119,7 @@ userauth_hostbased(Authctxt *authctxt) - /* test for allowed key and correct signature */ - authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && -- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), -+ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) - authenticated = 1; - -@@ -136,6 +136,18 @@ done: - return authenticated; - } - -+int -+hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) -+{ -+ int rv; -+ -+ rv = key_verify(key, sig, slen, data, datalen); -+#ifdef SSH_AUDIT_EVENTS -+ audit_key(0, &rv, key); -+#endif -+ return rv; -+} -+ - /* return 1 if given hostkey is allowed */ - int - hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, -diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index d78381a..8f913ab 100644 ---- a/auth2-pubkey.c -+++ b/auth2-pubkey.c -@@ -146,7 +146,7 @@ userauth_pubkey(Authctxt *authctxt) - /* test for correct signature */ - authenticated = 0; - if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && -- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), -+ PRIVSEP(user_key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) - authenticated = 1; - buffer_free(&b); -@@ -183,6 +183,18 @@ done: - return authenticated; - } - -+int -+user_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) -+{ -+ int rv; -+ -+ rv = key_verify(key, sig, slen, data, datalen); -+#ifdef SSH_AUDIT_EVENTS -+ audit_key(1, &rv, key); -+#endif -+ return rv; -+} -+ - static int - match_principals_option(const char *principal_list, struct KeyCert *cert) - { -diff --git a/auth2.c b/auth2.c -index e367a10..c28638b 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -242,9 +242,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) - } else { - logit("input_userauth_request: invalid user %s", user); - authctxt->pw = fakepw(); --#ifdef SSH_AUDIT_EVENTS -- PRIVSEP(audit_event(SSH_INVALID_USER)); --#endif - } - #ifdef USE_PAM - if (options.use_pam) -diff --git a/cipher.c b/cipher.c -index 9ca1d00..e1d716a 100644 ---- a/cipher.c -+++ b/cipher.c -@@ -55,17 +55,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(void); - extern const EVP_CIPHER *evp_ssh1_3des(void); - extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); - --struct Cipher { -- char *name; -- int number; /* for ssh1 only */ -- u_int block_size; -- u_int key_len; -- u_int iv_len; /* defaults to block_size */ -- u_int auth_len; -- u_int discard_len; -- u_int cbc_mode; -- const EVP_CIPHER *(*evptype)(void); --} ciphers[] = { -+struct Cipher ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, -diff --git a/cipher.h b/cipher.h -index 8cb57c3..89b2dc9 100644 ---- a/cipher.h -+++ b/cipher.h -@@ -61,7 +61,18 @@ - typedef struct Cipher Cipher; - typedef struct CipherContext CipherContext; - --struct Cipher; -+struct Cipher { -+ char *name; -+ int number; /* for ssh1 only */ -+ u_int block_size; -+ u_int key_len; -+ u_int iv_len; /* defaults to block_size */ -+ u_int auth_len; -+ u_int discard_len; -+ u_int cbc_mode; -+ const EVP_CIPHER *(*evptype)(void); -+}; -+ - struct CipherContext { - int plaintext; - int encrypt; -diff --git a/kex.c b/kex.c -index 57a79dd..922cf9d 100644 ---- a/kex.c -+++ b/kex.c -@@ -49,6 +49,7 @@ - #include "dispatch.h" - #include "monitor.h" - #include "roaming.h" -+#include "audit.h" - - #if OPENSSL_VERSION_NUMBER >= 0x00907000L - # if defined(HAVE_EVP_SHA256) -@@ -296,9 +297,13 @@ static void - choose_enc(Enc *enc, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(0); -+#endif - fatal("no matching cipher found: client %s server %s", - client, server); -+ } - if ((enc->cipher = cipher_by_name(name)) == NULL) - fatal("matching cipher is not supported: %s", name); - enc->name = name; -@@ -314,9 +319,13 @@ static void - choose_mac(Mac *mac, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(1); -+#endif - fatal("no matching mac found: client %s server %s", - client, server); -+ } - if (mac_setup(mac, name) < 0) - fatal("unsupported mac %s", name); - /* truncate the key */ -@@ -331,8 +340,12 @@ static void - choose_comp(Comp *comp, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(2); -+#endif - fatal("no matching comp found: client %s server %s", client, server); -+ } - if (strcmp(name, "zlib@openssh.com") == 0) { - comp->type = COMP_DELAYED; - } else if (strcmp(name, "zlib") == 0) { -@@ -460,6 +473,9 @@ kex_choose_conf(Kex *kex) - newkeys->enc.name, - authlen == 0 ? newkeys->mac.name : "", - newkeys->comp.name); -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); -+#endif - } - choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); - choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], -@@ -624,3 +640,34 @@ dump_digest(char *msg, u_char *digest, int len) - fprintf(stderr, "\n"); - } - #endif -+ -+static void -+enc_destroy(Enc *enc) -+{ -+ if (enc == NULL) -+ return; -+ -+ if (enc->key) { -+ memset(enc->key, 0, enc->key_len); -+ xfree(enc->key); -+ } -+ -+ if (enc->iv) { -+ memset(enc->iv, 0, enc->block_size); -+ xfree(enc->iv); -+ } -+ -+ memset(enc, 0, sizeof(*enc)); -+} -+ -+void -+newkeys_destroy(Newkeys *newkeys) -+{ -+ if (newkeys == NULL) -+ return; -+ -+ enc_destroy(&newkeys->enc); -+ mac_destroy(&newkeys->mac); -+ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); -+} -+ -diff --git a/kex.h b/kex.h -index 46731fa..8a59114 100644 ---- a/kex.h -+++ b/kex.h -@@ -158,6 +158,8 @@ void kexgex_server(Kex *); - void kexecdh_client(Kex *); - void kexecdh_server(Kex *); - -+void newkeys_destroy(Newkeys *newkeys); -+ - void - kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, - BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); -diff --git a/key.c b/key.c -index a30e6d1..9d04f11 100644 ---- a/key.c -+++ b/key.c -@@ -1809,6 +1809,30 @@ key_demote(const Key *k) - } - - int -+key_is_private(const Key *k) -+{ -+ switch (k->type) { -+ case KEY_RSA_CERT_V00: -+ case KEY_RSA_CERT: -+ case KEY_RSA1: -+ case KEY_RSA: -+ return k->rsa->d != NULL; -+ case KEY_DSA_CERT_V00: -+ case KEY_DSA_CERT: -+ case KEY_DSA: -+ return k->dsa->priv_key != NULL; -+#ifdef OPENSSL_HAS_ECC -+ case KEY_ECDSA_CERT: -+ case KEY_ECDSA: -+ return EC_KEY_get0_private_key(k->ecdsa) != NULL; -+#endif -+ default: -+ fatal("key_is_private: bad key type %d", k->type); -+ return 1; -+ } -+} -+ -+int - key_is_cert(const Key *k) - { - if (k == NULL) -diff --git a/key.h b/key.h -index 09f7b7d..8d9be57 100644 ---- a/key.h -+++ b/key.h -@@ -110,6 +110,7 @@ Key *key_generate(int, u_int); - Key *key_from_private(const Key *); - int key_type_from_name(char *); - int key_is_cert(const Key *); -+int key_is_private(const Key *k); - int key_type_plain(int); - int key_to_certified(Key *, int); - int key_drop_cert(Key *); -diff --git a/mac.c b/mac.c -index 3f2dc6f..a1e61be 100644 ---- a/mac.c -+++ b/mac.c -@@ -199,6 +199,20 @@ mac_clear(Mac *mac) - mac->umac_ctx = NULL; - } - -+void -+mac_destroy(Mac *mac) -+{ -+ if (mac == NULL) -+ return; -+ -+ if (mac->key) { -+ memset(mac->key, 0, mac->key_len); -+ xfree(mac->key); -+ } -+ -+ memset(mac, 0, sizeof(*mac)); -+} -+ - /* XXX copied from ciphers_valid */ - #define MAC_SEP "," - int -diff --git a/mac.h b/mac.h -index 39f564d..640db0f 100644 ---- a/mac.h -+++ b/mac.h -@@ -28,3 +28,4 @@ int mac_setup(Mac *, char *); - int mac_init(Mac *); - u_char *mac_compute(Mac *, u_int32_t, u_char *, int); - void mac_clear(Mac *); -+void mac_destroy(Mac *); -diff --git a/monitor.c b/monitor.c -index 7816a8f..f1c0ba1 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -97,6 +97,7 @@ - #include "ssh2.h" - #include "jpake.h" - #include "roaming.h" -+#include "audit.h" - - #ifdef GSSAPI - static Gssctxt *gsscontext = NULL; -@@ -113,6 +114,8 @@ extern Buffer auth_debug; - extern int auth_debug_init; - extern Buffer loginmsg; - -+extern void destroy_sensitive_data(int); -+ - /* State exported from the child */ - - struct { -@@ -185,6 +188,11 @@ int mm_answer_gss_checkmic(int, Buffer *); - #ifdef SSH_AUDIT_EVENTS - int mm_answer_audit_event(int, Buffer *); - int mm_answer_audit_command(int, Buffer *); -+int mm_answer_audit_end_command(int, Buffer *); -+int mm_answer_audit_unsupported_body(int, Buffer *); -+int mm_answer_audit_kex_body(int, Buffer *); -+int mm_answer_audit_session_key_free_body(int, Buffer *); -+int mm_answer_audit_server_key_free(int, Buffer *); - #endif - - static int monitor_read_log(struct monitor *); -@@ -236,6 +244,10 @@ struct mon_table mon_dispatch_proto20[] = { - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - #ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -272,6 +284,11 @@ struct mon_table mon_dispatch_postauth20[] = { - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -303,6 +320,10 @@ struct mon_table mon_dispatch_proto15[] = { - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -314,6 +335,11 @@ struct mon_table mon_dispatch_postauth15[] = { - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -1350,9 +1376,11 @@ mm_answer_keyverify(int sock, Buffer *m) - Key *key; - u_char *signature, *data, *blob; - u_int signaturelen, datalen, bloblen; -+ int type = 0; - int verified = 0; - int valid_data = 0; - -+ type = buffer_get_int(m); - blob = buffer_get_string(m, &bloblen); - signature = buffer_get_string(m, &signaturelen); - data = buffer_get_string(m, &datalen); -@@ -1360,6 +1388,8 @@ mm_answer_keyverify(int sock, Buffer *m) - if (hostbased_cuser == NULL || hostbased_chost == NULL || - !monitor_allowed_key(blob, bloblen)) - fatal("%s: bad key, not previously allowed", __func__); -+ if (type != key_blobtype) -+ fatal("%s: bad key type", __func__); - - key = key_from_blob(blob, bloblen); - if (key == NULL) -@@ -1380,7 +1410,17 @@ mm_answer_keyverify(int sock, Buffer *m) - if (!valid_data) - fatal("%s: bad signature data blob", __func__); - -- verified = key_verify(key, signature, signaturelen, data, datalen); -+ switch (key_blobtype) { -+ case MM_USERKEY: -+ verified = user_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ case MM_HOSTKEY: -+ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ default: -+ verified = 0; -+ break; -+ } - debug3("%s: key %p signature %s", - __func__, key, (verified == 1) ? "verified" : "unverified"); - -@@ -1433,6 +1473,12 @@ mm_session_close(Session *s) - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); - session_pty_cleanup2(s); - } -+#ifdef SSH_AUDIT_EVENTS -+ if (s->command != NULL) { -+ debug3("%s: command %d", __func__, s->command_handle); -+ session_end_command2(s); -+ } -+#endif - session_unused(s->self); - } - -@@ -1713,6 +1759,8 @@ mm_answer_term(int sock, Buffer *req) - sshpam_cleanup(); - #endif - -+ destroy_sensitive_data(0); -+ - while (waitpid(pmonitor->m_pid, &status, 0) == -1) - if (errno != EINTR) - exit(1); -@@ -1755,11 +1803,44 @@ mm_answer_audit_command(int socket, Buffer *m) - { - u_int len; - char *cmd; -+ Session *s; - - debug3("%s entering", __func__); - cmd = buffer_get_string(m, &len); -+ - /* sanity check command, if so how? */ -- audit_run_command(cmd); -+ s = session_new(); -+ if (s == NULL) -+ fatal("%s: error allocating a session", __func__); -+ s->command = cmd; -+ s->command_handle = audit_run_command(cmd); -+ -+ buffer_clear(m); -+ buffer_put_int(m, s->self); -+ -+ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m); -+ -+ return (0); -+} -+ -+int -+mm_answer_audit_end_command(int socket, Buffer *m) -+{ -+ int handle; -+ u_int len; -+ char *cmd; -+ Session *s; -+ -+ debug3("%s entering", __func__); -+ handle = buffer_get_int(m); -+ cmd = buffer_get_string(m, &len); -+ -+ s = session_by_id(handle); -+ if (s == NULL || s->ttyfd != -1 || s->command == NULL || -+ strcmp(s->command, cmd) != 0) -+ fatal("%s: invalid handle", __func__); -+ mm_session_close(s); -+ - xfree(cmd); - return (0); - } -@@ -1890,11 +1971,13 @@ mm_get_keystate(struct monitor *pmonitor) - - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); -+ memset(blob, 0, bloblen); - xfree(blob); - - debug3("%s: Waiting for second key", __func__); - blob = buffer_get_string(&m, &bloblen); - current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); -+ memset(blob, 0, bloblen); - xfree(blob); - - /* Now get sequence numbers for the packets */ -@@ -1940,6 +2023,21 @@ mm_get_keystate(struct monitor *pmonitor) - } - - buffer_free(&m); -+ -+#ifdef SSH_AUDIT_EVENTS -+ if (compat20) { -+ buffer_init(&m); -+ mm_request_receive_expect(pmonitor->m_sendfd, -+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); -+ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, &m); -+ buffer_free(&m); -+ } -+#endif -+ -+ /* Drain any buffered messages from the child */ -+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) -+ ; -+ - } - - -@@ -2341,3 +2439,86 @@ mm_answer_jpake_check_confirm(int sock, Buffer *m) - } - - #endif /* JPAKE */ -+ -+#ifdef SSH_AUDIT_EVENTS -+int -+mm_answer_audit_unsupported_body(int sock, Buffer *m) -+{ -+ int what; -+ -+ what = buffer_get_int(m); -+ -+ audit_unsupported_body(what); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); -+ return 0; -+} -+ -+int -+mm_answer_audit_kex_body(int sock, Buffer *m) -+{ -+ int ctos, len; -+ char *cipher, *mac, *compress; -+ pid_t pid; -+ uid_t uid; -+ -+ ctos = buffer_get_int(m); -+ cipher = buffer_get_string(m, &len); -+ mac = buffer_get_string(m, &len); -+ compress = buffer_get_string(m, &len); -+ pid = buffer_get_int64(m); -+ uid = buffer_get_int64(m); -+ -+ audit_kex_body(ctos, cipher, mac, compress, pid, uid); -+ -+ xfree(cipher); -+ xfree(mac); -+ xfree(compress); -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); -+ return 0; -+} -+ -+int -+mm_answer_audit_session_key_free_body(int sock, Buffer *m) -+{ -+ int ctos; -+ pid_t pid; -+ uid_t uid; -+ -+ ctos = buffer_get_int(m); -+ pid = buffer_get_int64(m); -+ uid = buffer_get_int64(m); -+ -+ audit_session_key_free_body(ctos, pid, uid); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); -+ return 0; -+} -+ -+int -+mm_answer_audit_server_key_free(int sock, Buffer *m) -+{ -+ int len; -+ char *fp; -+ pid_t pid; -+ uid_t uid; -+ -+ fp = buffer_get_string(m, &len); -+ pid = buffer_get_int64(m); -+ uid = buffer_get_int64(m); -+ -+ audit_destroy_sensitive_data(fp, pid, uid); -+ -+ xfree(fp); -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m); -+ return 0; -+} -+#endif /* SSH_AUDIT_EVENTS */ -diff --git a/monitor.h b/monitor.h -index 2caa469..1a15066 100644 ---- a/monitor.h -+++ b/monitor.h -@@ -68,7 +68,13 @@ enum monitor_reqtype { - MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, - MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, - MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, -- MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, -+ MONITOR_REQ_AUDIT_EVENT = 112, -+ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115, -+ MONITOR_REQ_AUDIT_END_COMMAND = 116, -+ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, -+ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, -+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, -+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, MONITOR_ANS_AUDIT_SERVER_KEY_FREE = 125 - - }; - -diff --git a/monitor_wrap.c b/monitor_wrap.c -index 350c960..8c3599d 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -431,7 +431,7 @@ mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) - */ - - int --mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) - { - Buffer m; - u_char *blob; -@@ -445,6 +445,7 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) - return (0); - - buffer_init(&m); -+ buffer_put_int(&m, type); - buffer_put_string(&m, blob, len); - buffer_put_string(&m, sig, siglen); - buffer_put_string(&m, data, datalen); -@@ -462,6 +463,19 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) - return (verified); - } - -+int -+mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+{ -+ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen); -+} -+ -+int -+mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+{ -+ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen); -+} -+ -+ - /* Export key state after authentication */ - Newkeys * - mm_newkeys_from_blob(u_char *blob, int blen) -@@ -480,7 +494,7 @@ mm_newkeys_from_blob(u_char *blob, int blen) - buffer_init(&b); - buffer_append(&b, blob, blen); - -- newkey = xmalloc(sizeof(*newkey)); -+ newkey = xcalloc(1, sizeof(*newkey)); - enc = &newkey->enc; - mac = &newkey->mac; - comp = &newkey->comp; -@@ -640,12 +654,14 @@ mm_send_keystate(struct monitor *monitor) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); -+ memset(blob, 0, bloblen); - xfree(blob); - - if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) - fatal("%s: conversion of newkeys failed", __func__); - - buffer_put_string(&m, blob, bloblen); -+ memset(blob, 0, bloblen); - xfree(blob); - - packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); -@@ -1189,10 +1205,11 @@ mm_audit_event(ssh_audit_event_t event) - buffer_free(&m); - } - --void -+int - mm_audit_run_command(const char *command) - { - Buffer m; -+ int handle; - - debug3("%s entering command %s", __func__, command); - -@@ -1200,6 +1217,26 @@ mm_audit_run_command(const char *command) - buffer_put_cstring(&m, command); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m); -+ -+ handle = buffer_get_int(&m); -+ buffer_free(&m); -+ -+ return (handle); -+} -+ -+void -+mm_audit_end_command(int handle, const char *command) -+{ -+ Buffer m; -+ -+ debug3("%s entering command %s", __func__, command); -+ -+ buffer_init(&m); -+ buffer_put_int(&m, handle); -+ buffer_put_cstring(&m, command); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m); - buffer_free(&m); - } - #endif /* SSH_AUDIT_EVENTS */ -@@ -1451,3 +1488,72 @@ mm_jpake_check_confirm(const BIGNUM *k, - return success; - } - #endif /* JPAKE */ -+ -+#ifdef SSH_AUDIT_EVENTS -+void -+mm_audit_unsupported_body(int what) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, what); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, -+ &m); -+ -+ buffer_free(&m); -+} -+ -+void -+mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, pid_t pid, -+ uid_t uid) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, ctos); -+ buffer_put_cstring(&m, cipher); -+ buffer_put_cstring(&m, (mac ? mac : "")); -+ buffer_put_cstring(&m, compress); -+ buffer_put_int64(&m, pid); -+ buffer_put_int64(&m, uid); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, -+ &m); -+ -+ buffer_free(&m); -+} -+ -+void -+mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, ctos); -+ buffer_put_int64(&m, pid); -+ buffer_put_int64(&m, uid); -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, -+ &m); -+ buffer_free(&m); -+} -+ -+void -+mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_cstring(&m, fp); -+ buffer_put_int64(&m, pid); -+ buffer_put_int64(&m, uid); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, -+ &m); -+ buffer_free(&m); -+} -+#endif /* SSH_AUDIT_EVENTS */ -diff --git a/monitor_wrap.h b/monitor_wrap.h -index 0c7f2e3..f47c7df 100644 ---- a/monitor_wrap.h -+++ b/monitor_wrap.h -@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char *, char *, Key *); - int mm_user_key_allowed(struct passwd *, Key *); - int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *); - int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); --int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); -+int mm_hostbased_key_verify(Key *, u_char *, u_int, u_char *, u_int); -+int mm_user_key_verify(Key *, u_char *, u_int, u_char *, u_int); - int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); - int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); - BIGNUM *mm_auth_rsa_generate_challenge(Key *); -@@ -74,7 +75,12 @@ void mm_sshpam_free_ctx(void *); - #ifdef SSH_AUDIT_EVENTS - #include "audit.h" - void mm_audit_event(ssh_audit_event_t); --void mm_audit_run_command(const char *); -+int mm_audit_run_command(const char *); -+void mm_audit_end_command(int, const char *); -+void mm_audit_unsupported_body(int); -+void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t); -+void mm_audit_session_key_free_body(int, pid_t, uid_t); -+void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); - #endif - - struct Session; -diff --git a/packet.c b/packet.c -index a51c1f2..faa3a85 100644 ---- a/packet.c -+++ b/packet.c -@@ -60,6 +60,7 @@ - #include - - #include "xmalloc.h" -+#include "audit.h" - #include "buffer.h" - #include "packet.h" - #include "crc32.h" -@@ -470,6 +471,13 @@ packet_get_connection_out(void) - return active_state->connection_out; - } - -+static int -+packet_state_has_keys (const struct session_state *state) -+{ -+ return state != NULL && -+ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL); -+} -+ - /* Closes the connection and clears and frees internal data structures. */ - - void -@@ -478,13 +486,6 @@ packet_close(void) - if (!active_state->initialized) - return; - active_state->initialized = 0; -- if (active_state->connection_in == active_state->connection_out) { -- shutdown(active_state->connection_out, SHUT_RDWR); -- close(active_state->connection_out); -- } else { -- close(active_state->connection_in); -- close(active_state->connection_out); -- } - buffer_free(&active_state->input); - buffer_free(&active_state->output); - buffer_free(&active_state->outgoing_packet); -@@ -493,8 +494,18 @@ packet_close(void) - buffer_free(&active_state->compression_buffer); - buffer_compress_uninit(); - } -- cipher_cleanup(&active_state->send_context); -- cipher_cleanup(&active_state->receive_context); -+ if (packet_state_has_keys(active_state)) { -+ cipher_cleanup(&active_state->send_context); -+ cipher_cleanup(&active_state->receive_context); -+ audit_session_key_free(2); -+ } -+ if (active_state->connection_in == active_state->connection_out) { -+ shutdown(active_state->connection_out, SHUT_RDWR); -+ close(active_state->connection_out); -+ } else { -+ close(active_state->connection_in); -+ close(active_state->connection_out); -+ } - } - - /* Sets remote side protocol flags. */ -@@ -729,6 +740,25 @@ packet_send1(void) - */ - } - -+static void -+newkeys_destroy_and_free(Newkeys *newkeys) -+{ -+ if (newkeys == NULL) -+ return; -+ -+ xfree(newkeys->enc.name); -+ -+ if (newkeys->mac.enabled) { -+ mac_clear(&newkeys->mac); -+ xfree(newkeys->mac.name); -+ } -+ -+ xfree(newkeys->comp.name); -+ -+ newkeys_destroy(newkeys); -+ xfree(newkeys); -+} -+ - void - set_newkeys(int mode) - { -@@ -754,21 +784,9 @@ set_newkeys(int mode) - } - if (active_state->newkeys[mode] != NULL) { - debug("set_newkeys: rekeying"); -+ audit_session_key_free(mode); - cipher_cleanup(cc); -- enc = &active_state->newkeys[mode]->enc; -- mac = &active_state->newkeys[mode]->mac; -- comp = &active_state->newkeys[mode]->comp; -- mac_clear(mac); -- memset(enc->iv, 0, enc->iv_len); -- memset(enc->key, 0, enc->key_len); -- memset(mac->key, 0, mac->key_len); -- xfree(enc->name); -- xfree(enc->iv); -- xfree(enc->key); -- xfree(mac->name); -- xfree(mac->key); -- xfree(comp->name); -- xfree(active_state->newkeys[mode]); -+ newkeys_destroy_and_free(active_state->newkeys[mode]); - } - active_state->newkeys[mode] = kex_get_newkeys(mode); - if (active_state->newkeys[mode] == NULL) -@@ -1971,6 +1989,47 @@ packet_get_newkeys(int mode) - return (void *)active_state->newkeys[mode]; - } - -+static void -+packet_destroy_state(struct session_state *state) -+{ -+ if (state == NULL) -+ return; -+ -+ cipher_cleanup(&state->receive_context); -+ cipher_cleanup(&state->send_context); -+ -+ buffer_free(&state->input); -+ buffer_free(&state->output); -+ buffer_free(&state->outgoing_packet); -+ buffer_free(&state->incoming_packet); -+ buffer_free(&state->compression_buffer); -+ newkeys_destroy_and_free(state->newkeys[MODE_IN]); -+ state->newkeys[MODE_IN] = NULL; -+ newkeys_destroy_and_free(state->newkeys[MODE_OUT]); -+ state->newkeys[MODE_OUT] = NULL; -+ mac_destroy(state->packet_discard_mac); -+// TAILQ_HEAD(, packet) outgoing; -+// memset(state, 0, sizeof(state)); -+} -+ -+void -+packet_destroy_all(int audit_it, int privsep) -+{ -+ if (audit_it) -+ audit_it = packet_state_has_keys (active_state) || -+ packet_state_has_keys (backup_state); -+ packet_destroy_state(active_state); -+ packet_destroy_state(backup_state); -+ if (audit_it) { -+#ifdef SSH_AUDIT_EVENTS -+ if (privsep) -+ audit_session_key_free(2); -+ else -+ audit_session_key_free_body(2, getpid(), getuid()); -+#endif -+ } -+} -+ - /* - * Save the state for the real connection, and use a separate state when - * resuming a suspended connection. -@@ -1978,18 +2037,12 @@ packet_get_newkeys(int mode) - void - packet_backup_state(void) - { -- struct session_state *tmp; -- - close(active_state->connection_in); - active_state->connection_in = -1; - close(active_state->connection_out); - active_state->connection_out = -1; -- if (backup_state) -- tmp = backup_state; -- else -- tmp = alloc_session_state(); - backup_state = active_state; -- active_state = tmp; -+ active_state = alloc_session_state(); - } - - /* -@@ -2006,9 +2059,7 @@ packet_restore_state(void) - backup_state = active_state; - active_state = tmp; - active_state->connection_in = backup_state->connection_in; -- backup_state->connection_in = -1; - active_state->connection_out = backup_state->connection_out; -- backup_state->connection_out = -1; - len = buffer_len(&backup_state->input); - if (len > 0) { - buf = buffer_ptr(&backup_state->input); -@@ -2016,4 +2067,10 @@ packet_restore_state(void) - buffer_clear(&backup_state->input); - add_recv_bytes(len); - } -+ backup_state->connection_in = -1; -+ backup_state->connection_out = -1; -+ packet_destroy_state(backup_state); -+ xfree(backup_state); -+ backup_state = NULL; - } -+ -diff --git a/packet.h b/packet.h -index 09ba079..0742f74 100644 ---- a/packet.h -+++ b/packet.h -@@ -123,4 +123,5 @@ void packet_restore_state(void); - void *packet_get_input(void); - void *packet_get_output(void); - -+void packet_destroy_all(int, int); - #endif /* PACKET_H */ -diff --git a/session.c b/session.c -index 19eaa20..dc0a2e2 100644 ---- a/session.c -+++ b/session.c -@@ -136,7 +136,7 @@ extern int log_stderr; - extern int debug_flag; - extern u_int utmp_len; - extern int startup_pipe; --extern void destroy_sensitive_data(void); -+extern void destroy_sensitive_data(int); - extern Buffer loginmsg; - - /* original command from peer. */ -@@ -745,6 +745,14 @@ do_exec_pty(Session *s, const char *command) - /* Parent. Close the slave side of the pseudo tty. */ - close(ttyfd); - -+#ifndef HAVE_OSF_SIA -+ /* do_login in the child did not affect state in this process, -+ compensate. From an architectural standpoint, this is extremely -+ ugly. */ -+ if (!(options.use_login && command == NULL)) -+ audit_count_session_open(); -+#endif -+ - /* Enter interactive session. */ - s->ptymaster = ptymaster; - packet_set_interactive(1, -@@ -816,15 +824,19 @@ do_exec(Session *s, const char *command) - } - - #ifdef SSH_AUDIT_EVENTS -+ if (s->command != NULL || s->command_handle != -1) -+ fatal("do_exec: command already set"); - if (command != NULL) -- PRIVSEP(audit_run_command(command)); -+ s->command = xstrdup(command); - else if (s->ttyfd == -1) { - char *shell = s->pw->pw_shell; - - if (shell[0] == '\0') /* empty shell means /bin/sh */ - shell =_PATH_BSHELL; -- PRIVSEP(audit_run_command(shell)); -+ s->command = xstrdup(shell); - } -+ if (s->command != NULL) -+ s->command_handle = PRIVSEP(audit_run_command(s->command)); - #endif - if (s->ttyfd != -1) - ret = do_exec_pty(s, command); -@@ -1629,7 +1641,10 @@ do_child(Session *s, const char *command) - int r = 0; - - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(); -+ destroy_sensitive_data(1); -+ /* Don't audit this - both us and the parent would be talking to the -+ monitor over a single socket, with no synchronization. */ -+ packet_destroy_all(0, 1); - - /* Force a password change */ - if (s->authctxt->force_pwchange) { -@@ -1856,6 +1871,7 @@ session_unused(int id) - sessions[id].ttyfd = -1; - sessions[id].ptymaster = -1; - sessions[id].x11_chanids = NULL; -+ sessions[id].command_handle = -1; - sessions[id].next_unused = sessions_first_unused; - sessions_first_unused = id; - } -@@ -1938,6 +1954,19 @@ session_open(Authctxt *authctxt, int chanid) - } - - Session * -+session_by_id(int id) -+{ -+ if (id >= 0 && id < sessions_nalloc) { -+ Session *s = &sessions[id]; -+ if (s->used) -+ return s; -+ } -+ debug("session_by_id: unknown id %d", id); -+ session_dump(); -+ return NULL; -+} -+ -+Session * - session_by_tty(char *tty) - { - int i; -@@ -2463,6 +2492,30 @@ session_exit_message(Session *s, int status) - chan_write_failed(c); - } - -+#ifdef SSH_AUDIT_EVENTS -+void -+session_end_command2(Session *s) -+{ -+ if (s->command != NULL) { -+ audit_end_command(s->command_handle, s->command); -+ xfree(s->command); -+ s->command = NULL; -+ s->command_handle = -1; -+ } -+} -+ -+static void -+session_end_command(Session *s) -+{ -+ if (s->command != NULL) { -+ PRIVSEP(audit_end_command(s->command_handle, s->command)); -+ xfree(s->command); -+ s->command = NULL; -+ s->command_handle = -1; -+ } -+} -+#endif -+ - void - session_close(Session *s) - { -@@ -2471,6 +2524,10 @@ session_close(Session *s) - debug("session_close: session %d pid %ld", s->self, (long)s->pid); - if (s->ttyfd != -1) - session_pty_cleanup(s); -+#ifdef SSH_AUDIT_EVENTS -+ if (s->command) -+ session_end_command(s); -+#endif - if (s->term) - xfree(s->term); - if (s->display) -@@ -2690,6 +2747,15 @@ do_authenticated2(Authctxt *authctxt) - server_loop2(authctxt); - } - -+static void -+do_cleanup_one_session(Session *s) -+{ -+ session_pty_cleanup2(s); -+#ifdef SSH_AUDIT_EVENTS -+ session_end_command2(s); -+#endif -+} -+ - void - do_cleanup(Authctxt *authctxt) - { -@@ -2738,5 +2804,5 @@ do_cleanup(Authctxt *authctxt) - * or if running in monitor. - */ - if (!use_privsep || mm_is_monitor()) -- session_destroy_all(session_pty_cleanup2); -+ session_destroy_all(do_cleanup_one_session); - } -diff --git a/session.h b/session.h -index cbb8e3a..fc6a7d3 100644 ---- a/session.h -+++ b/session.h -@@ -60,6 +60,12 @@ struct Session { - char *name; - char *val; - } *env; -+ -+ /* exec */ -+#ifdef SSH_AUDIT_EVENTS -+ int command_handle; -+ char *command; -+#endif - }; - - void do_authenticated(Authctxt *); -@@ -72,8 +78,10 @@ void session_close_by_pid(pid_t, int); - void session_close_by_channel(int, void *); - void session_destroy_all(void (*)(Session *)); - void session_pty_cleanup2(Session *); -+void session_end_command2(Session *); - - Session *session_new(void); -+Session *session_by_id(int); - Session *session_by_tty(char *); - void session_close(Session *); - void do_setusercontext(struct passwd *); -diff --git a/sshd.c b/sshd.c -index 740ef4b..9aff64c 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -118,6 +118,7 @@ - #endif - #include "monitor_wrap.h" - #include "roaming.h" -+#include "audit.h" - #include "ssh-sandbox.h" - #include "version.h" - -@@ -254,7 +255,7 @@ Buffer loginmsg; - struct passwd *privsep_pw = NULL; - - /* Prototypes for various functions defined later in this file. */ --void destroy_sensitive_data(void); -+void destroy_sensitive_data(int); - void demote_sensitive_data(void); - - static void do_ssh1_kex(void); -@@ -273,6 +274,15 @@ close_listen_socks(void) - num_listen_socks = -1; - } - -+/* -+ * Is this process listening for clients (i.e. not specific to any specific -+ * client connection?) -+ */ -+int listening_for_clients(void) -+{ -+ return num_listen_socks > 0; -+} -+ - static void - close_startup_pipes(void) - { -@@ -544,22 +554,47 @@ sshd_exchange_identification(int sock_in, int sock_out) - } - } - --/* Destroy the host and server keys. They will no longer be needed. */ -+/* -+ * Destroy the host and server keys. They will no longer be needed. Careful, -+ * this can be called from cleanup_exit() - i.e. from just about anywhere. -+ */ - void --destroy_sensitive_data(void) -+destroy_sensitive_data(int privsep) - { - int i; -+ pid_t pid; -+ uid_t uid; - - if (sensitive_data.server_key) { - key_free(sensitive_data.server_key); - sensitive_data.server_key = NULL; - } -+ pid = getpid(); -+ uid = getuid(); - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { -+ char *fp; -+ -+ if (key_is_private(sensitive_data.host_keys[i])) -+ fp = key_fingerprint(sensitive_data.host_keys[i], -+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, -+ SSH_FP_HEX); -+ else -+ fp = NULL; - key_free(sensitive_data.host_keys[i]); - sensitive_data.host_keys[i] = NULL; -+ if (fp != NULL) { -+ if (privsep) -+ PRIVSEP(audit_destroy_sensitive_data(fp, -+ pid, uid)); -+ else -+ audit_destroy_sensitive_data(fp, -+ pid, uid); -+ xfree(fp); -+ } - } -- if (sensitive_data.host_certificates[i]) { -+ if (sensitive_data.host_certificates -+ && sensitive_data.host_certificates[i]) { - key_free(sensitive_data.host_certificates[i]); - sensitive_data.host_certificates[i] = NULL; - } -@@ -573,6 +608,8 @@ void - demote_sensitive_data(void) - { - Key *tmp; -+ pid_t pid; -+ uid_t uid; - int i; - - if (sensitive_data.server_key) { -@@ -581,13 +618,27 @@ demote_sensitive_data(void) - sensitive_data.server_key = tmp; - } - -+ pid = getpid(); -+ uid = getuid(); - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { -+ char *fp; -+ -+ if (key_is_private(sensitive_data.host_keys[i])) -+ fp = key_fingerprint(sensitive_data.host_keys[i], -+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, -+ SSH_FP_HEX); -+ else -+ fp = NULL; - tmp = key_demote(sensitive_data.host_keys[i]); - key_free(sensitive_data.host_keys[i]); - sensitive_data.host_keys[i] = tmp; - if (tmp->type == KEY_RSA1) - sensitive_data.ssh1_host_key = tmp; -+ if (fp != NULL) { -+ audit_destroy_sensitive_data(fp, pid, uid); -+ xfree(fp); -+ } - } - /* Certs do not need demotion */ - } -@@ -700,6 +751,8 @@ privsep_preauth(Authctxt *authctxt) - } - } - -+extern Newkeys *current_keys[]; -+ - static void - privsep_postauth(Authctxt *authctxt) - { -@@ -724,6 +777,10 @@ privsep_postauth(Authctxt *authctxt) - else if (pmonitor->m_pid != 0) { - verbose("User child is on pid %ld", (long)pmonitor->m_pid); - buffer_clear(&loginmsg); -+ newkeys_destroy(current_keys[MODE_OUT]); -+ newkeys_destroy(current_keys[MODE_IN]); -+ audit_session_key_free_body(2, getpid(), getuid()); -+ packet_destroy_all(0, 0); - monitor_child_postauth(pmonitor); - - /* NEVERREACHED */ -@@ -1153,6 +1210,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) - if (received_sigterm) { - logit("Received signal %d; terminating.", - (int) received_sigterm); -+ destroy_sensitive_data(0); - close_listen_socks(); - unlink(options.pid_file); - exit(received_sigterm == SIGTERM ? 0 : 255); -@@ -2032,6 +2090,7 @@ main(int ac, char **av) - */ - if (use_privsep) { - mm_send_keystate(pmonitor); -+ packet_destroy_all(1, 1); - exit(0); - } - -@@ -2074,7 +2133,7 @@ main(int ac, char **av) - privsep_postauth(authctxt); - /* the monitor process [priv] will not return */ - if (!compat20) -- destroy_sensitive_data(); -+ destroy_sensitive_data(0); - } - - packet_set_timeout(options.client_alive_interval, -@@ -2084,6 +2143,9 @@ main(int ac, char **av) - do_authenticated(authctxt); - - /* The connection has been terminated. */ -+ packet_destroy_all(1, 1); -+ destroy_sensitive_data(1); -+ - packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); - packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); - verbose("Transferred: sent %llu, received %llu bytes", -@@ -2241,6 +2303,10 @@ do_ssh1_kex(void) - if (cookie[i] != packet_get_char()) - packet_disconnect("IP Spoofing check bytes do not match."); - -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(2, cipher_name(cipher_type), "crc", "none"); -+#endif -+ - debug("Encryption type: %.200s", cipher_name(cipher_type)); - - /* Get the encrypted integer. */ -@@ -2307,7 +2373,7 @@ do_ssh1_kex(void) - session_id[i] = session_key[i] ^ session_key[i + 16]; - } - /* Destroy the private and public keys. No longer. */ -- destroy_sensitive_data(); -+ destroy_sensitive_data(0); - - if (use_privsep) - mm_ssh1_session_id(session_id); -@@ -2397,6 +2463,16 @@ do_ssh2_kex(void) - void - cleanup_exit(int i) - { -+ static int in_cleanup = 0; -+ int is_privsep_child; -+ -+ /* cleanup_exit can be called at the very least from the privsep -+ wrappers used for auditing. Make sure we don't recurse -+ indefinitely. */ -+ if (in_cleanup) -+ _exit(i); -+ in_cleanup = 1; -+ - if (the_authctxt) { - do_cleanup(the_authctxt); - if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) { -@@ -2407,9 +2483,14 @@ cleanup_exit(int i) - pmonitor->m_pid, strerror(errno)); - } - } -+ is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor(); -+ if (sensitive_data.host_keys != NULL) -+ destroy_sensitive_data(is_privsep_child); -+ packet_destroy_all(1, is_privsep_child); - #ifdef SSH_AUDIT_EVENTS - /* done after do_cleanup so it can cancel the PAM auth 'thread' */ -- if (!use_privsep || mm_is_monitor()) -+ if ((the_authctxt == NULL || !the_authctxt->authenticated) && -+ (!use_privsep || mm_is_monitor())) - audit_event(SSH_CONNECTION_ABANDON); - #endif - _exit(i); diff --git a/openssh-6.2p1-coverity.patch b/openssh-6.2p1-coverity.patch deleted file mode 100644 index 98e70d3..0000000 --- a/openssh-6.2p1-coverity.patch +++ /dev/null @@ -1,806 +0,0 @@ -diff -up openssh-6.2p1/auth-pam.c.coverity openssh-6.2p1/auth-pam.c ---- openssh-6.2p1/auth-pam.c.coverity 2009-07-12 14:07:21.000000000 +0200 -+++ openssh-6.2p1/auth-pam.c 2013-03-22 09:49:37.341595458 +0100 -@@ -216,7 +216,12 @@ pthread_join(sp_pthread_t thread, void * - if (sshpam_thread_status != -1) - return (sshpam_thread_status); - signal(SIGCHLD, sshpam_oldsig); -- waitpid(thread, &status, 0); -+ while (waitpid(thread, &status, 0) < 0) { -+ if (errno == EINTR) -+ continue; -+ fatal("%s: waitpid: %s", __func__, -+ strerror(errno)); -+ } - return (status); - } - #endif -diff -up openssh-6.2p1/channels.c.coverity openssh-6.2p1/channels.c ---- openssh-6.2p1/channels.c.coverity 2012-12-02 23:50:55.000000000 +0100 -+++ openssh-6.2p1/channels.c 2013-03-22 09:49:37.344595444 +0100 -@@ -232,11 +232,11 @@ channel_register_fds(Channel *c, int rfd - channel_max_fd = MAX(channel_max_fd, wfd); - channel_max_fd = MAX(channel_max_fd, efd); - -- if (rfd != -1) -+ if (rfd >= 0) - fcntl(rfd, F_SETFD, FD_CLOEXEC); -- if (wfd != -1 && wfd != rfd) -+ if (wfd >= 0 && wfd != rfd) - fcntl(wfd, F_SETFD, FD_CLOEXEC); -- if (efd != -1 && efd != rfd && efd != wfd) -+ if (efd >= 0 && efd != rfd && efd != wfd) - fcntl(efd, F_SETFD, FD_CLOEXEC); - - c->rfd = rfd; -@@ -251,11 +251,11 @@ channel_register_fds(Channel *c, int rfd - - /* enable nonblocking mode */ - if (nonblock) { -- if (rfd != -1) -+ if (rfd >= 0) - set_nonblock(rfd); -- if (wfd != -1) -+ if (wfd >= 0) - set_nonblock(wfd); -- if (efd != -1) -+ if (efd >= 0) - set_nonblock(efd); - } - } -diff -up openssh-6.2p1/clientloop.c.coverity openssh-6.2p1/clientloop.c ---- openssh-6.2p1/clientloop.c.coverity 2013-01-09 05:55:51.000000000 +0100 -+++ openssh-6.2p1/clientloop.c 2013-03-22 09:49:37.342595453 +0100 -@@ -2061,14 +2061,15 @@ client_input_global_request(int type, u_ - char *rtype; - int want_reply; - int success = 0; -+/* success is still 0 the packet is allways SSH2_MSG_REQUEST_FAILURE, isn't it? */ - - rtype = packet_get_string(NULL); - want_reply = packet_get_char(); - debug("client_input_global_request: rtype %s want_reply %d", - rtype, want_reply); - if (want_reply) { -- packet_start(success ? -- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); -+ packet_start(/*success ? -+ SSH2_MSG_REQUEST_SUCCESS :*/ SSH2_MSG_REQUEST_FAILURE); - packet_send(); - packet_write_wait(); - } -diff -up openssh-6.2p1/key.c.coverity openssh-6.2p1/key.c ---- openssh-6.2p1/key.c.coverity 2013-01-18 01:44:05.000000000 +0100 -+++ openssh-6.2p1/key.c 2013-03-22 09:49:37.345595440 +0100 -@@ -808,8 +808,10 @@ key_read(Key *ret, char **cpp) - success = 1; - /*XXXX*/ - key_free(k); -+/*XXXX - if (success != 1) - break; -+XXXX*/ - /* advance cp: skip whitespace and data */ - while (*cp == ' ' || *cp == '\t') - cp++; -diff -up openssh-6.2p1/monitor.c.coverity openssh-6.2p1/monitor.c ---- openssh-6.2p1/monitor.c.coverity 2012-12-12 00:44:39.000000000 +0100 -+++ openssh-6.2p1/monitor.c 2013-03-22 12:19:55.189921353 +0100 -@@ -449,7 +449,7 @@ monitor_child_preauth(Authctxt *_authctx - mm_get_keystate(pmonitor); - - /* Drain any buffered messages from the child */ -- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) -+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) - ; - - close(pmonitor->m_sendfd); -@@ -1194,6 +1194,10 @@ mm_answer_keyallowed(int sock, Buffer *m - break; - } - } -+ -+ debug3("%s: key %p is %s", -+ __func__, key, allowed ? "allowed" : "not allowed"); -+ - if (key != NULL) - key_free(key); - -@@ -1216,9 +1220,6 @@ mm_answer_keyallowed(int sock, Buffer *m - xfree(chost); - } - -- debug3("%s: key %p is %s", -- __func__, key, allowed ? "allowed" : "not allowed"); -- - buffer_clear(m); - buffer_put_int(m, allowed); - buffer_put_int(m, forced_command != NULL); -diff -up openssh-6.2p1/monitor_wrap.c.coverity openssh-6.2p1/monitor_wrap.c ---- openssh-6.2p1/monitor_wrap.c.coverity 2013-01-09 06:12:19.000000000 +0100 -+++ openssh-6.2p1/monitor_wrap.c 2013-03-22 09:49:37.347595431 +0100 -@@ -708,10 +708,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, - if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || - (tmp2 = dup(pmonitor->m_recvfd)) == -1) { - error("%s: cannot allocate fds for pty", __func__); -- if (tmp1 > 0) -+ if (tmp1 >= 0) - close(tmp1); -- if (tmp2 > 0) -- close(tmp2); -+ /*DEAD CODE if (tmp2 >= 0) -+ close(tmp2);*/ - return 0; - } - close(tmp1); -diff -up openssh-6.2p1/openbsd-compat/bindresvport.c.coverity openssh-6.2p1/openbsd-compat/bindresvport.c ---- openssh-6.2p1/openbsd-compat/bindresvport.c.coverity 2010-12-03 00:50:26.000000000 +0100 -+++ openssh-6.2p1/openbsd-compat/bindresvport.c 2013-03-22 09:49:37.347595431 +0100 -@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr - struct sockaddr_in6 *in6; - u_int16_t *portp; - u_int16_t port; -- socklen_t salen; -+ socklen_t salen = sizeof(struct sockaddr_storage); - int i; - - if (sa == NULL) { -diff -up openssh-6.2p1/packet.c.coverity openssh-6.2p1/packet.c ---- openssh-6.2p1/packet.c.coverity 2013-02-12 01:03:59.000000000 +0100 -+++ openssh-6.2p1/packet.c 2013-03-22 09:49:37.348595426 +0100 -@@ -1192,6 +1192,7 @@ packet_read_poll1(void) - case DEATTACK_DETECTED: - packet_disconnect("crc32 compensation attack: " - "network attack detected"); -+ break; - case DEATTACK_DOS_DETECTED: - packet_disconnect("deattack denial of " - "service detected"); -@@ -1728,7 +1729,7 @@ void - packet_write_wait(void) - { - fd_set *setp; -- int ret, ms_remain; -+ int ret, ms_remain = 0; - struct timeval start, timeout, *timeoutp = NULL; - - setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, -diff -up openssh-6.2p1/progressmeter.c.coverity openssh-6.2p1/progressmeter.c ---- openssh-6.2p1/progressmeter.c.coverity 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-6.2p1/progressmeter.c 2013-03-22 09:49:37.349595422 +0100 -@@ -65,7 +65,7 @@ static void update_progress_meter(int); - - static time_t start; /* start progress */ - static time_t last_update; /* last progress update */ --static char *file; /* name of the file being transferred */ -+static const 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 volatile off_t *counter; /* progress counter */ -@@ -247,7 +247,7 @@ update_progress_meter(int ignore) - } - - void --start_progress_meter(char *f, off_t filesize, off_t *ctr) -+start_progress_meter(const char *f, off_t filesize, off_t *ctr) - { - start = last_update = time(NULL); - file = f; -diff -up openssh-6.2p1/progressmeter.h.coverity openssh-6.2p1/progressmeter.h ---- openssh-6.2p1/progressmeter.h.coverity 2006-03-26 05:30:02.000000000 +0200 -+++ openssh-6.2p1/progressmeter.h 2013-03-22 09:49:37.349595422 +0100 -@@ -23,5 +23,5 @@ - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - --void start_progress_meter(char *, off_t, off_t *); -+void start_progress_meter(const char *, off_t, off_t *); - void stop_progress_meter(void); -diff -up openssh-6.2p1/scp.c.coverity openssh-6.2p1/scp.c ---- openssh-6.2p1/scp.c.coverity 2013-03-20 02:55:15.000000000 +0100 -+++ openssh-6.2p1/scp.c 2013-03-22 09:49:37.349595422 +0100 -@@ -155,7 +155,7 @@ killchild(int signo) - { - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid, NULL, 0); -+ (void) waitpid(do_cmd_pid, NULL, 0); - } - - if (signo) -diff -up openssh-6.2p1/servconf.c.coverity openssh-6.2p1/servconf.c ---- openssh-6.2p1/servconf.c.coverity 2013-02-12 01:02:08.000000000 +0100 -+++ openssh-6.2p1/servconf.c 2013-03-22 09:49:37.350595418 +0100 -@@ -1268,7 +1268,7 @@ process_server_config_line(ServerOptions - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - if (!*activep) { -- arg = strdelim(&cp); -+ /*arg =*/ (void) strdelim(&cp); - break; - } - for (i = 0; i < options->num_subsystems; i++) -@@ -1359,8 +1359,9 @@ process_server_config_line(ServerOptions - if (*activep && *charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ -- if (intptr != NULL) -- *intptr = *intptr + 1; -+ /* DEAD CODE intptr is still NULL ;) -+ if (intptr != NULL) -+ *intptr = *intptr + 1; */ - } - break; - -diff -up openssh-6.2p1/serverloop.c.coverity openssh-6.2p1/serverloop.c ---- openssh-6.2p1/serverloop.c.coverity 2012-12-07 03:07:47.000000000 +0100 -+++ openssh-6.2p1/serverloop.c 2013-03-22 09:49:37.351595413 +0100 -@@ -147,13 +147,13 @@ notify_setup(void) - static void - notify_parent(void) - { -- if (notify_pipe[1] != -1) -+ if (notify_pipe[1] >= 0) - write(notify_pipe[1], "", 1); - } - static void - notify_prepare(fd_set *readset) - { -- if (notify_pipe[0] != -1) -+ if (notify_pipe[0] >= 0) - FD_SET(notify_pipe[0], readset); - } - static void -@@ -161,8 +161,8 @@ notify_done(fd_set *readset) - { - char c; - -- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) -- while (read(notify_pipe[0], &c, 1) != -1) -+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) -+ while (read(notify_pipe[0], &c, 1) >= 0) - debug2("notify_done: reading"); - } - -@@ -336,7 +336,7 @@ wait_until_can_do_something(fd_set **rea - * If we have buffered data, try to write some of that data - * to the program. - */ -- if (fdin != -1 && buffer_len(&stdin_buffer) > 0) -+ if (fdin >= 0 && buffer_len(&stdin_buffer) > 0) - FD_SET(fdin, *writesetp); - } - notify_prepare(*readsetp); -@@ -476,7 +476,7 @@ process_output(fd_set *writeset) - int len; - - /* Write buffered data to program stdin. */ -- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { -+ if (!compat20 && fdin >= 0 && FD_ISSET(fdin, writeset)) { - data = buffer_ptr(&stdin_buffer); - dlen = buffer_len(&stdin_buffer); - len = write(fdin, data, dlen); -@@ -589,7 +589,7 @@ server_loop(pid_t pid, int fdin_arg, int - set_nonblock(fdin); - set_nonblock(fdout); - /* we don't have stderr for interactive terminal sessions, see below */ -- if (fderr != -1) -+ if (fderr >= 0) - set_nonblock(fderr); - - if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) -@@ -613,7 +613,7 @@ server_loop(pid_t pid, int fdin_arg, int - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); -- if (fderr != -1) -+ if (fderr >= 0) - max_fd = MAX(max_fd, fderr); - #endif - -@@ -643,7 +643,7 @@ server_loop(pid_t pid, int fdin_arg, int - * If we have received eof, and there is no more pending - * input data, cause a real eof by closing fdin. - */ -- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { -+ if (stdin_eof && fdin >= 0 && buffer_len(&stdin_buffer) == 0) { - if (fdin != fdout) - close(fdin); - else -@@ -741,15 +741,15 @@ server_loop(pid_t pid, int fdin_arg, int - buffer_free(&stderr_buffer); - - /* Close the file descriptors. */ -- if (fdout != -1) -+ if (fdout >= 0) - close(fdout); - fdout = -1; - fdout_eof = 1; -- if (fderr != -1) -+ if (fderr >= 0) - close(fderr); - fderr = -1; - fderr_eof = 1; -- if (fdin != -1) -+ if (fdin >= 0) - close(fdin); - fdin = -1; - -@@ -943,7 +943,7 @@ server_input_window_size(int type, u_int - - debug("Window change received."); - packet_check_eom(); -- if (fdin != -1) -+ if (fdin >= 0) - pty_change_window_size(fdin, row, col, xpixel, ypixel); - } - -@@ -1003,7 +1003,7 @@ server_request_tun(void) - } - - tun = packet_get_int(); -- if (forced_tun_device != -1) { -+ if (forced_tun_device >= 0) { - if (tun != SSH_TUNID_ANY && forced_tun_device != tun) - goto done; - tun = forced_tun_device; -diff -up openssh-6.2p1/sftp.c.coverity openssh-6.2p1/sftp.c ---- openssh-6.2p1/sftp.c.coverity 2013-02-22 23:12:24.000000000 +0100 -+++ openssh-6.2p1/sftp.c 2013-03-22 09:49:37.352595409 +0100 -@@ -202,7 +202,7 @@ killchild(int signo) - { - if (sshpid > 1) { - kill(sshpid, SIGTERM); -- waitpid(sshpid, NULL, 0); -+ (void) waitpid(sshpid, NULL, 0); - } - - _exit(1); -@@ -312,7 +312,7 @@ local_do_ls(const char *args) - - /* Strip one path (usually the pwd) from the start of another */ - static char * --path_strip(char *path, char *strip) -+path_strip(const char *path, const char *strip) - { - size_t len; - -@@ -330,7 +330,7 @@ path_strip(char *path, char *strip) - } - - static char * --make_absolute(char *p, char *pwd) -+make_absolute(char *p, const char *pwd) - { - char *abs_str; - -@@ -478,7 +478,7 @@ parse_df_flags(const char *cmd, char **a - } - - static int --is_dir(char *path) -+is_dir(const char *path) - { - struct stat sb; - -@@ -490,7 +490,7 @@ is_dir(char *path) - } - - static int --remote_is_dir(struct sftp_conn *conn, char *path) -+remote_is_dir(struct sftp_conn *conn, const char *path) - { - Attrib *a; - -@@ -504,7 +504,7 @@ remote_is_dir(struct sftp_conn *conn, ch - - /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ - static int --pathname_is_dir(char *pathname) -+pathname_is_dir(const char *pathname) - { - size_t l = strlen(pathname); - -@@ -512,7 +512,7 @@ pathname_is_dir(char *pathname) - } - - static int --process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, -+process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, - int pflag, int rflag) - { - char *abs_src = NULL; -@@ -586,7 +586,7 @@ out: - } - - static int --process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, -+process_put(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, - int pflag, int rflag) - { - char *tmp_dst = NULL; -@@ -691,7 +691,7 @@ sdirent_comp(const void *aa, const void - - /* sftp ls.1 replacement for directories */ - static int --do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) -+do_ls_dir(struct sftp_conn *conn, const char *path, const char *strip_path, int lflag) - { - int n; - u_int c = 1, colspace = 0, columns = 1; -@@ -776,7 +776,7 @@ do_ls_dir(struct sftp_conn *conn, char * - - /* sftp ls.1 replacement which handles path globs */ - static int --do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, -+do_globbed_ls(struct sftp_conn *conn, const char *path, const char *strip_path, - int lflag) - { - char *fname, *lname; -@@ -857,7 +857,7 @@ do_globbed_ls(struct sftp_conn *conn, ch - } - - static int --do_df(struct sftp_conn *conn, char *path, int hflag, int iflag) -+do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) - { - struct sftp_statvfs st; - char s_used[FMT_SCALED_STRSIZE]; -diff -up openssh-6.2p1/sftp-client.c.coverity openssh-6.2p1/sftp-client.c ---- openssh-6.2p1/sftp-client.c.coverity 2012-07-02 14:15:39.000000000 +0200 -+++ openssh-6.2p1/sftp-client.c 2013-03-22 09:49:37.353595404 +0100 -@@ -149,7 +149,7 @@ get_msg(struct sftp_conn *conn, Buffer * - } - - static void --send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, -+send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, - u_int len) - { - Buffer msg; -@@ -165,7 +165,7 @@ send_string_request(struct sftp_conn *co - - static void - send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, -- char *s, u_int len, Attrib *a) -+ const char *s, u_int len, Attrib *a) - { - Buffer msg; - -@@ -422,7 +422,7 @@ sftp_proto_version(struct sftp_conn *con - } - - int --do_close(struct sftp_conn *conn, char *handle, u_int handle_len) -+do_close(struct sftp_conn *conn, const char *handle, u_int handle_len) - { - u_int id, status; - Buffer msg; -@@ -447,7 +447,7 @@ do_close(struct sftp_conn *conn, char *h - - - static int --do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, -+do_lsreaddir(struct sftp_conn *conn, const char *path, int printflag, - SFTP_DIRENT ***dir) - { - Buffer msg; -@@ -572,7 +572,7 @@ do_lsreaddir(struct sftp_conn *conn, cha - } - - int --do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) -+do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) - { - return(do_lsreaddir(conn, path, 0, dir)); - } -@@ -590,7 +590,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) - } - - int --do_rm(struct sftp_conn *conn, char *path) -+do_rm(struct sftp_conn *conn, const char *path) - { - u_int status, id; - -@@ -605,7 +605,7 @@ do_rm(struct sftp_conn *conn, char *path - } - - int --do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag) -+do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int printflag) - { - u_int status, id; - -@@ -621,7 +621,7 @@ do_mkdir(struct sftp_conn *conn, char *p - } - - int --do_rmdir(struct sftp_conn *conn, char *path) -+do_rmdir(struct sftp_conn *conn, const char *path) - { - u_int status, id; - -@@ -637,7 +637,7 @@ do_rmdir(struct sftp_conn *conn, char *p - } - - Attrib * --do_stat(struct sftp_conn *conn, char *path, int quiet) -+do_stat(struct sftp_conn *conn, const char *path, int quiet) - { - u_int id; - -@@ -651,7 +651,7 @@ do_stat(struct sftp_conn *conn, char *pa - } - - Attrib * --do_lstat(struct sftp_conn *conn, char *path, int quiet) -+do_lstat(struct sftp_conn *conn, const char *path, int quiet) - { - u_int id; - -@@ -685,7 +685,7 @@ do_fstat(struct sftp_conn *conn, char *h - #endif - - int --do_setstat(struct sftp_conn *conn, char *path, Attrib *a) -+do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) - { - u_int status, id; - -@@ -702,7 +702,7 @@ do_setstat(struct sftp_conn *conn, char - } - - int --do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, -+do_fsetstat(struct sftp_conn *conn, const char *handle, u_int handle_len, - Attrib *a) - { - u_int status, id; -@@ -719,7 +719,7 @@ do_fsetstat(struct sftp_conn *conn, char - } - - char * --do_realpath(struct sftp_conn *conn, char *path) -+do_realpath(struct sftp_conn *conn, const char *path) - { - Buffer msg; - u_int type, expected_id, count, id; -@@ -768,7 +768,7 @@ do_realpath(struct sftp_conn *conn, char - } - - int --do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -802,7 +802,7 @@ do_rename(struct sftp_conn *conn, char * - } - - int --do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -835,7 +835,7 @@ do_hardlink(struct sftp_conn *conn, char - } - - int --do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -987,7 +987,7 @@ send_read_request(struct sftp_conn *conn - } - - int --do_download(struct sftp_conn *conn, char *remote_path, char *local_path, -+do_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, - Attrib *a, int pflag) - { - Attrib junk; -@@ -1226,7 +1226,7 @@ do_download(struct sftp_conn *conn, char - } - - static int --download_dir_internal(struct sftp_conn *conn, char *src, char *dst, -+download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - Attrib *dirattrib, int pflag, int printflag, int depth) - { - int i, ret = 0; -@@ -1316,7 +1316,7 @@ download_dir_internal(struct sftp_conn * - } - - int --download_dir(struct sftp_conn *conn, char *src, char *dst, -+download_dir(struct sftp_conn *conn, const char *src, const char *dst, - Attrib *dirattrib, int pflag, int printflag) - { - char *src_canon; -@@ -1334,7 +1334,7 @@ download_dir(struct sftp_conn *conn, cha - } - - int --do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, -+do_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, - int pflag) - { - int local_fd; -@@ -1517,7 +1517,7 @@ do_upload(struct sftp_conn *conn, char * - } - - static int --upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, -+upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - int pflag, int printflag, int depth) - { - int ret = 0, status; -@@ -1608,7 +1608,7 @@ upload_dir_internal(struct sftp_conn *co - } - - int --upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, -+upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int printflag, - int pflag) - { - char *dst_canon; -@@ -1625,7 +1625,7 @@ upload_dir(struct sftp_conn *conn, char - } - - char * --path_append(char *p1, char *p2) -+path_append(const char *p1, const char *p2) - { - char *ret; - size_t len = strlen(p1) + strlen(p2) + 2; -diff -up openssh-6.2p1/sftp-client.h.coverity openssh-6.2p1/sftp-client.h ---- openssh-6.2p1/sftp-client.h.coverity 2010-12-04 23:02:48.000000000 +0100 -+++ openssh-6.2p1/sftp-client.h 2013-03-22 09:49:37.353595404 +0100 -@@ -56,49 +56,49 @@ struct sftp_conn *do_init(int, int, u_in - u_int sftp_proto_version(struct sftp_conn *); - - /* Close file referred to by 'handle' */ --int do_close(struct sftp_conn *, char *, u_int); -+int do_close(struct sftp_conn *, const char *, u_int); - - /* Read contents of 'path' to NULL-terminated array 'dir' */ --int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); -+int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); - - /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ - void free_sftp_dirents(SFTP_DIRENT **); - - /* Delete file 'path' */ --int do_rm(struct sftp_conn *, char *); -+int do_rm(struct sftp_conn *, const char *); - - /* Create directory 'path' */ --int do_mkdir(struct sftp_conn *, char *, Attrib *, int); -+int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); - - /* Remove directory 'path' */ --int do_rmdir(struct sftp_conn *, char *); -+int do_rmdir(struct sftp_conn *, const char *); - - /* Get file attributes of 'path' (follows symlinks) */ --Attrib *do_stat(struct sftp_conn *, char *, int); -+Attrib *do_stat(struct sftp_conn *, const char *, int); - - /* Get file attributes of 'path' (does not follow symlinks) */ --Attrib *do_lstat(struct sftp_conn *, char *, int); -+Attrib *do_lstat(struct sftp_conn *, const char *, int); - - /* Set file attributes of 'path' */ --int do_setstat(struct sftp_conn *, char *, Attrib *); -+int do_setstat(struct sftp_conn *, const char *, Attrib *); - - /* Set file attributes of open file 'handle' */ --int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); -+int do_fsetstat(struct sftp_conn *, const char *, u_int, Attrib *); - - /* Canonicalise 'path' - caller must free result */ --char *do_realpath(struct sftp_conn *, char *); -+char *do_realpath(struct sftp_conn *, const char *); - - /* Get statistics for filesystem hosting file at "path" */ - int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); - - /* Rename 'oldpath' to 'newpath' */ --int do_rename(struct sftp_conn *, char *, char *); -+int do_rename(struct sftp_conn *, const char *, const char *); - - /* Link 'oldpath' to 'newpath' */ --int do_hardlink(struct sftp_conn *, char *, char *); -+int do_hardlink(struct sftp_conn *, const char *, const char *); - --/* Rename 'oldpath' to 'newpath' */ --int do_symlink(struct sftp_conn *, char *, char *); -+/* Symlink 'oldpath' to 'newpath' */ -+int do_symlink(struct sftp_conn *, const char *, const char *); - - /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ - -@@ -106,27 +106,27 @@ int do_symlink(struct sftp_conn *, char - * Download 'remote_path' to 'local_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_download(struct sftp_conn *, char *, char *, Attrib *, int); -+int do_download(struct sftp_conn *, const char *, const char *, Attrib *, int); - - /* - * Recursively download 'remote_directory' to 'local_directory'. Preserve - * times if 'pflag' is set - */ --int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int); -+int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int); - - /* - * Upload 'local_path' to 'remote_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_upload(struct sftp_conn *, char *, char *, int); -+int do_upload(struct sftp_conn *, const char *, const char *, int); - - /* - * Recursively upload 'local_directory' to 'remote_directory'. Preserve - * times if 'pflag' is set - */ --int upload_dir(struct sftp_conn *, char *, char *, int, int); -+int upload_dir(struct sftp_conn *, const char *, const char *, int, int); - - /* Concatenate paths, taking care of slashes. Caller must free result. */ --char *path_append(char *, char *); -+char *path_append(const char *, const char *); - - #endif -diff -up openssh-6.2p1/ssh-agent.c.coverity openssh-6.2p1/ssh-agent.c ---- openssh-6.2p1/ssh-agent.c.coverity 2011-06-03 06:14:16.000000000 +0200 -+++ openssh-6.2p1/ssh-agent.c 2013-03-22 09:49:37.354595400 +0100 -@@ -1147,8 +1147,8 @@ main(int ac, char **av) - sanitise_stdfd(); - - /* drop */ -- setegid(getgid()); -- setgid(getgid()); -+ (void) setegid(getgid()); -+ (void) setgid(getgid()); - - #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) - /* Disable ptrace on Linux without sgid bit */ -diff -up openssh-6.2p1/sshd.c.coverity openssh-6.2p1/sshd.c ---- openssh-6.2p1/sshd.c.coverity 2013-02-12 01:04:48.000000000 +0100 -+++ openssh-6.2p1/sshd.c 2013-03-22 09:49:37.355595396 +0100 -@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) - if (getuid() == 0 || geteuid() == 0) - privsep_preauth_child(); - setproctitle("%s", "[net]"); -- if (box != NULL) -+ if (box != NULL) { - ssh_sandbox_child(box); -+ xfree(box); -+ } - - return 0; - } -@@ -1320,6 +1322,9 @@ server_accept_loop(int *sock_in, int *so - if (num_listen_socks < 0) - break; - } -+ -+ if (fdset != NULL) -+ xfree(fdset); - } - - -@@ -1806,7 +1811,7 @@ main(int ac, char **av) - - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ -- chdir("/"); -+ (void) chdir("/"); - - /* ignore SIGPIPE */ - signal(SIGPIPE, SIG_IGN); diff --git a/openssh-6.2p1-ctr-cavstest.patch b/openssh-6.2p1-ctr-cavstest.patch deleted file mode 100644 index 1376a3f..0000000 --- a/openssh-6.2p1-ctr-cavstest.patch +++ /dev/null @@ -1,250 +0,0 @@ -diff -up openssh-6.2p1/ctr-cavstest.c.ctr-cavs openssh-6.2p1/ctr-cavstest.c ---- openssh-6.2p1/ctr-cavstest.c.ctr-cavs 2013-03-25 21:35:52.512586671 +0100 -+++ openssh-6.2p1/ctr-cavstest.c 2013-03-25 21:35:52.512586671 +0100 -@@ -0,0 +1,208 @@ -+/* -+ * -+ * invocation (all of the following are equal): -+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 -+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000 -+ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xmalloc.h" -+#include "log.h" -+#include "cipher.h" -+ -+/* compatibility with old or broken OpenSSL versions */ -+#include "openbsd-compat/openssl-compat.h" -+ -+void usage(void) { -+ fprintf(stderr, "Usage: ctr-cavstest --algo \n" -+ " --key --mode \n" -+ " [--iv ] --data \n\n" -+ "Hexadecimal output is printed to stdout.\n" -+ "Hexadecimal input data can be alternatively read from stdin.\n"); -+ exit(1); -+} -+ -+void *fromhex(char *hex, size_t *len) -+{ -+ unsigned char *bin; -+ char *p; -+ size_t n = 0; -+ int shift = 4; -+ unsigned char out = 0; -+ unsigned char *optr; -+ -+ bin = xmalloc(strlen(hex)/2); -+ optr = bin; -+ -+ for (p = hex; *p != '\0'; ++p) { -+ unsigned char c; -+ -+ c = *p; -+ if (isspace(c)) -+ continue; -+ -+ if (c >= '0' && c <= '9') { -+ c = c - '0'; -+ } else if (c >= 'A' && c <= 'F') { -+ c = c - 'A' + 10; -+ } else if (c >= 'a' && c <= 'f') { -+ c = c - 'a' + 10; -+ } else { -+ /* truncate on nonhex cipher */ -+ break; -+ } -+ -+ out |= c << shift; -+ shift = (shift + 4) % 8; -+ -+ if (shift) { -+ *(optr++) = out; -+ out = 0; -+ ++n; -+ } -+ } -+ -+ *len = n; -+ return bin; -+} -+ -+#define READ_CHUNK 4096 -+#define MAX_READ_SIZE 1024*1024*100 -+char *read_stdin(void) -+{ -+ char *buf; -+ size_t n, total = 0; -+ -+ buf = xmalloc(READ_CHUNK); -+ -+ do { -+ n = fread(buf + total, 1, READ_CHUNK, stdin); -+ if (n < READ_CHUNK) /* terminate on short read */ -+ break; -+ -+ total += n; -+ buf = xrealloc(buf, total + READ_CHUNK, 1); -+ } while(total < MAX_READ_SIZE); -+ return buf; -+} -+ -+int main (int argc, char *argv[]) -+{ -+ -+ Cipher *c; -+ CipherContext cc; -+ char *algo = "aes128-ctr"; -+ char *hexkey = NULL; -+ char *hexiv = "00000000000000000000000000000000"; -+ char *hexdata = NULL; -+ char *p; -+ int i; -+ int encrypt = 1; -+ void *key; -+ size_t keylen; -+ void *iv; -+ size_t ivlen; -+ void *data; -+ size_t datalen; -+ void *outdata; -+ -+ for (i = 1; i < argc; ++i) { -+ if (strcmp(argv[i], "--algo") == 0) { -+ algo = argv[++i]; -+ } else if (strcmp(argv[i], "--key") == 0) { -+ hexkey = argv[++i]; -+ } else if (strcmp(argv[i], "--mode") == 0) { -+ ++i; -+ if (argv[i] == NULL) { -+ usage(); -+ } -+ if (strncmp(argv[i], "enc", 3) == 0) { -+ encrypt = 1; -+ } else if (strncmp(argv[i], "dec", 3) == 0) { -+ encrypt = 0; -+ } else { -+ usage(); -+ } -+ } else if (strcmp(argv[i], "--iv") == 0) { -+ hexiv = argv[++i]; -+ } else if (strcmp(argv[i], "--data") == 0) { -+ hexdata = argv[++i]; -+ } -+ } -+ -+ if (hexkey == NULL || algo == NULL) { -+ usage(); -+ } -+ -+ SSLeay_add_all_algorithms(); -+ -+ c = cipher_by_name(algo); -+ if (c == NULL) { -+ fprintf(stderr, "Error: unknown algorithm\n"); -+ return 2; -+ } -+ -+ if (hexdata == NULL) { -+ hexdata = read_stdin(); -+ } else { -+ hexdata = xstrdup(hexdata); -+ } -+ -+ key = fromhex(hexkey, &keylen); -+ -+ if (keylen != 16 && keylen != 24 && keylen == 32) { -+ fprintf(stderr, "Error: unsupported key length\n"); -+ return 2; -+ } -+ -+ iv = fromhex(hexiv, &ivlen); -+ -+ if (ivlen != 16) { -+ fprintf(stderr, "Error: unsupported iv length\n"); -+ return 2; -+ } -+ -+ data = fromhex(hexdata, &datalen); -+ -+ if (data == NULL || datalen == 0) { -+ fprintf(stderr, "Error: no data to encrypt/decrypt\n"); -+ return 2; -+ } -+ -+ cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt); -+ -+ xfree(key); -+ xfree(iv); -+ -+ outdata = malloc(datalen); -+ if(outdata == NULL) { -+ fprintf(stderr, "Error: memory allocation failure\n"); -+ return 2; -+ } -+ -+ cipher_crypt(&cc, outdata, data, datalen, 0, 0); -+ -+ xfree(data); -+ -+ cipher_cleanup(&cc); -+ -+ for (p = outdata; datalen > 0; ++p, --datalen) { -+ printf("%02X", (unsigned char)*p); -+ } -+ -+ xfree(outdata); -+ -+ printf("\n"); -+ return 0; -+} -+ -diff -up openssh-6.2p1/Makefile.in.ctr-cavs openssh-6.2p1/Makefile.in ---- openssh-6.2p1/Makefile.in.ctr-cavs 2013-03-25 21:35:52.451586280 +0100 -+++ openssh-6.2p1/Makefile.in 2013-03-25 21:37:14.956114584 +0100 -@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign - SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper - SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper - SSH_KEYCAT=$(libexecdir)/ssh-keycat -+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest - SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ -@@ -65,7 +66,7 @@ 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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(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-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) - - LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ - canohost.o channels.o cipher.o cipher-aes.o \ -@@ -174,6 +175,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l - ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o - $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) - -+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o -+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -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 -lfipscheck $(LIBS) - -@@ -281,6 +285,7 @@ install-files: - $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ - fi - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) -+ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 diff --git a/openssh-6.2p1-fingerprint.patch b/openssh-6.2p1-fingerprint.patch deleted file mode 100644 index 92f8a4c..0000000 --- a/openssh-6.2p1-fingerprint.patch +++ /dev/null @@ -1,421 +0,0 @@ -diff -up openssh-6.2p1/auth2-hostbased.c.fingerprint openssh-6.2p1/auth2-hostbased.c ---- openssh-6.2p1/auth2-hostbased.c.fingerprint 2010-08-05 05:04:50.000000000 +0200 -+++ openssh-6.2p1/auth2-hostbased.c 2013-03-22 12:20:49.009685008 +0100 -@@ -196,16 +196,18 @@ hostbased_key_allowed(struct passwd *pw, - - if (host_status == HOST_OK) { - if (key_is_cert(key)) { -- fp = key_fingerprint(key->cert->signature_key, -- SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_selected_fingerprint(key->cert->signature_key, -+ SSH_FP_HEX); - verbose("Accepted certificate ID \"%s\" signed by " -- "%s CA %s from %s@%s", key->cert->key_id, -- key_type(key->cert->signature_key), fp, -+ "%s CA %s%s from %s@%s", key->cert->key_id, -+ key_type(key->cert->signature_key), -+ key_fingerprint_prefix(), fp, - cuser, lookup); - } else { -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- verbose("Accepted %s public key %s from %s@%s", -- key_type(key), fp, cuser, lookup); -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ verbose("Accepted %s public key %s%s from %s@%s", -+ key_type(key), key_fingerprint_prefix(), -+ fp, cuser, lookup); - } - xfree(fp); - } -diff -up openssh-6.2p1/auth2-pubkey.c.fingerprint openssh-6.2p1/auth2-pubkey.c ---- openssh-6.2p1/auth2-pubkey.c.fingerprint 2013-02-15 00:28:56.000000000 +0100 -+++ openssh-6.2p1/auth2-pubkey.c 2013-03-22 12:20:49.009685008 +0100 -@@ -317,10 +317,10 @@ check_authkeys_file(FILE *f, char *file, - continue; - if (!key_is_cert_authority) - continue; -- fp = key_fingerprint(found, SSH_FP_MD5, -- SSH_FP_HEX); -- debug("matching CA found: file %s, line %lu, %s %s", -- file, linenum, key_type(found), fp); -+ fp = key_selected_fingerprint(found, SSH_FP_HEX); -+ debug("matching CA found: file %s, line %lu, %s %s%s", -+ file, linenum, key_type(found), -+ key_fingerprint_prefix(), fp); - /* - * If the user has specified a list of principals as - * a key option, then prefer that list to matching -@@ -360,9 +360,9 @@ check_authkeys_file(FILE *f, char *file, - found_key = 1; - debug("matching key found: file %s, line %lu", - file, linenum); -- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -- verbose("Found matching %s key: %s", -- key_type(found), fp); -+ fp = key_selected_fingerprint(found, SSH_FP_HEX); -+ verbose("Found matching %s key: %s%s", -+ key_type(found), key_fingerprint_prefix(), fp); - xfree(fp); - break; - } -@@ -384,13 +384,13 @@ user_cert_trusted_ca(struct passwd *pw, - if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) - return 0; - -- ca_fp = key_fingerprint(key->cert->signature_key, -- SSH_FP_MD5, SSH_FP_HEX); -+ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); - - if (key_in_file(key->cert->signature_key, - options.trusted_user_ca_keys, 1) != 1) { -- debug2("%s: CA %s %s is not listed in %s", __func__, -- key_type(key->cert->signature_key), ca_fp, -+ debug2("%s: CA %s%s %s is not listed in %s", __func__, -+ key_type(key->cert->signature_key), -+ key_fingerprint_prefix(), ca_fp, - options.trusted_user_ca_keys); - goto out; - } -diff -up openssh-6.2p1/auth.c.fingerprint openssh-6.2p1/auth.c ---- openssh-6.2p1/auth.c.fingerprint 2013-03-12 01:31:05.000000000 +0100 -+++ openssh-6.2p1/auth.c 2013-03-22 12:22:32.515230386 +0100 -@@ -663,9 +663,10 @@ auth_key_is_revoked(Key *key) - case 1: - revoked: - /* Key revoked */ -- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ key_fp = key_selected_fingerprint(key, SSH_FP_HEX); - error("WARNING: authentication attempt with a revoked " -- "%s key %s ", key_type(key), key_fp); -+ "%s key %s%s ", key_type(key), -+ key_fingerprint_prefix(), key_fp); - xfree(key_fp); - return 1; - } -diff -up openssh-6.2p1/auth-rsa.c.fingerprint openssh-6.2p1/auth-rsa.c ---- openssh-6.2p1/auth-rsa.c.fingerprint 2012-10-30 22:58:59.000000000 +0100 -+++ openssh-6.2p1/auth-rsa.c 2013-03-22 12:20:49.011684999 +0100 -@@ -328,9 +328,9 @@ auth_rsa(Authctxt *authctxt, BIGNUM *cli - * options; this will be reset if the options cause the - * authentication to be rejected. - */ -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- verbose("Found matching %s key: %s", -- key_type(key), fp); -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ verbose("Found matching %s key: %s%s", -+ key_type(key), key_fingerprint_prefix(), fp); - xfree(fp); - key_free(key); - -diff -up openssh-6.2p1/key.c.fingerprint openssh-6.2p1/key.c ---- openssh-6.2p1/key.c.fingerprint 2013-03-22 12:20:48.971685175 +0100 -+++ openssh-6.2p1/key.c 2013-03-22 12:20:49.012684995 +0100 -@@ -599,6 +599,34 @@ key_fingerprint(Key *k, enum fp_type dgs - return retval; - } - -+enum fp_type -+key_fingerprint_selection(void) -+{ -+ static enum fp_type rv; -+ static char rv_defined = 0; -+ char *env; -+ -+ if (!rv_defined) { -+ env = getenv("SSH_FINGERPRINT_TYPE"); -+ rv = (env && !strcmp (env, "sha")) ? -+ SSH_FP_SHA1 : SSH_FP_MD5; -+ rv_defined = 1; -+ } -+ return rv; -+} -+ -+char * -+key_selected_fingerprint(Key *k, enum fp_rep dgst_rep) -+{ -+ return key_fingerprint(k, key_fingerprint_selection(), dgst_rep); -+} -+ -+char * -+key_fingerprint_prefix(void) -+{ -+ return key_fingerprint_selection() == SSH_FP_SHA1 ? "sha1:" : ""; -+} -+ - /* - * Reads a multiple-precision integer in decimal from the buffer, and advances - * the pointer. The integer must already be initialized. This function is -diff -up openssh-6.2p1/key.h.fingerprint openssh-6.2p1/key.h ---- openssh-6.2p1/key.h.fingerprint 2013-01-18 01:44:05.000000000 +0100 -+++ openssh-6.2p1/key.h 2013-03-22 12:23:35.308954528 +0100 -@@ -97,6 +97,9 @@ int key_equal_public(const Key *, cons - int key_equal(const Key *, const Key *); - char *key_fingerprint(Key *, enum fp_type, enum fp_rep); - u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); -+enum fp_type key_fingerprint_selection(void); -+char *key_selected_fingerprint(Key *, enum fp_rep); -+char *key_fingerprint_prefix(void); - const char *key_type(const Key *); - const char *key_cert_type(const Key *); - int key_write(const Key *, FILE *); -diff -up openssh-6.2p1/ssh-add.c.fingerprint openssh-6.2p1/ssh-add.c ---- openssh-6.2p1/ssh-add.c.fingerprint 2012-12-07 03:07:03.000000000 +0100 -+++ openssh-6.2p1/ssh-add.c 2013-03-22 12:20:49.029684920 +0100 -@@ -326,10 +326,10 @@ list_identities(AuthenticationConnection - key = ssh_get_next_identity(ac, &comment, version)) { - had_identities = 1; - if (do_fp) { -- fp = key_fingerprint(key, SSH_FP_MD5, -- SSH_FP_HEX); -- printf("%d %s %s (%s)\n", -- key_size(key), fp, comment, key_type(key)); -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ printf("%d %s%s %s (%s)\n", -+ key_size(key), key_fingerprint_prefix(), -+ fp, comment, key_type(key)); - xfree(fp); - } else { - if (!key_write(key, stdout)) -diff -up openssh-6.2p1/ssh-agent.c.fingerprint openssh-6.2p1/ssh-agent.c ---- openssh-6.2p1/ssh-agent.c.fingerprint 2013-03-22 12:20:48.979685140 +0100 -+++ openssh-6.2p1/ssh-agent.c 2013-03-22 12:20:49.030684916 +0100 -@@ -199,9 +199,9 @@ confirm_key(Identity *id) - char *p; - int ret = -1; - -- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); -- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", -- id->comment, p)) -+ p = key_selected_fingerprint(id->key, SSH_FP_HEX); -+ if (ask_permission("Allow use of key %s?\nKey fingerprint %s%s.", -+ id->comment, key_fingerprint_prefix(), p)) - ret = 0; - xfree(p); - -diff -up openssh-6.2p1/sshconnect2.c.fingerprint openssh-6.2p1/sshconnect2.c ---- openssh-6.2p1/sshconnect2.c.fingerprint 2013-03-20 02:55:15.000000000 +0100 -+++ openssh-6.2p1/sshconnect2.c 2013-03-22 12:20:49.031684912 +0100 -@@ -592,8 +592,9 @@ input_userauth_pk_ok(int type, u_int32_t - key->type, pktype); - goto done; - } -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- debug2("input_userauth_pk_ok: fp %s", fp); -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ debug2("input_userauth_pk_ok: fp %s%s", -+ key_fingerprint_prefix(), fp); - xfree(fp); - - /* -@@ -1205,8 +1206,9 @@ sign_and_send_pubkey(Authctxt *authctxt, - int have_sig = 1; - char *fp; - -- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); -- debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); -+ fp = key_selected_fingerprint(id->key, SSH_FP_HEX); -+ debug3("sign_and_send_pubkey: %s %s%s", key_type(id->key), -+ key_fingerprint_prefix(), fp); - xfree(fp); - - if (key_to_blob(id->key, &blob, &bloblen) == 0) { -diff -up openssh-6.2p1/sshconnect.c.fingerprint openssh-6.2p1/sshconnect.c ---- openssh-6.2p1/sshconnect.c.fingerprint 2012-09-17 05:25:44.000000000 +0200 -+++ openssh-6.2p1/sshconnect.c 2013-03-22 12:20:49.032684907 +0100 -@@ -824,10 +824,10 @@ check_host_key(char *hostname, struct so - "key for IP address '%.128s' to the list " - "of known hosts.", type, ip); - } else if (options.visual_host_key) { -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(host_key, SSH_FP_MD5, -- SSH_FP_RANDOMART); -- logit("Host key fingerprint is %s\n%s\n", fp, ra); -+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); -+ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART); -+ logit("Host key fingerprint is %s%s\n%s\n", -+ key_fingerprint_prefix(), fp, ra); - xfree(ra); - xfree(fp); - } -@@ -865,9 +865,8 @@ check_host_key(char *hostname, struct so - else - snprintf(msg1, sizeof(msg1), "."); - /* The default */ -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(host_key, SSH_FP_MD5, -- SSH_FP_RANDOMART); -+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); -+ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART); - msg2[0] = '\0'; - if (options.verify_host_key_dns) { - if (matching_host_key_dns) -@@ -882,10 +881,11 @@ check_host_key(char *hostname, struct so - snprintf(msg, sizeof(msg), - "The authenticity of host '%.200s (%s)' can't be " - "established%s\n" -- "%s key fingerprint is %s.%s%s\n%s" -+ "%s key fingerprint is %s%s.%s%s\n%s" - "Are you sure you want to continue connecting " - "(yes/no)? ", -- host, ip, msg1, type, fp, -+ host, ip, msg1, type, -+ key_fingerprint_prefix(), fp, - options.visual_host_key ? "\n" : "", - options.visual_host_key ? ra : "", - msg2); -@@ -1130,8 +1130,9 @@ verify_host_key(char *host, struct socka - int flags = 0; - char *fp; - -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -- debug("Server host key: %s %s", key_type(host_key), fp); -+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); -+ debug("Server host key: %s %s%s", key_type(host_key), -+ key_fingerprint_prefix(), fp); - xfree(fp); - - /* XXX certs are not yet supported for DNS */ -@@ -1232,14 +1233,15 @@ show_other_keys(struct hostkeys *hostkey - continue; - if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) - continue; -- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); -+ fp = key_selected_fingerprint(found->key, SSH_FP_HEX); -+ ra = key_selected_fingerprint(found->key, SSH_FP_RANDOMART); - logit("WARNING: %s key found for host %s\n" - "in %s:%lu\n" -- "%s key fingerprint %s.", -+ "%s key fingerprint %s%s.", - key_type(found->key), - found->host, found->file, found->line, -- key_type(found->key), fp); -+ key_type(found->key), -+ key_fingerprint_prefix(), fp); - if (options.visual_host_key) - logit("%s", ra); - xfree(ra); -@@ -1254,7 +1256,7 @@ warn_changed_key(Key *host_key) - { - char *fp; - -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); - - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); -@@ -1262,8 +1264,8 @@ warn_changed_key(Key *host_key) - error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); - error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); - error("It is also possible that a host key has just been changed."); -- error("The fingerprint for the %s key sent by the remote host is\n%s.", -- key_type(host_key), fp); -+ error("The fingerprint for the %s key sent by the remote host is\n%s%s.", -+ key_type(host_key),key_fingerprint_prefix(), fp); - error("Please contact your system administrator."); - - xfree(fp); -diff -up openssh-6.2p1/ssh-keygen.c.fingerprint openssh-6.2p1/ssh-keygen.c ---- openssh-6.2p1/ssh-keygen.c.fingerprint 2013-02-12 01:03:36.000000000 +0100 -+++ openssh-6.2p1/ssh-keygen.c 2013-03-22 12:20:49.033684903 +0100 -@@ -767,13 +767,14 @@ do_fingerprint(struct passwd *pw) - { - FILE *f; - Key *public; -- char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; -+ char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra, *pfx; - int i, skip = 0, num = 0, invalid = 1; - enum fp_rep rep; - enum fp_type fptype; - struct stat st; - -- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; -+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection(); -+ pfx = print_bubblebabble ? "" : key_fingerprint_prefix(); - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - - if (!have_identity) -@@ -785,8 +786,8 @@ do_fingerprint(struct passwd *pw) - public = key_load_public(identity_file, &comment); - if (public != NULL) { - fp = key_fingerprint(public, fptype, rep); -- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); -- printf("%u %s %s (%s)\n", key_size(public), fp, comment, -+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); -+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, comment, - key_type(public)); - if (log_level >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); -@@ -851,8 +852,8 @@ do_fingerprint(struct passwd *pw) - } - comment = *cp ? cp : comment; - fp = key_fingerprint(public, fptype, rep); -- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); -- printf("%u %s %s (%s)\n", key_size(public), fp, -+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); -+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, - comment ? comment : "no comment", key_type(public)); - if (log_level >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); -@@ -970,13 +971,15 @@ printhost(FILE *f, const char *name, Key - if (print_fingerprint) { - enum fp_rep rep; - enum fp_type fptype; -- char *fp, *ra; -+ char *fp, *ra, *pfx; - -- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; -+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection(); -+ pfx = print_bubblebabble ? "" : key_fingerprint_prefix(); - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; -+ - fp = key_fingerprint(public, fptype, rep); -- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); -- printf("%u %s %s (%s)\n", key_size(public), fp, name, -+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); -+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, name, - key_type(public)); - if (log_level >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); -@@ -1854,16 +1857,17 @@ do_show_cert(struct passwd *pw) - fatal("%s is not a certificate", identity_file); - v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; - -- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- ca_fp = key_fingerprint(key->cert->signature_key, -- SSH_FP_MD5, SSH_FP_HEX); -+ key_fp = key_selected_fingerprint(key, SSH_FP_HEX); -+ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); - - printf("%s:\n", identity_file); - printf(" Type: %s %s certificate\n", key_ssh_name(key), - key_cert_type(key)); -- printf(" Public key: %s %s\n", key_type(key), key_fp); -- printf(" Signing CA: %s %s\n", -- key_type(key->cert->signature_key), ca_fp); -+ printf(" Public key: %s %s%s\n", key_type(key), -+ key_fingerprint_prefix(), key_fp); -+ printf(" Signing CA: %s %s%s\n", -+ key_type(key->cert->signature_key), -+ key_fingerprint_prefix(), ca_fp); - printf(" Key ID: \"%s\"\n", key->cert->key_id); - if (!v00) { - printf(" Serial: %llu\n", -@@ -2651,13 +2655,12 @@ passphrase_again: - fclose(f); - - if (!quiet) { -- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); -- char *ra = key_fingerprint(public, SSH_FP_MD5, -- SSH_FP_RANDOMART); -+ char *fp = key_selected_fingerprint(public, SSH_FP_HEX); -+ char *ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); - printf("Your public key has been saved in %s.\n", - identity_file); - printf("The key fingerprint is:\n"); -- printf("%s %s\n", fp, comment); -+ printf("%s%s %s\n", key_fingerprint_prefix(), fp, comment); - printf("The key's randomart image is:\n"); - printf("%s\n", ra); - xfree(ra); diff --git a/openssh-6.2p1-fips.patch b/openssh-6.2p1-fips.patch deleted file mode 100644 index fddf0f5..0000000 --- a/openssh-6.2p1-fips.patch +++ /dev/null @@ -1,546 +0,0 @@ -diff -up openssh-6.2p1/authfile.c.fips openssh-6.2p1/authfile.c ---- openssh-6.2p1/authfile.c.fips 2013-03-27 13:14:49.164683482 +0100 -+++ openssh-6.2p1/authfile.c 2013-03-27 13:14:49.177683431 +0100 -@@ -148,8 +148,14 @@ key_private_rsa1_to_blob(Key *key, Buffe - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_ENCRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_ENCRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&encrypted); -+ buffer_free(&buffer); -+ return 0; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); - cipher_cleanup(&ciphercontext); -@@ -472,8 +478,13 @@ key_parse_private_rsa1(Buffer *blob, con - cp = buffer_append_space(&decrypted, buffer_len(©)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_DECRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_DECRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&decrypted); -+ goto fail; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(©), buffer_len(©), 0, 0); - cipher_cleanup(&ciphercontext); -diff -up openssh-6.2p1/cipher.c.fips openssh-6.2p1/cipher.c ---- openssh-6.2p1/cipher.c.fips 2013-03-27 13:14:49.087683788 +0100 -+++ openssh-6.2p1/cipher.c 2013-03-27 13:14:49.177683431 +0100 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - - #include - #include -@@ -89,6 +90,27 @@ struct Cipher ciphers[] = { - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } - }; - -+struct Cipher fips_ciphers[] = { -+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, -+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, -+ -+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, -+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, -+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, -+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, -+ { "rijndael-cbc@lysator.liu.se", -+ SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, -+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, -+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_128_ctr }, -+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_128_ctr }, -+#ifdef OPENSSL_HAVE_EVPGCM -+ { "aes128-gcm@openssh.com", -+ SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, -+ { "aes256-gcm@openssh.com", -+ SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, -+#endif -+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, NULL } -+}; - /*--*/ - - u_int -@@ -143,7 +165,7 @@ Cipher * - cipher_by_name(const char *name) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcmp(c->name, name) == 0) - return c; - return NULL; -@@ -153,7 +175,7 @@ Cipher * - cipher_by_number(int id) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -@@ -197,7 +219,7 @@ cipher_number(const char *name) - Cipher *c; - if (name == NULL) - return -1; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c->number; - return -1; -@@ -356,14 +378,15 @@ cipher_cleanup(CipherContext *cc) - * passphrase and using the resulting 16 bytes as the key. - */ - --void -+int - cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase, int do_encrypt) - { - MD5_CTX md; - u_char digest[16]; - -- MD5_Init(&md); -+ if (MD5_Init(&md) <= 0) -+ return -1; - MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); - MD5_Final(digest, &md); - -@@ -371,6 +394,7 @@ cipher_set_key_string(CipherContext *cc, - - memset(digest, 0, sizeof(digest)); - memset(&md, 0, sizeof(md)); -+ return 0; - } - - /* -diff -up openssh-6.2p1/cipher-ctr.c.fips openssh-6.2p1/cipher-ctr.c ---- openssh-6.2p1/cipher-ctr.c.fips 2013-01-20 12:31:30.000000000 +0100 -+++ openssh-6.2p1/cipher-ctr.c 2013-03-27 13:14:49.177683431 +0100 -@@ -138,7 +138,8 @@ evp_aes_128_ctr(void) - 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; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } -diff -up openssh-6.2p1/cipher.h.fips openssh-6.2p1/cipher.h ---- openssh-6.2p1/cipher.h.fips 2013-03-27 13:14:49.088683784 +0100 -+++ openssh-6.2p1/cipher.h 2013-03-27 13:14:49.177683431 +0100 -@@ -91,7 +91,7 @@ void cipher_init(CipherContext *, Ciphe - void cipher_crypt(CipherContext *, u_char *, const u_char *, - u_int, u_int, u_int); - void cipher_cleanup(CipherContext *); --void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); -+int cipher_set_key_string(CipherContext *, Cipher *, const char *, int); - u_int cipher_blocksize(const Cipher *); - u_int cipher_keylen(const Cipher *); - u_int cipher_authlen(const Cipher *); -diff -up openssh-6.2p1/key.c.fips openssh-6.2p1/key.c ---- openssh-6.2p1/key.c.fips 2013-03-27 13:14:49.100683736 +0100 -+++ openssh-6.2p1/key.c 2013-03-27 13:14:49.178683427 +0100 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - #include - - #include -@@ -607,9 +608,13 @@ key_fingerprint_selection(void) - char *env; - - if (!rv_defined) { -- env = getenv("SSH_FINGERPRINT_TYPE"); -- rv = (env && !strcmp (env, "sha")) ? -- SSH_FP_SHA1 : SSH_FP_MD5; -+ if (FIPS_mode()) -+ rv = SSH_FP_SHA1; -+ else { -+ env = getenv("SSH_FINGERPRINT_TYPE"); -+ rv = (env && !strcmp (env, "sha")) ? -+ SSH_FP_SHA1 : SSH_FP_MD5; -+ } - rv_defined = 1; - } - return rv; -diff -up openssh-6.2p1/mac.c.fips openssh-6.2p1/mac.c ---- openssh-6.2p1/mac.c.fips 2013-03-27 13:14:49.093683764 +0100 -+++ openssh-6.2p1/mac.c 2013-03-27 13:16:33.524266158 +0100 -@@ -28,6 +28,7 @@ - #include - - #include -+#include - - #include - #include -@@ -50,7 +51,7 @@ - #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ - #define SSH_UMAC128 3 - --struct { -+struct Macs { - char *name; - int type; - const EVP_MD * (*mdfunc)(void); -@@ -58,7 +59,9 @@ struct { - int key_len; /* just for UMAC */ - int len; /* just for UMAC */ - int etm; /* Encrypt-then-MAC */ --} macs[] = { -+}; -+ -+struct Macs all_macs[] = { - /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, -@@ -89,9 +92,19 @@ struct { - { NULL, 0, NULL, 0, 0, 0, 0 } - }; - -+struct Macs fips_macs[] = { -+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, -+#ifdef HAVE_EVP_SHA256 -+ { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 }, -+ { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 }, -+#endif -+ { NULL, 0, NULL, 0, -1, -1 } -+}; -+ - static void - mac_setup_by_id(Mac *mac, int which) - { -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - int evp_len; - mac->type = macs[which].type; - if (mac->type == SSH_EVP) { -@@ -113,6 +126,7 @@ int - mac_setup(Mac *mac, char *name) - { - int i; -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - - for (i = 0; macs[i].name; i++) { - if (strcmp(name, macs[i].name) == 0) { -diff -up openssh-6.2p1/Makefile.in.fips openssh-6.2p1/Makefile.in ---- openssh-6.2p1/Makefile.in.fips 2013-03-27 13:14:49.155683518 +0100 -+++ openssh-6.2p1/Makefile.in 2013-03-27 13:14:49.178683427 +0100 -@@ -145,25 +145,25 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ - - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o -- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o -- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - 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) -@@ -175,7 +175,7 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh - $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) - - 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) -+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) - - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -diff -up openssh-6.2p1/myproposal.h.fips openssh-6.2p1/myproposal.h ---- openssh-6.2p1/myproposal.h.fips 2013-01-09 06:12:19.000000000 +0100 -+++ openssh-6.2p1/myproposal.h 2013-03-27 13:14:49.178683427 +0100 -@@ -106,6 +106,19 @@ - #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" - #define KEX_DEFAULT_LANG "" - -+#define KEX_FIPS_ENCRYPT \ -+ "aes128-ctr,aes192-ctr,aes256-ctr," \ -+ "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" -+#ifdef HAVE_EVP_SHA256 -+#define KEX_FIPS_MAC \ -+ "hmac-sha1," \ -+ "hmac-sha2-256," \ -+ "hmac-sha2-512" -+#else -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" -+#endif - - static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, -diff -up openssh-6.2p1/openbsd-compat/bsd-arc4random.c.fips openssh-6.2p1/openbsd-compat/bsd-arc4random.c ---- openssh-6.2p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100 -+++ openssh-6.2p1/openbsd-compat/bsd-arc4random.c 2013-03-27 13:14:49.179683423 +0100 -@@ -37,25 +37,18 @@ - #define REKEY_BYTES (1 << 24) - - static int rc4_ready = 0; --static RC4_KEY rc4; - - unsigned int - arc4random(void) - { - unsigned int r = 0; -- static int first_time = 1; -+ void *rp = &r; - -- if (rc4_ready <= 0) { -- if (first_time) -- seed_rng(); -- first_time = 0; -+ if (!rc4_ready) { - arc4random_stir(); - } -+ RAND_bytes(rp, sizeof(r)); - -- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); -- -- rc4_ready -= sizeof(r); -- - return(r); - } - -@@ -63,24 +56,11 @@ void - arc4random_stir(void) - { - unsigned char rand_buf[SEED_SIZE]; -- int i; - -- memset(&rc4, 0, sizeof(rc4)); - if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) - fatal("Couldn't obtain random bytes (error %ld)", - ERR_get_error()); -- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); -- -- /* -- * Discard early keystream, as per recommendations in: -- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps -- */ -- for(i = 0; i <= 256; i += sizeof(rand_buf)) -- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); -- -- memset(rand_buf, 0, sizeof(rand_buf)); -- -- rc4_ready = REKEY_BYTES; -+ rc4_ready = 1; - } - #endif /* !HAVE_ARC4RANDOM */ - -diff -up openssh-6.2p2/ssh.c.fips openssh-6.2p2/ssh.c ---- openssh-6.2p2/ssh.c.fips 2013-04-05 02:22:36.000000000 +0200 -+++ openssh-6.2p2/ssh.c 2013-10-08 17:21:26.894761211 +0200 -@@ -73,6 +73,8 @@ - - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -253,6 +255,13 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) -+ if (FIPS_mode()) -+ fatal("FIPS integrity verification test failed."); -+ else -+ logit("FIPS integrity verification test failed."); - - #ifndef HAVE_SETPROCTITLE - /* Prepare for later setproctitle emulation */ -@@ -329,6 +338,9 @@ main(int ac, char **av) - "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { - switch (opt) { - case '1': -+ if (FIPS_mode()) { -+ fatal("Protocol 1 not allowed in the FIPS mode."); -+ } - options.protocol = SSH_PROTO_1; - break; - case '2': -@@ -628,7 +640,6 @@ main(int ac, char **av) - if (!host) - usage(); - -- OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - - /* Initialize the command to execute on remote host. */ -@@ -719,6 +730,10 @@ main(int ac, char **av) - - seed_rng(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - -@@ -787,6 +802,12 @@ main(int ac, char **av) - - timeout_ms = options.connection_timeout * 1000; - -+ if (FIPS_mode()) { -+ options.protocol &= SSH_PROTO_2; -+ if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); -+ } -+ - /* Open a connection to the remote host. */ - if (ssh_connect(host, &hostaddr, options.port, - options.address_family, options.connection_attempts, &timeout_ms, -diff -up openssh-6.2p1/sshconnect2.c.fips openssh-6.2p1/sshconnect2.c ---- openssh-6.2p1/sshconnect2.c.fips 2013-03-27 13:14:49.066683871 +0100 -+++ openssh-6.2p1/sshconnect2.c 2013-03-27 13:14:49.179683423 +0100 -@@ -44,6 +44,8 @@ - #include - #endif - -+#include -+ - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -170,6 +172,10 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; -+ - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -185,7 +191,11 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } -+ - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; -diff -up openssh-6.2p2/sshd.c.fips openssh-6.2p2/sshd.c ---- openssh-6.2p2/sshd.c.fips 2013-10-08 17:14:05.455864248 +0200 -+++ openssh-6.2p2/sshd.c 2013-10-08 17:22:15.897527827 +0200 -@@ -76,6 +76,8 @@ - #include - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - - #ifdef HAVE_SECUREWARE -@@ -1423,6 +1425,14 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) -+ if (FIPS_mode()) -+ fatal("FIPS integrity verification test failed."); -+ else -+ logit("FIPS integrity verification test failed."); -+ - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; -@@ -1571,8 +1581,6 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - -- OpenSSL_add_all_algorithms(); -- - /* - * Force logging to stderr until we have loaded the private host - * key (unless started from inetd) -@@ -1715,6 +1723,10 @@ main(int ac, char **av) - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); - } -+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { -+ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); -+ options.protocol &= ~SSH_PROTO_1; -+ } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; -@@ -1878,6 +1890,10 @@ main(int ac, char **av) - /* Initialize the random number generator. */ - arc4random_stir(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - (void) chdir("/"); -@@ -2420,6 +2436,9 @@ do_ssh2_kex(void) - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -2429,6 +2448,9 @@ do_ssh2_kex(void) - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } - if (options.compression == COMP_NONE) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = diff --git a/openssh-6.2p1-force_krb.patch b/openssh-6.2p1-force_krb.patch deleted file mode 100644 index 5423171..0000000 --- a/openssh-6.2p1-force_krb.patch +++ /dev/null @@ -1,289 +0,0 @@ -diff -up openssh-6.2p1/gss-serv-krb5.c.force_krb openssh-6.2p1/gss-serv-krb5.c ---- openssh-6.2p1/gss-serv-krb5.c.force_krb 2013-03-25 20:04:53.807817333 +0100 -+++ openssh-6.2p1/gss-serv-krb5.c 2013-03-25 20:04:53.818817403 +0100 -@@ -32,7 +32,9 @@ - #include - - #include -+#include - #include -+#include - - #include "xmalloc.h" - #include "key.h" -@@ -40,12 +42,11 @@ - #include "auth.h" - #include "log.h" - #include "servconf.h" -+#include "misc.h" - - #include "buffer.h" - #include "ssh-gss.h" - --extern ServerOptions options; -- - #ifdef HEIMDAL - # include - #else -@@ -56,6 +57,16 @@ extern ServerOptions options; - # endif - #endif - -+extern Authctxt *the_authctxt; -+extern ServerOptions options; -+ -+/* all commands are allowed by default */ -+char **k5users_allowed_cmds = NULL; -+ -+static int ssh_gssapi_k5login_exists(); -+static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *, -+ int); -+ - static krb5_context krb_context = NULL; - - /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ -@@ -83,10 +94,11 @@ ssh_gssapi_krb5_init(void) - */ - - static int --ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) -+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *luser) - { - krb5_principal princ; - int retval; -+ int k5login_exists; - - if (ssh_gssapi_krb5_init() == 0) - return 0; -@@ -97,10 +109,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client - krb5_get_err_text(krb_context, retval)); - return 0; - } -- if (krb5_kuserok(krb_context, princ, name)) { -+ /* krb5_kuserok() returns 1 if .k5login DNE and this is self-login. -+ * We have to make sure to check .k5users in that case. */ -+ k5login_exists = ssh_gssapi_k5login_exists(); -+ /* NOTE: .k5login and .k5users must opened as root, not the user, -+ * because if they are on a krb5-protected filesystem, user credentials -+ * to access these files aren't available yet. */ -+ if (krb5_kuserok(krb_context, princ, luser) && k5login_exists) { - retval = 1; - logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", -- name, (char *)client->displayname.value); -+ luser, (char *)client->displayname.value); -+ } else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value, -+ luser, k5login_exists)) { -+ retval = 1; -+ logit("Authorized to %s, krb5 principal %s " -+ "(ssh_gssapi_krb5_cmdok)", -+ luser, (char *)client->displayname.value); - } else - retval = 0; - -@@ -108,6 +132,135 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client - return retval; - } - -+/* Test for existence of .k5login. -+ * We need this as part of our .k5users check, because krb5_kuserok() -+ * returns success if .k5login DNE and user is logging in as himself. -+ * With .k5login absent and .k5users present, we don't want absence -+ * of .k5login to authorize self-login. (absence of both is required) -+ * Returns 1 if .k5login is available, 0 otherwise. -+ */ -+static int -+ssh_gssapi_k5login_exists() -+{ -+ char file[MAXPATHLEN]; -+ struct passwd *pw = the_authctxt->pw; -+ -+ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); -+ return access(file, F_OK) == 0; -+} -+ -+/* check .k5users for login or command authorization -+ * Returns 1 if principal is authorized, 0 otherwise. -+ * If principal is authorized, (global) k5users_allowed_cmds may be populated. -+ */ -+static int -+ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, -+ const char *luser, int k5login_exists) -+{ -+ FILE *fp; -+ char file[MAXPATHLEN]; -+ char line[BUFSIZ]; -+ char kuser[65]; /* match krb5_kuserok() */ -+ struct stat st; -+ struct passwd *pw = the_authctxt->pw; -+ int found_principal = 0; -+ int ncommands = 0, allcommands = 0; -+ u_long linenum; -+ -+ snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); -+ /* If both .k5login and .k5users DNE, self-login is ok. */ -+ if (!k5login_exists && (access(file, F_OK) == -1)) { -+ return (krb5_aname_to_localname(krb_context, principal, -+ sizeof(kuser), kuser) == 0) && -+ (strcmp(kuser, luser) == 0); -+ } -+ if ((fp = fopen(file, "r")) == NULL) { -+ int saved_errno = errno; -+ /* 2nd access check to ease debugging if file perms are wrong. -+ * But we don't want to report this if .k5users simply DNE. */ -+ if (access(file, F_OK) == 0) { -+ logit("User %s fopen %s failed: %s", -+ pw->pw_name, file, strerror(saved_errno)); -+ } -+ return 0; -+ } -+ /* .k5users must be owned either by the user or by root */ -+ if (fstat(fileno(fp), &st) == -1) { -+ /* can happen, but very wierd error so report it */ -+ logit("User %s fstat %s failed: %s", -+ pw->pw_name, file, strerror(errno)); -+ fclose(fp); -+ return 0; -+ } -+ if (!(st.st_uid == pw->pw_uid || st.st_uid == 0)) { -+ logit("User %s %s is not owned by root or user", -+ pw->pw_name, file); -+ fclose(fp); -+ return 0; -+ } -+ /* .k5users must be a regular file. krb5_kuserok() doesn't do this -+ * check, but we don't want to be deficient if they add a check. */ -+ if (!S_ISREG(st.st_mode)) { -+ logit("User %s %s is not a regular file", pw->pw_name, file); -+ fclose(fp); -+ return 0; -+ } -+ /* file exists; initialize k5users_allowed_cmds (to none!) */ -+ k5users_allowed_cmds = xcalloc(++ncommands, -+ sizeof(*k5users_allowed_cmds)); -+ -+ /* Check each line. ksu allows unlimited length lines. We don't. */ -+ while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line), -+ &linenum) != -1) { -+ char *token; -+ -+ /* we parse just like ksu, even though we could do better */ -+ if ((token = strtok(line, " \t\n")) == NULL) -+ continue; -+ if (strcmp(name, token) == 0) { -+ /* we matched on client principal */ -+ found_principal = 1; -+ if ((token = strtok(NULL, " \t\n")) == NULL) { -+ /* only shell is allowed */ -+ k5users_allowed_cmds[ncommands-1] = -+ xstrdup(pw->pw_shell); -+ k5users_allowed_cmds = -+ xrealloc(k5users_allowed_cmds, ++ncommands, -+ sizeof(*k5users_allowed_cmds)); -+ break; -+ } -+ /* process the allowed commands */ -+ while (token) { -+ if (strcmp(token, "*") == 0) { -+ allcommands = 1; -+ break; -+ } -+ k5users_allowed_cmds[ncommands-1] = -+ xstrdup(token); -+ k5users_allowed_cmds = -+ xrealloc(k5users_allowed_cmds, ++ncommands, -+ sizeof(*k5users_allowed_cmds)); -+ token = strtok(NULL, " \t\n"); -+ } -+ } -+ } -+ if (k5users_allowed_cmds) { -+ /* terminate vector */ -+ k5users_allowed_cmds[ncommands-1] = NULL; -+ /* if all commands are allowed, free vector */ -+ if (allcommands) { -+ int i; -+ for (i = 0; i < ncommands; i++) { -+ free(k5users_allowed_cmds[i]); -+ } -+ free(k5users_allowed_cmds); -+ k5users_allowed_cmds = NULL; -+ } -+ } -+ fclose(fp); -+ return found_principal; -+} -+ - - /* This writes out any forwarded credentials from the structure populated - * during userauth. Called after we have setuid to the user */ -diff -up openssh-6.2p1/session.c.force_krb openssh-6.2p1/session.c ---- openssh-6.2p1/session.c.force_krb 2013-03-25 20:04:53.724816810 +0100 -+++ openssh-6.2p1/session.c 2013-03-25 20:04:53.818817403 +0100 -@@ -823,6 +823,29 @@ do_exec(Session *s, const char *command) - debug("Forced command (key option) '%.900s'", command); - } - -+#ifdef GSSAPI -+#ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */ -+ else if (k5users_allowed_cmds) { -+ const char *match = command; -+ int allowed = 0, i = 0; -+ -+ if (!match) -+ match = s->pw->pw_shell; -+ while (k5users_allowed_cmds[i]) { -+ if (strcmp(match, k5users_allowed_cmds[i++]) == 0) { -+ debug("Allowed command '%.900s'", match); -+ allowed = 1; -+ break; -+ } -+ } -+ if (!allowed) { -+ debug("command '%.900s' not allowed", match); -+ return 1; -+ } -+ } -+#endif -+#endif -+ - #ifdef SSH_AUDIT_EVENTS - if (s->command != NULL || s->command_handle != -1) - fatal("do_exec: command already set"); -diff -up openssh-6.2p1/sshd.8.force_krb openssh-6.2p1/sshd.8 ---- openssh-6.2p1/sshd.8.force_krb 2013-03-25 20:04:53.787817207 +0100 -+++ openssh-6.2p1/sshd.8 2013-03-25 20:04:53.819817409 +0100 -@@ -323,6 +323,7 @@ Finally, the server and the client enter - The client tries to authenticate itself using - host-based authentication, - public key authentication, -+GSSAPI authentication, - challenge-response authentication, - or password authentication. - .Pp -@@ -796,6 +797,12 @@ This file is used in exactly the same wa - but allows host-based authentication without permitting login with - rlogin/rsh. - .Pp -+.It Pa ~/.k5login -+.It Pa ~/.k5users -+These files enforce GSSAPI/Kerberos authentication access control. -+Further details are described in -+.Xr ksu 1 . -+.Pp - .It Pa ~/.ssh/ - This directory is the default location for all user-specific configuration - and authentication information. -diff -up openssh-6.2p1/ssh-gss.h.force_krb openssh-6.2p1/ssh-gss.h ---- openssh-6.2p1/ssh-gss.h.force_krb 2013-03-25 20:04:53.819817409 +0100 -+++ openssh-6.2p1/ssh-gss.h 2013-03-25 20:05:26.463023197 +0100 -@@ -49,6 +49,10 @@ - # endif /* !HAVE_DECL_GSS_C_NT_... */ - - # endif /* !HEIMDAL */ -+ -+/* .k5users support */ -+extern char **k5users_allowed_cmds; -+ - #endif /* KRB5 */ - - /* draft-ietf-secsh-gsskeyex-06 */ diff --git a/openssh-6.2p1-gsskex.patch b/openssh-6.2p1-gsskex.patch deleted file mode 100644 index f1fe8d1..0000000 --- a/openssh-6.2p1-gsskex.patch +++ /dev/null @@ -1,3067 +0,0 @@ -diff -up openssh-6.2p1/auth2.c.gsskex openssh-6.2p1/auth2.c ---- openssh-6.2p1/auth2.c.gsskex 2013-03-27 13:19:11.062624591 +0100 -+++ openssh-6.2p1/auth2.c 2013-03-27 13:19:11.140624271 +0100 -@@ -69,6 +69,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif - #ifdef JPAKE -@@ -79,6 +80,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - #endif - #ifdef JPAKE -diff -up openssh-6.2p1/auth2-gss.c.gsskex openssh-6.2p1/auth2-gss.c ---- openssh-6.2p1/auth2-gss.c.gsskex 2013-03-27 13:19:11.062624591 +0100 -+++ openssh-6.2p1/auth2-gss.c 2013-03-27 13:19:11.141624267 +0100 -@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u - static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); - static void input_gssapi_errtok(int, u_int32_t, void *); - -+/* -+ * The 'gssapi_keyex' userauth mechanism. -+ */ -+static int -+userauth_gsskeyex(Authctxt *authctxt) -+{ -+ int authenticated = 0; -+ Buffer b; -+ gss_buffer_desc mic, gssbuf; -+ u_int len; -+ -+ mic.value = packet_get_string(&len); -+ mic.length = len; -+ -+ packet_check_eom(); -+ -+ ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, -+ "gssapi-keyex"); -+ -+ gssbuf.value = buffer_ptr(&b); -+ gssbuf.length = buffer_len(&b); -+ -+ /* gss_kex_context is NULL with privsep, so we can't check it here */ -+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, -+ &gssbuf, &mic)))) -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); -+ -+ buffer_free(&b); -+ xfree(mic.value); -+ -+ return (authenticated); -+} -+ - /* - * We only support those mechanisms that we know about (ie ones that we know - * how to check local user kuserok and the like) -@@ -244,7 +278,8 @@ input_gssapi_exchange_complete(int type, - - packet_check_eom(); - -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); - - authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -@@ -286,7 +321,8 @@ input_gssapi_mic(int type, u_int32_t ple - gssbuf.length = buffer_len(&b); - - if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = -+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); - else - logit("GSSAPI MIC check failed"); - -@@ -303,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); - } - -+Authmethod method_gsskeyex = { -+ "gssapi-keyex", -+ userauth_gsskeyex, -+ &options.gss_authentication -+}; -+ - Authmethod method_gssapi = { - "gssapi-with-mic", - userauth_gssapi, -diff -up openssh-6.2p1/auth-krb5.c.gsskex openssh-6.2p1/auth-krb5.c ---- openssh-6.2p1/auth-krb5.c.gsskex 2012-04-26 01:52:15.000000000 +0200 -+++ openssh-6.2p1/auth-krb5.c 2013-03-27 13:19:11.140624271 +0100 -@@ -50,6 +50,7 @@ - #include - #include - #include -+#include - #include - - extern ServerOptions options; -@@ -77,6 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c - #endif - krb5_error_code problem; - krb5_ccache ccache = NULL; -+ const char *ccache_type; - int len; - char *client, *platform_client; - -@@ -166,12 +168,30 @@ auth_krb5_password(Authctxt *authctxt, c - goto out; - #endif - -+ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - -- len = strlen(authctxt->krb5_ticket_file) + 6; -+ if (authctxt->krb5_ticket_file[0] == ':') -+ authctxt->krb5_ticket_file++; -+ -+ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type); - authctxt->krb5_ccname = xmalloc(len); -- snprintf(authctxt->krb5_ccname, len, "FILE:%s", -+ -+#ifdef USE_CCAPI -+ snprintf(authctxt->krb5_ccname, len, "API:%s", - authctxt->krb5_ticket_file); -+#else -+ snprintf(authctxt->krb5_ccname, len, "%s:%s", -+ ccache_type, authctxt->krb5_ticket_file); -+#endif -+ -+ if (strcmp(ccache_type, "DIR") == 0) { -+ char *p; -+ p = strrchr(authctxt->krb5_ccname, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ - - #ifdef USE_PAM - if (options.use_pam) -@@ -208,10 +228,30 @@ auth_krb5_password(Authctxt *authctxt, c - void - krb5_cleanup_proc(Authctxt *authctxt) - { -+ struct stat krb5_ccname_stat; -+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end; -+ - debug("krb5_cleanup_proc called"); - if (authctxt->krb5_fwd_ccache) { - krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - authctxt->krb5_fwd_ccache = NULL; -+ -+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10); -+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1; -+ strcat(krb5_ccname_dir_start, "/primary"); -+ -+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) { -+ if (unlink(krb5_ccname_dir_start) == 0) { -+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/'); -+ *krb5_ccname_dir_end = '\0'; -+ if (rmdir(krb5_ccname_dir_start) == -1) -+ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno)); -+ } -+ else -+ debug("cache primary file '%s', remove failed: %s", -+ krb5_ccname_dir_start, strerror(errno) -+ ); -+ } - } - if (authctxt->krb5_user) { - krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); -@@ -226,31 +266,45 @@ krb5_cleanup_proc(Authctxt *authctxt) - #ifndef HEIMDAL - krb5_error_code - ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { -- int tmpfd, ret, oerrno; -- char ccname[40]; -+ int ret, oerrno; -+ char ccname[128]; -+#ifdef USE_CCAPI -+ char cctemplate[] = "API:krb5cc_%d"; -+#else - mode_t old_umask; -+ char cctemplate[] = "DIR:/run/user/%d/krb5cc_XXXXXXXXXX"; -+ char *tmpdir; -+#endif - -- ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ ret = snprintf(ccname, sizeof(ccname), cctemplate, geteuid()); - if (ret < 0 || (size_t)ret >= sizeof(ccname)) - return ENOMEM; - -- old_umask = umask(0177); -- tmpfd = mkstemp(ccname + strlen("FILE:")); -+#ifndef USE_CCAPI -+ old_umask = umask(0077); -+ tmpdir = mkdtemp(ccname + strlen("DIR:")); - oerrno = errno; -+ if (tmpdir == NULL && errno == ENOENT) { -+ /* /run/user/uid doesn't exist -> fallback to /tmp */ -+ ret = snprintf(ccname, sizeof(ccname), "DIR:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ if (ret < 0 || (size_t)ret >= sizeof(ccname)) -+ return ENOMEM; -+ tmpdir = mkdtemp(ccname + strlen("DIR:")); -+ oerrno = errno; -+ } -+ - umask(old_umask); -- if (tmpfd == -1) { -- logit("mkstemp(): %.100s", strerror(oerrno)); -+ if (tmpdir == NULL) { -+ logit("mkdtemp(): %s - %.100s", ccname, strerror(oerrno)); - return oerrno; - } - -- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { -+ if (chmod(tmpdir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { - oerrno = errno; -- logit("fchmod(): %.100s", strerror(oerrno)); -- close(tmpfd); -+ logit("chmod(): %s - %.100s", ccname, strerror(oerrno)); - return oerrno; - } -- close(tmpfd); -+#endif - - return (krb5_cc_resolve(ctx, ccname, ccache)); - } -diff -up openssh-6.2p1/ChangeLog.gssapi.gsskex openssh-6.2p1/ChangeLog.gssapi ---- openssh-6.2p1/ChangeLog.gssapi.gsskex 2013-03-27 13:19:11.143624259 +0100 -+++ openssh-6.2p1/ChangeLog.gssapi 2013-03-27 13:19:11.143624259 +0100 -@@ -0,0 +1,113 @@ -+20110101 -+ - Finally update for OpenSSH 5.6p1 -+ - Add GSSAPIServerIdentity option from Jim Basney -+ -+20100308 -+ - [ Makefile.in, key.c, key.h ] -+ Updates for OpenSSH 5.4p1 -+ - [ servconf.c ] -+ Include GSSAPI options in the sshd -T configuration dump, and flag -+ some older configuration options as being unsupported. Thanks to Colin -+ Watson. -+ - -+ -+20100124 -+ - [ sshconnect2.c ] -+ Adapt to deal with additional element in Authmethod structure. Thanks to -+ Colin Watson -+ -+20090615 -+ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c -+ sshd.c ] -+ Fix issues identified by Greg Hudson following a code review -+ Check return value of gss_indicate_mechs -+ Protect GSSAPI calls in monitor, so they can only be used if enabled -+ Check return values of bignum functions in key exchange -+ Use BN_clear_free to clear other side's DH value -+ Make ssh_gssapi_id_kex more robust -+ Only configure kex table pointers if GSSAPI is enabled -+ Don't leak mechanism list, or gss mechanism list -+ Cast data.length before printing -+ If serverkey isn't provided, use an empty string, rather than NULL -+ -+20090201 -+ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h -+ ssh_config.5 sshconnet2.c ] -+ Add support for the GSSAPIClientIdentity option, which allows the user -+ to specify which GSSAPI identity to use to contact a given server -+ -+20080404 -+ - [ gss-serv.c ] -+ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow -+ been omitted from a previous version of this patch. Reported by Borislav -+ Stoichkov -+ -+20070317 -+ - [ gss-serv-krb5.c ] -+ Remove C99ism, where new_ccname was being declared in the middle of a -+ function -+ -+20061220 -+ - [ servconf.c ] -+ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and -+ documented, behaviour. Reported by Dan Watson. -+ -+20060910 -+ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c -+ ssh-gss.h ] -+ add support for gss-group14-sha1 key exchange mechanisms -+ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] -+ Add GSSAPIStrictAcceptorCheck option to allow the disabling of -+ acceptor principal checking on multi-homed machines. -+ -+ - [ sshd_config ssh_config ] -+ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample -+ configuration files -+ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] -+ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() -+ Limit length of error messages displayed by client -+ -+20060909 -+ - [ gss-genr.c gss-serv.c ] -+ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server -+ only, where they belong -+ -+ -+20060829 -+ - [ gss-serv-krb5.c ] -+ Fix CCAPI credentials cache name when creating KRB5CCNAME environment -+ variable -+ -+20060828 -+ - [ gss-genr.c ] -+ Avoid Heimdal context freeing problem -+ -+ -+20060818 -+ - [ gss-genr.c ssh-gss.h sshconnect2.c ] -+ Make sure that SPENGO is disabled -+ -+ -+20060421 -+ - [ gssgenr.c, sshconnect2.c ] -+ a few type changes (signed versus unsigned, int versus size_t) to -+ fix compiler errors/warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ kexgssc.c, sshconnect2.c ] -+ fix uninitialized variable warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ gssgenr.c ] -+ pass oid to gss_display_status (helpful when using GSSAPI mechglue) -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ gss-serv-krb5.c ] -+ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c -+ add client-side GssapiKeyExchange option -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ sshconnect2.c ] -+ add support for GssapiTrustDns option for gssapi-with-mic -+ (from jbasney AT ncsa.uiuc.edu) -+ -diff -up openssh-6.2p1/clientloop.c.gsskex openssh-6.2p1/clientloop.c ---- openssh-6.2p1/clientloop.c.gsskex 2013-03-27 13:19:11.001624842 +0100 -+++ openssh-6.2p1/clientloop.c 2013-03-27 13:19:11.141624267 +0100 -@@ -111,6 +111,10 @@ - #include "msg.h" - #include "roaming.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - /* import options */ - extern Options options; - -@@ -1599,6 +1603,15 @@ client_loop(int have_pty, int escape_cha - /* Do channel operations unless rekeying in progress. */ - if (!rekeying) { - channel_after_select(readset, writeset); -+ -+#ifdef GSSAPI -+ if (options.gss_renewal_rekey && -+ ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { -+ debug("credentials updated - forcing rekey"); -+ need_rekeying = 1; -+ } -+#endif -+ - if (need_rekeying || packet_need_rekeying()) { - debug("need rekeying"); - xxx_kex->done = 0; -diff -up openssh-6.2p1/configure.ac.gsskex openssh-6.2p1/configure.ac ---- openssh-6.2p1/configure.ac.gsskex 2013-03-27 13:19:11.128624320 +0100 -+++ openssh-6.2p1/configure.ac 2013-03-27 13:19:11.142624263 +0100 -@@ -533,6 +533,30 @@ main() { if (NSVersionOfRunTimeLibrary(" - [Use tunnel device compatibility to OpenBSD]) - AC_DEFINE([SSH_TUN_PREPEND_AF], [1], - [Prepend the address family to IP tunnel traffic]) -+ AC_MSG_CHECKING(if we have the Security Authorization Session API) -+ AC_TRY_COMPILE([#include ], -+ [SessionCreate(0, 0);], -+ [ac_cv_use_security_session_api="yes" -+ AC_DEFINE(USE_SECURITY_SESSION_API, 1, -+ [platform has the Security Authorization Session API]) -+ LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes)], -+ [ac_cv_use_security_session_api="no" -+ AC_MSG_RESULT(no)]) -+ AC_MSG_CHECKING(if we have an in-memory credentials cache) -+ AC_TRY_COMPILE( -+ [#include ], -+ [cc_context_t c; -+ (void) cc_initialize (&c, 0, NULL, NULL);], -+ [AC_DEFINE(USE_CCAPI, 1, -+ [platform uses an in-memory credentials cache]) -+ LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes) -+ if test "x$ac_cv_use_security_session_api" = "xno"; then -+ AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) -+ fi], -+ [AC_MSG_RESULT(no)] -+ ) - m4_pattern_allow([AU_IPv]) - AC_CHECK_DECL([AU_IPv4], [], - AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -diff -up openssh-6.2p1/gss-genr.c.gsskex openssh-6.2p1/gss-genr.c ---- openssh-6.2p1/gss-genr.c.gsskex 2009-06-22 08:11:07.000000000 +0200 -+++ openssh-6.2p1/gss-genr.c 2013-03-27 13:19:11.142624263 +0100 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */ - - /* -- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -39,12 +39,167 @@ - #include "buffer.h" - #include "log.h" - #include "ssh2.h" -+#include "cipher.h" -+#include "key.h" -+#include "kex.h" -+#include - - #include "ssh-gss.h" - - extern u_char *session_id2; - extern u_int session_id2_len; - -+typedef struct { -+ char *encoded; -+ gss_OID oid; -+} ssh_gss_kex_mapping; -+ -+/* -+ * XXX - It would be nice to find a more elegant way of handling the -+ * XXX passing of the key exchange context to the userauth routines -+ */ -+ -+Gssctxt *gss_kex_context = NULL; -+ -+static ssh_gss_kex_mapping *gss_enc2oid = NULL; -+ -+int -+ssh_gssapi_oid_table_ok() { -+ return (gss_enc2oid != NULL); -+} -+ -+/* -+ * Return a list of the gss-group1-sha1 mechanisms supported by this program -+ * -+ * We test mechanisms to ensure that we can use them, to avoid starting -+ * a key exchange with a bad mechanism -+ */ -+ -+char * -+ssh_gssapi_client_mechanisms(const char *host, const char *client) { -+ gss_OID_set gss_supported; -+ OM_uint32 min_status; -+ -+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) -+ return NULL; -+ -+ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, -+ host, client)); -+} -+ -+char * -+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, -+ const char *host, const char *client) { -+ Buffer buf; -+ size_t i; -+ int oidpos, enclen; -+ char *mechs, *encoded; -+ u_char digest[EVP_MAX_MD_SIZE]; -+ char deroid[2]; -+ const EVP_MD *evp_md = EVP_md5(); -+ EVP_MD_CTX md; -+ -+ if (gss_enc2oid != NULL) { -+ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) -+ xfree(gss_enc2oid[i].encoded); -+ xfree(gss_enc2oid); -+ } -+ -+ gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * -+ (gss_supported->count + 1)); -+ -+ buffer_init(&buf); -+ -+ oidpos = 0; -+ for (i = 0; i < gss_supported->count; i++) { -+ if (gss_supported->elements[i].length < 128 && -+ (*check)(NULL, &(gss_supported->elements[i]), host, client)) { -+ -+ deroid[0] = SSH_GSS_OIDTYPE; -+ deroid[1] = gss_supported->elements[i].length; -+ -+ EVP_DigestInit(&md, evp_md); -+ EVP_DigestUpdate(&md, deroid, 2); -+ EVP_DigestUpdate(&md, -+ gss_supported->elements[i].elements, -+ gss_supported->elements[i].length); -+ EVP_DigestFinal(&md, digest, NULL); -+ -+ encoded = xmalloc(EVP_MD_size(evp_md) * 2); -+ enclen = __b64_ntop(digest, EVP_MD_size(evp_md), -+ encoded, EVP_MD_size(evp_md) * 2); -+ -+ if (oidpos != 0) -+ buffer_put_char(&buf, ','); -+ -+ buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, -+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ buffer_put_char(&buf, ','); -+ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, -+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ buffer_put_char(&buf, ','); -+ buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, -+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ -+ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); -+ gss_enc2oid[oidpos].encoded = encoded; -+ oidpos++; -+ } -+ } -+ gss_enc2oid[oidpos].oid = NULL; -+ gss_enc2oid[oidpos].encoded = NULL; -+ -+ buffer_put_char(&buf, '\0'); -+ -+ mechs = xmalloc(buffer_len(&buf)); -+ buffer_get(&buf, mechs, buffer_len(&buf)); -+ buffer_free(&buf); -+ -+ if (strlen(mechs) == 0) { -+ xfree(mechs); -+ mechs = NULL; -+ } -+ -+ return (mechs); -+} -+ -+gss_OID -+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { -+ int i = 0; -+ -+ switch (kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GEX_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; -+ break; -+ default: -+ return GSS_C_NO_OID; -+ } -+ -+ while (gss_enc2oid[i].encoded != NULL && -+ strcmp(name, gss_enc2oid[i].encoded) != 0) -+ i++; -+ -+ if (gss_enc2oid[i].oid != NULL && ctx != NULL) -+ ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); -+ -+ return gss_enc2oid[i].oid; -+} -+ - /* Check that the OID in a data stream matches that in the context */ - int - ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) -@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de - } - - ctx->major = gss_init_sec_context(&ctx->minor, -- GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, -+ ctx->client_creds, &ctx->context, ctx->name, ctx->oid, - GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, - 0, NULL, recv_tok, NULL, send_tok, flags, NULL); - -@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con - } - - OM_uint32 -+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) -+{ -+ gss_buffer_desc gssbuf; -+ gss_name_t gssname; -+ OM_uint32 status; -+ gss_OID_set oidset; -+ -+ gssbuf.value = (void *) name; -+ gssbuf.length = strlen(gssbuf.value); -+ -+ gss_create_empty_oid_set(&status, &oidset); -+ gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ -+ ctx->major = gss_import_name(&ctx->minor, &gssbuf, -+ GSS_C_NT_USER_NAME, &gssname); -+ -+ if (!ctx->major) -+ ctx->major = gss_acquire_cred(&ctx->minor, -+ gssname, 0, oidset, GSS_C_INITIATE, -+ &ctx->client_creds, NULL, NULL); -+ -+ gss_release_name(&status, &gssname); -+ gss_release_oid_set(&status, &oidset); -+ -+ if (ctx->major) -+ ssh_gssapi_error(ctx); -+ -+ return(ctx->major); -+} -+ -+OM_uint32 - ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) - { -+ if (ctx == NULL) -+ return -1; -+ - if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, - GSS_C_QOP_DEFAULT, buffer, hash))) - ssh_gssapi_error(ctx); -@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer - return (ctx->major); - } - -+/* Priviledged when used by server */ -+OM_uint32 -+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+{ -+ if (ctx == NULL) -+ return -1; -+ -+ ctx->major = gss_verify_mic(&ctx->minor, ctx->context, -+ gssbuf, gssmic, NULL); -+ -+ return (ctx->major); -+} -+ - void - ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, - const char *context) -@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha - } - - int --ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) -+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, -+ const char *client) - { - gss_buffer_desc token = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; - gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; -+ Gssctxt *intctx = NULL; -+ -+ if (ctx == NULL) -+ ctx = &intctx; - - /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && -@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx - ssh_gssapi_build_ctx(ctx); - ssh_gssapi_set_oid(*ctx, oid); - major = ssh_gssapi_import_name(*ctx, host); -+ -+ if (!GSS_ERROR(major) && client) -+ major = ssh_gssapi_client_identity(*ctx, client); -+ - if (!GSS_ERROR(major)) { - major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, - NULL); -@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx - GSS_C_NO_BUFFER); - } - -- if (GSS_ERROR(major)) -+ if (GSS_ERROR(major) || intctx != NULL) - ssh_gssapi_delete_ctx(ctx); - - return (!GSS_ERROR(major)); - } - -+int -+ssh_gssapi_credentials_updated(Gssctxt *ctxt) { -+ static gss_name_t saved_name = GSS_C_NO_NAME; -+ static OM_uint32 saved_lifetime = 0; -+ static gss_OID saved_mech = GSS_C_NO_OID; -+ static gss_name_t name; -+ static OM_uint32 last_call = 0; -+ OM_uint32 lifetime, now, major, minor; -+ int equal; -+ gss_cred_usage_t usage = GSS_C_INITIATE; -+ -+ now = time(NULL); -+ -+ if (ctxt) { -+ debug("Rekey has happened - updating saved versions"); -+ -+ if (saved_name != GSS_C_NO_NAME) -+ gss_release_name(&minor, &saved_name); -+ -+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, -+ &saved_name, &saved_lifetime, NULL, NULL); -+ -+ if (!GSS_ERROR(major)) { -+ saved_mech = ctxt->oid; -+ saved_lifetime+= now; -+ } else { -+ /* Handle the error */ -+ } -+ return 0; -+ } -+ -+ if (now - last_call < 10) -+ return 0; -+ -+ last_call = now; -+ -+ if (saved_mech == GSS_C_NO_OID) -+ return 0; -+ -+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, -+ &name, &lifetime, NULL, NULL); -+ if (major == GSS_S_CREDENTIALS_EXPIRED) -+ return 0; -+ else if (GSS_ERROR(major)) -+ return 0; -+ -+ major = gss_compare_name(&minor, saved_name, name, &equal); -+ gss_release_name(&minor, &name); -+ if (GSS_ERROR(major)) -+ return 0; -+ -+ if (equal && (saved_lifetime < lifetime + now - 10)) -+ return 1; -+ -+ return 0; -+} -+ - #endif /* GSSAPI */ -diff -up openssh-6.2p1/gss-serv.c.gsskex openssh-6.2p1/gss-serv.c ---- openssh-6.2p1/gss-serv.c.gsskex 2011-08-05 22:16:46.000000000 +0200 -+++ openssh-6.2p1/gss-serv.c 2013-03-27 13:19:11.142624263 +0100 -@@ -45,15 +45,20 @@ - #include "channels.h" - #include "session.h" - #include "misc.h" -+#include "servconf.h" -+#include "uidswap.h" - - #include "ssh-gss.h" -+#include "monitor_wrap.h" -+ -+extern ServerOptions options; - - static ssh_gssapi_client gssapi_client = - { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, -- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}}; -+ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; - - ssh_gssapi_mech gssapi_null_mech = -- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; -+ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; - - #ifdef KRB5 - extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) - char lname[MAXHOSTNAMELEN]; - gss_OID_set oidset; - -- gss_create_empty_oid_set(&status, &oidset); -- gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ if (options.gss_strict_acceptor) { -+ gss_create_empty_oid_set(&status, &oidset); -+ gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ -+ if (gethostname(lname, MAXHOSTNAMELEN)) { -+ gss_release_oid_set(&status, &oidset); -+ return (-1); -+ } - -- if (gethostname(lname, MAXHOSTNAMELEN)) { -- gss_release_oid_set(&status, &oidset); -- return (-1); -- } -+ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { -+ gss_release_oid_set(&status, &oidset); -+ return (ctx->major); -+ } -+ -+ if ((ctx->major = gss_acquire_cred(&ctx->minor, -+ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, -+ NULL, NULL))) -+ ssh_gssapi_error(ctx); - -- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { - gss_release_oid_set(&status, &oidset); - return (ctx->major); -+ } else { -+ ctx->name = GSS_C_NO_NAME; -+ ctx->creds = GSS_C_NO_CREDENTIAL; - } -- -- if ((ctx->major = gss_acquire_cred(&ctx->minor, -- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) -- ssh_gssapi_error(ctx); -- -- gss_release_oid_set(&status, &oidset); -- return (ctx->major); -+ return GSS_S_COMPLETE; - } - - /* Privileged */ -@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss - } - - /* Unprivileged */ -+char * -+ssh_gssapi_server_mechanisms() { -+ gss_OID_set supported; -+ -+ ssh_gssapi_supported_oids(&supported); -+ return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, -+ NULL, NULL)); -+} -+ -+/* Unprivileged */ -+int -+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, -+ const char *dummy) { -+ Gssctxt *ctx = NULL; -+ int res; -+ -+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); -+ ssh_gssapi_delete_ctx(&ctx); -+ -+ return (res); -+} -+ -+/* Unprivileged */ - void - ssh_gssapi_supported_oids(gss_OID_set *oidset) - { -@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o - gss_OID_set supported; - - gss_create_empty_oid_set(&min_status, oidset); -- gss_indicate_mechs(&min_status, &supported); -+ -+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) -+ return; - - while (supported_mechs[i]->name != NULL) { - if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -249,8 +286,48 @@ OM_uint32 - ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) - { - int i = 0; -+ int equal = 0; -+ gss_name_t new_name = GSS_C_NO_NAME; -+ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; -+ -+ if (options.gss_store_rekey && client->used && ctx->client_creds) { -+ if (client->mech->oid.length != ctx->oid->length || -+ (memcmp(client->mech->oid.elements, -+ ctx->oid->elements, ctx->oid->length) !=0)) { -+ debug("Rekeyed credentials have different mechanism"); -+ return GSS_S_COMPLETE; -+ } -+ -+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &new_name, -+ NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } - -- gss_buffer_desc ename; -+ ctx->major = gss_compare_name(&ctx->minor, client->name, -+ new_name, &equal); -+ -+ if (GSS_ERROR(ctx->major)) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ -+ if (!equal) { -+ debug("Rekeyed credentials have different name"); -+ return GSS_S_COMPLETE; -+ } -+ -+ debug("Marking rekeyed credentials for export"); -+ -+ gss_release_name(&ctx->minor, &client->name); -+ gss_release_cred(&ctx->minor, &client->creds); -+ client->name = new_name; -+ client->creds = ctx->client_creds; -+ ctx->client_creds = GSS_C_NO_CREDENTIAL; -+ client->updated = 1; -+ return GSS_S_COMPLETE; -+ } - - client->mech = NULL; - -@@ -265,6 +342,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - if (client->mech == NULL) - return GSS_S_FAILURE; - -+ if (ctx->client_creds && -+ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ - if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, - &client->displayname, NULL))) { - ssh_gssapi_error(ctx); -@@ -282,6 +366,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - return (ctx->major); - } - -+ gss_release_buffer(&ctx->minor, &ename); -+ - /* We can't copy this structure, so we just move the pointer to it */ - client->creds = ctx->client_creds; - ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -292,11 +378,33 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - void - ssh_gssapi_cleanup_creds(void) - { -+ struct stat krb5_ccname_stat; -+ char krb5_ccname[128], *krb5_ccname_dir_end; -+ - if (gssapi_client.store.filename != NULL) { - /* Unlink probably isn't sufficient */ - debug("removing gssapi cred file\"%s\"", - gssapi_client.store.filename); - unlink(gssapi_client.store.filename); -+ -+ /* Ticket cache: DIR::/run/user/13558/krb5cc_T9eDKSQvzb/tkt */ -+ /* same code as in auth-krb5.c:krb5_cleanup_proc */ -+ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10); -+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); -+ if (krb5_ccname_dir_end != NULL) -+ strcpy(krb5_ccname_dir_end, "/primary"); -+ -+ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { -+ if (unlink(krb5_ccname) == 0) { -+ *krb5_ccname_dir_end = '\0'; -+ if (rmdir(krb5_ccname) == -1) -+ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); -+ } -+ else -+ debug("cache primary file '%s', remove failed: %s", -+ krb5_ccname, strerror(errno) -+ ); -+ } - } - } - -@@ -329,7 +437,7 @@ ssh_gssapi_do_child(char ***envp, u_int - - /* Privileged */ - int --ssh_gssapi_userok(char *user) -+ssh_gssapi_userok(char *user, struct passwd *pw) - { - OM_uint32 lmin; - -@@ -339,9 +447,11 @@ ssh_gssapi_userok(char *user) - return 0; - } - if (gssapi_client.mech && gssapi_client.mech->userok) -- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) -+ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { -+ gssapi_client.used = 1; -+ gssapi_client.store.owner = pw; - return 1; -- else { -+ } else { - /* Destroy delegated credentials if userok fails */ - gss_release_buffer(&lmin, &gssapi_client.displayname); - gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -354,14 +464,90 @@ ssh_gssapi_userok(char *user) - return (0); - } - --/* Privileged */ --OM_uint32 --ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+/* These bits are only used for rekeying. The unpriviledged child is running -+ * as the user, the monitor is root. -+ * -+ * In the child, we want to : -+ * *) Ask the monitor to store our credentials into the store we specify -+ * *) If it succeeds, maybe do a PAM update -+ */ -+ -+/* Stuff for PAM */ -+ -+#ifdef USE_PAM -+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, -+ struct pam_response **resp, void *data) - { -- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, -- gssbuf, gssmic, NULL); -+ return (PAM_CONV_ERR); -+} -+#endif - -- return (ctx->major); -+void -+ssh_gssapi_rekey_creds() { -+ int ok; -+ int ret; -+#ifdef USE_PAM -+ pam_handle_t *pamh = NULL; -+ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; -+ char *envstr; -+#endif -+ -+ if (gssapi_client.store.filename == NULL && -+ gssapi_client.store.envval == NULL && -+ gssapi_client.store.envvar == NULL) -+ return; -+ -+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); -+ -+ if (!ok) -+ return; -+ -+ debug("Rekeyed credentials stored successfully"); -+ -+ /* Actually managing to play with the ssh pam stack from here will -+ * be next to impossible. In any case, we may want different options -+ * for rekeying. So, use our own :) -+ */ -+#ifdef USE_PAM -+ if (!use_privsep) { -+ debug("Not even going to try and do PAM with privsep disabled"); -+ return; -+ } -+ -+ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, -+ &pamconv, &pamh); -+ if (ret) -+ return; -+ -+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, -+ gssapi_client.store.envval); -+ -+ ret = pam_putenv(pamh, envstr); -+ if (!ret) -+ pam_setcred(pamh, PAM_REINITIALIZE_CRED); -+ pam_end(pamh, PAM_SUCCESS); -+#endif -+} -+ -+int -+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { -+ int ok = 0; -+ -+ /* Check we've got credentials to store */ -+ if (!gssapi_client.updated) -+ return 0; -+ -+ gssapi_client.updated = 0; -+ -+ temporarily_use_uid(gssapi_client.store.owner); -+ if (gssapi_client.mech && gssapi_client.mech->updatecreds) -+ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); -+ else -+ debug("No update function for this mechanism"); -+ -+ restore_uid(); -+ -+ return ok; - } - - #endif -diff -up openssh-6.2p1/gss-serv-krb5.c.gsskex openssh-6.2p1/gss-serv-krb5.c ---- openssh-6.2p1/gss-serv-krb5.c.gsskex 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-6.2p1/gss-serv-krb5.c 2013-03-27 13:19:11.143624259 +0100 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -119,7 +119,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - - if (client->creds == NULL) { - debug("No credentials stored"); -@@ -168,11 +168,25 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -184,6 +198,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -191,7 +270,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ -diff -up openssh-6.2p1/kex.c.gsskex openssh-6.2p1/kex.c ---- openssh-6.2p1/kex.c.gsskex 2013-03-27 13:19:11.039624686 +0100 -+++ openssh-6.2p1/kex.c 2013-03-27 13:19:11.143624259 +0100 -@@ -51,6 +51,10 @@ - #include "roaming.h" - #include "audit.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - #if OPENSSL_VERSION_NUMBER >= 0x00907000L - # if defined(HAVE_EVP_SHA256) - # define evp_ssh_sha256 EVP_sha256 -@@ -382,6 +386,20 @@ choose_kex(Kex *k, char *client, char *s - k->kex_type = KEX_ECDH_SHA2; - k->evp_md = kex_ecdh_name_to_evpmd(k->name); - #endif -+#ifdef GSSAPI -+ } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, -+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GEX_SHA1; -+ k->evp_md = EVP_sha1(); -+ } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, -+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GRP1_SHA1; -+ k->evp_md = EVP_sha1(); -+ } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID, -+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GRP14_SHA1; -+ k->evp_md = EVP_sha1(); -+#endif - } else - fatal("bad kex alg %s", k->name); - } -diff -up openssh-6.2p1/kexgssc.c.gsskex openssh-6.2p1/kexgssc.c ---- openssh-6.2p1/kexgssc.c.gsskex 2013-03-27 13:19:11.143624259 +0100 -+++ openssh-6.2p1/kexgssc.c 2013-03-27 13:19:11.143624259 +0100 -@@ -0,0 +1,334 @@ -+/* -+ * Copyright (c) 2001-2009 Simon Wilkinson. 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" -+ -+#ifdef GSSAPI -+ -+#include "includes.h" -+ -+#include -+#include -+ -+#include -+ -+#include "xmalloc.h" -+#include "buffer.h" -+#include "ssh2.h" -+#include "key.h" -+#include "cipher.h" -+#include "kex.h" -+#include "log.h" -+#include "packet.h" -+#include "dh.h" -+ -+#include "ssh-gss.h" -+ -+void -+kexgss_client(Kex *kex) { -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; -+ Gssctxt *ctxt; -+ OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen, kout, slen = 0, hashlen, strlen; -+ DH *dh; -+ BIGNUM *dh_server_pub = NULL; -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *p = NULL; -+ BIGNUM *g = NULL; -+ u_char *kbuf, *hash; -+ u_char *serverhostkey = NULL; -+ u_char *empty = ""; -+ char *msg; -+ char *lang; -+ int type = 0; -+ int first = 1; -+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; -+ -+ /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -+ == GSS_C_NO_OID) -+ fatal("Couldn't identify host exchange"); -+ -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -+ fatal("Couldn't import hostname"); -+ -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) -+ fatal("Couldn't acquire client credentials"); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange\n"); -+ nbits = dh_estimate(kex->we_need * 8); -+ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); -+ packet_put_int(min); -+ packet_put_int(nbits); -+ packet_put_int(max); -+ -+ packet_send(); -+ -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); -+ -+ if ((p = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(p); -+ if ((g = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(g); -+ packet_check_eom(); -+ -+ if (BN_num_bits(p) < min || BN_num_bits(p) > max) -+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -+ min, BN_num_bits(p), max); -+ -+ dh = dh_new_group(g, p); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ /* Step 1 - e is dh->pub_key */ -+ dh_gen_key(dh, kex->we_need * 8); -+ -+ /* This is f, we initialise it now to make life easier */ -+ dh_server_pub = BN_new(); -+ if (dh_server_pub == NULL) -+ fatal("dh_server_pub == NULL"); -+ -+ token_ptr = GSS_C_NO_BUFFER; -+ -+ do { -+ debug("Calling gss_init_sec_context"); -+ -+ maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, -+ &ret_flags); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length != 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ xfree(recv_tok.value); -+ -+ if (maj_status == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (first) { -+ packet_start(SSH2_MSG_KEXGSS_INIT); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ packet_put_bignum2(dh->pub_key); -+ first = 0; -+ } else { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ do { -+ type = packet_read(); -+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ debug("Received KEXGSS_HOSTKEY"); -+ if (serverhostkey) -+ fatal("Server host key received more than once"); -+ serverhostkey = -+ packet_get_string(&slen); -+ } -+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -+ -+ switch (type) { -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ recv_tok.value = packet_get_string(&strlen); -+ recv_tok.length = strlen; -+ break; -+ case SSH2_MSG_KEXGSS_COMPLETE: -+ debug("Received GSSAPI_COMPLETE"); -+ packet_get_bignum2(dh_server_pub); -+ msg_tok.value = packet_get_string(&strlen); -+ msg_tok.length = strlen; -+ -+ /* Is there a token included? */ -+ if (packet_get_char()) { -+ recv_tok.value= -+ packet_get_string(&strlen); -+ recv_tok.length = strlen; -+ /* If we're already complete - protocol error */ -+ if (maj_status == GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: did not receive final token"); -+ } -+ break; -+ case SSH2_MSG_KEXGSS_ERROR: -+ debug("Received Error"); -+ maj_status = packet_get_int(); -+ min_status = packet_get_int(); -+ msg = packet_get_string(NULL); -+ lang = packet_get_string(NULL); -+ fatal("GSSAPI Error: \n%.400s",msg); -+ default: -+ packet_disconnect("Protocol error: didn't expect packet type %d", -+ type); -+ } -+ token_ptr = &recv_tok; -+ } else { -+ /* No data, and not complete */ -+ if (maj_status != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ /* -+ * We _must_ have received a COMPLETE message in reply from the -+ * server, which will have set dh_server_pub and msg_tok -+ */ -+ -+ if (type != SSH2_MSG_KEXGSS_COMPLETE) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ -+ /* Check f in range [1, p-1] */ -+ if (!dh_pub_is_valid(dh, dh_server_pub)) -+ packet_disconnect("bad server public DH value"); -+ -+ /* compute K=f^x mod p */ -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_server_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); -+ -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_client: BN_new failed"); -+ -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexdh_client: BN_bin2bn failed"); -+ -+ memset(kbuf, 0, klen); -+ xfree(kbuf); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ dh->pub_key, /* e */ -+ dh_server_pub, /* f */ -+ shared_secret, /* K */ -+ &hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ kex->evp_md, -+ kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ min, nbits, max, -+ dh->p, dh->g, -+ dh->pub_key, -+ dh_server_pub, -+ shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ /* Verify that the hash matches the MIC we just got. */ -+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ packet_disconnect("Hash's MIC didn't verify"); -+ -+ xfree(msg_tok.value); -+ -+ DH_free(dh); -+ if (serverhostkey) -+ xfree(serverhostkey); -+ BN_clear_free(dh_server_pub); -+ -+ /* save session id */ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ if (kex->gss_deleg_creds) -+ ssh_gssapi_credentials_updated(ctxt); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ kex_derive_keys(kex, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ kex_finish(kex); -+} -+ -+#endif /* GSSAPI */ -diff -up openssh-6.2p1/kexgsss.c.gsskex openssh-6.2p1/kexgsss.c ---- openssh-6.2p1/kexgsss.c.gsskex 2013-03-27 13:19:11.144624254 +0100 -+++ openssh-6.2p1/kexgsss.c 2013-03-27 13:19:11.144624254 +0100 -@@ -0,0 +1,288 @@ -+/* -+ * Copyright (c) 2001-2009 Simon Wilkinson. 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" -+ -+#ifdef GSSAPI -+ -+#include -+ -+#include -+#include -+ -+#include "xmalloc.h" -+#include "buffer.h" -+#include "ssh2.h" -+#include "key.h" -+#include "cipher.h" -+#include "kex.h" -+#include "log.h" -+#include "packet.h" -+#include "dh.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" -+#include "servconf.h" -+ -+extern ServerOptions options; -+ -+void -+kexgss_server(Kex *kex) -+{ -+ OM_uint32 maj_status, min_status; -+ -+ /* -+ * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. -+ */ -+ -+ OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf, recv_tok, msg_tok; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ Gssctxt *ctxt = NULL; -+ u_int slen, klen, kout, hashlen; -+ u_char *kbuf, *hash; -+ DH *dh; -+ int min = -1, max = -1, nbits = -1; -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *dh_client_pub = NULL; -+ int type = 0; -+ gss_OID oid; -+ char *mechs; -+ -+ /* Initialise GSSAPI */ -+ -+ /* If we're rekeying, privsep means that some of the private structures -+ * in the GSSAPI code are no longer available. This kludges them back -+ * into life -+ */ -+ if (!ssh_gssapi_oid_table_ok()) -+ if ((mechs = ssh_gssapi_server_mechanisms())) -+ xfree(mechs); -+ -+ debug2("%s: Identifying %s", __func__, kex->name); -+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); -+ if (oid == GSS_C_NO_OID) -+ fatal("Unknown gssapi mechanism"); -+ -+ debug2("%s: Acquiring credentials", __func__); -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) -+ fatal("Unable to acquire credentials for the server"); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange"); -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); -+ min = packet_get_int(); -+ nbits = packet_get_int(); -+ max = packet_get_int(); -+ min = MAX(DH_GRP_MIN, min); -+ max = MIN(DH_GRP_MAX, max); -+ packet_check_eom(); -+ if (max < min || nbits < min || max < nbits) -+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", -+ min, nbits, max); -+ dh = PRIVSEP(choose_dh(min, nbits, max)); -+ if (dh == NULL) -+ packet_disconnect("Protocol error: no matching group found"); -+ -+ packet_start(SSH2_MSG_KEXGSS_GROUP); -+ packet_put_bignum2(dh->p); -+ packet_put_bignum2(dh->g); -+ packet_send(); -+ -+ packet_write_wait(); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ dh_gen_key(dh, kex->we_need * 8); -+ -+ do { -+ debug("Wait SSH2_MSG_GSSAPI_INIT"); -+ type = packet_read(); -+ switch(type) { -+ case SSH2_MSG_KEXGSS_INIT: -+ if (dh_client_pub != NULL) -+ fatal("Received KEXGSS_INIT after initialising"); -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ -+ if ((dh_client_pub = BN_new()) == NULL) -+ fatal("dh_client_pub == NULL"); -+ -+ packet_get_bignum2(dh_client_pub); -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ break; -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ break; -+ default: -+ packet_disconnect( -+ "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); -+ -+ xfree(recv_tok.value); -+ -+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -+ fatal("Zero length token output when incomplete"); -+ -+ if (dh_client_pub == NULL) -+ fatal("No client public key"); -+ -+ if (maj_status & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length > 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ } -+ fatal("accept_ctx died"); -+ } -+ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual Authentication flag wasn't set"); -+ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity flag wasn't set"); -+ -+ if (!dh_pub_is_valid(dh, dh_client_pub)) -+ packet_disconnect("bad client public DH value"); -+ -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_client_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); -+ -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_server: BN_new failed"); -+ -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexgss_server: BN_bin2bn failed"); -+ -+ memset(kbuf, 0, klen); -+ xfree(kbuf); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ NULL, 0, /* Change this if we start sending host keys */ -+ dh_client_pub, dh->pub_key, shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ kex->evp_md, -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ NULL, 0, -+ min, nbits, max, -+ dh->p, dh->g, -+ dh_client_pub, -+ dh->pub_key, -+ shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ BN_clear_free(dh_client_pub); -+ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) -+ fatal("Couldn't get MIC"); -+ -+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); -+ packet_put_bignum2(dh->pub_key); -+ packet_put_string(msg_tok.value,msg_tok.length); -+ -+ if (send_tok.length != 0) { -+ packet_put_char(1); /* true */ -+ packet_put_string(send_tok.value, send_tok.length); -+ } else { -+ packet_put_char(0); /* false */ -+ } -+ packet_send(); -+ -+ gss_release_buffer(&min_status, &send_tok); -+ gss_release_buffer(&min_status, &msg_tok); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ DH_free(dh); -+ -+ kex_derive_keys(kex, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ kex_finish(kex); -+ -+ /* If this was a rekey, then save out any delegated credentials we -+ * just exchanged. */ -+ if (options.gss_store_rekey) -+ ssh_gssapi_rekey_creds(); -+} -+#endif /* GSSAPI */ -diff -up openssh-6.2p1/kex.h.gsskex openssh-6.2p1/kex.h ---- openssh-6.2p1/kex.h.gsskex 2013-03-27 13:19:11.039624686 +0100 -+++ openssh-6.2p1/kex.h 2013-03-27 13:19:11.144624254 +0100 -@@ -73,6 +73,9 @@ enum kex_exchange { - KEX_DH_GEX_SHA1, - KEX_DH_GEX_SHA256, - KEX_ECDH_SHA2, -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, - KEX_MAX - }; - -@@ -131,6 +134,12 @@ struct Kex { - sig_atomic_t done; - int flags; - const EVP_MD *evp_md; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *client_version_string; - char *server_version_string; - int (*verify_host_key)(Key *); -@@ -158,6 +167,11 @@ void kexgex_server(Kex *); - void kexecdh_client(Kex *); - void kexecdh_server(Kex *); - -+#ifdef GSSAPI -+void kexgss_client(Kex *); -+void kexgss_server(Kex *); -+#endif -+ - void newkeys_destroy(Newkeys *newkeys); - - void -diff -up openssh-6.2p1/key.c.gsskex openssh-6.2p1/key.c ---- openssh-6.2p1/key.c.gsskex 2013-03-27 13:19:11.102624427 +0100 -+++ openssh-6.2p1/key.c 2013-03-27 13:19:11.144624254 +0100 -@@ -1011,6 +1011,8 @@ key_ssh_name_from_type_nid(int type, int - } - break; - #endif /* OPENSSL_HAS_ECC */ -+ case KEY_NULL: -+ return "null"; - } - return "ssh-unknown"; - } -@@ -1316,6 +1318,8 @@ key_type_from_name(char *name) - strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { - return KEY_ECDSA_CERT; - #endif -+ } else if (strcmp(name, "null") == 0) { -+ return KEY_NULL; - } - - debug2("key_type_from_name: unknown key type '%s'", name); -diff -up openssh-6.2p1/key.h.gsskex openssh-6.2p1/key.h ---- openssh-6.2p1/key.h.gsskex 2013-03-27 13:19:11.046624657 +0100 -+++ openssh-6.2p1/key.h 2013-03-27 13:19:11.145624250 +0100 -@@ -44,6 +44,7 @@ enum types { - KEY_ECDSA_CERT, - KEY_RSA_CERT_V00, - KEY_DSA_CERT_V00, -+ KEY_NULL, - KEY_UNSPEC - }; - enum fp_type { -diff -up openssh-6.2p1/Makefile.in.gsskex openssh-6.2p1/Makefile.in ---- openssh-6.2p1/Makefile.in.gsskex 2013-03-27 13:19:11.138624279 +0100 -+++ openssh-6.2p1/Makefile.in 2013-03-27 13:19:11.145624250 +0100 -@@ -77,6 +77,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o - atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ -+ kexgssc.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - jpake.o schnorr.o ssh-pkcs11.o krl.o auditstub.o - -@@ -93,7 +94,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ - monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ - auth-krb5.o \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ - sftp-server.o sftp-common.o \ - roaming_common.o roaming_serv.o \ -diff -up openssh-6.2p1/monitor.c.gsskex openssh-6.2p1/monitor.c ---- openssh-6.2p1/monitor.c.gsskex 2013-03-27 13:19:11.063624587 +0100 -+++ openssh-6.2p1/monitor.c 2013-03-27 13:19:11.145624250 +0100 -@@ -186,6 +186,8 @@ int mm_answer_gss_setup_ctx(int, Buffer - int mm_answer_gss_accept_ctx(int, Buffer *); - int mm_answer_gss_userok(int, Buffer *); - int mm_answer_gss_checkmic(int, Buffer *); -+int mm_answer_gss_sign(int, Buffer *); -+int mm_answer_gss_updatecreds(int, Buffer *); - #endif - - #ifdef SSH_AUDIT_EVENTS -@@ -270,6 +272,7 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, - {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, - {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, -+ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, - #endif - #ifdef JPAKE - {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, -@@ -282,6 +285,12 @@ struct mon_table mon_dispatch_proto20[] - }; - - struct mon_table mon_dispatch_postauth20[] = { -+#ifdef GSSAPI -+ {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, -+ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, -+ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, -+ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, -+#endif - {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, - {MONITOR_REQ_SIGN, 0, mm_answer_sign}, - {MONITOR_REQ_PTY, 0, mm_answer_pty}, -@@ -404,6 +413,10 @@ monitor_child_preauth(Authctxt *_authctx - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); -+#ifdef GSSAPI -+ /* and for the GSSAPI key exchange */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -+#endif - } else { - mon_dispatch = mon_dispatch_proto15; - -@@ -519,6 +532,10 @@ monitor_child_postauth(struct monitor *p - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); -+#ifdef GSSAPI -+ /* and for the GSSAPI key exchange */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -+#endif - } else { - mon_dispatch = mon_dispatch_postauth15; - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); -@@ -1950,6 +1967,13 @@ mm_get_kex(Buffer *m) - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ } -+#endif - kex->server = 1; - kex->hostkey_type = buffer_get_int(m); - kex->kex_type = buffer_get_int(m); -@@ -2173,6 +2197,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer - OM_uint32 major; - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - goid.elements = buffer_get_string(m, &len); - goid.length = len; - -@@ -2200,6 +2227,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe - OM_uint32 flags = 0; /* GSI needs this */ - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - in.value = buffer_get_string(m, &len); - in.length = len; - major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); -@@ -2217,6 +2247,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); - } - return (0); - } -@@ -2228,6 +2259,9 @@ mm_answer_gss_checkmic(int sock, Buffer - OM_uint32 ret; - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - gssbuf.value = buffer_get_string(m, &len); - gssbuf.length = len; - mic.value = buffer_get_string(m, &len); -@@ -2254,7 +2288,11 @@ mm_answer_gss_userok(int sock, Buffer *m - { - int authenticated; - -- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ -+ authenticated = authctxt->valid && -+ ssh_gssapi_userok(authctxt->user, authctxt->pw); - - buffer_clear(m); - buffer_put_int(m, authenticated); -@@ -2267,6 +2305,74 @@ mm_answer_gss_userok(int sock, Buffer *m - /* Monitor loop will terminate if authenticated */ - return (authenticated); - } -+ -+int -+mm_answer_gss_sign(int socket, Buffer *m) -+{ -+ gss_buffer_desc data; -+ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; -+ OM_uint32 major, minor; -+ u_int len; -+ -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ -+ data.value = buffer_get_string(m, &len); -+ data.length = len; -+ if (data.length != 20) -+ fatal("%s: data length incorrect: %d", __func__, -+ (int) data.length); -+ -+ /* Save the session ID on the first time around */ -+ if (session_id2_len == 0) { -+ session_id2_len = data.length; -+ session_id2 = xmalloc(session_id2_len); -+ memcpy(session_id2, data.value, session_id2_len); -+ } -+ major = ssh_gssapi_sign(gsscontext, &data, &hash); -+ -+ xfree(data.value); -+ -+ buffer_clear(m); -+ buffer_put_int(m, major); -+ buffer_put_string(m, hash.value, hash.length); -+ -+ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); -+ -+ gss_release_buffer(&minor, &hash); -+ -+ /* Turn on getpwnam permissions */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); -+ -+ /* And credential updating, for when rekeying */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); -+ -+ return (0); -+} -+ -+int -+mm_answer_gss_updatecreds(int socket, Buffer *m) { -+ ssh_gssapi_ccache store; -+ int ok; -+ -+ store.filename = buffer_get_string(m, NULL); -+ store.envvar = buffer_get_string(m, NULL); -+ store.envval = buffer_get_string(m, NULL); -+ -+ ok = ssh_gssapi_update_creds(&store); -+ -+ xfree(store.filename); -+ xfree(store.envvar); -+ xfree(store.envval); -+ -+ buffer_clear(m); -+ buffer_put_int(m, ok); -+ -+ mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); -+ -+ return(0); -+} -+ - #endif /* GSSAPI */ - - #ifdef JPAKE -diff -up openssh-6.2p1/monitor.h.gsskex openssh-6.2p1/monitor.h ---- openssh-6.2p1/monitor.h.gsskex 2013-03-27 13:19:11.063624587 +0100 -+++ openssh-6.2p1/monitor.h 2013-03-27 13:19:11.146624246 +0100 -@@ -64,6 +64,8 @@ enum monitor_reqtype { - #ifdef WITH_SELINUX - MONITOR_REQ_AUTHROLE = 80, - #endif -+ MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83, -+ MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85, - - MONITOR_REQ_PAM_START = 100, - MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, -diff -up openssh-6.2p1/monitor_wrap.c.gsskex openssh-6.2p1/monitor_wrap.c ---- openssh-6.2p1/monitor_wrap.c.gsskex 2013-03-27 13:19:11.064624583 +0100 -+++ openssh-6.2p1/monitor_wrap.c 2013-03-27 13:19:11.146624246 +0100 -@@ -1327,7 +1327,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss - } - - int --mm_ssh_gssapi_userok(char *user) -+mm_ssh_gssapi_userok(char *user, struct passwd *pw) - { - Buffer m; - int authenticated = 0; -@@ -1344,6 +1344,51 @@ mm_ssh_gssapi_userok(char *user) - debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); - return (authenticated); - } -+ -+OM_uint32 -+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) -+{ -+ Buffer m; -+ OM_uint32 major; -+ u_int len; -+ -+ buffer_init(&m); -+ buffer_put_string(&m, data->value, data->length); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); -+ -+ major = buffer_get_int(&m); -+ hash->value = buffer_get_string(&m, &len); -+ hash->length = len; -+ -+ buffer_free(&m); -+ -+ return(major); -+} -+ -+int -+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) -+{ -+ Buffer m; -+ int ok; -+ -+ buffer_init(&m); -+ -+ buffer_put_cstring(&m, store->filename ? store->filename : ""); -+ buffer_put_cstring(&m, store->envvar ? store->envvar : ""); -+ buffer_put_cstring(&m, store->envval ? store->envval : ""); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); -+ -+ ok = buffer_get_int(&m); -+ -+ buffer_free(&m); -+ -+ return (ok); -+} -+ - #endif /* GSSAPI */ - - #ifdef JPAKE -diff -up openssh-6.2p1/monitor_wrap.h.gsskex openssh-6.2p1/monitor_wrap.h ---- openssh-6.2p1/monitor_wrap.h.gsskex 2013-03-27 13:19:11.064624583 +0100 -+++ openssh-6.2p1/monitor_wrap.h 2013-03-27 13:19:11.146624246 +0100 -@@ -62,8 +62,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K - OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); - OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, - gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); --int mm_ssh_gssapi_userok(char *user); -+int mm_ssh_gssapi_userok(char *user, struct passwd *); - OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); -+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); -+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); - #endif - - #ifdef USE_PAM -diff -up openssh-6.2p1/readconf.c.gsskex openssh-6.2p1/readconf.c ---- openssh-6.2p1/readconf.c.gsskex 2011-10-02 09:59:03.000000000 +0200 -+++ openssh-6.2p1/readconf.c 2013-03-27 13:19:11.147624242 +0100 -@@ -129,6 +129,8 @@ typedef enum { - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, -+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -+ oGssServerIdentity, - oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oControlPath, oControlMaster, oControlPersist, - oHashKnownHosts, -@@ -169,10 +171,19 @@ static struct { - { "afstokenpassing", oUnsupported }, - #if defined(GSSAPI) - { "gssapiauthentication", oGssAuthentication }, -+ { "gssapikeyexchange", oGssKeyEx }, - { "gssapidelegatecredentials", oGssDelegateCreds }, -+ { "gssapitrustdns", oGssTrustDns }, -+ { "gssapiclientidentity", oGssClientIdentity }, -+ { "gssapiserveridentity", oGssServerIdentity }, -+ { "gssapirenewalforcesrekey", oGssRenewalRekey }, - #else - { "gssapiauthentication", oUnsupported }, -+ { "gssapikeyexchange", oUnsupported }, - { "gssapidelegatecredentials", oUnsupported }, -+ { "gssapitrustdns", oUnsupported }, -+ { "gssapiclientidentity", oUnsupported }, -+ { "gssapirenewalforcesrekey", oUnsupported }, - #endif - { "fallbacktorsh", oDeprecated }, - { "usersh", oDeprecated }, -@@ -503,10 +514,30 @@ parse_flag: - intptr = &options->gss_authentication; - goto parse_flag; - -+ case oGssKeyEx: -+ intptr = &options->gss_keyex; -+ goto parse_flag; -+ - case oGssDelegateCreds: - intptr = &options->gss_deleg_creds; - goto parse_flag; - -+ case oGssTrustDns: -+ intptr = &options->gss_trust_dns; -+ goto parse_flag; -+ -+ case oGssClientIdentity: -+ charptr = &options->gss_client_identity; -+ goto parse_string; -+ -+ case oGssServerIdentity: -+ charptr = &options->gss_server_identity; -+ goto parse_string; -+ -+ case oGssRenewalRekey: -+ intptr = &options->gss_renewal_rekey; -+ goto parse_flag; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; -@@ -1158,7 +1189,12 @@ initialize_options(Options * options) - options->pubkey_authentication = -1; - options->challenge_response_authentication = -1; - options->gss_authentication = -1; -+ options->gss_keyex = -1; - options->gss_deleg_creds = -1; -+ options->gss_trust_dns = -1; -+ options->gss_renewal_rekey = -1; -+ options->gss_client_identity = NULL; -+ options->gss_server_identity = NULL; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; -@@ -1258,8 +1294,14 @@ fill_default_options(Options * options) - options->challenge_response_authentication = 1; - if (options->gss_authentication == -1) - options->gss_authentication = 0; -+ if (options->gss_keyex == -1) -+ options->gss_keyex = 0; - if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; -+ if (options->gss_trust_dns == -1) -+ options->gss_trust_dns = 0; -+ if (options->gss_renewal_rekey == -1) -+ options->gss_renewal_rekey = 0; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) -diff -up openssh-6.2p1/readconf.h.gsskex openssh-6.2p1/readconf.h ---- openssh-6.2p1/readconf.h.gsskex 2011-10-02 09:59:03.000000000 +0200 -+++ openssh-6.2p1/readconf.h 2013-03-27 13:19:11.147624242 +0100 -@@ -48,7 +48,12 @@ typedef struct { - int challenge_response_authentication; - /* Try S/Key or TIS, authentication. */ - int gss_authentication; /* Try GSS authentication */ -+ int gss_keyex; /* Try GSS key exchange */ - int gss_deleg_creds; /* Delegate GSS credentials */ -+ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ -+ int gss_renewal_rekey; /* Credential renewal forces rekey */ -+ char *gss_client_identity; /* Principal to initiate GSSAPI with */ -+ char *gss_server_identity; /* GSSAPI target principal */ - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up openssh-6.2p1/servconf.c.gsskex openssh-6.2p1/servconf.c ---- openssh-6.2p1/servconf.c.gsskex 2013-03-27 13:19:11.128624320 +0100 -+++ openssh-6.2p1/servconf.c 2013-03-27 13:19:11.147624242 +0100 -@@ -102,7 +102,10 @@ initialize_server_options(ServerOptions - options->kerberos_ticket_cleanup = -1; - options->kerberos_get_afs_token = -1; - options->gss_authentication=-1; -+ options->gss_keyex = -1; - options->gss_cleanup_creds = -1; -+ options->gss_strict_acceptor = -1; -+ options->gss_store_rekey = -1; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; -@@ -234,8 +237,14 @@ fill_default_server_options(ServerOption - options->kerberos_get_afs_token = 0; - if (options->gss_authentication == -1) - options->gss_authentication = 0; -+ if (options->gss_keyex == -1) -+ options->gss_keyex = 0; - if (options->gss_cleanup_creds == -1) - options->gss_cleanup_creds = 1; -+ if (options->gss_strict_acceptor == -1) -+ options->gss_strict_acceptor = 1; -+ if (options->gss_store_rekey == -1) -+ options->gss_store_rekey = 0; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) -@@ -331,7 +340,9 @@ typedef enum { - sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, -- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -+ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, -+ sGssKeyEx, sGssStoreRekey, -+ sAcceptEnv, sPermitTunnel, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, sHostCertificate, -@@ -397,10 +408,20 @@ static struct { - #ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, - { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, - #else - { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, - { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, - #endif -+ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, - { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, - { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, - { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, -@@ -1054,10 +1075,22 @@ process_server_config_line(ServerOptions - intptr = &options->gss_authentication; - goto parse_flag; - -+ case sGssKeyEx: -+ intptr = &options->gss_keyex; -+ goto parse_flag; -+ - case sGssCleanupCreds: - intptr = &options->gss_cleanup_creds; - goto parse_flag; - -+ case sGssStrictAcceptor: -+ intptr = &options->gss_strict_acceptor; -+ goto parse_flag; -+ -+ case sGssStoreRekey: -+ intptr = &options->gss_store_rekey; -+ goto parse_flag; -+ - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; -@@ -1938,6 +1971,9 @@ dump_config(ServerOptions *o) - #ifdef GSSAPI - dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); - dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); -+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); -+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); -+ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); - #endif - #ifdef JPAKE - dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, -diff -up openssh-6.2p1/servconf.h.gsskex openssh-6.2p1/servconf.h ---- openssh-6.2p1/servconf.h.gsskex 2013-03-27 13:19:11.128624320 +0100 -+++ openssh-6.2p1/servconf.h 2013-03-27 13:19:11.147624242 +0100 -@@ -110,7 +110,10 @@ typedef struct { - int kerberos_get_afs_token; /* If true, try to get AFS token if - * authenticated with Kerberos. */ - int gss_authentication; /* If true, permit GSSAPI authentication */ -+ int gss_keyex; /* If true, permit GSSAPI key exchange */ - int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -+ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ -+ int gss_store_rekey; - int password_authentication; /* If true, permit password - * authentication. */ - int kbd_interactive_authentication; /* If true, permit */ -diff -up openssh-6.2p1/ssh_config.5.gsskex openssh-6.2p1/ssh_config.5 ---- openssh-6.2p1/ssh_config.5.gsskex 2013-01-09 06:12:19.000000000 +0100 -+++ openssh-6.2p1/ssh_config.5 2013-03-27 13:19:11.148624238 +0100 -@@ -530,11 +530,43 @@ Specifies whether user authentication ba - The default is - .Dq no . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI may be used. When using -+GSSAPI key exchange the server need not have a host key. -+The default is -+.Dq no . -+Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIClientIdentity -+If set, specifies the GSSAPI client identity that ssh should use when -+connecting to the server. The default is unset, which means that the default -+identity will be used. -+.It Cm GSSAPIServerIdentity -+If set, specifies the GSSAPI server identity that ssh should expect when -+connecting to the server. The default is unset, which means that the -+expected GSSAPI server identity will be determined from the target -+hostname. - .It Cm GSSAPIDelegateCredentials - Forward (delegate) credentials to the server. - The default is - .Dq no . --Note that this option applies to protocol version 2 only. -+Note that this option applies to protocol version 2 connections using GSSAPI. -+.It Cm GSSAPIRenewalForcesRekey -+If set to -+.Dq yes -+then renewal of the client's GSSAPI credentials will force the rekeying of the -+ssh connection. With a compatible server, this can delegate the renewed -+credentials to a session on the server. -+The default is -+.Dq no . -+.It Cm GSSAPITrustDns -+Set to -+.Dq yes to indicate that the DNS is trusted to securely canonicalize -+the name of the host being connected to. If -+.Dq no, the hostname entered on the -+command line will be passed untouched to the GSSAPI library. -+The default is -+.Dq no . -+This option only applies to protocol version 2 connections using GSSAPI. - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -diff -up openssh-6.2p1/ssh_config.gsskex openssh-6.2p1/ssh_config ---- openssh-6.2p1/ssh_config.gsskex 2013-03-27 13:19:11.120624353 +0100 -+++ openssh-6.2p1/ssh_config 2013-03-27 13:19:11.148624238 +0100 -@@ -26,6 +26,8 @@ - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any -diff -up openssh-6.2p1/sshconnect2.c.gsskex openssh-6.2p1/sshconnect2.c ---- openssh-6.2p1/sshconnect2.c.gsskex 2013-03-27 13:19:11.104624419 +0100 -+++ openssh-6.2p1/sshconnect2.c 2013-03-27 13:19:11.149624234 +0100 -@@ -162,9 +162,34 @@ ssh_kex2(char *host, struct sockaddr *ho - { - Kex *kex; - -+#ifdef GSSAPI -+ char *orig = NULL, *gss = NULL; -+ char *gss_host = NULL; -+#endif -+ - xxx_host = host; - xxx_hostaddr = hostaddr; - -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ /* Add the GSSAPI mechanisms currently supported on this -+ * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ if (options.gss_trust_dns) -+ gss_host = (char *)get_canonical_hostname(1); -+ else -+ gss_host = host; -+ -+ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ } -+ } -+#endif -+ - if (options.ciphers == (char *)-1) { - logit("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; -@@ -207,6 +232,17 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.kex_algorithms != NULL) - myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; - -+#ifdef GSSAPI -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ if (options.gss_keyex && gss) { -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ xfree(gss); -+ } -+#endif -+ - if (options.rekey_limit) - packet_set_rekey_limit((u_int32_t)options.rekey_limit); - -@@ -217,10 +253,30 @@ ssh_kex2(char *host, struct sockaddr *ho - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; - kex->kex[KEX_ECDH_SHA2] = kexecdh_client; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; -+ } -+#endif - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; - -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->gss_deleg_creds = options.gss_deleg_creds; -+ kex->gss_trust_dns = options.gss_trust_dns; -+ kex->gss_client = options.gss_client_identity; -+ if (options.gss_server_identity) { -+ kex->gss_host = options.gss_server_identity; -+ } else { -+ kex->gss_host = gss_host; -+ } -+ } -+#endif -+ - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); -@@ -316,6 +372,7 @@ void input_gssapi_token(int type, u_int3 - void input_gssapi_hash(int type, u_int32_t, void *); - void input_gssapi_error(int, u_int32_t, void *); - void input_gssapi_errtok(int, u_int32_t, void *); -+int userauth_gsskeyex(Authctxt *authctxt); - #endif - - void userauth(Authctxt *, char *); -@@ -331,6 +388,11 @@ static char *authmethods_get(void); - - Authmethod authmethods[] = { - #ifdef GSSAPI -+ {"gssapi-keyex", -+ userauth_gsskeyex, -+ NULL, -+ &options.gss_authentication, -+ NULL}, - {"gssapi-with-mic", - userauth_gssapi, - NULL, -@@ -638,19 +700,31 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; - OM_uint32 min; - int ok = 0; -+ const char *gss_host; -+ -+ if (options.gss_server_identity) -+ gss_host = options.gss_server_identity; -+ else if (options.gss_trust_dns) -+ gss_host = get_canonical_hostname(1); -+ else -+ gss_host = authctxt->host; - - /* Try one GSSAPI method at a time, rather than sending them all at - * once. */ - - if (gss_supported == NULL) -- gss_indicate_mechs(&min, &gss_supported); -+ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { -+ gss_supported = NULL; -+ return 0; -+ } - - /* Check to see if the mechanism is usable before we offer it */ - while (mech < gss_supported->count && !ok) { - /* My DER encoding requires length<128 */ - if (gss_supported->elements[mech].length < 128 && - ssh_gssapi_check_mechanism(&gssctxt, -- &gss_supported->elements[mech], authctxt->host)) { -+ &gss_supported->elements[mech], gss_host, -+ options.gss_client_identity)) { - ok = 1; /* Mechanism works */ - } else { - mech++; -@@ -747,8 +821,8 @@ input_gssapi_response(int type, u_int32_ - { - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; -- int oidlen; -- char *oidv; -+ u_int oidlen; -+ u_char *oidv; - - if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); -@@ -858,6 +932,48 @@ input_gssapi_error(int type, u_int32_t p - xfree(msg); - xfree(lang); - } -+ -+int -+userauth_gsskeyex(Authctxt *authctxt) -+{ -+ Buffer b; -+ gss_buffer_desc gssbuf; -+ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ms; -+ -+ static int attempt = 0; -+ if (attempt++ >= 1) -+ return (0); -+ -+ if (gss_kex_context == NULL) { -+ debug("No valid Key exchange context"); -+ return (0); -+ } -+ -+ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, -+ "gssapi-keyex"); -+ -+ gssbuf.value = buffer_ptr(&b); -+ gssbuf.length = buffer_len(&b); -+ -+ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { -+ buffer_free(&b); -+ return (0); -+ } -+ -+ packet_start(SSH2_MSG_USERAUTH_REQUEST); -+ packet_put_cstring(authctxt->server_user); -+ packet_put_cstring(authctxt->service); -+ packet_put_cstring(authctxt->method->name); -+ packet_put_string(mic.value, mic.length); -+ packet_send(); -+ -+ buffer_free(&b); -+ gss_release_buffer(&ms, &mic); -+ -+ return (1); -+} -+ - #endif /* GSSAPI */ - - int -diff -up openssh-6.2p1/sshd.c.gsskex openssh-6.2p1/sshd.c ---- openssh-6.2p1/sshd.c.gsskex 2013-03-27 13:19:11.133624300 +0100 -+++ openssh-6.2p1/sshd.c 2013-03-27 13:19:11.149624234 +0100 -@@ -124,6 +124,10 @@ - #include "ssh-sandbox.h" - #include "version.h" - -+#ifdef USE_SECURITY_SESSION_API -+#include -+#endif -+ - #ifdef LIBWRAP - #include - #include -@@ -1733,10 +1737,13 @@ main(int ac, char **av) - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; - } -+#ifndef GSSAPI -+ /* The GSSAPI key exchange can run without a host key */ - if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { - logit("Disabling protocol version 2. Could not load host key"); - options.protocol &= ~SSH_PROTO_2; - } -+#endif - if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { - logit("sshd: no hostkeys available -- exiting."); - exit(1); -@@ -2068,6 +2075,60 @@ main(int ac, char **av) - /* Log the connection. */ - verbose("Connection from %.500s port %d", remote_ip, remote_port); - -+#ifdef USE_SECURITY_SESSION_API -+ /* -+ * Create a new security session for use by the new user login if -+ * the current session is the root session or we are not launched -+ * by inetd (eg: debugging mode or server mode). We do not -+ * necessarily need to create a session if we are launched from -+ * inetd because Panther xinetd will create a session for us. -+ * -+ * The only case where this logic will fail is if there is an -+ * inetd running in a non-root session which is not creating -+ * new sessions for us. Then all the users will end up in the -+ * same session (bad). -+ * -+ * When the client exits, the session will be destroyed for us -+ * automatically. -+ * -+ * We must create the session before any credentials are stored -+ * (including AFS pags, which happens a few lines below). -+ */ -+ { -+ OSStatus err = 0; -+ SecuritySessionId sid = 0; -+ SessionAttributeBits sattrs = 0; -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("Current Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ -+ if (inetd_flag && !(sattrs & sessionIsRoot)) -+ debug("Running in inetd mode in a non-root session... " -+ "assuming inetd created the session for us."); -+ else { -+ debug("Creating new security session..."); -+ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); -+ if (err) -+ error("SessionCreate() failed with error %.8X", -+ (unsigned) err); -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, -+ &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("New Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ } -+ } -+#endif -+ - /* - * We don't want to listen forever unless the other side - * successfully authenticates itself. So we set up an alarm which is -@@ -2466,6 +2526,48 @@ do_ssh2_kex(void) - - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); - -+#ifdef GSSAPI -+ { -+ char *orig; -+ char *gss = NULL; -+ char *newstr = NULL; -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ /* -+ * If we don't have a host key, then there's no point advertising -+ * the other key exchange algorithms -+ */ -+ -+ if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) -+ orig = NULL; -+ -+ if (options.gss_keyex) -+ gss = ssh_gssapi_server_mechanisms(); -+ else -+ gss = NULL; -+ -+ if (gss && orig) -+ xasprintf(&newstr, "%s,%s", gss, orig); -+ else if (gss) -+ newstr = gss; -+ else if (orig) -+ newstr = orig; -+ -+ /* -+ * If we've got GSSAPI mechanisms, then we've got the 'null' host -+ * key alg, but we can't tell people about it unless its the only -+ * host key algorithm we support -+ */ -+ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; -+ -+ if (newstr) -+ myproposal[PROPOSAL_KEX_ALGS] = newstr; -+ else -+ fatal("No supported key exchange algorithms"); -+ } -+#endif -+ - /* start key exchange */ - kex = kex_setup(myproposal); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; -@@ -2473,6 +2575,13 @@ do_ssh2_kex(void) - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ } -+#endif - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; -diff -up openssh-6.2p1/sshd_config.5.gsskex openssh-6.2p1/sshd_config.5 ---- openssh-6.2p1/sshd_config.5.gsskex 2013-03-27 13:19:11.129624316 +0100 -+++ openssh-6.2p1/sshd_config.5 2013-03-27 13:19:11.150624230 +0100 -@@ -481,12 +481,40 @@ Specifies whether user authentication ba - The default is - .Dq no . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange -+doesn't rely on ssh keys to verify host identity. -+The default is -+.Dq no . -+Note that this option applies to protocol version 2 only. - .It Cm GSSAPICleanupCredentials - Specifies whether to automatically destroy the user's credentials cache - on logout. - The default is - .Dq yes . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIStrictAcceptorCheck -+Determines whether to be strict about the identity of the GSSAPI acceptor -+a client authenticates against. If -+.Dq yes -+then the client must authenticate against the -+.Pa host -+service on the current hostname. If -+.Dq no -+then the client may authenticate against any service key stored in the -+machine's default store. This facility is provided to assist with operation -+on multi homed machines. -+The default is -+.Dq yes . -+Note that this option applies only to protocol version 2 GSSAPI connections, -+and setting it to -+.Dq no -+may only work with recent Kerberos GSSAPI libraries. -+.It Cm GSSAPIStoreCredentialsOnRekey -+Controls whether the user's GSSAPI credentials should be updated following a -+successful connection rekeying. This option can be used to accepted renewed -+or updated credentials from a compatible client. The default is -+.Dq no . - .It Cm HostbasedAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication together - with successful public key client host authentication is allowed -diff -up openssh-6.2p1/sshd_config.gsskex openssh-6.2p1/sshd_config ---- openssh-6.2p1/sshd_config.gsskex 2013-03-27 13:19:11.133624300 +0100 -+++ openssh-6.2p1/sshd_config 2013-03-27 13:19:11.150624230 +0100 -@@ -89,6 +89,8 @@ ChallengeResponseAuthentication no - GSSAPIAuthentication yes - #GSSAPICleanupCredentials yes - GSSAPICleanupCredentials yes -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -diff -up openssh-6.2p1/ssh-gss.h.gsskex openssh-6.2p1/ssh-gss.h ---- openssh-6.2p1/ssh-gss.h.gsskex 2013-02-25 01:24:44.000000000 +0100 -+++ openssh-6.2p1/ssh-gss.h 2013-03-27 13:19:11.150624230 +0100 -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -61,10 +61,22 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -72,8 +84,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -94,10 +110,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -117,16 +134,30 @@ void ssh_gssapi_build_ctx(Gssctxt **); - void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ diff --git a/openssh-6.2p1-keycat.patch b/openssh-6.2p1-keycat.patch deleted file mode 100644 index 41770b3..0000000 --- a/openssh-6.2p1-keycat.patch +++ /dev/null @@ -1,371 +0,0 @@ -diff -up openssh-6.2p1/auth2-pubkey.c.keycat openssh-6.2p1/auth2-pubkey.c ---- openssh-6.2p1/auth2-pubkey.c.keycat 2013-03-25 21:34:17.779978851 +0100 -+++ openssh-6.2p1/auth2-pubkey.c 2013-03-25 21:34:17.798978973 +0100 -@@ -573,6 +573,14 @@ user_key_command_allowed2(struct passwd - _exit(1); - } - -+#ifdef WITH_SELINUX -+ if (ssh_selinux_setup_env_variables() < 0) { -+ error ("failed to copy environment: %s", -+ strerror(errno)); -+ _exit(127); -+ } -+#endif -+ - execl(options.authorized_keys_command, - options.authorized_keys_command, user_pw->pw_name, NULL); - -diff -up openssh-6.2p1/HOWTO.ssh-keycat.keycat openssh-6.2p1/HOWTO.ssh-keycat ---- openssh-6.2p1/HOWTO.ssh-keycat.keycat 2013-03-25 21:34:17.798978973 +0100 -+++ openssh-6.2p1/HOWTO.ssh-keycat 2013-03-25 21:34:17.798978973 +0100 -@@ -0,0 +1,12 @@ -+The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys -+of an user in any environment. This includes environments with -+polyinstantiation of home directories and SELinux MLS policy enabled. -+ -+To use ssh-keycat, set these options in /etc/ssh/sshd_config file: -+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat -+ AuthorizedKeysCommandRunAs root -+ -+Do not forget to enable public key authentication: -+ PubkeyAuthentication yes -+ -+ -diff -up openssh-6.2p1/Makefile.in.keycat openssh-6.2p1/Makefile.in ---- openssh-6.2p1/Makefile.in.keycat 2013-03-25 21:34:17.793978941 +0100 -+++ openssh-6.2p1/Makefile.in 2013-03-25 21:35:48.282559562 +0100 -@@ -27,6 +27,7 @@ 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_KEYCAT=$(libexecdir)/ssh-keycat - SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ -@@ -64,7 +65,7 @@ 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) 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-keycat$(EXEEXT) - - LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ - canohost.o channels.o cipher.o cipher-aes.o \ -@@ -170,6 +171,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) - 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-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o -+ $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) -+ - 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) - -@@ -276,6 +280,7 @@ install-files: - $(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) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -diff -up openssh-6.2p1/openbsd-compat/port-linux.c.keycat openssh-6.2p1/openbsd-compat/port-linux.c ---- openssh-6.2p1/openbsd-compat/port-linux.c.keycat 2013-03-25 21:34:17.785978890 +0100 -+++ openssh-6.2p1/openbsd-compat/port-linux.c 2013-03-25 21:34:17.800978986 +0100 -@@ -315,7 +315,7 @@ ssh_selinux_getctxbyname(char *pwname, - - /* Setup environment variables for pam_selinux */ - static int --ssh_selinux_setup_pam_variables(void) -+ssh_selinux_setup_variables(int(*set_it)(const char *, const char *)) - { - const char *reqlvl; - char *role; -@@ -326,16 +326,16 @@ ssh_selinux_setup_pam_variables(void) - - ssh_selinux_get_role_level(&role, &reqlvl); - -- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); -+ rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); - - if (inetd_flag && !rexeced_flag) { - use_current = "1"; - } else { - use_current = ""; -- rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); -+ rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); - } - -- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); -+ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current); - - if (role != NULL) - xfree(role); -@@ -343,6 +343,24 @@ ssh_selinux_setup_pam_variables(void) - return rv; - } - -+static int -+ssh_selinux_setup_pam_variables(void) -+{ -+ return ssh_selinux_setup_variables(do_pam_putenv); -+} -+ -+static int -+do_setenv(char *name, char *value) -+{ -+ return setenv(name, value, 1); -+} -+ -+int -+ssh_selinux_setup_env_variables(void) -+{ -+ return ssh_selinux_setup_variables(do_setenv); -+} -+ - /* Set the execution context to the default for the specified user */ - void - ssh_selinux_setup_exec_context(char *pwname) -diff -up openssh-6.2p1/ssh-keycat.c.keycat openssh-6.2p1/ssh-keycat.c ---- openssh-6.2p1/ssh-keycat.c.keycat 2013-03-25 21:34:17.800978986 +0100 -+++ openssh-6.2p1/ssh-keycat.c 2013-03-25 21:34:17.800978986 +0100 -@@ -0,0 +1,238 @@ -+/* -+ * 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, and the entire permission notice in its entirety, -+ * including the disclaimer of warranties. -+ * 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. -+ * 3. The name of the author may not be used to endorse or promote -+ * products derived from this software without specific prior -+ * written permission. -+ * -+ * ALTERNATIVELY, this product may be distributed under the terms of -+ * the GNU Public License, in which case the provisions of the GPL are -+ * required INSTEAD OF the above restrictions. (This clause is -+ * necessary due to a potential bad interaction between the GPL and -+ * the restrictions contained in a BSD-style copyright.) -+ * -+ * THIS SOFTWARE IS PROVIDED ``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. -+ */ -+ -+/* -+ * Copyright (c) 2011 Red Hat, Inc. -+ * Written by Tomas Mraz -+*/ -+ -+#define _GNU_SOURCE -+ -+#include "config.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "uidswap.h" -+#include "misc.h" -+ -+#define ERR_USAGE 1 -+#define ERR_PAM_START 2 -+#define ERR_OPEN_SESSION 3 -+#define ERR_CLOSE_SESSION 4 -+#define ERR_PAM_END 5 -+#define ERR_GETPWNAM 6 -+#define ERR_MEMORY 7 -+#define ERR_OPEN 8 -+#define ERR_FILE_MODE 9 -+#define ERR_FDOPEN 10 -+#define ERR_STAT 11 -+#define ERR_WRITE 12 -+#define ERR_PAM_PUTENV 13 -+#define BUFLEN 4096 -+ -+/* Just ignore the messages in the conversation function */ -+static int -+dummy_conv(int num_msg, const struct pam_message **msgm, -+ struct pam_response **response, void *appdata_ptr) -+{ -+ struct pam_response *rsp; -+ -+ (void)msgm; -+ (void)appdata_ptr; -+ -+ if (num_msg <= 0) -+ return PAM_CONV_ERR; -+ -+ /* Just allocate the array as empty responses */ -+ rsp = calloc (num_msg, sizeof (struct pam_response)); -+ if (rsp == NULL) -+ return PAM_CONV_ERR; -+ -+ *response = rsp; -+ return PAM_SUCCESS; -+} -+ -+static struct pam_conv conv = { -+ dummy_conv, -+ NULL -+}; -+ -+char * -+make_auth_keys_name(const struct passwd *pwd) -+{ -+ char *fname; -+ -+ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0) -+ return NULL; -+ -+ return fname; -+} -+ -+int -+dump_keys(const char *user) -+{ -+ struct passwd *pwd; -+ int fd = -1; -+ FILE *f = NULL; -+ char *fname = NULL; -+ int rv = 0; -+ char buf[BUFLEN]; -+ size_t len; -+ struct stat st; -+ -+ if ((pwd = getpwnam(user)) == NULL) { -+ return ERR_GETPWNAM; -+ } -+ -+ if ((fname = make_auth_keys_name(pwd)) == NULL) { -+ return ERR_MEMORY; -+ } -+ -+ temporarily_use_uid(pwd); -+ -+ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) { -+ rv = ERR_OPEN; -+ goto fail; -+ } -+ -+ if (fstat(fd, &st) < 0) { -+ rv = ERR_STAT; -+ goto fail; -+ } -+ -+ if (!S_ISREG(st.st_mode) || -+ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) { -+ rv = ERR_FILE_MODE; -+ goto fail; -+ } -+ -+ unset_nonblock(fd); -+ -+ if ((f = fdopen(fd, "r")) == NULL) { -+ rv = ERR_FDOPEN; -+ goto fail; -+ } -+ -+ fd = -1; -+ -+ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { -+ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0; -+ } -+ -+fail: -+ if (fd != -1) -+ close(fd); -+ if (f != NULL) -+ fclose(f); -+ free(fname); -+ restore_uid(); -+ return rv; -+} -+ -+static const char *env_names[] = { "SELINUX_ROLE_REQUESTED", -+ "SELINUX_LEVEL_REQUESTED", -+ "SELINUX_USE_CURRENT_RANGE" -+}; -+ -+extern char **environ; -+ -+int -+set_pam_environment(pam_handle_t *pamh) -+{ -+ int i; -+ size_t j; -+ -+ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) { -+ int len = strlen(env_names[j]); -+ -+ for (i = 0; environ[i] != NULL; ++i) { -+ if (strncmp(env_names[j], environ[i], len) == 0 && -+ environ[i][len] == '=') { -+ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS) -+ return ERR_PAM_PUTENV; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+int -+main(int argc, char *argv[]) -+{ -+ pam_handle_t *pamh = NULL; -+ int retval; -+ int ev = 0; -+ -+ if (argc != 2) { -+ fprintf(stderr, "Usage: %s \n", argv[0]); -+ return ERR_USAGE; -+ } -+ -+ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh); -+ if (retval != PAM_SUCCESS) { -+ return ERR_PAM_START; -+ } -+ -+ ev = set_pam_environment(pamh); -+ if (ev != 0) -+ goto finish; -+ -+ retval = pam_open_session(pamh, PAM_SILENT); -+ if (retval != PAM_SUCCESS) { -+ ev = ERR_OPEN_SESSION; -+ goto finish; -+ } -+ -+ ev = dump_keys(argv[1]); -+ -+ retval = pam_close_session(pamh, PAM_SILENT); -+ if (retval != PAM_SUCCESS) { -+ ev = ERR_CLOSE_SESSION; -+ } -+ -+finish: -+ retval = pam_end (pamh,retval); -+ if (retval != PAM_SUCCESS) { -+ ev = ERR_PAM_END; -+ } -+ return ev; -+} diff --git a/openssh-6.2p1-kuserok.patch b/openssh-6.2p1-kuserok.patch deleted file mode 100644 index 641ad03..0000000 --- a/openssh-6.2p1-kuserok.patch +++ /dev/null @@ -1,167 +0,0 @@ -diff -up openssh-6.2p1/auth-krb5.c.kuserok openssh-6.2p1/auth-krb5.c ---- openssh-6.2p1/auth-krb5.c.kuserok 2013-03-25 20:06:51.295558062 +0100 -+++ openssh-6.2p1/auth-krb5.c 2013-03-25 20:06:51.318558207 +0100 -@@ -55,6 +55,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) - { -@@ -147,7 +161,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-6.2p1/gss-serv-krb5.c.kuserok openssh-6.2p1/gss-serv-krb5.c ---- openssh-6.2p1/gss-serv-krb5.c.kuserok 2013-03-25 20:06:51.311558163 +0100 -+++ openssh-6.2p1/gss-serv-krb5.c 2013-03-25 20:06:51.319558214 +0100 -@@ -68,6 +68,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr - int); - - 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 */ - -@@ -115,7 +116,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client - /* NOTE: .k5login and .k5users must opened as root, not the user, - * because if they are on a krb5-protected filesystem, user credentials - * to access these files aren't available yet. */ -- if (krb5_kuserok(krb_context, princ, luser) && k5login_exists) { -+ if (ssh_krb5_kuserok(krb_context, princ, luser) && k5login_exists) { - retval = 1; - logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", - luser, (char *)client->displayname.value); -diff -up openssh-6.2p1/servconf.c.kuserok openssh-6.2p1/servconf.c ---- openssh-6.2p1/servconf.c.kuserok 2013-03-25 20:06:51.305558125 +0100 -+++ openssh-6.2p1/servconf.c 2013-03-25 20:06:51.319558214 +0100 -@@ -150,6 +150,7 @@ initialize_server_options(ServerOptions - options->ip_qos_interactive = -1; - options->ip_qos_bulk = -1; - options->version_addendum = NULL; -+ options->use_kuserok = -1; - } - - void -@@ -299,6 +300,8 @@ fill_default_server_options(ServerOption - options->version_addendum = xstrdup(""); - if (options->show_patchlevel == -1) - options->show_patchlevel = 0; -+ if (options->use_kuserok == -1) -+ options->use_kuserok = 1; - - /* Turn privilege separation on by default */ - if (use_privsep == -1) -@@ -325,7 +328,7 @@ typedef enum { - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, -+ sKerberosGetAFSToken, sKerberosUseKuserok, - sKerberosTgtPassing, sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, -@@ -397,11 +400,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 }, -@@ -1460,6 +1465,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') -@@ -1761,6 +1770,7 @@ copy_set_server_options(ServerOptions *d - M_CP_INTOPT(max_authtries); - M_CP_INTOPT(ip_qos_interactive); - M_CP_INTOPT(ip_qos_bulk); -+ M_CP_INTOPT(use_kuserok); - - /* See comment in servconf.h */ - COPY_MATCH_STRING_OPTS(); -@@ -1999,6 +2009,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-6.2p1/servconf.h.kuserok openssh-6.2p1/servconf.h ---- openssh-6.2p1/servconf.h.kuserok 2013-03-25 20:06:51.305558125 +0100 -+++ openssh-6.2p1/servconf.h 2013-03-25 20:06:51.320558220 +0100 -@@ -173,6 +173,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-6.2p1/sshd_config.kuserok openssh-6.2p1/sshd_config ---- openssh-6.2p1/sshd_config.kuserok 2013-03-25 20:06:51.308558144 +0100 -+++ openssh-6.2p1/sshd_config 2013-03-25 20:06:51.320558220 +0100 -@@ -83,6 +83,7 @@ ChallengeResponseAuthentication no - #KerberosOrLocalPasswd yes - #KerberosTicketCleanup yes - #KerberosGetAFSToken no -+#KerberosUseKuserok yes - - # GSSAPI options - #GSSAPIAuthentication no -diff -up openssh-6.2p1/sshd_config.5.kuserok openssh-6.2p1/sshd_config.5 ---- openssh-6.2p1/sshd_config.5.kuserok 2013-03-25 20:06:51.308558144 +0100 -+++ openssh-6.2p1/sshd_config.5 2013-03-25 20:08:34.249207272 +0100 -@@ -660,6 +660,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. -@@ -819,6 +823,7 @@ Available keywords are - .Cm HostbasedUsesNameFromPacketOnly , - .Cm KbdInteractiveAuthentication , - .Cm KerberosAuthentication , -+.Cm KerberosUseKuserok , - .Cm MaxAuthTries , - .Cm MaxSessions , - .Cm PasswordAuthentication , diff --git a/openssh-6.2p1-ldap.patch b/openssh-6.2p1-ldap.patch deleted file mode 100644 index 8d717c5..0000000 --- a/openssh-6.2p1-ldap.patch +++ /dev/null @@ -1,2609 +0,0 @@ -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); -+ xfree (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)); -+ xfree (buffer); -+ return; -+ } -+ -+ /* free */ -+ xfree (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-6.2p1-modpipe-cflags.patch b/openssh-6.2p1-modpipe-cflags.patch deleted file mode 100644 index abcf47a..0000000 --- a/openssh-6.2p1-modpipe-cflags.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-6.2p1/Makefile.in.modpipe-pie openssh-6.2p1/Makefile.in ---- openssh-6.2p1/Makefile.in.modpipe-pie 2013-04-04 14:44:26.293745777 +0200 -+++ openssh-6.2p1/Makefile.in 2013-04-04 14:44:49.483647020 +0200 -@@ -418,7 +418,7 @@ uninstall: - - regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c - [ -d `pwd`/regress ] || mkdir -p `pwd`/regress; \ -- $(CC) $(CPPFLAGS) -o $@ $? \ -+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $? \ - $(LDFLAGS) -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) - - tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) diff --git a/openssh-6.2p1-role-mls.patch b/openssh-6.2p1-role-mls.patch deleted file mode 100644 index 3635fef..0000000 --- a/openssh-6.2p1-role-mls.patch +++ /dev/null @@ -1,934 +0,0 @@ -diff -up openssh-6.2p1/auth.h.role-mls openssh-6.2p1/auth.h ---- openssh-6.2p1/auth.h.role-mls 2013-03-25 17:47:00.565746862 +0100 -+++ openssh-6.2p1/auth.h 2013-03-25 17:47:00.602747073 +0100 -@@ -59,6 +59,9 @@ struct Authctxt { - char *service; - struct passwd *pw; /* set if 'valid' */ - char *style; -+#ifdef WITH_SELINUX -+ char *role; -+#endif - void *kbdintctxt; - void *jpake_ctx; - #ifdef BSD_AUTH -diff -up openssh-6.2p1/auth-pam.c.role-mls openssh-6.2p1/auth-pam.c ---- openssh-6.2p1/auth-pam.c.role-mls 2013-03-25 17:47:00.535746690 +0100 -+++ openssh-6.2p1/auth-pam.c 2013-03-25 17:47:00.602747073 +0100 -@@ -1074,7 +1074,7 @@ is_pam_session_open(void) - * during the ssh authentication process. - */ - int --do_pam_putenv(char *name, char *value) -+do_pam_putenv(char *name, const char *value) - { - int ret = 1; - #ifdef HAVE_PAM_PUTENV -diff -up openssh-6.2p1/auth-pam.h.role-mls openssh-6.2p1/auth-pam.h ---- openssh-6.2p1/auth-pam.h.role-mls 2004-09-11 14:17:26.000000000 +0200 -+++ openssh-6.2p1/auth-pam.h 2013-03-25 17:47:00.602747073 +0100 -@@ -38,7 +38,7 @@ void do_pam_session(void); - void do_pam_set_tty(const char *); - void do_pam_setcred(int ); - void do_pam_chauthtok(void); --int do_pam_putenv(char *, char *); -+int do_pam_putenv(char *, const char *); - char ** fetch_pam_environment(void); - char ** fetch_pam_child_environment(void); - void free_pam_environment(char **); -diff -up openssh-6.2p1/auth1.c.role-mls openssh-6.2p1/auth1.c ---- openssh-6.2p1/auth1.c.role-mls 2012-12-02 23:53:20.000000000 +0100 -+++ openssh-6.2p1/auth1.c 2013-03-25 17:47:00.600747062 +0100 -@@ -386,6 +386,9 @@ do_authentication(Authctxt *authctxt) - { - u_int ulen; - char *user, *style = NULL; -+#ifdef WITH_SELINUX -+ char *role=NULL; -+#endif - - /* Get the name of the user that we wish to log in as. */ - packet_read_expect(SSH_CMSG_USER); -@@ -394,11 +397,24 @@ do_authentication(Authctxt *authctxt) - user = packet_get_cstring(&ulen); - packet_check_eom(); - -+#ifdef WITH_SELINUX -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = '\0'; -+#endif -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = '\0'; -+#ifdef WITH_SELINUX -+ else -+ if (role && (style = strchr(role, ':')) != NULL) -+ *style++ = '\0'; -+#endif - - authctxt->user = user; - authctxt->style = style; -+#ifdef WITH_SELINUX -+ authctxt->role = role; -+#endif - - /* Verify that the user is a valid user. */ - if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) -diff -up openssh-6.2p1/auth2.c.role-mls openssh-6.2p1/auth2.c ---- openssh-6.2p1/auth2.c.role-mls 2013-03-25 17:47:00.556746810 +0100 -+++ openssh-6.2p1/auth2.c 2013-03-25 17:47:00.600747062 +0100 -@@ -218,6 +218,9 @@ input_userauth_request(int type, u_int32 - Authctxt *authctxt = ctxt; - Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; -+#ifdef WITH_SELINUX -+ char *role = NULL; -+#endif - int authenticated = 0; - - if (authctxt == NULL) -@@ -229,6 +232,11 @@ input_userauth_request(int type, u_int32 - debug("userauth-request for user %s service %s method %s", user, service, method); - debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); - -+#ifdef WITH_SELINUX -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = 0; -+#endif -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = 0; - -@@ -251,8 +259,15 @@ input_userauth_request(int type, u_int32 - use_privsep ? " [net]" : ""); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; -- if (use_privsep) -+#ifdef WITH_SELINUX -+ authctxt->role = role ? xstrdup(role) : NULL; -+#endif -+ if (use_privsep) { - mm_inform_authserv(service, style); -+#ifdef WITH_SELINUX -+ mm_inform_authrole(role); -+#endif -+ } - userauth_banner(); - if (auth2_setup_methods_lists(authctxt) != 0) - packet_disconnect("no authentication methods enabled"); -diff -up openssh-6.2p1/auth2-gss.c.role-mls openssh-6.2p1/auth2-gss.c ---- openssh-6.2p1/auth2-gss.c.role-mls 2012-12-02 23:53:20.000000000 +0100 -+++ openssh-6.2p1/auth2-gss.c 2013-03-25 17:47:00.601747067 +0100 -@@ -260,6 +260,7 @@ input_gssapi_mic(int type, u_int32_t ple - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - int authenticated = 0; -+ char *micuser; - Buffer b; - gss_buffer_desc mic, gssbuf; - u_int len; -@@ -272,7 +273,13 @@ input_gssapi_mic(int type, u_int32_t ple - mic.value = packet_get_string(&len); - mic.length = len; - -- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, -+#ifdef WITH_SELINUX -+ if (authctxt->role && (strlen(authctxt->role) > 0)) -+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); -+ else -+#endif -+ micuser = authctxt->user; -+ ssh_gssapi_buildmic(&b, micuser, authctxt->service, - "gssapi-with-mic"); - - gssbuf.value = buffer_ptr(&b); -@@ -284,6 +291,8 @@ input_gssapi_mic(int type, u_int32_t ple - logit("GSSAPI MIC check failed"); - - buffer_free(&b); -+ if (micuser != authctxt->user) -+ xfree(micuser); - xfree(mic.value); - - authctxt->postponed = 0; -diff -up openssh-6.2p1/auth2-hostbased.c.role-mls openssh-6.2p1/auth2-hostbased.c ---- openssh-6.2p1/auth2-hostbased.c.role-mls 2013-03-25 17:47:00.565746862 +0100 -+++ openssh-6.2p1/auth2-hostbased.c 2013-03-25 17:47:00.601747067 +0100 -@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt) - buffer_put_string(&b, session_id2, session_id2_len); - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); -- buffer_put_cstring(&b, authctxt->user); -+#ifdef WITH_SELINUX -+ if (authctxt->role) { -+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); -+ buffer_append(&b, authctxt->user, strlen(authctxt->user)); -+ buffer_put_char(&b, '/'); -+ buffer_append(&b, authctxt->role, strlen(authctxt->role)); -+ } else -+#endif -+ buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); -diff -up openssh-6.2p1/auth2-pubkey.c.role-mls openssh-6.2p1/auth2-pubkey.c ---- openssh-6.2p1/auth2-pubkey.c.role-mls 2013-03-25 17:47:00.565746862 +0100 -+++ openssh-6.2p1/auth2-pubkey.c 2013-03-25 17:47:00.601747067 +0100 -@@ -127,7 +127,15 @@ userauth_pubkey(Authctxt *authctxt) - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); -- buffer_put_cstring(&b, authctxt->user); -+#ifdef WITH_SELINUX -+ if (authctxt->role) { -+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); -+ buffer_append(&b, authctxt->user, strlen(authctxt->user)); -+ buffer_put_char(&b, '/'); -+ buffer_append(&b, authctxt->role, strlen(authctxt->role)); -+ } else -+#endif -+ buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : -diff -up openssh-6.2p1/misc.c.role-mls openssh-6.2p1/misc.c ---- openssh-6.2p1/misc.c.role-mls 2011-09-22 13:34:36.000000000 +0200 -+++ openssh-6.2p1/misc.c 2013-03-25 17:47:00.603747079 +0100 -@@ -427,6 +427,7 @@ char * - colon(char *cp) - { - int flag = 0; -+ int start = 1; - - if (*cp == ':') /* Leading colon is part of file name. */ - return NULL; -@@ -442,6 +443,13 @@ colon(char *cp) - return (cp); - if (*cp == '/') - return NULL; -+ if (start) { -+ /* Slash on beginning or after dots only denotes file name. */ -+ if (*cp == '/') -+ return (0); -+ if (*cp != '.') -+ start = 0; -+ } - } - return NULL; - } -diff -up openssh-6.2p1/monitor.c.role-mls openssh-6.2p1/monitor.c ---- openssh-6.2p1/monitor.c.role-mls 2013-03-25 17:47:00.587746987 +0100 -+++ openssh-6.2p1/monitor.c 2013-03-25 17:47:00.604747085 +0100 -@@ -148,6 +148,9 @@ int mm_answer_sign(int, Buffer *); - int mm_answer_pwnamallow(int, Buffer *); - int mm_answer_auth2_read_banner(int, Buffer *); - int mm_answer_authserv(int, Buffer *); -+#ifdef WITH_SELINUX -+int mm_answer_authrole(int, Buffer *); -+#endif - int mm_answer_authpassword(int, Buffer *); - int mm_answer_bsdauthquery(int, Buffer *); - int mm_answer_bsdauthrespond(int, Buffer *); -@@ -232,6 +235,9 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, -+#ifdef WITH_SELINUX -+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, -+#endif - {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - #ifdef USE_PAM -@@ -846,6 +852,9 @@ mm_answer_pwnamallow(int sock, Buffer *m - else { - /* Allow service/style information on the auth context */ - monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); -+#ifdef WITH_SELINUX -+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); -+#endif - monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); - } - #ifdef USE_PAM -@@ -889,6 +898,25 @@ mm_answer_authserv(int sock, Buffer *m) - return (0); - } - -+#ifdef WITH_SELINUX -+int -+mm_answer_authrole(int sock, Buffer *m) -+{ -+ monitor_permit_authentications(1); -+ -+ authctxt->role = buffer_get_string(m, NULL); -+ debug3("%s: role=%s", -+ __func__, authctxt->role); -+ -+ if (strlen(authctxt->role) == 0) { -+ xfree(authctxt->role); -+ authctxt->role = NULL; -+ } -+ -+ return (0); -+} -+#endif -+ - int - mm_answer_authpassword(int sock, Buffer *m) - { -@@ -1262,7 +1290,7 @@ static int - monitor_valid_userblob(u_char *data, u_int datalen) - { - Buffer b; -- char *p; -+ char *p, *r; - u_int len; - int fail = 0; - -@@ -1288,6 +1316,8 @@ monitor_valid_userblob(u_char *data, u_i - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); -+ if ((r = strchr(p, '/')) != NULL) -+ *r = '\0'; - if (strcmp(authctxt->user, p) != 0) { - logit("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); -@@ -1319,7 +1349,7 @@ monitor_valid_hostbasedblob(u_char *data - char *chost) - { - Buffer b; -- char *p; -+ char *p, *r; - u_int len; - int fail = 0; - -@@ -1336,6 +1366,8 @@ monitor_valid_hostbasedblob(u_char *data - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); -+ if ((r = strchr(p, '/')) != NULL) -+ *r = '\0'; - if (strcmp(authctxt->user, p) != 0) { - logit("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); -diff -up openssh-6.2p1/monitor.h.role-mls openssh-6.2p1/monitor.h ---- openssh-6.2p1/monitor.h.role-mls 2013-03-25 17:47:00.605747090 +0100 -+++ openssh-6.2p1/monitor.h 2013-03-25 17:50:00.824775483 +0100 -@@ -61,6 +61,9 @@ enum monitor_reqtype { - MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57, - MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59, - MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61, -+#ifdef WITH_SELINUX -+ MONITOR_REQ_AUTHROLE = 80, -+#endif - - MONITOR_REQ_PAM_START = 100, - MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, -diff -up openssh-6.2p1/monitor_wrap.c.role-mls openssh-6.2p1/monitor_wrap.c ---- openssh-6.2p1/monitor_wrap.c.role-mls 2013-03-25 17:47:00.588746993 +0100 -+++ openssh-6.2p1/monitor_wrap.c 2013-03-25 17:47:00.605747090 +0100 -@@ -336,6 +336,25 @@ mm_inform_authserv(char *service, char * - buffer_free(&m); - } - -+/* Inform the privileged process about role */ -+ -+#ifdef WITH_SELINUX -+void -+mm_inform_authrole(char *role) -+{ -+ Buffer m; -+ -+ debug3("%s entering", __func__); -+ -+ buffer_init(&m); -+ buffer_put_cstring(&m, role ? role : ""); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); -+ -+ buffer_free(&m); -+} -+#endif -+ - /* Do the password authentication */ - int - mm_auth_password(Authctxt *authctxt, char *password) -diff -up openssh-6.2p1/monitor_wrap.h.role-mls openssh-6.2p1/monitor_wrap.h ---- openssh-6.2p1/monitor_wrap.h.role-mls 2013-03-25 17:47:00.588746993 +0100 -+++ openssh-6.2p1/monitor_wrap.h 2013-03-25 17:47:00.605747090 +0100 -@@ -42,6 +42,9 @@ int mm_is_monitor(void); - DH *mm_choose_dh(int, int, int); - int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); - void mm_inform_authserv(char *, char *); -+#ifdef WITH_SELINUX -+void mm_inform_authrole(char *); -+#endif - struct passwd *mm_getpwnamallow(const char *); - char *mm_auth2_read_banner(void); - int mm_auth_password(struct Authctxt *, char *); -diff -up openssh-6.2p1/openbsd-compat/Makefile.in.role-mls openssh-6.2p1/openbsd-compat/Makefile.in ---- openssh-6.2p1/openbsd-compat/Makefile.in.role-mls 2013-03-25 17:47:00.606747096 +0100 -+++ openssh-6.2p1/openbsd-compat/Makefile.in 2013-03-25 17:50:36.024979473 +0100 -@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport - - COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o - --PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o -+PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o - - .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -diff -up openssh-6.2p1/openbsd-compat/port-linux.c.role-mls openssh-6.2p1/openbsd-compat/port-linux.c ---- openssh-6.2p1/openbsd-compat/port-linux.c.role-mls 2012-03-09 00:25:18.000000000 +0100 -+++ openssh-6.2p1/openbsd-compat/port-linux.c 2013-03-25 17:47:00.606747096 +0100 -@@ -31,68 +31,271 @@ - - #include "log.h" - #include "xmalloc.h" -+#include "servconf.h" - #include "port-linux.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" - - #ifdef WITH_SELINUX - #include - #include -+#include - #include -+#include -+#include -+ -+#ifdef HAVE_LINUX_AUDIT -+#include -+#include -+#endif - - #ifndef SSH_SELINUX_UNCONFINED_TYPE - # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:" - #endif - --/* Wrapper around is_selinux_enabled() to log its return value once only */ --int --ssh_selinux_enabled(void) -+extern ServerOptions options; -+extern Authctxt *the_authctxt; -+extern int inetd_flag; -+extern int rexeced_flag; -+ -+/* Send audit message */ -+static int -+send_audit_message(int success, security_context_t default_context, -+ security_context_t selected_context) -+{ -+ int rc=0; -+#ifdef HAVE_LINUX_AUDIT -+ char *msg = NULL; -+ int audit_fd = audit_open(); -+ security_context_t default_raw=NULL; -+ security_context_t selected_raw=NULL; -+ rc = -1; -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 0; /* No audit support in kernel */ -+ error("Error connecting to audit system."); -+ return rc; -+ } -+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { -+ error("Error translating default context."); -+ default_raw = NULL; -+ } -+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { -+ error("Error translating selected context."); -+ selected_raw = NULL; -+ } -+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", -+ default_raw ? default_raw : (default_context ? default_context: "?"), -+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { -+ error("Error allocating memory."); -+ goto out; -+ } -+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, -+ msg, NULL, NULL, NULL, success) <= 0) { -+ error("Error sending audit message."); -+ goto out; -+ } -+ rc = 0; -+ out: -+ free(msg); -+ freecon(default_raw); -+ freecon(selected_raw); -+ close(audit_fd); -+#endif -+ return rc; -+} -+ -+static int -+mls_range_allowed(security_context_t src, security_context_t dst) - { -- static int enabled = -1; -+ struct av_decision avd; -+ int retval; -+ unsigned int bit = CONTEXT__CONTAINS; -+ -+ debug("%s: src:%s dst:%s", __func__, src, dst); -+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); -+ if (retval || ((bit & avd.allowed) != bit)) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+get_user_context(const char *sename, const char *role, const char *lvl, -+ security_context_t *sc) { -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { -+ /* User may have requested a level completely outside of his -+ allowed range. We get a context just for auditing as the -+ range check below will certainly fail for default context. */ -+#endif -+ if (get_default_context(sename, NULL, sc) != 0) { -+ *sc = NULL; -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ } -+#endif -+ if (role != NULL && role[0]) { -+ context_t con; -+ char *type=NULL; -+ if (get_default_type(role, &type) != 0) { -+ error("get_default_type: failed to get default type for '%s'", -+ role); -+ goto out; -+ } -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_role_set(con, role); -+ context_type_set(con, type); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ if (!*sc) -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl != NULL && lvl[0]) { -+ /* verify that the requested range is obtained */ -+ context_t con; -+ security_context_t obtained_raw; -+ security_context_t requested_raw; -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_range_set(con, lvl); -+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { -+ context_free(con); -+ goto out; -+ } -+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { -+ freecon(obtained_raw); -+ context_free(con); -+ goto out; -+ } - -- if (enabled == -1) { -- enabled = (is_selinux_enabled() == 1); -- debug("SELinux support %s", enabled ? "enabled" : "disabled"); -+ debug("get_user_context: obtained context '%s' requested context '%s'", -+ obtained_raw, requested_raw); -+ if (strcmp(obtained_raw, requested_raw)) { -+ /* set the context to the real requested one but fail */ -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ return -1; -+ } -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ context_free(con); - } -+#endif -+ return 0; -+ out: -+ freecon(*sc); -+ *sc = NULL; -+ return -1; -+} - -- return (enabled); -+static void -+ssh_selinux_get_role_level(char **role, const char **level) -+{ -+ *role = NULL; -+ *level = NULL; -+ if (the_authctxt) { -+ if (the_authctxt->role != NULL) { -+ char *slash; -+ *role = xstrdup(the_authctxt->role); -+ if ((slash = strchr(*role, '/')) != NULL) { -+ *slash = '\0'; -+ *level = slash + 1; -+ } -+ } -+ } - } - - /* Return the default security context for the given username */ - static security_context_t --ssh_selinux_getctxbyname(char *pwname) -+ssh_selinux_getctxbyname(char *pwname, -+ security_context_t *default_sc, security_context_t *user_sc) - { -- security_context_t sc = NULL; -- char *sename = NULL, *lvl = NULL; -- int r; -+ char *sename, *lvl; -+ char *role; -+ const char *reqlvl; -+ int r = 0; -+ context_t con = NULL; -+ -+ ssh_selinux_get_role_level(&role, &reqlvl); - - #ifdef HAVE_GETSEUSERBYNAME -- if (getseuserbyname(pwname, &sename, &lvl) != 0) -- return NULL; -+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -+ sename = NULL; -+ lvl = NULL; -+ } - #else - sename = pwname; -- lvl = NULL; -+ lvl = ""; - #endif - -+ if (r == 0) { - #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -- r = get_default_context_with_level(sename, lvl, NULL, &sc); -+ r = get_default_context_with_level(sename, lvl, NULL, default_sc); - #else -- r = get_default_context(sename, NULL, &sc); -+ r = get_default_context(sename, NULL, default_sc); - #endif -+ } -+ -+ if (r == 0) { -+ /* If launched from xinetd, we must use current level */ -+ if (inetd_flag && !rexeced_flag) { -+ security_context_t sshdsc=NULL; -+ -+ if (getcon_raw(&sshdsc) < 0) -+ fatal("failed to allocate security context"); -+ -+ if ((con=context_new(sshdsc)) == NULL) -+ fatal("failed to allocate selinux context"); -+ reqlvl = context_range_get(con); -+ freecon(sshdsc); -+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) -+ /* we actually don't change level */ -+ reqlvl = ""; -+ -+ debug("%s: current connection level '%s'", __func__, reqlvl); - -- if (r != 0) { -- switch (security_getenforce()) { -- case -1: -- fatal("%s: ssh_selinux_getctxbyname: " -- "security_getenforce() failed", __func__); -- case 0: -- error("%s: Failed to get default SELinux security " -- "context for %s", __func__, pwname); -- sc = NULL; -- break; -- default: -- fatal("%s: Failed to get default SELinux security " -- "context for %s (in enforcing mode)", -- __func__, pwname); - } -+ -+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { -+ r = get_user_context(sename, role, reqlvl, user_sc); -+ -+ if (r == 0 && reqlvl != NULL && reqlvl[0]) { -+ security_context_t default_level_sc = *default_sc; -+ if (role != NULL && role[0]) { -+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) -+ default_level_sc = *default_sc; -+ } -+ /* verify that the requested range is contained in the user range */ -+ if (mls_range_allowed(default_level_sc, *user_sc)) { -+ logit("permit MLS level %s (user range %s)", reqlvl, lvl); -+ } else { -+ r = -1; -+ error("deny MLS level %s (user range %s)", reqlvl, lvl); -+ } -+ if (default_level_sc != *default_sc) -+ freecon(default_level_sc); -+ } -+ } else { -+ *user_sc = *default_sc; -+ } -+ } -+ if (r != 0) { -+ error("%s: Failed to get default SELinux security " -+ "context for %s", __func__, pwname); - } - - #ifdef HAVE_GETSEUSERBYNAME -@@ -102,7 +305,42 @@ ssh_selinux_getctxbyname(char *pwname) - xfree(lvl); - #endif - -- return sc; -+ if (role != NULL) -+ xfree(role); -+ if (con) -+ context_free(con); -+ -+ return (r); -+} -+ -+/* Setup environment variables for pam_selinux */ -+static int -+ssh_selinux_setup_pam_variables(void) -+{ -+ const char *reqlvl; -+ char *role; -+ char *use_current; -+ int rv; -+ -+ debug3("%s: setting execution context", __func__); -+ -+ ssh_selinux_get_role_level(&role, &reqlvl); -+ -+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); -+ -+ if (inetd_flag && !rexeced_flag) { -+ use_current = "1"; -+ } else { -+ use_current = ""; -+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); -+ } -+ -+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); -+ -+ if (role != NULL) -+ xfree(role); -+ -+ return rv; - } - - /* Set the execution context to the default for the specified user */ -@@ -110,28 +348,71 @@ void - ssh_selinux_setup_exec_context(char *pwname) - { - security_context_t user_ctx = NULL; -+ int r = 0; -+ security_context_t default_ctx = NULL; - - if (!ssh_selinux_enabled()) - return; - -+ if (options.use_pam) { -+ /* do not compute context, just setup environment for pam_selinux */ -+ if (ssh_selinux_setup_pam_variables()) { -+ switch (security_getenforce()) { -+ case -1: -+ fatal("%s: security_getenforce() failed", __func__); -+ case 0: -+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", -+ __func__); -+ break; -+ default: -+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", -+ __func__); -+ } -+ } -+ return; -+ } -+ - debug3("%s: setting execution context", __func__); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -- if (setexeccon(user_ctx) != 0) { -+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); -+ if (r >= 0) { -+ r = setexeccon(user_ctx); -+ if (r < 0) { -+ error("%s: Failed to set SELinux execution context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+#ifdef HAVE_SETKEYCREATECON -+ else if (setkeycreatecon(user_ctx) < 0) { -+ error("%s: Failed to set SELinux keyring creation context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+#endif -+ } -+ if (user_ctx == NULL) { -+ user_ctx = default_ctx; -+ } -+ if (r < 0 || user_ctx != default_ctx) { -+ /* audit just the case when user changed a role or there was -+ a failure */ -+ send_audit_message(r >= 0, default_ctx, user_ctx); -+ } -+ if (r < 0) { - switch (security_getenforce()) { - case -1: - fatal("%s: security_getenforce() failed", __func__); - case 0: -- error("%s: Failed to set SELinux execution " -- "context for %s", __func__, pwname); -+ error("%s: SELinux failure. Continuing in permissive mode.", -+ __func__); - break; - default: -- fatal("%s: Failed to set SELinux execution context " -- "for %s (in enforcing mode)", __func__, pwname); -+ fatal("%s: SELinux failure. Aborting connection.", -+ __func__); - } - } -- if (user_ctx != NULL) -+ if (user_ctx != NULL && user_ctx != default_ctx) - freecon(user_ctx); -+ if (default_ctx != NULL) -+ freecon(default_ctx); - - debug3("%s: done", __func__); - } -@@ -149,7 +430,10 @@ ssh_selinux_setup_pty(char *pwname, cons - - debug3("%s: setting TTY context on %s", __func__, tty); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -+ if (getexeccon(&user_ctx) < 0) { -+ error("%s: getexeccon: %s", __func__, strerror(errno)); -+ goto out; -+ } - - /* XXX: should these calls fatal() upon failure in enforcing mode? */ - -@@ -221,21 +505,6 @@ ssh_selinux_change_context(const char *n - xfree(newctx); - } - --void --ssh_selinux_setfscreatecon(const char *path) --{ -- security_context_t context; -- -- if (!ssh_selinux_enabled()) -- return; -- if (path == NULL) { -- setfscreatecon(NULL); -- return; -- } -- if (matchpathcon(path, 0700, &context) == 0) -- setfscreatecon(context); --} -- - #endif /* WITH_SELINUX */ - - #ifdef LINUX_OOM_ADJUST -diff -up openssh-6.2p1/openbsd-compat/port-linux_part_2.c.role-mls openssh-6.2p1/openbsd-compat/port-linux_part_2.c ---- openssh-6.2p1/openbsd-compat/port-linux_part_2.c.role-mls 2013-03-25 17:47:00.607747102 +0100 -+++ openssh-6.2p1/openbsd-compat/port-linux_part_2.c 2013-03-25 17:47:00.607747102 +0100 -@@ -0,0 +1,75 @@ -+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */ -+ -+/* -+ * Copyright (c) 2005 Daniel Walsh -+ * Copyright (c) 2006 Damien Miller -+ * -+ * 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. -+ */ -+ -+/* -+ * Linux-specific portability code - just SELinux support at present -+ */ -+ -+#include "includes.h" -+ -+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) -+#include -+#include -+#include -+#include -+ -+#include "log.h" -+#include "xmalloc.h" -+#include "port-linux.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" -+ -+#ifdef WITH_SELINUX -+#include -+#include -+#include -+ -+/* Wrapper around is_selinux_enabled() to log its return value once only */ -+int -+ssh_selinux_enabled(void) -+{ -+ static int enabled = -1; -+ -+ if (enabled == -1) { -+ enabled = (is_selinux_enabled() == 1); -+ debug("SELinux support %s", enabled ? "enabled" : "disabled"); -+ } -+ -+ return (enabled); -+} -+ -+void -+ssh_selinux_setfscreatecon(const char *path) -+{ -+ security_context_t context; -+ -+ if (!ssh_selinux_enabled()) -+ return; -+ if (path == NULL) { -+ setfscreatecon(NULL); -+ return; -+ } -+ if (matchpathcon(path, 0700, &context) == 0) -+ setfscreatecon(context); -+} -+ -+#endif /* WITH_SELINUX */ -+ -+#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ -diff -up openssh-6.2p1/sshd.c.role-mls openssh-6.2p1/sshd.c ---- openssh-6.2p1/sshd.c.role-mls 2013-03-25 17:47:00.589746999 +0100 -+++ openssh-6.2p1/sshd.c 2013-03-25 17:47:00.607747102 +0100 -@@ -2118,6 +2118,9 @@ main(int ac, char **av) - restore_uid(); - } - #endif -+#ifdef WITH_SELINUX -+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); -+#endif - #ifdef USE_PAM - if (options.use_pam) { - do_pam_setcred(1); diff --git a/openssh-6.2p2-sftp-multibyte.patch b/openssh-6.2p2-sftp-multibyte.patch deleted file mode 100644 index 2f9b423..0000000 --- a/openssh-6.2p2-sftp-multibyte.patch +++ /dev/null @@ -1,64 +0,0 @@ -diff --git a/ChangeLog b/ChangeLog -index f5e2df0..74a03f8 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,3 +1,11 @@ -+20130605 -+ - dtucker@cvs.openbsd.org 2013/06/04 20:42:36 -+ [sftp.c] -+ Make sftp's libedit interface marginally multibyte aware by building up -+ the quoted string by character instead of by byte. Prevents failures -+ when linked against a libedit built with wide character support (bz#1990). -+ "looks ok" djm -+ - 20130516 - - (djm) [contrib/ssh-copy-id] Fix bug that could cause "rm *" to be - executed if mktemp failed; bz#2105 ok dtucker@ -diff --git a/sftp.c b/sftp.c -index 25c35fa..c9a9919 100644 ---- a/sftp.c -+++ b/sftp.c -@@ -38,6 +38,7 @@ - #ifdef HAVE_LIBGEN_H - #include - #endif -+#include - #ifdef USE_LIBEDIT - #include - #else -@@ -1694,8 +1695,9 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, - char *file, int remote, int lastarg, char quote, int terminated) - { - glob_t g; -- char *tmp, *tmp2, ins[3]; -+ char *tmp, *tmp2, ins[8]; - u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs; -+ int clen; - const LineInfo *lf; - - /* Glob from "file" location */ -@@ -1764,10 +1766,13 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, - tmp2 = tmp + filelen - cesc; - len = strlen(tmp2); - /* quote argument on way out */ -- for (i = 0; i < len; i++) { -+ for (i = 0; i < len; i += clen) { -+ if ((clen = mblen(tmp2 + i, len - i)) < 0 || -+ (size_t)clen > sizeof(ins) - 2) -+ fatal("invalid multibyte character"); - ins[0] = '\\'; -- ins[1] = tmp2[i]; -- ins[2] = '\0'; -+ memcpy(ins + 1, tmp2 + i, clen); -+ ins[clen + 1] = '\0'; - switch (tmp2[i]) { - case '\'': - case '"': -@@ -2112,6 +2117,7 @@ main(int argc, char **argv) - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); -+ setlocale(LC_CTYPE, ""); - - __progname = ssh_get_progname(argv[0]); - memset(&args, '\0', sizeof(args)); diff --git a/openssh-6.2p2-ssh_gai_strerror.patch b/openssh-6.2p2-ssh_gai_strerror.patch deleted file mode 100644 index 0e433fa..0000000 --- a/openssh-6.2p2-ssh_gai_strerror.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -U0 openssh-6.2p2/ChangeLog.ssh_gai_strerror openssh-6.2p2/ChangeLog ---- openssh-6.2p2/ChangeLog.ssh_gai_strerror 2013-07-23 12:03:41.467902339 +0200 -+++ openssh-6.2p2/ChangeLog 2013-07-23 12:06:03.414281151 +0200 -@@ -0,0 +1,7 @@ -+20130718 -+ - djm@cvs.openbsd.org 2013/07/12 00:43:50 -+ [misc.c] -+ in ssh_gai_strerror() don't fallback to strerror for EAI_SYSTEM when -+ errno == 0. Avoids confusing error message in some broken resolver -+ cases. bz#2122 patch from plautrba AT redhat.com; ok dtucker -+ -diff -up openssh-6.2p2/misc.c.ssh_gai_strerror openssh-6.2p2/misc.c ---- openssh-6.2p2/misc.c.ssh_gai_strerror 2013-07-23 12:03:41.321902978 +0200 -+++ openssh-6.2p2/misc.c 2013-07-23 12:03:41.467902339 +0200 -@@ -127,7 +127,7 @@ unset_nonblock(int fd) - const char * - ssh_gai_strerror(int gaierr) - { -- if (gaierr == EAI_SYSTEM) -+ if (gaierr == EAI_SYSTEM && errno != 0) - return strerror(errno); - return gai_strerror(gaierr); - } diff --git a/openssh-6.3p1-audit.patch b/openssh-6.3p1-audit.patch new file mode 100644 index 0000000..39296c1 --- /dev/null +++ b/openssh-6.3p1-audit.patch @@ -0,0 +1,2267 @@ +diff -up openssh-6.3p1/Makefile.in.audit openssh-6.3p1/Makefile.in +--- openssh-6.3p1/Makefile.in.audit 2013-06-11 03:26:10.000000000 +0200 ++++ openssh-6.3p1/Makefile.in 2013-10-07 15:53:34.246717277 +0200 +@@ -73,7 +73,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ + kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ +- jpake.o schnorr.o ssh-pkcs11.o krl.o ++ jpake.o schnorr.o ssh-pkcs11.o krl.o auditstub.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ +diff -up openssh-6.3p1/audit-bsm.c.audit openssh-6.3p1/audit-bsm.c +--- openssh-6.3p1/audit-bsm.c.audit 2012-02-24 00:40:43.000000000 +0100 ++++ openssh-6.3p1/audit-bsm.c 2013-10-07 15:53:34.246717277 +0200 +@@ -375,10 +375,23 @@ audit_connection_from(const char *host, + #endif + } + +-void ++int + audit_run_command(const char *command) + { + /* not implemented */ ++ return 0; ++} ++ ++void ++audit_end_command(int handle, const char *command) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_count_session_open(void) ++{ ++ /* not necessary */ + } + + void +@@ -393,6 +406,12 @@ audit_session_close(struct logininfo *li + /* not implemented */ + } + ++int ++audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) ++{ ++ /* not implemented */ ++} ++ + void + audit_event(ssh_audit_event_t event) + { +@@ -454,4 +473,40 @@ audit_event(ssh_audit_event_t event) + debug("%s: unhandled event %d", __func__, event); + } + } ++ ++void ++audit_unsupported_body(int what) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_destroy_sensitive_data(const char *fp) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_generate_ephemeral_server_key(const char *fp) ++{ ++ /* not implemented */ ++} + #endif /* BSM */ +diff -up openssh-6.3p1/audit-linux.c.audit openssh-6.3p1/audit-linux.c +--- openssh-6.3p1/audit-linux.c.audit 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-6.3p1/audit-linux.c 2013-10-07 15:53:34.246717277 +0200 +@@ -35,13 +35,24 @@ + + #include "log.h" + #include "audit.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" ++#include "servconf.h" + #include "canohost.h" ++#include "packet.h" ++#include "cipher.h" + ++#define AUDIT_LOG_SIZE 128 ++ ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern u_int utmp_len; + const char* audit_username(void); + +-int +-linux_audit_record_event(int uid, const char *username, +- const char *hostname, const char *ip, const char *ttyn, int success) ++static void ++linux_audit_user_logxxx(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; + +@@ -49,11 +60,11 @@ linux_audit_record_event(int uid, const + if (audit_fd < 0) { + if (errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT) +- return 1; /* No audit support in kernel */ ++ return; /* No audit support in kernel */ + else +- return 0; /* Must prevent login */ ++ goto fatal_report; /* Must prevent login */ + } +- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, ++ rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", + username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; +@@ -65,35 +76,150 @@ linux_audit_record_event(int uid, const + if ((rc == -EPERM) && (geteuid() != 0)) + rc = 0; + errno = saved_errno; +- return (rc >= 0); ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } + } + ++static void ++linux_audit_user_auth(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success, int event) ++{ ++ int audit_fd, rc, saved_errno; ++ static const char *event_name[] = { ++ "maxtries exceeded", ++ "root denied", ++ "success", ++ "none", ++ "password", ++ "challenge-response", ++ "pubkey", ++ "hostbased", ++ "gssapi", ++ "invalid user", ++ "nologin", ++ "connection closed", ++ "connection abandoned", ++ "unknown" ++ }; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ goto fatal_report; /* Must prevent login */ ++ } ++ ++ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN)) ++ event = SSH_AUDIT_UNKNOWN; ++ ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, ++ NULL, event_name[event], username ? username : "(unknown)", ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); ++ saved_errno = errno; ++ close(audit_fd); ++ /* ++ * Do not report error if the error is EPERM and sshd is run as non ++ * root user. ++ */ ++ if ((rc == -EPERM) && (geteuid() != 0)) ++ rc = 0; ++ errno = saved_errno; ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } ++} ++ ++int ++audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, rc, saved_errno; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 1; /* No audit support in kernel */ ++ else ++ return 0; /* Must prevent login */ ++ } ++ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "pubkey" : "hostbased", get_remote_port()); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d", ++ type, bits, key_fingerprint_prefix(), fp, get_remote_port()); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); ++out: ++ saved_errno = errno; ++ audit_close(audit_fd); ++ errno = saved_errno; ++ /* do not report error if the error is EPERM and sshd is run as non root user */ ++ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); ++} ++ ++static int user_login_count = 0; ++ + /* Below is the sshd audit API code */ + + void + audit_connection_from(const char *host, int port) + { +-} + /* not implemented */ ++} + +-void ++int + audit_run_command(const char *command) + { +- /* not implemented */ ++ if (!user_login_count++) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_START); ++ return 0; ++} ++ ++void ++audit_end_command(int handle, const char *command) ++{ ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGOUT); ++} ++ ++void ++audit_count_session_open(void) ++{ ++ user_login_count++; + } + + void + audit_session_open(struct logininfo *li) + { +- if (linux_audit_record_event(li->uid, NULL, li->hostname, +- NULL, li->line, 1) == 0) +- fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ if (!user_login_count++) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- /* not implemented */ ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_LOGOUT); + } + + void +@@ -101,21 +227,43 @@ audit_event(ssh_audit_event_t event) + { + switch(event) { + case SSH_AUTH_SUCCESS: +- case SSH_CONNECTION_CLOSE: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 1, event); ++ break; ++ + case SSH_NOLOGIN: +- case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_LOGIN_ROOT_DENIED: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, event); ++ linux_audit_user_logxxx(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); + break; + ++ case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_AUTH_FAIL_NONE: + case SSH_AUTH_FAIL_PASSWD: + case SSH_AUTH_FAIL_KBDINT: + case SSH_AUTH_FAIL_PUBKEY: + case SSH_AUTH_FAIL_HOSTBASED: + case SSH_AUTH_FAIL_GSSAPI: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, event); ++ break; ++ ++ case SSH_CONNECTION_CLOSE: ++ if (user_login_count) { ++ while (user_login_count--) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_END); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGOUT); ++ } ++ break; ++ ++ case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: +- linux_audit_record_event(-1, audit_username(), NULL, +- get_remote_ipaddr(), "sshd", 0); ++ linux_audit_user_logxxx(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); + break; + + default: +@@ -123,4 +271,135 @@ audit_event(ssh_audit_event_t event) + } + } + ++void ++audit_unsupported_body(int what) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ const static char *name[] = { "cipher", "mac", "comp" }; ++ char *s; ++ int audit_fd; ++ ++ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", ++ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), ++ get_local_port()); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) ++ /* no problem, the next instruction will be fatal() */ ++ return; ++ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, get_remote_ipaddr(), NULL, 0); ++ audit_close(audit_fd); ++#endif ++} ++ ++const static char *direction[] = { "from-server", "from-client", "both" }; ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, ++ uid_t uid) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ Cipher *cipher = cipher_by_name(enc); ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, ++ (intmax_t)pid, (intmax_t)uid, ++ get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port()); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ fatal("cannot open audit"); /* Must prevent login */ ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, get_remote_ipaddr(), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ fatal("cannot write into audit"); /* Must prevent login */ ++#endif ++} ++ ++void ++audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], (intmax_t)pid, (intmax_t)uid, ++ get_remote_port(), ++ (s = get_local_ipaddr(packet_get_connection_in())), ++ get_local_port()); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, get_remote_ipaddr(), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} ++ ++void ++audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ", ++ fp, (intmax_t)pid, (intmax_t)uid); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, ++ listening_for_clients() ? NULL : get_remote_ipaddr(), ++ NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} ++ ++void ++audit_generate_ephemeral_server_key(const char *fp) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "op=create kind=server fp=%s direction=? ", fp); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, 0, NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} + #endif /* USE_LINUX_AUDIT */ +diff -up openssh-6.3p1/audit.c.audit openssh-6.3p1/audit.c +--- openssh-6.3p1/audit.c.audit 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-6.3p1/audit.c 2013-10-07 15:53:34.246717277 +0200 +@@ -28,6 +28,7 @@ + + #include + #include ++#include + + #ifdef SSH_AUDIT_EVENTS + +@@ -36,6 +37,9 @@ + #include "key.h" + #include "hostfile.h" + #include "auth.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "xmalloc.h" + + /* + * Care must be taken when using this since it WILL NOT be initialized when +@@ -111,6 +115,40 @@ audit_event_lookup(ssh_audit_event_t ev) + return(event_lookup[i].name); + } + ++void ++audit_key(int host_user, int *rv, const Key *key) ++{ ++ char *fp; ++ const char *crypto_name; ++ ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ if (key->type == KEY_RSA1) ++ crypto_name = "ssh-rsa1"; ++ else ++ crypto_name = key_ssh_name(key); ++ if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0) ++ *rv = 0; ++ free(fp); ++} ++ ++void ++audit_unsupported(int what) ++{ ++ PRIVSEP(audit_unsupported_body(what)); ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp) ++{ ++ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid())); ++} ++ ++void ++audit_session_key_free(int ctos) ++{ ++ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid())); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -140,6 +178,17 @@ audit_event(ssh_audit_event_t event) + } + + /* ++ * Called when a child process has called, or will soon call, ++ * audit_session_open. ++ */ ++void ++audit_count_session_open(void) ++{ ++ debug("audit count session open euid %d user %s", geteuid(), ++ audit_username()); ++} ++ ++/* + * Called when a user session is started. Argument is the tty allocated to + * the session, or NULL if no tty was allocated. + * +@@ -174,13 +223,91 @@ audit_session_close(struct logininfo *li + /* + * This will be called when a user runs a non-interactive command. Note that + * it may be called multiple times for a single connection since SSH2 allows +- * multiple sessions within a single connection. ++ * multiple sessions within a single connection. Returns a "handle" for ++ * audit_end_command. + */ +-void ++int + audit_run_command(const char *command) + { + debug("audit run command euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); ++ return 0; ++} ++ ++/* ++ * This will be called when the non-interactive command finishes. Note that ++ * it may be called multiple times for a single connection since SSH2 allows ++ * multiple sessions within a single connection. "handle" should come from ++ * the corresponding audit_run_command. ++ */ ++void ++audit_end_command(int handle, const char *command) ++{ ++ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), ++ audit_username(), command); ++} ++ ++/* ++ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. ++ * ++ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. ++ */ ++int ++audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) ++{ ++ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d", ++ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits, ++ key_fingerprint_prefix(), fp, rv); ++} ++ ++/* ++ * This will be called when the protocol negotiation fails. ++ */ ++void ++audit_unsupported_body(int what) ++{ ++ debug("audit unsupported protocol euid %d type %d", geteuid(), what); ++} ++ ++/* ++ * This will be called on succesfull protocol negotiation. ++ */ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, ++ uid_t uid) ++{ ++ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, enc, mac, compress, (long)pid, ++ (unsigned)uid); ++} ++ ++/* ++ * This will be called on succesfull session key discard ++ */ ++void ++audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++ debug("audit session key discard euid %u direction %d from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); ++} ++ ++/* ++ * This will be called on destroy private part of the server key ++ */ ++void ++audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++{ ++ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", ++ geteuid(), fp, (long)pid, (unsigned)uid); ++} ++ ++/* ++ * This will be called on generation of the ephemeral server key ++ */ ++void ++audit_generate_ephemeral_server_key(const char *) ++{ ++ debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp); + } + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-6.3p1/audit.h.audit openssh-6.3p1/audit.h +--- openssh-6.3p1/audit.h.audit 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-6.3p1/audit.h 2013-10-07 15:53:34.246717277 +0200 +@@ -28,6 +28,7 @@ + # define _SSH_AUDIT_H + + #include "loginrec.h" ++#include "key.h" + + enum ssh_audit_event_type { + SSH_LOGIN_EXCEED_MAXTRIES, +@@ -47,11 +48,25 @@ enum ssh_audit_event_type { + }; + typedef enum ssh_audit_event_type ssh_audit_event_t; + ++int listening_for_clients(void); ++ + void audit_connection_from(const char *, int); + void audit_event(ssh_audit_event_t); ++void audit_count_session_open(void); + void audit_session_open(struct logininfo *); + void audit_session_close(struct logininfo *); +-void audit_run_command(const char *); ++int audit_run_command(const char *); ++void audit_end_command(int, const char *); + ssh_audit_event_t audit_classify_auth(const char *); ++int audit_keyusage(int, const char *, unsigned, char *, int); ++void audit_key(int, int *, const Key *); ++void audit_unsupported(int); ++void audit_kex(int, char *, char *, char *); ++void audit_unsupported_body(int); ++void audit_kex_body(int, char *, char *, char *, pid_t, uid_t); ++void audit_session_key_free(int ctos); ++void audit_session_key_free_body(int ctos, pid_t, uid_t); ++void audit_destroy_sensitive_data(const char *, pid_t, uid_t); ++void audit_generate_ephemeral_server_key(const char *); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-6.3p1/auditstub.c.audit openssh-6.3p1/auditstub.c +--- openssh-6.3p1/auditstub.c.audit 2013-10-07 15:53:34.247717272 +0200 ++++ openssh-6.3p1/auditstub.c 2013-10-07 15:53:34.247717272 +0200 +@@ -0,0 +1,50 @@ ++/* $Id: auditstub.c,v 1.1 jfch Exp $ */ ++ ++/* ++ * Copyright 2010 Red Hat, Inc. All rights reserved. ++ * Use is subject to license terms. ++ * ++ * 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. ++ * ++ * Red Hat author: Jan F. Chadima ++ */ ++ ++#include ++ ++void ++audit_unsupported(int n) ++{ ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp) ++{ ++} ++ ++void ++audit_session_key_free(int ctos) ++{ ++} ++ ++void ++audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++} +diff -up openssh-6.3p1/auth-rsa.c.audit openssh-6.3p1/auth-rsa.c +--- openssh-6.3p1/auth-rsa.c.audit 2013-07-18 08:12:44.000000000 +0200 ++++ openssh-6.3p1/auth-rsa.c 2013-10-07 15:53:34.247717272 +0200 +@@ -92,7 +92,10 @@ auth_rsa_verify_response(Key *key, BIGNU + { + u_char buf[32], mdbuf[16]; + MD5_CTX md; +- int len; ++ int len, rv; ++#ifdef SSH_AUDIT_EVENTS ++ char *fp; ++#endif + + /* don't allow short keys */ + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +@@ -113,12 +116,18 @@ auth_rsa_verify_response(Key *key, BIGNU + MD5_Final(mdbuf, &md); + + /* Verify that the response is the original challenge. */ +- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { +- /* Wrong answer. */ +- return (0); ++ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; ++ ++#ifdef SSH_AUDIT_EVENTS ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa) * 8, fp, rv) == 0) { ++ debug("unsuccessful audit"); ++ rv = 0; + } +- /* Correct answer. */ +- return (1); ++ free(fp); ++#endif ++ ++ return rv; + } + + /* +diff -up openssh-6.3p1/auth.h.audit openssh-6.3p1/auth.h +--- openssh-6.3p1/auth.h.audit 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/auth.h 2013-10-07 16:02:38.629171107 +0200 +@@ -187,6 +187,7 @@ void abandon_challenge_response(Authctxt + + char *expand_authorized_keys(const char *, struct passwd *pw); + char *authorized_principals_file(struct passwd *); ++int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); +@@ -204,6 +205,7 @@ Key *get_hostkey_private_by_type(int); + int get_hostkey_index(Key *); + int ssh1_session_key(BIGNUM *); + void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int); ++int hostbased_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + + /* debug messages during authentication */ + void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); +diff -up openssh-6.3p1/auth2-hostbased.c.audit openssh-6.3p1/auth2-hostbased.c +--- openssh-6.3p1/auth2-hostbased.c.audit 2013-10-07 15:53:34.223717384 +0200 ++++ openssh-6.3p1/auth2-hostbased.c 2013-10-07 15:53:34.247717272 +0200 +@@ -123,7 +123,7 @@ userauth_hostbased(Authctxt *authctxt) + /* test for allowed key and correct signature */ + authenticated = 0; + if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && +- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), ++ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + +@@ -140,6 +140,18 @@ done: + return authenticated; + } + ++int ++hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) ++{ ++ int rv; ++ ++ rv = key_verify(key, sig, slen, data, datalen); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(0, &rv, key); ++#endif ++ return rv; ++} ++ + /* return 1 if given hostkey is allowed */ + int + hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, +diff -up openssh-6.3p1/auth2-pubkey.c.audit openssh-6.3p1/auth2-pubkey.c +--- openssh-6.3p1/auth2-pubkey.c.audit 2013-10-07 15:53:34.224717379 +0200 ++++ openssh-6.3p1/auth2-pubkey.c 2013-10-08 15:11:42.282436972 +0200 +@@ -152,7 +152,7 @@ userauth_pubkey(Authctxt *authctxt) + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && +- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), ++ PRIVSEP(user_key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + buffer_free(&b); +@@ -223,6 +223,18 @@ pubkey_auth_info(Authctxt *authctxt, con + free(extra); + } + ++int ++user_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) ++{ ++ int rv; ++ ++ rv = key_verify(key, sig, slen, data, datalen); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(1, &rv, key); ++#endif ++ return rv; ++} ++ + static int + match_principals_option(const char *principal_list, struct KeyCert *cert) + { +diff -up openssh-6.3p1/auth2.c.audit openssh-6.3p1/auth2.c +--- openssh-6.3p1/auth2.c.audit 2013-06-01 23:41:51.000000000 +0200 ++++ openssh-6.3p1/auth2.c 2013-10-07 15:53:34.248717268 +0200 +@@ -245,9 +245,6 @@ input_userauth_request(int type, u_int32 + } else { + logit("input_userauth_request: invalid user %s", user); + authctxt->pw = fakepw(); +-#ifdef SSH_AUDIT_EVENTS +- PRIVSEP(audit_event(SSH_INVALID_USER)); +-#endif + } + #ifdef USE_PAM + if (options.use_pam) +diff -up openssh-6.3p1/cipher.c.audit openssh-6.3p1/cipher.c +--- openssh-6.3p1/cipher.c.audit 2013-10-07 15:53:34.248717268 +0200 ++++ openssh-6.3p1/cipher.c 2013-10-07 16:06:51.117971891 +0200 +@@ -55,18 +55,6 @@ 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); + +-struct Cipher { +- char *name; +- int number; /* for ssh1 only */ +- u_int block_size; +- u_int key_len; +- u_int iv_len; /* defaults to block_size */ +- u_int auth_len; +- u_int discard_len; +- u_int cbc_mode; +- const EVP_CIPHER *(*evptype)(void); +-}; +- + static const struct Cipher ciphers[] = { + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, + { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, +diff -up openssh-6.3p1/cipher.h.audit openssh-6.3p1/cipher.h +--- openssh-6.3p1/cipher.h.audit 2013-04-23 11:24:32.000000000 +0200 ++++ openssh-6.3p1/cipher.h 2013-10-07 15:53:34.248717268 +0200 +@@ -61,7 +61,18 @@ + typedef struct Cipher Cipher; + typedef struct CipherContext CipherContext; + +-struct Cipher; ++struct Cipher { ++ char *name; ++ int number; /* for ssh1 only */ ++ u_int block_size; ++ u_int key_len; ++ u_int iv_len; /* defaults to block_size */ ++ u_int auth_len; ++ u_int discard_len; ++ u_int cbc_mode; ++ const EVP_CIPHER *(*evptype)(void); ++}; ++ + struct CipherContext { + int plaintext; + int encrypt; +diff -up openssh-6.3p1/kex.c.audit openssh-6.3p1/kex.c +--- openssh-6.3p1/kex.c.audit 2013-06-01 23:31:18.000000000 +0200 ++++ openssh-6.3p1/kex.c 2013-10-07 15:53:34.249717264 +0200 +@@ -49,6 +49,7 @@ + #include "dispatch.h" + #include "monitor.h" + #include "roaming.h" ++#include "audit.h" + + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) +@@ -341,9 +342,13 @@ static void + choose_enc(Enc *enc, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(0); ++#endif + fatal("no matching cipher found: client %s server %s", + client, server); ++ } + if ((enc->cipher = cipher_by_name(name)) == NULL) + fatal("matching cipher is not supported: %s", name); + enc->name = name; +@@ -359,9 +364,13 @@ static void + choose_mac(Mac *mac, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(1); ++#endif + fatal("no matching mac found: client %s server %s", + client, server); ++ } + if (mac_setup(mac, name) < 0) + fatal("unsupported mac %s", name); + /* truncate the key */ +@@ -376,8 +385,12 @@ static void + choose_comp(Comp *comp, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(2); ++#endif + fatal("no matching comp found: client %s server %s", client, server); ++ } + if (strcmp(name, "zlib@openssh.com") == 0) { + comp->type = COMP_DELAYED; + } else if (strcmp(name, "zlib") == 0) { +@@ -492,6 +505,9 @@ kex_choose_conf(Kex *kex) + newkeys->enc.name, + authlen == 0 ? newkeys->mac.name : "", + newkeys->comp.name); ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); ++#endif + } + choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); + choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], +@@ -656,3 +672,34 @@ dump_digest(char *msg, u_char *digest, i + fprintf(stderr, "\n"); + } + #endif ++ ++static void ++enc_destroy(Enc *enc) ++{ ++ if (enc == NULL) ++ return; ++ ++ if (enc->key) { ++ memset(enc->key, 0, enc->key_len); ++ free(enc->key); ++ } ++ ++ if (enc->iv) { ++ memset(enc->iv, 0, enc->block_size); ++ free(enc->iv); ++ } ++ ++ memset(enc, 0, sizeof(*enc)); ++} ++ ++void ++newkeys_destroy(Newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ enc_destroy(&newkeys->enc); ++ mac_destroy(&newkeys->mac); ++ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); ++} ++ +diff -up openssh-6.3p1/kex.h.audit openssh-6.3p1/kex.h +--- openssh-6.3p1/kex.h.audit 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/kex.h 2013-10-07 15:53:34.249717264 +0200 +@@ -162,6 +162,8 @@ void kexgex_server(Kex *); + void kexecdh_client(Kex *); + void kexecdh_server(Kex *); + ++void newkeys_destroy(Newkeys *newkeys); ++ + void + kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, + BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); +diff -up openssh-6.3p1/key.c.audit openssh-6.3p1/key.c +--- openssh-6.3p1/key.c.audit 2013-10-07 15:53:34.224717379 +0200 ++++ openssh-6.3p1/key.c 2013-10-07 15:53:34.249717264 +0200 +@@ -1773,6 +1773,30 @@ key_demote(const Key *k) + } + + int ++key_is_private(const Key *k) ++{ ++ switch (k->type) { ++ case KEY_RSA_CERT_V00: ++ case KEY_RSA_CERT: ++ case KEY_RSA1: ++ case KEY_RSA: ++ return k->rsa->d != NULL; ++ case KEY_DSA_CERT_V00: ++ case KEY_DSA_CERT: ++ case KEY_DSA: ++ return k->dsa->priv_key != NULL; ++#ifdef OPENSSL_HAS_ECC ++ case KEY_ECDSA_CERT: ++ case KEY_ECDSA: ++ return EC_KEY_get0_private_key(k->ecdsa) != NULL; ++#endif ++ default: ++ fatal("key_is_private: bad key type %d", k->type); ++ return 1; ++ } ++} ++ ++int + key_is_cert(const Key *k) + { + if (k == NULL) +diff -up openssh-6.3p1/key.h.audit openssh-6.3p1/key.h +--- openssh-6.3p1/key.h.audit 2013-10-07 15:53:34.224717379 +0200 ++++ openssh-6.3p1/key.h 2013-10-07 15:53:34.249717264 +0200 +@@ -110,6 +110,7 @@ Key *key_generate(int, u_int); + Key *key_from_private(const Key *); + int key_type_from_name(char *); + int key_is_cert(const Key *); ++int key_is_private(const Key *k); + int key_type_plain(int); + int key_to_certified(Key *, int); + int key_drop_cert(Key *); +diff -up openssh-6.3p1/mac.c.audit openssh-6.3p1/mac.c +--- openssh-6.3p1/mac.c.audit 2013-06-06 00:12:37.000000000 +0200 ++++ openssh-6.3p1/mac.c 2013-10-07 15:53:34.250717259 +0200 +@@ -224,6 +224,20 @@ mac_clear(Mac *mac) + mac->umac_ctx = NULL; + } + ++void ++mac_destroy(Mac *mac) ++{ ++ if (mac == NULL) ++ return; ++ ++ if (mac->key) { ++ memset(mac->key, 0, mac->key_len); ++ free(mac->key); ++ } ++ ++ memset(mac, 0, sizeof(*mac)); ++} ++ + /* XXX copied from ciphers_valid */ + #define MAC_SEP "," + int +diff -up openssh-6.3p1/mac.h.audit openssh-6.3p1/mac.h +--- openssh-6.3p1/mac.h.audit 2013-04-23 11:24:32.000000000 +0200 ++++ openssh-6.3p1/mac.h 2013-10-07 15:53:34.250717259 +0200 +@@ -29,3 +29,4 @@ int mac_setup(Mac *, char *); + int mac_init(Mac *); + u_char *mac_compute(Mac *, u_int32_t, u_char *, int); + void mac_clear(Mac *); ++void mac_destroy(Mac *); +diff -up openssh-6.3p1/monitor.c.audit openssh-6.3p1/monitor.c +--- openssh-6.3p1/monitor.c.audit 2013-10-07 15:53:34.217717411 +0200 ++++ openssh-6.3p1/monitor.c 2013-10-08 15:10:38.270726936 +0200 +@@ -98,6 +98,7 @@ + #include "jpake.h" + #include "roaming.h" + #include "authfd.h" ++#include "audit.h" + + #ifdef GSSAPI + static Gssctxt *gsscontext = NULL; +@@ -114,6 +115,8 @@ extern Buffer auth_debug; + extern int auth_debug_init; + extern Buffer loginmsg; + ++extern void destroy_sensitive_data(int); ++ + /* State exported from the child */ + + struct { +@@ -186,6 +189,11 @@ int mm_answer_gss_checkmic(int, Buffer * + #ifdef SSH_AUDIT_EVENTS + int mm_answer_audit_event(int, Buffer *); + int mm_answer_audit_command(int, Buffer *); ++int mm_answer_audit_end_command(int, Buffer *); ++int mm_answer_audit_unsupported_body(int, Buffer *); ++int mm_answer_audit_kex_body(int, Buffer *); ++int mm_answer_audit_session_key_free_body(int, Buffer *); ++int mm_answer_audit_server_key_free(int, Buffer *); + #endif + + static int monitor_read_log(struct monitor *); +@@ -237,6 +245,10 @@ struct mon_table mon_dispatch_proto20[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + #ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, +@@ -273,6 +285,11 @@ struct mon_table mon_dispatch_postauth20 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -304,6 +321,10 @@ struct mon_table mon_dispatch_proto15[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -315,6 +336,11 @@ struct mon_table mon_dispatch_postauth15 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -1365,9 +1391,11 @@ mm_answer_keyverify(int sock, Buffer *m) + Key *key; + u_char *signature, *data, *blob; + u_int signaturelen, datalen, bloblen; ++ int type = 0; + int verified = 0; + int valid_data = 0; + ++ type = buffer_get_int(m); + blob = buffer_get_string(m, &bloblen); + signature = buffer_get_string(m, &signaturelen); + data = buffer_get_string(m, &datalen); +@@ -1375,6 +1403,8 @@ mm_answer_keyverify(int sock, Buffer *m) + if (hostbased_cuser == NULL || hostbased_chost == NULL || + !monitor_allowed_key(blob, bloblen)) + fatal("%s: bad key, not previously allowed", __func__); ++ if (type != key_blobtype) ++ fatal("%s: bad key type", __func__); + + key = key_from_blob(blob, bloblen); + if (key == NULL) +@@ -1395,7 +1425,17 @@ mm_answer_keyverify(int sock, Buffer *m) + if (!valid_data) + fatal("%s: bad signature data blob", __func__); + +- verified = key_verify(key, signature, signaturelen, data, datalen); ++ switch (key_blobtype) { ++ case MM_USERKEY: ++ verified = user_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ case MM_HOSTKEY: ++ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ default: ++ verified = 0; ++ break; ++ } + debug3("%s: key %p signature %s", + __func__, key, (verified == 1) ? "verified" : "unverified"); + +@@ -1448,6 +1488,12 @@ mm_session_close(Session *s) + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + session_pty_cleanup2(s); + } ++#ifdef SSH_AUDIT_EVENTS ++ if (s->command != NULL) { ++ debug3("%s: command %d", __func__, s->command_handle); ++ session_end_command2(s); ++ } ++#endif + session_unused(s->self); + } + +@@ -1728,6 +1774,8 @@ mm_answer_term(int sock, Buffer *req) + sshpam_cleanup(); + #endif + ++ destroy_sensitive_data(0); ++ + while (waitpid(pmonitor->m_pid, &status, 0) == -1) + if (errno != EINTR) + exit(1); +@@ -1770,11 +1818,43 @@ mm_answer_audit_command(int socket, Buff + { + u_int len; + char *cmd; ++ Session *s; + + debug3("%s entering", __func__); + cmd = buffer_get_string(m, &len); ++ + /* sanity check command, if so how? */ +- audit_run_command(cmd); ++ s = session_new(); ++ if (s == NULL) ++ fatal("%s: error allocating a session", __func__); ++ s->command = cmd; ++ s->command_handle = audit_run_command(cmd); ++ ++ buffer_clear(m); ++ buffer_put_int(m, s->self); ++ ++ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m); ++ ++ return (0); ++} ++ ++int ++mm_answer_audit_end_command(int socket, Buffer *m) ++{ ++ int handle; ++ u_int len; ++ char *cmd; ++ Session *s; ++ ++ debug3("%s entering", __func__); ++ handle = buffer_get_int(m); ++ cmd = buffer_get_string(m, &len); ++ ++ s = session_by_id(handle); ++ if (s == NULL || s->ttyfd != -1 || s->command == NULL || ++ strcmp(s->command, cmd) != 0) ++ fatal("%s: invalid handle", __func__); ++ mm_session_close(s); + free(cmd); + return (0); + } +@@ -1910,11 +1990,13 @@ mm_get_keystate(struct monitor *pmonitor + + blob = buffer_get_string(&m, &bloblen); + current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); ++ memset(blob, 0, bloblen); + free(blob); + + debug3("%s: Waiting for second key", __func__); + blob = buffer_get_string(&m, &bloblen); + current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); ++ memset(blob, 0, bloblen); + free(blob); + + /* Now get sequence numbers for the packets */ +@@ -1960,6 +2042,21 @@ mm_get_keystate(struct monitor *pmonitor + } + + buffer_free(&m); ++ ++#ifdef SSH_AUDIT_EVENTS ++ if (compat20) { ++ buffer_init(&m); ++ mm_request_receive_expect(pmonitor->m_sendfd, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); ++ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, &m); ++ buffer_free(&m); ++ } ++#endif ++ ++ /* Drain any buffered messages from the child */ ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) ++ ; ++ + } + + +@@ -2361,3 +2458,86 @@ mm_answer_jpake_check_confirm(int sock, + } + + #endif /* JPAKE */ ++ ++#ifdef SSH_AUDIT_EVENTS ++int ++mm_answer_audit_unsupported_body(int sock, Buffer *m) ++{ ++ int what; ++ ++ what = buffer_get_int(m); ++ ++ audit_unsupported_body(what); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_kex_body(int sock, Buffer *m) ++{ ++ int ctos, len; ++ char *cipher, *mac, *compress; ++ pid_t pid; ++ uid_t uid; ++ ++ ctos = buffer_get_int(m); ++ cipher = buffer_get_string(m, &len); ++ mac = buffer_get_string(m, &len); ++ compress = buffer_get_string(m, &len); ++ pid = buffer_get_int64(m); ++ uid = buffer_get_int64(m); ++ ++ audit_kex_body(ctos, cipher, mac, compress, pid, uid); ++ ++ free(cipher); ++ free(mac); ++ free(compress); ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_session_key_free_body(int sock, Buffer *m) ++{ ++ int ctos; ++ pid_t pid; ++ uid_t uid; ++ ++ ctos = buffer_get_int(m); ++ pid = buffer_get_int64(m); ++ uid = buffer_get_int64(m); ++ ++ audit_session_key_free_body(ctos, pid, uid); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_server_key_free(int sock, Buffer *m) ++{ ++ int len; ++ char *fp; ++ pid_t pid; ++ uid_t uid; ++ ++ fp = buffer_get_string(m, &len); ++ pid = buffer_get_int64(m); ++ uid = buffer_get_int64(m); ++ ++ audit_destroy_sensitive_data(fp, pid, uid); ++ ++ free(fp); ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m); ++ return 0; ++} ++#endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-6.3p1/monitor.h.audit openssh-6.3p1/monitor.h +--- openssh-6.3p1/monitor.h.audit 2012-12-02 23:53:21.000000000 +0100 ++++ openssh-6.3p1/monitor.h 2013-10-07 15:53:34.251717254 +0200 +@@ -68,7 +68,13 @@ enum monitor_reqtype { + MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, + MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, + MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, +- MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, ++ MONITOR_REQ_AUDIT_EVENT = 112, ++ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115, ++ MONITOR_REQ_AUDIT_END_COMMAND = 116, ++ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, ++ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, ++ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, MONITOR_ANS_AUDIT_SERVER_KEY_FREE = 125 + + }; + +diff -up openssh-6.3p1/monitor_wrap.c.audit openssh-6.3p1/monitor_wrap.c +--- openssh-6.3p1/monitor_wrap.c.audit 2013-10-07 15:53:34.217717411 +0200 ++++ openssh-6.3p1/monitor_wrap.c 2013-10-07 16:03:16.190993304 +0200 +@@ -433,7 +433,7 @@ mm_key_allowed(enum mm_keytype type, cha + */ + + int +-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) + { + Buffer m; + u_char *blob; +@@ -447,6 +447,7 @@ mm_key_verify(Key *key, u_char *sig, u_i + return (0); + + buffer_init(&m); ++ buffer_put_int(&m, type); + buffer_put_string(&m, blob, len); + buffer_put_string(&m, sig, siglen); + buffer_put_string(&m, data, datalen); +@@ -464,6 +465,19 @@ mm_key_verify(Key *key, u_char *sig, u_i + return (verified); + } + ++int ++mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++{ ++ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen); ++} ++ ++int ++mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++{ ++ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen); ++} ++ ++ + /* Export key state after authentication */ + Newkeys * + mm_newkeys_from_blob(u_char *blob, int blen) +@@ -482,7 +496,7 @@ mm_newkeys_from_blob(u_char *blob, int b + buffer_init(&b); + buffer_append(&b, blob, blen); + +- newkey = xmalloc(sizeof(*newkey)); ++ newkey = xcalloc(1, sizeof(*newkey)); + enc = &newkey->enc; + mac = &newkey->mac; + comp = &newkey->comp; +@@ -642,12 +656,14 @@ mm_send_keystate(struct monitor *monitor + fatal("%s: conversion of newkeys failed", __func__); + + buffer_put_string(&m, blob, bloblen); ++ memset(blob, 0, bloblen); + free(blob); + + if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) + fatal("%s: conversion of newkeys failed", __func__); + + buffer_put_string(&m, blob, bloblen); ++ memset(blob, 0, bloblen); + free(blob); + + packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes); +@@ -1191,10 +1207,11 @@ mm_audit_event(ssh_audit_event_t event) + buffer_free(&m); + } + +-void ++int + mm_audit_run_command(const char *command) + { + Buffer m; ++ int handle; + + debug3("%s entering command %s", __func__, command); + +@@ -1202,6 +1219,26 @@ mm_audit_run_command(const char *command + buffer_put_cstring(&m, command); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m); ++ ++ handle = buffer_get_int(&m); ++ buffer_free(&m); ++ ++ return (handle); ++} ++ ++void ++mm_audit_end_command(int handle, const char *command) ++{ ++ Buffer m; ++ ++ debug3("%s entering command %s", __func__, command); ++ ++ buffer_init(&m); ++ buffer_put_int(&m, handle); ++ buffer_put_cstring(&m, command); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m); + buffer_free(&m); + } + #endif /* SSH_AUDIT_EVENTS */ +@@ -1453,3 +1490,72 @@ mm_jpake_check_confirm(const BIGNUM *k, + return success; + } + #endif /* JPAKE */ ++ ++#ifdef SSH_AUDIT_EVENTS ++void ++mm_audit_unsupported_body(int what) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, what); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, ++ &m); ++ ++ buffer_free(&m); ++} ++ ++void ++mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, pid_t pid, ++ uid_t uid) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, ctos); ++ buffer_put_cstring(&m, cipher); ++ buffer_put_cstring(&m, (mac ? mac : "")); ++ buffer_put_cstring(&m, compress); ++ buffer_put_int64(&m, pid); ++ buffer_put_int64(&m, uid); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, ++ &m); ++ ++ buffer_free(&m); ++} ++ ++void ++mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, ctos); ++ buffer_put_int64(&m, pid); ++ buffer_put_int64(&m, uid); ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, ++ &m); ++ buffer_free(&m); ++} ++ ++void ++mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_cstring(&m, fp); ++ buffer_put_int64(&m, pid); ++ buffer_put_int64(&m, uid); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, ++ &m); ++ buffer_free(&m); ++} ++#endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-6.3p1/monitor_wrap.h.audit openssh-6.3p1/monitor_wrap.h +--- openssh-6.3p1/monitor_wrap.h.audit 2011-06-20 06:42:23.000000000 +0200 ++++ openssh-6.3p1/monitor_wrap.h 2013-10-07 15:53:34.252717250 +0200 +@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char + int mm_user_key_allowed(struct passwd *, Key *); + int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *); + int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); +-int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); ++int mm_hostbased_key_verify(Key *, u_char *, u_int, u_char *, u_int); ++int mm_user_key_verify(Key *, u_char *, u_int, u_char *, u_int); + int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); + int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); + BIGNUM *mm_auth_rsa_generate_challenge(Key *); +@@ -74,7 +75,12 @@ void mm_sshpam_free_ctx(void *); + #ifdef SSH_AUDIT_EVENTS + #include "audit.h" + void mm_audit_event(ssh_audit_event_t); +-void mm_audit_run_command(const char *); ++int mm_audit_run_command(const char *); ++void mm_audit_end_command(int, const char *); ++void mm_audit_unsupported_body(int); ++void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t); ++void mm_audit_session_key_free_body(int, pid_t, uid_t); ++void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); + #endif + + struct Session; +diff -up openssh-6.3p1/packet.c.audit openssh-6.3p1/packet.c +--- openssh-6.3p1/packet.c.audit 2013-10-07 15:53:34.231717347 +0200 ++++ openssh-6.3p1/packet.c 2013-10-07 16:08:00.764639577 +0200 +@@ -61,6 +61,7 @@ + #include + + #include "xmalloc.h" ++#include "audit.h" + #include "buffer.h" + #include "packet.h" + #include "crc32.h" +@@ -476,6 +477,13 @@ packet_get_connection_out(void) + return active_state->connection_out; + } + ++static int ++packet_state_has_keys (const struct session_state *state) ++{ ++ return state != NULL && ++ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL); ++} ++ + /* Closes the connection and clears and frees internal data structures. */ + + void +@@ -484,13 +492,6 @@ packet_close(void) + if (!active_state->initialized) + return; + active_state->initialized = 0; +- if (active_state->connection_in == active_state->connection_out) { +- shutdown(active_state->connection_out, SHUT_RDWR); +- close(active_state->connection_out); +- } else { +- close(active_state->connection_in); +- close(active_state->connection_out); +- } + buffer_free(&active_state->input); + buffer_free(&active_state->output); + buffer_free(&active_state->outgoing_packet); +@@ -499,8 +500,18 @@ packet_close(void) + buffer_free(&active_state->compression_buffer); + buffer_compress_uninit(); + } +- cipher_cleanup(&active_state->send_context); +- cipher_cleanup(&active_state->receive_context); ++ if (packet_state_has_keys(active_state)) { ++ cipher_cleanup(&active_state->send_context); ++ cipher_cleanup(&active_state->receive_context); ++ audit_session_key_free(2); ++ } ++ if (active_state->connection_in == active_state->connection_out) { ++ shutdown(active_state->connection_out, SHUT_RDWR); ++ close(active_state->connection_out); ++ } else { ++ close(active_state->connection_in); ++ close(active_state->connection_out); ++ } + } + + /* Sets remote side protocol flags. */ +@@ -735,6 +746,25 @@ packet_send1(void) + */ + } + ++static void ++newkeys_destroy_and_free(Newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ free(newkeys->enc.name); ++ ++ if (newkeys->mac.enabled) { ++ mac_clear(&newkeys->mac); ++ free(newkeys->mac.name); ++ } ++ ++ free(newkeys->comp.name); ++ ++ newkeys_destroy(newkeys); ++ free(newkeys); ++} ++ + void + set_newkeys(int mode) + { +@@ -760,21 +790,9 @@ set_newkeys(int mode) + } + if (active_state->newkeys[mode] != NULL) { + debug("set_newkeys: rekeying"); ++ audit_session_key_free(mode); + cipher_cleanup(cc); +- enc = &active_state->newkeys[mode]->enc; +- mac = &active_state->newkeys[mode]->mac; +- comp = &active_state->newkeys[mode]->comp; +- mac_clear(mac); +- memset(enc->iv, 0, enc->iv_len); +- memset(enc->key, 0, enc->key_len); +- memset(mac->key, 0, mac->key_len); +- free(enc->name); +- free(enc->iv); +- free(enc->key); +- free(mac->name); +- free(mac->key); +- free(comp->name); +- free(active_state->newkeys[mode]); ++ newkeys_destroy_and_free(active_state->newkeys[mode]); + } + active_state->newkeys[mode] = kex_get_newkeys(mode); + if (active_state->newkeys[mode] == NULL) +@@ -2003,6 +2021,47 @@ packet_get_newkeys(int mode) + return (void *)active_state->newkeys[mode]; + } + ++static void ++packet_destroy_state(struct session_state *state) ++{ ++ if (state == NULL) ++ return; ++ ++ cipher_cleanup(&state->receive_context); ++ cipher_cleanup(&state->send_context); ++ ++ buffer_free(&state->input); ++ buffer_free(&state->output); ++ buffer_free(&state->outgoing_packet); ++ buffer_free(&state->incoming_packet); ++ buffer_free(&state->compression_buffer); ++ newkeys_destroy_and_free(state->newkeys[MODE_IN]); ++ state->newkeys[MODE_IN] = NULL; ++ newkeys_destroy_and_free(state->newkeys[MODE_OUT]); ++ state->newkeys[MODE_OUT] = NULL; ++ mac_destroy(state->packet_discard_mac); ++// TAILQ_HEAD(, packet) outgoing; ++// memset(state, 0, sizeof(state)); ++} ++ ++void ++packet_destroy_all(int audit_it, int privsep) ++{ ++ if (audit_it) ++ audit_it = packet_state_has_keys (active_state) || ++ packet_state_has_keys (backup_state); ++ packet_destroy_state(active_state); ++ packet_destroy_state(backup_state); ++ if (audit_it) { ++#ifdef SSH_AUDIT_EVENTS ++ if (privsep) ++ audit_session_key_free(2); ++ else ++ audit_session_key_free_body(2, getpid(), getuid()); ++#endif ++ } ++} ++ + /* + * Save the state for the real connection, and use a separate state when + * resuming a suspended connection. +@@ -2010,18 +2069,12 @@ packet_get_newkeys(int mode) + void + packet_backup_state(void) + { +- struct session_state *tmp; +- + close(active_state->connection_in); + active_state->connection_in = -1; + close(active_state->connection_out); + active_state->connection_out = -1; +- if (backup_state) +- tmp = backup_state; +- else +- tmp = alloc_session_state(); + backup_state = active_state; +- active_state = tmp; ++ active_state = alloc_session_state(); + } + + /* +@@ -2038,9 +2091,7 @@ packet_restore_state(void) + backup_state = active_state; + active_state = tmp; + active_state->connection_in = backup_state->connection_in; +- backup_state->connection_in = -1; + active_state->connection_out = backup_state->connection_out; +- backup_state->connection_out = -1; + len = buffer_len(&backup_state->input); + if (len > 0) { + buf = buffer_ptr(&backup_state->input); +@@ -2048,4 +2099,10 @@ packet_restore_state(void) + buffer_clear(&backup_state->input); + add_recv_bytes(len); + } ++ backup_state->connection_in = -1; ++ backup_state->connection_out = -1; ++ packet_destroy_state(backup_state); ++ free(backup_state); ++ backup_state = NULL; + } ++ +diff -up openssh-6.3p1/packet.h.audit openssh-6.3p1/packet.h +--- openssh-6.3p1/packet.h.audit 2013-07-18 08:12:45.000000000 +0200 ++++ openssh-6.3p1/packet.h 2013-10-07 15:53:34.252717250 +0200 +@@ -124,4 +124,5 @@ void packet_restore_state(void); + void *packet_get_input(void); + void *packet_get_output(void); + ++void packet_destroy_all(int, int); + #endif /* PACKET_H */ +diff -up openssh-6.3p1/session.c.audit openssh-6.3p1/session.c +--- openssh-6.3p1/session.c.audit 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/session.c 2013-10-07 16:03:43.975861636 +0200 +@@ -137,7 +137,7 @@ extern int log_stderr; + extern int debug_flag; + extern u_int utmp_len; + extern int startup_pipe; +-extern void destroy_sensitive_data(void); ++extern void destroy_sensitive_data(int); + extern Buffer loginmsg; + + /* original command from peer. */ +@@ -745,6 +745,14 @@ do_exec_pty(Session *s, const char *comm + /* Parent. Close the slave side of the pseudo tty. */ + close(ttyfd); + ++#ifndef HAVE_OSF_SIA ++ /* do_login in the child did not affect state in this process, ++ compensate. From an architectural standpoint, this is extremely ++ ugly. */ ++ if (!(options.use_login && command == NULL)) ++ audit_count_session_open(); ++#endif ++ + /* Enter interactive session. */ + s->ptymaster = ptymaster; + packet_set_interactive(1, +@@ -816,15 +824,19 @@ do_exec(Session *s, const char *command) + } + + #ifdef SSH_AUDIT_EVENTS ++ if (s->command != NULL || s->command_handle != -1) ++ fatal("do_exec: command already set"); + if (command != NULL) +- PRIVSEP(audit_run_command(command)); ++ s->command = xstrdup(command); + else if (s->ttyfd == -1) { + char *shell = s->pw->pw_shell; + + if (shell[0] == '\0') /* empty shell means /bin/sh */ + shell =_PATH_BSHELL; +- PRIVSEP(audit_run_command(shell)); ++ s->command = xstrdup(shell); + } ++ if (s->command != NULL) ++ s->command_handle = PRIVSEP(audit_run_command(s->command)); + #endif + if (s->ttyfd != -1) + ret = do_exec_pty(s, command); +@@ -1642,7 +1654,10 @@ do_child(Session *s, const char *command + int r = 0; + + /* remove hostkey from the child's memory */ +- destroy_sensitive_data(); ++ destroy_sensitive_data(1); ++ /* Don't audit this - both us and the parent would be talking to the ++ monitor over a single socket, with no synchronization. */ ++ packet_destroy_all(0, 1); + + /* Force a password change */ + if (s->authctxt->force_pwchange) { +@@ -1869,6 +1884,7 @@ session_unused(int id) + sessions[id].ttyfd = -1; + sessions[id].ptymaster = -1; + sessions[id].x11_chanids = NULL; ++ sessions[id].command_handle = -1; + sessions[id].next_unused = sessions_first_unused; + sessions_first_unused = id; + } +@@ -1951,6 +1967,19 @@ session_open(Authctxt *authctxt, int cha + } + + Session * ++session_by_id(int id) ++{ ++ if (id >= 0 && id < sessions_nalloc) { ++ Session *s = &sessions[id]; ++ if (s->used) ++ return s; ++ } ++ debug("session_by_id: unknown id %d", id); ++ session_dump(); ++ return NULL; ++} ++ ++Session * + session_by_tty(char *tty) + { + int i; +@@ -2467,6 +2496,30 @@ session_exit_message(Session *s, int sta + chan_write_failed(c); + } + ++#ifdef SSH_AUDIT_EVENTS ++void ++session_end_command2(Session *s) ++{ ++ if (s->command != NULL) { ++ audit_end_command(s->command_handle, s->command); ++ free(s->command); ++ s->command = NULL; ++ s->command_handle = -1; ++ } ++} ++ ++static void ++session_end_command(Session *s) ++{ ++ if (s->command != NULL) { ++ PRIVSEP(audit_end_command(s->command_handle, s->command)); ++ free(s->command); ++ s->command = NULL; ++ s->command_handle = -1; ++ } ++} ++#endif ++ + void + session_close(Session *s) + { +@@ -2475,6 +2528,10 @@ session_close(Session *s) + debug("session_close: session %d pid %ld", s->self, (long)s->pid); + if (s->ttyfd != -1) + session_pty_cleanup(s); ++#ifdef SSH_AUDIT_EVENTS ++ if (s->command) ++ session_end_command(s); ++#endif + free(s->term); + free(s->display); + free(s->x11_chanids); +@@ -2688,6 +2745,15 @@ do_authenticated2(Authctxt *authctxt) + server_loop2(authctxt); + } + ++static void ++do_cleanup_one_session(Session *s) ++{ ++ session_pty_cleanup2(s); ++#ifdef SSH_AUDIT_EVENTS ++ session_end_command2(s); ++#endif ++} ++ + void + do_cleanup(Authctxt *authctxt) + { +@@ -2736,5 +2802,5 @@ do_cleanup(Authctxt *authctxt) + * or if running in monitor. + */ + if (!use_privsep || mm_is_monitor()) +- session_destroy_all(session_pty_cleanup2); ++ session_destroy_all(do_cleanup_one_session); + } +diff -up openssh-6.3p1/session.h.audit openssh-6.3p1/session.h +--- openssh-6.3p1/session.h.audit 2008-05-19 07:34:50.000000000 +0200 ++++ openssh-6.3p1/session.h 2013-10-07 15:53:34.253717245 +0200 +@@ -60,6 +60,12 @@ struct Session { + char *name; + char *val; + } *env; ++ ++ /* exec */ ++#ifdef SSH_AUDIT_EVENTS ++ int command_handle; ++ char *command; ++#endif + }; + + void do_authenticated(Authctxt *); +@@ -72,8 +78,10 @@ void session_close_by_pid(pid_t, int); + void session_close_by_channel(int, void *); + void session_destroy_all(void (*)(Session *)); + void session_pty_cleanup2(Session *); ++void session_end_command2(Session *); + + Session *session_new(void); ++Session *session_by_id(int); + Session *session_by_tty(char *); + void session_close(Session *); + void do_setusercontext(struct passwd *); +diff -up openssh-6.3p1/sshd.c.audit openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.audit 2013-10-07 15:53:34.221717393 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-07 15:53:34.254717240 +0200 +@@ -119,6 +119,7 @@ + #endif + #include "monitor_wrap.h" + #include "roaming.h" ++#include "audit.h" + #include "ssh-sandbox.h" + #include "version.h" + +@@ -260,7 +261,7 @@ Buffer loginmsg; + struct passwd *privsep_pw = NULL; + + /* Prototypes for various functions defined later in this file. */ +-void destroy_sensitive_data(void); ++void destroy_sensitive_data(int); + void demote_sensitive_data(void); + + static void do_ssh1_kex(void); +@@ -279,6 +280,15 @@ close_listen_socks(void) + num_listen_socks = -1; + } + ++/* ++ * Is this process listening for clients (i.e. not specific to any specific ++ * client connection?) ++ */ ++int listening_for_clients(void) ++{ ++ return num_listen_socks > 0; ++} ++ + static void + close_startup_pipes(void) + { +@@ -550,22 +560,47 @@ sshd_exchange_identification(int sock_in + } + } + +-/* Destroy the host and server keys. They will no longer be needed. */ ++/* ++ * Destroy the host and server keys. They will no longer be needed. Careful, ++ * this can be called from cleanup_exit() - i.e. from just about anywhere. ++ */ + void +-destroy_sensitive_data(void) ++destroy_sensitive_data(int privsep) + { + int i; ++ pid_t pid; ++ uid_t uid; + + if (sensitive_data.server_key) { + key_free(sensitive_data.server_key); + sensitive_data.server_key = NULL; + } ++ pid = getpid(); ++ uid = getuid(); + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (key_is_private(sensitive_data.host_keys[i])) ++ fp = key_fingerprint(sensitive_data.host_keys[i], ++ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, ++ SSH_FP_HEX); ++ else ++ fp = NULL; + key_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = NULL; ++ if (fp != NULL) { ++ if (privsep) ++ PRIVSEP(audit_destroy_sensitive_data(fp, ++ pid, uid)); ++ else ++ audit_destroy_sensitive_data(fp, ++ pid, uid); ++ free(fp); ++ } + } +- if (sensitive_data.host_certificates[i]) { ++ if (sensitive_data.host_certificates ++ && sensitive_data.host_certificates[i]) { + key_free(sensitive_data.host_certificates[i]); + sensitive_data.host_certificates[i] = NULL; + } +@@ -579,6 +614,8 @@ void + demote_sensitive_data(void) + { + Key *tmp; ++ pid_t pid; ++ uid_t uid; + int i; + + if (sensitive_data.server_key) { +@@ -587,13 +624,27 @@ demote_sensitive_data(void) + sensitive_data.server_key = tmp; + } + ++ pid = getpid(); ++ uid = getuid(); + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (key_is_private(sensitive_data.host_keys[i])) ++ fp = key_fingerprint(sensitive_data.host_keys[i], ++ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, ++ SSH_FP_HEX); ++ else ++ fp = NULL; + tmp = key_demote(sensitive_data.host_keys[i]); + key_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = tmp; + if (tmp->type == KEY_RSA1) + sensitive_data.ssh1_host_key = tmp; ++ if (fp != NULL) { ++ audit_destroy_sensitive_data(fp, pid, uid); ++ free(fp); ++ } + } + /* Certs do not need demotion */ + } +@@ -708,6 +759,8 @@ privsep_preauth(Authctxt *authctxt) + } + } + ++extern Newkeys *current_keys[]; ++ + static void + privsep_postauth(Authctxt *authctxt) + { +@@ -732,6 +785,10 @@ privsep_postauth(Authctxt *authctxt) + else if (pmonitor->m_pid != 0) { + verbose("User child is on pid %ld", (long)pmonitor->m_pid); + buffer_clear(&loginmsg); ++ newkeys_destroy(current_keys[MODE_OUT]); ++ newkeys_destroy(current_keys[MODE_IN]); ++ audit_session_key_free_body(2, getpid(), getuid()); ++ packet_destroy_all(0, 0); + monitor_child_postauth(pmonitor); + + /* NEVERREACHED */ +@@ -1178,6 +1235,7 @@ server_accept_loop(int *sock_in, int *so + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ destroy_sensitive_data(0); + close_listen_socks(); + unlink(options.pid_file); + exit(received_sigterm == SIGTERM ? 0 : 255); +@@ -2093,6 +2151,7 @@ main(int ac, char **av) + */ + if (use_privsep) { + mm_send_keystate(pmonitor); ++ packet_destroy_all(1, 1); + exit(0); + } + +@@ -2135,7 +2194,7 @@ main(int ac, char **av) + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ + if (!compat20) +- destroy_sensitive_data(); ++ destroy_sensitive_data(0); + } + + packet_set_timeout(options.client_alive_interval, +@@ -2145,6 +2204,9 @@ main(int ac, char **av) + do_authenticated(authctxt); + + /* The connection has been terminated. */ ++ packet_destroy_all(1, 1); ++ destroy_sensitive_data(1); ++ + packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); + packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + verbose("Transferred: sent %llu, received %llu bytes", +@@ -2302,6 +2364,10 @@ do_ssh1_kex(void) + if (cookie[i] != packet_get_char()) + packet_disconnect("IP Spoofing check bytes do not match."); + ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(2, cipher_name(cipher_type), "crc", "none"); ++#endif ++ + debug("Encryption type: %.200s", cipher_name(cipher_type)); + + /* Get the encrypted integer. */ +@@ -2368,7 +2434,7 @@ do_ssh1_kex(void) + session_id[i] = session_key[i] ^ session_key[i + 16]; + } + /* Destroy the private and public keys. No longer. */ +- destroy_sensitive_data(); ++ destroy_sensitive_data(0); + + if (use_privsep) + mm_ssh1_session_id(session_id); +@@ -2480,6 +2546,16 @@ do_ssh2_kex(void) + void + cleanup_exit(int i) + { ++ static int in_cleanup = 0; ++ int is_privsep_child; ++ ++ /* cleanup_exit can be called at the very least from the privsep ++ wrappers used for auditing. Make sure we don't recurse ++ indefinitely. */ ++ if (in_cleanup) ++ _exit(i); ++ in_cleanup = 1; ++ + if (the_authctxt) { + do_cleanup(the_authctxt); + if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) { +@@ -2490,9 +2566,14 @@ cleanup_exit(int i) + pmonitor->m_pid, strerror(errno)); + } + } ++ is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor(); ++ if (sensitive_data.host_keys != NULL) ++ destroy_sensitive_data(is_privsep_child); ++ packet_destroy_all(1, is_privsep_child); + #ifdef SSH_AUDIT_EVENTS + /* done after do_cleanup so it can cancel the PAM auth 'thread' */ +- if (!use_privsep || mm_is_monitor()) ++ if ((the_authctxt == NULL || !the_authctxt->authenticated) && ++ (!use_privsep || mm_is_monitor())) + audit_event(SSH_CONNECTION_ABANDON); + #endif + _exit(i); diff --git a/openssh-6.3p1-coverity.patch b/openssh-6.3p1-coverity.patch new file mode 100644 index 0000000..69bcb81 --- /dev/null +++ b/openssh-6.3p1-coverity.patch @@ -0,0 +1,788 @@ +diff -up openssh-6.3p1/auth-pam.c.coverity openssh-6.3p1/auth-pam.c +--- openssh-6.3p1/auth-pam.c.coverity 2013-06-02 00:07:32.000000000 +0200 ++++ openssh-6.3p1/auth-pam.c 2013-10-07 13:20:36.288298063 +0200 +@@ -216,7 +216,12 @@ pthread_join(sp_pthread_t thread, void * + if (sshpam_thread_status != -1) + return (sshpam_thread_status); + signal(SIGCHLD, sshpam_oldsig); +- waitpid(thread, &status, 0); ++ while (waitpid(thread, &status, 0) < 0) { ++ if (errno == EINTR) ++ continue; ++ fatal("%s: waitpid: %s", __func__, ++ strerror(errno)); ++ } + return (status); + } + #endif +diff -up openssh-6.3p1/channels.c.coverity openssh-6.3p1/channels.c +--- openssh-6.3p1/channels.c.coverity 2013-09-13 08:19:31.000000000 +0200 ++++ openssh-6.3p1/channels.c 2013-10-07 13:20:36.289298058 +0200 +@@ -233,11 +233,11 @@ channel_register_fds(Channel *c, int rfd + channel_max_fd = MAX(channel_max_fd, wfd); + channel_max_fd = MAX(channel_max_fd, efd); + +- if (rfd != -1) ++ if (rfd >= 0) + fcntl(rfd, F_SETFD, FD_CLOEXEC); +- if (wfd != -1 && wfd != rfd) ++ if (wfd >= 0 && wfd != rfd) + fcntl(wfd, F_SETFD, FD_CLOEXEC); +- if (efd != -1 && efd != rfd && efd != wfd) ++ if (efd >= 0 && efd != rfd && efd != wfd) + fcntl(efd, F_SETFD, FD_CLOEXEC); + + c->rfd = rfd; +@@ -255,11 +255,11 @@ channel_register_fds(Channel *c, int rfd + + /* enable nonblocking mode */ + if (nonblock) { +- if (rfd != -1) ++ if (rfd >= 0) + set_nonblock(rfd); +- if (wfd != -1) ++ if (wfd >= 0) + set_nonblock(wfd); +- if (efd != -1) ++ if (efd >= 0) + set_nonblock(efd); + } + } +diff -up openssh-6.3p1/clientloop.c.coverity openssh-6.3p1/clientloop.c +--- openssh-6.3p1/clientloop.c.coverity 2013-06-10 05:07:12.000000000 +0200 ++++ openssh-6.3p1/clientloop.c 2013-10-07 13:20:36.289298058 +0200 +@@ -2068,14 +2068,15 @@ client_input_global_request(int type, u_ + char *rtype; + int want_reply; + int success = 0; ++/* success is still 0 the packet is allways SSH2_MSG_REQUEST_FAILURE, isn't it? */ + + rtype = packet_get_string(NULL); + want_reply = packet_get_char(); + debug("client_input_global_request: rtype %s want_reply %d", + rtype, want_reply); + if (want_reply) { +- packet_start(success ? +- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); ++ packet_start(/*success ? ++ SSH2_MSG_REQUEST_SUCCESS :*/ SSH2_MSG_REQUEST_FAILURE); + packet_send(); + packet_write_wait(); + } +diff -up openssh-6.3p1/key.c.coverity openssh-6.3p1/key.c +--- openssh-6.3p1/key.c.coverity 2013-06-01 23:41:51.000000000 +0200 ++++ openssh-6.3p1/key.c 2013-10-07 13:20:36.290298054 +0200 +@@ -807,8 +807,10 @@ key_read(Key *ret, char **cpp) + success = 1; + /*XXXX*/ + key_free(k); ++/*XXXX + if (success != 1) + break; ++XXXX*/ + /* advance cp: skip whitespace and data */ + while (*cp == ' ' || *cp == '\t') + cp++; +diff -up openssh-6.3p1/monitor.c.coverity openssh-6.3p1/monitor.c +--- openssh-6.3p1/monitor.c.coverity 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/monitor.c 2013-10-07 13:54:36.761314042 +0200 +@@ -449,7 +449,7 @@ monitor_child_preauth(Authctxt *_authctx + mm_get_keystate(pmonitor); + + /* Drain any buffered messages from the child */ +- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) + ; + + close(pmonitor->m_sendfd); +@@ -1202,6 +1202,10 @@ mm_answer_keyallowed(int sock, Buffer *m + break; + } + } ++ ++ debug3("%s: key %p is %s", ++ __func__, key, allowed ? "allowed" : "not allowed"); ++ + if (key != NULL) + key_free(key); + +@@ -1223,9 +1227,6 @@ mm_answer_keyallowed(int sock, Buffer *m + free(chost); + } + +- debug3("%s: key %p is %s", +- __func__, key, allowed ? "allowed" : "not allowed"); +- + buffer_clear(m); + buffer_put_int(m, allowed); + buffer_put_int(m, forced_command != NULL); +diff -up openssh-6.3p1/monitor_wrap.c.coverity openssh-6.3p1/monitor_wrap.c +--- openssh-6.3p1/monitor_wrap.c.coverity 2013-06-02 00:07:32.000000000 +0200 ++++ openssh-6.3p1/monitor_wrap.c 2013-10-07 13:20:36.291298049 +0200 +@@ -710,10 +710,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, + if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || + (tmp2 = dup(pmonitor->m_recvfd)) == -1) { + error("%s: cannot allocate fds for pty", __func__); +- if (tmp1 > 0) ++ if (tmp1 >= 0) + close(tmp1); +- if (tmp2 > 0) +- close(tmp2); ++ /*DEAD CODE if (tmp2 >= 0) ++ close(tmp2);*/ + return 0; + } + close(tmp1); +diff -up openssh-6.3p1/openbsd-compat/bindresvport.c.coverity openssh-6.3p1/openbsd-compat/bindresvport.c +--- openssh-6.3p1/openbsd-compat/bindresvport.c.coverity 2010-12-03 00:50:26.000000000 +0100 ++++ openssh-6.3p1/openbsd-compat/bindresvport.c 2013-10-07 13:20:36.291298049 +0200 +@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr + struct sockaddr_in6 *in6; + u_int16_t *portp; + u_int16_t port; +- socklen_t salen; ++ socklen_t salen = sizeof(struct sockaddr_storage); + int i; + + if (sa == NULL) { +diff -up openssh-6.3p1/packet.c.coverity openssh-6.3p1/packet.c +--- openssh-6.3p1/packet.c.coverity 2013-07-18 08:12:45.000000000 +0200 ++++ openssh-6.3p1/packet.c 2013-10-07 13:20:36.291298049 +0200 +@@ -1199,6 +1199,7 @@ packet_read_poll1(void) + case DEATTACK_DETECTED: + packet_disconnect("crc32 compensation attack: " + "network attack detected"); ++ break; + case DEATTACK_DOS_DETECTED: + packet_disconnect("deattack denial of " + "service detected"); +diff -up openssh-6.3p1/progressmeter.c.coverity openssh-6.3p1/progressmeter.c +--- openssh-6.3p1/progressmeter.c.coverity 2013-06-02 15:46:24.000000000 +0200 ++++ openssh-6.3p1/progressmeter.c 2013-10-07 13:42:32.377850691 +0200 +@@ -65,7 +65,7 @@ static void update_progress_meter(int); + + static time_t start; /* start progress */ + static time_t last_update; /* last progress update */ +-static char *file; /* name of the file being transferred */ ++static const 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 volatile off_t *counter; /* progress counter */ +@@ -247,7 +247,7 @@ update_progress_meter(int ignore) + } + + void +-start_progress_meter(char *f, off_t filesize, off_t *ctr) ++start_progress_meter(const char *f, off_t filesize, off_t *ctr) + { + start = last_update = monotime(); + file = f; +diff -up openssh-6.3p1/progressmeter.h.coverity openssh-6.3p1/progressmeter.h +--- openssh-6.3p1/progressmeter.h.coverity 2006-03-26 05:30:02.000000000 +0200 ++++ openssh-6.3p1/progressmeter.h 2013-10-07 13:20:36.292298044 +0200 +@@ -23,5 +23,5 @@ + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-void start_progress_meter(char *, off_t, off_t *); ++void start_progress_meter(const char *, off_t, off_t *); + void stop_progress_meter(void); +diff -up openssh-6.3p1/scp.c.coverity openssh-6.3p1/scp.c +--- openssh-6.3p1/scp.c.coverity 2013-07-18 08:11:25.000000000 +0200 ++++ openssh-6.3p1/scp.c 2013-10-07 13:20:36.292298044 +0200 +@@ -155,7 +155,7 @@ killchild(int signo) + { + if (do_cmd_pid > 1) { + kill(do_cmd_pid, signo ? signo : SIGTERM); +- waitpid(do_cmd_pid, NULL, 0); ++ (void) waitpid(do_cmd_pid, NULL, 0); + } + + if (signo) +diff -up openssh-6.3p1/servconf.c.coverity openssh-6.3p1/servconf.c +--- openssh-6.3p1/servconf.c.coverity 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/servconf.c 2013-10-07 13:20:36.293298039 +0200 +@@ -1323,7 +1323,7 @@ process_server_config_line(ServerOptions + fatal("%s line %d: Missing subsystem name.", + filename, linenum); + if (!*activep) { +- arg = strdelim(&cp); ++ /*arg =*/ (void) strdelim(&cp); + break; + } + for (i = 0; i < options->num_subsystems; i++) +@@ -1414,8 +1414,9 @@ process_server_config_line(ServerOptions + if (*activep && *charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ +- if (intptr != NULL) +- *intptr = *intptr + 1; ++ /* DEAD CODE intptr is still NULL ;) ++ if (intptr != NULL) ++ *intptr = *intptr + 1; */ + } + break; + +diff -up openssh-6.3p1/serverloop.c.coverity openssh-6.3p1/serverloop.c +--- openssh-6.3p1/serverloop.c.coverity 2013-07-18 08:12:45.000000000 +0200 ++++ openssh-6.3p1/serverloop.c 2013-10-07 13:43:36.620537138 +0200 +@@ -147,13 +147,13 @@ notify_setup(void) + static void + notify_parent(void) + { +- if (notify_pipe[1] != -1) ++ if (notify_pipe[1] >= 0) + (void)write(notify_pipe[1], "", 1); + } + static void + notify_prepare(fd_set *readset) + { +- if (notify_pipe[0] != -1) ++ if (notify_pipe[0] >= 0) + FD_SET(notify_pipe[0], readset); + } + static void +@@ -161,8 +161,8 @@ notify_done(fd_set *readset) + { + char c; + +- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) +- while (read(notify_pipe[0], &c, 1) != -1) ++ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) ++ while (read(notify_pipe[0], &c, 1) >= 0) + debug2("notify_done: reading"); + } + +@@ -336,7 +336,7 @@ wait_until_can_do_something(fd_set **rea + * If we have buffered data, try to write some of that data + * to the program. + */ +- if (fdin != -1 && buffer_len(&stdin_buffer) > 0) ++ if (fdin >= 0 && buffer_len(&stdin_buffer) > 0) + FD_SET(fdin, *writesetp); + } + notify_prepare(*readsetp); +@@ -476,7 +476,7 @@ process_output(fd_set *writeset) + int len; + + /* Write buffered data to program stdin. */ +- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { ++ if (!compat20 && fdin >= 0 && FD_ISSET(fdin, writeset)) { + data = buffer_ptr(&stdin_buffer); + dlen = buffer_len(&stdin_buffer); + len = write(fdin, data, dlen); +@@ -589,7 +589,7 @@ server_loop(pid_t pid, int fdin_arg, int + set_nonblock(fdin); + set_nonblock(fdout); + /* we don't have stderr for interactive terminal sessions, see below */ +- if (fderr != -1) ++ if (fderr >= 0) + set_nonblock(fderr); + + if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) +@@ -613,7 +613,7 @@ server_loop(pid_t pid, int fdin_arg, int + max_fd = MAX(connection_in, connection_out); + max_fd = MAX(max_fd, fdin); + max_fd = MAX(max_fd, fdout); +- if (fderr != -1) ++ if (fderr >= 0) + max_fd = MAX(max_fd, fderr); + #endif + +@@ -643,7 +643,7 @@ server_loop(pid_t pid, int fdin_arg, int + * If we have received eof, and there is no more pending + * input data, cause a real eof by closing fdin. + */ +- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { ++ if (stdin_eof && fdin >= 0 && buffer_len(&stdin_buffer) == 0) { + if (fdin != fdout) + close(fdin); + else +@@ -739,15 +739,15 @@ server_loop(pid_t pid, int fdin_arg, int + buffer_free(&stderr_buffer); + + /* Close the file descriptors. */ +- if (fdout != -1) ++ if (fdout >= 0) + close(fdout); + fdout = -1; + fdout_eof = 1; +- if (fderr != -1) ++ if (fderr >= 0) + close(fderr); + fderr = -1; + fderr_eof = 1; +- if (fdin != -1) ++ if (fdin >= 0) + close(fdin); + fdin = -1; + +@@ -946,7 +946,7 @@ server_input_window_size(int type, u_int + + debug("Window change received."); + packet_check_eom(); +- if (fdin != -1) ++ if (fdin >= 0) + pty_change_window_size(fdin, row, col, xpixel, ypixel); + } + +@@ -1006,7 +1006,7 @@ server_request_tun(void) + } + + tun = packet_get_int(); +- if (forced_tun_device != -1) { ++ if (forced_tun_device >= 0) { + if (tun != SSH_TUNID_ANY && forced_tun_device != tun) + goto done; + tun = forced_tun_device; +diff -up openssh-6.3p1/sftp-client.c.coverity openssh-6.3p1/sftp-client.c +--- openssh-6.3p1/sftp-client.c.coverity 2013-07-26 00:40:00.000000000 +0200 ++++ openssh-6.3p1/sftp-client.c 2013-10-07 13:48:45.885027420 +0200 +@@ -149,7 +149,7 @@ get_msg(struct sftp_conn *conn, Buffer * + } + + static void +-send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, ++send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, + u_int len) + { + Buffer msg; +@@ -165,7 +165,7 @@ send_string_request(struct sftp_conn *co + + static void + send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, +- char *s, u_int len, Attrib *a) ++ const char *s, u_int len, Attrib *a) + { + Buffer msg; + +@@ -422,7 +422,7 @@ sftp_proto_version(struct sftp_conn *con + } + + int +-do_close(struct sftp_conn *conn, char *handle, u_int handle_len) ++do_close(struct sftp_conn *conn, const char *handle, u_int handle_len) + { + u_int id, status; + Buffer msg; +@@ -447,7 +447,7 @@ do_close(struct sftp_conn *conn, char *h + + + static int +-do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, ++do_lsreaddir(struct sftp_conn *conn, const char *path, int printflag, + SFTP_DIRENT ***dir) + { + Buffer msg; +@@ -572,7 +572,7 @@ do_lsreaddir(struct sftp_conn *conn, cha + } + + int +-do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) ++do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) + { + return(do_lsreaddir(conn, path, 0, dir)); + } +@@ -590,7 +590,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) + } + + int +-do_rm(struct sftp_conn *conn, char *path) ++do_rm(struct sftp_conn *conn, const char *path) + { + u_int status, id; + +@@ -605,7 +605,7 @@ do_rm(struct sftp_conn *conn, char *path + } + + int +-do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag) ++do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int printflag) + { + u_int status, id; + +@@ -621,7 +621,7 @@ do_mkdir(struct sftp_conn *conn, char *p + } + + int +-do_rmdir(struct sftp_conn *conn, char *path) ++do_rmdir(struct sftp_conn *conn, const char *path) + { + u_int status, id; + +@@ -637,7 +637,7 @@ do_rmdir(struct sftp_conn *conn, char *p + } + + Attrib * +-do_stat(struct sftp_conn *conn, char *path, int quiet) ++do_stat(struct sftp_conn *conn, const char *path, int quiet) + { + u_int id; + +@@ -651,7 +651,7 @@ do_stat(struct sftp_conn *conn, char *pa + } + + Attrib * +-do_lstat(struct sftp_conn *conn, char *path, int quiet) ++do_lstat(struct sftp_conn *conn, const char *path, int quiet) + { + u_int id; + +@@ -685,7 +685,7 @@ do_fstat(struct sftp_conn *conn, char *h + #endif + + int +-do_setstat(struct sftp_conn *conn, char *path, Attrib *a) ++do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) + { + u_int status, id; + +@@ -702,7 +702,7 @@ do_setstat(struct sftp_conn *conn, char + } + + int +-do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, ++do_fsetstat(struct sftp_conn *conn, const char *handle, u_int handle_len, + Attrib *a) + { + u_int status, id; +@@ -719,7 +719,7 @@ do_fsetstat(struct sftp_conn *conn, char + } + + char * +-do_realpath(struct sftp_conn *conn, char *path) ++do_realpath(struct sftp_conn *conn, const char *path) + { + Buffer msg; + u_int type, expected_id, count, id; +@@ -768,7 +768,7 @@ do_realpath(struct sftp_conn *conn, char + } + + int +-do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -802,7 +802,7 @@ do_rename(struct sftp_conn *conn, char * + } + + int +-do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -835,7 +835,7 @@ do_hardlink(struct sftp_conn *conn, char + } + + int +-do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -987,7 +987,7 @@ send_read_request(struct sftp_conn *conn + } + + int +-do_download(struct sftp_conn *conn, char *remote_path, char *local_path, ++do_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, + Attrib *a, int pflag, int resume) + { + Attrib junk; +@@ -1255,7 +1255,7 @@ do_download(struct sftp_conn *conn, char + } + + static int +-download_dir_internal(struct sftp_conn *conn, char *src, char *dst, ++download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int pflag, int printflag, int depth, int resume) + { + int i, ret = 0; +@@ -1345,7 +1345,7 @@ download_dir_internal(struct sftp_conn * + } + + int +-download_dir(struct sftp_conn *conn, char *src, char *dst, ++download_dir(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int pflag, int printflag, int resume) + { + char *src_canon; +@@ -1363,7 +1363,7 @@ download_dir(struct sftp_conn *conn, cha + } + + int +-do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, ++do_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, + int pflag) + { + int local_fd; +@@ -1548,7 +1548,7 @@ do_upload(struct sftp_conn *conn, char * + } + + static int +-upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, ++upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int pflag, int printflag, int depth) + { + int ret = 0, status; +@@ -1639,7 +1639,7 @@ upload_dir_internal(struct sftp_conn *co + } + + int +-upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, ++upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int printflag, + int pflag) + { + char *dst_canon; +@@ -1656,7 +1656,7 @@ upload_dir(struct sftp_conn *conn, char + } + + char * +-path_append(char *p1, char *p2) ++path_append(const char *p1, const char *p2) + { + char *ret; + size_t len = strlen(p1) + strlen(p2) + 2; +diff -up openssh-6.3p1/sftp-client.h.coverity openssh-6.3p1/sftp-client.h +--- openssh-6.3p1/sftp-client.h.coverity 2013-07-25 03:56:52.000000000 +0200 ++++ openssh-6.3p1/sftp-client.h 2013-10-07 13:45:10.108080813 +0200 +@@ -56,49 +56,49 @@ struct sftp_conn *do_init(int, int, u_in + u_int sftp_proto_version(struct sftp_conn *); + + /* Close file referred to by 'handle' */ +-int do_close(struct sftp_conn *, char *, u_int); ++int do_close(struct sftp_conn *, const char *, u_int); + + /* Read contents of 'path' to NULL-terminated array 'dir' */ +-int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); ++int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); + + /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ + void free_sftp_dirents(SFTP_DIRENT **); + + /* Delete file 'path' */ +-int do_rm(struct sftp_conn *, char *); ++int do_rm(struct sftp_conn *, const char *); + + /* Create directory 'path' */ +-int do_mkdir(struct sftp_conn *, char *, Attrib *, int); ++int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); + + /* Remove directory 'path' */ +-int do_rmdir(struct sftp_conn *, char *); ++int do_rmdir(struct sftp_conn *, const char *); + + /* Get file attributes of 'path' (follows symlinks) */ +-Attrib *do_stat(struct sftp_conn *, char *, int); ++Attrib *do_stat(struct sftp_conn *, const char *, int); + + /* Get file attributes of 'path' (does not follow symlinks) */ +-Attrib *do_lstat(struct sftp_conn *, char *, int); ++Attrib *do_lstat(struct sftp_conn *, const char *, int); + + /* Set file attributes of 'path' */ +-int do_setstat(struct sftp_conn *, char *, Attrib *); ++int do_setstat(struct sftp_conn *, const char *, Attrib *); + + /* Set file attributes of open file 'handle' */ +-int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); ++int do_fsetstat(struct sftp_conn *, const char *, u_int, Attrib *); + + /* Canonicalise 'path' - caller must free result */ +-char *do_realpath(struct sftp_conn *, char *); ++char *do_realpath(struct sftp_conn *, const char *); + + /* Get statistics for filesystem hosting file at "path" */ + int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); + + /* Rename 'oldpath' to 'newpath' */ +-int do_rename(struct sftp_conn *, char *, char *); ++int do_rename(struct sftp_conn *, const char *, const char *); + + /* Link 'oldpath' to 'newpath' */ +-int do_hardlink(struct sftp_conn *, char *, char *); ++int do_hardlink(struct sftp_conn *, const char *, const char *); + +-/* Rename 'oldpath' to 'newpath' */ +-int do_symlink(struct sftp_conn *, char *, char *); ++/* Symlink 'oldpath' to 'newpath' */ ++int do_symlink(struct sftp_conn *, const char *, const char *); + + /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ + +@@ -106,27 +106,27 @@ int do_symlink(struct sftp_conn *, char + * Download 'remote_path' to 'local_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int); ++int do_download(struct sftp_conn *, const char *, const char *, Attrib *, int, int); + + /* + * Recursively download 'remote_directory' to 'local_directory'. Preserve + * times if 'pflag' is set + */ +-int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int, int); ++int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int, int); + + /* + * Upload 'local_path' to 'remote_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_upload(struct sftp_conn *, char *, char *, int); ++int do_upload(struct sftp_conn *, const char *, const char *, int); + + /* + * Recursively upload 'local_directory' to 'remote_directory'. Preserve + * times if 'pflag' is set + */ +-int upload_dir(struct sftp_conn *, char *, char *, int, int); ++int upload_dir(struct sftp_conn *, const char *, const char *, int, int); + + /* Concatenate paths, taking care of slashes. Caller must free result. */ +-char *path_append(char *, char *); ++char *path_append(const char *, const char *); + + #endif +diff -up openssh-6.3p1/sftp.c.coverity openssh-6.3p1/sftp.c +--- openssh-6.3p1/sftp.c.coverity 2013-07-25 03:56:52.000000000 +0200 ++++ openssh-6.3p1/sftp.c 2013-10-07 13:49:47.322727449 +0200 +@@ -213,7 +213,7 @@ killchild(int signo) + { + if (sshpid > 1) { + kill(sshpid, SIGTERM); +- waitpid(sshpid, NULL, 0); ++ (void) waitpid(sshpid, NULL, 0); + } + + _exit(1); +@@ -324,7 +324,7 @@ local_do_ls(const char *args) + + /* Strip one path (usually the pwd) from the start of another */ + static char * +-path_strip(char *path, char *strip) ++path_strip(const char *path, const char *strip) + { + size_t len; + +@@ -342,7 +342,7 @@ path_strip(char *path, char *strip) + } + + static char * +-make_absolute(char *p, char *pwd) ++make_absolute(char *p, const char *pwd) + { + char *abs_str; + +@@ -493,7 +493,7 @@ parse_df_flags(const char *cmd, char **a + } + + static int +-is_dir(char *path) ++is_dir(const char *path) + { + struct stat sb; + +@@ -505,7 +505,7 @@ is_dir(char *path) + } + + static int +-remote_is_dir(struct sftp_conn *conn, char *path) ++remote_is_dir(struct sftp_conn *conn, const char *path) + { + Attrib *a; + +@@ -519,7 +519,7 @@ remote_is_dir(struct sftp_conn *conn, ch + + /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ + static int +-pathname_is_dir(char *pathname) ++pathname_is_dir(const char *pathname) + { + size_t l = strlen(pathname); + +@@ -527,7 +527,7 @@ pathname_is_dir(char *pathname) + } + + static int +-process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, ++process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, + int pflag, int rflag, int resume) + { + char *abs_src = NULL; +@@ -605,7 +605,7 @@ out: + } + + static int +-process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, ++process_put(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, + int pflag, int rflag) + { + char *tmp_dst = NULL; +@@ -709,7 +709,7 @@ sdirent_comp(const void *aa, const void + + /* sftp ls.1 replacement for directories */ + static int +-do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) ++do_ls_dir(struct sftp_conn *conn, const char *path, const char *strip_path, int lflag) + { + int n; + u_int c = 1, colspace = 0, columns = 1; +@@ -794,7 +794,7 @@ do_ls_dir(struct sftp_conn *conn, char * + + /* sftp ls.1 replacement which handles path globs */ + static int +-do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, ++do_globbed_ls(struct sftp_conn *conn, const char *path, const char *strip_path, + int lflag) + { + char *fname, *lname; +@@ -875,7 +875,7 @@ do_globbed_ls(struct sftp_conn *conn, ch + } + + static int +-do_df(struct sftp_conn *conn, char *path, int hflag, int iflag) ++do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) + { + struct sftp_statvfs st; + char s_used[FMT_SCALED_STRSIZE]; +diff -up openssh-6.3p1/ssh-agent.c.coverity openssh-6.3p1/ssh-agent.c +--- openssh-6.3p1/ssh-agent.c.coverity 2013-07-20 05:22:49.000000000 +0200 ++++ openssh-6.3p1/ssh-agent.c 2013-10-07 13:20:36.296298024 +0200 +@@ -1143,8 +1143,8 @@ main(int ac, char **av) + sanitise_stdfd(); + + /* drop */ +- setegid(getgid()); +- setgid(getgid()); ++ (void) setegid(getgid()); ++ (void) setgid(getgid()); + + #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* Disable ptrace on Linux without sgid bit */ +diff -up openssh-6.3p1/sshd.c.coverity openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.coverity 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-07 13:20:36.296298024 +0200 +@@ -699,8 +699,10 @@ privsep_preauth(Authctxt *authctxt) + if (getuid() == 0 || geteuid() == 0) + privsep_preauth_child(); + setproctitle("%s", "[net]"); +- if (box != NULL) ++ if (box != NULL) { + ssh_sandbox_child(box); ++ free(box); ++ } + + return 0; + } +@@ -1345,6 +1347,9 @@ server_accept_loop(int *sock_in, int *so + if (num_listen_socks < 0) + break; + } ++ ++ if (fdset != NULL) ++ free(fdset); + } + + diff --git a/openssh-6.3p1-ctr-cavstest.patch b/openssh-6.3p1-ctr-cavstest.patch new file mode 100644 index 0000000..5cd9997 --- /dev/null +++ b/openssh-6.3p1-ctr-cavstest.patch @@ -0,0 +1,250 @@ +diff -up openssh-6.2p1/ctr-cavstest.c.ctr-cavs openssh-6.2p1/ctr-cavstest.c +--- openssh-6.2p1/ctr-cavstest.c.ctr-cavs 2013-03-25 21:35:52.512586671 +0100 ++++ openssh-6.2p1/ctr-cavstest.c 2013-03-25 21:35:52.512586671 +0100 +@@ -0,0 +1,208 @@ ++/* ++ * ++ * invocation (all of the following are equal): ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000 ++ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt ++ */ ++ ++#include "includes.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xmalloc.h" ++#include "log.h" ++#include "cipher.h" ++ ++/* compatibility with old or broken OpenSSL versions */ ++#include "openbsd-compat/openssl-compat.h" ++ ++void usage(void) { ++ fprintf(stderr, "Usage: ctr-cavstest --algo \n" ++ " --key --mode \n" ++ " [--iv ] --data \n\n" ++ "Hexadecimal output is printed to stdout.\n" ++ "Hexadecimal input data can be alternatively read from stdin.\n"); ++ exit(1); ++} ++ ++void *fromhex(char *hex, size_t *len) ++{ ++ unsigned char *bin; ++ char *p; ++ size_t n = 0; ++ int shift = 4; ++ unsigned char out = 0; ++ unsigned char *optr; ++ ++ bin = xmalloc(strlen(hex)/2); ++ optr = bin; ++ ++ for (p = hex; *p != '\0'; ++p) { ++ unsigned char c; ++ ++ c = *p; ++ if (isspace(c)) ++ continue; ++ ++ if (c >= '0' && c <= '9') { ++ c = c - '0'; ++ } else if (c >= 'A' && c <= 'F') { ++ c = c - 'A' + 10; ++ } else if (c >= 'a' && c <= 'f') { ++ c = c - 'a' + 10; ++ } else { ++ /* truncate on nonhex cipher */ ++ break; ++ } ++ ++ out |= c << shift; ++ shift = (shift + 4) % 8; ++ ++ if (shift) { ++ *(optr++) = out; ++ out = 0; ++ ++n; ++ } ++ } ++ ++ *len = n; ++ return bin; ++} ++ ++#define READ_CHUNK 4096 ++#define MAX_READ_SIZE 1024*1024*100 ++char *read_stdin(void) ++{ ++ char *buf; ++ size_t n, total = 0; ++ ++ buf = xmalloc(READ_CHUNK); ++ ++ do { ++ n = fread(buf + total, 1, READ_CHUNK, stdin); ++ if (n < READ_CHUNK) /* terminate on short read */ ++ break; ++ ++ total += n; ++ buf = xrealloc(buf, total + READ_CHUNK, 1); ++ } while(total < MAX_READ_SIZE); ++ return buf; ++} ++ ++int main (int argc, char *argv[]) ++{ ++ ++ Cipher *c; ++ CipherContext cc; ++ char *algo = "aes128-ctr"; ++ char *hexkey = NULL; ++ char *hexiv = "00000000000000000000000000000000"; ++ char *hexdata = NULL; ++ char *p; ++ int i; ++ int encrypt = 1; ++ void *key; ++ size_t keylen; ++ void *iv; ++ size_t ivlen; ++ void *data; ++ size_t datalen; ++ void *outdata; ++ ++ for (i = 1; i < argc; ++i) { ++ if (strcmp(argv[i], "--algo") == 0) { ++ algo = argv[++i]; ++ } else if (strcmp(argv[i], "--key") == 0) { ++ hexkey = argv[++i]; ++ } else if (strcmp(argv[i], "--mode") == 0) { ++ ++i; ++ if (argv[i] == NULL) { ++ usage(); ++ } ++ if (strncmp(argv[i], "enc", 3) == 0) { ++ encrypt = 1; ++ } else if (strncmp(argv[i], "dec", 3) == 0) { ++ encrypt = 0; ++ } else { ++ usage(); ++ } ++ } else if (strcmp(argv[i], "--iv") == 0) { ++ hexiv = argv[++i]; ++ } else if (strcmp(argv[i], "--data") == 0) { ++ hexdata = argv[++i]; ++ } ++ } ++ ++ if (hexkey == NULL || algo == NULL) { ++ usage(); ++ } ++ ++ SSLeay_add_all_algorithms(); ++ ++ c = cipher_by_name(algo); ++ if (c == NULL) { ++ fprintf(stderr, "Error: unknown algorithm\n"); ++ return 2; ++ } ++ ++ if (hexdata == NULL) { ++ hexdata = read_stdin(); ++ } else { ++ hexdata = xstrdup(hexdata); ++ } ++ ++ key = fromhex(hexkey, &keylen); ++ ++ if (keylen != 16 && keylen != 24 && keylen == 32) { ++ fprintf(stderr, "Error: unsupported key length\n"); ++ return 2; ++ } ++ ++ iv = fromhex(hexiv, &ivlen); ++ ++ if (ivlen != 16) { ++ fprintf(stderr, "Error: unsupported iv length\n"); ++ return 2; ++ } ++ ++ data = fromhex(hexdata, &datalen); ++ ++ if (data == NULL || datalen == 0) { ++ fprintf(stderr, "Error: no data to encrypt/decrypt\n"); ++ return 2; ++ } ++ ++ cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt); ++ ++ free(key); ++ free(iv); ++ ++ outdata = malloc(datalen); ++ if(outdata == NULL) { ++ fprintf(stderr, "Error: memory allocation failure\n"); ++ return 2; ++ } ++ ++ cipher_crypt(&cc, outdata, data, datalen, 0, 0); ++ ++ free(data); ++ ++ cipher_cleanup(&cc); ++ ++ for (p = outdata; datalen > 0; ++p, --datalen) { ++ printf("%02X", (unsigned char)*p); ++ } ++ ++ free(outdata); ++ ++ printf("\n"); ++ return 0; ++} ++ +diff -up openssh-6.2p1/Makefile.in.ctr-cavs openssh-6.2p1/Makefile.in +--- openssh-6.2p1/Makefile.in.ctr-cavs 2013-03-25 21:35:52.451586280 +0100 ++++ openssh-6.2p1/Makefile.in 2013-03-25 21:37:14.956114584 +0100 +@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign + SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper + SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper + SSH_KEYCAT=$(libexecdir)/ssh-keycat ++CTR_CAVSTEST=$(libexecdir)/ctr-cavstest + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ +@@ -65,7 +66,7 @@ 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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(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-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) + + LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-aes.o \ +@@ -174,6 +175,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l + ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o + $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) + ++ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o ++ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -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 -lfipscheck $(LIBS) + +@@ -281,6 +285,7 @@ install-files: + $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ + fi + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) ++ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 diff --git a/openssh-6.3p1-ctr-evp-fast.patch b/openssh-6.3p1-ctr-evp-fast.patch new file mode 100644 index 0000000..ddcb7f1 --- /dev/null +++ b/openssh-6.3p1-ctr-evp-fast.patch @@ -0,0 +1,101 @@ +diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c +--- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100 ++++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100 +@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in + + struct ssh_aes_ctr_ctx + { +- AES_KEY aes_ctx; ++ EVP_CIPHER_CTX ecbctx; + u_char aes_counter[AES_BLOCK_SIZE]; + }; + +@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char + { + struct ssh_aes_ctr_ctx *c; + size_t n = 0; +- u_char buf[AES_BLOCK_SIZE]; ++ u_char ctrbuf[AES_BLOCK_SIZE*256]; ++ u_char buf[AES_BLOCK_SIZE*256]; + + if (len == 0) + return (1); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) + return (0); + +- while ((len--) > 0) { ++ for (; len > 0; len -= sizeof(u_int)) { ++ u_int r,a,b; ++ + if (n == 0) { +- AES_encrypt(c->aes_counter, buf, &c->aes_ctx); +- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); ++ int outl, i, buflen; ++ ++ buflen = MIN(len, sizeof(ctrbuf)); ++ ++ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) { ++ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE); ++ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); ++ } ++ ++ EVP_EncryptUpdate(&c->ecbctx, buf, &outl, ++ ctrbuf, buflen); + } +- *(dest++) = *(src++) ^ buf[n]; +- n = (n + 1) % AES_BLOCK_SIZE; ++ ++ memcpy(&a, src, sizeof(a)); ++ memcpy(&b, &buf[n], sizeof(b)); ++ r = a ^ b; ++ memcpy(dest, &r, sizeof(r)); ++ src += sizeof(a); ++ dest += sizeof(r); ++ ++ n = (n + sizeof(b)) % sizeof(buf); + } ++ memset(ctrbuf, '\0', sizeof(ctrbuf)); ++ memset(buf, '\0', sizeof(buf)); + return (1); + } + +@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } +- if (key != NULL) +- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +- &c->aes_ctx); ++ ++ EVP_CIPHER_CTX_init(&c->ecbctx); ++ ++ if (key != NULL) { ++ const EVP_CIPHER *cipher; ++ switch(EVP_CIPHER_CTX_key_length(ctx)*8) { ++ case 128: ++ cipher = EVP_aes_128_ecb(); ++ break; ++ case 192: ++ cipher = EVP_aes_192_ecb(); ++ break; ++ case 256: ++ cipher = EVP_aes_256_ecb(); ++ break; ++ default: ++ fatal("ssh_aes_ctr_init: wrong aes key length"); ++ } ++ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL)) ++ fatal("ssh_aes_ctr_init: cannot initialize aes encryption"); ++ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0); ++ } + if (iv != NULL) + memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); + return (1); +@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { ++ EVP_CIPHER_CTX_cleanup(&c->ecbctx); + memset(c, 0, sizeof(*c)); + free(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); diff --git a/openssh-6.3p1-fingerprint.patch b/openssh-6.3p1-fingerprint.patch new file mode 100644 index 0000000..b9cfbdb --- /dev/null +++ b/openssh-6.3p1-fingerprint.patch @@ -0,0 +1,406 @@ +diff -up openssh-6.3p1/auth-rsa.c.fingerprint openssh-6.3p1/auth-rsa.c +diff -up openssh-6.3p1/auth.c.fingerprint openssh-6.3p1/auth.c +--- openssh-6.3p1/auth.c.fingerprint 2013-10-07 14:02:36.998968153 +0200 ++++ openssh-6.3p1/auth.c 2013-10-07 15:42:05.243812405 +0200 +@@ -685,9 +685,10 @@ auth_key_is_revoked(Key *key) + case 1: + revoked: + /* Key revoked */ +- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ key_fp = key_selected_fingerprint(key, SSH_FP_HEX); + error("WARNING: authentication attempt with a revoked " +- "%s key %s ", key_type(key), key_fp); ++ "%s key %s%s ", key_type(key), ++ key_fingerprint_prefix(), key_fp); + free(key_fp); + return 1; + } +diff -up openssh-6.3p1/auth2-hostbased.c.fingerprint openssh-6.3p1/auth2-hostbased.c +--- openssh-6.3p1/auth2-hostbased.c.fingerprint 2013-10-07 14:02:36.998968153 +0200 ++++ openssh-6.3p1/auth2-hostbased.c 2013-10-07 15:43:49.747355927 +0200 +@@ -200,16 +200,18 @@ hostbased_key_allowed(struct passwd *pw, + + if (host_status == HOST_OK) { + if (key_is_cert(key)) { +- fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(key->cert->signature_key, ++ SSH_FP_HEX); + verbose("Accepted certificate ID \"%s\" signed by " +- "%s CA %s from %s@%s", key->cert->key_id, +- key_type(key->cert->signature_key), fp, ++ "%s CA %s%s from %s@%s", key->cert->key_id, ++ key_type(key->cert->signature_key), ++ key_fingerprint_prefix(), fp, + cuser, lookup); + } else { +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); +- verbose("Accepted %s public key %s from %s@%s", +- key_type(key), fp, cuser, lookup); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ verbose("Accepted %s public key %s%s from %s@%s", ++ key_type(key), key_fingerprint_prefix(), ++ fp, cuser, lookup); + } + free(fp); + } +diff -up openssh-6.3p1/auth2-pubkey.c.fingerprint openssh-6.3p1/auth2-pubkey.c +--- openssh-6.3p1/auth2-pubkey.c.fingerprint 2013-07-18 08:10:10.000000000 +0200 ++++ openssh-6.3p1/auth2-pubkey.c 2013-10-07 15:50:44.617495624 +0200 +@@ -359,10 +359,10 @@ check_authkeys_file(FILE *f, char *file, + continue; + if (!key_is_cert_authority) + continue; +- fp = key_fingerprint(found, SSH_FP_MD5, +- SSH_FP_HEX); +- debug("matching CA found: file %s, line %lu, %s %s", +- file, linenum, key_type(found), fp); ++ fp = key_selected_fingerprint(found, SSH_FP_HEX); ++ debug("matching CA found: file %s, line %lu, %s %s%s", ++ file, linenum, key_type(found), ++ key_fingerprint_prefix(), fp); + /* + * If the user has specified a list of principals as + * a key option, then prefer that list to matching +@@ -400,9 +400,9 @@ check_authkeys_file(FILE *f, char *file, + if (key_is_cert_authority) + continue; + found_key = 1; +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); +- debug("matching key found: file %s, line %lu %s %s", +- file, linenum, key_type(found), fp); ++ fp = key_selected_fingerprint(found, SSH_FP_HEX); ++ verbose("Found matching %s key: %s%s", ++ key_type(found), key_fingerprint_prefix(), fp); + free(fp); + break; + } +@@ -425,13 +425,13 @@ user_cert_trusted_ca(struct passwd *pw, + if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) + return 0; + +- ca_fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, SSH_FP_HEX); ++ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); + + if (key_in_file(key->cert->signature_key, + options.trusted_user_ca_keys, 1) != 1) { +- debug2("%s: CA %s %s is not listed in %s", __func__, +- key_type(key->cert->signature_key), ca_fp, ++ debug2("%s: CA %s%s %s is not listed in %s", __func__, ++ key_type(key->cert->signature_key), ++ key_fingerprint_prefix(), ca_fp, + options.trusted_user_ca_keys); + goto out; + } +diff -up openssh-6.3p1/key.c.fingerprint openssh-6.3p1/key.c +--- openssh-6.3p1/key.c.fingerprint 2013-10-07 14:02:36.971968285 +0200 ++++ openssh-6.3p1/key.c 2013-10-07 14:02:36.999968148 +0200 +@@ -598,6 +598,34 @@ key_fingerprint(const Key *k, enum fp_ty + return retval; + } + ++enum fp_type ++key_fingerprint_selection(void) ++{ ++ static enum fp_type rv; ++ static char rv_defined = 0; ++ char *env; ++ ++ if (!rv_defined) { ++ env = getenv("SSH_FINGERPRINT_TYPE"); ++ rv = (env && !strcmp (env, "sha")) ? ++ SSH_FP_SHA1 : SSH_FP_MD5; ++ rv_defined = 1; ++ } ++ return rv; ++} ++ ++char * ++key_selected_fingerprint(Key *k, enum fp_rep dgst_rep) ++{ ++ return key_fingerprint(k, key_fingerprint_selection(), dgst_rep); ++} ++ ++char * ++key_fingerprint_prefix(void) ++{ ++ return key_fingerprint_selection() == SSH_FP_SHA1 ? "sha1:" : ""; ++} ++ + /* + * Reads a multiple-precision integer in decimal from the buffer, and advances + * the pointer. The integer must already be initialized. This function is +diff -up openssh-6.3p1/key.h.fingerprint openssh-6.3p1/key.h +--- openssh-6.3p1/key.h.fingerprint 2013-10-07 14:02:36.999968148 +0200 ++++ openssh-6.3p1/key.h 2013-10-07 15:44:17.574233450 +0200 +@@ -97,6 +97,9 @@ int key_equal_public(const Key *, cons + int key_equal(const Key *, const Key *); + char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); + u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); ++enum fp_type key_fingerprint_selection(void); ++char *key_selected_fingerprint(Key *, enum fp_rep); ++char *key_fingerprint_prefix(void); + const char *key_type(const Key *); + const char *key_cert_type(const Key *); + int key_write(const Key *, FILE *); +diff -up openssh-6.3p1/ssh-add.c.fingerprint openssh-6.3p1/ssh-add.c +--- openssh-6.3p1/ssh-add.c.fingerprint 2013-10-07 14:02:37.000968143 +0200 ++++ openssh-6.3p1/ssh-add.c 2013-10-07 14:44:57.466515766 +0200 +@@ -326,10 +326,10 @@ list_identities(AuthenticationConnection + key = ssh_get_next_identity(ac, &comment, version)) { + had_identities = 1; + if (do_fp) { +- fp = key_fingerprint(key, SSH_FP_MD5, +- SSH_FP_HEX); +- printf("%d %s %s (%s)\n", +- key_size(key), fp, comment, key_type(key)); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ printf("%d %s%s %s (%s)\n", ++ key_size(key), key_fingerprint_prefix(), ++ fp, comment, key_type(key)); + free(fp); + } else { + if (!key_write(key, stdout)) +diff -up openssh-6.3p1/ssh-agent.c.fingerprint openssh-6.3p1/ssh-agent.c +--- openssh-6.3p1/ssh-agent.c.fingerprint 2013-10-07 14:02:37.000968143 +0200 ++++ openssh-6.3p1/ssh-agent.c 2013-10-07 15:41:11.627044336 +0200 +@@ -198,9 +198,9 @@ confirm_key(Identity *id) + char *p; + int ret = -1; + +- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); +- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", +- id->comment, p)) ++ p = key_selected_fingerprint(id->key, SSH_FP_HEX); ++ if (ask_permission("Allow use of key %s?\nKey fingerprint %s%s.", ++ id->comment, key_fingerprint_prefix(), p)) + ret = 0; + free(p); + +diff -up openssh-6.3p1/ssh-keygen.c.fingerprint openssh-6.3p1/ssh-keygen.c +--- openssh-6.3p1/ssh-keygen.c.fingerprint 2013-07-20 05:22:32.000000000 +0200 ++++ openssh-6.3p1/ssh-keygen.c 2013-10-07 14:25:52.864145038 +0200 +@@ -767,13 +767,14 @@ do_fingerprint(struct passwd *pw) + { + FILE *f; + Key *public; +- char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra; ++ char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra, *pfx; + int i, skip = 0, num = 0, invalid = 1; + enum fp_rep rep; + enum fp_type fptype; + struct stat st; + +- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; ++ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection(); ++ pfx = print_bubblebabble ? "" : key_fingerprint_prefix(); + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + + if (!have_identity) +@@ -785,8 +786,8 @@ do_fingerprint(struct passwd *pw) + public = key_load_public(identity_file, &comment); + if (public != NULL) { + fp = key_fingerprint(public, fptype, rep); +- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); +- printf("%u %s %s (%s)\n", key_size(public), fp, comment, ++ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); ++ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, comment, + key_type(public)); + if (log_level >= SYSLOG_LEVEL_VERBOSE) + printf("%s\n", ra); +@@ -851,8 +852,8 @@ do_fingerprint(struct passwd *pw) + } + comment = *cp ? cp : comment; + fp = key_fingerprint(public, fptype, rep); +- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); +- printf("%u %s %s (%s)\n", key_size(public), fp, ++ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); ++ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, + comment ? comment : "no comment", key_type(public)); + if (log_level >= SYSLOG_LEVEL_VERBOSE) + printf("%s\n", ra); +@@ -970,13 +971,15 @@ printhost(FILE *f, const char *name, Key + if (print_fingerprint) { + enum fp_rep rep; + enum fp_type fptype; +- char *fp, *ra; ++ char *fp, *ra, *pfx; + +- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; ++ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection(); ++ pfx = print_bubblebabble ? "" : key_fingerprint_prefix(); + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; ++ + fp = key_fingerprint(public, fptype, rep); +- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART); +- printf("%u %s %s (%s)\n", key_size(public), fp, name, ++ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); ++ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, name, + key_type(public)); + if (log_level >= SYSLOG_LEVEL_VERBOSE) + printf("%s\n", ra); +@@ -1855,16 +1858,17 @@ do_show_cert(struct passwd *pw) + fatal("%s is not a certificate", identity_file); + v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; + +- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); +- ca_fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, SSH_FP_HEX); ++ key_fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); + + printf("%s:\n", identity_file); + printf(" Type: %s %s certificate\n", key_ssh_name(key), + key_cert_type(key)); +- printf(" Public key: %s %s\n", key_type(key), key_fp); +- printf(" Signing CA: %s %s\n", +- key_type(key->cert->signature_key), ca_fp); ++ printf(" Public key: %s %s%s\n", key_type(key), ++ key_fingerprint_prefix(), key_fp); ++ printf(" Signing CA: %s %s%s\n", ++ key_type(key->cert->signature_key), ++ key_fingerprint_prefix(), ca_fp); + printf(" Key ID: \"%s\"\n", key->cert->key_id); + if (!v00) { + printf(" Serial: %llu\n", +@@ -2655,13 +2659,12 @@ passphrase_again: + fclose(f); + + if (!quiet) { +- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); +- char *ra = key_fingerprint(public, SSH_FP_MD5, +- SSH_FP_RANDOMART); ++ char *fp = key_selected_fingerprint(public, SSH_FP_HEX); ++ char *ra = key_selected_fingerprint(public, SSH_FP_RANDOMART); + printf("Your public key has been saved in %s.\n", + identity_file); + printf("The key fingerprint is:\n"); +- printf("%s %s\n", fp, comment); ++ printf("%s%s %s\n", key_fingerprint_prefix(), fp, comment); + printf("The key's randomart image is:\n"); + printf("%s\n", ra); + free(ra); +diff -up openssh-6.3p1/sshconnect.c.fingerprint openssh-6.3p1/sshconnect.c +--- openssh-6.3p1/sshconnect.c.fingerprint 2013-06-01 23:31:19.000000000 +0200 ++++ openssh-6.3p1/sshconnect.c 2013-10-07 14:43:54.859822036 +0200 +@@ -830,10 +830,10 @@ check_host_key(char *hostname, struct so + "key for IP address '%.128s' to the list " + "of known hosts.", type, ip); + } else if (options.visual_host_key) { +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(host_key, SSH_FP_MD5, +- SSH_FP_RANDOMART); +- logit("Host key fingerprint is %s\n%s\n", fp, ra); ++ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); ++ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART); ++ logit("Host key fingerprint is %s%s\n%s\n", ++ key_fingerprint_prefix(), fp, ra); + free(ra); + free(fp); + } +@@ -871,9 +871,8 @@ check_host_key(char *hostname, struct so + else + snprintf(msg1, sizeof(msg1), "."); + /* The default */ +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(host_key, SSH_FP_MD5, +- SSH_FP_RANDOMART); ++ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); ++ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART); + msg2[0] = '\0'; + if (options.verify_host_key_dns) { + if (matching_host_key_dns) +@@ -888,10 +887,11 @@ check_host_key(char *hostname, struct so + snprintf(msg, sizeof(msg), + "The authenticity of host '%.200s (%s)' can't be " + "established%s\n" +- "%s key fingerprint is %s.%s%s\n%s" ++ "%s key fingerprint is %s%s.%s%s\n%s" + "Are you sure you want to continue connecting " + "(yes/no)? ", +- host, ip, msg1, type, fp, ++ host, ip, msg1, type, ++ key_fingerprint_prefix(), fp, + options.visual_host_key ? "\n" : "", + options.visual_host_key ? ra : "", + msg2); +@@ -1136,8 +1136,9 @@ verify_host_key(char *host, struct socka + int flags = 0; + char *fp; + +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- debug("Server host key: %s %s", key_type(host_key), fp); ++ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); ++ debug("Server host key: %s %s%s", key_type(host_key), ++ key_fingerprint_prefix(), fp); + free(fp); + + /* XXX certs are not yet supported for DNS */ +@@ -1238,14 +1239,15 @@ show_other_keys(struct hostkeys *hostkey + continue; + if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) + continue; +- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); ++ fp = key_selected_fingerprint(found->key, SSH_FP_HEX); ++ ra = key_selected_fingerprint(found->key, SSH_FP_RANDOMART); + logit("WARNING: %s key found for host %s\n" + "in %s:%lu\n" +- "%s key fingerprint %s.", ++ "%s key fingerprint %s%s.", + key_type(found->key), + found->host, found->file, found->line, +- key_type(found->key), fp); ++ key_type(found->key), ++ key_fingerprint_prefix(), fp); + if (options.visual_host_key) + logit("%s", ra); + free(ra); +@@ -1260,7 +1262,7 @@ warn_changed_key(Key *host_key) + { + char *fp; + +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(host_key, SSH_FP_HEX); + + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); +@@ -1268,8 +1270,8 @@ warn_changed_key(Key *host_key) + error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); + error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); + error("It is also possible that a host key has just been changed."); +- error("The fingerprint for the %s key sent by the remote host is\n%s.", +- key_type(host_key), fp); ++ error("The fingerprint for the %s key sent by the remote host is\n%s%s.", ++ key_type(host_key),key_fingerprint_prefix(), fp); + error("Please contact your system administrator."); + + free(fp); +diff -up openssh-6.3p1/sshconnect2.c.fingerprint openssh-6.3p1/sshconnect2.c +--- openssh-6.3p1/sshconnect2.c.fingerprint 2013-10-07 14:02:37.001968139 +0200 ++++ openssh-6.3p1/sshconnect2.c 2013-10-07 15:20:09.403234714 +0200 +@@ -590,8 +590,9 @@ input_userauth_pk_ok(int type, u_int32_t + key->type, pktype); + goto done; + } +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); +- debug2("input_userauth_pk_ok: fp %s", fp); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); ++ debug2("input_userauth_pk_ok: fp %s%s", ++ key_fingerprint_prefix(), fp); + free(fp); + + /* +@@ -1202,8 +1203,9 @@ sign_and_send_pubkey(Authctxt *authctxt, + int have_sig = 1; + char *fp; + +- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); +- debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); ++ fp = key_selected_fingerprint(id->key, SSH_FP_HEX); ++ debug3("sign_and_send_pubkey: %s %s%s", key_type(id->key), ++ key_fingerprint_prefix(), fp); + free(fp); + + if (key_to_blob(id->key, &blob, &bloblen) == 0) { diff --git a/openssh-6.3p1-fips.patch b/openssh-6.3p1-fips.patch new file mode 100644 index 0000000..f216d6e --- /dev/null +++ b/openssh-6.3p1-fips.patch @@ -0,0 +1,553 @@ +diff -up openssh-6.3p1/Makefile.in.fips openssh-6.3p1/Makefile.in +--- openssh-6.3p1/Makefile.in.fips 2013-10-11 22:24:32.850031186 +0200 ++++ openssh-6.3p1/Makefile.in 2013-10-11 22:24:32.870031092 +0200 +@@ -147,25 +147,25 @@ libssh.a: $(LIBSSH_OBJS) + $(RANLIB) $@ + + ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) +- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) ++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o + $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + + ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o +- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o +- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o +- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o +- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + 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) +@@ -177,7 +177,7 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh + $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) + + 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) ++ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +diff -up openssh-6.3p1/authfile.c.fips openssh-6.3p1/authfile.c +--- openssh-6.3p1/authfile.c.fips 2013-10-11 22:24:32.857031153 +0200 ++++ openssh-6.3p1/authfile.c 2013-10-11 22:24:32.870031092 +0200 +@@ -148,8 +148,14 @@ key_private_rsa1_to_blob(Key *key, Buffe + /* Allocate space for the private part of the key in the buffer. */ + cp = buffer_append_space(&encrypted, buffer_len(&buffer)); + +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_ENCRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_ENCRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&encrypted); ++ buffer_free(&buffer); ++ return 0; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); + cipher_cleanup(&ciphercontext); +@@ -472,8 +478,13 @@ key_parse_private_rsa1(Buffer *blob, con + cp = buffer_append_space(&decrypted, buffer_len(©)); + + /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_DECRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_DECRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&decrypted); ++ goto fail; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(©), buffer_len(©), 0, 0); + cipher_cleanup(&ciphercontext); +diff -up openssh-6.3p1/cipher-ctr.c.fips openssh-6.3p1/cipher-ctr.c +--- openssh-6.3p1/cipher-ctr.c.fips 2013-06-02 00:07:32.000000000 +0200 ++++ openssh-6.3p1/cipher-ctr.c 2013-10-11 22:24:32.870031092 +0200 +@@ -138,7 +138,8 @@ evp_aes_128_ctr(void) + 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; ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | ++ EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); + } +diff -up openssh-6.3p1/cipher.c.fips openssh-6.3p1/cipher.c +--- openssh-6.3p1/cipher.c.fips 2013-10-11 22:24:32.820031327 +0200 ++++ openssh-6.3p1/cipher.c 2013-10-11 22:24:32.871031087 +0200 +@@ -40,6 +40,7 @@ + #include + + #include ++#include + + #include + #include +@@ -86,6 +87,27 @@ static const struct Cipher ciphers[] = { + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } + }; + ++static const struct Cipher fips_ciphers[] = { ++ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, ++ { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, ++ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, ++ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, ++ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, ++ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, ++ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, ++ { "rijndael-cbc@lysator.liu.se", ++ SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, ++#ifdef OPENSSL_HAVE_EVPGCM ++ { "aes128-gcm@openssh.com", ++ SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, ++ { "aes256-gcm@openssh.com", ++ SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, ++#endif ++ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } ++}; + /*--*/ + + /* Returns a comma-separated list of supported ciphers. */ +@@ -96,7 +118,7 @@ cipher_alg_list(void) + size_t nlen, rlen = 0; + const Cipher *c; + +- for (c = ciphers; c->name != NULL; c++) { ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { + if (c->number != SSH_CIPHER_SSH2) + continue; + if (ret != NULL) +@@ -161,7 +183,7 @@ const Cipher * + cipher_by_name(const char *name) + { + const Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; + return NULL; +@@ -171,7 +193,7 @@ const Cipher * + cipher_by_number(int id) + { + const Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (c->number == id) + return c; + return NULL; +@@ -215,7 +237,7 @@ cipher_number(const char *name) + const Cipher *c; + if (name == NULL) + return -1; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcasecmp(c->name, name) == 0) + return c->number; + return -1; +@@ -374,14 +396,15 @@ cipher_cleanup(CipherContext *cc) + * passphrase and using the resulting 16 bytes as the key. + */ + +-void ++int + cipher_set_key_string(CipherContext *cc, const Cipher *cipher, + const char *passphrase, int do_encrypt) + { + MD5_CTX md; + u_char digest[16]; + +- MD5_Init(&md); ++ if (MD5_Init(&md) <= 0) ++ return -1; + MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); + MD5_Final(digest, &md); + +@@ -389,6 +412,7 @@ cipher_set_key_string(CipherContext *cc, + + memset(digest, 0, sizeof(digest)); + memset(&md, 0, sizeof(md)); ++ return 0; + } + + /* +diff -up openssh-6.3p1/cipher.h.fips openssh-6.3p1/cipher.h +--- openssh-6.3p1/cipher.h.fips 2013-10-11 22:24:32.820031327 +0200 ++++ openssh-6.3p1/cipher.h 2013-10-11 22:24:32.871031087 +0200 +@@ -92,7 +92,7 @@ void cipher_init(CipherContext *, const + void cipher_crypt(CipherContext *, u_char *, const u_char *, + u_int, u_int, u_int); + void cipher_cleanup(CipherContext *); +-void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); ++int cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); + u_int cipher_blocksize(const Cipher *); + u_int cipher_keylen(const Cipher *); + u_int cipher_authlen(const Cipher *); +diff -up openssh-6.3p1/key.c.fips openssh-6.3p1/key.c +--- openssh-6.3p1/key.c.fips 2013-10-11 22:24:32.821031322 +0200 ++++ openssh-6.3p1/key.c 2013-10-11 22:24:32.871031087 +0200 +@@ -40,6 +40,7 @@ + #include + + #include ++#include + #include + + #include +@@ -606,9 +607,13 @@ key_fingerprint_selection(void) + char *env; + + if (!rv_defined) { +- env = getenv("SSH_FINGERPRINT_TYPE"); +- rv = (env && !strcmp (env, "sha")) ? +- SSH_FP_SHA1 : SSH_FP_MD5; ++ if (FIPS_mode()) ++ rv = SSH_FP_SHA1; ++ else { ++ env = getenv("SSH_FINGERPRINT_TYPE"); ++ rv = (env && !strcmp (env, "sha")) ? ++ SSH_FP_SHA1 : SSH_FP_MD5; ++ } + rv_defined = 1; + } + return rv; +diff -up openssh-6.3p1/mac.c.fips openssh-6.3p1/mac.c +--- openssh-6.3p1/mac.c.fips 2013-10-11 22:24:32.821031322 +0200 ++++ openssh-6.3p1/mac.c 2013-10-11 22:25:35.394737186 +0200 +@@ -28,6 +28,7 @@ + #include + + #include ++#include + + #include + #include +@@ -60,7 +61,7 @@ struct macalg { + int etm; /* Encrypt-then-MAC */ + }; + +-static const struct macalg macs[] = { ++static const struct macalg all_macs[] = { + /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ + { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, + { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, +@@ -91,6 +92,18 @@ static const struct macalg macs[] = { + { NULL, 0, NULL, 0, 0, 0, 0 } + }; + ++static const struct macalg fips_macs[] = { ++ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, ++ { "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 }, ++#ifdef HAVE_EVP_SHA256 ++ { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 }, ++ { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 }, ++ { "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 }, ++ { "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 }, ++#endif ++ { NULL, 0, NULL, 0, 0, 0, 0 } ++}; ++ + /* Returns a comma-separated list of supported MACs. */ + char * + mac_alg_list(void) +@@ -99,7 +112,7 @@ mac_alg_list(void) + size_t nlen, rlen = 0; + const struct macalg *m; + +- for (m = macs; m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { + if (ret != NULL) + ret[rlen++] = '\n'; + nlen = strlen(m->name); +@@ -136,7 +149,7 @@ mac_setup(Mac *mac, char *name) + { + const struct macalg *m; + +- for (m = macs; m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { + if (strcmp(name, m->name) != 0) + continue; + if (mac != NULL) +diff -up openssh-6.3p1/myproposal.h.fips openssh-6.3p1/myproposal.h +--- openssh-6.3p1/myproposal.h.fips 2013-06-11 04:10:02.000000000 +0200 ++++ openssh-6.3p1/myproposal.h 2013-10-11 22:24:32.872031082 +0200 +@@ -114,6 +114,19 @@ + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" + #define KEX_DEFAULT_LANG "" + ++#define KEX_FIPS_ENCRYPT \ ++ "aes128-ctr,aes192-ctr,aes256-ctr," \ ++ "aes128-cbc,3des-cbc," \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" ++#ifdef HAVE_EVP_SHA256 ++#define KEX_FIPS_MAC \ ++ "hmac-sha1," \ ++ "hmac-sha2-256," \ ++ "hmac-sha2-512" ++#else ++#define KEX_FIPS_MAC \ ++ "hmac-sha1" ++#endif + + static char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, +diff -up openssh-6.3p1/openbsd-compat/bsd-arc4random.c.fips openssh-6.3p1/openbsd-compat/bsd-arc4random.c +--- openssh-6.3p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100 ++++ openssh-6.3p1/openbsd-compat/bsd-arc4random.c 2013-10-11 22:24:32.872031082 +0200 +@@ -37,25 +37,18 @@ + #define REKEY_BYTES (1 << 24) + + static int rc4_ready = 0; +-static RC4_KEY rc4; + + unsigned int + arc4random(void) + { + unsigned int r = 0; +- static int first_time = 1; ++ void *rp = &r; + +- if (rc4_ready <= 0) { +- if (first_time) +- seed_rng(); +- first_time = 0; ++ if (!rc4_ready) { + arc4random_stir(); + } ++ RAND_bytes(rp, sizeof(r)); + +- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); +- +- rc4_ready -= sizeof(r); +- + return(r); + } + +@@ -63,24 +56,11 @@ void + arc4random_stir(void) + { + unsigned char rand_buf[SEED_SIZE]; +- int i; + +- memset(&rc4, 0, sizeof(rc4)); + if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) + fatal("Couldn't obtain random bytes (error %ld)", + ERR_get_error()); +- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); +- +- /* +- * Discard early keystream, as per recommendations in: +- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps +- */ +- for(i = 0; i <= 256; i += sizeof(rand_buf)) +- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); +- +- memset(rand_buf, 0, sizeof(rand_buf)); +- +- rc4_ready = REKEY_BYTES; ++ rc4_ready = 1; + } + #endif /* !HAVE_ARC4RANDOM */ + +diff -up openssh-6.3p1/ssh.c.fips openssh-6.3p1/ssh.c +--- openssh-6.3p1/ssh.c.fips 2013-07-25 03:55:53.000000000 +0200 ++++ openssh-6.3p1/ssh.c 2013-10-11 22:24:32.872031082 +0200 +@@ -73,6 +73,8 @@ + + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -253,6 +255,13 @@ main(int ac, char **av) + sanitise_stdfd(); + + __progname = ssh_get_progname(av[0]); ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)) ++ if (FIPS_mode()) ++ fatal("FIPS integrity verification test failed."); ++ else ++ logit("FIPS integrity verification test failed."); + + #ifndef HAVE_SETPROCTITLE + /* Prepare for later setproctitle emulation */ +@@ -330,6 +339,9 @@ main(int ac, char **av) + "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { + switch (opt) { + case '1': ++ if (FIPS_mode()) { ++ fatal("Protocol 1 not allowed in the FIPS mode."); ++ } + options.protocol = SSH_PROTO_1; + break; + case '2': +@@ -647,7 +659,6 @@ main(int ac, char **av) + if (!host) + usage(); + +- OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + /* Initialize the command to execute on remote host. */ +@@ -748,6 +759,10 @@ main(int ac, char **av) + + seed_rng(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); + +@@ -816,6 +831,12 @@ main(int ac, char **av) + + timeout_ms = options.connection_timeout * 1000; + ++ if (FIPS_mode()) { ++ options.protocol &= SSH_PROTO_2; ++ if (options.protocol == 0) ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); ++ } ++ + /* Open a connection to the remote host. */ + if (ssh_connect(host, &hostaddr, options.port, + options.address_family, options.connection_attempts, &timeout_ms, +diff -up openssh-6.3p1/sshconnect2.c.fips openssh-6.3p1/sshconnect2.c +--- openssh-6.3p1/sshconnect2.c.fips 2013-10-11 22:24:32.810031374 +0200 ++++ openssh-6.3p1/sshconnect2.c 2013-10-11 22:24:32.873031077 +0200 +@@ -44,6 +44,8 @@ + #include + #endif + ++#include ++ + #include "openbsd-compat/sys-queue.h" + + #include "xmalloc.h" +@@ -170,6 +172,10 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; ++ + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -185,7 +191,11 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } ++ + if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + options.hostkeyalgorithms; +diff -up openssh-6.3p1/sshd.c.fips openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.fips 2013-10-11 22:24:32.842031223 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-11 22:24:32.873031077 +0200 +@@ -76,6 +76,8 @@ + #include + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + + #ifdef HAVE_SECUREWARE +@@ -1450,6 +1452,14 @@ main(int ac, char **av) + #endif + __progname = ssh_get_progname(av[0]); + ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)) ++ if (FIPS_mode()) ++ fatal("FIPS integrity verification test failed."); ++ else ++ logit("FIPS integrity verification test failed."); ++ + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ + saved_argc = ac; + rexec_argc = ac; +@@ -1601,8 +1611,6 @@ main(int ac, char **av) + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + +- OpenSSL_add_all_algorithms(); +- + /* If requested, redirect the logs to the specified logfile. */ + if (logfile != NULL) { + log_redirect_stderr_to(logfile); +@@ -1773,6 +1781,10 @@ main(int ac, char **av) + debug("private host key: #%d type %d %s", i, keytype, + key_type(key ? key : pubkey)); + } ++ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { ++ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); ++ options.protocol &= ~SSH_PROTO_1; ++ } + if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; +@@ -1936,6 +1948,10 @@ main(int ac, char **av) + /* Initialize the random number generator. */ + arc4random_stir(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ + if (chdir("/") == -1) +@@ -2498,6 +2514,9 @@ do_ssh2_kex(void) + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -2507,6 +2526,9 @@ do_ssh2_kex(void) + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = diff --git a/openssh-6.3p1-force_krb.patch b/openssh-6.3p1-force_krb.patch new file mode 100644 index 0000000..695c0eb --- /dev/null +++ b/openssh-6.3p1-force_krb.patch @@ -0,0 +1,279 @@ +diff -up openssh-6.3p1/gss-serv-krb5.c.force_krb openssh-6.3p1/gss-serv-krb5.c +--- openssh-6.3p1/gss-serv-krb5.c.force_krb 2013-10-11 18:58:51.553948159 +0200 ++++ openssh-6.3p1/gss-serv-krb5.c 2013-10-11 21:40:49.972337025 +0200 +@@ -32,7 +32,9 @@ + #include + + #include ++#include + #include ++#include + + #include "xmalloc.h" + #include "key.h" +@@ -40,10 +42,12 @@ + #include "auth.h" + #include "log.h" + #include "servconf.h" ++#include "misc.h" + + #include "buffer.h" + #include "ssh-gss.h" + ++extern Authctxt *the_authctxt; + extern ServerOptions options; + + #ifdef HEIMDAL +@@ -55,6 +59,13 @@ extern ServerOptions options; + # include + #endif + ++/* all commands are allowed by default */ ++char **k5users_allowed_cmds = NULL; ++ ++static int ssh_gssapi_k5login_exists(); ++static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *, ++ int); ++ + static krb5_context krb_context = NULL; + + /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ +@@ -87,6 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + krb5_principal princ; + int retval; + const char *errmsg; ++ int k5login_exists; + + if (ssh_gssapi_krb5_init() == 0) + return 0; +@@ -98,10 +110,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + krb5_free_error_message(krb_context, errmsg); + return 0; + } +- if (krb5_kuserok(krb_context, princ, name)) { ++ /* krb5_kuserok() returns 1 if .k5login DNE and this is self-login. ++ * We have to make sure to check .k5users in that case. */ ++ k5login_exists = ssh_gssapi_k5login_exists(); ++ /* NOTE: .k5login and .k5users must opened as root, not the user, ++ * because if they are on a krb5-protected filesystem, user credentials ++ * to access these files aren't available yet. */ ++ if (krb5_kuserok(krb_context, princ, name) && k5login_exists) { + retval = 1; + logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", + name, (char *)client->displayname.value); ++ } else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value, ++ name, k5login_exists)) { ++ retval = 1; ++ logit("Authorized to %s, krb5 principal %s " ++ "(ssh_gssapi_krb5_cmdok)", ++ name, (char *)client->displayname.value); + } else + retval = 0; + +@@ -109,6 +133,135 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + return retval; + } + ++/* Test for existence of .k5login. ++ * We need this as part of our .k5users check, because krb5_kuserok() ++ * returns success if .k5login DNE and user is logging in as himself. ++ * With .k5login absent and .k5users present, we don't want absence ++ * of .k5login to authorize self-login. (absence of both is required) ++ * Returns 1 if .k5login is available, 0 otherwise. ++ */ ++static int ++ssh_gssapi_k5login_exists() ++{ ++ char file[MAXPATHLEN]; ++ struct passwd *pw = the_authctxt->pw; ++ ++ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); ++ return access(file, F_OK) == 0; ++} ++ ++/* check .k5users for login or command authorization ++ * Returns 1 if principal is authorized, 0 otherwise. ++ * If principal is authorized, (global) k5users_allowed_cmds may be populated. ++ */ ++static int ++ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, ++ const char *luser, int k5login_exists) ++{ ++ FILE *fp; ++ char file[MAXPATHLEN]; ++ char line[BUFSIZ]; ++ char kuser[65]; /* match krb5_kuserok() */ ++ struct stat st; ++ struct passwd *pw = the_authctxt->pw; ++ int found_principal = 0; ++ int ncommands = 0, allcommands = 0; ++ u_long linenum; ++ ++ snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); ++ /* If both .k5login and .k5users DNE, self-login is ok. */ ++ if (!k5login_exists && (access(file, F_OK) == -1)) { ++ return (krb5_aname_to_localname(krb_context, principal, ++ sizeof(kuser), kuser) == 0) && ++ (strcmp(kuser, luser) == 0); ++ } ++ if ((fp = fopen(file, "r")) == NULL) { ++ int saved_errno = errno; ++ /* 2nd access check to ease debugging if file perms are wrong. ++ * But we don't want to report this if .k5users simply DNE. */ ++ if (access(file, F_OK) == 0) { ++ logit("User %s fopen %s failed: %s", ++ pw->pw_name, file, strerror(saved_errno)); ++ } ++ return 0; ++ } ++ /* .k5users must be owned either by the user or by root */ ++ if (fstat(fileno(fp), &st) == -1) { ++ /* can happen, but very wierd error so report it */ ++ logit("User %s fstat %s failed: %s", ++ pw->pw_name, file, strerror(errno)); ++ fclose(fp); ++ return 0; ++ } ++ if (!(st.st_uid == pw->pw_uid || st.st_uid == 0)) { ++ logit("User %s %s is not owned by root or user", ++ pw->pw_name, file); ++ fclose(fp); ++ return 0; ++ } ++ /* .k5users must be a regular file. krb5_kuserok() doesn't do this ++ * check, but we don't want to be deficient if they add a check. */ ++ if (!S_ISREG(st.st_mode)) { ++ logit("User %s %s is not a regular file", pw->pw_name, file); ++ fclose(fp); ++ return 0; ++ } ++ /* file exists; initialize k5users_allowed_cmds (to none!) */ ++ k5users_allowed_cmds = xcalloc(++ncommands, ++ sizeof(*k5users_allowed_cmds)); ++ ++ /* Check each line. ksu allows unlimited length lines. We don't. */ ++ while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line), ++ &linenum) != -1) { ++ char *token; ++ ++ /* we parse just like ksu, even though we could do better */ ++ if ((token = strtok(line, " \t\n")) == NULL) ++ continue; ++ if (strcmp(name, token) == 0) { ++ /* we matched on client principal */ ++ found_principal = 1; ++ if ((token = strtok(NULL, " \t\n")) == NULL) { ++ /* only shell is allowed */ ++ k5users_allowed_cmds[ncommands-1] = ++ xstrdup(pw->pw_shell); ++ k5users_allowed_cmds = ++ xrealloc(k5users_allowed_cmds, ++ncommands, ++ sizeof(*k5users_allowed_cmds)); ++ break; ++ } ++ /* process the allowed commands */ ++ while (token) { ++ if (strcmp(token, "*") == 0) { ++ allcommands = 1; ++ break; ++ } ++ k5users_allowed_cmds[ncommands-1] = ++ xstrdup(token); ++ k5users_allowed_cmds = ++ xrealloc(k5users_allowed_cmds, ++ncommands, ++ sizeof(*k5users_allowed_cmds)); ++ token = strtok(NULL, " \t\n"); ++ } ++ } ++ } ++ if (k5users_allowed_cmds) { ++ /* terminate vector */ ++ k5users_allowed_cmds[ncommands-1] = NULL; ++ /* if all commands are allowed, free vector */ ++ if (allcommands) { ++ int i; ++ for (i = 0; i < ncommands; i++) { ++ free(k5users_allowed_cmds[i]); ++ } ++ free(k5users_allowed_cmds); ++ k5users_allowed_cmds = NULL; ++ } ++ } ++ fclose(fp); ++ return found_principal; ++} ++ + + /* This writes out any forwarded credentials from the structure populated + * during userauth. Called after we have setuid to the user */ +diff -up openssh-6.3p1/session.c.force_krb openssh-6.3p1/session.c +--- openssh-6.3p1/session.c.force_krb 2013-10-11 18:58:51.487948468 +0200 ++++ openssh-6.3p1/session.c 2013-10-11 18:58:51.563948112 +0200 +@@ -823,6 +823,29 @@ do_exec(Session *s, const char *command) + debug("Forced command (key option) '%.900s'", command); + } + ++#ifdef GSSAPI ++#ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */ ++ else if (k5users_allowed_cmds) { ++ const char *match = command; ++ int allowed = 0, i = 0; ++ ++ if (!match) ++ match = s->pw->pw_shell; ++ while (k5users_allowed_cmds[i]) { ++ if (strcmp(match, k5users_allowed_cmds[i++]) == 0) { ++ debug("Allowed command '%.900s'", match); ++ allowed = 1; ++ break; ++ } ++ } ++ if (!allowed) { ++ debug("command '%.900s' not allowed", match); ++ return 1; ++ } ++ } ++#endif ++#endif ++ + #ifdef SSH_AUDIT_EVENTS + if (s->command != NULL || s->command_handle != -1) + fatal("do_exec: command already set"); +diff -up openssh-6.3p1/ssh-gss.h.force_krb openssh-6.3p1/ssh-gss.h +--- openssh-6.3p1/ssh-gss.h.force_krb 2013-10-11 18:58:51.558948136 +0200 ++++ openssh-6.3p1/ssh-gss.h 2013-10-11 18:58:51.563948112 +0200 +@@ -49,6 +49,10 @@ + # endif /* !HAVE_DECL_GSS_C_NT_... */ + + # endif /* !HEIMDAL */ ++ ++/* .k5users support */ ++extern char **k5users_allowed_cmds; ++ + #endif /* KRB5 */ + + /* draft-ietf-secsh-gsskeyex-06 */ +diff -up openssh-6.3p1/sshd.8.force_krb openssh-6.3p1/sshd.8 +--- openssh-6.3p1/sshd.8.force_krb 2013-10-11 18:58:51.537948234 +0200 ++++ openssh-6.3p1/sshd.8 2013-10-11 18:58:51.563948112 +0200 +@@ -326,6 +326,7 @@ Finally, the server and the client enter + The client tries to authenticate itself using + host-based authentication, + public key authentication, ++GSSAPI authentication, + challenge-response authentication, + or password authentication. + .Pp +@@ -797,6 +798,12 @@ This file is used in exactly the same wa + but allows host-based authentication without permitting login with + rlogin/rsh. + .Pp ++.It Pa ~/.k5login ++.It Pa ~/.k5users ++These files enforce GSSAPI/Kerberos authentication access control. ++Further details are described in ++.Xr ksu 1 . ++.Pp + .It Pa ~/.ssh/ + This directory is the default location for all user-specific configuration + and authentication information. diff --git a/openssh-6.3p1-gsskex.patch b/openssh-6.3p1-gsskex.patch new file mode 100644 index 0000000..7161b34 --- /dev/null +++ b/openssh-6.3p1-gsskex.patch @@ -0,0 +1,3028 @@ +diff -up openssh-6.3p1/ChangeLog.gssapi.gsskex openssh-6.3p1/ChangeLog.gssapi +--- openssh-6.3p1/ChangeLog.gssapi.gsskex 2013-10-11 15:15:17.284216176 +0200 ++++ openssh-6.3p1/ChangeLog.gssapi 2013-10-11 15:15:17.284216176 +0200 +@@ -0,0 +1,113 @@ ++20110101 ++ - Finally update for OpenSSH 5.6p1 ++ - Add GSSAPIServerIdentity option from Jim Basney ++ ++20100308 ++ - [ Makefile.in, key.c, key.h ] ++ Updates for OpenSSH 5.4p1 ++ - [ servconf.c ] ++ Include GSSAPI options in the sshd -T configuration dump, and flag ++ some older configuration options as being unsupported. Thanks to Colin ++ Watson. ++ - ++ ++20100124 ++ - [ sshconnect2.c ] ++ Adapt to deal with additional element in Authmethod structure. Thanks to ++ Colin Watson ++ ++20090615 ++ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c ++ sshd.c ] ++ Fix issues identified by Greg Hudson following a code review ++ Check return value of gss_indicate_mechs ++ Protect GSSAPI calls in monitor, so they can only be used if enabled ++ Check return values of bignum functions in key exchange ++ Use BN_clear_free to clear other side's DH value ++ Make ssh_gssapi_id_kex more robust ++ Only configure kex table pointers if GSSAPI is enabled ++ Don't leak mechanism list, or gss mechanism list ++ Cast data.length before printing ++ If serverkey isn't provided, use an empty string, rather than NULL ++ ++20090201 ++ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h ++ ssh_config.5 sshconnet2.c ] ++ Add support for the GSSAPIClientIdentity option, which allows the user ++ to specify which GSSAPI identity to use to contact a given server ++ ++20080404 ++ - [ gss-serv.c ] ++ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow ++ been omitted from a previous version of this patch. Reported by Borislav ++ Stoichkov ++ ++20070317 ++ - [ gss-serv-krb5.c ] ++ Remove C99ism, where new_ccname was being declared in the middle of a ++ function ++ ++20061220 ++ - [ servconf.c ] ++ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and ++ documented, behaviour. Reported by Dan Watson. ++ ++20060910 ++ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c ++ ssh-gss.h ] ++ add support for gss-group14-sha1 key exchange mechanisms ++ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] ++ Add GSSAPIStrictAcceptorCheck option to allow the disabling of ++ acceptor principal checking on multi-homed machines. ++ ++ - [ sshd_config ssh_config ] ++ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample ++ configuration files ++ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] ++ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() ++ Limit length of error messages displayed by client ++ ++20060909 ++ - [ gss-genr.c gss-serv.c ] ++ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server ++ only, where they belong ++ ++ ++20060829 ++ - [ gss-serv-krb5.c ] ++ Fix CCAPI credentials cache name when creating KRB5CCNAME environment ++ variable ++ ++20060828 ++ - [ gss-genr.c ] ++ Avoid Heimdal context freeing problem ++ ++ ++20060818 ++ - [ gss-genr.c ssh-gss.h sshconnect2.c ] ++ Make sure that SPENGO is disabled ++ ++ ++20060421 ++ - [ gssgenr.c, sshconnect2.c ] ++ a few type changes (signed versus unsigned, int versus size_t) to ++ fix compiler errors/warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ kexgssc.c, sshconnect2.c ] ++ fix uninitialized variable warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ gssgenr.c ] ++ pass oid to gss_display_status (helpful when using GSSAPI mechglue) ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ gss-serv-krb5.c ] ++ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c ++ add client-side GssapiKeyExchange option ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ sshconnect2.c ] ++ add support for GssapiTrustDns option for gssapi-with-mic ++ (from jbasney AT ncsa.uiuc.edu) ++ +diff -up openssh-6.3p1/Makefile.in.gsskex openssh-6.3p1/Makefile.in +--- openssh-6.3p1/Makefile.in.gsskex 2013-10-11 15:15:17.281216190 +0200 ++++ openssh-6.3p1/Makefile.in 2013-10-11 15:15:17.289216153 +0200 +@@ -77,6 +77,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o + atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ + kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ ++ kexgssc.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ + jpake.o schnorr.o ssh-pkcs11.o krl.o auditstub.o + +@@ -93,7 +94,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ + monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ + auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ + sftp-server.o sftp-common.o \ + roaming_common.o roaming_serv.o \ +diff -up openssh-6.3p1/auth-krb5.c.gsskex openssh-6.3p1/auth-krb5.c +--- openssh-6.3p1/auth-krb5.c.gsskex 2013-08-04 13:48:41.000000000 +0200 ++++ openssh-6.3p1/auth-krb5.c 2013-10-11 15:43:50.261299742 +0200 +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + #include + + extern ServerOptions options; +@@ -77,6 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c + #endif + krb5_error_code problem; + krb5_ccache ccache = NULL; ++ const char *ccache_type; + int len; + char *client, *platform_client; + const char *errmsg; +@@ -177,12 +179,30 @@ auth_krb5_password(Authctxt *authctxt, c + goto out; + #endif + ++ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + +- len = strlen(authctxt->krb5_ticket_file) + 6; ++ if (authctxt->krb5_ticket_file[0] == ':') ++ authctxt->krb5_ticket_file++; ++ ++ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type); + authctxt->krb5_ccname = xmalloc(len); +- snprintf(authctxt->krb5_ccname, len, "FILE:%s", ++ ++#ifdef USE_CCAPI ++ snprintf(authctxt->krb5_ccname, len, "API:%s", + authctxt->krb5_ticket_file); ++#else ++ snprintf(authctxt->krb5_ccname, len, "%s:%s", ++ ccache_type, authctxt->krb5_ticket_file); ++#endif ++ ++ if (strcmp(ccache_type, "DIR") == 0) { ++ char *p; ++ p = strrchr(authctxt->krb5_ccname, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ + + #ifdef USE_PAM + if (options.use_pam) +@@ -221,10 +241,30 @@ auth_krb5_password(Authctxt *authctxt, c + void + krb5_cleanup_proc(Authctxt *authctxt) + { ++ struct stat krb5_ccname_stat; ++ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end; ++ + debug("krb5_cleanup_proc called"); + if (authctxt->krb5_fwd_ccache) { + krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_fwd_ccache = NULL; ++ ++ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10); ++ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1; ++ strcat(krb5_ccname_dir_start, "/primary"); ++ ++ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) { ++ if (unlink(krb5_ccname_dir_start) == 0) { ++ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/'); ++ *krb5_ccname_dir_end = '\0'; ++ if (rmdir(krb5_ccname_dir_start) == -1) ++ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno)); ++ } ++ else ++ debug("cache primary file '%s', remove failed: %s", ++ krb5_ccname_dir_start, strerror(errno) ++ ); ++ } + } + if (authctxt->krb5_user) { + krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); +@@ -239,31 +279,45 @@ krb5_cleanup_proc(Authctxt *authctxt) + #ifndef HEIMDAL + krb5_error_code + ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret, oerrno; +- char ccname[40]; ++ int ret, oerrno; ++ char ccname[128]; ++#ifdef USE_CCAPI ++ char cctemplate[] = "API:krb5cc_%d"; ++#else + mode_t old_umask; ++ char cctemplate[] = "DIR:/run/user/%d/krb5cc_XXXXXXXXXX"; ++ char *tmpdir; ++#endif + +- ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ ret = snprintf(ccname, sizeof(ccname), cctemplate, geteuid()); + if (ret < 0 || (size_t)ret >= sizeof(ccname)) + return ENOMEM; + +- old_umask = umask(0177); +- tmpfd = mkstemp(ccname + strlen("FILE:")); ++#ifndef USE_CCAPI ++ old_umask = umask(0077); ++ tmpdir = mkdtemp(ccname + strlen("DIR:")); + oerrno = errno; ++ if (tmpdir == NULL && errno == ENOENT) { ++ /* /run/user/uid doesn't exist -> fallback to /tmp */ ++ ret = snprintf(ccname, sizeof(ccname), "DIR:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ if (ret < 0 || (size_t)ret >= sizeof(ccname)) ++ return ENOMEM; ++ tmpdir = mkdtemp(ccname + strlen("DIR:")); ++ oerrno = errno; ++ } ++ + umask(old_umask); +- if (tmpfd == -1) { +- logit("mkstemp(): %.100s", strerror(oerrno)); ++ if (tmpdir == NULL) { ++ logit("mkdtemp(): %s - %.100s", ccname, strerror(oerrno)); + return oerrno; + } + +- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ if (chmod(tmpdir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { + oerrno = errno; +- logit("fchmod(): %.100s", strerror(oerrno)); +- close(tmpfd); ++ logit("chmod(): %s - %.100s", ccname, strerror(oerrno)); + return oerrno; + } +- close(tmpfd); ++#endif + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } +diff -up openssh-6.3p1/auth2-gss.c.gsskex openssh-6.3p1/auth2-gss.c +--- openssh-6.3p1/auth2-gss.c.gsskex 2013-10-11 15:15:17.213216506 +0200 ++++ openssh-6.3p1/auth2-gss.c 2013-10-11 15:15:17.283216181 +0200 +@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u + static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); + static void input_gssapi_errtok(int, u_int32_t, void *); + ++/* ++ * The 'gssapi_keyex' userauth mechanism. ++ */ ++static int ++userauth_gsskeyex(Authctxt *authctxt) ++{ ++ int authenticated = 0; ++ Buffer b; ++ gss_buffer_desc mic, gssbuf; ++ u_int len; ++ ++ mic.value = packet_get_string(&len); ++ mic.length = len; ++ ++ packet_check_eom(); ++ ++ ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, ++ "gssapi-keyex"); ++ ++ gssbuf.value = buffer_ptr(&b); ++ gssbuf.length = buffer_len(&b); ++ ++ /* gss_kex_context is NULL with privsep, so we can't check it here */ ++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic)))) ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); ++ ++ buffer_free(&b); ++ free(mic.value); ++ ++ return (authenticated); ++} ++ + /* + * We only support those mechanisms that we know about (ie ones that we know + * how to check local user kuserok and the like) +@@ -240,7 +274,8 @@ input_gssapi_exchange_complete(int type, + + packet_check_eom(); + +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +@@ -282,7 +317,8 @@ input_gssapi_mic(int type, u_int32_t ple + gssbuf.length = buffer_len(&b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = ++ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + else + logit("GSSAPI MIC check failed"); + +@@ -299,6 +335,12 @@ input_gssapi_mic(int type, u_int32_t ple + userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + } + ++Authmethod method_gsskeyex = { ++ "gssapi-keyex", ++ userauth_gsskeyex, ++ &options.gss_authentication ++}; ++ + Authmethod method_gssapi = { + "gssapi-with-mic", + userauth_gssapi, +diff -up openssh-6.3p1/auth2.c.gsskex openssh-6.3p1/auth2.c +--- openssh-6.3p1/auth2.c.gsskex 2013-10-11 15:15:17.214216502 +0200 ++++ openssh-6.3p1/auth2.c 2013-10-11 15:15:17.283216181 +0200 +@@ -69,6 +69,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + #ifdef JPAKE +@@ -79,6 +80,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + #ifdef JPAKE +diff -up openssh-6.3p1/clientloop.c.gsskex openssh-6.3p1/clientloop.c +--- openssh-6.3p1/clientloop.c.gsskex 2013-10-11 15:15:17.178216669 +0200 ++++ openssh-6.3p1/clientloop.c 2013-10-11 15:15:17.284216176 +0200 +@@ -111,6 +111,10 @@ + #include "msg.h" + #include "roaming.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + /* import options */ + extern Options options; + +@@ -1608,6 +1612,15 @@ client_loop(int have_pty, int escape_cha + /* Do channel operations unless rekeying in progress. */ + if (!rekeying) { + channel_after_select(readset, writeset); ++ ++#ifdef GSSAPI ++ if (options.gss_renewal_rekey && ++ ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { ++ debug("credentials updated - forcing rekey"); ++ need_rekeying = 1; ++ } ++#endif ++ + if (need_rekeying || packet_need_rekeying()) { + debug("need rekeying"); + xxx_kex->done = 0; +diff -up openssh-6.3p1/configure.ac.gsskex openssh-6.3p1/configure.ac +--- openssh-6.3p1/configure.ac.gsskex 2013-10-11 15:15:17.273216227 +0200 ++++ openssh-6.3p1/configure.ac 2013-10-11 15:15:17.285216171 +0200 +@@ -548,6 +548,30 @@ main() { if (NSVersionOfRunTimeLibrary(" + [Use tunnel device compatibility to OpenBSD]) + AC_DEFINE([SSH_TUN_PREPEND_AF], [1], + [Prepend the address family to IP tunnel traffic]) ++ AC_MSG_CHECKING(if we have the Security Authorization Session API) ++ AC_TRY_COMPILE([#include ], ++ [SessionCreate(0, 0);], ++ [ac_cv_use_security_session_api="yes" ++ AC_DEFINE(USE_SECURITY_SESSION_API, 1, ++ [platform has the Security Authorization Session API]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT(yes)], ++ [ac_cv_use_security_session_api="no" ++ AC_MSG_RESULT(no)]) ++ AC_MSG_CHECKING(if we have an in-memory credentials cache) ++ AC_TRY_COMPILE( ++ [#include ], ++ [cc_context_t c; ++ (void) cc_initialize (&c, 0, NULL, NULL);], ++ [AC_DEFINE(USE_CCAPI, 1, ++ [platform uses an in-memory credentials cache]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT(yes) ++ if test "x$ac_cv_use_security_session_api" = "xno"; then ++ AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) ++ fi], ++ [AC_MSG_RESULT(no)] ++ ) + m4_pattern_allow([AU_IPv]) + AC_CHECK_DECL([AU_IPv4], [], + AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) +diff -up openssh-6.3p1/gss-genr.c.gsskex openssh-6.3p1/gss-genr.c +--- openssh-6.3p1/gss-genr.c.gsskex 2013-06-01 23:31:18.000000000 +0200 ++++ openssh-6.3p1/gss-genr.c 2013-10-11 15:15:17.286216167 +0200 +@@ -39,12 +39,167 @@ + #include "buffer.h" + #include "log.h" + #include "ssh2.h" ++#include "cipher.h" ++#include "key.h" ++#include "kex.h" ++#include + + #include "ssh-gss.h" + + extern u_char *session_id2; + extern u_int session_id2_len; + ++typedef struct { ++ char *encoded; ++ gss_OID oid; ++} ssh_gss_kex_mapping; ++ ++/* ++ * XXX - It would be nice to find a more elegant way of handling the ++ * XXX passing of the key exchange context to the userauth routines ++ */ ++ ++Gssctxt *gss_kex_context = NULL; ++ ++static ssh_gss_kex_mapping *gss_enc2oid = NULL; ++ ++int ++ssh_gssapi_oid_table_ok() { ++ return (gss_enc2oid != NULL); ++} ++ ++/* ++ * Return a list of the gss-group1-sha1 mechanisms supported by this program ++ * ++ * We test mechanisms to ensure that we can use them, to avoid starting ++ * a key exchange with a bad mechanism ++ */ ++ ++char * ++ssh_gssapi_client_mechanisms(const char *host, const char *client) { ++ gss_OID_set gss_supported; ++ OM_uint32 min_status; ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) ++ return NULL; ++ ++ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, ++ host, client)); ++} ++ ++char * ++ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, ++ const char *host, const char *client) { ++ Buffer buf; ++ size_t i; ++ int oidpos, enclen; ++ char *mechs, *encoded; ++ u_char digest[EVP_MAX_MD_SIZE]; ++ char deroid[2]; ++ const EVP_MD *evp_md = EVP_md5(); ++ EVP_MD_CTX md; ++ ++ if (gss_enc2oid != NULL) { ++ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) ++ free(gss_enc2oid[i].encoded); ++ free(gss_enc2oid); ++ } ++ ++ gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * ++ (gss_supported->count + 1)); ++ ++ buffer_init(&buf); ++ ++ oidpos = 0; ++ for (i = 0; i < gss_supported->count; i++) { ++ if (gss_supported->elements[i].length < 128 && ++ (*check)(NULL, &(gss_supported->elements[i]), host, client)) { ++ ++ deroid[0] = SSH_GSS_OIDTYPE; ++ deroid[1] = gss_supported->elements[i].length; ++ ++ EVP_DigestInit(&md, evp_md); ++ EVP_DigestUpdate(&md, deroid, 2); ++ EVP_DigestUpdate(&md, ++ gss_supported->elements[i].elements, ++ gss_supported->elements[i].length); ++ EVP_DigestFinal(&md, digest, NULL); ++ ++ encoded = xmalloc(EVP_MD_size(evp_md) * 2); ++ enclen = __b64_ntop(digest, EVP_MD_size(evp_md), ++ encoded, EVP_MD_size(evp_md) * 2); ++ ++ if (oidpos != 0) ++ buffer_put_char(&buf, ','); ++ ++ buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, ++ sizeof(KEX_GSS_GEX_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ buffer_put_char(&buf, ','); ++ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, ++ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ buffer_put_char(&buf, ','); ++ buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, ++ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ ++ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); ++ gss_enc2oid[oidpos].encoded = encoded; ++ oidpos++; ++ } ++ } ++ gss_enc2oid[oidpos].oid = NULL; ++ gss_enc2oid[oidpos].encoded = NULL; ++ ++ buffer_put_char(&buf, '\0'); ++ ++ mechs = xmalloc(buffer_len(&buf)); ++ buffer_get(&buf, mechs, buffer_len(&buf)); ++ buffer_free(&buf); ++ ++ if (strlen(mechs) == 0) { ++ free(mechs); ++ mechs = NULL; ++ } ++ ++ return (mechs); ++} ++ ++gss_OID ++ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { ++ int i = 0; ++ ++ switch (kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; ++ break; ++ case KEX_GSS_GEX_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; ++ break; ++ default: ++ return GSS_C_NO_OID; ++ } ++ ++ while (gss_enc2oid[i].encoded != NULL && ++ strcmp(name, gss_enc2oid[i].encoded) != 0) ++ i++; ++ ++ if (gss_enc2oid[i].oid != NULL && ctx != NULL) ++ ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); ++ ++ return gss_enc2oid[i].oid; ++} ++ + /* Check that the OID in a data stream matches that in the context */ + int + ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) +@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + } + + ctx->major = gss_init_sec_context(&ctx->minor, +- GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, ++ ctx->client_creds, &ctx->context, ctx->name, ctx->oid, + GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, + 0, NULL, recv_tok, NULL, send_tok, flags, NULL); + +@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + } + + OM_uint32 ++ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) ++{ ++ gss_buffer_desc gssbuf; ++ gss_name_t gssname; ++ OM_uint32 status; ++ gss_OID_set oidset; ++ ++ gssbuf.value = (void *) name; ++ gssbuf.length = strlen(gssbuf.value); ++ ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ ctx->major = gss_import_name(&ctx->minor, &gssbuf, ++ GSS_C_NT_USER_NAME, &gssname); ++ ++ if (!ctx->major) ++ ctx->major = gss_acquire_cred(&ctx->minor, ++ gssname, 0, oidset, GSS_C_INITIATE, ++ &ctx->client_creds, NULL, NULL); ++ ++ gss_release_name(&status, &gssname); ++ gss_release_oid_set(&status, &oidset); ++ ++ if (ctx->major) ++ ssh_gssapi_error(ctx); ++ ++ return(ctx->major); ++} ++ ++OM_uint32 + ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) + { ++ if (ctx == NULL) ++ return -1; ++ + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, + GSS_C_QOP_DEFAULT, buffer, hash))) + ssh_gssapi_error(ctx); +@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer + return (ctx->major); + } + ++/* Priviledged when used by server */ ++OM_uint32 ++ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++{ ++ if (ctx == NULL) ++ return -1; ++ ++ ctx->major = gss_verify_mic(&ctx->minor, ctx->context, ++ gssbuf, gssmic, NULL); ++ ++ return (ctx->major); ++} ++ + void + ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, + const char *context) +@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha + } + + int +-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) ++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, ++ const char *client) + { + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; ++ Gssctxt *intctx = NULL; ++ ++ if (ctx == NULL) ++ ctx = &intctx; + + /* RFC 4462 says we MUST NOT do SPNEGO */ + if (oid->length == spnego_oid.length && +@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + ssh_gssapi_build_ctx(ctx); + ssh_gssapi_set_oid(*ctx, oid); + major = ssh_gssapi_import_name(*ctx, host); ++ ++ if (!GSS_ERROR(major) && client) ++ major = ssh_gssapi_client_identity(*ctx, client); ++ + if (!GSS_ERROR(major)) { + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + NULL); +@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + GSS_C_NO_BUFFER); + } + +- if (GSS_ERROR(major)) ++ if (GSS_ERROR(major) || intctx != NULL) + ssh_gssapi_delete_ctx(ctx); + + return (!GSS_ERROR(major)); + } + ++int ++ssh_gssapi_credentials_updated(Gssctxt *ctxt) { ++ static gss_name_t saved_name = GSS_C_NO_NAME; ++ static OM_uint32 saved_lifetime = 0; ++ static gss_OID saved_mech = GSS_C_NO_OID; ++ static gss_name_t name; ++ static OM_uint32 last_call = 0; ++ OM_uint32 lifetime, now, major, minor; ++ int equal; ++ gss_cred_usage_t usage = GSS_C_INITIATE; ++ ++ now = time(NULL); ++ ++ if (ctxt) { ++ debug("Rekey has happened - updating saved versions"); ++ ++ if (saved_name != GSS_C_NO_NAME) ++ gss_release_name(&minor, &saved_name); ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &saved_name, &saved_lifetime, NULL, NULL); ++ ++ if (!GSS_ERROR(major)) { ++ saved_mech = ctxt->oid; ++ saved_lifetime+= now; ++ } else { ++ /* Handle the error */ ++ } ++ return 0; ++ } ++ ++ if (now - last_call < 10) ++ return 0; ++ ++ last_call = now; ++ ++ if (saved_mech == GSS_C_NO_OID) ++ return 0; ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &name, &lifetime, NULL, NULL); ++ if (major == GSS_S_CREDENTIALS_EXPIRED) ++ return 0; ++ else if (GSS_ERROR(major)) ++ return 0; ++ ++ major = gss_compare_name(&minor, saved_name, name, &equal); ++ gss_release_name(&minor, &name); ++ if (GSS_ERROR(major)) ++ return 0; ++ ++ if (equal && (saved_lifetime < lifetime + now - 10)) ++ return 1; ++ ++ return 0; ++} ++ + #endif /* GSSAPI */ +diff -up openssh-6.3p1/gss-serv-krb5.c.gsskex openssh-6.3p1/gss-serv-krb5.c +--- openssh-6.3p1/gss-serv-krb5.c.gsskex 2013-07-20 05:35:45.000000000 +0200 ++++ openssh-6.3p1/gss-serv-krb5.c 2013-10-11 15:26:02.165189578 +0200 +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -174,11 +174,25 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -190,6 +204,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -197,7 +276,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff -up openssh-6.3p1/gss-serv.c.gsskex openssh-6.3p1/gss-serv.c +--- openssh-6.3p1/gss-serv.c.gsskex 2013-07-20 05:35:45.000000000 +0200 ++++ openssh-6.3p1/gss-serv.c 2013-10-11 15:27:32.889763132 +0200 +@@ -45,15 +45,20 @@ + #include "channels.h" + #include "session.h" + #include "misc.h" ++#include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" ++ ++extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = + { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, +- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; ++ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; + + ssh_gssapi_mech gssapi_null_mech = +- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; ++ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + + #ifdef KRB5 + extern ssh_gssapi_mech gssapi_kerberos_mech; +@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) + char lname[MAXHOSTNAMELEN]; + gss_OID_set oidset; + +- gss_create_empty_oid_set(&status, &oidset); +- gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ if (options.gss_strict_acceptor) { ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ if (gethostname(lname, MAXHOSTNAMELEN)) { ++ gss_release_oid_set(&status, &oidset); ++ return (-1); ++ } + +- if (gethostname(lname, MAXHOSTNAMELEN)) { +- gss_release_oid_set(&status, &oidset); +- return (-1); +- } ++ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { ++ gss_release_oid_set(&status, &oidset); ++ return (ctx->major); ++ } ++ ++ if ((ctx->major = gss_acquire_cred(&ctx->minor, ++ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, ++ NULL, NULL))) ++ ssh_gssapi_error(ctx); + +- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { + gss_release_oid_set(&status, &oidset); + return (ctx->major); ++ } else { ++ ctx->name = GSS_C_NO_NAME; ++ ctx->creds = GSS_C_NO_CREDENTIAL; + } +- +- if ((ctx->major = gss_acquire_cred(&ctx->minor, +- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) +- ssh_gssapi_error(ctx); +- +- gss_release_oid_set(&status, &oidset); +- return (ctx->major); ++ return GSS_S_COMPLETE; + } + + /* Privileged */ +@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + } + + /* Unprivileged */ ++char * ++ssh_gssapi_server_mechanisms() { ++ gss_OID_set supported; ++ ++ ssh_gssapi_supported_oids(&supported); ++ return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, ++ NULL, NULL)); ++} ++ ++/* Unprivileged */ ++int ++ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, ++ const char *dummy) { ++ Gssctxt *ctx = NULL; ++ int res; ++ ++ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); ++ ssh_gssapi_delete_ctx(&ctx); ++ ++ return (res); ++} ++ ++/* Unprivileged */ + void + ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + gss_OID_set supported; + + gss_create_empty_oid_set(&min_status, oidset); +- gss_indicate_mechs(&min_status, &supported); ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ return; + + while (supported_mechs[i]->name != NULL) { + if (GSS_ERROR(gss_test_oid_set_member(&min_status, +@@ -249,8 +286,48 @@ OM_uint32 + ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) + { + int i = 0; ++ int equal = 0; ++ gss_name_t new_name = GSS_C_NO_NAME; ++ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; ++ ++ if (options.gss_store_rekey && client->used && ctx->client_creds) { ++ if (client->mech->oid.length != ctx->oid->length || ++ (memcmp(client->mech->oid.elements, ++ ctx->oid->elements, ctx->oid->length) !=0)) { ++ debug("Rekeyed credentials have different mechanism"); ++ return GSS_S_COMPLETE; ++ } ++ ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, ++ NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } + +- gss_buffer_desc ename; ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); ++ ++ if (GSS_ERROR(ctx->major)) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ if (!equal) { ++ debug("Rekeyed credentials have different name"); ++ return GSS_S_COMPLETE; ++ } ++ ++ debug("Marking rekeyed credentials for export"); ++ ++ gss_release_name(&ctx->minor, &client->name); ++ gss_release_cred(&ctx->minor, &client->creds); ++ client->name = new_name; ++ client->creds = ctx->client_creds; ++ ctx->client_creds = GSS_C_NO_CREDENTIAL; ++ client->updated = 1; ++ return GSS_S_COMPLETE; ++ } + + client->mech = NULL; + +@@ -265,6 +342,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + if (client->mech == NULL) + return GSS_S_FAILURE; + ++ if (ctx->client_creds && ++ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, + &client->displayname, NULL))) { + ssh_gssapi_error(ctx); +@@ -282,6 +366,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + return (ctx->major); + } + ++ gss_release_buffer(&ctx->minor, &ename); ++ + /* We can't copy this structure, so we just move the pointer to it */ + client->creds = ctx->client_creds; + ctx->client_creds = GSS_C_NO_CREDENTIAL; +@@ -292,11 +378,33 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + void + ssh_gssapi_cleanup_creds(void) + { ++ struct stat krb5_ccname_stat; ++ char krb5_ccname[128], *krb5_ccname_dir_end; ++ + if (gssapi_client.store.filename != NULL) { + /* Unlink probably isn't sufficient */ + debug("removing gssapi cred file\"%s\"", + gssapi_client.store.filename); + unlink(gssapi_client.store.filename); ++ ++ /* Ticket cache: DIR::/run/user/13558/krb5cc_T9eDKSQvzb/tkt */ ++ /* same code as in auth-krb5.c:krb5_cleanup_proc */ ++ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10); ++ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); ++ if (krb5_ccname_dir_end != NULL) ++ strcpy(krb5_ccname_dir_end, "/primary"); ++ ++ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { ++ if (unlink(krb5_ccname) == 0) { ++ *krb5_ccname_dir_end = '\0'; ++ if (rmdir(krb5_ccname) == -1) ++ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); ++ } ++ else ++ debug("cache primary file '%s', remove failed: %s", ++ krb5_ccname, strerror(errno) ++ ); ++ } + } + } + +@@ -329,7 +437,7 @@ ssh_gssapi_do_child(char ***envp, u_int + + /* Privileged */ + int +-ssh_gssapi_userok(char *user) ++ssh_gssapi_userok(char *user, struct passwd *pw) + { + OM_uint32 lmin; + +@@ -339,9 +447,11 @@ ssh_gssapi_userok(char *user) + return 0; + } + if (gssapi_client.mech && gssapi_client.mech->userok) +- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) ++ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { ++ gssapi_client.used = 1; ++ gssapi_client.store.owner = pw; + return 1; +- else { ++ } else { + /* Destroy delegated credentials if userok fails */ + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); +@@ -354,14 +464,90 @@ ssh_gssapi_userok(char *user) + return (0); + } + +-/* Privileged */ +-OM_uint32 +-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++/* These bits are only used for rekeying. The unpriviledged child is running ++ * as the user, the monitor is root. ++ * ++ * In the child, we want to : ++ * *) Ask the monitor to store our credentials into the store we specify ++ * *) If it succeeds, maybe do a PAM update ++ */ ++ ++/* Stuff for PAM */ ++ ++#ifdef USE_PAM ++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, ++ struct pam_response **resp, void *data) + { +- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, +- gssbuf, gssmic, NULL); ++ return (PAM_CONV_ERR); ++} ++#endif + +- return (ctx->major); ++void ++ssh_gssapi_rekey_creds() { ++ int ok; ++ int ret; ++#ifdef USE_PAM ++ pam_handle_t *pamh = NULL; ++ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; ++ char *envstr; ++#endif ++ ++ if (gssapi_client.store.filename == NULL && ++ gssapi_client.store.envval == NULL && ++ gssapi_client.store.envvar == NULL) ++ return; ++ ++ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); ++ ++ if (!ok) ++ return; ++ ++ debug("Rekeyed credentials stored successfully"); ++ ++ /* Actually managing to play with the ssh pam stack from here will ++ * be next to impossible. In any case, we may want different options ++ * for rekeying. So, use our own :) ++ */ ++#ifdef USE_PAM ++ if (!use_privsep) { ++ debug("Not even going to try and do PAM with privsep disabled"); ++ return; ++ } ++ ++ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, ++ &pamconv, &pamh); ++ if (ret) ++ return; ++ ++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, ++ gssapi_client.store.envval); ++ ++ ret = pam_putenv(pamh, envstr); ++ if (!ret) ++ pam_setcred(pamh, PAM_REINITIALIZE_CRED); ++ pam_end(pamh, PAM_SUCCESS); ++#endif ++} ++ ++int ++ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { ++ int ok = 0; ++ ++ /* Check we've got credentials to store */ ++ if (!gssapi_client.updated) ++ return 0; ++ ++ gssapi_client.updated = 0; ++ ++ temporarily_use_uid(gssapi_client.store.owner); ++ if (gssapi_client.mech && gssapi_client.mech->updatecreds) ++ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); ++ else ++ debug("No update function for this mechanism"); ++ ++ restore_uid(); ++ ++ return ok; + } + + #endif +diff -up openssh-6.3p1/kex.c.gsskex openssh-6.3p1/kex.c +--- openssh-6.3p1/kex.c.gsskex 2013-10-11 15:15:17.197216581 +0200 ++++ openssh-6.3p1/kex.c 2013-10-11 15:47:41.629242975 +0200 +@@ -51,6 +51,10 @@ + #include "roaming.h" + #include "audit.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) + # define evp_ssh_sha256 EVP_sha256 +@@ -81,6 +85,9 @@ static const struct kexalg kexalgs[] = { + { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, + { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, + #endif ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, EVP_sha1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, EVP_sha1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, EVP_sha1 }, + { NULL, -1, -1, NULL}, + }; + +diff -up openssh-6.3p1/kex.h.gsskex openssh-6.3p1/kex.h +--- openssh-6.3p1/kex.h.gsskex 2013-10-11 15:15:17.197216581 +0200 ++++ openssh-6.3p1/kex.h 2013-10-11 15:43:21.757429309 +0200 +@@ -74,6 +74,9 @@ enum kex_exchange { + KEX_DH_GEX_SHA1, + KEX_DH_GEX_SHA256, + KEX_ECDH_SHA2, ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GEX_SHA1, + KEX_MAX + }; + +@@ -133,6 +136,12 @@ struct Kex { + int flags; + const EVP_MD *evp_md; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *client_version_string; + char *server_version_string; + int (*verify_host_key)(Key *); +@@ -162,6 +171,11 @@ void kexgex_server(Kex *); + void kexecdh_client(Kex *); + void kexecdh_server(Kex *); + ++#ifdef GSSAPI ++void kexgss_client(Kex *); ++void kexgss_server(Kex *); ++#endif ++ + void newkeys_destroy(Newkeys *newkeys); + + void +diff -up openssh-6.3p1/kexgssc.c.gsskex openssh-6.3p1/kexgssc.c +--- openssh-6.3p1/kexgssc.c.gsskex 2013-10-11 15:15:17.287216162 +0200 ++++ openssh-6.3p1/kexgssc.c 2013-10-11 15:15:17.287216162 +0200 +@@ -0,0 +1,334 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. 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" ++ ++#ifdef GSSAPI ++ ++#include "includes.h" ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++ ++#include "ssh-gss.h" ++ ++void ++kexgss_client(Kex *kex) { ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; ++ Gssctxt *ctxt; ++ OM_uint32 maj_status, min_status, ret_flags; ++ u_int klen, kout, slen = 0, hashlen, strlen; ++ DH *dh; ++ BIGNUM *dh_server_pub = NULL; ++ BIGNUM *shared_secret = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ u_char *kbuf, *hash; ++ u_char *serverhostkey = NULL; ++ u_char *empty = ""; ++ char *msg; ++ char *lang; ++ int type = 0; ++ int first = 1; ++ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ dh = dh_new_group1(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ debug("Doing group exchange\n"); ++ nbits = dh_estimate(kex->we_need * 8); ++ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); ++ packet_put_int(min); ++ packet_put_int(nbits); ++ packet_put_int(max); ++ ++ packet_send(); ++ ++ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); ++ ++ if ((p = BN_new()) == NULL) ++ fatal("BN_new() failed"); ++ packet_get_bignum2(p); ++ if ((g = BN_new()) == NULL) ++ fatal("BN_new() failed"); ++ packet_get_bignum2(g); ++ packet_check_eom(); ++ ++ if (BN_num_bits(p) < min || BN_num_bits(p) > max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ min, BN_num_bits(p), max); ++ ++ dh = dh_new_group(g, p); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ /* Step 1 - e is dh->pub_key */ ++ dh_gen_key(dh, kex->we_need * 8); ++ ++ /* This is f, we initialise it now to make life easier */ ++ dh_server_pub = BN_new(); ++ if (dh_server_pub == NULL) ++ fatal("dh_server_pub == NULL"); ++ ++ token_ptr = GSS_C_NO_BUFFER; ++ ++ do { ++ debug("Calling gss_init_sec_context"); ++ ++ maj_status = ssh_gssapi_init_ctx(ctxt, ++ kex->gss_deleg_creds, token_ptr, &send_tok, ++ &ret_flags); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length != 0) { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ free(recv_tok.value); ++ ++ if (maj_status == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (first) { ++ packet_start(SSH2_MSG_KEXGSS_INIT); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ packet_put_bignum2(dh->pub_key); ++ first = 0; ++ } else { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ } ++ packet_send(); ++ gss_release_buffer(&min_status, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ do { ++ type = packet_read(); ++ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ debug("Received KEXGSS_HOSTKEY"); ++ if (serverhostkey) ++ fatal("Server host key received more than once"); ++ serverhostkey = ++ packet_get_string(&slen); ++ } ++ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ ++ switch (type) { ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ debug("Received GSSAPI_CONTINUE"); ++ if (maj_status == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ recv_tok.value = packet_get_string(&strlen); ++ recv_tok.length = strlen; ++ break; ++ case SSH2_MSG_KEXGSS_COMPLETE: ++ debug("Received GSSAPI_COMPLETE"); ++ packet_get_bignum2(dh_server_pub); ++ msg_tok.value = packet_get_string(&strlen); ++ msg_tok.length = strlen; ++ ++ /* Is there a token included? */ ++ if (packet_get_char()) { ++ recv_tok.value= ++ packet_get_string(&strlen); ++ recv_tok.length = strlen; ++ /* If we're already complete - protocol error */ ++ if (maj_status == GSS_S_COMPLETE) ++ packet_disconnect("Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ packet_disconnect("Protocol error: did not receive final token"); ++ } ++ break; ++ case SSH2_MSG_KEXGSS_ERROR: ++ debug("Received Error"); ++ maj_status = packet_get_int(); ++ min_status = packet_get_int(); ++ msg = packet_get_string(NULL); ++ lang = packet_get_string(NULL); ++ fatal("GSSAPI Error: \n%.400s",msg); ++ default: ++ packet_disconnect("Protocol error: didn't expect packet type %d", ++ type); ++ } ++ token_ptr = &recv_tok; ++ } else { ++ /* No data, and not complete */ ++ if (maj_status != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set dh_server_pub and msg_tok ++ */ ++ ++ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ ++ /* Check f in range [1, p-1] */ ++ if (!dh_pub_is_valid(dh, dh_server_pub)) ++ packet_disconnect("bad server public DH value"); ++ ++ /* compute K=f^x mod p */ ++ klen = DH_size(dh); ++ kbuf = xmalloc(klen); ++ kout = DH_compute_key(kbuf, dh_server_pub, dh); ++ if ((int)kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ if (shared_secret == NULL) ++ fatal("kexgss_client: BN_new failed"); ++ ++ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) ++ fatal("kexdh_client: BN_bin2bn failed"); ++ ++ memset(kbuf, 0, klen); ++ free(kbuf); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ kex_dh_hash( kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ (serverhostkey ? serverhostkey : empty), slen, ++ dh->pub_key, /* e */ ++ dh_server_pub, /* f */ ++ shared_secret, /* K */ ++ &hash, &hashlen ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ kexgex_hash( ++ kex->evp_md, ++ kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ (serverhostkey ? serverhostkey : empty), slen, ++ min, nbits, max, ++ dh->p, dh->g, ++ dh->pub_key, ++ dh_server_pub, ++ shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ packet_disconnect("Hash's MIC didn't verify"); ++ ++ free(msg_tok.value); ++ ++ DH_free(dh); ++ if (serverhostkey) ++ free(serverhostkey); ++ BN_clear_free(dh_server_pub); ++ ++ /* save session id */ ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); ++ } ++ ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ kex_derive_keys(kex, hash, hashlen, shared_secret); ++ BN_clear_free(shared_secret); ++ kex_finish(kex); ++} ++ ++#endif /* GSSAPI */ +diff -up openssh-6.3p1/kexgsss.c.gsskex openssh-6.3p1/kexgsss.c +--- openssh-6.3p1/kexgsss.c.gsskex 2013-10-11 15:15:17.287216162 +0200 ++++ openssh-6.3p1/kexgsss.c 2013-10-11 15:15:17.287216162 +0200 +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. 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" ++ ++#ifdef GSSAPI ++ ++#include ++ ++#include ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "servconf.h" ++ ++extern ServerOptions options; ++ ++void ++kexgss_server(Kex *kex) ++{ ++ OM_uint32 maj_status, min_status; ++ ++ /* ++ * Some GSSAPI implementations use the input value of ret_flags (an ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. ++ */ ++ ++ OM_uint32 ret_flags = 0; ++ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ Gssctxt *ctxt = NULL; ++ u_int slen, klen, kout, hashlen; ++ u_char *kbuf, *hash; ++ DH *dh; ++ int min = -1, max = -1, nbits = -1; ++ BIGNUM *shared_secret = NULL; ++ BIGNUM *dh_client_pub = NULL; ++ int type = 0; ++ gss_OID oid; ++ char *mechs; ++ ++ /* Initialise GSSAPI */ ++ ++ /* If we're rekeying, privsep means that some of the private structures ++ * in the GSSAPI code are no longer available. This kludges them back ++ * into life ++ */ ++ if (!ssh_gssapi_oid_table_ok()) ++ if ((mechs = ssh_gssapi_server_mechanisms())) ++ free(mechs); ++ ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ if (oid == GSS_C_NO_OID) ++ fatal("Unknown gssapi mechanism"); ++ ++ debug2("%s: Acquiring credentials", __func__); ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ fatal("Unable to acquire credentials for the server"); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ dh = dh_new_group1(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ debug("Doing group exchange"); ++ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); ++ min = packet_get_int(); ++ nbits = packet_get_int(); ++ max = packet_get_int(); ++ min = MAX(DH_GRP_MIN, min); ++ max = MIN(DH_GRP_MAX, max); ++ packet_check_eom(); ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", ++ min, nbits, max); ++ dh = PRIVSEP(choose_dh(min, nbits, max)); ++ if (dh == NULL) ++ packet_disconnect("Protocol error: no matching group found"); ++ ++ packet_start(SSH2_MSG_KEXGSS_GROUP); ++ packet_put_bignum2(dh->p); ++ packet_put_bignum2(dh->g); ++ packet_send(); ++ ++ packet_write_wait(); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ dh_gen_key(dh, kex->we_need * 8); ++ ++ do { ++ debug("Wait SSH2_MSG_GSSAPI_INIT"); ++ type = packet_read(); ++ switch(type) { ++ case SSH2_MSG_KEXGSS_INIT: ++ if (dh_client_pub != NULL) ++ fatal("Received KEXGSS_INIT after initialising"); ++ recv_tok.value = packet_get_string(&slen); ++ recv_tok.length = slen; ++ ++ if ((dh_client_pub = BN_new()) == NULL) ++ fatal("dh_client_pub == NULL"); ++ ++ packet_get_bignum2(dh_client_pub); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ break; ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ recv_tok.value = packet_get_string(&slen); ++ recv_tok.length = slen; ++ break; ++ default: ++ packet_disconnect( ++ "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags)); ++ ++ free(recv_tok.value); ++ ++ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (dh_client_pub == NULL) ++ fatal("No client public key"); ++ ++ if (maj_status & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, send_tok.length); ++ packet_send(); ++ gss_release_buffer(&min_status, &send_tok); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length > 0) { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, send_tok.length); ++ packet_send(); ++ } ++ fatal("accept_ctx died"); ++ } ++ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ if (!dh_pub_is_valid(dh, dh_client_pub)) ++ packet_disconnect("bad client public DH value"); ++ ++ klen = DH_size(dh); ++ kbuf = xmalloc(klen); ++ kout = DH_compute_key(kbuf, dh_client_pub, dh); ++ if ((int)kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ if (shared_secret == NULL) ++ fatal("kexgss_server: BN_new failed"); ++ ++ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) ++ fatal("kexgss_server: BN_bin2bn failed"); ++ ++ memset(kbuf, 0, klen); ++ free(kbuf); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ kex_dh_hash( ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ NULL, 0, /* Change this if we start sending host keys */ ++ dh_client_pub, dh->pub_key, shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ kexgex_hash( ++ kex->evp_md, ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ NULL, 0, ++ min, nbits, max, ++ dh->p, dh->g, ++ dh_client_pub, ++ dh->pub_key, ++ shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ BN_clear_free(dh_client_pub); ++ ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); ++ } ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) ++ fatal("Couldn't get MIC"); ++ ++ packet_start(SSH2_MSG_KEXGSS_COMPLETE); ++ packet_put_bignum2(dh->pub_key); ++ packet_put_string(msg_tok.value,msg_tok.length); ++ ++ if (send_tok.length != 0) { ++ packet_put_char(1); /* true */ ++ packet_put_string(send_tok.value, send_tok.length); ++ } else { ++ packet_put_char(0); /* false */ ++ } ++ packet_send(); ++ ++ gss_release_buffer(&min_status, &send_tok); ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ DH_free(dh); ++ ++ kex_derive_keys(kex, hash, hashlen, shared_secret); ++ BN_clear_free(shared_secret); ++ kex_finish(kex); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++} ++#endif /* GSSAPI */ +diff -up openssh-6.3p1/key.c.gsskex openssh-6.3p1/key.c +--- openssh-6.3p1/key.c.gsskex 2013-10-11 15:15:17.288216158 +0200 ++++ openssh-6.3p1/key.c 2013-10-11 15:41:44.982868222 +0200 +@@ -968,6 +968,7 @@ static const struct keytype keytypes[] = + KEY_RSA_CERT_V00, 0, 1 }, + { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", + KEY_DSA_CERT_V00, 0, 1 }, ++ { "null", "null", KEY_NULL, 0, 0 }, + { NULL, NULL, -1, -1, 0 } + }; + +diff -up openssh-6.3p1/key.h.gsskex openssh-6.3p1/key.h +--- openssh-6.3p1/key.h.gsskex 2013-10-11 15:15:17.198216576 +0200 ++++ openssh-6.3p1/key.h 2013-10-11 15:15:17.289216153 +0200 +@@ -44,6 +44,7 @@ enum types { + KEY_ECDSA_CERT, + KEY_RSA_CERT_V00, + KEY_DSA_CERT_V00, ++ KEY_NULL, + KEY_UNSPEC + }; + enum fp_type { +diff -up openssh-6.3p1/monitor.c.gsskex openssh-6.3p1/monitor.c +--- openssh-6.3p1/monitor.c.gsskex 2013-10-11 15:15:17.214216502 +0200 ++++ openssh-6.3p1/monitor.c 2013-10-11 15:15:17.290216148 +0200 +@@ -187,6 +187,8 @@ int mm_answer_gss_setup_ctx(int, Buffer + int mm_answer_gss_accept_ctx(int, Buffer *); + int mm_answer_gss_userok(int, Buffer *); + int mm_answer_gss_checkmic(int, Buffer *); ++int mm_answer_gss_sign(int, Buffer *); ++int mm_answer_gss_updatecreds(int, Buffer *); + #endif + + #ifdef SSH_AUDIT_EVENTS +@@ -271,6 +273,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, ++ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + #endif + #ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, +@@ -283,6 +286,12 @@ struct mon_table mon_dispatch_proto20[] + }; + + struct mon_table mon_dispatch_postauth20[] = { ++#ifdef GSSAPI ++ {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, ++ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, ++ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, ++ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, ++#endif + {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, + {MONITOR_REQ_SIGN, 0, mm_answer_sign}, + {MONITOR_REQ_PTY, 0, mm_answer_pty}, +@@ -405,6 +414,10 @@ monitor_child_preauth(Authctxt *_authctx + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + } else { + mon_dispatch = mon_dispatch_proto15; + +@@ -519,6 +532,10 @@ monitor_child_postauth(struct monitor *p + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + } else { + mon_dispatch = mon_dispatch_postauth15; + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); +@@ -1968,6 +1985,13 @@ mm_get_kex(Buffer *m) + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; ++ } ++#endif + kex->server = 1; + kex->hostkey_type = buffer_get_int(m); + kex->kex_type = buffer_get_int(m); +@@ -2192,6 +2216,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer + OM_uint32 major; + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + goid.elements = buffer_get_string(m, &len); + goid.length = len; + +@@ -2219,6 +2246,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe + OM_uint32 flags = 0; /* GSI needs this */ + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + in.value = buffer_get_string(m, &len); + in.length = len; + major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); +@@ -2236,6 +2266,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); + } + return (0); + } +@@ -2247,6 +2278,9 @@ mm_answer_gss_checkmic(int sock, Buffer + OM_uint32 ret; + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + gssbuf.value = buffer_get_string(m, &len); + gssbuf.length = len; + mic.value = buffer_get_string(m, &len); +@@ -2273,7 +2307,11 @@ mm_answer_gss_userok(int sock, Buffer *m + { + int authenticated; + +- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ ++ authenticated = authctxt->valid && ++ ssh_gssapi_userok(authctxt->user, authctxt->pw); + + buffer_clear(m); + buffer_put_int(m, authenticated); +@@ -2286,6 +2324,74 @@ mm_answer_gss_userok(int sock, Buffer *m + /* Monitor loop will terminate if authenticated */ + return (authenticated); + } ++ ++int ++mm_answer_gss_sign(int socket, Buffer *m) ++{ ++ gss_buffer_desc data; ++ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; ++ OM_uint32 major, minor; ++ u_int len; ++ ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ ++ data.value = buffer_get_string(m, &len); ++ data.length = len; ++ if (data.length != 20) ++ fatal("%s: data length incorrect: %d", __func__, ++ (int) data.length); ++ ++ /* Save the session ID on the first time around */ ++ if (session_id2_len == 0) { ++ session_id2_len = data.length; ++ session_id2 = xmalloc(session_id2_len); ++ memcpy(session_id2, data.value, session_id2_len); ++ } ++ major = ssh_gssapi_sign(gsscontext, &data, &hash); ++ ++ free(data.value); ++ ++ buffer_clear(m); ++ buffer_put_int(m, major); ++ buffer_put_string(m, hash.value, hash.length); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); ++ ++ gss_release_buffer(&minor, &hash); ++ ++ /* Turn on getpwnam permissions */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); ++ ++ /* And credential updating, for when rekeying */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); ++ ++ return (0); ++} ++ ++int ++mm_answer_gss_updatecreds(int socket, Buffer *m) { ++ ssh_gssapi_ccache store; ++ int ok; ++ ++ store.filename = buffer_get_string(m, NULL); ++ store.envvar = buffer_get_string(m, NULL); ++ store.envval = buffer_get_string(m, NULL); ++ ++ ok = ssh_gssapi_update_creds(&store); ++ ++ free(store.filename); ++ free(store.envvar); ++ free(store.envval); ++ ++ buffer_clear(m); ++ buffer_put_int(m, ok); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); ++ ++ return(0); ++} ++ + #endif /* GSSAPI */ + + #ifdef JPAKE +diff -up openssh-6.3p1/monitor.h.gsskex openssh-6.3p1/monitor.h +--- openssh-6.3p1/monitor.h.gsskex 2013-10-11 15:15:17.215216497 +0200 ++++ openssh-6.3p1/monitor.h 2013-10-11 15:15:17.290216148 +0200 +@@ -64,6 +64,8 @@ enum monitor_reqtype { + #ifdef WITH_SELINUX + MONITOR_REQ_AUTHROLE = 80, + #endif ++ MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83, ++ MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85, + + MONITOR_REQ_PAM_START = 100, + MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, +diff -up openssh-6.3p1/monitor_wrap.c.gsskex openssh-6.3p1/monitor_wrap.c +--- openssh-6.3p1/monitor_wrap.c.gsskex 2013-10-11 15:15:17.215216497 +0200 ++++ openssh-6.3p1/monitor_wrap.c 2013-10-11 15:15:17.290216148 +0200 +@@ -1329,7 +1329,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss + } + + int +-mm_ssh_gssapi_userok(char *user) ++mm_ssh_gssapi_userok(char *user, struct passwd *pw) + { + Buffer m; + int authenticated = 0; +@@ -1346,6 +1346,51 @@ mm_ssh_gssapi_userok(char *user) + debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); + return (authenticated); + } ++ ++OM_uint32 ++mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) ++{ ++ Buffer m; ++ OM_uint32 major; ++ u_int len; ++ ++ buffer_init(&m); ++ buffer_put_string(&m, data->value, data->length); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); ++ ++ major = buffer_get_int(&m); ++ hash->value = buffer_get_string(&m, &len); ++ hash->length = len; ++ ++ buffer_free(&m); ++ ++ return(major); ++} ++ ++int ++mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) ++{ ++ Buffer m; ++ int ok; ++ ++ buffer_init(&m); ++ ++ buffer_put_cstring(&m, store->filename ? store->filename : ""); ++ buffer_put_cstring(&m, store->envvar ? store->envvar : ""); ++ buffer_put_cstring(&m, store->envval ? store->envval : ""); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); ++ ++ ok = buffer_get_int(&m); ++ ++ buffer_free(&m); ++ ++ return (ok); ++} ++ + #endif /* GSSAPI */ + + #ifdef JPAKE +diff -up openssh-6.3p1/monitor_wrap.h.gsskex openssh-6.3p1/monitor_wrap.h +--- openssh-6.3p1/monitor_wrap.h.gsskex 2013-10-11 15:15:17.215216497 +0200 ++++ openssh-6.3p1/monitor_wrap.h 2013-10-11 15:15:17.290216148 +0200 +@@ -62,8 +62,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K + OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); + OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); +-int mm_ssh_gssapi_userok(char *user); ++int mm_ssh_gssapi_userok(char *user, struct passwd *); + OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); ++OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); ++int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); + #endif + + #ifdef USE_PAM +diff -up openssh-6.3p1/readconf.c.gsskex openssh-6.3p1/readconf.c +--- openssh-6.3p1/readconf.c.gsskex 2013-07-18 08:09:05.000000000 +0200 ++++ openssh-6.3p1/readconf.c 2013-10-11 15:15:17.291216143 +0200 +@@ -132,6 +132,8 @@ typedef enum { + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, + oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, ++ oGssServerIdentity, + oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oControlPath, oControlMaster, oControlPersist, + oHashKnownHosts, +@@ -172,10 +174,19 @@ static struct { + { "afstokenpassing", oUnsupported }, + #if defined(GSSAPI) + { "gssapiauthentication", oGssAuthentication }, ++ { "gssapikeyexchange", oGssKeyEx }, + { "gssapidelegatecredentials", oGssDelegateCreds }, ++ { "gssapitrustdns", oGssTrustDns }, ++ { "gssapiclientidentity", oGssClientIdentity }, ++ { "gssapiserveridentity", oGssServerIdentity }, ++ { "gssapirenewalforcesrekey", oGssRenewalRekey }, + #else + { "gssapiauthentication", oUnsupported }, ++ { "gssapikeyexchange", oUnsupported }, + { "gssapidelegatecredentials", oUnsupported }, ++ { "gssapitrustdns", oUnsupported }, ++ { "gssapiclientidentity", oUnsupported }, ++ { "gssapirenewalforcesrekey", oUnsupported }, + #endif + { "fallbacktorsh", oDeprecated }, + { "usersh", oDeprecated }, +@@ -516,10 +527,30 @@ parse_flag: + intptr = &options->gss_authentication; + goto parse_flag; + ++ case oGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case oGssDelegateCreds: + intptr = &options->gss_deleg_creds; + goto parse_flag; + ++ case oGssTrustDns: ++ intptr = &options->gss_trust_dns; ++ goto parse_flag; ++ ++ case oGssClientIdentity: ++ charptr = &options->gss_client_identity; ++ goto parse_string; ++ ++ case oGssServerIdentity: ++ charptr = &options->gss_server_identity; ++ goto parse_string; ++ ++ case oGssRenewalRekey: ++ intptr = &options->gss_renewal_rekey; ++ goto parse_flag; ++ + case oBatchMode: + intptr = &options->batch_mode; + goto parse_flag; +@@ -1168,7 +1199,12 @@ initialize_options(Options * options) + options->pubkey_authentication = -1; + options->challenge_response_authentication = -1; + options->gss_authentication = -1; ++ options->gss_keyex = -1; + options->gss_deleg_creds = -1; ++ options->gss_trust_dns = -1; ++ options->gss_renewal_rekey = -1; ++ options->gss_client_identity = NULL; ++ options->gss_server_identity = NULL; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->kbd_interactive_devices = NULL; +@@ -1268,8 +1304,14 @@ fill_default_options(Options * options) + options->challenge_response_authentication = 1; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_deleg_creds == -1) + options->gss_deleg_creds = 0; ++ if (options->gss_trust_dns == -1) ++ options->gss_trust_dns = 0; ++ if (options->gss_renewal_rekey == -1) ++ options->gss_renewal_rekey = 0; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +diff -up openssh-6.3p1/readconf.h.gsskex openssh-6.3p1/readconf.h +--- openssh-6.3p1/readconf.h.gsskex 2013-05-16 12:30:03.000000000 +0200 ++++ openssh-6.3p1/readconf.h 2013-10-11 15:15:17.291216143 +0200 +@@ -48,7 +48,12 @@ typedef struct { + int challenge_response_authentication; + /* Try S/Key or TIS, authentication. */ + int gss_authentication; /* Try GSS authentication */ ++ int gss_keyex; /* Try GSS key exchange */ + int gss_deleg_creds; /* Delegate GSS credentials */ ++ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ ++ int gss_renewal_rekey; /* Credential renewal forces rekey */ ++ char *gss_client_identity; /* Principal to initiate GSSAPI with */ ++ char *gss_server_identity; /* GSSAPI target principal */ + int password_authentication; /* Try password + * authentication. */ + int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ +diff -up openssh-6.3p1/servconf.c.gsskex openssh-6.3p1/servconf.c +--- openssh-6.3p1/servconf.c.gsskex 2013-10-11 15:15:17.273216227 +0200 ++++ openssh-6.3p1/servconf.c 2013-10-11 15:15:17.292216139 +0200 +@@ -107,7 +107,10 @@ initialize_server_options(ServerOptions + options->kerberos_ticket_cleanup = -1; + options->kerberos_get_afs_token = -1; + options->gss_authentication=-1; ++ options->gss_keyex = -1; + options->gss_cleanup_creds = -1; ++ options->gss_strict_acceptor = -1; ++ options->gss_store_rekey = -1; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->challenge_response_authentication = -1; +@@ -241,8 +244,14 @@ fill_default_server_options(ServerOption + options->kerberos_get_afs_token = 0; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_cleanup_creds == -1) + options->gss_cleanup_creds = 1; ++ if (options->gss_strict_acceptor == -1) ++ options->gss_strict_acceptor = 1; ++ if (options->gss_store_rekey == -1) ++ options->gss_store_rekey = 0; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +@@ -342,7 +351,9 @@ typedef enum { + sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, +- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, ++ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssKeyEx, sGssStoreRekey, ++ sAcceptEnv, sPermitTunnel, + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sHostCertificate, +@@ -409,10 +420,20 @@ static struct { + #ifdef GSSAPI + { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, + #else + { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, + #endif ++ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, + { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, + { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, +@@ -1078,10 +1099,22 @@ process_server_config_line(ServerOptions + intptr = &options->gss_authentication; + goto parse_flag; + ++ case sGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case sGssCleanupCreds: + intptr = &options->gss_cleanup_creds; + goto parse_flag; + ++ case sGssStrictAcceptor: ++ intptr = &options->gss_strict_acceptor; ++ goto parse_flag; ++ ++ case sGssStoreRekey: ++ intptr = &options->gss_store_rekey; ++ goto parse_flag; ++ + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; +@@ -1994,6 +2027,9 @@ dump_config(ServerOptions *o) + #ifdef GSSAPI + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); ++ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); ++ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); + #endif + #ifdef JPAKE + dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, +diff -up openssh-6.3p1/servconf.h.gsskex openssh-6.3p1/servconf.h +--- openssh-6.3p1/servconf.h.gsskex 2013-10-11 15:15:17.273216227 +0200 ++++ openssh-6.3p1/servconf.h 2013-10-11 15:15:17.292216139 +0200 +@@ -111,7 +111,10 @@ typedef struct { + int kerberos_get_afs_token; /* If true, try to get AFS token if + * authenticated with Kerberos. */ + int gss_authentication; /* If true, permit GSSAPI authentication */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_cleanup_creds; /* If true, destroy cred cache on logout */ ++ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ ++ int gss_store_rekey; + int password_authentication; /* If true, permit password + * authentication. */ + int kbd_interactive_authentication; /* If true, permit */ +diff -up openssh-6.3p1/ssh-gss.h.gsskex openssh-6.3p1/ssh-gss.h +--- openssh-6.3p1/ssh-gss.h.gsskex 2013-02-25 01:24:44.000000000 +0100 ++++ openssh-6.3p1/ssh-gss.h 2013-10-11 15:15:17.294216130 +0200 +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -61,10 +61,22 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +84,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +110,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -117,16 +134,30 @@ void ssh_gssapi_build_ctx(Gssctxt **); + void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +diff -up openssh-6.3p1/ssh_config.5.gsskex openssh-6.3p1/ssh_config.5 +--- openssh-6.3p1/ssh_config.5.gsskex 2013-07-18 08:11:50.000000000 +0200 ++++ openssh-6.3p1/ssh_config.5 2013-10-11 15:15:17.292216139 +0200 +@@ -529,11 +529,43 @@ Specifies whether user authentication ba + The default is + .Dq no . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIClientIdentity ++If set, specifies the GSSAPI client identity that ssh should use when ++connecting to the server. The default is unset, which means that the default ++identity will be used. ++.It Cm GSSAPIServerIdentity ++If set, specifies the GSSAPI server identity that ssh should expect when ++connecting to the server. The default is unset, which means that the ++expected GSSAPI server identity will be determined from the target ++hostname. + .It Cm GSSAPIDelegateCredentials + Forward (delegate) credentials to the server. + The default is + .Dq no . +-Note that this option applies to protocol version 2 only. ++Note that this option applies to protocol version 2 connections using GSSAPI. ++.It Cm GSSAPIRenewalForcesRekey ++If set to ++.Dq yes ++then renewal of the client's GSSAPI credentials will force the rekeying of the ++ssh connection. With a compatible server, this can delegate the renewed ++credentials to a session on the server. ++The default is ++.Dq no . ++.It Cm GSSAPITrustDns ++Set to ++.Dq yes to indicate that the DNS is trusted to securely canonicalize ++the name of the host being connected to. If ++.Dq no, the hostname entered on the ++command line will be passed untouched to the GSSAPI library. ++The default is ++.Dq no . ++This option only applies to protocol version 2 connections using GSSAPI. + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +diff -up openssh-6.3p1/ssh_config.gsskex openssh-6.3p1/ssh_config +--- openssh-6.3p1/ssh_config.gsskex 2013-10-11 15:15:17.265216264 +0200 ++++ openssh-6.3p1/ssh_config 2013-10-11 15:15:17.292216139 +0200 +@@ -26,6 +26,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +diff -up openssh-6.3p1/sshconnect2.c.gsskex openssh-6.3p1/sshconnect2.c +--- openssh-6.3p1/sshconnect2.c.gsskex 2013-10-11 15:15:17.251216330 +0200 ++++ openssh-6.3p1/sshconnect2.c 2013-10-11 15:28:22.617529416 +0200 +@@ -162,9 +162,34 @@ ssh_kex2(char *host, struct sockaddr *ho + { + Kex *kex; + ++#ifdef GSSAPI ++ char *orig = NULL, *gss = NULL; ++ char *gss_host = NULL; ++#endif ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ /* Add the GSSAPI mechanisms currently supported on this ++ * client to the key exchange algorithm proposal */ ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ if (options.gss_trust_dns) ++ gss_host = (char *)get_canonical_hostname(1); ++ else ++ gss_host = host; ++ ++ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ } ++ } ++#endif ++ + if (options.ciphers == (char *)-1) { + logit("No valid ciphers for protocol version 2 given, using defaults."); + options.ciphers = NULL; +@@ -207,6 +232,17 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.kex_algorithms != NULL) + myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; + ++#ifdef GSSAPI ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ if (options.gss_keyex && gss) { ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ free(gss); ++ } ++#endif ++ + if (options.rekey_limit || options.rekey_interval) + packet_set_rekey_limits((u_int32_t)options.rekey_limit, + (time_t)options.rekey_interval); +@@ -218,10 +254,30 @@ ssh_kex2(char *host, struct sockaddr *ho + kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + kex->kex[KEX_ECDH_SHA2] = kexecdh_client; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; ++ } ++#endif + kex->client_version_string=client_version_string; + kex->server_version_string=server_version_string; + kex->verify_host_key=&verify_host_key_callback; + ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->gss_deleg_creds = options.gss_deleg_creds; ++ kex->gss_trust_dns = options.gss_trust_dns; ++ kex->gss_client = options.gss_client_identity; ++ if (options.gss_server_identity) { ++ kex->gss_host = options.gss_server_identity; ++ } else { ++ kex->gss_host = gss_host; ++ } ++ } ++#endif ++ + xxx_kex = kex; + + dispatch_run(DISPATCH_BLOCK, &kex->done, kex); +@@ -317,6 +373,7 @@ void input_gssapi_token(int type, u_int3 + void input_gssapi_hash(int type, u_int32_t, void *); + void input_gssapi_error(int, u_int32_t, void *); + void input_gssapi_errtok(int, u_int32_t, void *); ++int userauth_gsskeyex(Authctxt *authctxt); + #endif + + void userauth(Authctxt *, char *); +@@ -332,6 +389,11 @@ static char *authmethods_get(void); + + Authmethod authmethods[] = { + #ifdef GSSAPI ++ {"gssapi-keyex", ++ userauth_gsskeyex, ++ NULL, ++ &options.gss_authentication, ++ NULL}, + {"gssapi-with-mic", + userauth_gssapi, + NULL, +@@ -636,19 +698,31 @@ userauth_gssapi(Authctxt *authctxt) + static u_int mech = 0; + OM_uint32 min; + int ok = 0; ++ const char *gss_host; ++ ++ if (options.gss_server_identity) ++ gss_host = options.gss_server_identity; ++ else if (options.gss_trust_dns) ++ gss_host = get_canonical_hostname(1); ++ else ++ gss_host = authctxt->host; + + /* Try one GSSAPI method at a time, rather than sending them all at + * once. */ + + if (gss_supported == NULL) +- gss_indicate_mechs(&min, &gss_supported); ++ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { ++ gss_supported = NULL; ++ return 0; ++ } + + /* Check to see if the mechanism is usable before we offer it */ + while (mech < gss_supported->count && !ok) { + /* My DER encoding requires length<128 */ + if (gss_supported->elements[mech].length < 128 && + ssh_gssapi_check_mechanism(&gssctxt, +- &gss_supported->elements[mech], authctxt->host)) { ++ &gss_supported->elements[mech], gss_host, ++ options.gss_client_identity)) { + ok = 1; /* Mechanism works */ + } else { + mech++; +@@ -745,8 +819,8 @@ input_gssapi_response(int type, u_int32_ + { + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; +- int oidlen; +- char *oidv; ++ u_int oidlen; ++ u_char *oidv; + + if (authctxt == NULL) + fatal("input_gssapi_response: no authentication context"); +@@ -855,6 +929,48 @@ input_gssapi_error(int type, u_int32_t p + free(msg); + free(lang); + } ++ ++int ++userauth_gsskeyex(Authctxt *authctxt) ++{ ++ Buffer b; ++ gss_buffer_desc gssbuf; ++ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ms; ++ ++ static int attempt = 0; ++ if (attempt++ >= 1) ++ return (0); ++ ++ if (gss_kex_context == NULL) { ++ debug("No valid Key exchange context"); ++ return (0); ++ } ++ ++ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex"); ++ ++ gssbuf.value = buffer_ptr(&b); ++ gssbuf.length = buffer_len(&b); ++ ++ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { ++ buffer_free(&b); ++ return (0); ++ } ++ ++ packet_start(SSH2_MSG_USERAUTH_REQUEST); ++ packet_put_cstring(authctxt->server_user); ++ packet_put_cstring(authctxt->service); ++ packet_put_cstring(authctxt->method->name); ++ packet_put_string(mic.value, mic.length); ++ packet_send(); ++ ++ buffer_free(&b); ++ gss_release_buffer(&ms, &mic); ++ ++ return (1); ++} ++ + #endif /* GSSAPI */ + + int +diff -up openssh-6.3p1/sshd.c.gsskex openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.gsskex 2013-10-11 15:15:17.277216209 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-11 15:15:17.294216130 +0200 +@@ -125,6 +125,10 @@ + #include "ssh-sandbox.h" + #include "version.h" + ++#ifdef USE_SECURITY_SESSION_API ++#include ++#endif ++ + #ifdef LIBWRAP + #include + #include +@@ -1794,10 +1798,13 @@ main(int ac, char **av) + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; + } ++#ifndef GSSAPI ++ /* The GSSAPI key exchange can run without a host key */ + if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { + logit("Disabling protocol version 2. Could not load host key"); + options.protocol &= ~SSH_PROTO_2; + } ++#endif + if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); +@@ -2130,6 +2137,60 @@ main(int ac, char **av) + /* Log the connection. */ + verbose("Connection from %.500s port %d", remote_ip, remote_port); + ++#ifdef USE_SECURITY_SESSION_API ++ /* ++ * Create a new security session for use by the new user login if ++ * the current session is the root session or we are not launched ++ * by inetd (eg: debugging mode or server mode). We do not ++ * necessarily need to create a session if we are launched from ++ * inetd because Panther xinetd will create a session for us. ++ * ++ * The only case where this logic will fail is if there is an ++ * inetd running in a non-root session which is not creating ++ * new sessions for us. Then all the users will end up in the ++ * same session (bad). ++ * ++ * When the client exits, the session will be destroyed for us ++ * automatically. ++ * ++ * We must create the session before any credentials are stored ++ * (including AFS pags, which happens a few lines below). ++ */ ++ { ++ OSStatus err = 0; ++ SecuritySessionId sid = 0; ++ SessionAttributeBits sattrs = 0; ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("Current Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ ++ if (inetd_flag && !(sattrs & sessionIsRoot)) ++ debug("Running in inetd mode in a non-root session... " ++ "assuming inetd created the session for us."); ++ else { ++ debug("Creating new security session..."); ++ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); ++ if (err) ++ error("SessionCreate() failed with error %.8X", ++ (unsigned) err); ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, ++ &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("New Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ } ++ } ++#endif ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2551,6 +2612,48 @@ do_ssh2_kex(void) + + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); + ++#ifdef GSSAPI ++ { ++ char *orig; ++ char *gss = NULL; ++ char *newstr = NULL; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ /* ++ * If we don't have a host key, then there's no point advertising ++ * the other key exchange algorithms ++ */ ++ ++ if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) ++ orig = NULL; ++ ++ if (options.gss_keyex) ++ gss = ssh_gssapi_server_mechanisms(); ++ else ++ gss = NULL; ++ ++ if (gss && orig) ++ xasprintf(&newstr, "%s,%s", gss, orig); ++ else if (gss) ++ newstr = gss; ++ else if (orig) ++ newstr = orig; ++ ++ /* ++ * If we've got GSSAPI mechanisms, then we've got the 'null' host ++ * key alg, but we can't tell people about it unless its the only ++ * host key algorithm we support ++ */ ++ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; ++ ++ if (newstr) ++ myproposal[PROPOSAL_KEX_ALGS] = newstr; ++ else ++ fatal("No supported key exchange algorithms"); ++ } ++#endif ++ + /* start key exchange */ + kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; +@@ -2558,6 +2661,13 @@ do_ssh2_kex(void) + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; ++ } ++#endif + kex->server = 1; + kex->client_version_string=client_version_string; + kex->server_version_string=server_version_string; +diff -up openssh-6.3p1/sshd_config.5.gsskex openssh-6.3p1/sshd_config.5 +--- openssh-6.3p1/sshd_config.5.gsskex 2013-10-11 15:15:17.274216223 +0200 ++++ openssh-6.3p1/sshd_config.5 2013-10-11 15:15:17.294216130 +0200 +@@ -484,12 +484,40 @@ Specifies whether user authentication ba + The default is + .Dq no . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange ++doesn't rely on ssh keys to verify host identity. ++The default is ++.Dq no . ++Note that this option applies to protocol version 2 only. + .It Cm GSSAPICleanupCredentials + Specifies whether to automatically destroy the user's credentials cache + on logout. + The default is + .Dq yes . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIStrictAcceptorCheck ++Determines whether to be strict about the identity of the GSSAPI acceptor ++a client authenticates against. If ++.Dq yes ++then the client must authenticate against the ++.Pa host ++service on the current hostname. If ++.Dq no ++then the client may authenticate against any service key stored in the ++machine's default store. This facility is provided to assist with operation ++on multi homed machines. ++The default is ++.Dq yes . ++Note that this option applies only to protocol version 2 GSSAPI connections, ++and setting it to ++.Dq no ++may only work with recent Kerberos GSSAPI libraries. ++.It Cm GSSAPIStoreCredentialsOnRekey ++Controls whether the user's GSSAPI credentials should be updated following a ++successful connection rekeying. This option can be used to accepted renewed ++or updated credentials from a compatible client. The default is ++.Dq no . + .It Cm HostbasedAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful public key client host authentication is allowed +diff -up openssh-6.3p1/sshd_config.gsskex openssh-6.3p1/sshd_config +--- openssh-6.3p1/sshd_config.gsskex 2013-10-11 15:15:17.277216209 +0200 ++++ openssh-6.3p1/sshd_config 2013-10-11 15:15:17.294216130 +0200 +@@ -92,6 +92,8 @@ ChallengeResponseAuthentication no + GSSAPIAuthentication yes + #GSSAPICleanupCredentials yes + GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will diff --git a/openssh-6.3p1-keycat.patch b/openssh-6.3p1-keycat.patch new file mode 100644 index 0000000..90cfb7e --- /dev/null +++ b/openssh-6.3p1-keycat.patch @@ -0,0 +1,371 @@ +diff -up openssh-6.3p1/HOWTO.ssh-keycat.keycat openssh-6.3p1/HOWTO.ssh-keycat +--- openssh-6.3p1/HOWTO.ssh-keycat.keycat 2013-10-10 15:16:33.445566916 +0200 ++++ openssh-6.3p1/HOWTO.ssh-keycat 2013-10-10 15:16:33.445566916 +0200 +@@ -0,0 +1,12 @@ ++The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys ++of an user in any environment. This includes environments with ++polyinstantiation of home directories and SELinux MLS policy enabled. ++ ++To use ssh-keycat, set these options in /etc/ssh/sshd_config file: ++ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat ++ AuthorizedKeysCommandRunAs root ++ ++Do not forget to enable public key authentication: ++ PubkeyAuthentication yes ++ ++ +diff -up openssh-6.3p1/Makefile.in.keycat openssh-6.3p1/Makefile.in +--- openssh-6.3p1/Makefile.in.keycat 2013-10-10 15:16:33.442566930 +0200 ++++ openssh-6.3p1/Makefile.in 2013-10-10 15:16:33.445566916 +0200 +@@ -27,6 +27,7 @@ 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_KEYCAT=$(libexecdir)/ssh-keycat + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ +@@ -64,7 +65,7 @@ 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) 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-keycat$(EXEEXT) + + LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ + canohost.o channels.o cipher.o cipher-aes.o \ +@@ -172,6 +173,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) + 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-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o ++ $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) ++ + 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) + +@@ -279,6 +283,7 @@ install-files: + $(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) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 +diff -up openssh-6.3p1/auth2-pubkey.c.keycat openssh-6.3p1/auth2-pubkey.c +--- openssh-6.3p1/auth2-pubkey.c.keycat 2013-10-10 15:16:33.429566992 +0200 ++++ openssh-6.3p1/auth2-pubkey.c 2013-10-10 15:16:33.445566916 +0200 +@@ -606,6 +606,14 @@ user_key_command_allowed2(struct passwd + _exit(1); + } + ++#ifdef WITH_SELINUX ++ if (ssh_selinux_setup_env_variables() < 0) { ++ error ("failed to copy environment: %s", ++ strerror(errno)); ++ _exit(127); ++ } ++#endif ++ + execl(options.authorized_keys_command, + options.authorized_keys_command, user_pw->pw_name, NULL); + +diff -up openssh-6.3p1/openbsd-compat/port-linux.c.keycat openssh-6.3p1/openbsd-compat/port-linux.c +--- openssh-6.3p1/openbsd-compat/port-linux.c.keycat 2013-10-10 15:16:33.435566964 +0200 ++++ openssh-6.3p1/openbsd-compat/port-linux.c 2013-10-10 15:32:19.946065189 +0200 +@@ -313,7 +313,7 @@ ssh_selinux_getctxbyname(char *pwname, + + /* Setup environment variables for pam_selinux */ + static int +-ssh_selinux_setup_pam_variables(void) ++ssh_selinux_setup_variables(int(*set_it)(const char *, const char *)) + { + const char *reqlvl; + char *role; +@@ -324,16 +324,16 @@ ssh_selinux_setup_pam_variables(void) + + ssh_selinux_get_role_level(&role, &reqlvl); + +- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); + + if (inetd_flag && !rexeced_flag) { + use_current = "1"; + } else { + use_current = ""; +- rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); + } + +- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current); + + if (role != NULL) + free(role); +@@ -341,6 +341,24 @@ ssh_selinux_setup_pam_variables(void) + return rv; + } + ++static int ++ssh_selinux_setup_pam_variables(void) ++{ ++ return ssh_selinux_setup_variables(do_pam_putenv); ++} ++ ++static int ++do_setenv(char *name, char *value) ++{ ++ return setenv(name, value, 1); ++} ++ ++int ++ssh_selinux_setup_env_variables(void) ++{ ++ return ssh_selinux_setup_variables(do_setenv); ++} ++ + /* Set the execution context to the default for the specified user */ + void + ssh_selinux_setup_exec_context(char *pwname) +diff -up openssh-6.3p1/ssh-keycat.c.keycat openssh-6.3p1/ssh-keycat.c +--- openssh-6.3p1/ssh-keycat.c.keycat 2013-10-10 15:16:33.446566911 +0200 ++++ openssh-6.3p1/ssh-keycat.c 2013-10-10 15:16:33.446566911 +0200 +@@ -0,0 +1,238 @@ ++/* ++ * 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, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 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. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``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. ++ */ ++ ++/* ++ * Copyright (c) 2011 Red Hat, Inc. ++ * Written by Tomas Mraz ++*/ ++ ++#define _GNU_SOURCE ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "uidswap.h" ++#include "misc.h" ++ ++#define ERR_USAGE 1 ++#define ERR_PAM_START 2 ++#define ERR_OPEN_SESSION 3 ++#define ERR_CLOSE_SESSION 4 ++#define ERR_PAM_END 5 ++#define ERR_GETPWNAM 6 ++#define ERR_MEMORY 7 ++#define ERR_OPEN 8 ++#define ERR_FILE_MODE 9 ++#define ERR_FDOPEN 10 ++#define ERR_STAT 11 ++#define ERR_WRITE 12 ++#define ERR_PAM_PUTENV 13 ++#define BUFLEN 4096 ++ ++/* Just ignore the messages in the conversation function */ ++static int ++dummy_conv(int num_msg, const struct pam_message **msgm, ++ struct pam_response **response, void *appdata_ptr) ++{ ++ struct pam_response *rsp; ++ ++ (void)msgm; ++ (void)appdata_ptr; ++ ++ if (num_msg <= 0) ++ return PAM_CONV_ERR; ++ ++ /* Just allocate the array as empty responses */ ++ rsp = calloc (num_msg, sizeof (struct pam_response)); ++ if (rsp == NULL) ++ return PAM_CONV_ERR; ++ ++ *response = rsp; ++ return PAM_SUCCESS; ++} ++ ++static struct pam_conv conv = { ++ dummy_conv, ++ NULL ++}; ++ ++char * ++make_auth_keys_name(const struct passwd *pwd) ++{ ++ char *fname; ++ ++ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0) ++ return NULL; ++ ++ return fname; ++} ++ ++int ++dump_keys(const char *user) ++{ ++ struct passwd *pwd; ++ int fd = -1; ++ FILE *f = NULL; ++ char *fname = NULL; ++ int rv = 0; ++ char buf[BUFLEN]; ++ size_t len; ++ struct stat st; ++ ++ if ((pwd = getpwnam(user)) == NULL) { ++ return ERR_GETPWNAM; ++ } ++ ++ if ((fname = make_auth_keys_name(pwd)) == NULL) { ++ return ERR_MEMORY; ++ } ++ ++ temporarily_use_uid(pwd); ++ ++ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) { ++ rv = ERR_OPEN; ++ goto fail; ++ } ++ ++ if (fstat(fd, &st) < 0) { ++ rv = ERR_STAT; ++ goto fail; ++ } ++ ++ if (!S_ISREG(st.st_mode) || ++ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) { ++ rv = ERR_FILE_MODE; ++ goto fail; ++ } ++ ++ unset_nonblock(fd); ++ ++ if ((f = fdopen(fd, "r")) == NULL) { ++ rv = ERR_FDOPEN; ++ goto fail; ++ } ++ ++ fd = -1; ++ ++ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { ++ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0; ++ } ++ ++fail: ++ if (fd != -1) ++ close(fd); ++ if (f != NULL) ++ fclose(f); ++ free(fname); ++ restore_uid(); ++ return rv; ++} ++ ++static const char *env_names[] = { "SELINUX_ROLE_REQUESTED", ++ "SELINUX_LEVEL_REQUESTED", ++ "SELINUX_USE_CURRENT_RANGE" ++}; ++ ++extern char **environ; ++ ++int ++set_pam_environment(pam_handle_t *pamh) ++{ ++ int i; ++ size_t j; ++ ++ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) { ++ int len = strlen(env_names[j]); ++ ++ for (i = 0; environ[i] != NULL; ++i) { ++ if (strncmp(env_names[j], environ[i], len) == 0 && ++ environ[i][len] == '=') { ++ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS) ++ return ERR_PAM_PUTENV; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ pam_handle_t *pamh = NULL; ++ int retval; ++ int ev = 0; ++ ++ if (argc != 2) { ++ fprintf(stderr, "Usage: %s \n", argv[0]); ++ return ERR_USAGE; ++ } ++ ++ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh); ++ if (retval != PAM_SUCCESS) { ++ return ERR_PAM_START; ++ } ++ ++ ev = set_pam_environment(pamh); ++ if (ev != 0) ++ goto finish; ++ ++ retval = pam_open_session(pamh, PAM_SILENT); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_OPEN_SESSION; ++ goto finish; ++ } ++ ++ ev = dump_keys(argv[1]); ++ ++ retval = pam_close_session(pamh, PAM_SILENT); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_CLOSE_SESSION; ++ } ++ ++finish: ++ retval = pam_end (pamh,retval); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_PAM_END; ++ } ++ return ev; ++} diff --git a/openssh-6.3p1-kuserok.patch b/openssh-6.3p1-kuserok.patch new file mode 100644 index 0000000..60688db --- /dev/null +++ b/openssh-6.3p1-kuserok.patch @@ -0,0 +1,167 @@ +diff -up openssh-6.3p1/auth-krb5.c.kuserok openssh-6.3p1/auth-krb5.c +--- openssh-6.3p1/auth-krb5.c.kuserok 2013-10-11 21:41:42.889087613 +0200 ++++ openssh-6.3p1/auth-krb5.c 2013-10-11 21:41:42.905087537 +0200 +@@ -55,6 +55,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) + { +@@ -159,7 +173,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-6.3p1/gss-serv-krb5.c.kuserok openssh-6.3p1/gss-serv-krb5.c +--- openssh-6.3p1/gss-serv-krb5.c.kuserok 2013-10-11 21:41:42.901087556 +0200 ++++ openssh-6.3p1/gss-serv-krb5.c 2013-10-11 21:46:42.898673597 +0200 +@@ -67,6 +67,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr + int); + + 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 */ + +@@ -116,7 +117,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + /* NOTE: .k5login and .k5users must opened as root, not the user, + * because if they are on a krb5-protected filesystem, user credentials + * to access these files aren't available yet. */ +- if (krb5_kuserok(krb_context, princ, name) && k5login_exists) { ++ if (ssh_krb5_kuserok(krb_context, princ, name) && k5login_exists) { + retval = 1; + logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", + name, (char *)client->displayname.value); +diff -up openssh-6.3p1/servconf.c.kuserok openssh-6.3p1/servconf.c +--- openssh-6.3p1/servconf.c.kuserok 2013-10-11 21:41:42.896087580 +0200 ++++ openssh-6.3p1/servconf.c 2013-10-11 21:48:24.664194016 +0200 +@@ -157,6 +157,7 @@ initialize_server_options(ServerOptions + options->ip_qos_interactive = -1; + options->ip_qos_bulk = -1; + options->version_addendum = NULL; ++ options->use_kuserok = -1; + } + + void +@@ -310,6 +311,8 @@ fill_default_server_options(ServerOption + options->version_addendum = xstrdup(""); + if (options->show_patchlevel == -1) + options->show_patchlevel = 0; ++ if (options->use_kuserok == -1) ++ options->use_kuserok = 1; + + /* Turn privilege separation on by default */ + if (use_privsep == -1) +@@ -336,7 +339,7 @@ typedef enum { + sPermitRootLogin, sLogFacility, sLogLevel, + sRhostsRSAAuthentication, sRSAAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, ++ sKerberosGetAFSToken, sKerberosUseKuserok, + sKerberosTgtPassing, sChallengeResponseAuthentication, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, +@@ -409,11 +412,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 }, +@@ -1515,6 +1520,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') +@@ -1815,6 +1824,7 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(max_authtries); + M_CP_INTOPT(ip_qos_interactive); + M_CP_INTOPT(ip_qos_bulk); ++ M_CP_INTOPT(use_kuserok); + M_CP_INTOPT(rekey_limit); + M_CP_INTOPT(rekey_interval); + +@@ -2055,6 +2065,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-6.3p1/servconf.h.kuserok openssh-6.3p1/servconf.h +--- openssh-6.3p1/servconf.h.kuserok 2013-10-11 21:41:42.896087580 +0200 ++++ openssh-6.3p1/servconf.h 2013-10-11 21:41:42.907087528 +0200 +@@ -174,6 +174,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-6.3p1/sshd_config.5.kuserok openssh-6.3p1/sshd_config.5 +--- openssh-6.3p1/sshd_config.5.kuserok 2013-10-11 21:41:42.898087571 +0200 ++++ openssh-6.3p1/sshd_config.5 2013-10-11 21:41:42.907087528 +0200 +@@ -675,6 +675,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. +@@ -833,6 +837,7 @@ Available keywords are + .Cm HostbasedUsesNameFromPacketOnly , + .Cm KbdInteractiveAuthentication , + .Cm KerberosAuthentication , ++.Cm KerberosUseKuserok , + .Cm MaxAuthTries , + .Cm MaxSessions , + .Cm PasswordAuthentication , +diff -up openssh-6.3p1/sshd_config.kuserok openssh-6.3p1/sshd_config +--- openssh-6.3p1/sshd_config.kuserok 2013-10-11 21:41:42.898087571 +0200 ++++ openssh-6.3p1/sshd_config 2013-10-11 21:41:42.907087528 +0200 +@@ -86,6 +86,7 @@ ChallengeResponseAuthentication no + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no ++#KerberosUseKuserok yes + + # GSSAPI options + #GSSAPIAuthentication no diff --git a/openssh-6.3p1-ldap.patch b/openssh-6.3p1-ldap.patch new file mode 100644 index 0000000..994ef59 --- /dev/null +++ b/openssh-6.3p1-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-6.3p1-privsep-selinux.patch b/openssh-6.3p1-privsep-selinux.patch new file mode 100644 index 0000000..529468c --- /dev/null +++ b/openssh-6.3p1-privsep-selinux.patch @@ -0,0 +1,104 @@ +diff -up openssh-6.3p1/openbsd-compat/port-linux.c.privsep-selinux openssh-6.3p1/openbsd-compat/port-linux.c +--- openssh-6.3p1/openbsd-compat/port-linux.c.privsep-selinux 2013-10-10 14:58:20.634762245 +0200 ++++ openssh-6.3p1/openbsd-compat/port-linux.c 2013-10-10 15:13:57.864306950 +0200 +@@ -503,6 +503,25 @@ ssh_selinux_change_context(const char *n + free(newctx); + } + ++void ++ssh_selinux_copy_context(void) ++{ ++ security_context_t *ctx; ++ ++ if (!ssh_selinux_enabled()) ++ return; ++ ++ if (getexeccon((security_context_t *)&ctx) != 0) { ++ logit("%s: getcon failed with %s", __func__, strerror (errno)); ++ return; ++ } ++ if (ctx != NULL) { ++ if (setcon(ctx) != 0) ++ logit("%s: setcon failed with %s", __func__, strerror (errno)); ++ freecon(ctx); ++ } ++} ++ + #endif /* WITH_SELINUX */ + + #ifdef LINUX_OOM_ADJUST +diff -up openssh-6.3p1/openbsd-compat/port-linux.h.privsep-selinux openssh-6.3p1/openbsd-compat/port-linux.h +--- openssh-6.3p1/openbsd-compat/port-linux.h.privsep-selinux 2011-01-25 02:16:18.000000000 +0100 ++++ openssh-6.3p1/openbsd-compat/port-linux.h 2013-10-10 14:58:20.634762245 +0200 +@@ -24,6 +24,7 @@ int ssh_selinux_enabled(void); + void ssh_selinux_setup_pty(char *, const char *); + void ssh_selinux_setup_exec_context(char *); + void ssh_selinux_change_context(const char *); ++void ssh_selinux_copy_context(void); + void ssh_selinux_setfscreatecon(const char *); + #endif + +diff -up openssh-6.3p1/session.c.privsep-selinux openssh-6.3p1/session.c +--- openssh-6.3p1/session.c.privsep-selinux 2013-10-10 14:58:20.617762326 +0200 ++++ openssh-6.3p1/session.c 2013-10-10 15:13:16.520503590 +0200 +@@ -1522,6 +1522,9 @@ do_setusercontext(struct passwd *pw) + pw->pw_uid); + chroot_path = percent_expand(tmp, "h", pw->pw_dir, + "u", pw->pw_name, (char *)NULL); ++#ifdef WITH_SELINUX ++ ssh_selinux_copy_context(); ++#endif + safely_chroot(chroot_path, pw->pw_uid); + free(tmp); + free(chroot_path); +@@ -1544,6 +1547,12 @@ do_setusercontext(struct passwd *pw) + /* Permanently switch to the desired uid. */ + permanently_set_uid(pw); + #endif ++ ++#ifdef WITH_SELINUX ++ if (options.chroot_directory == NULL || ++ strcasecmp(options.chroot_directory, "none") == 0) ++ ssh_selinux_copy_context(); ++#endif + } else if (options.chroot_directory != NULL && + strcasecmp(options.chroot_directory, "none") != 0) { + fatal("server lacks privileges to chroot to ChrootDirectory"); +@@ -1808,9 +1817,6 @@ do_child(Session *s, const char *command + argv[i] = NULL; + optind = optreset = 1; + __progname = argv[0]; +-#ifdef WITH_SELINUX +- ssh_selinux_change_context("sftpd_t"); +-#endif + exit(sftp_server_main(i, argv, s->pw)); + } + +diff -up openssh-6.3p1/sshd.c.privsep-selinux openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.privsep-selinux 2013-10-10 14:58:20.632762255 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-10 14:58:20.635762241 +0200 +@@ -668,6 +668,10 @@ privsep_preauth_child(void) + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + ++#ifdef WITH_SELINUX ++ ssh_selinux_change_context("sshd_net_t"); ++#endif ++ + /* Change our root directory */ + if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) + fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, +@@ -811,6 +815,13 @@ privsep_postauth(Authctxt *authctxt) + do_setusercontext(authctxt->pw); + + skip: ++#ifdef WITH_SELINUX ++ /* switch SELinux content for root too */ ++ if (authctxt->pw->pw_uid == 0) { ++ ssh_selinux_copy_context(); ++ } ++#endif ++ + /* It is safe now to apply the key state */ + monitor_apply_keystate(pmonitor); + diff --git a/openssh-6.3p1-redhat.patch b/openssh-6.3p1-redhat.patch new file mode 100644 index 0000000..5b1ec1d --- /dev/null +++ b/openssh-6.3p1-redhat.patch @@ -0,0 +1,117 @@ +diff -up openssh-6.3p1/ssh_config.redhat openssh-6.3p1/ssh_config +--- openssh-6.3p1/ssh_config.redhat 2013-10-11 14:51:18.345876648 +0200 ++++ openssh-6.3p1/ssh_config 2013-10-11 15:13:05.429829266 +0200 +@@ -46,3 +46,14 @@ + # VisualHostKey no + # ProxyCommand ssh -q -W %h:%p gateway.example.com + # RekeyLimit 1G 1h ++Host * ++ GSSAPIAuthentication yes ++# 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 ++# Send locale-related environment variables ++ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE ++ SendEnv XMODIFIERS +diff -up openssh-6.3p1/sshd_config.0.redhat openssh-6.3p1/sshd_config.0 +--- openssh-6.3p1/sshd_config.0.redhat 2013-09-13 08:20:43.000000000 +0200 ++++ openssh-6.3p1/sshd_config.0 2013-10-11 14:51:18.345876648 +0200 +@@ -653,9 +653,9 @@ DESCRIPTION + + SyslogFacility + Gives the facility code that is used when logging messages from +- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, +- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The +- default is AUTH. ++ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, ++ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. ++ The default is AUTH. + + TCPKeepAlive + Specifies whether the system should send TCP keepalive messages +diff -up openssh-6.3p1/sshd_config.5.redhat openssh-6.3p1/sshd_config.5 +--- openssh-6.3p1/sshd_config.5.redhat 2013-07-20 05:21:53.000000000 +0200 ++++ openssh-6.3p1/sshd_config.5 2013-10-11 14:51:18.346876643 +0200 +@@ -1095,7 +1095,7 @@ Note that this option applies to protoco + .It Cm SyslogFacility + Gives the facility code that is used when logging messages from + .Xr sshd 8 . +-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, ++The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, + LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. + The default is AUTH. + .It Cm TCPKeepAlive +diff -up openssh-6.3p1/sshd_config.redhat openssh-6.3p1/sshd_config +--- openssh-6.3p1/sshd_config.redhat 2013-10-11 14:51:18.343876657 +0200 ++++ openssh-6.3p1/sshd_config 2013-10-11 14:51:18.346876643 +0200 +@@ -10,6 +10,10 @@ + # possible, but leave them commented. Uncommented options override the + # default value. + ++# If you want to change the port on a SELinux system, you have to tell ++# SELinux about this change. ++# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER ++# + #Port 22 + #AddressFamily any + #ListenAddress 0.0.0.0 +@@ -35,6 +39,7 @@ + # Logging + # obsoletes QuietMode and FascistLogging + #SyslogFacility AUTH ++SyslogFacility AUTHPRIV + #LogLevel INFO + + # Authentication: +@@ -70,9 +75,11 @@ AuthorizedKeysFile .ssh/authorized_keys + # To disable tunneled clear text passwords, change to no here! + #PasswordAuthentication yes + #PermitEmptyPasswords no ++PasswordAuthentication yes + + # Change to no to disable s/key passwords + #ChallengeResponseAuthentication yes ++ChallengeResponseAuthentication no + + # Kerberos options + #KerberosAuthentication no +@@ -82,7 +89,9 @@ AuthorizedKeysFile .ssh/authorized_keys + + # GSSAPI options + #GSSAPIAuthentication no ++GSSAPIAuthentication yes + #GSSAPICleanupCredentials yes ++GSSAPICleanupCredentials yes + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +@@ -94,11 +103,13 @@ AuthorizedKeysFile .ssh/authorized_keys + # PAM authentication, then enable this but set PasswordAuthentication + # and ChallengeResponseAuthentication to 'no'. + #UsePAM no ++UsePAM yes + + #AllowAgentForwarding yes + #AllowTcpForwarding yes + #GatewayPorts no + #X11Forwarding no ++X11Forwarding yes + #X11DisplayOffset 10 + #X11UseLocalhost yes + #PrintMotd yes +@@ -120,6 +131,12 @@ UsePrivilegeSeparation sandbox # Defaul + # no default banner path + #Banner none + ++# Accept locale-related environment variables ++AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE ++AcceptEnv XMODIFIERS ++ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + diff --git a/openssh-6.3p1-role-mls.patch b/openssh-6.3p1-role-mls.patch new file mode 100644 index 0000000..89d54b3 --- /dev/null +++ b/openssh-6.3p1-role-mls.patch @@ -0,0 +1,931 @@ +diff -up openssh-6.3p1/auth-pam.c.role-mls openssh-6.3p1/auth-pam.c +--- openssh-6.3p1/auth-pam.c.role-mls 2013-10-10 14:34:43.799494546 +0200 ++++ openssh-6.3p1/auth-pam.c 2013-10-10 14:34:43.835494375 +0200 +@@ -1071,7 +1071,7 @@ is_pam_session_open(void) + * during the ssh authentication process. + */ + int +-do_pam_putenv(char *name, char *value) ++do_pam_putenv(char *name, const char *value) + { + int ret = 1; + #ifdef HAVE_PAM_PUTENV +diff -up openssh-6.3p1/auth-pam.h.role-mls openssh-6.3p1/auth-pam.h +--- openssh-6.3p1/auth-pam.h.role-mls 2004-09-11 14:17:26.000000000 +0200 ++++ openssh-6.3p1/auth-pam.h 2013-10-10 14:34:43.835494375 +0200 +@@ -38,7 +38,7 @@ void do_pam_session(void); + void do_pam_set_tty(const char *); + void do_pam_setcred(int ); + void do_pam_chauthtok(void); +-int do_pam_putenv(char *, char *); ++int do_pam_putenv(char *, const char *); + char ** fetch_pam_environment(void); + char ** fetch_pam_child_environment(void); + void free_pam_environment(char **); +diff -up openssh-6.3p1/auth.h.role-mls openssh-6.3p1/auth.h +--- openssh-6.3p1/auth.h.role-mls 2013-10-10 14:34:43.834494379 +0200 ++++ openssh-6.3p1/auth.h 2013-10-10 14:38:45.060348227 +0200 +@@ -59,6 +59,9 @@ struct Authctxt { + char *service; + struct passwd *pw; /* set if 'valid' */ + char *style; ++#ifdef WITH_SELINUX ++ char *role; ++#endif + void *kbdintctxt; + char *info; /* Extra info for next auth_log */ + void *jpake_ctx; +diff -up openssh-6.3p1/auth1.c.role-mls openssh-6.3p1/auth1.c +--- openssh-6.3p1/auth1.c.role-mls 2013-06-02 00:01:24.000000000 +0200 ++++ openssh-6.3p1/auth1.c 2013-10-10 14:34:43.835494375 +0200 +@@ -381,6 +381,9 @@ do_authentication(Authctxt *authctxt) + { + u_int ulen; + char *user, *style = NULL; ++#ifdef WITH_SELINUX ++ char *role=NULL; ++#endif + + /* Get the name of the user that we wish to log in as. */ + packet_read_expect(SSH_CMSG_USER); +@@ -389,11 +392,24 @@ do_authentication(Authctxt *authctxt) + user = packet_get_cstring(&ulen); + packet_check_eom(); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = '\0'; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = '\0'; ++#ifdef WITH_SELINUX ++ else ++ if (role && (style = strchr(role, ':')) != NULL) ++ *style++ = '\0'; ++#endif + + authctxt->user = user; + authctxt->style = style; ++#ifdef WITH_SELINUX ++ authctxt->role = role; ++#endif + + /* Verify that the user is a valid user. */ + if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) +diff -up openssh-6.3p1/auth2-gss.c.role-mls openssh-6.3p1/auth2-gss.c +--- openssh-6.3p1/auth2-gss.c.role-mls 2013-06-01 23:31:18.000000000 +0200 ++++ openssh-6.3p1/auth2-gss.c 2013-10-10 14:34:43.836494370 +0200 +@@ -256,6 +256,7 @@ input_gssapi_mic(int type, u_int32_t ple + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; + int authenticated = 0; ++ char *micuser; + Buffer b; + gss_buffer_desc mic, gssbuf; + u_int len; +@@ -268,7 +269,13 @@ input_gssapi_mic(int type, u_int32_t ple + mic.value = packet_get_string(&len); + mic.length = len; + +- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, ++#ifdef WITH_SELINUX ++ if (authctxt->role && (strlen(authctxt->role) > 0)) ++ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); ++ else ++#endif ++ micuser = authctxt->user; ++ ssh_gssapi_buildmic(&b, micuser, authctxt->service, + "gssapi-with-mic"); + + gssbuf.value = buffer_ptr(&b); +@@ -280,6 +287,8 @@ input_gssapi_mic(int type, u_int32_t ple + logit("GSSAPI MIC check failed"); + + buffer_free(&b); ++ if (micuser != authctxt->user) ++ free(micuser); + free(mic.value); + + authctxt->postponed = 0; +diff -up openssh-6.3p1/auth2-hostbased.c.role-mls openssh-6.3p1/auth2-hostbased.c +--- openssh-6.3p1/auth2-hostbased.c.role-mls 2013-10-10 14:34:43.818494455 +0200 ++++ openssh-6.3p1/auth2-hostbased.c 2013-10-10 14:34:43.836494370 +0200 +@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt) + buffer_put_string(&b, session_id2, session_id2_len); + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); +- buffer_put_cstring(&b, authctxt->user); ++#ifdef WITH_SELINUX ++ if (authctxt->role) { ++ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); ++ buffer_append(&b, authctxt->user, strlen(authctxt->user)); ++ buffer_put_char(&b, '/'); ++ buffer_append(&b, authctxt->role, strlen(authctxt->role)); ++ } else ++#endif ++ buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, service); + buffer_put_cstring(&b, "hostbased"); + buffer_put_string(&b, pkalg, alen); +diff -up openssh-6.3p1/auth2-pubkey.c.role-mls openssh-6.3p1/auth2-pubkey.c +--- openssh-6.3p1/auth2-pubkey.c.role-mls 2013-10-10 14:34:43.836494370 +0200 ++++ openssh-6.3p1/auth2-pubkey.c 2013-10-10 14:57:17.452062486 +0200 +@@ -127,9 +127,11 @@ userauth_pubkey(Authctxt *authctxt) + } + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); +- xasprintf(&userstyle, "%s%s%s", authctxt->user, ++ xasprintf(&userstyle, "%s%s%s%s%s", authctxt->user, + authctxt->style ? ":" : "", +- authctxt->style ? authctxt->style : ""); ++ authctxt->style ? authctxt->style : "", ++ authctxt->role ? "/" : "", ++ authctxt->role ? authctxt->role : ""); + buffer_put_cstring(&b, userstyle); + free(userstyle); + buffer_put_cstring(&b, +diff -up openssh-6.3p1/auth2.c.role-mls openssh-6.3p1/auth2.c +--- openssh-6.3p1/auth2.c.role-mls 2013-10-10 14:34:43.819494451 +0200 ++++ openssh-6.3p1/auth2.c 2013-10-10 14:34:43.835494375 +0200 +@@ -221,6 +221,9 @@ input_userauth_request(int type, u_int32 + Authctxt *authctxt = ctxt; + Authmethod *m = NULL; + char *user, *service, *method, *style = NULL; ++#ifdef WITH_SELINUX ++ char *role = NULL; ++#endif + int authenticated = 0; + + if (authctxt == NULL) +@@ -232,6 +235,11 @@ input_userauth_request(int type, u_int32 + debug("userauth-request for user %s service %s method %s", user, service, method); + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = 0; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; + +@@ -254,8 +262,15 @@ input_userauth_request(int type, u_int32 + use_privsep ? " [net]" : ""); + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; +- if (use_privsep) ++#ifdef WITH_SELINUX ++ authctxt->role = role ? xstrdup(role) : NULL; ++#endif ++ if (use_privsep) { + mm_inform_authserv(service, style); ++#ifdef WITH_SELINUX ++ mm_inform_authrole(role); ++#endif ++ } + userauth_banner(); + if (auth2_setup_methods_lists(authctxt) != 0) + packet_disconnect("no authentication methods enabled"); +diff -up openssh-6.3p1/misc.c.role-mls openssh-6.3p1/misc.c +--- openssh-6.3p1/misc.c.role-mls 2013-08-08 04:50:06.000000000 +0200 ++++ openssh-6.3p1/misc.c 2013-10-10 14:34:43.836494370 +0200 +@@ -429,6 +429,7 @@ char * + colon(char *cp) + { + int flag = 0; ++ int start = 1; + + if (*cp == ':') /* Leading colon is part of file name. */ + return NULL; +@@ -444,6 +445,13 @@ colon(char *cp) + return (cp); + if (*cp == '/') + return NULL; ++ if (start) { ++ /* Slash on beginning or after dots only denotes file name. */ ++ if (*cp == '/') ++ return (0); ++ if (*cp != '.') ++ start = 0; ++ } + } + return NULL; + } +diff -up openssh-6.3p1/monitor.c.role-mls openssh-6.3p1/monitor.c +--- openssh-6.3p1/monitor.c.role-mls 2013-10-10 14:34:43.821494441 +0200 ++++ openssh-6.3p1/monitor.c 2013-10-10 14:54:57.933725463 +0200 +@@ -149,6 +149,9 @@ int mm_answer_sign(int, Buffer *); + int mm_answer_pwnamallow(int, Buffer *); + int mm_answer_auth2_read_banner(int, Buffer *); + int mm_answer_authserv(int, Buffer *); ++#ifdef WITH_SELINUX ++int mm_answer_authrole(int, Buffer *); ++#endif + int mm_answer_authpassword(int, Buffer *); + int mm_answer_bsdauthquery(int, Buffer *); + int mm_answer_bsdauthrespond(int, Buffer *); +@@ -233,6 +236,9 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, ++#ifdef WITH_SELINUX ++ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, ++#endif + {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, + #ifdef USE_PAM +@@ -853,6 +859,9 @@ mm_answer_pwnamallow(int sock, Buffer *m + else { + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); ++#ifdef WITH_SELINUX ++ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); ++#endif + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + } + #ifdef USE_PAM +@@ -894,6 +903,25 @@ mm_answer_authserv(int sock, Buffer *m) + return (0); + } + ++#ifdef WITH_SELINUX ++int ++mm_answer_authrole(int sock, Buffer *m) ++{ ++ monitor_permit_authentications(1); ++ ++ authctxt->role = buffer_get_string(m, NULL); ++ debug3("%s: role=%s", ++ __func__, authctxt->role); ++ ++ if (strlen(authctxt->role) == 0) { ++ free(authctxt->role); ++ authctxt->role = NULL; ++ } ++ ++ return (0); ++} ++#endif ++ + int + mm_answer_authpassword(int sock, Buffer *m) + { +@@ -1269,7 +1297,7 @@ static int + monitor_valid_userblob(u_char *data, u_int datalen) + { + Buffer b; +- char *p, *userstyle; ++ char *p, *r, *userstyle; + u_int len; + int fail = 0; + +@@ -1295,6 +1323,8 @@ monitor_valid_userblob(u_char *data, u_i + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_cstring(&b, NULL); ++ if ((r = strchr(p, '/')) != NULL) ++ *r = '\0'; + xasprintf(&userstyle, "%s%s%s", authctxt->user, + authctxt->style ? ":" : "", + authctxt->style ? authctxt->style : ""); +@@ -1330,7 +1360,7 @@ monitor_valid_hostbasedblob(u_char *data + char *chost) + { + Buffer b; +- char *p, *userstyle; ++ char *p, *r, *userstyle; + u_int len; + int fail = 0; + +@@ -1347,6 +1377,8 @@ monitor_valid_hostbasedblob(u_char *data + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_cstring(&b, NULL); ++ if ((r = strchr(p, '/')) != NULL) ++ *r = '\0'; + xasprintf(&userstyle, "%s%s%s", authctxt->user, + authctxt->style ? ":" : "", + authctxt->style ? authctxt->style : ""); +diff -up openssh-6.3p1/monitor.h.role-mls openssh-6.3p1/monitor.h +--- openssh-6.3p1/monitor.h.role-mls 2013-10-10 14:34:43.821494441 +0200 ++++ openssh-6.3p1/monitor.h 2013-10-10 14:34:43.837494365 +0200 +@@ -61,6 +61,9 @@ enum monitor_reqtype { + MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57, + MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59, + MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61, ++#ifdef WITH_SELINUX ++ MONITOR_REQ_AUTHROLE = 80, ++#endif + + MONITOR_REQ_PAM_START = 100, + MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, +diff -up openssh-6.3p1/monitor_wrap.c.role-mls openssh-6.3p1/monitor_wrap.c +--- openssh-6.3p1/monitor_wrap.c.role-mls 2013-10-10 14:34:43.822494436 +0200 ++++ openssh-6.3p1/monitor_wrap.c 2013-10-10 14:34:43.838494360 +0200 +@@ -338,6 +338,25 @@ mm_inform_authserv(char *service, char * + buffer_free(&m); + } + ++/* Inform the privileged process about role */ ++ ++#ifdef WITH_SELINUX ++void ++mm_inform_authrole(char *role) ++{ ++ Buffer m; ++ ++ debug3("%s entering", __func__); ++ ++ buffer_init(&m); ++ buffer_put_cstring(&m, role ? role : ""); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); ++ ++ buffer_free(&m); ++} ++#endif ++ + /* Do the password authentication */ + int + mm_auth_password(Authctxt *authctxt, char *password) +diff -up openssh-6.3p1/monitor_wrap.h.role-mls openssh-6.3p1/monitor_wrap.h +--- openssh-6.3p1/monitor_wrap.h.role-mls 2013-10-10 14:34:43.822494436 +0200 ++++ openssh-6.3p1/monitor_wrap.h 2013-10-10 14:34:43.838494360 +0200 +@@ -42,6 +42,9 @@ int mm_is_monitor(void); + DH *mm_choose_dh(int, int, int); + int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); + void mm_inform_authserv(char *, char *); ++#ifdef WITH_SELINUX ++void mm_inform_authrole(char *); ++#endif + struct passwd *mm_getpwnamallow(const char *); + char *mm_auth2_read_banner(void); + int mm_auth_password(struct Authctxt *, char *); +diff -up openssh-6.3p1/openbsd-compat/Makefile.in.role-mls openssh-6.3p1/openbsd-compat/Makefile.in +--- openssh-6.3p1/openbsd-compat/Makefile.in.role-mls 2013-05-10 08:28:56.000000000 +0200 ++++ openssh-6.3p1/openbsd-compat/Makefile.in 2013-10-10 14:34:43.838494360 +0200 +@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport + + COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o + +-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o ++PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o + + .c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +diff -up openssh-6.3p1/openbsd-compat/port-linux.c.role-mls openssh-6.3p1/openbsd-compat/port-linux.c +--- openssh-6.3p1/openbsd-compat/port-linux.c.role-mls 2013-06-02 00:07:32.000000000 +0200 ++++ openssh-6.3p1/openbsd-compat/port-linux.c 2013-10-10 14:40:41.841793347 +0200 +@@ -31,68 +31,271 @@ + + #include "log.h" + #include "xmalloc.h" ++#include "servconf.h" + #include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" + + #ifdef WITH_SELINUX + #include + #include ++#include + #include ++#include ++#include ++ ++#ifdef HAVE_LINUX_AUDIT ++#include ++#include ++#endif + + #ifndef SSH_SELINUX_UNCONFINED_TYPE + # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:" + #endif + +-/* Wrapper around is_selinux_enabled() to log its return value once only */ +-int +-ssh_selinux_enabled(void) ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern int inetd_flag; ++extern int rexeced_flag; ++ ++/* Send audit message */ ++static int ++send_audit_message(int success, security_context_t default_context, ++ security_context_t selected_context) + { +- static int enabled = -1; ++ int rc=0; ++#ifdef HAVE_LINUX_AUDIT ++ char *msg = NULL; ++ int audit_fd = audit_open(); ++ security_context_t default_raw=NULL; ++ security_context_t selected_raw=NULL; ++ rc = -1; ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 0; /* No audit support in kernel */ ++ error("Error connecting to audit system."); ++ return rc; ++ } ++ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { ++ error("Error translating default context."); ++ default_raw = NULL; ++ } ++ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { ++ error("Error translating selected context."); ++ selected_raw = NULL; ++ } ++ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", ++ default_raw ? default_raw : (default_context ? default_context: "?"), ++ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { ++ error("Error allocating memory."); ++ goto out; ++ } ++ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, ++ msg, NULL, NULL, NULL, success) <= 0) { ++ error("Error sending audit message."); ++ goto out; ++ } ++ rc = 0; ++ out: ++ free(msg); ++ freecon(default_raw); ++ freecon(selected_raw); ++ close(audit_fd); ++#endif ++ return rc; ++} ++ ++static int ++mls_range_allowed(security_context_t src, security_context_t dst) ++{ ++ struct av_decision avd; ++ int retval; ++ unsigned int bit = CONTEXT__CONTAINS; ++ ++ debug("%s: src:%s dst:%s", __func__, src, dst); ++ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); ++ if (retval || ((bit & avd.allowed) != bit)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++get_user_context(const char *sename, const char *role, const char *lvl, ++ security_context_t *sc) { ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { ++ /* User may have requested a level completely outside of his ++ allowed range. We get a context just for auditing as the ++ range check below will certainly fail for default context. */ ++#endif ++ if (get_default_context(sename, NULL, sc) != 0) { ++ *sc = NULL; ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ } ++#endif ++ if (role != NULL && role[0]) { ++ context_t con; ++ char *type=NULL; ++ if (get_default_type(role, &type) != 0) { ++ error("get_default_type: failed to get default type for '%s'", ++ role); ++ goto out; ++ } ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_role_set(con, role); ++ context_type_set(con, type); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ if (!*sc) ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl != NULL && lvl[0]) { ++ /* verify that the requested range is obtained */ ++ context_t con; ++ security_context_t obtained_raw; ++ security_context_t requested_raw; ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_range_set(con, lvl); ++ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { ++ context_free(con); ++ goto out; ++ } ++ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { ++ freecon(obtained_raw); ++ context_free(con); ++ goto out; ++ } + +- if (enabled == -1) { +- enabled = (is_selinux_enabled() == 1); +- debug("SELinux support %s", enabled ? "enabled" : "disabled"); ++ debug("get_user_context: obtained context '%s' requested context '%s'", ++ obtained_raw, requested_raw); ++ if (strcmp(obtained_raw, requested_raw)) { ++ /* set the context to the real requested one but fail */ ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ return -1; ++ } ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ context_free(con); + } ++#endif ++ return 0; ++ out: ++ freecon(*sc); ++ *sc = NULL; ++ return -1; ++} + +- return (enabled); ++static void ++ssh_selinux_get_role_level(char **role, const char **level) ++{ ++ *role = NULL; ++ *level = NULL; ++ if (the_authctxt) { ++ if (the_authctxt->role != NULL) { ++ char *slash; ++ *role = xstrdup(the_authctxt->role); ++ if ((slash = strchr(*role, '/')) != NULL) { ++ *slash = '\0'; ++ *level = slash + 1; ++ } ++ } ++ } + } + + /* Return the default security context for the given username */ + static security_context_t +-ssh_selinux_getctxbyname(char *pwname) ++ssh_selinux_getctxbyname(char *pwname, ++ security_context_t *default_sc, security_context_t *user_sc) + { +- security_context_t sc = NULL; +- char *sename = NULL, *lvl = NULL; +- int r; ++ char *sename, *lvl; ++ char *role; ++ const char *reqlvl; ++ int r = 0; ++ context_t con = NULL; ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); + + #ifdef HAVE_GETSEUSERBYNAME +- if (getseuserbyname(pwname, &sename, &lvl) != 0) +- return NULL; ++ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { ++ sename = NULL; ++ lvl = NULL; ++ } + #else + sename = pwname; +- lvl = NULL; ++ lvl = ""; + #endif + ++ if (r == 0) { + #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL +- r = get_default_context_with_level(sename, lvl, NULL, &sc); ++ r = get_default_context_with_level(sename, lvl, NULL, default_sc); + #else +- r = get_default_context(sename, NULL, &sc); ++ r = get_default_context(sename, NULL, default_sc); + #endif ++ } ++ ++ if (r == 0) { ++ /* If launched from xinetd, we must use current level */ ++ if (inetd_flag && !rexeced_flag) { ++ security_context_t sshdsc=NULL; ++ ++ if (getcon_raw(&sshdsc) < 0) ++ fatal("failed to allocate security context"); ++ ++ if ((con=context_new(sshdsc)) == NULL) ++ fatal("failed to allocate selinux context"); ++ reqlvl = context_range_get(con); ++ freecon(sshdsc); ++ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) ++ /* we actually don't change level */ ++ reqlvl = ""; ++ ++ debug("%s: current connection level '%s'", __func__, reqlvl); + +- if (r != 0) { +- switch (security_getenforce()) { +- case -1: +- fatal("%s: ssh_selinux_getctxbyname: " +- "security_getenforce() failed", __func__); +- case 0: +- error("%s: Failed to get default SELinux security " +- "context for %s", __func__, pwname); +- sc = NULL; +- break; +- default: +- fatal("%s: Failed to get default SELinux security " +- "context for %s (in enforcing mode)", +- __func__, pwname); + } ++ ++ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { ++ r = get_user_context(sename, role, reqlvl, user_sc); ++ ++ if (r == 0 && reqlvl != NULL && reqlvl[0]) { ++ security_context_t default_level_sc = *default_sc; ++ if (role != NULL && role[0]) { ++ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) ++ default_level_sc = *default_sc; ++ } ++ /* verify that the requested range is contained in the user range */ ++ if (mls_range_allowed(default_level_sc, *user_sc)) { ++ logit("permit MLS level %s (user range %s)", reqlvl, lvl); ++ } else { ++ r = -1; ++ error("deny MLS level %s (user range %s)", reqlvl, lvl); ++ } ++ if (default_level_sc != *default_sc) ++ freecon(default_level_sc); ++ } ++ } else { ++ *user_sc = *default_sc; ++ } ++ } ++ if (r != 0) { ++ error("%s: Failed to get default SELinux security " ++ "context for %s", __func__, pwname); + } + + #ifdef HAVE_GETSEUSERBYNAME +@@ -100,7 +303,42 @@ ssh_selinux_getctxbyname(char *pwname) + free(lvl); + #endif + +- return sc; ++ if (role != NULL) ++ free(role); ++ if (con) ++ context_free(con); ++ ++ return (r); ++} ++ ++/* Setup environment variables for pam_selinux */ ++static int ++ssh_selinux_setup_pam_variables(void) ++{ ++ const char *reqlvl; ++ char *role; ++ char *use_current; ++ int rv; ++ ++ debug3("%s: setting execution context", __func__); ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); ++ ++ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ ++ if (inetd_flag && !rexeced_flag) { ++ use_current = "1"; ++ } else { ++ use_current = ""; ++ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ } ++ ++ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ ++ if (role != NULL) ++ free(role); ++ ++ return rv; + } + + /* Set the execution context to the default for the specified user */ +@@ -108,28 +346,71 @@ void + ssh_selinux_setup_exec_context(char *pwname) + { + security_context_t user_ctx = NULL; ++ int r = 0; ++ security_context_t default_ctx = NULL; + + if (!ssh_selinux_enabled()) + return; + ++ if (options.use_pam) { ++ /* do not compute context, just setup environment for pam_selinux */ ++ if (ssh_selinux_setup_pam_variables()) { ++ switch (security_getenforce()) { ++ case -1: ++ fatal("%s: security_getenforce() failed", __func__); ++ case 0: ++ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", ++ __func__); ++ break; ++ default: ++ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", ++ __func__); ++ } ++ } ++ return; ++ } ++ + debug3("%s: setting execution context", __func__); + +- user_ctx = ssh_selinux_getctxbyname(pwname); +- if (setexeccon(user_ctx) != 0) { ++ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); ++ if (r >= 0) { ++ r = setexeccon(user_ctx); ++ if (r < 0) { ++ error("%s: Failed to set SELinux execution context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++#ifdef HAVE_SETKEYCREATECON ++ else if (setkeycreatecon(user_ctx) < 0) { ++ error("%s: Failed to set SELinux keyring creation context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++#endif ++ } ++ if (user_ctx == NULL) { ++ user_ctx = default_ctx; ++ } ++ if (r < 0 || user_ctx != default_ctx) { ++ /* audit just the case when user changed a role or there was ++ a failure */ ++ send_audit_message(r >= 0, default_ctx, user_ctx); ++ } ++ if (r < 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: security_getenforce() failed", __func__); + case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); ++ error("%s: SELinux failure. Continuing in permissive mode.", ++ __func__); + break; + default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); ++ fatal("%s: SELinux failure. Aborting connection.", ++ __func__); + } + } +- if (user_ctx != NULL) ++ if (user_ctx != NULL && user_ctx != default_ctx) + freecon(user_ctx); ++ if (default_ctx != NULL) ++ freecon(default_ctx); + + debug3("%s: done", __func__); + } +@@ -147,7 +428,10 @@ ssh_selinux_setup_pty(char *pwname, cons + + debug3("%s: setting TTY context on %s", __func__, tty); + +- user_ctx = ssh_selinux_getctxbyname(pwname); ++ if (getexeccon(&user_ctx) < 0) { ++ error("%s: getexeccon: %s", __func__, strerror(errno)); ++ goto out; ++ } + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + +@@ -219,21 +503,6 @@ ssh_selinux_change_context(const char *n + free(newctx); + } + +-void +-ssh_selinux_setfscreatecon(const char *path) +-{ +- security_context_t context; +- +- if (!ssh_selinux_enabled()) +- return; +- if (path == NULL) { +- setfscreatecon(NULL); +- return; +- } +- if (matchpathcon(path, 0700, &context) == 0) +- setfscreatecon(context); +-} +- + #endif /* WITH_SELINUX */ + + #ifdef LINUX_OOM_ADJUST +diff -up openssh-6.3p1/openbsd-compat/port-linux_part_2.c.role-mls openssh-6.3p1/openbsd-compat/port-linux_part_2.c +--- openssh-6.3p1/openbsd-compat/port-linux_part_2.c.role-mls 2013-10-10 14:34:43.839494355 +0200 ++++ openssh-6.3p1/openbsd-compat/port-linux_part_2.c 2013-10-10 14:34:43.839494355 +0200 +@@ -0,0 +1,75 @@ ++/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */ ++ ++/* ++ * Copyright (c) 2005 Daniel Walsh ++ * Copyright (c) 2006 Damien Miller ++ * ++ * 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. ++ */ ++ ++/* ++ * Linux-specific portability code - just SELinux support at present ++ */ ++ ++#include "includes.h" ++ ++#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) ++#include ++#include ++#include ++#include ++ ++#include "log.h" ++#include "xmalloc.h" ++#include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" ++ ++#ifdef WITH_SELINUX ++#include ++#include ++#include ++ ++/* Wrapper around is_selinux_enabled() to log its return value once only */ ++int ++ssh_selinux_enabled(void) ++{ ++ static int enabled = -1; ++ ++ if (enabled == -1) { ++ enabled = (is_selinux_enabled() == 1); ++ debug("SELinux support %s", enabled ? "enabled" : "disabled"); ++ } ++ ++ return (enabled); ++} ++ ++void ++ssh_selinux_setfscreatecon(const char *path) ++{ ++ security_context_t context; ++ ++ if (!ssh_selinux_enabled()) ++ return; ++ if (path == NULL) { ++ setfscreatecon(NULL); ++ return; ++ } ++ if (matchpathcon(path, 0700, &context) == 0) ++ setfscreatecon(context); ++} ++ ++#endif /* WITH_SELINUX */ ++ ++#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ +diff -up openssh-6.3p1/sshd.c.role-mls openssh-6.3p1/sshd.c +--- openssh-6.3p1/sshd.c.role-mls 2013-10-10 14:34:43.824494427 +0200 ++++ openssh-6.3p1/sshd.c 2013-10-10 14:34:43.839494355 +0200 +@@ -2179,6 +2179,9 @@ main(int ac, char **av) + restore_uid(); + } + #endif ++#ifdef WITH_SELINUX ++ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); ++#endif + #ifdef USE_PAM + if (options.use_pam) { + do_pam_setcred(1); diff --git a/openssh.spec b/openssh.spec index 4e4558d..d752ee7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -92,9 +92,9 @@ Source13: sshd-keygen Patch0: openssh-5.9p1-wIm.patch #? -Patch100: openssh-6.2p1-coverity.patch +Patch100: openssh-6.3p1-coverity.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1872 -Patch101: openssh-6.2p1-fingerprint.patch +Patch101: openssh-6.3p1-fingerprint.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1894 #https://bugzilla.redhat.com/show_bug.cgi?id=735889 Patch102: openssh-5.8p1-getaddrinfo.patch @@ -102,7 +102,7 @@ Patch102: openssh-5.8p1-getaddrinfo.patch Patch103: openssh-5.8p1-packet.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1402 -Patch200: openssh-6.2p1-audit.patch +Patch200: openssh-6.3p1-audit.patch # --- pam_ssh-agent --- # make it build reusing the openssh sources @@ -112,14 +112,14 @@ Patch301: pam_ssh_agent_auth-0.9.2-seteuid.patch # explicitly make pam callbacks visible Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) -Patch400: openssh-6.2p1-role-mls.patch +Patch400: openssh-6.3p1-role-mls.patch #https://bugzilla.redhat.com/show_bug.cgi?id=781634 -Patch404: openssh-6.1p1-privsep-selinux.patch +Patch404: openssh-6.3p1-privsep-selinux.patch #?-- unwanted child :( -Patch501: openssh-6.2p1-ldap.patch +Patch501: openssh-6.3p1-ldap.patch #? -Patch502: openssh-6.2p1-keycat.patch +Patch502: openssh-6.3p1-keycat.patch #http6://bugzilla.mindrot.org/show_bug.cgi?id=1644 Patch601: openssh-5.2p1-allow-ip-opts.patch @@ -141,7 +141,7 @@ Patch608: openssh-6.1p1-askpass-ld.patch Patch609: openssh-5.5p1-x11.patch #? -Patch700: openssh-6.2p1-fips.patch +Patch700: openssh-6.3p1-fips.patch #? Patch701: openssh-5.6p1-exit-deadlock.patch #? @@ -155,7 +155,7 @@ Patch705: openssh-5.1p1-scp-manpage.patch #? Patch706: openssh-5.8p1-localdomain.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX) -Patch707: openssh-6.1p1-redhat.patch +Patch707: openssh-6.3p1-redhat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1890 (WONTFIX) need integration to prng helper which is discontinued :) Patch708: openssh-6.2p1-entropy.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX) @@ -163,29 +163,19 @@ Patch709: openssh-6.2p1-vendor.patch # warn users for unsupported UsePAM=no (#757545) Patch711: openssh-6.1p1-log-usepam-no.patch # make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL -Patch712: openssh-5.9p1-ctr-evp-fast.patch +Patch712: openssh-6.3p1-ctr-evp-fast.patch # add cavs test binary for the aes-ctr -Patch713: openssh-6.2p1-ctr-cavstest.patch +Patch713: openssh-6.3p1-ctr-cavstest.patch #http://www.sxw.org.uk/computing/patches/openssh.html #changed cache storage type - #848228 -Patch800: openssh-6.2p1-gsskex.patch +Patch800: openssh-6.3p1-gsskex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html -Patch801: openssh-6.2p1-force_krb.patch +Patch801: openssh-6.3p1-force_krb.patch Patch900: openssh-6.1p1-gssapi-canohost.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 -Patch901: openssh-6.2p1-kuserok.patch - -# build regress/modpipe tests with $(CFLAGS), based on -# http://lists.mindrot.org/pipermail/openssh-unix-dev/2013-March/031167.html -Patch905: openssh-6.2p1-modpipe-cflags.patch -# add latest config.{sub,guess} to support aarch64 (#926284) -Patch907: openssh-6.2p1-aarch64.patch -# make sftp's libedit interface marginally multibyte aware (#841771) -Patch908: openssh-6.2p2-sftp-multibyte.patch -# don't show Success for EAI_SYSTEM (#985964) -Patch909: openssh-6.2p2-ssh_gai_strerror.patch +Patch901: openssh-6.3p1-kuserok.patch License: BSD @@ -404,10 +394,6 @@ popd %patch900 -p1 -b .canohost %patch901 -p1 -b .kuserok -%patch905 -p1 -b .modpipe-cflags -%patch907 -p1 -b .aarch64 -%patch908 -p1 -b .sftp-multibyte -%patch909 -p1 -b .ssh_gai_strerror %if 0 # Nothing here yet