Linux: RBAC claims resolution fails if user has group with brackets in name
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
Real-world AD deployments can have groups with brackets in name (example: `Some resource access (rw)`). In this case, when nested claims resolution is enabled, Linux clients will get `LdapException: The search filter is invalid`.
### Expected Behavior
In case, when nested claims resolution is enabled, expected that each user's group will parse correctly, even if it contains brackets.
### Steps To Reproduce
1. Set up any AD server (contoso.com in the example).
2. Add AD group with brackets in name (`Some resource access (rw)`).
3. Add user to that group.
4. Create a simple API project, set up RBAC claims resolution:
```
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate(options =>
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return;
}
options.EnableLdap(settings =>
{
settings.Domain = "contoso.com";
settings.MachineAccountName = "someuser";
settings.MachineAccountPassword = "somepassword";
});
});
services.AddAuthorization();
```
```
[ApiController]
[Route("api/[controller]")]
[Authorize(Roles = "GroupA")]
public class SomeController : Controller
{
[HttpGet]
[Route("someMethod")]
public async Task> SomeMethod()
{
return 1;
}
}
```
### Exceptions (if any)
```
System.DirectoryServices.Protocols.LdapException: The search filter is invalid.
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
at Microsoft.AspNetCore.Authentication.Negotiate.NegotiateEvents.RetrieveLdapClaims(LdapContext context)
at Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler.HandleAuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
```
### .NET Version
8.0.204
### Anything else?
The problem is that class `LdapAdapter` does not [escape](https://learn.microsoft.com/en-us/archive/technet-wiki/5312.active-directory-characters-to-escape#ldap-filters) group name when place it in query to LDAP [here](https://github.com/dotnet/aspnetcore/blob/7033ec7f402fa4b7df2bf72a5e3dff1df6831f57/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs#L105):
```
var filter = $"(&(objectClass=group)(sAMAccountName={groupCN}))"; // This is using ldap search query language, it is looking on the server for someUser
```
It seems that you can use one of existing tool here:
1. [System.DirectoryServices.ActiveDirectory.Utils.GetEscapedFilterValue()](https://github.com/dotnet/runtime/blob/ce84f1d8a3f12711bad678a33efbc37b461f684f/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs#L1771)
2. [System.DirectoryServices.AccountManagement.ADUtils.EscapeRFC2254SpecialChars()](https://github.com/dotnet/runtime/blob/ce84f1d8a3f12711bad678a33efbc37b461f684f/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADUtils.cs#L148).
Also, you can use mentioned tools to get the common name (CN) from the distinguished name (DN) [here](https://github.com/dotnet/aspnetcore/blob/7033ec7f402fa4b7df2bf72a5e3dff1df6831f57/src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs#L69):
```
var groupCN = DistinguishedNameSeparator().Split(groupDN)[0].Substring("CN=".Length);
```
Method: [System.DirectoryServices.ActiveDirectory.Utils.GetDNComponents()](https://github.com/dotnet/runtime/blob/ce84f1d8a3f12711bad678a33efbc37b461f684f/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs#L459).
Contributor guide
Assessment
This issue has not been assessed yet.