gpg: Add import filter "drop-sig".
authorWerner Koch <wk@gnupg.org>
Thu, 18 Aug 2016 14:15:49 +0000 (16:15 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 18 Aug 2016 14:15:49 +0000 (16:15 +0200)
* g10/import.c (import_drop_sig): New variable.
(cleanup_import_globals): Release that.
(parse_and_set_import_filter): Add filter "drop-sig".
(filter_getval): Implement properties for drop-sig.
(apply_drop_sig_filter): New.
(import_one): Apply that filter.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/gpg.texi
g10/import.c

index 52a50f5..fbcaa15 100644 (file)
@@ -2254,6 +2254,11 @@ The available filter types are:
   This filter will keep a user id packet and its dependent packets in
   the keyblock if the expression evaluates to true.
 
   This filter will keep a user id packet and its dependent packets in
   the keyblock if the expression evaluates to true.
 
+  @item drop-sig
+  This filter drops the selected key signatures on user ids.
+  Self-signatures are not consideres.
+  Currently only implemented for --import-filter.
+
 @end table
 
 For the syntax of the expression see the chapter "FILTER EXPRESSIONS".
 @end table
 
 For the syntax of the expression see the chapter "FILTER EXPRESSIONS".
@@ -2274,6 +2279,18 @@ The available properties are:
   @item primary
   Boolean indicating whether the user id is the primary one.  (keep-uid)
 
   @item primary
   Boolean indicating whether the user id is the primary one.  (keep-uid)
 
+  @item sig_created
+  @itemx sig_created_d
+  The first is the timestamp a signature packet was created.  The
+  second is the same but given as an ISO string,
+  e.g. "2016-08-17". (drop-sig)
+
+  @item sig_algo
+  A number with the public key algorithm of a signature packet. (drop-sig)
+
+  @item sig_digest_algo
+  A number with the digest algorithm of a signature packet. (drop-sig)
+
 @end table
 
 @item --export-options @code{parameters}
 @end table
 
 @item --export-options @code{parameters}
index 3c7edd7..f7cb923 100644 (file)
@@ -76,13 +76,15 @@ struct import_stats_s
 #define NODE_FLAG_A  8
 
 
 #define NODE_FLAG_A  8
 
 
-/* A global variable to store the selector created from
+/* Global variables to store selector created from
  * --import-filter keep-uid=EXPR.
  * --import-filter keep-uid=EXPR.
+ * --import-filter drop-sig=EXPR.
  *
  * FIXME: We should put this into the CTRL object but that requires a
  * lot more changes right now.
  */
 static recsel_expr_t import_keep_uid;
  *
  * FIXME: We should put this into the CTRL object but that requires a
  * lot more changes right now.
  */
 static recsel_expr_t import_keep_uid;
+static recsel_expr_t import_drop_sig;
 
 
 
 
 
 
@@ -122,6 +124,8 @@ cleanup_import_globals (void)
 {
   recsel_release (import_keep_uid);
   import_keep_uid = NULL;
 {
   recsel_release (import_keep_uid);
   import_keep_uid = NULL;
+  recsel_release (import_drop_sig);
+  import_drop_sig = NULL;
 }
 
 
 }
 
 
@@ -198,6 +202,8 @@ parse_and_set_import_filter (const char *string)
 
   if (!strncmp (string, "keep-uid=", 9))
     err = recsel_parse_expr (&import_keep_uid, string+9);
 
   if (!strncmp (string, "keep-uid=", 9))
     err = recsel_parse_expr (&import_keep_uid, string+9);
+  else if (!strncmp (string, "drop-sig=", 9))
+    err = recsel_parse_expr (&import_drop_sig, string+9);
   else
     err = gpg_error (GPG_ERR_INV_NAME);
 
   else
     err = gpg_error (GPG_ERR_INV_NAME);
 
@@ -1097,11 +1103,13 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
 }
 
 
 }
 
 
-/* Helper for apply_keep_uid_filter.  */
+/* Helper for apply_keep_uid_filter and apply_drop_sig_filter.  */
 static const char *
 filter_getval (void *cookie, const char *propname)
 {
 static const char *
 filter_getval (void *cookie, const char *propname)
 {
+  /* FIXME: Malloc our static buffers and access them via the cookie.  */
   kbnode_t node = cookie;
   kbnode_t node = cookie;
+  static char numbuf[20];
   const char *result;
 
   if (node->pkt->pkttype == PKT_USER_ID)
   const char *result;
 
   if (node->pkt->pkttype == PKT_USER_ID)
@@ -1115,19 +1123,47 @@ filter_getval (void *cookie, const char *propname)
               node->pkt->pkt.user_id->mbox
                 = mailbox_from_userid (node->pkt->pkt.user_id->name);
             }
               node->pkt->pkt.user_id->mbox
                 = mailbox_from_userid (node->pkt->pkt.user_id->name);
             }
