diff --git a/sm/ChangeLog b/sm/ChangeLog index 756cb45f8..5b97cf13c 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,10 @@ 2002-03-06 Werner Koch + * server.c (cmd_listkeys, cmd_listsecretkeys): Divert to + (do_listkeys): new. Add pattern parsing. + + * keylist.c (gpgsm_list_keys): Handle selection pattern. + * gpgsm.c: New command --learn-card * call-agent.c (learn_cb,gpgsm_agent_learn): New. diff --git a/sm/keylist.c b/sm/keylist.c index 0c8416810..6c57897de 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -227,28 +227,68 @@ void gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) { KEYDB_HANDLE hd; + KEYDB_SEARCH_DESC *desc = NULL; + STRLIST sl; + int ndesc; KsbaCert cert = NULL; int rc=0; const char *lastresname, *resname; int have_secret; -#warning there is no key selection yet - /* We must take care of quoting here */ hd = keydb_new (0); if (!hd) - rc = GNUPG_General_Error; - else - rc = keydb_search_first (hd); - if (rc) { - if (rc != -1) - log_error ("keydb_search_first failed: %s\n", gnupg_strerror (rc) ); + log_error ("keydb_new failed\n"); goto leave; } - lastresname = NULL; - do + if (!names) + ndesc = 1; + else { + for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) + ; + } + + desc = xtrycalloc (ndesc, sizeof *desc); + if (!ndesc) + { + log_error ("out of core\n"); + goto leave; + } + + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + else + { + for (ndesc=0, sl=names; sl; sl = sl->next) + { + rc = keydb_classify_name (sl->d, desc+ndesc); + if (rc) + { + log_error ("key `%s' not found: %s\n", + sl->d, gnupg_strerror (rc)); + rc = 0; + } + else + ndesc++; + } + + } + + /* it would be nice to see which of the given users did actually + match one in the keyring. To implement this we need to have a + found flag for each entry in desc and to set this we must check + all those entries after a match to mark all matched one - + currently we stop at the first match. To do this we need an + extra flag to enable this feature so */ + + lastresname = NULL; + while (!(rc = keydb_search (hd, desc, ndesc))) + { + if (!names) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + rc = keydb_get_cert (hd, &cert); if (rc) { @@ -296,12 +336,14 @@ gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode) ksba_cert_release (cert); cert = NULL; } - while (!(rc = keydb_search_next (hd))); if (rc && rc != -1) - log_error ("keydb_search_next failed: %s\n", gnupg_strerror (rc)); + log_error ("keydb_search failed: %s\n", gnupg_strerror (rc)); leave: ksba_cert_release (cert); + xfree (desc); keydb_release (hd); } + + diff --git a/sm/server.c b/sm/server.c index 065fc5acc..856eb56be 100644 --- a/sm/server.c +++ b/sm/server.c @@ -42,6 +42,32 @@ struct server_local_s { CERTLIST recplist; }; + + +/* note, that it is sufficient to allocate the target string D as + long as the source string S, i.e.: strlen(s)+1; */ +static void +strcpy_escaped_plus (char *d, const unsigned char *s) +{ + while (*s) + { + if (*s == '%' && s[1] && s[2]) + { + s++; + *d++ = xtoi_2 ( s); + s += 2; + } + else if (*s == '+') + *d++ = ' ', s++; + else + *d++ = *s++; + } + *d = 0; +} + + + + /* Check whether the option NAME appears in LINE */ static int has_option (const char *line, const char *name) @@ -370,35 +396,56 @@ cmd_message (ASSUAN_CONTEXT ctx, char *line) } -/* Note that the line contains a space separated list of pappern where - each pappern is percent escaped and spaces may be replaced by - '+'. */ static int -cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) +do_listkeys (ASSUAN_CONTEXT ctx, char *line, int mode) { CTRL ctrl = assuan_get_pointer (ctx); FILE *fp = assuan_get_data_fp (ctx); + char *p; + STRLIST list, sl; if (!fp) return set_error (General_Error, "no data stream"); - ctrl->with_colons = 1; - gpgsm_list_keys (assuan_get_pointer (ctx), NULL, fp, 3); + + /* break the line down into an STRLIST */ + list = NULL; + for (p=line; *p; line = p) + { + while (*p && *p != ' ') + p++; + if (*p) + *p++ = 0; + if (*line) + { + sl = xtrymalloc (sizeof *sl + strlen (line)); + if (!sl) + { + free_strlist (list); + return ASSUAN_Out_Of_Core; + } + sl->flags = 0; + strcpy_escaped_plus (sl->d, line); + sl->next = list; + list = sl; + } + } + ctrl->with_colons = 1; + gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, 3); + free_strlist (list); return 0; } +static int +cmd_listkeys (ASSUAN_CONTEXT ctx, char *line) +{ + return do_listkeys (ctx, line, 3); +} + static int cmd_listsecretkeys (ASSUAN_CONTEXT ctx, char *line) { - CTRL ctrl = assuan_get_pointer (ctx); - FILE *fp = assuan_get_data_fp (ctx); - - ctrl->with_colons = 1; - if (!fp) - return set_error (General_Error, "no data stream"); - gpgsm_list_keys (assuan_get_pointer (ctx), NULL, fp, 2); - - return 0; + return do_listkeys (ctx, line, 2); }