Rev 60 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#! /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-0 23:57:07.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.cliblsh_a_LIBADD = @LIBOBJS@diff -urNad trunk~/src/Makefile.in trunk/src/Makefile.in--- trunk~/src/Makefile.in 2009-11-07 23:57:06.000000000 +0100+++ trunk/src/Makefile.in 2009-11-07 23:57:07.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.cliblsh_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/abstract_crypto.h trunk/src/abstract_crypto.h--- trunk~/src/abstract_crypto.h 2003-11-16 19:10:30.000000000 +0100+++ trunk/src/abstract_crypto.h 2009-11-07 23:57:37.000000000 +0100@@ -162,7 +162,9 @@(public_key method (string)); Returns (public-key (<pub-sig-alg-id> <s-expr>*))- (public_spki_key method (string) "int transport")))+ (public_spki_key method (string) "int transport")++ (key_size method uint32_t)))*/#define VERIFY(verifier, algorithm, length, data, slength, sdata) \@@ -170,7 +172,7 @@#define PUBLIC_KEY(verifier) ((verifier)->public_key((verifier)))#define PUBLIC_SPKI_KEY(verifier, t) ((verifier)->public_spki_key((verifier), (t)))-+#define KEY_SIZE(verifier) ((verifier)->key_size((verifier)))/* GABA:(classdiff -urNad trunk~/src/abstract_crypto.h.x trunk/src/abstract_crypto.h.x--- trunk~/src/abstract_crypto.h.x 2007-06-04 22:18:39.000000000 +0200+++ trunk/src/abstract_crypto.h.x 2009-11-07 23:57:07.000000000 +0100@@ -161,6 +161,7 @@int (*(verify))(struct verifier *self,int algorithm,uint32_t length,const uint8_t *data,uint32_t signature_length,const uint8_t *signature_data);struct lsh_string *(*(public_key))(struct verifier *self);struct lsh_string *(*(public_spki_key))(struct verifier *self,int transport);+ uint32_t *(*(key_size))(struct verifier *self);};extern struct lsh_class verifier_class;#endif /* !GABA_DEFINE */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-07 23:57:07.000000000 +0100@@ -0,0 +1,150 @@+#if HAVE_CONFIG_H+#include "config.h"+#endif++#include <assert.h>++#include "atoms.h"+#include "format.h"+#include "lsh_string.h"+#include "werror.h"+#include "crypto.h"++#include <sys/types.h>+#include <sys/stat.h>+#include <unistd.h>+#include <fcntl.h>+#include <string.h>++int blacklisted_key(struct verifier *v, int method);++/* 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;+ 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)+{+ 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));+ uint32_t keysize = KEY_SIZE(v);++ switch (method)+ {+ case ATOM_SSH_DSS:+ case ATOM_DSA:+ keytype = "DSA";+ break;+ case ATOM_SSH_RSA:+ case ATOM_RSA_PKCS1_SHA1:+ case ATOM_RSA_PKCS1_MD5:+ case ATOM_RSA_PKCS1:+ keytype = "RSA";+ break;+ default:+ werror("Unrecognized key type");+ return -1;+ }++ 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/dsa.c trunk/src/dsa.c--- trunk~/src/dsa.c 2004-06-08 20:00:45.000000000 +0200+++ trunk/src/dsa.c 2009-11-07 23:57:07.000000000 +0100@@ -189,6 +189,14 @@"y", self->key.y);}+static uint32_t+do_dsa_key_size(struct verifier *v)+{+ CAST(dsa_verifier, self, v);++ return mpz_sizeinbase(self->key.p, 2);+}+static voidinit_dsa_verifier(struct dsa_verifier *self){@@ -199,6 +207,7 @@self->super.verify = do_dsa_verify;self->super.public_spki_key = do_dsa_public_spki_key;self->super.public_key = do_dsa_public_key;+ self->super.key_size = do_dsa_key_size;}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-07 23:57:07.000000000 +0100@@ -133,6 +133,10 @@werror("Invalid dsa key.\n");return NULL;}+ else if (blacklisted_key(v, type))+ {+ return NULL;+ }elsereturn PUBLIC_SPKI_KEY(v, 1);}@@ -150,6 +154,10 @@werror("Invalid rsa key.\n");return NULL;}+ else if (blacklisted_key(v, type))+ {+ return NULL;+ }elsereturn 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-07 23:57:07.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-07 23:57:07.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/rsa.c trunk/src/rsa.c--- trunk~/src/rsa.c 2003-11-16 19:49:12.000000000 +0100+++ trunk/src/rsa.c 2009-11-07 23:57:07.000000000 +0100@@ -167,6 +167,14 @@self->key.n, self->key.e);}+static uint32_t+do_rsa_key_size(struct verifier *v)+{+ CAST(rsa_verifier, self, v);++ return mpz_sizeinbase(self->key.n, 2);+}+/* NOTE: To initialize an rsa verifier, one must*@@ -184,6 +192,7 @@self->super.verify = do_rsa_verify;self->super.public_key = do_rsa_public_key;self->super.public_spki_key = do_rsa_public_spki_key;+ self->super.key_size = do_rsa_key_size;}/* Alternative constructor using a key of type ssh-rsa, when the atomdiff -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-07 23:57:07.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;