From 4a3a9d4bbf8048473f5cc202cd8db7164d5e6b8d Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 30 Oct 2013 22:19:47 +1100 Subject: [PATCH] - djm@cvs.openbsd.org 2013/10/29 09:42:11 [key.c key.h] fix potential stack exhaustion caused by nested certificates; report by Mateusz Kocielski; ok dtucker@ markus@ --- ChangeLog | 7 +++++++ key.c | 45 +++++++++++++++++++++++++++++---------------- key.h | 3 ++- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4519a922e..54f7b0042 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +20131030 + - (djm) OpenBSD CVS Sync + - djm@cvs.openbsd.org 2013/10/29 09:42:11 + [key.c key.h] + fix potential stack exhaustion caused by nested certificates; + report by Mateusz Kocielski; ok dtucker@ markus@ + 20131026 - (djm) OpenBSD CVS Sync - djm@cvs.openbsd.org 2013/10/25 23:04:51 diff --git a/key.c b/key.c index 55ee78998..90f0a0173 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.104 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: key.c,v 1.105 2013/10/29 09:42:11 djm Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -56,6 +56,7 @@ #include "ssh2.h" static int to_blob(const Key *, u_char **, u_int *, int); +static Key *key_from_blob2(const u_char *, u_int, int); static struct KeyCert * cert_new(void) @@ -1023,6 +1024,18 @@ key_alg_list(void) return ret; } +int +key_type_is_cert(int type) +{ + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { + if (kt->type == type) + return kt->cert; + } + return 0; +} + u_int key_size(const Key *k) { @@ -1387,8 +1400,8 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) } buffer_clear(&tmp); - if ((key->cert->signature_key = key_from_blob(sig_key, - sklen)) == NULL) { + if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0)) + == NULL) { error("%s: Signature key invalid", __func__); goto out; } @@ -1425,8 +1438,8 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) return ret; } -Key * -key_from_blob(const u_char *blob, u_int blen) +static Key * +key_from_blob2(const u_char *blob, u_int blen, int allow_cert) { Buffer b; int rlen, type; @@ -1452,7 +1465,10 @@ key_from_blob(const u_char *blob, u_int blen) if (key_type_plain(type) == KEY_ECDSA) nid = key_ecdsa_nid_from_name(ktype); #endif - + if (!allow_cert && key_type_is_cert(type)) { + error("key_from_blob: certificate not allowed in this context"); + goto out; + } switch (type) { case KEY_RSA_CERT: (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ @@ -1551,6 +1567,12 @@ key_from_blob(const u_char *blob, u_int blen) return key; } +Key * +key_from_blob(const u_char *blob, u_int blen) +{ + return key_from_blob2(blob, blen, 1); +} + static int to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain) { @@ -1747,16 +1769,7 @@ key_is_cert(const Key *k) { if (k == NULL) return 0; - switch (k->type) { - case KEY_RSA_CERT_V00: - case KEY_DSA_CERT_V00: - case KEY_RSA_CERT: - case KEY_DSA_CERT: - case KEY_ECDSA_CERT: - return 1; - default: - return 0; - } + return key_type_is_cert(k->type); } /* Return the cert-less equivalent to a certified key type */ diff --git a/key.h b/key.h index 17358ae1f..8a78a828a 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.37 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: key.h,v 1.38 2013/10/29 09:42:11 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -107,6 +107,7 @@ Key *key_generate(int, u_int); Key *key_from_private(const Key *); int key_type_from_name(char *); int key_is_cert(const Key *); +int key_type_is_cert(int); int key_type_plain(int); int key_to_certified(Key *, int); int key_drop_cert(Key *);