summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in13
-rw-r--r--auth-rh-rsa.c16
-rw-r--r--auth-rsa.c15
-rw-r--r--auth2-hostbased.c15
-rw-r--r--auth2-pubkey.c15
-rw-r--r--authfile.c111
-rw-r--r--authfile.h3
-rw-r--r--debian/changelog15
-rw-r--r--debian/control8
-rw-r--r--debian/openssh-server.postinst30
-rw-r--r--debian/openssh-server.templates20
-rw-r--r--pathnames.h2
-rw-r--r--servconf.c10
-rw-r--r--servconf.h1
-rw-r--r--ssh-vulnkey.1151
-rw-r--r--ssh-vulnkey.c311
-rw-r--r--sshd.c15
-rw-r--r--sshd_config.514
18 files changed, 756 insertions, 9 deletions
diff --git a/Makefile.in b/Makefile.in
index 3ac9aaf45..0c6f7e550 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60,7 +60,7 @@ EXEEXT=@EXEEXT@
60INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ 60INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
61INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ 61INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
62 62
63TARGETS=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) 63TARGETS=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)
64 64
65LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 65LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
66 canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ 66 canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -88,8 +88,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
88 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ 88 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
89 audit.o audit-bsm.o platform.o 89 audit.o audit-bsm.o platform.o
90 90
91MANPAGES = 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 91MANPAGES = 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
92MANPAGES_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 92MANPAGES_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
93MANTYPE = @MANTYPE@ 93MANTYPE = @MANTYPE@
94 94
95CONFIGFILES=sshd_config.out ssh_config.out moduli.out 95CONFIGFILES=sshd_config.out ssh_config.out moduli.out
@@ -165,6 +165,9 @@ sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glo
165ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o 165ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
166 $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 166 $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
167 167
168ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
169 $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
170
168# test driver for the loginrec code - not built by default 171# test driver for the loginrec code - not built by default
169logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o 172logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
170 $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) 173 $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
@@ -264,6 +267,7 @@ install-files: scard-install
264 $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign $(DESTDIR)$(SSH_KEYSIGN) 267 $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign $(DESTDIR)$(SSH_KEYSIGN)
265 $(INSTALL) -m 0755 $(STRIP_OPT) sftp $(DESTDIR)$(bindir)/sftp 268 $(INSTALL) -m 0755 $(STRIP_OPT) sftp $(DESTDIR)$(bindir)/sftp
266 $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server $(DESTDIR)$(SFTP_SERVER) 269 $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server $(DESTDIR)$(SFTP_SERVER)
270 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey $(DESTDIR)$(bindir)/ssh-vulnkey
267 $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 271 $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
268 $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 272 $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
269 $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 273 $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@@ -280,6 +284,7 @@ install-files: scard-install
280 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 284 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
281 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 285 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
282 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 286 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
287 $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
283 -rm -f $(DESTDIR)$(bindir)/slogin 288 -rm -f $(DESTDIR)$(bindir)/slogin
284 ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin 289 ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
285 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 290 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
@@ -361,6 +366,7 @@ uninstall:
361 -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) 366 -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
362 -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) 367 -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
363 -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) 368 -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
369 -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
364 -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) 370 -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
365 -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) 371 -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
366 -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) 372 -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
@@ -373,6 +379,7 @@ uninstall:
373 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 379 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
374 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 380 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
375 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 381 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
382 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
376 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 383 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
377 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 384 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8
378 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 385 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index eca750275..093461e83 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -20,6 +20,7 @@
20#include <pwd.h> 20#include <pwd.h>
21#include <stdarg.h> 21#include <stdarg.h>
22 22
23#include "xmalloc.h"
23#include "packet.h" 24#include "packet.h"
24#include "uidswap.h" 25#include "uidswap.h"
25#include "log.h" 26#include "log.h"
@@ -27,6 +28,7 @@
27#include "servconf.h" 28#include "servconf.h"
28#include "key.h" 29#include "key.h"
29#include "hostfile.h" 30#include "hostfile.h"
31#include "authfile.h"
30#include "pathnames.h" 32#include "pathnames.h"
31#include "auth.h" 33#include "auth.h"
32#include "canohost.h" 34#include "canohost.h"
@@ -42,8 +44,22 @@ int
42auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost, 44auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
43 Key *client_host_key) 45 Key *client_host_key)
44{ 46{
47 char *fp;
45 HostStatus host_status; 48 HostStatus host_status;
46 49
50 if (blacklisted_key(client_host_key)) {
51 fp = key_fingerprint(client_host_key, SSH_FP_MD5, SSH_FP_HEX);
52 if (options.permit_blacklisted_keys)
53 logit("Public key %s blacklisted (see "
54 "ssh-vulnkey(1)); continuing anyway", fp);
55 else
56 logit("Public key %s blacklisted (see "
57 "ssh-vulnkey(1))", fp);
58 xfree(fp);
59 if (!options.permit_blacklisted_keys)
60 return 0;
61 }
62
47 /* Check if we would accept it using rhosts authentication. */ 63 /* Check if we would accept it using rhosts authentication. */
48 if (!auth_rhosts(pw, cuser)) 64 if (!auth_rhosts(pw, cuser))
49 return 0; 65 return 0;
diff --git a/auth-rsa.c b/auth-rsa.c
index 69f9a5896..1d277f92a 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -40,6 +40,7 @@
40#include "servconf.h" 40#include "servconf.h"
41#include "key.h" 41#include "key.h"
42#include "hostfile.h" 42#include "hostfile.h"
43#include "authfile.h"
43#include "auth.h" 44#include "auth.h"
44#ifdef GSSAPI 45#ifdef GSSAPI
45#include "ssh-gss.h" 46#include "ssh-gss.h"
@@ -221,6 +222,7 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
221 char *cp; 222 char *cp;
222 char *key_options; 223 char *key_options;
223 int keybits; 224 int keybits;
225 char *fp;
224 226
225 /* Skip leading whitespace, empty and comment lines. */ 227 /* Skip leading whitespace, empty and comment lines. */
226 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 228 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
@@ -265,6 +267,19 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
265 "actual %d vs. announced %d.", 267 "actual %d vs. announced %d.",
266 file, linenum, BN_num_bits(key->rsa->n), bits); 268 file, linenum, BN_num_bits(key->rsa->n), bits);
267 269
270 if (blacklisted_key(key)) {
271 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
272 if (options.permit_blacklisted_keys)
273 logit("Public key %s blacklisted (see "
274 "ssh-vulnkey(1)); continuing anyway", fp);
275 else
276 logit("Public key %s blacklisted (see "
277 "ssh-vulnkey(1))", fp);
278 xfree(fp);
279 if (!options.permit_blacklisted_keys)
280 continue;
281 }
282
268 /* We have found the desired key. */ 283 /* We have found the desired key. */
269 /* 284 /*
270 * If our options do not allow this key to be used, 285 * If our options do not allow this key to be used,
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 663dec5d9..a0ee3060a 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -40,6 +40,7 @@
40#include "compat.h" 40#include "compat.h"
41#include "key.h" 41#include "key.h"
42#include "hostfile.h" 42#include "hostfile.h"
43#include "authfile.h"
43#include "auth.h" 44#include "auth.h"
44#include "canohost.h" 45#include "canohost.h"
45#ifdef GSSAPI 46#ifdef GSSAPI
@@ -141,10 +142,24 @@ int
141hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, 142hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
142 Key *key) 143 Key *key)
143{ 144{
145 char *fp;
144 const char *resolvedname, *ipaddr, *lookup; 146 const char *resolvedname, *ipaddr, *lookup;
145 HostStatus host_status; 147 HostStatus host_status;
146 int len; 148 int len;
147 149
150 if (blacklisted_key(key)) {
151 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
152 if (options.permit_blacklisted_keys)
153 logit("Public key %s blacklisted (see "
154 "ssh-vulnkey(1)); continuing anyway", fp);
155 else
156 logit("Public key %s blacklisted (see "
157 "ssh-vulnkey(1))", fp);
158 xfree(fp);
159 if (!options.permit_blacklisted_keys)
160 return 0;
161 }
162
148 resolvedname = get_canonical_hostname(options.use_dns); 163 resolvedname = get_canonical_hostname(options.use_dns);
149 ipaddr = get_remote_ipaddr(); 164 ipaddr = get_remote_ipaddr();
150 165
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 9863cd9e6..cf911968a 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -42,6 +42,7 @@
42#include "compat.h" 42#include "compat.h"
43#include "key.h" 43#include "key.h"
44#include "hostfile.h" 44#include "hostfile.h"
45#include "authfile.h"
45#include "auth.h" 46#include "auth.h"
46#include "pathnames.h" 47#include "pathnames.h"
47#include "uidswap.h" 48#include "uidswap.h"
@@ -269,9 +270,23 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
269int 270int
270user_key_allowed(struct passwd *pw, Key *key) 271user_key_allowed(struct passwd *pw, Key *key)
271{ 272{
273 char *fp;
272 int success; 274 int success;
273 char *file; 275 char *file;
274 276
277 if (blacklisted_key(key)) {
278 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
279 if (options.permit_blacklisted_keys)
280 logit("Public key %s blacklisted (see "
281 "ssh-vulnkey(1)); continuing anyway", fp);
282 else
283 logit("Public key %s blacklisted (see "
284 "ssh-vulnkey(1))", fp);
285 xfree(fp);
286 if (!options.permit_blacklisted_keys)
287 return 0;
288 }
289
275 file = authorized_keys_file(pw); 290 file = authorized_keys_file(pw);
276 success = user_key_allowed2(pw, key, file); 291 success = user_key_allowed2(pw, key, file);
277 xfree(file); 292 xfree(file);
diff --git a/authfile.c b/authfile.c
index 735c64780..5348a014d 100644
--- a/authfile.c
+++ b/authfile.c
@@ -65,6 +65,7 @@
65#include "rsa.h" 65#include "rsa.h"
66#include "misc.h" 66#include "misc.h"
67#include "atomicio.h" 67#include "atomicio.h"
68#include "pathnames.h"
68 69
69/* Version identification string for SSH v1 identity files. */ 70/* Version identification string for SSH v1 identity files. */
70static const char authfile_id_string[] = 71static const char authfile_id_string[] =
@@ -677,3 +678,113 @@ key_load_public(const char *filename, char **commentp)
677 key_free(pub); 678 key_free(pub);
678 return NULL; 679 return NULL;
679} 680}
681
682char *
683blacklist_filename(const Key *key)
684{
685 char *name;
686
687 xasprintf(&name, "%s.%s-%u",
688 _PATH_BLACKLIST, key_type(key), key_size(key));
689 return name;
690}
691
692/* Scan a blacklist of known-vulnerable keys. */
693int
694blacklisted_key(const Key *key)
695{
696 char *blacklist_file;
697 int fd = -1;
698 char *dgst_hex = NULL;
699 char *dgst_packed = NULL, *p;
700 int i;
701 size_t line_len;
702 struct stat st;
703 char buf[256];
704 off_t start, lower, upper;
705 int ret = 0;
706
707 blacklist_file = blacklist_filename(key);
708 debug("Checking blacklist file %s", blacklist_file);
709 fd = open(blacklist_file, O_RDONLY);
710 if (fd < 0)
711 goto out;
712
713 dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
714 /* Remove all colons */
715 dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
716 for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
717 if (dgst_hex[i] != ':')
718 *p++ = dgst_hex[i];
719 /* Only compare least-significant 80 bits (to keep the blacklist
720 * size down)
721 */
722 line_len = strlen(dgst_packed + 12);
723 if (line_len > 32)
724 goto out;
725
726 /* Skip leading comments */
727 start = 0;
728 for (;;) {
729 ssize_t r;
730 char *newline;
731
732 r = atomicio(read, fd, buf, 256);
733 if (r <= 0)
734 goto out;
735 if (buf[0] != '#')
736 break;
737
738 newline = memchr(buf, '\n', 256);
739 if (!newline)
740 goto out;
741 start += newline + 1 - buf;
742 if (lseek(fd, start, SEEK_SET) < 0)
743 goto out;
744 }
745
746 /* Initialise binary search record numbers */
747 if (fstat(fd, &st) < 0)
748 goto out;
749 lower = 0;
750 upper = (st.st_size - start) / (line_len + 1);
751
752 while (lower != upper) {
753 off_t cur;
754 char buf[32];
755 int cmp;
756
757 cur = lower + (upper - lower) / 2;
758
759 /* Read this line and compare to digest; this is
760 * overflow-safe since cur < max(off_t) / (line_len + 1) */
761 if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
762 break;
763 if (atomicio(read, fd, buf, line_len) != line_len)
764 break;
765 cmp = memcmp(buf, dgst_packed + 12, line_len);
766 if (cmp < 0) {
767 if (cur == lower)
768 break;
769 lower = cur;
770 } else if (cmp > 0) {
771 if (cur == upper)
772 break;
773 upper = cur;
774 } else {
775 debug("Found %s in blacklist", dgst_hex);
776 ret = 1;
777 break;
778 }
779 }
780
781out:
782 if (dgst_packed)
783 xfree(dgst_packed);
784 if (dgst_hex)
785 xfree(dgst_hex);
786 if (fd >= 0)
787 close(fd);
788 xfree(blacklist_file);
789 return ret;
790}
diff --git a/authfile.h b/authfile.h
index a6c74934d..e47710495 100644
--- a/authfile.h
+++ b/authfile.h
@@ -23,4 +23,7 @@ Key *key_load_private_type(int, const char *, const char *, char **, int *);
23Key *key_load_private_pem(int, int, const char *, char **); 23Key *key_load_private_pem(int, int, const char *, char **);
24int key_perm_ok(int, const char *); 24int key_perm_ok(int, const char *);
25 25
26char *blacklist_filename(const Key *key);
27int blacklisted_key(const Key *key);
28
26#endif 29#endif
diff --git a/debian/changelog b/debian/changelog
index 9a9095189..95ab72caf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,19 @@
1openssh (1:4.7p1-9) UNRELEASED; urgency=low 1openssh (1:4.7p1-9) UNRELEASED; urgency=critical
2 2
3 * Fill in CVE identifier for security vulnerability fixed in 1:4.7p1-8. 3 * Fill in CVE identifier for security vulnerability fixed in 1:4.7p1-8.
4 * Mitigate OpenSSL security vulnerability:
5 - Add key blacklisting support. Keys listed in
6 /etc/ssh/blacklist.TYPE-LENGTH will be rejected for authentication by
7 sshd, unless "PermitBlacklistedKeys yes" is set in
8 /etc/ssh/sshd_config.
9 - Add a new program, ssh-vulnkey, which can be used to check keys
10 against these blacklists.
11 - Depend on openssh-blacklist.
12 - Force dependencies on libssl0.9.8 / libcrypto0.9.8-udeb to at least
13 0.9.8g-9.
14 - Automatically regenerate known-compromised host keys, with a
15 critical-priority debconf note. (I regret that there was no time to
16 gather translations.)
4 17
5 -- Colin Watson <cjwatson@debian.org> Wed, 09 Apr 2008 14:57:43 +0100 18 -- Colin Watson <cjwatson@debian.org> Wed, 09 Apr 2008 14:57:43 +0100
6 19
diff --git a/debian/control b/debian/control
index 290799998..c2bf961eb 100644
--- a/debian/control
+++ b/debian/control
@@ -8,7 +8,7 @@ Uploaders: Colin Watson <cjwatson@debian.org>, Matthew Vernon <matthew@debian.or
8 8
9Package: openssh-client 9Package: openssh-client
10Architecture: any 10Architecture: any
11Depends: ${shlibs:Depends}, debconf (>= 1.2.0) | debconf-2.0, adduser (>= 3.10), dpkg (>= 1.7.0), passwd 11Depends: ${shlibs:Depends}, debconf (>= 1.2.0) | debconf-2.0, adduser (>= 3.10), dpkg (>= 1.7.0), passwd, libssl0.9.8 (>= 0.9.8g-9)
12Recommends: xauth 12Recommends: xauth
13Conflicts: ssh (<< 1:3.8.1p1-9), sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7) 13Conflicts: ssh (<< 1:3.8.1p1-9), sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7)
14Replaces: ssh, ssh-krb5 14Replaces: ssh, ssh-krb5
@@ -37,7 +37,7 @@ Description: secure shell client, an rlogin/rsh/rcp replacement
37Package: openssh-server 37Package: openssh-server
38Priority: optional 38Priority: optional
39Architecture: any 39Architecture: any
40Depends: ${shlibs:Depends}, debconf (>= 1.2.0) | debconf-2.0, libpam-runtime (>= 0.76-14), libpam-modules (>= 0.72-9), adduser (>= 3.9), dpkg (>= 1.9.0), openssh-client (= ${binary:Version}), lsb-base (>= 3.0-6) 40Depends: ${shlibs:Depends}, debconf (>= 1.2.0) | debconf-2.0, libpam-runtime (>= 0.76-14), libpam-modules (>= 0.72-9), adduser (>= 3.9), dpkg (>= 1.9.0), openssh-client (= ${binary:Version}), lsb-base (>= 3.0-6), libssl0.9.8 (>= 0.9.8g-9), openssh-blacklist
41Recommends: xauth 41Recommends: xauth
42Conflicts: ssh (<< 1:3.8.1p1-9), ssh-nonfree (<<2), ssh-socks, ssh2, sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7) 42Conflicts: ssh (<< 1:3.8.1p1-9), ssh-nonfree (<<2), ssh-socks, ssh2, sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7)
43Replaces: ssh, openssh-client (<< 1:3.8.1p1-11), ssh-krb5 43Replaces: ssh, openssh-client (<< 1:3.8.1p1-11), ssh-krb5
@@ -99,7 +99,7 @@ XC-Package-Type: udeb
99Section: debian-installer 99Section: debian-installer
100Priority: optional 100Priority: optional
101Architecture: any 101Architecture: any
102Depends: ${shlibs:Depends}, libnss-files-udeb 102Depends: ${shlibs:Depends}, libnss-files-udeb, libcrypto0.9.8-udeb (>= 0.9.8g-9)
103XB-Installer-Menu-Item: 99900 103XB-Installer-Menu-Item: 99900
104Description: secure shell client for the Debian installer 104Description: secure shell client for the Debian installer
105 This is the portable version of OpenSSH, a free implementation of 105 This is the portable version of OpenSSH, a free implementation of
@@ -113,7 +113,7 @@ XC-Package-Type: udeb
113Section: debian-installer 113Section: debian-installer
114Priority: optional 114Priority: optional
115Architecture: any 115Architecture: any
116Depends: ${shlibs:Depends}, libnss-files-udeb 116Depends: ${shlibs:Depends}, libnss-files-udeb, libcrypto0.9.8-udeb (>= 0.9.8g-9)
117Description: secure shell server for the Debian installer 117Description: secure shell server for the Debian installer
118 This is the portable version of OpenSSH, a free implementation of 118 This is the portable version of OpenSSH, a free implementation of
119 the Secure Shell protocol as specified by the IETF secsh working 119 the Secure Shell protocol as specified by the IETF secsh working
diff --git a/debian/openssh-server.postinst b/debian/openssh-server.postinst
index 1d26a7b55..b7ea210c4 100644
--- a/debian/openssh-server.postinst
+++ b/debian/openssh-server.postinst
@@ -183,6 +183,35 @@ create_keys() {
183} 183}
184 184
185 185
186vulnerable_host_keys() {
187 # If the admin has explicitly put the vulnerable keys back, we
188 # assume they can look after themselves.
189 db_fget ssh/vulnerable_host_keys seen
190 if [ "$RET" = true ]; then
191 return 0
192 fi
193
194 hostkeys="$(host_keys_required)"
195 vulnerable=
196 for hostkey in $hostkeys; do
197 [ -f "$hostkey" ] || continue
198 if ssh-vulnkey -q "$hostkey"; then
199 vulnerable="${vulnerable:+$vulnerable }$hostkey"
200 fi
201 done
202 if [ "$vulnerable" ]; then
203 db_subst ssh/vulnerable_host_keys HOST_KEYS "$vulnerable"
204 db_input critical ssh/vulnerable_host_keys || true
205 db_go
206 for hostkey in $vulnerable; do
207 mv "$hostkey" "$hostkey.broken" || true
208 mv "$hostkey.pub" "$hostkey.pub.broken" || true
209 done
210 create_keys
211 fi
212}
213
214
186check_password_auth() { 215check_password_auth() {
187 passwordauth="$(get_config_option PasswordAuthentication)" 216 passwordauth="$(get_config_option PasswordAuthentication)"
188 crauth="$(get_config_option ChallengeResponseAuthentication)" 217 crauth="$(get_config_option ChallengeResponseAuthentication)"
@@ -422,6 +451,7 @@ fix_doc_symlink
422create_sshdconfig 451create_sshdconfig
423check_idea_key 452check_idea_key
424create_keys 453create_keys
454vulnerable_host_keys
425fix_statoverride 455fix_statoverride
426if dpkg --compare-versions "$2" lt 1:4.3p2-3; then 456if dpkg --compare-versions "$2" lt 1:4.3p2-3; then
427 fix_sshd_shell 457 fix_sshd_shell
diff --git a/debian/openssh-server.templates b/debian/openssh-server.templates
index 2cc62f8f1..6c1187e7f 100644
--- a/debian/openssh-server.templates
+++ b/debian/openssh-server.templates
@@ -62,3 +62,23 @@ _Description: Disable challenge-response authentication?
62 able to log in using passwords. If you leave it enabled (the default 62 able to log in using passwords. If you leave it enabled (the default
63 answer), then the 'PasswordAuthentication no' option will have no useful 63 answer), then the 'PasswordAuthentication no' option will have no useful
64 effect unless you also adjust your PAM configuration in /etc/pam.d/ssh. 64 effect unless you also adjust your PAM configuration in /etc/pam.d/ssh.
65
66Template: ssh/vulnerable_host_keys
67Type: note
68_Description: Vulnerable host keys will be regenerated
69 Some of the OpenSSH server host keys on this system were generated with a
70 version of OpenSSL that had a broken random number generator. As a result,
71 these host keys are from a well-known set, are subject to brute-force
72 attacks, and must be regenerated.
73 .
74 Users of this system should be informed of this change, as they will be
75 prompted about the host key change the next time they log in. Use
76 'ssh-keygen -l -f HOST_KEY_FILE' after the upgrade has changed to print the
77 fingerprints of the new host keys.
78 .
79 The affected host keys are:
80 .
81 ${HOST_KEYS}
82 .
83 User keys may also be affected by this problem. The 'ssh-vulnkey' command
84 may be used as a partial test for this.
diff --git a/pathnames.h b/pathnames.h
index f2571e274..8886e8edd 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -43,6 +43,8 @@
43/* Backwards compatibility */ 43/* Backwards compatibility */
44#define _PATH_DH_PRIMES SSHDIR "/primes" 44#define _PATH_DH_PRIMES SSHDIR "/primes"
45 45
46#define _PATH_BLACKLIST SSHDIR "/blacklist"
47
46#ifndef _PATH_SSH_PROGRAM 48#ifndef _PATH_SSH_PROGRAM
47#define _PATH_SSH_PROGRAM "/usr/bin/ssh" 49#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
48#endif 50#endif
diff --git a/servconf.c b/servconf.c
index 14a9dde3d..c5688912d 100644
--- a/servconf.c
+++ b/servconf.c
@@ -96,6 +96,7 @@ initialize_server_options(ServerOptions *options)
96 options->password_authentication = -1; 96 options->password_authentication = -1;
97 options->kbd_interactive_authentication = -1; 97 options->kbd_interactive_authentication = -1;
98 options->challenge_response_authentication = -1; 98 options->challenge_response_authentication = -1;
99 options->permit_blacklisted_keys = -1;
99 options->permit_empty_passwd = -1; 100 options->permit_empty_passwd = -1;
100 options->permit_user_env = -1; 101 options->permit_user_env = -1;
101 options->use_login = -1; 102 options->use_login = -1;
@@ -218,6 +219,8 @@ fill_default_server_options(ServerOptions *options)
218 options->kbd_interactive_authentication = 0; 219 options->kbd_interactive_authentication = 0;
219 if (options->challenge_response_authentication == -1) 220 if (options->challenge_response_authentication == -1)
220 options->challenge_response_authentication = 1; 221 options->challenge_response_authentication = 1;
222 if (options->permit_blacklisted_keys == -1)
223 options->permit_blacklisted_keys = 0;
221 if (options->permit_empty_passwd == -1) 224 if (options->permit_empty_passwd == -1)
222 options->permit_empty_passwd = 0; 225 options->permit_empty_passwd = 0;
223 if (options->permit_user_env == -1) 226 if (options->permit_user_env == -1)
@@ -287,7 +290,7 @@ typedef enum {
287 sListenAddress, sAddressFamily, 290 sListenAddress, sAddressFamily,
288 sPrintMotd, sPrintLastLog, sIgnoreRhosts, 291 sPrintMotd, sPrintLastLog, sIgnoreRhosts,
289 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, 292 sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
290 sStrictModes, sEmptyPasswd, sTCPKeepAlive, 293 sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
291 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, 294 sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
292 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 295 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
293 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 296 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
@@ -387,6 +390,7 @@ static struct {
387 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 390 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
388 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 391 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
389 { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 392 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
393 { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
390 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL }, 394 { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
391 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, 395 { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
392 { "uselogin", sUseLogin, SSHCFG_GLOBAL }, 396 { "uselogin", sUseLogin, SSHCFG_GLOBAL },
@@ -943,6 +947,10 @@ parse_flag:
943 intptr = &options->tcp_keep_alive; 947 intptr = &options->tcp_keep_alive;
944 goto parse_flag; 948 goto parse_flag;
945 949
950 case sPermitBlacklistedKeys:
951 intptr = &options->permit_blacklisted_keys;
952 goto parse_flag;
953
946 case sEmptyPasswd: 954 case sEmptyPasswd:
947 intptr = &options->permit_empty_passwd; 955 intptr = &options->permit_empty_passwd;
948 goto parse_flag; 956 goto parse_flag;
diff --git a/servconf.h b/servconf.h
index 257de1c8b..be42e9f60 100644
--- a/servconf.h
+++ b/servconf.h
@@ -94,6 +94,7 @@ typedef struct {
94 * authentication. */ 94 * authentication. */
95 int kbd_interactive_authentication; /* If true, permit */ 95 int kbd_interactive_authentication; /* If true, permit */
96 int challenge_response_authentication; 96 int challenge_response_authentication;
97 int permit_blacklisted_keys; /* If true, permit */
97 int permit_empty_passwd; /* If false, do not permit empty 98 int permit_empty_passwd; /* If false, do not permit empty
98 * passwords. */ 99 * passwords. */
99 int permit_user_env; /* If true, read ~/.ssh/environment */ 100 int permit_user_env; /* If true, read ~/.ssh/environment */
diff --git a/ssh-vulnkey.1 b/ssh-vulnkey.1
new file mode 100644
index 000000000..9286e73c0
--- /dev/null
+++ b/ssh-vulnkey.1
@@ -0,0 +1,151 @@
1.\" Copyright (c) 2008 Canonical Ltd. All rights reserved.
2.\"
3.\" Redistribution and use in source and binary forms, with or without
4.\" modification, are permitted provided that the following conditions
5.\" are met:
6.\" 1. Redistributions of source code must retain the above copyright
7.\" notice, this list of conditions and the following disclaimer.
8.\" 2. Redistributions in binary form must reproduce the above copyright
9.\" notice, this list of conditions and the following disclaimer in the
10.\" documentation and/or other materials provided with the distribution.
11.\"
12.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
13.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
18.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22.\"
23.Dd $Mdocdate: May 12 2008 $
24.Dt SSH-VULNKEY 1
25.Os
26.Sh NAME
27.Nm ssh-vulnkey
28.Nd check blacklist of compromised keys
29.Sh SYNOPSIS
30.Nm
31.Op Fl q
32.Ar file ...
33.Nm
34.Fl a
35.Sh DESCRIPTION
36.Nm
37checks a key against a blacklist of compromised keys.
38.Pp
39A substantial number of keys are known to have been generated using a broken
40version of OpenSSL distributed by Debian which failed to seed its random
41number generator correctly.
42Keys generated using these OpenSSL versions should be assumed to be
43compromised.
44This tool may be useful in checking for such keys.
45.Pp
46Keys that are compromised cannot be repaired; replacements must be generated
47using
48.Xr ssh-keygen 1 .
49Make sure to update
50.Pa authorized_keys
51files on all systems where compromised keys were permitted to authenticate.
52.Pp
53The argument list will be interpreted as a list of paths to public key files
54or
55.Pa authorized_keys
56files.
57If no suitable file is found at a given path,
58.Nm
59will append
60.Pa .pub
61and retry, in case it was given a private key file.
62If no files are given as arguments,
63.Nm
64will check
65.Pa ~/.ssh/id_rsa ,
66.Pa ~/.ssh/id_dsa ,
67.Pa ~/.ssh/identity ,
68.Pa ~/.ssh/authorized_keys
69and
70.Pa ~/.ssh/authorized_keys2 ,
71as well as the system's host keys if readable.
72.Pp
73If
74.Dq -
75is given as an argument,
76.Nm
77will read from standard input.
78This can be used to process output from
79.Xr ssh-keyscan 1 ,
80for example:
81.Pp
82.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey -
83.Pp
84.Nm
85will exit zero if any of the given keys were in the compromised list,
86otherwise non-zero.
87.Pp
88Unless the
89.Cm PermitBlacklistedKeys
90option is used,
91.Xr sshd 8
92will reject attempts to authenticate with keys in the compromised list.
93.Pp
94The options are as follows:
95.Bl -tag -width Ds
96.It Fl a
97Check keys of all users on the system.
98You will typically need to run
99.Nm
100as root to use this option.
101For each user,
102.Nm
103will check
104.Pa ~/.ssh/id_rsa ,
105.Pa ~/.ssh/id_dsa ,
106.Pa ~/.ssh/identity ,
107.Pa ~/.ssh/authorized_keys
108and
109.Pa ~/.ssh/authorized_keys2 .
110It will also check the system's host keys.
111.It Fl q
112Quiet mode.
113Normally,
114.Nm
115outputs the fingerprint of each key scanned, with a description of its
116status.
117This option suppresses that output.
118.El
119.Sh BLACKLIST FILE FORMAT
120The blacklist file may start with comments, on lines starting with
121.Dq # .
122After these initial comments, it must follow a strict format:
123.Pp
124.Bl -bullet -offset indent -compact
125.It
126All the lines must be exactly the same length (20 characters followed by a
127newline) and must be in sorted order.
128.It
129Each line must consist of the lower-case hexadecimal MD5 key fingerprint,
130without colons, and with the first 12 characters removed (that is, the least
131significant 80 bits of the fingerprint).
132.El
133.Pp
134The key fingerprint may be generated using
135.Xr ssh-keygen 1 :
136.Pp
137.Dl $ ssh-keygen -l -f /path/to/key
138.Pp
139This strict format is necessary to allow the blacklist file to be checked
140quickly, using a binary-search algorithm.
141.Sh SEE ALSO
142.Xr ssh-keygen 1 ,
143.Xr sshd 8
144.Sh AUTHORS
145.An -nosplit
146.An Colin Watson Aq cjwatson@ubuntu.com
147.Pp
148Florian Weimer suggested the option to check keys of all users, and the idea
149of processing
150.Xr ssh-keyscan 1
151output.
diff --git a/ssh-vulnkey.c b/ssh-vulnkey.c
new file mode 100644
index 000000000..ba87cbd28
--- /dev/null
+++ b/ssh-vulnkey.c
@@ -0,0 +1,311 @@
1/*
2 * Copyright (c) 2008 Canonical Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
27#include <sys/types.h>
28#include <sys/stat.h>
29
30#include <string.h>
31#include <stdio.h>
32#include <fcntl.h>
33#include <unistd.h>
34
35#include <openssl/evp.h>
36
37#include "xmalloc.h"
38#include "ssh.h"
39#include "log.h"
40#include "key.h"
41#include "authfile.h"
42#include "pathnames.h"
43#include "misc.h"
44
45extern char *__progname;
46
47/* Default files to check */
48static char *default_host_files[] = {
49 _PATH_HOST_RSA_KEY_FILE,
50 _PATH_HOST_DSA_KEY_FILE,
51 _PATH_HOST_KEY_FILE,
52 NULL
53};
54static char *default_files[] = {
55 _PATH_SSH_CLIENT_ID_RSA,
56 _PATH_SSH_CLIENT_ID_DSA,
57 _PATH_SSH_CLIENT_IDENTITY,
58 _PATH_SSH_USER_PERMITTED_KEYS,
59 _PATH_SSH_USER_PERMITTED_KEYS2,
60 NULL
61};
62
63static int quiet = 0;
64
65static void
66usage(void)
67{
68 fprintf(stderr, "usage: %s [-aq] [file ...]\n", __progname);
69 fprintf(stderr, "Options:\n");
70 fprintf(stderr, " -a Check keys of all users.\n");
71 fprintf(stderr, " -q Quiet mode.\n");
72 exit(1);
73}
74
75void
76describe_key(const char *msg, const Key *key, const char *comment)
77{
78 char *fp;
79
80 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
81 if (!quiet)
82 printf("%s: %u %s %s\n", msg, key_size(key), fp, comment);
83 xfree(fp);
84}
85
86int
87do_key(const Key *key, const char *comment)
88{
89 char *blacklist_file;
90 struct stat st;
91 int ret = 1;
92
93 blacklist_file = blacklist_filename(key);
94 if (stat(blacklist_file, &st) < 0)
95 describe_key("Unknown (no blacklist information)",
96 key, comment);
97 else if (blacklisted_key(key)) {
98 describe_key("COMPROMISED", key, comment);
99 ret = 0;
100 } else
101 describe_key("Not blacklisted", key, comment);
102 xfree(blacklist_file);
103
104 return ret;
105}
106
107int
108do_filename(const char *filename, int quiet_open)
109{
110 FILE *f;
111 char line[SSH_MAX_PUBKEY_BYTES];
112 char *cp;
113 u_long linenum = 0;
114 Key *key;
115 char *comment = NULL;
116 int found = 0, ret = 1;
117
118 /* Copy much of key_load_public's logic here so that we can read
119 * several keys from a single file (e.g. authorized_keys).
120 */
121
122 if (strcmp(filename, "-") != 0) {
123 f = fopen(filename, "r");
124 if (!f) {
125 char pubfile[MAXPATHLEN];
126 if (strlcpy(pubfile, filename, sizeof pubfile) <
127 sizeof(pubfile) &&
128 strlcat(pubfile, ".pub", sizeof pubfile) <
129 sizeof(pubfile))
130 f = fopen(pubfile, "r");
131 }
132 if (!f) {
133 if (!quiet_open)
134 perror(filename);
135 return -1;
136 }
137 } else
138 f = stdin;
139 while (read_keyfile_line(f, filename, line, sizeof(line),
140 &linenum) != -1) {
141 cp = line;
142 switch (*cp) {
143 case '#':
144 case '\n':
145 case '\0':
146 continue;
147 }
148 /* Skip leading whitespace. */
149 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
150 ;
151 /* Cope with ssh-keyscan output. */
152 comment = NULL;
153 if (*cp) {
154 char *space;
155 int type;
156
157 space = strchr(cp, ' ');
158 if (!space)
159 continue;
160 *space = '\0';
161 type = key_type_from_name(cp);
162 if (type == KEY_UNSPEC) {
163 comment = xstrdup(cp);
164 cp = space + 1;
165 }
166 *space = ' ';
167 }
168 if (!comment)
169 comment = xstrdup(filename);
170 if (*cp) {
171 key = key_new(KEY_RSA1);
172 if (key_read(key, &cp) == 1) {
173 if (!do_key(key, comment))
174 ret = 0;
175 key_free(key);
176 found = 1;
177 } else {
178 key_free(key);
179 key = key_new(KEY_UNSPEC);
180 if (key_read(key, &cp) == 1) {
181 if (!do_key(key, comment))
182 ret = 0;
183 key_free(key);
184 found = 1;
185 }
186 }
187 }
188 xfree(comment);
189 comment = NULL;
190 }
191 if (f != stdin)
192 fclose(f);
193
194 if (!found && filename) {
195 key = key_load_public(filename, &comment);
196 if (key) {
197 if (!do_key(key, comment))
198 ret = 0;
199 found = 1;
200 }
201 if (comment)
202 xfree(comment);
203 }
204
205 return ret;
206}
207
208int
209do_host(void)
210{
211 int i;
212 struct stat st;
213 int ret = 1;
214
215 for (i = 0; default_host_files[i]; i++) {
216 if (stat(default_host_files[i], &st) < 0)
217 continue;
218 if (!do_filename(default_host_files[i], 1))
219 ret = 0;
220 }
221
222 return ret;
223}
224
225int
226do_user(const char *dir)
227{
228 int i;
229 char buf[MAXPATHLEN];
230 struct stat st;
231 int ret = 1;
232
233 for (i = 0; default_files[i]; i++) {
234 snprintf(buf, sizeof(buf), "%s/%s", dir, default_files[i]);
235 if (stat(buf, &st) < 0)
236 continue;
237 if (!do_filename(buf, 0))
238 ret = 0;
239 }
240
241 return ret;
242}
243
244int
245main(int argc, char **argv)
246{
247 int opt, all_users = 0;
248 int ret = 1;
249 extern int optind;
250
251 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
252 sanitise_stdfd();
253
254 __progname = ssh_get_progname(argv[0]);
255
256 SSLeay_add_all_algorithms();
257 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
258
259 /* We don't need the RNG ourselves, but symbol references here allow
260 * ld to link us properly.
261 */
262 init_rng();
263 seed_rng();
264
265 while ((opt = getopt(argc, argv, "ahq")) != -1) {
266 switch (opt) {
267 case 'a':
268 all_users = 1;
269 break;
270 case 'q':
271 quiet = 1;
272 break;
273 case 'h':
274 default:
275 usage();
276 }
277 }
278
279 if (all_users) {
280 struct passwd *pw;
281
282 if (!do_host())
283 ret = 0;
284
285 while ((pw = getpwent()) != NULL) {
286 if (pw->pw_dir) {
287 if (!do_user(pw->pw_dir))
288 ret = 0;
289 }
290 }
291 } else if (optind == argc) {
292 struct passwd *pw;
293
294 if (!do_host())
295 ret = 0;
296
297 if ((pw = getpwuid(getuid())) == NULL)
298 fprintf(stderr, "No user found with uid %u\n",
299 (u_int)getuid());
300 else {
301 if (!do_user(pw->pw_dir))
302 ret = 0;
303 }
304 } else {
305 while (optind < argc)
306 if (!do_filename(argv[optind++], 0))
307 ret = 0;
308 }
309
310 return ret;
311}
diff --git a/sshd.c b/sshd.c
index add61cc5f..2d428967c 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1466,6 +1466,21 @@ main(int ac, char **av)
1466 1466
1467 for (i = 0; i < options.num_host_key_files; i++) { 1467 for (i = 0; i < options.num_host_key_files; i++) {
1468 key = key_load_private(options.host_key_files[i], "", NULL); 1468 key = key_load_private(options.host_key_files[i], "", NULL);
1469 if (key && blacklisted_key(key)) {
1470 char *fp;
1471 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
1472 if (options.permit_blacklisted_keys)
1473 error("Host key %s blacklisted (see "
1474 "ssh-vulnkey(1)); continuing anyway", fp);
1475 else
1476 error("Host key %s blacklisted (see "
1477 "ssh-vulnkey(1))", fp);
1478 xfree(fp);
1479 if (!options.permit_blacklisted_keys) {
1480 sensitive_data.host_keys[i] = NULL;
1481 continue;
1482 }
1483 }
1469 sensitive_data.host_keys[i] = key; 1484 sensitive_data.host_keys[i] = key;
1470 if (key == NULL) { 1485 if (key == NULL) {
1471 error("Could not load host key: %s", 1486 error("Could not load host key: %s",
diff --git a/sshd_config.5 b/sshd_config.5
index a7a7227b2..dab26e079 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -615,6 +615,20 @@ are refused if the number of unauthenticated connections reaches
615Specifies whether password authentication is allowed. 615Specifies whether password authentication is allowed.
616The default is 616The default is
617.Dq yes . 617.Dq yes .
618.It Cm PermitBlacklistedKeys
619Specifies whether
620.Xr sshd 8
621should allow keys recorded in its blacklist of known-compromised keys (see
622.Xr ssh-vulnkey 1 ) .
623If
624.Dq yes ,
625then attempts to authenticate with compromised keys will be logged but
626accepted.
627If
628.Dq no ,
629then attempts to authenticate with compromised keys will be rejected.
630The default is
631.Dq no .
618.It Cm PermitEmptyPasswords 632.It Cm PermitEmptyPasswords
619When password authentication is allowed, it specifies whether the 633When password authentication is allowed, it specifies whether the
620server allows login to accounts with empty password strings. 634server allows login to accounts with empty password strings.