| 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: debian/patches/00list |
| =================================================================== |
| --- debian/patches/00list (revision 59) |
| +++ debian/patches/00list (revision 60) |
| @@ -2,3 +2,4 @@ |
| 30_nonettle |
| 40_better_errmsg_when_dotlsh_missing |
| nettle_2.0 |
| +blacklist |
| Index: debian/changelog |
| =================================================================== |
| --- debian/changelog (revision 59) |
| +++ debian/changelog (revision 60) |
| @@ -2,8 +2,13 @@ |
| * lsh-server.init.d: Don't suppress start/stop messages when $VERBOSE = |
| "no". /etc/init.d/skeleton is not a good example in this matter. |
| + * blacklist.dpatch: Check keys against openssh-blacklist before |
| + accepting for pubkey authentication as well as on conversion by |
| + lsh-writekey and lsh-decode-key. |
| + * lsh-server: Depend on openssh-blacklist, recommend -blacklist-extra. |
| + lsh-utils: Recommend openssh-blacklist and -blacklist-extra. |
| |
| - -- Magnus Holmgren <holmgren@debian.org> Sat, 10 Oct 2009 23:16:33 +0200 |
| + -- Magnus Holmgren <holmgren@debian.org> Sat, 07 Nov 2009 23:08:23 +0100 |
| |
| lsh-utils (2.0.4-dfsg-4) unstable; urgency=high |
| |