From c30d5829c9ab076e9fd39c223273b065cdb58a0d Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Tue, 9 May 2023 08:17:30 +0200
Subject: [PATCH] gpg: New option --debug-ignore-expiration to help with
 testing.

* g10/gpg.c (oDebugIgnoreExpiration): New.
(opts): Add option.
(main): Set flag.
* g10/options.h (opt): Add field ignore_expiration.
* g10/pkclist.c (do_we_trust): Handle the option.
* g10/getkey.c (skip_unusable): Ditto.
(finish_lookup): Ditto.
--

GnuPG-bug-id: 2703
---
 doc/gpg.texi  | 13 +++++++++----
 g10/getkey.c  |  7 ++++---
 g10/gpg.c     |  8 +++++++-
 g10/options.h |  1 +
 g10/pkclist.c |  6 +++++-
 5 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 9fdabc743..6b584a913 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -3185,12 +3185,17 @@ and may thus be changed or removed at any time without notice.
 To facilitate software tests and experiments this option allows to
 specify a limit of up to 4 EiB (@code{--chunk-size 62}).
 
+@item --debug-ignore-expiration
+@opindex debug-ignore-expiration
+This option tries to override certain key expiration dates.  It is
+only useful for certain regression tests.
+
 @item --faked-system-time @var{epoch}
 @opindex faked-system-time
-This option is only useful for testing; it sets the system time back or
-forth to @var{epoch} which is the number of seconds elapsed since the year
-1970.  Alternatively @var{epoch} may be given as a full ISO time string
-(e.g. "20070924T154812").
+This option is only useful for testing; it sets the system time back
+or forth to @var{epoch} which is the number of seconds elapsed since
+the year 1970.  Alternatively @var{epoch} may be given as a full ISO
+time string (e.g. "20070924T154812").
 
 If you suffix @var{epoch} with an exclamation mark (!), the system time
 will appear to be frozen at the specified time.
diff --git a/g10/getkey.c b/g10/getkey.c
index 1b37c597d..15905dc63 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -685,7 +685,7 @@ skip_unusable (void *opaque, u32 * keyid, int uid_no)
   pk = keyblock->pkt->pkt.public_key;
 
   /* Is the key revoked or expired?  */
-  if (pk->flags.revoked || pk->has_expired)
+  if (pk->flags.revoked || (pk->has_expired && !opt.ignore_expiration))
     unusable = 1;
 
   /* Is the user ID in question revoked or expired? */
@@ -704,7 +704,8 @@ skip_unusable (void *opaque, u32 * keyid, int uid_no)
 	      if (uids_seen != uid_no)
 		continue;
 
-	      if (user_id->flags.revoked || user_id->flags.expired)
+	      if (user_id->flags.revoked
+                  || (user_id->flags.expired && !opt.ignore_expiration))
 		unusable = 1;
 
 	      break;
@@ -3736,7 +3737,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
               n_revoked_or_expired++;
 	      continue;
 	    }
-	  if (pk->has_expired)
+	  if (pk->has_expired && !opt.ignore_expiration)
 	    {
 	      if (DBG_LOOKUP)
 		log_debug ("\tsubkey has expired\n");
diff --git a/g10/gpg.c b/g10/gpg.c
index 737753a40..6e54aa763 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -234,6 +234,7 @@ enum cmd_and_opt_values
     oDebugIOLBF,
     oDebugSetIobufSize,
     oDebugAllowLargeChunks,
+    oDebugIgnoreExpiration,
     oStatusFD,
     oStatusFile,
     oAttributeFD,
@@ -607,7 +608,6 @@ static gpgrt_opt_t opts[] = {
                 N_("|FILE|write server mode logs to FILE")),
   ARGPARSE_s_s (oLoggerFile, "logger-file", "@"),  /* 1.4 compatibility.  */
   ARGPARSE_s_n (oLogTime, "log-time", "@"),
-  ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
 
 
   ARGPARSE_header ("Configuration",
@@ -929,6 +929,8 @@ static gpgrt_opt_t opts[] = {
   ARGPARSE_s_n (oRFC2440Text,      "rfc2440-text", "@"),
   ARGPARSE_s_n (oNoRFC2440Text, "no-rfc2440-text", "@"),
   ARGPARSE_p_u (oKbxBufferSize,  "kbx-buffer-size", "@"),
+  ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
+  ARGPARSE_s_n (oDebugIgnoreExpiration,  "debug-ignore-expiration", "@"),
 
   ARGPARSE_header (NULL, ""),  /* Stop the header group.  */
 
@@ -2851,6 +2853,10 @@ main (int argc, char **argv)
             allow_large_chunks = 1;
             break;
 
+          case oDebugIgnoreExpiration:
+            opt.ignore_expiration = 1;
+            break;
+
           case oCompatibilityFlags:
             if (parse_compatibility_flags (pargs.r.ret_str, &opt.compat_flags,
                                            compatibility_flags))
diff --git a/g10/options.h b/g10/options.h
index 9015e321f..914c24849 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -208,6 +208,7 @@ struct
   int ignore_valid_from;
   int ignore_crc_error;
   int ignore_mdc_error;
+  int ignore_expiration;
   int command_fd;
   const char *override_session_key;
   int show_session_key;
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 2e8932b9c..42e124e9e 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -417,7 +417,11 @@ do_we_trust( PKT_public_key *pk, unsigned int trustlevel )
   if(trustlevel & TRUST_FLAG_REVOKED
      || trustlevel & TRUST_FLAG_SUB_REVOKED
      || (trustlevel & TRUST_MASK) == TRUST_EXPIRED)
-    BUG();
+    {
+      if (opt.ignore_expiration)
+        return 0;
+      BUG ();
+    }
 
   if( opt.trust_model==TM_ALWAYS )
     {