See ChangeLog: Wed Apr 7 20:51:39 CEST 1999 Werner Koch
[gnupg.git] / g10 / import.c
index 0b5fdf2..5a739b9 100644 (file)
@@ -1,5 +1,5 @@
 /* import.c
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -51,8 +51,8 @@ static struct {
 } stats;
 
 
-static int read_block( IOBUF a, compress_filter_context_t *cfx,
-                            PACKET **pending_pkt, KBNODE *ret_root );
+static int import( IOBUF inp, int fast, const char* fname );
+static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
 static int import_one( const char *fname, KBNODE keyblock, int fast );
 static int import_secret_one( const char *fname, KBNODE keyblock );
 static int import_revoke_cert( const char *fname, KBNODE node );
@@ -106,22 +106,9 @@ static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs,
 int
 import_keys( const char *fname, int fast )
 {
-    armor_filter_context_t afx;
-    compress_filter_context_t cfx;
-    PACKET *pending_pkt = NULL;
     IOBUF inp = NULL;
-    KBNODE keyblock;
-    int rc = 0;
-    ulong count=0;
-
-    memset( &afx, 0, sizeof afx);
-    memset( &cfx, 0, sizeof cfx);
-    afx.only_keyblocks = 1;
-
-    /* fixme: don't use static variables */
-    memset( &stats, 0, sizeof( stats ) );
+    int rc;
 
-    /* open file */
     inp = iobuf_open(fname);
     if( !fname )
        fname = "[stdin]";
@@ -130,13 +117,38 @@ import_keys( const char *fname, int fast )
        return G10ERR_OPEN_FILE;
     }
 
+    rc = import( inp, fast, fname );
+
+    iobuf_close(inp);
+    return rc;
+}
+
+int
+import_keys_stream( IOBUF inp, int fast )
+{
+    return import( inp, fast, "[stream]" );
+}
+
+static int
+import( IOBUF inp, int fast, const char* fname )
+{
+    PACKET *pending_pkt = NULL;
+    KBNODE keyblock;
+    int rc = 0;
+    ulong count=0;
+
+    /* fixme: don't use static variables */
+    memset( &stats, 0, sizeof( stats ) );
 
     getkey_disable_caches();
 
-    if( !opt.no_armor ) /* armored reading is not disabled */
-       iobuf_push_filter( inp, armor_filter, &afx );
+    if( !opt.no_armor ) { /* armored reading is not disabled */
+       armor_filter_context_t *afx = m_alloc_clear( sizeof *afx );
+       afx->only_keyblocks = 1;
+       iobuf_push_filter2( inp, armor_filter, afx, 1 );
+    }
 
-    while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) {
+    while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
        if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
            rc = import_one( fname, keyblock, fast );
        else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
@@ -185,21 +197,18 @@ import_keys( const char *fname, int fast )
     if( stats.secret_dups )
        log_info(_(" secret keys unchanged: %lu\n"), stats.secret_dups );
 
-
-    iobuf_close(inp);
     return rc;
 }
 
 
 /****************
- * Read the next keyblock from stream A, CFX is used to handle
- * compressed keyblocks. PENDING_PKT should be initialzed to NULL
+ * Read the next keyblock from stream A.
+ * PENDING_PKT should be initialzed to NULL
  * and not chnaged form the caller.
  * Retunr: 0 = okay, -1 no more blocks or another errorcode.
  */
 static int
-read_block( IOBUF a, compress_filter_context_t *cfx,
-           PACKET **pending_pkt, KBNODE *ret_root )
+read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
 {
     int rc;
     PACKET *pkt;
@@ -244,9 +253,12 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
                rc = G10ERR_COMPR_ALGO;
                goto ready;
            }
-           cfx->algo = pkt->pkt.compressed->algorithm;
-           pkt->pkt.compressed->buf = NULL;
-           iobuf_push_filter( a, compress_filter, cfx );
+           {
+               compress_filter_context_t *cfx = m_alloc_clear( sizeof *cfx );
+               cfx->algo = pkt->pkt.compressed->algorithm;
+               pkt->pkt.compressed->buf = NULL;
+               iobuf_push_filter2( a, compress_filter, cfx, 1 );
+           }
            free_packet( pkt );
            init_packet(pkt);
            break;
@@ -706,6 +718,7 @@ chk_self_sigs( const char *fname, KBNODE keyblock,
                    log_error_f(fname,
                              _("key %08lX: no subkey for key binding\n"),
                                            (ulong)keyid[1]);
+                   n->flag |= 4; /* delete this */
                }
                else {
                    rc = check_key_signature( keyblock, n, NULL);
@@ -717,8 +730,8 @@ chk_self_sigs( const char *fname, KBNODE keyblock,
 
                        knode->flag |= 2; /* mark as invalid */
                    }
+                   knode->flag |= 1; /* mark that signature checked */
                }
-               knode->flag |= 1; /* mark that signature checked */
            }
        }
     }
@@ -737,6 +750,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
 {
     KBNODE node;
     int nvalid=0, uid_seen=0;
+    const char *p;
 
     for(node=keyblock->next; node; node = node->next ) {
        if( node->pkt->pkttype == PKT_USER_ID ) {
@@ -751,7 +765,10 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
                }
                delete_kbnode( node ); /* the user-id */
                /* and all following packets up to the next user-id */
-               while( node->next && node->next->pkt->pkttype != PKT_USER_ID ){
+               while( node->next
+                      && node->next->pkt->pkttype != PKT_USER_ID
+                      && node->next->pkt->pkttype != PKT_PUBLIC_SUBKEY
+                      && node->next->pkt->pkttype != PKT_SECRET_SUBKEY ){
                    delete_kbnode( node->next );
                    node = node->next;
                }
@@ -780,6 +797,21 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
                 && node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA )
            delete_kbnode( node ); /* build_packet() can't handle this */
        else if( node->pkt->pkttype == PKT_SIGNATURE
+                && (p = parse_sig_subpkt2( node->pkt->pkt.signature,
+                                           SIGSUBPKT_EXPORTABLE, NULL ))
+                && !*p
+                && seckey_available( node->pkt->pkt.signature->keyid ) ) {
+           /* here we violate the rfc a bit by still allowing
+            * to import non-exportable signature when we have the
+            * the secret key used to create this signature - it
+            * seems that this makes sense */
+           log_info_f(fname, _("key %08lX: non exportable signature "
+                                   "(class %02x) - skipped\n"),
+                                   (ulong)keyid[1],
+                                    node->pkt->pkt.signature->sig_class );
+           delete_kbnode( node );
+       }
+       else if( node->pkt->pkttype == PKT_SIGNATURE
                 && node->pkt->pkt.signature->sig_class == 0x20 )  {
            if( uid_seen ) {
                log_error_f(fname, _("key %08lX: revocation certificate "
@@ -797,6 +829,8 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
                }
            }
        }
+       else if( (node->flag & 4) ) /* marked for deletion */
+           delete_kbnode( node );
     }
 
     /* note: because keyblock is the public key, it is never marked