Renames tile control classes

Adds conditional logging for memory debugging
Hides CrredentialTile3 implementation
This commit is contained in:
Ryan Newington
2023-02-03 07:26:07 +11:00
parent 9c1f89dfc8
commit bc984aaaa0
16 changed files with 122 additions and 85 deletions
@@ -53,10 +53,9 @@ namespace Lithnet.CredentialProvider
{ {
this.bitmap = value; this.bitmap = value;
if (this.Events is ICredentialProviderCredentialEvents3 e) if (this.Events is ICredentialProviderCredentialEvents2 e)
{ {
var buffer = this.GetBitmapBuffer(out uint size); e.SetFieldBitmap(this.Credential, this.Id, this.GetHBitmap());
e.SetFieldBitmapBuffer(this.Credential, this.Id, size, buffer);
} }
this.RaisePropertyChanged(); this.RaisePropertyChanged();
@@ -20,7 +20,7 @@ namespace Lithnet.CredentialProvider
internal ControlCollection() { } internal ControlCollection() { }
internal ControlCollection(CredentialProviderCredential1Tile credential) internal ControlCollection(CredentialTile credential)
{ {
this.credential = credential; this.credential = credential;
} }
@@ -24,6 +24,7 @@ namespace Lithnet.CredentialProvider
/// <param name="key">The unique key for this control</param> /// <param name="key">The unique key for this control</param>
/// <param name="label">The label associated with the control</param> /// <param name="label">The label associated with the control</param>
public InsecurePasswordTextboxControl(string key, string label) : base(key, label, FieldType.PasswordText) { } public InsecurePasswordTextboxControl(string key, string label) : base(key, label, FieldType.PasswordText) { }
private InsecurePasswordTextboxControl(InsecurePasswordTextboxControl source) : base(source) { } private InsecurePasswordTextboxControl(InsecurePasswordTextboxControl source) : base(source) { }
/// <summary> /// <summary>
@@ -40,7 +41,7 @@ namespace Lithnet.CredentialProvider
if (this.password?.Length > 0) if (this.password?.Length > 0)
{ {
var ptr = Marshal.StringToCoTaskMemUni(this.password); var ptr = Marshal.StringToCoTaskMemUni(this.password);
this.logger.LogTrace($"0x:{ptr.ToString("X16")} - Created ptr for outgoing SetFieldString"); this.logger.LogWarningDebug($"0x:{ptr.ToString("X16")} - Created ptr for outgoing SetFieldString");
this.Events?.SetFieldString(this.Credential, this.Id, ptr); this.Events?.SetFieldString(this.Credential, this.Id, ptr);
} }
else else
@@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using Lithnet.CredentialProvider.Interop; using Lithnet.CredentialProvider.Interop;
@@ -40,7 +39,7 @@ namespace Lithnet.CredentialProvider
if (this.password?.Length > 0) if (this.password?.Length > 0)
{ {
var ptr = Marshal.SecureStringToCoTaskMemUnicode(this.password); var ptr = Marshal.SecureStringToCoTaskMemUnicode(this.password);
Trace.WriteLine($"0x:{ptr.ToString("X16")} - CONTROL: Created ptr for outgoing SetFieldString"); this.logger.LogWarningDebug($"0x:{ptr.ToString("X16")} - CONTROL: Created ptr for outgoing SetFieldString");
this.Events?.SetFieldString(this.Credential, this.Id, ptr); this.Events?.SetFieldString(this.Credential, this.Id, ptr);
} }
else else
@@ -10,11 +10,11 @@ namespace Lithnet.CredentialProvider
{ {
try try
{ {
this.logger.LogTrace($"SetUserArray"); this.logger.LogTrace("SetUserArray");
if (users.GetCount(out uint count) != HRESULT.S_OK) if (users.GetCount(out uint count) != HRESULT.S_OK)
{ {
this.logger.LogTrace($"ICredentialProviderUserArray.GetCount failed"); this.logger.LogTrace("ICredentialProviderUserArray.GetCount failed");
return HRESULT.S_FALSE; return HRESULT.S_FALSE;
} }
@@ -19,7 +19,7 @@ namespace Lithnet.CredentialProvider
private IntPtr credentialProviderEventsAdviseContext; private IntPtr credentialProviderEventsAdviseContext;
private bool notifyOnTileCollectionChange; private bool notifyOnTileCollectionChange;
private List<CredentialProviderCredential1Tile> tiles; private List<CredentialTile> tiles;
internal ILoggerFactory LoggerFactory { get; } internal ILoggerFactory LoggerFactory { get; }
@@ -46,7 +46,7 @@ namespace Lithnet.CredentialProvider
/// <summary> /// <summary>
/// Gets a list of the tiles created for this credential provider /// Gets a list of the tiles created for this credential provider
/// </summary> /// </summary>
public IReadOnlyList<CredentialProviderCredential1Tile> Tiles { get; private set; } public IReadOnlyList<CredentialTile> Tiles { get; private set; }
/// <summary> /// <summary>
/// Provides access to the serialized input data provided by CredUI /// Provides access to the serialized input data provided by CredUI
@@ -106,7 +106,7 @@ namespace Lithnet.CredentialProvider
/// Adds additional user tiles to the collection, and notifies LogonUI that new tiles are available /// Adds additional user tiles to the collection, and notifies LogonUI that new tiles are available
/// </summary> /// </summary>
/// <param name="tiles">One or more credential tiles to add</param> /// <param name="tiles">One or more credential tiles to add</param>
public void AddAdditionalUserTiles(params CredentialProviderCredential1Tile[] tiles) public void AddAdditionalUserTiles(params CredentialTile[] tiles)
{ {
if (tiles == null) if (tiles == null)
{ {
@@ -129,7 +129,7 @@ namespace Lithnet.CredentialProvider
/// Removes one or more user tiles, and notifies LogonUI that tiles have been removed /// Removes one or more user tiles, and notifies LogonUI that tiles have been removed
/// </summary> /// </summary>
/// <param name="tiles">The crendential tiles to remove</param> /// <param name="tiles">The crendential tiles to remove</param>
public void RemoveUserTiles(params CredentialProviderCredential1Tile[] tiles) public void RemoveUserTiles(params CredentialTile[] tiles)
{ {
if (tiles == null) if (tiles == null)
{ {
@@ -147,13 +147,13 @@ namespace Lithnet.CredentialProvider
/// <summary> /// <summary>
/// This method is used to generate the generic tile for this credential provider. This is called when <c ref="ShouldIncludeGenericTile"/> return true /// This method is used to generate the generic tile for this credential provider. This is called when <c ref="ShouldIncludeGenericTile"/> return true
/// </summary> /// </summary>
public abstract CredentialProviderCredential1Tile CreateGenericTile(); public abstract CredentialTile CreateGenericTile();
/// <summary> /// <summary>
/// Creates a credential tile for the specified user /// Creates a credential tile for the specified user
/// </summary> /// </summary>
/// <param name="user">The user to create the tile for</param> /// <param name="user">The user to create the tile for</param>
public abstract CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user); public abstract CredentialTile2 CreateUserTile(CredentialProviderUser user);
/// <summary> /// <summary>
/// This method is called when the LogonUI or CredUI provides inbound credential data. Override this method to respond to the incoming data. /// This method is called when the LogonUI or CredUI provides inbound credential data. Override this method to respond to the incoming data.
@@ -177,11 +177,11 @@ namespace Lithnet.CredentialProvider
} }
} }
private List<CredentialProviderCredential1Tile> GenerateSuppliedUserTiles() private List<CredentialTile> GenerateSuppliedUserTiles()
{ {
this.BuildControls(); this.BuildControls();
var tiles = new List<CredentialProviderCredential1Tile>(); var tiles = new List<CredentialTile>();
var users = new List<CredentialProviderUser>(); var users = new List<CredentialProviderUser>();
@@ -203,26 +203,38 @@ namespace Lithnet.CredentialProvider
var credentialProviderUser = new CredentialProviderUser(this.LoggerFactory, user); var credentialProviderUser = new CredentialProviderUser(this.LoggerFactory, user);
users.Add(credentialProviderUser); users.Add(credentialProviderUser);
if (this.ShouldIncludeUserTile(credentialProviderUser)) try
{ {
var userTile = this.CreateUserTile(credentialProviderUser); if (this.ShouldIncludeUserTile(credentialProviderUser))
if (userTile != null)
{ {
tiles.Add(userTile); var userTile = this.CreateUserTile(credentialProviderUser);
userTile.Initialize(); if (userTile != null)
{
tiles.Add(userTile);
userTile.Initialize();
}
} }
} }
catch (NotImplementedException)
{
}
} }
if (this.ShouldIncludeGenericTile()) try
{ {
var genericTile = this.CreateGenericTile(); if (this.ShouldIncludeGenericTile())
if (genericTile != null)
{ {
tiles.Add(genericTile); var genericTile = this.CreateGenericTile();
genericTile.Initialize(); if (genericTile != null)
{
tiles.Add(genericTile);
genericTile.Initialize();
}
} }
} }
catch (NotImplementedException)
{
}
this.SuppliedUsers = users.AsReadOnly(); this.SuppliedUsers = users.AsReadOnly();
@@ -231,7 +243,7 @@ namespace Lithnet.CredentialProvider
private void SetupTiles() private void SetupTiles()
{ {
this.tiles = new List<CredentialProviderCredential1Tile>(this.GenerateSuppliedUserTiles()); this.tiles = new List<CredentialTile>(this.GenerateSuppliedUserTiles());
this.Tiles = this.tiles.AsReadOnly(); this.Tiles = this.tiles.AsReadOnly();
} }
@@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider namespace Lithnet.CredentialProvider
{ {
public partial class CredentialProviderCredential1Tile : ICredentialProviderCredential public partial class CredentialTile : ICredentialProviderCredential
{ {
int ICredentialProviderCredential.Advise(ICredentialProviderCredentialEvents pcpce) int ICredentialProviderCredential.Advise(ICredentialProviderCredentialEvents pcpce)
{ {
@@ -145,7 +145,7 @@ namespace Lithnet.CredentialProvider
else else
{ {
ppsz = Marshal.SecureStringToCoTaskMemUnicode(p.Password); ppsz = Marshal.SecureStringToCoTaskMemUnicode(p.Password);
this.logger.LogCritical($"0x{ppsz.ToString("X16")} - Put password for outbound GetStringValue"); this.logger.LogWarningDebug($"0x{ppsz.ToString("X16")} - Put password for outbound GetStringValue");
} }
return HRESULT.S_OK; return HRESULT.S_OK;
@@ -160,7 +160,7 @@ namespace Lithnet.CredentialProvider
else else
{ {
ppsz = Marshal.StringToCoTaskMemUni(i.Password); ppsz = Marshal.StringToCoTaskMemUni(i.Password);
this.logger.LogCritical($"0x{ppsz.ToString("X16")} - Put password for outbound GetStringValue"); this.logger.LogWarningDebug($"0x{ppsz.ToString("X16")} - Put password for outbound GetStringValue");
} }
return HRESULT.S_OK; return HRESULT.S_OK;
@@ -316,7 +316,7 @@ namespace Lithnet.CredentialProvider
{ {
try try
{ {
this.logger.LogTrace($"0x{psz.ToString("X16")} - Incoming SetStringValue: field {dwFieldID}"); this.logger.LogWarningDebug($"0x{psz.ToString("X16")} - Incoming SetStringValue: field {dwFieldID}");
if (this.Controls.TryGetControl(dwFieldID, out var instance)) if (this.Controls.TryGetControl(dwFieldID, out var instance))
{ {
@@ -328,8 +328,7 @@ namespace Lithnet.CredentialProvider
if (instance.Type == FieldType.PasswordText && instance is SecurePasswordTextboxControl p) if (instance.Type == FieldType.PasswordText && instance is SecurePasswordTextboxControl p)
{ {
this.logger.LogCritical($"0x{psz.ToString("X16")} - Incoming password in SetStringValue"); this.logger.LogWarningDebug($"0x{psz.ToString("X16")} - Incoming password in SetStringValue");
p.SetPasswordInternal(psz.IntPtrToSecureString()); p.SetPasswordInternal(psz.IntPtrToSecureString());
PInvoke.SecureZeroMemory(psz, (uint)(psz.Wcslen() * 2)); PInvoke.SecureZeroMemory(psz, (uint)(psz.Wcslen() * 2));
return HRESULT.S_OK; return HRESULT.S_OK;
@@ -337,8 +336,7 @@ namespace Lithnet.CredentialProvider
if (instance.Type == FieldType.PasswordText && instance is InsecurePasswordTextboxControl i) if (instance.Type == FieldType.PasswordText && instance is InsecurePasswordTextboxControl i)
{ {
this.logger.LogCritical($"0x{psz.ToString("X16")} - Incoming password in SetStringValue"); this.logger.LogWarningDebug($"0x{psz.ToString("X16")} - Incoming password in SetStringValue");
i.SetPasswordInternal(Marshal.PtrToStringUni(psz)); i.SetPasswordInternal(Marshal.PtrToStringUni(psz));
PInvoke.SecureZeroMemory(psz, (uint)(psz.Wcslen() * 2)); PInvoke.SecureZeroMemory(psz, (uint)(psz.Wcslen() * 2));
return HRESULT.S_OK; return HRESULT.S_OK;
@@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider namespace Lithnet.CredentialProvider
{ {
public abstract partial class CredentialProviderCredential1Tile : ICredentialProviderCredentialWithFieldOptions public abstract partial class CredentialTile : ICredentialProviderCredentialWithFieldOptions
{ {
int ICredentialProviderCredentialWithFieldOptions.GetFieldOptions(uint dwFieldID, out FieldOptions options) int ICredentialProviderCredentialWithFieldOptions.GetFieldOptions(uint dwFieldID, out FieldOptions options)
{ {
@@ -9,7 +9,7 @@ namespace Lithnet.CredentialProvider
/// Represents a 'v1' user credential tile that implements the minimum functionality required by the credential provider framework /// Represents a 'v1' user credential tile that implements the minimum functionality required by the credential provider framework
/// </summary> /// </summary>
/// <remarks>Inheriting from this class enables you to provide a v1 credential tile. V1 credential tiles were introduced in Windows Vista. These tiles are not personalized. See the Microsoft documentation on ICredentialProviderCredential for more information</remarks> /// <remarks>Inheriting from this class enables you to provide a v1 credential tile. V1 credential tiles were introduced in Windows Vista. These tiles are not personalized. See the Microsoft documentation on ICredentialProviderCredential for more information</remarks>
public abstract partial class CredentialProviderCredential1Tile public abstract partial class CredentialTile
{ {
private protected readonly ILogger logger; private protected readonly ILogger logger;
private protected ICredentialProviderCredentialEvents events; private protected ICredentialProviderCredentialEvents events;
@@ -17,7 +17,7 @@ namespace Lithnet.CredentialProvider
private protected ControlCollection controls; private protected ControlCollection controls;
protected CredentialProviderCredential1Tile(CredentialProviderBase credentialProvider) protected CredentialTile(CredentialProviderBase credentialProvider)
{ {
this.CredentialProvider = credentialProvider; this.CredentialProvider = credentialProvider;
this.logger = credentialProvider.LoggerFactory.CreateLogger(this.GetType()); this.logger = credentialProvider.LoggerFactory.CreateLogger(this.GetType());
@@ -4,26 +4,8 @@ using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider namespace Lithnet.CredentialProvider
{ {
/// <summary> public abstract partial class CredentialTile2 : ICredentialProviderCredential2
/// Represents a 'v2' user credential tile that implements the functionality of <see cref="CredentialProviderCredential1Tile"/>, and includes support for personalized tile, where a single user tile is shown, with multiple logon options grouped within it.
/// </summary>
/// <remarks>Inheriting from this class enables you to provide a v2 credential tile. V2 credential tiles were introduced in Windows 8. See the Microsoft documentation on ICredentialProviderCredential2 for more information</remarks>
/// <inheritdoc/>
public abstract class CredentialProviderCredential2Tile : CredentialProviderCredential1Tile, ICredentialProviderCredential2
{ {
public CredentialProviderUser User { get; }
public override bool IsGenericTile => this.User == null;
public GenericTileDisplayMode GenericTileDisplayMode { get; set; }
protected CredentialProviderCredential2Tile(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
protected CredentialProviderCredential2Tile(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider)
{
this.User = user;
}
int ICredentialProviderCredential2.GetUserSid(out string sid) int ICredentialProviderCredential2.GetUserSid(out string sid)
{ {
sid = null; sid = null;
@@ -0,0 +1,33 @@
namespace Lithnet.CredentialProvider
{
/// <summary>
/// Represents a 'v2' user credential tile that implements the functionality of <see cref="CredentialTile"/>, and includes support for personalized tile, where a single user tile is shown, with multiple logon options grouped within it.
/// </summary>
/// <remarks>Inheriting from this class enables you to provide a v2 credential tile. V2 credential tiles were introduced in Windows 8. See the Microsoft documentation on ICredentialProviderCredential2 for more information</remarks>
/// <inheritdoc/>
public abstract partial class CredentialTile2 : CredentialTile
{
/// <summary>
/// Gets the user represented by this credential tile
/// </summary>
public CredentialProviderUser User { get; }
/// <summary>
/// Gets a value indicating if this is a personalized or generic tile
/// </summary>
public override bool IsGenericTile => this.User == null;
/// <summary>
/// Gets or sets a value that controls how the generic tile is displayed to the end user.
/// </summary>
/// <remarks>This does not apply in scenarios where a personalized tile is provided</remarks>
public GenericTileDisplayMode GenericTileDisplayMode { get; set; }
protected CredentialTile2(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
protected CredentialTile2(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider)
{
this.User = user;
}
}
}
@@ -4,16 +4,8 @@ using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider namespace Lithnet.CredentialProvider
{ {
/// <summary> internal abstract partial class CredentialTile3 : ICredentialProviderCredential3
/// Represents a user credential tile that implements the functionality of <see cref="CredentialProviderCredential1Tile"/> and <see cref="CredentialProviderCredential2Tile"/>, but includes support for dynamically updating bitmap images.
/// </summary>
/// <remarks>This interface is public, but undocumented by Microsoft. It is recommended to use <see cref="CredentialProviderCredential2Tile"/> tiles unless this specific functionality is needed</remarks>
public abstract class CredentialProviderCredential3Tile : CredentialProviderCredential2Tile, ICredentialProviderCredential3
{ {
protected CredentialProviderCredential3Tile(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
protected CredentialProviderCredential3Tile(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider, user) { }
int ICredentialProviderCredential3.GetBitmapBufferValue(uint dwFieldID, out uint pImageBufferSize, out IntPtr ppImageBuffer) int ICredentialProviderCredential3.GetBitmapBufferValue(uint dwFieldID, out uint pImageBufferSize, out IntPtr ppImageBuffer)
{ {
this.logger.LogTrace($"Called GetBitmapBufferValue {dwFieldID}"); this.logger.LogTrace($"Called GetBitmapBufferValue {dwFieldID}");
@@ -41,20 +33,16 @@ namespace Lithnet.CredentialProvider
} }
} }
///<inheritdoc cref="ICredentialProviderCredential2.GetUserSid(out string)"/>
int ICredentialProviderCredential3.GetUserSid(out string sid) int ICredentialProviderCredential3.GetUserSid(out string sid)
{ {
return ((ICredentialProviderCredential2)this).GetUserSid(out sid); return ((ICredentialProviderCredential2)this).GetUserSid(out sid);
} }
///<inheritdoc cref="CredentialProviderCredential1Tile"/>
int ICredentialProviderCredential3.SetSelected(out int pbAutoLogon) int ICredentialProviderCredential3.SetSelected(out int pbAutoLogon)
{ {
return ((ICredentialProviderCredential)this).SetSelected(out pbAutoLogon); return ((ICredentialProviderCredential)this).SetSelected(out pbAutoLogon);
} }
///<inheritdoc cref="CredentialProviderCredential1Tile"/>
int ICredentialProviderCredential3.SetDeselected() int ICredentialProviderCredential3.SetDeselected()
{ {
return ((ICredentialProviderCredential)this).SetDeselected(); return ((ICredentialProviderCredential)this).SetDeselected();
@@ -119,14 +107,17 @@ namespace Lithnet.CredentialProvider
{ {
return ((ICredentialProviderCredential)this).GetSerialization(out pcpgsr, out pcpcs, out ppszOptionalStatusText, out pcpsiOptionalStatusIcon); return ((ICredentialProviderCredential)this).GetSerialization(out pcpgsr, out pcpcs, out ppszOptionalStatusText, out pcpsiOptionalStatusIcon);
} }
int ICredentialProviderCredential3.UnAdvise() int ICredentialProviderCredential3.UnAdvise()
{ {
return ((ICredentialProviderCredential)this).UnAdvise(); return ((ICredentialProviderCredential)this).UnAdvise();
} }
int ICredentialProviderCredential3.Advise(ICredentialProviderCredentialEvents pcpce) int ICredentialProviderCredential3.Advise(ICredentialProviderCredentialEvents pcpce)
{ {
return ((ICredentialProviderCredential)this).Advise(pcpce); return ((ICredentialProviderCredential)this).Advise(pcpce);
} }
int ICredentialProviderCredential3.ReportResult(int ntsStatus, int ntsSubstatus, out string ppszOptionalStatusText, out StatusIcon pcpsiOptionalStatusIcon) int ICredentialProviderCredential3.ReportResult(int ntsStatus, int ntsSubstatus, out string ppszOptionalStatusText, out StatusIcon pcpsiOptionalStatusIcon)
{ {
return ((ICredentialProviderCredential)this).ReportResult(ntsStatus, ntsSubstatus, out ppszOptionalStatusText, out pcpsiOptionalStatusIcon); return ((ICredentialProviderCredential)this).ReportResult(ntsStatus, ntsSubstatus, out ppszOptionalStatusText, out pcpsiOptionalStatusIcon);
@@ -0,0 +1,17 @@
using System;
using Lithnet.CredentialProvider.Interop;
using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider
{
/// <summary>
/// Represents a user credential tile that implements the functionality of <see cref="CredentialTile"/> and <see cref="CredentialTile2"/>, but includes support for dynamically updating bitmap images.
/// </summary>
/// <remarks>This interface is public, but undocumented by Microsoft. It is recommended to use <see cref="CredentialTile2"/> tiles unless this specific functionality is needed</remarks>
internal abstract partial class CredentialTile3 : CredentialTile2
{
protected CredentialTile3(CredentialProviderBase credentialProvider) : this(credentialProvider, null) { }
protected CredentialTile3(CredentialProviderBase credentialProvider, CredentialProviderUser user) : base(credentialProvider, user) { }
}
}
@@ -19,8 +19,7 @@ namespace Lithnet.CredentialProvider.Interop
{ {
var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A); var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A);
var pData = this.SerializeKerbLogon(domain, username, password, isWorkstationUnlock ? KerbLogonSubmitType.WorkstationUnlockLogon : KerbLogonSubmitType.InteractiveLogon, out int size); var pData = this.SerializeKerbLogon(domain, username, password, isWorkstationUnlock ? KerbLogonSubmitType.WorkstationUnlockLogon : KerbLogonSubmitType.InteractiveLogon, out int size);
this.logger.LogWarningDebug($"0x{pData.ToString("X16")} - Serializer: Password got packed into ");
this.logger.LogTrace($"0x{pData.ToString("X16")} - Serializer: Password got packed into ");
return new CredentialSerialization() return new CredentialSerialization()
{ {
@@ -35,8 +34,7 @@ namespace Lithnet.CredentialProvider.Interop
{ {
var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A); var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A);
var pData = this.SerializeKerbLogon(domain, username, password, isWorkstationUnlock ? KerbLogonSubmitType.WorkstationUnlockLogon : KerbLogonSubmitType.InteractiveLogon, out int size); var pData = this.SerializeKerbLogon(domain, username, password, isWorkstationUnlock ? KerbLogonSubmitType.WorkstationUnlockLogon : KerbLogonSubmitType.InteractiveLogon, out int size);
this.logger.LogWarningDebug($"0x{pData.ToString("X16")}: Password got packed");
this.logger.LogTrace($"0x{pData.ToString("X16")}: Password got packed");
return new CredentialSerialization() return new CredentialSerialization()
{ {
@@ -131,25 +129,23 @@ namespace Lithnet.CredentialProvider.Interop
try try
{ {
buff = Marshal.SecureStringToCoTaskMemUnicode(password); buff = Marshal.SecureStringToCoTaskMemUnicode(password);
this.logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Unprotected password"); this.logger.LogWarningDebug($"0x{buff.ToString("X16")} - Serializer: Unprotected password");
IntPtr targetPositionToCopyTo = (IntPtr)(buffer + logon->Password.Buffer.ToInt64()); IntPtr targetPositionToCopyTo = (IntPtr)(buffer + logon->Password.Buffer.ToInt64());
Buffer.MemoryCopy(buff.ToPointer(), targetPositionToCopyTo.ToPointer(), logon->Password.Length, password.Length * sizeof(char)); Buffer.MemoryCopy(buff.ToPointer(), targetPositionToCopyTo.ToPointer(), logon->Password.Length, password.Length * sizeof(char));
this.logger.LogTrace($"0x{targetPositionToCopyTo.ToString("X16")} - Serializer: Copied unprotected password into LSA string buffer"); this.logger.LogWarningDebug($"0x{targetPositionToCopyTo.ToString("X16")} - Serializer: Copied unprotected password into LSA string buffer");
} }
finally finally
{ {
if (buff != IntPtr.Zero) if (buff != IntPtr.Zero)
{ {
Marshal.ZeroFreeCoTaskMemUnicode(buff); Marshal.ZeroFreeCoTaskMemUnicode(buff);
this.logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Freed Unprotected password"); this.logger.LogWarningDebug($"0x{buff.ToString("X16")} - Serializer: Freed Unprotected password");
} }
} }
this.logger.LogTrace($"0x{((IntPtr)buffer).ToString("X16")} - Serializer: Put password"); this.logger.LogWarningDebug($"0x{((IntPtr)buffer).ToString("X16")} - Serializer: Put password");
return pBuffer; return pBuffer;
} }
} }
@@ -1,10 +1,18 @@
using System; using System;
using System.Diagnostics;
using System.Security; using System.Security;
using Microsoft.Extensions.Logging;
namespace Lithnet.CredentialProvider.Interop namespace Lithnet.CredentialProvider.Interop
{ {
internal static class InternalExtensions internal static class InternalExtensions
{ {
[Conditional("DEBUG")]
internal static void LogWarningDebug(this ILogger logger, string message)
{
logger.LogWarning(message);
}
internal static unsafe int Wcslen(this IntPtr addr) internal static unsafe int Wcslen(this IntPtr addr)
{ {
const int maxLength = int.MaxValue; const int maxLength = int.MaxValue;
@@ -3,7 +3,6 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading;
namespace Lithnet.CredentialProvider.ModuleInit namespace Lithnet.CredentialProvider.ModuleInit
{ {
@@ -11,7 +10,9 @@ namespace Lithnet.CredentialProvider.ModuleInit
{ {
private static string basePath; private static string basePath;
#pragma warning disable CA2255
[ModuleInitializer] [ModuleInitializer]
#pragma warning restore CA2255
public static void AttachResolver() public static void AttachResolver()
{ {
Trace.WriteLine($"Loaded assembly {Assembly.GetExecutingAssembly().Location}"); Trace.WriteLine($"Loaded assembly {Assembly.GetExecutingAssembly().Location}");
@@ -39,7 +40,7 @@ namespace Lithnet.CredentialProvider.ModuleInit
var name = new AssemblyName(args.Name); var name = new AssemblyName(args.Name);
Trace.WriteLine($"Request for {args.Name}"); Trace.WriteLine($"Request for {args.Name}");
string assyPath = Path.Combine(basePath, $"{name.Name}.dll"); string assyPath = Path.Combine(basePath, $"{name.Name}.dll");
if (File.Exists(assyPath)) if (File.Exists(assyPath))