diff options
-rw-r--r-- | net-misc/openssh/files/openssh_4.7p1-blacklist.patch | 969 | ||||
-rw-r--r-- | net-misc/openssh/openssh-4.7_p1-r6.ebuild | 173 |
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 +} |