dirmngr: Add command option to mark hosts as dead or alive.

* dirmngr/server.c (cmd_killdirmngr): Factor some code out to ...
(check_owner_permission): here.
(cmd_keyserver): Add options --dead and --alive.
* dirmngr/ks-engine-hkp.c (host_in_pool_p): New.
(ks_hkp_mark_host): New.
--

Also removed the warning that the widnows part has not yet been done.
AFAICS, the current mingw supports the all used socket functions.
This commit is contained in:
Werner Koch 2014-03-11 16:19:41 +01:00
parent 71b55c9455
commit a3dee28891
3 changed files with 164 additions and 20 deletions

View File

@ -18,7 +18,6 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#warning fixme Windows part not yet done
#include <config.h>
#include <stdio.h>
@ -153,6 +152,19 @@ sort_hostpool (const void *xa, const void *xb)
}
/* Return true if the host with the hosttable index TBLIDX is in POOL. */
static int
host_in_pool_p (int *pool, int tblidx)
{
int i, pidx;
for (i=0; (pidx = pool[i]) != -1; i++)
if (pidx == tblidx && hosttable[pidx])
return 1;
return 0;
}
/* Select a random host. Consult TABLE which indices into the global
hosttable. Returns index into TABLE or -1 if no host could be
selected. */
@ -374,6 +386,80 @@ mark_host_dead (const char *name)
}
/* Mark a host in the hosttable as dead or - if ALIVE is true - as
alive. If the host NAME does not exist a warning status message is
printed. */
gpg_error_t
ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
{
gpg_error_t err = 0;
hostinfo_t hi, hi2;
int idx, idx2, idx3, n;
if (!name || !*name || !strcmp (name, "localhost"))
return 0;
idx = find_hostinfo (name);
if (idx == -1)
return gpg_error (GPG_ERR_NOT_FOUND);
hi = hosttable[idx];
if (alive && hi->dead)
{
hi->dead = 0;
err = ks_printf_help (ctrl, "marking '%s' as alive", name);
}
else if (!alive && !hi->dead)
{
hi->dead = 1;
err = ks_printf_help (ctrl, "marking '%s' as dead", name);
}
/* If the host is a pool mark all member hosts. */
if (!err && hi->pool)
{
for (idx2=0; !err && (n=hi->pool[idx2]) != -1; idx2++)
{
assert (n >= 0 && n < hosttable_size);
if (!alive)
{
/* Do not mark a host from a pool dead if it is also a
member in another pool. */
for (idx3=0; idx3 < hosttable_size; idx3++)
{
if (hosttable[idx3] && hosttable[idx3]
&& hosttable[idx3]->pool
&& idx3 != idx
&& host_in_pool_p (hosttable[idx3]->pool, n))
break;
}
if (idx3 < hosttable_size)
continue; /* Host is also a member of another pool. */
}
hi2 = hosttable[n];
if (!hi2)
;
else if (alive && hi2->dead)
{
hi2->dead = 0;
err = ks_printf_help (ctrl, "marking '%s' as alive",
hi2->name);
}
else if (!alive && !hi2->dead)
{
hi2->dead = 1;
err = ks_printf_help (ctrl, "marking '%s' as dead",
hi2->name);
}
}
}
return err;
}
/* Debug function to print the entire hosttable. */
gpg_error_t
ks_hkp_print_hosttable (ctrl_t ctrl)

View File

@ -30,6 +30,7 @@ gpg_error_t ks_printf_help (ctrl_t ctrl, const char *format,
/*-- ks-engine-hkp.c --*/
gpg_error_t ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri);
gpg_error_t ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive);
gpg_error_t ks_hkp_print_hosttable (ctrl_t ctrl);
gpg_error_t ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri);
gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,

View File

@ -298,6 +298,32 @@ skip_options (char *line)
}
/* Return an error if the assuan context does not belong to teh owner
of the process or to root. On error FAILTEXT is set as Assuan
error string. */
static gpg_error_t
check_owner_permission (assuan_context_t ctx, const char *failtext)
{
#ifdef HAVE_W32_SYSTEM
/* Under Windows the dirmngr is always run under the control of the
user. */
(void)ctx;
(void)failtext;
#else
gpg_err_code_t ec;
assuan_peercred_t cred;
ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
if (!ec && cred->uid && cred->uid != getuid ())
ec = GPG_ERR_EPERM;
if (ec)
return set_error (ec, failtext);
#endif
return 0;
}
/* Common code for get_cert_local and get_issuer_cert_local. */
static ksba_cert_t
do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
@ -1392,10 +1418,16 @@ cmd_validate (assuan_context_t ctx, char *line)
static const char hlp_keyserver[] =
"KEYSERVER [--clear|--help] [<uri>]\n"
"KEYSERVER [<options>] [<uri>|<host>]\n"
"Options are:\n"
" --help\n"
" --clear Remove all configured keyservers\n"
" --resolve Resolve HKP host names and rotate\n"
" --hosttable Print table of known hosts and pools\n"
" --dead Mark <host> as dead\n"
" --alive Mark <host> as alive\n"
"\n"
"If called without arguments list all configured keyserver URLs.\n"
"If called with option \"--clear\" remove all configured keyservers\n"
"If called with an URI add this as keyserver. Note that keyservers\n"
"are configured on a per-session base. A default keyserver may already be\n"
"present, thus the \"--clear\" option must be used to get full control.\n"
@ -1408,6 +1440,7 @@ cmd_keyserver (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
int dead_flag, alive_flag;
uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
is always initialized. */
@ -1415,6 +1448,8 @@ cmd_keyserver (assuan_context_t ctx, char *line)
help_flag = has_option (line, "--help");
resolve_flag = has_option (line, "--resolve");
host_flag = has_option (line, "--hosttable");
dead_flag = has_option (line, "--dead");
alive_flag = has_option (line, "--alive");
line = skip_options (line);
add_flag = !!*line;
@ -1431,13 +1466,37 @@ cmd_keyserver (assuan_context_t ctx, char *line)
goto leave;
}
if (alive_flag && dead_flag)
{
err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
goto leave;
}
if (dead_flag)
{
err = check_owner_permission (ctx, "no permission to use --dead");
if (err)
goto leave;
}
if (alive_flag || dead_flag)
{
if (!*line)
{
err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
goto leave;
}
err = ks_hkp_mark_host (ctrl, line, alive_flag);
if (err)
goto leave;
}
if (host_flag)
{
err = ks_hkp_print_hosttable (ctrl);
if (err)
goto leave;
}
if (resolve_flag || host_flag)
if (resolve_flag || host_flag || alive_flag || dead_flag)
goto leave;
if (add_flag)
@ -1746,30 +1805,28 @@ static gpg_error_t
cmd_killdirmngr (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err;
(void)line;
if (opt.system_daemon)
{
if (opt.system_service)
return set_error (GPG_ERR_NOT_SUPPORTED,
"can't do that whilst running as system service");
#ifndef HAVE_W32_SYSTEM
{
gpg_err_code_t ec;
assuan_peercred_t cred;
ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
if (!ec && cred->uid)
ec = GPG_ERR_EPERM; /* Only root may terminate. */
if (ec)
return set_error (ec, "no permission to kill this process");
}
#endif
err = set_error (GPG_ERR_NOT_SUPPORTED,
"can't do that whilst running as system service");
else
err = check_owner_permission (ctx,
"no permission to kill this process");
}
else
err = 0;
ctrl->server_local->stopme = 1;
return gpg_error (GPG_ERR_EOF);
if (!err)
{
ctrl->server_local->stopme = 1;
err = gpg_error (GPG_ERR_EOF);
}
return err;
}