aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2002-06-29 14:01:53 +0000
committerWerner Koch <[email protected]>2002-06-29 14:01:53 +0000
commitdf58e024e71b100a1557b1023d35b2a0092a8748 (patch)
tree18c586e4583637186779686afef445c71427307f
parent* query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY. (diff)
downloadgnupg-df58e024e71b100a1557b1023d35b2a0092a8748.tar.gz
gnupg-df58e024e71b100a1557b1023d35b2a0092a8748.zip
* 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.
-rw-r--r--sm/ChangeLog16
-rw-r--r--sm/call-agent.c2
-rw-r--r--sm/call-dirmngr.c14
-rw-r--r--sm/certchain.c82
-rw-r--r--sm/certpath.c82
-rw-r--r--sm/gpgsm.c10
-rw-r--r--sm/gpgsm.h2
-rw-r--r--sm/keydb.c29
8 files changed, 214 insertions, 23 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 160fe4766..6a0200ba0 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,19 @@
+2002-06-29 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
* server.c (cmd_recipient): Add more reason codes.
diff --git a/sm/call-agent.c b/sm/call-agent.c
index b3c78579c..9462deb40 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -164,7 +164,7 @@ start_agent (void)
}
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, '/')))
pgmname = opt.agent_program;
else
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index 017191dbe..30b34762f 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -156,7 +156,7 @@ start_dirmngr (void)
}
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, '/')))
pgmname = opt.dirmngr_program;
else
@@ -432,9 +432,12 @@ lookup_status_cb (void *opaque, const char *line)
if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
{
- for (line +=9; *line == ' '; line++)
- ;
- gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
+ if (parm->ctrl)
+ {
+ for (line +=9; *line == ' '; line++)
+ ;
+ gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
+ }
}
return 0;
}
@@ -442,7 +445,8 @@ lookup_status_cb (void *opaque, const char *line)
/* Run the Directroy Managers lookup command using the apptern
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
gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
void (*cb)(void*, KsbaCert), void *cb_value)
diff --git a/sm/certchain.c b/sm/certchain.c
index a32c2d7f7..0457a0aa1 100644
--- a/sm/certchain.c
+++ b/sm/certchain.c
@@ -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
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);
if (rc)
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);
xfree (authidno);
+ /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
}
- if (rc)
- rc = keydb_search_subject (kh, issuer);
+ if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
+ 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;
}
diff --git a/sm/certpath.c b/sm/certpath.c
index a32c2d7f7..0457a0aa1 100644
--- a/sm/certpath.c
+++ b/sm/certpath.c
@@ -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
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);
if (rc)
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);
xfree (authidno);
+ /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
}
- if (rc)
- rc = keydb_search_subject (kh, issuer);
+ if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
+ 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;
}
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 9d91cd9db..7b1b0d715 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -112,7 +112,7 @@ enum cmd_and_opt_values {
oPolicyFile,
oDisablePolicyChecks,
oEnablePolicyChecks,
-
+ oAutoIssuerKeyRetrieve,
oTextmode,
@@ -259,6 +259,9 @@ static ARGPARSE_OPTS opts[] = {
N_("do not check certificate policies")},
{ oEnablePolicyChecks, "enable-policy-checks", 0, "@"},
+ { oAutoIssuerKeyRetrieve, "auto-issuer-key-retrieve", 0,
+ N_("fetch missing issuer certificates")},
+
#if 0
{ oDefRecipient, "default-recipient" ,2,
N_("|NAME|use NAME as default recipient")},
@@ -809,7 +812,10 @@ main ( int argc, char **argv)
case oEnablePolicyChecks:
opt.no_policy_check = 0;
break;
-
+
+ case oAutoIssuerKeyRetrieve:
+ opt.auto_issuer_key_retrieve = 1;
+ break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index b4f7ebe5c..efa98dee5 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -79,6 +79,8 @@ struct {
char *policy_file; /* full pathname of policy file */
int no_policy_check; /* ignore certificate policies */
int no_path_validation; /* Bypass all cert path validity tests */
+
+ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */
} opt;
diff --git a/sm/keydb.c b/sm/keydb.c
index bc4721418..52f40f1ad 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -59,7 +59,7 @@ struct keydb_handle {
int locked;
int found;
int current;
- int ephemeral;
+ int is_ephemeral;
int used; /* items in active */
struct resource_item active[MAX_KEYDB_RESOURCES];
};
@@ -332,27 +332,34 @@ keydb_get_resource_name (KEYDB_HANDLE hd)
return s? s: "";
}
+/* Switch the handle into ephemeral mode and return the orginal value. */
int
keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
{
int i;
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:
- break;
- case KEYDB_RESOURCE_TYPE_KEYBOX:
- keybox_set_ephemeral (hd->active[i].u.kr, yes);
- break;
+ switch (hd->active[i].type)
+ {
+ case KEYDB_RESOURCE_TYPE_NONE:
+ 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;
}