* options.h, g10.c (main), plaintext.c (handle_plaintext): Add
authorDavid Shaw <dshaw@jabberwocky.com>
Wed, 18 Feb 2004 23:09:27 +0000 (23:09 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Wed, 18 Feb 2004 23:09:27 +0000 (23:09 +0000)
--max-output option to help people deal with decompression bombs.

g10/ChangeLog
g10/g10.c
g10/options.h
g10/plaintext.c

index fe7145f..b5dbbec 100644 (file)
@@ -1,3 +1,8 @@
+2004-02-18  David Shaw  <dshaw@jabberwocky.com>
+
+       * options.h, g10.c (main), plaintext.c (handle_plaintext): Add
+       --max-output option to help people deal with decompression bombs.
+
 2004-02-15  David Shaw  <dshaw@jabberwocky.com>
 
        * build-packet.c (do_user_id): Do not force a header for attribute
index 916934c..c15cea3 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -76,6 +76,7 @@ enum cmd_and_opt_values
     oCompress    = 'z',
     oSetNotation  = 'N',
     oBatch       = 500,
+    oMaxOutput,
     oSigNotation,
     oCertNotation,
     oShowNotation,
@@ -436,6 +437,7 @@ static ARGPARSE_OPTS opts[] = {
     { oAskCertExpire, "ask-cert-expire",   0, "@"},
     { oNoAskCertExpire, "no-ask-cert-expire",   0, "@"},
     { oOutput, "output",    2, N_("use as output file")},
+    { oMaxOutput, "max-output", 16|4, "@" },
     { oVerbose, "verbose",   0, N_("verbose") },
     { oQuiet,  "quiet",   0, "@"},
     { oNoTTY, "no-tty", 0, "@"},
@@ -1697,6 +1699,7 @@ main( int argc, char **argv )
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
          case oOutput: opt.outfile = pargs.r.ret_str; break;
+         case oMaxOutput: opt.max_output = pargs.r.ret_ulong; break;
          case oQuiet: opt.quiet = 1; break;
          case oNoTTY: tty_no_terminal(1); break;
          case oDryRun: opt.dry_run = 1; break;
index aa7c244..ea5dd13 100644 (file)
@@ -1,6 +1,6 @@
 /* options.h
- * Copyright (C) 1998, 1999, 2000, 2001, 2002,
- *               2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
+ *               2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -21,6 +21,7 @@
 #ifndef G10_OPTIONS_H
 #define G10_OPTIONS_H
 
+#include <sys/types.h>
 #include <types.h>
 #include "main.h"
 #include "packet.h"
@@ -43,6 +44,7 @@ struct {
     unsigned debug;
     int armor;
     char *outfile;
+    off_t max_output;
     int dry_run;
     int list_only;
     int textmode;
index 6aad0ef..e057d3f 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
+#include <sys/types.h>
 #ifdef HAVE_DOSISH_SYSTEM
 #include <fcntl.h> /* for setmode() */
 #endif
@@ -52,6 +53,7 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
 {
     char *fname = NULL;
     FILE *fp = NULL;
+    off_t count=0;
     int rc = 0;
     int c;
     int convert = pt->mode == 't';
@@ -164,14 +166,23 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
                if( c == '\r' )  /* convert to native line ending */
                    continue;    /* fixme: this hack might be too simple */
 #endif
-               if( fp ) {
-                   if( putc( c, fp ) == EOF ) {
+               if( fp )
+                 {
+                   if((count++)>opt.max_output)
+                     {
+                       log_error("Error writing to `%s': %s\n",
+                                 fname,"exceeded --max-output limit\n");
+                       rc = G10ERR_WRITE_FILE;
+                       goto leave;
+                     }
+                   else if( putc( c, fp ) == EOF )
+                     {
                        log_error("Error writing to `%s': %s\n",
                                  fname, strerror(errno) );
                        rc = G10ERR_WRITE_FILE;
                        goto leave;
-                   }
-               }
+                     }
+                 }
            }
        }
        else { /* binary mode */
@@ -188,15 +199,25 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
                }
                if( mfx->md )
                    md_write( mfx->md, buffer, len );
-               if( fp ) {
-                   if( fwrite( buffer, 1, len, fp ) != len ) {
+               if( fp )
+                 {
+                   if((count+=len)>opt.max_output)
+                     {
+                       log_error("Error writing to `%s': %s\n",
+                                 fname,"exceeded --max-output limit\n");
+                       rc = G10ERR_WRITE_FILE;
+                       m_free( buffer );
+                       goto leave;
+                     }
+                   else if( fwrite( buffer, 1, len, fp ) != len )
+                     {
                        log_error("Error writing to `%s': %s\n",
                                  fname, strerror(errno) );
                        rc = G10ERR_WRITE_FILE;
                        m_free( buffer );
                        goto leave;
-                   }
-               }
+                     }
+                 }
                pt->len -= len;
            }
            m_free( buffer );
@@ -211,14 +232,23 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
                if( convert && c == '\r' )
                    continue; /* fixme: this hack might be too simple */
 #endif
-               if( fp ) {
-                   if( putc( c, fp ) == EOF ) {
+               if( fp )
+                 {
+                   if((count++)>opt.max_output)
+                     {
+                       log_error("Error writing to `%s': %s\n",
+                                 fname,"exceeded --max-output limit\n");
+                       rc = G10ERR_WRITE_FILE;
+                       goto leave;
+                     }
+                   else if( putc( c, fp ) == EOF )
+                     {
                        log_error("Error writing to `%s': %s\n",
                                  fname, strerror(errno) );
                        rc = G10ERR_WRITE_FILE;
                        goto leave;
-                   }
-               }
+                     }
+                 }
            }
        }
        else { /* binary mode */
@@ -238,15 +268,24 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
                    eof = 1;
                if( mfx->md )
                    md_write( mfx->md, buffer, len );
-               if( fp ) {
-                   if( fwrite( buffer, 1, len, fp ) != len ) {
+               if( fp )
+                 {
+                   if((count+=len)>opt.max_output)
+                     {
                        log_error("Error writing to `%s': %s\n",
-                                 fname, strerror(errno) );
+                                 fname,"exceeded --max-output limit\n");
                        rc = G10ERR_WRITE_FILE;
                        m_free( buffer );
                        goto leave;
+                     }
+                   else if( fwrite( buffer, 1, len, fp ) != len ) {
+                     log_error("Error writing to `%s': %s\n",
+                               fname, strerror(errno) );
+                     rc = G10ERR_WRITE_FILE;
+                     m_free( buffer );
+                     goto leave;
                    }
-               }
+                 }
            }
            m_free( buffer );
        }
@@ -256,14 +295,23 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
        int state = 0;
 
        while( (c = iobuf_get(pt->buf)) != -1 ) {
-           if( fp ) {
-               if( putc( c, fp ) == EOF ) {
+           if( fp )
+             {
+               if((count++)>opt.max_output)
+                 {
                    log_error("Error writing to `%s': %s\n",
-                                               fname, strerror(errno) );
+                             fname,"exceeded --max-output limit\n");
                    rc = G10ERR_WRITE_FILE;
                    goto leave;
-               }
-           }
+                 }
+               else if( putc( c, fp ) == EOF )
+                 {
+                   log_error("Error writing to `%s': %s\n",
+                             fname, strerror(errno) );
+                   rc = G10ERR_WRITE_FILE;
+                   goto leave;
+                 }
+             }
            if( !mfx->md )
                continue;
            if( state == 2 ) {