Use macros for iobuf ioctls.
[gnupg.git] / g10 / revoke.c
index ca67d80..5e22a70 100644 (file)
@@ -1,11 +1,12 @@
 /* revoke.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
+ *               2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <assert.h>
 #include <ctype.h>
 
+#include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "errors.h"
+#include "status.h"
 #include "keydb.h"
-#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "ttyio.h"
@@ -59,31 +59,148 @@ revocation_reason_build_cb( PKT_signature *sig, void *opaque )
        ud = native_to_utf8( reason->desc );
        buflen += strlen(ud);
     }
-    buffer = m_alloc( buflen );
+    buffer = xmalloc( buflen );
     *buffer = reason->code;
     if( ud ) {
        memcpy(buffer+1, ud, strlen(ud) );
-       m_free( ud );
+       xfree( ud );
     }
 
     build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
-    m_free( buffer );
+    xfree( buffer );
     return 0;
 }
 
+/* Outputs a minimal pk (as defined by 2440) from a keyblock.  A
+   minimal pk consists of the public key packet and a user ID.  We try
+   and pick a user ID that has a uid signature, and include it if
+   possible. */
+static int
+export_minimal_pk(IOBUF out,KBNODE keyblock,
+                 PKT_signature *revsig,PKT_signature *revkey)
+{
+  KBNODE node;
+  PACKET pkt;
+  PKT_user_id *uid=NULL;
+  PKT_signature *selfsig=NULL;
+  u32 keyid[2];
+  int rc;
+
+  node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
+  if(!node)
+    {
+      log_error("key incomplete\n");
+      return G10ERR_GENERAL;
+    }
+
+  keyid_from_pk(node->pkt->pkt.public_key,keyid);
+
+  pkt=*node->pkt;
+  rc=build_packet(out,&pkt);
+  if(rc)
+    {
+      log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+      return rc;
+    }
+
+  init_packet(&pkt);
+  pkt.pkttype=PKT_SIGNATURE;
+
+  /* the revocation itself, if any.  2440 likes this to come first. */
+  if(revsig)
+    {
+      pkt.pkt.signature=revsig;
+      rc=build_packet(out,&pkt);
+      if(rc)
+       {
+         log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+         return rc;
+       }
+    }
+
+  /* If a revkey in a 1F sig is present, include it too */
+  if(revkey)
+    {
+      pkt.pkt.signature=revkey;
+      rc=build_packet(out,&pkt);
+      if(rc)
+       {
+         log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+         return rc;
+       }
+    }
+
+  while(!selfsig)
+    {
+      KBNODE signode;
+
+      node=find_next_kbnode(node,PKT_USER_ID);
+      if(!node)
+       {
+         /* We're out of user IDs - none were self-signed. */
+         if(uid)
+           break;
+         else
+           {
+             log_error(_("key %s has no user IDs\n"),keystr(keyid));
+             return G10ERR_GENERAL;
+           }
+       }
+
+      if(node->pkt->pkt.user_id->attrib_data)
+       continue;
+
+      uid=node->pkt->pkt.user_id;
+      signode=node;
+
+      while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
+       {
+         if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
+            keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
+            IS_UID_SIG(signode->pkt->pkt.signature))
+           {
+             selfsig=signode->pkt->pkt.signature;
+             break;
+           }
+       }
+    }
 
+  pkt.pkttype=PKT_USER_ID;
+  pkt.pkt.user_id=uid;
+
+  rc=build_packet(out,&pkt);
+  if(rc)
+    {
+      log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+      return rc;
+    }
+
+  if(selfsig)
+    {
+      pkt.pkttype=PKT_SIGNATURE;
+      pkt.pkt.signature=selfsig;
+
+      rc=build_packet(out,&pkt);
+      if(rc)
+       {
+         log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+         return rc;
+       }
+    }
+
+  return 0;
+}
 
 /****************
  * Generate a revocation certificate for UNAME via a designated revoker
  */
 int
