* gpg.sgml: Add bkuptocard command for --edit-key.
authorWerner Koch <wk@gnupg.org>
Tue, 15 Feb 2005 11:02:32 +0000 (11:02 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 15 Feb 2005 11:02:32 +0000 (11:02 +0000)
* passphrase.c (agent_get_passphrase): Don't call free_public_key
if PK is NULL.
(passphrase_clear_cache): Ditto. Removed debug output.
(passphrase_to_dek): Ditto.

NEWS
doc/ChangeLog
doc/gpg.sgml
g10/ChangeLog
g10/card-util.c
g10/keyedit.c
g10/keygen.c
g10/misc.c
g10/passphrase.c

diff --git a/NEWS b/NEWS
index c8cea2d..30d8142 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -47,6 +47,9 @@ Noteworthy changes in version 1.4.1
       that directory must be stored in the registry at the same key as
       above with the name "Install Directory".
 
+    * Add new --edit-key command "bkuptocard" to allow restoring a
+      card key from a backup.
+
 
 Noteworthy changes in version 1.4.0 (2004-12-16)
 ------------------------------------------------
index eb94d7a..b76491e 100644 (file)
@@ -1,3 +1,7 @@
+2005-02-15  Werner Koch  <wk@g10code.com>
+
+       * gpg.sgml: Add bkuptocard command for --edit-key.
+
 2005-02-05  David Shaw  <dshaw@jabberwocky.com>
 
        * gpg.sgml: Note that level 0 signatures are always accepted
index 686fa88..03a7eb8 100644 (file)
@@ -1,6 +1,6 @@
 <!-- gpg.sgml - the man page for GnuPG
     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
-                  2004 Free Software Foundation, Inc.
+                  2004, 2005 Free Software Foundation, Inc.
 
     This file is part of GnuPG.
 
@@ -427,6 +427,18 @@ to store the key.  Note that it is not possible to get that key back
 from the card - if the card gets broken your secret key will be lost
 unless you have a backup somewhere.</para></listitem></varlistentry>
     <varlistentry>
+    <term>bkuptocard &ParmFile;</term>
+    <listitem><para>
+Restore the given file to a card. This command
+may be used to restore a backup key (as generated during card
+initialization) to a new card.  In almost all cases this will be the
+encryption key. You should use this command only
+with the corresponding public key and make sure that the file
+given as argument is indeed the backup to restore.  You should
+then select 2 to restore as encryption key.
+You will first be asked to enter the passphrase of the backup key and
+then for the Admin PIN of the card.</para></listitem></varlistentry>
+    <varlistentry>
     <term>delkey</term>
     <listitem><para>
 Remove a subkey.</para></listitem></varlistentry>
index c3cf99e..b3364d4 100644 (file)
@@ -1,3 +1,15 @@
+2005-02-15  Werner Koch  <wk@g10code.com>
+
+       * passphrase.c (agent_get_passphrase): Don't call free_public_key
+       if PK is NULL.
+       (passphrase_clear_cache): Ditto. Removed debug output.
+       (passphrase_to_dek): Ditto.
+
+2005-02-13  Werner Koch  <wk@g10code.com>
+
+       * keyedit.c (cmds): Limit code to 80 columns. Add command
+       BKUPTOCARD.
+
 2005-02-09  David Shaw  <dshaw@jabberwocky.com>
 
        * encr-data.c (decrypt_data): Use it here to turn off the "quick
@@ -7,6 +19,11 @@
        * mainproc.c (proc_symkey_enc): Set a flag to indicate that a
        particular session key came from a passphrase and not a PK.
 
+2005-02-08  Werner Koch  <wk@g10code.com>
+
+       * misc.c (w32_shgetfolderpath): New.
+       (default_homedir): Use it to avoid problems under Windows95.
+
 2005-02-06  David Shaw  <dshaw@jabberwocky.com>
 
        * trustdb.h, trustdb.c (trustdb_check_or_update): New.  If the
index 3b67400..928a5af 100644 (file)
@@ -1122,9 +1122,10 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
 }
 
 
-/* Store the subkey at NODE into the smartcard and modify NODE to
-   carry the serrialno stuff instead of the actual secret key
-   parameters. */
+/* Store the key at NODE into the smartcard and modify NODE to
+   carry the serialno stuff instead of the actual secret key
+   parameters.  USE is the usage for that key; 0 means any
+   usage. */
 int 
 card_store_subkey (KBNODE node, int use)
 {
index 39e7fbd..27cd941 100644 (file)
@@ -1303,7 +1303,7 @@ enum cmdids
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
     cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
     cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
-    cmdADDCARDKEY, cmdKEYTOCARD, cmdNOP
+    cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdNOP
   };
 
 static struct
