g10: Always save standard revocation certificate in file.
[gnupg.git] / g10 / skclist.c
index fd677eb..78890dc 100644 (file)
@@ -15,7 +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, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "status.h"
+#include "../common/status.h"
 #include "keydb.h"
-#include "util.h"
-#include "i18n.h"
-#include "cipher.h"
+#include "../common/util.h"
+#include "../common/i18n.h"
+#include "call-agent.h"
 
 
 /* Return true if Libgcrypt's RNG is in faked mode.  */
@@ -51,8 +50,7 @@ release_sk_list (SK_LIST sk_list)
   for (; sk_list; sk_list = sk_rover)
     {
       sk_rover = sk_list->next;
-      if (sk_list->pk)
-        free_public_key (sk_list->pk);
+      free_public_key (sk_list->pk);
       xfree (sk_list);
     }
 }
@@ -62,14 +60,14 @@ release_sk_list (SK_LIST sk_list)
  * the string "(insecure!)" or "not secure" or "do not use"
  * in one of the user ids.  */
 static int
-is_insecure (PKT_public_key *pk)
+is_insecure (ctrl_t ctrl, PKT_public_key *pk)
 {
   u32 keyid[2];
   KBNODE node = NULL, u;
   int insecure = 0;
 
   keyid_from_pk (pk, keyid);
-  node = get_pubkeyblock (keyid);
+  node = get_pubkeyblock (ctrl, keyid);
   for (u = node; u; u = u->next)
     {
       if (u->pkt->pkttype == PKT_USER_ID)
@@ -115,21 +113,44 @@ is_duplicated_entry (strlist_t list, strlist_t item)
 }
 
 
-/* FIXME:  We ignore the UNLOCK flag - should not be needed anymore.  */
 gpg_error_t
-build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
-              int unlock, unsigned int use)
+build_sk_list (ctrl_t ctrl,
+               strlist_t locusr, SK_LIST *ret_sk_list, unsigned int use)
 {
   gpg_error_t err;
   SK_LIST sk_list = NULL;
 
-  if (!locusr) /* No user ids given - use the default key.  */
+  /* XXX: Change this function to use get_pubkeys instead of
+     getkey_byname to detect ambiguous key specifications and warn
+     about duplicate keyblocks.  For ambiguous key specifications on
+     the command line or provided interactively, prompt the user to
+     select the best key.  If a key specification is ambiguous and we
+     are in batch mode, die.  */
+
+  if (!locusr) /* No user ids given - use the card key or the default key.  */
     {
+      struct agent_card_info_s info;
       PKT_public_key *pk;
+      char *serialno;
 
+      memset (&info, 0, sizeof(info));
       pk = xmalloc_clear (sizeof *pk);
       pk->req_usage = use;
-      if ((err = getkey_byname (NULL, pk, NULL, 1, NULL)))
+
+      /* Check if a card is available.  If any, use the key as a hint.  */
+      err = agent_scd_serialno (&serialno, NULL);
+      if (!err)
+        {
+          xfree (serialno);
+          err = agent_scd_getattr ("KEY-FPR", &info);
+          if (err)
+            log_error ("error retrieving key fingerprint from card: %s\n",
+                       gpg_strerror (err));
+        }
+
+      err = get_seckey_default_or_card (ctrl, pk,
+                                        info.fpr1valid? info.fpr1 : NULL, 20);
+      if (err)
        {
          free_public_key (pk);
          pk = NULL;
@@ -146,8 +167,8 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
       else
        {
          SK_LIST r;
-          
-         if (random_is_faked () && !is_insecure (pk))
+
+         if (random_is_faked () && !is_insecure (ctrl, pk))
            {
              log_info (_("key is not flagged as insecure - "
                          "can't use it with the faked RNG!\n"));
@@ -186,7 +207,7 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
            }
          pk = xmalloc_clear (sizeof *pk);
          pk->req_usage = use;
-          if ((err = getkey_byname (NULL, pk, locusr->d, 1, NULL)))
+          if ((err = getkey_byname (ctrl, NULL, pk, locusr->d, 1, NULL)))
            {
              free_public_key (pk);
              pk = NULL;
@@ -202,18 +223,6 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
              pk = NULL;
              log_info (_("skipped: secret key already present\n"));
            }
-          /* Fixme:  We could change the next test by a call to gpg-agent which
-             would then cache the passphrase.  */
-         /* else if (unlock && (rc = check_secret_key (sk, 0))) */
-         /*   { */
-         /*     free_secret_key (sk); */
-         /*     sk = NULL; */
-         /*     log_error (_("skipped \"%s\": %s\n"), */
-         /*             locusr->d, g10_errstr (rc)); */
-         /*     write_status_text_and_buffer */
-         /*       (STATUS_INV_SGNR, get_inv_recpsgnr_code (rc), */
-         /*        locusr->d, strlen (locusr->d), -1); */
-         /*   } */
          else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
            {
              free_public_key (pk);
@@ -226,7 +235,7 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
          else
            {
              SK_LIST r;
-              
+
              if (pk->version == 4 && (use & PUBKEY_USAGE_SIG)
                  && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
                {
@@ -240,7 +249,7 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
                     get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE),
                     locusr->d, strlen (locusr->d), -1);
                }
-             else if (random_is_faked () && !is_insecure (pk))
+             else if (random_is_faked () && !is_insecure (ctrl, pk))
                {
                  log_info (_("key is not flagged as insecure - "
                              "can't use it with the faked RNG!\n"));
@@ -270,7 +279,7 @@ build_sk_list (strlist_t locusr, SK_LIST *ret_sk_list,
       write_status_text (STATUS_NO_SGNR, "0");
       err = gpg_error (GPG_ERR_NO_USER_ID);
     }
-  
+
   if (err)
     release_sk_list (sk_list);
   else