-gen_desig_revoke( const char *uname )
+gen_desig_revoke( const char *uname, strlist_t locusr )
 {
     int rc = 0;
-    armor_filter_context_t afx;
-    PACKET pkt;
+    armor_filter_context_t *afx;
     PKT_public_key *pk = NULL;
-    PKT_secret_key *sk = NULL;
+    PKT_public_key *pk2 = NULL;
     PKT_signature *sig = NULL;
     IOBUF out = NULL;
     struct revocation_reason_info *reason = NULL;
@@ -92,19 +209,22 @@ gen_desig_revoke( const char *uname )
     KBNODE keyblock=NULL,node;
     u32 keyid[2];
     int i,any=0;
+    SK_LIST sk_list=NULL;
 
-    if( opt.batch ) {
-       log_error(_("sorry, can't do this in batch mode\n"));
+    if( opt.batch )
+      {
+       log_error(_("can't do this in batch mode\n"));
        return G10ERR_GENERAL;
-    }
+      }
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
 
     kdbhd = keydb_new (0);
-    classify_user_id (uname, &desc);
-    rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
+    rc = classify_user_id (uname, &desc);
+    if (!rc)
+      rc = keydb_search (kdbhd, &desc, 1);
     if (rc) {
-       log_error (_("key `%s' not found: %s\n"),uname, g10_errstr (rc));
+       log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc));
        goto leave;
     }
 
@@ -126,6 +246,13 @@ gen_desig_revoke( const char *uname )
 
     keyid_from_pk(pk,keyid);
 
+    if(locusr)
+      {
+       rc=build_sk_list(locusr,&sk_list,0,PUBKEY_USAGE_CERT);
+       if(rc)
+         goto leave;
+      }
+
     /* Are we a designated revoker for this key? */
 
     if(!pk->revkey && pk->numrevkeys)
@@ -133,49 +260,60 @@ gen_desig_revoke( const char *uname )
 
     for(i=0;i<pk->numrevkeys;i++)
       {
-       if(sk)
-         free_secret_key(sk);
-
-       sk=m_alloc_clear(sizeof(*sk));
+       SK_LIST list;
 
-       rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
+       if (pk2)
+         free_public_key (pk2);
 
-       /* We have the revocation key */
-       if(!rc)
+       if(sk_list)
          {
-           size_t n;
-           char *p;
-           u32 sk_keyid[2];
-           PKT_user_id *uid=NULL;
-           PKT_signature *selfsig=NULL;
+           for(list=sk_list;list;list=list->next)
+             {
+               byte fpr[MAX_FINGERPRINT_LEN];
+               size_t fprlen;
+
+               fingerprint_from_pk (list->pk, fpr, &fprlen);
+
+               /* Don't get involved with keys that don't have 160
+                  bit fingerprints */
+               if(fprlen!=20)
+                 continue;
 
-           any=1;
-           keyid_from_sk(sk,sk_keyid);
+               if(memcmp(fpr,pk->revkey[i].fpr,20)==0)
+                 break;
+             }
 
-           tty_printf("\npub  %4u%c/%08lX %s   ",
-                      nbits_from_pk( pk ),
-                      pubkey_letter( pk->pubkey_algo ),
-                      (ulong)keyid[1], datestr_from_pk(pk) );
+           if (list)
+             pk2 = copy_public_key (NULL, list->pk);
+           else
+             continue;
+         }
+       else
+         {
+           pk2 = xmalloc_clear (sizeof *pk2);
+           rc = get_pubkey_byfprint (pk2,
+                                      pk->revkey[i].fpr, MAX_FINGERPRINT_LEN);
+         }
+
+       /* We have the revocation key.  */
+       if(!rc)
+         {
+           PKT_signature *revkey = NULL;
 
-           p = get_user_id( keyid, &n );
-           tty_print_utf8_string( p, n );
-           m_free(p);
-           tty_printf("\n\n");
+           any = 1;
 
-           tty_printf(_("To be revoked by:\n"));
+            print_pubkey_info (NULL, pk);
+           tty_printf ("\n");
 
-           tty_printf("\nsec  %4u%c/%08lX %s   ",
-                      nbits_from_sk( sk ),
-                      pubkey_letter( sk->pubkey_algo ),
-                      (ulong)sk_keyid[1], datestr_from_sk(sk) );
+           tty_printf (_("To be revoked by:\n"));
+            print_seckey_info (pk2);
 
-           p = get_user_id( sk_keyid, &n );
-           tty_print_utf8_string( p, n );
-           m_free(p);
-           tty_printf("\n\n");
+           if(pk->revkey[i].class&0x40)
+             tty_printf(_("(This is a sensitive revocation key)\n"));
+           tty_printf("\n");
 
            if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
-                      _("Create a revocation certificate for this key? ")) )
+         _("Create a designated revocation certificate for this key? (y/N) ")))
              continue;
 
            /* get the reason for the revocation (this is always v4) */
