See ChangeLog: Fri Oct 6 14:29:16 CEST 2000 Werner Koch
authorWerner Koch <wk@gnupg.org>
Fri, 6 Oct 2000 12:28:44 +0000 (12:28 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 6 Oct 2000 12:28:44 +0000 (12:28 +0000)
18 files changed:
NEWS
configure.in
g10/ChangeLog
g10/delkey.c
g10/export.c
g10/getkey.c
g10/import.c
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/keyid.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/pkclist.c
g10/revoke.c
g10/ringedit.c
g10/skclist.c

diff --git a/NEWS b/NEWS
index 66d650a..3354d39 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ Noteworthy changes in the current CVS HEAD
 
     * Add Rijndael (AES) support.
 
+    * Removed gdbm support.
+
     * Fixed problems with piping to/from other MS-Windows software
 
     * Expiration time of the primary key can be changed again.
@@ -28,8 +30,6 @@ Noteworthy changes in the current CVS HEAD
     * Twofish and MDC enhanced encryption is now used.  PGP 7 supports 
       this.  Older versions of GnuPG don't support it, so they should be
       upgraded to at least 1.0.2
-      
-      
     
 
 Noteworthy changes in version 1.1.1
index 38d2c94..133e65b 100644 (file)
@@ -184,7 +184,6 @@ MPI_OPT_FLAGS=""
 
 
 try_gettext=yes
-try_gdbm=yes
 case "${target}" in
     *-*-mingw32*)
         # special stuff for Windoze NT
@@ -194,7 +193,6 @@ case "${target}" in
         AC_DEFINE(HAVE_DOSISH_SYSTEM)
         AC_DEFINE(USE_SIMPLE_GETTEXT)
         try_gettext="no"
-        try_gdbm="no"
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         # OS/2 with the EMX environment
@@ -202,7 +200,6 @@ case "${target}" in
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         AC_DEFINE(HAVE_DOSISH_SYSTEM)
         try_gettext="no"
-        try_gdbm="no"
         ;;
 
     i?86-*-msdosdjgpp*)
@@ -211,7 +208,6 @@ case "${target}" in
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         AC_DEFINE(HAVE_DOSISH_SYSTEM)
         try_gettext="no"
-        try_gdbm="no"
         ;;
 
     *-*-freebsd*)
@@ -331,19 +327,6 @@ fi
 AM_CONDITIONAL(COMPILE_AGENT, test x$compile_agent = xyes)
 
 
-
-dnl
-dnl There are lot of misconfigured systems.  We include
-dnl gdbm support only if the lib and the header is installed.
-dnl
-if test "$try_gdbm" = yes; then
-AC_CHECK_HEADERS(gdbm.h)
-if test "$ac_cv_header_gdbm_h" = yes ; then
-  AC_CHECK_LIB(gdbm,gdbm_firstkey)
-fi
-fi
-
-
 dnl Solaris needs -lsocket and -lnsl. Unisys system includes
 dnl gethostbyname in libsocket but needs libnsl for socket.
 AC_CHECK_LIB(nsl, gethostbyname)
index fb25e7f..127e54f 100644 (file)
@@ -1,3 +1,37 @@
+Fri Oct  6 14:29:16 CEST 2000  Werner Koch  <wk@openit.de>
+
+        Started to rework the whole getkey/ringedit stuff to make
+        it simpler, correcter and faster. 
+
+        * parse-packet.c (parse_packet): Add a 3rd arg to return the filepos.
+        Changed all callers.
+        * getkey.c (classify_user_id): Add new mode 21.
+        (find_by_fpr): Find using this new mode.
+        (get_seckey_byname): New arg to return the context. Changed all
+        callers.
+        * keyid.c (unified_fingerprint_from_pk): New.
+        (unified_fingerprint_from_sk): New.
+        * ringedit.c (find_keyblock_bypk): Changed to use the unified 
+        fingerprint for lookup.  I can't see a reason why we did compare
+        the entire public key.
+        (find_keyblock_bysk): Ditto.
+        (search,cmp_pubkey,cmp_seckey): Removed.
+        (keyring_search, do_kbxf_search): Removed.
+        (locate_keyblock_by_fpr,locate_keyblock_by_keyid): Removed.
+        (find_keyblock_byname): Removed use o search function.
+        (find_secret_keyblock_byname): Ditto.
+        (merge_public_with_secret): Fixed removing subkeys.
+        (premerge_public_with_secret): New.
+
+        * ringedit.c: Removed all GDBM support
+
+        * ringedit.c (read_keyblock): Removed.
+        * ringedit.c (find_keyblock_byname,find_secret_keyblock_byname,
+        find_keyblock_bypk,find_keyblock_bysk): Moved from here to ....
+        * getkey.c: ... here. Changed first arg to return a keyblock and
+        changed all callers to merge the old read_keyblock() with these
+        functions.       
+
 Wed Oct  4 13:16:18 CEST 2000  Werner Koch  <wk@openit.de>
 
         * getkey.c (merge_selfsigs_main): Fixed for v3 keys.
index 0c64d41..91413ed 100644 (file)
@@ -58,21 +58,14 @@ delete_key( const char *username, int secret )
     int yes;
 
     /* search the userid */
-    rc = secret? find_secret_keyblock_byname( &kbpos, username )
-              : find_keyblock_byname( &kbpos, username );
+    rc = secret? find_secret_keyblock_byname( &keyblock, username )
+              : find_keyblock_byname( &keyblock, username );
     if( rc ) {
-       log_error(_("%s: user not found\n"), username );
+       log_error(_("%s: user not found: %s\n"), username, gpg_errstr(rc) );
        write_status_text( STATUS_DELETE_PROBLEM, "1" );
        goto leave;
     }
 
-    /* read the keyblock */
-    rc = read_keyblock( &kbpos, &keyblock );
-    if( rc ) {
-       log_error("%s: read problem: %s\n", username, gpg_errstr(rc) );
-       goto leave;
-    }
-
     /* get the keyid from the keyblock */
     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
     if( !node ) {
index ddcc971..8b8ba48 100644 (file)
@@ -147,22 +147,15 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
        }
        else {
            /* search the userid */
-           rc = secret? find_secret_keyblock_byname( &kbpos, sl->d )
-                      : find_keyblock_byname( &kbpos, sl->d );
+           rc = secret? find_secret_keyblock_byname( &keyblock, sl->d )
+                      : find_keyblock_byname( &keyblock, sl->d );
            if( rc ) {
                log_error(_("%s: user not found: %s\n"), sl->d, gpg_errstr(rc));
                rc = 0;
                continue;
            }
-           /* read the keyblock */
-           rc = read_keyblock( &kbpos, &keyblock );
        }
 
-       if( rc ) {
-           log_error(_("certificate read problem: %s\n"), gpg_errstr(rc));
-           goto leave;
-       }
-      
 
        /* do not export keys which are incompatible with rfc2440 */
        if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
index aa32dff..a0fa445 100644 (file)
@@ -112,10 +112,6 @@ struct getkey_ctx_s {
     getkey_item_t items[1];
 };
 
-
-
-
-
 #if 0
 static struct {
     int any;
@@ -595,6 +591,8 @@ hextobyte( const byte *s )
  * 12 = it is a trustdb index (keyid is looked up)
  * 16 = it is a 16 byte fingerprint
  * 20 = it is a 20 byte fingerprint
+ * 21 = Unified fingerprint :fpr:pk_algo:
+ *      (We don't use pk_algo yet)
  *
  * if fprint is not NULL, it should be an array of at least 20 bytes.
  *
@@ -606,6 +604,8 @@ hextobyte( const byte *s )
  *   must be in the range 0..9), this is considered a fingerprint.
  * - If the username starts with a left angle, we assume it is a complete
  *   email address and look only at this part.
+ * - If the username starts with a colon we assume it is a unified 
+ *   key specfification. 
  * - If the username starts with a '.', we assume it is the ending
  *   part of an email address
  * - If the username starts with an '@', we assume it is a part of an
@@ -674,7 +674,32 @@ classify_user_id( const char *name, u32 *keyid, byte *fprint,
                    keyid[0] = keyid[1] = 0;
            }
            break;
-
+        
+        case ':': /*Unified fingerprint */
+            {  
+                const char *se, *si;
+                int i;
+                
+                se = strchr( ++s,':');
+                if ( !se )
+                    return 0;
+                for (i=0,si=s; si < se; si++, i++ ) {
+                    if ( !strchr("01234567890abcdefABCDEF", *si ) )
+                        return 0; /* invalid digit */
+                }
+                if (i != 32 && i != 40)
+                    return 0; /* invalid length of fpr*/
+               if (fprint) {
+                   for (i=0,si=s; si < se; i++, si +=2) 
+                       fprint[i] = hextobyte(si);
+                    for ( ; i < 20; i++)
+                        fprint[i]= 0;
+               }
+                s = se + 1;
+                mode = 21;
+            } 
+            break;
+           
        default:
            if (s[0] == '0' && s[1] == 'x') {
                hexprefix = 1;
@@ -803,7 +828,8 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
 
         /* if we don't use one of the exact key specifications, we assume that
          * the primary key is requested */
-        if ( mode != 10 && mode != 11 && mode != 16 && mode == 20 )
+        if ( mode != 10 && mode != 11
+             && mode != 16 && mode == 20 && mode != 21 )
             ctx->primary = 1; 
 
        ctx->items[n].mode = mode;
@@ -836,6 +862,10 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
         }
     }
 
+    if (!rc )
+       log_debug ( "pk_byname: kbpos %s %lu %p\n",
+                   ctx->kbpos.valid? "valid":"",
+                   ctx->kbpos.offset, ctx->kbpos.fp );
     release_kbnode ( help_kb );
 
     if( retctx ) /* caller wants the context */
@@ -883,6 +913,7 @@ get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
     return rc;
 }
 
+
 void
 get_pubkey_end( GETKEY_CTX ctx )
 {
@@ -897,8 +928,66 @@ get_pubkey_end( GETKEY_CTX ctx )
     }
 }
 
