diff --git a/sm/ChangeLog b/sm/ChangeLog index 47ccc671f..32fe1d95d 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,14 @@ +2002-01-29 Werner Koch + + * call-agent.c (gpgsm_agent_havekey): New. + * keylist.c (list_cert_colon): New arg HAVE_SECRET, print "crs" + when we know that the secret key is available. + (gpgsm_list_keys): New arg MODE, check whether a secret key is + available. Changed all callers. + * gpgsm.c (main): New command --list-secret-keys. + * server.c (cmd_listsecretkeys): New. + (cmd_listkeys): Return secret keys with "crs" record. + 2002-01-28 Werner Koch * certreqgen.c (create_request): Store the email address in the req. diff --git a/sm/call-agent.c b/sm/call-agent.c index 8efa539ea..ec294f6d6 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -456,3 +456,26 @@ gpgsm_agent_istrusted (KsbaCert cert) rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL); return map_assuan_err (rc); } + + +/* Ask the agent whether the a corresponding secret key is available + for the given keygrip */ +int +gpgsm_agent_havekey (const char *hexkeygrip) +{ + int rc; + char line[ASSUAN_LINELENGTH]; + + rc = start_agent (); + if (rc) + return rc; + + if (!hexkeygrip || strlen (hexkeygrip) != 40) + return GNUPG_Invalid_Value; + + snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip); + line[DIM(line)-1] = 0; + + rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL); + return map_assuan_err (rc); +} diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 0203c5a2a..22fed31bd 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -207,6 +207,7 @@ static ARGPARSE_OPTS opts[] = { { aVerifyFiles, "verify-files" , 256, "@" }, { aListKeys, "list-keys", 256, N_("list keys")}, { aListKeys, "list-public-keys", 256, "@" }, + { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")}, { aDummy, "list-sigs", 256, "@"}, { aDummy, "check-sigs",256, "@"}, { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")}, @@ -699,6 +700,7 @@ main ( int argc, char **argv) case aRecvKeys: set_cmd (&cmd, aRecvKeys); break; case aExport: set_cmd (&cmd, aExport); break; case aListKeys: set_cmd (&cmd, aListKeys); break; + case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break; case aDeleteKey: set_cmd (&cmd, aDeleteKey); @@ -1108,15 +1110,14 @@ main ( int argc, char **argv) case aListKeys: for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); - gpgsm_list_keys (&ctrl, sl, stdout); + gpgsm_list_keys (&ctrl, sl, stdout, 0); free_strlist(sl); break; case aListSecretKeys: - sl = NULL; - for( ; argc; argc--, argv++ ) + for (sl=NULL; argc; argc--, argv++) add_to_strlist (&sl, *argv); -/* secret_key_list ( sl ); */ + gpgsm_list_keys (&ctrl, sl, stdout, 2); free_strlist(sl); break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index f8f5ed8b6..fdb68441e 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -176,7 +176,7 @@ void gpgsm_release_certlist (CERTLIST list); int gpgsm_find_cert (const char *name, KsbaCert *r_cert); /*-- keylist.c --*/ -void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp); +void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode); /*-- import.c --*/ int gpgsm_import (CTRL ctrl, int in_fd); @@ -207,6 +207,7 @@ int gpgsm_agent_pkdecrypt (const char *keygrip, char **r_buf, size_t *r_buflen); int gpgsm_agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey); int gpgsm_agent_istrusted (KsbaCert cert); +int gpgsm_agent_havekey (const char *hexkeygrip); /*-- call-dirmngr.c --*/ int gpgsm_dirmngr_isvalid (KsbaCert cert); diff --git a/sm/keylist.c b/sm/keylist.c index f4c90939f..0050ac464 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -113,13 +113,13 @@ email_kludge (const char *name) /* List one certificate in colon mode */ static void -list_cert_colon (KsbaCert cert, FILE *fp) +list_cert_colon (KsbaCert cert, FILE *fp, int have_secret) { int idx, trustletter = 0; char *p; KsbaSexp sexp; - fputs ("crt:", fp); + fputs (have_secret? "crs:":"crt:", fp); trustletter = 0; #if 0 if (is_not_valid (cert)) @@ -216,14 +216,21 @@ list_cert_colon (KsbaCert cert, FILE *fp) -/* List all keys or just the key given as NAMES */ +/* List all keys or just the key given as NAMES. + MODE controls the operation mode: + 0 = list all public keys but don't flag secret ones + 1 = list only public keys + 2 = list only secret keys + 3 = list secret and public keys + */ void -gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp) +gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) { KEYDB_HANDLE hd; KsbaCert cert = NULL; int rc=0; const char *lastresname, *resname; + int have_secret; hd = keydb_new (0); if (!hd) @@ -262,10 +269,28 @@ gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp) lastresname = resname; } } - if (ctrl->with_colons) - list_cert_colon (cert, fp); - else - list_cert_colon (cert, fp); + + have_secret = 0; + if (mode) + { + char *p = gpgsm_get_keygrip_hexstring (cert); + if (p) + { + if (!gpgsm_agent_havekey (p)) + have_secret = 1; + xfree (p); + } + } + + if (!mode + || ((mode & 1) && !have_secret) + || ((mode & 2) && have_secret) ) + { + if (ctrl->with_colons) + list_cert_colon (cert, fp, have_secret); + else + list_cert_colon (cert, fp, have_secret); + } ksba_cert_release (cert); cert = NULL; } diff --git a/sm/server.c b/sm/server.c index 616ae9bfe..298ccda2d 100644 --- a/sm/server.c +++ b/sm/server.c @@ -378,7 +378,20 @@ cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) ctrl->with_colons = 1; /* fixme: check that the returned data_fp is not NULL */ gpgsm_list_keys (assuan_get_pointer (ctx), NULL, - assuan_get_data_fp (ctx)); + assuan_get_data_fp (ctx), 3); + + return 0; +} + +static int +cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + + ctrl->with_colons = 1; + /* fixme: check that the returned data_fp is not NULL */ + gpgsm_list_keys (assuan_get_pointer (ctx), NULL, + assuan_get_data_fp (ctx), 2); return 0; } @@ -442,6 +455,7 @@ register_commands (ASSUAN_CONTEXT ctx) { "", ASSUAN_CMD_OUTPUT, NULL }, { "MESSAGE", 0, cmd_message }, { "LISTKEYS", 0, cmd_listkeys }, + { "LISTSECRETKEYS", 0, cmd_listsecretkeys }, { "GENKEY", 0, cmd_genkey }, { NULL } };