@@ -1326,47 +1326,79 @@ static struct
     { "key"     , cmdSELKEY    , 0, N_("select subkey N") },
     { "check"   , cmdCHECK     , 0, N_("check signatures") },
     { "c"       , cmdCHECK     , 0, NULL },
-    { "sign"    , cmdSIGN      , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH, N_("sign selected user IDs [* see below for related commands]") },
+    { "sign"    , cmdSIGN      , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH,
+      N_("sign selected user IDs [* see below for related commands]") },
     { "s"       , cmdSIGN      , KEYEDIT_NOT_SK, NULL },
     /* "lsign" and friends will never match since "sign" comes first
        and it is a tail match.  They are just here so they show up in
        the help menu. */
     { "lsign"   , cmdNOP       , 0, N_("sign selected user IDs locally") },
-    { "tsign"   , cmdNOP       , 0, N_("sign selected user IDs with a trust signature") },
-    { "nrsign"  , cmdNOP       , 0, N_("sign selected user IDs with a non-revocable signature") },
+    { "tsign"   , cmdNOP       , 0,
+      N_("sign selected user IDs with a trust signature") },
+    { "nrsign"  , cmdNOP       , 0,
+      N_("sign selected user IDs with a non-revocable signature") },
+
     { "debug"   , cmdDEBUG     , 0, NULL },
