gpg: Remove options --pgp2 and --rfc1991.
[gnupg.git] / g10 / revoke.c
index f7af5c3..67f62e5 100644 (file)
@@ -220,9 +220,9 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
     afx = new_armor_context ();
 
     kdbhd = keydb_new ();
-    rc = classify_user_id (uname, &desc);
+    rc = classify_user_id (uname, &desc, 1);
     if (!rc)
-      rc = keydb_search (kdbhd, &desc, 1);
+      rc = keydb_search (kdbhd, &desc, 1, NULL);
     if (rc) {
        log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc));
        goto leave;
@@ -239,7 +239,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
 
     /* get the key from the keyblock */
     node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
-    if( !node ) 
+    if( !node )
       BUG ();
 
     pk=node->pkt->pkt.public_key;
@@ -262,8 +262,8 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
       {
        SK_LIST list;
 
-       if (pk2)
-         free_public_key (pk2);
+        free_public_key (pk2);
+        pk2 = NULL;
 
        if(sk_list)
          {
@@ -328,7 +328,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
            if( !opt.armor )
              tty_printf(_("ASCII armored output forced.\n"));
 
-           if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
+           if( (rc = open_outfile (-1, NULL, 0, 1, &out )) )
              goto leave;
 
            afx->what = 1;
@@ -414,10 +414,8 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
       log_error(_("no revocation keys found for \"%s\"\n"),uname);
 
   leave:
-    if( pk )
-       free_public_key( pk );
-    if (pk2)
-       free_public_key (pk2);
+    free_public_key (pk);
+    free_public_key (pk2);
     if( sig )
        free_seckey_enc( sig );
 
@@ -433,6 +431,157 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
 }
 
 
+/* Common core to create the revocation. FILENAME may be NULL to write
+   to stdout or the filename given by --output.  REASON describes the
+   revocation reason.  PSK is the public primary key - we expect that
+   a corresponding secret key is available.  KEYBLOCK is the entire
+   KEYBLOCK which is used in PGP mode to write a a minimal key and not
+   just the naked revocation signature; it may be NULL.  If LEADINTEXT
+   is not NULL, it is written right before the (armored) output.*/
+static int
+create_revocation (const char *filename,
+                   struct revocation_reason_info *reason,
+                   PKT_public_key *psk,
+                   kbnode_t keyblock,
+                   const char *leadintext, int suffix)
+{
+  int rc;
+  iobuf_t out = NULL;
+  armor_filter_context_t *afx;
+  PKT_signature *sig = NULL;
+  PACKET pkt;
+
+  afx = new_armor_context ();
+
+  if ((rc = open_outfile (-1, filename, suffix, 1, &out)))
+    goto leave;
+
+  if (leadintext )
+    iobuf_writestr (out, leadintext);
+
+  afx->what = 1;
+  afx->hdrlines = "Comment: This is a revocation certificate\n";
+  push_armor_filter (afx, out);
+
+  rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
+                           opt.force_v4_certs? 4:0,
+                           0, 0,
+                           revocation_reason_build_cb, reason, NULL);
+  if (rc)
+    {
+      log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
+      goto leave;
+    }
+
+  if (keyblock && (PGP6 || PGP7 || PGP8))
+    {
+      /* Use a minimal pk for PGPx mode, since PGP can't import bare
+         revocation certificates. */
+      rc = export_minimal_pk (out, keyblock, sig, NULL);
+      if (rc)
+        goto leave;
+    }
+  else
+    {
+      init_packet (&pkt);
+      pkt.pkttype = PKT_SIGNATURE;
+      pkt.pkt.signature = sig;
+
+      rc = build_packet (out, &pkt);
+      if (rc)
+        {
+          log_error (_("build_packet failed: %s\n"), g10_errstr (rc));
+          goto leave;
+        }
+    }
+
+ leave:
+  if (sig)
+    free_seckey_enc (sig);
+  if (rc)
+    iobuf_cancel (out);
+  else
+    iobuf_close (out);
+  release_armor_context (afx);
+  return rc;
+}
+
+
+/* This function is used to generate a standard revocation certificate
+   by gpg's interactive key generation function.  The certificate is
+   stored at a dedicated place in a slightly modified form to avoid an
+   accidental import.  PSK is the primary key; a corresponding secret
+   key must be available.  */
+int
+gen_standard_revoke (PKT_public_key *psk)
+{
+  int rc;
+  estream_t memfp;
+  struct revocation_reason_info reason;
+  char *dir, *tmpstr, *fname;
+  void *leadin;
+  size_t len;
+  u32 keyid[2];
+  char pkstrbuf[PUBKEY_STRING_SIZE];
+  char *orig_codeset;
+
+  dir = get_openpgp_revocdir (opt.homedir);
+  tmpstr = hexfingerprint (psk);
+  fname = xstrconcat (dir, DIRSEP_S, tmpstr, NULL);
+  xfree (tmpstr);
+  xfree (dir);
+
+  keyid_from_pk (psk, keyid);
+
+  memfp = es_fopenmem (0, "r+");
+  if (!memfp)
+    log_fatal ("error creating memory stream\n");
+
+  orig_codeset = i18n_switchto_utf8 ();
+
+  es_fprintf (memfp, "%s\n\n",
+              _("This is a revocation certificate for the OpenPGP key:"));
+
+  es_fprintf (memfp, "pub  %s/%s %s\n",
+              pubkey_string (psk, pkstrbuf, sizeof pkstrbuf),
+              keystr (keyid),
+              datestr_from_pk (psk));
+
+  print_fingerprint (memfp, psk, 3);
+
+  tmpstr = get_user_id (keyid, &len);
+  es_fprintf (memfp, "uid%*s%.*s\n\n",
+              (int)keystrlen () + 10, "",
+              (int)len, tmpstr);
+  xfree (tmpstr);
+
+  es_fprintf (memfp, "%s\n\n%s\n\n:",
+     _("Use it to revoke this key in case of a compromise or loss of\n"
+       "the secret key.  However, if the secret key is still accessible,\n"
+       "it is better to generate a new revocation certificate and give\n"
+       "a reason for the revocation."),
+     _("To avoid an accidental use of this file, a colon has been inserted\n"
+       "before the 5 dashes below.  Remove this colon with a text editor\n"
+       "before making use of this revocation certificate."));
+
+  es_putc (0, memfp);
+
+  i18n_switchback (orig_codeset);
+
+  if (es_fclose_snatch (memfp, &leadin, NULL))
+    log_fatal ("error snatching memory stream\n");
+
+  reason.code = 0x00; /* No particular reason.  */
+  reason.desc = NULL;
+  rc = create_revocation (fname, &reason, psk, NULL, leadin, 3);
+  xfree (leadin);
+  xfree (fname);
+
+  return rc;
+}
+
+
+
 /****************
  * Generate a revocation certificate for UNAME
  */
