]> git.pld-linux.org Git - packages/openssh.git/blob - openssh-blacklist.diff
- fix ssh-ldap-helper path
[packages/openssh.git] / openssh-blacklist.diff
1 This patch is against OpenSSH 4.7p1, although should apply to other versions
2 without too much difficulty. It makes the following changes:
3
4   * Add key blacklisting support. Keys listed in
5     /etc/ssh/blacklist.TYPE-LENGTH will be rejected for authentication by
6     sshd, unless "PermitBlacklistedKeys yes" is set in /etc/ssh/sshd_config.
7
8   * Add a new program, ssh-vulnkey, which can be used to check keys against
9     these blacklists.
10
11 This patch is up to date with respect to Debian openssh 1:4.7p1-10.
12
13 --- openssh-4.7p1.orig/sshd_config.5
14 +++ openssh-4.7p1/sshd_config.5
15 @@ -615,6 +615,20 @@
16  Specifies whether password authentication is allowed.
17  The default is
18  .Dq yes .
19 +.It Cm PermitBlacklistedKeys
20 +Specifies whether
21 +.Xr sshd 8
22 +should allow keys recorded in its blacklist of known-compromised keys (see
23 +.Xr ssh-vulnkey 1 ) .
24 +If
25 +.Dq yes ,
26 +then attempts to authenticate with compromised keys will be logged but
27 +accepted.
28 +If
29 +.Dq no ,
30 +then attempts to authenticate with compromised keys will be rejected.
31 +The default is
32 +.Dq no .
33  .It Cm PermitEmptyPasswords
34  When password authentication is allowed, it specifies whether the
35  server allows login to accounts with empty password strings.
36 --- openssh-4.7p1.orig/sshd.c
37 +++ openssh-4.7p1/sshd.c
38 @@ -1466,6 +1466,21 @@
39  
40         for (i = 0; i < options.num_host_key_files; i++) {
41                 key = key_load_private(options.host_key_files[i], "", NULL);
42 +               if (key && blacklisted_key(key)) {
43 +                       char *fp;
44 +                       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
45 +                       if (options.permit_blacklisted_keys)
46 +                               error("Host key %s blacklisted (see "
47 +                                   "ssh-vulnkey(1)); continuing anyway", fp);
48 +                       else
49 +                               error("Host key %s blacklisted (see "
50 +                                   "ssh-vulnkey(1))", fp);
51 +                       xfree(fp);
52 +                       if (!options.permit_blacklisted_keys) {
53 +                               sensitive_data.host_keys[i] = NULL;
54 +                               continue;
55 +                       }
56 +               }
57                 sensitive_data.host_keys[i] = key;
58                 if (key == NULL) {
59                         error("Could not load host key: %s",
60 --- openssh-4.7p1.orig/servconf.c
61 +++ openssh-4.7p1/servconf.c
62 @@ -96,6 +96,7 @@
63         options->password_authentication = -1;
64         options->kbd_interactive_authentication = -1;
65         options->challenge_response_authentication = -1;
66 +       options->permit_blacklisted_keys = -1;
67         options->permit_empty_passwd = -1;
68         options->permit_user_env = -1;
69         options->use_login = -1;
70 @@ -218,6 +219,8 @@
71                 options->kbd_interactive_authentication = 0;
72         if (options->challenge_response_authentication == -1)
73                 options->challenge_response_authentication = 1;
74 +       if (options->permit_blacklisted_keys == -1)
75 +               options->permit_blacklisted_keys = 0;
76         if (options->permit_empty_passwd == -1)
77                 options->permit_empty_passwd = 0;
78         if (options->permit_user_env == -1)
79 @@ -287,7 +290,7 @@
80         sListenAddress, sAddressFamily,
81         sPrintMotd, sPrintLastLog, sIgnoreRhosts,
82         sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
83 -       sStrictModes, sEmptyPasswd, sTCPKeepAlive,
84 +       sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
85         sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
86         sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
87         sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
88 @@ -387,6 +390,7 @@
89         { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
90         { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
91         { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
92 +       { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
93         { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
94         { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
95         { "uselogin", sUseLogin, SSHCFG_GLOBAL },
96 @@ -943,6 +947,10 @@
97                 intptr = &options->tcp_keep_alive;
98                 goto parse_flag;
99  
100 +       case sPermitBlacklistedKeys:
101 +               intptr = &options->permit_blacklisted_keys;
102 +               goto parse_flag;
103 +
104         case sEmptyPasswd:
105                 intptr = &options->permit_empty_passwd;
106                 goto parse_flag;
107 --- openssh-4.7p1.orig/servconf.h
108 +++ openssh-4.7p1/servconf.h
109 @@ -94,6 +94,7 @@
110                                                  * authentication. /
111         int     kbd_interactive_authentication; /* If true, permit */
112         int     challenge_response_authentication;
113 +       int     permit_blacklisted_keys;        /* If true, permit */
114         int     zero_knowledge_password_authentication;
115                                         /* If true, permit jpake auth */
116         int     permit_empty_passwd;    /* If false, do not permit empty
117 --- openssh-4.7p1.orig/Makefile.in
118 +++ openssh-4.7p1/Makefile.in
119 @@ -62,7 +62,7 @@
120  INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
121  INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
122  
123 -TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT)
124 +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-vulnkey$(EXEEXT)
125  
126  LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
127         canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
128 @@ -93,8 +93,8 @@
129         audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
130         roaming_common.o roaming_serv.o ldapauth.o
131  
132 -MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out
133 -MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5
134 +MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out ssh-vulnkey.1.out
135 +MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 ssh-vulnkey.1
136  MANTYPE                = @MANTYPE@
137  
138  CONFIGFILES=sshd_config.out ssh_config.out moduli.out
139 @@ -165,6 +165,9 @@
140  ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
141         $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
142  
143 +ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
144 +       $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
145 +
146  # test driver for the loginrec code - not built by default
147  logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
148         $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
149 @@ -271,6 +271,7 @@
150         $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
151         $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
152         $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
153 +       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
154         $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
155         $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
156         $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
157 @@ -289,6 +289,7 @@
158         $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
159         $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
160         $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
161 +       $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
162         $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
163         -rm -f $(DESTDIR)$(bindir)/slogin
164         ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
165 @@ -361,6 +366,7 @@
166         -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
167         -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
168         -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
169 +       -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
170         -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
171         -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
172         -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
173 @@ -373,6 +379,7 @@
174         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
175         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
176         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
177 +       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
178         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
179         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8
180         -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
181 --- openssh-4.7p1.orig/auth-rh-rsa.c
182 +++ openssh-4.7p1/auth-rh-rsa.c
183 @@ -20,6 +20,7 @@
184  #include <pwd.h>
185  #include <stdarg.h>
186  
187 +#include "xmalloc.h"
188  #include "packet.h"
189  #include "uidswap.h"
190  #include "log.h"
191 @@ -27,6 +28,7 @@
192  #include "servconf.h"
193  #include "key.h"
194  #include "hostfile.h"
195 +#include "authfile.h"
196  #include "pathnames.h"
197  #include "auth.h"
198  #include "canohost.h"
199 @@ -42,8 +44,22 @@
200  auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
201      Key *client_host_key)
202  {
203 +       char *fp;
204         HostStatus host_status;
205  
206 +       if (blacklisted_key(client_host_key)) {
207 +               fp = key_fingerprint(client_host_key, SSH_FP_MD5, SSH_FP_HEX);
208 +               if (options.permit_blacklisted_keys)
209 +                       logit("Public key %s blacklisted (see "
210 +                           "ssh-vulnkey(1)); continuing anyway", fp);
211 +               else
212 +                       logit("Public key %s blacklisted (see "
213 +                           "ssh-vulnkey(1))", fp);
214 +               xfree(fp);
215 +               if (!options.permit_blacklisted_keys)
216 +                       return 0;
217 +       }
218 +
219         if (auth_key_is_revoked(client_host_key))
220                 return 0;
221  
222 --- openssh-4.7p1.orig/authfile.h
223 +++ openssh-4.7p1/authfile.h
224 @@ -23,4 +23,7 @@
225  Key    *key_load_private_pem(int, int, const char *, char **);
226  int     key_perm_ok(int, const char *);
227  
228 +char   *blacklist_filename(const Key *key);
229 +int     blacklisted_key(const Key *key);
230 +
231  #endif
232 --- openssh-4.7p1.orig/ssh-vulnkey.1
233 +++ openssh-4.7p1/ssh-vulnkey.1
234 @@ -0,0 +1,187 @@
235 +.\" Copyright (c) 2008 Canonical Ltd.  All rights reserved.
236 +.\"
237 +.\" Redistribution and use in source and binary forms, with or without
238 +.\" modification, are permitted provided that the following conditions
239 +.\" are met:
240 +.\" 1. Redistributions of source code must retain the above copyright
241 +.\"    notice, this list of conditions and the following disclaimer.
242 +.\" 2. Redistributions in binary form must reproduce the above copyright
243 +.\"    notice, this list of conditions and the following disclaimer in the
244 +.\"    documentation and/or other materials provided with the distribution.
245 +.\"
246 +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
247 +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
248 +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
249 +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
250 +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
251 +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252 +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
253 +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254 +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
255 +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
256 +.\"
257 +.Dd $Mdocdate: May 12 2008 $
258 +.Dt SSH-VULNKEY 1
259 +.Os
260 +.Sh NAME
261 +.Nm ssh-vulnkey
262 +.Nd check blacklist of compromised keys
263 +.Sh SYNOPSIS
264 +.Nm
265 +.Op Fl q
266 +.Ar file ...
267 +.Nm
268 +.Fl a
269 +.Sh DESCRIPTION
270 +.Nm
271 +checks a key against a blacklist of compromised keys.
272 +.Pp
273 +A substantial number of keys are known to have been generated using a broken
274 +version of OpenSSL distributed by Debian which failed to seed its random
275 +number generator correctly.
276 +Keys generated using these OpenSSL versions should be assumed to be
277 +compromised.
278 +This tool may be useful in checking for such keys.
279 +.Pp
280 +Keys that are compromised cannot be repaired; replacements must be generated
281 +using
282 +.Xr ssh-keygen 1 .
283 +Make sure to update
284 +.Pa authorized_keys
285 +files on all systems where compromised keys were permitted to authenticate.
286 +.Pp
287 +The argument list will be interpreted as a list of paths to public key files
288 +or
289 +.Pa authorized_keys
290 +files.
291 +If no suitable file is found at a given path,
292 +.Nm
293 +will append
294 +.Pa .pub
295 +and retry, in case it was given a private key file.
296 +If no files are given as arguments,
297 +.Nm
298 +will check
299 +.Pa ~/.ssh/id_rsa ,
300 +.Pa ~/.ssh/id_dsa ,
301 +.Pa ~/.ssh/identity ,
302 +.Pa ~/.ssh/authorized_keys
303 +and
304 +.Pa ~/.ssh/authorized_keys2 ,
305 +as well as the system's host keys if readable.
306 +.Pp
307 +If
308 +.Dq -
309 +is given as an argument,
310 +.Nm
311 +will read from standard input.
312 +This can be used to process output from
313 +.Xr ssh-keyscan 1 ,
314 +for example:
315 +.Pp
316 +.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey -
317 +.Pp
318 +.Nm
319 +will exit zero if any of the given keys were in the compromised list,
320 +otherwise non-zero.
321 +.Pp
322 +Unless the
323 +.Cm PermitBlacklistedKeys
324 +option is used,
325 +.Xr sshd 8
326 +will reject attempts to authenticate with keys in the compromised list.
327 +.Pp
328 +The options are as follows:
329 +.Bl -tag -width Ds
330 +.It Fl a
331 +Check keys of all users on the system.
332 +You will typically need to run
333 +.Nm
334 +as root to use this option.
335 +For each user,
336 +.Nm
337 +will check
338 +.Pa ~/.ssh/id_rsa ,
339 +.Pa ~/.ssh/id_dsa ,
340 +.Pa ~/.ssh/identity ,
341 +.Pa ~/.ssh/authorized_keys
342 +and
343 +.Pa ~/.ssh/authorized_keys2 .
344 +It will also check the system's host keys.
345 +.It Fl q
346 +Quiet mode.
347 +Normally,
348 +.Nm
349 +outputs the fingerprint of each key scanned, with a description of its
350 +status.
351 +This option suppresses that output.
352 +.El
353 +.Sh BLACKLIST FILE FORMAT
354 +The blacklist file may start with comments, on lines starting with
355 +.Dq # .
356 +After these initial comments, it must follow a strict format:
357 +.Pp
358 +.Bl -bullet -offset indent -compact
359 +.It
360 +All the lines must be exactly the same length (20 characters followed by a
361 +newline) and must be in sorted order.
362 +.It
363 +Each line must consist of the lower-case hexadecimal MD5 key fingerprint,
364 +without colons, and with the first 12 characters removed (that is, the least
365 +significant 80 bits of the fingerprint).
366 +.El
367 +.Pp
368 +The key fingerprint may be generated using
369 +.Xr ssh-keygen 1 :
370 +.Pp
371 +.Dl $ ssh-keygen -l -f /path/to/key
372 +.Pp
373 +This strict format is necessary to allow the blacklist file to be checked
374 +quickly, using a binary-search algorithm.
375 +.Sh FILES
376 +.Bl -tag -width Ds
377 +.It Pa ~/.ssh/id_rsa
378 +If present, contains the protocol version 2 RSA authentication identity of
379 +the user.
380 +.It Pa ~/.ssh/id_dsa
381 +If present, contains the protocol version 2 DSA authentication identity of
382 +the user.
383 +.It Pa ~/.ssh/identity
384 +If present, contains the protocol version 1 RSA authentication identity of
385 +the user.
386 +.It Pa ~/.ssh/authorized_keys
387 +If present, lists the public keys (RSA/DSA) that can be used for logging in
388 +as this user.
389 +.It Pa ~/.ssh/authorized_keys2
390 +Obsolete name for
391 +.Pa ~/.ssh/authorized_keys .
392 +This file may still be present on some old systems, but should not be
393 +created if it is missing.
394 +.It Pa /etc/ssh/ssh_host_rsa_key
395 +If present, contains the protocol version 2 RSA identity of the system.
396 +.It Pa /etc/ssh/ssh_host_dsa_key
397 +If present, contains the protocol version 2 DSA identity of the system.
398 +.It Pa /etc/ssh/ssh_host_key
399 +If present, contains the protocol version 1 RSA identity of the system.
400 +.It Pa /etc/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH
401 +If present, lists the blacklisted keys of type
402 +.Ar TYPE
403 +.Pf ( Dq RSA1 ,
404 +.Dq RSA ,
405 +or
406 +.Dq DSA )
407 +and bit length
408 +.Ar LENGTH .
409 +The format of this file is described above.
410 +.El
411 +.Sh SEE ALSO
412 +.Xr ssh-keygen 1 ,
413 +.Xr sshd 8
414 +.Sh AUTHORS
415 +.An -nosplit
416 +.An Colin Watson Aq cjwatson@ubuntu.com
417 +.Pp
418 +Florian Weimer suggested the option to check keys of all users, and the idea
419 +of processing
420 +.Xr ssh-keyscan 1
421 +output.
422 --- openssh-5.6p1/auth2-hostbased.c~    2010-08-24 14:10:03.000000000 +0300
423 +++ openssh-5.6p1/auth2-hostbased.c     2010-08-24 14:12:10.632553591 +0300
424 @@ -40,6 +40,7 @@
425  #include "compat.h"
426  #include "key.h"
427  #include "hostfile.h"
428 +#include "authfile.h"
429  #include "auth.h"
430  #include "canohost.h"
431  #ifdef GSSAPI
432 @@ -147,6 +147,19 @@
433         int len;
434         char *fp;
435  
436 +       if (blacklisted_key(key)) {
437 +               fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
438 +               if (options.permit_blacklisted_keys)
439 +                       logit("Public key %s blacklisted (see "
440 +                           "ssh-vulnkey(1)); continuing anyway", fp);
441 +               else
442 +                       logit("Public key %s blacklisted (see "
443 +                           "ssh-vulnkey(1))", fp);
444 +               xfree(fp);
445 +               if (!options.permit_blacklisted_keys)
446 +                       return 0;
447 +       }
448 +
449         if (auth_key_is_revoked(key))
450                 return 0;
451  
452 --- openssh-4.7p1.orig/authfile.c
453 +++ openssh-4.7p1/authfile.c
454 @@ -65,6 +65,7 @@
455  #include "rsa.h"
456  #include "misc.h"
457  #include "atomicio.h"
458 +#include "pathnames.h"
459  
460  /* Version identification string for SSH v1 identity files. */
461  static const char authfile_id_string[] =
462 @@ -677,3 +678,113 @@
463         return ret;
464  }
465  
466 +
467 +char *
468 +blacklist_filename(const Key *key)
469 +{
470 +       char *name;
471 +
472 +       xasprintf(&name, "%s.%s-%u",
473 +           _PATH_BLACKLIST, key_type(key), key_size(key));
474 +       return name;
475 +}
476 +
477 +/* Scan a blacklist of known-vulnerable keys. */
478 +int
479 +blacklisted_key(const Key *key)
480 +{
481 +       char *blacklist_file;
482 +       int fd = -1;
483 +       char *dgst_hex = NULL;
484 +       char *dgst_packed = NULL, *p;
485 +       int i;
486 +       size_t line_len;
487 +       struct stat st;
488 +       char buf[256];
489 +       off_t start, lower, upper;
490 +       int ret = 0;
491 +
492 +       blacklist_file = blacklist_filename(key);
493 +       debug("Checking blacklist file %s", blacklist_file);
494 +       fd = open(blacklist_file, O_RDONLY);
495 +       if (fd < 0)
496 +               goto out;
497 +
498 +       dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
499 +       /* Remove all colons */
500 +       dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
501 +       for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
502 +               if (dgst_hex[i] != ':')
503 +                       *p++ = dgst_hex[i];
504 +       /* Only compare least-significant 80 bits (to keep the blacklist
505 +        * size down)
506 +        */
507 +       line_len = strlen(dgst_packed + 12);
508 +       if (line_len > 32)
509 +               goto out;
510 +
511 +       /* Skip leading comments */
512 +       start = 0;
513 +       for (;;) {
514 +               ssize_t r;
515 +               char *newline;
516 +
517 +               r = atomicio(read, fd, buf, 256);
518 +               if (r <= 0)
519 +                       goto out;
520 +               if (buf[0] != '#')
521 +                       break;
522 +
523 +               newline = memchr(buf, '\n', 256);
524 +               if (!newline)
525 +                       goto out;
526 +               start += newline + 1 - buf;
527 +               if (lseek(fd, start, SEEK_SET) < 0)
528 +                       goto out;
529 +       }
530 +
531 +       /* Initialise binary search record numbers */
532 +       if (fstat(fd, &st) < 0)
533 +               goto out;
534 +       lower = 0;
535 +       upper = (st.st_size - start) / (line_len + 1);
536 +
537 +       while (lower != upper) {
538 +               off_t cur;
539 +               char buf[32];
540 +               int cmp;
541 +
542 +               cur = lower + (upper - lower) / 2;
543 +
544 +               /* Read this line and compare to digest; this is
545 +                * overflow-safe since cur < max(off_t) / (line_len + 1) */
546 +               if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
547 +                       break;
548 +               if (atomicio(read, fd, buf, line_len) != line_len)
549 +                       break;
550 +               cmp = memcmp(buf, dgst_packed + 12, line_len);
551 +               if (cmp < 0) {
552 +                       if (cur == lower)
553 +                               break;
554 +                       lower = cur;
555 +               } else if (cmp > 0) {
556 +                       if (cur == upper)
557 +                               break;
558 +                       upper = cur;
559 +               } else {
560 +                       debug("Found %s in blacklist", dgst_hex);
561 +                       ret = 1;
562 +                       break;
563 +               }
564 +       }
565 +
566 +out:
567 +       if (dgst_packed)
568 +               xfree(dgst_packed);
569 +       if (dgst_hex)
570 +               xfree(dgst_hex);
571 +       if (fd >= 0)
572 +               close(fd);
573 +       xfree(blacklist_file);
574 +       return ret;
575 +}
576 --- openssh-4.7p1.orig/ssh-vulnkey.c
577 +++ openssh-4.7p1/ssh-vulnkey.c
578 @@ -0,0 +1,325 @@
579 +/*
580 + * Copyright (c) 2008 Canonical Ltd.  All rights reserved.
581 + *
582 + * Redistribution and use in source and binary forms, with or without
583 + * modification, are permitted provided that the following conditions
584 + * are met:
585 + * 1. Redistributions of source code must retain the above copyright
586 + *    notice, this list of conditions and the following disclaimer.
587 + * 2. Redistributions in binary form must reproduce the above copyright
588 + *    notice, this list of conditions and the following disclaimer in the
589 + *    documentation and/or other materials provided with the distribution.
590 + *
591 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
592 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
593 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
594 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
595 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
596 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
597 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
598 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
599 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
600 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
601 + */
602 +
603 +#include "includes.h"
604 +
605 +#include <sys/types.h>
606 +#include <sys/stat.h>
607 +
608 +#include <string.h>
609 +#include <stdio.h>
610 +#include <fcntl.h>
611 +#include <unistd.h>
612 +
613 +#include <openssl/evp.h>
614 +
615 +#include "xmalloc.h"
616 +#include "ssh.h"
617 +#include "log.h"
618 +#include "key.h"
619 +#include "authfile.h"
620 +#include "pathnames.h"
621 +#include "misc.h"
622 +
623 +extern char *__progname;
624 +
625 +/* Default files to check */
626 +static char *default_host_files[] = {
627 +       _PATH_HOST_RSA_KEY_FILE,
628 +       _PATH_HOST_DSA_KEY_FILE,
629 +       _PATH_HOST_KEY_FILE,
630 +       NULL
631 +};
632 +static char *default_files[] = {
633 +       _PATH_SSH_CLIENT_ID_RSA,
634 +       _PATH_SSH_CLIENT_ID_DSA,
635 +       _PATH_SSH_CLIENT_IDENTITY,
636 +       _PATH_SSH_USER_PERMITTED_KEYS,
637 +       _PATH_SSH_USER_PERMITTED_KEYS2,
638 +       NULL
639 +};
640 +
641 +static int quiet = 0;
642 +
643 +static void
644 +usage(void)
645 +{
646 +       fprintf(stderr, "usage: %s [-aq] [file ...]\n", __progname);
647 +       fprintf(stderr, "Options:\n");
648 +       fprintf(stderr, "  -a          Check keys of all users.\n");
649 +       fprintf(stderr, "  -q          Quiet mode.\n");
650 +       exit(1);
651 +}
652 +
653 +void
654 +describe_key(const char *msg, const Key *key, const char *comment)
655 +{
656 +       char *fp;
657 +
658 +       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
659 +       if (!quiet)
660 +               printf("%s: %u %s %s\n", msg, key_size(key), fp, comment);
661 +       xfree(fp);
662 +}
663 +
664 +int
665 +do_key(const Key *key, const char *comment)
666 +{
667 +       char *blacklist_file;
668 +       struct stat st;
669 +       int ret = 1;
670 +
671 +       blacklist_file = blacklist_filename(key);
672 +       if (stat(blacklist_file, &st) < 0)
673 +               describe_key("Unknown (no blacklist information)",
674 +                   key, comment);
675 +       else if (blacklisted_key(key)) {
676 +               describe_key("COMPROMISED", key, comment);
677 +               ret = 0;
678 +       } else
679 +               describe_key("Not blacklisted", key, comment);
680 +       xfree(blacklist_file);
681 +
682 +       return ret;
683 +}
684 +
685 +int
686 +do_filename(const char *filename, int quiet_open)
687 +{
688 +       FILE *f;
689 +       char line[SSH_MAX_PUBKEY_BYTES];
690 +       char *cp;
691 +       u_long linenum = 0;
692 +       Key *key;
693 +       char *comment = NULL;
694 +       int found = 0, ret = 1;
695 +
696 +       /* Copy much of key_load_public's logic here so that we can read
697 +        * several keys from a single file (e.g. authorized_keys).
698 +        */
699 +
700 +       if (strcmp(filename, "-") != 0) {
701 +               f = fopen(filename, "r");
702 +               if (!f) {
703 +                       char pubfile[MAXPATHLEN];
704 +                       if (strlcpy(pubfile, filename, sizeof pubfile) <
705 +                           sizeof(pubfile) &&
706 +                           strlcat(pubfile, ".pub", sizeof pubfile) <
707 +                           sizeof(pubfile))
708 +                               f = fopen(pubfile, "r");
709 +               }
710 +               if (!f) {
711 +                       if (!quiet_open)
712 +                               perror(filename);
713 +                       return -1;
714 +               }
715 +       } else
716 +               f = stdin;
717 +       while (read_keyfile_line(f, filename, line, sizeof(line),
718 +                   &linenum) != -1) {
719 +               int i;
720 +               char *space;
721 +               int type;
722 +
723 +               /* Chop trailing newline. */
724 +               i = strlen(line) - 1;
725 +               if (line[i] == '\n')
726 +                       line[i] = '\0';
727 +
728 +               /* Skip leading whitespace, empty and comment lines. */
729 +               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
730 +                       ;
731 +               if (!*cp || *cp == '\n' || *cp == '#')
732 +                       continue;
733 +
734 +               /* Cope with ssh-keyscan output and options in
735 +                * authorized_keys files.
736 +                */
737 +               space = strchr(cp, ' ');
738 +               if (!space)
739 +                       continue;
740 +               *space = '\0';
741 +               type = key_type_from_name(cp);
742 +               *space = ' ';
743 +               /* Leading number (RSA1) or valid type (RSA/DSA) indicates
744 +                * that we have no host name or options to skip.
745 +                */
746 +               if (atoi(cp) == 0 && type == KEY_UNSPEC) {
747 +                       int quoted = 0;
748 +
749 +                       for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
750 +                               if (*cp == '\\' && cp[1] == '"')
751 +                                       cp++;   /* Skip both */
752 +                               else if (*cp == '"')
753 +                                       quoted = !quoted;
754 +                       }
755 +                       /* Skip remaining whitespace. */
756 +                       for (; *cp == ' ' || *cp == '\t'; cp++)
757 +                               ;
758 +                       if (!*cp)
759 +                               continue;
760 +               }
761 +
762 +               /* Read and process the key itself. */
763 +               key = key_new(KEY_RSA1);
764 +               if (key_read(key, &cp) == 1) {
765 +                       while (*cp == ' ' || *cp == '\t')
766 +                               cp++;
767 +                       if (!do_key(key, *cp ? cp : filename))
768 +                               ret = 0;
769 +                       found = 1;
770 +               } else {
771 +                       key_free(key);
772 +                       key = key_new(KEY_UNSPEC);
773 +                       if (key_read(key, &cp) == 1) {
774 +                               while (*cp == ' ' || *cp == '\t')
775 +                                       cp++;
776 +                               if (!do_key(key, *cp ? cp : filename))
777 +                                       ret = 0;
778 +                               found = 1;
779 +                       }
780 +               }
781 +               key_free(key);
782 +       }
783 +       if (f != stdin)
784 +               fclose(f);
785 +
786 +       if (!found && filename) {
787 +               key = key_load_public(filename, &comment);
788 +               if (key) {
789 +                       if (!do_key(key, comment))
790 +                               ret = 0;
791 +                       found = 1;
792 +               }
793 +               if (comment)
794 +                       xfree(comment);
795 +       }
796 +
797 +       return ret;
798 +}
799 +
800 +int
801 +do_host(void)
802 +{
803 +       int i;
804 +       struct stat st;
805 +       int ret = 1;
806 +
807 +       for (i = 0; default_host_files[i]; i++) {
808 +               if (stat(default_host_files[i], &st) < 0)
809 +                       continue;
810 +               if (!do_filename(default_host_files[i], 1))
811 +                       ret = 0;
812 +       }
813 +
814 +       return ret;
815 +}
816 +
817 +int
818 +do_user(const char *dir)
819 +{
820 +       int i;
821 +       char buf[MAXPATHLEN];
822 +       struct stat st;
823 +       int ret = 1;
824 +
825 +       for (i = 0; default_files[i]; i++) {
826 +               snprintf(buf, sizeof(buf), "%s/%s", dir, default_files[i]);
827 +               if (stat(buf, &st) < 0)
828 +                       continue;
829 +               if (!do_filename(buf, 0))
830 +                       ret = 0;
831 +       }
832 +
833 +       return ret;
834 +}
835 +
836 +int
837 +main(int argc, char **argv)
838 +{
839 +       int opt, all_users = 0;
840 +       int ret = 1;
841 +       extern int optind;
842 +
843 +       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
844 +       sanitise_stdfd();
845 +
846 +       __progname = ssh_get_progname(argv[0]);
847 +
848 +       SSLeay_add_all_algorithms();
849 +       log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
850 +
851 +       /* We don't need the RNG ourselves, but symbol references here allow
852 +        * ld to link us properly.
853 +        */
854 +       //init_rng();
855 +       //seed_rng();
856 +
857 +       while ((opt = getopt(argc, argv, "ahq")) != -1) {
858 +               switch (opt) {
859 +               case 'a':
860 +                       all_users = 1;
861 +                       break;
862 +               case 'q':
863 +                       quiet = 1;
864 +                       break;
865 +               case 'h':
866 +               default:
867 +                       usage();
868 +               }
869 +       }
870 +
871 +       if (all_users) {
872 +               struct passwd *pw;
873 +
874 +               if (!do_host())
875 +                       ret = 0;
876 +
877 +               while ((pw = getpwent()) != NULL) {
878 +                       if (pw->pw_dir) {
879 +                               if (!do_user(pw->pw_dir))
880 +                                       ret = 0;
881 +                       }
882 +               }
883 +       } else if (optind == argc) {
884 +               struct passwd *pw;
885 +
886 +               if (!do_host())
887 +                       ret = 0;
888 +
889 +               if ((pw = getpwuid(getuid())) == NULL)
890 +                       fprintf(stderr, "No user found with uid %u\n",
891 +                           (u_int)getuid());
892 +               else {
893 +                       if (!do_user(pw->pw_dir))
894 +                               ret = 0;
895 +               }
896 +       } else {
897 +               while (optind < argc)
898 +                       if (!do_filename(argv[optind++], 0))
899 +                               ret = 0;
900 +       }
901 +
902 +       return ret;
903 +}
904 --- openssh-4.7p1.orig/auth-rsa.c
905 +++ openssh-4.7p1/auth-rsa.c
906 @@ -40,6 +40,7 @@
907  #include "servconf.h"
908  #include "key.h"
909  #include "hostfile.h"
910 +#include "authfile.h"
911  #include "auth.h"
912  #ifdef GSSAPI
913  #include "ssh-gss.h"
914 @@ -221,6 +222,7 @@
915                 char *cp;
916                 char *key_options;
917                 int keybits;
918 +               char *fp;
919  
920                 /* Skip leading whitespace, empty and comment lines. */
921                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
922 @@ -265,6 +267,19 @@
923                             "actual %d vs. announced %d.",
924                             file, linenum, BN_num_bits(key->rsa->n), bits);
925  
926 +               if (blacklisted_key(key)) {
927 +                       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
928 +                       if (options.permit_blacklisted_keys)
929 +                               logit("Public key %s blacklisted (see "
930 +                                   "ssh-vulnkey(1)); continuing anyway", fp);
931 +                       else
932 +                               logit("Public key %s blacklisted (see "
933 +                                   "ssh-vulnkey(1))", fp);
934 +                       xfree(fp);
935 +                       if (!options.permit_blacklisted_keys)
936 +                               continue;
937 +               }
938 +
939                 /* We have found the desired key. */
940                 /*
941                  * If our options do not allow this key to be used,
942 --- openssh-4.7p1.orig/pathnames.h
943 +++ openssh-4.7p1/pathnames.h
944 @@ -43,6 +43,8 @@
945  /* Backwards compatibility */
946  #define _PATH_DH_PRIMES                        SSHDIR "/primes"
947  
948 +#define _PATH_BLACKLIST                        SSHDIR "/blacklist"
949 +
950  #ifndef _PATH_SSH_PROGRAM
951  #define _PATH_SSH_PROGRAM              "/usr/bin/ssh"
952  #endif
953 --- openssh-5.9p1/auth2-pubkey.c~       2011-09-29 00:36:17.000000000 +0300
954 +++ openssh-5.9p1/auth2-pubkey.c        2011-09-29 00:37:17.847762648 +0300
955 @@ -42,6 +42,7 @@
956  #include "compat.h"
957  #include "key.h"
958  #include "hostfile.h"
959 +#include "authfile.h"
960  #include "auth.h"
961  #include "pathnames.h"
962  #include "uidswap.h"
963 @@ -596,9 +596,23 @@
964  int
965  user_key_allowed(struct passwd *pw, Key *key)
966  {
967 +       char *fp;
968         u_int success, i;
969         char *file;
970  
971 +       if (blacklisted_key(key)) {
972 +               fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
973 +               if (options.permit_blacklisted_keys)
974 +                       logit("Public key %s blacklisted (see "
975 +                           "ssh-vulnkey(1)); continuing anyway", fp);
976 +               else
977 +                       logit("Public key %s blacklisted (see "
978 +                           "ssh-vulnkey(1))", fp);
979 +               xfree(fp);
980 +               if (!options.permit_blacklisted_keys)
981 +                       return 0;
982 +       }
983 +
984  #ifdef WITH_AUTHORIZED_KEYS_COMMAND
985         success = user_key_via_command_allowed2(pw, key);
986         if (success > 0)
This page took 0.201393 seconds and 3 git commands to generate.