From 2cce42c23f628383485d04a8c38a13c490b62257 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 11 May 2004 19:11:53 +0000 Subject: [PATCH] * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. (start_connection_thread): Hack to simulate a ticker. * trustlist.c (agent_trustlist_housekeeping) (agent_reload_trustlist): New. Protected all global functions here with a simple counter which is sufficient for Pth. * fingerprint.c (gpgsm_get_key_algo_info): New. * sign.c (gpgsm_sign): Don't assume RSA in the status line. * keylist.c (list_cert_colon): Really print the algorithm and key length. (list_cert_raw, list_cert_std): Ditto. (list_cert_colon): Reorganized to be able to tell whether a root certificate is trusted. --- agent/ChangeLog | 8 ++++ agent/agent.h | 2 + agent/gpg-agent.c | 7 +++ agent/trustlist.c | 111 +++++++++++++++++++++++++++++++++++++--------- sm/ChangeLog | 2 + sm/keylist.c | 65 ++++++++++++++++++--------- 6 files changed, 153 insertions(+), 42 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index cf4ae79bf..ae1dd884e 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,11 @@ +2004-05-11 Werner Koch + + * gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP. + (start_connection_thread): Hack to simulate a ticker. + * trustlist.c (agent_trustlist_housekeeping) + (agent_reload_trustlist): New. Protected all global functions + here with a simple counter which is sufficient for Pth. + 2004-05-03 Werner Koch * gpg-agent.c: Remove help texts for options lile --lc-ctype. diff --git a/agent/agent.h b/agent/agent.h index 99fdc0547..6b7821e30 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -189,6 +189,8 @@ int agent_istrusted (const char *fpr); int agent_listtrusted (void *assuan_context); int agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag); +void agent_trustlist_housekeeping (void); +void agent_reload_trustlist (void); /*-- divert-scd.c --*/ diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ad6ef33ea..8d21dc43c 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1083,6 +1083,7 @@ handle_signal (int signo) "re-reading configuration and flushing cache\n"); agent_flush_cache (); reread_configuration (); + agent_reload_trustlist (); break; case SIGUSR1: @@ -1129,6 +1130,12 @@ start_connection_thread (void *arg) if (opt.verbose) log_info ("handler for fd %d started\n", fd); + + /* FIXME: Move this housekeeping into a ticker function. Calling it + for each connection should work but won't work anymore if our + cleints start to keep connections. */ + agent_trustlist_housekeeping (); + start_command_handler (-1, fd); if (opt.verbose) log_info ("handler for fd %d terminated\n", fd); diff --git a/agent/trustlist.c b/agent/trustlist.c index 19de0708d..16b7dc34e 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -1,5 +1,5 @@ /* trustlist.c - Maintain the list of trusted keys - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -41,10 +41,13 @@ static const char headerblurb[] = "# with optional white spaces, followed by exactly 40 hex character,\n" "# optioanlly followed by a flag character which my either be 'P', 'S'\n" "# or '*'. Additional data delimited with by a white space is ignored.\n" +"# NOTE: You should give the gpg-agent a HUP after editing this file.\n" "\n"; static FILE *trustfp; +static int trustfp_used; /* Counter to track usage of TRUSTFP. */ +static int reload_trustlist_pending; static int @@ -164,7 +167,7 @@ read_list (char *key, int *keyflag) return 0; } -/* check whether the given fpr is in our trustdb. We expect FPR to be +/* Check whether the given fpr is in our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. */ int agent_istrusted (const char *fpr) @@ -173,25 +176,31 @@ agent_istrusted (const char *fpr) static char key[41]; int keyflag; + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) { if (!strcmp (key, fpr)) - return 0; + { + trustfp_used--; + return 0; + } } if (rc != -1) { - /* error in the trustdb - close it to give the user a chance for + /* Error in the trustdb - close it to give the user a chance for correction */ - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; } + trustfp_used--; return rc; } -/* write all trust entries to FP */ +/* Write all trust entries to FP. */ int agent_listtrusted (void *assuan_context) { @@ -199,6 +208,7 @@ agent_listtrusted (void *assuan_context) static char key[51]; int keyflag; + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) @@ -213,11 +223,13 @@ agent_listtrusted (void *assuan_context) rc = 0; if (rc) { - /* error in the trustdb - close it to give the user a chance for + /* Error in the trustdb - close it to give the user a chance for correction */ - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; } + trustfp_used--; return rc; } @@ -252,7 +264,7 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) } xfree (fname); - + trustfp_used++; if (trustfp) rewind (trustfp); while (!(rc=read_list (key, &keyflag))) @@ -260,14 +272,21 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) if (!strcmp (key, fpr)) return 0; } - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; if (rc != -1) - return rc; /* error in the trustdb */ + { + trustfp_used--; + return rc; /* Error in the trustlist. */ + } /* This feature must explicitly been enabled. */ if (!opt.allow_mark_trusted) - return gpg_error (GPG_ERR_NOT_SUPPORTED); + { + trustfp_used--; + return gpg_error (GPG_ERR_NOT_SUPPORTED); + } /* insert a new one */ if (asprintf (&desc, @@ -275,42 +294,62 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) " \"%s\"%%0A" "has the fingerprint:%%0A" " %s", name, fpr) < 0 ) - return out_of_core (); + { + trustfp_used--; + return out_of_core (); + } rc = agent_get_confirmation (ctrl, desc, "Correct", "No"); free (desc); if (rc) - return rc; + { + trustfp_used--; + return rc; + } if (asprintf (&desc, "Do you ultimately trust%%0A" " \"%s\"%%0A" "to correctly certify user certificates?", name) < 0 ) - return out_of_core (); + { + trustfp_used--; + return out_of_core (); + } rc = agent_get_confirmation (ctrl, desc, "Yes", "No"); free (desc); if (rc) - return rc; + { + trustfp_used--; + return rc; + } - /* now check again to avoid duplicates. Also open in append mode now */ + /* Now check again to avoid duplicates. Also open in append mode now. */ rc = open_list (1); if (rc) - return rc; + { + trustfp_used--; + return rc; + } rewind (trustfp); while (!(rc=read_list (key, &keyflag))) { if (!strcmp (key, fpr)) - return 0; + { + trustfp_used--; + return 0; + } } if (rc != -1) { - fclose (trustfp); + if (trustfp) + fclose (trustfp); trustfp = NULL; - return rc; /* error in the trustdb */ + trustfp_used--; + return rc; /* Error in the trustlist. */ } rc = 0; - /* append the key */ + /* Append the key. */ fflush (trustfp); fputs ("\n# ", trustfp); print_sanitized_string (trustfp, name, 0); @@ -322,5 +361,33 @@ agent_marktrusted (CTRL ctrl, const char *name, const char *fpr, int flag) if (fclose (trustfp)) rc = gpg_error (gpg_err_code_from_errno (errno)); trustfp = NULL; + trustfp_used--; return rc; } + + +void +agent_trustlist_housekeeping (void) +{ + if (reload_trustlist_pending && !trustfp_used) + { + if (trustfp) + { + fclose (trustfp); + trustfp = NULL; + } + reload_trustlist_pending = 0; + } +} + + +/* Not all editors are editing files in place, thus a changes + trustlist.txt won't be recognozed if we keep the file descriptor + open. This function may be used to explicitly close that file + descriptor, which will force a reopen in turn. */ +void +agent_reload_trustlist (void) +{ + reload_trustlist_pending = 1; + agent_trustlist_housekeeping (); +} diff --git a/sm/ChangeLog b/sm/ChangeLog index a1997e27e..eed350b24 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -9,6 +9,8 @@ * keylist.c (list_cert_colon): Really print the algorithm and key length. (list_cert_raw, list_cert_std): Ditto. + (list_cert_colon): Reorganized to be able to tell whether a root + certificate is trusted. * gpgsm.c: New option --debug-allow-core-dump. diff --git a/sm/keylist.c b/sm/keylist.c index e9056b6da..27c67ded3 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -289,6 +289,7 @@ static void list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, FILE *fp, int have_secret) { + int rc; int idx; char truststring[2]; char *p; @@ -298,12 +299,39 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, gpg_error_t valerr; int algo; unsigned int nbits; + const char *chain_id; + char *chain_id_buffer = NULL; + int is_root = 0; if (ctrl->with_validation) valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0); else valerr = 0; + + /* We need to get the fingerprint and the chaining ID in advance. */ + fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + { + ksba_cert_t next; + + rc = gpgsm_walk_cert_chain (cert, &next); + if (!rc) /* We known the issuer's certificate. */ + { + p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); + chain_id_buffer = p; + chain_id = chain_id_buffer; + ksba_cert_release (next); + } + else if (rc == -1) /* We have reached the root certificate. */ + { + chain_id = fpr; + is_root = 1; + } + else + chain_id = NULL; + } + + fputs (have_secret? "crs:":"crt:", fp); truststring[0] = 0; truststring[1] = 0; @@ -327,11 +355,23 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, && *not_after && strcmp (current_time, not_after) > 0 ) *truststring = 'e'; } + + /* Is we have no truststring yet (i.e. the certificate might be + good) and this is a root certificate, we ask the agent whether + this is a trusted root certificate. */ + if (!*truststring && is_root) + { + rc = gpgsm_agent_istrusted (ctrl, cert); + if (!rc) + *truststring = 'u'; /* Yes, we trust this one (ultimately). */ + else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED) + *truststring = 'n'; /* No, we do not trust this one. */ + /* (in case of an error we can't tell anything.) */ + } if (*truststring) fputs (truststring, fp); - fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); algo = gpgsm_get_key_algo_info (cert, &nbits); fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24); @@ -379,27 +419,12 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity, /* FPR record */ fprintf (fp, "fpr:::::::::%s:::", fpr); /* Print chaining ID (field 13)*/ - { - ksba_cert_t next; - int rc; - - rc = gpgsm_walk_cert_chain (cert, &next); - if (!rc) /* We known the issuer's certificate. */ - { - p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1); - fputs (p, fp); - xfree (p); - ksba_cert_release (next); - } - else if (rc == -1) /* We reached the root certificate. */ - { - fputs (fpr, fp); - } - } + if (chain_id) + fputs (chain_id, fp); putc (':', fp); putc ('\n', fp); - xfree (fpr); fpr = NULL; - + xfree (fpr); fpr = NULL; chain_id = NULL; + xfree (chain_id_buffer); chain_id_buffer = NULL; if (opt.with_key_data) {