@@ -183,22 +321,23 @@ gen_desig_revoke( const char *uname )
            if( !reason )
              continue;
 
-           rc = check_secret_key( sk, 0 );
-           if( rc )
+           rc = -1;/*FIXME: check_secret_key (pk2, 0 );*/
+           if (rc)
              continue;
 
            if( !opt.armor )
              tty_printf(_("ASCII armored output forced.\n"));
 
-           if( (rc = open_outfile( NULL, 0, &out )) )
+           if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
              goto leave;
 
-           afx.what = 1;
-           afx.hdrlines = "Comment: A revocation certificate should follow\n";
-           iobuf_push_filter( out, armor_filter, &afx );
+           afx->what = 1;
+           afx->hdrlines = "Comment: A designated revocation certificate"
+             " should follow\n";
+           push_armor_filter (afx, out);
 
            /* create it */
-           rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
+           rc = make_keysig_packet( &sig, pk, NULL, NULL, pk2, 0x20, 0,
                                     0, 0, 0,
                                     revocation_reason_build_cb, reason );
            if( rc ) {
@@ -207,91 +346,62 @@ gen_desig_revoke( const char *uname )
            }
 
            /* Spit out a minimal pk as well, since otherwise there is
-               no way to know which key to attach this revocation
-               to. */
-
-           node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
-           if(!node)
-             {
-               rc=G10ERR_GENERAL;
-               log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
-               goto leave;
-             }
-
-           pkt = *node->pkt;
-           rc=build_packet(out,&pkt);
-           if( rc ) {
-             log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
-             goto leave;
-           }
-
-           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;
-           }
-
-           while(!selfsig)
+               no way to know which key to attach this revocation to.
+               Also include the direct key signature that contains
+               this revocation key.  We're allowed to include
+               sensitive revocation keys along with a revocation, as
+               this may be the only time the recipient has seen it.
+               Note that this means that if we have multiple different
+               sensitive revocation keys in a given direct key
+               signature, we're going to include them all here.  This
+               is annoying, but the good outweighs the bad, since
+               without including this a sensitive revoker can't really
+               do their job.  People should not include multiple
+               sensitive revocation keys in one signature: 2440 says
+               "Note that it may be appropriate to isolate this
+               subpacket within a separate signature so that it is not
+               combined with other subpackets that need to be
+               exported." -dms */
+
+           while(!revkey)
              {
                KBNODE signode;
 
-               node=find_next_kbnode(node,PKT_USER_ID);
-               if(!node)
-                 {
-                   /* We're out of user IDs - none were
-                       self-signed. */
-                   if(uid)
-                     break;
-                   else
-                     {
-                       rc=G10ERR_GENERAL;
-                       log_error(_("key %08lX incomplete\n"),(ulong)keyid[1]);
-                       goto leave;
-                     }
-                 }
-
-               if(node->pkt->pkt.user_id->attrib_data)
-                 continue;
+               signode=find_next_kbnode(node,PKT_SIGNATURE);
+               if(!signode)
+                 break;
 
-               uid=node->pkt->pkt.user_id;
-               signode=node;
+               node=signode;
 
-               while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
+               if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
+                  keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
+                  IS_KEY_SIG(signode->pkt->pkt.signature))
                  {
-                   if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
-                      keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
-                      IS_UID_SIG(signode->pkt->pkt.signature))
+                   int j;
+
+                   for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++)
                      {
-                       selfsig=signode->pkt->pkt.signature;
-                       break;
+                       if(pk->revkey[i].class==
+                          signode->pkt->pkt.signature->revkey[j]->class &&
+                          pk->revkey[i].algid==
+                          signode->pkt->pkt.signature->revkey[j]->algid &&
+                          memcmp(pk->revkey[i].fpr,
+                                 signode->pkt->pkt.signature->revkey[j]->fpr,
+                                 MAX_FINGERPRINT_LEN)==0)
+                         {
+                           revkey=signode->pkt->pkt.signature;
+                           break;
+                         }
                      }
                  }
              }
 
-           pkt.pkttype = PKT_USER_ID;
-           pkt.pkt.user_id = uid;
+           if(!revkey)
+             BUG();
 
