0,0 → 1,351 |
#! /bin/sh /usr/share/dpatch/dpatch-run |
## blacklist.dpatch by Magnus Holmgren <holmgren@debian.org> |
## blacklist.c code copied from OpenSSH's authfile.c and adapted for LSH. |
## |
## DP: Check keys against openssh-blacklist before accepting for |
## DP: pubkey authentication as well as on conversion by lsh-writekey |
## DP: and lsh-decode-key. |
|
@DPATCH@ |
diff -urNad trunk~/src/Makefile.am trunk/src/Makefile.am |
--- trunk~/src/Makefile.am 2004-11-18 22:52:16.000000000 +0100 |
+++ trunk/src/Makefile.am 2009-11-06 01:07:40.000000000 +0100 |
@@ -72,7 +72,8 @@ |
unix_interact.c unix_process.c unix_random.c unix_user.c \ |
userauth.c \ |
werror.c write_buffer.c write_packet.c \ |
- xalloc.c xauth.c zlib.c |
+ xalloc.c xauth.c zlib.c \ |
+ blacklist.c |
|
liblsh_a_LIBADD = @LIBOBJS@ |
|
diff -urNad trunk~/src/Makefile.in trunk/src/Makefile.in |
--- trunk~/src/Makefile.in 2009-11-06 01:07:40.000000000 +0100 |
+++ trunk/src/Makefile.in 2009-11-06 01:07:40.000000000 +0100 |
@@ -91,7 +91,8 @@ |
tty.$(OBJEXT) unix_interact.$(OBJEXT) unix_process.$(OBJEXT) \ |
unix_random.$(OBJEXT) unix_user.$(OBJEXT) userauth.$(OBJEXT) \ |
werror.$(OBJEXT) write_buffer.$(OBJEXT) write_packet.$(OBJEXT) \ |
- xalloc.$(OBJEXT) xauth.$(OBJEXT) zlib.$(OBJEXT) |
+ xalloc.$(OBJEXT) xauth.$(OBJEXT) zlib.$(OBJEXT) \ |
+ blacklist.$(OBJEXT) |
liblsh_a_OBJECTS = $(am_liblsh_a_OBJECTS) |
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \ |
"$(DESTDIR)$(bindir)" |
@@ -510,7 +511,8 @@ |
unix_interact.c unix_process.c unix_random.c unix_user.c \ |
userauth.c \ |
werror.c write_buffer.c write_packet.c \ |
- xalloc.c xauth.c zlib.c |
+ xalloc.c xauth.c zlib.c \ |
+ blacklist.c |
|
liblsh_a_LIBADD = @LIBOBJS@ |
|
@@ -705,6 +707,7 @@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/algorithms.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alist.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoms.Po@am__quote@ |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blacklist.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_commands.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel_forward.Po@am__quote@ |
diff -urNad trunk~/src/blacklist.c trunk/src/blacklist.c |
--- trunk~/src/blacklist.c 1970-01-01 01:00:00.000000000 +0100 |
+++ trunk/src/blacklist.c 2009-11-06 01:07:40.000000000 +0100 |
@@ -0,0 +1,164 @@ |
+#if HAVE_CONFIG_H |
+#include "config.h" |
+#endif |
+ |
+#include <assert.h> |
+ |
+#include "nettle/bignum.h" |
+#include "nettle/dsa.h" |
+#include "nettle/rsa.h" |
+#include "xalloc.h" |
+#include "atoms.h" |
+#include "format.h" |
+#include "lsh_string.h" |
+#include "abstract_crypto.h" |
+#include "werror.h" |
+#include "crypto.h" |
+#define GABA_DECLARE |
+#include "rsa.c.x" |
+#include "dsa.c.x" |
+ |
+#include <sys/types.h> |
+#include <sys/stat.h> |
+#include <unistd.h> |
+#include <fcntl.h> |
+#include <string.h> |
+ |
+/* Scan a blacklist of known-vulnerable keys in blacklist_file. */ |
+static int |
+blacklisted_key_in_file(struct lsh_string *lsh_hash, struct lsh_string *blacklist_file) |
+{ |
+ int fd = -1; |
+ const char *hash = 0; |
+ int i; |
+ uint32_t line_len; |
+ struct stat st; |
+ char buf[256]; |
+ off_t start, lower, upper; |
+ int ret = 0; |
+ |
+ debug("Checking blacklist file %S\n", blacklist_file); |
+ fd = open(lsh_get_cstring(blacklist_file), O_RDONLY); |
+ if (fd < 0) { |
+ ret = -1; |
+ goto out; |
+ } |
+ |
+ hash = lsh_get_cstring(lsh_hash) + 12; |
+ line_len = strlen(hash); |
+ if (line_len != 20) |
+ goto out; |
+ |
+ /* Skip leading comments */ |
+ start = 0; |
+ for (;;) { |
+ ssize_t r; |
+ char *newline; |
+ |
+ r = read(fd, buf, sizeof(buf)); |
+ if (r <= 0) |
+ goto out; |
+ if (buf[0] != '#') |
+ break; |
+ |
+ newline = memchr(buf, '\n', sizeof(buf)); |
+ if (!newline) |
+ goto out; |
+ start += newline + 1 - buf; |
+ if (lseek(fd, start, SEEK_SET) < 0) |
+ goto out; |
+ } |
+ |
+ /* Initialise binary search record numbers */ |
+ if (fstat(fd, &st) < 0) |
+ goto out; |
+ lower = 0; |
+ upper = (st.st_size - start) / (line_len + 1); |
+ |
+ while (lower != upper) { |
+ off_t cur; |
+ int cmp; |
+ |
+ cur = lower + (upper - lower) / 2; |
+ |
+ /* Read this line and compare to digest; this is |
+ * overflow-safe since cur < max(off_t) / (line_len + 1) */ |
+ if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0) |
+ break; |
+ if (read(fd, buf, line_len) != line_len) |
+ break; |
+ cmp = memcmp(buf, hash, line_len); |
+ if (cmp < 0) { |
+ if (cur == lower) |
+ break; |
+ lower = cur; |
+ } else if (cmp > 0) { |
+ if (cur == upper) |
+ break; |
+ upper = cur; |
+ } else { |
+ ret = 1; |
+ break; |
+ } |
+ } |
+ |
+out: |
+ if (fd >= 0) |
+ close(fd); |
+ return ret; |
+} |
+ |
+/* |
+ * Scan blacklists of known-vulnerable keys. If a vulnerable key is found, |
+ * its fingerprint is returned in *fp, unless fp is NULL. |
+ */ |
+int |
+blacklisted_key(struct verifier *v, int method) |
+{ |
+ size_t keysize; |
+ const char *keytype; |
+ int ret = -1; |
+ const char *paths[] = { "/usr/share/ssh/blacklist", "/etc/ssh/blacklist", NULL }; |
+ const char **pp; |
+ struct lsh_string *lsh_hash = ssh_format("%lfxS", |
+ hash_string(&crypto_md5_algorithm, |
+ PUBLIC_KEY(v), 1)); |
+ |
+ switch (method) |
+ { |
+ case ATOM_SSH_DSS: |
+ case ATOM_DSA: |
+ { |
+ CAST(dsa_verifier, self, v); |
+ keytype = "DSA"; |
+ keysize = mpz_sizeinbase(self->key.p, 2); |
+ } |
+ break; |
+ case ATOM_SSH_RSA: |
+ case ATOM_RSA_PKCS1_SHA1: |
+ case ATOM_RSA_PKCS1_MD5: |
+ case ATOM_RSA_PKCS1: |
+ { |
+ CAST(rsa_verifier, self, v); |
+ keytype = "RSA"; |
+ keysize = mpz_sizeinbase(self->key.n, 2); |
+ } break; |
+ default: |
+ werror("Unrecognized key type"); |
+ return 0; |
+ } |
+ |
+ for (pp = paths; *pp && ret <= 0; pp++) { |
+ struct lsh_string *blacklist_file = ssh_format("%lz.%lz-%di", |
+ *pp, keytype, keysize); |
+ int r = blacklisted_key_in_file(lsh_hash, blacklist_file); |
+ lsh_string_free(blacklist_file); |
+ if (r > ret) ret = r; |
+ } |
+ |
+ if (ret > 0) { |
+ werror("Key is compromised: %z %i %fS\n", keytype, keysize, |
+ lsh_string_colonize(lsh_hash, 2, 0)); |
+ } |
+ return ret; |
+} |
diff -urNad trunk~/src/lsh-decode-key.c trunk/src/lsh-decode-key.c |
--- trunk~/src/lsh-decode-key.c 2005-09-06 14:43:15.000000000 +0200 |
+++ trunk/src/lsh-decode-key.c 2009-11-06 01:07:40.000000000 +0100 |
@@ -133,6 +133,10 @@ |
werror("Invalid dsa key.\n"); |
return NULL; |
} |
+ else if (blacklisted_key(v, type)) |
+ { |
+ return NULL; |
+ } |
else |
return PUBLIC_SPKI_KEY(v, 1); |
} |
@@ -150,6 +154,10 @@ |
werror("Invalid rsa key.\n"); |
return NULL; |
} |
+ else if (blacklisted_key(v, type)) |
+ { |
+ return NULL; |
+ } |
else |
return PUBLIC_SPKI_KEY(v, 1); |
} |
diff -urNad trunk~/src/lsh-writekey.c trunk/src/lsh-writekey.c |
--- trunk~/src/lsh-writekey.c 2004-11-17 11:55:11.000000000 +0100 |
+++ trunk/src/lsh-writekey.c 2009-11-06 01:11:54.000000000 +0100 |
@@ -397,14 +397,18 @@ |
{ |
struct signer *s; |
struct verifier *v; |
+ int algorithm_name; |
|
- s = spki_make_signer(options->signature_algorithms, key, NULL); |
+ s = spki_make_signer(options->signature_algorithms, key, &algorithm_name); |
|
if (!s) |
return NULL; |
|
v = SIGNER_GET_VERIFIER(s); |
assert(v); |
+ if (blacklisted_key(v, algorithm_name)) { |
+ return NULL; |
+ } |
|
return PUBLIC_SPKI_KEY(v, 1); |
} |
@@ -416,7 +420,8 @@ |
int private_fd; |
int public_fd; |
struct lsh_string *input; |
- struct lsh_string *output; |
+ struct lsh_string *priv_output; |
+ struct lsh_string *pub_output; |
const struct exception *e; |
|
argp_parse(&main_argp, argc, argv, 0, NULL, options); |
@@ -439,16 +444,22 @@ |
return EXIT_FAILURE; |
} |
|
- output = process_private(input, options); |
- if (!output) |
+ pub_output = process_public(input, options); |
+ if (!pub_output) |
+ return EXIT_FAILURE; |
+ |
+ priv_output = process_private(input, options); |
+ if (!priv_output) |
return EXIT_FAILURE; |
|
+ lsh_string_free(input); |
+ |
private_fd = open_file(options->private_file); |
if (private_fd < 0) |
return EXIT_FAILURE; |
|
- e = write_raw(private_fd, STRING_LD(output)); |
- lsh_string_free(output); |
+ e = write_raw(private_fd, STRING_LD(priv_output)); |
+ lsh_string_free(priv_output); |
|
if (e) |
{ |
@@ -457,18 +468,12 @@ |
return EXIT_FAILURE; |
} |
|
- output = process_public(input, options); |
- lsh_string_free(input); |
- |
- if (!output) |
- return EXIT_FAILURE; |
- |
public_fd = open_file(options->public_file); |
if (public_fd < 0) |
return EXIT_FAILURE; |
|
- e = write_raw(public_fd, STRING_LD(output)); |
- lsh_string_free(output); |
+ e = write_raw(public_fd, STRING_LD(pub_output)); |
+ lsh_string_free(pub_output); |
|
if (e) |
{ |
diff -urNad trunk~/src/publickey_crypto.h trunk/src/publickey_crypto.h |
--- trunk~/src/publickey_crypto.h 2004-06-15 13:32:51.000000000 +0200 |
+++ trunk/src/publickey_crypto.h 2009-11-06 01:07:40.000000000 +0100 |
@@ -203,5 +203,7 @@ |
struct verifier * |
make_ssh_dss_verifier(const struct lsh_string *public); |
|
+int |
+blacklisted_key(struct verifier *v, int method); |
|
#endif /* LSH_PUBLICKEY_CRYPTO_H_INCLUDED */ |
diff -urNad trunk~/src/server_authorization.c trunk/src/server_authorization.c |
--- trunk~/src/server_authorization.c 2004-06-08 20:01:15.000000000 +0200 |
+++ trunk/src/server_authorization.c 2009-11-06 01:07:40.000000000 +0100 |
@@ -93,7 +93,8 @@ |
PUBLIC_SPKI_KEY(v, 0), |
1)); |
|
- if (USER_FILE_EXISTS(keyholder, filename, 1)) |
+ if (USER_FILE_EXISTS(keyholder, filename, 1) |
+ && blacklisted_key(v, method) < 1) |
return v; |
|
return NULL; |
Property changes: |
Added: svn:executable |
## -0,0 +1 ## |
+* |
\ No newline at end of property |
Index: 00list |
=================================================================== |
--- 00list (revision 59) |
+++ 00list (revision 60) |
@@ -2,3 +2,4 @@ |
30_nonettle |
40_better_errmsg_when_dotlsh_missing |
nettle_2.0 |
+blacklist |