From 776876ce1c4c5da3a0fe1dc538fc7a67cf18c054 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 31 Aug 2023 11:13:38 +0200 Subject: [PATCH] gpgsm: Add --always-trust feature. * sm/gpgsm.h (opt): Re-purpose unused flag always_trust. (struct server_control_s): Add "always_trust". (VALIDATE_FLAG_BYPASS): New. * sm/gpgsm.c (oAlwaysTrust): New. (opts): Add "--always-trust" (main): Set option. * sm/server.c (option_handler): Add option "always-trust". (reset_notify): Clear that option. (cmd_encrypt): Ditto. (cmd_getinfo): Add sub-command always-trust. * sm/certchain.c (gpgsm_validate_chain): Handle VALIDATE_FLAG_BYPASS. * sm/certlist.c (gpgsm_add_to_certlist): Set that flag for recipients in always-trust mode. -- GnuPG-bug-id: 6559 --- doc/gpgsm.texi | 20 ++++++++++++++++++++ sm/certchain.c | 14 +++++++++++--- sm/certlist.c | 8 +++++++- sm/gpgsm.c | 13 +++++++++++++ sm/gpgsm.h | 10 ++++++++-- sm/server.c | 21 ++++++++++++++++++++- 6 files changed, 79 insertions(+), 7 deletions(-) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index e976767f6..497b33203 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -732,6 +732,13 @@ instead to make sure that the gpgsm process exits with a failure if the compliance rules are not fulfilled. Note that this option has currently an effect only in "de-vs" mode. +@item --always-trust +@opindex always-trust +Force encryption to the specified certificates without any validation +of the certificate chain. The only requirement is that the +certificate is capable of encryption. Note that this option is +ineffective if @option{--require-compliance} is used. + @item --ignore-cert-with-oid @var{oid} @opindex ignore-cert-with-oid Add @var{oid} to the list of OIDs to be checked while reading @@ -1622,6 +1629,10 @@ The leading two dashes usually used with @var{opt} shall not be given. Return OK if the connection is in offline mode. This may be either due to a @code{OPTION offline=1} or due to @command{gpgsm} being started with option @option{--disable-dirmngr}. +@item always-trust +Returns OK of the connection is in always-trust mode. That is either +@option{--always-trust} or @option{GPGSM OPTION always-trust} are +active. @end table @node GPGSM OPTION @@ -1728,6 +1739,15 @@ If @var{value} is true or @var{value} is not given all network access is disabled for this session. This is the same as the command line option @option{--disable-dirmngr}. +@item always-trust +If @var{value} is true or @var{value} is not given encryption to the +specified certificates is forced without any validation of the +certificate chain. The only requirement is that the certificates are +capable of encryption. If set to false the standard behaviour is +re-established. This option is cleared by a RESET and after each +encrypt operation. Note that this option is ignored if +@option{--always-trust} or @option{--require-compliance} are used. + @item input-size-hint This is the same as the @option{--input-size-hint} command line option. diff --git a/sm/certchain.c b/sm/certchain.c index 84dbed696..9d0fe684b 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -2199,9 +2199,15 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime, memset (&rootca_flags, 0, sizeof rootca_flags); - rc = do_validate_chain (ctrl, cert, checktime, - r_exptime, listmode, listfp, flags, - &rootca_flags); + if ((flags & VALIDATE_FLAG_BYPASS)) + { + *retflags |= VALIDATE_FLAG_BYPASS; + rc = 0; + } + else + rc = do_validate_chain (ctrl, cert, checktime, + r_exptime, listmode, listfp, flags, + &rootca_flags); if (!rc && (flags & VALIDATE_FLAG_STEED)) { *retflags |= VALIDATE_FLAG_STEED; @@ -2223,6 +2229,8 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime, if (opt.verbose) do_list (0, listmode, listfp, _("validation model used: %s"), + (*retflags & VALIDATE_FLAG_BYPASS)? + "bypass" : (*retflags & VALIDATE_FLAG_STEED)? "steed" : (*retflags & VALIDATE_FLAG_CHAIN_MODEL)? diff --git a/sm/certlist.c b/sm/certlist.c index fdf31a198..53d90ac30 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -448,6 +448,11 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, if (!rc && !is_cert_in_certlist (cert, *listaddr)) { + unsigned int valflags = 0; + + if (!secret && (opt.always_trust || ctrl->always_trust)) + valflags |= VALIDATE_FLAG_BYPASS; + if (!rc && secret) { char *p; @@ -461,9 +466,10 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, xfree (p); } } + if (!rc) rc = gpgsm_validate_chain (ctrl, cert, GNUPG_ISOTIME_NONE, NULL, - 0, NULL, 0, NULL); + 0, NULL, valflags, NULL); if (!rc) { certlist_t cl = xtrycalloc (1, sizeof *cl); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index ce977413d..b3d48abce 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -215,6 +215,7 @@ enum cmd_and_opt_values { oRequireCompliance, oCompatibilityFlags, oKbxBufferSize, + oAlwaysTrust, oNoAutostart }; @@ -417,6 +418,7 @@ static gpgrt_opt_t opts[] = { ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"), ARGPARSE_s_n (oNoRandomSeedFile, "no-random-seed-file", "@"), ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"), + ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"), ARGPARSE_header (NULL, N_("Options for unattended use")), @@ -1499,6 +1501,7 @@ main ( int argc, char **argv) case oMinRSALength: opt.min_rsa_length = pargs.r.ret_ulong; break; case oRequireCompliance: opt.require_compliance = 1; break; + case oAlwaysTrust: opt.always_trust = 1; break; case oKbxBufferSize: keybox_set_buffersize (pargs.r.ret_ulong, 0); @@ -1588,10 +1591,20 @@ main ( int argc, char **argv) if (may_coredump && !opt.quiet) log_info (_("WARNING: program may create a core file!\n")); + if (opt.require_compliance && opt.always_trust) + { + opt.always_trust = 0; + if (opt.quiet) + log_info (_("WARNING: %s overrides %s\n"), + "--require-compliance","--always-trust"); + } + + npth_init (); assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH); gpgrt_set_syscall_clamp (npth_unprotect, npth_protect); + /* if (opt.qualsig_approval && !opt.quiet) */ /* log_info (_("This software has officially been approved to " */ /* "create and verify\n" */ diff --git a/sm/gpgsm.h b/sm/gpgsm.h index e1aca8bb7..a22327edc 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -116,8 +116,6 @@ struct int extra_digest_algo; /* A digest algorithm also used for verification of signatures. */ - int always_trust; /* Trust the given keys even if there is no - valid certification chain */ int skip_verify; /* do not check signatures on data */ int lock_once; /* Keep lock once they are set */ @@ -164,6 +162,10 @@ struct * mode. */ int require_compliance; + /* Enable always-trust mode - note that there is also server option + * for this. */ + int always_trust; + /* Enable creation of authenticode signatures. */ int authenticode; @@ -269,6 +271,9 @@ struct server_control_s 2 := STEED model. */ int offline; /* If true gpgsm won't do any network access. */ + int always_trust; /* True in always-trust mode; see also + * opt.always-trust. */ + /* The current time. Used as a helper in certchain.c. */ ksba_isotime_t current_time; @@ -388,6 +393,7 @@ int gpgsm_create_cms_signature (ctrl_t ctrl, #define VALIDATE_FLAG_NO_DIRMNGR 1 #define VALIDATE_FLAG_CHAIN_MODEL 2 #define VALIDATE_FLAG_STEED 4 +#define VALIDATE_FLAG_BYPASS 8 /* No actual validation. */ gpg_error_t gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next); diff --git a/sm/server.c b/sm/server.c index b545c1bfb..184ec9379 100644 --- a/sm/server.c +++ b/sm/server.c @@ -287,6 +287,17 @@ option_handler (assuan_context_t ctx, const char *key, const char *value) ctrl->offline = i; } } + else if (!strcmp (key, "always-trust")) + { + /* We ignore this option if gpgsm has been started with + --always-trust (which also sets offline) and if + --require-compliance is active */ + if (!opt.always_trust && !opt.require_compliance) + { + int i = *value? !!atoi (value) : 1; + ctrl->always_trust = i; + } + } else if (!strcmp (key, "request-origin")) { if (!opt.request_origin) @@ -320,6 +331,7 @@ reset_notify (assuan_context_t ctx, char *line) gpgsm_release_certlist (ctrl->server_local->signerlist); ctrl->server_local->recplist = NULL; ctrl->server_local->signerlist = NULL; + ctrl->always_trust = 0; close_message_fd (ctrl); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); @@ -488,6 +500,7 @@ cmd_encrypt (assuan_context_t ctx, char *line) gpgsm_release_certlist (ctrl->server_local->recplist); ctrl->server_local->recplist = NULL; + ctrl->always_trust = 0; /* Close and reset the fd */ close_message_fd (ctrl); assuan_close_input_fd (ctx); @@ -1189,7 +1202,8 @@ static const char hlp_getinfo[] = " agent-check - Return success if the agent is running.\n" " cmd_has_option CMD OPT\n" " - Returns OK if the command CMD implements the option OPT.\n" - " offline - Returns OK if the connection is in offline mode."; + " offline - Returns OK if the connection is in offline mode." + " always-trust- Returns OK if the connection is in always-trust mode."; static gpg_error_t cmd_getinfo (assuan_context_t ctx, char *line) { @@ -1248,6 +1262,11 @@ cmd_getinfo (assuan_context_t ctx, char *line) { rc = ctrl->offline? 0 : gpg_error (GPG_ERR_FALSE); } + else if (!strcmp (line, "always-trust")) + { + rc = (ctrl->always_trust || opt.always_trust)? 0 + /**/ : gpg_error (GPG_ERR_FALSE); + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");