Greetings.
This command fails in an unexpected way:
% ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)' Could not parse LDAP URI(s)=ldap:///dc=example,dc=net (3)
It appears that ldapsearch wants me to escape the '=' and ',' in that URI:
% ldapsearch -x -H 'ldap:///dc%3dexample%2cdc%3dnet' '(cn=foo)' DNS SRV: Could not turn domain=example.net into a hostlist
But why? The manpage for ldapsearch says
-HÂ ldapuri Specify URI(s) referring to the ldap server(s); a list of URI, separated by whitespace or commas is expected; only the protocol/host/port fields are allowed. As an exception, if no host/port is specified, but a DN is, the DN is used to look up the corresponding host(s) using the DNS SRV records, according to RFC 2782. The DN must be a non-empty sequence of AVAs whose attribute type is "dc" (domain component), and must be escaped according to RFC 2396.
I read that as clearly saying (via the 'exception' branch of that paragraph) that the first -H argument is correct.
RFC digression:
According to RFC 2396, the /dc... is `"/" path_segments`, segments are composed of *pchar, and
pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
...which includes both '=' and ','. Thus those characters don't need to be escaped, by RFC 2396. Or, put another way, 'ldap:///dc=example,dc=net' _is_ escaped according to RFC2396, in the sense that nothing in it needs to be escaped.
Looking instead at RFC 4516, the 'dn' in the 'ldapurl' is a 'distinguishedName' from RFC 4514 which (Sect.3) permits '=' and ',' to be included. Sect.2.1 of 4516 requires that the URI must include <reserved>, <unreserved> or <pct-encoded> of RFC 3986, but if we look at that, then Sect.2.2 indicates that <reserved> includes both '=' and ','.
Thus the behaviour of ldapsearch, when parsing the -H option, doesn't appear to match the documentation.
Explanation:
Looking at common.c:tool_args and common.c line 1199, I see that it calls ldap_url_parselist to break the -H argument into a list of URIs, and this will separate dc=example,dc=net at the comma. And sure enough, in practice it's only the ',' that has to be escaped by %2c.
I believe this behaviour doesn't match the manpage, which (clearly in my reading of it) requires either a list of protocol/host/port URIs OR (the exception) a single URI containing no host/port but only a DN. That suggests that common.c:tool_args has to detect that exception/second case. Apart from the documentation issue, having to escape commas is both repeatedly surprising and a pain in the neck on the occasions when I want to use the dc=... syntax with ldapsearch.
Re detecting that exception, searching for "///" in the ldapuri string would seem to be sufficient, and calling ldap_url_parselist_int in that case (instead of ldap_url_parselist) with a sep argument of " " looks like it would do the job with a minimal change to the code.
Best wishes,
Norman
Hi,
Just guessing by the error message, but your DNS Server does have a valid service record for that Base DN? As the error message suggests otherwise, but I may as well be completely off here.
Otherwise, but I am sure you know that, with only two "/" you can alway use the hostname, in case the DNS serive record is missing:
ldapsearch -H ldap://server.example.net -b dc=example,dc=net" 'cn=foo'
Am 10.02.23 um 17:51 schrieb Norman Gray:
Greetings.
This command fails in an unexpected way:
% ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)' Could not parse LDAP URI(s)=ldap:///dc=example,dc=net (3)
It appears that ldapsearch wants me to escape the '=' and ',' in that URI:
% ldapsearch -x -H 'ldap:///dc%3dexample%2cdc%3dnet' '(cn=foo)' DNS SRV: Could not turn domain=example.net into a hostlist
But why? The manpage for ldapsearch says
-HÂ ldapuri Specify URI(s) referring to the ldap server(s); a list of URI, separated by whitespace or commas is expected; only the protocol/host/port fields are allowed. As an exception, if no host/port is specified, but a DN is, the DN is used to look up the corresponding host(s) using the DNS SRV records, according to RFC 2782. The DN must be a non-empty sequence of AVAs whose attribute type is "dc" (domain component), and must be escaped according to RFC 2396.
I read that as clearly saying (via the 'exception' branch of that paragraph) that the first -H argument is correct.
RFC digression:
According to RFC 2396, the /dc... is `"/" path_segments`, segments are composed of *pchar, and
pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
...which includes both '=' and ','. Thus those characters don't need to be escaped, by RFC 2396. Or, put another way, 'ldap:///dc=example,dc=net' _is_ escaped according to RFC2396, in the sense that nothing in it needs to be escaped.
Looking instead at RFC 4516, the 'dn' in the 'ldapurl' is a 'distinguishedName' from RFC 4514 which (Sect.3) permits '=' and ',' to be included. Sect.2.1 of 4516 requires that the URI must include <reserved>, <unreserved> or <pct-encoded> of RFC 3986, but if we look at that, then Sect.2.2 indicates that <reserved> includes both '=' and ','.
Thus the behaviour of ldapsearch, when parsing the -H option, doesn't appear to match the documentation.
Explanation:
Looking at common.c:tool_args and common.c line 1199, I see that it calls ldap_url_parselist to break the -H argument into a list of URIs, and this will separate dc=example,dc=net at the comma. And sure enough, in practice it's only the ',' that has to be escaped by %2c.
I believe this behaviour doesn't match the manpage, which (clearly in my reading of it) requires either a list of protocol/host/port URIs OR (the exception) a single URI containing no host/port but only a DN. That suggests that common.c:tool_args has to detect that exception/second case. Apart from the documentation issue, having to escape commas is both repeatedly surprising and a pain in the neck on the occasions when I want to use the dc=... syntax with ldapsearch.
Re detecting that exception, searching for "///" in the ldapuri string would seem to be sufficient, and calling ldap_url_parselist_int in that case (instead of ldap_url_parselist) with a sep argument of " " looks like it would do the job with a minimal change to the code.
Best wishes,
Norman
Ede, hello.
On 20 Feb 2023, at 12:49, Ede Wolf wrote:
Just guessing by the error message, but your DNS Server does have a valid service record for that Base DN? As the error message suggests otherwise, but I may as well be completely off here.
A good thought -- thanks -- but yes, the SRV records are set up correctly, and I can make the query if the ',' in the dc= list are escaped (even though RFC 2396 doesn't require that).
Otherwise, but I am sure you know that, with only two "/" you can alway use the hostname, in case the DNS serive record is missing:
ldapsearch -H ldap://server.example.net -b dc=example,dc=net" 'cn=foo'
Indeed, and that's what I do most of the time. In fact, this is a case where a sequence of host+port LDAP URIs is useful.
Best wishes,
Norman
Norman,
did you try to provide a hostname in the URI?
ldapsearch -x -H 'ldap://<HOST>/dc=example,dc=net' '(cn=foo)'
instead of
ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)'
?
Regards,
Uwe
Am 20.02.23 um 14:19 schrieb Norman Gray:
Ede, hello.
On 20 Feb 2023, at 12:49, Ede Wolf wrote:
Just guessing by the error message, but your DNS Server does have a valid service record for that Base DN? As the error message suggests otherwise, but I may as well be completely off here.
A good thought -- thanks -- but yes, the SRV records are set up correctly, and I can make the query if the ',' in the dc= list are escaped (even though RFC 2396 doesn't require that).
Otherwise, but I am sure you know that, with only two "/" you can alway use the hostname, in case the DNS serive record is missing:
ldapsearch -H ldap://server.example.net -b dc=example,dc=net" 'cn=foo'
Indeed, and that's what I do most of the time. In fact, this is a case where a sequence of host+port LDAP URIs is useful.
Best wishes,
Norman
Uwe, helllo.
On 20 Feb 2023, at 13:28, Uwe Sauter wrote:
ldapsearch -x -H 'ldap://<HOST>/dc=example,dc=net' '(cn=foo)'
instead of
ldapsearch -x -H 'ldap:///dc=example,dc=net' '(cn=foo)'
No: the documentation for the -H option says that the SRV-lookup form, with the dc= components, is only tried when the host:port element of the URI is empty.
Looking at the code, the problem does appear to be that common.c:tool_args attempts to break the -H argument into multiple LDAP URIs by separating at commas, as well as spaces. That's the right thing to do to match the first sentence of the ldapsearch(1) documentation of -H, but the second sentence there (the one starting 'As an exception...') doesn't mention a list of SRV names (sensibly, since an SRV record is implicitly a list anyway), so shouldn't, I think, attempt to split the argument.
As the code stands, you have to escape the ',' in order to trick the code into not splitting this argument.
I noted in the OP that there's a mild code change which would make this work as expected.
I'm raise this as a bugreport with suggested fix, since it doesn't sound from this discussion that there's something obvious I'm missing.
Best wishes,
Norman
openldap-technical@openldap.org