mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
dirmngr: New options --first and --next for KS_GET.
* dirmngr/server.c (cmd_ks_get): Add option --first and --next. (start_command_handler): Free that new ldap state. * dirmngr/ks-engine-ldap.c (struct ks_engine_ldap_local_s): New. (ks_ldap_new_state, ks_ldap_clear_state): New. (ks_ldap_free_state): New. (return_one_keyblock): New. Mostly factored out from .... (ks_ldap_get): here. Implement --first/--next feature. * dirmngr/ks-action.c (ks_action_get): Rename arg ldap_only to ks_get_flags. * dirmngr/ks-engine.h (KS_GET_FLAG_ONLY_LDAP): New. (KS_GET_FLAG_FIRST): New. (KS_GET_FLAG_NEXT): New. * dirmngr/dirmngr.h (struct server_control_s): Add member ks_get_state. (struct ks_engine_ldap_local_s): New forward reference. -- This feature allows to fetch keyblock by keyblock from an LDAP server. This way tools can process and maybe filter each keyblock in a more flexible way. Here is an example where two keyblocks for one mail address are returned: $ gpg-connect-agent --dirmngr > ks_get --ldap --first <foo@example.org> [... First keyblock is returned ] OK > ks_get --next [ ... Next keyblock is returned ] OK > ks_get --next ERR 167772218 No data <Dirmngr> GnuPG_bug_id: 6224
This commit is contained in:
parent
3390951ffd
commit
4de98d4468
@ -187,8 +187,10 @@ struct cert_ref_s
|
||||
};
|
||||
typedef struct cert_ref_s *cert_ref_t;
|
||||
|
||||
/* Forward reference; access only via ks-engine-ldap.c. */
|
||||
struct ks_engine_ldap_local_s;
|
||||
|
||||
/* Forward references; access only through server.c. */
|
||||
/* Forward reference; access only through server.c. */
|
||||
struct server_local_s;
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
@ -205,6 +207,7 @@ struct server_control_s
|
||||
int no_server; /* We are not running under server control. */
|
||||
int status_fd; /* Only for non-server mode. */
|
||||
struct server_local_s *server_local;
|
||||
struct ks_engine_ldap_local_s *ks_get_state;
|
||||
int force_crl_refresh; /* Always load a fresh CRL. */
|
||||
|
||||
int check_revocations_nest_level; /* Internal to check_revovations. */
|
||||
|
@ -243,7 +243,7 @@ ks_action_search (ctrl_t ctrl, uri_item_t keyservers,
|
||||
keyservers and write the result to the provided output stream. */
|
||||
gpg_error_t
|
||||
ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, int ldap_only, estream_t outfp)
|
||||
strlist_t patterns, unsigned int ks_get_flags, estream_t outfp)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
gpg_error_t first_err = 0;
|
||||
@ -270,7 +270,7 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
|| strcmp (uri->parsed_uri->scheme, "https") == 0);
|
||||
int is_ldap = 0;
|
||||
|
||||
if (ldap_only)
|
||||
if ((ks_get_flags & KS_GET_FLAG_ONLY_LDAP))
|
||||
is_hkp_s = is_http_s = 0;
|
||||
|
||||
#if USE_LDAP
|
||||
@ -287,7 +287,8 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
{
|
||||
#if USE_LDAP
|
||||
if (is_ldap)
|
||||
err = ks_ldap_get (ctrl, uri->parsed_uri, sl->d, &infp);
|
||||
err = ks_ldap_get (ctrl, uri->parsed_uri, sl->d, ks_get_flags,
|
||||
&infp);
|
||||
else
|
||||
#endif
|
||||
if (is_hkp_s)
|
||||
|
@ -26,7 +26,8 @@ gpg_error_t ks_action_resolve (ctrl_t ctrl, uri_item_t keyservers);
|
||||
gpg_error_t ks_action_search (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, estream_t outfp);
|
||||
gpg_error_t ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|
||||
strlist_t patterns, int ldap_only, estream_t outfp);
|
||||
strlist_t patterns, unsigned int ks_get_flags,
|
||||
estream_t outfp);
|
||||
gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp);
|
||||
gpg_error_t ks_action_put (ctrl_t ctrl, uri_item_t keyservers,
|
||||
void *data, size_t datalen,
|
||||
|
@ -40,7 +40,7 @@
|
||||
|
||||
/* Flags with infos from the connected server. */
|
||||
#define SERVERINFO_REALLDAP 1 /* This is not the PGP keyserver. */
|
||||
#define SERVERINFO_PGPKEYV2 2 /* Needs "pgpeyV2" instead of "pgpKey" */
|
||||
#define SERVERINFO_PGPKEYV2 2 /* Needs "pgpKeyV2" instead of "pgpKey"*/
|
||||
#define SERVERINFO_SCHEMAV2 4 /* Version 2 of the Schema. */
|
||||
#define SERVERINFO_NTDS 8 /* Server is an Active Directory. */
|
||||
|
||||
@ -50,6 +50,17 @@ time_t timegm(struct tm *tm);
|
||||
#endif
|
||||
|
||||
|
||||
/* Object to keep state pertaining to this module. */
|
||||
struct ks_engine_ldap_local_s
|
||||
{
|
||||
LDAP *ldap_conn;
|
||||
LDAPMessage *message;
|
||||
LDAPMessage *msg_iter; /* Iterator for message. */
|
||||
unsigned int serverinfo;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static time_t
|
||||
ldap2epochtime (const char *timestr)
|
||||
@ -165,6 +176,45 @@ ks_ldap_help (ctrl_t ctrl, parsed_uri_t uri)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create a new empty state object. Returns NULL on error */
|
||||
static struct ks_engine_ldap_local_s *
|
||||
ks_ldap_new_state (void)
|
||||
{
|
||||
return xtrycalloc (1, sizeof(struct ks_engine_ldap_local_s));
|
||||
}
|
||||
|
||||
|
||||
/* Clear the state object STATE. Returns the STATE object. */
|
||||
static struct ks_engine_ldap_local_s *
|
||||
ks_ldap_clear_state (struct ks_engine_ldap_local_s *state)
|
||||
{
|
||||
if (state->ldap_conn)
|
||||
{
|
||||
ldap_unbind (state->ldap_conn);
|
||||
state->ldap_conn = NULL;
|
||||
}
|
||||
if (state->message)
|
||||
{
|
||||
ldap_msgfree (state->message);
|
||||
state->message = NULL;
|
||||
}
|
||||
state->serverinfo = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
/* Release a state object. */
|
||||
void
|
||||
ks_ldap_free_state (struct ks_engine_ldap_local_s *state)
|
||||
{
|
||||
if (!state)
|
||||
return;
|
||||
ks_ldap_clear_state (state);
|
||||
xfree (state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Convert a keyspec to a filter. Return an error if the keyspec is
|
||||
bad or is not supported. The filter is escaped and returned in
|
||||
@ -288,6 +338,8 @@ keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Helper for my_ldap_connect. */
|
||||
static char *
|
||||
interrogate_ldap_dn (LDAP *ldap_conn, const char *basedn_search,
|
||||
unsigned int *r_serverinfo)
|
||||
@ -874,12 +926,90 @@ no_ldap_due_to_tor (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
|
||||
/* Helper for ks_ldap_get. Returns 0 if a key was fetched and printed
|
||||
* to FP. The error code GPG_ERR_NO_DATA is returned if no key was
|
||||
* printed. Note that FP is updated by this function. */
|
||||
static gpg_error_t
|
||||
return_one_keyblock (LDAP *ldap_conn, LDAPMessage *msg, unsigned int serverinfo,
|
||||
estream_t *fp, strlist_t *seenp)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char **vals;
|
||||
char **certid;
|
||||
|
||||
/* Use the long keyid to remove duplicates. The LDAP server returns
|
||||
* the same keyid more than once if there are multiple user IDs on
|
||||
* the key. Note that this does NOT mean that a keyid that exists
|
||||
* multiple times on the keyserver will not be fetched. It means
|
||||
* that each KEY, no matter how many user IDs share its keyid, will
|
||||
* be fetched only once. If a keyid that belongs to more than one
|
||||
* key is fetched, the server quite properly responds with all
|
||||
* matching keys. -ds
|
||||
*
|
||||
* Note that in --first/--next mode we don't do any duplicate
|
||||
* detection.
|
||||
*/
|
||||
|
||||
certid = ldap_get_values (ldap_conn, msg, "pgpcertid");
|
||||
if (certid && certid[0])
|
||||
{
|
||||
if (!seenp || !strlist_find (*seenp, certid[0]))
|
||||
{
|
||||
/* It's not a duplicate, add it */
|
||||
if (seenp)
|
||||
add_to_strlist (seenp, certid[0]);
|
||||
|
||||
if (!*fp)
|
||||
{
|
||||
*fp = es_fopenmem(0, "rw");
|
||||
if (!*fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
extract_keys (*fp, ldap_conn, certid[0], msg);
|
||||
|
||||
vals = ldap_get_values (ldap_conn, msg,
|
||||
(serverinfo & SERVERINFO_PGPKEYV2)?
|
||||
"pgpKeyV2" : "pgpKey");
|
||||
if (!vals)
|
||||
{
|
||||
err = ldap_to_gpg_err (ldap_conn);
|
||||
log_error("ks-ldap: unable to retrieve key %s "
|
||||
"from keyserver\n", certid[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We should strip the new lines. */
|
||||
es_fprintf (*fp, "KEY 0x%s BEGIN\n", certid[0]);
|
||||
es_fputs (vals[0], *fp);
|
||||
es_fprintf (*fp, "\nKEY 0x%s END\n", certid[0]);
|
||||
|
||||
ldap_value_free (vals);
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
else /* Duplicate. */
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
leave:
|
||||
my_ldap_value_free (certid);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Get the key described key the KEYSPEC string from the keyserver
|
||||
identified by URI. On success R_FP has an open stream to read the
|
||||
data. */
|
||||
* identified by URI. On success R_FP has an open stream to read the
|
||||
* data. KS_GET_FLAGS conveys flags from the client. */
|
||||
gpg_error_t
|
||||
ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
|
||||
estream_t *r_fp)
|
||||
unsigned int ks_get_flags, estream_t *r_fp)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
int ldap_err;
|
||||
@ -890,7 +1020,24 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
|
||||
LDAP *ldap_conn = NULL;
|
||||
char *basedn = NULL;
|
||||
estream_t fp = NULL;
|
||||
int count;
|
||||
LDAPMessage *message = NULL;
|
||||
LDAPMessage *msg;
|
||||
int anykey = 0;
|
||||
int first_mode = 0;
|
||||
int next_mode = 0;
|
||||
strlist_t seen = NULL; /* The set of entries that we've seen. */
|
||||
/* The ordering is significant. Specifically, "pgpcertid" needs to
|
||||
* be the second item in the list, since everything after it may be
|
||||
* discarded if we aren't in verbose mode. */
|
||||
char *attrs[] =
|
||||
{
|
||||
"dummy", /* (to be be replaced.) */
|
||||
"pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
|
||||
"pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
|
||||
"gpgfingerprint",
|
||||
NULL
|
||||
};
|
||||
|
||||
(void) ctrl;
|
||||
|
||||
@ -899,143 +1046,138 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
|
||||
return no_ldap_due_to_tor (ctrl);
|
||||
}
|
||||
|
||||
/* Make sure we are talking to an OpenPGP LDAP server. */
|
||||
err = my_ldap_connect (uri, &ldap_conn,
|
||||
&basedn, &host, &use_tls, &serverinfo);
|
||||
if (err || !basedn)
|
||||
/* Make sure we got a state. */
|
||||
if ((ks_get_flags & KS_GET_FLAG_FIRST))
|
||||
{
|
||||
if (!err)
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto out;
|
||||
if (ctrl->ks_get_state)
|
||||
ks_ldap_clear_state (ctrl->ks_get_state);
|
||||
else if (!(ctrl->ks_get_state = ks_ldap_new_state ()))
|
||||
return gpg_error_from_syserror ();
|
||||
first_mode = 1;
|
||||
}
|
||||
|
||||
/* Now that we have information about the server we can construct a
|
||||
* query best suited for the capabilities of the server. */
|
||||
err = keyspec_to_ldap_filter (keyspec, &filter, 1, serverinfo);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (opt.debug)
|
||||
log_debug ("ks-ldap: using filter: %s\n", filter);
|
||||
|
||||
{
|
||||
/* The ordering is significant. Specifically, "pgpcertid" needs
|
||||
to be the second item in the list, since everything after it
|
||||
may be discarded if we aren't in verbose mode. */
|
||||
char *attrs[] =
|
||||
{
|
||||
"dummy",
|
||||
"pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
|
||||
"pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
|
||||
"gpgfingerprint",
|
||||
NULL
|
||||
};
|
||||
/* 1 if we want just attribute types; 0 if we want both attribute
|
||||
* types and values. */
|
||||
int attrsonly = 0;
|
||||
int count;
|
||||
|
||||
/* Replace "dummy". */
|
||||
attrs[0] = (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2" : "pgpKey";
|
||||
|
||||
npth_unprotect ();
|
||||
ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
|
||||
filter, attrs, attrsonly, &message);
|
||||
npth_protect ();
|
||||
if (ldap_err)
|
||||
{
|
||||
err = ldap_err_to_gpg_err (ldap_err);
|
||||
|
||||
log_error ("ks-ldap: LDAP search error: %s\n",
|
||||
ldap_err2string (ldap_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
count = ldap_count_entries (ldap_conn, message);
|
||||
if (count < 1)
|
||||
{
|
||||
log_info ("ks-ldap: key %s not found on keyserver\n", keyspec);
|
||||
|
||||
if (count == -1)
|
||||
err = ldap_to_gpg_err (ldap_conn);
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ks_get_flags & KS_GET_FLAG_NEXT))
|
||||
{
|
||||
/* There may be more than one unique result for a given keyID,
|
||||
so we should fetch them all (test this by fetching short key
|
||||
id 0xDEADBEEF). */
|
||||
if (!ctrl->ks_get_state || !ctrl->ks_get_state->ldap_conn
|
||||
|| !ctrl->ks_get_state->message)
|
||||
{
|
||||
log_error ("ks_ldap: --next requested but no state\n");
|
||||
return gpg_error (GPG_ERR_INV_STATE);
|
||||
}
|
||||
next_mode = 1;
|
||||
}
|
||||
|
||||
/* The set of entries that we've seen. */
|
||||
strlist_t seen = NULL;
|
||||
LDAPMessage *each;
|
||||
int anykey = 0;
|
||||
/* Do not keep an old state around if not needed. */
|
||||
if (!(first_mode || next_mode))
|
||||
{
|
||||
ks_ldap_free_state (ctrl->ks_get_state);
|
||||
ctrl->ks_get_state = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (next_mode)
|
||||
{
|
||||
while (ctrl->ks_get_state->msg_iter)
|
||||
{
|
||||
npth_unprotect ();
|
||||
ctrl->ks_get_state->msg_iter
|
||||
= ldap_next_entry (ctrl->ks_get_state->ldap_conn,
|
||||
ctrl->ks_get_state->msg_iter);
|
||||
npth_protect ();
|
||||
if (ctrl->ks_get_state->msg_iter)
|
||||
{
|
||||
err = return_one_keyblock (ctrl->ks_get_state->ldap_conn,
|
||||
ctrl->ks_get_state->msg_iter,
|
||||
ctrl->ks_get_state->serverinfo,
|
||||
&fp, NULL);
|
||||
if (!err)
|
||||
break; /* Found. */
|
||||
else if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||
err = 0; /* Skip empty/duplicate attributes. */
|
||||
else
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if (!ctrl->ks_get_state->msg_iter || !fp)
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
}
|
||||
else /* Not in --next mode. */
|
||||
{
|
||||
/* Make sure we are talking to an OpenPGP LDAP server. */
|
||||
err = my_ldap_connect (uri, &ldap_conn,
|
||||
&basedn, &host, &use_tls, &serverinfo);
|
||||
if (err || !basedn)
|
||||
{
|
||||
if (!err)
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Now that we have information about the server we can construct a
|
||||
* query best suited for the capabilities of the server. */
|
||||
err = keyspec_to_ldap_filter (keyspec, &filter, 1, serverinfo);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (opt.debug)
|
||||
log_debug ("ks-ldap: using filter: %s\n", filter);
|
||||
|
||||
/* Replace "dummy". */
|
||||
attrs[0] = (serverinfo & SERVERINFO_PGPKEYV2)? "pgpKeyV2" : "pgpKey";
|
||||
|
||||
npth_unprotect ();
|
||||
ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
|
||||
filter, attrs, 0, &message);
|
||||
npth_protect ();
|
||||
if (ldap_err)
|
||||
{
|
||||
err = ldap_err_to_gpg_err (ldap_err);
|
||||
|
||||
log_error ("ks-ldap: LDAP search error: %s\n",
|
||||
ldap_err2string (ldap_err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
count = ldap_count_entries (ldap_conn, message);
|
||||
if (count < 1)
|
||||
{
|
||||
log_info ("ks-ldap: key %s not found on keyserver\n", keyspec);
|
||||
|
||||
if (count == -1)
|
||||
err = ldap_to_gpg_err (ldap_conn);
|
||||
else
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
goto leave;
|
||||
}
|
||||
|
||||
for (npth_unprotect (),
|
||||
each = ldap_first_entry (ldap_conn, message),
|
||||
msg = ldap_first_entry (ldap_conn, message),
|
||||
npth_protect ();
|
||||
each;
|
||||
msg;
|
||||
npth_unprotect (),
|
||||
each = ldap_next_entry (ldap_conn, each),
|
||||
msg = ldap_next_entry (ldap_conn, msg),
|
||||
npth_protect ())
|
||||
{
|
||||
char **vals;
|
||||
char **certid;
|
||||
|
||||
/* Use the long keyid to remove duplicates. The LDAP
|
||||
server returns the same keyid more than once if there
|
||||
are multiple user IDs on the key. Note that this does
|
||||
NOT mean that a keyid that exists multiple times on the
|
||||
keyserver will not be fetched. It means that each KEY,
|
||||
no matter how many user IDs share its keyid, will be
|
||||
fetched only once. If a keyid that belongs to more
|
||||
than one key is fetched, the server quite properly
|
||||
responds with all matching keys. -ds */
|
||||
|
||||
certid = ldap_get_values (ldap_conn, each, "pgpcertid");
|
||||
if (certid && certid[0])
|
||||
{
|
||||
if (! strlist_find (seen, certid[0]))
|
||||
{
|
||||
/* It's not a duplicate, add it */
|
||||
|
||||
add_to_strlist (&seen, certid[0]);
|
||||
|
||||
if (! fp)
|
||||
fp = es_fopenmem(0, "rw");
|
||||
|
||||
extract_keys (fp, ldap_conn, certid[0], each);
|
||||
|
||||
vals = ldap_get_values (ldap_conn, each, attrs[0]);
|
||||
if (! vals)
|
||||
{
|
||||
err = ldap_to_gpg_err (ldap_conn);
|
||||
log_error("ks-ldap: unable to retrieve key %s "
|
||||
"from keyserver\n", certid[0]);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We should strip the new lines. */
|
||||
es_fprintf (fp, "KEY 0x%s BEGIN\n", certid[0]);
|
||||
es_fputs (vals[0], fp);
|
||||
es_fprintf (fp, "\nKEY 0x%s END\n", certid[0]);
|
||||
|
||||
ldap_value_free (vals);
|
||||
anykey = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my_ldap_value_free (certid);
|
||||
err = return_one_keyblock (ldap_conn, msg, serverinfo,
|
||||
&fp, first_mode? NULL : &seen);
|
||||
if (!err)
|
||||
{
|
||||
anykey = 1;
|
||||
if (first_mode)
|
||||
break;
|
||||
}
|
||||
else if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||
err = 0; /* Skip empty/duplicate attributes. */
|
||||
else
|
||||
goto leave;
|
||||
}
|
||||
|
||||
free_strlist (seen);
|
||||
if (ctrl->ks_get_state) /* Save the iterator. */
|
||||
ctrl->ks_get_state->msg_iter = msg;
|
||||
|
||||
if (! fp)
|
||||
if (!fp) /* Nothing was found. */
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
if (!err && anykey)
|
||||
@ -1043,9 +1185,27 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
|
||||
use_tls? "ldaps" : "ldap",
|
||||
host? host:"");
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
leave:
|
||||
/* Store our state if needed. */
|
||||
if (!err && (ks_get_flags & KS_GET_FLAG_FIRST))
|
||||
{
|
||||
log_assert (!ctrl->ks_get_state->ldap_conn);
|
||||
ctrl->ks_get_state->ldap_conn = ldap_conn;
|
||||
ldap_conn = NULL;
|
||||
log_assert (!ctrl->ks_get_state->message);
|
||||
ctrl->ks_get_state->message = message;
|
||||
message = NULL;
|
||||
ctrl->ks_get_state->serverinfo = serverinfo;
|
||||
}
|
||||
if ((ks_get_flags & KS_GET_FLAG_NEXT))
|
||||
{
|
||||
/* Keep the state in --next mode even with errors. */
|
||||
ldap_conn = NULL;
|
||||
message = NULL;
|
||||
}
|
||||
|
||||
if (message)
|
||||
ldap_msgfree (message);
|
||||
|
||||
@ -1062,6 +1222,7 @@ ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
|
||||
*r_fp = fp;
|
||||
}
|
||||
|
||||
free_strlist (seen);
|
||||
xfree (basedn);
|
||||
xfree (host);
|
||||
|
||||
|
@ -23,6 +23,12 @@
|
||||
|
||||
#include "http.h"
|
||||
|
||||
/* Flags for engine functions. */
|
||||
#define KS_GET_FLAG_ONLY_LDAP 1
|
||||
#define KS_GET_FLAG_FIRST 2
|
||||
#define KS_GET_FLAG_NEXT 4
|
||||
|
||||
|
||||
/*-- ks-action.c --*/
|
||||
gpg_error_t ks_print_help (ctrl_t ctrl, const char *text);
|
||||
gpg_error_t ks_printf_help (ctrl_t ctrl, const char *format,
|
||||
@ -63,10 +69,12 @@ gpg_error_t ks_kdns_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp);
|
||||
|
||||
/*-- ks-engine-ldap.c --*/
|
||||
gpg_error_t ks_ldap_help (ctrl_t ctrl, parsed_uri_t uri);
|
||||
void ks_ldap_free_state (struct ks_engine_ldap_local_s *state);
|
||||
gpg_error_t ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
estream_t *r_fp);
|
||||
gpg_error_t ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri,
|
||||
const char *keyspec, estream_t *r_fp);
|
||||
const char *keyspec, unsigned int ks_get_flags,
|
||||
estream_t *r_fp);
|
||||
gpg_error_t ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
|
||||
void *data, size_t datalen,
|
||||
void *info, size_t infolen);
|
||||
|
@ -49,7 +49,7 @@
|
||||
# include "ldap-wrapper.h"
|
||||
#endif
|
||||
#include "ks-action.h"
|
||||
#include "ks-engine.h" /* (ks_hkp_print_hosttable) */
|
||||
#include "ks-engine.h"
|
||||
#if USE_LDAP
|
||||
# include "ldap-parse-uri.h"
|
||||
#endif
|
||||
@ -2518,12 +2518,13 @@ cmd_ks_search (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_ks_get[] =
|
||||
"KS_GET [--quick] [--ldap] {<pattern>}\n"
|
||||
"KS_GET [--quick] [--ldap] [--first|--next] {<pattern>}\n"
|
||||
"\n"
|
||||
"Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
|
||||
"(see command KEYSERVER). Each pattern should be a keyid, a fingerprint,\n"
|
||||
"or an exact name indicated by the '=' prefix. Option --quick uses a\n"
|
||||
"shorter timeout; --ldap will use only ldap servers";
|
||||
"shorter timeout; --ldap will use only ldap servers. With --first only\n"
|
||||
"the first item is returned; --next is used to return the next item";
|
||||
static gpg_error_t
|
||||
cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -2532,11 +2533,16 @@ cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
strlist_t list, sl;
|
||||
char *p;
|
||||
estream_t outfp;
|
||||
int ldap_only;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (has_option (line, "--quick"))
|
||||
ctrl->timeout = opt.connect_quick_timeout;
|
||||
ldap_only = has_option (line, "--ldap");
|
||||
if (has_option (line, "--ldap"))
|
||||
flags |= KS_GET_FLAG_ONLY_LDAP;
|
||||
if (has_option (line, "--first"))
|
||||
flags |= KS_GET_FLAG_FIRST;
|
||||
if (has_option (line, "--next"))
|
||||
flags |= KS_GET_FLAG_NEXT;
|
||||
line = skip_options (line);
|
||||
|
||||
/* Break the line into a strlist. Each pattern is by
|
||||
@ -2565,6 +2571,36 @@ cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & KS_GET_FLAG_FIRST) && !(flags & KS_GET_FLAG_ONLY_LDAP))
|
||||
{
|
||||
err = PARM_ERROR ("--first is only supported with --ldap");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (list && list->next && (flags & KS_GET_FLAG_FIRST))
|
||||
{
|
||||
/* ks_action_get loops over the pattern and we can't easily keep
|
||||
* this state. */
|
||||
err = PARM_ERROR ("Only one pattern allowed with --first");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if ((flags & KS_GET_FLAG_NEXT))
|
||||
{
|
||||
if (list || (flags & ~KS_GET_FLAG_NEXT))
|
||||
{
|
||||
err = PARM_ERROR ("No pattern or other options allowed with --next");
|
||||
goto leave;
|
||||
}
|
||||
/* Add a dummy pattern. */
|
||||
if (!add_to_strlist_try (&list, ""))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
err = ensure_keyserver (ctrl);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -2579,7 +2615,7 @@ cmd_ks_get (assuan_context_t ctx, char *line)
|
||||
ctrl->server_local->inhibit_data_logging_now = 0;
|
||||
ctrl->server_local->inhibit_data_logging_count = 0;
|
||||
err = ks_action_get (ctrl, ctrl->server_local->keyservers,
|
||||
list, ldap_only, outfp);
|
||||
list, flags, outfp);
|
||||
es_fclose (outfp);
|
||||
ctrl->server_local->inhibit_data_logging = 0;
|
||||
}
|
||||
@ -3090,6 +3126,8 @@ start_command_handler (assuan_fd_t fd, unsigned int session_id)
|
||||
ctrl->refcount);
|
||||
else
|
||||
{
|
||||
ks_ldap_free_state (ctrl->ks_get_state);
|
||||
ctrl->ks_get_state = NULL;
|
||||
release_ctrl_ocsp_certs (ctrl);
|
||||
xfree (ctrl->server_local);
|
||||
dirmngr_deinit_default_ctrl (ctrl);
|
||||
|
Loading…
x
Reference in New Issue
Block a user