Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

Rev 63 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
60 magnus 1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
## blacklist.dpatch by Magnus Holmgren <holmgren@debian.org>
3
## blacklist.c code copied from OpenSSH's authfile.c and adapted for LSH.
4
##
5
## DP: Check keys against openssh-blacklist before accepting for
6
## DP: pubkey authentication as well as on conversion by lsh-writekey
7
## DP: and lsh-decode-key.
8
 
9
@DPATCH@
10
diff -urNad trunk~/src/Makefile.am trunk/src/Makefile.am
11
--- trunk~/src/Makefile.am      2004-11-18 22:52:16.000000000 +0100
12
+++ trunk/src/Makefile.am       2009-11-06 01:07:40.000000000 +0100
13
@@ -72,7 +72,8 @@
14
        unix_interact.c unix_process.c unix_random.c unix_user.c \
15
        userauth.c \
16
        werror.c write_buffer.c write_packet.c \
17
-       xalloc.c xauth.c zlib.c
18
+       xalloc.c xauth.c zlib.c \
19
+       blacklist.c
20
 
21
 liblsh_a_LIBADD = @LIBOBJS@
22
 
23
diff -urNad trunk~/src/Makefile.in trunk/src/Makefile.in
24
--- trunk~/src/Makefile.in      2009-11-06 01:07:40.000000000 +0100
25
+++ trunk/src/Makefile.in       2009-11-06 01:07:40.000000000 +0100
26
@@ -91,7 +91,8 @@
27
        tty.$(OBJEXT) unix_interact.$(OBJEXT) unix_process.$(OBJEXT) \
28
        unix_random.$(OBJEXT) unix_user.$(OBJEXT) userauth.$(OBJEXT) \
29
        werror.$(OBJEXT) write_buffer.$(OBJEXT) write_packet.$(OBJEXT) \
30
-       xalloc.$(OBJEXT) xauth.$(OBJEXT) zlib.$(OBJEXT)
31
+       xalloc.$(OBJEXT) xauth.$(OBJEXT) zlib.$(OBJEXT) \
32
+       blacklist.$(OBJEXT)
33
 liblsh_a_OBJECTS = $(am_liblsh_a_OBJECTS)
34
 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
35
        "$(DESTDIR)$(bindir)"
36
@@ -510,7 +511,8 @@
37
        unix_interact.c unix_process.c unix_random.c unix_user.c \
38
        userauth.c \
39
        werror.c write_buffer.c write_packet.c \
40
-       xalloc.c xauth.c zlib.c
41
+       xalloc.c xauth.c zlib.c \
42
+       blacklist.c
43
 
44
 liblsh_a_LIBADD = @LIBOBJS@
45
 
