(parse_dn_part): Map common OIDs to human readable
[gnupg.git] / g10 / parse-packet.c
index c1a716b..c922eb5 100644 (file)
@@ -367,9 +367,29 @@ parse( iobuf_t 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 = gpg_error (GPG_ERR_INV_PACKET);
+                goto leave;
+            }
+       }
        else {
            for( ; lenbytes; lenbytes-- ) {
                pktlen <<= 8;
@@ -860,7 +880,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";
@@ -936,6 +957,7 @@ 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;
@@ -992,9 +1014,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:
@@ -1220,11 +1244,8 @@ parse_signature( iobuf_t 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 wasting this if there is a cache
-             * packet already, but in the other case it avoids an realloc */
-           sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n + 8 - 1 );
-            sig->unhashed->size = n + 8;
+           sig->unhashed = xmalloc (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 "
@@ -1259,17 +1280,19 @@ parse_signature( iobuf_t 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 {
-           sig->keyid[0] = buffer_to_u32(p);
-           sig->keyid[1] = buffer_to_u32(p+4);
+       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)
@@ -1281,6 +1304,10 @@ parse_signature( iobuf_t 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;
@@ -1342,7 +1369,8 @@ parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen,
        unknown_pubkey_warning( sig->pubkey_algo );
        /* we store the plain material in data[0], so that we are able
         * to write it back with build_packet() */
-       sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
+       sig->data[0] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen),
+                                           pktlen*8 );
        pktlen = 0;
     }
     else {
@@ -1446,7 +1474,7 @@ read_protected_v3_mpi (iobuf_t inp, unsigned long *length)
     }
 
   /* convert buffer into an opaque gcry_mpi_t */
-  val = mpi_set_opaque (NULL, buf, p-buf); 
+  val = gcry_mpi_set_opaque (NULL, buf, (p-buf)*8); 
   return val;
 }
 
@@ -1562,10 +1590,11 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
     if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
        PKT_secret_key *sk = pkt->pkt.secret_key;
        byte temp[16];
+        size_t snlen = 0;
 
        if( !npkey ) {
-           sk->skey[0] = mpi_set_opaque( NULL,
-                                         read_rest(inp, pktlen), pktlen );
+           sk->skey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen),
+                                               pktlen*8 );
            pktlen = 0;
            goto leave;
        }
@@ -1634,6 +1663,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
                    break;
                  case 1001: if( list_mode ) printf(  "\tgnu-dummy S2K" );
                    break;
+                 case 1002: if (list_mode) printf("\tgnu-divert-to-card S2K");
+                   break;
                  default:
                    if( list_mode )
                        printf(  "\tunknown %sS2K %d\n",
@@ -1669,6 +1700,19 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
                        printf("\tprotect count: %lu\n",
                                            (ulong)sk->protect.s2k.count);
                }
+               else if( sk->protect.s2k.mode == 1002 ) {
+                    /* Read the serial number. */
+                    if (pktlen < 1) {
+                       rc = GPG_ERR_INV_PACKET;
+                       goto leave;
+                   }
+                   snlen = iobuf_get (inp);
+                   pktlen--;
+                    if (pktlen < snlen || snlen == -1) {
+                       rc = GPG_ERR_INV_PACKET;
+                       goto leave;
+                    }
+               }
            }
            /* Note that a sk->protect.algo > 110 is illegal, but I'm
               not erroring on it here as otherwise there would be no
@@ -1698,7 +1742,12 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
            }
            if( sk->protect.s2k.mode == 1001 )
                sk->protect.ivlen = 0;
+           else if( sk->protect.s2k.mode == 1002 ) {
+                if (snlen > 16)
+                    log_info ("WARNING: serial number of card truncated\n");
+               sk->protect.ivlen = snlen < 16? snlen : 16;
 
+            }
            if( pktlen < sk->protect.ivlen ) {
                rc = GPG_ERR_INV_PACKET;
                goto leave;
@@ -1706,7 +1755,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
            for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
                temp[i] = iobuf_get_noeof(inp);
            if( list_mode ) {
-               printf(  "\tprotect IV: ");
+               printf( sk->protect.s2k.mode == 1002? "\tserial-number: "
+                                                    : "\tprotect IV: ");
                for(i=0; i < sk->protect.ivlen; i++ )
                    printf(" %02x", temp[i] );
                putchar('\n');
@@ -1719,17 +1769,19 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
         * If the user is so careless, not to protect his secret key,
         * we can assume, that he operates an open system :=(.
         * So we put the key into secure memory when we unprotect it. */
-       if( sk->protect.s2k.mode == 1001 ) {
+       if( sk->protect.s2k.mode == 1001
+            || sk->protect.s2k.mode == 1002 ) {
            /* better set some dummy stuff here */
-           sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup ("dummydata"), 10);
+           sk->skey[npkey] = gcry_mpi_set_opaque(NULL, xstrdup ("dummydata"),
+                                                  10*8);
            pktlen = 0;
        }
        else if( is_v4 && sk->is_protected ) {
            /* ugly; the length is encrypted too, so we read all
             * stuff up to the end of the packet into the first
             * skey element */
-           sk->skey[npkey] = mpi_set_opaque(NULL,
-                                            read_rest(inp, pktlen), pktlen );
+           sk->skey[npkey] = gcry_mpi_set_opaque(NULL, read_rest(inp, pktlen),
+                                                  pktlen*8 );
            pktlen = 0;
            if( list_mode ) {
                printf("\tencrypted stuff follows\n");
@@ -1769,8 +1821,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
        PKT_public_key *pk = pkt->pkt.public_key;
 
        if( !npkey ) {
-           pk->pkey[0] = mpi_set_opaque( NULL,
-                                         read_rest(inp, pktlen), pktlen );
+           pk->pkey[0] = gcry_mpi_set_opaque( NULL, read_rest(inp, pktlen),
+                                               pktlen*8 );
            pktlen = 0;
            goto leave;
        }