gpg: default to AES-256.
[gnupg.git] / g10 / armor.c
index e368660..cc80968 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 #include <ctype.h>
 
 #include "gpg.h"
-#include "status.h"
-#include "iobuf.h"
-#include "util.h"
+#include "../common/status.h"
+#include "../common/iobuf.h"
+#include "../common/util.h"
 #include "filter.h"
 #include "packet.h"
 #include "options.h"
 #include "main.h"
-#include "status.h"
-#include "i18n.h"
+#include "../common/i18n.h"
 
 #define MAX_LINELEN 20000
 
@@ -137,7 +135,7 @@ release_armor_context (armor_filter_context_t *afx)
 {
   if (!afx)
     return;
-  assert (afx->refcount);
+  log_assert (afx->refcount);
   if ( --afx->refcount )
     return;
   xfree (afx);
@@ -191,38 +189,84 @@ initialize(void)
     is_initialized=1;
 }
 
-/****************
- * Check whether this is an armored file or not See also
- * parse-packet.c for details on this code For unknown historic
- * reasons we use a string here but only the first byte will be used.
+
+/*
+ * Check whether this is an armored file.  See also
+ * parse-packet.c for details on this code.
+ *
+ * Note that the buffer BUF needs to be at least 2 bytes long.  If in
+ * doubt that the second byte to 0.
+ *
  * Returns: True if it seems to be armored
  */
 static int
-is_armored( const byte *buf )
+is_armored (const byte *buf)
 {
-    int ctb, pkttype;
+  int ctb, pkttype;
+  int indeterminate_length_allowed;
 
     ctb = *buf;
     if( !(ctb & 0x80) )
-       return 1; /* invalid packet: assume it is armored */
+      /* The most significant bit of the CTB must be set.  Since it is
+         cleared, this is not a binary OpenPGP message.  Assume it is
+         armored.  */
+      return 1;
+
     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
     switch( pkttype ) {
-      case PKT_MARKER:
+      case PKT_PUBKEY_ENC:
+      case PKT_SIGNATURE:
       case PKT_SYMKEY_ENC:
       case PKT_ONEPASS_SIG:
-      case PKT_PUBLIC_KEY:
       case PKT_SECRET_KEY:
-      case PKT_PUBKEY_ENC:
-      case PKT_SIGNATURE:
-      case PKT_COMMENT:
-      case PKT_OLD_COMMENT:
-      case PKT_PLAINTEXT:
+      case PKT_PUBLIC_KEY:
+      case PKT_SECRET_SUBKEY:
+      case PKT_MARKER:
+      case PKT_RING_TRUST:
+      case PKT_USER_ID:
+      case PKT_PUBLIC_SUBKEY:
+      case PKT_ATTRIBUTE:
+      case PKT_MDC:
+       indeterminate_length_allowed = 0;
+        break;
+
       case PKT_COMPRESSED:
       case PKT_ENCRYPTED:
-       return 0; /* seems to be a regular packet: not armored */
+      case PKT_ENCRYPTED_MDC:
+      case PKT_PLAINTEXT:
+      case PKT_OLD_COMMENT:
+      case PKT_COMMENT:
+      case PKT_GPG_CONTROL:
+       indeterminate_length_allowed = 1;
+        break;
+
+      default:
+        /* Invalid packet type.  */
+        return 1;
     }
 
-    return 1;
+    if (! indeterminate_length_allowed)
+      /* It is only legal to use an indeterminate length with a few
+         packet types.  If a packet uses an indeterminate length, but
+         that is not allowed, then the data is not valid binary
+         OpenPGP data.  */
+      {
+        int new_format;
+        int indeterminate_length;
+
+        new_format = !! (ctb & (1 << 6));
+        if (new_format)
+          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
+        else
+          indeterminate_length = (ctb & 3) == 3;
+
+        if (indeterminate_length)
+          return 1;
+      }
+
+    /* The first CTB seems legit.  It is probably not armored
+       data.  */
+    return 0;
 }
 
 
@@ -234,15 +278,17 @@ is_armored( const byte *buf )
 int
 use_armor_filter( IOBUF a )
 {
-    byte buf[1];
+    byte buf[2];
     int n;
 
     /* fixme: there might be a problem with iobuf_peek */
-    n = iobuf_peek(a, buf, 1 );
+    n = iobuf_peek (a, buf, 2);
     if( n == -1 )
        return 0; /* EOF, doesn't matter whether armored or not */
     if( !n )
        return 1; /* can't check it: try armored */
+    if (n != 2)
+       return 0; /* short buffer */
     return is_armored(buf);
 }
 
