diff --git a/agent/ChangeLog b/agent/ChangeLog index b544ee5db..ac4eb1db6 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,13 @@ +2002-07-26 Werner Koch + + * gpg-agent.c (main): New option --ignore-cache-for-signing. + * command.c (option_handler): New server option + use-cache-for-signing defaulting to true. + (cmd_pksign): handle global and per session option. + * findkey.c (agent_key_from_file, unprotect): New arg + ignore_cache. Changed all callers. + * pksign.c (agent_pksign): Likewise. + 2002-06-29 Werner Koch * query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY. @@ -25,7 +35,7 @@ (import_p12_file): Store the new file if requested. (main): New options --force and --store. - * gpg-agent.c (main): Set a global flag when runing detached. + * gpg-agent.c (main): Set a global flag when running detached. * query.c (start_pinentry): Pass the list of FD to keep in the child when not running detached. * call-scd.c (start_scd): Ditto. diff --git a/agent/agent.h b/agent/agent.h index ba6934366..41654a46f 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -47,6 +47,8 @@ struct { int running_detached; /* we are running detached from the tty. */ + int ignore_cache_for_signing; + } opt; @@ -115,7 +117,7 @@ void start_command_handler (int, int); int agent_write_private_key (const unsigned char *grip, const void *buffer, size_t length, int force); GCRY_SEXP agent_key_from_file (const unsigned char *grip, - unsigned char **shadow_info); + unsigned char **shadow_info, int ignore_cache); int agent_key_available (const unsigned char *grip); /*-- query.c --*/ @@ -133,7 +135,7 @@ void agent_unlock_cache_entry (void **cache_id); /*-- pksign.c --*/ -int agent_pksign (CTRL ctrl, FILE *outfp); +int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache); /*-- pkdecrypt.c --*/ int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, diff --git a/agent/command.c b/agent/command.c index b98ec25ff..55ee8b84a 100644 --- a/agent/command.c +++ b/agent/command.c @@ -48,6 +48,7 @@ struct server_local_s { ASSUAN_CONTEXT assuan_ctx; int message_fd; + int use_cache_for_signing; }; @@ -286,9 +287,15 @@ static int cmd_pksign (ASSUAN_CONTEXT ctx, char *line) { int rc; + int ignore_cache = 0; CTRL ctrl = assuan_get_pointer (ctx); - rc = agent_pksign (ctrl, assuan_get_data_fp (ctx)); + if (opt.ignore_cache_for_signing) + ignore_cache = 1; + else if (!ctrl->server_local->use_cache_for_signing) + ignore_cache = 1; + + rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache); if (rc) log_error ("command pksign failed: %s\n", gnupg_strerror (rc)); return map_to_assuan_status (rc); @@ -516,7 +523,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) { -/* CTRL ctrl = assuan_get_pointer (ctx); */ + CTRL ctrl = assuan_get_pointer (ctx); /* FIXME: We should not change opt. here. It is not a problem right now but as soon as we are allowing concurrent connections we mess @@ -561,6 +568,8 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) if (!opt.lc_messages) return ASSUAN_Out_Of_Core; } + else if (!strcmp (key, "use-cache-for-signing")) + ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0; else return ASSUAN_Invalid_Option; @@ -656,6 +665,7 @@ start_command_handler (int listen_fd, int fd) ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local); ctrl.server_local->assuan_ctx = ctx; ctrl.server_local->message_fd = -1; + ctrl.server_local->use_cache_for_signing = 1; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); diff --git a/agent/findkey.c b/agent/findkey.c index fb3b36e4c..2201f0ae5 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -114,7 +114,7 @@ try_unprotect_cb (struct pin_entry_info_s *pi) should be the hex encoded keygrip of that key to be used with the cahing mechanism. */ static int -unprotect (unsigned char **keybuf, const unsigned char *grip) +unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache) { struct pin_entry_info_s *pi; struct try_unprotect_arg_s arg; @@ -129,22 +129,23 @@ unprotect (unsigned char **keybuf, const unsigned char *grip) /* first try to get it from the cache - if there is none or we can't unprotect it, we fall back to ask the user */ - { - void *cache_marker; - const char *pw = agent_get_cache (hexgrip, &cache_marker); - if (pw) - { - rc = agent_unprotect (*keybuf, pw, &result, &resultlen); - agent_unlock_cache_entry (&cache_marker); - if (!rc) - { - xfree (*keybuf); - *keybuf = result; - return 0; - } - rc = 0; - } - } + if (!ignore_cache) + { + void *cache_marker; + const char *pw = agent_get_cache (hexgrip, &cache_marker); + if (pw) + { + rc = agent_unprotect (*keybuf, pw, &result, &resultlen); + agent_unlock_cache_entry (&cache_marker); + if (!rc) + { + xfree (*keybuf); + *keybuf = result; + return 0; + } + rc = 0; + } + } pi = gcry_calloc_secure (1, sizeof (*pi) + 100); pi->max_length = 100; @@ -173,10 +174,12 @@ unprotect (unsigned char **keybuf, const unsigned char *grip) /* Return the secret key as an S-Exp after locating it using the grip. Returns NULL if key is not available or the operation should be diverted to a token. In the latter case shadow_info will point to - an allocated S-Expression with the shadow_info part from the - file. */ + an allocated S-Expression with the shadow_info part from the file. + With IGNORE_CACHE passed as true the passphrase is not taken from + the cache.*/ GCRY_SEXP -agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info) +agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info, + int ignore_cache) { int i, rc; char *fname; @@ -249,7 +252,7 @@ agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info) case PRIVATE_KEY_CLEAR: break; /* no unprotection needed */ case PRIVATE_KEY_PROTECTED: - rc = unprotect (&buf, grip); + rc = unprotect (&buf, grip, ignore_cache); if (rc) log_error ("failed to unprotect the secret key: %s\n", gnupg_strerror (rc)); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 4441cf557..46de48efa 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -81,6 +81,8 @@ enum cmd_and_opt_values oDefCacheTTL, oDisablePth, + oIgnoreCacheForSigning, + aTest }; @@ -113,6 +115,8 @@ static ARGPARSE_OPTS opts[] = { { oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" }, { oDefCacheTTL, "default-cache-ttl", 4, "|N|expire cached PINs after N seconds"}, + { oIgnoreCacheForSigning, "ignore-cache-for-signing", 0, + "do not use the PIN cache when signing"}, {0} }; @@ -407,6 +411,8 @@ main (int argc, char **argv ) case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break; case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break; + case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; + default : pargs.err = configfp? 1:2; break; } } diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 9a32e76d7..6add3d467 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -64,7 +64,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, log_printhex ("keygrip:", ctrl->keygrip, 20); log_printhex ("cipher: ", ciphertext, ciphertextlen); } - s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info); + s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0); if (!s_skey && !shadow_info) { log_error ("failed to read the secret key\n"); diff --git a/agent/pksign.c b/agent/pksign.c index 7873ce8c4..2acc63dd9 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -86,7 +86,7 @@ do_encode_md (const unsigned char *digest, size_t digestlen, int algo, /* SIGN whatever information we have accumulated in CTRL and write it back to OUTFP. */ int -agent_pksign (CTRL ctrl, FILE *outfp) +agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache) { GCRY_SEXP s_skey = NULL, s_hash = NULL, s_sig = NULL; GCRY_MPI frame = NULL; @@ -98,7 +98,7 @@ agent_pksign (CTRL ctrl, FILE *outfp) if (!ctrl->have_keygrip) return seterr (No_Secret_Key); - s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info); + s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache); if (!s_skey && !shadow_info) { log_error ("failed to read the secret key\n");