From 4fa82eec43e8d205fa336113f6ea554923fd6986 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 1 Oct 2024 18:07:32 +0200 Subject: [PATCH] agent: Add option --status to the LISTRUSTED command. * agent/trustlist.c (istrusted_internal): Add arg listmode and print new status line in this mode. Adjust callers. (agent_listtrusted): Add new args ctrl and status_mode. Get all trusted keys and then call is_trusted_internal for all of them. * agent/command.c (cmd_listtrusted): Add new option --status. -- This allows in a non-restricted connection to list all trusted keys in one go. (cherry picked from commit 4275d5fa7a51731544d243ba16628a9958ffe3ce) --- agent/agent.h | 3 ++- agent/command.c | 14 ++++++----- agent/trustlist.c | 59 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/agent/agent.h b/agent/agent.h index d32b89215..9a92bb83f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -556,7 +556,8 @@ gpg_error_t agent_write_shadow_key (const unsigned char *grip, /*-- trustlist.c --*/ void initialize_module_trustlist (void); gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled); -gpg_error_t agent_listtrusted (void *assuan_context); +gpg_error_t agent_listtrusted (ctrl_t ctrl, void *assuan_context, + int status_mode); gpg_error_t agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag); void agent_reload_trustlist (void); diff --git a/agent/command.c b/agent/command.c index 1be033824..ad693969b 100644 --- a/agent/command.c +++ b/agent/command.c @@ -492,22 +492,24 @@ cmd_istrusted (assuan_context_t ctx, char *line) static const char hlp_listtrusted[] = - "LISTTRUSTED\n" + "LISTTRUSTED [--status]\n" "\n" - "List all entries from the trustlist."; + "List all entries from the trustlist. With --status the\n" + "keys are listed using status line similar to ISTRUSTED"; static gpg_error_t cmd_listtrusted (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); - int rc; + gpg_error_t err; + int opt_status; - (void)line; + opt_status = has_option (line, "--status"); if (ctrl->restricted) return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); - rc = agent_listtrusted (ctx); - return leave_cmd (ctx, rc); + err = agent_listtrusted (ctrl, ctx, opt_status); + return leave_cmd (ctx, err); } diff --git a/agent/trustlist.c b/agent/trustlist.c index 3467dc8fb..4f4ef65d2 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -431,10 +431,13 @@ read_trustfiles (void) /* Check whether the given fpr is in our trustdb. We expect FPR to be - an all uppercase hexstring of 40 characters. If ALREADY_LOCKED is - true the function assumes that the trusttable is already locked. */ + * an all uppercase hexstring of 40 characters. If ALREADY_LOCKED is + * true the function assumes that the trusttable is already locked. + * If LISTMODE is set, a status line TRUSTLISTFPR is emitted first and + * disabled keys are not listed. + */ static gpg_error_t -istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled, +istrusted_internal (ctrl_t ctrl, const char *fpr, int listmode, int *r_disabled, int already_locked) { gpg_error_t err = 0; @@ -473,6 +476,8 @@ istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled, for (ti=trusttable, len = trusttablesize; len; ti++, len--) if (!memcmp (ti->fpr, fprbin, 20)) { + if (listmode && ti->flags.disabled) + continue; if (ti->flags.disabled && r_disabled) *r_disabled = 1; @@ -486,7 +491,13 @@ istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled, unlock_trusttable (); locked = 0; err = 0; - if (ti->flags.relax) + if (listmode) + { + char hexfpr[2*20+1]; + bin2hex (ti->fpr, 20, hexfpr); + err = agent_write_status (ctrl,"TRUSTLISTFPR", hexfpr,NULL); + } + if (!err && ti->flags.relax) err = agent_write_status (ctrl,"TRUSTLISTFLAG", "relax",NULL); if (!err && ti->flags.cm) err = agent_write_status (ctrl,"TRUSTLISTFLAG", "cm", NULL); @@ -515,20 +526,24 @@ istrusted_internal (ctrl_t ctrl, const char *fpr, int *r_disabled, gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled) { - return istrusted_internal (ctrl, fpr, r_disabled, 0); + return istrusted_internal (ctrl, fpr, 0, r_disabled, 0); } /* Write all trust entries to FP. */ gpg_error_t -agent_listtrusted (void *assuan_context) +agent_listtrusted (ctrl_t ctrl, void *assuan_context, int status_mode) { trustitem_t *ti; char key[51]; + int table_locked; gpg_error_t err; size_t len; + strlist_t allhexgrips = NULL; + strlist_t sl; lock_trusttable (); + table_locked = 1; if (!trusttable) { err = read_trustfiles (); @@ -540,6 +555,7 @@ agent_listtrusted (void *assuan_context) } } + err = 0; if (trusttable) { for (ti=trusttable, len = trusttablesize; len; ti++, len--) @@ -547,6 +563,15 @@ agent_listtrusted (void *assuan_context) if (ti->flags.disabled) continue; bin2hex (ti->fpr, 20, key); + if (status_mode) + { + if (!add_to_strlist_try (&allhexgrips, key)) + { + err = gpg_error_from_syserror (); + goto leave; + } + continue; + } key[40] = ' '; key[41] = ((ti->flags.for_smime && ti->flags.for_pgp)? '*' : ti->flags.for_smime? 'S': ti->flags.for_pgp? 'P':' '); @@ -556,8 +581,24 @@ agent_listtrusted (void *assuan_context) } } - unlock_trusttable (); - return 0; + if (status_mode) + { + unlock_trusttable (); + table_locked = 0; + + /* The back and forth converting of the fingerprint and all the + * locking and unlocking is somewhat clumsy but helps to re-use + * existing code. */ + for (sl = allhexgrips; sl; sl = sl->next) + if ((err = istrusted_internal (ctrl, sl->d, 1, NULL, 0))) + goto leave; + } + + leave: + if (table_locked) + unlock_trusttable (); + free_strlist (allhexgrips); + return err; } @@ -771,7 +812,7 @@ agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag) sure that nobody else plays with our file and force a reread. */ lock_trusttable (); clear_trusttable (); - if (!istrusted_internal (ctrl, fpr, &is_disabled, 1) || is_disabled) + if (!istrusted_internal (ctrl, fpr, 0, &is_disabled, 1) || is_disabled) { unlock_trusttable (); xfree (fprformatted);