summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net-misc/openssh/files/openssh_4.7p1-blacklist.patch969
-rw-r--r--net-misc/openssh/openssh-4.7_p1-r6.ebuild173
2 files changed, 1142 insertions, 0 deletions
diff --git a/net-misc/openssh/files/openssh_4.7p1-blacklist.patch b/net-misc/openssh/files/openssh_4.7p1-blacklist.patch
new file mode 100644
index 00000000..d4df4b1a
--- /dev/null
+++ b/net-misc/openssh/files/openssh_4.7p1-blacklist.patch
@@ -0,0 +1,969 @@
+openssh (1:4.7p1-9) unstable; urgency=critical
+
+ * Mitigate OpenSSL security vulnerability (CVE-2008-0166):
+ - Add key blacklisting support. Keys listed in
+ /etc/ssh/blacklist.TYPE-LENGTH will be rejected for authentication by
+ sshd, unless "PermitBlacklistedKeys yes" is set in
+ /etc/ssh/sshd_config.
+ - Add a new program, ssh-vulnkey, which can be used to check keys
+ against these blacklists.
+
+ -- Colin Watson <cjwatson@debian.org> Tue, 13 May 2008 12:33:38 +0100
+
+Index: openssh-4.7p1/sshd_config.5
+===================================================================
+--- openssh-4.7p1.orig/sshd_config.5
++++ openssh-4.7p1/sshd_config.5
+@@ -677,6 +677,20 @@ are refused if the number of unauthentic
+ Specifies whether password authentication is allowed.
+ The default is
+ .Dq yes .
++.It Cm PermitBlacklistedKeys
++Specifies whether
++.Xr sshd 8
++should allow keys recorded in its blacklist of known-compromised keys (see
++.Xr ssh-vulnkey 1 ) .
++If
++.Dq yes ,
++then attempts to authenticate with compromised keys will be logged but
++accepted.
++If
++.Dq no ,
++then attempts to authenticate with compromised keys will be rejected.
++The default is
++.Dq no .
+ .It Cm PermitEmptyPasswords
+ When password authentication is allowed, it specifies whether the
+ server allows login to accounts with empty password strings.
+Index: openssh-4.7p1/sshd.c
+===================================================================
+--- openssh-4.7p1.orig/sshd.c
++++ openssh-4.7p1/sshd.c
+@@ -1469,6 +1469,21 @@ main(int ac, char **av)
+
+ for (i = 0; i < options.num_host_key_files; i++) {
+ key = key_load_private(options.host_key_files[i], "", NULL);
++ if (key && blacklisted_key(key)) {
++ char *fp;
++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ if (options.permit_blacklisted_keys)
++ error("Host key %s blacklisted (see "
++ "ssh-vulnkey(1)); continuing anyway", fp);
++ else
++ error("Host key %s blacklisted (see "
++ "ssh-vulnkey(1))", fp);
++ xfree(fp);
++ if (!options.permit_blacklisted_keys) {
++ sensitive_data.host_keys[i] = NULL;
++ continue;
++ }
++ }
+ sensitive_data.host_keys[i] = key;
+ if (key == NULL) {
+ error("Could not load host key: %s",
+Index: openssh-4.7p1/servconf.c
+===================================================================
+--- openssh-4.7p1.orig/servconf.c
++++ openssh-4.7p1/servconf.c
+@@ -130,6 +130,7 @@ initialize_server_options(ServerOptions
+ options->password_authentication = -1;
+ options->kbd_interactive_authentication = -1;
+ options->challenge_response_authentication = -1;
++ options->permit_blacklisted_keys = -1;
+ options->permit_empty_passwd = -1;
+ options->permit_user_env = -1;
+ options->use_login = -1;
+@@ -248,6 +249,8 @@ fill_default_server_options(ServerOption
+ options->kbd_interactive_authentication = 0;
+ if (options->challenge_response_authentication == -1)
+ options->challenge_response_authentication = 1;
++ if (options->permit_blacklisted_keys == -1)
++ options->permit_blacklisted_keys = 0;
+ if (options->permit_empty_passwd == -1)
+ options->permit_empty_passwd = 0;
+ if (options->permit_user_env == -1)
+@@ -349,7 +352,7 @@ typedef enum {
+ sListenAddress, sAddressFamily,
+ sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+ sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+- sStrictModes, sEmptyPasswd, sTCPKeepAlive,
++ sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
+ sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+ sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+ sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+@@ -439,6 +442,7 @@ static struct {
+ { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+ { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+ { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
++ { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
+ { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
+ { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+ { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+@@ -1003,6 +1007,10 @@ parse_flag:
+ intptr = &options->tcp_keep_alive;
+ goto parse_flag;
+
++ case sPermitBlacklistedKeys:
++ intptr = &options->permit_blacklisted_keys;
++ goto parse_flag;
++
+ case sEmptyPasswd:
+ intptr = &options->permit_empty_passwd;
+ goto parse_flag;
+Index: openssh-4.7p1/servconf.h
+===================================================================
+--- openssh-4.7p1.orig/servconf.h
++++ openssh-4.7p1/servconf.h
+@@ -117,6 +117,7 @@ typedef struct {
+ * authentication. */
+ int kbd_interactive_authentication; /* If true, permit */
+ int challenge_response_authentication;
++ int permit_blacklisted_keys; /* If true, permit */
+ int permit_empty_passwd; /* If false, do not permit empty
+ * passwords. */
+ int permit_user_env; /* If true, read ~/.ssh/environment */
+Index: openssh-4.7p1/Makefile.in
+===================================================================
+--- openssh-4.7p1.orig/Makefile.in
++++ openssh-4.7p1/Makefile.in
+@@ -73,7 +73,7 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAN
+ SSHX509_OBJS=ssh-x509.o ssh-xkalg.o x509_nm_cmp.o
+ X509STORE_OBJS=x509store.o $(LDAP_OBJS) $(OCSP_OBJS)
+
+-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT)
+
+ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+ canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+@@ -101,8 +101,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
+ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+ audit.o audit-bsm.o platform.o $(X509STORE_OBJS)
+
+-MANPAGES = 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-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
+-MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
++MANPAGES = 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-rand-helper.8.out ssh-keysign.8.out ssh-vulnkey.1.out sshd_config.5.out ssh_config.5.out
++MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-vulnkey.1 sshd_config.5 ssh_config.5
+ MANTYPE = @MANTYPE@
+
+ CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+@@ -182,6 +182,9 @@ sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sft
+ ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
+ $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
++ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
++ $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
++
+ # test driver for the loginrec code - not built by default
+ logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+ $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+@@ -284,6 +287,7 @@ install-files: scard-install
+ $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign $(DESTDIR)$(SSH_KEYSIGN)
+ $(INSTALL) -m 0755 $(STRIP_OPT) sftp $(DESTDIR)$(bindir)/sftp
+ $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server $(DESTDIR)$(SFTP_SERVER)
++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey $(DESTDIR)$(bindir)/ssh-vulnkey
+ $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+ $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+ $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+@@ -299,6 +303,7 @@ install-files: scard-install
+ $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+ $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+ $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
++ $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+ -rm -f $(DESTDIR)$(bindir)/slogin
+ ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+@@ -380,6 +385,7 @@ uninstall:
+ -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+ -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+ -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
++ -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+ -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+ -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+ -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+@@ -392,6 +398,7 @@ uninstall:
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
++ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+Index: openssh-4.7p1/auth-rh-rsa.c
+===================================================================
+--- openssh-4.7p1.orig/auth-rh-rsa.c
++++ openssh-4.7p1/auth-rh-rsa.c
+@@ -20,6 +20,7 @@
+ #include <pwd.h>
+ #include <stdarg.h>
+
++#include "xmalloc.h"
+ #include "packet.h"
+ #include "uidswap.h"
+ #include "log.h"
+@@ -27,6 +28,7 @@
+ #include "servconf.h"
+ #include "key.h"
+ #include "hostfile.h"
++#include "authfile.h"
+ #include "pathnames.h"
+ #include "auth.h"
+ #include "canohost.h"
+@@ -42,8 +44,22 @@ int
+ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
+ Key *client_host_key)
+ {
++ char *fp;
+ HostStatus host_status;
+
++ if (blacklisted_key(client_host_key)) {
++ fp = key_fingerprint(client_host_key, SSH_FP_MD5, SSH_FP_HEX);
++ if (options.permit_blacklisted_keys)
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1)); continuing anyway", fp);
++ else
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1))", fp);
++ xfree(fp);
++ if (!options.permit_blacklisted_keys)
++ return 0;
++ }
++
+ /* Check if we would accept it using rhosts authentication. */
+ if (!auth_rhosts(pw, cuser))
+ return 0;
+Index: openssh-4.7p1/authfile.h
+===================================================================
+--- openssh-4.7p1.orig/authfile.h
++++ openssh-4.7p1/authfile.h
+@@ -23,4 +23,7 @@ Key *key_load_private_type(int, const ch
+ Key *key_load_private_pem(int, int, const char *, char **);
+ int key_perm_ok(int, const char *);
+
++char *blacklist_filename(const Key *key);
++int blacklisted_key(const Key *key);
++
+ #endif
+Index: openssh-4.7p1/ssh-vulnkey.1
+===================================================================
+--- /dev/null
++++ openssh-4.7p1/ssh-vulnkey.1
+@@ -0,0 +1,151 @@
++.\" Copyright (c) 2008 Canonical Ltd. All rights reserved.
++.\"
++.\" Redistribution and use in source and binary forms, with or without
++.\" modification, are permitted provided that the following conditions
++.\" are met:
++.\" 1. Redistributions of source code must retain the above copyright
++.\" notice, this list of conditions and the following disclaimer.
++.\" 2. Redistributions in binary form must reproduce the above copyright
++.\" notice, this list of conditions and the following disclaimer in the
++.\" documentation and/or other materials provided with the distribution.
++.\"
++.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++.\"
++.Dd $Mdocdate: May 12 2008 $
++.Dt SSH-VULNKEY 1
++.Os
++.Sh NAME
++.Nm ssh-vulnkey
++.Nd check blacklist of compromised keys
++.Sh SYNOPSIS
++.Nm
++.Op Fl q
++.Ar file ...
++.Nm
++.Fl a
++.Sh DESCRIPTION
++.Nm
++checks a key against a blacklist of compromised keys.
++.Pp
++A substantial number of keys are known to have been generated using a broken
++version of OpenSSL distributed by Debian which failed to seed its random
++number generator correctly.
++Keys generated using these OpenSSL versions should be assumed to be
++compromised.
++This tool may be useful in checking for such keys.
++.Pp
++Keys that are compromised cannot be repaired; replacements must be generated
++using
++.Xr ssh-keygen 1 .
++Make sure to update
++.Pa authorized_keys
++files on all systems where compromised keys were permitted to authenticate.
++.Pp
++The argument list will be interpreted as a list of paths to public key files
++or
++.Pa authorized_keys
++files.
++If no suitable file is found at a given path,
++.Nm
++will append
++.Pa .pub
++and retry, in case it was given a private key file.
++If no files are given as arguments,
++.Nm
++will check
++.Pa ~/.ssh/id_rsa ,
++.Pa ~/.ssh/id_dsa ,
++.Pa ~/.ssh/identity ,
++.Pa ~/.ssh/authorized_keys
++and
++.Pa ~/.ssh/authorized_keys2 ,
++as well as the system's host keys if readable.
++.Pp
++If
++.Dq -
++is given as an argument,
++.Nm
++will read from standard input.
++This can be used to process output from
++.Xr ssh-keyscan 1 ,
++for example:
++.Pp
++.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey -
++.Pp
++.Nm
++will exit zero if any of the given keys were in the compromised list,
++otherwise non-zero.
++.Pp
++Unless the
++.Cm PermitBlacklistedKeys
++option is used,
++.Xr sshd 8
++will reject attempts to authenticate with keys in the compromised list.
++.Pp
++The options are as follows:
++.Bl -tag -width Ds
++.It Fl a
++Check keys of all users on the system.
++You will typically need to run
++.Nm
++as root to use this option.
++For each user,
++.Nm
++will check
++.Pa ~/.ssh/id_rsa ,
++.Pa ~/.ssh/id_dsa ,
++.Pa ~/.ssh/identity ,
++.Pa ~/.ssh/authorized_keys
++and
++.Pa ~/.ssh/authorized_keys2 .
++It will also check the system's host keys.
++.It Fl q
++Quiet mode.
++Normally,
++.Nm
++outputs the fingerprint of each key scanned, with a description of its
++status.
++This option suppresses that output.
++.El
++.Sh BLACKLIST FILE FORMAT
++The blacklist file may start with comments, on lines starting with
++.Dq # .
++After these initial comments, it must follow a strict format:
++.Pp
++.Bl -bullet -offset indent -compact
++.It
++All the lines must be exactly the same length (20 characters followed by a
++newline) and must be in sorted order.
++.It
++Each line must consist of the lower-case hexadecimal MD5 key fingerprint,
++without colons, and with the first 12 characters removed (that is, the least
++significant 80 bits of the fingerprint).
++.El
++.Pp
++The key fingerprint may be generated using
++.Xr ssh-keygen 1 :
++.Pp
++.Dl $ ssh-keygen -l -f /path/to/key
++.Pp
++This strict format is necessary to allow the blacklist file to be checked
++quickly, using a binary-search algorithm.
++.Sh SEE ALSO
++.Xr ssh-keygen 1 ,
++.Xr sshd 8
++.Sh AUTHORS
++.An -nosplit
++.An Colin Watson Aq cjwatson@ubuntu.com
++.Pp
++Florian Weimer suggested the option to check keys of all users, and the idea
++of processing
++.Xr ssh-keyscan 1
++output.
+Index: openssh-4.7p1/auth2-hostbased.c
+===================================================================
+--- openssh-4.7p1.orig/auth2-hostbased.c
++++ openssh-4.7p1/auth2-hostbased.c
+@@ -40,6 +40,7 @@
+ #include "compat.h"
+ #include "key.h"
+ #include "hostfile.h"
++#include "authfile.h"
+ #include "auth.h"
+ #include "canohost.h"
+ #ifdef GSSAPI
+@@ -170,10 +171,24 @@ int
+ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
+ Key *key)
+ {
++ char *fp;
+ const char *resolvedname, *ipaddr, *lookup;
+ HostStatus host_status;
+ int len;
+
++ if (blacklisted_key(key)) {
++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ if (options.permit_blacklisted_keys)
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1)); continuing anyway", fp);
++ else
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1))", fp);
++ xfree(fp);
++ if (!options.permit_blacklisted_keys)
++ return 0;
++ }
++
+ resolvedname = get_canonical_hostname(options.use_dns);
+ ipaddr = get_remote_ipaddr();
+
+Index: openssh-4.7p1/authfile.c
+===================================================================
+--- openssh-4.7p1.orig/authfile.c
++++ openssh-4.7p1/authfile.c
+@@ -68,6 +68,7 @@
+ #include "ssh-x509.h"
+ #include "misc.h"
+ #include "atomicio.h"
++#include "pathnames.h"
+
+ /* Version identification string for SSH v1 identity files. */
+ static const char authfile_id_string[] =
+@@ -696,3 +697,113 @@ key_load_public(const char *filename, ch
+ key_free(pub);
+ return NULL;
+ }
++
++char *
++blacklist_filename(const Key *key)
++{
++ char *name;
++
++ xasprintf(&name, "%s.%s-%u",
++ _PATH_BLACKLIST, key_type(key), key_size(key));
++ return name;
++}
++
++/* Scan a blacklist of known-vulnerable keys. */
++int
++blacklisted_key(const Key *key)
++{
++ char *blacklist_file;
++ int fd = -1;
++ char *dgst_hex = NULL;
++ char *dgst_packed = NULL, *p;
++ int i;
++ size_t line_len;
++ struct stat st;
++ char buf[256];
++ off_t start, lower, upper;
++ int ret = 0;
++
++ blacklist_file = blacklist_filename(key);
++ debug("Checking blacklist file %s", blacklist_file);
++ fd = open(blacklist_file, O_RDONLY);
++ if (fd < 0)
++ goto out;
++
++ dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ /* Remove all colons */
++ dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
++ for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
++ if (dgst_hex[i] != ':')
++ *p++ = dgst_hex[i];
++ /* Only compare least-significant 80 bits (to keep the blacklist
++ * size down)
++ */
++ line_len = strlen(dgst_packed + 12);
++ if (line_len > 32)
++ goto out;
++
++ /* Skip leading comments */
++ start = 0;
++ for (;;) {
++ ssize_t r;
++ char *newline;
++
++ r = atomicio(read, fd, buf, 256);
++ if (r <= 0)
++ goto out;
++ if (buf[0] != '#')
++ break;
++
++ newline = memchr(buf, '\n', 256);
++ if (!newline)
++ goto out;
++ start += newline + 1 - buf;
++ if (lseek(fd, start, SEEK_SET) < 0)
++ goto out;
++ }
++
++ /* Initialise binary search record numbers */
++ if (fstat(fd, &st) < 0)
++ goto out;
++ lower = 0;
++ upper = (st.st_size - start) / (line_len + 1);
++
++ while (lower != upper) {
++ off_t cur;
++ char buf[32];
++ int cmp;
++
++ cur = lower + (upper - lower) / 2;
++
++ /* Read this line and compare to digest; this is
++ * overflow-safe since cur < max(off_t) / (line_len + 1) */
++ if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
++ break;
++ if (atomicio(read, fd, buf, line_len) != line_len)
++ break;
++ cmp = memcmp(buf, dgst_packed + 12, line_len);
++ if (cmp < 0) {
++ if (cur == lower)
++ break;
++ lower = cur;
++ } else if (cmp > 0) {
++ if (cur == upper)
++ break;
++ upper = cur;
++ } else {
++ debug("Found %s in blacklist", dgst_hex);
++ ret = 1;
++ break;
++ }
++ }
++
++out:
++ if (dgst_packed)
++ xfree(dgst_packed);
++ if (dgst_hex)
++ xfree(dgst_hex);
++ if (fd >= 0)
++ close(fd);
++ xfree(blacklist_file);
++ return ret;
++}
+Index: openssh-4.7p1/ssh-vulnkey.c
+===================================================================
+--- /dev/null
++++ openssh-4.7p1/ssh-vulnkey.c
+@@ -0,0 +1,311 @@
++/*
++ * Copyright (c) 2008 Canonical Ltd. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "includes.h"
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <string.h>
++#include <stdio.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#include <openssl/evp.h>
++
++#include "xmalloc.h"
++#include "ssh.h"
++#include "log.h"
++#include "key.h"
++#include "authfile.h"
++#include "pathnames.h"
++#include "misc.h"
++
++extern char *__progname;
++
++/* Default files to check */
++static char *default_host_files[] = {
++ _PATH_HOST_RSA_KEY_FILE,
++ _PATH_HOST_DSA_KEY_FILE,
++ _PATH_HOST_KEY_FILE,
++ NULL
++};
++static char *default_files[] = {
++ _PATH_SSH_CLIENT_ID_RSA,
++ _PATH_SSH_CLIENT_ID_DSA,
++ _PATH_SSH_CLIENT_IDENTITY,
++ _PATH_SSH_USER_PERMITTED_KEYS,
++ _PATH_SSH_USER_PERMITTED_KEYS2,
++ NULL
++};
++
++static int quiet = 0;
++
++static void
++usage(void)
++{
++ fprintf(stderr, "usage: %s [-aq] [file ...]\n", __progname);
++ fprintf(stderr, "Options:\n");
++ fprintf(stderr, " -a Check keys of all users.\n");
++ fprintf(stderr, " -q Quiet mode.\n");
++ exit(1);
++}
++
++void
++describe_key(const char *msg, const Key *key, const char *comment)
++{
++ char *fp;
++
++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ if (!quiet)
++ printf("%s: %u %s %s\n", msg, key_size(key), fp, comment);
++ xfree(fp);
++}
++
++int
++do_key(const Key *key, const char *comment)
++{
++ char *blacklist_file;
++ struct stat st;
++ int ret = 1;
++
++ blacklist_file = blacklist_filename(key);
++ if (stat(blacklist_file, &st) < 0)
++ describe_key("Unknown (no blacklist information)",
++ key, comment);
++ else if (blacklisted_key(key)) {
++ describe_key("COMPROMISED", key, comment);
++ ret = 0;
++ } else
++ describe_key("Not blacklisted", key, comment);
++ xfree(blacklist_file);
++
++ return ret;
++}
++
++int
++do_filename(const char *filename, int quiet_open)
++{
++ FILE *f;
++ char line[SSH_MAX_PUBKEY_BYTES];
++ char *cp;
++ u_long linenum = 0;
++ Key *key;
++ char *comment = NULL;
++ int found = 0, ret = 1;
++
++ /* Copy much of key_load_public's logic here so that we can read
++ * several keys from a single file (e.g. authorized_keys).
++ */
++
++ if (strcmp(filename, "-") != 0) {
++ f = fopen(filename, "r");
++ if (!f) {
++ char pubfile[MAXPATHLEN];
++ if (strlcpy(pubfile, filename, sizeof pubfile) <
++ sizeof(pubfile) &&
++ strlcat(pubfile, ".pub", sizeof pubfile) <
++ sizeof(pubfile))
++ f = fopen(pubfile, "r");
++ }
++ if (!f) {
++ if (!quiet_open)
++ perror(filename);
++ return -1;
++ }
++ } else
++ f = stdin;
++ while (read_keyfile_line(f, filename, line, sizeof(line),
++ &linenum) != -1) {
++ cp = line;
++ switch (*cp) {
++ case '#':
++ case '\n':
++ case '\0':
++ continue;
++ }
++ /* Skip leading whitespace. */
++ for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
++ ;
++ /* Cope with ssh-keyscan output. */
++ comment = NULL;
++ if (*cp) {
++ char *space;
++ int type;
++
++ space = strchr(cp, ' ');
++ if (!space)
++ continue;
++ *space = '\0';
++ type = key_type_from_name(cp);
++ if (type == KEY_UNSPEC) {
++ comment = xstrdup(cp);
++ cp = space + 1;
++ }
++ *space = ' ';
++ }
++ if (!comment)
++ comment = xstrdup(filename);
++ if (*cp) {
++ key = key_new(KEY_RSA1);
++ if (key_read(key, &cp) == 1) {
++ if (!do_key(key, comment))
++ ret = 0;
++ key_free(key);
++ found = 1;
++ } else {
++ key_free(key);
++ key = key_new(KEY_UNSPEC);
++ if (key_read(key, &cp) == 1) {
++ if (!do_key(key, comment))
++ ret = 0;
++ key_free(key);
++ found = 1;
++ }
++ }
++ }
++ xfree(comment);
++ comment = NULL;
++ }
++ if (f != stdin)
++ fclose(f);
++
++ if (!found && filename) {
++ key = key_load_public(filename, &comment);
++ if (key) {
++ if (!do_key(key, comment))
++ ret = 0;
++ found = 1;
++ }
++ if (comment)
++ xfree(comment);
++ }
++
++ return ret;
++}
++
++int
++do_host(void)
++{
++ int i;
++ struct stat st;
++ int ret = 1;
++
++ for (i = 0; default_host_files[i]; i++) {
++ if (stat(default_host_files[i], &st) < 0)
++ continue;
++ if (!do_filename(default_host_files[i], 1))
++ ret = 0;
++ }
++
++ return ret;
++}
++
++int
++do_user(const char *dir)
++{
++ int i;
++ char buf[MAXPATHLEN];
++ struct stat st;
++ int ret = 1;
++
++ for (i = 0; default_files[i]; i++) {
++ snprintf(buf, sizeof(buf), "%s/%s", dir, default_files[i]);
++ if (stat(buf, &st) < 0)
++ continue;
++ if (!do_filename(buf, 0))
++ ret = 0;
++ }
++
++ return ret;
++}
++
++int
++main(int argc, char **argv)
++{
++ int opt, all_users = 0;
++ int ret = 1;
++ extern int optind;
++
++ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
++ sanitise_stdfd();
++
++ __progname = ssh_get_progname(argv[0]);
++
++ SSLeay_add_all_algorithms();
++ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
++
++ /* We don't need the RNG ourselves, but symbol references here allow
++ * ld to link us properly.
++ */
++ init_rng();
++ seed_rng();
++
++ while ((opt = getopt(argc, argv, "ahq")) != -1) {
++ switch (opt) {
++ case 'a':
++ all_users = 1;
++ break;
++ case 'q':
++ quiet = 1;
++ break;
++ case 'h':
++ default:
++ usage();
++ }
++ }
++
++ if (all_users) {
++ struct passwd *pw;
++
++ if (!do_host())
++ ret = 0;
++
++ while ((pw = getpwent()) != NULL) {
++ if (pw->pw_dir) {
++ if (!do_user(pw->pw_dir))
++ ret = 0;
++ }
++ }
++ } else if (optind == argc) {
++ struct passwd *pw;
++
++ if (!do_host())
++ ret = 0;
++
++ if ((pw = getpwuid(getuid())) == NULL)
++ fprintf(stderr, "No user found with uid %u\n",
++ (u_int)getuid());
++ else {
++ if (!do_user(pw->pw_dir))
++ ret = 0;
++ }
++ } else {
++ while (optind < argc)
++ if (!do_filename(argv[optind++], 0))
++ ret = 0;
++ }
++
++ return ret;
++}
+Index: openssh-4.7p1/auth-rsa.c
+===================================================================
+--- openssh-4.7p1.orig/auth-rsa.c
++++ openssh-4.7p1/auth-rsa.c
+@@ -40,6 +40,7 @@
+ #include "servconf.h"
+ #include "key.h"
+ #include "hostfile.h"
++#include "authfile.h"
+ #include "auth.h"
+ #ifdef GSSAPI
+ #include "ssh-gss.h"
+@@ -221,6 +222,7 @@ auth_rsa_key_allowed(struct passwd *pw,
+ char *cp;
+ char *key_options;
+ int keybits;
++ char *fp;
+
+ /* Skip leading whitespace, empty and comment lines. */
+ for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+@@ -265,6 +267,19 @@ auth_rsa_key_allowed(struct passwd *pw,
+ "actual %d vs. announced %d.",
+ file, linenum, BN_num_bits(key->rsa->n), bits);
+
++ if (blacklisted_key(key)) {
++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ if (options.permit_blacklisted_keys)
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1)); continuing anyway", fp);
++ else
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1))", fp);
++ xfree(fp);
++ if (!options.permit_blacklisted_keys)
++ continue;
++ }
++
+ /* We have found the desired key. */
+ /*
+ * If our options do not allow this key to be used,
+Index: openssh-4.7p1/pathnames.h
+===================================================================
+--- openssh-4.7p1.orig/pathnames.h
++++ openssh-4.7p1/pathnames.h
+@@ -66,6 +66,8 @@
+ /* Backwards compatibility */
+ #define _PATH_DH_PRIMES SSHDIR "/primes"
+
++#define _PATH_BLACKLIST SSHDIR "/blacklist"
++
+ #ifndef _PATH_SSH_PROGRAM
+ #define _PATH_SSH_PROGRAM "/usr/bin/ssh"
+ #endif
+Index: openssh-4.7p1/auth2-pubkey.c
+===================================================================
+--- openssh-4.7p1.orig/auth2-pubkey.c
++++ openssh-4.7p1/auth2-pubkey.c
+@@ -47,6 +47,7 @@
+ #include "compat.h"
+ #include "key.h"
+ #include "hostfile.h"
++#include "authfile.h"
+ #include "auth.h"
+ #include "pathnames.h"
+ #include "uidswap.h"
+@@ -411,9 +412,23 @@ user_key_allowed2(struct passwd *pw, Key
+ int
+ user_key_allowed(struct passwd *pw, Key *key)
+ {
++ char *fp;
+ int success;
+ char *file;
+
++ if (blacklisted_key(key)) {
++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++ if (options.permit_blacklisted_keys)
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1)); continuing anyway", fp);
++ else
++ logit("Public key %s blacklisted (see "
++ "ssh-vulnkey(1))", fp);
++ xfree(fp);
++ if (!options.permit_blacklisted_keys)
++ return 0;
++ }
++
+ file = authorized_keys_file(pw);
+ success = user_key_allowed2(pw, key, file);
+ xfree(file);
diff --git a/net-misc/openssh/openssh-4.7_p1-r6.ebuild b/net-misc/openssh/openssh-4.7_p1-r6.ebuild
new file mode 100644
index 00000000..16804092
--- /dev/null
+++ b/net-misc/openssh/openssh-4.7_p1-r6.ebuild
@@ -0,0 +1,173 @@
+# Copyright 1999-2008 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-misc/openssh/openssh-4.7_p1-r6.ebuild,v 1.9 2008/05/11 13:12:32 ulm Exp $
+
+inherit eutils flag-o-matic ccc multilib autotools pam
+
+# Make it more portable between straight releases
+# and _p? releases.
+PARCH=${P/_/}
+
+X509_PATCH="${PARCH}+x509-6.1.diff.gz"
+LDAP_PATCH="${PARCH/openssh-4.7/openssh-lpk-4.6}-0.3.9.patch"
+HPN_PATCH="${PARCH}-hpn13v1.diff.gz"
+
+DESCRIPTION="Port of OpenBSD's free SSH release"
+HOMEPAGE="http://www.openssh.org/"
+SRC_URI="mirror://openbsd/OpenSSH/portable/${PARCH}.tar.gz
+ http://www.sxw.org.uk/computing/patches/openssh-4.7p1-gsskex-20070927.patch
+ ldap? ( http://dev.inversepath.com/openssh-lpk/${LDAP_PATCH} )
+ X509? ( http://roumenpetrov.info/openssh/x509-6.1/${X509_PATCH} )
+ hpn? ( http://www.psc.edu/networking/projects/hpn-ssh/${HPN_PATCH} )"
+
+LICENSE="as-is"
+SLOT="0"
+KEYWORDS="alpha amd64 arm hppa ia64 m68k ~mips ppc ppc64 s390 sh sparc ~sparc-fbsd x86 ~x86-fbsd"
+IUSE="static pam tcpd kerberos skey selinux chroot X509 ldap smartcard hpn libedit X"
+
+RDEPEND="pam? ( virtual/pam )
+ kerberos? ( virtual/krb5 )
+ selinux? ( >=sys-libs/libselinux-1.28 )
+ skey? ( >=sys-auth/skey-1.1.5-r1 )
+ ldap? ( net-nds/openldap )
+ libedit? ( dev-libs/libedit )
+ >=dev-libs/openssl-0.9.6d
+ >=sys-libs/zlib-1.2.3
+ smartcard? ( dev-libs/opensc )
+ tcpd? ( >=sys-apps/tcp-wrappers-7.6 )
+ X? ( x11-apps/xauth )
+ userland_GNU? ( sys-apps/shadow )"
+DEPEND="${RDEPEND}
+ dev-util/pkgconfig
+ virtual/os-headers
+ sys-devel/autoconf"
+PROVIDE="virtual/ssh"
+
+S=${WORKDIR}/${PARCH}
+
+pkg_setup() {
+ # this sucks, but i'd rather have people unable to `emerge -u openssh`
+ # than not be able to log in to their server any more
+ maybe_fail() { [[ -z ${!2} ]] && use ${1} && echo ${1} ; }
+ local fail="
+ $(maybe_fail X509 X509_PATCH)
+ $(maybe_fail ldap LDAP_PATCH)
+ "
+ fail=$(echo ${fail})
+ if [[ -n ${fail} ]] ; then
+ eerror "Sorry, but this version does not yet support features"
+ eerror "that you requested: ${fail}"
+ eerror "Please mask ${PF} for now and check back later:"
+ eerror " # echo '=${CATEGORY}/${PF}' >> /etc/portage/package.mask"
+ die "booooo"
+ fi
+}
+
+src_unpack() {
+ unpack ${PARCH}.tar.gz
+ cd "${S}"
+
+ sed -i \
+ -e '/_PATH_XAUTH/s:/usr/X11R6/bin/xauth:/usr/bin/xauth:' \
+ pathnames.h || die
+
+ use X509 && epatch "${DISTDIR}"/${X509_PATCH} "${FILESDIR}"/${PN}-4.7_p1-x509-hpn-glue.patch
+ use chroot && epatch "${FILESDIR}"/openssh-4.3_p1-chroot.patch
+ use smartcard && epatch "${FILESDIR}"/openssh-3.9_p1-opensc.patch
+ if ! use X509 ; then
+ if [[ -n ${LDAP_PATCH} ]] && use ldap ; then
+ epatch "${DISTDIR}"/${LDAP_PATCH} "${FILESDIR}"/${PN}-4.4_p1-ldap-hpn-glue.patch
+ epatch "${FILESDIR}"/${P}-lpk-64bit.patch #210110
+ fi
+ epatch "${DISTDIR}"/openssh-4.7p1-gsskex-20070927.patch #115553
+ else
+ use ldap && ewarn "Sorry, X509 and ldap don't get along, disabling ldap"
+ epatch "${FILESDIR}"/${P}-GSSAPI-dns.patch #165444 integrated into gsskex
+ fi
+ [[ -n ${HPN_PATCH} ]] && use hpn && epatch "${DISTDIR}"/${HPN_PATCH}
+ epatch "${FILESDIR}"/${P}-CVE-2008-1483.patch #214985
+ epatch "${FILESDIR}"/${P}-packet-size.patch #212433
+ epatch "${FILESDIR}"/${P}-ForceCommand.patch #215702
+
+ sed -i "s:-lcrypto:$(pkg-config --libs openssl):" configure{,.ac} || die
+
+ # fix #191665
+ epatch "${FILESDIR}"/openssh-4.7p1-selinux.diff
+
+ epatch "${FILESDIR}"/openssh-4.7p1-blacklist.patch
+
+ eautoreconf
+}
+
+src_compile() {
+ addwrite /dev/ptmx
+ addpredict /etc/skey/skeykeys #skey configure code triggers this
+
+ local myconf=""
+ if use static ; then
+ append-ldflags -static
+ use pam && ewarn "Disabling pam support becuse of static flag"
+ myconf="${myconf} --without-pam"
+ else
+ myconf="${myconf} $(use_with pam)"
+ fi
+
+ econf \
+ --with-ldflags="${LDFLAGS}" \
+ --disable-strip \
+ --sysconfdir=/etc/ssh \
+ --libexecdir=/usr/$(get_libdir)/misc \
+ --datadir=/usr/share/openssh \
+ --disable-suid-ssh \
+ --with-privsep-path=/var/empty \
+ --with-privsep-user=sshd \
+ --with-md5-passwords \
+ --with-ssl-engine \
+ $(use_with ldap) \
+ $(use_with libedit) \
+ $(use_with kerberos kerberos5 /usr) \
+ $(use_with tcpd tcp-wrappers) \
+ $(use_with selinux) \
+ $(use_with skey) \
+ $(use_with smartcard opensc) \
+ ${myconf} \
+ || die "bad configure"
+ emake || die "compile problem"
+}
+
+src_install() {
+ emake install-nokeys DESTDIR="${D}" || die
+ fperms 600 /etc/ssh/sshd_config
+ dobin contrib/ssh-copy-id
+ newinitd "${FILESDIR}"/sshd.rc6 sshd
+ newconfd "${FILESDIR}"/sshd.confd sshd
+ keepdir /var/empty
+
+ newpamd "${FILESDIR}"/sshd.pam_include.1 sshd
+ use pam \
+ && dosed "/^#UsePAM /s:.*:UsePAM yes:" /etc/ssh/sshd_config \
+ && dosed "/^#PasswordAuthentication /s:.*:PasswordAuthentication no:" /etc/ssh/sshd_config
+
+ doman contrib/ssh-copy-id.1
+ dodoc ChangeLog CREDITS OVERVIEW README* TODO sshd_config
+
+ diropts -m 0700
+ dodir /etc/skel/.ssh
+}
+
+pkg_postinst() {
+ enewgroup sshd 22
+ enewuser sshd 22 -1 /var/empty sshd
+
+ # help fix broken perms caused by older ebuilds.
+ # can probably cut this after the next stage release.
+ chmod u+x "${ROOT}"/etc/skel/.ssh >& /dev/null
+
+ ewarn "Remember to merge your config files in /etc/ssh/ and then"
+ ewarn "restart sshd: '/etc/init.d/sshd restart'."
+ if use pam ; then
+ echo
+ ewarn "Please be aware users need a valid shell in /etc/passwd"
+ ewarn "in order to be allowed to login."
+ fi
+}