-           rc = build_packet( out, &pkt );
-           if( rc ) {
-             log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
+           rc=export_minimal_pk(out,keyblock,sig,revkey);
+           if(rc)
              goto leave;
-           }
-
-           if(selfsig)
-             {
-               pkt.pkttype = PKT_SIGNATURE;
-               pkt.pkt.signature = selfsig;
-
-               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"));
@@ -300,21 +410,24 @@ gen_desig_revoke( const char *uname )
       }
 
     if(!any)
-      log_error(_("no revocation keys found for `%s'\n"),uname);
+      log_error(_("no revocation keys found for \"%s\"\n"),uname);
 
   leave:
     if( pk )
        free_public_key( pk );
-    if( sk )
-       free_secret_key( sk );
+    if (pk2)
+       free_public_key (pk2);
     if( sig )
        free_seckey_enc( sig );
 
+    release_sk_list(sk_list);
+
     if( rc )
        iobuf_cancel(out);
     else
        iobuf_close(out);
     release_revocation_reason_info( reason );
+    release_armor_context (afx);
     return rc;
 }
 
@@ -326,38 +439,41 @@ int
 gen_revoke( const char *uname )
 {
     int rc = 0;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx;
     PACKET pkt;
     PKT_secret_key *sk; /* used as pointer into a kbnode */
     PKT_public_key *pk = NULL;
     PKT_signature *sig = NULL;
     u32 sk_keyid[2];
     IOBUF out = NULL;
-    KBNODE keyblock = NULL;
+    KBNODE keyblock = NULL, pub_keyblock = NULL;
     KBNODE node;
     KEYDB_HANDLE kdbhd;
     struct revocation_reason_info *reason = NULL;
     KEYDB_SEARCH_DESC desc;
 
-    if( opt.batch ) {
-       log_error(_("sorry, can't do this in batch mode\n"));
+    if( opt.batch )
+      {
+       log_error(_("can't do this in batch mode\n"));
        return G10ERR_GENERAL;
-    }
+      }
 
-    memset( &afx, 0, sizeof afx);
+    afx = new_armor_context ();
     init_packet( &pkt );
 
     /* search the userid: 
      * We don't want the whole getkey stuff here but the entire keyblock
      */
     kdbhd = keydb_new (1);
-    classify_user_id (uname, &desc);
-    rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
-    if (rc) {
-       log_error (_("secret key `%s' not found: %s\n"),
+    rc = classify_user_id (uname, &desc);
+    if (!rc)
+      rc = keydb_search (kdbhd, &desc, 1);
+    if (rc)
+      {
+       log_error (_("secret key \"%s\" not found: %s\n"),
                    uname, g10_errstr (rc));
        goto leave;
-    }
+      }
 
     rc = keydb_get_keyblock (kdbhd, &keyblock );
     if( rc ) {
@@ -374,25 +490,23 @@ gen_revoke( const char *uname )
      * it's used all over the source */
     sk = node->pkt->pkt.secret_key;
     keyid_from_sk( sk, sk_keyid );
-    tty_printf("\nsec  %4u%c/%08lX %s   ",
-             nbits_from_sk( sk ),
-             pubkey_letter( sk->pubkey_algo ),
-             (ulong)sk_keyid[1], datestr_from_sk(sk) );
-    {
-       size_t n;
-       char *p = get_user_id( sk_keyid, &n );
-       tty_print_utf8_string( p, n );
-       m_free(p);
-       tty_printf("\n");
-    }
-    pk = m_alloc_clear( sizeof *pk );
+    print_seckey_info (sk);
 
     /* FIXME: We should get the public key direct from the secret one */
-    rc = get_pubkey( pk, sk_keyid );
-    if( rc ) {
+
+    pub_keyblock=get_pubkeyblock(sk_keyid);
+    if(!pub_keyblock)
+      {
        log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
        goto leave;
-    }
+      }
+
+    node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
+    if(!node)
+      BUG();
+
+    pk=node->pkt->pkt.public_key;
+
     if( cmp_public_secret_key( pk, sk ) ) {
        log_error(_("public key does not match secret key!\n") );
        rc = G10ERR_GENERAL;
@@ -401,10 +515,11 @@ gen_revoke( const char *uname )
 
     tty_printf("\n");
     if( !cpr_get_answer_is_yes("gen_revoke.okay",
-                       _("Create a revocation certificate for this key? ")) ){
+                 _("Create a revocation certificate for this key? (y/N) ")) )
+      {
        rc = 0;
        goto leave;
-    }
+      }
 
     if(sk->version>=4 || opt.force_v4_certs) {
       /* get the reason for the revocation */
@@ -420,11 +535,15 @@ gen_revoke( const char *uname )
        log_error(_("unknown protection algorithm\n"));
        rc = G10ERR_PUBKEY_ALGO;
        break;
+      case -3:
+       tty_printf (_("Secret parts of primary key are not available.\n"));
+        rc = G10ERR_NO_SECKEY;
+        break;
       case 0:
        tty_printf(_("NOTE: This key is not protected!\n"));
        break;
       default:
-       rc = check_secret_key( sk, 0 );
+        rc = check_secret_key( sk, 0 );
        break;
     }
     if( rc )
@@ -434,12 +553,12 @@ gen_revoke( const char *uname )
     if( !opt.armor )
        tty_printf(_("ASCII armored output forced.\n"));
 
-    if( (rc = open_outfile( NULL, 0, &out )) )
+    if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
        goto leave;
 
-    afx.what = 1;
-    afx.hdrlines = "Comment: A revocation certificate should follow\n";
-    iobuf_push_filter( out, armor_filter, &afx );
+    afx->what = 1;
+    afx->hdrlines = "Comment: A revocation certificate should follow\n";
+    push_armor_filter (afx, out);
 
     /* create it */
     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
@@ -449,15 +568,27 @@ gen_revoke( const char *uname )
        log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
        goto leave;
     }
-    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;
-    }
+    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,pub_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"
@@ -467,20 +598,18 @@ gen_revoke( const char *uname )
 "your media become unreadable.  But have some caution:  The print system of\n"
 "your machine might store the data and make it available to others!\n"));
 
