diff options
author | Werner Koch <[email protected]> | 2021-07-08 11:55:18 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2021-07-08 11:57:13 +0000 |
commit | 101ba4f18aceb39c4d5f0e0a7e16e66827f8e612 (patch) | |
tree | 7cdc6b3f168b8f62e6e7dcf3fbab3ec165b33f7c | |
parent | scd: Detect external interference when PCSC_SHARED. (diff) | |
download | gnupg-101ba4f18aceb39c4d5f0e0a7e16e66827f8e612.tar.gz gnupg-101ba4f18aceb39c4d5f0e0a7e16e66827f8e612.zip |
kbx: Fix keyboxd searching with multiple patterns.
* kbx/keybox-search-desc.h (struct keydb_search_desc): New flag
name_used.
* common/userids.c (classify_user_id): Set flag.
* kbx/kbxserver.c (struct search_backing_store_s): New.
(cmd_search): use a backing store for the const pointers.
(kbxd_start_command_handler): Release the backing store.
--
Well, the search object partly uses buffers but also const
pointers (for strings and the serial number). This when assigning
such objects to an another one we should really take a deep copy and
not just copy the pointer. The more clean solution would have been to
provide a storage option the search object but that needs checking the
code at too many places so that I decided to use a separate backing
store array here.
Signed-off-by: Werner Koch <[email protected]>
-rw-r--r-- | common/userids.c | 10 | ||||
-rw-r--r-- | kbx/kbxserver.c | 94 | ||||
-rw-r--r-- | kbx/keybox-search-desc.h | 1 |
3 files changed, 95 insertions, 10 deletions
diff --git a/common/userids.c b/common/userids.c index 0f03896ee..9d866d583 100644 --- a/common/userids.c +++ b/common/userids.c @@ -115,6 +115,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) mode = KEYDB_SEARCH_MODE_MAILEND; s++; desc->u.name = s; + desc->name_used = 1; break; case '<': /* An email address. */ @@ -126,24 +127,28 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) if (!openpgp_hack) s++; desc->u.name = s; + desc->name_used = 1; break; case '@': /* Part of an email address. */ mode = KEYDB_SEARCH_MODE_MAILSUB; s++; desc->u.name = s; + desc->name_used = 1; break; case '=': /* Exact compare. */ mode = KEYDB_SEARCH_MODE_EXACT; s++; desc->u.name = s; + desc->name_used = 1; break; case '*': /* Case insensitive substring search. */ mode = KEYDB_SEARCH_MODE_SUBSTR; s++; desc->u.name = s; + desc->name_used = 1; break; case '+': /* Compare individual words. Note that this has not @@ -151,6 +156,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) mode = KEYDB_SEARCH_MODE_WORDS; s++; desc->u.name = s; + desc->name_used = 1; break; case '/': /* Subject's DN. */ @@ -161,6 +167,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) goto out; } desc->u.name = s; + desc->name_used = 1; mode = KEYDB_SEARCH_MODE_SUBJECT; break; @@ -178,6 +185,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) goto out; } desc->u.name = s; + desc->name_used = 1; mode = KEYDB_SEARCH_MODE_ISSUER; } else @@ -205,6 +213,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) goto out; } desc->u.name = s; + desc->name_used = 1; mode = KEYDB_SEARCH_MODE_ISSUER_SN; } } @@ -472,6 +481,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) if (!mode) /* Default to substring search. */ { desc->u.name = s; + desc->name_used = 1; mode = KEYDB_SEARCH_MODE_SUBSTR; } } diff --git a/kbx/kbxserver.c b/kbx/kbxserver.c index 0b76cde31..1949e6278 100644 --- a/kbx/kbxserver.c +++ b/kbx/kbxserver.c @@ -46,6 +46,13 @@ /**/: gpg_error (e)) +/* Helper to provide packing memory for search descriptions. */ +struct search_backing_store_s +{ + unsigned char *sn; + char *name; +}; + /* Control structure per connection. */ struct server_local_s @@ -84,10 +91,13 @@ struct server_local_s * cmd_search. If more than one pattern is required, cmd_search * also allocates and sets multi_search_desc and * multi_search_desc_len. If a search description has ever been - * allocated the allocated size is stored at - * multi_search_desc_size. */ + * allocated the allocated size is stored at multi_search_desc_size. + * multi_search_store is allocated at the same size as + * multi_search_desc and used to provde backing store for the SN and + * NAME elements of KEYBOX_SEARCH_DESC. */ KEYBOX_SEARCH_DESC search_desc; KEYBOX_SEARCH_DESC *multi_search_desc; + struct search_backing_store_s *multi_search_store; unsigned int multi_search_desc_size; unsigned int multi_search_desc_len; @@ -345,6 +355,9 @@ cmd_search (assuan_context_t ctx, char *line) { /* More pattern are expected - store the current one and return * success. */ + KEYBOX_SEARCH_DESC *desc; + struct search_backing_store_s *store; + if (!ctrl->server_local->multi_search_desc_size) { n = 10; @@ -355,13 +368,21 @@ cmd_search (assuan_context_t ctx, char *line) err = gpg_error_from_syserror (); goto leave; } + ctrl->server_local->multi_search_store + = xtrycalloc (n, sizeof *ctrl->server_local->multi_search_store); + if (!ctrl->server_local->multi_search_store) + { + err = gpg_error_from_syserror (); + xfree (ctrl->server_local->multi_search_desc); + ctrl->server_local->multi_search_desc = NULL; + goto leave; + } ctrl->server_local->multi_search_desc_size = n; } if (ctrl->server_local->multi_search_desc_len == ctrl->server_local->multi_search_desc_size) { - KEYBOX_SEARCH_DESC *desc; n = ctrl->server_local->multi_search_desc_size + 10; desc = xtrycalloc (n, sizeof *desc); if (!desc) @@ -369,20 +390,62 @@ cmd_search (assuan_context_t ctx, char *line) err = gpg_error_from_syserror (); goto leave; } + store = xtrycalloc (n, sizeof *store); + if (!desc) + { + err = gpg_error_from_syserror (); + xfree (desc); + goto leave; + } for (k=0; k < ctrl->server_local->multi_search_desc_size; k++) - desc[k] = ctrl->server_local->multi_search_desc[k]; + { + desc[k] = ctrl->server_local->multi_search_desc[k]; + store[k] = ctrl->server_local->multi_search_store[k]; + } xfree (ctrl->server_local->multi_search_desc); + xfree (ctrl->server_local->multi_search_store); ctrl->server_local->multi_search_desc = desc; + ctrl->server_local->multi_search_store = store; ctrl->server_local->multi_search_desc_size = n; } - /* Actually store. */ - ctrl->server_local->multi_search_desc - [ctrl->server_local->multi_search_desc_len++] - = ctrl->server_local->search_desc; + /* Actually store. We need to fix up the const pointers by + * copies from our backing store. */ + desc = &(ctrl->server_local->multi_search_desc + [ctrl->server_local->multi_search_desc_len]); + store = &(ctrl->server_local->multi_search_store + [ctrl->server_local->multi_search_desc_len]); + *desc = ctrl->server_local->search_desc; + if (ctrl->server_local->search_desc.sn) + { + xfree (store->sn); + store->sn = xtrymalloc (ctrl->server_local->search_desc.snlen); + if (!store->sn) + { + err = gpg_error_from_syserror (); + goto leave; + } + memcpy (store->sn, ctrl->server_local->search_desc.sn, + ctrl->server_local->search_desc.snlen); + desc->sn = store->sn; + } + if (ctrl->server_local->search_desc.name_used) + { + xfree (store->name); + store->name = xtrystrdup (ctrl->server_local->search_desc.u.name); + if (!store->name) + { + err = gpg_error_from_syserror (); + xfree (store->sn); + store->sn = NULL; + goto leave; + } + desc->u.name = store->name; + } + ctrl->server_local->multi_search_desc_len++; if (opt_more) { - /* We need to be called aagain with more pattern. */ + /* We need to be called again with more pattern. */ ctrl->server_local->search_expecting_more = 1; goto leave; } @@ -456,7 +519,7 @@ cmd_next (assuan_context_t ctx, char *line) ; else if (ctrl->server_local->multi_search_desc_len) { - /* The next condition should never be tru but we better handle + /* The next condition should never be true but we better handle * the first/next transition anyway. */ if (ctrl->server_local->multi_search_desc[0].mode == KEYDB_SEARCH_MODE_FIRST) @@ -993,6 +1056,17 @@ kbxd_start_command_handler (ctrl_t ctrl, gnupg_fd_t fd, unsigned int session_id) } xfree (ctrl->server_local->multi_search_desc); + if (ctrl->server_local->multi_search_store) + { + size_t nn; + + for (nn=0; nn < ctrl->server_local->multi_search_desc_size; nn++) + { + xfree (ctrl->server_local->multi_search_store[nn].sn); + xfree (ctrl->server_local->multi_search_store[nn].name); + } + xfree (ctrl->server_local->multi_search_store); + } xfree (ctrl->server_local); ctrl->server_local = NULL; } diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h index 9a0df2846..f312da99b 100644 --- a/kbx/keybox-search-desc.h +++ b/kbx/keybox-search-desc.h @@ -83,6 +83,7 @@ struct keydb_search_desc unsigned char grip[KEYGRIP_LEN]; unsigned char ubid[UBID_LEN]; } u; + byte name_used;/* The union uses NAME. */ byte snhex; /* SN above is a hexstring and not binary. */ byte fprlen; /* Only used with KEYDB_SEARCH_MODE_FPR. */ int exact; /* Use exactly this key ('!' suffix in gpg). */ |