Métricas do repositório
- Stars
- (17.886 stars)
- Métricas de merge de PR
- (Mesclagem média 12d 11h) (661 fundiu PRs em 30d)
Description
The System.DirectoryServices.Protocols API for setting referral callbacks aligns with how the Windows LDAP library works, but . This prevents consumers to use LDAP referrals on Linux. See below for more analysis:
Originally posted by @makrattaur in https://github.com/dotnet/runtime/issues/44826#issuecomment-777963933
Hi, I am also running into this issue and I am able to reproduce with ldapsearch. I am using Microsoft Active Directory as the LDAP server (which has the behaviour described).
I have changed the query so it returns one match and one property only so the ldapsearch output is shorter.
On any other DN other than the base DN, the result looks like this:
$ ldapsearch -o ldif-wrap=no -H ldap://contoso.com -b 'CN=Users,DC=contoso,DC=com' '(sAMAccountName=Administrator)' 'name'
SASL/GSS-SPNEGO authentication started
SASL username: johndoe@contoso.com
SASL SSF: 256
SASL data security layer installed.
# extended LDIF
#
# LDAPv3
# base <CN=Users,DC=contoso,DC=com> with scope subtree
# filter: (sAMAccountName=Administrator)
# requesting: name
#
# Administrator, Users, contoso.com
dn: CN=Administrator,CN=Users,DC=contoso,DC=com
name: Administrator
# search result
search: 3
result: 0 Success
# numResponses: 2
# numEntries: 1
But on the root DN, the result looks like this:
$ ldapsearch -o ldif-wrap=no -H ldap://contoso.com -b 'DC=contoso,DC=com' '(sAMAccountName=Administrator)' 'name'
SASL/GSS-SPNEGO authentication started
SASL username: johndoe@contoso.com
SASL SSF: 256
SASL data security layer installed.
# extended LDIF
#
# LDAPv3
# base <DC=contoso,DC=com> with scope subtree
# filter: (sAMAccountName=Administrator)
# requesting: name
#
# Administrator, Users, contoso.com
dn: CN=Administrator,CN=Users,DC=contoso,DC=com
name: Administrator
# search reference
ref: ldap://ForestDnsZones.contoso.com/DC=ForestDnsZones,DC=contoso,DC=com
# search reference
ref: ldap://DomainDnsZones.contoso.com/DC=DomainDnsZones,DC=contoso,DC=com
# search reference
ref: ldap://contoso.com/CN=Configuration,DC=contoso,DC=com
# search result
search: 3
result: 0 Success
# numResponses: 5
# numEntries: 1
# numReferences: 3
The difference between the two is that referrals are returned.
They can be also seen in the first comment in this issue after the line Response.Error Message: Referral: in the exception details, ForestDnsZones and DomainDnsZones are usually Active Directory specific.
By default, ldapsearch does not follow referrals, the option -C enables referral following:
$ ldapsearch -C -o ldif-wrap=no -H ldap://contoso.com -b 'DC=contoso,DC=com' '(sAMAccountName=Administrator)' 'name'
SASL/GSS-SPNEGO authentication started
SASL username: johndoe@contoso.com
SASL SSF: 256
SASL data security layer installed.
# extended LDIF
#
# LDAPv3
# base <DC=contoso,DC=com> with scope subtree
# filter: (sAMAccountName=Administrator)
# requesting: name
#
# Administrator, Users, contoso.com
dn: CN=Administrator,CN=Users,DC=contoso,DC=com
name: Administrator
# search reference
ref: ldap://ForestDnsZones.contoso.com/DC=ForestDnsZones,DC=contoso,DC=com
# search reference
ref: ldap://contoso.com/CN=Configuration,DC=contoso,DC=com
# search reference
ref: ldap://DomainDnsZones.contoso.com/DC=DomainDnsZones,DC=contoso,DC=com
# search reference
ref: ldap://contoso.com/CN=Schema,CN=Configuration,DC=contoso,DC=com
# search result
search: 3
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090A7D, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v3839
# numResponses: 6
# numEntries: 1
# numReferences: 4
So I can get the operation error using ldapsearch. (The option is in fact obsolete, see here, it's not documented)
Trying to understand what is happening, I turned on debug logging for ldapsearch (-d 1), indicated a SASL mechanism so it's easier to see in the debug log (-Y GSSAPI), redirected the debug log to stdout and filtered the output with grep -B 10 -A 5 ldap_pvt_connect.
I get the following output:
$ ldapsearch -C -d 1 -o ldif-wrap=no -Y GSSAPI -H ldap://contoso.com -b 'DC=contoso,DC=com' -s subtree '(sAMAccountName=Administrator)' 'name' 2>&1 | grep -B 10 -A 5 ldap_pvt_connect
ldap_create
ldap_url_parse_ext(ldap://contoso.com:389/??base)
ldap_sasl_interactive_bind: user selected: GSSAPI
ldap_int_sasl_bind: GSSAPI
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP contoso.com:389
ldap_new_socket: 3
ldap_prepare_socket: 3
ldap_connect_to_host: Trying 10.10.10.42:389
ldap_pvt_connect: fd: 3 tm: -1 async: 0
attempting to connect:
connect success
ldap_int_sasl_open: host=dc1.contoso.com
SASL/GSSAPI authentication started
ldap_sasl_bind
--
ber_scanf fmt ({it) ber:
ber_scanf fmt ({me) ber:
ldap_chase_v3referral: msgid 4, url "ldap://ForestDnsZones.contoso.com/DC=ForestDnsZones,DC=contoso,DC=com"
ldap_send_server_request
ldap_new_connection 0 1 1
ldap_int_open_connection
ldap_connect_to_host: TCP ForestDnsZones.contoso.com:389
ldap_new_socket: 5
ldap_prepare_socket: 5
ldap_connect_to_host: Trying 10.10.10.42:389
ldap_pvt_connect: fd: 5 tm: -1 async: 0
attempting to connect:
connect success
anonymous rebind via ldap_sasl_bind("")
ldap_sasl_bind
ldap_send_initial_request
--
ber_scanf fmt ({it) ber:
ber_scanf fmt ({me) ber:
ldap_chase_v3referral: msgid 4, url "ldap://DomainDnsZones.contoso.com/DC=DomainDnsZones,DC=contoso,DC=com"
ldap_send_server_request
ldap_new_connection 0 1 1
ldap_int_open_connection
ldap_connect_to_host: TCP DomainDnsZones.contoso.com:389
ldap_new_socket: 6
ldap_prepare_socket: 6
ldap_connect_to_host: Trying 10.10.10.42:389
ldap_pvt_connect: fd: 6 tm: -1 async: 0
attempting to connect:
connect success
anonymous rebind via ldap_sasl_bind("")
ldap_sasl_bind
ldap_send_initial_request
OpenLDAP seems to follow referrals unauthenticated by default and Active Directory seems to accept the anonymous bind done in this case but gives an error on the first request done on the connection (the errors are further in the output but mixed together).
Callbacks are set with LdapConnection.SessionOptions.ReferralCallback and this property contains three delegates which match the ones in the structure LDAP_REFERRAL_CALLBACK (see here) and the structure is passed to ldap_set_option with LDAP_OPT_REFERRAL_CALLBACK to set them on a LDAP connection object.
But OpenLDAP does not support this structure and option, it only has one callback which is set with ldap_set_rebind_proc and is for rebinds only, there is no multiple callbacks, so setting the property causes a LDAP exception when checking the error code of ldap_set_option.