runtime: System.DirectoryServices.Protocols.LdapConnection fails to find the new version of the LDAP library on Ubuntu 22.04
Description
Ubuntu 20.04 has LDAP library libldap-2.4 https://packages.ubuntu.com/source/focal/openldap Ubuntu 22.04 has LDAP library libldap-2.5.11 https://packages.ubuntu.com/source/jammy/openldap
When running .NET Core 6 code on Ubuntu 22.04, System.DirectoryServices.Protocols.LdapConnection cannot find the latest version of LDAP an fails.
Reproduction Steps
Install the LDAP libraries on Ubuntu 22.04:
ubuntu@w-ubuntu-2:~$ sudo apt-get install --no-install-recommends -y krb5-user ldap-utils libsasl2-modules-gssapi-mit wget
[sudo] password for ubuntu:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
ldap-utils is already the newest version (2.5.11+dfsg-1~exp1ubuntu3).
libsasl2-modules-gssapi-mit is already the newest version (2.1.27+dfsg2-3ubuntu1).
wget is already the newest version (1.21.2-2ubuntu1).
krb5-user is already the newest version (1.19.2-2).
The following package was automatically installed and is no longer required:
libfreetype6
Use 'sudo apt autoremove' to remove it.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
ubuntu@w-ubuntu-2:~$
Steps to reproduce: Run the following code from an ASP.NET Core 6 application on Ubuntu 22.04:
using System.DirectoryServices.Protocols;
var id = new LdapDirectoryIdentifier(servers[i], true, false);
Expected behavior
System.DirectoryServices.Protocols.LdapConnection finds the 2.5.11 version of LDAP library on Ubuntu 22.04 and connects to the LDAP server.
Actual behavior
System.TypeInitializationException
HResult=0x80131534
Message=The type initializer for 'Ldap' threw an exception.
Source=System.DirectoryServices.Protocols
StackTrace:
at Interop.Ldap.ldap_initialize(IntPtr& ld, String uri)
at System.DirectoryServices.Protocols.ConnectionHandle..ctor(String uri)
at System.DirectoryServices.Protocols.LdapConnection.InternalInitConnectionHandle(String hostname)
at System.DirectoryServices.Protocols.LdapConnection.Init()
at System.DirectoryServices.Protocols.LdapConnection..ctor(LdapDirectoryIdentifier identifier, NetworkCredential credential, AuthType authType)
at TheLdapService.Server.Services.LdapService.GetLdapConnection() in C:\Users\ubuntu\source\repos\TheLdapService\src\TheLdapService.Server\Services\LdapService.cs:line 58
at TheLdapService.Server.Services.LdapService.Authenticate(String username, String password) in C:\Users\ubuntu\source\repos\TheLdapService\src\TheLdapService.Server\Services\LdapService.cs:line 199
at TheLdapService.Server.Services.AuthorizationService.<>c__DisplayClass4_0.<Login>b__0() in C:\Users\ubuntu\source\repos\TheLdapService\src\TheLdapService.Server\Services\AuthorizationService.cs:line 39
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
DllNotFoundException: Unable to load shared library 'libldap-2.4.so.2' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibldap-2.4.so.2: cannot open shared object file: No such file or directory
Regression?
Same code worked under Ubuntu 20.04, which has libldap-2.4, the library System.DirectoryServices.Protocols.LdapConnection is looking for.
Known Workarounds
On Ubuntu 22.04, create a symbolic link from ldap-2.4 to ldap-2.5:
ubuntu@w-ubuntu-2:~$ sudo ln -s /usr/lib/x86_64-linux-gnu/libldap-2.5.so.0 /usr/lib/x86_64-linux-gnu/libldap-2.4.so.2
ubuntu@w-ubuntu-2:/usr/lib/x86_64-linux-gnu$ ll | grep ldap
lrwxrwxrwx 1 root root 42 May 17 15:29 libldap-2.4.so.2 -> /usr/lib/x86_64-linux-gnu/libldap-2.5.so.0
lrwxrwxrwx 1 root root 20 Feb 16 12:15 libldap-2.5.so.0 -> libldap-2.5.so.0.1.6
-rw-r--r-- 1 root root 376576 Feb 16 12:15 libldap-2.5.so.0.1.6
Configuration
ubuntu@w-ubuntu-2:~$ dotnet --info
.NET SDK (reflecting any global.json):
Version: 6.0.300
Commit: 8473146e7d
Runtime Environment:
OS Name: ubuntu
OS Version: 22.04
OS Platform: Linux
RID: ubuntu.22.04-x64
Base Path: /usr/share/dotnet/sdk/6.0.300/
Host (useful for support):
Version: 6.0.5
Commit: 70ae3df4a6
.NET SDKs installed:
6.0.300 [/usr/share/dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
To install additional .NET runtimes or SDKs:
https://aka.ms/dotnet-download
Other information
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 15 (6 by maintainers)
After some quick testing. Looks like this workaround does work for .net 6 alpine based images. Might need to update the link if the libldap version changes. Here is my docker file
Looks like this is what you want in you /usr/lib directory.
My C# for ref.
An alternative work around that worked for me is to use AssemblyLoadContext as shown below:
This is expected. The reason why this happens has nothing to do with your code, but instead with the native library installed in ubuntu 22.04. There is no fix for this available yet, just a known workaround that was posted above. Copying it here for reference:
After running that, you should be able to run your app (this is assuming you are running on a x64 machine)
I chatted with @AaronRobinsonMSFT about this last week. There is a way for us to basically hook into an event that gets triggered whenever binding to the native assembly fails, and at that point we can try some other versions to see if we can find one supported which is installed, and that seemed like a good-enough solution for now. Unfortunately, we won’t have enough bandwidth to get that done for 7.0 any longer, so I’m adjusting the milestone accordingly.
For folks hitting this in 7.0, They will be able to use the workarounds provided above (adding symlink or manually downloading the 2.4 version) in order to get unblocked. I tried both and they worked for me in Ubuntu 22.04.
I took a look at this today. Unfortunately, seems like libldap doesn’t provide a major version
.soor a version-less.sothat we can create our PInvokes against. There is a version-less one but only on the dev packagelibldap2-devwhich doesn’t come installed on the distros. Due to the fact that DllImports require the library name to be a string constant, in order to support multiple versions we would need to create Interop stubs for each version in order for this to work. Alternatively, we could manually use NativeLibrary and implement our own policy for picking the right versions, or providing a native shim. Depending on the solution we go with, this may not make it to 7.0 depending on the complexity. I’ll post an update in the next few days, and will adjust the milestone if necessary.