-          return node->pkt->pkt.user_id->mbox;
+          result = node->pkt->pkt.user_id->mbox;
         }
       else if (!strcmp (propname, "primary"))
         result = node->pkt->pkt.user_id->is_primary? "1":"0";
       else
         result = NULL;
     }
         }
       else if (!strcmp (propname, "primary"))
         result = node->pkt->pkt.user_id->is_primary? "1":"0";
       else
         result = NULL;
     }
+  else if (node->pkt->pkttype == PKT_SIGNATURE
+           || node->pkt->pkttype == PKT_ATTRIBUTE)
+    {
+      PKT_signature *sig = node->pkt->pkt.signature;
+
+      if (!strcmp (propname, "sig_created"))
+        {
+          snprintf (numbuf, sizeof numbuf, "%lu", (ulong)sig->timestamp);
+          result = numbuf;
+        }
+      else if (!strcmp (propname, "sig_created_d"))
+        {
+          result = datestr_from_sig (sig);
+        }
+      else if (!strcmp (propname, "sig_algo"))
+        {
+          snprintf (numbuf, sizeof numbuf, "%d", sig->pubkey_algo);
+          result = numbuf;
+        }
+      else if (!strcmp (propname, "sig_digest_algo"))
+        {
+          snprintf (numbuf, sizeof numbuf, "%d", sig->digest_algo);
+          result = numbuf;
+        }
+      else
+        result = NULL;
+    }
   else
     result = NULL;
 
   return result;
 }
 
   else
     result = NULL;
 
   return result;
 }
 
+
 /*
  * Apply the keep-uid filter to the keyblock.  The deleted nodes are
  * marked and thus the caller should call commit_kbnode afterwards.
 /*
  * Apply the keep-uid filter to the keyblock.  The deleted nodes are
  * marked and thus the caller should call commit_kbnode afterwards.
@@ -1166,6 +1202,49 @@ apply_keep_uid_filter (kbnode_t keyblock, recsel_expr_t selector)
 
 
 /*
 
 
 /*
+ * Apply the drop-sig filter to the keyblock.  The deleted nodes are
+ * marked and thus the caller should call commit_kbnode afterwards.
+ * KEYBLOCK must not have any blocks marked as deleted.
+ */
+static void
+apply_drop_sig_filter (kbnode_t keyblock, recsel_expr_t selector)
+{
+  kbnode_t node;
+  int active = 0;
+  u32 main_keyid[2];
+  PKT_signature *sig;
+
+  keyid_from_pk (keyblock->pkt->pkt.public_key, main_keyid);
+
+  /* Loop over all signatures for user id and attribute packets which
+   * are not self signatures.  */
+  for (node = keyblock->next; node; node = node->next )
+    {
+      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+          || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+        break; /* ready.  */
+      if (node->pkt->pkttype == PKT_USER_ID)
+        active = 1;
+      if (!active)
+        continue;
+      if (node->pkt->pkttype != PKT_SIGNATURE
+          && node->pkt->pkttype != PKT_ATTRIBUTE)
+        continue;
+
+      sig = node->pkt->pkt.signature;
+      if (main_keyid[0] == sig->keyid[0] || main_keyid[1] == sig->keyid[1])
+        continue;  /* Skip self-signatures.  */
+
+      if (IS_UID_SIG(sig) || IS_UID_REV(sig))
+        {
+          if (recsel_select (selector, filter_getval, node))
+            delete_kbnode (node);
+        }
+    }
+}
+
+
+/*
  * Try to import one keyblock. Return an error only in serious cases,
  * but never for an invalid keyblock.  It uses log_error to increase
  * the internal errorcount, so that invalid input can be detected by
  * Try to import one keyblock. Return an error only in serious cases,
  * but never for an invalid keyblock.  It uses log_error to increase
  * the internal errorcount, so that invalid input can be detected by
@@ -1306,6 +1385,11 @@ import_one (ctrl_t ctrl,
       apply_keep_uid_filter (keyblock, import_keep_uid);
       commit_kbnode (&keyblock);
     }
       apply_keep_uid_filter (keyblock, import_keep_uid);
       commit_kbnode (&keyblock);
     }
+  if (import_drop_sig)
+    {
+      apply_drop_sig_filter (keyblock, import_drop_sig);
+      commit_kbnode (&keyblock);
+    }
 
 
   /* Show the key in the form it is merged or inserted.  We skip this
 
 
   /* Show the key in the form it is merged or inserted.  We skip this