+
+
+/****************
+ * Combined function to search for a username and get the position
+ * of the keyblock.
+ */
+int
+find_keyblock_byname( KBNODE *retblock, const char *username )
+{
+    PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
+    int rc;
+
+    rc = get_pubkey_byname( NULL, pk, username, retblock );
+    free_public_key(pk);
+    return rc;
+}
+
+
+/****************
+ * Combined function to search for a key and get the position
+ * of the keyblock.  Used for merging while importing keys.
+ */
+int
+find_keyblock_bypk( KBNODE *retblock, PKT_public_key *pk )
+{
+    char ufpr[50];
+
+    unified_fingerprint_from_pk( pk, ufpr, sizeof ufpr );
+    return find_keyblock_byname( retblock, ufpr );
+}
+
+int 
+find_kblocation_bypk( void *re_opaque, PKT_public_key *pk )
+{
+    PKT_public_key *dummy_pk = gcry_xcalloc( 1, sizeof *pk );
+    char ufpr[50];
+    GETKEY_CTX ctx;
+    int rc;
+     
+    unified_fingerprint_from_pk( pk, ufpr, sizeof ufpr );
+    /* FIXME: There is no need to return any informaton, we just
+     * wnat to know the location.  Using the general lookup function
+     * has the problem that we might not get the key becuase it has expired
+     * or due to some similar probelm.  A solotion would be a locate-only
+     * flag in the ctx */
+    rc = get_pubkey_byname( &ctx, dummy_pk, ufpr, NULL );
+    free_public_key(dummy_pk);
+    if ( !rc )
+        ringedit_copy_kbpos( re_opaque, &ctx->kbpos );
+    get_pubkey_end( ctx );
+
+    return rc;
+}
+
+
 /****************
  * Search for a key with the given fingerprint.
+ * FIXME:
+ * We should replace this with the _byname function.  Thiscsan be done
+ * by creating a userID conforming to the unified fingerprint style. 
  */
 int
 get_pubkey_byfprint( PKT_public_key *pk,
@@ -988,19 +1077,23 @@ get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid )
  * If NAME is NULL use the default key
  */
 int
-get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect )
+get_seckey_byname( GETKEY_CTX *retctx,
+                   PKT_secret_key *sk, const char *name, int unprotect,
+                   KBNODE *retblock )
 {
     STRLIST namelist = NULL;
     int rc;
 
     if( !name && opt.def_secret_key && *opt.def_secret_key ) {
        add_to_strlist( &namelist, opt.def_secret_key );
-       rc = key_byname( NULL, namelist, NULL, sk, NULL );
+       rc = key_byname( retctx, namelist, NULL, sk, retblock );
     }
     else if( !name ) { /* use the first one as default key */
        struct getkey_ctx_s ctx;
         KBNODE kb = NULL;
 
+        assert (!retctx ); /* do we need this at all */
+        assert (!retblock);
        memset( &ctx, 0, sizeof ctx );
        ctx.not_allocated = 1;
        ctx.primary = 1;
@@ -1014,7 +1107,7 @@ get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect )
     }
     else {
        add_to_strlist( &namelist, name );
-       rc = key_byname( NULL, namelist, NULL, sk, NULL );
+       rc = key_byname( retctx, namelist, NULL, sk, retblock );
     }
 
     free_strlist( namelist );
@@ -1045,6 +1138,7 @@ get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock )
     return rc;
 }
 
+
 void
 get_seckey_end( GETKEY_CTX ctx )
 {
@@ -1052,6 +1146,57 @@ get_seckey_end( GETKEY_CTX ctx )
 }
 
 
+
+/****************
+ * Combined function to search for a username and get the position
+ * of the keyblock. This function does not unprotect the secret key.
+ */
+int
+find_secret_keyblock_byname( KBNODE *retblock, const char *username )
+{
+    PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
+    int rc;
+
+    rc = get_seckey_byname( NULL, sk, username, 0, retblock );
+    free_secret_key(sk);
+    return rc;
+}
+
+
+
+/****************
+ * Combined function to search for a key and get the position
+ * of the keyblock.
+ */
+int
+find_keyblock_bysk( KBNODE *retblock, PKT_secret_key *sk )
+{
+    char ufpr[50];
+
+    unified_fingerprint_from_sk( sk, ufpr, sizeof ufpr );
+    return find_secret_keyblock_byname( retblock, ufpr );
+}
+
+int 
+find_kblocation_bysk( void *re_opaque, PKT_secret_key *sk )
+{
+    PKT_secret_key *dummy_sk = gcry_xcalloc( 1, sizeof *sk );
+    char ufpr[50];
+    GETKEY_CTX ctx;
+    int rc;
+     
+    unified_fingerprint_from_sk( sk, ufpr, sizeof ufpr );
+    rc = get_seckey_byname( &ctx, dummy_sk, ufpr, 0, NULL );
+    free_secret_key(dummy_sk);
+    if ( !rc )
+        ringedit_copy_kbpos( re_opaque, &ctx->kbpos );
+    get_seckey_end( ctx );
+
+    return rc;
+}
+
+
+
 \f
 /*******************************************************
  ************** compare functions **********************
@@ -1728,8 +1873,6 @@ void
 merge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
 {
     KBNODE pub;
-    int deleting = 0;
-    int any_deleted = 0;
 
     assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY );
     assert ( secblock->pkt->pkttype == PKT_SECRET_KEY );
@@ -1750,7 +1893,6 @@ merge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
             KBNODE sec;
             PKT_public_key *pk = pub->pkt->pkt.public_key;
 
-            deleting = 0;
             /* this is more complicated: it may happen that the sequence
              * of the subkeys dosn't match, so we have to find the
              * appropriate secret key */
@@ -1766,26 +1908,57 @@ merge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
                     }
                 }
             }
+            if ( !sec ) 
+                BUG(); /* already checked in premerge */
+        }
+    }
+}
+
+/* This function checks that for every public subkey a corresponding
+ * secret subkey is avalable and deletes the public subkey otherwise.
+ * We need this function becuase we can'tdelete it later when we
+ * actually merge the secret parts into the pubring.
+ */
+void
+premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
+{
+    KBNODE last, pub;
+
+    assert ( pubblock->pkt->pkttype == PKT_PUBLIC_KEY );
+    assert ( secblock->pkt->pkttype == PKT_SECRET_KEY );
+    
+    for (pub=pubblock,last=NULL; pub; last = pub, pub = pub->next ) {
+        if ( pub->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
+            KBNODE sec;
+            PKT_public_key *pk = pub->pkt->pkt.public_key;
+
+            for (sec=secblock->next; sec; sec = sec->next ) {
+                if ( sec->pkt->pkttype == PKT_SECRET_SUBKEY ) {
+                    PKT_secret_key *sk = sec->pkt->pkt.secret_key;
+                    if ( !cmp_public_secret_key ( pk, sk ) ) 
+                        break;
+                }
+            }
             if ( !sec ) {
+                KBNODE next, ll;
                 log_error ( "no corresponding secret subkey "
                             "for public subkey - removing\n" );
-                /* better remove the public subkey in this case */
-                delete_kbnode ( pub );
-                deleting = 1;
-                any_deleted = 1;
+                /* we have to remove the subkey in this case */
+                assert ( last );
+                /* find the next subkey */
+                for (next=pub->next,ll=pub;
+                     next && pub->pkt->pkttype != PKT_PUBLIC_SUBKEY;
+                     ll = next, next = next->next ) 
+                    ;
+                /* make new link */
+                last->next = next;
+                /* release this public subkey with all sigs */
+                ll->next = NULL;
+                release_kbnode( pub );
+                /* let the loop continue */
+                pub = last;
             }
         }
-        else if ( deleting ) {
-            delete_kbnode (pub);
-        }
-    }
-
-    if ( any_deleted ) {
-        /* because we have not deleted the root node, we don't need to
-         * update the pubblock */
-        pub = pubblock;
-        commit_kbnode ( &pubblock );
-        assert ( pub == pubblock );
     }
 }
 
@@ -1859,8 +2032,17 @@ find_by_fpr( KBNODE keyblock,  const char *name, int mode )
            size_t an;
 
            fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
-           if( an == mode && !memcmp( afp, name, an) ) {
-                return k;
+            if ( mode == 21 ) {
+                /* Unified fingerprint. The fingerprint is always 20 bytes*/
+                while ( an < 20 )
+                    afp[an++] = 0;
+                if ( !memcmp( afp, name, 20 ) )
+                    return k;
+            }
+           else { 
+                if( an == mode && !memcmp( afp, name, an) ) {
+                    return k;
+                }
             }
        }
     }
@@ -2055,6 +2237,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
                 }
                 secblock = ctx->keyblock;
                 ctx->keyblock = k;
+                premerge_public_with_secret ( ctx->keyblock, secblock );
             }
 
 
@@ -2078,7 +2261,8 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
                else if( item->mode == 15 ) {
                    found = 1;
                 }
