fix(security): resolve Security-009,010,011 — LDAP connection timeout, design-doc correction, security-path test coverage; Security-008 deferred
This commit is contained in:
@@ -34,6 +34,12 @@ public class LdapAuthService
|
||||
{
|
||||
using var connection = new LdapConnection();
|
||||
|
||||
// Bound how long a hung LDAP server can pin a thread-pool thread. The
|
||||
// `ct` passed to Task.Run below only prevents the work item from starting;
|
||||
// it cannot interrupt an in-progress blocking Connect/Bind/Search. This
|
||||
// timeout is the real safeguard (Security-009).
|
||||
ApplyConnectionTimeout(connection);
|
||||
|
||||
// LDAPS: TLS negotiated at connection time. StartTLS: connect plaintext,
|
||||
// then upgrade the session before any credentials are sent.
|
||||
if (_options.LdapTransport == LdapTransport.Ldaps)
|
||||
@@ -127,6 +133,27 @@ public class LdapAuthService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies <see cref="SecurityOptions.LdapConnectionTimeoutMs"/> to both the socket
|
||||
/// connect timeout and the per-operation (bind/search) time limit, so a hung or
|
||||
/// unresponsive LDAP server cannot pin a thread-pool thread indefinitely. The
|
||||
/// <c>CancellationToken</c> handed to the <c>Task.Run</c> wrappers only guards
|
||||
/// work-item scheduling and cannot interrupt an in-progress blocking call.
|
||||
/// </summary>
|
||||
private void ApplyConnectionTimeout(LdapConnection connection)
|
||||
{
|
||||
var timeoutMs = _options.LdapConnectionTimeoutMs;
|
||||
if (timeoutMs <= 0)
|
||||
return;
|
||||
|
||||
connection.ConnectionTimeout = timeoutMs;
|
||||
|
||||
// LdapConstraints.TimeLimit is the server-side operation time limit in ms.
|
||||
var constraints = connection.Constraints;
|
||||
constraints.TimeLimit = timeoutMs;
|
||||
connection.Constraints = constraints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the user's full DN. When a service account is configured, performs a
|
||||
/// search-then-bind lookup. Otherwise falls back to constructing the DN directly.
|
||||
|
||||
@@ -65,6 +65,16 @@ public class SecurityOptions
|
||||
/// </summary>
|
||||
public string LdapGroupAttribute { get; set; } = "memberOf";
|
||||
|
||||
/// <summary>
|
||||
/// Network timeout, in milliseconds, applied to the LDAP socket connect and to
|
||||
/// LDAP operations (bind/search). The synchronous Novell LDAP calls are wrapped
|
||||
/// in <c>Task.Run</c>, where the <c>CancellationToken</c> only guards work-item
|
||||
/// scheduling — it cannot interrupt an in-progress blocking call. This timeout is
|
||||
/// the real safeguard: it bounds how long a hung LDAP server can pin a thread-pool
|
||||
/// thread (Security-009). Default 10 seconds.
|
||||
/// </summary>
|
||||
public int LdapConnectionTimeoutMs { get; set; } = 10_000;
|
||||
|
||||
/// <summary>
|
||||
/// Symmetric HMAC-SHA256 signing key for cookie-embedded JWTs. Must be at least
|
||||
/// 32 bytes (256 bits) — validated at <see cref="JwtTokenService"/> construction.
|
||||
|
||||
Reference in New Issue
Block a user