-
Notifications
You must be signed in to change notification settings - Fork 6
DEV-1565 поддержка Global Catalog #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| using Multifactor.Core.Ldap; | ||
| using Multifactor.Core.Ldap.Name; | ||
| using Multifactor.Radius.Adapter.v2.Application.Core.Models.Abstractions; | ||
|
|
||
| namespace Multifactor.Radius.Adapter.v2.Application.Core.Extensions; | ||
|
|
||
| public static class LdapGlobalCatalogExtensions | ||
| { | ||
| private const int GlobalCatalogPort = 3268; | ||
| private const int GlobalCatalogSslPort = 3269; | ||
| private const int LdapPort = 389; | ||
| private const int LdapsPort = 636; | ||
|
|
||
| /// <summary> | ||
| /// LDAP-сервер считается Global Catalog, если в connection-string указан порт 3268/3269 | ||
| /// </summary> | ||
| public static bool IsGlobalCatalog(this ILdapServerConfiguration config) | ||
| { | ||
| ArgumentNullException.ThrowIfNull(config); | ||
| return IsGlobalCatalogPort(new LdapConnectionString(config.ConnectionString).Port); | ||
| } | ||
|
|
||
| public static bool IsGlobalCatalogPort(int port) => port is GlobalCatalogPort or GlobalCatalogSslPort; | ||
|
|
||
| /// <summary> | ||
| /// Извлекает DNS-имя домена (например, "child.test.group") из DN пользователя, | ||
| /// найденного через GC (например, "CN=User1,OU=Users,DC=child,DC=test,DC=group"). | ||
| /// </summary> | ||
| public static string ExtractDomainDnsName(this DistinguishedName dn) | ||
| { | ||
| ArgumentNullException.ThrowIfNull(dn); | ||
|
|
||
| var parts = dn.StringRepresentation | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. лучше dn.Components |
||
| .Split(',') | ||
| .Select(p => p.Trim()) | ||
| .Where(p => p.StartsWith("DC=", StringComparison.OrdinalIgnoreCase)) | ||
| .Select(p => p[3..].Trim()); | ||
|
|
||
| return string.Join(".", parts); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Строит connection-string для bind к контроллеру конкретного домена по его DNS-имени. | ||
| /// </summary> | ||
| public static string ToDomainControllerConnectionString(this LdapConnectionString globalCatalogConnectionString, string domainDnsName) | ||
| { | ||
| ArgumentNullException.ThrowIfNull(globalCatalogConnectionString); | ||
| ArgumentException.ThrowIfNullOrWhiteSpace(domainDnsName); | ||
|
|
||
| var isSsl = globalCatalogConnectionString.Port == GlobalCatalogSslPort | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. кажется это функционал для ldap.core
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да и почти все остальное |
||
| || globalCatalogConnectionString.Scheme.Equals("ldaps", StringComparison.OrdinalIgnoreCase); | ||
|
|
||
| var scheme = isSsl ? "ldaps" : "ldap"; | ||
| var port = isSsl ? LdapsPort : LdapPort; | ||
|
|
||
| return $"{scheme}://{domainDnsName}:{port}"; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,31 @@ | ||
| using Multifactor.Radius.Adapter.v2.Application.Core.Models.Abstractions; | ||
| using System.DirectoryServices.Protocols; | ||
| using Multifactor.Radius.Adapter.v2.Application.Core.Models.Abstractions; | ||
| using Multifactor.Radius.Adapter.v2.Application.Features.PacketHandler.UseCases.LoadProfile.Models; | ||
|
|
||
| namespace Multifactor.Radius.Adapter.v2.Application.Features.PacketHandler.UseCases.LoadProfile.Ports; | ||
|
|
||
| public interface IProfileSearch | ||
| { | ||
| ILdapProfile? Execute(FindUserDto request); | ||
|
|
||
| /// <summary> | ||
| /// Возвращает ВСЕ записи, подошедшие под фильтр поиска, а не только первую. | ||
| /// Нужен при поиске через Global Catalog, где sAMAccountName формально уникален | ||
| /// только в рамках домена (не леса). | ||
| /// </summary> | ||
| IReadOnlyList<ILdapProfile> ExecuteMany(FindUserDto request); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Не надо так |
||
|
|
||
| /// <summary> | ||
| /// Резолвит NetBIOS-имя домена в его DNS-имя | ||
| /// Нужен, чтобы явно указанный пользователем домен в DOMAIN\user не терялся при поиске | ||
| /// через Global Catalog. Возвращает null, если сопоставление не найдено. | ||
| /// </summary> | ||
| string? ResolveDomainDnsNameByNetBiosName( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не имеет отношение к интерфейсу |
||
| string connectionString, | ||
| AuthType authType, | ||
| string userName, | ||
| string password, | ||
| int bindTimeoutInSeconds, | ||
| string netBiosName); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Кажется что метод не на своем месте