diff options
author | Werner Koch <[email protected]> | 2023-03-20 18:24:49 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2023-03-20 18:24:49 +0000 |
commit | 625aeb65b0e75192a414fdca5383cb67c996adee (patch) | |
tree | 13a75292066d048617f426e391218180950ecd53 /dirmngr/ks-action.c | |
parent | dirmngr: Add framework to implement a fake CRL feature. (diff) | |
download | gnupg-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.c | 145 |
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 +} |