Skip to content

Commit 510c98b

Browse files
committed
Add support for setting CertificateDirectory
1 parent becfc21 commit 510c98b

File tree

9 files changed

+110
-12
lines changed

9 files changed

+110
-12
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ internal enum LdapOption
157157
LDAP_OPT_ROOTDSE_CACHE = 0x9a, // Not Supported in Linux
158158
LDAP_OPT_DEBUG_LEVEL = 0x5001,
159159
LDAP_OPT_URI = 0x5006, // Not Supported in Windows
160+
LDAP_OPT_X_TLS_CACERTDIR = 0x6003, // Not Supported in Windows
161+
LDAP_OPT_X_TLS_NEWCTX = 0x600F, // Not Supported in Windows
160162
LDAP_OPT_X_SASL_REALM = 0x6101,
161163
LDAP_OPT_X_SASL_AUTHCID = 0x6102,
162164
LDAP_OPT_X_SASL_AUTHZID = 0x6103

src/libraries/Common/tests/System/DirectoryServices/LDAP.Configuration.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ To ship, we should test on both an Active Directory LDAP server, and at least on
66

77
When testing with later of versions of LDAP, the ldapsearch commands below may need to use
88

9-
-H ldap://localhost:<PORT>
9+
-H ldap://localhost:YOURPORT
1010

1111
instead of
1212

13-
-h localhost -p <PORT>
13+
-h localhost -p YOURPORT
1414

1515
OPENDJ SERVER
1616
=============