46
@@ -705,6 +707,7 @@
47
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/algorithms.Po@am__quote@
48
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alist.Po@am__quote@
49
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoms.Po@am__quote@
50
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blacklist.Po@am__quote@
51
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Po@am__quote@
52
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_commands.Po@am__quote@
53
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_forward.Po@am__quote@
54
diff -urNad trunk~/src/blacklist.c trunk/src/blacklist.c
55
--- trunk~/src/blacklist.c      1970-01-01 01:00:00.000000000 +0100
56
+++ trunk/src/blacklist.c       2009-11-06 01:07:40.000000000 +0100
57
@@ -0,0 +1,164 @@
58
+#if HAVE_CONFIG_H
59
+#include "config.h"
60
+#endif
61
+
62
+#include <assert.h>
63
+
64
+#include "nettle/bignum.h"
65
+#include "nettle/dsa.h"
66
+#include "nettle/rsa.h"
67
+#include "xalloc.h"
68
+#include "atoms.h"
69
+#include "format.h"
70
+#include "lsh_string.h"
71
+#include "abstract_crypto.h"
72
+#include "werror.h"
73
+#include "crypto.h"
74
+#define GABA_DECLARE
75
+#include "rsa.c.x"
76
+#include "dsa.c.x"
77
+
78
+#include <sys/types.h>
79
+#include <sys/stat.h>
80
+#include <unistd.h>
81
+#include <fcntl.h>
82
+#include <string.h>
83
+
84
+/* Scan a blacklist of known-vulnerable keys in blacklist_file. */
85
+static int
86
+blacklisted_key_in_file(struct lsh_string *lsh_hash, struct lsh_string *blacklist_file)
87
+{
88
+  int fd = -1;
89
+  const char *hash = 0;
90
+  int i;
91
+  uint32_t line_len;
92
+  struct stat st;
93
+  char buf[256];
94
+  off_t start, lower, upper;
95
+  int ret = 0;
96
+
97
+  debug("Checking blacklist file %S\n", blacklist_file);
98
+  fd = open(lsh_get_cstring(blacklist_file), O_RDONLY);
99
+  if (fd < 0) {
100
+    ret = -1;
101
+    goto out;
102
+  }
103
+
104
+  hash = lsh_get_cstring(lsh_hash) + 12;
105
+  line_len = strlen(hash);
106
+  if (line_len != 20)
107
+    goto out;
108
+
109
+  /* Skip leading comments */
110
+  start = 0;
111
+  for (;;) {
112
+    ssize_t r;
113
+    char *newline;
114
+
115
+    r = read(fd, buf, sizeof(buf));
116
+    if (r <= 0)
117
+      goto out;
118
+    if (buf[0] != '#')
119
+      break;
120
+
121
+    newline = memchr(buf, '\n', sizeof(buf));
122
+    if (!newline)
123
+      goto out;
124
+    start += newline + 1 - buf;
125
+    if (lseek(fd, start, SEEK_SET) < 0)
126
+      goto out;
127
+  }
128
+
129
+  /* Initialise binary search record numbers */
130
+  if (fstat(fd, &st) < 0)
131
+    goto out;
132
+  lower = 0;
133
+  upper = (st.st_size - start) / (line_len + 1);
134
+
135
+  while (lower != upper) {
136
+    off_t cur;
137
+    int cmp;
138
+
139
+    cur = lower + (upper - lower) / 2;
140
+
141
+    /* Read this line and compare to digest; this is
142
+     * overflow-safe since cur < max(off_t) / (line_len + 1) */
143
+    if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
144
+      break;
145
+    if (read(fd, buf, line_len) != line_len)
146
+      break;
147
+    cmp = memcmp(buf, hash, line_len);
148
+    if (cmp < 0) {
149
+      if (cur == lower)
150
+       break;
151
+      lower = cur;
152
+    } else if (cmp > 0) {
153
+      if (cur == upper)
154
+       break;
155
+      upper = cur;
156
+    } else {
157
+      ret = 1;
158
+      break;
159
+    }
160
+  }
161
+
162
+out:
163
+  if (fd >= 0)
164
+    close(fd);
165
+  return ret;
166
+}
167
+
168
+/*
169
+ * Scan blacklists of known-vulnerable keys. If a vulnerable key is found,
170
+ * its fingerprint is returned in *fp, unless fp is NULL.
171
+ */
172
+int
173
+blacklisted_key(struct verifier *v, int method)
174
+{
175
+    size_t keysize;
176
+    const char *keytype;
177
+    int ret = -1;
178
+    const char *paths[] = { "/usr/share/ssh/blacklist", "/etc/ssh/blacklist", NULL };
179
+    const char **pp;
180
+    struct lsh_string *lsh_hash = ssh_format("%lfxS",
181
+                                            hash_string(&crypto_md5_algorithm,
182
+                                                        PUBLIC_KEY(v), 1));
183
+
184
+    switch (method)
185
+      {
186
+      case ATOM_SSH_DSS:
187
+      case ATOM_DSA:
188
+       {
189
+         CAST(dsa_verifier, self, v);
190
+         keytype = "DSA";
191
+         keysize = mpz_sizeinbase(self->key.p, 2);
192
+       }
193
+       break;
194
+      case ATOM_SSH_RSA:
195
+      case ATOM_RSA_PKCS1_SHA1:
196
+      case ATOM_RSA_PKCS1_MD5:
197
+      case ATOM_RSA_PKCS1:
198
+       {
199
+         CAST(rsa_verifier, self, v);
200
+         keytype = "RSA";
201
+         keysize = mpz_sizeinbase(self->key.n, 2);
202
+       } break;
203
+      default:
204
+         werror("Unrecognized key type");
205
+       return 0;
206
+      }
207
+
208
+    for (pp = paths; *pp && ret <= 0; pp++) {
209
+      struct lsh_string *blacklist_file = ssh_format("%lz.%lz-%di",
210
+                                                    *pp, keytype, keysize);
211
+      int r = blacklisted_key_in_file(lsh_hash, blacklist_file);
212
+      lsh_string_free(blacklist_file);
213
+      if (r > ret) ret = r;
214
+    }
215
+
216
+    if (ret > 0) {
217
+       werror("Key is compromised: %z %i %fS\n", keytype, keysize,
218
+              lsh_string_colonize(lsh_hash, 2, 0));
219
+    }
220
+    return ret;
221
+}
222
diff -urNad trunk~/src/lsh-decode-key.c trunk/src/lsh-decode-key.c
223
--- trunk~/src/lsh-decode-key.c 2005-09-06 14:43:15.000000000 +0200
224
+++ trunk/src/lsh-decode-key.c  2009-11-06 01:07:40.000000000 +0100
225
@@ -133,6 +133,10 @@
226
             werror("Invalid dsa key.\n");
227
             return NULL;
