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/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#warning fixme Windows part not yet done
#include <config.h> #include <config.h>
#include <stdio.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 /* Select a random host. Consult TABLE which indices into the global
hosttable. Returns index into TABLE or -1 if no host could be hosttable. Returns index into TABLE or -1 if no host could be
selected. */ 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. */ /* Debug function to print the entire hosttable. */
gpg_error_t gpg_error_t
ks_hkp_print_hosttable (ctrl_t ctrl) 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 --*/ /*-- ks-engine-hkp.c --*/
gpg_error_t ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri); 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_print_hosttable (ctrl_t ctrl);
gpg_error_t ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri); 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, 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. */ /* Common code for get_cert_local and get_issuer_cert_local. */
static ksba_cert_t static ksba_cert_t
do_get_cert_local (ctrl_t ctrl, const char *name, const char *command) 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[] = 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" "\n"
"If called without arguments list all configured keyserver URLs.\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" "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" "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" "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); ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0; gpg_error_t err = 0;
int clear_flag, add_flag, help_flag, host_flag, resolve_flag; 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 uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
is always initialized. */ is always initialized. */
@ -1415,6 +1448,8 @@ cmd_keyserver (assuan_context_t ctx, char *line)
help_flag = has_option (line, "--help"); help_flag = has_option (line, "--help");
resolve_flag = has_option (line, "--resolve"); resolve_flag = has_option (line, "--resolve");
host_flag = has_option (line, "--hosttable"); host_flag = has_option (line, "--hosttable");
dead_flag = has_option (line, "--dead");
alive_flag = has_option (line, "--alive");
line = skip_options (line); line = skip_options (line);
add_flag = !!*line; add_flag = !!*line;
@ -1431,13 +1466,37 @@ cmd_keyserver (assuan_context_t ctx, char *line)
goto leave; 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) if (host_flag)
{ {
err = ks_hkp_print_hosttable (ctrl); err = ks_hkp_print_hosttable (ctrl);
if (err) if (err)
goto leave; goto leave;
} }
if (resolve_flag || host_flag) if (resolve_flag || host_flag || alive_flag || dead_flag)
goto leave; goto leave;
if (add_flag) if (add_flag)
@ -1746,30 +1805,28 @@ static gpg_error_t
cmd_killdirmngr (assuan_context_t ctx, char *line) cmd_killdirmngr (assuan_context_t ctx, char *line)
{ {
ctrl_t ctrl = assuan_get_pointer (ctx); ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err;
(void)line; (void)line;
if (opt.system_daemon) if (opt.system_daemon)
{ {
if (opt.system_service) if (opt.system_service)
return set_error (GPG_ERR_NOT_SUPPORTED, err = set_error (GPG_ERR_NOT_SUPPORTED,
"can't do that whilst running as system service"); "can't do that whilst running as system service");
#ifndef HAVE_W32_SYSTEM else
{ err = check_owner_permission (ctx,
gpg_err_code_t ec; "no permission to kill this process");
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
} }
else
err = 0;
ctrl->server_local->stopme = 1; if (!err)
return gpg_error (GPG_ERR_EOF); {
ctrl->server_local->stopme = 1;
err = gpg_error (GPG_ERR_EOF);
}
return err;
} }