-               else if( item->mode == 16 || item->mode == 20 ) {
+               else if( item->mode == 16 || item->mode == 20
+                         || item->mode == 21 ) {
                    k = find_by_fpr( ctx->keyblock,
                                     item->fprint, item->mode );
                     found = !!k;
@@ -2218,7 +2402,7 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
 
        save_mode = set_packet_list_mode(0);
        init_packet(&pkt);
-       while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
+       while( (rc=parse_packet(c->iobuf, &pkt, NULL)) != -1 ) {
            if( rc )
                ; /* e.g. unknown packet */
            else if( pkt.pkttype == PKT_SECRET_KEY
index 94b83f0..fa21fbc 100644 (file)
@@ -274,7 +274,7 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
        in_cert = 0;
     pkt = gcry_xmalloc( sizeof *pkt );
     init_packet(pkt);
-    while( (rc=parse_packet(a, pkt)) != -1 ) {
+    while( (rc=parse_packet(a, pkt, NULL)) != -1 ) {
        if( rc ) {  /* ignore errors */
            if( rc != GPGERR_UNKNOWN_PACKET ) {
                log_error("read_block: read error: %s\n", gpg_errstr(rc) );
@@ -436,7 +436,7 @@ import_one( const char *fname, KBNODE keyblock, int fast )
        if( (rc=lock_keyblock( &kbpos )) )
           log_error(_("can't lock keyring `%s': %s\n"),
                       keyblock_resource_name(&kbpos), gpg_errstr(rc) );
-       else if( (rc=insert_keyblock( &kbpos, keyblock )) )
+       else if( (rc=insert_keyblock( keyblock )) )
           log_error( _("error writing keyring `%s': %s\n"),
                       keyblock_resource_name(&kbpos), gpg_errstr(rc) );
        unlock_keyblock( &kbpos );
@@ -466,18 +466,12 @@ import_one( const char *fname, KBNODE keyblock, int fast )
        }
 
        /* now read the original keyblock */
-       rc = find_keyblock_bypk( &kbpos, pk_orig );
+       rc = find_keyblock_bypk( &keyblock_orig, pk_orig );
        if( rc ) {
            log_error( _("key %08lX: can't locate original keyblock: %s\n"),
                                     (ulong)keyid[1], gpg_errstr(rc));
            goto leave;
        }
-       rc = read_keyblock( &kbpos, &keyblock_orig );
-       if( rc ) {
-           log_error( _("key %08lX: can't read original keyblock: %s\n"),
-                                           (ulong)keyid[1], gpg_errstr(rc));
-           goto leave;
-       }
 
        collapse_uids( &keyblock );
        /* and try to merge the block */
@@ -494,7 +488,7 @@ import_one( const char *fname, KBNODE keyblock, int fast )
            if( (rc=lock_keyblock( &kbpos )) )
               log_error( _("can't lock keyring `%s': %s\n"),
                          keyblock_resource_name(&kbpos), gpg_errstr(rc) );
-           else if( (rc=update_keyblock( &kbpos, keyblock_orig )) )
+           else if( (rc=update_keyblock( keyblock_orig )) )
                log_error( _("error writing keyring `%s': %s\n"),
                             keyblock_resource_name(&kbpos), gpg_errstr(rc) );
            unlock_keyblock( &kbpos );
@@ -603,7 +597,7 @@ import_secret_one( const char *fname, KBNODE keyblock )
        if( (rc=lock_keyblock( &kbpos )) )
            log_error( _("can't lock keyring `%s': %s\n"),
                         keyblock_resource_name(&kbpos), gpg_errstr(rc) );
-       else if( (rc=insert_keyblock( &kbpos, keyblock )) )
+       else if( (rc=insert_keyblock( keyblock )) )
            log_error( _("error writing keyring `%s': %s\n"),
                      keyblock_resource_name(&kbpos), gpg_errstr(rc) );
        unlock_keyblock( &kbpos );
@@ -659,18 +653,12 @@ import_revoke_cert( const char *fname, KBNODE node )
     }
 
     /* read the original keyblock */
-    rc = find_keyblock_bypk( &kbpos, pk );
+    rc = find_keyblock_bypk( &keyblock, pk );
     if( rc ) {
        log_error( _("key %08lX: can't locate original keyblock: %s\n"),
                                        (ulong)keyid[1], gpg_errstr(rc));
        goto leave;
     }
-    rc = read_keyblock( &kbpos, &keyblock );
-    if( rc ) {
-       log_error( _("key %08lX: can't read original keyblock: %s\n"),
-                                       (ulong)keyid[1], gpg_errstr(rc));
-       goto leave;
-    }
 
 
     /* it is okay, that node is not in keyblock because
@@ -704,7 +692,7 @@ import_revoke_cert( const char *fname, KBNODE node )
     if( (rc=lock_keyblock( &kbpos )) )
        log_error( _("can't lock keyring `%s': %s\n"),
                   keyblock_resource_name(&kbpos), gpg_errstr(rc) );
-    else if( (rc=update_keyblock( &kbpos, keyblock )) )
+    else if( (rc=update_keyblock( keyblock )) )
        log_error( _("error writing keyring `%s': %s\n"),
                    keyblock_resource_name(&kbpos), gpg_errstr(rc) );
     unlock_keyblock( &kbpos );
index 43c36e7..95d369e 100644 (file)
 #ifndef GPG_KEYDB_H
 #define GPG_KEYDB_H
 
-#ifdef HAVE_LIBGDBM
-  #include <gdbm.h>
-#endif
-
 #include "types.h"
 #include "basicdefs.h"
 #include "packet.h"
@@ -67,30 +63,16 @@ struct kbnode_struct {
 enum resource_type {
     rt_UNKNOWN = 0,
     rt_RING = 1,
-    rt_GDBM = 2,
-    rt_KBXF = 3
+    rt_KBXF = 2
 };
 
 
 /****************
- * A data structre to hold information about the external position
+ * A data structure to hold information about the external position
  * of a keyblock.
  */
-struct keyblock_pos_struct {
-    int   resno;     /* resource number */
-    enum resource_type rt;
-    ulong offset;    /* position information */
-    unsigned count;  /* length of the keyblock in packets */
-    IOBUF  fp;      /* used by enum_keyblocks */
-    int secret;      /* working on a secret keyring */
-  #ifdef HAVE_LIBGDBM
-    GDBM_FILE dbf;
-    byte keybuf[21];
-  #endif
-    PACKET *pkt;     /* ditto */
-    int valid;
-};
-typedef struct keyblock_pos_struct KBPOS;
+struct keyblock_pos_struct;
+typedef struct keyblock_pos_struct *KBPOS;
 
 /* structure to hold a couple of public key certificates */
 struct pk_list {
@@ -106,18 +88,6 @@ struct sk_list {
     int mark;
 };
 
-/* structure to collect all information which can be used to
- * identify a public key */
-typedef struct pubkey_find_info *PUBKEY_FIND_INFO;
-struct pubkey_find_info {
-    u32  keyid[2];
-    unsigned nbits;
-    byte pubkey_algo;
-    byte fingerprint[MAX_FINGERPRINT_LEN];
-    char userid[1];
-};
-
-
 
 /*-- pkclist.c --*/
 int  check_signatures_trust( PKT_signature *sig );
@@ -159,11 +129,18 @@ int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
                                                 size_t fprint_len );
 int get_keyblock_bylid( KBNODE *ret_keyblock, ulong lid );
 int seckey_available( u32 *keyid );
-int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
+int get_seckey_byname( GETKEY_CTX *rx,
+                       PKT_secret_key *sk, const char *name, int unlock,
+                       KBNODE *retblock );
 int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk,
                        STRLIST names, KBNODE *ret_keyblock );
 int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock );
 void get_seckey_end( GETKEY_CTX ctx );
+int find_keyblock_byname( KBNODE *retblock, const char *username );
+int find_secret_keyblock_byname( KBNODE *retblock, const char *username );
+int find_keyblock_bypk( KBNODE *retblock, PKT_public_key *pk );
+int find_keyblock_bysk( KBNODE *retblock, PKT_secret_key *sk );
+
 int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
 void merge_keys_and_selfsig( KBNODE keyblock );
 void merge_public_with_secret ( KBNODE pubblock, KBNODE secblock );
@@ -187,6 +164,10 @@ const char *expirestr_from_pk( PKT_public_key *pk );
 const char *expirestr_from_sk( PKT_secret_key *sk );
 byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
 byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
+char *unified_fingerprint_from_pk( PKT_public_key *pk,
+                                   char *buffer, size_t bufsize );
+char *unified_fingerprint_from_sk( PKT_secret_key *sk,
+                                   char *buffer, size_t bufsize );
 
 /*-- kbnode.c --*/
 KBNODE new_kbnode( PACKET *pkt );
@@ -208,25 +189,13 @@ void dump_kbnode( KBNODE node );
 /*-- ringedit.c --*/
 const char *enum_keyblock_resources( int *sequence, int secret );
 int add_keyblock_resource( const char *resname, int force, int secret );
-const char *keyblock_resource_name( KBPOS *kbpos );
-int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
+const char *keyblock_resource_name( KBPOS kbpos );
+int get_keyblock_handle( const char *filename, int secret, KBPOS kbpos );
 char *get_writable_keyblock_file( int secret );
-int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
-                                           int fprlen, int secret );
-int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,
-                                           int shortkid, int secret );
-int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
-int find_keyblock_byname( KBPOS *kbpos, const char *username );
-int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
-int find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk );
-int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
-int lock_keyblock( KBPOS *kbpos );
-void unlock_keyblock( KBPOS *kbpos );
-int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
-int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root );
-int insert_keyblock( KBPOS *kbpos, KBNODE root );
-int delete_keyblock( KBPOS *kbpos );
-int update_keyblock( KBPOS *kbpos, KBNODE root );
+int enum_keyblocks( int mode, KBPOS kbpos, KBNODE *ret_root );
+int insert_keyblock( KBNODE keyblock );
+int delete_keyblock( KBNODE keyblock );
+int update_keyblock( KBNODE keyblock );
 
 
 #endif /*GPG_KEYDB_H*/
index b7e8367..095e43b 100644 (file)
@@ -89,18 +89,13 @@ get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
 
     *keyblock = NULL;
     /* search the userid */
-    rc = find_keyblock_byname( kbpos, username );
+    rc = find_keyblock_byname( keyblock, username );
     if( rc ) {
-       log_error(_("%s: user not found\n"), username );
+       log_error(_("%s: user not found: %s\n"), username, gpg_errstr(rc) );
        return rc;
     }
 
-    /* read the keyblock */
-    rc = read_keyblock( kbpos, keyblock );
-    if( rc )
-       log_error("%s: keyblock read problem: %s\n", username, gpg_errstr(rc));
-    else
-       merge_keys_and_selfsig( *keyblock );
+    merge_keys_and_selfsig( *keyblock );
 
     return rc;
 }
@@ -616,7 +611,6 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
     KBNODE keyblock = NULL;
     KBPOS keyblockpos;
     KBNODE sec_keyblock = NULL;
-    KBPOS sec_keyblockpos;
     KBNODE cur_keyblock;
     char *answer = NULL;
     int redisplay = 1;
