diff options
Diffstat (limited to 'dirmngr/ks-action.c')
-rw-r--r-- | dirmngr/ks-action.c | 151 |
1 files changed, 148 insertions, 3 deletions
diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c index edf4ca5..ad200ec 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) @@ -241,7 +335,8 @@ 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, unsigned int ks_get_flags, estream_t outfp) + strlist_t patterns, unsigned int ks_get_flags, + gnupg_isotime_t newer, estream_t outfp) { gpg_error_t err = 0; gpg_error_t first_err = 0; @@ -268,7 +363,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 @@ -286,7 +381,7 @@ 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, ks_get_flags, - &infp); + newer, &infp); else #endif if (is_hkp_s) @@ -446,3 +541,53 @@ 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, + gnupg_isotime_t newer, 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, newer, &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 +} |