* options.h, getkey.c (merge_selfsigs_subkey), gpg.c (main), sig-check.c
[gnupg.git] / g10 / delkey.c
index b84a8bf..354851d 100644 (file)
@@ -1,21 +1,23 @@
 /* delkey.c - delete keys
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
+ *               2005 Free Software Foundation, Inc.
  *
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
  *
- * GNUPG is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
 
 /****************
  * Delete a public or secret key from a keyring.
+ * r_sec_avail will be set if a secret key is available and the public
+ * key can't be deleted for that reason.
  */
-int
-delete_key( const char *username, int secret )
+static int
+do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
 {
     int rc = 0;
     KBNODE keyblock = NULL;
     KBNODE node;
-    KBPOS kbpos;
+    KEYDB_HANDLE hd = keydb_new (secret);
     PKT_public_key *pk = NULL;
     PKT_secret_key *sk = NULL;
     u32 keyid[2];
     int okay=0;
     int yes;
+    KEYDB_SEARCH_DESC desc;
+    int exactmatch;
+
+    *r_sec_avail = 0;
 
     /* search the userid */
-    rc = secret? find_secret_keyblock_byname( &kbpos, username )
-              : find_keyblock_byname( &kbpos, username );
-    if( rc ) {
-       log_error(_("%s: user not found\n"), username );
+    classify_user_id (username, &desc);
+    exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR
+                  || desc.mode == KEYDB_SEARCH_MODE_FPR16
+                  || desc.mode == KEYDB_SEARCH_MODE_FPR20);
+    rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID;
+    if (rc) {
+       log_error (_("key \"%s\" not found: %s\n"), username, g10_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, g10_errstr(rc) );
+    rc = keydb_get_keyblock (hd, &keyblock );
+    if (rc) {
+       log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
        goto leave;
     }
 
@@ -80,65 +92,67 @@ delete_key( const char *username, int secret )
        goto leave;
     }
 
-    if( secret ) {
+    if( secret )
+      {
        sk = node->pkt->pkt.secret_key;
        keyid_from_sk( sk, keyid );
-    }
-    else {
+      }
+    else
+      {
+       /* public */
        pk = node->pkt->pkt.public_key;
        keyid_from_pk( pk, keyid );
-       rc = seckey_available( keyid );
-       if( !rc ) {
-           log_error(_(
-           "there is a secret key for this public key!\n"));
-           log_info(_(
-           "use option \"--delete-secret-key\" to delete it first.\n"));
-           rc = -1;
-       }
-       else if( rc != G10ERR_NO_SECKEY )
-           log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
-       else
-           rc = 0;
-    }
+
+       if(!force)
+         {
+           rc = seckey_available( keyid );
+           if( !rc )
+             {
+               *r_sec_avail = 1;
+               rc = -1;
+               goto leave;
+             }
+           else if( rc != G10ERR_NO_SECKEY )
+             log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
+           else
+             rc = 0;
+         }
+      }
 
     if( rc )
        rc = 0;
+    else if (opt.batch && exactmatch)
+        okay++;
     else if( opt.batch && secret )
-       log_error(_("can't do that in batchmode\n"));
+      {
+       log_error(_("can't do this in batch mode\n"));
+        log_info (_("(unless you specify the key by fingerprint)\n"));
+      }
     else if( opt.batch && opt.answer_yes )
        okay++;
     else if( opt.batch )
-       log_error(_("can't do that in batchmode without \"--yes\"\n"));
+      {
+       log_error(_("can't do this in batch mode without \"--yes\"\n"));
+        log_info (_("(unless you specify the key by fingerprint)\n"));
+      }
     else {
-       char *p;
-       size_t n;
-
-       if( secret )
-           tty_printf("sec  %4u%c/%08lX %s   ",
-                     nbits_from_sk( sk ),
-                     pubkey_letter( sk->pubkey_algo ),
-                     keyid[1], datestr_from_sk(sk) );
-       else
-           tty_printf("pub  %4u%c/%08lX %s   ",
-                     nbits_from_pk( pk ),
-                     pubkey_letter( pk->pubkey_algo ),
-                     keyid[1], datestr_from_pk(pk) );
-       p = get_user_id( keyid, &n );
-       tty_print_string( p, n );
-       m_free(p);
-       tty_printf("\n\n");
-
-       yes = cpr_get_answer_is_yes( secret? N_("delete_key.secret.okay")
-                          : N_("delete_key.okay"),
-                             _("Delete this key from the keyring? "));
+        if( secret )
+            print_seckey_info( sk );
+        else
+            print_pubkey_info(NULL, pk );
+       tty_printf( "\n" );
+
+       yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
+                                          : "delete_key.okay",
+                             _("Delete this key from the keyring? (y/N) "));
        if( !cpr_enabled() && secret && yes ) {
            /* I think it is not required to check a passphrase; if
             * the user is so stupid as to let others access his secret keyring
             * (and has no backup) - it is up him to read some very
             * basic texts about security.
             */
-           yes = cpr_get_answer_is_yes(N_("delete_key.secret.okay"),
-                        _("This is a secret key! - really delete? "));
+           yes = cpr_get_answer_is_yes("delete_key.secret.okay",
+                        _("This is a secret key! - really delete? (y/N) "));
        }
        if( yes )
            okay++;
@@ -146,15 +160,62 @@ delete_key( const char *username, int secret )
 
 
     if( okay ) {
-       rc = delete_keyblock( &kbpos );
-       if( rc ) {
-           log_error("delete_keyblock failed: %s\n", g10_errstr(rc) );
+       rc = keydb_delete_keyblock (hd);
+       if (rc) {
+           log_error (_("deleting keyblock failed: %s\n"), g10_errstr(rc) );
            goto leave;
        }
+
+       /* Note that the ownertrust being cleared will trigger a
+           revalidation_mark().  This makes sense - only deleting keys
+           that have ownertrust set should trigger this. */
+
+        if (!secret && pk && clear_ownertrusts (pk)) {
+          if (opt.verbose)
+            log_info (_("ownertrust information cleared\n"));
+        }
     }
 
   leave:
-    release_kbnode( keyblock );
+    keydb_release (hd);
+    release_kbnode (keyblock);
     return rc;
 }
 
+/****************
+ * Delete a public or secret key from a keyring.
+ */
+int
+delete_keys( STRLIST names, int secret, int allow_both )
+{
+    int rc, avail, force=(!allow_both && !secret && opt.expert);
+
+    /* Force allows us to delete a public key even if a secret key
+       exists. */
+
+    for(;names;names=names->next) {
+       rc = do_delete_key (names->d, secret, force, &avail );
+       if ( rc && avail ) { 
+        if ( allow_both ) {
+          rc = do_delete_key (names->d, 1, 0, &avail );
+          if ( !rc )
+            rc = do_delete_key (names->d, 0, 0, &avail );
+        }
+        else {
+          log_error(_(
+             "there is a secret key for public key \"%s\"!\n"),names->d);
+          log_info(_(
+             "use option \"--delete-secret-keys\" to delete it first.\n"));
+          write_status_text( STATUS_DELETE_PROBLEM, "2" );
+          return rc;
+        }
+       }
+
+       if(rc) {
+        log_error("%s: delete key failed: %s\n", names->d, g10_errstr(rc) );
+        return rc;
+       }
+    }
+
+    return 0;
+}