Sophie

Sophie

distrib > Mageia > 2 > i586 > by-pkgid > 127b7534ef77fd0d024b4a9f3a071a6c > files > 4

gnupg-1.4.12-1.3.mga2.src.rpm

diff -Naurp gnupg-1.4.12/g10/mainproc.c gnupg-1.4.12.oden/g10/mainproc.c
--- gnupg-1.4.12/g10/mainproc.c	2012-01-20 05:51:16.000000000 -0500
+++ gnupg-1.4.12.oden/g10/mainproc.c	2013-10-09 11:16:23.000000000 -0400
@@ -41,6 +41,11 @@
 #include "photoid.h"
 
 
+/* Put an upper limit on nested packets.  The 32 is an arbitrary
+   value, a much lower should actually be sufficient.  */
+#define MAX_NESTING_DEPTH 32
+
+
 struct kidlist_item {
     struct kidlist_item *next;
     u32 kid[2];
@@ -784,7 +789,7 @@ proc_encrypt_cb( IOBUF a, void *info )
     return proc_encryption_packets( info, a );
 }
 
-static void
+static int
 proc_compressed( CTX c, PACKET *pkt )
 {
     PKT_compressed *zd = pkt->pkt.compressed;
@@ -803,6 +808,7 @@ proc_compressed( CTX c, PACKET *pkt )
 	log_error("uncompressing failed: %s\n", g10_errstr(rc));
     free_packet(pkt);
     c->last_was_session_key = 0;
+    return rc;
 }
 
 /****************
@@ -1233,14 +1239,37 @@ proc_encryption_packets( void *anchor, I
 }
 
 
-int
+static int
+check_nesting (CTX c)
+{
+  int level;
+
+  for (level = 0; c; c = c->anchor)
+    level++;
+
+  if (level > MAX_NESTING_DEPTH)
+    {
+      log_error ("input data with too deeply nested packets\n");
+      write_status_text (STATUS_UNEXPECTED, "1");
+      return G10ERR_UNEXPECTED;
+    }
+  return 0;
+}
+
+
+static int
 do_proc_packets( CTX c, IOBUF a )
 {
-    PACKET *pkt = xmalloc( sizeof *pkt );
-    int rc=0;
-    int any_data=0;
+    PACKET *pkt;
+    int rc = 0;
+    int any_data = 0;
     int newpkt;
 
+    rc = check_nesting (c);
+    if (rc)
+      return rc;
+
+    pkt = xmalloc( sizeof *pkt );
     c->iobuf = a;
     init_packet(pkt);
     while( (rc=parse_packet(a, pkt)) != -1 ) {
@@ -1260,7 +1289,7 @@ do_proc_packets( CTX c, IOBUF a )
 	      case PKT_SYMKEY_ENC:  proc_symkey_enc( c, pkt ); break;
 	      case PKT_ENCRYPTED:
 	      case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
-	      case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+	      case PKT_COMPRESSED:  rc = proc_compressed( c, pkt ); break;
 	      default: newpkt = 0; break;
 	    }
 	}
@@ -1278,7 +1307,7 @@ do_proc_packets( CTX c, IOBUF a )
 		goto leave;
 	      case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
 	      case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
-	      case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+	      case PKT_COMPRESSED:  rc = proc_compressed( c, pkt ); break;
 	      case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
               case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
 	      default: newpkt = 0; break;
@@ -1298,7 +1327,7 @@ do_proc_packets( CTX c, IOBUF a )
 	      case PKT_ENCRYPTED:
 	      case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
 	      case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
-	      case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+	      case PKT_COMPRESSED:  rc = proc_compressed( c, pkt ); break;
 	      case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
 	      case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
 	      default: newpkt = 0; break;
@@ -1323,13 +1352,17 @@ do_proc_packets( CTX c, IOBUF a )
 	      case PKT_ENCRYPTED:
 	      case PKT_ENCRYPTED_MDC: proc_encrypted( c, pkt ); break;
 	      case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
-	      case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
+	      case PKT_COMPRESSED:  rc = proc_compressed( c, pkt ); break;
 	      case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
               case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break;
 	      case PKT_RING_TRUST:  newpkt = add_ring_trust( c, pkt ); break;
 	      default: newpkt = 0; break;
 	    }
 	}
+
+        if (rc)
+          goto leave;
+
         /* This is a very ugly construct and frankly, I don't remember why
          * I used it.  Adding the MDC check here is a hack.
          * The right solution is to initiate another context for encrypted
diff -Naurp gnupg-1.4.12/util/iobuf.c gnupg-1.4.12.oden/util/iobuf.c
--- gnupg-1.4.12/util/iobuf.c	2012-01-20 05:51:16.000000000 -0500
+++ gnupg-1.4.12.oden/util/iobuf.c	2013-10-09 11:16:23.000000000 -0400
@@ -55,6 +55,11 @@
 
 #undef FILE_FILTER_USES_STDIO
 
+/* To avoid a potential DoS with compression packets we better limit
+   the number of filters in a chain.  */
+#define MAX_NESTING_FILTER 64
+
+
 #ifdef HAVE_DOSISH_SYSTEM
 #define USE_SETMODE 1
 #endif
@@ -1403,6 +1408,12 @@ iobuf_push_filter2( IOBUF a,
 
     if( a->use == 2 && (rc=iobuf_flush(a)) )
 	return rc;
+
+    if (a->subno >= MAX_NESTING_FILTER) {
+        log_error ("i/o filter too deeply nested - corrupted data?\n");
+        return G10ERR_UNEXPECTED;
+    }
+
     /* make a copy of the current stream, so that
      * A is the new stream and B the original one.
      * The contents of the buffers are transferred to the