-
-
   leave:
-    if( pk )
-       free_public_key( pk );
     if( sig )
        free_seckey_enc( sig );
     release_kbnode( keyblock );
+    release_kbnode( pub_keyblock );
     keydb_release (kdbhd);
     if( rc )
        iobuf_cancel(out);
     else
        iobuf_close(out);
     release_revocation_reason_info( reason );
+    release_armor_context (afx);
     return rc;
 }
 
@@ -500,7 +629,8 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
     const char *code_text = NULL;
 
     do {
-       m_free(description);
+        code=-1;
+       xfree(description);
        description = NULL;
 
        tty_printf(_("Please select the reason for the revocation:\n"));
@@ -527,11 +657,11 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
              return NULL; /* cancel */
            if( hint && !*answer )
                n = hint;
-           else if(!isdigit( *answer ) )
+           else if(!digitp( answer ) )
                n = -1;
            else
                n = atoi(answer);
-           m_free(answer);
+           xfree(answer);
            if( n == 0 ) {
                code = 0x00; /* no particular reason */
                code_text = text_0;
@@ -563,25 +693,25 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
            trim_trailing_ws( answer, strlen(answer) );
            cpr_kill_prompt();
            if( !*answer ) {
-               m_free(answer);
+               xfree(answer);
                break;
            }
 
            {
                char *p = make_printable_string( answer, strlen(answer), 0 );
-               m_free(answer);
+               xfree(answer);
                answer = p;
            }
 
            if( !description )
-               description = m_strdup(answer);
+               description = xstrdup(answer);
            else {
-               char *p = m_alloc( strlen(description) + strlen(answer) + 2 );
+               char *p = xmalloc( strlen(description) + strlen(answer) + 2 );
                strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
-               m_free(description);
+               xfree(description);
                description = p;
            }
-           m_free(answer);
+           xfree(answer);
        }
 
        tty_printf(_("Reason for revocation: %s\n"), code_text );
@@ -591,9 +721,9 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint )
            tty_printf("%s\n", description );
 
     } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
-                                           _("Is this okay? "))  );
+                                           _("Is this okay? (y/N) "))  );
 
-    reason = m_alloc( sizeof *reason );
+    reason = xmalloc( sizeof *reason );
     reason->code = code;
     reason->desc = description;
     return reason;
@@ -603,7 +733,7 @@ void
 release_revocation_reason_info( struct revocation_reason_info *reason )
 {
     if( reason ) {
-       m_free( reason->desc );
-       m_free( reason );
+       xfree( reason->desc );
+       xfree( reason );
     }
 }