@@ -640,14 +634,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
 
     if( !sign_mode ) {
        /* first try to locate it as secret key */
-       rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
-       if( !rc ) {
-           rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
-           if( rc ) {
-               log_error("%s: secret keyblock read problem: %s\n",
+       rc = find_secret_keyblock_byname( &sec_keyblock, username );
+        if( rc && rc != GPGERR_NO_SECKEY ) 
+            log_debug("%s: secret keyblock read problem: %s\n",
                                                username, gpg_errstr(rc));
-               goto leave;
-           }
+       if( !rc ) {
            merge_keys_and_selfsig( sec_keyblock );
            if( fix_keyblock( sec_keyblock ) )
                sec_modified++;
@@ -966,14 +957,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
          do_cmd_save:
            if( modified || sec_modified  ) {
                if( modified ) {
-                   rc = update_keyblock( &keyblockpos, keyblock );
+                   rc = update_keyblock( keyblock );
                    if( rc ) {
                        log_error(_("update failed: %s\n"), gpg_errstr(rc) );
                        break;
                    }
                }
                if( sec_modified ) {
-                   rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
+                   rc = update_keyblock( sec_keyblock );
                    if( rc ) {
                        log_error(_("update secret failed: %s\n"),
                                                            gpg_errstr(rc) );
index ef0064f..d3887dd 100644 (file)
@@ -1752,9 +1752,9 @@ do_generate_keypair( struct para_data_s *para,
            log_error("can't lock public keyring: %s\n", gpg_errstr(rc) );
        else if( (rc=rc2=lock_keyblock( &sec_kbpos )) )
            log_error("can't lock secret keyring: %s\n", gpg_errstr(rc) );
-       else if( (rc=insert_keyblock( &pub_kbpos, pub_root )) )
+       else if( (rc=insert_keyblock( pub_root )) )
            log_error("can't write public key: %s\n", gpg_errstr(rc) );
-       else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
+       else if( (rc=insert_keyblock( sec_root )) )
            log_error("can't write secret key: %s\n", gpg_errstr(rc) );
        else {
            if( !opt.batch )
index a4acb16..0269a6b 100644 (file)
@@ -436,6 +436,40 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
     return array;
 }
 
+
+/* Create a unified fingerprint, that is a printable fingerprint along
+ * wth some other information suitable to passto get_pubkye_byname.
+ * Pass NULL for buffer to let this function allocate the buffer.
+ * This function will truncate the buffer in a way that a valid C string
+ * is returnd (unless bufsize is 0)
+ * Returns: Supplied buffer or newly allocated buffer
+ */
+char *
+unified_fingerprint_from_pk( PKT_public_key *pk,
+                             char *buffer, size_t bufsize )
+{
+    byte fpr[MAX_FINGERPRINT_LEN];
+    size_t fprlen;
+    int i;
+
+    fingerprint_from_pk( pk, fpr, &fprlen );
+    if ( !buffer ) {
+        bufsize = 1+fprlen*2+1+4+1+1;
+        buffer = gcry_xmalloc( bufsize );
+    }
+    if ( bufsize < 1+fprlen*2+1+4+1+1 ) {
+        /* Hmmm, that should be sufficiend also not very nice */
+        if ( bufsize )
+            *buffer = 0;
+        return buffer;
+    }
+    *buffer = ':';
+    for (i=0; i < fprlen; i++ )
+        sprintf( buffer+1+i*2, "%02X", fpr[i] );
+    sprintf( buffer+1+i*2, ":%d:", (pk->pubkey_algo & 0xff) );
+    return buffer;
+}
+
 byte *
 fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
 {
@@ -495,5 +529,36 @@ fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
     return array;
 }
 
+char *
+unified_fingerprint_from_sk( PKT_secret_key *sk,
+                             char *buffer, size_t bufsize )
+{
+    byte fpr[MAX_FINGERPRINT_LEN];
+    size_t fprlen;
+    int i;
+
+    fingerprint_from_sk( sk, fpr, &fprlen );
+    if ( !buffer ) {
+        bufsize = 1+fprlen*2+1+4+1+1;
+        buffer = gcry_xmalloc( bufsize );
+    }
+    if ( bufsize < 1+fprlen*2+1+4+1+1 ) {
+        /* Hmmm, that should be sufficiend also not very nice */
+        if ( bufsize )
+            *buffer = 0;
+        return buffer;
+    }
+    *buffer = ':';
+    for (i=0; i < fprlen; i++ )
+        sprintf( buffer+1+i*2, "%02X", fpr[i] );
+    sprintf( buffer+1+i*2, ":%d:", (sk->pubkey_algo & 0xff) );
+    return buffer;
+}
+
+
+
+
+
+
 
 
index 09c35db..7b04b3e 100644 (file)
@@ -953,7 +953,7 @@ do_proc_packets( CTX c, IOBUF a )
 
     c->iobuf = a;
     init_packet(pkt);
-    while( (rc=parse_packet(a, pkt)) != -1 ) {
+    while( (rc=parse_packet(a, pkt, NULL)) != -1 ) {
        any_data = 1;
        if( rc ) {
            free_packet(pkt);
index 03fa2ca..33bcf79 100644 (file)
@@ -293,18 +293,19 @@ int set_packet_list_mode( int mode );
 
 #if DEBUG_PARSE_PACKET
 int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos, const char* file, int lineno  );
-int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, const char* file, int lineno );
+int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, ulong *pos,
+                      const char* file, int lineno );
 int dbg_copy_all_packets( IOBUF inp, IOBUF out, const char* file, int lineno  );
 int dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff, const char* file, int lineno  );
 int dbg_skip_some_packets( IOBUF inp, unsigned n, const char* file, int lineno );
 #define search_packet( a,b,c,d )   dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ )
-#define parse_packet( a, b )      dbg_parse_packet( (a), (b), __FILE__, __LINE__ )
+#define parse_packet( a, b, c )           dbg_parse_packet( (a), (b), (c), __FILE__, __LINE__ )
 #define copy_all_packets( a,b )    dbg_copy_all_packets((a),(b), __FILE__, __LINE__ )
 #define copy_some_packets( a,b,c ) dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ )
 #define skip_some_packets( a,b )   dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
 #else
 int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
-int parse_packet( IOBUF inp, PACKET *ret_pkt);
+int parse_packet( IOBUF inp, PACKET *ret_pkt, ulong *retpos);
 int copy_all_packets( IOBUF inp, IOBUF out );
 int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
 int skip_some_packets( IOBUF inp, unsigned n );
index 3cabe77..b22a599 100644 (file)
@@ -127,23 +127,25 @@ unknown_pubkey_warning( int algo )
  */
 #ifdef DEBUG_PARSE_PACKET
 int
-dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
+dbg_parse_packet( IOBUF inp, PACKET *pkt, ulong *retpos,
+                  const char *dbg_f, int dbg_l )
 {
     int skip, rc;
 
     do {
-       rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l );
+       rc = parse( inp, pkt, 0, retpos,
+                    &skip, NULL, 0, "parse", dbg_f, dbg_l );
     } while( skip );
     return rc;
 }
 #else
 int
-parse_packet( IOBUF inp, PACKET *pkt )
+parse_packet( IOBUF inp, PACKET *pkt, ulong *retpos )
 {
     int skip, rc;
 
     do {
-       rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
+       rc = parse( inp, pkt, 0, retpos, &skip, NULL, 0 );
     } while( skip );
     return rc;
 }
index d585880..1170c40 100644 (file)
@@ -779,7 +779,7 @@ default_recipient(void)
     if( !opt.def_recipient_self )
        return NULL;
     sk = gcry_xcalloc( 1, sizeof *sk );
-    i = get_seckey_byname( sk, NULL, 0 );
+    i = get_seckey_byname( NULL, sk, NULL, 0, NULL );
     if( i ) {
        free_secret_key( sk );
        return NULL;
index 4abd5ed..e988e5e 100644 (file)
@@ -87,7 +87,6 @@ gen_revoke( const char *uname )
     IOBUF out = NULL;
     KBNODE keyblock = NULL;
     KBNODE node;
-    KBPOS kbpos;
     struct revocation_reason_info *reason = NULL;
 
     if( opt.batch ) {
@@ -102,16 +101,10 @@ gen_revoke( const char *uname )
 
 
     /* search the userid */
-    rc = find_secret_keyblock_byname( &kbpos, uname );
+    rc = find_secret_keyblock_byname( &keyblock, uname );
     if( rc ) {
-       log_error(_("secret key for user `%s' not found\n"), uname );
-       goto leave;
-    }
-
-    /* read the keyblock */
-    rc = read_keyblock( &kbpos, &keyblock );
-    if( rc ) {
-       log_error(_("error reading the certificate: %s\n"), gpg_errstr(rc) );
+       log_error(_("secret key for user `%s' not found: %s\n"),
+                  uname, gpg_errstr(rc) );
        goto leave;
     }
 
index 311cf41..de05ba6 100644 (file)
@@ -48,9 +48,6 @@
 #include <sys/stat.h>
 #include <unistd.h> /* for truncate */
 #include <assert.h>
-#ifdef HAVE_LIBGDBM
-  #include <gdbm.h>
-#endif
 
 #include <gcrypt.h>
 #include "util.h"
@@ -71,47 +68,42 @@ struct resource_table_struct {
     int secret; /* this is a secret keyring */
     char *fname;
     IOBUF iobuf;
-  #ifdef HAVE_LIBGDBM
-    GDBM_FILE dbf;
-  #endif
     enum resource_type rt;
     DOTLOCK lockhd;
     int    is_locked;
 };
 typedef struct resource_table_struct RESTBL;
 
+
+struct keyblock_pos_struct {
+    int   resno;     /* resource number */
+    enum resource_type rt;
+    ulong offset;    /* position information */
+    unsigned count;  /* length of the keyblock in packets */
+    IOBUF  fp;      /* used by enum_keyblocks */
+    int secret;      /* working on a secret keyring */
+    PACKET *pkt;     /* ditto */
+    int valid;
+    ulong save_offset;
+};
+
+
+
+
 #define MAX_RESOURCES 10
 static RESTBL resource_table[MAX_RESOURCES];
 static int default_public_resource;
 static int default_secret_resource;
 
-static int search( PACKET *pkt, KBPOS *kbpos, int secret );
-
-
-static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
-                                               const char *fname );
-static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
-static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
-static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
+static int keyring_enum( KBPOS kbpos, KBNODE *ret_root, int skipsigs );
+static int keyring_copy( KBPOS kbpos, int mode, KBNODE root );
 
-static int do_kbxf_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
-                                               const char *fname );
-static int do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root );
-static int do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
-static int do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root );
-
-#ifdef HAVE_LIBGDBM
-static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
-static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
-                                         const byte *fpr, int fprlen );
-static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );
-static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root );
-static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root );
-#endif
+static int do_kbxf_enum( KBPOS kbpos, KBNODE *ret_root, int skipsigs );
+static int do_kbxf_copy( KBPOS kbpos, int mode, KBNODE root );
 
 
 static RESTBL *
-check_pos( KBPOS *kbpos )
+check_pos( KBPOS kbpos )
 {
     if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
        return NULL;
@@ -120,15 +112,6 @@ check_pos( KBPOS *kbpos )
     return resource_table + kbpos->resno;
 }
 
-#ifdef HAVE_LIBGDBM
-static void
-fatal_gdbm_error( const char *string )
-{
-    log_fatal("gdbm failed: %s\n", string);
-}
-
-#endif /* HAVE_LIBGDBM */
-
 
 /****************
  * Hmmm, how to avoid deadlock? They should not happen if everyone
@@ -208,7 +191,6 @@ add_keyblock_resource( const char *url, int force, int secret )
 
 
     /* Do we have an URL?
-     * gnupg-gdbm:filename  := this is a GDBM resource
      * gnupg-kbxf:filename  := this is a KBX file resource
      * gnupg-ring:filename  := this is a plain keyring
      * filename := See what is is, but create as plain keyring.
@@ -222,10 +204,6 @@ add_keyblock_resource( const char *url, int force, int secret )
            rt = rt_KBXF;
            resname += 11;
        }
-       else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
-           rt = rt_GDBM;
-           resname += 11;
-       }
       #ifndef HAVE_DRIVE_LETTERS
        else if( strchr( resname, ':' ) ) {
            log_error("%s: invalid URL\n", url );
@@ -263,22 +241,16 @@ add_keyblock_resource( const char *url, int force, int secret )
            u32 magic;
 
            if( fread( &magic, 4, 1, fp) == 1 ) {
-               if( magic == 0x13579ace )
-                   rt = rt_GDBM;
-               else if( magic == 0xce9a5713 )
-                   log_error("%s: endianess does not match\n", url );
-               else {
-                   char buf[8];
-
-                   rt = rt_RING;
-                   if( fread( buf, 8, 1, fp) == 1 ) {
-                       if( !memcmp( buf+4, "KBXf", 4 )
-                           && buf[0] == 1 && buf[1] == 1 ) {
-                           rt = rt_KBXF;
-                       }
-                   }
-               }
-           }
+                char buf[8];
+
+                rt = rt_RING;
+                if( fread( buf, 8, 1, fp) == 1 ) {
+                    if( !memcmp( buf+4, "KBXf", 4 )
+                        && buf[0] == 1 && buf[1] == 1 ) {
+                        rt = rt_KBXF;
+                    }
+                }
+                           }
            else /* maybe empty: assume ring */
                rt = rt_RING;
            fclose( fp );