228
           }
229
+        else if (blacklisted_key(v, type))
230
+          {
231
+            return NULL;
232
+          }
233
         else
234
           return PUBLIC_SPKI_KEY(v, 1);
235
       }
236
@@ -150,6 +154,10 @@
237
               werror("Invalid rsa key.\n");
238
               return NULL;
239
             }
240
+          else if (blacklisted_key(v, type))
241
+            {
242
+              return NULL;
243
+            }
244
           else
245
             return PUBLIC_SPKI_KEY(v, 1);
246
       }      
247
diff -urNad trunk~/src/lsh-writekey.c trunk/src/lsh-writekey.c
248
--- trunk~/src/lsh-writekey.c   2004-11-17 11:55:11.000000000 +0100
249
+++ trunk/src/lsh-writekey.c    2009-11-06 01:11:54.000000000 +0100
250
@@ -397,14 +397,18 @@
251
 {
252
   struct signer *s;
253
   struct verifier *v;
254
+  int algorithm_name;
255
 
256
-  s = spki_make_signer(options->signature_algorithms, key, NULL);
257
+  s = spki_make_signer(options->signature_algorithms, key, &algorithm_name);
258
 
259
   if (!s)
260
     return NULL;
261
 
262
   v = SIGNER_GET_VERIFIER(s);
263
   assert(v);
264
+  if (blacklisted_key(v, algorithm_name)) {
265
+    return NULL;
266
+  }
267
 
268
   return PUBLIC_SPKI_KEY(v, 1);
269
 }
270
@@ -416,7 +420,8 @@
271
   int private_fd;
272
   int public_fd;
273
   struct lsh_string *input;
274
-  struct lsh_string *output;
275
+  struct lsh_string *priv_output;
276
+  struct lsh_string *pub_output;
277
   const struct exception *e;
278
 
279
   argp_parse(&main_argp, argc, argv, 0, NULL, options);
280
@@ -439,16 +444,22 @@
281
       return EXIT_FAILURE;
282
     }
283
 
284
-  output = process_private(input, options);
285
-  if (!output)
286
+  pub_output = process_public(input, options);
287
+  if (!pub_output)
288
+    return EXIT_FAILURE;
289
+
290
+  priv_output = process_private(input, options);
291
+  if (!priv_output)
292
     return EXIT_FAILURE;
293
 
294
+  lsh_string_free(input);
295
+
296
   private_fd = open_file(options->private_file);
297
   if (private_fd < 0)
298
     return EXIT_FAILURE;
299
 
300
-  e = write_raw(private_fd, STRING_LD(output));
301
-  lsh_string_free(output);
302
+  e = write_raw(private_fd, STRING_LD(priv_output));
303
+  lsh_string_free(priv_output);
304
 
305
   if (e)
306
     {
307
@@ -457,18 +468,12 @@
308
       return EXIT_FAILURE;
309
     }
310
 
311
-  output = process_public(input, options);
312
-  lsh_string_free(input);
313
-  
314
-  if (!output)
315
-    return EXIT_FAILURE;
316
-
317
   public_fd = open_file(options->public_file);
318
   if (public_fd < 0)
319
     return EXIT_FAILURE;
320
 
321
-  e = write_raw(public_fd, STRING_LD(output));
322
-  lsh_string_free(output);
323
+  e = write_raw(public_fd, STRING_LD(pub_output));
324
+  lsh_string_free(pub_output);
325
 
326
   if (e)
327
     {
328
diff -urNad trunk~/src/publickey_crypto.h trunk/src/publickey_crypto.h
329
--- trunk~/src/publickey_crypto.h       2004-06-15 13:32:51.000000000 +0200
330
+++ trunk/src/publickey_crypto.h        2009-11-06 01:07:40.000000000 +0100
331
@@ -203,5 +203,7 @@
332
 struct verifier *
333
 make_ssh_dss_verifier(const struct lsh_string *public);
334
 
335
+int
336
+blacklisted_key(struct verifier *v, int method);
337
 
338
 #endif /* LSH_PUBLICKEY_CRYPTO_H_INCLUDED */
339
diff -urNad trunk~/src/server_authorization.c trunk/src/server_authorization.c
340
--- trunk~/src/server_authorization.c   2004-06-08 20:01:15.000000000 +0200
341
+++ trunk/src/server_authorization.c    2009-11-06 01:07:40.000000000 +0100
342
@@ -93,7 +93,8 @@
343
                                    PUBLIC_SPKI_KEY(v, 0),
344
                                    1));
345
 
346
-  if (USER_FILE_EXISTS(keyholder, filename, 1))
347
+  if (USER_FILE_EXISTS(keyholder, filename, 1)
348
+      && blacklisted_key(v, method) < 1)
349
     return v;
350
 
351
   return NULL;