aboutsummaryrefslogtreecommitdiffstats
path: root/dirmngr/ks-action.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2023-03-20 18:24:49 +0000
committerWerner Koch <[email protected]>2023-03-20 18:24:49 +0000
commit625aeb65b0e75192a414fdca5383cb67c996adee (patch)
tree13a75292066d048617f426e391218180950ecd53 /dirmngr/ks-action.c
parentdirmngr: Add framework to implement a fake CRL feature. (diff)
downloadgnupg-625aeb65b0e75192a414fdca5383cb67c996adee.tar.gz
gnupg-625aeb65b0e75192a414fdca5383cb67c996adee.zip
dirmngr: New command AD_QUERY.
* dirmngr/dirmngr.h: Include name-value.h (struct server_control_s): Add rootdse and rootdse_tried. * dirmngr/dirmngr.c (dirmngr_deinit_default_ctrl): Release them. * dirmngr/ks-engine.h (KS_GET_FLAG_ROOTDSE): Add two new flags. * dirmngr/ks-engine-ldap.c: Include ks-action.h (SERVERINFO_GENERIC): New. (struct ks_engine_ldap_local_s): Add scope. (ks_ldap_new_state): Set a default scope. (ks_ldap_clear_state): Ditto. (my_ldap_connect): Add flag generic. (return_all_attributes): New. (fetch_rootdse): New. (basedn_from_rootdse): New. (ks_ldap_get): Move some code out to ... (ks_ldap_prepare_my_state): New. (ks_ldap_query): New. * dirmngr/ks-action.c (ks_action_parse_uri): Factored out from server.c (ks_action_query): New. * dirmngr/server.c (make_keyserver_item): Factored most code out to ks_action_parse_uri. (cmd_ad_query): New. -- This command allows to query the Windows Active directory.
Diffstat (limited to 'dirmngr/ks-action.c')
-rw-r--r--dirmngr/ks-action.c145
1 files changed, 144 insertions, 1 deletions
diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c
index 7de4a3b95..6b5f78f49 100644
--- a/dirmngr/ks-action.c
+++ b/dirmngr/ks-action.c
@@ -34,6 +34,100 @@
# include "ldap-parse-uri.h"
#endif
+
+/* Parse an URI and store it in a new parsed URI item object which is
+ * returned at R_PARSEDURI (with its next set to NULL). On error an
+ * error code is returned an NULL stored at R_PARSEDITEM. */
+gpg_error_t
+ks_action_parse_uri (const char *uri, uri_item_t *r_parseduri)
+{
+ gpg_error_t err;
+ uri_item_t item;
+ char *tmpstr = NULL;
+#if USE_LDAP
+ const char *s;
+#endif
+
+ *r_parseduri = NULL;
+
+ if (!uri)
+ return gpg_error (GPG_ERR_INV_URI);
+
+ item = xtrymalloc (sizeof *item + strlen (uri));
+ if (!item)
+ return gpg_error_from_syserror ();
+
+ item->next = NULL;
+ item->parsed_uri = NULL;
+ strcpy (item->uri, uri);
+
+#if USE_LDAP
+ if (!strncmp (uri, "ldap:", 5) && !(uri[5] == '/' && uri[6] == '/'))
+ {
+ /* Special ldap scheme given. This differs from a valid ldap
+ * scheme in that no double slash follows. We use
+ * http_parse_uri to put it as opaque value into parsed_uri. */
+ tmpstr = strconcat ("opaque:", uri+5, NULL);
+ if (!tmpstr)
+ err = gpg_error_from_syserror ();
+ else
+ err = http_parse_uri (&item->parsed_uri, tmpstr, 0);
+ }
+ else if ((s=strchr (uri, ':')) && !(s[1] == '/' && s[2] == '/'))
+ {
+ /* No valid scheme given. We use http_parse_uri to put the
+ * string as opaque value into parsed_uri. */
+ tmpstr = strconcat ("opaque:", uri, NULL);
+ if (!tmpstr)
+ err = gpg_error_from_syserror ();
+ else
+ err = http_parse_uri (&item->parsed_uri, tmpstr, 0);
+ }
+ else if (ldap_uri_p (uri))
+ {
+ int fixup = 0;
+ /* Fixme: We should get rid of that parser and replace it with
+ * our generic (http) URI parser. */
+
+ /* If no port has been specified and the scheme ist ldaps we use
+ * our idea of the default port because the standard LDAP URL
+ * parser would use 636 here. This is because we redefined
+ * ldaps to mean starttls. */
+#ifdef HAVE_W32_SYSTEM
+ if (!strcmp (uri, "ldap:///"))
+ fixup = 1;
+ else
+#endif
+ if (!http_parse_uri (&item->parsed_uri,uri,HTTP_PARSE_NO_SCHEME_CHECK))
+ {
+ if (!item->parsed_uri->port
+ && !strcmp (item->parsed_uri->scheme, "ldaps"))
+ fixup = 2;
+ http_release_parsed_uri (item->parsed_uri);
+ item->parsed_uri = NULL;
+ }
+
+ err = ldap_parse_uri (&item->parsed_uri, uri);
+ if (!err && fixup == 1)
+ item->parsed_uri->ad_current = 1;
+ else if (!err && fixup == 2)
+ item->parsed_uri->port = 389;
+ }
+ else
+#endif /* USE_LDAP */
+ {
+ err = http_parse_uri (&item->parsed_uri, uri, HTTP_PARSE_NO_SCHEME_CHECK);
+ }
+
+ xfree (tmpstr);
+ if (err)
+ xfree (item);
+ else
+ *r_parseduri = item;
+ return err;
+}
+
+
/* Called by the engine's help functions to print the actual help. */
gpg_error_t
ks_print_help (ctrl_t ctrl, const char *text)
@@ -270,7 +364,7 @@ ks_action_get (ctrl_t ctrl, uri_item_t keyservers,
|| strcmp (uri->parsed_uri->scheme, "https") == 0);
int is_ldap = 0;
- if ((ks_get_flags & KS_GET_FLAG_ONLY_LDAP))
+ if ((ks_get_flags & (KS_GET_FLAG_ONLY_LDAP|KS_GET_FLAG_ONLY_AD)))
is_hkp_s = is_http_s = 0;
#if USE_LDAP
@@ -448,3 +542,52 @@ ks_action_put (ctrl_t ctrl, uri_item_t keyservers,
err = first_err;
return err;
}
+
+
+
+/* Query the default LDAP server or the one given by URL using
+ * the filter expression FILTER. Write the result to OUTFP. */
+gpg_error_t
+ks_action_query (ctrl_t ctrl, const char *url, unsigned int ks_get_flags,
+ const char *filter, char **attrs, estream_t outfp)
+{
+#if USE_LDAP
+ gpg_error_t err;
+ estream_t infp = NULL;
+ uri_item_t puri; /* The broken down URI (only one item used). */
+
+ if (!url && (ks_get_flags & KS_GET_FLAG_ROOTDSE))
+ url = "ldap://";
+
+ err = ks_action_parse_uri (url, &puri);
+ if (err)
+ return err;
+
+ if ((ks_get_flags & KS_GET_FLAG_ROOTDSE))
+ {
+ /* Reset authentication for a serverless connection. */
+ puri->parsed_uri->ad_current = 0;
+ puri->parsed_uri->auth = NULL;
+ }
+
+ if (!strcmp (puri->parsed_uri->scheme, "ldap")
+ || !strcmp (puri->parsed_uri->scheme, "ldaps")
+ || !strcmp (puri->parsed_uri->scheme, "ldapi")
+ || puri->parsed_uri->opaque)
+ {
+ err = ks_ldap_query (ctrl, puri->parsed_uri, ks_get_flags, filter,
+ attrs, &infp);
+ if (!err)
+ err = copy_stream (infp, outfp);
+ }
+ else
+ err = gpg_error (GPG_ERR_CONFIGURATION); /* No LDAP server known. */
+
+ es_fclose (infp);
+ release_uri_item_list (puri);
+ return err;
+
+#else /* !USE_LDAP */
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif
+}