Skip to content

Commit 0605bb3

Browse files
author
iinuwa
authored
Allow disabling LDAP referral chasing on Linux. (#54380)
* Allow disabling LDAP referral chasing on Linux. Before this, changing SessionOptions.ReferralChasing on Linux was ineffective, since we were passing `ref int` to OpenLDAP, which does not follow the pointer passed and interprets any non-zero value as "enabled". This passes a boolean directly instead, which the library is able to detect properly. * fixup! Allow disabling LDAP referral chasing on Linux. * fixup! Allow disabling LDAP referral chasing on Linux. * fixup! Allow disabling LDAP referral chasing on Linux. * fixup! Allow disabling LDAP referral chasing on Linux.
1 parent fe9a54d commit 0605bb3

File tree

7 files changed

+98
-21
lines changed

7 files changed

+98
-21
lines changed

src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ static Ldap()
8585
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_dn", CharSet = CharSet.Ansi)]
8686
public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result);
8787

88+
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
89+
public static extern int ldap_get_option_bool([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref bool outValue);
90+
8891
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
8992
public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue);
9093

@@ -112,6 +115,9 @@ static Ldap()
112115
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_search_ext", CharSet = CharSet.Ansi)]
113116
public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber);
114117

118+
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi, SetLastError = true)]
119+
public static extern int ldap_set_option_bool([In] ConnectionHandle ld, [In] LdapOption option, bool value);
120+
115121
[DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)]
116122
public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue);
117123

src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -492,4 +492,7 @@
492492
<data name="QuotaControlNotSupported" xml:space="preserve">
493493
<value>System.DirectoryServices.Protocols.QuotaControl is not supported on this platform.</value>
494494
</data>
495+
<data name="ReferralChasingOptionsNotSupported" xml:space="preserve">
496+
<value>Only ReferralChasingOptions.None and ReferralChasingOptions.All are supported on Linux.</value>
497+
</data>
495498
</root>

src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ internal static int GetLastErrorFromConnection(ConnectionHandle ldapHandle)
4141
return result;
4242
}
4343

44+
internal static int GetBoolOption(ConnectionHandle ldapHandle, LdapOption option, ref bool outValue) => Interop.Ldap.ldap_get_option_bool(ldapHandle, option, ref outValue);
45+
4446
internal static int GetIntOption(ConnectionHandle ldapHandle, LdapOption option, ref int outValue) => Interop.Ldap.ldap_get_option_int(ldapHandle, option, ref outValue);
4547

4648
internal static int GetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr outValue) => Interop.Ldap.ldap_get_option_ptr(ldapHandle, option, ref outValue);
@@ -85,6 +87,8 @@ internal static int RenameDirectoryEntry(ConnectionHandle ldapHandle, string dn,
8587
internal static int SearchDirectory(ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber) =>
8688
Interop.Ldap.ldap_search(ldapHandle, dn, scope, filter, attributes, attributeOnly, servercontrol, clientcontrol, timelimit, sizelimit, ref messageNumber);
8789

90+
internal static int SetBoolOption(ConnectionHandle ld, LdapOption option, bool value) => Interop.Ldap.ldap_set_option_bool(ld, option, value);
91+
8892
// This option is not supported in Linux, so it would most likely throw.
8993
internal static int SetClientCertOption(ConnectionHandle ldapHandle, LdapOption option, QUERYCLIENTCERT outValue) => Interop.Ldap.ldap_set_option_clientcert(ldapHandle, option, outValue);
9094

src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Runtime.Versioning;
4+
using System.ComponentModel;
55

66
namespace System.DirectoryServices.Protocols
77
{
@@ -30,5 +30,52 @@ public int ProtocolVersion
3030
get => GetPtrValueHelper(LdapOption.LDAP_OPT_VERSION).ToInt32();
3131
set => SetPtrValueHelper(LdapOption.LDAP_OPT_VERSION, new IntPtr(value));
3232
}
33+
34+
public ReferralChasingOptions ReferralChasing
35+
{
36+
get
37+
{
38+
return GetBoolValueHelper(LdapOption.LDAP_OPT_REFERRALS) ? ReferralChasingOptions.All : ReferralChasingOptions.None;
39+
}
40+
set
41+
{
42+
if (((value) & (~ReferralChasingOptions.All)) != 0)
43+
{
44+
throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(ReferralChasingOptions));
45+
}
46+
if (value != ReferralChasingOptions.None && value != ReferralChasingOptions.All)
47+
{
48+
throw new PlatformNotSupportedException(SR.ReferralChasingOptionsNotSupported);
49+
}
50+
51+
SetBoolValueHelper(LdapOption.LDAP_OPT_REFERRALS, value == ReferralChasingOptions.All);
52+
}
53+
}
54+
55+
private bool GetBoolValueHelper(LdapOption option)
56+
{
57+
if (_connection._disposed)
58+
{
59+
throw new ObjectDisposedException(GetType().Name);
60+
}
61+
62+
bool outValue = false;
63+
int error = LdapPal.GetBoolOption(_connection._ldapHandle, option, ref outValue);
64+
ErrorChecking.CheckAndSetLdapError(error);
65+
66+
return outValue;
67+
}
68+
69+
private void SetBoolValueHelper(LdapOption option, bool value)
70+
{
71+
if (_connection._disposed)
72+
{
73+
throw new ObjectDisposedException(GetType().Name);
74+
}
75+
76+
int error = LdapPal.SetBoolOption(_connection._ldapHandle, option, value);
77+
78+
ErrorChecking.CheckAndSetLdapError(error);
79+
}
3380
}
3481
}

