Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 154917 Details for
Bug 221759
net-misc/openssh blacklist feature for known weak keys (CVE-2008-0166)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
openssh-5.0p1-blacklist.patch
openssh-5.0p1-blacklist.patch (text/plain), 16.72 KB, created by
SpanKY
on 2008-05-31 09:50:44 UTC
(
hide
)
Description:
openssh-5.0p1-blacklist.patch
Filename:
MIME Type:
Creator:
SpanKY
Created:
2008-05-31 09:50:44 UTC
Size:
16.72 KB
patch
obsolete
>--- openssh-5.0p1/Makefile.in >+++ openssh-5.0p1/Makefile.in >@@ -62,7 +62,7 @@ > > 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) > >-LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ >+LIBSSH_OBJS=acss.o authfd.o authfile.o blacklist.o bufaux.o bufbn.o buffer.o \ > canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ > cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ > compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ >--- openssh-5.0p1/auth-rh-rsa.c >+++ openssh-5.0p1/auth-rh-rsa.c >@@ -34,6 +34,7 @@ > #include "ssh-gss.h" > #endif > #include "monitor_wrap.h" >+#include "blacklist.h" > > /* import */ > extern ServerOptions options; >@@ -48,6 +49,9 @@ > if (!auth_rhosts(pw, cuser)) > return 0; > >+ if (blacklisted_key(client_host_key, 0)) >+ return 0; >+ > host_status = check_key_in_hostfiles(pw, client_host_key, > chost, _PATH_SSH_SYSTEM_HOSTFILE, > options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); >--- openssh-5.0p1/auth-rsa.c >+++ openssh-5.0p1/auth-rsa.c >@@ -47,6 +47,7 @@ > #include "monitor_wrap.h" > #include "ssh.h" > #include "misc.h" >+#include "blacklist.h" > > /* import */ > extern ServerOptions options; >@@ -265,6 +272,9 @@ > "actual %d vs. announced %d.", > file, linenum, BN_num_bits(key->rsa->n), bits); > >+ if (blacklisted_key(key, 0)) >+ continue; >+ > /* We have found the desired key. */ > /* > * If our options do not allow this key to be used, >--- openssh-5.0p1/auth2-hostbased.c >+++ openssh-5.0p1/auth2-hostbased.c >@@ -47,6 +47,7 @@ > #endif > #include "monitor_wrap.h" > #include "pathnames.h" >+#include "blacklist.h" > > /* import */ > extern ServerOptions options; >@@ -145,6 +146,9 @@ > HostStatus host_status; > int len; > >+ if (blacklisted_key(key, 0)) >+ return 0; >+ > resolvedname = get_canonical_hostname(options.use_dns); > ipaddr = get_remote_ipaddr(); > >--- openssh-5.0p1/auth2-pubkey.c >+++ openssh-5.0p1/auth2-pubkey.c >@@ -52,6 +52,7 @@ > #endif > #include "monitor_wrap.h" > #include "misc.h" >+#include "blacklist.h" > > /* import */ > extern ServerOptions options; >@@ -272,6 +273,9 @@ > int success; > char *file; > >+ if (blacklisted_key(key, 0)) >+ return 0; >+ > file = authorized_keys_file(pw); > success = user_key_allowed2(pw, key, file); > xfree(file); >new file mode 100644 >--- /dev/null >+++ openssh-5.0p1/blacklist.c >@@ -0,0 +1,267 @@ >+/* >+ * Support for RSA/DSA key blacklisting based on partial fingerprints, >+ * developed under Openwall Project for Owl - http://www.openwall.com/Owl/ >+ * >+ * Copyright (c) 2008 Dmitry V. Levin <ldv at cvs.openwall.com> >+ * >+ * 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. >+ * >+ * The blacklist encoding was designed by Solar Designer and Dmitry V. Levin. >+ * No intellectual property rights to the encoding scheme are claimed. >+ * >+ * This effort was supported by CivicActions - http://www.civicactions.com >+ * >+ * The file size to encode 294,903 of 48-bit fingerprints is just 1.3 MB, >+ * which corresponds to less than 4.5 bytes per fingerprint. >+ */ >+ >+#include "includes.h" >+#include <string.h> >+#include <unistd.h> >+#include <errno.h> >+#include <fcntl.h> >+ >+#include "atomicio.h" >+#include "blacklist.h" >+#include "canohost.h" >+#include "log.h" >+#include "pathnames.h" >+#include "servconf.h" >+#include "xmalloc.h" >+ >+extern ServerOptions options; >+ >+typedef struct >+{ >+ /* format version identifier */ >+ char version[8]; >+ /* index size, in bits */ >+ uint8_t index_size; >+ /* offset size, in bits */ >+ uint8_t offset_size; >+ /* record size, in bits */ >+ uint8_t record_bits; >+ /* number of records */ >+ uint8_t records[3]; >+ /* offset shift */ >+ uint8_t shift[2]; >+ >+} __attribute__((packed)) blacklist_header; >+ >+static unsigned >+c2u(uint8_t c) >+{ >+ return (c >= 'a') ? (c - 'a' + 10) : (c - '0'); >+} >+ >+static blacklist_error_t >+validate_blacklist(const char *fname, int fd, unsigned *bytes, >+ unsigned *records, unsigned *shift) >+{ >+ unsigned expected; >+ struct stat st; >+ blacklist_header header; >+ >+ if (fstat(fd, &st)) { >+ error("fstat for blacklist file %s failed: %m", fname); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ >+ if (atomicio(read, fd, &header, sizeof(header)) != sizeof(header)) { >+ error("read blacklist file %s header failed: %m", fname); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ >+ if (memcmp(header.version, "SSH-FP", 6)) { >+ error("blacklist file %s has unrecognized format", fname); >+ return BLACKLIST_ERROR_FORMAT; >+ } >+ >+ if (header.index_size != 16 || header.offset_size != 16 || >+ memcmp(header.version, "SSH-FP00", 8)) { >+ error("blacklist file %s has unsupported format", fname); >+ return BLACKLIST_ERROR_VERSION; >+ } >+ >+ *bytes = (header.record_bits >> 3) - 2; >+ *records = >+ (((header.records[0] << 8) + >+ header.records[1]) << 8) + header.records[2]; >+ *shift = (header.shift[0] << 8) + header.shift[1]; >+ >+ expected = sizeof(header) + 0x20000 + (*records) * (*bytes); >+ if (st.st_size != expected) { >+ error("blacklist file %s size mismatch: " >+ "expected size %u, found size %lu", >+ fname, expected, (unsigned long) st.st_size); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ >+ return BLACKLIST_ERROR_NONE; >+} >+ >+static int >+expected_offset(uint16_t index, uint16_t shift, unsigned records) >+{ >+ return ((index * (long long) records) >> 16) - shift; >+} >+ >+static int >+xlseek(const char *fname, int fd, unsigned seek) >+{ >+ if (lseek(fd, seek, SEEK_SET) != seek) { >+ error("lseek for blacklist file %s failed: %m", fname); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ return BLACKLIST_ERROR_NONE; >+} >+ >+static blacklist_error_t >+check(const char *fname, int fd, const char *s) >+{ >+ unsigned bytes, records, shift; >+ unsigned num, i, j; >+ int off_start, off_end; >+ blacklist_error_t rc; >+ uint16_t index; >+ /* max number of bytes stored in record_bits, minus two bytes used for index */ >+ uint8_t buf[(0xff >> 3) - 2]; >+ >+ if ((rc = validate_blacklist(fname, fd, &bytes, &records, &shift))) >+ return rc; >+ >+ index = (((((c2u(s[0]) << 4) | c2u(s[1])) << 4) | >+ c2u(s[2])) << 4) | c2u(s[3]); >+ if (xlseek(fname, fd, sizeof(blacklist_header) + index * 2)) >+ return BLACKLIST_ERROR_ACCESS; >+ >+ if (atomicio(read, fd, buf, 4) != 4) { >+ error("read blacklist file %s offsets failed: %m", fname); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ >+ off_start = (buf[0] << 8) + buf[1] + >+ expected_offset(index, shift, records); >+ if (off_start < 0 || (unsigned) off_start > records) { >+ error("blacklist file %s off_start overflow [%d] for index %#x", >+ fname, off_start, index); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ if (index < 0xffff) { >+ off_end = (buf[2] << 8) + buf[3] + >+ expected_offset(index + 1, shift, records); >+ if (off_end < off_start || (unsigned) off_end > records) { >+ error("blacklist file %s off_end overflow [%d] for index %#x", >+ fname, off_end, index); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ } else >+ off_end = records; >+ >+ if (xlseek(fname, fd, >+ sizeof(blacklist_header) + 0x20000 + off_start * bytes)) >+ return BLACKLIST_ERROR_ACCESS; >+ >+ num = off_end - off_start; >+ for (i = 0; i < num; ++i) { >+ if (atomicio(read, fd, buf, bytes) != bytes) { >+ error("read blacklist file %s fingerprints failed: %m", >+ fname); >+ return BLACKLIST_ERROR_ACCESS; >+ } >+ >+ for (j = 0; j < bytes; ++j) >+ if (((c2u(s[4 + j * 2]) << 4) | c2u(s[5 + j * 2])) != >+ buf[j]) >+ break; >+ if (j >= bytes) { >+ debug("blacklisted fingerprint: %s offset=%u, number=%u", >+ s, off_start, i); >+ return BLACKLIST_ERROR_ALL; >+ } >+ } >+ >+ debug("non-blacklisted fingerprint: %s offset=%u, number=%u", >+ s, off_start, num); >+ return BLACKLIST_ERROR_NONE; >+} >+ >+static blacklist_error_t >+blacklisted_fingerprint(const char *hex) >+{ >+ int fd = -1; >+ blacklist_error_t rc = BLACKLIST_ERROR_ACCESS; >+ const char *fname = _PATH_BLACKLIST; >+ char *s, *p; >+ >+ debug("Checking fingerprint %s using blacklist file %s", hex, fname); >+ >+ s = xstrdup(hex); >+ for (p = s; *hex; ++hex) >+ if (*hex != ':') >+ *p++ = *hex; >+ *p = '\0'; >+ >+ if (strlen(s) != 32 || strlen(s) != strspn(s, "0123456789abcdef")) { >+ error("%s: invalid fingerprint", s); >+ goto out; >+ } >+ >+ if ((fd = open(fname, O_RDONLY)) < 0) { >+ if (ENOENT == errno) { >+ rc = BLACKLIST_ERROR_MISSING; >+ verbose("open blacklist file %s failed: %m", fname); >+ } else >+ logit("open blacklist file %s failed: %m", fname); >+ goto out; >+ } >+ >+ rc = check(fname, fd, s); >+ >+out: >+ close(fd); >+ xfree(s); >+ return rc; >+} >+ >+int >+blacklisted_key(Key *key, int hostkey) >+{ >+ int rc; >+ const char *text; >+ char *fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); >+ >+ switch ((rc = blacklisted_fingerprint(fp))) { >+ case BLACKLIST_ERROR_NONE: >+ break; >+ case BLACKLIST_ERROR_ALL: >+ text = (options.ignore_blacklist_errors == rc) ? >+ "Permitted" : "Rejected"; >+ if (hostkey) >+ logit("%s blacklisted host key %s", text, fp); >+ else >+ logit("%s blacklisted public key %s from %.100s", >+ text, fp, get_remote_ipaddr()); >+ break; >+ default: >+ if (hostkey) >+ logit("Unable to check blacklist for host key %s", >+ fp); >+ else >+ logit("Unable to check blacklist for public key %s from %.100s", >+ fp, get_remote_ipaddr()); >+ } >+ >+ xfree(fp); >+ return (rc > options.ignore_blacklist_errors); >+} >new file mode 100644 >--- /dev/null >+++ openssh-5.0p1/blacklist.h >@@ -0,0 +1,37 @@ >+/* >+ * Support for RSA/DSA key blacklisting based on partial fingerprints, >+ * developed under Openwall Project for Owl - http://www.openwall.com/Owl/ >+ * >+ * Copyright (c) 2008 Dmitry V. Levin <ldv at cvs.openwall.com> >+ * >+ * Permission to use, copy, modify, and distribute this software for any >+ * purpose with or without fee is hereby granted, provided that the above >+ * copyright notice and this permission notice appear in all copies. >+ * >+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES >+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF >+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR >+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES >+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN >+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF >+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. >+ */ >+ >+#ifndef BLACKLIST_H_ >+#define BLACKLIST_H_ >+ >+#include "key.h" >+ >+int blacklisted_key(Key *, int); >+ >+typedef enum >+{ >+ BLACKLIST_ERROR_NONE = 0, >+ BLACKLIST_ERROR_MISSING, >+ BLACKLIST_ERROR_VERSION, >+ BLACKLIST_ERROR_FORMAT, >+ BLACKLIST_ERROR_ACCESS, >+ BLACKLIST_ERROR_ALL >+} blacklist_error_t; >+ >+#endif /* BLACKLIST_H_ */ >--- openssh-5.0p1/pathnames.h >+++ openssh-5.0p1/pathnames.h >@@ -43,6 +43,8 @@ > /* Backwards compatibility */ > #define _PATH_DH_PRIMES SSHDIR "/primes" > >+#define _PATH_BLACKLIST SSHDIR "/blacklist" >+ > #ifndef _PATH_SSH_PROGRAM > #define _PATH_SSH_PROGRAM "/usr/bin/ssh" > #endif >--- openssh-5.0p1/servconf.c >+++ openssh-5.0p1/servconf.c >@@ -39,6 +39,7 @@ > #include "match.h" > #include "channels.h" > #include "groupaccess.h" >+#include "blacklist.h" > > static void add_listen_addr(ServerOptions *, char *, u_short); > static void add_one_listen_addr(ServerOptions *, char *, u_short); >@@ -94,6 +95,7 @@ > options->password_authentication = -1; > options->kbd_interactive_authentication = -1; > options->challenge_response_authentication = -1; >+ options->ignore_blacklist_errors = -1; > options->permit_empty_passwd = -1; > options->permit_user_env = -1; > options->use_login = -1; >@@ -213,6 +217,8 @@ > options->kbd_interactive_authentication = 0; > if (options->challenge_response_authentication == -1) > options->challenge_response_authentication = 1; >+ if (options->ignore_blacklist_errors == -1) >+ options->ignore_blacklist_errors = BLACKLIST_ERROR_ALL; //VERSION; > if (options->permit_empty_passwd == -1) > options->permit_empty_passwd = 0; > if (options->permit_user_env == -1) >@@ -282,7 +299,7 @@ > sListenAddress, sAddressFamily, > sPrintMotd, sPrintLastLog, sIgnoreRhosts, > sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, >- sStrictModes, sEmptyPasswd, sTCPKeepAlive, >+ sStrictModes, sIgnoreBlacklistErrors, sEmptyPasswd, sTCPKeepAlive, > sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, > sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, > sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, >@@ -372,6 +390,7 @@ > { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, > { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, > { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, >+ { "ignoreblacklisterrors", sIgnoreBlacklistErrors, SSHCFG_GLOBAL }, > { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL }, > { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, > { "uselogin", sUseLogin, SSHCFG_GLOBAL }, >@@ -923,6 +944,32 @@ > intptr = &options->tcp_keep_alive; > goto parse_flag; > >+ case sIgnoreBlacklistErrors: >+ intptr = &options->ignore_blacklist_errors; >+ arg = strdelim(&cp); >+ if (!arg || *arg == '\0') >+ fatal("%s line %d: missing none/missing/version/format/access/all argument.", >+ filename, linenum); >+ value = 0; /* silence compiler */ >+ if (strcmp(arg, "none") == 0) >+ value = BLACKLIST_ERROR_NONE; >+ else if (strcmp(arg, "missing") == 0) >+ value = BLACKLIST_ERROR_MISSING; >+ else if (strcmp(arg, "version") == 0) >+ value = BLACKLIST_ERROR_VERSION; >+ else if (strcmp(arg, "format") == 0) >+ value = BLACKLIST_ERROR_FORMAT; >+ else if (strcmp(arg, "access") == 0) >+ value = BLACKLIST_ERROR_ACCESS; >+ else if (strcmp(arg, "all") == 0) >+ value = BLACKLIST_ERROR_ALL; >+ else >+ fatal("%s line %d: Bad none/missing/version/format/access/all argument: %s", >+ filename, linenum, arg); >+ if (*activep && *intptr == -1) >+ *intptr = value; >+ break; >+ > case sEmptyPasswd: > intptr = &options->permit_empty_passwd; > goto parse_flag; >--- openssh-5.0p1/servconf.h >+++ openssh-5.0p1/servconf.h >@@ -95,6 +95,7 @@ > * authentication. */ > int kbd_interactive_authentication; /* If true, permit */ > int challenge_response_authentication; >+ int ignore_blacklist_errors; /* none/missing/version/format/access/all */ > int permit_empty_passwd; /* If false, do not permit empty > * passwords. */ > int permit_user_env; /* If true, read ~/.ssh/environment */ >--- openssh-5.0p1/sshd.c >+++ openssh-5.0p1/sshd.c >@@ -118,6 +118,7 @@ > #include "monitor_wrap.h" > #include "monitor_fdpass.h" > #include "version.h" >+#include "blacklist.h" > > #ifdef LIBWRAP > #include <tcpd.h> >@@ -1484,6 +1494,11 @@ > sensitive_data.host_keys[i] = NULL; > continue; > } >+ if (blacklisted_key(key, 1)) { >+ sensitive_data.host_keys[i] = NULL; >+ key_free(key); >+ continue; >+ } > switch (key->type) { > case KEY_RSA1: > sensitive_data.ssh1_host_key = key; >--- openssh-5.0p1/sshd_config.5 >+++ openssh-5.0p1/sshd_config.5 >@@ -611,6 +611,39 @@ > Specifies whether password authentication is allowed. > The default is > .Dq yes . >+.It Cm IgnoreBlacklistErrors >+Specifies whether >+.Xr sshd 8 >+should allow keys recorded in its blacklist of known-compromised keys. >+If >+.Dq all , >+then attempts to authenticate with compromised keys will be logged >+but accepted. >+If >+.Dq access , >+then attempts to authenticate with compromised keys will be rejected, >+but blacklist file access errors will be ignored. >+If >+.Dq format , >+then attempts to authenticate with compromised keys will be rejected, but >+blacklist file access errors due to missing blacklist file or blacklist >+file unrecognized format will be ignored. >+If >+.Dq version , >+then attempts to authenticate with compromised keys will be rejected, but >+blacklist file access errors due to missing blacklist file or blacklist >+file format version mismatch will be ignored. >+If >+.Dq missing , >+then attempts to authenticate with compromised keys will be rejected, >+but blacklist file access errors due to missing blacklist file will >+be ignored. >+If >+.Dq none , >+then attempts to authenticate with compromised keys, or in case of >+any blacklist file access error, will be rejected. >+The default is >+.Dq version . > .It Cm PermitEmptyPasswords > When password authentication is allowed, it specifies whether the > server allows login to accounts with empty password strings.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 221759
:
153175
|
153177
| 154917