* gpgsm.c: New option --auto-issuer-key-retrieve.

* certpath.c (find_up): Try to retrieve an issuer key from an
external source and from the ephemeral key DB.
(find_up_store_certs_cb): New.

* keydb.c (keydb_set_ephemeral): Does now return the old
state.  Call the backend only when required.

* call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR.
(lookup_status_cb): Issue status only when CTRL is not NULL.
(gpgsm_dirmngr_lookup): Document that CTRL is optional.

* call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT.
This commit is contained in:
Werner Koch 2002-06-29 14:01:53 +00:00
parent 2082905525
commit df58e024e7
8 changed files with 214 additions and 23 deletions

View File

@ -1,3 +1,19 @@
2002-06-29 Werner Koch <wk@gnupg.org>
* gpgsm.c: New option --auto-issuer-key-retrieve.
* certpath.c (find_up): Try to retrieve an issuer key from an
external source and from the ephemeral key DB.
(find_up_store_certs_cb): New.
* keydb.c (keydb_set_ephemeral): Does now return the old
state. Call the backend only when required.
* call-dirmngr.c (start_dirmngr): Use GNUPG_DEFAULT_DIRMNGR.
(lookup_status_cb): Issue status only when CTRL is not NULL.
(gpgsm_dirmngr_lookup): Document that CTRL is optional.
* call-agent.c (start_agent): Use GNUPG_DEFAULT_AGENT.
2002-06-28 Werner Koch <wk@gnupg.org> 2002-06-28 Werner Koch <wk@gnupg.org>
* server.c (cmd_recipient): Add more reason codes. * server.c (cmd_recipient): Add more reason codes.

View File

@ -164,7 +164,7 @@ start_agent (void)
} }
if (!opt.agent_program || !*opt.agent_program) if (!opt.agent_program || !*opt.agent_program)
opt.agent_program = "../agent/gpg-agent"; opt.agent_program = GNUPG_DEFAULT_AGENT;
if ( !(pgmname = strrchr (opt.agent_program, '/'))) if ( !(pgmname = strrchr (opt.agent_program, '/')))
pgmname = opt.agent_program; pgmname = opt.agent_program;
else else

View File

@ -156,7 +156,7 @@ start_dirmngr (void)
} }
if (!opt.dirmngr_program || !*opt.dirmngr_program) if (!opt.dirmngr_program || !*opt.dirmngr_program)
opt.dirmngr_program = "/usr/sbin/dirmngr"; opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR;
if ( !(pgmname = strrchr (opt.dirmngr_program, '/'))) if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
pgmname = opt.dirmngr_program; pgmname = opt.dirmngr_program;
else else
@ -432,9 +432,12 @@ lookup_status_cb (void *opaque, const char *line)
if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9])) if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
{ {
for (line +=9; *line == ' '; line++) if (parm->ctrl)
; {
gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line); for (line +=9; *line == ' '; line++)
;
gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
}
} }
return 0; return 0;
} }
@ -442,7 +445,8 @@ lookup_status_cb (void *opaque, const char *line)
/* Run the Directroy Managers lookup command using the apptern /* Run the Directroy Managers lookup command using the apptern
compiled from the strings given in NAMES. The caller must provide compiled from the strings given in NAMES. The caller must provide
the callback CB which will be passed cert by cert. */ the callback CB which will be passed cert by cert. Note that CTRL
is optional. */
int int
gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names, gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
void (*cb)(void*, KsbaCert), void *cb_value) void (*cb)(void*, KsbaCert), void *cb_value)

View File

@ -196,6 +196,15 @@ check_cert_policy (KsbaCert cert)
} }
static void
find_up_store_certs_cb (void *cb_value, KsbaCert cert)
{
if (keydb_store_cert (cert, 1))
log_error ("error storing issuer certificate as ephemeral\n");
++*(int*)cb_value;
}
static int static int
find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
{ {
@ -211,13 +220,82 @@ find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
rc = keydb_search_issuer_sn (kh, s, authidno); rc = keydb_search_issuer_sn (kh, s, authidno);
if (rc) if (rc)
keydb_search_reset (kh); keydb_search_reset (kh);
if (rc == -1)
{ /* And try the ephemeral DB. */
int old = keydb_set_ephemeral (kh, 1);
if (!old)
{
rc = keydb_search_issuer_sn (kh, s, authidno);
if (rc)
keydb_search_reset (kh);
}
keydb_set_ephemeral (kh, old);
}
} }
ksba_name_release (authid); ksba_name_release (authid);
xfree (authidno); xfree (authidno);
/* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
} }
if (rc) if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
rc = keydb_search_subject (kh, issuer); rc = keydb_search_subject (kh, issuer);
if (rc == -1)
{
/* Not found, lets see whether we have one in the ephemeral key DB. */
int old = keydb_set_ephemeral (kh, 1);
if (!old)
{
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
}
keydb_set_ephemeral (kh, old);
}
if (rc == -1 && opt.auto_issuer_key_retrieve)
{
STRLIST names = NULL;
int count = 0;
char *pattern;
const char *s;
if (opt.verbose)
log_info (_("looking up issuer at external location\n"));
/* dirmngr is confused about unknown attributes so has a quick
and ugly hack we locate the CN and use this and the
following. Fixme: we should have far ebtter parsing in the
dirmngr. */
s = strstr (issuer, "CN=");
if (!s || s == issuer || s[-1] != ',')
s = issuer;
pattern = xtrymalloc (strlen (s)+2);
if (!pattern)
return GNUPG_Out_Of_Core;
strcpy (stpcpy (pattern, "/"), s);
add_to_strlist (&names, pattern);
xfree (pattern);
rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
free_strlist (names);
if (opt.verbose)
log_info (_("number of issuers matching: %d\n"), count);
if (rc)
{
log_error ("external key lookup failed: %s\n", gnupg_strerror (rc));
rc = -1;
}
else if (!count)
rc = -1;
else
{
int old;
/* The issuers are currently stored in the ephemeral key
DB, so we temporary switch to ephemeral mode. */
old = keydb_set_ephemeral (kh, 1);
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
keydb_set_ephemeral (kh, old);
}
}
return rc; return rc;
} }

View File

@ -196,6 +196,15 @@ check_cert_policy (KsbaCert cert)
} }
static void
find_up_store_certs_cb (void *cb_value, KsbaCert cert)
{
if (keydb_store_cert (cert, 1))
log_error ("error storing issuer certificate as ephemeral\n");
++*(int*)cb_value;
}
static int static int
find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer) find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
{ {
@ -211,13 +220,82 @@ find_up (KEYDB_HANDLE kh, KsbaCert cert, const char *issuer)
rc = keydb_search_issuer_sn (kh, s, authidno); rc = keydb_search_issuer_sn (kh, s, authidno);
if (rc) if (rc)
keydb_search_reset (kh); keydb_search_reset (kh);
if (rc == -1)
{ /* And try the ephemeral DB. */
int old = keydb_set_ephemeral (kh, 1);
if (!old)
{
rc = keydb_search_issuer_sn (kh, s, authidno);
if (rc)
keydb_search_reset (kh);
}
keydb_set_ephemeral (kh, old);
}
} }
ksba_name_release (authid); ksba_name_release (authid);
xfree (authidno); xfree (authidno);
/* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
} }
if (rc) if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
rc = keydb_search_subject (kh, issuer); rc = keydb_search_subject (kh, issuer);
if (rc == -1)
{
/* Not found, lets see whether we have one in the ephemeral key DB. */
int old = keydb_set_ephemeral (kh, 1);
if (!old)
{
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
}
keydb_set_ephemeral (kh, old);
}
if (rc == -1 && opt.auto_issuer_key_retrieve)
{
STRLIST names = NULL;
int count = 0;
char *pattern;
const char *s;
if (opt.verbose)
log_info (_("looking up issuer at external location\n"));
/* dirmngr is confused about unknown attributes so has a quick
and ugly hack we locate the CN and use this and the
following. Fixme: we should have far ebtter parsing in the
dirmngr. */
s = strstr (issuer, "CN=");
if (!s || s == issuer || s[-1] != ',')
s = issuer;
pattern = xtrymalloc (strlen (s)+2);
if (!pattern)
return GNUPG_Out_Of_Core;
strcpy (stpcpy (pattern, "/"), s);
add_to_strlist (&names, pattern);
xfree (pattern);
rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
free_strlist (names);
if (opt.verbose)
log_info (_("number of issuers matching: %d\n"), count);
if (rc)
{
log_error ("external key lookup failed: %s\n", gnupg_strerror (rc));
rc = -1;
}
else if (!count)
rc = -1;
else
{
int old;
/* The issuers are currently stored in the ephemeral key
DB, so we temporary switch to ephemeral mode. */
old = keydb_set_ephemeral (kh, 1);
keydb_search_reset (kh);
rc = keydb_search_subject (kh, issuer);
keydb_set_ephemeral (kh, old);
}
}
return rc; return rc;
} }

View File

@ -112,7 +112,7 @@ enum cmd_and_opt_values {
oPolicyFile, oPolicyFile,
oDisablePolicyChecks, oDisablePolicyChecks,
oEnablePolicyChecks, oEnablePolicyChecks,
oAutoIssuerKeyRetrieve,
oTextmode, oTextmode,
@ -259,6 +259,9 @@ static ARGPARSE_OPTS opts[] = {
N_("do not check certificate policies")}, N_("do not check certificate policies")},
{ oEnablePolicyChecks, "enable-policy-checks", 0, "@"}, { oEnablePolicyChecks, "enable-policy-checks", 0, "@"},
{ oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0,
N_("fetch missing issuer certificates")},
#if 0 #if 0
{ oDefRecipient, "default-recipient" ,2, { oDefRecipient, "default-recipient" ,2,
N_("|NAME|use NAME as default recipient")}, N_("|NAME|use NAME as default recipient")},
@ -809,7 +812,10 @@ main ( int argc, char **argv)
case oEnablePolicyChecks: case oEnablePolicyChecks:
opt.no_policy_check = 0; opt.no_policy_check = 0;
break; break;
case oAutoIssuerKeyRetrieve:
opt.auto_issuer_key_retrieve = 1;
break;
case oOutput: opt.outfile = pargs.r.ret_str; break; case oOutput: opt.outfile = pargs.r.ret_str; break;

View File

@ -79,6 +79,8 @@ struct {
char *policy_file; /* full pathname of policy file */ char *policy_file; /* full pathname of policy file */
int no_policy_check; /* ignore certificate policies */ int no_policy_check; /* ignore certificate policies */
int no_path_validation; /* Bypass all cert path validity tests */ int no_path_validation; /* Bypass all cert path validity tests */
int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */
} opt; } opt;

View File

@ -59,7 +59,7 @@ struct keydb_handle {
int locked; int locked;
int found; int found;
int current; int current;
int ephemeral; int is_ephemeral;
int used; /* items in active */ int used; /* items in active */
struct resource_item active[MAX_KEYDB_RESOURCES]; struct resource_item active[MAX_KEYDB_RESOURCES];
}; };
@ -332,27 +332,34 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
return s? s: ""; return s? s: "";
} }
/* Switch the handle into ephemeral mode and return the orginal value. */
int int
keydb_set_ephemeral (KEYDB_HANDLE hd, int yes) keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
{ {
int i; int i;
if (!hd) if (!hd)
return GNUPG_Invalid_Value; return 0;
for (i=0; i < hd->used; i++) yes = !!yes;
if (hd->is_ephemeral != yes)
{ {
switch (hd->active[i].type) for (i=0; i < hd->used; i++)
{ {
case KEYDB_RESOURCE_TYPE_NONE: switch (hd->active[i].type)
break; {
case KEYDB_RESOURCE_TYPE_KEYBOX: case KEYDB_RESOURCE_TYPE_NONE:
keybox_set_ephemeral (hd->active[i].u.kr, yes); break;
break; case KEYDB_RESOURCE_TYPE_KEYBOX:
keybox_set_ephemeral (hd->active[i].u.kr, yes);
break;
}
} }
} }
return 0; i = hd->is_ephemeral;
hd->is_ephemeral = yes;
return i;
} }