fix: session B — Go-faithful auth error states, NKey padding, permissions, signal disposal

This commit is contained in:
Joseph Doherty
2026-02-26 17:49:13 -05:00
parent 8c380e7ca6
commit a0c9c0094c
12 changed files with 97 additions and 46 deletions

View File

@@ -278,16 +278,19 @@ public static partial class AuthHandler
/// </summary>
public static ClosedState GetAuthErrClosedState(Exception? err)
{
if (err == null) return ClosedState.AuthenticationTimeout;
var msg = err.Message;
if (msg.Contains("expired", StringComparison.OrdinalIgnoreCase)) return ClosedState.AuthenticationExpired;
if (msg.Contains("revoked", StringComparison.OrdinalIgnoreCase)) return ClosedState.AuthRevoked;
return ClosedState.AuthenticationViolation;
return err switch
{
AuthProxyNotTrustedException => ClosedState.ProxyNotTrusted,
AuthProxyRequiredException => ClosedState.ProxyRequired,
_ => ClosedState.AuthenticationViolation,
};
}
/// <summary>
/// Validates proxy configuration entries in options.
/// Mirrors Go <c>validateProxies</c> in server/auth.go.
/// Validates that proxy protocol configuration is consistent.
/// If <see cref="ServerOptions.ProxyRequired"/> is set, <see cref="ServerOptions.ProxyProtocol"/> must also be enabled.
/// Note: Full NKey-format validation of trusted proxy keys is deferred until proxy auth is fully implemented.
/// Partially mirrors Go <c>validateProxies</c> in server/auth.go.
/// </summary>
public static Exception? ValidateProxies(ServerOptions opts)
{

View File

@@ -170,3 +170,21 @@ public class RoutePermissions
// Account stub removed — full implementation is in Accounts/Account.cs
// in the ZB.MOM.NatsNet.Server namespace.
/// <summary>
/// Sentinel exception representing a proxy-auth "not trusted" error.
/// Mirrors Go <c>ErrAuthProxyNotTrusted</c> in server/auth.go.
/// </summary>
public sealed class AuthProxyNotTrustedException : InvalidOperationException
{
public AuthProxyNotTrustedException() : base("proxy not trusted") { }
}
/// <summary>
/// Sentinel exception representing a proxy-auth "required" error.
/// Mirrors Go <c>ErrAuthProxyRequired</c> in server/auth.go.
/// </summary>
public sealed class AuthProxyRequiredException : InvalidOperationException
{
public AuthProxyRequiredException() : base("proxy required") { }
}

View File

@@ -31,15 +31,6 @@ public static class JwtProcessor
/// </summary>
public const string JwtPrefix = "eyJ";
/// <summary>
/// Wipes a byte slice by filling with 'x', for clearing nkey seed data.
/// Mirrors Go <c>wipeSlice</c>.
/// </summary>
public static void WipeSlice(Span<byte> buf)
{
buf.Fill((byte)'x');
}
/// <summary>
/// Validates that the given IP host address is allowed by the user claims source CIDRs.
/// Returns true if the host is within any of the allowed CIDRs, or if no CIDRs are specified.
@@ -227,17 +218,9 @@ public static class JwtProcessor
if (opts.TrustedOperators == null || opts.TrustedOperators.Count == 0)
return null;
// Each operator should be a well-formed JWT.
foreach (var op in opts.TrustedOperators)
{
var jwtStr = op?.ToString() ?? string.Empty;
var (_, err) = ReadOperatorJwtInternal(jwtStr);
// Allow the "not implemented" case through — structure validated up to prefix check.
if (err is FormatException fe && fe.Message.Contains("not fully implemented"))
continue;
if (err is ArgumentException)
return new InvalidOperationException($"invalid trusted operator JWT: {err.Message}");
}
// TODO: Full trusted operator JWT validation requires a NATS JWT library.
// Each operator JWT should be decoded and its signing key chain verified.
// For now, we accept any non-empty operator list and validate at connect time.
return null;
}
}