Skip to content

Commit 702b937

Browse files
authored
Enable nullable on Authentication.Negotiate (#29252)
1 parent b66402c commit 702b937

12 files changed

+110
-101
lines changed

src/Security/Authentication/Negotiate/src/Events/AuthenticationFailedContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ public AuthenticationFailedContext(
2424
/// <summary>
2525
/// The exception that occurred while processing the authentication.
2626
/// </summary>
27-
public Exception Exception { get; set; }
27+
public Exception Exception { get; set; } = default!;
2828
}
2929
}

src/Security/Authentication/Negotiate/src/Internal/INegotiateState.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
99
// For testing
1010
internal interface INegotiateState : IDisposable
1111
{
12-
string GetOutgoingBlob(string incomingBlob, out BlobErrorType status, out Exception error);
12+
string? GetOutgoingBlob(string incomingBlob, out BlobErrorType status, out Exception? error);
1313

1414
bool IsCompleted { get; }
1515

src/Security/Authentication/Negotiate/src/Internal/LdapAdapter.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System.Collections.Generic;
5+
using System.Diagnostics;
56
using System.DirectoryServices.Protocols;
67
using System.Linq;
78
using System.Security.Claims;
@@ -16,7 +17,7 @@ internal static class LdapAdapter
1617
{
1718
public static async Task RetrieveClaimsAsync(LdapSettings settings, ClaimsIdentity identity, ILogger logger)
1819
{
19-
var user = identity.Name;
20+
var user = identity.Name!;
2021
var userAccountNameIndex = user.IndexOf('@');
2122
var userAccountName = userAccountNameIndex == -1 ? user : user.Substring(0, userAccountNameIndex);
2223

@@ -40,6 +41,8 @@ public static async Task RetrieveClaimsAsync(LdapSettings settings, ClaimsIdenti
4041

4142
var filter = $"(&(objectClass=user)(sAMAccountName={userAccountName}))"; // This is using ldap search query language, it is looking on the server for someUser
4243
var searchRequest = new SearchRequest(distinguishedName, filter, SearchScope.Subtree, null);
44+
45+
Debug.Assert(settings.LdapConnection != null);
4346
var searchResponse = (SearchResponse) await Task<DirectoryResponse>.Factory.FromAsync(
4447
settings.LdapConnection.BeginSendRequest,
4548
settings.LdapConnection.EndSendRequest,

src/Security/Authentication/Negotiate/src/Internal/NegotiateLoggingExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ namespace Microsoft.Extensions.Logging
77
{
88
internal static class NegotiateLoggingExtensions
99
{
10-
private static Action<ILogger, Exception> _incompleteNegotiateChallenge;
11-
private static Action<ILogger, Exception> _negotiateComplete;
12-
private static Action<ILogger, Exception> _enablingCredentialPersistence;
13-
private static Action<ILogger, string, Exception> _disablingCredentialPersistence;
10+
private static Action<ILogger, Exception?> _incompleteNegotiateChallenge;
11+
private static Action<ILogger, Exception?> _negotiateComplete;
12+
private static Action<ILogger, Exception?> _enablingCredentialPersistence;
13+
private static Action<ILogger, string, Exception?> _disablingCredentialPersistence;
1414
private static Action<ILogger, Exception> _exceptionProcessingAuth;
1515
private static Action<ILogger, Exception> _credentialError;
1616
private static Action<ILogger, Exception> _clientError;
17-
private static Action<ILogger, Exception> _challengeNegotiate;
18-
private static Action<ILogger, Exception> _reauthenticating;
19-
private static Action<ILogger, Exception> _deferring;
20-
private static Action<ILogger, string, Exception> _negotiateError;
17+
private static Action<ILogger, Exception?> _challengeNegotiate;
18+
private static Action<ILogger, Exception?> _reauthenticating;
19+
private static Action<ILogger, Exception?> _deferring;
20+
private static Action<ILogger, string, Exception?> _negotiateError;
2121

2222
static NegotiateLoggingExtensions()
2323
{

src/Security/Authentication/Negotiate/src/Internal/ReflectedNegotiateState.cs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ internal class ReflectedNegotiateState : INegotiateState
2525
private static readonly FieldInfo _statusCode;
2626
private static readonly FieldInfo _statusException;
2727
private static readonly MethodInfo _getException;
28-
private static readonly FieldInfo _gssMinorStatus;
29-
private static readonly Type _gssExceptionType;
28+
private static readonly FieldInfo? _gssMinorStatus;
29+
private static readonly Type? _gssExceptionType;
3030

3131
private readonly object _instance;
3232

3333
static ReflectedNegotiateState()
3434
{
3535
var secAssembly = typeof(AuthenticationException).Assembly;
36-
var ntAuthType = secAssembly.GetType("System.Net.NTAuthentication", throwOnError: true);
36+
var ntAuthType = secAssembly.GetType("System.Net.NTAuthentication", throwOnError: true)!;
3737
_constructor = ntAuthType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First();
3838
_getOutgoingBlob = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info =>
3939
info.Name.Equals("GetOutgoingBlob") && info.GetParameters().Count() == 3).Single();
@@ -44,19 +44,19 @@ static ReflectedNegotiateState()
4444
_closeContext = ntAuthType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Where(info =>
4545
info.Name.Equals("CloseContext")).Single();
4646

47-
var securityStatusType = secAssembly.GetType("System.Net.SecurityStatusPal", throwOnError: true);
48-
_statusCode = securityStatusType.GetField("ErrorCode");
49-
_statusException = securityStatusType.GetField("Exception");
47+
var securityStatusType = secAssembly.GetType("System.Net.SecurityStatusPal", throwOnError: true)!;
48+
_statusCode = securityStatusType.GetField("ErrorCode")!;
49+
_statusException = securityStatusType.GetField("Exception")!;
5050

5151
if (!OperatingSystem.IsWindows())
5252
{
53-
var interopType = secAssembly.GetType("Interop", throwOnError: true);
54-
var netNativeType = interopType.GetNestedType("NetSecurityNative", BindingFlags.NonPublic | BindingFlags.Static);
55-
_gssExceptionType = netNativeType.GetNestedType("GssApiException", BindingFlags.NonPublic);
56-
_gssMinorStatus = _gssExceptionType.GetField("_minorStatus", BindingFlags.Instance | BindingFlags.NonPublic);
53+
var interopType = secAssembly.GetType("Interop", throwOnError: true)!;
54+
var netNativeType = interopType.GetNestedType("NetSecurityNative", BindingFlags.NonPublic | BindingFlags.Static)!;
55+
_gssExceptionType = netNativeType.GetNestedType("GssApiException", BindingFlags.NonPublic)!;
56+
_gssMinorStatus = _gssExceptionType.GetField("_minorStatus", BindingFlags.Instance | BindingFlags.NonPublic)!;
5757
}
5858

59-
var negoStreamPalType = secAssembly.GetType("System.Net.Security.NegotiateStreamPal", throwOnError: true);
59+
var negoStreamPalType = secAssembly.GetType("System.Net.Security.NegotiateStreamPal", throwOnError: true)!;
6060
_getIdentity = negoStreamPalType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(info =>
6161
info.Name.Equals("GetIdentity")).Single();
6262
_getException = negoStreamPalType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Where(info =>
@@ -67,24 +67,24 @@ public ReflectedNegotiateState()
6767
{
6868
// internal NTAuthentication(bool isServer, string package, NetworkCredential credential, string spn, ContextFlagsPal requestedContextFlags, ChannelBinding channelBinding)
6969
var credential = CredentialCache.DefaultCredentials;
70-
_instance = _constructor.Invoke(new object[] { true, "Negotiate", credential, null, 0, null });
70+
_instance = _constructor.Invoke(new object?[] { true, "Negotiate", credential, null, 0, null });
7171
}
7272

7373
// Copied rather than reflected to remove the IsCompleted -> CloseContext check.
7474
// The client doesn't need the context once auth is complete, but the server does.
7575
// I'm not sure why it auto-closes for the client given that the client closes it just a few lines later.
7676
// https://github.com/dotnet/corefx/blob/a3ab91e10045bb298f48c1d1f9bd5b0782a8ac46/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.cs#L134
77-
public string GetOutgoingBlob(string incomingBlob, out BlobErrorType status, out Exception error)
77+
public string? GetOutgoingBlob(string incomingBlob, out BlobErrorType status, out Exception? error)
7878
{
79-
byte[] decodedIncomingBlob = null;
79+
byte[]? decodedIncomingBlob = null;
8080
if (incomingBlob != null && incomingBlob.Length > 0)
8181
{
8282
decodedIncomingBlob = Convert.FromBase64String(incomingBlob);
8383
}
8484

8585
byte[] decodedOutgoingBlob = GetOutgoingBlob(decodedIncomingBlob, out status, out error);
8686

87-
string outgoingBlob = null;
87+
string? outgoingBlob = null;
8888
if (decodedOutgoingBlob != null && decodedOutgoingBlob.Length > 0)
8989
{
9090
outgoingBlob = Convert.ToBase64String(decodedOutgoingBlob);
@@ -93,28 +93,28 @@ public string GetOutgoingBlob(string incomingBlob, out BlobErrorType status, out
9393
return outgoingBlob;
9494
}
9595

96-
private byte[] GetOutgoingBlob(byte[] incomingBlob, out BlobErrorType status, out Exception error)
96+
private byte[] GetOutgoingBlob(byte[]? incomingBlob, out BlobErrorType status, out Exception? error)
9797
{
9898
try
9999
{
100100
// byte[] GetOutgoingBlob(byte[] incomingBlob, bool throwOnError, out SecurityStatusPal statusCode)
101-
var parameters = new object[] { incomingBlob, false, null };
102-
var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters);
101+
var parameters = new object?[] { incomingBlob, false, null };
102+
var blob = (byte[])_getOutgoingBlob.Invoke(_instance, parameters)!;
103103

104104
var securityStatus = parameters[2];
105105
// TODO: Update after corefx changes
106-
error = (Exception)(_statusException.GetValue(securityStatus)
106+
error = (Exception?)(_statusException.GetValue(securityStatus)
107107
?? _getException.Invoke(null, new[] { securityStatus }));
108-
var errorCode = (SecurityStatusPalErrorCode)_statusCode.GetValue(securityStatus);
108+
var errorCode = (SecurityStatusPalErrorCode)_statusCode.GetValue(securityStatus)!;
109109

110110
// TODO: Remove after corefx changes
111111
// The linux implementation always uses InternalError;
112112
if (errorCode == SecurityStatusPalErrorCode.InternalError
113113
&& !OperatingSystem.IsWindows()
114-
&& _gssExceptionType.IsInstanceOfType(error))
114+
&& _gssExceptionType!.IsInstanceOfType(error))
115115
{
116116
var majorStatus = (uint)error.HResult;
117-
var minorStatus = (uint)_gssMinorStatus.GetValue(error);
117+
var minorStatus = (uint)_gssMinorStatus!.GetValue(error)!;
118118

119119
// Remap specific errors
120120
if (majorStatus == GSS_S_NO_CRED && minorStatus == 0)
@@ -149,24 +149,24 @@ private byte[] GetOutgoingBlob(byte[] incomingBlob, out BlobErrorType status, ou
149149
catch (TargetInvocationException tex)
150150
{
151151
// Unwrap
152-
ExceptionDispatchInfo.Capture(tex.InnerException).Throw();
152+
ExceptionDispatchInfo.Capture(tex.InnerException!).Throw();
153153
throw;
154154
}
155155
}
156156

157157
public bool IsCompleted
158158
{
159-
get => (bool)_isCompleted.Invoke(_instance, Array.Empty<object>());
159+
get => (bool)_isCompleted.Invoke(_instance, Array.Empty<object>())!;
160160
}
161161

162162
public string Protocol
163163
{
164-
get => (string)_protocol.Invoke(_instance, Array.Empty<object>());
164+
get => (string)_protocol.Invoke(_instance, Array.Empty<object>())!;
165165
}
166166

167167
public IIdentity GetIdentity()
168168
{
169-
return (IIdentity)_getIdentity.Invoke(obj: null, parameters: new object[] { _instance });
169+
return (IIdentity)_getIdentity.Invoke(obj: null, parameters: new object[] { _instance })!;
170170
}
171171

172172
public void Dispose()

src/Security/Authentication/Negotiate/src/LdapSettings.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ public class LdapSettings
2424
/// <example>
2525
/// DOMAIN.com
2626
/// </example>
27-
public string Domain { get; set; }
27+
public string Domain { get; set; } = default!;
2828

2929
/// <summary>
3030
/// The machine account name to use when opening the LDAP connection.
3131
/// If this is not provided, the machine wide credentials of the
3232
/// domain joined machine will be used.
3333
/// </summary>
34-
public string MachineAccountName { get; set; }
34+
public string? MachineAccountName { get; set; }
3535

3636
/// <summary>
3737
/// The machine account password to use when opening the LDAP connection.
3838
/// This must be provided if a <see cref="MachineAccountName"/> is provided.
3939
/// </summary>
40-
public string MachineAccountPassword { get; set; }
40+
public string? MachineAccountPassword { get; set; }
4141

4242
/// <summary>
4343
/// This option indicates whether nested groups should be ignored when
@@ -55,7 +55,7 @@ public class LdapSettings
5555
/// <see cref="MachineAccountPassword"/> options will not be used to create
5656
/// the <see cref="LdapConnection"/>.
5757
/// </summary>
58-
public LdapConnection LdapConnection { get; set; }
58+
public LdapConnection? LdapConnection { get; set; }
5959

6060
/// <summary>
6161
/// The sliding expiration that should be used for entries in the cache for user claims, defaults to 10 minutes.
@@ -74,7 +74,7 @@ public class LdapSettings
7474
/// </summary>
7575
public int ClaimsCacheSize { get; set; } = 100 * 1024 * 1024;
7676

77-
internal MemoryCache ClaimsCache { get; set; }
77+
internal MemoryCache? ClaimsCache { get; set; }
7878

7979
/// <summary>
8080
/// Validates the <see cref="LdapSettings"/>.

src/Security/Authentication/Negotiate/src/Microsoft.AspNetCore.Authentication.Negotiate.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
66
<GenerateDocumentationFile>true</GenerateDocumentationFile>
77
<PackageTags>aspnetcore;authentication;security</PackageTags>
8+
<Nullable>enable</Nullable>
89
</PropertyGroup>
910

1011
<ItemGroup>

src/Security/Authentication/Negotiate/src/NegotiateExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder buil
6767
/// <param name="displayName">The name displayed to users when selecting an authentication handler. The default is null to prevent this from displaying.</param>
6868
/// <param name="configureOptions">Allows for configuring the authentication handler.</param>
6969
/// <returns>The original builder.</returns>
70-
public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<NegotiateOptions> configureOptions)
70+
public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder builder, string authenticationScheme, string? displayName, Action<NegotiateOptions> configureOptions)
7171
{
7272
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<NegotiateOptions>, PostConfigureNegotiateOptions>());
7373
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IStartupFilter>(new NegotiateOptionsValidationStartupFilter(authenticationScheme)));

0 commit comments

Comments
 (0)