2003-09-28 Timo Schulz <twoaday@freakmail.de>
[gnupg.git] / g10 / parse-packet.c
index 5ed75e4..0831d26 100644 (file)
@@ -1,5 +1,6 @@
 /* parse-packet.c  - read packets
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ *               2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -41,9 +42,9 @@ static int list_mode = 0;
 
 static int  parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
                   off_t *retpos, int *skip, IOBUF out, int do_skip
-           #ifdef DEBUG_PARSE_PACKET
+#ifdef DEBUG_PARSE_PACKET
                   ,const char *dbg_w, const char *dbg_f, int dbg_l
-           #endif
+#endif
                 );
 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
                                               unsigned long pktlen );
@@ -366,8 +367,28 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
        lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
        if( !lenbytes ) {
            pktlen = 0; /* don't know the value */
-           if( pkttype != PKT_COMPRESSED )
-               iobuf_set_block_mode(inp, 1);
+            switch (pkttype) {
+              case PKT_ENCRYPTED:
+              case PKT_PLAINTEXT:
+                /* These partial length encodings are from an very
+                  early GnuPG release and deprecated.  However we
+                  still support them read-wise.  Note, that we should
+                  not allow them for any key related packets, because
+                  this might render a keyring unusable if an errenous
+                  packet indicated this mode but not complying to it
+                  gets imported. */
+                iobuf_set_block_mode(inp, 1);
+               break;
+
+              case PKT_COMPRESSED:
+                break; /* the orginal pgp 2 way. */
+
+              default:
+                log_error ("%s: old style partial length "
+                           "for invalid packet type\n", iobuf_where(inp) );
+                rc = G10ERR_INVALID_PACKET;
+                goto leave;
+            }
        }
        else {
            for( ; lenbytes; lenbytes-- ) {
@@ -752,12 +773,12 @@ dump_sig_subpkt( int hashed, int type, int critical,
                type, (unsigned)length );
     }
     
+    buffer++;
+    length--;
    
     printf("\t%s%ssubpkt %d len %u (", /*)*/
              critical ? "critical ":"",
              hashed ? "hashed ":"", type, (unsigned)length );
-    buffer++;
-    length--;
     if( length > buflen ) {
        printf("too short: buffer is only %u)\n", (unsigned)buflen );
        return;
@@ -778,13 +799,13 @@ dump_sig_subpkt( int hashed, int type, int critical,
        break;
       case SIGSUBPKT_TRUST:
        if(length!=2)
-         p="[invalid trust signature]";
+         p="[invalid trust subpacket]";
        else
-         printf("trust signature of level %d, amount %d",buffer[0],buffer[1]);
+         printf("trust signature of depth %d, value %d",buffer[0],buffer[1]);
        break;
       case SIGSUBPKT_REGEXP:
        if(!length)
-         p="[invalid regexp]";
+         p="[invalid regexp subpacket]";
        else
          printf("regular expression: \"%s\"",buffer);
        break;
@@ -823,8 +844,6 @@ dump_sig_subpkt( int hashed, int type, int critical,
            fputs("notation: ", stdout );
            if( length < 8 )
                p = "[too short]";
-           else if( !(*buffer & 0x80) )
-               p = "[not human readable]";
            else {
                const byte *s = buffer;
                size_t n1, n2;
@@ -837,7 +856,11 @@ dump_sig_subpkt( int hashed, int type, int critical,
                else {
                    print_string( stdout, s, n1, ')' );
                    putc( '=', stdout );
-                   print_string( stdout, s+n1, n2, ')' );
+
+                   if( *buffer & 0x80 )
+                     print_string( stdout, s+n1, n2, ')' );
+                   else
+                     p = "[not human readable]";
                }
            }
        }
@@ -858,7 +881,8 @@ dump_sig_subpkt( int hashed, int type, int critical,
          printf(" %02X", buffer[i]);
        break;
       case SIGSUBPKT_PREF_KS:
-       p = "preferred key server";
+       fputs("preferred key server: ", stdout );
+       print_string( stdout, buffer, length, ')' );
        break;
       case SIGSUBPKT_PRIMARY_UID:
        p = "primary user ID";
@@ -897,10 +921,12 @@ dump_sig_subpkt( int hashed, int type, int critical,
         for( i=0; i < length; i++ )
             printf(" %02x", buffer[i] );
        break;
-      case SIGSUBPKT_PRIV_VERIFY_CACHE:
-       p = "obsolete verification cache";
+      default:
+       if(type>=100 && type<=110)
+         p="experimental / private subpacket";
+       else
+         p = "?";
        break;
-      default: p = "?"; break;
     }
 
     printf("%s)\n", p? p: "");
@@ -932,7 +958,9 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
       case SIGSUBPKT_PREF_HASH:
       case SIGSUBPKT_PREF_COMPR:
       case SIGSUBPKT_POLICY:
+      case SIGSUBPKT_PREF_KS:
       case SIGSUBPKT_FEATURES:
+      case SIGSUBPKT_REGEXP:
        return 0;
       case SIGSUBPKT_EXPORTABLE:
       case SIGSUBPKT_REVOCABLE:
@@ -955,19 +983,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
           if ( n != 1 )
               break;
           return 0;   
-      case SIGSUBPKT_PRIV_VERIFY_CACHE:
-        /* We used this in gpg 1.0.5 and 1.0.6 to cache signature
-         * verification results - it is no longer used.
-         * "GPG" 0x00 <mode> <stat>
-         * where mode == 1: valid data, stat == 0: invalid signature
-         * stat == 1: valid signature 
-        * (because we use private data, we check our marker) */
-       if( n < 6 )
-           break;
-       if( buffer[0] != 'G' || buffer[1] != 'P'
-            || buffer[2] != 'G' || buffer[3] )
-           return -2;
-       return 4;
+      case SIGSUBPKT_TRUST:
+         if ( n != 2 )
+             break;
+         return 0;
       default: return -1;
     }
     return -3;
@@ -996,7 +1015,11 @@ can_handle_critical( const byte *buffer, size_t n, int type )
       case SIGSUBPKT_KEY_FLAGS:
       case SIGSUBPKT_PRIMARY_UID:
       case SIGSUBPKT_FEATURES:
-      case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
+      case SIGSUBPKT_TRUST:
+      case SIGSUBPKT_REGEXP:
+       /* Is it enough to show the policy or keyserver? */
+      case SIGSUBPKT_POLICY:
+      case SIGSUBPKT_PREF_KS:
        return 1;
 
       default:
@@ -1061,13 +1084,15 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
            if( *critical ) {
                if( n-1 > buflen+1 )
                    goto too_short;
-               if( !can_handle_critical(buffer+1, n-1, type ) ) {
-                   log_info(_("subpacket of type %d has critical bit set\n"),
-                                                                       type);
+               if( !can_handle_critical(buffer+1, n-1, type ) )
+                 {
+                   if(opt.verbose)
+                     log_info(_("subpacket of type %d has "
+                                "critical bit set\n"),type);
                    if( start )
-                       *start = seq;
+                     *start = seq;
                    return NULL; /* this is an error */
-               }
+                 }
            }
        }
        else if( reqtype < 0 ) /* list packets */
@@ -1220,11 +1245,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
            goto leave;
        }
        if( n ) {
-            /* we add 8 extra bytes so that we have space for the signature
-             * status cache.  Well we are wastin this if there is a cache
-             * packet already, but in the other case it avoids an realloc */
-           sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 );
-            sig->unhashed->size = n + 8;
+           sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n - 1 );
+            sig->unhashed->size = n;
            sig->unhashed->len = n;
            if( iobuf_read(inp, sig->unhashed->data, n ) != n ) {
                log_error("premature eof while reading "
@@ -1247,6 +1269,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
 
     if( is_v4 && sig->pubkey_algo ) { /*extract required information */
        const byte *p;
+       size_t len;
 
        /* set sig->flags.unknown_critical if there is a
         * critical bit set for packets which we do not understand */
@@ -1258,17 +1281,19 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        }
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
-       if( !p )
-           log_error("signature packet without timestamp\n");
-       else
-           sig->timestamp = buffer_to_u32(p);
+       if(p)
+         sig->timestamp = buffer_to_u32(p);
+       else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
+         log_error("signature packet without timestamp\n");
+
        p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
-       if( !p )
-           log_error("signature packet without keyid\n");
-       else {
+       if(p)
+         {
            sig->keyid[0] = buffer_to_u32(p);
            sig->keyid[1] = buffer_to_u32(p+4);
-       }
+         }
+       else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110))
+         log_error("signature packet without keyid\n");
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
        if(p)
@@ -1280,6 +1305,10 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        if(p)
          sig->flags.policy_url=1;
 
+       p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,NULL);
+       if(p)
+         sig->flags.pref_ks=1;
+
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
        if(p)
          sig->flags.notation=1;