-    { "adduid"  , cmdADDUID    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a user ID") },
-    { "addphoto", cmdADDPHOTO  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a photo ID") },
-    { "deluid"  , cmdDELUID    , KEYEDIT_NOT_SK, N_("delete selected user IDs") },
+    { "adduid"  , cmdADDUID    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("add a user ID") },
+    { "addphoto", cmdADDPHOTO  , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("add a photo ID") },
+    { "deluid"  , cmdDELUID    , KEYEDIT_NOT_SK,
+      N_("delete selected user IDs") },
     /* delphoto is really deluid in disguise */
     { "delphoto", cmdDELUID    , KEYEDIT_NOT_SK, NULL },
-    { "addkey"  , cmdADDKEY    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a subkey") },
+
+    { "addkey"  , cmdADDKEY    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("add a subkey") },
+
 #ifdef ENABLE_CARD_SUPPORT
-    { "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a key to a smartcard") },
-    { "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, N_("move a key to a smartcard")},
+    { "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("add a key to a smartcard") },
+    { "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
+      N_("move a key to a smartcard")},
+    { "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
+      N_("move a backup key to a smartcard")},
 #endif /*ENABLE_CARD_SUPPORT*/
-    { "delkey"  , cmdDELKEY    , KEYEDIT_NOT_SK, N_("delete selected subkeys") },
-    { "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a revocation key") },
-    { "delsig"  , cmdDELSIG    , KEYEDIT_NOT_SK, N_("delete signatures from the selected user IDs") },
-    { "expire"  , cmdEXPIRE    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the expiration date for the key or selected subkeys") },
-    { "primary" , cmdPRIMARY   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("flag the selected user ID as primary")},
-    { "toggle"  , cmdTOGGLE    , KEYEDIT_NEED_SK, N_("toggle between the secret and public key listings") },
+
+    { "delkey"  , cmdDELKEY    , KEYEDIT_NOT_SK,
+      N_("delete selected subkeys") },
+    { "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("add a revocation key") },
+    { "delsig"  , cmdDELSIG    , KEYEDIT_NOT_SK,
+      N_("delete signatures from the selected user IDs") },
+    { "expire"  , cmdEXPIRE    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("change the expiration date for the key or selected subkeys") },
+    { "primary" , cmdPRIMARY   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("flag the selected user ID as primary")},
+    { "toggle"  , cmdTOGGLE    , KEYEDIT_NEED_SK,
+      N_("toggle between the secret and public key listings") },
     { "t"       , cmdTOGGLE    , KEYEDIT_NEED_SK, NULL },
-    { "pref"    , cmdPREF      , KEYEDIT_NOT_SK, N_("list preferences (expert)")},
-    { "showpref", cmdSHOWPREF  , KEYEDIT_NOT_SK, N_("list preferences (verbose)") },
-    { "setpref" , cmdSETPREF   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preference list for the selected user IDs") },
+    { "pref"    , cmdPREF      , KEYEDIT_NOT_SK,
+      N_("list preferences (expert)")},
+    { "showpref", cmdSHOWPREF  , KEYEDIT_NOT_SK,
+      N_("list preferences (verbose)") },
+    { "setpref" , cmdSETPREF   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("set preference list for the selected user IDs") },
     /* Alias */
     { "updpref" , cmdSETPREF   , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
-    { "keyserver",cmdPREFKS    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preferred keyserver URL for the selected user IDs")},
-    { "passwd"  , cmdPASSWD    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the passphrase") },
+
+    { "keyserver",cmdPREFKS    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("set preferred keyserver URL for the selected user IDs")},
+    { "passwd"  , cmdPASSWD    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("change the passphrase") },
     /* Alias */
     { "password", cmdPASSWD    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
+
     { "trust"   , cmdTRUST     , KEYEDIT_NOT_SK, N_("change the ownertrust") },
-    { "revsig"  , cmdREVSIG    , KEYEDIT_NOT_SK, N_("revoke signatures on the selected user IDs") },
-    { "revuid"  , cmdREVUID    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke selected user IDs") },
+    { "revsig"  , cmdREVSIG    , KEYEDIT_NOT_SK,
+      N_("revoke signatures on the selected user IDs") },
+    { "revuid"  , cmdREVUID    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("revoke selected user IDs") },
     /* Alias */
     { "revphoto", cmdREVUID    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
-    { "revkey"  , cmdREVKEY    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke key or selected subkeys") },
+
+    { "revkey"  , cmdREVKEY    , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
+      N_("revoke key or selected subkeys") },
     { "enable"  , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") },
     { "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") },
     { "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") },
@@ -1550,7 +1582,8 @@ keyedit_menu( const char *username, STRLIST locusr,
 
            tty_printf("\n");
            tty_printf(_(
-"* The `sign' command may be prefixed with an `l' for local signatures (lsign),\n"
+"* The `sign' command may be prefixed with an `l' for local "
+"signatures (lsign),\n"
 "  a `t' for trust signatures (tsign), an `nr' for non-revocable signatures\n"
 "  (nrsign), or any combination thereof (ltsign, tnrsign, etc.).\n"));
 
@@ -1744,6 +1777,69 @@ keyedit_menu( const char *username, STRLIST locusr,
              }
          }
           break;
+
+        case cmdBKUPTOCARD:
+         {
+            /* Ask for a filename, check whether this is really a
+               backup key as generated by the card generation, parse
+               that key and store it on card. */
+           KBNODE node;
+            const char *fname;
+            PACKET *pkt;
+            IOBUF a;
+
+            fname = arg_string;
+            if (!*fname)
+              {
+                tty_printf (_("Command expects a filename argument\n"));
+                break;
+              }
+
+            /* Open that file.  */
+            a = iobuf_open (fname);
+            if (a && is_secured_file (iobuf_get_fd (a)))
+              {
+                iobuf_close (a);
+                a = NULL;
+                errno = EPERM;
+              }
+            if (!a)
+              {
+               tty_printf (_("Can't open `%s': %s\n"),
+                            fname, strerror(errno));
+                break;
+              }
+            
+            /* Parse and check that file.  */
+            pkt = xmalloc (sizeof *pkt);
+            init_packet (pkt);
+            rc = parse_packet (a, pkt);
+            iobuf_close (a);
+            iobuf_ioctl (NULL, 2, 0, (char*)fname); /* (invalidate cache).  */
+            if (!rc 
+                && pkt->pkttype != PKT_SECRET_KEY 
+                && pkt->pkttype != PKT_SECRET_SUBKEY)
+              rc = G10ERR_NO_SECKEY;
+            if (rc)
+              {
+                tty_printf(_("Error reading backup key from `%s': %s\n"),
+                           fname, g10_errstr (rc));
+                free_packet (pkt);
+                xfree (pkt);
+                break;
+              }
+            node = new_kbnode (pkt);
+
+            /* Store it.  */
+            if (card_store_subkey (node, 0))
+              {
+                redisplay = 1;
+                sec_modified = 1;
+              }
+            release_kbnode (node);
+         }
+          break;
+
 #endif /* ENABLE_CARD_SUPPORT */
 
          case cmdDELKEY: {
index abef681..be8a8e5 100644 (file)
@@ -1636,7 +1636,8 @@ ask_user_id( int mode )
 
     if( !mode )
        tty_printf( _("\n"
-"You need a user ID to identify your key; the software constructs the user ID\n"
+"You need a user ID to identify your key; "
+                                        "the software constructs the user ID\n"
 "from the Real Name, Comment and Email Address in this form:\n"
 "    \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
     uid = aname = acomment = amail = NULL;
@@ -1731,7 +1732,7 @@ ask_user_id( int mode )
        }
 
        for(;;) {
-            /* Note to translators: These are the allowed answers in
+            /* TRANSLATORS: These are the allowed answers in
                lower and uppercase.  Below you will find the matching
                string which should be translated accordingly and the
                letter changed to match the one in the answer string.
index 2c3fbf1..9334dae 100644 (file)
@@ -51,6 +51,8 @@
 #ifndef CSIDL_FLAG_CREATE
 #define CSIDL_FLAG_CREATE 0x8000
 #endif
+#include "errors.h"
+#include "dynload.h"
 #endif /*_WIN32*/
 
 #include "util.h"
@@ -1018,6 +1020,46 @@ parse_options(char *str,unsigned int *options,
 }
 
 
+/* This is a helper function to load a Windows function from either of
+   one DLLs. */
+#ifdef HAVE_W32_SYSTEM
+static HRESULT
+w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
+{
+  static int initialized;
+  static HRESULT (* WINAPI func)(HWND,int,HANDLE,DWORD,LPSTR);
+
+  if (!initialized)
+    {
+      static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
+      void *handle;
+      int i;
+
+      initialized = 1;
+
+      for (i=0, handle = NULL; !handle && dllnames[i]; i++)
+        {
+          handle = dlopen (dllnames[i], RTLD_LAZY);
+          if (handle)
+            {
+              func = dlsym (handle, "SHGetFolderPathA");
+              if (!func)
+                {
+                  dlclose (handle);
+                  handle = NULL;
+                }
+            }
+        }
+    }
+
+  if (func)
+    return func (a,b,c,d,e);
+  else
+    return -1;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
 /* Set up the default home directory.  The usual --homedir option
    should be parsed later. */
 char *
@@ -1040,8 +1082,8 @@ default_homedir (void)
          using a system roaming serives might be better than to let
          them do it manually.  A security conscious user will anyway
          use the registry entry to have better control.  */
-      if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
-                          NULL, 0, path) >= 0) 
+      if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
+                               NULL, 0, path) >= 0) 
         {
           char *tmp = xmalloc (strlen (path) + 6 +1);
           strcpy (stpcpy (tmp, path), "\\gnupg");
index eed2399..da2820b 100644 (file)
@@ -1,6 +1,6 @@
 /* passphrase.c -  Get a passphrase
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004 Free Software Foundation, Inc.
+ *               2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -661,7 +661,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
   memset (fpr, 0, MAX_FINGERPRINT_LEN );
   if( keyid && get_pubkey( pk, keyid ) )
     {
-      free_public_key( pk );      
+      if (pk)
+        free_public_key( pk );      
       pk = NULL; /* oops: no key for some reason */
     }
   
@@ -795,7 +796,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
             }
           pw[pwlen] = 0; /* make a C String */
           agent_close (fd);
-          free_public_key( pk );
+          if (pk)
+            free_public_key( pk );
 #ifdef ENABLE_NLS
           if (orig_codeset)
             bind_textdomain_codeset (PACKAGE, orig_codeset);
@@ -912,7 +914,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
             pw[pwlen++] = xtoi_2 (pw+i);
           pw[pwlen] = 0; /* make a C String */
           agent_close (fd);
-          free_public_key( pk );
+          if (pk)
+            free_public_key( pk );
 #ifdef ENABLE_NLS
           if (orig_codeset)
             bind_textdomain_codeset (PACKAGE, orig_codeset);
@@ -946,7 +949,8 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
   if ( fd != -1 )
     agent_close (fd);
   m_free (pw );
-  free_public_key( pk );
+  if (pk)
+    free_public_key( pk );
   
   return NULL;
 #endif /* Posix or W32 */
@@ -981,7 +985,6 @@ passphrase_clear_cache ( u32 *keyid, int algo )
   memset (fpr, 0, MAX_FINGERPRINT_LEN );
   if( !keyid || get_pubkey( pk, keyid ) )
     {
-      log_debug ("oops, no key in passphrase_clear_cache\n");
       goto failure; /* oops: no key for some reason */
     }
   
@@ -1051,7 +1054,8 @@ passphrase_clear_cache ( u32 *keyid, int algo )
  failure:
   if (fd != -1)
     agent_close (fd);
-  free_public_key( pk );
+  if (pk)
+    free_public_key( pk );
 #endif /* Posix or W32 */
 }
 
@@ -1208,7 +1212,8 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
        }
 
        tty_printf("\n");
-       free_public_key( pk );
+        if (pk)
+          free_public_key( pk );
     }
 
  agent_died: