Merge pull request #584 from ONLYOFFICE/feature/LDAP-new
Feature/LDAP-new
This commit is contained in:
commit
e3e12b902f
@ -103,6 +103,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.EventBus.Extensions.Log
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Migration", "common\ASC.Migration\ASC.Migration.csproj", "{05B8FF27-446B-49BF-B508-4A4C096D2BB2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.ActiveDirectory", "common\ASC.ActiveDirectory\ASC.ActiveDirectory.csproj", "{9F81862F-303D-467F-8DC9-044BE2CCF329}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -293,6 +295,10 @@ Global
|
||||
{05B8FF27-446B-49BF-B508-4A4C096D2BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{05B8FF27-446B-49BF-B508-4A4C096D2BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{05B8FF27-446B-49BF-B508-4A4C096D2BB2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9F81862F-303D-467F-8DC9-044BE2CCF329}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9F81862F-303D-467F-8DC9-044BE2CCF329}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9F81862F-303D-467F-8DC9-044BE2CCF329}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9F81862F-303D-467F-8DC9-044BE2CCF329}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -2,6 +2,7 @@
|
||||
"solution": {
|
||||
"path": "ASC.Web.sln",
|
||||
"projects": [
|
||||
"common\\ASC.ActiveDirectory\\ASC.ActiveDirectory.csproj",
|
||||
"common\\ASC.Api.Core\\ASC.Api.Core.csproj",
|
||||
"common\\ASC.Common\\ASC.Common.csproj",
|
||||
"common\\ASC.Core.Common\\ASC.Core.Common.csproj",
|
||||
|
18
common/ASC.ActiveDirectory/ASC.ActiveDirectory.csproj
Normal file
18
common/ASC.ActiveDirectory/ASC.ActiveDirectory.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ASC.Common\ASC.Common.csproj" />
|
||||
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
|
||||
<ProjectReference Include="..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
50
common/ASC.ActiveDirectory/Base/ActiveDirectoryDbContext.cs
Normal file
50
common/ASC.ActiveDirectory/Base/ActiveDirectoryDbContext.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
public class ActiveDirectoryDbContext : BaseDbContext
|
||||
{
|
||||
public DbSet<DbTenant> Tenants { get; set; }
|
||||
public DbSet<DbWebstudioSettings> WebstudioSettings { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
ModelBuilderWrapper
|
||||
.From(modelBuilder, _provider)
|
||||
.AddDbTenant()
|
||||
.AddWebstudioSettings()
|
||||
.AddDbFunction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ActiveDirectoryDbContextExtention
|
||||
{
|
||||
public static DIHelper AddCRMDbContextService(this DIHelper services)
|
||||
{
|
||||
return services.AddDbContextManagerService<ActiveDirectoryDbContext>();
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Data;
|
||||
[Serializable]
|
||||
public class LdapCertificateConfirmRequest
|
||||
{
|
||||
private volatile bool _approved;
|
||||
private volatile bool _requested;
|
||||
private volatile string _serialNumber;
|
||||
private volatile string _issuerName;
|
||||
private volatile string _subjectName;
|
||||
private volatile string _hash;
|
||||
private volatile int[] _certificateErrors;
|
||||
|
||||
public bool Approved { get { return _approved; } set { _approved = value; } }
|
||||
|
||||
public bool Requested { get { return _requested; } set { _requested = value; } }
|
||||
|
||||
public string SerialNumber { get { return _serialNumber; } set { _serialNumber = value; } }
|
||||
|
||||
public string IssuerName { get { return _issuerName; } set { _issuerName = value; } }
|
||||
|
||||
public string SubjectName { get { return _subjectName; } set { _subjectName = value; } }
|
||||
|
||||
public DateTime ValidFrom { get; set; }
|
||||
|
||||
public DateTime ValidUntil { get; set; }
|
||||
|
||||
public string Hash { get { return _hash; } set { _hash = value; } }
|
||||
|
||||
public int[] CertificateErrors { get { return _certificateErrors; } set { _certificateErrors = value; } }
|
||||
|
||||
private enum LdapCertificateProblem
|
||||
{
|
||||
CertExpired = -2146762495,
|
||||
CertCnNoMatch = -2146762481,
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
CertIssuerChaining = -2146762489,
|
||||
CertUntrustedCa = -2146762478,
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
CertUntrustedRoot = -2146762487,
|
||||
CertMalformed = -2146762488,
|
||||
CertUnrecognizedError = -2146762477
|
||||
}
|
||||
|
||||
public static int[] GetLdapCertProblems(X509Certificate certificate, X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors, ILogger log = null)
|
||||
{
|
||||
var certificateErrors = new List<int>();
|
||||
try
|
||||
{
|
||||
if (sslPolicyErrors == SslPolicyErrors.None)
|
||||
{
|
||||
return certificateErrors.ToArray();
|
||||
}
|
||||
|
||||
var expDate = DateTime.Parse(certificate.GetExpirationDateString()).ToUniversalTime();
|
||||
var utcNow = DateTime.UtcNow;
|
||||
if (expDate < utcNow && expDate.AddDays(1) >= utcNow)
|
||||
{
|
||||
certificateErrors.Add((int)LdapCertificateProblem.CertExpired);
|
||||
}
|
||||
|
||||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors))
|
||||
{
|
||||
certificateErrors.Add((int)LdapCertificateProblem.CertMalformed);
|
||||
}
|
||||
|
||||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.WarnGetLdapCertProblems(Enum.GetName(typeof(SslPolicyErrors), LdapCertificateProblem.CertCnNoMatch));
|
||||
}
|
||||
|
||||
certificateErrors.Add((int)LdapCertificateProblem.CertCnNoMatch);
|
||||
}
|
||||
|
||||
if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable))
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.WarnGetLdapCertProblems(Enum.GetName(typeof(SslPolicyErrors), LdapCertificateProblem.CertCnNoMatch));
|
||||
}
|
||||
|
||||
certificateErrors.Add((int)LdapCertificateProblem.CertUntrustedCa);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.ErrorGetLdapCertProblems(ex);
|
||||
}
|
||||
|
||||
certificateErrors.Add((int)LdapCertificateProblem.CertUnrecognizedError);
|
||||
}
|
||||
|
||||
return certificateErrors.ToArray();
|
||||
}
|
||||
|
||||
public static LdapCertificateConfirmRequest FromCert(X509Certificate certificate, X509Chain chain,
|
||||
SslPolicyErrors sslPolicyErrors, bool approved = false, bool requested = false, ILogger log = null)
|
||||
{
|
||||
var certificateErrors = GetLdapCertProblems(certificate, chain, sslPolicyErrors, log);
|
||||
|
||||
try
|
||||
{
|
||||
string serialNumber = "", issuerName = "", subjectName = "", hash = "";
|
||||
DateTime validFrom = DateTime.UtcNow, validUntil = DateTime.UtcNow;
|
||||
|
||||
LdapUtils.SkipErrors(() => serialNumber = certificate.GetSerialNumberString(), log);
|
||||
LdapUtils.SkipErrors(() => issuerName = certificate.Issuer, log);
|
||||
LdapUtils.SkipErrors(() => subjectName = certificate.Subject, log);
|
||||
LdapUtils.SkipErrors(() => validFrom = DateTime.Parse(certificate.GetEffectiveDateString()), log);
|
||||
LdapUtils.SkipErrors(() => validUntil = DateTime.Parse(certificate.GetExpirationDateString()), log);
|
||||
LdapUtils.SkipErrors(() => hash = certificate.GetCertHashString(), log);
|
||||
|
||||
var certificateConfirmRequest = new LdapCertificateConfirmRequest
|
||||
{
|
||||
SerialNumber = serialNumber,
|
||||
IssuerName = issuerName,
|
||||
SubjectName = subjectName,
|
||||
ValidFrom = validFrom,
|
||||
ValidUntil = validUntil,
|
||||
Hash = hash,
|
||||
CertificateErrors = certificateErrors,
|
||||
Approved = approved,
|
||||
Requested = requested
|
||||
};
|
||||
|
||||
return certificateConfirmRequest;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.ErrorLdapCertificateConfirmRequest(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
88
common/ASC.ActiveDirectory/Base/Data/LdapLogin.cs
Normal file
88
common/ASC.ActiveDirectory/Base/Data/LdapLogin.cs
Normal file
@ -0,0 +1,88 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Data;
|
||||
public class LdapLogin
|
||||
{
|
||||
public string Username { get; private set; }
|
||||
public string Domain { get; private set; }
|
||||
|
||||
public LdapLogin(string username, string domain)
|
||||
{
|
||||
Username = username;
|
||||
Domain = domain;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Domain) ? string.Format("{0}@{1}", Username, Domain) : Username;
|
||||
}
|
||||
|
||||
public static LdapLogin ParseLogin(string login)
|
||||
{
|
||||
if (string.IsNullOrEmpty(login))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string username;
|
||||
string domain = null;
|
||||
|
||||
if (login.Contains("\\"))
|
||||
{
|
||||
var splited = login.Split('\\');
|
||||
|
||||
if (!splited.Any() || splited.Length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
domain = splited[0];
|
||||
username = splited[1];
|
||||
|
||||
}
|
||||
else if (login.Contains("@"))
|
||||
{
|
||||
var splited = login.Split('@');
|
||||
|
||||
if (!splited.Any() || splited.Length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
username = splited[0];
|
||||
domain = splited[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
username = login;
|
||||
}
|
||||
|
||||
var result = new LdapLogin(username, domain);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
58
common/ASC.ActiveDirectory/Base/Data/LdapObject.cs
Normal file
58
common/ASC.ActiveDirectory/Base/Data/LdapObject.cs
Normal file
@ -0,0 +1,58 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Data;
|
||||
/// <summary>
|
||||
/// LDAP object class
|
||||
/// </summary>
|
||||
public abstract class LdapObject
|
||||
{
|
||||
#region .Public
|
||||
|
||||
public abstract string DistinguishedName { get; }
|
||||
|
||||
public abstract string Sid { get; }
|
||||
|
||||
public abstract string SidAttribute { get; }
|
||||
|
||||
public abstract bool IsDisabled { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Get property object
|
||||
/// </summary>
|
||||
/// <param name="propertyName">property name</param>
|
||||
/// <returns>value object</returns>
|
||||
public abstract object GetValue(string propertyName, bool getBytes = false);
|
||||
|
||||
/// <summary>
|
||||
/// Get property values
|
||||
/// </summary>
|
||||
/// <param name="propertyName">property name</param>
|
||||
/// <returns>list of values</returns>
|
||||
public abstract List<string> GetValues(string propertyName);
|
||||
}
|
271
common/ASC.ActiveDirectory/Base/Data/LdapObjectExtension.cs
Normal file
271
common/ASC.ActiveDirectory/Base/Data/LdapObjectExtension.cs
Normal file
@ -0,0 +1,271 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Mapping = ASC.ActiveDirectory.Base.Settings.LdapSettings.MappingFields;
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Data;
|
||||
/// <summary>
|
||||
/// LDAP object extensions class
|
||||
/// </summary>
|
||||
[Scope]
|
||||
public class LdapObjectExtension
|
||||
{
|
||||
private readonly TenantUtil _tenantUtil;
|
||||
private readonly ILogger<LdapObjectExtension> _logger;
|
||||
public LdapObjectExtension(TenantUtil tenantUtil, ILogger<LdapObjectExtension> logger)
|
||||
{
|
||||
_tenantUtil = tenantUtil;
|
||||
_logger = logger;
|
||||
}
|
||||
public string GetAttribute(LdapObject ldapObject, string attribute)
|
||||
{
|
||||
if (string.IsNullOrEmpty(attribute))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return ldapObject.GetValue(attribute) as string;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorCanNotGetAttribute(attribute, ldapObject.DistinguishedName, e);
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> GetAttributes(LdapObject ldapObject, string attribute)
|
||||
{
|
||||
var list = new List<string>();
|
||||
|
||||
if (string.IsNullOrEmpty(attribute))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return ldapObject.GetValues(attribute);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
_logger.ErrorCanNotGetAttributes(attribute, ldapObject.DistinguishedName, e);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
private const int MAX_NUMBER_OF_SYMBOLS = 64;
|
||||
private const string EXT_MOB_PHONE = "extmobphone";
|
||||
private const string EXT_MAIL = "extmail";
|
||||
private const string EXT_PHONE = "extphone";
|
||||
private const string EXT_SKYPE = "extskype";
|
||||
|
||||
private List<string> GetContacts(LdapObject ldapUser, Mapping key, LdapSettings settings)
|
||||
{
|
||||
if (!settings.LdapMapping.ContainsKey(key))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var bindings = settings.LdapMapping[key].Split(',').Select(x => x.Trim()).ToArray();
|
||||
if (bindings.Length > 1)
|
||||
{
|
||||
var list = new List<string>();
|
||||
foreach (var bind in bindings)
|
||||
{
|
||||
list.AddRange(GetAttributes(ldapUser, bind));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetAttributes(ldapUser, bindings[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateContacts(List<string> Contacts, string type, List<string> values)
|
||||
{
|
||||
if (values == null || !values.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var val in values)
|
||||
{
|
||||
Contacts.Add(type);
|
||||
Contacts.Add(val);
|
||||
}
|
||||
}
|
||||
|
||||
public UserInfo ToUserInfo(LdapObject ldapUser, LdapUserImporter ldapUserImporter)
|
||||
{
|
||||
var settings = ldapUserImporter.Settings;
|
||||
var resource = ldapUserImporter.Resource;
|
||||
|
||||
var userName = GetAttribute(ldapUser, settings.LoginAttribute);
|
||||
|
||||
var firstName = settings.LdapMapping.ContainsKey(Mapping.FirstNameAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.FirstNameAttribute]) : string.Empty;
|
||||
var secondName = settings.LdapMapping.ContainsKey(Mapping.SecondNameAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.SecondNameAttribute]) : string.Empty;
|
||||
var birthDay = settings.LdapMapping.ContainsKey(Mapping.BirthDayAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.BirthDayAttribute]) : string.Empty;
|
||||
var gender = settings.LdapMapping.ContainsKey(Mapping.GenderAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.GenderAttribute]) : string.Empty;
|
||||
var primaryPhone = settings.LdapMapping.ContainsKey(Mapping.MobilePhoneAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.MobilePhoneAttribute]) : string.Empty;
|
||||
var mail = settings.LdapMapping.ContainsKey(Mapping.MailAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.MailAttribute]) : string.Empty;
|
||||
var title = settings.LdapMapping.ContainsKey(Mapping.TitleAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.TitleAttribute]) : string.Empty;
|
||||
var location = settings.LdapMapping.ContainsKey(Mapping.LocationAttribute) ? GetAttribute(ldapUser, settings.LdapMapping[Mapping.LocationAttribute]) : string.Empty;
|
||||
|
||||
var phones = GetContacts(ldapUser, Mapping.AdditionalPhone, settings);
|
||||
var mobilePhones = GetContacts(ldapUser, Mapping.AdditionalMobilePhone, settings);
|
||||
var emails = GetContacts(ldapUser, Mapping.AdditionalMail, settings);
|
||||
var skype = GetContacts(ldapUser, Mapping.Skype, settings);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(userName))
|
||||
{
|
||||
throw new Exception("LDAP LoginAttribute is empty");
|
||||
}
|
||||
|
||||
var contacts = new List<string>();
|
||||
|
||||
PopulateContacts(contacts, EXT_PHONE, phones);
|
||||
PopulateContacts(contacts, EXT_MOB_PHONE, mobilePhones);
|
||||
PopulateContacts(contacts, EXT_MAIL, emails);
|
||||
PopulateContacts(contacts, EXT_SKYPE, skype);
|
||||
|
||||
var user = new UserInfo
|
||||
{
|
||||
Id = Guid.Empty,
|
||||
UserName = userName,
|
||||
Sid = ldapUser.Sid,
|
||||
ActivationStatus = settings.SendWelcomeEmail && !string.IsNullOrEmpty(mail) ? EmployeeActivationStatus.Pending : EmployeeActivationStatus.NotActivated,
|
||||
Status = ldapUser.IsDisabled ? EmployeeStatus.Terminated : EmployeeStatus.Active,
|
||||
Title = !string.IsNullOrEmpty(title) ? title : string.Empty,
|
||||
Location = !string.IsNullOrEmpty(location) ? location : string.Empty,
|
||||
WorkFromDate = _tenantUtil.DateTimeNow(),
|
||||
ContactsList = contacts
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(firstName))
|
||||
{
|
||||
user.FirstName = firstName.Length > MAX_NUMBER_OF_SYMBOLS
|
||||
? firstName.Substring(0, MAX_NUMBER_OF_SYMBOLS)
|
||||
: firstName;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.FirstName = resource.FirstName;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(secondName))
|
||||
{
|
||||
user.LastName = secondName.Length > MAX_NUMBER_OF_SYMBOLS
|
||||
? secondName.Substring(0, MAX_NUMBER_OF_SYMBOLS)
|
||||
: secondName;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.LastName = resource.LastName;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(birthDay))
|
||||
{
|
||||
DateTime date;
|
||||
if (DateTime.TryParse(birthDay, out date))
|
||||
{
|
||||
user.BirthDate = date;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(gender))
|
||||
{
|
||||
bool b;
|
||||
if (bool.TryParse(gender, out b))
|
||||
{
|
||||
user.Sex = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (gender.ToLowerInvariant())
|
||||
{
|
||||
case "male":
|
||||
case "m":
|
||||
user.Sex = true;
|
||||
break;
|
||||
case "female":
|
||||
case "f":
|
||||
user.Sex = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(mail))
|
||||
{
|
||||
user.Email = userName.Contains("@") ? userName : string.Format("{0}@{1}", userName, ldapUserImporter.LDAPDomain);
|
||||
user.ActivationStatus = EmployeeActivationStatus.AutoGenerated;
|
||||
}
|
||||
else
|
||||
{
|
||||
user.Email = mail;
|
||||
}
|
||||
|
||||
user.MobilePhone = string.IsNullOrEmpty(primaryPhone)
|
||||
? null : primaryPhone;
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public GroupInfo ToGroupInfo(LdapObject ldapGroup, LdapSettings settings)
|
||||
{
|
||||
var name = GetAttribute(ldapGroup, settings.GroupNameAttribute);
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new Exception("LDAP GroupNameAttribute is empty");
|
||||
}
|
||||
|
||||
var group = new GroupInfo
|
||||
{
|
||||
Name = name,
|
||||
Sid = ldapGroup.Sid
|
||||
};
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
public string GetDomainFromDn(LdapObject ldapObject)
|
||||
{
|
||||
if (ldapObject == null || string.IsNullOrEmpty(ldapObject.DistinguishedName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return LdapUtils.DistinguishedNameToDomain(ldapObject.DistinguishedName);
|
||||
}
|
||||
}
|
58
common/ASC.ActiveDirectory/Base/DbHelper.cs
Normal file
58
common/ASC.ActiveDirectory/Base/DbHelper.cs
Normal file
@ -0,0 +1,58 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
[Scope]
|
||||
public class DbHelper
|
||||
{
|
||||
private readonly Lazy<ActiveDirectoryDbContext> _lazyActiveDirectoryDbContext;
|
||||
private readonly LdapSettings _ldapSettings;
|
||||
private ActiveDirectoryDbContext ActiveDirectoryDbContext { get => _lazyActiveDirectoryDbContext.Value; }
|
||||
|
||||
public DbHelper(
|
||||
DbContextManager<ActiveDirectoryDbContext> activeDirectoryDbContext,
|
||||
LdapSettings ldapSettings)
|
||||
{
|
||||
_ldapSettings = ldapSettings;
|
||||
_lazyActiveDirectoryDbContext = new Lazy<ActiveDirectoryDbContext>(() => activeDirectoryDbContext.Value);
|
||||
}
|
||||
|
||||
public List<int> GetTenants()
|
||||
{
|
||||
var id = _ldapSettings.ID;
|
||||
var enableLdapAuthentication = _ldapSettings.EnableLdapAuthentication;
|
||||
|
||||
var data = ActiveDirectoryDbContext.WebstudioSettings
|
||||
.Where(r => r.Id == id)
|
||||
.Join(ActiveDirectoryDbContext.Tenants, r => r.TenantId, r => r.Id, (settings, tenant) => new { settings, tenant })
|
||||
.Select(r => JsonExtensions.JsonValue(nameof(r.settings.Data).ToLower(), enableLdapAuthentication.ToString()))
|
||||
.Distinct()
|
||||
.Select(r => r != null ? Convert.ToInt32(r) : 0)
|
||||
.ToList();
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
134
common/ASC.ActiveDirectory/Base/Expressions/Criteria.cs
Normal file
134
common/ASC.ActiveDirectory/Base/Expressions/Criteria.cs
Normal file
@ -0,0 +1,134 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Expressions;
|
||||
/// <summary>
|
||||
/// Criteria
|
||||
/// </summary>
|
||||
public class Criteria : ICloneable
|
||||
{
|
||||
private readonly CriteriaType _type;
|
||||
private readonly List<Expression> _expressions = new List<Expression>();
|
||||
private readonly List<Criteria> _nestedCriteras = new List<Criteria>();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="type">Type of critera</param>
|
||||
/// <param name="expressions">Expressions</param>
|
||||
public Criteria(CriteriaType type, params Expression[] expressions)
|
||||
{
|
||||
_expressions.AddRange(expressions);
|
||||
_type = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add nested expressions as And criteria
|
||||
/// </summary>
|
||||
/// <param name="expressions">Expressions</param>
|
||||
/// <returns>Self</returns>
|
||||
public Criteria And(params Expression[] expressions)
|
||||
{
|
||||
_nestedCriteras.Add(All(expressions));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add nested expressions as Or criteria
|
||||
/// </summary>
|
||||
/// <param name="expressions">Expressions</param>
|
||||
/// <returns>Self</returns>
|
||||
public Criteria Or(params Expression[] expressions)
|
||||
{
|
||||
_nestedCriteras.Add(Any(expressions));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add nested Criteria
|
||||
/// </summary>
|
||||
/// <param name="nested"></param>
|
||||
/// <returns>себя</returns>
|
||||
public Criteria Add(Criteria nested)
|
||||
{
|
||||
_nestedCriteras.Add(nested);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Criteria as a string
|
||||
/// </summary>
|
||||
/// <returns>Criteria string</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var criteria = "({0}{1}{2})";
|
||||
var expressions = _expressions.Aggregate(string.Empty, (current, expr) => current + expr.ToString());
|
||||
var criterias = _nestedCriteras.Aggregate(string.Empty, (current, crit) => current + crit.ToString());
|
||||
return string.Format(criteria, _type == CriteriaType.And ? "&" : "|", expressions, criterias);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group of Expression union as And
|
||||
/// </summary>
|
||||
/// <param name="expressions">Expressions</param>
|
||||
/// <returns>new Criteria</returns>
|
||||
public static Criteria All(params Expression[] expressions)
|
||||
{
|
||||
return new Criteria(CriteriaType.And, expressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group of Expression union as Or
|
||||
/// </summary>
|
||||
/// <param name="expressions">Expressions</param>
|
||||
/// <returns>new Criteria</returns>
|
||||
public static Criteria Any(params Expression[] expressions)
|
||||
{
|
||||
return new Criteria(CriteriaType.Or, expressions);
|
||||
}
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
/// <summary>
|
||||
/// ICloneable implemetation
|
||||
/// </summary>
|
||||
/// <returns>Clone object</returns>
|
||||
public object Clone()
|
||||
{
|
||||
var cr = new Criteria(_type);
|
||||
foreach (var ex in _expressions)
|
||||
{
|
||||
cr._expressions.Add(ex.Clone() as Expression);
|
||||
}
|
||||
foreach (var nc in _nestedCriteras)
|
||||
{
|
||||
cr._nestedCriteras.Add(nc.Clone() as Criteria);
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
36
common/ASC.ActiveDirectory/Base/Expressions/CriteriaType.cs
Normal file
36
common/ASC.ActiveDirectory/Base/Expressions/CriteriaType.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Expressions;
|
||||
/// <summary>
|
||||
/// Criteria enum
|
||||
/// </summary>
|
||||
public enum CriteriaType
|
||||
{
|
||||
None,
|
||||
And,
|
||||
Or
|
||||
}
|
304
common/ASC.ActiveDirectory/Base/Expressions/Expression.cs
Normal file
304
common/ASC.ActiveDirectory/Base/Expressions/Expression.cs
Normal file
@ -0,0 +1,304 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Expressions;
|
||||
public class Expression : ICloneable
|
||||
{
|
||||
private readonly Op _op;
|
||||
private bool _negative;
|
||||
private readonly string _attributeName;
|
||||
private readonly string _attributeValue;
|
||||
|
||||
private const string EQUIAL = "=";
|
||||
private const string APPROXIMATELY_EQUIAL = "~=";
|
||||
private const string GREATER = ">";
|
||||
private const string GREATER_OR_EQUAL = ">=";
|
||||
private const string LESS = "<";
|
||||
private const string LESS_OR_EQUAL = "<=";
|
||||
|
||||
internal Expression()
|
||||
{
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _attributeName; }
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get { return _attributeValue; }
|
||||
}
|
||||
|
||||
public Op Operation
|
||||
{
|
||||
get { return _op; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To specify unary operations
|
||||
/// </summary>
|
||||
/// <param name="op">Operator</param>
|
||||
/// <param name="attrbuteName">Attribute name</param>
|
||||
public Expression(string attrbuteName, Op op)
|
||||
{
|
||||
if (op != Op.Exists && op != Op.NotExists)
|
||||
{
|
||||
throw new ArgumentException("op");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(attrbuteName))
|
||||
{
|
||||
throw new ArgumentException("attrbuteName");
|
||||
}
|
||||
|
||||
_op = op;
|
||||
_attributeName = attrbuteName;
|
||||
_attributeValue = "*";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To specify binary operations
|
||||
/// </summary>
|
||||
/// <param name="op">Operator</param>
|
||||
/// <param name="attrbuteName">Attribute name</param>
|
||||
/// <param name="attrbuteValue">Attribute value</param>
|
||||
public Expression(string attrbuteName, Op op, string attrbuteValue)
|
||||
{
|
||||
if (op == Op.Exists || op == Op.NotExists)
|
||||
{
|
||||
throw new ArgumentException("op");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(attrbuteName))
|
||||
{
|
||||
throw new ArgumentException("attrbuteName");
|
||||
}
|
||||
|
||||
_op = op;
|
||||
_attributeName = attrbuteName;
|
||||
_attributeValue = attrbuteValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expression as a string
|
||||
/// </summary>
|
||||
/// <returns>Expression string</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string sop;
|
||||
switch (_op)
|
||||
{
|
||||
case Op.NotExists:
|
||||
case Op.Exists:
|
||||
case Op.Equal:
|
||||
case Op.NotEqual:
|
||||
sop = EQUIAL;
|
||||
break;
|
||||
case Op.Greater:
|
||||
sop = GREATER;
|
||||
break;
|
||||
case Op.GreaterOrEqual:
|
||||
sop = GREATER_OR_EQUAL;
|
||||
break;
|
||||
case Op.Less:
|
||||
sop = LESS;
|
||||
break;
|
||||
case Op.LessOrEqual:
|
||||
sop = LESS_OR_EQUAL;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
var expressionString = "({0}{1}{2}{3})";
|
||||
expressionString = string.Format(expressionString,
|
||||
//positive or negative
|
||||
(((int)_op & 0x010000) == 0x010000 || _negative) ? "!" : "", _attributeName, sop,
|
||||
EscapeLdapSearchFilter(_attributeValue));
|
||||
|
||||
return expressionString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escapes the LDAP search filter to prevent LDAP injection attacks.
|
||||
/// </summary>
|
||||
/// <param name="searchFilter">The search filter.</param>
|
||||
/// <see cref="https://blogs.oracle.com/shankar/entry/what_is_ldap_injection" />
|
||||
/// <see cref="http://msdn.microsoft.com/en-us/library/aa746475.aspx" />
|
||||
/// <returns>The escaped search filter.</returns>
|
||||
private static string EscapeLdapSearchFilter(string searchFilter)
|
||||
{
|
||||
var escape = new StringBuilder(); // If using JDK >= 1.5 consider using StringBuilder
|
||||
foreach (var current in searchFilter)
|
||||
{
|
||||
switch (current)
|
||||
{
|
||||
case '\\':
|
||||
escape.Append(@"\5c");
|
||||
break;
|
||||
case '*':
|
||||
escape.Append(@"\2a");
|
||||
break;
|
||||
case '(':
|
||||
escape.Append(@"\28");
|
||||
break;
|
||||
case ')':
|
||||
escape.Append(@"\29");
|
||||
break;
|
||||
case '\u0000':
|
||||
escape.Append(@"\00");
|
||||
break;
|
||||
case '/':
|
||||
escape.Append(@"\2f");
|
||||
break;
|
||||
default:
|
||||
escape.Append(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return escape.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Negation
|
||||
/// </summary>
|
||||
/// <returns>Self</returns>
|
||||
public Expression Negative()
|
||||
{
|
||||
_negative = !_negative;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Existence
|
||||
/// </summary>
|
||||
/// <param name="attrbuteName"></param>
|
||||
/// <returns>New Expression</returns>
|
||||
public static Expression Exists(string attrbuteName)
|
||||
{
|
||||
return new Expression(attrbuteName, Op.Exists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Non-Existence
|
||||
/// </summary>
|
||||
/// <param name="attrbuteName"></param>
|
||||
/// <returns>New Expression</returns>
|
||||
public static Expression NotExists(string attrbuteName)
|
||||
{
|
||||
return new Expression(attrbuteName, Op.NotExists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality
|
||||
/// </summary>
|
||||
/// <param name="attrbuteName"></param>
|
||||
/// <param name="attrbuteValue"></param>
|
||||
/// <returns>New Expression</returns>
|
||||
public static Expression Equal(string attrbuteName, string attrbuteValue)
|
||||
{
|
||||
return new Expression(attrbuteName, Op.Equal, attrbuteValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not equality
|
||||
/// </summary>
|
||||
/// <param name="attrbuteName"></param>
|
||||
/// <param name="attrbuteValue"></param>
|
||||
/// <returns></returns>
|
||||
public static Expression NotEqual(string attrbuteName, string attrbuteValue)
|
||||
{
|
||||
return new Expression(attrbuteName, Op.NotEqual, attrbuteValue);
|
||||
}
|
||||
|
||||
public static Expression Parse(string origin)
|
||||
{
|
||||
string spliter = null;
|
||||
var op = Op.Equal;
|
||||
|
||||
var index = origin.IndexOf(EQUIAL, StringComparison.Ordinal);
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
spliter = EQUIAL;
|
||||
op = Op.Equal;
|
||||
}
|
||||
else if ((index = origin.IndexOf(GREATER, StringComparison.Ordinal)) > -1)
|
||||
{
|
||||
spliter = GREATER;
|
||||
op = Op.Greater;
|
||||
}
|
||||
else if ((index = origin.IndexOf(GREATER_OR_EQUAL, StringComparison.Ordinal)) > -1)
|
||||
{
|
||||
spliter = GREATER_OR_EQUAL;
|
||||
op = Op.GreaterOrEqual;
|
||||
}
|
||||
else if ((index = origin.IndexOf(LESS, StringComparison.Ordinal)) > -1)
|
||||
{
|
||||
spliter = LESS;
|
||||
op = Op.Less;
|
||||
}
|
||||
else if ((index = origin.IndexOf(LESS_OR_EQUAL, StringComparison.Ordinal)) > -1)
|
||||
{
|
||||
spliter = LESS_OR_EQUAL;
|
||||
op = Op.LessOrEqual;
|
||||
}
|
||||
else if ((index = origin.IndexOf(APPROXIMATELY_EQUIAL, StringComparison.Ordinal)) > -1)
|
||||
{
|
||||
spliter = APPROXIMATELY_EQUIAL;
|
||||
op = Op.Exists;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(spliter))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var attributeName = origin.Substring(0, index);
|
||||
var attributeValue = origin.Substring(index + 1);
|
||||
|
||||
if (string.IsNullOrEmpty(attributeName) || string.IsNullOrEmpty(attributeValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Expression(attributeName, op, attributeValue);
|
||||
}
|
||||
|
||||
#region ICloneable Members
|
||||
/// <summary>
|
||||
/// ICloneable implemetation
|
||||
/// </summary>
|
||||
/// <returns>Clone object</returns>
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
55
common/ASC.ActiveDirectory/Base/Expressions/Op.cs
Normal file
55
common/ASC.ActiveDirectory/Base/Expressions/Op.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Expressions;
|
||||
/// <summary>
|
||||
/// Operations
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// [1 - negation][1 - binary][number]
|
||||
/// </remarks>
|
||||
public enum Op
|
||||
{
|
||||
//------------ UNARY -------------
|
||||
/// <summary>Attribute exists</summary>
|
||||
Exists = 0x000001,
|
||||
/// <summary>Attribute does not exist</summary>
|
||||
NotExists = 0x010002,
|
||||
|
||||
//------------ BINARY -------------
|
||||
/// <summary>Equal</summary>
|
||||
Equal = 0x000103,
|
||||
/// <summary>Not equal</summary>
|
||||
NotEqual = 0x010104,
|
||||
/// <summary>Strong less</summary>
|
||||
Less = 0x000105,
|
||||
/// <summary>Less or equal</summary>
|
||||
LessOrEqual = 0x000106,
|
||||
/// <summary>Strong greater</summary>
|
||||
Greater = 0x000107,
|
||||
/// <summary>Greater or equal</summary>
|
||||
GreaterOrEqual = 0x000108
|
||||
}
|
415
common/ASC.ActiveDirectory/Base/LdapConstants.cs
Normal file
415
common/ASC.ActiveDirectory/Base/LdapConstants.cs
Normal file
@ -0,0 +1,415 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
/// <summary>
|
||||
/// Constants of Active Directory
|
||||
/// </summary>
|
||||
public sealed class LdapConstants
|
||||
{
|
||||
public const int STANDART_LDAP_PORT = 389;
|
||||
public const int SSL_LDAP_PORT = 636;
|
||||
public const int LDAP_ERROR_INVALID_CREDENTIALS = 0x31;
|
||||
public const int LDAP_V3 = 3;
|
||||
|
||||
public const string OBJECT_FILTER = "(ObjectClass=*)";
|
||||
|
||||
/// <summary>
|
||||
/// User Account type
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AccountType : uint
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_DOMAIN_OBJECT = 0x00000000,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_GROUP_OBJECT = 0x10000000,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_NON_SECURITY_GROUP_OBJECT = 0x10000001,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_ALIAS_OBJECT = 0x20000000,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_NON_SECURITY_ALIAS_OBJECT = 0x20000001,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_USER_OBJECT = 0x30000000,
|
||||
|
||||
//SAM_NORMAL_USER_ACCOUNT = 0x30000000,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_MACHINE_ACCOUNT = 0x30000001,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_TRUST_ACCOUNT = 0x30000002,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_APP_BASIC_GROUP = 0x40000000,
|
||||
|
||||
/// <summary></summary>
|
||||
SAM_APP_QUERY_GROUP = 0x40000001
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User Account Control
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum UserAccountControl : uint
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
/// <summary>Zero flag</summary>
|
||||
EMPTY = 0x00000000,
|
||||
|
||||
/// <summary>The logon script is executed.</summary>
|
||||
ADS_UF_SCRIPT = 0x00000001,
|
||||
|
||||
/// <summary>The user account is disabled.</summary>
|
||||
ADS_UF_ACCOUNTDISABLE = 0x00000002,
|
||||
|
||||
/// <summary>The home directory is required.</summary>
|
||||
ADS_UF_HOMEDIR_REQUIRED = 0x00000008,
|
||||
|
||||
/// <summary>The account is currently locked out.</summary>
|
||||
ADS_UF_LOCKOUT = 0x00000010,
|
||||
|
||||
/// <summary>No password is required.</summary>
|
||||
ADS_UF_PASSWD_NOTREQD = 0x00000020,
|
||||
|
||||
/// <summary>The user cannot change the password</summary>
|
||||
ADS_UF_PASSWD_CANT_CHANGE = 0x00000040,
|
||||
|
||||
/// <summary>The user can send an encrypted password.</summary>
|
||||
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x00000080,
|
||||
|
||||
/// <summary>This is an account for users whose primary account is in another domain.
|
||||
/// This account provides user access to this domain, but not to any domain that trusts
|
||||
/// this domain. Also known as a local user account.</summary>
|
||||
ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0x00000100,
|
||||
|
||||
/// <summary>This is a default account type that represents a typical user.</summary>
|
||||
ADS_UF_NORMAL_ACCOUNT = 0x00000200,
|
||||
|
||||
/// <summary>This is a computer account for a computer that is a member of this domain.</summary>
|
||||
ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x00001000,
|
||||
|
||||
/// <summary>This is a computer account for a system backup domain controller
|
||||
/// that is a member of this domain.</summary>
|
||||
ADS_UF_SERVER_TRUST_ACCOUNT = 0x00002000,
|
||||
|
||||
/// <summary>The password for this account will never expire.</summary>
|
||||
ADS_UF_DONT_EXPIRE_PASSWD = 0x00010000,
|
||||
|
||||
/// <summary>The user must log on using a smart card.</summary>
|
||||
ADS_UF_SMARTCARD_REQUIRED = 0x00040000,
|
||||
|
||||
/// <summary>The service account (user or computer account), under which a service runs,
|
||||
/// is trusted for Kerberos delegation. Any such service can impersonate a client
|
||||
/// requesting the service.</summary>
|
||||
ADS_UF_TRUSTED_FOR_DELEGATION = 0x00080000,
|
||||
|
||||
/// <summary>The security context of the user will not be delegated to a service even
|
||||
/// if the service account is set as trusted for Kerberos delegation.</summary>
|
||||
ADS_UF_NOT_DELEGATED = 0x00100000,
|
||||
|
||||
/// <summary>Restrict this principal to use only Data Encryption Standard
|
||||
/// (DES) encryption types for keys.</summary>
|
||||
ADS_UF_USE_DES_KEY_ONLY = 0x00200000,
|
||||
|
||||
/// <summary>This account does not require Kerberos pre-authentication for logon.</summary>
|
||||
ADS_UF_DONT_REQUIRE_PREAUTH = 0x00400000,
|
||||
|
||||
/// <summary>The user password has expired. This flag is created by the system
|
||||
/// using data from the Pwd-Last-Set attribute and the domain policy.</summary>
|
||||
ADS_UF_PASSWORD_EXPIRED = 0x00800000,
|
||||
|
||||
/// <summary>The account is enabled for delegation. This is a security-sensitive
|
||||
/// setting; accounts with this option enabled should be strictly controlled.
|
||||
/// This setting enables a service running under the account to assume a client
|
||||
/// identity and authenticate as that user to other remote servers on the network.</summary>
|
||||
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of Group
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum GroupType : uint
|
||||
{
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
/// <summary>System group</summary>
|
||||
SYSTEM = 0x00000001,
|
||||
|
||||
/// <summary>Global scope group</summary>
|
||||
GLOBAL_SCOPE = 0x00000002,
|
||||
|
||||
/// <summary>Local domain scope group</summary>
|
||||
LOCAL_DOMAIN_SCOPE = 0x00000004,
|
||||
|
||||
/// <summary>Universal scope group</summary>
|
||||
UNIVERSAL_SCOPE = 0x00000008,
|
||||
|
||||
/// <summary>Specifies an APP_BASIC group for Windows Server Authorization Manager.</summary>
|
||||
APP_BASIC = 0x000000010,
|
||||
|
||||
/// <summary>Specifies an APP_QUERY group for Windows Server Authorization Manager.</summary>
|
||||
APP_QUERY = 0x000000020,
|
||||
|
||||
/// <summary>Security group</summary>
|
||||
SECURITY_GROUP = 0x80000000
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schema attributes of Active Directory
|
||||
/// </summary>
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static class ADSchemaAttributes
|
||||
{
|
||||
/// <summary>Relative Distinguished Name </summary>
|
||||
public const string NAME = "name";
|
||||
|
||||
/// <summary>Common-Name</summary>
|
||||
public const string COMMON_NAME = "cn";
|
||||
|
||||
/// <summary>Display-Name</summary>
|
||||
public const string DISPLAY_NAME = "displayName";
|
||||
|
||||
/// <summary>The list of classes from which this class is derived.</summary>
|
||||
public const string OBJECT_CLASS = "objectClass";
|
||||
|
||||
/// <summary>DN category</summary>
|
||||
public const string OBJECT_CATEGORY = "objectCategory";
|
||||
|
||||
/// <summary>The unique identifier for an object.</summary>
|
||||
public const string OBJECT_GUID = "objectGUID";
|
||||
|
||||
/// <summary>Show-In-Advanced-View-Only</summary>
|
||||
public const string SHOW_IN_ADVANCED_VIEW_ONLY = "showInAdvancedViewOnly";
|
||||
|
||||
/// <summary>Obj-Dist-Name</summary>
|
||||
public const string DISTINGUISHED_NAME = "distinguishedName";
|
||||
|
||||
/// <summary>Is-Critical-System-Object</summary>
|
||||
public const string IS_CRITICAL_SYSTEM_OBJECT = "isCriticalSystemObject";
|
||||
|
||||
/// <summary>NT-Security-Descriptor in format SDDL</summary>
|
||||
public const string NT_SECURITY_DESCRIPTOR = "nTSecurityDescriptor";
|
||||
|
||||
/// <summary>Is-Member-Of-DL</summary>
|
||||
public const string MEMBER_OF = "memberOf";
|
||||
|
||||
/// <summary>Users which are members of this object</summary>
|
||||
public const string MEMBER = "member";
|
||||
|
||||
/// <summary>Organizational-Unit-Name</summary>
|
||||
public const string ORGANIZATIONAL_UNIT_NAME = "ou";
|
||||
|
||||
/// <summary>Organization-Name</summary>
|
||||
public const string ORGANIZATION_NAME = "o";
|
||||
|
||||
/// <summary>SAM-Account-Name</summary>
|
||||
public const string ACCOUNT_NAME = "sAMAccountName";
|
||||
|
||||
/// <summary>SAM-Account-Type</summary>
|
||||
public const string ACCOUNT_TYPE = "sAMAccountType";
|
||||
|
||||
/// <summary>A binary value that specifies the security identifier (SID) of the user.
|
||||
/// The SID is a unique value used to identify the user as a security principal.</summary>
|
||||
public const string OBJECT_SID = "objectSid"; //Object-Sid
|
||||
|
||||
/// <summary>Flags that control the behavior of the user account.</summary>
|
||||
public const string USER_ACCOUNT_CONTROL = "userAccountControl";
|
||||
|
||||
/// <summary>This attribute contains the UPN that is an Internet-style login name
|
||||
/// for a user based on the Internet standard RFC 822. The UPN is shorter than
|
||||
/// the distinguished name and easier to remember. By convention, this should map
|
||||
/// to the user e-mail name. The value set for this attribute is equal to the length
|
||||
/// of the user's ID and the domain name. For more information about this attribute,
|
||||
/// see the Naming Properties topic in the Active Directory guide.</summary>
|
||||
public const string USER_PRINCIPAL_NAME = "userPrincipalName";
|
||||
|
||||
/// <summary>Contains the given name (first name) of the user.</summary>
|
||||
public const string FIRST_NAME = "givenName";
|
||||
|
||||
/// <summary>This attribute contains the family or last name for a user.</summary>
|
||||
public const string SURNAME = "sn";
|
||||
|
||||
/// <summary>Primary-Group-ID</summary>
|
||||
public const string PRIMARY_GROUP_ID = "primaryGroupID";
|
||||
|
||||
/// <summary>Name of computer as registered in DNS</summary>
|
||||
public const string DNS_HOST_NAME = "dNSHostName";
|
||||
|
||||
/// <summary>The Operating System Version string </summary>
|
||||
public const string OPERATING_SYSTEM_VERSION = "operatingSystemVersion";
|
||||
|
||||
/// <summary>The Operating System Service Pack ID String </summary>
|
||||
public const string OPERATING_SYSTEM_SERVICE_PACK = "operatingSystemServicePack";
|
||||
|
||||
/// <summary>The hotfix level of the operating system.</summary>
|
||||
public const string OPERATING_SYSTEM_HOTFIX = "operatingSystemHotfix";
|
||||
|
||||
/// <summary>The Operating System name .</summary>
|
||||
public const string OPERATING_SYSTEM = "operatingSystem";
|
||||
|
||||
/// <summary>The TCP/IP address for a network segment. Also called the subnet address.</summary>
|
||||
public const string NETWORK_ADDRESS = "networkAddress";
|
||||
|
||||
/// <summary>Mobile phone</summary>
|
||||
public const string MOBILE = "mobile";
|
||||
|
||||
/// <summary>Email address</summary>
|
||||
public const string MAIL = "mail";
|
||||
|
||||
/// <summary>Telephone number</summary>
|
||||
public const string TELEPHONE_NUMBER = "telephoneNumber";
|
||||
|
||||
/// <summary>Title</summary>
|
||||
public const string TITLE = "title";
|
||||
|
||||
/// <summary>Street Address</summary>
|
||||
public const string STREET = "street";
|
||||
|
||||
/// <summary>Postal code</summary>
|
||||
public const string POSTAL_CODE = "postalCode";
|
||||
|
||||
/// <summary>Home phone</summary>
|
||||
public const string HOME_PHONE = "homePhone";
|
||||
|
||||
/// <summary>Initials</summary>
|
||||
public const string INITIALS = "initials";
|
||||
|
||||
/// <summary>Department</summary>
|
||||
public const string DIVISION = "division";
|
||||
|
||||
/// <summary>Company</summary>
|
||||
public const string COMPANY = "company";
|
||||
}
|
||||
|
||||
public static class RfcLDAPAttributes
|
||||
{
|
||||
public const string ENTRY_DN = "entryDN";
|
||||
public const string GUID = "GUID";
|
||||
public const string ENTRY_UUID = "entryUUID";
|
||||
public const string NS_UNIQUE_ID = "nsuniqueid";
|
||||
public const string UID = "uid";
|
||||
public const string MEMBER_UID = "memberUid";
|
||||
public const string DN = "dn";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Standart attributes of ObjectClass
|
||||
/// </summary>
|
||||
public static class ObjectClassKnowedValues
|
||||
{
|
||||
/// <summary>
|
||||
/// top value
|
||||
/// </summary>
|
||||
public const string TOP = "top";
|
||||
|
||||
/// <summary>
|
||||
/// Domain name
|
||||
/// </summary>
|
||||
public const string DOMAIN = "domain";
|
||||
|
||||
/// <summary>
|
||||
/// Domain DNS
|
||||
/// </summary>
|
||||
public const string DOMAIN_DNS = "domainDNS";
|
||||
|
||||
/// <summary>
|
||||
/// Group name
|
||||
/// </summary>
|
||||
public const string GROUP = "group";
|
||||
|
||||
/// <summary>
|
||||
/// posix-group
|
||||
/// </summary>
|
||||
public const string POSIX_GROUP = "posixGroup";
|
||||
|
||||
/// <summary>
|
||||
/// Person
|
||||
/// </summary>
|
||||
public const string PERSON = "person";
|
||||
|
||||
/// <summary>
|
||||
/// Container
|
||||
/// </summary>
|
||||
public const string CONTAINER = "container";
|
||||
|
||||
/// <summary>
|
||||
/// Org unit
|
||||
/// </summary>
|
||||
public const string ORGANIZATIONAL_UNIT = "organizationalUnit";
|
||||
|
||||
/// <summary>
|
||||
/// Org name
|
||||
/// </summary>
|
||||
public const string ORGANIZATION = "organization";
|
||||
|
||||
/// <summary>
|
||||
/// posix-account
|
||||
/// </summary>
|
||||
public const string POSIX_ACCOUNT = "posixAccount";
|
||||
|
||||
/// <summary>
|
||||
/// Org person
|
||||
/// </summary>
|
||||
public const string ORGANIZATIONAL_PERSON = "organizationalPerson";
|
||||
|
||||
/// <summary>
|
||||
/// User
|
||||
/// </summary>
|
||||
public const string USER = "user";
|
||||
|
||||
/// <summary>
|
||||
/// Computer
|
||||
/// </summary>
|
||||
public const string COMPUTER = "computer";
|
||||
|
||||
/// <summary>
|
||||
/// RPC container
|
||||
/// </summary>
|
||||
public const string RPC_CONTAINER = "rpcContainer";
|
||||
|
||||
/// <summary>
|
||||
/// Built in domain flag
|
||||
/// </summary>
|
||||
public const string BUILD_IN_DOMAIN = "builtinDomain";
|
||||
}
|
||||
}
|
158
common/ASC.ActiveDirectory/Base/LdapHelper.cs
Normal file
158
common/ASC.ActiveDirectory/Base/LdapHelper.cs
Normal file
@ -0,0 +1,158 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
|
||||
[Scope]
|
||||
public abstract class LdapHelper : IDisposable
|
||||
{
|
||||
public LdapSettings Settings { get; private set; }
|
||||
public abstract bool IsConnected { get; }
|
||||
|
||||
protected readonly ILogger<LdapHelper> _logger;
|
||||
protected readonly InstanceCrypto _instanceCrypto;
|
||||
|
||||
protected LdapHelper(
|
||||
ILogger<LdapHelper> logger,
|
||||
InstanceCrypto instanceCrypto)
|
||||
{
|
||||
_logger = logger;
|
||||
_instanceCrypto = instanceCrypto;
|
||||
}
|
||||
|
||||
public void Init(LdapSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public abstract void Connect();
|
||||
|
||||
public abstract Dictionary<string, string[]> GetCapabilities();
|
||||
|
||||
public abstract string SearchDomain();
|
||||
|
||||
public abstract void CheckCredentials(string login, string password, string server, int portNumber,
|
||||
bool startTls, bool ssl, bool acceptCertificate, string acceptCertificateHash);
|
||||
|
||||
public abstract bool CheckUserDn(string userDn);
|
||||
|
||||
public abstract List<LdapObject> GetUsers(string filter = null, int limit = -1);
|
||||
|
||||
public abstract LdapObject GetUserBySid(string sid);
|
||||
|
||||
public abstract bool CheckGroupDn(string groupDn);
|
||||
|
||||
public abstract List<LdapObject> GetGroups(Criteria criteria = null);
|
||||
|
||||
public bool UserExistsInGroup(LdapObject domainGroup, LdapObject domainUser, LdapSettings settings) // string memberString, string groupAttribute, string primaryGroupId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (domainGroup == null || domainUser == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var memberString = domainUser.GetValue(Settings.UserAttribute) as string;
|
||||
if (string.IsNullOrEmpty(memberString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var groupAttribute = settings.GroupAttribute;
|
||||
if (string.IsNullOrEmpty(groupAttribute))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var userPrimaryGroupId = domainUser.GetValue(LdapConstants.ADSchemaAttributes.PRIMARY_GROUP_ID) as string;
|
||||
|
||||
if (!string.IsNullOrEmpty(userPrimaryGroupId) && domainGroup.Sid.EndsWith("-" + userPrimaryGroupId))
|
||||
{
|
||||
// Domain Users found
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var members = domainGroup.GetValues(groupAttribute);
|
||||
|
||||
if (members.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (members.Any(member => memberString.Equals(member, StringComparison.InvariantCultureIgnoreCase)
|
||||
|| member.Equals(domainUser.DistinguishedName, StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorUserExistsInGroupFailed(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetPassword(byte[] passwordBytes)
|
||||
{
|
||||
if (passwordBytes == null || passwordBytes.Length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string password;
|
||||
try
|
||||
{
|
||||
password = _instanceCrypto.Decrypt(passwordBytes, new UnicodeEncoding());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
password = string.Empty;
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
public byte[] GetPasswordBytes(string password)
|
||||
{
|
||||
byte[] passwordBytes;
|
||||
|
||||
try
|
||||
{
|
||||
passwordBytes = _instanceCrypto.Encrypt(new UnicodeEncoding().GetBytes(password));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
passwordBytes = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
return passwordBytes;
|
||||
}
|
||||
|
||||
public abstract void Dispose();
|
||||
}
|
131
common/ASC.ActiveDirectory/Base/LdapNotifyHelper.cs
Normal file
131
common/ASC.ActiveDirectory/Base/LdapNotifyHelper.cs
Normal file
@ -0,0 +1,131 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
|
||||
[Singletone(Additional = typeof(LdapNotifyHelperExtension))]
|
||||
public class LdapNotifyService : BackgroundService
|
||||
{
|
||||
private readonly ConcurrentDictionary<int, Tuple<INotifyClient, LdapNotifySource>> _clients;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly WorkContext _workContext;
|
||||
private readonly LdapSaveSyncOperation _ldapSaveSyncOperation;
|
||||
private readonly NotifyEngineQueue _notifyEngineQueue;
|
||||
|
||||
public LdapNotifyService(
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
WorkContext workContext,
|
||||
LdapSaveSyncOperation ldapSaveSyncOperation,
|
||||
NotifyEngineQueue notifyEngineQueue)
|
||||
{
|
||||
_clients = new ConcurrentDictionary<int, Tuple<INotifyClient, LdapNotifySource>>();
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_workContext = workContext;
|
||||
_ldapSaveSyncOperation = ldapSaveSyncOperation;
|
||||
_notifyEngineQueue = notifyEngineQueue;
|
||||
}
|
||||
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<TenantManager>();
|
||||
var settingsManager = scope.ServiceProvider.GetRequiredService<SettingsManager>();
|
||||
var dbHelper = scope.ServiceProvider.GetRequiredService<DbHelper>();
|
||||
|
||||
var tenants = tenantManager.GetTenants(dbHelper.GetTenants());
|
||||
foreach (var t in tenants)
|
||||
{
|
||||
var tId = t.Id;
|
||||
|
||||
var ldapSettings = settingsManager.LoadForTenant<LdapSettings>(tId);
|
||||
if (!ldapSettings.EnableLdapAuthentication)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var cronSettings = settingsManager.LoadForTenant<LdapCronSettings>(tId);
|
||||
if (string.IsNullOrEmpty(cronSettings.Cron))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RegisterAutoSync(t, cronSettings.Cron);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void RegisterAutoSync(Tenant tenant, string cron)
|
||||
{
|
||||
if (!_clients.ContainsKey(tenant.Id))
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var source = scope.ServiceProvider.GetRequiredService<LdapNotifySource>();
|
||||
source.Init(tenant);
|
||||
var client = _workContext.NotifyContext.RegisterClient(_notifyEngineQueue, source);
|
||||
_workContext.RegisterSendMethod(source.AutoSync, cron);
|
||||
_clients.TryAdd(tenant.Id, new Tuple<INotifyClient, LdapNotifySource>(client, source));
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterAutoSync(Tenant tenant)
|
||||
{
|
||||
if (_clients.ContainsKey(tenant.Id))
|
||||
{
|
||||
var client = _clients[tenant.Id];
|
||||
_workContext.UnregisterSendMethod(client.Item2.AutoSync);
|
||||
_clients.TryRemove(tenant.Id, out _);
|
||||
}
|
||||
}
|
||||
|
||||
public void AutoSync(Tenant tenant)
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var settingsManager = scope.ServiceProvider.GetRequiredService<SettingsManager>();
|
||||
var ldapSettings = settingsManager.LoadForTenant<LdapSettings>(tenant.Id);
|
||||
|
||||
if (!ldapSettings.EnableLdapAuthentication)
|
||||
{
|
||||
var cronSettings = settingsManager.LoadForTenant<LdapCronSettings>(tenant.Id);
|
||||
cronSettings.Cron = "";
|
||||
settingsManager.SaveForTenant(cronSettings, tenant.Id);
|
||||
UnregisterAutoSync(tenant);
|
||||
return;
|
||||
}
|
||||
|
||||
_ldapSaveSyncOperation.RunJob(ldapSettings, tenant, LdapOperationType.Sync);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LdapNotifyHelperExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<DbHelper>();
|
||||
services.TryAdd<LdapNotifySource>();
|
||||
services.TryAdd<NotifyEngineQueue>();
|
||||
}
|
||||
}
|
74
common/ASC.ActiveDirectory/Base/LdapNotifySource.cs
Normal file
74
common/ASC.ActiveDirectory/Base/LdapNotifySource.cs
Normal file
@ -0,0 +1,74 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
|
||||
[Scope]
|
||||
public class LdapNotifySource : INotifySource
|
||||
{
|
||||
private Tenant _tenant;
|
||||
private readonly LdapNotifyService _ldapNotifyHelper;
|
||||
|
||||
public string Id
|
||||
{
|
||||
get { return "asc.activedirectory." + _tenant.Id; }
|
||||
}
|
||||
|
||||
public LdapNotifySource(LdapNotifyService ldapNotifyHelper)
|
||||
{
|
||||
_ldapNotifyHelper = ldapNotifyHelper;
|
||||
}
|
||||
|
||||
public void Init(Tenant tenant)
|
||||
{
|
||||
_tenant = tenant;
|
||||
}
|
||||
|
||||
public void AutoSync(DateTime date)
|
||||
{
|
||||
_ldapNotifyHelper.AutoSync(_tenant);
|
||||
}
|
||||
|
||||
public IActionProvider GetActionProvider()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPatternProvider GetPatternProvider()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IRecipientProvider GetRecipientsProvider()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ISubscriptionProvider GetSubscriptionProvider()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
934
common/ASC.ActiveDirectory/Base/LdapUserImporter.cs
Normal file
934
common/ASC.ActiveDirectory/Base/LdapUserImporter.cs
Normal file
@ -0,0 +1,934 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Constants = ASC.Core.Users.Constants;
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
[Scope]
|
||||
public class LdapUserImporter : IDisposable
|
||||
{
|
||||
public List<LdapObject> AllDomainUsers { get; private set; }
|
||||
public List<LdapObject> AllDomainGroups { get; private set; }
|
||||
|
||||
public Dictionary<LdapObject, LdapSettingsStatus> AllSkipedDomainUsers { get; private set; }
|
||||
public Dictionary<LdapObject, LdapSettingsStatus> AllSkipedDomainGroups { get; private set; }
|
||||
|
||||
private string _ldapDomain;
|
||||
private readonly string _unknownDomain;
|
||||
public string LDAPDomain
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_ldapDomain))
|
||||
{
|
||||
return _ldapDomain;
|
||||
}
|
||||
|
||||
_ldapDomain = LoadLDAPDomain();
|
||||
|
||||
if (string.IsNullOrEmpty(_ldapDomain))
|
||||
{
|
||||
_ldapDomain = _unknownDomain;
|
||||
}
|
||||
|
||||
return _ldapDomain;
|
||||
}
|
||||
}
|
||||
public List<string> PrimaryGroupIds { get; set; }
|
||||
|
||||
public LdapSettings Settings
|
||||
{
|
||||
get { return LdapHelper.Settings; }
|
||||
}
|
||||
|
||||
public LdapHelper LdapHelper { get; private set; }
|
||||
public LdapLocalization Resource { get; private set; }
|
||||
|
||||
private List<string> _watchedNestedGroups;
|
||||
|
||||
private readonly ILogger<LdapUserImporter> _logger;
|
||||
private readonly LdapObjectExtension _ldapObjectExtension;
|
||||
|
||||
private UserManager UserManager { get; set; }
|
||||
|
||||
public LdapUserImporter(
|
||||
ILogger<LdapUserImporter> logger,
|
||||
UserManager userManager,
|
||||
IConfiguration configuration,
|
||||
NovellLdapHelper novellLdapHelper,
|
||||
LdapObjectExtension ldapObjectExtension)
|
||||
{
|
||||
_unknownDomain = configuration["ldap:domain"] ?? "LDAP";
|
||||
AllDomainUsers = new List<LdapObject>();
|
||||
AllDomainGroups = new List<LdapObject>();
|
||||
AllSkipedDomainUsers = new Dictionary<LdapObject, LdapSettingsStatus>();
|
||||
AllSkipedDomainGroups = new Dictionary<LdapObject, LdapSettingsStatus>();
|
||||
|
||||
LdapHelper = novellLdapHelper;
|
||||
_logger = logger;
|
||||
UserManager = userManager;
|
||||
|
||||
_watchedNestedGroups = new List<string>();
|
||||
_ldapObjectExtension = ldapObjectExtension;
|
||||
}
|
||||
|
||||
public void Init(LdapSettings settings, LdapLocalization resource)
|
||||
{
|
||||
((NovellLdapHelper)LdapHelper).Init(settings);
|
||||
Resource = resource;
|
||||
}
|
||||
|
||||
public List<UserInfo> GetDiscoveredUsersByAttributes()
|
||||
{
|
||||
var users = new List<UserInfo>();
|
||||
|
||||
if (!AllDomainUsers.Any() && !TryLoadLDAPUsers())
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
var usersToAdd = AllDomainUsers.Select(ldapObject => _ldapObjectExtension.ToUserInfo(ldapObject, this));
|
||||
|
||||
users.AddRange(usersToAdd);
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public List<GroupInfo> GetDiscoveredGroupsByAttributes()
|
||||
{
|
||||
if (!Settings.GroupMembership)
|
||||
{
|
||||
return new List<GroupInfo>();
|
||||
}
|
||||
|
||||
if (!AllDomainGroups.Any() && !TryLoadLDAPGroups())
|
||||
{
|
||||
return new List<GroupInfo>();
|
||||
}
|
||||
|
||||
var groups = new List<GroupInfo>();
|
||||
|
||||
var groupsToAdd = AllDomainGroups.ConvertAll(g => _ldapObjectExtension.ToGroupInfo(g, Settings));
|
||||
|
||||
groups.AddRange(groupsToAdd);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
public List<UserInfo> GetGroupUsers(GroupInfo groupInfo)
|
||||
{
|
||||
return GetGroupUsers(groupInfo, true);
|
||||
}
|
||||
|
||||
private List<UserInfo> GetGroupUsers(GroupInfo groupInfo, bool clearCache)
|
||||
{
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
_logger.DebugGetGroupUsers(groupInfo.Name);
|
||||
|
||||
var users = new List<UserInfo>();
|
||||
|
||||
if (!AllDomainGroups.Any() && !TryLoadLDAPGroups())
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
var domainGroup = AllDomainGroups.FirstOrDefault(lg => lg.Sid.Equals(groupInfo.Sid));
|
||||
|
||||
if (domainGroup == null)
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
var members = _ldapObjectExtension.GetAttributes(domainGroup, Settings.GroupAttribute);
|
||||
|
||||
foreach (var member in members)
|
||||
{
|
||||
var ldapUser = FindUserByMember(member);
|
||||
|
||||
if (ldapUser == null)
|
||||
{
|
||||
var nestedLdapGroup = FindGroupByMember(member);
|
||||
|
||||
if (nestedLdapGroup != null)
|
||||
{
|
||||
_logger.DebugFoundNestedLdapGroup(nestedLdapGroup.DistinguishedName);
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
_watchedNestedGroups = new List<string>();
|
||||
}
|
||||
|
||||
if (_watchedNestedGroups.Contains(nestedLdapGroup.DistinguishedName))
|
||||
{
|
||||
_logger.DebugSkipAlreadyWatched(nestedLdapGroup.DistinguishedName);
|
||||
continue;
|
||||
}
|
||||
|
||||
_watchedNestedGroups.Add(nestedLdapGroup.DistinguishedName);
|
||||
|
||||
var nestedGroupInfo = _ldapObjectExtension.ToGroupInfo(nestedLdapGroup, Settings);
|
||||
|
||||
var nestedGroupUsers = GetGroupUsers(nestedGroupInfo, false);
|
||||
|
||||
foreach (var groupUser in nestedGroupUsers)
|
||||
{
|
||||
if (!users.Exists(u => u.Sid == groupUser.Sid))
|
||||
{
|
||||
users.Add(groupUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var userInfo = _ldapObjectExtension.ToUserInfo(ldapUser, this);
|
||||
|
||||
if (!users.Exists(u => u.Sid == userInfo.Sid))
|
||||
{
|
||||
users.Add(userInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (PrimaryGroupIds != null && PrimaryGroupIds.Any(id => domainGroup.Sid.EndsWith("-" + id)))
|
||||
{
|
||||
// Domain Users found
|
||||
var ldapUsers = FindUsersByPrimaryGroup(domainGroup.Sid);
|
||||
|
||||
foreach (var ldapUser in ldapUsers)
|
||||
{
|
||||
var userInfo = _ldapObjectExtension.ToUserInfo(ldapUser, this);
|
||||
|
||||
if (!users.Exists(u => u.Sid == userInfo.Sid))
|
||||
{
|
||||
users.Add(userInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
const string GROUP_MEMBERSHIP = "groupMembership";
|
||||
|
||||
private IEnumerable<LdapObject> GetLdapUserGroups(LdapObject ldapUser)
|
||||
{
|
||||
var ldapUserGroups = new List<LdapObject>();
|
||||
try
|
||||
{
|
||||
if (!Settings.GroupMembership)
|
||||
{
|
||||
return ldapUserGroups;
|
||||
}
|
||||
|
||||
if (ldapUser == null ||
|
||||
string.IsNullOrEmpty(ldapUser.Sid))
|
||||
{
|
||||
return ldapUserGroups;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
var userGroups = _ldapObjectExtension.GetAttributes(ldapUser, LdapConstants.ADSchemaAttributes.MEMBER_OF)
|
||||
.Select(s => LdapUtils.UnescapeLdapString(s))
|
||||
.ToList();
|
||||
|
||||
if (!userGroups.Any())
|
||||
{
|
||||
userGroups = _ldapObjectExtension.GetAttributes(ldapUser, GROUP_MEMBERSHIP);
|
||||
}
|
||||
|
||||
var searchExpressions = new List<Expression>();
|
||||
|
||||
var primaryGroupId = ldapUser.GetValue(LdapConstants.ADSchemaAttributes.PRIMARY_GROUP_ID) as string;
|
||||
|
||||
if (!string.IsNullOrEmpty(primaryGroupId))
|
||||
{
|
||||
var userSid = ldapUser.Sid;
|
||||
var index = userSid.LastIndexOf("-", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (index > -1)
|
||||
{
|
||||
var primaryGroupSid = userSid.Substring(0, index + 1) + primaryGroupId;
|
||||
searchExpressions.Add(Expression.Equal(ldapUser.SidAttribute, primaryGroupSid));
|
||||
}
|
||||
}
|
||||
|
||||
if (userGroups.Any())
|
||||
{
|
||||
var cnRegex = new Regex(",[A-z]{2}=");
|
||||
searchExpressions.AddRange(userGroups
|
||||
.Select(g => g.Substring(0, cnRegex.Match(g).Index))
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.Select(Expression.Parse)
|
||||
.Where(e => e != null));
|
||||
|
||||
var criteria = Criteria.Any(searchExpressions.ToArray());
|
||||
|
||||
var foundList = LdapHelper.GetGroups(criteria);
|
||||
|
||||
if (foundList.Any())
|
||||
{
|
||||
ldapUserGroups.AddRange(foundList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var ldapGroups = LdapHelper.GetGroups();
|
||||
|
||||
ldapUserGroups.AddRange(
|
||||
ldapGroups.Where(
|
||||
ldapGroup =>
|
||||
LdapHelper.UserExistsInGroup(ldapGroup, ldapUser, Settings)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ldapUser != null)
|
||||
{
|
||||
_logger.ErrorIsUserExistInGroups(ldapUser.DistinguishedName, ldapUser.Sid, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return ldapUserGroups;
|
||||
}
|
||||
|
||||
public IEnumerable<GroupInfo> GetAndCheckCurrentGroups(LdapObject ldapUser, IEnumerable<GroupInfo> portalGroups)
|
||||
{
|
||||
var result = new List<GroupInfo>();
|
||||
try
|
||||
{
|
||||
var searchExpressions = new List<Expression>();
|
||||
if (portalGroups != null && portalGroups.Any())
|
||||
{
|
||||
searchExpressions.AddRange(portalGroups.Select(g => Expression.Equal(LdapConstants.ADSchemaAttributes.OBJECT_SID, g.Sid)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var criteria = Criteria.Any(searchExpressions.ToArray());
|
||||
var foundList = LdapHelper.GetGroups(criteria);
|
||||
|
||||
if (foundList.Any())
|
||||
{
|
||||
var stillExistingGroups = portalGroups.Where(g => foundList.Any(fg => fg.Sid == g.Sid));
|
||||
|
||||
foreach (var group in stillExistingGroups)
|
||||
{
|
||||
if (GetGroupUsers(group).Any(u => u.Sid == ldapUser.Sid))
|
||||
{
|
||||
result.Add(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ldapUser != null)
|
||||
{
|
||||
_logger.ErrorGetAndCheckCurrentGroups(ldapUser.DistinguishedName, ldapUser.Sid, ex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TrySyncUserGroupMembership(Tuple<UserInfo, LdapObject> ldapUserInfo)
|
||||
{
|
||||
if (ldapUserInfo == null ||
|
||||
!Settings.GroupMembership)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var userInfo = ldapUserInfo.Item1;
|
||||
var ldapUser = ldapUserInfo.Item2;
|
||||
|
||||
var portalUserLdapGroups =
|
||||
UserManager.GetUserGroups(userInfo.Id, IncludeType.All)
|
||||
.Where(g => !string.IsNullOrEmpty(g.Sid))
|
||||
.ToList();
|
||||
|
||||
var ldapUserGroupList = new List<LdapObject>();
|
||||
|
||||
ldapUserGroupList.AddRange(GetLdapUserGroups(ldapUser));
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
var actualPortalLdapGroups = GetAndCheckCurrentGroups(ldapUser, portalUserLdapGroups).ToList();
|
||||
|
||||
foreach (var ldapUserGroup in ldapUserGroupList)
|
||||
{
|
||||
var groupInfo = UserManager.GetGroupInfoBySid(ldapUserGroup.Sid);
|
||||
|
||||
if (Equals(groupInfo, Constants.LostGroupInfo))
|
||||
{
|
||||
_logger.DebugTrySyncUserGroupMembershipCreatingPortalGroup(ldapUserGroup.DistinguishedName, ldapUserGroup.Sid);
|
||||
groupInfo = UserManager.SaveGroupInfo(_ldapObjectExtension.ToGroupInfo(ldapUserGroup, Settings));
|
||||
|
||||
_logger.DebugTrySyncUserGroupMembershipAddingUserToGroup(userInfo.UserName, ldapUser.Sid, groupInfo.Name, groupInfo.Sid);
|
||||
UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID);
|
||||
}
|
||||
else if (!portalUserLdapGroups.Contains(groupInfo))
|
||||
{
|
||||
_logger.DebugTrySyncUserGroupMembershipAddingUserToGroup(userInfo.UserName, ldapUser.Sid, groupInfo.Name, groupInfo.Sid);
|
||||
UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID);
|
||||
}
|
||||
|
||||
actualPortalLdapGroups.Add(groupInfo);
|
||||
}
|
||||
|
||||
foreach (var portalUserLdapGroup in portalUserLdapGroups)
|
||||
{
|
||||
if (!actualPortalLdapGroups.Contains(portalUserLdapGroup))
|
||||
{
|
||||
_logger.DebugTrySyncUserGroupMembershipRemovingUserFromGroup(userInfo.UserName, ldapUser.Sid, portalUserLdapGroup.Name, portalUserLdapGroup.Sid);
|
||||
UserManager.RemoveUserFromGroup(userInfo.Id, portalUserLdapGroup.ID);
|
||||
}
|
||||
}
|
||||
|
||||
return actualPortalLdapGroups.Count != 0;
|
||||
}
|
||||
|
||||
public bool TryLoadLDAPUsers()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Settings.EnableLdapAuthentication)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
var users = LdapHelper.GetUsers();
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
if (string.IsNullOrEmpty(user.Sid))
|
||||
{
|
||||
AllSkipedDomainUsers.Add(user, LdapSettingsStatus.WrongSidAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CheckLoginAttribute(user, Settings.LoginAttribute))
|
||||
{
|
||||
AllSkipedDomainUsers.Add(user, LdapSettingsStatus.WrongLoginAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Settings.GroupMembership)
|
||||
{
|
||||
AllDomainUsers.Add(user);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Settings.UserAttribute.Equals(LdapConstants.RfcLDAPAttributes.DN,
|
||||
StringComparison.InvariantCultureIgnoreCase) && !CheckUserAttribute(user, Settings.UserAttribute))
|
||||
{
|
||||
AllSkipedDomainUsers.Add(user, LdapSettingsStatus.WrongUserAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
AllDomainUsers.Add(user);
|
||||
}
|
||||
|
||||
if (AllDomainUsers.Any())
|
||||
{
|
||||
PrimaryGroupIds = AllDomainUsers.Select(u => u.GetValue(LdapConstants.ADSchemaAttributes.PRIMARY_GROUP_ID)).Cast<string>()
|
||||
.Distinct().ToList();
|
||||
}
|
||||
|
||||
return AllDomainUsers.Any() || !users.Any();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
_logger.ErrorTryLoadLDAPUsersIncorrectUserFilter(Settings.UserFilter);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryLoadLDAPGroups()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Settings.EnableLdapAuthentication || !Settings.GroupMembership)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
var groups = LdapHelper.GetGroups();
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (string.IsNullOrEmpty(group.Sid))
|
||||
{
|
||||
AllSkipedDomainGroups.Add(group, LdapSettingsStatus.WrongSidAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CheckGroupAttribute(group, Settings.GroupAttribute))
|
||||
{
|
||||
AllSkipedDomainGroups.Add(group, LdapSettingsStatus.WrongGroupAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CheckGroupNameAttribute(group, Settings.GroupNameAttribute))
|
||||
{
|
||||
AllSkipedDomainGroups.Add(group, LdapSettingsStatus.WrongGroupNameAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
AllDomainGroups.Add(group);
|
||||
}
|
||||
|
||||
return AllDomainGroups.Any() || !groups.Any();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
_logger.ErrorTryLoadLDAPUsersIncorrectGroupFilter(Settings.GroupFilter);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string LoadLDAPDomain()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Settings.EnableLdapAuthentication)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
string ldapDomain;
|
||||
|
||||
if (AllDomainUsers.Any())
|
||||
{
|
||||
ldapDomain = _ldapObjectExtension.GetDomainFromDn(AllDomainUsers.First());
|
||||
|
||||
if (!string.IsNullOrEmpty(ldapDomain))
|
||||
{
|
||||
return ldapDomain;
|
||||
}
|
||||
}
|
||||
|
||||
ldapDomain = LdapHelper.SearchDomain();
|
||||
|
||||
if (!string.IsNullOrEmpty(ldapDomain))
|
||||
{
|
||||
return ldapDomain;
|
||||
}
|
||||
|
||||
ldapDomain = LdapUtils.DistinguishedNameToDomain(Settings.UserDN);
|
||||
|
||||
if (!string.IsNullOrEmpty(ldapDomain))
|
||||
{
|
||||
return ldapDomain;
|
||||
}
|
||||
|
||||
ldapDomain = LdapUtils.DistinguishedNameToDomain(Settings.GroupDN);
|
||||
|
||||
if (!string.IsNullOrEmpty(ldapDomain))
|
||||
{
|
||||
return ldapDomain;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorLoadLDAPDomain(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected bool CheckLoginAttribute(LdapObject user, string loginAttribute)
|
||||
{
|
||||
try
|
||||
{
|
||||
var member = user.GetValue(loginAttribute);
|
||||
if (member == null || string.IsNullOrWhiteSpace(member.ToString()))
|
||||
{
|
||||
_logger.DebugLoginAttributeParameterNotFound(Settings.LoginAttribute, user.DistinguishedName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorLoginAttributeParameterNotFound(Settings.LoginAttribute, loginAttribute, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool CheckUserAttribute(LdapObject user, string userAttr)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userAttribute = user.GetValue(userAttr);
|
||||
if (userAttribute == null || string.IsNullOrWhiteSpace(userAttribute.ToString()))
|
||||
{
|
||||
_logger.DebugUserAttributeParameterNotFound(Settings.UserAttribute,
|
||||
user.DistinguishedName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorUserAttributeParameterNotFound(Settings.UserAttribute, userAttr, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool CheckGroupAttribute(LdapObject group, string groupAttr)
|
||||
{
|
||||
try
|
||||
{
|
||||
group.GetValue(groupAttr); // Group attribute can be empty - example => Domain users
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorGroupAttributeParameterNotFound(Settings.GroupAttribute, groupAttr, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool CheckGroupNameAttribute(LdapObject group, string groupAttr)
|
||||
{
|
||||
try
|
||||
{
|
||||
var groupNameAttribute = group.GetValues(groupAttr);
|
||||
if (!groupNameAttribute.Any())
|
||||
{
|
||||
_logger.DebugGroupNameAttributeParameterNotFound(Settings.GroupNameAttribute,
|
||||
groupAttr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorGroupAttributeParameterNotFound(Settings.GroupNameAttribute,
|
||||
groupAttr, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<LdapObject> FindUsersByPrimaryGroup(string sid)
|
||||
{
|
||||
_logger.DebugFindUsersByPrimaryGroup();
|
||||
|
||||
if (!AllDomainUsers.Any() && !TryLoadLDAPUsers())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return
|
||||
AllDomainUsers.Where(
|
||||
lu =>
|
||||
{
|
||||
var primaryGroupId = lu.GetValue(LdapConstants.ADSchemaAttributes.PRIMARY_GROUP_ID) as string;
|
||||
|
||||
return !string.IsNullOrEmpty(primaryGroupId) &&
|
||||
sid.EndsWith(primaryGroupId);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
}
|
||||
|
||||
private LdapObject FindUserByMember(string userAttributeValue)
|
||||
{
|
||||
if (!AllDomainUsers.Any() && !TryLoadLDAPUsers())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.DebugFindUserByMember(userAttributeValue);
|
||||
|
||||
return AllDomainUsers.FirstOrDefault(u =>
|
||||
u.DistinguishedName.Equals(userAttributeValue, StringComparison.InvariantCultureIgnoreCase)
|
||||
|| Convert.ToString(u.GetValue(Settings.UserAttribute)).Equals(userAttributeValue,
|
||||
StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
private LdapObject FindGroupByMember(string member)
|
||||
{
|
||||
if (!AllDomainGroups.Any() && !TryLoadLDAPGroups())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.DebugFindGroupByMember(member);
|
||||
|
||||
return AllDomainGroups.FirstOrDefault(g =>
|
||||
g.DistinguishedName.Equals(member, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public List<Tuple<UserInfo, LdapObject>> FindLdapUsers(string login)
|
||||
{
|
||||
var listResults = new List<Tuple<UserInfo, LdapObject>>();
|
||||
|
||||
var ldapLogin = LdapLogin.ParseLogin(login);
|
||||
|
||||
if (ldapLogin == null)
|
||||
{
|
||||
return listResults;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
|
||||
var exps = new List<Expression> { Expression.Equal(Settings.LoginAttribute, ldapLogin.Username) };
|
||||
|
||||
if (!ldapLogin.Username.Equals(login) && ldapLogin.ToString().Equals(login))
|
||||
{
|
||||
exps.Add(Expression.Equal(Settings.LoginAttribute, login));
|
||||
}
|
||||
|
||||
string email = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(Settings.MailAttribute) && !string.IsNullOrEmpty(ldapLogin.Domain) && login.Contains("@"))
|
||||
{
|
||||
email = ldapLogin.ToString();
|
||||
exps.Add(Expression.Equal(Settings.MailAttribute, email));
|
||||
}
|
||||
|
||||
var searchTerm = exps.Count > 1 ? Criteria.Any(exps.ToArray()).ToString() : exps.First().ToString();
|
||||
|
||||
var users = LdapHelper.GetUsers(searchTerm, !string.IsNullOrEmpty(email) ? -1 : 1)
|
||||
.Where(user => user != null)
|
||||
.ToLookup(lu =>
|
||||
{
|
||||
var ui = Constants.LostUser;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(_ldapDomain))
|
||||
{
|
||||
_ldapDomain = LdapUtils.DistinguishedNameToDomain(lu.DistinguishedName);
|
||||
}
|
||||
|
||||
ui = _ldapObjectExtension.ToUserInfo(lu, this);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorToUserInfo(ex);
|
||||
}
|
||||
|
||||
return Tuple.Create(ui, lu);
|
||||
|
||||
});
|
||||
|
||||
if (!users.Any())
|
||||
{
|
||||
return listResults;
|
||||
}
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
var ui = user.Key.Item1;
|
||||
|
||||
if (ui.Equals(Constants.LostUser))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var ul = user.Key.Item2;
|
||||
|
||||
var ldapLoginAttribute = ul.GetValue(Settings.LoginAttribute) as string;
|
||||
|
||||
if (string.IsNullOrEmpty(ldapLoginAttribute))
|
||||
{
|
||||
_logger.WarnLoginAttributeIsEmpty(ul.DistinguishedName, Settings.LoginAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ldapLoginAttribute.Equals(login))
|
||||
{
|
||||
listResults.Add(user.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(email))
|
||||
{
|
||||
if (ui.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
listResults.Add(user.Key);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (LdapUtils.IsLoginAccepted(ldapLogin, ui, LDAPDomain))
|
||||
{
|
||||
listResults.Add(user.Key);
|
||||
}
|
||||
}
|
||||
|
||||
return listResults;
|
||||
}
|
||||
|
||||
public List<LdapObject> FindUsersByAttribute(string key, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase)
|
||||
{
|
||||
var users = new List<LdapObject>();
|
||||
|
||||
if (!AllDomainUsers.Any() && !TryLoadLDAPUsers())
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
return users.Where(us => !us.IsDisabled && string.Equals((string)us.GetValue(key), value, comparison)).ToList();
|
||||
}
|
||||
|
||||
public List<LdapObject> FindUsersByAttribute(string key, IEnumerable<string> value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase)
|
||||
{
|
||||
var users = new List<LdapObject>();
|
||||
|
||||
if (!AllDomainUsers.Any() && !TryLoadLDAPUsers())
|
||||
{
|
||||
return users;
|
||||
}
|
||||
|
||||
return AllDomainUsers.Where(us => !us.IsDisabled && value.Any(val => string.Equals(val, (string)us.GetValue(key), comparison))).ToList();
|
||||
}
|
||||
|
||||
public List<LdapObject> FindGroupsByAttribute(string key, string value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase)
|
||||
{
|
||||
var gr = new List<LdapObject>();
|
||||
|
||||
if (!AllDomainGroups.Any() && !TryLoadLDAPGroups())
|
||||
{
|
||||
return gr;
|
||||
}
|
||||
|
||||
return gr.Where(g => !g.IsDisabled && string.Equals((string)g.GetValue(key), value, comparison)).ToList();
|
||||
}
|
||||
|
||||
public List<LdapObject> FindGroupsByAttribute(string key, IEnumerable<string> value, StringComparison comparison = StringComparison.InvariantCultureIgnoreCase)
|
||||
{
|
||||
var gr = new List<LdapObject>();
|
||||
|
||||
if (!AllDomainGroups.Any() && !TryLoadLDAPGroups())
|
||||
{
|
||||
return gr;
|
||||
}
|
||||
|
||||
return AllDomainGroups.Where(g => !g.IsDisabled && value.Any(val => string.Equals(val, (string)g.GetValue(key), comparison))).ToList();
|
||||
}
|
||||
|
||||
public Tuple<UserInfo, LdapObject> Login(string login, string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ldapUsers = FindLdapUsers(login);
|
||||
|
||||
_logger.DebugFindLdapUsers(login, ldapUsers.Count);
|
||||
|
||||
foreach (var ldapUser in ldapUsers)
|
||||
{
|
||||
string currentLogin = null;
|
||||
try
|
||||
{
|
||||
var ldapUserInfo = ldapUser.Item1;
|
||||
var ldapUserObject = ldapUser.Item2;
|
||||
|
||||
if (ldapUserInfo.Equals(Constants.LostUser)
|
||||
|| ldapUserObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(ldapUserObject.DistinguishedName)
|
||||
|| string.IsNullOrEmpty(ldapUserObject.Sid))
|
||||
{
|
||||
_logger.DebugLdapUserImporterFailed(login, ldapUserObject.Sid);
|
||||
continue;
|
||||
}
|
||||
|
||||
currentLogin = ldapUserObject.DistinguishedName;
|
||||
|
||||
_logger.DebugLdapUserImporterLogin(currentLogin);
|
||||
|
||||
LdapHelper.CheckCredentials(currentLogin, password, Settings.Server,
|
||||
Settings.PortNumber, Settings.StartTls, Settings.Ssl, Settings.AcceptCertificate,
|
||||
Settings.AcceptCertificateHash);
|
||||
|
||||
return new Tuple<UserInfo, LdapObject>(ldapUserInfo, ldapUserObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorLdapUserImporterLoginFailed(currentLogin ?? login, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorLdapUserImporterLoginFailed(login, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (LdapHelper != null)
|
||||
{
|
||||
LdapHelper.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
81
common/ASC.ActiveDirectory/Base/NotifyConstants.cs
Normal file
81
common/ASC.ActiveDirectory/Base/NotifyConstants.cs
Normal file
@ -0,0 +1,81 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base;
|
||||
|
||||
public static class NotifyConstants
|
||||
{
|
||||
public static string TagUserName = "UserName";
|
||||
public static string TagUserEmail = "UserEmail";
|
||||
public static string TagMyStaffLink = "MyStaffLink";
|
||||
|
||||
public static INotifyAction ActionLdapActivation = new NotifyAction("user_ldap_activation");
|
||||
|
||||
public static ITagValue TagGreenButton(string btnText, string btnUrl)
|
||||
{
|
||||
Func<string> action = () =>
|
||||
{
|
||||
return
|
||||
string.Format(@"<table style=""height: 48px; width: 540px; border-collapse: collapse; empty-cells: show; vertical-align: middle; text-align: center; margin: 30px auto; padding: 0;""><tbody><tr cellpadding=""0"" cellspacing=""0"" border=""0"">{2}<td style=""height: 48px; width: 380px; margin:0; padding:0; background-color: #66b76d; -moz-border-radius: 2px; -webkit-border-radius: 2px; border-radius: 2px;""><a style=""{3}"" target=""_blank"" href=""{0}"">{1}</a></td>{2}</tr></tbody></table>",
|
||||
btnUrl,
|
||||
btnText,
|
||||
"<td style=\"height: 48px; width: 80px; margin:0; padding:0;\"> </td>",
|
||||
"color: #fff; font-family: Helvetica, Arial, Tahoma; font-size: 18px; font-weight: 600; vertical-align: middle; display: block; padding: 12px 0; text-align: center; text-decoration: none; background-color: #66b76d;");
|
||||
};
|
||||
return new TagActionValue("GreenButton", action);
|
||||
}
|
||||
|
||||
private class TagActionValue : ITagValue
|
||||
{
|
||||
private readonly Func<string> action;
|
||||
|
||||
public string Tag
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return action(); }
|
||||
}
|
||||
|
||||
public TagActionValue(string name, Func<string> action)
|
||||
{
|
||||
Tag = name;
|
||||
this.action = action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class NotifyCommonTags
|
||||
{
|
||||
public static string Footer = "Footer";
|
||||
|
||||
public static string MasterTemplate = "MasterTemplate";
|
||||
|
||||
public static string WithoutUnsubscribe = "WithoutUnsubscribe";
|
||||
}
|
458
common/ASC.ActiveDirectory/Base/Settings/LdapSettings.cs
Normal file
458
common/ASC.ActiveDirectory/Base/Settings/LdapSettings.cs
Normal file
@ -0,0 +1,458 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Settings;
|
||||
|
||||
[Scope]
|
||||
[Serializable]
|
||||
public class LdapSettings : ISettings<LdapSettings>, ICloneable
|
||||
{
|
||||
[JsonIgnore]
|
||||
public Guid ID
|
||||
{
|
||||
get { return new Guid("{197149b3-fbc9-44c2-b42a-232f7e729c16}"); }
|
||||
}
|
||||
|
||||
public LdapSettings()
|
||||
{
|
||||
LdapMapping = new Dictionary<MappingFields, string>();
|
||||
AccessRights = new Dictionary<AccessRight, string>();
|
||||
}
|
||||
|
||||
public enum MappingFields
|
||||
{
|
||||
FirstNameAttribute,
|
||||
SecondNameAttribute,
|
||||
BirthDayAttribute,
|
||||
GenderAttribute,
|
||||
MobilePhoneAttribute,
|
||||
MailAttribute,
|
||||
TitleAttribute,
|
||||
LocationAttribute,
|
||||
AvatarAttribute,
|
||||
|
||||
AdditionalPhone,
|
||||
AdditionalMobilePhone,
|
||||
AdditionalMail,
|
||||
Skype
|
||||
}
|
||||
|
||||
public enum AccessRight
|
||||
{
|
||||
FullAccess,
|
||||
Documents,
|
||||
Projects,
|
||||
CRM,
|
||||
Community,
|
||||
People,
|
||||
Mail
|
||||
}
|
||||
|
||||
public static readonly Dictionary<AccessRight, Guid> AccessRightsGuids = new Dictionary<AccessRight, Guid>()
|
||||
{
|
||||
{ AccessRight.FullAccess, Guid.Empty },
|
||||
{ AccessRight.Documents, WebItemManager.DocumentsProductID },
|
||||
{ AccessRight.Projects, WebItemManager.ProjectsProductID },
|
||||
{ AccessRight.CRM, WebItemManager.CRMProductID },
|
||||
{ AccessRight.Community, WebItemManager.CommunityProductID },
|
||||
{ AccessRight.People, WebItemManager.PeopleProductID },
|
||||
{ AccessRight.Mail, WebItemManager.MailProductID }
|
||||
};
|
||||
|
||||
public LdapSettings GetDefault()
|
||||
{
|
||||
var isMono = WorkContext.IsMono;
|
||||
|
||||
var settings = new LdapSettings()
|
||||
{
|
||||
Server = "",
|
||||
UserDN = "",
|
||||
PortNumber = LdapConstants.STANDART_LDAP_PORT,
|
||||
UserFilter = string.Format("({0}=*)",
|
||||
isMono
|
||||
? LdapConstants.RfcLDAPAttributes.UID
|
||||
: LdapConstants.ADSchemaAttributes.USER_PRINCIPAL_NAME),
|
||||
LoginAttribute = isMono
|
||||
? LdapConstants.RfcLDAPAttributes.UID
|
||||
: LdapConstants.ADSchemaAttributes.ACCOUNT_NAME,
|
||||
FirstNameAttribute = LdapConstants.ADSchemaAttributes.FIRST_NAME,
|
||||
SecondNameAttribute = LdapConstants.ADSchemaAttributes.SURNAME,
|
||||
MailAttribute = LdapConstants.ADSchemaAttributes.MAIL,
|
||||
TitleAttribute = LdapConstants.ADSchemaAttributes.TITLE,
|
||||
MobilePhoneAttribute = LdapConstants.ADSchemaAttributes.MOBILE,
|
||||
LocationAttribute = LdapConstants.ADSchemaAttributes.STREET,
|
||||
GroupDN = "",
|
||||
GroupFilter = string.Format("({0}={1})", LdapConstants.ADSchemaAttributes.OBJECT_CLASS,
|
||||
isMono
|
||||
? LdapConstants.ObjectClassKnowedValues.POSIX_GROUP
|
||||
: LdapConstants.ObjectClassKnowedValues.GROUP),
|
||||
UserAttribute =
|
||||
isMono
|
||||
? LdapConstants.RfcLDAPAttributes.UID
|
||||
: LdapConstants.ADSchemaAttributes.DISTINGUISHED_NAME,
|
||||
GroupAttribute = isMono ? LdapConstants.RfcLDAPAttributes.MEMBER_UID : LdapConstants.ADSchemaAttributes.MEMBER,
|
||||
GroupNameAttribute = LdapConstants.ADSchemaAttributes.COMMON_NAME,
|
||||
Authentication = true,
|
||||
AcceptCertificate = false,
|
||||
AcceptCertificateHash = null,
|
||||
StartTls = false,
|
||||
Ssl = false,
|
||||
SendWelcomeEmail = false
|
||||
};
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var settings = obj as LdapSettings;
|
||||
|
||||
return settings != null
|
||||
&& EnableLdapAuthentication == settings.EnableLdapAuthentication
|
||||
&& StartTls == settings.StartTls
|
||||
&& Ssl == settings.Ssl
|
||||
&& SendWelcomeEmail == settings.SendWelcomeEmail
|
||||
&& (string.IsNullOrEmpty(Server)
|
||||
&& string.IsNullOrEmpty(settings.Server)
|
||||
|| Server == settings.Server)
|
||||
&& (string.IsNullOrEmpty(UserDN)
|
||||
&& string.IsNullOrEmpty(settings.UserDN)
|
||||
|| UserDN == settings.UserDN)
|
||||
&& PortNumber == settings.PortNumber
|
||||
&& UserFilter == settings.UserFilter
|
||||
&& LoginAttribute == settings.LoginAttribute
|
||||
&& LdapMapping.Count == settings.LdapMapping.Count
|
||||
&& LdapMapping.All(pair => settings.LdapMapping.ContainsKey(pair.Key)
|
||||
&& pair.Value == settings.LdapMapping[pair.Key])
|
||||
&& AccessRights.Count == settings.AccessRights.Count
|
||||
&& AccessRights.All(pair => settings.AccessRights.ContainsKey(pair.Key)
|
||||
&& pair.Value == settings.AccessRights[pair.Key])
|
||||
&& GroupMembership == settings.GroupMembership
|
||||
&& (string.IsNullOrEmpty(GroupDN)
|
||||
&& string.IsNullOrEmpty(settings.GroupDN)
|
||||
|| GroupDN == settings.GroupDN)
|
||||
&& GroupFilter == settings.GroupFilter
|
||||
&& UserAttribute == settings.UserAttribute
|
||||
&& GroupAttribute == settings.GroupAttribute
|
||||
&& (string.IsNullOrEmpty(Login)
|
||||
&& string.IsNullOrEmpty(settings.Login)
|
||||
|| Login == settings.Login)
|
||||
&& Authentication == settings.Authentication;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = 3;
|
||||
hash = (hash * 2) + EnableLdapAuthentication.GetHashCode();
|
||||
hash = (hash * 2) + StartTls.GetHashCode();
|
||||
hash = (hash * 2) + Ssl.GetHashCode();
|
||||
hash = (hash * 2) + SendWelcomeEmail.GetHashCode();
|
||||
hash = (hash * 2) + Server.GetHashCode();
|
||||
hash = (hash * 2) + UserDN.GetHashCode();
|
||||
hash = (hash * 2) + PortNumber.GetHashCode();
|
||||
hash = (hash * 2) + UserFilter.GetHashCode();
|
||||
hash = (hash * 2) + LoginAttribute.GetHashCode();
|
||||
hash = (hash * 2) + GroupMembership.GetHashCode();
|
||||
hash = (hash * 2) + GroupDN.GetHashCode();
|
||||
hash = (hash * 2) + GroupNameAttribute.GetHashCode();
|
||||
hash = (hash * 2) + GroupFilter.GetHashCode();
|
||||
hash = (hash * 2) + UserAttribute.GetHashCode();
|
||||
hash = (hash * 2) + GroupAttribute.GetHashCode();
|
||||
hash = (hash * 2) + Authentication.GetHashCode();
|
||||
hash = (hash * 2) + Login.GetHashCode();
|
||||
|
||||
foreach (var pair in LdapMapping)
|
||||
{
|
||||
hash = (hash * 2) + pair.Value.GetHashCode();
|
||||
}
|
||||
|
||||
foreach (var pair in AccessRights)
|
||||
{
|
||||
hash = (hash * 2) + pair.Value.GetHashCode();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return MemberwiseClone();
|
||||
}
|
||||
|
||||
public bool EnableLdapAuthentication { get; set; }
|
||||
|
||||
public bool StartTls { get; set; }
|
||||
|
||||
public bool Ssl { get; set; }
|
||||
|
||||
public bool SendWelcomeEmail { get; set; }
|
||||
|
||||
public string Server { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string UserDN { get; set; }
|
||||
|
||||
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
|
||||
public int PortNumber { get; set; }
|
||||
|
||||
public string UserFilter { get; set; }
|
||||
|
||||
public string LoginAttribute { get; set; }
|
||||
|
||||
public Dictionary<MappingFields, string> LdapMapping { get; set; }
|
||||
|
||||
//ToDo: use SId instead of group name
|
||||
public Dictionary<AccessRight, string> AccessRights { get; set; }
|
||||
|
||||
public string FirstNameAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.FirstNameAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.FirstNameAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string SecondNameAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.SecondNameAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.SecondNameAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string MailAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.MailAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.MailAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string TitleAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.TitleAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.TitleAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string MobilePhoneAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.MobilePhoneAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.MobilePhoneAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string LocationAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetOldSetting(MappingFields.LocationAttribute);
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SetOldSetting(MappingFields.LocationAttribute, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool GroupMembership { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string GroupDN { get; set; }
|
||||
|
||||
public string GroupNameAttribute { get; set; }
|
||||
|
||||
public string GroupFilter { get; set; }
|
||||
|
||||
public string UserAttribute { get; set; }
|
||||
|
||||
public string GroupAttribute { get; set; }
|
||||
|
||||
public bool Authentication { get; set; }
|
||||
|
||||
public string Login { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public byte[] PasswordBytes { get; set; }
|
||||
|
||||
public bool IsDefault { get; set; }
|
||||
|
||||
public bool AcceptCertificate { get; set; }
|
||||
|
||||
public string AcceptCertificateHash { get; set; }
|
||||
|
||||
private string GetOldSetting(MappingFields field)
|
||||
{
|
||||
if (LdapMapping == null)
|
||||
{
|
||||
LdapMapping = new Dictionary<MappingFields, string>();
|
||||
}
|
||||
|
||||
if (LdapMapping.ContainsKey(field))
|
||||
{
|
||||
return LdapMapping[field];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
private void SetOldSetting(MappingFields field, string value)
|
||||
{
|
||||
if (LdapMapping == null)
|
||||
{
|
||||
LdapMapping = new Dictionary<MappingFields, string>();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (LdapMapping.ContainsKey(field))
|
||||
{
|
||||
LdapMapping.Remove(field);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (LdapMapping.ContainsKey(field))
|
||||
{
|
||||
LdapMapping[field] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LdapMapping.Add(field, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
[Serializable]
|
||||
public class LdapCronSettings : ISettings<LdapCronSettings>
|
||||
{
|
||||
[JsonIgnore]
|
||||
public Guid ID
|
||||
{
|
||||
get { return new Guid("{58C42C54-56CD-4BEF-A3ED-C60ACCF6E975}"); }
|
||||
}
|
||||
|
||||
public LdapCronSettings GetDefault()
|
||||
{
|
||||
return new LdapCronSettings()
|
||||
{
|
||||
Cron = null
|
||||
};
|
||||
}
|
||||
|
||||
public string Cron { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LdapCurrentAcccessSettings : ISettings<LdapCurrentAcccessSettings>
|
||||
{
|
||||
[JsonIgnore]
|
||||
public Guid ID
|
||||
{
|
||||
get { return new Guid("{134B5EAA-F612-4834-AEAB-34C90515EA4E}"); }
|
||||
}
|
||||
|
||||
public LdapCurrentAcccessSettings GetDefault()
|
||||
{
|
||||
return new LdapCurrentAcccessSettings() { CurrentAccessRights = null };
|
||||
}
|
||||
|
||||
public LdapCurrentAcccessSettings()
|
||||
{
|
||||
CurrentAccessRights = new Dictionary<LdapSettings.AccessRight, List<string>>();
|
||||
}
|
||||
|
||||
public Dictionary<LdapSettings.AccessRight, List<string>> CurrentAccessRights { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LdapCurrentUserPhotos : ISettings<LdapCurrentUserPhotos>
|
||||
{
|
||||
[JsonIgnore]
|
||||
public Guid ID
|
||||
{
|
||||
get { return new Guid("{50AE3C2B-0783-480F-AF30-679D0F0A2D3E}"); }
|
||||
}
|
||||
|
||||
public LdapCurrentUserPhotos GetDefault()
|
||||
{
|
||||
return new LdapCurrentUserPhotos() { CurrentPhotos = null };
|
||||
}
|
||||
|
||||
public LdapCurrentUserPhotos()
|
||||
{
|
||||
CurrentPhotos = new Dictionary<Guid, string>();
|
||||
}
|
||||
|
||||
public Dictionary<Guid, string> CurrentPhotos { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LdapCurrentDomain : ISettings<LdapCurrentDomain>
|
||||
{
|
||||
[JsonIgnore]
|
||||
public Guid ID
|
||||
{
|
||||
get { return new Guid("{75A5F745-F697-4418-B38D-0FE0D277E258}"); }
|
||||
}
|
||||
|
||||
public LdapCurrentDomain GetDefault()
|
||||
{
|
||||
return new LdapCurrentDomain() { CurrentDomain = null };
|
||||
}
|
||||
|
||||
public string CurrentDomain { get; set; }
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Settings;
|
||||
public abstract class LdapSettingsChecker
|
||||
{
|
||||
protected readonly ILogger<LdapSettingsChecker> _logger;
|
||||
|
||||
public LdapUserImporter LdapImporter { get; private set; }
|
||||
|
||||
public LdapSettings Settings
|
||||
{
|
||||
get { return LdapImporter.Settings; }
|
||||
}
|
||||
|
||||
protected LdapSettingsChecker(ILogger<LdapSettingsChecker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Init(LdapUserImporter importer)
|
||||
{
|
||||
LdapImporter = importer;
|
||||
}
|
||||
|
||||
public abstract LdapSettingsStatus CheckSettings();
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Base.Settings;
|
||||
public enum LdapSettingsStatus
|
||||
{
|
||||
Ok = 0,
|
||||
WrongServerOrPort = 1,
|
||||
WrongUserDn = 2,
|
||||
IncorrectLDAPFilter = 3,
|
||||
UsersNotFound = 4,
|
||||
WrongLoginAttribute = 5,
|
||||
WrongGroupDn = 6,
|
||||
IncorrectGroupLDAPFilter = 7,
|
||||
GroupsNotFound = 8,
|
||||
WrongGroupAttribute = 9,
|
||||
WrongUserAttribute = 10,
|
||||
WrongGroupNameAttribute = 11,
|
||||
CredentialsNotValid = 12,
|
||||
ConnectError = 13,
|
||||
StrongAuthRequired = 14,
|
||||
WrongSidAttribute = 15,
|
||||
CertificateRequest = 16,
|
||||
TlsNotSupported = 17,
|
||||
DomainNotFound = 18
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
public class LdapChange
|
||||
{
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public LdapChangeAction Action { get; private set; }
|
||||
|
||||
public string Sid { get; private set; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string Email { get; private set; }
|
||||
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public LdapChangeType Type { get; private set; }
|
||||
|
||||
public List<LdapItemChange> Changes { get; private set; }
|
||||
|
||||
public LdapChange(string sid, string name, LdapChangeType type, LdapChangeAction action,
|
||||
List<LdapItemChange> changes = null) : this(sid, name, null, type, action, changes)
|
||||
{
|
||||
}
|
||||
|
||||
public LdapChange(string sid, string name, string email, LdapChangeType type, LdapChangeAction action, List<LdapItemChange> changes = null)
|
||||
{
|
||||
Sid = sid;
|
||||
Name = name;
|
||||
Type = type;
|
||||
Action = action;
|
||||
Changes = changes ?? new List<LdapItemChange>();
|
||||
Email = email;
|
||||
}
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
|
||||
[Scope]
|
||||
public class LdapChangeCollection : List<LdapChange>
|
||||
{
|
||||
private readonly UserFormatter _userFormatter;
|
||||
public LdapChangeCollection(UserFormatter userFormatter)
|
||||
{
|
||||
_userFormatter = userFormatter;
|
||||
}
|
||||
|
||||
#region User
|
||||
|
||||
public void SetSkipUserChange(UserInfo user)
|
||||
{
|
||||
var change = new LdapChange(user.Sid,
|
||||
_userFormatter.GetUserName(user, DisplayUserNameFormat.Default),
|
||||
user.Email,
|
||||
LdapChangeType.User, LdapChangeAction.Skip);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetSaveAsPortalUserChange(UserInfo user)
|
||||
{
|
||||
var fieldChanges = new List<LdapItemChange>
|
||||
{
|
||||
new LdapItemChange(LdapItemChangeKey.Sid, user.Sid, null)
|
||||
};
|
||||
|
||||
var change = new LdapChange(user.Sid,
|
||||
_userFormatter.GetUserName(user, DisplayUserNameFormat.Default),
|
||||
user.Email, LdapChangeType.User, LdapChangeAction.SaveAsPortal, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetNoneUserChange(UserInfo user)
|
||||
{
|
||||
var change = new LdapChange(user.Sid,
|
||||
_userFormatter.GetUserName(user, DisplayUserNameFormat.Default), user.Email,
|
||||
LdapChangeType.User, LdapChangeAction.None);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetUpdateUserChange(UserInfo beforeUserInfo, UserInfo afterUserInfo, ILogger log = null)
|
||||
{
|
||||
var fieldChanges =
|
||||
LdapUserMapping.Fields.Select(field => GetPropChange(field, beforeUserInfo, afterUserInfo, log))
|
||||
.Where(pch => pch != null)
|
||||
.ToList();
|
||||
|
||||
var change = new LdapChange(beforeUserInfo.Sid,
|
||||
_userFormatter.GetUserName(afterUserInfo, DisplayUserNameFormat.Default), afterUserInfo.Email,
|
||||
LdapChangeType.User, LdapChangeAction.Update, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetAddUserChange(UserInfo user, ILogger log = null)
|
||||
{
|
||||
var fieldChanges =
|
||||
LdapUserMapping.Fields.Select(field => GetPropChange(field, after: user, log: log))
|
||||
.Where(pch => pch != null)
|
||||
.ToList();
|
||||
|
||||
var change = new LdapChange(user.Sid,
|
||||
_userFormatter.GetUserName(user, DisplayUserNameFormat.Default), user.Email,
|
||||
LdapChangeType.User, LdapChangeAction.Add, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetRemoveUserChange(UserInfo user)
|
||||
{
|
||||
var change = new LdapChange(user.Sid,
|
||||
_userFormatter.GetUserName(user, DisplayUserNameFormat.Default), user.Email,
|
||||
LdapChangeType.User, LdapChangeAction.Remove);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Group
|
||||
|
||||
public void SetAddGroupChange(GroupInfo group, ILogger log = null)
|
||||
{
|
||||
var fieldChanges = new List<LdapItemChange>
|
||||
{
|
||||
new LdapItemChange(LdapItemChangeKey.Name, null, group.Name),
|
||||
new LdapItemChange(LdapItemChangeKey.Sid, null, group.Sid)
|
||||
};
|
||||
|
||||
var change = new LdapChange(group.Sid, group.Name,
|
||||
LdapChangeType.Group, LdapChangeAction.Add, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetAddGroupMembersChange(GroupInfo group,
|
||||
List<UserInfo> members)
|
||||
{
|
||||
var fieldChanges =
|
||||
members.Select(
|
||||
member =>
|
||||
new LdapItemChange(LdapItemChangeKey.Member, null,
|
||||
_userFormatter.GetUserName(member, DisplayUserNameFormat.Default))).ToList();
|
||||
|
||||
var change = new LdapChange(group.Sid, group.Name,
|
||||
LdapChangeType.Group, LdapChangeAction.AddMember, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetSkipGroupChange(GroupInfo group)
|
||||
{
|
||||
var change = new LdapChange(group.Sid, group.Name, LdapChangeType.Group,
|
||||
LdapChangeAction.Skip);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetUpdateGroupChange(GroupInfo group)
|
||||
{
|
||||
var fieldChanges = new List<LdapItemChange>
|
||||
{
|
||||
new LdapItemChange(LdapItemChangeKey.Name, group.Name, group.Name)
|
||||
};
|
||||
|
||||
var change = new LdapChange(group.Sid, group.Name,
|
||||
LdapChangeType.Group, LdapChangeAction.Update, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetRemoveGroupChange(GroupInfo group, ILogger log = null)
|
||||
{
|
||||
var change = new LdapChange(group.Sid, group.Name,
|
||||
LdapChangeType.Group, LdapChangeAction.Remove);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
public void SetRemoveGroupMembersChange(GroupInfo group,
|
||||
List<UserInfo> members)
|
||||
{
|
||||
var fieldChanges =
|
||||
members.Select(
|
||||
member =>
|
||||
new LdapItemChange(LdapItemChangeKey.Member, null,
|
||||
_userFormatter.GetUserName(member, DisplayUserNameFormat.Default))).ToList();
|
||||
|
||||
var change = new LdapChange(group.Sid, group.Name,
|
||||
LdapChangeType.Group, LdapChangeAction.RemoveMember, fieldChanges);
|
||||
|
||||
Add(change);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static LdapItemChange GetPropChange(string propName, UserInfo before = null, UserInfo after = null, ILogger log = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var valueSrc = before != null
|
||||
? before.GetType().GetProperty(propName).GetValue(before, null) as string
|
||||
: "";
|
||||
var valueDst = after != null
|
||||
? after.GetType().GetProperty(propName).GetValue(before, null) as string
|
||||
: "";
|
||||
|
||||
LdapItemChangeKey key;
|
||||
if (!Enum.TryParse(propName, out key))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(propName);
|
||||
}
|
||||
|
||||
var change = new LdapItemChange(key, valueSrc, valueDst);
|
||||
|
||||
return change;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.ErrorCanNotGetSidProperty(propName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
|
||||
public enum LdapChangeType
|
||||
{
|
||||
User,
|
||||
Group
|
||||
}
|
||||
|
||||
public enum LdapItemChangeKey
|
||||
{
|
||||
Sid,
|
||||
Name,
|
||||
FirstName,
|
||||
LastName,
|
||||
Mail,
|
||||
Phone,
|
||||
Title,
|
||||
Location,
|
||||
Member
|
||||
}
|
||||
|
||||
public enum LdapChangeAction
|
||||
{
|
||||
None,
|
||||
Skip,
|
||||
Add,
|
||||
AddMember,
|
||||
Merge,
|
||||
Update,
|
||||
Remove,
|
||||
RemoveMember,
|
||||
SaveAsPortal
|
||||
}
|
||||
|
||||
public static class LdapUserMapping
|
||||
{
|
||||
public static readonly List<string> Fields = new List<string>
|
||||
{
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.FirstName),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.LastName),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Mail),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Phone),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Title),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Location),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Sid),
|
||||
Enum.GetName(typeof(LdapItemChangeKey), LdapItemChangeKey.Member)
|
||||
};
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
|
||||
public class LdapItemChange
|
||||
{
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public LdapItemChangeKey Key { get; private set; }
|
||||
|
||||
public string Before { get; private set; }
|
||||
public string After { get; private set; }
|
||||
|
||||
public bool IsChanged { get; private set; }
|
||||
|
||||
public LdapItemChange(LdapItemChangeKey key, string before, string after)
|
||||
{
|
||||
Key = key;
|
||||
Before = before;
|
||||
After = after;
|
||||
|
||||
IsChanged = Before != null && !Before.Equals(After) || After != null && !After.Equals(Before);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
|
||||
public static class LdapTaskProperty
|
||||
{
|
||||
public static string OWNER = "LDAPOwner";
|
||||
public static string OPERATION_TYPE = "LDAPOperationType";
|
||||
public static string SOURCE = "LDAPSource";
|
||||
public static string PROGRESS = "LDAPProgress";
|
||||
public static string RESULT = "LDAPResult";
|
||||
public static string ERROR = "LDAPError";
|
||||
public static string WARNING = "LDAPWarning";
|
||||
public static string CERT_REQUEST = "LDAPCertRequest";
|
||||
public static string FINISHED = "LDAPFinished";
|
||||
}
|
614
common/ASC.ActiveDirectory/ComplexOperations/LdapLocalization.cs
Normal file
614
common/ASC.ActiveDirectory/ComplexOperations/LdapLocalization.cs
Normal file
@ -0,0 +1,614 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations;
|
||||
|
||||
[Scope]
|
||||
public class LdapLocalization
|
||||
{
|
||||
private ResourceManager _resourceManager;
|
||||
private ResourceManager _notifyResourceManager;
|
||||
|
||||
public void Init(ResourceManager resourceManager = null, ResourceManager notifyResourceManager = null)
|
||||
{
|
||||
_resourceManager = resourceManager;
|
||||
_notifyResourceManager = notifyResourceManager;
|
||||
}
|
||||
|
||||
public string FirstName
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "FirstName";
|
||||
const string def_val = "First Name";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LastName
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LastName";
|
||||
const string def_val = "Last Name";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsModifyLdapUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsModifyLdapUsers";
|
||||
const string def_val = "Modifying LDAP users on ordinary portal users";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsTenantQuotaSettled
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsTenantQuotaSettled";
|
||||
const string def_val = "The current pricing plan user limit has been reached";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorCantCreateUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorCantCreateUsers";
|
||||
const string def_val = "Users could not be created, the received data are incorrect.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsInternalServerError
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsInternalServerError";
|
||||
const string def_val = "Server internal error.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusGettingUsersFromLdap
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusGettingUsersFromLdap";
|
||||
const string def_val = "Retrieving the user list from the LDAP server";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusGivingRights
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusGivingRights";
|
||||
const string def_val = "Setting user {0} as {1} admin";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorUsersNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorUsersNotFound";
|
||||
const string def_val = "No users could be found.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusRemovingOldRights
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusRemovingOldRights";
|
||||
const string def_val = "Removing outdated access rights that have been loaded via LDAP earlier";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusRemovingOldUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusRemovingOldUsers";
|
||||
const string def_val = "Removing outdated user profiles that have been loaded via LDAP earlier";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusSavingUserPhoto
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusSavingUserPhoto";
|
||||
const string def_val = "Saving photo";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusSavingUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusSavingUsers";
|
||||
const string def_val = "Saving users";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusSyncingUsers
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusSyncingUsers";
|
||||
const string def_val = "Syncing users";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusRemovingOldGroups
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusRemovingOldGroups";
|
||||
const string def_val = "Removing outdated groups that have been loaded via LDAP earlier";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusGettingGroupsFromLdap
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusGettingGroupsFromLdap";
|
||||
const string def_val = "Retrieving the group list from the LDAP server";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorGroupsNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorGroupsNotFound";
|
||||
const string def_val = "No groups could be found.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusSavingGroups
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusSavingGroups";
|
||||
const string def_val = "Saving groups";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorCantGetLdapSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorCantGetLdapSettings";
|
||||
const string def_val = "The server could not get settings.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusCheckingLdapSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusCheckingLdapSettings";
|
||||
const string def_val = "Checking LDAP support settings";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusLoadingBaseInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusLoadingBaseInfo";
|
||||
const string def_val = "Loading LDAP base info";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusCertificateVerification
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusCertificateVerification";
|
||||
const string def_val = "Certificate verification";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongServerOrPort
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongServerOrPort";
|
||||
const string def_val =
|
||||
"Unable to connect to LDAP server. Please check if the server address and port number are correct.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongUserDn
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongUserDN";
|
||||
const string def_val = "Incorrect User DN.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorIncorrectLdapFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorIncorrectLdapFilter";
|
||||
const string def_val = "Invalid User Filter value.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorLostRights
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorLostRights";
|
||||
const string def_val = "You attempted to take away admin rights from yourself. Your admin rights was unaffected.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorRemovedYourself
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorRemovedYourself";
|
||||
const string def_val = "Your account has been unlinked from LDAP. You may need to set a password for your account because you won't be able to login using LDAP password.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongLoginAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongLoginAttribute";
|
||||
const string def_val = "Could not get Login Attribute for one or several users.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongGroupDn
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongGroupDN";
|
||||
const string def_val = "Incorrect Group DN.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongGroupFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongGroupFilter";
|
||||
const string def_val = "Could not get Group Attribute for one or several groups.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongGroupAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongGroupAttribute";
|
||||
const string def_val = "Could not get User Attribute for one or several users.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongUserAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongUserAttribute";
|
||||
const string def_val = "Could not get User Attribute for one or several users.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorWrongGroupNameAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorWrongGroupNameAttribute";
|
||||
const string def_val = "Could not obtain Group Name Attribute for one or several groups.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorCredentialsNotValid
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorCredentialsNotValid";
|
||||
const string def_val = "Incorrect login or password.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsConnectError
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsConnectError";
|
||||
const string def_val =
|
||||
"A more secure authentication type is required. Please use encripted connection or enable plain authentication on the server.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStrongAuthRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStrongAuthRequired";
|
||||
const string def_val =
|
||||
"A more secure authentication type is required. Please use encripted connection or enable plain authentication on the server.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsWrongSidAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsWrongSidAttribute";
|
||||
const string def_val =
|
||||
"Unique ID for user/group objects could not be obtained. By default the system will try to match one of the following identifiers: entryUUID, nsuniqueid, GUID, objectSid. If none of the attributes corresponds to your LDAP server, please specify the necessary attribute in the ldap.unique.id setting of the web.appsettings.config file.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsTlsNotSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsTlsNotSupported";
|
||||
const string def_val = "StartTLS not supported for current LDAP server.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorDomainNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorDomainNotFound";
|
||||
const string def_val = "LDAP domain not found.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorUnknownError
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorUnknownError";
|
||||
const string def_val = "Unknown error.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusSavingSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusSavingSettings";
|
||||
const string def_val = "Saving settings";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsErrorCantSaveLdapSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsErrorCantSaveLdapSettings";
|
||||
const string def_val = "The server could not save settings.";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string ErrorEmailEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "ErrorEmailEmpty";
|
||||
const string def_val = "Email field is empty";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string ErrorAccessDenied
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "ErrorAccessDenied";
|
||||
const string def_val = "No permissions to perform this action";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusAddingGroupUser
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusAddingGroupUser";
|
||||
const string def_val = "adding user";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusRemovingGroupUser
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusRemovingGroupUser";
|
||||
const string def_val = "removing user";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusUpdatingAccessRights
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusUpdatingAccessRights";
|
||||
const string def_val = "Updating users access rights";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusUpdatingUserPhotos
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusUpdatingUserPhotos";
|
||||
const string def_val = "Updating user photos";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string LdapSettingsStatusDisconnecting
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "LdapSettingsStatusDisconnecting";
|
||||
const string def_val = "LDAP disconnecting";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
public string NotifyButtonJoin
|
||||
{
|
||||
get
|
||||
{
|
||||
const string def_key = "ButtonAccessYourPortal";
|
||||
const string def_val = "Click here to join the portal";
|
||||
|
||||
return GetValueOrDefault(def_key, def_val);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetValueOrDefault(string key, string defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = _resourceManager != null ? _resourceManager.GetString(key) : null;
|
||||
if (val == null && _notifyResourceManager != null)
|
||||
{
|
||||
val = _notifyResourceManager.GetString(key);
|
||||
}
|
||||
|
||||
return val != null ? val : defaultValue;
|
||||
}
|
||||
catch
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
1487
common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs
Normal file
1487
common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations;
|
||||
|
||||
public class LdapOperationStatus
|
||||
{
|
||||
public bool Completed { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
|
||||
public string Error { get; set; }
|
||||
|
||||
public string Warning { get; set; }
|
||||
|
||||
public int Percents { get; set; }
|
||||
|
||||
public string CertificateConfirmRequest { get; set; }
|
||||
|
||||
public string Source { get; set; }
|
||||
|
||||
public string OperationType { get; set; }
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations;
|
||||
|
||||
public enum LdapOperationType
|
||||
{
|
||||
Save,
|
||||
Sync,
|
||||
SaveTest,
|
||||
SyncTest
|
||||
}
|
@ -0,0 +1,247 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.ComplexOperations;
|
||||
|
||||
[Singletone(Additional = typeof(LdapOperationExtension))]
|
||||
public class LdapSaveSyncOperation
|
||||
{
|
||||
public const string CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME = "ldapOperation";
|
||||
|
||||
private readonly DistributedTaskQueue _progressQueue;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public LdapSaveSyncOperation(
|
||||
IServiceProvider serviceProvider,
|
||||
IDistributedTaskQueueFactory queueFactory)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_progressQueue = queueFactory.CreateQueue(CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME);
|
||||
}
|
||||
|
||||
public void RunJob(LdapSettings settings, Tenant tenant, LdapOperationType operationType, LdapLocalization resource = null, string userId = null)
|
||||
{
|
||||
var item = _progressQueue.GetAllTasks<LdapOperationJob>().FirstOrDefault(t => t.TenantId == tenant.Id);
|
||||
if (item != null && item.IsCompleted)
|
||||
{
|
||||
_progressQueue.DequeueTask(item.Id);
|
||||
item = null;
|
||||
}
|
||||
if (item == null)
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
item = scope.ServiceProvider.GetRequiredService<LdapOperationJob>();
|
||||
item.InitJob(settings, tenant, operationType, resource, userId);
|
||||
_progressQueue.EnqueueTask(item);
|
||||
}
|
||||
|
||||
item.PublishChanges();
|
||||
}
|
||||
|
||||
public LdapOperationStatus TestLdapSave(LdapSettings ldapSettings, Tenant tenant, string userId)
|
||||
{
|
||||
var (hasStarted, operations) = HasStarterdForTenant(tenant.Id, LdapOperationType.SyncTest, LdapOperationType.SaveTest);
|
||||
|
||||
if (hasStarted)
|
||||
{
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
|
||||
{
|
||||
return GetStartProcessError();
|
||||
}
|
||||
|
||||
var ldapLocalization = new LdapLocalization();
|
||||
ldapLocalization.Init(Resource.ResourceManager);
|
||||
|
||||
RunJob(ldapSettings, tenant, LdapOperationType.SaveTest, ldapLocalization, userId);
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
public LdapOperationStatus SaveLdapSettings(LdapSettings ldapSettings, Tenant tenant, string userId)
|
||||
{
|
||||
var operations = GetOperationsForTenant(tenant.Id);
|
||||
|
||||
if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
|
||||
{
|
||||
return GetStartProcessError();
|
||||
}
|
||||
|
||||
//ToDo
|
||||
ldapSettings.AccessRights.Clear();
|
||||
|
||||
if (!ldapSettings.LdapMapping.ContainsKey(LdapSettings.MappingFields.MailAttribute) || string.IsNullOrEmpty(ldapSettings.LdapMapping[LdapSettings.MappingFields.MailAttribute]))
|
||||
{
|
||||
ldapSettings.SendWelcomeEmail = false;
|
||||
}
|
||||
|
||||
var ldapLocalization = new LdapLocalization();
|
||||
ldapLocalization.Init(Resource.ResourceManager, WebstudioNotifyPatternResource.ResourceManager);
|
||||
|
||||
RunJob(ldapSettings, tenant, LdapOperationType.Save, ldapLocalization, userId);
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
public LdapOperationStatus SyncLdap(LdapSettings ldapSettings, Tenant tenant, string userId)
|
||||
{
|
||||
var (hasStarted, operations) = HasStarterdForTenant(tenant.Id, LdapOperationType.Sync, LdapOperationType.Save);
|
||||
|
||||
if (hasStarted)
|
||||
{
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
|
||||
{
|
||||
return GetStartProcessError();
|
||||
}
|
||||
|
||||
var ldapLocalization = new LdapLocalization();
|
||||
ldapLocalization.Init(Resource.ResourceManager);
|
||||
|
||||
RunJob(ldapSettings, tenant, LdapOperationType.Sync, ldapLocalization, userId);
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
public LdapOperationStatus TestLdapSync(LdapSettings ldapSettings, Tenant tenant)
|
||||
{
|
||||
var (hasStarted, operations) = HasStarterdForTenant(tenant.Id, LdapOperationType.SyncTest, LdapOperationType.SaveTest);
|
||||
|
||||
if (hasStarted)
|
||||
{
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
|
||||
{
|
||||
return GetStartProcessError();
|
||||
}
|
||||
|
||||
var ldapLocalization = new LdapLocalization();
|
||||
ldapLocalization.Init(Resource.ResourceManager);
|
||||
|
||||
RunJob(ldapSettings, tenant, LdapOperationType.SyncTest, ldapLocalization);
|
||||
return ToLdapOperationStatus(tenant.Id);
|
||||
}
|
||||
|
||||
public LdapOperationStatus ToLdapOperationStatus(int tenantId)
|
||||
{
|
||||
var operations = _progressQueue.GetAllTasks<LdapOperationJob>().ToList();
|
||||
|
||||
foreach (var o in operations)
|
||||
{
|
||||
if (Process.GetProcesses().Any(p => p.Id == o.InstanceId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
o[LdapTaskProperty.PROGRESS] = 100;
|
||||
_progressQueue.DequeueTask(o.Id);
|
||||
}
|
||||
|
||||
var operation =
|
||||
operations
|
||||
.FirstOrDefault(t => t[LdapTaskProperty.OWNER] == tenantId);
|
||||
|
||||
if (operation == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DistributedTaskStatus.Running < operation.Status)
|
||||
{
|
||||
operation[LdapTaskProperty.PROGRESS] = 100;
|
||||
_progressQueue.DequeueTask(operation.Id);
|
||||
}
|
||||
|
||||
var result = new LdapOperationStatus
|
||||
{
|
||||
Id = operation.Id,
|
||||
Completed = operation[LdapTaskProperty.FINISHED],
|
||||
Percents = operation[LdapTaskProperty.PROGRESS],
|
||||
Status = operation[LdapTaskProperty.RESULT],
|
||||
Error = operation[LdapTaskProperty.ERROR],
|
||||
CertificateConfirmRequest = operation[LdapTaskProperty.CERT_REQUEST] != "" ? operation[LdapTaskProperty.CERT_REQUEST] : null,
|
||||
Source = operation[LdapTaskProperty.SOURCE],
|
||||
OperationType = operation[LdapTaskProperty.OPERATION_TYPE],
|
||||
Warning = operation[LdapTaskProperty.WARNING]
|
||||
};
|
||||
|
||||
if (!(string.IsNullOrEmpty(result.Warning)))
|
||||
{
|
||||
operation[LdapTaskProperty.WARNING] = ""; // "mark" as read
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static LdapOperationStatus GetStartProcessError()
|
||||
{
|
||||
var result = new LdapOperationStatus
|
||||
{
|
||||
Id = null,
|
||||
Completed = true,
|
||||
Percents = 0,
|
||||
Status = "",
|
||||
Error = Resource.LdapSettingsTooManyOperations,
|
||||
CertificateConfirmRequest = null,
|
||||
Source = ""
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private (bool hasStarted, List<LdapOperationJob> operations) HasStarterdForTenant(int tenantId, LdapOperationType arg1, LdapOperationType arg2)
|
||||
{
|
||||
var operations = GetOperationsForTenant(tenantId);
|
||||
|
||||
var hasStarted = operations.Any(o =>
|
||||
{
|
||||
var opType = o[LdapTaskProperty.OPERATION_TYPE];
|
||||
|
||||
return o.Status <= DistributedTaskStatus.Running &&
|
||||
(opType == arg1.ToString() || opType == arg2.ToString());
|
||||
});
|
||||
|
||||
return (hasStarted, operations);
|
||||
}
|
||||
|
||||
private List<LdapOperationJob> GetOperationsForTenant(int tenantId)
|
||||
{
|
||||
return _progressQueue.GetAllTasks<LdapOperationJob>()
|
||||
.Where(t => t[LdapTaskProperty.OWNER] == tenantId)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static class LdapOperationExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<LdapOperationJob>();
|
||||
}
|
||||
}
|
||||
}
|
83
common/ASC.ActiveDirectory/GlobalUsings.cs
Normal file
83
common/ASC.ActiveDirectory/GlobalUsings.cs
Normal file
@ -0,0 +1,83 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
global using System.Collections.Concurrent;
|
||||
global using System.ComponentModel;
|
||||
global using System.Diagnostics;
|
||||
global using System.Globalization;
|
||||
global using System.Net.Mail;
|
||||
global using System.Net.Security;
|
||||
global using System.Net.Sockets;
|
||||
global using System.Resources;
|
||||
global using System.Security;
|
||||
global using System.Security.Cryptography;
|
||||
global using System.Security.Cryptography.X509Certificates;
|
||||
global using System.Text;
|
||||
global using System.Text.Json;
|
||||
global using System.Text.Json.Serialization;
|
||||
global using System.Text.RegularExpressions;
|
||||
|
||||
global using ASC.ActiveDirectory.Base;
|
||||
global using ASC.ActiveDirectory.Base.Data;
|
||||
global using ASC.ActiveDirectory.Base.Expressions;
|
||||
global using ASC.ActiveDirectory.Base.Settings;
|
||||
global using ASC.ActiveDirectory.ComplexOperations;
|
||||
global using ASC.ActiveDirectory.ComplexOperations.Data;
|
||||
global using ASC.ActiveDirectory.Log;
|
||||
global using ASC.ActiveDirectory.Novell;
|
||||
global using ASC.ActiveDirectory.Novell.Data;
|
||||
global using ASC.ActiveDirectory.Novell.Exceptions;
|
||||
global using ASC.ActiveDirectory.Novell.Extensions;
|
||||
global using ASC.Common;
|
||||
global using ASC.Common.Security.Authorizing;
|
||||
global using ASC.Common.Threading;
|
||||
global using ASC.Core;
|
||||
global using ASC.Core.Common.EF;
|
||||
global using ASC.Core.Common.EF.Model;
|
||||
global using ASC.Core.Common.Settings;
|
||||
global using ASC.Core.Tenants;
|
||||
global using ASC.Core.Users;
|
||||
global using ASC.Notify;
|
||||
global using ASC.Notify.Engine;
|
||||
global using ASC.Notify.Model;
|
||||
global using ASC.Notify.Patterns;
|
||||
global using ASC.Notify.Recipients;
|
||||
global using ASC.Security.Cryptography;
|
||||
global using ASC.Web.Core;
|
||||
global using ASC.Web.Core.PublicResources;
|
||||
global using ASC.Web.Core.Users;
|
||||
global using ASC.Web.Studio.Utility;
|
||||
|
||||
global using Microsoft.EntityFrameworkCore;
|
||||
global using Microsoft.Extensions.Configuration;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
|
||||
global using Novell.Directory.Ldap;
|
||||
global using Novell.Directory.Ldap.Controls;
|
||||
global using Novell.Directory.Ldap.Rfc2251;
|
||||
global using Novell.Directory.Ldap.Utilclass;
|
752
common/ASC.ActiveDirectory/LdapUserManager.cs
Normal file
752
common/ASC.ActiveDirectory/LdapUserManager.cs
Normal file
@ -0,0 +1,752 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
using Constants = ASC.Core.Users.Constants;
|
||||
using Mapping = ASC.ActiveDirectory.Base.Settings.LdapSettings.MappingFields;
|
||||
using SecurityContext = ASC.Core.SecurityContext;
|
||||
|
||||
namespace ASC.ActiveDirectory;
|
||||
[Scope]
|
||||
public class LdapUserManager
|
||||
{
|
||||
private readonly ILogger<LdapUserManager> _logger;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly TenantUtil _tenantUtil;
|
||||
private readonly SecurityContext _securityContext;
|
||||
private readonly CommonLinkUtility _commonLinkUtility;
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
|
||||
private readonly UserFormatter _userFormatter;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly NovellLdapUserImporter _novellLdapUserImporter;
|
||||
private LdapLocalization _resource;
|
||||
|
||||
public LdapUserManager(
|
||||
ILogger<LdapUserManager> logger,
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
SecurityContext securityContext,
|
||||
CommonLinkUtility commonLinkUtility,
|
||||
SettingsManager settingsManager,
|
||||
DisplayUserSettingsHelper displayUserSettingsHelper,
|
||||
UserFormatter userFormatter,
|
||||
NovellLdapUserImporter novellLdapUserImporter,
|
||||
WorkContext workContext)
|
||||
{
|
||||
_logger = logger;
|
||||
_userManager = userManager;
|
||||
_tenantManager = tenantManager;
|
||||
_tenantUtil = tenantUtil;
|
||||
_securityContext = securityContext;
|
||||
_commonLinkUtility = commonLinkUtility;
|
||||
_settingsManager = settingsManager;
|
||||
_displayUserSettingsHelper = displayUserSettingsHelper;
|
||||
_userFormatter = userFormatter;
|
||||
_serviceProvider = serviceProvider;
|
||||
_novellLdapUserImporter = novellLdapUserImporter;
|
||||
}
|
||||
|
||||
public void Init(LdapLocalization resource = null)
|
||||
{
|
||||
_resource = resource ?? new LdapLocalization();
|
||||
}
|
||||
|
||||
private bool TestUniqueUserName(string uniqueName)
|
||||
{
|
||||
return !string.IsNullOrEmpty(uniqueName) && Equals(_userManager.GetUserByUserName(uniqueName), Constants.LostUser);
|
||||
}
|
||||
|
||||
private string MakeUniqueName(UserInfo userInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userInfo.Email))
|
||||
{
|
||||
throw new ArgumentException(_resource.ErrorEmailEmpty, "userInfo");
|
||||
}
|
||||
|
||||
var uniqueName = new MailAddress(userInfo.Email).User;
|
||||
var startUniqueName = uniqueName;
|
||||
var i = 0;
|
||||
while (!TestUniqueUserName(uniqueName))
|
||||
{
|
||||
uniqueName = string.Format("{0}{1}", startUniqueName, (++i).ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
return uniqueName;
|
||||
}
|
||||
|
||||
private bool CheckUniqueEmail(Guid userId, string email)
|
||||
{
|
||||
var foundUser = _userManager.GetUserByEmail(email);
|
||||
return Equals(foundUser, Constants.LostUser) || foundUser.Id == userId;
|
||||
}
|
||||
|
||||
public bool TryAddLDAPUser(UserInfo ldapUserInfo, bool onlyGetChanges, out UserInfo portalUserInfo)
|
||||
{
|
||||
portalUserInfo = Constants.LostUser;
|
||||
|
||||
try
|
||||
{
|
||||
if (ldapUserInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException("ldapUserInfo");
|
||||
}
|
||||
|
||||
_logger.DebugTryAddLdapUser(ldapUserInfo.Sid, ldapUserInfo.Email, ldapUserInfo.UserName);
|
||||
|
||||
if (!CheckUniqueEmail(ldapUserInfo.Id, ldapUserInfo.Email))
|
||||
{
|
||||
_logger.DebugUserAlredyExistsForEmail(ldapUserInfo.Sid, ldapUserInfo.Email);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryChangeExistingUserName(ldapUserInfo.UserName, onlyGetChanges))
|
||||
{
|
||||
_logger.DebugUserAlredyExistsForUserName(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var q = _tenantManager.GetTenantQuota(_tenantManager.GetCurrentTenant().Id);
|
||||
if (q.ActiveUsers <= _userManager.GetUsersByGroup(Constants.GroupUser.ID).Length)
|
||||
{
|
||||
_logger.DebugExceedQuota(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", q.ActiveUsers));
|
||||
}
|
||||
|
||||
if (!ldapUserInfo.WorkFromDate.HasValue)
|
||||
{
|
||||
ldapUserInfo.WorkFromDate = _tenantUtil.DateTimeNow();
|
||||
}
|
||||
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
portalUserInfo = ldapUserInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.DebugSaveUserInfo(ldapUserInfo.GetUserInfoString());
|
||||
|
||||
portalUserInfo = _userManager.SaveUserInfo(ldapUserInfo);
|
||||
|
||||
var passwordHash = LdapUtils.GeneratePassword();
|
||||
|
||||
_logger.DebugSetUserPassword(portalUserInfo.Id);
|
||||
|
||||
_securityContext.SetUserPasswordHash(portalUserInfo.Id, passwordHash);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (TenantQuotaException ex)
|
||||
{
|
||||
// rethrow if quota
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ldapUserInfo != null)
|
||||
{
|
||||
_logger.ErrorTryAddLdapUser(ldapUserInfo.UserName, ldapUserInfo.Sid, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryChangeExistingUserName(string ldapUserName, bool onlyGetChanges)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(ldapUserName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var otherUser = _userManager.GetUserByUserName(ldapUserName);
|
||||
|
||||
if (Equals(otherUser, Constants.LostUser))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (otherUser.IsLDAP())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
otherUser.UserName = MakeUniqueName(otherUser);
|
||||
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.DebugTryChangeExistingUserName();
|
||||
|
||||
_logger.DebugSaveUserInfo(otherUser.GetUserInfoString());
|
||||
|
||||
_userManager.SaveUserInfo(otherUser);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorTryChangeOtherUserName(ldapUserName, ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public UserInfo GetLDAPSyncUserChange(UserInfo ldapUserInfo, List<UserInfo> ldapUsers, out LdapChangeCollection changes)
|
||||
{
|
||||
return SyncLDAPUser(ldapUserInfo, ldapUsers, out changes, true);
|
||||
}
|
||||
|
||||
public UserInfo SyncLDAPUser(UserInfo ldapUserInfo, List<UserInfo> ldapUsers = null)
|
||||
{
|
||||
LdapChangeCollection changes;
|
||||
return SyncLDAPUser(ldapUserInfo, ldapUsers, out changes);
|
||||
}
|
||||
|
||||
private UserInfo SyncLDAPUser(UserInfo ldapUserInfo, List<UserInfo> ldapUsers, out LdapChangeCollection changes, bool onlyGetChanges = false)
|
||||
{
|
||||
UserInfo result;
|
||||
|
||||
changes = new LdapChangeCollection(_userFormatter);
|
||||
|
||||
UserInfo userToUpdate;
|
||||
|
||||
var userBySid = _userManager.GetUserBySid(ldapUserInfo.Sid);
|
||||
|
||||
if (Equals(userBySid, Constants.LostUser))
|
||||
{
|
||||
var userByEmail = _userManager.GetUserByEmail(ldapUserInfo.Email);
|
||||
|
||||
if (Equals(userByEmail, Constants.LostUser))
|
||||
{
|
||||
if (ldapUserInfo.Status != EmployeeStatus.Active)
|
||||
{
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetSkipUserChange(ldapUserInfo);
|
||||
}
|
||||
|
||||
_logger.DebugSyncUserLdapFailedWithStatus(ldapUserInfo.Sid, ldapUserInfo.UserName,
|
||||
Enum.GetName(typeof(EmployeeStatus), ldapUserInfo.Status));
|
||||
|
||||
return Constants.LostUser;
|
||||
}
|
||||
|
||||
if (!TryAddLDAPUser(ldapUserInfo, onlyGetChanges, out result))
|
||||
{
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetSkipUserChange(ldapUserInfo);
|
||||
}
|
||||
|
||||
return Constants.LostUser;
|
||||
}
|
||||
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetAddUserChange(result, _logger);
|
||||
}
|
||||
|
||||
if (!onlyGetChanges && _settingsManager.Load<LdapSettings>().SendWelcomeEmail &&
|
||||
(ldapUserInfo.ActivationStatus != EmployeeActivationStatus.AutoGenerated))
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<TenantManager>();
|
||||
var ldapNotifyHelper = scope.ServiceProvider.GetRequiredService<LdapNotifyService>();
|
||||
var source = scope.ServiceProvider.GetRequiredService<LdapNotifySource>();
|
||||
source.Init(tenantManager.GetCurrentTenant());
|
||||
var workContext = scope.ServiceProvider.GetRequiredService<WorkContext>();
|
||||
var notifuEngineQueue = scope.ServiceProvider.GetRequiredService<NotifyEngineQueue>();
|
||||
var client = workContext.NotifyContext.RegisterClient(notifuEngineQueue, source);
|
||||
|
||||
var confirmLink = _commonLinkUtility.GetConfirmationUrl(ldapUserInfo.Email, ConfirmType.EmailActivation);
|
||||
|
||||
client.SendNoticeToAsync(
|
||||
NotifyConstants.ActionLdapActivation,
|
||||
null,
|
||||
new[] { new DirectRecipient(ldapUserInfo.Email, null, new[] { ldapUserInfo.Email }, false) },
|
||||
new[] { ASC.Core.Configuration.Constants.NotifyEMailSenderSysName },
|
||||
null,
|
||||
new TagValue(NotifyConstants.TagUserName, ldapUserInfo.DisplayUserName(_displayUserSettingsHelper)),
|
||||
new TagValue(NotifyConstants.TagUserEmail, ldapUserInfo.Email),
|
||||
new TagValue(NotifyConstants.TagMyStaffLink, _commonLinkUtility.GetFullAbsolutePath(_commonLinkUtility.GetMyStaff())),
|
||||
NotifyConstants.TagGreenButton(_resource.NotifyButtonJoin, confirmLink),
|
||||
new TagValue(NotifyCommonTags.WithoutUnsubscribe, true));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (userByEmail.IsLDAP())
|
||||
{
|
||||
if (ldapUsers == null || ldapUsers.Any(u => u.Sid.Equals(userByEmail.Sid)))
|
||||
{
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetSkipUserChange(ldapUserInfo);
|
||||
}
|
||||
|
||||
_logger.DebugSyncUserLdapFailedWithEmail(
|
||||
ldapUserInfo.Sid, ldapUserInfo.UserName, ldapUserInfo.Email);
|
||||
|
||||
return Constants.LostUser;
|
||||
}
|
||||
}
|
||||
|
||||
userToUpdate = userByEmail;
|
||||
}
|
||||
else
|
||||
{
|
||||
userToUpdate = userBySid;
|
||||
}
|
||||
|
||||
UpdateLdapUserContacts(ldapUserInfo, userToUpdate.ContactsList);
|
||||
|
||||
if (!NeedUpdateUser(userToUpdate, ldapUserInfo))
|
||||
{
|
||||
_logger.DebugSyncUserLdapSkipping(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetNoneUserChange(ldapUserInfo);
|
||||
}
|
||||
|
||||
return userBySid;
|
||||
}
|
||||
|
||||
_logger.DebugSyncUserLdapUpdaiting(ldapUserInfo.Sid, ldapUserInfo.UserName);
|
||||
if (!TryUpdateUserWithLDAPInfo(userToUpdate, ldapUserInfo, onlyGetChanges, out result))
|
||||
{
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetSkipUserChange(ldapUserInfo);
|
||||
}
|
||||
|
||||
return Constants.LostUser;
|
||||
}
|
||||
|
||||
if (onlyGetChanges)
|
||||
{
|
||||
changes.SetUpdateUserChange(ldapUserInfo, result, _logger);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private const string EXT_MOB_PHONE = "extmobphone";
|
||||
private const string EXT_MAIL = "extmail";
|
||||
private const string EXT_PHONE = "extphone";
|
||||
private const string EXT_SKYPE = "extskype";
|
||||
|
||||
private static void UpdateLdapUserContacts(UserInfo ldapUser, List<string> portalUserContacts)
|
||||
{
|
||||
if (portalUserContacts == null || !portalUserContacts.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ldapUserContacts = ldapUser.Contacts;
|
||||
|
||||
var newContacts = new List<string>(ldapUser.ContactsList);
|
||||
|
||||
for (int i = 0; i < portalUserContacts.Count; i += 2)
|
||||
{
|
||||
if (portalUserContacts[i] == EXT_MOB_PHONE || portalUserContacts[i] == EXT_MAIL
|
||||
|| portalUserContacts[i] == EXT_PHONE || portalUserContacts[i] == EXT_SKYPE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 1 >= portalUserContacts.Count)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
newContacts.Add(portalUserContacts[i]);
|
||||
newContacts.Add(portalUserContacts[i + 1]);
|
||||
}
|
||||
|
||||
ldapUser.ContactsList = newContacts;
|
||||
}
|
||||
|
||||
private bool NeedUpdateUser(UserInfo portalUser, UserInfo ldapUser)
|
||||
{
|
||||
var needUpdate = false;
|
||||
|
||||
try
|
||||
{
|
||||
var settings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
Func<string, string, bool> notEqual =
|
||||
(f1, f2) =>
|
||||
f1 == null && f2 != null ||
|
||||
f1 != null && !f1.Equals(f2, StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (notEqual(portalUser.FirstName, ldapUser.FirstName))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByFirstName(portalUser.FirstName ?? "NULL",
|
||||
ldapUser.FirstName ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (notEqual(portalUser.LastName, ldapUser.LastName))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByLastName(portalUser.LastName ?? "NULL",
|
||||
ldapUser.LastName ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (notEqual(portalUser.UserName, ldapUser.UserName))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByUserName(portalUser.UserName ?? "NULL",
|
||||
ldapUser.UserName ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (notEqual(portalUser.Email, ldapUser.Email) &&
|
||||
(ldapUser.ActivationStatus != EmployeeActivationStatus.AutoGenerated
|
||||
|| ldapUser.ActivationStatus == EmployeeActivationStatus.AutoGenerated && portalUser.ActivationStatus == EmployeeActivationStatus.AutoGenerated))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByEmail(portalUser.Email ?? "NULL",
|
||||
ldapUser.Email ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (notEqual(portalUser.Sid, ldapUser.Sid))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserBySid(portalUser.Sid ?? "NULL",
|
||||
ldapUser.Sid ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.TitleAttribute) && notEqual(portalUser.Title, ldapUser.Title))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByTitle(portalUser.Title ?? "NULL",
|
||||
ldapUser.Title ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.LocationAttribute) && notEqual(portalUser.Location, ldapUser.Location))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByLocation(portalUser.Location ?? "NULL",
|
||||
ldapUser.Location ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (portalUser.ActivationStatus != ldapUser.ActivationStatus &&
|
||||
(!portalUser.ActivationStatus.HasFlag(EmployeeActivationStatus.Activated) || portalUser.Email != ldapUser.Email) &&
|
||||
ldapUser.ActivationStatus != EmployeeActivationStatus.AutoGenerated)
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByActivationStatus(portalUser.ActivationStatus,
|
||||
ldapUser.ActivationStatus);
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (portalUser.Status != ldapUser.Status)
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByStatus(portalUser.Status,
|
||||
ldapUser.Status);
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (portalUser.ContactsList == null && ldapUser.ContactsList.Count != 0 || portalUser.ContactsList != null && (ldapUser.ContactsList.Count != portalUser.ContactsList.Count ||
|
||||
!ldapUser.Contacts.All(portalUser.Contacts.Contains)))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByContacts(string.Join("|", portalUser.Contacts),
|
||||
string.Join("|", ldapUser.Contacts));
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.MobilePhoneAttribute) && notEqual(portalUser.MobilePhone, ldapUser.MobilePhone))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByPrimaryPhone(portalUser.MobilePhone ?? "NULL",
|
||||
ldapUser.MobilePhone ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.BirthDayAttribute) && portalUser.BirthDate == null && ldapUser.BirthDate != null || portalUser.BirthDate != null && !portalUser.BirthDate.Equals(ldapUser.BirthDate))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserByBirthDate(portalUser.BirthDate.ToString() ?? "NULL",
|
||||
ldapUser.BirthDate.ToString() ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.GenderAttribute) && portalUser.Sex == null && ldapUser.Sex != null || portalUser.Sex != null && !portalUser.Sex.Equals(ldapUser.Sex))
|
||||
{
|
||||
_logger.DebugNeedUpdateUserBySex(portalUser.Sex.ToString() ?? "NULL",
|
||||
ldapUser.Sex.ToString() ?? "NULL");
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.DebugNeedUpdateUser(ex);
|
||||
}
|
||||
|
||||
return needUpdate;
|
||||
}
|
||||
|
||||
private bool TryUpdateUserWithLDAPInfo(UserInfo userToUpdate, UserInfo updateInfo, bool onlyGetChanges, out UserInfo portlaUserInfo)
|
||||
{
|
||||
portlaUserInfo = Constants.LostUser;
|
||||
|
||||
try
|
||||
{
|
||||
_logger.DebugTryUpdateUserWithLdapInfo();
|
||||
|
||||
var settings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
if (!userToUpdate.UserName.Equals(updateInfo.UserName, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& !TryChangeExistingUserName(updateInfo.UserName, onlyGetChanges))
|
||||
{
|
||||
_logger.DebugUpdateUserUserNameAlredyExists(userToUpdate.Id, userToUpdate.UserName, updateInfo.UserName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!userToUpdate.Email.Equals(updateInfo.Email, StringComparison.InvariantCultureIgnoreCase)
|
||||
&& !CheckUniqueEmail(userToUpdate.Id, updateInfo.Email))
|
||||
{
|
||||
_logger.DebugUpdateUserEmailAlreadyExists(userToUpdate.Id, userToUpdate.Email, updateInfo.Email);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (userToUpdate.Email != updateInfo.Email && !(updateInfo.ActivationStatus == EmployeeActivationStatus.AutoGenerated &&
|
||||
userToUpdate.ActivationStatus == (EmployeeActivationStatus.AutoGenerated | EmployeeActivationStatus.Activated)))
|
||||
{
|
||||
userToUpdate.ActivationStatus = updateInfo.ActivationStatus;
|
||||
userToUpdate.Email = updateInfo.Email;
|
||||
}
|
||||
|
||||
userToUpdate.UserName = updateInfo.UserName;
|
||||
userToUpdate.FirstName = updateInfo.FirstName;
|
||||
userToUpdate.LastName = updateInfo.LastName;
|
||||
userToUpdate.Sid = updateInfo.Sid;
|
||||
userToUpdate.Contacts = updateInfo.Contacts;
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.TitleAttribute))
|
||||
{
|
||||
userToUpdate.Title = updateInfo.Title;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.LocationAttribute))
|
||||
{
|
||||
userToUpdate.Location = updateInfo.Location;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.GenderAttribute))
|
||||
{
|
||||
userToUpdate.Sex = updateInfo.Sex;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.BirthDayAttribute))
|
||||
{
|
||||
userToUpdate.BirthDate = updateInfo.BirthDate;
|
||||
}
|
||||
|
||||
if (settings.LdapMapping.ContainsKey(Mapping.MobilePhoneAttribute))
|
||||
{
|
||||
userToUpdate.MobilePhone = updateInfo.MobilePhone;
|
||||
}
|
||||
|
||||
if (!userToUpdate.IsOwner(_tenantManager.GetCurrentTenant())) // Owner must never be terminated by LDAP!
|
||||
{
|
||||
userToUpdate.Status = updateInfo.Status;
|
||||
}
|
||||
|
||||
if (!onlyGetChanges)
|
||||
{
|
||||
_logger.DebugSaveUserInfo(userToUpdate.GetUserInfoString());
|
||||
|
||||
portlaUserInfo = _userManager.SaveUserInfo(userToUpdate);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorUpdateUserWithLDAPInfo(userToUpdate.Id, userToUpdate.UserName,
|
||||
userToUpdate.Sid, ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetAndSyncLdapUserInfo(string login, string password, out UserInfo userInfo)
|
||||
{
|
||||
userInfo = Constants.LostUser;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
var settings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
if (!settings.EnableLdapAuthentication)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.DebugTryGetAndSyncLdapUserInfo(login);
|
||||
|
||||
_novellLdapUserImporter.Init(settings, _resource);
|
||||
|
||||
var ldapUserInfo = _novellLdapUserImporter.Login(login, password);
|
||||
|
||||
if (ldapUserInfo == null || ldapUserInfo.Item1.Equals(Constants.LostUser))
|
||||
{
|
||||
_logger.DebugNovellLdapUserImporterLoginFailed(login);
|
||||
return false;
|
||||
}
|
||||
|
||||
var portalUser = _userManager.GetUserBySid(ldapUserInfo.Item1.Sid);
|
||||
|
||||
if (portalUser.Status == EmployeeStatus.Terminated || portalUser.Equals(Constants.LostUser))
|
||||
{
|
||||
if (!ldapUserInfo.Item2.IsDisabled)
|
||||
{
|
||||
_logger.DebugTryCheckAndSyncToLdapUser(ldapUserInfo.Item1.UserName, ldapUserInfo.Item1.Email, ldapUserInfo.Item2.DistinguishedName);
|
||||
|
||||
if (!TryCheckAndSyncToLdapUser(ldapUserInfo, _novellLdapUserImporter, out userInfo))
|
||||
{
|
||||
_logger.DebugTryCheckAndSyncToLdapUserFailed();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.DebugTryCheckAndSyncToLdapUser(ldapUserInfo.Item1.UserName, ldapUserInfo.Item1.Email, ldapUserInfo.Item2.DistinguishedName);
|
||||
|
||||
var tenant = _tenantManager.GetCurrentTenant();
|
||||
|
||||
new Task(() =>
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var tenantManager = scope.ServiceProvider.GetRequiredService<TenantManager>();
|
||||
var securityContext = scope.ServiceProvider.GetRequiredService<SecurityContext>();
|
||||
var novellLdapUserImporter = scope.ServiceProvider.GetRequiredService<NovellLdapUserImporter>();
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserManager>();
|
||||
var cookiesManager = scope.ServiceProvider.GetRequiredService<CookiesManager>();
|
||||
var log = scope.ServiceProvider.GetRequiredService<ILogger<LdapUserManager>>();
|
||||
|
||||
tenantManager.SetCurrentTenant(tenant);
|
||||
securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
|
||||
|
||||
var uInfo = SyncLDAPUser(ldapUserInfo.Item1);
|
||||
|
||||
var newLdapUserInfo = new Tuple<UserInfo, LdapObject>(uInfo, ldapUserInfo.Item2);
|
||||
|
||||
if (novellLdapUserImporter.Settings.GroupMembership)
|
||||
{
|
||||
if (!novellLdapUserImporter.TrySyncUserGroupMembership(newLdapUserInfo))
|
||||
{
|
||||
log.DebugTryGetAndSyncLdapUserInfoDisablingUser(login, uInfo);
|
||||
uInfo.Status = EmployeeStatus.Terminated;
|
||||
uInfo.Sid = null;
|
||||
userManager.SaveUserInfo(uInfo);
|
||||
cookiesManager.ResetUserCookie(uInfo.Id);
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
|
||||
if (ldapUserInfo.Item2.IsDisabled)
|
||||
{
|
||||
_logger.DebugTryGetAndSyncLdapUserInfo(login);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
userInfo = portalUser;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorTryGetLdapUserInfoFailed(login, ex);
|
||||
userInfo = Constants.LostUser;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryCheckAndSyncToLdapUser(Tuple<UserInfo, LdapObject> ldapUserInfo, LdapUserImporter importer,
|
||||
out UserInfo userInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
_securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem);
|
||||
|
||||
userInfo = SyncLDAPUser(ldapUserInfo.Item1);
|
||||
|
||||
if (userInfo == null || userInfo.Equals(Constants.LostUser))
|
||||
{
|
||||
throw new Exception("The user did not pass the configuration check by ldap user settings");
|
||||
}
|
||||
|
||||
var newLdapUserInfo = new Tuple<UserInfo, LdapObject>(userInfo, ldapUserInfo.Item2);
|
||||
|
||||
if (!importer.Settings.GroupMembership)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!importer.TrySyncUserGroupMembership(newLdapUserInfo))
|
||||
{
|
||||
userInfo.Sid = null;
|
||||
userInfo.Status = EmployeeStatus.Terminated;
|
||||
_userManager.SaveUserInfo(userInfo);
|
||||
throw new Exception("The user did not pass the configuration check by ldap group settings");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorTrySyncLdapUser(ldapUserInfo.Item1.Sid,
|
||||
ldapUserInfo.Item1.Email, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_securityContext.Logout();
|
||||
}
|
||||
|
||||
userInfo = Constants.LostUser;
|
||||
return false;
|
||||
}
|
||||
}
|
220
common/ASC.ActiveDirectory/LdapUtils.cs
Normal file
220
common/ASC.ActiveDirectory/LdapUtils.cs
Normal file
@ -0,0 +1,220 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Action = System.Action;
|
||||
using Constants = ASC.Core.Users.Constants;
|
||||
|
||||
namespace ASC.ActiveDirectory;
|
||||
|
||||
public static class LdapUtils
|
||||
{
|
||||
private static readonly Regex _dcRegex = new Regex("dc=([^,]+)", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
|
||||
public static string DistinguishedNameToDomain(string distinguishedName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(distinguishedName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var matchList = _dcRegex.Matches(distinguishedName);
|
||||
|
||||
var dcList = matchList.Cast<Match>().Select(match => match.Groups[1].Value).ToList();
|
||||
|
||||
return !dcList.Any() ? null : string.Join(".", dcList);
|
||||
}
|
||||
|
||||
public static bool IsLoginAccepted(LdapLogin ldapLogin, UserInfo ldapUser, string ldapDomain)
|
||||
{
|
||||
if (ldapLogin == null
|
||||
|| string.IsNullOrEmpty(ldapLogin.ToString())
|
||||
|| string.IsNullOrEmpty(ldapDomain)
|
||||
|| ldapUser == null
|
||||
|| ldapUser.Equals(Constants.LostUser)
|
||||
|| string.IsNullOrEmpty(ldapUser.Email)
|
||||
|| string.IsNullOrEmpty(ldapUser.UserName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasDomain = !string.IsNullOrEmpty(ldapLogin.Domain);
|
||||
|
||||
if (!hasDomain)
|
||||
{
|
||||
return ldapLogin.Username.Equals(ldapUser.UserName, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
var fullLogin = ldapLogin.ToString();
|
||||
|
||||
if (fullLogin.Equals(ldapUser.Email, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ldapDomain.StartsWith(ldapLogin.Domain))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var alterEmail = ldapUser.UserName.Contains("@")
|
||||
? ldapUser.UserName
|
||||
: string.Format("{0}@{1}", ldapUser.UserName, ldapDomain);
|
||||
|
||||
return IsLoginAndEmailSuitable(fullLogin, alterEmail);
|
||||
}
|
||||
|
||||
private static string GetLdapAccessableEmail(string email)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(email))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var login = LdapLogin.ParseLogin(email);
|
||||
|
||||
if (string.IsNullOrEmpty(login.Domain))
|
||||
{
|
||||
return email;
|
||||
}
|
||||
|
||||
var dotIndex = login.Domain.LastIndexOf(".", StringComparison.Ordinal);
|
||||
|
||||
var accessableEmail = dotIndex > -1 ? string.Format("{0}@{1}", login.Username, login.Domain.Remove(dotIndex)) : email;
|
||||
|
||||
return accessableEmail;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsLoginAndEmailSuitable(string login, string email)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(email))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var accessableLogin = GetLdapAccessableEmail(login);
|
||||
|
||||
if (string.IsNullOrEmpty(accessableLogin))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var accessableEmail = GetLdapAccessableEmail(email);
|
||||
|
||||
if (string.IsNullOrEmpty(accessableEmail))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return accessableLogin.Equals(accessableEmail, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GeneratePassword()
|
||||
{
|
||||
return Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public static void SkipErrors(Action method, ILogger log = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
method();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (log != null)
|
||||
{
|
||||
log.ErrorSkipErrors(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetContactsString(this UserInfo userInfo)
|
||||
{
|
||||
if (userInfo.ContactsList == null || userInfo.ContactsList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var sBuilder = new StringBuilder();
|
||||
foreach (var contact in userInfo.Contacts)
|
||||
{
|
||||
sBuilder.AppendFormat("{0}|", contact);
|
||||
}
|
||||
return sBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string GetUserInfoString(this UserInfo userInfo)
|
||||
{
|
||||
return string.Format(
|
||||
"{{ ID: '{0}' SID: '{1}' Email '{2}' UserName: '{3}' FirstName: '{4}' LastName: '{5}' Title: '{6}' Location: '{7}' Contacts: '{8}' Status: '{9}' }}",
|
||||
userInfo.Id,
|
||||
userInfo.Sid,
|
||||
userInfo.Email,
|
||||
userInfo.UserName,
|
||||
userInfo.FirstName,
|
||||
userInfo.LastName,
|
||||
userInfo.Title,
|
||||
userInfo.Location,
|
||||
userInfo.GetContactsString(),
|
||||
Enum.GetName(typeof(EmployeeStatus), userInfo.Status));
|
||||
}
|
||||
|
||||
public static string UnescapeLdapString(string ldapString)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var i = 0; i < ldapString.Length; i++)
|
||||
{
|
||||
var ch = ldapString[i];
|
||||
if (ch == '\\')
|
||||
{
|
||||
if (i + 1 < ldapString.Length && ldapString[i + 1] == ch)
|
||||
{
|
||||
sb.Append(ch);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(ch);
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapCertificateConfirmRequestLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "GetLdapCertProblems: {SslPolicyErrors}")]
|
||||
public static partial void WarnGetLdapCertProblems(this ILogger logger, string SslPolicyErrors);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetLdapCertProblems() failed")]
|
||||
public static partial void ErrorGetLdapCertProblems(this ILogger logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LdapCertificateConfirmRequest.FromCert() failed")]
|
||||
public static partial void ErrorLdapCertificateConfirmRequest(this ILogger logger, Exception exception);
|
||||
}
|
33
common/ASC.ActiveDirectory/Log/LdapChangeCollectionLogger.cs
Normal file
33
common/ASC.ActiveDirectory/Log/LdapChangeCollectionLogger.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapChangeCollectionLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetPropChange({propName})")]
|
||||
public static partial void ErrorCanNotGetSidProperty(this ILogger logger, string propName, Exception exception);
|
||||
}
|
51
common/ASC.ActiveDirectory/Log/LdapHelperLogger.cs
Normal file
51
common/ASC.ActiveDirectory/Log/LdapHelperLogger.cs
Normal file
@ -0,0 +1,51 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapHelperLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "UserExistsInGroup() failed")]
|
||||
public static partial void ErrorUserExistsInGroupFailed(this ILogger<LdapHelper> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "NovellLdapHelper->SearchDomain() failed")]
|
||||
public static partial void WarnSearchDomainFailed(this ILogger<LdapHelper> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "NovellLdapHelper->CheckUserDn(userDn: {userDn}) Wrong User DN parameter")]
|
||||
public static partial void ErrorWrongUserDnParameter(this ILogger<LdapHelper> logger, string userDn);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "NovellLdapHelper->CheckGroupDn(groupDn: {groupDn}): Wrong Group DN parameter")]
|
||||
public static partial void ErrorWrongGroupDnParameter(this ILogger<LdapHelper> logger, string groupDn);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "NovellLdapHelper->GetUsers(filter: '{filter}' limit: {limit}) failed")]
|
||||
public static partial void ErrorGetUsersFailed(this ILogger<LdapHelper> logger, string filter, int limit, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "NovellLdapHelper->GetUserBySid(sid: '{sid}') failed")]
|
||||
public static partial void ErrorGetUserBySidFailed(this ILogger<LdapHelper> logger, string sid, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "NovellLdapHelper->GetGroups(criteria: '{criteria}') failed")]
|
||||
public static partial void ErrorGetGroupsFailed(this ILogger<LdapHelper> logger, Criteria criteria, Exception exception);
|
||||
}
|
37
common/ASC.ActiveDirectory/Log/LdapObjectExtensionLogger.cs
Normal file
37
common/ASC.ActiveDirectory/Log/LdapObjectExtensionLogger.cs
Normal file
@ -0,0 +1,37 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapObjectExtensionLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't get attribute from ldap object (attr = {attribute}, dn = {dn})")]
|
||||
public static partial void ErrorCanNotGetAttribute(this ILogger<LdapObjectExtension> logger, string attribute, string dn,Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't get attributes from ldap object (attr = {attribute}, dn = {dn})")]
|
||||
public static partial void ErrorCanNotGetAttributes(this ILogger<LdapObjectExtension> logger, string attribute, string dn, Exception exception);
|
||||
|
||||
}
|
160
common/ASC.ActiveDirectory/Log/LdapOperationJobLogger.cs
Normal file
160
common/ASC.ActiveDirectory/Log/LdapOperationJobLogger.cs
Normal file
@ -0,0 +1,160 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapOperationJobLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't save default LDAP settings.")]
|
||||
public static partial void ErrorSaveDefaultLdapSettings(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "Start '{operationtype}' operation")]
|
||||
public static partial void InfoStartOperation(this ILogger<LdapOperationJob> logger, string operationtype);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "PrepareSettings()")]
|
||||
public static partial void DebugPrepareSettings(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "PrepareSettings() Error: {error}")]
|
||||
public static partial void DebugPrepareSettingsError(this ILogger<LdapOperationJob> logger, string error);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapSettingsChecker.CheckSettings() Error: {error}")]
|
||||
public static partial void DebugCheckSettingsError(this ILogger<LdapOperationJob> logger, string error);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "{error}")]
|
||||
public static partial void ErrorAuthorizing(this ILogger<LdapOperationJob> logger, string error, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TenantQuotaException")]
|
||||
public static partial void ErrorTenantQuota(this ILogger<LdapOperationJob> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "FormatException")]
|
||||
public static partial void ErrorFormatException(this ILogger<LdapOperationJob> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Internal server error")]
|
||||
public static partial void ErrorInternal(this ILogger<LdapOperationJob> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LdapOperation finalization problem")]
|
||||
public static partial void ErrorLdapOperationFinalizationlProblem(this ILogger<LdapOperationJob> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't save LDAP settings.")]
|
||||
public static partial void ErrorSaveLdapSettings(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "{setting}")]
|
||||
public static partial void DebugLdapSettings(this ILogger<LdapOperationJob> logger, string setting);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TurnOffLDAP()")]
|
||||
public static partial void DebugTurnOffLDAP(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(acceptCertificate={acceptCertificate}, cert thumbprint: {acceptCertificatehash})")]
|
||||
public static partial void ErrorCheckSettings(this ILogger<LdapOperationJob> logger, bool acceptCertificate, string acceptCertificatehash, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "CoreContext.UserManager.SaveUserInfo({userInfo})")]
|
||||
public static partial void DebugSaveUserInfo(this ILogger<LdapOperationJob> logger, string userInfo);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncLDAPUsers()")]
|
||||
public static partial void DebugSyncLDAPUsers(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncLDAPUsersInGroups()")]
|
||||
public static partial void DebugSyncLDAPUsersInGroups(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "SyncLdapAvatar() Removing photo for '{guid}'")]
|
||||
public static partial void InfoSyncLdapAvatarsRemovingPhoto(this ILogger<LdapOperationJob> logger, Guid guid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncLdapAvatar() Found photo for '{sid}'")]
|
||||
public static partial void DebugSyncLdapAvatarsFoundPhoto(this ILogger<LdapOperationJob> logger, string sid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncLdapAvatar() Same hash, skipping.")]
|
||||
public static partial void DebugSyncLdapAvatarsSkipping(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncLdapAvatar() Couldn't save photo for '{guid}'")]
|
||||
public static partial void DebugSyncLdapAvatarsCouldNotSavePhoto(this ILogger<LdapOperationJob> logger, Guid guid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TakeUsersRights() CurrentAccessRights is empty, skipping")]
|
||||
public static partial void DebugAccessRightsIsEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TakeUsersRights() Attempting to take admin rights from yourself `{user}`, skipping")]
|
||||
public static partial void DebugAttemptingTakeAdminRights(this ILogger<LdapOperationJob> logger, string user);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TakeUsersRights() Taking admin rights ({accessRight}) from '{user}'")]
|
||||
public static partial void DebugTakingAdminRights(this ILogger<LdapOperationJob> logger, LdapSettings.AccessRight accessRight, string user);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "GiveUsersRights() No ldap groups found for ({accessRight}) access rights, skipping")]
|
||||
public static partial void DebugGiveUsersRightsNoLdapGroups(this ILogger<LdapOperationJob> logger, LdapSettings.AccessRight accessRight);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "GiveUsersRights() Couldn't find portal group for '{sid}'")]
|
||||
public static partial void DebugGiveUsersRightsCouldNotFindPortalGroup(this ILogger<LdapOperationJob> logger, string sid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "GiveUsersRights() Found '{countUsers}' users for group '{groupName}' ({groupId})")]
|
||||
public static partial void DebugGiveUsersRightsFoundUsersForGroup(this ILogger<LdapOperationJob> logger, int countUsers,string groupName, Guid groupId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "GiveUsersRights() Cleared manually added user rights for '{userName}'")]
|
||||
public static partial void DebugGiveUsersRightsClearedAndAddedRights(this ILogger<LdapOperationJob> logger, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Importer.GetDiscoveredUsersByAttributes() Success: Users count: {countUsers}")]
|
||||
public static partial void DebugGetDiscoveredUsersByAttributes(this ILogger<LdapOperationJob> logger, int countUsers);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Importer.GetDiscoveredGroupsByAttributes() Success: Groups count: {countGroups}")]
|
||||
public static partial void DebugGetDiscoveredGroupsByAttributes(this ILogger<LdapOperationJob> logger, int countGroups);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "GetGroupsUsers() Success: Users count: {countUsers}")]
|
||||
public static partial void DebugGetGroupsUsers(this ILogger<LdapOperationJob> logger, int countUsers);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "RemoveOldDbUsers() Attempting to exclude yourself `{id}` from group or user filters, skipping.")]
|
||||
public static partial void DebugRemoveOldDbUsersAttemptingExcludeYourself(this ILogger<LdapOperationJob> logger, Guid id);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "Progress: {percentage}% {status} {source}")]
|
||||
public static partial void InfoProgress(this ILogger<LdapOperationJob> logger,double percentage, string status, string source);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Wrong LDAP settings were received from client.")]
|
||||
public static partial void ErrorWrongLdapSettings(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.Server is null or empty.")]
|
||||
public static partial void ErrorServerIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.UserDN is null or empty.")]
|
||||
public static partial void ErrorUserDnIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.LoginAttribute is null or empty.")]
|
||||
public static partial void ErrorLoginAttributeIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.GroupDN is null or empty.")]
|
||||
public static partial void ErrorGroupDnIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.GroupAttribute is null or empty.")]
|
||||
public static partial void ErrorGroupAttributeIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.UserAttribute is null or empty.")]
|
||||
public static partial void ErrorUserAttributeIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.Login is null or empty.")]
|
||||
public static partial void ErrorloginIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.PasswordBytes is null.")]
|
||||
public static partial void ErrorPasswordBytesIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "settings.Password is null or empty.")]
|
||||
public static partial void ErrorPasswordIsNullOrEmpty(this ILogger<LdapOperationJob> logger);
|
||||
|
||||
}
|
57
common/ASC.ActiveDirectory/Log/LdapSettingsCheckerLogger.cs
Normal file
57
common/ASC.ActiveDirectory/Log/LdapSettingsCheckerLogger.cs
Normal file
@ -0,0 +1,57 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapSettingsCheckerLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(acceptCertificate={acceptCertificate}): NovellLdapTlsCertificateRequestedException")]
|
||||
public static partial void ErrorNovellLdapTlsCertificateRequestedException(this ILogger<LdapSettingsChecker> logger, bool acceptCertificate, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): NotSupportedException")]
|
||||
public static partial void ErrorNotSupportedException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): SocketException")]
|
||||
public static partial void ErrorSocketException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): ArgumentException")]
|
||||
public static partial void ErrorArgumentException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): SecurityException")]
|
||||
public static partial void ErrorSecurityException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): SystemException")]
|
||||
public static partial void ErrorSystemException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckSettings(): Exception")]
|
||||
public static partial void ErrorCheckSettingsException(this ILogger<LdapSettingsChecker> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Wrong User DN parameter: {userDn}")]
|
||||
public static partial void ErrorWrongUserDn(this ILogger<LdapSettingsChecker> logger, string userDn, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Wrong Group DN parameter: {groupDn}")]
|
||||
public static partial void ErrorWrongGroupDn(this ILogger<LdapSettingsChecker> logger, string groupDn, Exception exception);
|
||||
}
|
108
common/ASC.ActiveDirectory/Log/LdapUserImporterLogger.cs
Normal file
108
common/ASC.ActiveDirectory/Log/LdapUserImporterLogger.cs
Normal file
@ -0,0 +1,108 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapUserImporterLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter.GetGroupUsers(Group name: {groupName})")]
|
||||
public static partial void DebugGetGroupUsers(this ILogger<LdapUserImporter> logger, string groupName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Found nested LDAP Group: {groupName}")]
|
||||
public static partial void DebugFoundNestedLdapGroup(this ILogger<LdapUserImporter> logger, string groupName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Skip already watched nested LDAP Group: {groupName}")]
|
||||
public static partial void DebugSkipAlreadyWatched(this ILogger<LdapUserImporter> logger, string groupName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "IsUserExistInGroups(login: '{login}' sid: '{sid}')")]
|
||||
public static partial void ErrorIsUserExistInGroups(this ILogger<LdapUserImporter> logger, string login, string sid, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetAndCheckCurrentGroups(login: '{login}' sid: '{sid}')")]
|
||||
public static partial void ErrorGetAndCheckCurrentGroups(this ILogger<LdapUserImporter> logger, string login, string sid, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TrySyncUserGroupMembership(groupname: '{groupName}' sid: '{sid}') no portal group found, creating")]
|
||||
public static partial void DebugTrySyncUserGroupMembershipCreatingPortalGroup(this ILogger<LdapUserImporter> logger, string groupName, string sid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TrySyncUserGroupMembership(username: '{userName}' sid: '{userSid}') adding user to group (groupname: '{groupName}' sid: '{groupSid}')")]
|
||||
public static partial void DebugTrySyncUserGroupMembershipAddingUserToGroup(this ILogger<LdapUserImporter> logger, string userName, string userSid, string groupName, string groupSid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TrySyncUserGroupMembership(username: '{userName}' sid: '{userSid}') removing user from group (groupname: '{groupName}' sid: '{groupSid}')")]
|
||||
public static partial void DebugTrySyncUserGroupMembershipRemovingUserFromGroup(this ILogger<LdapUserImporter> logger, string userName, string userSid, string groupName, string groupSid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TryLoadLDAPUsers(): Incorrect filter. userFilter = {userFilter}")]
|
||||
public static partial void ErrorTryLoadLDAPUsersIncorrectUserFilter(this ILogger<LdapUserImporter> logger, string userFilter);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TryLoadLDAPGroups(): Incorrect group filter. groupFilter = {groupFilter}")]
|
||||
public static partial void ErrorTryLoadLDAPUsersIncorrectGroupFilter(this ILogger<LdapUserImporter> logger, string groupFilter);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LoadLDAPDomain(): Error")]
|
||||
public static partial void ErrorLoadLDAPDomain(this ILogger<LdapUserImporter> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Login Attribute parameter ({loginAttributeParametr}) not found: DN = {distinguishedName}")]
|
||||
public static partial void DebugLoginAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string loginAttributeParametr, string distinguishedName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Login Attribute parameter ({loginAttributeParametr}) not found: loginAttribute = {loginAttribute}")]
|
||||
public static partial void ErrorLoginAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string loginAttributeParametr, string loginAttribute, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "User Attribute parameter ({userAttributeParametr}) not found: DN = {distinguishedName}")]
|
||||
public static partial void DebugUserAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string userAttributeParametr, string distinguishedName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "User Attribute parameter ({userAttributeParametr}) not found: userAttr = {userAttribute}")]
|
||||
public static partial void ErrorUserAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string userAttributeParametr, string userAttribute, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Group Attribute parameter ({groupAttributeParametr}) not found: {groupAttribute}")]
|
||||
public static partial void ErrorGroupAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string groupAttributeParametr, string groupAttribute, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Group Name Attribute parameter ({groupNameAttributeParametr}) not found: {groupAttribute}")]
|
||||
public static partial void DebugGroupNameAttributeParameterNotFound(this ILogger<LdapUserImporter> logger, string groupNameAttributeParametr, string groupAttribute);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter.FindUsersByPrimaryGroup()")]
|
||||
public static partial void DebugFindUsersByPrimaryGroup(this ILogger<LdapUserImporter> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter.FindUserByMember(user attr: {userAttribute})")]
|
||||
public static partial void DebugFindUserByMember(this ILogger<LdapUserImporter> logger, string userAttribute);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter.FindGroupByMember(member: {member})")]
|
||||
public static partial void DebugFindGroupByMember(this ILogger<LdapUserImporter> logger, string member);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "FindLdapUser->ToUserInfo() failed")]
|
||||
public static partial void ErrorToUserInfo(this ILogger<LdapUserImporter> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "LDAP: DN: '{distinguishedName}' Login Attribute '{loginAttribute}' is empty")]
|
||||
public static partial void WarnLoginAttributeIsEmpty(this ILogger<LdapUserImporter> logger, string distinguishedName, string loginAttribute);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "FindLdapUsers(login '{login}') found: {usersCount} users")]
|
||||
public static partial void DebugFindLdapUsers(this ILogger<LdapUserImporter> logger, string login, int usersCount);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter->Login(login: '{login}', dn: '{sid}') failed. Error: missing DN or SID")]
|
||||
public static partial void DebugLdapUserImporterFailed(this ILogger<LdapUserImporter> logger, string login, string sid);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LdapUserImporter.Login('{login}')")]
|
||||
public static partial void DebugLdapUserImporterLogin(this ILogger<LdapUserImporter> logger, string login);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LdapUserImporter->Login(login: '{login}') failed")]
|
||||
public static partial void ErrorLdapUserImporterLoginFailed(this ILogger<LdapUserImporter> logger, string login, Exception exception);
|
||||
}
|
146
common/ASC.ActiveDirectory/Log/LdapUserManagerLogger.cs
Normal file
146
common/ASC.ActiveDirectory/Log/LdapUserManagerLogger.cs
Normal file
@ -0,0 +1,146 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapUserManagerLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryAddLDAPUser(SID: {sid}): Email '{email}' UserName: {userName}")]
|
||||
public static partial void DebugTryAddLdapUser(this ILogger<LdapUserManager> logger, string sid, string email, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryAddLDAPUser(SID: {sid}): Email '{email}' already exists.")]
|
||||
public static partial void DebugUserAlredyExistsForEmail(this ILogger<LdapUserManager> logger, string sid, string email);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryAddLDAPUser(SID: {sid}): Username '{userName}' already exists.")]
|
||||
public static partial void DebugUserAlredyExistsForUserName(this ILogger<LdapUserManager> logger, string sid, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryAddLDAPUser(SID: {sid}): Username '{userName}' adding this user would exceed quota.")]
|
||||
public static partial void DebugExceedQuota(this ILogger<LdapUserManager> logger, string sid, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "CoreContext.UserManager.SaveUserInfo({userInfo})")]
|
||||
public static partial void DebugSaveUserInfo(this ILogger<LdapUserManager> logger, string userInfo);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SecurityContext.SetUserPassword(ID:{id})")]
|
||||
public static partial void DebugSetUserPassword(this ILogger<LdapUserManager> logger, Guid id);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TryAddLDAPUser(UserName='{userName}' Sid='{sid}')")]
|
||||
public static partial void ErrorTryAddLdapUser(this ILogger<LdapUserManager> logger, string userName, string sid, Exception ex);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryChangeExistingUserName()")]
|
||||
public static partial void DebugTryChangeExistingUserName(this ILogger<LdapUserManager> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TryChangeOtherUserName({userName})")]
|
||||
public static partial void ErrorTryChangeOtherUserName(this ILogger<LdapUserManager> logger, string userName, Exception ex);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncUserLDAP(SID: {sid}, Username: '{userName}') ADD failed: Status is {status}")]
|
||||
public static partial void DebugSyncUserLdapFailedWithStatus(this ILogger<LdapUserManager> logger, string sid, string userName, string status);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncUserLDAP(SID: {sid}, Username: '{userName}') ADD failed: Another ldap user with email '{email}' already exists")]
|
||||
public static partial void DebugSyncUserLdapFailedWithEmail(this ILogger<LdapUserManager> logger, string sid, string userName, string email);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncUserLDAP(SID: {sid}, Username: '{userName}') No need to update, skipping")]
|
||||
public static partial void DebugSyncUserLdapSkipping(this ILogger<LdapUserManager> logger, string sid, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "SyncUserLDAP(SID: {sid}, Username: '{userName}') Userinfo is outdated, updating")]
|
||||
public static partial void DebugSyncUserLdapUpdaiting(this ILogger<LdapUserManager> logger, string sid, string userName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by FirstName->portal: '{firstNamePortalUser}', ldap: '{firstNameLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByFirstName(this ILogger<LdapUserManager> logger, string firstNamePortalUser, string firstNameLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by LastName -> portal: '{lastNamePortalUser}', ldap: '{lastNameLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByLastName(this ILogger<LdapUserManager> logger, string lastNamePortalUser, string lastNameLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by UserName -> portal: '{userNamePorta}', ldap: '{userNameLdap}'")]
|
||||
public static partial void DebugNeedUpdateUserByUserName(this ILogger<LdapUserManager> logger, string userNamePorta, string userNameLdap);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Email -> portal: '{emailPortalUser}', ldap: '{emailLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByEmail(this ILogger<LdapUserManager> logger, string emailPortalUser, string emailLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Sid -> portal: '{sidPortalUser}', ldap: '{sidLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserBySid(this ILogger<LdapUserManager> logger, string sidPortalUser, string sidLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Title -> portal: '{titlePortalUser}', ldap: '{titleLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByTitle(this ILogger<LdapUserManager> logger, string titlePortalUser, string titleLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Location -> portal: '{locationPortalUser}', ldap: '{locationLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByLocation(this ILogger<LdapUserManager> logger, string locationPortalUser, string locationLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by ActivationStatus -> portal: '{activationStatusPortalUser}', ldap: '{activationStatusLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByActivationStatus(this ILogger<LdapUserManager> logger, EmployeeActivationStatus activationStatusPortalUser, EmployeeActivationStatus activationStatusLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Status -> portal: '{statusPortalUser}', ldap: '{statusLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByStatus(this ILogger<LdapUserManager> logger, EmployeeStatus statusPortalUser, EmployeeStatus statusLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Contacts -> portal: '{contactsPortalUser}', ldap: '{contactsLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByContacts(this ILogger<LdapUserManager> logger, string contactsPortalUser, string contactsLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by PrimaryPhone -> portal: '{primaryPhonePortalUser}', ldap: '{primaryPhoneLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByPrimaryPhone(this ILogger<LdapUserManager> logger, string primaryPhonePortalUser, string primaryPhoneLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by BirthDate -> portal: '{birthDatePortalUser}', ldap: '{birthDateLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserByBirthDate(this ILogger<LdapUserManager> logger, string birthDatePortalUser, string birthDateLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser by Sex -> portal: '{sexPortalUser}', ldap: '{sexDateLdapUser}'")]
|
||||
public static partial void DebugNeedUpdateUserBySex(this ILogger<LdapUserManager> logger, string sexPortalUser, string sexDateLdapUser);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NeedUpdateUser")]
|
||||
public static partial void DebugNeedUpdateUser(this ILogger<LdapUserManager> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryUpdateUserWithLDAPInfo()")]
|
||||
public static partial void DebugTryUpdateUserWithLdapInfo(this ILogger<LdapUserManager> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "UpdateUserWithLDAPInfo(ID: {userId}): New username already exists. (Old: '{OldUserInfo})' New: '{NewUserInfo}'")]
|
||||
public static partial void DebugUpdateUserUserNameAlredyExists(this ILogger<LdapUserManager> logger, Guid userId, string oldUserInfo, string newUserInfo);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "UpdateUserWithLDAPInfo(ID: {userId}): New email already exists. (Old: '{oldEmail})' New: '{newEmail}'")]
|
||||
public static partial void DebugUpdateUserEmailAlreadyExists(this ILogger<LdapUserManager> logger, Guid userId, string oldEmail, string newEmail);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "UpdateUserWithLDAPInfo(Id='{userId}' UserName='{userName}' Sid='{sid}')")]
|
||||
public static partial void ErrorUpdateUserWithLDAPInfo(this ILogger<LdapUserManager> logger, Guid userId, string userName, string sid, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryGetAndSyncLdapUserInfo(login: \"{login}\")")]
|
||||
public static partial void DebugTryGetAndSyncLdapUserInfo(this ILogger<LdapUserManager> logger, string login);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "NovellLdapUserImporter.Login('{login}') failed.")]
|
||||
public static partial void DebugNovellLdapUserImporterLoginFailed(this ILogger<LdapUserManager> logger, string login);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryCheckAndSyncToLdapUser(Username: '{userName}', Email: {email}, DN: {distinguishedName})")]
|
||||
public static partial void DebugTryCheckAndSyncToLdapUser(this ILogger<LdapUserManager> logger, string userName, string email, string distinguishedName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryCheckAndSyncToLdapUser() failed")]
|
||||
public static partial void DebugTryCheckAndSyncToLdapUserFailed(this ILogger<LdapUserManager> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TryGetLdapUserInfo(login: '{login}')")]
|
||||
public static partial void ErrorTryGetLdapUserInfoFailed(this ILogger<LdapUserManager> logger, string login, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TrySyncLdapUser(SID: '{sid}', Email: {email})")]
|
||||
public static partial void ErrorTrySyncLdapUser(this ILogger<LdapUserManager> logger, string sid, string email, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "TryGetAndSyncLdapUserInfo(login: \"{login}\") disabling user {userInfo} due to not being included in any ldap group")]
|
||||
public static partial void DebugTryGetAndSyncLdapUserInfoDisablingUser(this ILogger<LdapUserManager> logger, string login, UserInfo userInfo);
|
||||
|
||||
|
||||
}
|
33
common/ASC.ActiveDirectory/Log/LdapUtilsLogger.cs
Normal file
33
common/ASC.ActiveDirectory/Log/LdapUtilsLogger.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class LdapUtilsLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "SkipErrors() failed")]
|
||||
public static partial void ErrorSkipErrors(this ILogger logger, Exception exception);
|
||||
}
|
36
common/ASC.ActiveDirectory/Log/NovellLdapObjectLogger.cs
Normal file
36
common/ASC.ActiveDirectory/Log/NovellLdapObjectLogger.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class NovellLdapObjectLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't get LDAPObject Sid property")]
|
||||
public static partial void ErrorCanNotGetSidProperty(this ILogger logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Can't get LDAPUser UserAccountControl property")]
|
||||
public static partial void ErrorCanNotGetUserAccountControlProperty(this ILogger logger, Exception exception);
|
||||
}
|
87
common/ASC.ActiveDirectory/Log/NovellLdapSearcherLogger.cs
Normal file
87
common/ASC.ActiveDirectory/Log/NovellLdapSearcherLogger.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
|
||||
namespace ASC.ActiveDirectory.Log;
|
||||
static internal partial class NovellLdapSearcherLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.Connect(Server='{server}', PortNumber='{portNumber}');")]
|
||||
public static partial void DebugldapConnection(this ILogger<NovellLdapSearcher> logger, string server, int portNumber);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.StartTls();")]
|
||||
public static partial void DebugStartTls(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "LDAP certificate confirmation requested.")]
|
||||
public static partial void DebugLdapCertificateConfirmationRequested(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.Bind(Anonymous)")]
|
||||
public static partial void DebugBindAnonymous(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.Bind(Login: '{login}')")]
|
||||
public static partial void DebugBind(this ILogger<NovellLdapSearcher> logger, string login);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "ServerCertValidationHandler: sslPolicyErrors = {sslPolicyErrors}")]
|
||||
public static partial void WarnSslPolicyErrors(this ILogger<NovellLdapSearcher> logger, SslPolicyErrors sslPolicyErrors);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Warning, Message = "The size of the search results is limited. Start TrySearchSimple()")]
|
||||
public static partial void WarnStartTrySearchSimple(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "Search({searchFilter}) failed")]
|
||||
public static partial void ErrorSearch(this ILogger<NovellLdapSearcher> logger, string searchFilter, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "TrySearchSimple() failed")]
|
||||
public static partial void ErrorTrySearchSimple(this ILogger<NovellLdapSearcher> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "SearchSimple({searchFilter}) failed")]
|
||||
public static partial void ErrorSearchSimple(this ILogger<NovellLdapSearcher> logger, string searchFilter, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "{i}. DN: {distinguishedName}")]
|
||||
public static partial void DebugDnEnumeration(this ILogger<NovellLdapSearcher> logger, int i, string distinguishedName);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "No controls returned")]
|
||||
public static partial void DebugNoControlsReturned(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetCapabilities()->LoopResults failed")]
|
||||
public static partial void ErrorGetCapabilitiesLoopResultsFailed(this ILogger<NovellLdapSearcher> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetCapabilities() failed")]
|
||||
public static partial void ErrorGetCapabilitiesFailed(this ILogger<NovellLdapSearcher> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "GetLdapUniqueId()")]
|
||||
public static partial void ErrorGetLdapUniqueId(this ILogger<NovellLdapSearcher> logger, Exception exception);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.StopTls();")]
|
||||
public static partial void DebugLdapConnectionStopTls(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.Disconnect();")]
|
||||
public static partial void DebugLdapConnectionDisconnect(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "ldapConnection.Dispose();")]
|
||||
public static partial void DebugLdapConnectionDispose(this ILogger<NovellLdapSearcher> logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "LDAP->Dispose() failed")]
|
||||
public static partial void ErrorLdapDisposeFailed(this ILogger<NovellLdapSearcher> logger, Exception exception);
|
||||
}
|
139
common/ASC.ActiveDirectory/Novell/Data/NovellLdapObject.cs
Normal file
139
common/ASC.ActiveDirectory/Novell/Data/NovellLdapObject.cs
Normal file
@ -0,0 +1,139 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell.Data;
|
||||
/// <summary>
|
||||
/// Novell LDAP object class
|
||||
/// </summary>
|
||||
public class NovellLdapObject : LdapObject
|
||||
{
|
||||
private LdapEntry _ldapEntry;
|
||||
private readonly ILogger _logger;
|
||||
private string _sid;
|
||||
private string _sidAttribute;
|
||||
private readonly NovellLdapEntryExtension _novellLdapEntryExtension;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="ldapEntry">init ldap entry</param>
|
||||
/// <param name="ldapUniqueIdAttribute"></param>
|
||||
public NovellLdapObject(ILogger logger, NovellLdapEntryExtension novellLdapEntryExtension)
|
||||
{
|
||||
_novellLdapEntryExtension = novellLdapEntryExtension;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Init(LdapEntry ldapEntry, string ldapUniqueIdAttribute = null)
|
||||
{
|
||||
if (ldapEntry == null)
|
||||
{
|
||||
throw new ArgumentNullException("ldapEntry");
|
||||
}
|
||||
|
||||
_ldapEntry = ldapEntry;
|
||||
|
||||
if (string.IsNullOrEmpty(ldapUniqueIdAttribute))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_sid = GetValue(ldapUniqueIdAttribute) as string;
|
||||
_sidAttribute = ldapUniqueIdAttribute;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorCanNotGetSidProperty(e);
|
||||
}
|
||||
}
|
||||
|
||||
#region .Public
|
||||
|
||||
public override string DistinguishedName
|
||||
{
|
||||
get { return _ldapEntry.Dn; }
|
||||
}
|
||||
|
||||
public override string Sid
|
||||
{
|
||||
get { return _sid; }
|
||||
}
|
||||
|
||||
public override string SidAttribute
|
||||
{
|
||||
get { return _sidAttribute; }
|
||||
}
|
||||
|
||||
public override bool IsDisabled
|
||||
{
|
||||
get
|
||||
{
|
||||
var userAccauntControl = LdapConstants.UserAccountControl.EMPTY;
|
||||
try
|
||||
{
|
||||
var uac = Convert.ToInt32(GetValue(LdapConstants.ADSchemaAttributes.USER_ACCOUNT_CONTROL));
|
||||
userAccauntControl = (LdapConstants.UserAccountControl)uac;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorCanNotGetUserAccountControlProperty(e);
|
||||
}
|
||||
|
||||
return (userAccauntControl & LdapConstants.UserAccountControl.ADS_UF_ACCOUNTDISABLE) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Get property object
|
||||
/// </summary>
|
||||
/// <param name="propertyName">property name</param>
|
||||
/// <returns>value object</returns>
|
||||
public sealed override object GetValue(string propertyName, bool getBytes = false)
|
||||
{
|
||||
return _novellLdapEntryExtension.GetAttributeValue(_ldapEntry, propertyName, getBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get property values
|
||||
/// </summary>
|
||||
/// <param name="propertyName">property name</param>
|
||||
/// <returns>list of values</returns>
|
||||
public override List<string> GetValues(string propertyName)
|
||||
{
|
||||
var propertyValueArray = _novellLdapEntryExtension.GetAttributeArrayValue(_ldapEntry, propertyName);
|
||||
if (propertyValueArray == null)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
var properties = propertyValueArray.ToList();
|
||||
return properties;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell.Exceptions;
|
||||
|
||||
[Serializable]
|
||||
public class NovellLdapTlsCertificateRequestedException : Exception
|
||||
{
|
||||
public LdapCertificateConfirmRequest CertificateConfirmRequest { get; set; }
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell.Extensions;
|
||||
|
||||
[Singletone]
|
||||
public class NovellLdapEntryExtension
|
||||
{
|
||||
private readonly ILogger<NovellLdapEntryExtension> _logger;
|
||||
public NovellLdapEntryExtension(ILogger<NovellLdapEntryExtension> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
public object GetAttributeValue(LdapEntry ldapEntry, string attributeName, bool getBytes = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
var attribute = ldapEntry.GetAttribute(attributeName);
|
||||
|
||||
if (attribute == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(string.Equals(attributeName, LdapConstants.ADSchemaAttributes.OBJECT_SID,
|
||||
StringComparison.OrdinalIgnoreCase) || getBytes))
|
||||
{
|
||||
return attribute.StringValue;
|
||||
}
|
||||
|
||||
if (attribute.ByteValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var value = new byte[attribute.ByteValue.Length];
|
||||
|
||||
Buffer.BlockCopy(attribute.ByteValue, 0, value, 0, attribute.ByteValue.Length);
|
||||
|
||||
if (getBytes)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return DecodeSid(value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetAttributeArrayValue(LdapEntry ldapEntry, string attributeName)
|
||||
{
|
||||
var attribute = ldapEntry.GetAttribute(attributeName);
|
||||
return attribute == null ? null : attribute.StringValueArray;
|
||||
}
|
||||
|
||||
private string DecodeSid(byte[] sid)
|
||||
{
|
||||
var strSid = new StringBuilder("S-");
|
||||
|
||||
// get version
|
||||
int revision = sid[0];
|
||||
strSid.Append(revision.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
//next byte is the count of sub-authorities
|
||||
var countSubAuths = sid[1] & 0xFF;
|
||||
|
||||
//get the authority
|
||||
long authority = 0;
|
||||
|
||||
//String rid = "";
|
||||
for (var i = 2; i <= 7; i++)
|
||||
{
|
||||
authority |= ((long)sid[i]) << (8 * (5 - (i - 2)));
|
||||
}
|
||||
|
||||
strSid.Append("-");
|
||||
strSid.Append(authority);
|
||||
|
||||
//iterate all the sub-auths
|
||||
var offset = 8;
|
||||
const int size = 4; //4 bytes for each sub auth
|
||||
|
||||
for (var j = 0; j < countSubAuths; j++)
|
||||
{
|
||||
long subAuthority = 0;
|
||||
for (var k = 0; k < size; k++)
|
||||
{
|
||||
subAuthority |= (long)(sid[offset + k] & 0xFF) << (8 * k);
|
||||
}
|
||||
|
||||
strSid.Append("-");
|
||||
strSid.Append(subAuthority);
|
||||
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return strSid.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create LDAPObject by LdapEntry
|
||||
/// </summary>
|
||||
/// <param name="ldapEntry">init ldapEntry</param>
|
||||
/// <param name="ldapUniqueIdAttribute"></param>
|
||||
/// <returns>LDAPObject</returns>
|
||||
public LdapObject ToLdapObject(LdapEntry ldapEntry, string ldapUniqueIdAttribute = null)
|
||||
{
|
||||
if (ldapEntry == null)
|
||||
{
|
||||
throw new ArgumentNullException("ldapEntry");
|
||||
}
|
||||
|
||||
var novellLdapObject = new NovellLdapObject(_logger, this);
|
||||
novellLdapObject.Init(ldapEntry, ldapUniqueIdAttribute);
|
||||
|
||||
return novellLdapObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create lis of LDAPObject by LdapEntry list
|
||||
/// </summary>
|
||||
/// <param name="entries">list of LdapEntry</param>
|
||||
/// <param name="ldapUniqueIdAttribute"></param>
|
||||
/// <returns>list of LDAPObjects</returns>
|
||||
public List<LdapObject> ToLdapObjects(IEnumerable<LdapEntry> entries, string ldapUniqueIdAttribute = null)
|
||||
{
|
||||
return entries.Select(e => ToLdapObject(e, ldapUniqueIdAttribute)).ToList();
|
||||
}
|
||||
}
|
295
common/ASC.ActiveDirectory/Novell/NovellLdapHelper.cs
Normal file
295
common/ASC.ActiveDirectory/Novell/NovellLdapHelper.cs
Normal file
@ -0,0 +1,295 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell;
|
||||
|
||||
[Scope]
|
||||
public class NovellLdapHelper : LdapHelper
|
||||
{
|
||||
private readonly NovellLdapSearcher _lDAPSearcher;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly LdapObjectExtension _ldapObjectExtension;
|
||||
|
||||
public NovellLdapHelper(IServiceProvider serviceProvider, ILogger<LdapHelper> logger, InstanceCrypto instanceCrypto, IConfiguration configuration, NovellLdapSearcher novellLdapSearcher, LdapObjectExtension ldapObjectExtension) :
|
||||
base(logger, instanceCrypto)
|
||||
{
|
||||
_lDAPSearcher = novellLdapSearcher;
|
||||
_configuration = configuration;
|
||||
_serviceProvider = serviceProvider;
|
||||
_ldapObjectExtension = ldapObjectExtension;
|
||||
}
|
||||
|
||||
public new void Init(LdapSettings settings)
|
||||
{
|
||||
var password = string.IsNullOrEmpty(settings.Password)
|
||||
? GetPassword(settings.PasswordBytes)
|
||||
: settings.Password;
|
||||
|
||||
_lDAPSearcher.Init(settings.Login, password, settings.Server, settings.PortNumber,
|
||||
settings.StartTls, settings.Ssl, settings.AcceptCertificate, settings.AcceptCertificateHash);
|
||||
|
||||
base.Init(settings);
|
||||
}
|
||||
|
||||
public override bool IsConnected
|
||||
{
|
||||
get { return _lDAPSearcher.IsConnected; }
|
||||
}
|
||||
|
||||
public override void Connect()
|
||||
{
|
||||
_lDAPSearcher.Connect();
|
||||
|
||||
Settings.AcceptCertificate = _lDAPSearcher.AcceptCertificate;
|
||||
Settings.AcceptCertificateHash = _lDAPSearcher.AcceptCertificateHash;
|
||||
}
|
||||
|
||||
public override Dictionary<string, string[]> GetCapabilities()
|
||||
{
|
||||
return _lDAPSearcher.GetCapabilities();
|
||||
}
|
||||
|
||||
public override string SearchDomain()
|
||||
{
|
||||
try
|
||||
{
|
||||
var capabilities = GetCapabilities();
|
||||
|
||||
if (capabilities.Count > 0)
|
||||
{
|
||||
if (capabilities.ContainsKey("defaultNamingContext"))
|
||||
{
|
||||
var dnList = capabilities["defaultNamingContext"];
|
||||
|
||||
var dn = dnList.FirstOrDefault(dc =>
|
||||
!string.IsNullOrEmpty(dc) &&
|
||||
dc.IndexOf("dc=", StringComparison.InvariantCultureIgnoreCase) != -1);
|
||||
|
||||
var domain = LdapUtils.DistinguishedNameToDomain(dn);
|
||||
|
||||
if (!string.IsNullOrEmpty(domain))
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
|
||||
if (capabilities.ContainsKey("rootDomainNamingContext"))
|
||||
{
|
||||
var dnList = capabilities["rootDomainNamingContext"];
|
||||
|
||||
var dn = dnList.FirstOrDefault(dc =>
|
||||
!string.IsNullOrEmpty(dc) &&
|
||||
dc.IndexOf("dc=", StringComparison.InvariantCultureIgnoreCase) != -1);
|
||||
|
||||
var domain = LdapUtils.DistinguishedNameToDomain(dn);
|
||||
|
||||
if (!string.IsNullOrEmpty(domain))
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
|
||||
if (capabilities.ContainsKey("namingContexts"))
|
||||
{
|
||||
var dnList = capabilities["namingContexts"];
|
||||
|
||||
var dn = dnList.FirstOrDefault(dc =>
|
||||
!string.IsNullOrEmpty(dc) &&
|
||||
dc.IndexOf("dc=", StringComparison.InvariantCultureIgnoreCase) != -1);
|
||||
|
||||
var domain = LdapUtils.DistinguishedNameToDomain(dn);
|
||||
|
||||
if (!string.IsNullOrEmpty(domain))
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.WarnSearchDomainFailed(e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var searchResult =
|
||||
_lDAPSearcher.Search(Settings.UserDN, NovellLdapSearcher.LdapScope.Sub, Settings.UserFilter, limit: 1)
|
||||
.FirstOrDefault();
|
||||
|
||||
return searchResult != null ? _ldapObjectExtension.GetDomainFromDn(searchResult) : null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.WarnSearchDomainFailed(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void CheckCredentials(string login, string password, string server, int portNumber,
|
||||
bool startTls, bool ssl, bool acceptCertificate, string acceptCertificateHash)
|
||||
{
|
||||
using var novellLdapSearcher = _serviceProvider.GetRequiredService<NovellLdapSearcher>();
|
||||
novellLdapSearcher.Init(login, password, server, portNumber, startTls, ssl, acceptCertificate, acceptCertificateHash);
|
||||
novellLdapSearcher.Connect();
|
||||
}
|
||||
|
||||
public override bool CheckUserDn(string userDn)
|
||||
{
|
||||
string[] attributes = { LdapConstants.ADSchemaAttributes.OBJECT_CLASS };
|
||||
|
||||
var searchResult = _lDAPSearcher.Search(userDn, NovellLdapSearcher.LdapScope.Base,
|
||||
LdapConstants.OBJECT_FILTER, attributes, 1);
|
||||
|
||||
if (searchResult.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.ErrorWrongUserDnParameter(userDn);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool CheckGroupDn(string groupDn)
|
||||
{
|
||||
string[] attributes = { LdapConstants.ADSchemaAttributes.OBJECT_CLASS };
|
||||
|
||||
var searchResult = _lDAPSearcher.Search(groupDn, NovellLdapSearcher.LdapScope.Base,
|
||||
LdapConstants.OBJECT_FILTER, attributes, 1);
|
||||
|
||||
if (searchResult.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.ErrorWrongGroupDnParameter(groupDn);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override List<LdapObject> GetUsers(string filter = null, int limit = -1)
|
||||
{
|
||||
var list = new List<LdapObject>();
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Settings.UserFilter) && !Settings.UserFilter.StartsWith("(") &&
|
||||
!Settings.UserFilter.EndsWith(")"))
|
||||
{
|
||||
Settings.UserFilter = string.Format("({0})", Settings.UserFilter);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter) && !filter.StartsWith("(") &&
|
||||
!filter.EndsWith(")"))
|
||||
{
|
||||
filter = string.Format("({0})", Settings.UserFilter);
|
||||
}
|
||||
|
||||
var searchfilter = string.IsNullOrEmpty(filter)
|
||||
? Settings.UserFilter
|
||||
: string.Format("(&{0}{1})", Settings.UserFilter, filter);
|
||||
|
||||
list = _lDAPSearcher.Search(Settings.UserDN, NovellLdapSearcher.LdapScope.Sub, searchfilter, limit: limit);
|
||||
|
||||
return list;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorGetUsersFailed(filter, limit, e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override LdapObject GetUserBySid(string sid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ldapUniqueIdAttribute = _configuration["ldap:unique:id"];
|
||||
|
||||
Criteria criteria;
|
||||
|
||||
if (ldapUniqueIdAttribute == null)
|
||||
{
|
||||
criteria = Criteria.Any(
|
||||
Expression.Equal(LdapConstants.RfcLDAPAttributes.ENTRY_UUID, sid),
|
||||
Expression.Equal(LdapConstants.RfcLDAPAttributes.NS_UNIQUE_ID, sid),
|
||||
Expression.Equal(LdapConstants.RfcLDAPAttributes.GUID, sid),
|
||||
Expression.Equal(LdapConstants.ADSchemaAttributes.OBJECT_SID, sid)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
criteria = Criteria.All(Expression.Equal(ldapUniqueIdAttribute, sid));
|
||||
}
|
||||
|
||||
var searchfilter = string.Format("(&{0}{1})", Settings.UserFilter, criteria);
|
||||
|
||||
var list = _lDAPSearcher.Search(Settings.UserDN, NovellLdapSearcher.LdapScope.Sub, searchfilter, limit: 1);
|
||||
|
||||
return list.FirstOrDefault();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorGetUserBySidFailed(sid, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override List<LdapObject> GetGroups(Criteria criteria = null)
|
||||
{
|
||||
var list = new List<LdapObject>();
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Settings.GroupFilter) && !Settings.GroupFilter.StartsWith("(") &&
|
||||
!Settings.GroupFilter.EndsWith(")"))
|
||||
{
|
||||
Settings.GroupFilter = string.Format("({0})", Settings.GroupFilter);
|
||||
}
|
||||
|
||||
var searchfilter = criteria == null
|
||||
? Settings.GroupFilter
|
||||
: string.Format("(&{0}{1})", Settings.GroupFilter, criteria);
|
||||
|
||||
|
||||
list = _lDAPSearcher.Search(Settings.GroupDN, NovellLdapSearcher.LdapScope.Sub, searchfilter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorGetGroupsFailed(criteria, e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_lDAPSearcher.Dispose();
|
||||
}
|
||||
}
|
652
common/ASC.ActiveDirectory/Novell/NovellLdapSearcher.cs
Normal file
652
common/ASC.ActiveDirectory/Novell/NovellLdapSearcher.cs
Normal file
@ -0,0 +1,652 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell;
|
||||
|
||||
[Scope]
|
||||
public class NovellLdapSearcher : IDisposable
|
||||
{
|
||||
protected readonly ILogger<NovellLdapSearcher> _logger;
|
||||
private LdapCertificateConfirmRequest _certificateConfirmRequest;
|
||||
private static readonly object _rootSync = new object();
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly NovellLdapEntryExtension _novellLdapEntryExtension;
|
||||
private LdapConnection _ldapConnection;
|
||||
|
||||
public string Login { get; private set; }
|
||||
public string Password { get; private set; }
|
||||
public string Server { get; private set; }
|
||||
public int PortNumber { get; private set; }
|
||||
public bool StartTls { get; private set; }
|
||||
public bool Ssl { get; private set; }
|
||||
public bool AcceptCertificate { get; private set; }
|
||||
public string AcceptCertificateHash { get; private set; }
|
||||
|
||||
public string LdapUniqueIdAttribute { get; set; }
|
||||
|
||||
private Dictionary<string, string[]> _capabilities;
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return _ldapConnection != null && _ldapConnection.Connected; }
|
||||
}
|
||||
|
||||
public NovellLdapSearcher(
|
||||
IConfiguration configuration,
|
||||
ILogger<NovellLdapSearcher> logger,
|
||||
NovellLdapEntryExtension novellLdapEntryExtension)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_novellLdapEntryExtension = novellLdapEntryExtension;
|
||||
LdapUniqueIdAttribute = configuration["ldap:unique:id"];
|
||||
}
|
||||
|
||||
public void Init(string login,
|
||||
string password,
|
||||
string server,
|
||||
int portNumber,
|
||||
bool startTls,
|
||||
bool ssl,
|
||||
bool acceptCertificate,
|
||||
string acceptCertificateHash = null)
|
||||
{
|
||||
Login = login;
|
||||
Password = password;
|
||||
Server = server;
|
||||
PortNumber = portNumber;
|
||||
StartTls = startTls;
|
||||
Ssl = ssl;
|
||||
AcceptCertificate = acceptCertificate;
|
||||
AcceptCertificateHash = acceptCertificateHash;
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
if (Server.StartsWith("LDAP://"))
|
||||
{
|
||||
Server = Server.Substring("LDAP://".Length);
|
||||
}
|
||||
|
||||
LdapConnection ldapConnection;
|
||||
|
||||
if (StartTls || Ssl)
|
||||
{
|
||||
var ldapConnectionOptions = new LdapConnectionOptions();
|
||||
ldapConnectionOptions.ConfigureRemoteCertificateValidationCallback(ServerCertValidationHandler);
|
||||
ldapConnection = new LdapConnection(ldapConnectionOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
ldapConnection = new LdapConnection();
|
||||
}
|
||||
|
||||
if (Ssl)
|
||||
{
|
||||
ldapConnection.SecureSocketLayer = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ldapConnection.ConnectionTimeout = 30000; // 30 seconds
|
||||
|
||||
_logger.DebugldapConnection(Server, PortNumber);
|
||||
|
||||
ldapConnection.Connect(Server, PortNumber);
|
||||
|
||||
if (StartTls)
|
||||
{
|
||||
_logger.DebugStartTls();
|
||||
ldapConnection.StartTls();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (_certificateConfirmRequest == null)
|
||||
{
|
||||
if (ex.Message.StartsWith("Connect Error"))
|
||||
{
|
||||
throw new SocketException();
|
||||
}
|
||||
|
||||
if (ex.Message.StartsWith("Unavailable"))
|
||||
{
|
||||
throw new NotSupportedException(ex.Message);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
_logger.DebugLdapCertificateConfirmationRequested();
|
||||
|
||||
ldapConnection.Disconnect();
|
||||
|
||||
var exception = new NovellLdapTlsCertificateRequestedException
|
||||
{
|
||||
CertificateConfirmRequest = _certificateConfirmRequest
|
||||
};
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Login) || string.IsNullOrEmpty(Password))
|
||||
{
|
||||
_logger.DebugBindAnonymous();
|
||||
|
||||
ldapConnection.Bind(null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.DebugBind(Login);
|
||||
|
||||
ldapConnection.Bind(Login, Password);
|
||||
}
|
||||
|
||||
if (!ldapConnection.Bound)
|
||||
{
|
||||
throw new Exception("Bind operation wasn't completed successfully.");
|
||||
}
|
||||
|
||||
_ldapConnection = ldapConnection;
|
||||
}
|
||||
|
||||
private bool ServerCertValidationHandler(object sender, X509Certificate certificate,
|
||||
X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
if (sslPolicyErrors == SslPolicyErrors.None)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
lock (_rootSync)
|
||||
{
|
||||
var certHash = certificate.GetCertHashString();
|
||||
|
||||
if (AcceptCertificate)
|
||||
{
|
||||
if (AcceptCertificateHash == null || AcceptCertificateHash.Equals(certHash))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AcceptCertificate = false;
|
||||
AcceptCertificateHash = null;
|
||||
}
|
||||
|
||||
_logger.WarnSslPolicyErrors(sslPolicyErrors);
|
||||
|
||||
_certificateConfirmRequest = LdapCertificateConfirmRequest.FromCert(certificate, chain, sslPolicyErrors, false, true, _logger);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum LdapScope
|
||||
{
|
||||
Base = LdapConnection.ScopeBase,
|
||||
One = LdapConnection.ScopeOne,
|
||||
Sub = LdapConnection.ScopeSub
|
||||
}
|
||||
|
||||
public List<LdapObject> Search(LdapScope scope, string searchFilter,
|
||||
string[] attributes = null, int limit = -1, LdapSearchConstraints searchConstraints = null)
|
||||
{
|
||||
return Search("", scope, searchFilter, attributes, limit, searchConstraints);
|
||||
}
|
||||
|
||||
public List<LdapObject> Search(string searchBase, LdapScope scope, string searchFilter,
|
||||
string[] attributes = null, int limit = -1, LdapSearchConstraints searchConstraints = null)
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
|
||||
if (searchBase == null)
|
||||
{
|
||||
searchBase = "";
|
||||
}
|
||||
|
||||
var entries = new List<LdapEntry>();
|
||||
|
||||
if (string.IsNullOrEmpty(searchFilter))
|
||||
{
|
||||
return new List<LdapObject>();
|
||||
}
|
||||
|
||||
if (attributes == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(LdapUniqueIdAttribute))
|
||||
{
|
||||
attributes = new[]
|
||||
{
|
||||
"*", LdapConstants.RfcLDAPAttributes.ENTRY_DN, LdapConstants.RfcLDAPAttributes.ENTRY_UUID,
|
||||
LdapConstants.RfcLDAPAttributes.NS_UNIQUE_ID, LdapConstants.RfcLDAPAttributes.GUID
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
attributes = new[] { "*", LdapUniqueIdAttribute };
|
||||
}
|
||||
}
|
||||
|
||||
var ldapSearchConstraints = searchConstraints ?? new LdapSearchConstraints
|
||||
{
|
||||
// Maximum number of search results to return.
|
||||
// The value 0 means no limit. The default is 1000.
|
||||
MaxResults = limit == -1 ? 0 : limit,
|
||||
// Returns the number of results to block on during receipt of search results.
|
||||
// This should be 0 if intermediate results are not needed, and 1 if results are to be processed as they come in.
|
||||
//BatchSize = 0,
|
||||
// The maximum number of referrals to follow in a sequence during automatic referral following.
|
||||
// The default value is 10. A value of 0 means no limit.
|
||||
HopLimit = 0,
|
||||
// Specifies whether referrals are followed automatically
|
||||
// Referrals of any type other than to an LDAP server (for example, a referral URL other than ldap://something) are ignored on automatic referral following.
|
||||
// The default is false.
|
||||
ReferralFollowing = true,
|
||||
// The number of seconds to wait for search results.
|
||||
// Sets the maximum number of seconds that the server is to wait when returning search results.
|
||||
//ServerTimeLimit = 600000, // 10 minutes
|
||||
// Sets the maximum number of milliseconds the client waits for any operation under these constraints to complete.
|
||||
// If the value is 0, there is no maximum time limit enforced by the API on waiting for the operation results.
|
||||
//TimeLimit = 600000 // 10 minutes
|
||||
};
|
||||
|
||||
var queue = _ldapConnection.Search(searchBase,
|
||||
(int)scope, searchFilter, attributes, false, ldapSearchConstraints);
|
||||
|
||||
while (queue.HasMore())
|
||||
{
|
||||
LdapEntry nextEntry;
|
||||
try
|
||||
{
|
||||
nextEntry = queue.Next();
|
||||
|
||||
if (nextEntry == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (LdapException ex)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ex.Message) && ex.Message.Contains("Sizelimit Exceeded"))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Login) && !string.IsNullOrEmpty(Password) && limit == -1)
|
||||
{
|
||||
_logger.WarnStartTrySearchSimple();
|
||||
|
||||
List<LdapObject> simpleResults;
|
||||
|
||||
if (TrySearchSimple(searchBase, scope, searchFilter, out simpleResults, attributes, limit,
|
||||
searchConstraints))
|
||||
{
|
||||
if (entries.Count >= simpleResults.Count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
return simpleResults;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.ErrorSearch( searchFilter, ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
entries.Add(nextEntry);
|
||||
|
||||
if (string.IsNullOrEmpty(LdapUniqueIdAttribute))
|
||||
{
|
||||
LdapUniqueIdAttribute = GetLdapUniqueId(nextEntry);
|
||||
}
|
||||
}
|
||||
|
||||
var result = _novellLdapEntryExtension.ToLdapObjects(entries, LdapUniqueIdAttribute);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool TrySearchSimple(string searchBase, LdapScope scope, string searchFilter, out List<LdapObject> results,
|
||||
string[] attributes = null, int limit = -1, LdapSearchConstraints searchConstraints = null)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
results = SearchSimple(searchBase, scope, searchFilter, attributes, limit, searchConstraints);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorTrySearchSimple(ex);
|
||||
}
|
||||
|
||||
results = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<LdapObject> SearchSimple(string searchBase, LdapScope scope, string searchFilter,
|
||||
string[] attributes = null, int limit = -1, LdapSearchConstraints searchConstraints = null)
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
|
||||
if (searchBase == null)
|
||||
{
|
||||
searchBase = "";
|
||||
}
|
||||
|
||||
var entries = new List<LdapEntry>();
|
||||
|
||||
if (string.IsNullOrEmpty(searchFilter))
|
||||
{
|
||||
return new List<LdapObject>();
|
||||
}
|
||||
|
||||
if (attributes == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(LdapUniqueIdAttribute))
|
||||
{
|
||||
attributes = new[]
|
||||
{
|
||||
"*", LdapConstants.RfcLDAPAttributes.ENTRY_DN, LdapConstants.RfcLDAPAttributes.ENTRY_UUID,
|
||||
LdapConstants.RfcLDAPAttributes.NS_UNIQUE_ID, LdapConstants.RfcLDAPAttributes.GUID
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
attributes = new[] { "*", LdapUniqueIdAttribute };
|
||||
}
|
||||
}
|
||||
|
||||
var ldapSearchConstraints = searchConstraints ?? new LdapSearchConstraints
|
||||
{
|
||||
// Maximum number of search results to return.
|
||||
// The value 0 means no limit. The default is 1000.
|
||||
MaxResults = limit == -1 ? 0 : limit,
|
||||
// Returns the number of results to block on during receipt of search results.
|
||||
// This should be 0 if intermediate results are not needed, and 1 if results are to be processed as they come in.
|
||||
//BatchSize = 0,
|
||||
// The maximum number of referrals to follow in a sequence during automatic referral following.
|
||||
// The default value is 10. A value of 0 means no limit.
|
||||
HopLimit = 0,
|
||||
// Specifies whether referrals are followed automatically
|
||||
// Referrals of any type other than to an LDAP server (for example, a referral URL other than ldap://something) are ignored on automatic referral following.
|
||||
// The default is false.
|
||||
ReferralFollowing = true,
|
||||
// The number of seconds to wait for search results.
|
||||
// Sets the maximum number of seconds that the server is to wait when returning search results.
|
||||
//ServerTimeLimit = 600000, // 10 minutes
|
||||
// Sets the maximum number of milliseconds the client waits for any operation under these constraints to complete.
|
||||
// If the value is 0, there is no maximum time limit enforced by the API on waiting for the operation results.
|
||||
//TimeLimit = 600000 // 10 minutes
|
||||
};
|
||||
|
||||
// initially, cookie must be set to an empty string
|
||||
var pageSize = 2;
|
||||
var cookie = Array.ConvertAll(Encoding.ASCII.GetBytes(""), b => unchecked(b));
|
||||
var i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
var requestControls = new LdapControl[1];
|
||||
requestControls[0] = new SimplePagedResultsControl(pageSize, cookie);
|
||||
ldapSearchConstraints.SetControls(requestControls);
|
||||
_ldapConnection.Constraints = ldapSearchConstraints;
|
||||
|
||||
var res = _ldapConnection.Search(searchBase,
|
||||
(int)scope, searchFilter, attributes, false, (LdapSearchConstraints)null);
|
||||
|
||||
while (res.HasMore())
|
||||
{
|
||||
LdapEntry nextEntry;
|
||||
try
|
||||
{
|
||||
nextEntry = res.Next();
|
||||
|
||||
if (nextEntry == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (LdapException ex)
|
||||
{
|
||||
if (ex is LdapReferralException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ex.Message) && ex.Message.Contains("Sizelimit Exceeded"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_logger.ErrorSearchSimple(searchFilter, ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.DebugDnEnumeration(++i, nextEntry.Dn);
|
||||
|
||||
entries.Add(nextEntry);
|
||||
|
||||
if (string.IsNullOrEmpty(LdapUniqueIdAttribute))
|
||||
{
|
||||
LdapUniqueIdAttribute = GetLdapUniqueId(nextEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// Server should send back a control irrespective of the
|
||||
// status of the search request
|
||||
var controls = res.ResponseControls;
|
||||
if (controls == null)
|
||||
{
|
||||
_logger.DebugNoControlsReturned();
|
||||
cookie = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multiple controls could have been returned
|
||||
foreach (var control in controls)
|
||||
{
|
||||
/* Is this the LdapPagedResultsResponse control? */
|
||||
if (!(control is SimplePagedResultsControl))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var response = new SimplePagedResultsControl(control.Id,
|
||||
control.Critical, control.GetValue());
|
||||
|
||||
cookie = response.Cookie;
|
||||
}
|
||||
}
|
||||
// if cookie is empty, we are done.
|
||||
} while (cookie != null && cookie.Length > 0);
|
||||
|
||||
var result = _novellLdapEntryExtension.ToLdapObjects(entries, LdapUniqueIdAttribute);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Dictionary<string, string[]> GetCapabilities()
|
||||
{
|
||||
if (_capabilities != null)
|
||||
{
|
||||
return _capabilities;
|
||||
}
|
||||
|
||||
_capabilities = new Dictionary<string, string[]>();
|
||||
|
||||
try
|
||||
{
|
||||
var ldapSearchConstraints = new LdapSearchConstraints
|
||||
{
|
||||
MaxResults = int.MaxValue,
|
||||
HopLimit = 0,
|
||||
ReferralFollowing = true
|
||||
};
|
||||
|
||||
var ldapSearchResults = _ldapConnection.Search("", LdapConnection.ScopeBase, LdapConstants.OBJECT_FILTER,
|
||||
new[] { "*", "supportedControls", "supportedCapabilities" }, false, ldapSearchConstraints);
|
||||
|
||||
while (ldapSearchResults.HasMore())
|
||||
{
|
||||
LdapEntry nextEntry;
|
||||
try
|
||||
{
|
||||
nextEntry = ldapSearchResults.Next();
|
||||
|
||||
if (nextEntry == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (LdapException ex)
|
||||
{
|
||||
_logger.ErrorGetCapabilitiesLoopResultsFailed(ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
var attributeSet = nextEntry.GetAttributeSet();
|
||||
|
||||
var ienum = attributeSet.GetEnumerator();
|
||||
|
||||
while (ienum.MoveNext())
|
||||
{
|
||||
var attribute = (LdapAttribute)ienum.Current;
|
||||
if (attribute == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var attributeName = attribute.Name;
|
||||
var attributeVals = attribute.StringValueArray
|
||||
.ToList()
|
||||
.Select(s =>
|
||||
{
|
||||
if (Base64.IsLdifSafe(s))
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
s = Base64.Encode(s);
|
||||
return s;
|
||||
}).ToArray();
|
||||
|
||||
_capabilities.Add(attributeName, attributeVals);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorGetCapabilitiesFailed(ex);
|
||||
}
|
||||
|
||||
return _capabilities;
|
||||
}
|
||||
|
||||
private string GetLdapUniqueId(LdapEntry ldapEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ldapUniqueIdAttribute = _configuration["ldap:unique:id"];
|
||||
|
||||
if (ldapUniqueIdAttribute != null)
|
||||
{
|
||||
return ldapUniqueIdAttribute;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(
|
||||
_novellLdapEntryExtension.GetAttributeValue(ldapEntry, LdapConstants.ADSchemaAttributes.OBJECT_SID) as string))
|
||||
{
|
||||
ldapUniqueIdAttribute = LdapConstants.ADSchemaAttributes.OBJECT_SID;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(
|
||||
_novellLdapEntryExtension.GetAttributeValue(ldapEntry, LdapConstants.RfcLDAPAttributes.ENTRY_UUID) as string))
|
||||
{
|
||||
ldapUniqueIdAttribute = LdapConstants.RfcLDAPAttributes.ENTRY_UUID;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(
|
||||
_novellLdapEntryExtension.GetAttributeValue(ldapEntry, LdapConstants.RfcLDAPAttributes.NS_UNIQUE_ID) as string))
|
||||
{
|
||||
ldapUniqueIdAttribute = LdapConstants.RfcLDAPAttributes.NS_UNIQUE_ID;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(
|
||||
_novellLdapEntryExtension.GetAttributeValue(ldapEntry, LdapConstants.RfcLDAPAttributes.GUID) as string))
|
||||
{
|
||||
ldapUniqueIdAttribute = LdapConstants.RfcLDAPAttributes.GUID;
|
||||
}
|
||||
|
||||
return ldapUniqueIdAttribute;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorGetLdapUniqueId(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_ldapConnection.Constraints.TimeLimit = 10000;
|
||||
_ldapConnection.SearchConstraints.ServerTimeLimit = 10000;
|
||||
_ldapConnection.SearchConstraints.TimeLimit = 10000;
|
||||
_ldapConnection.ConnectionTimeout = 10000;
|
||||
|
||||
if (_ldapConnection.Tls)
|
||||
{
|
||||
_logger.DebugLdapConnectionStopTls();
|
||||
_ldapConnection.StopTls();
|
||||
}
|
||||
|
||||
_logger.DebugLdapConnectionDisconnect();
|
||||
_ldapConnection.Disconnect();
|
||||
|
||||
_logger.DebugLdapConnectionDispose();
|
||||
_ldapConnection.Dispose();
|
||||
|
||||
_ldapConnection = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorLdapDisposeFailed(ex);
|
||||
}
|
||||
}
|
||||
}
|
222
common/ASC.ActiveDirectory/Novell/NovellLdapSettingsChecker.cs
Normal file
222
common/ASC.ActiveDirectory/Novell/NovellLdapSettingsChecker.cs
Normal file
@ -0,0 +1,222 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell;
|
||||
|
||||
[Scope]
|
||||
public class NovellLdapSettingsChecker : LdapSettingsChecker
|
||||
{
|
||||
public LdapCertificateConfirmRequest CertificateConfirmRequest { get; set; }
|
||||
|
||||
public LdapHelper LdapHelper
|
||||
{
|
||||
get { return LdapImporter.LdapHelper; }
|
||||
}
|
||||
|
||||
public NovellLdapSettingsChecker(ILogger<LdapSettingsChecker> logger) :
|
||||
base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
public new void Init(LdapUserImporter importer)
|
||||
{
|
||||
base.Init(importer);
|
||||
}
|
||||
|
||||
public override LdapSettingsStatus CheckSettings()
|
||||
{
|
||||
if (!Settings.EnableLdapAuthentication)
|
||||
{
|
||||
return LdapSettingsStatus.Ok;
|
||||
}
|
||||
|
||||
if (Settings.Server.Equals("LDAP://", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return LdapSettingsStatus.WrongServerOrPort;
|
||||
}
|
||||
|
||||
if (!LdapHelper.IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
LdapHelper.Connect();
|
||||
}
|
||||
catch (NovellLdapTlsCertificateRequestedException ex)
|
||||
{
|
||||
_logger.ErrorNovellLdapTlsCertificateRequestedException(Settings.AcceptCertificate, ex);
|
||||
CertificateConfirmRequest = ex.CertificateConfirmRequest;
|
||||
return LdapSettingsStatus.CertificateRequest;
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
_logger.ErrorNotSupportedException(ex);
|
||||
return LdapSettingsStatus.TlsNotSupported;
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_logger.ErrorSocketException(ex);
|
||||
return LdapSettingsStatus.ConnectError;
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
_logger.ErrorArgumentException( ex);
|
||||
return LdapSettingsStatus.WrongServerOrPort;
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
_logger.ErrorSecurityException(ex);
|
||||
return LdapSettingsStatus.StrongAuthRequired;
|
||||
}
|
||||
catch (SystemException ex)
|
||||
{
|
||||
_logger.ErrorSystemException(ex);
|
||||
return LdapSettingsStatus.WrongServerOrPort;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorCheckSettingsException(ex);
|
||||
return LdapSettingsStatus.CredentialsNotValid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CheckUserDn(Settings.UserDN))
|
||||
{
|
||||
return LdapSettingsStatus.WrongUserDn;
|
||||
}
|
||||
|
||||
if (Settings.GroupMembership)
|
||||
{
|
||||
if (!CheckGroupDn(Settings.GroupDN))
|
||||
{
|
||||
return LdapSettingsStatus.WrongGroupDn;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
new RfcFilter(Settings.GroupFilter);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return LdapSettingsStatus.IncorrectGroupLDAPFilter;
|
||||
}
|
||||
|
||||
if (!LdapImporter.TryLoadLDAPGroups())
|
||||
{
|
||||
if (!LdapImporter.AllSkipedDomainGroups.Any())
|
||||
{
|
||||
return LdapSettingsStatus.IncorrectGroupLDAPFilter;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainGroups.All(kv => kv.Value == LdapSettingsStatus.WrongSidAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongSidAttribute;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainGroups.All(kv => kv.Value == LdapSettingsStatus.WrongGroupAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongGroupAttribute;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainGroups.All(kv => kv.Value == LdapSettingsStatus.WrongGroupNameAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongGroupNameAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LdapImporter.AllDomainGroups.Any())
|
||||
{
|
||||
return LdapSettingsStatus.GroupsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
new RfcFilter(Settings.UserFilter);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return LdapSettingsStatus.IncorrectLDAPFilter;
|
||||
}
|
||||
|
||||
if (!LdapImporter.TryLoadLDAPUsers())
|
||||
{
|
||||
if (!LdapImporter.AllSkipedDomainUsers.Any())
|
||||
{
|
||||
return LdapSettingsStatus.IncorrectLDAPFilter;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainUsers.All(kv => kv.Value == LdapSettingsStatus.WrongSidAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongSidAttribute;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainUsers.All(kv => kv.Value == LdapSettingsStatus.WrongLoginAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongLoginAttribute;
|
||||
}
|
||||
|
||||
if (LdapImporter.AllSkipedDomainUsers.All(kv => kv.Value == LdapSettingsStatus.WrongUserAttribute))
|
||||
{
|
||||
return LdapSettingsStatus.WrongUserAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LdapImporter.AllDomainUsers.Any())
|
||||
{
|
||||
return LdapSettingsStatus.UsersNotFound;
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(LdapImporter.LDAPDomain)
|
||||
? LdapSettingsStatus.DomainNotFound
|
||||
: LdapSettingsStatus.Ok;
|
||||
}
|
||||
|
||||
private bool CheckUserDn(string userDn)
|
||||
{
|
||||
try
|
||||
{
|
||||
return LdapHelper.CheckUserDn(userDn);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorWrongUserDn(userDn, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckGroupDn(string groupDn)
|
||||
{
|
||||
try
|
||||
{
|
||||
return LdapHelper.CheckGroupDn(groupDn);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorWrongGroupDn(groupDn, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
36
common/ASC.ActiveDirectory/Novell/NovellLdapUserImporter.cs
Normal file
36
common/ASC.ActiveDirectory/Novell/NovellLdapUserImporter.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.ActiveDirectory.Novell;
|
||||
|
||||
[Scope]
|
||||
public class NovellLdapUserImporter : LdapUserImporter
|
||||
{
|
||||
public NovellLdapUserImporter(ILogger<LdapUserImporter> logger, UserManager userManager, IConfiguration configuration, NovellLdapHelper novellLdapHelper, LdapObjectExtension ldapObjectExtension)
|
||||
: base(logger, userManager, configuration, novellLdapHelper, ldapObjectExtension)
|
||||
{
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ public class InstanceCrypto
|
||||
|
||||
public string Decrypt(string data) => Decrypt(Convert.FromBase64String(data));
|
||||
|
||||
public string Decrypt(byte[] data)
|
||||
public string Decrypt(byte[] data, Encoding encoding = null)
|
||||
{
|
||||
using var hasher = Aes.Create();
|
||||
hasher.Key = _eKey;
|
||||
@ -68,7 +68,7 @@ public class InstanceCrypto
|
||||
|
||||
using var msDecrypt = new MemoryStream(data);
|
||||
using var csDecrypt = new CryptoStream(msDecrypt, hasher.CreateDecryptor(), CryptoStreamMode.Read);
|
||||
using var srDecrypt = new StreamReader(csDecrypt);
|
||||
using var srDecrypt = new StreamReader(csDecrypt, encoding);
|
||||
|
||||
// Read the decrypted bytes from the decrypting stream
|
||||
// and place them in a string.
|
||||
|
@ -664,7 +664,7 @@ public class NotifyEngine : INotifyEngine, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
[Singletone]
|
||||
public class NotifyEngineQueue
|
||||
{
|
||||
private readonly NotifyEngine _notifyEngine;
|
||||
|
@ -20,7 +20,8 @@
|
||||
<Compile Remove="Api\SsoSettingsV2Controller.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
|
||||
<ProjectReference Include="..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
|
||||
<ProjectReference Include="..\..\common\ASC.ActiveDirectory\ASC.ActiveDirectory.csproj" />
|
||||
<ProjectReference Include="..\..\common\ASC.Core.Common\ASC.Core.Common.csproj" />
|
||||
<ProjectReference Include="..\..\common\ASC.Data.Backup.Core\ASC.Data.Backup.Core.csproj" />
|
||||
<ProjectReference Include="..\..\common\services\ASC.AuditTrail\ASC.AuditTrail.csproj" />
|
||||
|
321
web/ASC.Web.Api/Api/Settings/LdapController.cs
Normal file
321
web/ASC.Web.Api/Api/Settings/LdapController.cs
Normal file
@ -0,0 +1,321 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.Controllers.Settings;
|
||||
|
||||
public class LdapController : BaseSettingsController
|
||||
{
|
||||
private Tenant Tenant { get { return ApiContext.Tenant; } }
|
||||
|
||||
private readonly SettingsManager _settingsManager;
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly LdapNotifyService _ldapNotifyHelper;
|
||||
private readonly LdapSaveSyncOperation _ldapSaveSyncOperation;
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly PermissionContext _permissionContext;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly TenantExtra _tenantExtra;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public LdapController(
|
||||
ApiContext apiContext,
|
||||
WebItemManager webItemManager,
|
||||
IMemoryCache memoryCache,
|
||||
SettingsManager settingsManager,
|
||||
TenantManager tenantManager,
|
||||
LdapNotifyService ldapNotifyHelper,
|
||||
LdapSaveSyncOperation ldapSaveSyncOperation,
|
||||
AuthContext authContext,
|
||||
PermissionContext permissionContext,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
TenantExtra tenantExtra,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IMapper mapper) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
|
||||
{
|
||||
_settingsManager = settingsManager;
|
||||
_tenantManager = tenantManager;
|
||||
_ldapNotifyHelper = ldapNotifyHelper;
|
||||
_ldapSaveSyncOperation = ldapSaveSyncOperation;
|
||||
_authContext = authContext;
|
||||
_permissionContext = permissionContext;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_tenantExtra = tenantExtra;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current portal LDAP settings.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Get the LDAP settings
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>LDAP settings</returns>
|
||||
[HttpGet("ldap")]
|
||||
public LdapSettingsDto GetLdapSettings()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var settings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
settings = settings.Clone() as LdapSettings; // clone LdapSettings object for clear password (potencial AscCache.Memory issue)
|
||||
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new LdapSettings().GetDefault();
|
||||
return _mapper.Map<LdapSettings, LdapSettingsDto>(settings);
|
||||
}
|
||||
|
||||
settings.Password = null;
|
||||
settings.PasswordBytes = null;
|
||||
|
||||
if (settings.IsDefault)
|
||||
return _mapper.Map<LdapSettings, LdapSettingsDto>(settings); ;
|
||||
|
||||
var defaultSettings = settings.GetDefault();
|
||||
|
||||
if (settings.Equals(defaultSettings))
|
||||
settings.IsDefault = true;
|
||||
|
||||
return _mapper.Map<LdapSettings, LdapSettingsDto>(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the LDAP autosynchronous cron expression of the current portal if it exists.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Get the LDAP cron expression
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>Cron expression or null</returns>
|
||||
[HttpGet("ldap/cron")]
|
||||
public LdapCronSettingsDto GetLdapCronSettings()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var settings = _settingsManager.Load<LdapCronSettings>();
|
||||
|
||||
if (settings == null)
|
||||
settings = new LdapCronSettings().GetDefault();
|
||||
|
||||
if (string.IsNullOrEmpty(settings.Cron))
|
||||
return null;
|
||||
|
||||
return _mapper.Map<LdapCronSettings, LdapCronSettingsDto>(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the LDAP autosynchronous cron expression of the current portal.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Set the LDAP cron expression
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <param name="cron">Cron expression</param>
|
||||
///
|
||||
[HttpPost("ldap/cron")]
|
||||
public void SetLdapCronSettingsFromBody(LdapCronRequestDto ldapCronRequest)
|
||||
{
|
||||
SetLdapCronSettings(ldapCronRequest);
|
||||
}
|
||||
|
||||
private void SetLdapCronSettings(LdapCronRequestDto ldapCronRequest)
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var cron = ldapCronRequest.Cron;
|
||||
|
||||
if (!string.IsNullOrEmpty(cron))
|
||||
{
|
||||
new CronExpression(cron); // validate
|
||||
|
||||
if (!_settingsManager.Load<LdapSettings>().EnableLdapAuthentication)
|
||||
{
|
||||
throw new Exception(Resource.LdapSettingsErrorCantSaveLdapSettings);
|
||||
}
|
||||
}
|
||||
|
||||
var settings = _settingsManager.Load<LdapCronSettings>();
|
||||
|
||||
if (settings == null)
|
||||
settings = new LdapCronSettings();
|
||||
|
||||
settings.Cron = cron;
|
||||
_settingsManager.Save(settings);
|
||||
|
||||
var t = _tenantManager.GetCurrentTenant();
|
||||
if (!string.IsNullOrEmpty(cron))
|
||||
{
|
||||
_ldapNotifyHelper.UnregisterAutoSync(t);
|
||||
_ldapNotifyHelper.RegisterAutoSync(t, cron);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ldapNotifyHelper.UnregisterAutoSync(t);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts synchronizing users and groups by LDAP.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Synchronize by LDAP
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>Operation status</returns>
|
||||
[HttpGet("ldap/sync")]
|
||||
public LdapStatusDto SyncLdap()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var ldapSettings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
var userId = _authContext.CurrentAccount.ID.ToString();
|
||||
|
||||
var result = _ldapSaveSyncOperation.SyncLdap(ldapSettings, Tenant, userId);
|
||||
|
||||
return _mapper.Map<LdapOperationStatus, LdapStatusDto>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the process of collecting preliminary changes on the portal during the synchronization process according to the selected LDAP settings.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Test the LDAP synchronization
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>Operation status</returns>
|
||||
[HttpGet("ldap/sync/test")]
|
||||
public LdapStatusDto TestLdapSync()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var ldapSettings = _settingsManager.Load<LdapSettings>();
|
||||
|
||||
var result = _ldapSaveSyncOperation.TestLdapSync(ldapSettings, Tenant);
|
||||
|
||||
return _mapper.Map<LdapOperationStatus, LdapStatusDto>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the LDAP settings specified in the request and starts importing/synchronizing users and groups by LDAP.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Save the LDAP settings
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <param name="settings">LDAP settings in the serialized string format</param>
|
||||
/// <param name="acceptCertificate">Specifies if the errors of checking certificates are allowed (true) or not (false)</param>
|
||||
/// <returns>Operation status</returns>
|
||||
[HttpPost("ldap")]
|
||||
public LdapStatusDto SaveLdapSettings(LdapRequestsDto ldapRequestsDto)
|
||||
{
|
||||
var ldapSettings = _mapper.Map<LdapRequestsDto, LdapSettings>(ldapRequestsDto);
|
||||
|
||||
CheckLdapPermissions();
|
||||
|
||||
if (!ldapSettings.EnableLdapAuthentication)
|
||||
{
|
||||
SetLdapCronSettings(null);
|
||||
}
|
||||
|
||||
var userId = _authContext.CurrentAccount.ID.ToString();
|
||||
|
||||
var result = _ldapSaveSyncOperation.SaveLdapSettings(ldapSettings, Tenant, userId);
|
||||
|
||||
return _mapper.Map<LdapOperationStatus, LdapStatusDto>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the process of collecting preliminary changes on the portal during the saving process according to the LDAP settings.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Test the LDAP saving process
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <param name="settings">LDAP settings in the serialized string format</param>
|
||||
/// <param name="acceptCertificate">Specifies if the errors of checking certificates are allowed (true) or not (false)</param>
|
||||
/// <returns>Operation status</returns>
|
||||
[HttpPost("ldap/save/test")]
|
||||
public LdapStatusDto TestLdapSave(LdapSettings ldapSettings)
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var userId = _authContext.CurrentAccount.ID.ToString();
|
||||
|
||||
var result = _ldapSaveSyncOperation.TestLdapSave(ldapSettings, Tenant, userId);
|
||||
|
||||
return _mapper.Map<LdapOperationStatus, LdapStatusDto>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the LDAP synchronization process status.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Get the LDAP synchronization process status
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>Operation status</returns>
|
||||
[HttpGet("ldap/status")]
|
||||
public LdapStatusDto GetLdapOperationStatus()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var result = _ldapSaveSyncOperation.ToLdapOperationStatus(Tenant.Id);
|
||||
|
||||
return _mapper.Map<LdapOperationStatus, LdapStatusDto>(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the LDAP default settings.
|
||||
/// </summary>
|
||||
/// <short>
|
||||
/// Get the LDAP default settings
|
||||
/// </short>
|
||||
/// <category>LDAP</category>
|
||||
/// <returns>LDAP default settings</returns>
|
||||
[HttpGet("ldap/default")]
|
||||
public LdapSettingsDto GetDefaultLdapSettings()
|
||||
{
|
||||
CheckLdapPermissions();
|
||||
|
||||
var settings = new LdapSettings().GetDefault();
|
||||
|
||||
return _mapper.Map<LdapSettings, LdapSettingsDto>(settings);
|
||||
}
|
||||
|
||||
private void CheckLdapPermissions()
|
||||
{
|
||||
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
|
||||
|
||||
if (!_coreBaseSettings.Standalone
|
||||
&& (!SetupInfo.IsVisibleSettings(ManagementType.LdapSettings.ToString())
|
||||
|| !_tenantExtra.GetTenantQuota().Ldap))
|
||||
{
|
||||
throw new BillingException(Resource.ErrorNotAllowedOption, "Ldap");
|
||||
}
|
||||
}
|
||||
}
|
32
web/ASC.Web.Api/ApiModels/RequestsDto/LdapCronRequest.cs
Normal file
32
web/ASC.Web.Api/ApiModels/RequestsDto/LdapCronRequest.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.ApiModels.RequestsDto;
|
||||
|
||||
public class LdapCronRequestDto
|
||||
{
|
||||
public string Cron { get; set; }
|
||||
}
|
81
web/ASC.Web.Api/ApiModels/RequestsDto/LdapRequestsDto.cs
Normal file
81
web/ASC.Web.Api/ApiModels/RequestsDto/LdapRequestsDto.cs
Normal file
@ -0,0 +1,81 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.ApiModels.RequestsDto;
|
||||
|
||||
public class LdapRequestsDto : IMapFrom<LdapSettings>
|
||||
{
|
||||
public bool EnableLdapAuthentication { get; set; }
|
||||
|
||||
public bool StartTls { get; set; }
|
||||
|
||||
public bool Ssl { get; set; }
|
||||
|
||||
public bool SendWelcomeEmail { get; set; }
|
||||
|
||||
public string Server { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string UserDN { get; set; }
|
||||
|
||||
public int PortNumber { get; set; }
|
||||
|
||||
public string UserFilter { get; set; }
|
||||
|
||||
public string LoginAttribute { get; set; }
|
||||
|
||||
public Dictionary<MappingFields, string> LdapMapping { get; set; }
|
||||
|
||||
//ToDo: use SId instead of group name
|
||||
public Dictionary<AccessRight, string> AccessRights { get; set; }
|
||||
|
||||
public bool GroupMembership { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string GroupDN { get; set; }
|
||||
|
||||
public string UserAttribute { get; set; }
|
||||
|
||||
public string GroupFilter { get; set; }
|
||||
|
||||
public string GroupAttribute { get; set; }
|
||||
|
||||
public string GroupNameAttribute { get; set; }
|
||||
|
||||
public bool Authentication { get; set; }
|
||||
|
||||
public string Login { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public bool AcceptCertificate { get; set; }
|
||||
|
||||
public void Mapping(Profile profile)
|
||||
{
|
||||
profile.CreateMap<LdapRequestsDto, LdapSettings>();
|
||||
}
|
||||
|
||||
}
|
36
web/ASC.Web.Api/ApiModels/ResponseDto/LdapCronSettingsDto.cs
Normal file
36
web/ASC.Web.Api/ApiModels/ResponseDto/LdapCronSettingsDto.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.ApiModels.ResponseDto;
|
||||
|
||||
public class LdapCronSettingsDto : IMapFrom<LdapCronSettings>
|
||||
{
|
||||
public string Cron { get; set; }
|
||||
public void Mapping(Profile profile)
|
||||
{
|
||||
profile.CreateMap<LdapCronSettings, LdapCronSettingsDto>();
|
||||
}
|
||||
}
|
81
web/ASC.Web.Api/ApiModels/ResponseDto/LdapSettingsDto.cs
Normal file
81
web/ASC.Web.Api/ApiModels/ResponseDto/LdapSettingsDto.cs
Normal file
@ -0,0 +1,81 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.ApiModels.ResponseDto;
|
||||
|
||||
public class LdapSettingsDto : IMapFrom<LdapSettings>
|
||||
{
|
||||
public bool EnableLdapAuthentication { get; set; }
|
||||
|
||||
public bool StartTls { get; set; }
|
||||
|
||||
public bool Ssl { get; set; }
|
||||
|
||||
public bool SendWelcomeEmail { get; set; }
|
||||
|
||||
public string Server { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string UserDN { get; set; }
|
||||
|
||||
public int PortNumber { get; set; }
|
||||
|
||||
public string UserFilter { get; set; }
|
||||
|
||||
public string LoginAttribute { get; set; }
|
||||
|
||||
public Dictionary<MappingFields, string> LdapMapping { get; set; }
|
||||
|
||||
//ToDo: use SId instead of group name
|
||||
public Dictionary<AccessRight, string> AccessRights { get; set; }
|
||||
|
||||
public bool GroupMembership { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public string GroupDN { get; set; }
|
||||
|
||||
public string UserAttribute { get; set; }
|
||||
|
||||
public string GroupFilter { get; set; }
|
||||
|
||||
public string GroupAttribute { get; set; }
|
||||
|
||||
public string GroupNameAttribute { get; set; }
|
||||
|
||||
public bool Authentication { get; set; }
|
||||
|
||||
public string Login { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public bool AcceptCertificate { get; set; }
|
||||
|
||||
public void Mapping(Profile profile)
|
||||
{
|
||||
profile.CreateMap<LdapSettings, LdapSettingsDto>();
|
||||
}
|
||||
|
||||
}
|
53
web/ASC.Web.Api/ApiModels/ResponseDto/LdapStatusDto.cs
Normal file
53
web/ASC.Web.Api/ApiModels/ResponseDto/LdapStatusDto.cs
Normal file
@ -0,0 +1,53 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api.ApiModels.ResponseDto;
|
||||
|
||||
public class LdapStatusDto : IMapFrom<LdapOperationStatus>
|
||||
{
|
||||
public bool Completed { get; set; }
|
||||
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
|
||||
public string Error { get; set; }
|
||||
|
||||
public string Warning { get; set; }
|
||||
|
||||
public int Percents { get; set; }
|
||||
|
||||
public string CertificateConfirmRequest { get; set; }
|
||||
|
||||
public string Source { get; set; }
|
||||
|
||||
public string OperationType { get; set; }
|
||||
|
||||
public void Mapping(Profile profile)
|
||||
{
|
||||
profile.CreateMap<LdapOperationStatus, LdapStatusDto>();
|
||||
}
|
||||
}
|
@ -37,17 +37,20 @@ global using System.Text.Json.Serialization;
|
||||
global using System.Text.RegularExpressions;
|
||||
global using System.Web;
|
||||
|
||||
global using ASC.ActiveDirectory.Base;
|
||||
global using ASC.ActiveDirectory.Base.Settings;
|
||||
global using ASC.ActiveDirectory.ComplexOperations;
|
||||
global using ASC.Api.Collections;
|
||||
global using ASC.Api.Core;
|
||||
global using ASC.Api.Core.Convention;
|
||||
global using ASC.Api.Core.Extensions;
|
||||
global using ASC.Api.Core.Extensions;
|
||||
global using ASC.Api.Core.Security;
|
||||
global using ASC.Api.Settings;
|
||||
global using ASC.Api.Settings.Smtp;
|
||||
global using ASC.Api.Utils;
|
||||
global using ASC.AuditTrail;
|
||||
global using ASC.AuditTrail.Mappers;
|
||||
global using ASC.AuditTrail.Models;
|
||||
global using ASC.AuditTrail.Models;
|
||||
global using ASC.AuditTrail.Repositories;
|
||||
global using ASC.AuditTrail.Types;
|
||||
global using ASC.Common;
|
||||
@ -85,11 +88,13 @@ global using ASC.FederatedLogin.Profile;
|
||||
global using ASC.IPSecurity;
|
||||
global using ASC.MessagingSystem.Core;
|
||||
global using ASC.MessagingSystem.Models;
|
||||
global using ASC.Notify.Cron;
|
||||
global using ASC.Security.Cryptography;
|
||||
global using ASC.Web.Api;
|
||||
global using ASC.Web.Api.ApiModel.RequestsDto;
|
||||
global using ASC.Web.Api.ApiModel.ResponseDto;
|
||||
global using ASC.Web.Api.ApiModels.RequestsDto;
|
||||
global using ASC.Web.Api.ApiModels.ResponseDto;
|
||||
global using ASC.Web.Api.Core;
|
||||
global using ASC.Web.Api.Log;
|
||||
global using ASC.Web.Api.Models;
|
||||
@ -137,6 +142,7 @@ global using Microsoft.Extensions.Options;
|
||||
|
||||
global using MimeKit;
|
||||
|
||||
global using static ASC.ActiveDirectory.Base.Settings.LdapSettings;
|
||||
global using static ASC.Security.Cryptography.EmailValidationKeyProvider;
|
||||
|
||||
|
||||
global using SecurityContext = ASC.Core.SecurityContext;
|
@ -25,14 +25,19 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
var options = new WebApplicationOptions
|
||||
{
|
||||
{
|
||||
Args = args,
|
||||
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
|
||||
};
|
||||
|
||||
var builder = WebApplication.CreateBuilder(options);
|
||||
|
||||
builder.Host.ConfigureDefault(args, configureServices: (hostContext, services, diHelper) =>
|
||||
{
|
||||
services.AddHostedService<LdapNotifyService>();
|
||||
diHelper.TryAdd<LdapNotifyService>();
|
||||
});
|
||||
|
||||
builder.Host.ConfigureDefault(args);
|
||||
builder.WebHost.ConfigureDefaultKestrel();
|
||||
|
||||
var startup = new Startup(builder.Configuration, builder.Environment);
|
||||
|
@ -1,38 +1,38 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Api;
|
||||
|
||||
public class Startup : BaseStartup
|
||||
{
|
||||
protected override bool ConfirmAddScheme { get => true; }
|
||||
|
||||
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
|
||||
{
|
||||
|
||||
namespace ASC.Web.Api;
|
||||
|
||||
public class Startup : BaseStartup
|
||||
{
|
||||
protected override bool ConfirmAddScheme { get => true; }
|
||||
|
||||
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user