@@ -274,7 +320,7 @@ parse_hash_header( const char *line )
        return 0; /* too short or too long */
     if( memcmp( line, "Hash:", 5 ) )
        return 0; /* invalid header */
-    s = line+5;
+
     for(s=line+5;;s=s2) {
        for(; *s && (*s==' ' || *s == '\t'); s++ )
            ;
@@ -490,7 +536,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
     /* (the line is always a C string but maybe longer) */
     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
        ;
-    else if( !is_armored( line ) ) {
+    else if (len >= 2 && !is_armored (line)) {
        afx->inp_checked = 1;
        afx->inp_bypass = 1;
        return 0;
@@ -796,6 +842,24 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                }
            }
 
+            /* Occasionally a bug MTA will leave the = escaped as
+               =3D.  If the 4 characters following that are valid
+               Radix64 characters and they are following by a new
+               line, assume that this is the case and skip the
+               3D.  */
+            if (afx->buffer_pos + 6 < afx->buffer_len
+                && afx->buffer[afx->buffer_pos + 0] == '3'
+                && afx->buffer[afx->buffer_pos + 1] == 'D'
+                && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
+                && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
+                && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
+                && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
+                && afx->buffer[afx->buffer_pos + 6] == '\n')
+              {
+                afx->buffer_pos += 2;
+                afx->qp_detected = 1;
+              }
+
            if (!n)
              onlypad = 1;
 
@@ -961,17 +1025,20 @@ armor_filter( void *opaque, int control,
     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
        n = 0;
        if( afx->buffer_len ) {
+            /* Copy the data from AFX->BUFFER to BUF.  */
            for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
                buf[n++] = afx->buffer[afx->buffer_pos++];
            if( afx->buffer_pos >= afx->buffer_len )
                afx->buffer_len = 0;
        }
+        /* If there is still space in BUF, read directly into it.  */
        for(; n < size; n++ ) {
            if( (c=iobuf_get(a)) == -1 )
                break;
            buf[n] = c & 0xff;
        }
        if( !n )
+            /* We didn't get any data.  EOF.  */
            rc = -1;
        *ret_len = n;
     }
@@ -1226,7 +1293,7 @@ armor_filter( void *opaque, int control,
            c = bintoasc[radbuf[2]&077];
            iobuf_put(a, c);
            iobuf_writestr(a,afx->eol);
-           /* and the the trailer */
+           /* and the trailer */
            if( afx->what >= DIM(tail_strings) )
                log_bug("afx->what=%d", afx->what);
            iobuf_writestr(a, "-----");
@@ -1251,7 +1318,7 @@ armor_filter( void *opaque, int control,
         release_armor_context (afx);
     }
     else if( control == IOBUFCTRL_DESC )
-       *(char**)buf = "armor_filter";
+        mem2str (buf, "armor_filter", *ret_len);
     return rc;
 }
 
@@ -1351,8 +1418,9 @@ unarmor_pump (UnarmorPump x, int c)
     switch (x->state) {
       case STA_init:
         {
-            byte tmp[1];
+            byte tmp[2];
             tmp[0] = c;
+            tmp[1] = 0;
             if ( is_armored (tmp) )
                 x->state = c == '-'? STA_first_dash : STA_wait_newline;
             else {
@@ -1370,9 +1438,9 @@ unarmor_pump (UnarmorPump x, int c)
       case STA_wait_dash:
         x->state = c == '-'? STA_first_dash : STA_wait_newline;
         break;
-      case STA_first_dash: /* just need for initalization */
+      case STA_first_dash: /* just need for initialization */
         x->pos = 0;
-        x->state = STA_compare_header;
+        x->state = STA_compare_header; /* fall through */
       case STA_compare_header:
         if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
             if ( x->pos == 28 )
@@ -1453,7 +1521,7 @@ unarmor_pump (UnarmorPump x, int c)
         /* assume that we are at the next line */
         x->state = STA_read_crc;
         x->pos = 0;
-        x->mycrc = 0;
+        x->mycrc = 0; /* fall through */
       case STA_read_crc:
         if( (c = asctobin[c]) == 255 ) {
             rval = -1; /* ready */