@@ -440,12 +589,8 @@ int
 gen_revoke (const char *uname)
 {
   int rc = 0;
-  armor_filter_context_t *afx;
-  PACKET pkt;
   PKT_public_key *psk;
-  PKT_signature *sig = NULL;
   u32 keyid[2];
-  iobuf_t out = NULL;
   kbnode_t keyblock = NULL;
   kbnode_t node;
   KEYDB_HANDLE kdbhd;
@@ -458,14 +603,11 @@ gen_revoke (const char *uname)
       return G10ERR_GENERAL;
     }
 
-  afx = new_armor_context ();
-  init_packet( &pkt );
-
   /* Search the userid; we don't want the whole getkey stuff here.  */
   kdbhd = keydb_new ();
-  rc = classify_user_id (uname, &desc);
+  rc = classify_user_id (uname, &desc, 1);
   if (!rc)
-    rc = keydb_search (kdbhd, &desc, 1);
+    rc = keydb_search (kdbhd, &desc, 1, NULL);
   if (rc)
     {
       log_error (_("secret key \"%s\" not found: %s\n"),
@@ -482,7 +624,7 @@ gen_revoke (const char *uname)
 
   /* Get the keyid from the keyblock.  */
   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
-  if (!node) 
+  if (!node)
     BUG ();
 
   psk = node->pkt->pkt.public_key;
@@ -504,61 +646,26 @@ gen_revoke (const char *uname)
       rc = 0;
       goto leave;
     }
-  
+
   if (psk->version >= 4 || opt.force_v4_certs)
     {
       /* Get the reason for the revocation.  */
       reason = ask_revocation_reason (1, 0, 1);
       if (!reason)
-        { 
+        {
           /* user decided to cancel */
           rc = 0;
           goto leave;
         }
     }
-  
+
   if (!opt.armor)
     tty_printf (_("ASCII armored output forced.\n"));
 
-  if ((rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )))
+  rc = create_revocation (NULL, reason, psk, keyblock, NULL, 0);
+  if (rc)
     goto leave;
 
-  afx->what = 1;
-  afx->hdrlines = "Comment: A revocation certificate should follow\n";
-  push_armor_filter (afx, out);
-
-  /* create it */
-  rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
-                           opt.force_v4_certs?4:0, 0, 0,
-                           revocation_reason_build_cb, reason, NULL);
-  if (rc)
-    {
-      log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
-      goto leave;
-    }
-    
-  if (PGP2 || PGP6 || PGP7 || PGP8)
-    {
-      /* Use a minimal pk for PGPx mode, since PGP can't import bare
-         revocation certificates. */
-      rc = export_minimal_pk (out, keyblock, sig, NULL);
-      if(rc)
-        goto leave;
-    }
-  else
-    {
-      init_packet( &pkt );
-      pkt.pkttype = PKT_SIGNATURE;
-      pkt.pkt.signature = sig;
-        
-      rc = build_packet (out, &pkt);
-      if (rc) 
-        {
-          log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
-          goto leave;
-        }
-    }
-    
   /* and issue a usage notice */
   tty_printf (_(
 "Revocation certificate created.\n\n"
@@ -569,16 +676,9 @@ gen_revoke (const char *uname)
 "your machine might store the data and make it available to others!\n"));
 
  leave:
-  if (sig)
-    free_seckey_enc (sig);
   release_kbnode (keyblock);
   keydb_release (kdbhd);
-  if (rc)
-    iobuf_cancel(out);
-  else
-    iobuf_close(out);
   release_revocation_reason_info( reason );
-  release_armor_context (afx);
   return rc;
 }