@@ -348,21 +320,6 @@ add_keyblock_resource( const char *url, int force, int secret )
       #endif
        break;
 
-    #ifdef HAVE_LIBGDBM
-      case rt_GDBM:
-       resource_table[i].dbf = gdbm_open( filename, 0,
-                                          force? GDBM_WRCREAT : GDBM_WRITER,
-                                          S_IRUSR | S_IWUSR |
-                                          S_IRGRP | S_IWGRP | S_IROTH,
-                                          fatal_gdbm_error );
-       if( !resource_table[i].dbf ) {
-           log_error("%s: can't open gdbm file: %s\n",
-                           filename, gdbm_strerror(gdbm_errno));
-           rc = GPGERR_OPEN_FILE;
-           goto leave;
-       }
-       break;
-    #endif
 
       default:
        log_error("%s: unsupported resource type\n", url );
@@ -403,7 +360,7 @@ add_keyblock_resource( const char *url, int force, int secret )
  * Return the resource name of the keyblock associated with KBPOS.
  */
 const char *
-keyblock_resource_name( KBPOS *kbpos )
+keyblock_resource_name( KBPOS kbpos )
 {
     RESTBL *rentry;
 
@@ -419,7 +376,7 @@ keyblock_resource_name( KBPOS *kbpos )
  * Using a filename of NULL returns the default resource
  */
 int
-get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
+get_keyblock_handle( const char *filename, int secret, KBPOS kbpos )
 {
     int i = 0;
 
@@ -471,253 +428,21 @@ get_writable_keyblock_file( int secret )
 }
 
 
-/****************
- * Search a keyblock which starts with the given packet and puts all
- * information into KBPOS, which can be used later to access this key block.
- * This function looks into all registered keyblock sources.
- * PACKET must be a packet with either a secret_key or a public_key
- *
- * This function is intended to check whether a given certificate
- * is already in a keyring or to prepare it for editing.
- *
- * Returns: 0 if found, -1 if not found or an errorcode.
- */
-static int
-search( PACKET *pkt, KBPOS *kbpos, int secret )
-{
-    int i, rc, last_rc=-1;
-
-    for(i=0; i < MAX_RESOURCES; i++ ) {
-       if( resource_table[i].used && !resource_table[i].secret == !secret ) {
-           switch( resource_table[i].rt ) {
-             case rt_RING:
-               rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
-                                                resource_table[i].fname );
-               break;
-             case rt_KBXF:
-               rc = do_kbxf_search( pkt, kbpos, resource_table[i].iobuf,
-                                                resource_table[i].fname );
-               break;
-            #ifdef HAVE_LIBGDBM
-             case rt_GDBM: {
-                   PKT_public_key *req_pk = pkt->pkt.public_key;
-                   byte fpr[20];
-                   size_t fprlen;
-
-                   fingerprint_from_pk( req_pk, fpr, &fprlen );
-                   rc = do_gdbm_locate( resource_table[i].dbf,
-                                        kbpos, fpr, fprlen );
-               }
-               break;
-            #endif
-             default: BUG();
-           }
-
-           kbpos->rt = resource_table[i].rt;
-           if( !rc ) {
-               kbpos->resno = i;
-               kbpos->fp = NULL;
-               return 0;
-           }
-           if( rc != -1 ) {
-               log_error("error searching resource %d: %s\n",
-                                                 i, gpg_errstr(rc));
-               last_rc = rc;
-           }
-       }
-    }
-    return last_rc;
-}
-
-
-/****************
- * Combined function to search for a username and get the position
- * of the keyblock.
- */
-int
-find_keyblock_byname( KBPOS *kbpos, const char *username )
-{
-    PACKET pkt;
-    PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
-    int rc;
-
-    rc = get_pubkey_byname( NULL, pk, username, NULL );
-    if( rc ) {
-       free_public_key(pk);
-       return rc;
-    }
-
-    init_packet( &pkt );
-    pkt.pkttype = PKT_PUBLIC_KEY;
-    pkt.pkt.public_key = pk;
-    rc = search( &pkt, kbpos, 0 );
-    free_public_key(pk);
-    return rc;
-}
-
-
-/****************
- * Combined function to search for a key and get the position
- * of the keyblock.
- */
-int
-find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
-{
-    PACKET pkt;
-    int rc;
-
-    init_packet( &pkt );
-    pkt.pkttype = PKT_PUBLIC_KEY;
-    pkt.pkt.public_key = pk;
-    rc = search( &pkt, kbpos, 0 );
-    return rc;
-}
-
-/****************
- * Combined function to search for a key and get the position
- * of the keyblock.
- */
-int
-find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk )
-{
-    PACKET pkt;
-    int rc;
-
-    init_packet( &pkt );
-    pkt.pkttype = PKT_SECRET_KEY;
-    pkt.pkt.secret_key = sk;
-    rc = search( &pkt, kbpos, 0 );
-    return rc;
-}
-
-
-/****************
- * Combined function to search for a username and get the position
- * of the keyblock. This function does not unprotect the secret key.
- */
-int
-find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
-{
-    PACKET pkt;
-    PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
-    int rc;
-
-    rc = get_seckey_byname( sk, username, 0 );
-    if( rc ) {
-       free_secret_key(sk);
-       return rc;
-    }
-
-    init_packet( &pkt );
-    pkt.pkttype = PKT_SECRET_KEY;
-    pkt.pkt.secret_key = sk;
-    rc = search( &pkt, kbpos, 1 );
-    free_secret_key(sk);
-    return rc;
-}
-
-
-/****************
- * Locate a keyblock in a database which is capable of direct access
- * Put all information into KBPOS, which can be later be to access this
- * key block.
- * This function looks into all registered keyblock sources.
- *
- * Returns: 0 if found,
- *         -1 if not found
- *         GPGERR_UNSUPPORTED if no resource is able to handle this
- *         or another errorcode.
- */
-int
-locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret )
-{
-    RESTBL *rentry;
-    int i, rc, any=0, last_rc=-1;
-
-
-    for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
-       if( rentry->used && !rentry->secret == !secret ) {
-           kbpos->rt = rentry->rt;
-           switch( rentry->rt ) {
-            #ifdef HAVE_LIBGDBM
-             case rt_GDBM:
-               any = 1;
-               rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
-               break;
-            #endif
-             default:
-               rc = GPGERR_UNSUPPORTED;
-               break;
-           }
-
-           if( !rc ) {
-               kbpos->resno = i;
-               kbpos->fp = NULL;
-               return 0;
-           }
-           else if( rc != -1 && rc != GPGERR_UNSUPPORTED ) {
-               log_error("error searching resource %d: %s\n",
-                                                 i, gpg_errstr(rc));
-               last_rc = rc;
-           }
-       }
-    }
-
-    return (last_rc == -1 && !any)? GPGERR_UNSUPPORTED : last_rc;
-}
-
-
-int
-locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret )
+void
+ringedit_copy_kbpos ( KBPOS d, KBPOS s )
 {
-    RESTBL *rentry;
-    int i, rc, any=0, last_rc=-1;
-
-    if( shortkid )
-       return GPGERR_UNSUPPORTED;
-
-    for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
-       if( rentry->used && !rentry->secret == !secret ) {
-           kbpos->rt = rentry->rt;
-           switch( rentry->rt ) {
-            #ifdef HAVE_LIBGDBM
-             case rt_GDBM:
-               any = 1;
-               rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
-               break;
-            #endif
-             default:
-               rc = GPGERR_UNSUPPORTED;
-               break;
-           }
-
-           if( !rc ) {
-               kbpos->resno = i;
-               kbpos->fp = NULL;
-               return 0;
-           }
-           else if( rc != -1 && rc != GPGERR_UNSUPPORTED ) {
-               log_error("error searching resource %d: %s\n",
-                                                 i, gpg_errstr(rc));
-               last_rc = rc;
-           }
-       }
-    }
-
-    return (last_rc == -1 && !any)? GPGERR_UNSUPPORTED : last_rc;
+    *d = *s;
 }
 
 
-
-
 /****************
  * Lock the keyblock; wait until it's available
  * This function may change the internal data in kbpos, in cases
  * when the keyblock to be locked has been modified.
  * fixme: remove this function and add an option to search()?
  */
-int
-lock_keyblock( KBPOS *kbpos )
+static int
+lock_keyblock( KBPOS kbpos )
 {
     if( !check_pos(kbpos) )
        return GPGERR_GENERAL;
@@ -727,35 +452,13 @@ lock_keyblock( KBPOS *kbpos )
 /****************
  * Release a lock on a keyblock
  */
-void
-unlock_keyblock( KBPOS *kbpos )
+static void
+unlock_keyblock( KBPOS kbpos )
 {
     if( !check_pos(kbpos) )
        BUG();
 }
 
-/****************
- * Read a complete keyblock and return the root in ret_root.
- */
-int
-read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
-{
-    if( !check_pos(kbpos) )
-       return GPGERR_GENERAL;
-
-    switch( kbpos->rt ) {
-      case rt_RING:
-       return keyring_read( kbpos, ret_root );
-      case rt_KBXF:
-       return do_kbxf_read( kbpos, ret_root );
-     #ifdef HAVE_LIBGDBM
-      case rt_GDBM:
-       return do_gdbm_read( kbpos, ret_root );
-     #endif
-      default: BUG();
-    }
-}
-
 
 /****************
  * This functions can be used to read through a complete keyring.
@@ -765,13 +468,9 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
  *         5 = open secret keyrings
  *         11 = read but skip signature and comment packets.
  *         all others are reserved!
- * Note that you do not need a search prior to this function,
- * only a handle is needed.
- * NOTE: It is not allowed to do an insert/update/delete with this
- *      keyblock, if you want to do this, use search/read!
  */
 int
-enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
+enum_keyblocks( int mode, KBPOS kbpos, KBNODE *ret_root )
 {
     int rc = 0;
     RESTBL *rentry;
@@ -811,12 +510,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
                return GPGERR_OPEN_FILE;
            }
            break;
-        #ifdef HAVE_LIBGDBM
-         case rt_GDBM:
-           /* FIXME: make sure that there is only one enum at a time */
-           kbpos->offset = 0;
-           break;
-        #endif
+
          default: BUG();
        }
        kbpos->pkt = NULL;