src/libraries/System.DirectoryServices.Protocols/ref/System.DirectoryServices.Protocols.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ public partial class LdapSessionOptions
382382
internal LdapSessionOptions() { }
383383
public bool AutoReconnect { get { throw null; } set { } }
384384
public string DomainName { get { throw null; } set { } }
385+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
386+
public string CertificateDirectory { get { throw null; } set { } }
385387
public string HostName { get { throw null; } set { } }
386388
public bool HostReachable { get { throw null; } }
387389
public System.DirectoryServices.Protocols.LocatorFlags LocatorFlag { get { throw null; } set { } }
@@ -402,6 +404,8 @@ internal LdapSessionOptions() { }
402404
public bool Signing { get { throw null; } set { } }
403405
public System.DirectoryServices.Protocols.SecurityPackageContextConnectionInformation SslInformation { get { throw null; } }
404406
public int SspiFlag { get { throw null; } set { } }
407+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
408+
public void StartNewTlsSessionContext() { }
405409
public bool TcpKeepAlive { get { throw null; } set { } }
406410
public System.DirectoryServices.Protocols.VerifyServerCertificateCallback VerifyServerCertificate { get { throw null; } set { } }
407411
public void FastConcurrentBind() { }

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,13 +955,13 @@ private unsafe Interop.BOOL ProcessClientCertificate(IntPtr ldapHandle, IntPtr C
955955

956956
private void Connect()
957957
{
958-
//Ccurrently ldap does not accept more than one certificate.
958+
// Currently ldap does not accept more than one certificate.
959959
if (ClientCertificates.Count > 1)
960960
{
961961
throw new InvalidOperationException(SR.InvalidClientCertificates);
962962
}
963963

964-
// Set the certificate callback routine here if user adds the certifcate to the certificate collection.
964+
// Set the certificate callback routine here if user adds the certificate to the certificate collection.
965965
if (ClientCertificates.Count != 0)
966966
{
967967
int certError = LdapPal.SetClientCertOption(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine);

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ public partial class LdapSessionOptions
1111

1212
private bool _secureSocketLayer;
1313

14+
/// <summary>
15+
/// Specifies the path of the directory containing CA certificates.
16+
/// </summary>
17+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
18+
public string CertificateDirectory
19+
{
20+
get => GetStringValueHelper(LdapOption.LDAP_OPT_X_TLS_CACERTDIR, releasePtr: true);
21+
set => SetStringOptionHelper(LdapOption.LDAP_OPT_X_TLS_CACERTDIR, value);
22+
}
23+
1424
public bool SecureSocketLayer
1525
{
1626
get
@@ -52,6 +62,15 @@ public ReferralChasingOptions ReferralChasing
5262
}
5363
}
5464

65+
/// <summary>
66+
/// Create a new TLS library context.
67+
/// </summary>
68+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
69+
public void StartNewTlsSessionContext()
70+
{
71+
SetIntValueHelper(LdapOption.LDAP_OPT_X_TLS_NEWCTX, 0);
72+
}
73+
5574
private bool GetBoolValueHelper(LdapOption option)
5675
{
5776
if (_connection._disposed) throw new ObjectDisposedException(GetType().Name);
@@ -71,5 +90,14 @@ private void SetBoolValueHelper(LdapOption option, bool value)
7190

7291
ErrorChecking.CheckAndSetLdapError(error);
7392
}
93+
94+
private void SetStringOptionHelper(LdapOption option, string value)
95+
{
96+
if (_connection._disposed) throw new ObjectDisposedException(GetType().Name);
97+
98+
int error = LdapPal.SetStringOption(_connection._ldapHandle, option, value);
99+
100+
ErrorChecking.CheckAndSetLdapError(error);
101+
}
74102
}
75103
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ public partial class LdapSessionOptions
1010
{
1111
private static void PALCertFreeCRLContext(IntPtr certPtr) => Interop.Ldap.CertFreeCRLContext(certPtr);
1212

13+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
14+
public string CertificateDirectory
15+
{
16+
get => throw new PlatformNotSupportedException();
17+
set => throw new PlatformNotSupportedException();
18+
}
19+
1320
public bool SecureSocketLayer
1421
{
1522
get
@@ -24,6 +31,9 @@ public bool SecureSocketLayer
2431
}
2532
}
2633

34+
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
35+
public void StartNewTlsSessionContext() => throw new PlatformNotSupportedException();
36+
2737
public int ProtocolVersion
2838
{
2939
get => GetIntValueHelper(LdapOption.LDAP_OPT_VERSION);

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
5-
using System.Diagnostics;
65
using System.DirectoryServices.Tests;
76
using System.Globalization;
87
using System.Net;
9-
using System.Text;
10-
using System.Threading;
118
using Xunit;
129

1310
namespace System.DirectoryServices.Protocols.Tests
@@ -706,6 +703,32 @@ public void TestMultipleServerBind()
706703
connection.Timeout = new TimeSpan(0, 3, 0);
707704
}
708705

706+
#if NET
707+
[ConditionalFact(nameof(LdapConfigurationExists))]
708+
[PlatformSpecific(TestPlatforms.Linux)]
709+
public void StartNewTlsSessionContext_ThrowsLdapException()
710+
{
711+
using (var connection = new LdapConnection("server"))
712+
{
713+
LdapSessionOptions options = connection.SessionOptions;
714+
715+
// To get this to not throw, we need to set CertificateDirectory and have a .crt file in that directory.
716+
Assert.Throws<LdapException>(() => options.StartNewTlsSessionContext());
717+
}
718+
}
719+
720+
[ConditionalFact(nameof(LdapConfigurationExists))]
721+
[PlatformSpecific(TestPlatforms.Windows)]
722+
public void StartNewTlsSessionContext_ThrowsPlatformNotSupportedException()
723+
{
724+
using (var connection = new LdapConnection("server"))
725+
{
726+
LdapSessionOptions options = connection.SessionOptions;
727+
Assert.Throws<PlatformNotSupportedException>(() => options.StartNewTlsSessionContext());
728+
}
729+
}
730+
#endif
731+
709732
private void DeleteAttribute(LdapConnection connection, string entryDn, string attributeName)
710733
{
711734
string dn = entryDn + "," + LdapConfiguration.Configuration.SearchDn;
@@ -786,14 +809,14 @@ private SearchResultEntry SearchUser(LdapConnection connection, string rootDn, s
786809
return null;
787810
}
788811

789-
private LdapConnection GetConnection(string server)
812+
private static LdapConnection GetConnection(string server)
790813
{
791814
LdapDirectoryIdentifier directoryIdentifier = new LdapDirectoryIdentifier(server, fullyQualifiedDnsHostName: true, connectionless: false);
792815

793816
return GetConnection(directoryIdentifier);
794817
}
795818

796-
private LdapConnection GetConnection()
819+
private static LdapConnection GetConnection()
797820
{
798821
LdapDirectoryIdentifier directoryIdentifier = string.IsNullOrEmpty(LdapConfiguration.Configuration.Port) ?
799822
new LdapDirectoryIdentifier(LdapConfiguration.Configuration.ServerName, fullyQualifiedDnsHostName: true, connectionless: false) :

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@ public static bool IsLibLdapInstalled
3131
}
3232
else
3333
{
34-
_isLibLdapInstalled = NativeLibrary.TryLoad("libldap-2.4.so.2", out _);
34+
_isLibLdapInstalled =
35+
NativeLibrary.TryLoad("libldap.so.2", out _) ||
36+
NativeLibrary.TryLoad("libldap-2.6.so.0", out _) ||
37+
NativeLibrary.TryLoad("libldap-2.5.so.0", out _) ||
38+
NativeLibrary.TryLoad("libldap-2.4.so.2", out _);
3539
}
3640
}
37-
return _isLibLdapInstalled.Value;
3841
#else
3942
_isLibLdapInstalled = true; // In .NET Framework ldap is always installed.
40-
return _isLibLdapInstalled.Value;
4143
#endif
44+
45+
return _isLibLdapInstalled.Value;
4246
}
4347
}
4448
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
namespace System.DirectoryServices.Protocols.Tests
99
{
10+
// To enable these tests locally for Mono, comment out this line in DirectoryServicesTestHelpers.cs:
11+
// [assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35912", TestRuntimes.Mono)]
1012
[ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
1113
public class LdapSessionOptionsTests
1214
{
@@ -756,5 +758,30 @@ public void StopTransportLayerSecurity_Disposed_ThrowsObjectDisposedException()
756758

757759
Assert.Throws<ObjectDisposedException>(() => connection.SessionOptions.StopTransportLayerSecurity());
758760
}
761+
762+
#if NET
763+
[Fact]
764+
[PlatformSpecific(TestPlatforms.Linux)]
765+
public void CertificateDirectoryProperty()
766+
{
767+
using (var connection = new LdapConnection("server"))
768+
{
769+
LdapSessionOptions options = connection.SessionOptions;
770+
options.CertificateDirectory = "CertificateDirectory";
771+
Assert.Equal("CertificateDirectory", options.CertificateDirectory);
772+
}
773+
}
774+
775+
[Fact]
776+
[PlatformSpecific(TestPlatforms.Windows)]
777+
public void CertificateDirectoryProperty_ThrowsPlatformNotSupportedException()
778+
{
779+
using (var connection = new LdapConnection("server"))
780+
{
781+
LdapSessionOptions options = connection.SessionOptions;
782+
Assert.Throws<PlatformNotSupportedException>(() => options.CertificateDirectory = "CertificateDirectory");
783+
}
784+
}
785+
#endif
759786
}
760787
}

0 commit comments

Comments
 (0)