11

I am developing an application based on .net core (2.2.103) which must connect to an LDAP server. On my development machine running Windows, I used the System.DirectoryServices namespace to do so. However, the application will have to run on Linux (Ubuntu) and I got a PlatformNotSupportedException, so I added a reference to <PackageReference Include="Novell.Directory.Ldap" Version="2.2.1" /> and used that.

Unfortunately, this throws another PlatformNotSupportedException (but because of Thread abort) when the Connection is disposed:

Unhandled Exception: System.PlatformNotSupportedException: Thread abort is not supported on this platform.
   at System.Threading.Thread.Abort()
   at Novell.Directory.Ldap.Connection.Dispose(Boolean disposing, String reason, Int32 semaphoreId, InterThreadException notifyUser)
   at Novell.Directory.Ldap.Connection.destroyClone(Boolean apiCall)
   at Novell.Directory.Ldap.LdapConnection.Finalize()

Is there any reliable LDAP implementation for dotnet core on Linux?

Philipp
  • 11,549
  • 8
  • 66
  • 126
  • 1
    Check what the exception says: `Thread abort is not supported`. Looks like you forgot to dispose the connection object. `Finalize()` is called by the garbage collector to clean up orphaned objects – Panagiotis Kanavos Feb 22 '19 at 12:48
  • 1
    In any case, the .NET Standard package is [Novell.Directory.Ldap.NETStandard](https://www.nuget.org/packages/Novell.Directory.Ldap.NETStandard/), not Novell.Directory.Ldap – Panagiotis Kanavos Feb 22 '19 at 12:51

4 Answers4

19

The package you tried to use was last updated in 2014. It's neither .NET Core nor .NET Standard compliant.

You can try Novell.Directory.Ldap.NETStandard instead. Despite the name, this isn't a Novell library. There are other LDAP libraries in NuGet but this seems to be the most popular and is still actively developed.

The exception suggests you forgot to dispose the connection too. Finalize is only called by the garbage collector.

This answer shows how to use Novell.Directory.Ldap.NETStandard to authenticate a user :

public bool ValidateUser(string domainName, string username, string password)
{
   string userDn = $"{username}@{domainName}";
   try
   {
      using (var connection = new LdapConnection {SecureSocketLayer = false})
      {
         connection.Connect(domainName, LdapConnection.DEFAULT_PORT);
         connection.Bind(userDn, password);
         if (connection.Bound)
            return true;
      }
   }
   catch (LdapException ex)
   {
      // Log exception
   }
   return false;
}

The connection is created inside a using block which ensures it gets disposed as soon as execution leaves the block's scope

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • 1
    the LdapConnection of the old package did not implement IDisposable, but thanks for the hint to the more recent package! I could use all my code without changing a thing (except that I added the using statement) – Philipp Feb 22 '19 at 14:03
  • Just for anyone reading in 2022 - as I am looking for a solution also, I believe Ldap4Net is now supported on .NET Standard - minimum required is 2.0 - compatible .NET runtimes: .NET Core, Mono, .NET Framework. – PKCS12 Jan 26 '22 at 17:31
11

With release of .NET 5 Microsoft added cross-platform support (windows, linux, macos) for library System.DirectoryServices.Protocols. It is low level LDAP API, that System.DirectoryServices is built on. I hope they will make System.DirectoryServices also cross-platform in the furure.

Source: .NET 5 - expanding directoryservices.protocols to linux and macos

I personally still use Novell.Directory.Ldap.NETStandard, but I am not satisfied with it. I hope I will find some time and switch to system.directoryservices.protocols or even better system.directoryservices library soon.

Miroslav Adamec
  • 1,060
  • 1
  • 15
  • 23
  • 1
    The new cross-platform support on System.DirectoryServices.Protocols works on windows, on linux there are several problems. For example, SSL/TSL do not work. see here: https://github.com/dotnet/runtime/issues/43890 and https://github.com/dotnet/runtime/issues/36947. – Ulf M. Jun 11 '21 at 07:39
  • It seems that [36947 - Compatibility between wldap32.dll and libldap](https://github.com/dotnet/runtime/issues/36947) is still not fixed. This [comment](https://github.com/dotnet/runtime/issues/36947#issuecomment-744046087) contains code that should work under windwos and linux. To my understanding [PR 52904](https://github.com/dotnet/runtime/pull/52904) solved [43890 - Add SSL support to LdapSessionOptions on Linux](https://github.com/dotnet/runtime/pull/43890). – surfmuggle Mar 28 '22 at 11:28
3

If you want use cross platform solution you can use the library https://github.com/flamencist/ldap4net. The library supports integrated authentication like Kerberos\gssapi\negotiate

0

In my case, Novell.Directory.Ldap.NETStandard worked fine on Windows but not on the Docker container that runs on a Linux VM.

In Linux, the problem was the DNS setting. After making the DNS setting of the Linux VM the same as the LDAP/Active Directory server setting and restarting the VM, the container worked fine. Hope it might help someone.

M. Abouzeid
  • 167
  • 7