@@ -836,11 +530,6 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
                    return GPGERR_GENERAL;
                rc = do_kbxf_enum( kbpos, ret_root, mode == 11 );
                break;
-            #ifdef HAVE_LIBGDBM
-             case rt_GDBM:
-               rc = do_gdbm_enum( kbpos, ret_root );
-               break;
-            #endif
              default: BUG();
            }
 
@@ -866,8 +555,6 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
                kbpos->fp = NULL;
            }
            break;
-         case rt_GDBM:
-           break;
          case rt_UNKNOWN:
            /* this happens when we have no keyring at all */
            return rc;
@@ -890,10 +577,10 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
  * by KBPOS.  This actually appends the data to the keyfile.
  */
 int
-insert_keyblock( KBPOS *kbpos, KBNODE root )
+insert_keyblock( KBNODE root )
 {
     int rc;
-
+#if 0
     if( !check_pos(kbpos) )
        return GPGERR_GENERAL;
 
@@ -904,14 +591,9 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
       case rt_KBXF:
        rc = do_kbxf_copy( kbpos, 1, root );
        break;
-     #ifdef HAVE_LIBGDBM
-      case rt_GDBM:
-       rc = do_gdbm_store( kbpos, root, 0 );
-       break;
-     #endif
       default: BUG();
     }
-
+#endif
     return rc;
 }
 
@@ -922,378 +604,69 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
  * zero bytes are written.
  */
 int
