1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

kbx: Add framework for the SEARCH command

* kbx/backend-kbx.c: New.
* kbx/backend-support.c: New.
* kbx/backend.h: New.
* kbx/frontend.c: New.
* kbx/frontend.h: New.
* kbx/kbxserver.c: Implement SEARCH and NEXT command.
* kbx/keybox-search-desc.h (enum pubkey_types): New.
* kbx/keybox-search.c (keybox_get_data): New.
* kbx/keyboxd.c (main): Add a standard resource.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-08-06 16:07:33 +02:00
parent 1f980d23af
commit 5ea6250cc5
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
13 changed files with 1237 additions and 34 deletions

View file

@ -1,5 +1,5 @@
/* kbxserver.c - Handle Assuan commands send to the keyboxd
* Copyright (C) 2018 g10 Code GmbH
* Copyright (C) 2019 g10 Code GmbH
*
* This file is part of GnuPG.
*
@ -31,10 +31,11 @@
#include "keyboxd.h"
#include <assuan.h>
#include "../common/i18n.h"
#include "../common/server-help.h"
#include "../common/userids.h"
#include "../common/asshelp.h"
#include "frontend.h"
@ -65,12 +66,99 @@ struct server_local_s
unsigned int inhibit_data_logging : 1;
unsigned int inhibit_data_logging_now : 1;
/* Dummy option. */
int foo;
/* This flag is set if the last search command was called with --more. */
unsigned int search_expecting_more : 1;
/* This flag is set if the last search command was successful. */
unsigned int search_any_found : 1;
/* The first is the current search description as parsed by the
* 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. */
KEYBOX_SEARCH_DESC search_desc;
KEYBOX_SEARCH_DESC *multi_search_desc;
unsigned int multi_search_desc_size;
unsigned int multi_search_desc_len;
};
/* Return the assuan contxt from the local server info in CTRL. */
static assuan_context_t
get_assuan_ctx_from_ctrl (ctrl_t ctrl)
{
if (!ctrl || !ctrl->server_local)
return NULL;
return ctrl->server_local->assuan_ctx;
}
/* A wrapper around assuan_send_data which makes debugging the output
* in verbose mode easier. It also takes CTRL as argument. */
gpg_error_t
kbxd_write_data_line (ctrl_t ctrl, const void *buffer_arg, size_t size)
{
const char *buffer = buffer_arg;
assuan_context_t ctx = get_assuan_ctx_from_ctrl (ctrl);
gpg_error_t err;
if (!ctx) /* Oops - no assuan context. */
return gpg_error (GPG_ERR_NOT_PROCESSED);
/* If we do not want logging, enable it here. */
if (ctrl && ctrl->server_local && ctrl->server_local->inhibit_data_logging)
ctrl->server_local->inhibit_data_logging_now = 1;
if (opt.verbose && buffer && size)
{
/* Ease reading of output by limiting the line length. */
size_t n, nbytes;
nbytes = size;
do
{
n = nbytes > 64? 64 : nbytes;
err = assuan_send_data (ctx, buffer, n);
if (err)
{
gpg_err_set_errno (EIO);
goto leave;
}
buffer += n;
nbytes -= n;
if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
{
gpg_err_set_errno (EIO);
goto leave;
}
}
while (nbytes);
}
else
{
err = assuan_send_data (ctx, buffer, size);
if (err)
{
gpg_err_set_errno (EIO); /* For use by data_line_cookie_write. */
goto leave;
}
}
leave:
if (ctrl && ctrl->server_local && ctrl->server_local->inhibit_data_logging)
{
ctrl->server_local->inhibit_data_logging_now = 0;
ctrl->server_local->inhibit_data_logging_count += size;
}
return err;
}
/* Helper to print a message while leaving a command. */
static gpg_error_t
@ -100,11 +188,7 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
if (!strcmp (key, "foo"))
{
ctrl->server_local->foo = 1;
}
else if (!strcmp (key, "lc-messages"))
if (!strcmp (key, "lc-messages"))
{
if (ctrl->lc_messages)
xfree (ctrl->lc_messages);
@ -120,22 +204,151 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
static const char hlp_foo[] =
"FOO <user_id>\n"
static const char hlp_search[] =
"SEARCH [--no-data] [[--more] PATTERN]\n"
"\n"
"Bla bla\n"
"more bla.";
"Search for the keys identified by PATTERN. With --more more\n"
"patterns to be used for the search are expected with the next\n"
"command. With --no-data only the search status is returned but\n"
"not the actual data. See also \"NEXT\".";
static gpg_error_t
cmd_foo (assuan_context_t ctx, char *line)
cmd_search (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int opt_more, opt_no_data;
gpg_error_t err;
unsigned int n, k;
opt_no_data = has_option (line, "--no-data");
opt_more = has_option (line, "--more");
line = skip_options (line);
ctrl->server_local->search_any_found = 0;
if (!*line && opt_more)
{
err = set_error (GPG_ERR_INV_ARG, "--more but no pattern");
goto leave;
}
else if (!*line && ctrl->server_local->search_expecting_more)
{
/* It would be too surprising to first set a pattern but finally
* add no pattern to search the entire DB. */
err = set_error (GPG_ERR_INV_ARG, "--more pending but no pattern");
goto leave;
}
err = classify_user_id (line, &ctrl->server_local->search_desc, 0);
if (err)
goto leave;
if (opt_more || ctrl->server_local->search_expecting_more)
{
/* More pattern are expected - store the current one and return
* success. */
if (!ctrl->server_local->multi_search_desc_size)
{
n = 10;
ctrl->server_local->multi_search_desc
= xtrycalloc (n, sizeof *ctrl->server_local->multi_search_desc);
if (!ctrl->server_local->multi_search_desc)
{
err = gpg_error_from_syserror ();
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)
{
err = gpg_error_from_syserror ();
goto leave;
}
for (k=0; k < ctrl->server_local->multi_search_desc_size; k++)
desc[k] = ctrl->server_local->multi_search_desc[k];
xfree (ctrl->server_local->multi_search_desc);
ctrl->server_local->multi_search_desc = desc;
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;
if (opt_more)
{
/* We need to be called aagain with more pattern. */
ctrl->server_local->search_expecting_more = 1;
goto leave;
}
ctrl->server_local->search_expecting_more = 0;
/* Continue with the actual search. */
}
else
ctrl->server_local->multi_search_desc_len = 0;
ctrl->no_data_return = opt_no_data;
if (ctrl->server_local->multi_search_desc_len)
err = kbxd_search (ctrl, ctrl->server_local->multi_search_desc,
ctrl->server_local->multi_search_desc_len, 1);
else
err = kbxd_search (ctrl, &ctrl->server_local->search_desc, 1, 1);
if (err)
goto leave;
/* Set a flag for use by NEXT. */
ctrl->server_local->search_any_found = 1;
leave:
if (err)
ctrl->server_local->multi_search_desc_len = 0;
ctrl->no_data_return = 0;
return leave_cmd (ctx, err);
}
static const char hlp_next[] =
"NEXT [--no-data]\n"
"\n"
"Get the next search result from a previus search.";
static gpg_error_t
cmd_next (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int opt_no_data;
gpg_error_t err;
(void)ctrl;
(void)line;
opt_no_data = has_option (line, "--no-data");
line = skip_options (line);
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (*line)
{
err = set_error (GPG_ERR_INV_ARG, "no args expected");
goto leave;
}
if (!ctrl->server_local->search_any_found)
{
err = set_error (GPG_ERR_NOTHING_FOUND, "no previous SEARCH");
goto leave;
}
ctrl->no_data_return = opt_no_data;
if (ctrl->server_local->multi_search_desc_len)
err = kbxd_search (ctrl, ctrl->server_local->multi_search_desc,
ctrl->server_local->multi_search_desc_len, 0);
else
err = kbxd_search (ctrl, &ctrl->server_local->search_desc, 1, 0);
if (err)
goto leave;
leave:
ctrl->no_data_return = 0;
return leave_cmd (ctx, err);
}
@ -250,7 +463,8 @@ register_commands (assuan_context_t ctx)
assuan_handler_t handler;
const char * const help;
} table[] = {
{ "FOO", cmd_foo, hlp_foo },
{ "SEARCH", cmd_search, hlp_search },
{ "NEXT", cmd_next, hlp_next },
{ "GETINFO", cmd_getinfo, hlp_getinfo },
{ "KILLKEYBOXD",cmd_killkeyboxd,hlp_killkeyboxd },
{ "RELOADKEYBOXD",cmd_reloadkeyboxd,hlp_reloadkeyboxd },
@ -306,16 +520,6 @@ kbxd_assuan_log_monitor (assuan_context_t ctx, unsigned int cat,
}
/* Return the assuan contxt from the local server info in CTRL. */
static assuan_context_t
get_assuan_ctx_from_ctrl (ctrl_t ctrl)
{
if (!ctrl || !ctrl->server_local)
return NULL;
return ctrl->server_local->assuan_ctx;
}
/* Startup the server and run the main command loop. With FD = -1,
* use stdin/stdout. SESSION_ID is either 0 or a unique number
* identifying a session. */
@ -441,6 +645,7 @@ kbxd_start_command_handler (ctrl_t ctrl, gnupg_fd_t fd, unsigned int session_id)
ctrl->refcount);
else
{
xfree (ctrl->server_local->multi_search_desc);
xfree (ctrl->server_local);
ctrl->server_local = NULL;
}