src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.ComponentModel;
45
using System.Runtime.Versioning;
56

67
namespace System.DirectoryServices.Protocols
@@ -28,5 +29,23 @@ public int ProtocolVersion
2829
get => GetIntValueHelper(LdapOption.LDAP_OPT_VERSION);
2930
set => SetIntValueHelper(LdapOption.LDAP_OPT_VERSION, value);
3031
}
32+
33+
public ReferralChasingOptions ReferralChasing
34+
{
35+
get
36+
{
37+
int result = GetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS);
38+
return result == 1 ? ReferralChasingOptions.All : (ReferralChasingOptions)result;
39+
}
40+
set
41+
{
42+
if (((value) & (~ReferralChasingOptions.All)) != 0)
43+
{
44+
throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(ReferralChasingOptions));
45+
}
46+
47+
SetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS, (int)value);
48+
}
49+
}
3150
}
3251
}

src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,6 @@ internal LdapSessionOptions(LdapConnection connection)
136136
_serverCertificateRoutine = new VERIFYSERVERCERT(ProcessServerCertificate);
137137
}
138138

139-
public ReferralChasingOptions ReferralChasing
140-
{
141-
get
142-
{
143-
int result = GetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS);
144-
return result == 1 ? ReferralChasingOptions.All : (ReferralChasingOptions)result;
145-
}
146-
set
147-
{
148-
if (((value) & (~ReferralChasingOptions.All)) != 0)
149-
{
150-
throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(ReferralChasingOptions));
151-
}
152-
153-
SetIntValueHelper(LdapOption.LDAP_OPT_REFERRALS, (int)value);
154-
}
155-
}
156-
157139
public int ReferralHopLimit
158140
{
159141
get => GetIntValueHelper(LdapOption.LDAP_OPT_REFERRAL_HOP_LIMIT);

src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,23 @@ public class LdapSessionOptionsTests
1414
[PlatformSpecific(TestPlatforms.Windows)]
1515
[InlineData(ReferralChasingOptions.None)]
1616
[InlineData(ReferralChasingOptions.External)]
17-
public void ReferralChasing_Set_GetReturnsExpected(ReferralChasingOptions value)
17+
public void ReferralChasing_Set_GetReturnsExpected_On_Windows(ReferralChasingOptions value)
18+
{
19+
using (var connection = new LdapConnection("server"))
20+
{
21+
LdapSessionOptions options = connection.SessionOptions;
22+
Assert.Equal(ReferralChasingOptions.All, options.ReferralChasing);
23+
24+
options.ReferralChasing = value;
25+
Assert.Equal(value, options.ReferralChasing);
26+
}
27+
}
28+
29+
[Theory]
30+
[PlatformSpecific(TestPlatforms.Linux)]
31+
[InlineData(ReferralChasingOptions.None)]
32+
[InlineData(ReferralChasingOptions.All)]
33+
public void ReferralChasing_Set_GetReturnsExpected_On_Linux(ReferralChasingOptions value)
1834
{
1935
using (var connection = new LdapConnection("server"))
2036
{

0 commit comments

Comments
 (0)