@@ -1288,6 +1317,23 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        if(p && *p==0)
          sig->flags.revocable=0;
 
+       p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_TRUST,&len);
+       if(p && len==2)
+         {
+           sig->trust_depth=p[0];
+           sig->trust_value=p[1];
+
+           /* Only look for a regexp if there is also a trust
+              subpacket. */
+           sig->trust_regexp=
+             parse_sig_subpkt(sig->hashed,SIGSUBPKT_REGEXP,&len);
+
+           /* If the regular expression is of 0 length, there is no
+              regular expression. */
+           if(len==0)
+             sig->trust_regexp=NULL;
+         }
+
        /* We accept the exportable subpacket from either the hashed
           or unhashed areas as older versions of gpg put it in the
           unhashed area.  In theory, anyway, we should never see this
@@ -1523,10 +1569,12 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        pk->max_expiredate = max_expiredate;
        pk->hdrbytes    = hdrlen;
        pk->version     = version;
+       pk->is_primary = pkttype == PKT_PUBLIC_KEY;
        pk->pubkey_algo = algorithm;
        pk->req_usage = 0; 
        pk->pubkey_usage = 0; /* not yet used */
         pk->is_revoked = 0;
+       pk->is_disabled = 0;
        pk->keyid[0] = 0;
        pk->keyid[1] = 0;
     }
@@ -1574,6 +1622,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                }
                 sk->protect.sha1chk = (sk->protect.algo == 254);
                sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
+               /* Note that a sk->protect.algo > 110 is illegal, but
+                  I'm not erroring on it here as otherwise there
+                  would be no way to delete such a key. */
                sk->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
                sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
                /* check for the special GNU extension */
@@ -1647,6 +1698,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                                            (ulong)sk->protect.s2k.count);
                }
            }
+           /* Note that a sk->protect.algo > 110 is illegal, but I'm
+              not erroring on it here as otherwise there would be no
+              way to delete such a key. */
            else { /* old version; no S2K, so we set mode to 0, hash MD5 */
                sk->protect.s2k.mode = 0;
                sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
@@ -1845,6 +1899,7 @@ static void setup_user_id(PACKET *packet)
   packet->pkt.user_id->help_key_usage = 0;
   packet->pkt.user_id->help_key_expire = 0;
   packet->pkt.user_id->prefs = NULL;
+  packet->pkt.user_id->namehash = NULL;
 }
 
 static int