-delete_keyblock( KBPOS *kbpos )
+delete_keyblock( KBNODE keyblock )
 {
     int rc;
-
-    if( !check_pos(kbpos) )
-       return GPGERR_GENERAL;
-
-    switch( kbpos->rt ) {
-      case rt_RING:
-       rc = keyring_copy( kbpos, 2, NULL );
-       break;
-      case rt_KBXF:
-       rc = do_kbxf_copy( kbpos, 2, NULL );
-       break;
-     #ifdef HAVE_LIBGDBM
-      case rt_GDBM:
-       log_debug("deleting gdbm keyblock is not yet implemented\n");
-       rc = 0;
-       break;
-     #endif
-      default: BUG();
-    }
-
-    return rc;
-}
-
-
-/****************
- * Update the keyblock at KBPOS with the one in ROOT.
- */
-int
-update_keyblock( KBPOS *kbpos, KBNODE root )
-{
-    int rc;
-
-    if( !check_pos(kbpos) )
-       return GPGERR_GENERAL;
-
-    switch( kbpos->rt ) {
-      case rt_RING:
-       rc = keyring_copy( kbpos, 3, root );
-       break;
-      case rt_KBXF:
-       rc = do_kbxf_copy( kbpos, 3, root );
-       break;
-     #ifdef HAVE_LIBGDBM
-      case rt_GDBM:
-       rc = do_gdbm_store( kbpos, root, 1 );
-       break;
-     #endif
-      default: BUG();
-    }
-
-    return rc;
-}
-
-
-\f
-/****************************************************************
- ********** Implemenation of a user ID database    **************
- ****************************************************************/
-#if 0
-/****************
- * Layout of the user ID db
- *
- * This user ID DB provides fast lookup of user ID, but the user ids are
- * not in any specific order.
- *
- * A string "GnuPG user db", a \n.
- * user ids of one key, delimited by \t,
- * a # or ^ followed by a 20 byte fingerprint, followed by an \n
- * The literal characters %, \n, \t, #, ^ must be replaced by a percent sign
- * and their hex value.
- *
- * (We use Boyer/Moore pattern matching)
- */
-
-/****************
- * This compiles pattern to the distance table, the table will be allocate
- * here and must be freed by using free().
- * Returns: Ptr to new allocated Table
- *         Caller must free the table.
- */
-
-static size_t *
-compile_bm_table( const byte *pattern, size_t len )
-{
-    ushort *dist;
-    int i;
-
-    dist = gcry_xcalloc( 1, 256 * sizeof *dist );
-    for(i=0; i < 256; i++ )
-       dist[i] = len;
-    for(i=0; i < len-1; i++ )
-       dTbl[p[i]] = len-i-1;
-    return dist;
-}
-
-
-
-
-/****************
- * Search BUF of BUFLEN for pattern P of length PATLEN.
- * dist is the Boyer/Moore distance table of 256 Elements,
- * case insensitive search is done if IGNCASE is true (In this case
- * the distance table has to compiled from uppercase chacaters and
- * PAT must also be uppercase.
- * Returns: Prt to maching string in BUF, or NULL if not found.
- */
-
-static const *
-do_bm_search( const byte *buf, size_t buflen,
-             const byte *pat, size_t patlen, size_t *dist, int igncase )
-{
-    int i, j, k;
-
-    if( igncase ) {
-       int c, c1;
-
-       for( i = --patlen; i < buflen; i += dist[c1] )
-           for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
-                                         j--, k--, c=toupper(buf[k]) ) {
-               if( !j )
-                   return buf+k;
-           }
-    }
-    else {
-       for( i = --patlen; i < buflen; i += dist[buf[i]] )
-           for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
-               if( !j )
-                   return buf+k;
-           }
-    }
-    return NULL;
-}
-
-
-typedef struct {
-    size_t dist[256];
-} *SCAN_USER_HANDLE;
-
-static SCAN_USER_HANDLE
-scan_user_file_open( const byte *name )
-{
-    SCAN_USER_HANDLE hd;
-    size_t *dist;
-    int i;
-
-    hd = gcry_xcalloc( 1, sizeof *hd );
-    dist = hd->dist;
-    /* compile the distance table */
-    for(i=0; i < 256; i++ )
-       dist[i] = len;
-    for(i=0; i < len-1; i++ )
-       dTbl[p[i]] = len-i-1;
-    /* setup other things */
-
-    return hd;
-}
-
-static int
-scan_user_file_close( SCAN_USER_HANDLE hd )
-{
-    gcry_free( hd );
-}
-
-static int
-scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
-{
-    char record[1000];
-
-    /* read a record */
-
-
-}
-#endif
-
-
-\f
-/****************************************************************
- ********** Functions which operates on regular keyrings ********
- ****************************************************************/
-
-static int
-cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
-{
-    int n,i;
-
-    assert( req_sk->pubkey_algo == sk->pubkey_algo );
-
-    n = pubkey_get_nskey( req_sk->pubkey_algo );
-    for(i=0; i < n; i++ ) {
-        /* Note: because v4 protected keys have nothing in the
-         * mpis except for the first one, we skip all NULL MPIs.
-         * This might not be always correct in cases where the both
-         * keys do not match in their secret parts but we can ignore that
-         * because the need for this function is quite ugly. */
-       if( req_sk->skey[1] && sk->skey[i]
-             && mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
-           return -1;
-    }
-    return 0;
-}
-
-static int
-cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
-{
-    int n, i;
-
-    assert( req_pk->pubkey_algo == pk->pubkey_algo );
-
-    n = pubkey_get_npkey( req_pk->pubkey_algo );
-    for(i=0; i < n; i++ ) {
-       if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] )  )
-           return -1;
-    }
-    return 0;
-}
-
-/****************
- * search one keyring, return 0 if found, -1 if not found or an errorcode.
- */
-static int
-keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
-{
-    int rc;
-    PACKET pkt;
-    int save_mode;
-    ulong offset;
-    int pkttype = req->pkttype;
-    PKT_public_key *req_pk = req->pkt.public_key;
-    PKT_secret_key *req_sk = req->pkt.secret_key;
-
-    init_packet(&pkt);
-    save_mode = set_packet_list_mode(0);
-    kbpos->rt = rt_RING;
-    kbpos->valid = 0;
-
-  #if HAVE_DOSISH_SYSTEM || 1
-    assert(!iobuf);
-    iobuf = iobuf_open( fname );
-    if( !iobuf ) {
-       log_error("%s: can't open keyring file\n", fname);
-       rc = GPGERR_KEYRING_OPEN;
-       goto leave;
-    }
-  #else
-    if( iobuf_seek( iobuf, 0 ) ) {
-       log_error("can't rewind keyring file\n");
-       rc = GPGERR_KEYRING_OPEN;
-       goto leave;
-    }
-  #endif
-
-    while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
-       if( pkt.pkttype == PKT_SECRET_KEY ) {
-           PKT_secret_key *sk = pkt.pkt.secret_key;
-
-           if(   req_sk->timestamp == sk->timestamp
-              && req_sk->pubkey_algo == sk->pubkey_algo
-              && !cmp_seckey( req_sk, sk) )
-               break; /* found */
-       }
-       else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
-           PKT_public_key *pk = pkt.pkt.public_key;
-
-           if(   req_pk->timestamp == pk->timestamp
-              && req_pk->pubkey_algo == pk->pubkey_algo
-              && !cmp_pubkey( req_pk, pk ) )
-               break; /* found */
-       }
-       else
-           BUG();
-       free_packet(&pkt);
-    }
-    if( !rc ) {
-       kbpos->offset = offset;
-       kbpos->valid = 1;
-    }
-
-  leave:
-    free_packet(&pkt);
-    set_packet_list_mode(save_mode);
-  #if HAVE_DOSISH_SYSTEM || 1
-    iobuf_close(iobuf);
-  #endif
-    return rc;
-}
-
-
-static int
-keyring_read( KBPOS *kbpos, KBNODE *ret_root )
-{
-    PACKET *pkt;
-    int rc;
-    RESTBL *rentry;
-    KBNODE root = NULL;
-    IOBUF a;
-    int in_cert = 0;
-
-    if( !(rentry=check_pos(kbpos)) )
-       return GPGERR_GENERAL;
-
-    a = iobuf_open( rentry->fname );
-    if( !a ) {
-       log_error("can't open `%s'\n", rentry->fname );
-       return GPGERR_OPEN_FILE;
-    }
-
-    if( !kbpos->valid )
-       log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
-    if( iobuf_seek( a, kbpos->offset ) ) {
-       log_error("can't seek to %lu\n", kbpos->offset);
-       iobuf_close(a);
-       return GPGERR_KEYRING_OPEN;
-    }
-
-    pkt = gcry_xmalloc( sizeof *pkt );
-    init_packet(pkt);
-    kbpos->count=0;
-    while( (rc=parse_packet(a, pkt)) != -1 ) {
-       if( rc ) {  /* ignore errors */
-           if( rc != GPGERR_UNKNOWN_PACKET ) {
-               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
-               rc = GPGERR_INV_KEYRING;
-               goto ready;
-           }
-           kbpos->count++;
-           free_packet( pkt );
-           init_packet( pkt );
-           continue;
-       }
-       /* make a linked list of all packets */
-       switch( pkt->pkttype ) {
-         case PKT_COMPRESSED:
-           log_error("skipped compressed packet in keyring\n" );
-           free_packet(pkt);
-           init_packet(pkt);
-           break;
-
-         case PKT_PUBLIC_KEY:
-         case PKT_SECRET_KEY:
-           if( in_cert )
-               goto ready;
-           in_cert = 1;
-         default:
-           kbpos->count++;
-           if( !root )
-               root = new_kbnode( pkt );
-           else
-               add_kbnode( root, new_kbnode( pkt ) );
-           pkt = gcry_xmalloc( sizeof *pkt );
-           init_packet(pkt);
-           break;
-       }
+  #if 0
+    if( !check_pos(kbpos) )
+       return GPGERR_GENERAL;
+
+    switch( kbpos->rt ) {
+      case rt_RING:
+       rc = keyring_copy( kbpos, 2, NULL );
+       break;
+      case rt_KBXF:
+       rc = do_kbxf_copy( kbpos, 2, NULL );
+       break;
+      default: BUG();
     }
-  ready:
-    kbpos->valid = 0;
-    if( rc == -1 && root )
-       rc = 0;
+  #endif
+    return rc;
+}
 
-    if( rc )
-       release_kbnode( root );
+
+/****************
+ * Update the keyblock in the ring (or whatever resource) one in ROOT.
+ */
+int
+update_keyblock( KBNODE root )
+{
+    int rc;
+    struct WORK WORK WORK KBPOS kbpos;
+    
+    /* We need to get the file position of original keyblock first */
+    if ( root->pkt->pkttype == PKT_PUBLIC_KEY )
+        rc = find_kblocation_bypk( &kbpos, root->pkt->pkt.public_key );
+    else if ( root->pkt->pkttype == PKT_SECRET_KEY )
+        rc = find_kblocation_bysk( &kbpos, root->pkt->pkt.secret_key );
     else
-       *ret_root = root;
-    free_packet( pkt );
-    gcry_free( pkt );
-    iobuf_close(a);
+        BUG();
+
+    if ( rc )
+        return rc;
+
+    if( !check_pos(&kbpos) )
+       return GPGERR_GENERAL;
+
+    switch( kbpos.rt ) {
+      case rt_RING:
+       rc = keyring_copy( &kbpos, 3, root );
+       break;
+      case rt_KBXF:
+       rc = do_kbxf_copy( &kbpos, 3, root );
+       break;
+      default: BUG();
+    }
+
     return rc;
 }
 
 
+\f
+/****************************************************************
+ ********** Functions which operates on regular keyrings ********
+ ****************************************************************/
+
 static int
 keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
 {
@@ -1301,21 +674,24 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
     int rc;
     RESTBL *rentry;
     KBNODE root = NULL;
+    ulong offset, first_offset=0;
 
     if( !(rentry=check_pos(kbpos)) )
        return GPGERR_GENERAL;
 
     if( kbpos->pkt ) {
        root = new_kbnode( kbpos->pkt );
+        first_offset = kbpos->save_offset;
        kbpos->pkt = NULL;
     }
+    kbpos->valid = 0;
 
     pkt = gcry_xmalloc( sizeof *pkt );
     init_packet(pkt);
-    while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
+    while( (rc=parse_packet(kbpos->fp, pkt, &offset )) != -1 ) {
        if( rc ) {  /* ignore errors */
            if( rc != GPGERR_UNKNOWN_PACKET ) {
-               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+               log_error("keyring_enum: read error: %s\n", gpg_errstr(rc) );
                rc = GPGERR_INV_KEYRING;
                goto ready;
            }
@@ -1333,12 +709,14 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
 
          case PKT_PUBLIC_KEY:
          case PKT_SECRET_KEY:
-           if( root ) { /* store this packet */
+           if( root ) { /* save this packet */
                kbpos->pkt = pkt;
+                kbpos->save_offset = offset;
                pkt = NULL;
                goto ready;
            }
            root = new_kbnode( pkt );
+            first_offset = offset;
            pkt = gcry_xmalloc( sizeof *pkt );
            init_packet(pkt);
            break;
@@ -1368,8 +746,13 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
 
     if( rc )
        release_kbnode( root );
-    else
+    else {
+        if ( root ) {
+            kbpos->offset = first_offset;
+            kbpos->valid = 1;
+        }
        *ret_root = root;
+    }
     free_packet( pkt );
     gcry_free( pkt );
 
@@ -1391,11 +774,11 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
     int rc=0;
     char *bakfname = NULL;
     char *tmpfname = NULL;
+#warning We need to lock the keyring while we are editing it.
+    /* rethink this whole module */
 
     if( !(rentry = check_pos( kbpos )) )
        return GPGERR_GENERAL;
-    if( kbpos->fp )
-       BUG(); /* not allowed with such a handle */
 
     if( opt.dry_run )
        return 0;
@@ -1403,6 +786,13 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
     lock_rentry( rentry );
 
     /* open the source file */
+    if( kbpos->fp ) {
+       /* BUG(); not allowed with such a handle */
+        log_debug("keyring_copy: closing fp %p\n", kbpos->fp );
+        iobuf_close (kbpos->fp);
+        kbpos->fp = NULL;
+        kbpos->valid = 0;
+    }
     fp = iobuf_open( rentry->fname );
     if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
        KBNODE kbctx, node;
@@ -1612,159 +1002,6 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
  ********** Functions which operate on KBX files ****************
  ****************************************************************/
 
-/****************
- * search a KBX file return 0 if found, -1 if not found or an errorcode.
- */
-static int
-do_kbxf_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
-{
-    int rc;
-    PACKET pkt;
-    int save_mode;
-    ulong offset;
-    int pkttype = req->pkttype;
-    PKT_public_key *req_pk = req->pkt.public_key;
-    PKT_secret_key *req_sk = req->pkt.secret_key;
-
-    init_packet(&pkt);
-    save_mode = set_packet_list_mode(0);
-    kbpos->rt = rt_RING;
-    kbpos->valid = 0;
-
-  #if HAVE_DOSISH_SYSTEM || 1
-    assert(!iobuf);
-    iobuf = iobuf_open( fname );
-    if( !iobuf ) {
-       log_error("%s: can't open keyring file\n", fname);
-       rc = GPGERR_KEYRING_OPEN;
-       goto leave;
-    }
-  #else
-    if( iobuf_seek( iobuf, 0 ) ) {
-       log_error("can't rewind keyring file\n");
-       rc = GPGERR_KEYRING_OPEN;
-       goto leave;
-    }
-  #endif
-
-    while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
-       if( pkt.pkttype == PKT_SECRET_KEY ) {
-           PKT_secret_key *sk = pkt.pkt.secret_key;
-
-           if(   req_sk->timestamp == sk->timestamp
-              && req_sk->pubkey_algo == sk->pubkey_algo
-              && !cmp_seckey( req_sk, sk) )
-               break; /* found */
-       }
-       else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
-           PKT_public_key *pk = pkt.pkt.public_key;
-
-           if(   req_pk->timestamp == pk->timestamp
-              && req_pk->pubkey_algo == pk->pubkey_algo
-              && !cmp_pubkey( req_pk, pk ) )
-               break; /* found */
-       }
-       else
-           BUG();
-       free_packet(&pkt);
-    }
-    if( !rc ) {
-       kbpos->offset = offset;
-       kbpos->valid = 1;
-    }
-
-  leave:
-    free_packet(&pkt);
-    set_packet_list_mode(save_mode);
-  #if HAVE_DOSISH_SYSTEM || 1
-    iobuf_close(iobuf);
-  #endif
-    return rc;
-}
-
-
-static int
-do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root )
-{
-    PACKET *pkt;
-    int rc;
-    RESTBL *rentry;
-    KBNODE root = NULL;
-    IOBUF a;
-    int in_cert = 0;
-
-    if( !(rentry=check_pos(kbpos)) )
-       return GPGERR_GENERAL;
-
-    a = iobuf_open( rentry->fname );
-    if( !a ) {
-       log_error("can't open `%s'\n", rentry->fname );
-       return GPGERR_OPEN_FILE;
-    }
-
-    if( !kbpos->valid )
-       log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
-    if( iobuf_seek( a, kbpos->offset ) ) {
-       log_error("can't seek to %lu\n", kbpos->offset);
-       iobuf_close(a);
-       return GPGERR_KEYRING_OPEN;
-    }
-
-    pkt = gcry_xmalloc( sizeof *pkt );
-    init_packet(pkt);
-    kbpos->count=0;
-    while( (rc=parse_packet(a, pkt)) != -1 ) {
-       if( rc ) {  /* ignore errors */
-           if( rc != GPGERR_UNKNOWN_PACKET ) {
-               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
-               rc = GPGERR_INV_KEYRING;
-               goto ready;
-           }
-           kbpos->count++;
-           free_packet( pkt );
-           init_packet( pkt );
-           continue;
-       }
-       /* make a linked list of all packets */
-       switch( pkt->pkttype ) {
-         case PKT_COMPRESSED:
-           log_error("skipped compressed packet in keyring\n" );
-           free_packet(pkt);
-           init_packet(pkt);
-           break;
-
-         case PKT_PUBLIC_KEY:
-         case PKT_SECRET_KEY:
-           if( in_cert )
-               goto ready;
-           in_cert = 1;
-         default:
-           kbpos->count++;
-           if( !root )
-               root = new_kbnode( pkt );
-           else
-               add_kbnode( root, new_kbnode( pkt ) );
-           pkt = gcry_xmalloc( sizeof *pkt );
-           init_packet(pkt);
-           break;
-       }
-    }
-  ready:
-    kbpos->valid = 0;
-    if( rc == -1 && root )
-       rc = 0;
-
-    if( rc )
-       release_kbnode( root );
-    else
-       *ret_root = root;
-    free_packet( pkt );
-    gcry_free( pkt );
-    iobuf_close(a);
-    return rc;
-}
-
-
 static int
 do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
 {
@@ -1783,10 +1020,10 @@ do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
 
     pkt = gcry_xmalloc( sizeof *pkt );
     init_packet(pkt);
-    while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
+    while( (rc=parse_packet(kbpos->fp, pkt, NULL)) != -1 ) {
        if( rc ) {  /* ignore errors */
            if( rc != GPGERR_UNKNOWN_PACKET ) {
-               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+               log_error("do_kbxf_enum: read error: %s\n", gpg_errstr(rc) );
                rc = GPGERR_INV_KEYRING;
                goto ready;
            }
@@ -2079,300 +1316,5 @@ do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root )
 }
 
 
-\f
-#ifdef HAVE_LIBGDBM
-/****************************************************************
- ********** Functions which operates on GDM files ***************
- ****************************************************************/
-
-#if MAX_FINGERPRINT_LEN > 20
-  #error A GDBM keyring assumes that fingerprints are less than 21
-#endif
-
-/****************
- * Insert the keyblock into the GDBM database
- */
-
-static int
-do_gdbm_store( KBPOS *kbpos, KBNODE root, int update )
-{
-    RESTBL *rentry;
-    PKT_public_key *pk;
-    KBNODE kbctx, node;
-    IOBUF fp = NULL;
-    byte fpr[20];
-    byte contbuf[21];
-    byte keybuf[21];
-    size_t fprlen;
-    datum key, content;
-    int i, rc;
-
-    if( !(rentry = check_pos( kbpos )) )
-       return GPGERR_GENERAL;
-
-    if( opt.dry_run )
-       return 0;
-
-    /* construct the fingerprint which is used as the primary key */
-    node = find_kbnode( root, PKT_PUBLIC_KEY );
-    if( !node )
-       log_bug("a gdbm database can't store secret keys\n");
-    pk = node->pkt->pkt.public_key;
-
-    fingerprint_from_pk( pk, fpr, &fprlen );
-    for(i=fprlen; i < DIM(fpr); i++ )
-       fpr[i] = 0;
-
-    /* build the keyblock */
-    kbctx=NULL;
-    fp = iobuf_temp();
-    iobuf_put( fp, 1 ); /* data is a keyblock */
-    while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
-       if( (rc = build_packet( fp, node->pkt )) ) {
-           log_error("build_packet(%d) failed: %s\n",
-                       node->pkt->pkttype, gpg_errstr(rc) );
-           rc = GPGERR_WRITE_FILE;
-           goto leave;
-       }
-    }
-    /* store data and key */
-    *keybuf = 1;   /* key is a padded fingerprint */
-    memcpy(keybuf+1, fpr, 20 );
-    key.dptr  = keybuf;
-    key.dsize = 21;
-    content.dptr  = iobuf_get_temp_buffer( fp );
-    content.dsize = iobuf_get_temp_length( fp );
-    rc = gdbm_store( rentry->dbf, key, content,
-                                 update? GDBM_REPLACE : GDBM_INSERT );
-    if( rc == 1 && !update )
-       rc = gdbm_store( rentry->dbf, key, content, GDBM_REPLACE );
-
-    if( rc ) {
-       log_error("%s: gdbm_store failed: %s\n", rentry->fname,
-                           rc == 1 ? "already stored"
-                                   : gdbm_strerror(gdbm_errno) );
-       rc = GPGERR_WRITE_FILE;
-       goto leave;
-    }
-    /* now store all keyids */
-    *contbuf = 2;  /* data is a list of fingerprints */
-    memcpy(contbuf+1, fpr, 20 );
-    content.dptr = contbuf;
-    content.dsize= 21;
-    kbctx=NULL;
-    while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
-       if(    node->pkt->pkttype == PKT_PUBLIC_KEY
-           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
-           u32 aki[2];
-
-           keyid_from_pk( node->pkt->pkt.public_key, aki );
-           *keybuf = 2; /* key is a 8 byte keyid */
-           u32tobuf( keybuf+1  , aki[0] );
-           u32tobuf( keybuf+5, aki[1] );
-           key.dptr = keybuf;
-           key.dsize= 9;
-           /* fixme: must be more clever when a insert failed:
-            *        build a list of fingerprints in this case */
-           rc = gdbm_store( rentry->dbf, key, content,
-                                         update? GDBM_REPLACE : GDBM_INSERT );
-           if( rc ) {
-               log_info("%s: gdbm_store keyid failed: %s\n", rentry->fname,
-                                   rc == 1 ? "already stored"
-                                           : gdbm_strerror(gdbm_errno) );
-               rc = 0;
-           }
-       }
-    }
-
-  leave:
-    iobuf_close(fp); /* don't need a cancel because it is a temp iobuf */
-    return rc;
-}
-
-
-
-/****************
- * search one keybox, return 0 if found, -1 if not found or an errorcode.
- */
-static int
-do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen )
-{
-    byte *keybuf = kbpos->keybuf;
-    datum key;
-    int i;
-
-    *keybuf = 1;
-    for(i=0; i < fprlen; i++ )
-       keybuf[i+1] = fpr[i];
-    for(; i < 20; i++ )
-       keybuf[i+1] = 0;
-
-    /* fetch the data */
-    key.dptr  = keybuf;
-    key.dsize = 21;
-    if( !gdbm_exists( dbf, key ) )
-       return -1; /* not found */
-    return 0;
-}
-
-/****************
- * locate by keyid.
- * FIXME: we must have a way to enumerate thru the list opf fingerprints
- */
-static int
-do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
-{
-    byte keybuf[9];
-    datum key, content;
-    int rc;
-
-    /* construct the fingerprint which is used as the primary key */
-    *keybuf = 2;
-    u32tobuf( keybuf+1, keyid[0] );
-    u32tobuf( keybuf+5, keyid[1] );
-
-    /* fetch the data */
-    key.dptr  = keybuf;
-    key.dsize = 9;
-    content = gdbm_fetch( dbf, key );
-    if( !content.dptr )
-       return -1;
-
-    if( content.dsize < 2 ) {
-       log_error("gdbm_fetch did not return enough data\n" );
-       free( content.dptr ); /* can't use gcry_free() here */
-       return GPGERR_INV_KEYRING;
-    }
-    if( *content.dptr != 2 ) {
-       log_error("gdbm_fetch returned unexpected type %d\n",
-                   *(byte*)content.dptr );
-       free( content.dptr ); /* can't use gcry_free() here */
-       return GPGERR_INV_KEYRING;
-    }
-    if( content.dsize < 21 ) {
-       log_error("gdbm_fetch did not return a complete fingerprint\n" );
-       free( content.dptr ); /* can't use gcry_free() here */
-       return GPGERR_INV_KEYRING;
-    }
-    if( content.dsize > 21 )
-       log_info("gdbm_fetch: WARNING: more than one fingerprint\n" );
-
-    rc = do_gdbm_locate( dbf, kbpos, content.dptr+1, 20 );
-    free( content.dptr ); /* can't use gcry_free() here */
-    return rc;
-}
-
-
-
-static int
-do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
-{
-    PACKET *pkt;
-    int rc;
-    RESTBL *rentry;
-    KBNODE root = NULL;
-    IOBUF a;
-    datum key, content;
-
-    if( !(rentry=check_pos(kbpos)) )
-       return GPGERR_GENERAL;
-
-    key.dptr  = kbpos->keybuf;
-    key.dsize = 21;
-    content = gdbm_fetch( rentry->dbf, key );
-    if( !content.dptr ) {
-       log_error("gdbm_fetch failed: %s\n", gdbm_strerror(gdbm_errno) );
-       return GPGERR_INV_KEYRING;
-    }
-    if( content.dsize < 2 ) {
-       log_error("gdbm_fetch did not return enough data\n" );
-       free( content.dptr ); /* can't use gcry_free() here */
-       return GPGERR_INV_KEYRING;
-    }
-    if( *content.dptr != 1 ) {
-       log_error("gdbm_fetch returned unexpected type %d\n",
-                   *(byte*)content.dptr );
-       free( content.dptr ); /* can't use gcry_free() here */
-       return GPGERR_INV_KEYRING;
-    }
-
-    a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 );
-    free( content.dptr ); /* can't use gcry_free() here */
-
-    pkt = gcry_xmalloc( sizeof *pkt );
-    init_packet(pkt);
-    kbpos->count=0;
-    while( (rc=parse_packet(a, pkt)) != -1 ) {
-       if( rc ) {  /* ignore errors */
-           if( rc != GPGERR_UNKNOWN_PACKET ) {
-               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
-               rc = GPGERR_INV_KEYRING;
-               break;
-           }
-           kbpos->count++;
-           free_packet( pkt );
-           init_packet( pkt );
-           continue;
-       }
-       /* make a linked list of all packets */
-       kbpos->count++;
-       if( !root )
-           root = new_kbnode( pkt );
-       else
-           add_kbnode( root, new_kbnode( pkt ) );
-       pkt = gcry_xmalloc( sizeof *pkt );
-       init_packet(pkt);
-    }
-    if( rc == -1 && root )
-       rc = 0;
-    if( rc )
-       release_kbnode( root );
-    else
-       *ret_root = root;
-    free_packet( pkt );
-    gcry_free( pkt );
-    iobuf_close(a);
-    return rc;
-}
-
-
-/****************
- * Enum over keyblok data
- */
-static int
-do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root )
-{
-    RESTBL *rentry;
-    datum key, helpkey;
-
-    if( !(rentry=check_pos(kbpos)) )
-       return GPGERR_GENERAL;
-
-    if( !kbpos->offset ) {
-       kbpos->offset = 1;
-       key = gdbm_firstkey( rentry->dbf );
-    }
-    else {
-       helpkey.dptr = kbpos->keybuf;
-       helpkey.dsize= 21;
-       key = gdbm_nextkey( rentry->dbf, helpkey );
-    }
-    while( key.dptr && (!key.dsize || *key.dptr != 1) ) {
-       helpkey = key;
-       key = gdbm_nextkey( rentry->dbf, helpkey );
-       free( helpkey.dptr ); /* free and not gcry_free() ! */
-    }
-    if( !key.dptr )
-       return -1; /* eof */
 
-    if( key.dsize < 21 ) {
-       free( key.dptr ); /* free and not gcry_free() ! */
-       log_error("do_gdm_enum: key is too short\n" );
-       return GPGERR_INV_KEYRING;
-    }
-    memcpy( kbpos->keybuf, key.dptr, 21 );
-    free( key.dptr ); /* free and not gcry_free() ! */
-    return do_gdbm_read( kbpos, ret_root );
-}
 
-#endif /*HAVE_LIBGDBM*/
index dceba71..bc325cd 100644 (file)
@@ -60,7 +60,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
 
        sk = gcry_xcalloc( 1, sizeof *sk );
        sk->req_usage = use;
-       if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
+       if( (rc = get_seckey_byname( NULL, sk, NULL, unlock, NULL )) ) {
            free_secret_key( sk ); sk = NULL;
            log_error("no default secret key: %s\n", gpg_errstr(rc) );
        }
@@ -93,7 +93,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
 
            sk = gcry_xcalloc( 1, sizeof *sk );
            sk->req_usage = use;
-           if( (rc = get_seckey_byname( sk, locusr->d, unlock )) ) {
+           if( (rc = get_seckey_byname( NULL, sk, locusr->d, unlock, NULL))) {
                free_secret_key( sk ); sk = NULL;
                log_error(_("skipped `%s': %s\n"), locusr->d, gpg_errstr(rc) );
            }