Cleans up static loggers
Adds test projects for different frameworks and architectures Adds registration tool assembly
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.25" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.CommandLine;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Lithnet.CredentialProvider.RegistrationTool
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
var rootCommand = new RootCommand("Lithnet credential provider registration tool");
|
||||
|
||||
var registerCommand = new Command("--register", "Registers the specified credential provider on this system");
|
||||
registerCommand.AddAlias("-r");
|
||||
var registerArgument = new Argument<FileInfo>("file name", "The name of the file to register");
|
||||
registerCommand.AddArgument(registerArgument);
|
||||
registerCommand.SetHandler((file) => RegisterAssembly(file), registerArgument);
|
||||
rootCommand.Add(registerCommand);
|
||||
|
||||
|
||||
var unregisterCommand = new Command("--unregister", "Unregisters the specified credential provider on this system");
|
||||
unregisterCommand.AddAlias("-u");
|
||||
var unregisterArgument = new Argument<FileInfo>("file name", "The name of the file to register");
|
||||
unregisterCommand.AddArgument(unregisterArgument);
|
||||
unregisterCommand.SetHandler((file) => UnregisterAssembly(file), unregisterArgument);
|
||||
rootCommand.Add(unregisterCommand);
|
||||
|
||||
|
||||
|
||||
var enableCommand = new Command("--enable", "Enables the specified credential provider on this system");
|
||||
enableCommand.AddAlias("-e");
|
||||
var enableFileOption = new Option<FileInfo>("file", "The path to the credential provider to enable");
|
||||
|
||||
var enableGuidOption = new Option<Guid>("providerid", "The GUID of the provider to enable");
|
||||
|
||||
enableCommand.AddOption(enableFileOption);
|
||||
enableCommand.AddOption(enableGuidOption);
|
||||
enableCommand.SetHandler((file) => EnableProviders(file), enableFileOption);
|
||||
enableCommand.SetHandler((id) => EnableProviders(id), enableGuidOption);
|
||||
rootCommand.Add(enableCommand);
|
||||
|
||||
|
||||
//var unregisterOption = new Option<FileInfo>(
|
||||
// name: "--unregister",
|
||||
// description: "Unregisters the specified file as a credential provider on this system");
|
||||
|
||||
//var enableOption = new Option<string>(
|
||||
// name: "--enable",
|
||||
// description: "Enables a credential provider on this system");
|
||||
|
||||
//var disableOption = new Option<string>(
|
||||
// name: "--disable",
|
||||
// description: "Disables a credential provider on this system");
|
||||
|
||||
|
||||
//rootCommand.AddOption(registerOptions);
|
||||
//rootCommand.AddOption(unregisterOption);
|
||||
//rootCommand.AddOption(enableOption);
|
||||
//rootCommand.AddOption(disableOption);
|
||||
|
||||
|
||||
//rootCommand.SetHandler((file) => RegisterAssembly(file), registerOptions);
|
||||
//rootCommand.SetHandler((file) => UnregisterAssembly(file), unregisterOption);
|
||||
//rootCommand.SetHandler((file) => EnableProviders(file), enableOption);
|
||||
//rootCommand.SetHandler((file) => DisableProviders(file), disableOption);
|
||||
|
||||
return await rootCommand.InvokeAsync(args);
|
||||
}
|
||||
|
||||
private static void UnregisterAssembly(FileInfo file)
|
||||
{
|
||||
var assembly = LoadAssembly(file.FullName);
|
||||
|
||||
foreach (var type in GetCredentialProviders(assembly))
|
||||
{
|
||||
CredentialProviderRegistrationServices.UnregisterCredentialProvider(type);
|
||||
Console.WriteLine($"Unregistered credential provider {type.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnableProviders(FileInfo file)
|
||||
{
|
||||
var assembly = LoadAssembly(file.FullName);
|
||||
|
||||
foreach (var type in GetCredentialProviders(assembly))
|
||||
{
|
||||
CredentialProviderRegistrationServices.EnableCredentialProvider(type);
|
||||
Console.WriteLine($"Enabled credential provider {type.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnableProviders(Guid id)
|
||||
{
|
||||
CredentialProviderRegistrationServices.EnableCredentialProvider(id);
|
||||
Console.WriteLine($"Enabled credential provider {id}");
|
||||
}
|
||||
|
||||
private static void DisableProviders(FileInfo file)
|
||||
{
|
||||
var assembly = LoadAssembly(file.FullName);
|
||||
|
||||
foreach (var type in GetCredentialProviders(assembly))
|
||||
{
|
||||
CredentialProviderRegistrationServices.DisableCredentialProvider(type);
|
||||
Console.WriteLine($"Disabled credential provider {type.FullName}");
|
||||
}
|
||||
}
|
||||
private static void DisableProviders(string id)
|
||||
{
|
||||
if (Guid.TryParse(id, out var providerId))
|
||||
{
|
||||
CredentialProviderRegistrationServices.DisableCredentialProvider(providerId);
|
||||
Console.WriteLine($"Disabled credential provider {providerId}");
|
||||
}
|
||||
|
||||
var assembly = LoadAssembly(Path.GetFullPath(id));
|
||||
|
||||
foreach (var type in GetCredentialProviders(assembly))
|
||||
{
|
||||
CredentialProviderRegistrationServices.DisableCredentialProvider(type);
|
||||
Console.WriteLine($"Disabled credential provider {type.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void RegisterAssembly(FileInfo file)
|
||||
{
|
||||
var assembly = LoadAssembly(file.FullName);
|
||||
|
||||
foreach (var type in GetCredentialProviders(assembly))
|
||||
{
|
||||
CredentialProviderRegistrationServices.RegisterCredentialProvider(type);
|
||||
Console.WriteLine($"Registered credential provider {type.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetCredentialProviders(Assembly assembly)
|
||||
{
|
||||
return assembly.GetExportedTypes().Where(t => t.GetInterfaces().Any(ifn => ifn.Name == "ICredentialProvider") && !t.IsAbstract && !t.IsInterface);
|
||||
}
|
||||
|
||||
private static Assembly LoadAssembly(string assemblyPath)
|
||||
{
|
||||
string assemblyBasePath = Path.GetDirectoryName(assemblyPath);
|
||||
|
||||
List<string> paths = new List<string>();
|
||||
paths.AddRange(Directory.GetFiles(Path.GetDirectoryName(assemblyPath)));
|
||||
paths.Add(typeof(object).Assembly.Location);
|
||||
paths.AddRange(Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll"));
|
||||
|
||||
var resolver = new PathAssemblyResolver(paths);
|
||||
MetadataLoadContext mlc = new MetadataLoadContext(resolver);
|
||||
return mlc.LoadFromAssemblyPath(assemblyPath);
|
||||
|
||||
//AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, args) =>
|
||||
//{
|
||||
// var name = new AssemblyName(args.Name);
|
||||
// string assyPath = Path.Combine(assemblyBasePath, $"{name.Name}.dll");
|
||||
// Trace.WriteLine($"Request for {args.Name}");
|
||||
|
||||
// if (File.Exists(assyPath))
|
||||
// {
|
||||
// Trace.WriteLine($"Found at {assyPath}");
|
||||
// return Assembly.ReflectionOnlyLoadFrom(assyPath);
|
||||
// }
|
||||
|
||||
// assyPath = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), $"{name.Name}.dll");
|
||||
|
||||
// if (File.Exists(assyPath))
|
||||
// {
|
||||
// Trace.WriteLine($"Found at {assyPath}");
|
||||
// return Assembly.ReflectionOnlyLoadFrom(assyPath);
|
||||
// }
|
||||
|
||||
// Trace.WriteLine($"Assembly {args.Name} not found");
|
||||
// return null;
|
||||
|
||||
//};
|
||||
|
||||
//var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Lithnet.CredentialProvider.RegistrationTool": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--unregister \"D:\\dev\\git\\ryannewington\\CredProvider.NET\\CredProvider.NET\\bin\\Debug\\CredProvider.NET.dll\""
|
||||
//"commandLineArgs": "--register \"D:\\dev\\git\\lithnet\\windows-credential-provider\\src\\samples\\Lithnet.CredentialProvider.Sample.net6.0.x64\\bin\\Debug\\net6.0-windows\\Lithnet.CredentialProvider.Sample.net6.0.x64.dll\""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 889 B |
@@ -1,99 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("Lithnet.CredentialProvider.Samples.TestCredentialProvider")]
|
||||
[Guid("1A3993B6-EB2B-44BB-A788-7AB1711DFF16")]
|
||||
public class TestCredentialProvider : CredentialProviderBase
|
||||
{
|
||||
private static readonly ILogger logger = Program.LoggerFactory.CreateLogger<TestCredentialProvider>();
|
||||
|
||||
public TestCredentialProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public override ILoggerFactory GetLoggerFactory()
|
||||
{
|
||||
return Program.LoggerFactory;
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
|
||||
var password = new SecurePasswordTextboxControl(TestCredentialProviderControlKeys.Password, "Password");
|
||||
|
||||
if (cpus == UsageScenario.ChangePassword)
|
||||
{
|
||||
var confirmPassword = new SecurePasswordTextboxControl(TestCredentialProviderControlKeys.ConfirmPassword, "Confirm password");
|
||||
yield return new TextboxControl(TestCredentialProviderControlKeys.Username, "Username");
|
||||
yield return password;
|
||||
yield return confirmPassword;
|
||||
yield return new SubmitButtonControl(TestCredentialProviderControlKeys.ButtonSubmit, "Submit", confirmPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new CredentialProviderLabelControl(TestCredentialProviderControlKeys.LabelCredentialProvider, "Login with showcase credential provider");
|
||||
yield return new CredentialProviderLogoControl(TestCredentialProviderControlKeys.ImageCredentialProvider, "Credential provider logo", Resources.TileIcon);
|
||||
yield return new CredentialProviderLogoControl(TestCredentialProviderControlKeys.ImageUserTile, "User tile image", Resources.TileIcon);
|
||||
|
||||
yield return new LargeLabelControl(TestCredentialProviderControlKeys.LabelLargeHeading, "The is our showcase credential provider");
|
||||
yield return new SmallLabelControl(TestCredentialProviderControlKeys.LabelSmallHeading, "Let's see what we can do");
|
||||
|
||||
yield return new CheckboxControl(TestCredentialProviderControlKeys.Checkbox, "A checkbox");
|
||||
yield return new SmallLabelControl(TestCredentialProviderControlKeys.LabelCheckboxValue, "The check box is currently unchecked");
|
||||
yield return new CommandLinkControl(TestCredentialProviderControlKeys.CommandLinkCheckboxValue, "Click this link to change the check box value in code behind");
|
||||
|
||||
yield return new ComboboxControl(TestCredentialProviderControlKeys.Combobox, "Items to choose from:");
|
||||
yield return new SmallLabelControl(TestCredentialProviderControlKeys.LabelComboboxSelectedItem, "This is the currently selected item: <none>");
|
||||
yield return new CommandLinkControl(TestCredentialProviderControlKeys.CommandLinkComboboxAdd, "Add a random item to the combo box");
|
||||
yield return new CommandLinkControl(TestCredentialProviderControlKeys.CommandLinkComboboxRemove, "Remove the last item from the combo box");
|
||||
|
||||
yield return new TextboxControl(TestCredentialProviderControlKeys.Username, "Username");
|
||||
yield return new CommandLinkControl(TestCredentialProviderControlKeys.CommandLinkUsername, "Click this link to generate a random username");
|
||||
|
||||
yield return password;
|
||||
yield return new SubmitButtonControl(TestCredentialProviderControlKeys.ButtonSubmit, "Submit", password);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUsageScenarioSupported(UsageScenario cpus, CredUIWinFlags dwFlags)
|
||||
{
|
||||
switch (cpus)
|
||||
{
|
||||
case UsageScenario.Logon:
|
||||
case UsageScenario.UnlockWorkstation:
|
||||
case UsageScenario.CredUI:
|
||||
case UsageScenario.ChangePassword:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeGenericTile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateGenericTile()
|
||||
{
|
||||
return new TestCredentialProviderTile(this);
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return new TestCredentialProviderTile(this, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,25 @@ VisualStudioVersion = 17.4.33205.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider", "Lithnet.CredentialProvider\Lithnet.CredentialProvider.csproj", "{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.Samples", "Lithnet.CredentialProvider.Samples\Lithnet.CredentialProvider.Samples.csproj", "{967DF0EB-F85A-4006-A3BF-0C558753A9DC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9E97082E-4E8D-4E8B-A320-40E2A1494C74}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.Sample.net6.0.x64", "samples\Lithnet.CredentialProvider.Sample.net6.0.x64\Lithnet.CredentialProvider.Sample.net6.0.x64.csproj", "{163E16D0-9FF3-40D3-AE96-3F221C922AA3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.Sample.net6.0.x86", "samples\Lithnet.CredentialProvider.Sample.net6.0.x86\Lithnet.CredentialProvider.Sample.net6.0.x86.csproj", "{7A8A10F9-7D79-4755-BBDD-77C80FDC58ED}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.Sample.net472.x64", "samples\Lithnet.CredentialProvider.Sample.net472.x64\Lithnet.CredentialProvider.Sample.net472.x64.csproj", "{F60AC10A-337C-46D9-A2DE-1ED48B4AB301}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.Sample.net472.x86", "samples\Lithnet.CredentialProvider.Sample.net472.x86\Lithnet.CredentialProvider.Sample.net472.x86.csproj", "{57F2780E-58F1-4A7B-BCB4-A218733273EA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.TestApp.x64", "samples\Lithnet.CredentialProvider.TestApp.x64\Lithnet.CredentialProvider.TestApp.x64.csproj", "{5019CCEB-AD78-4688-8C11-89A85C4289CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider.TestApp.x86", "samples\Lithnet.CredentialProvider.TestApp.x86\Lithnet.CredentialProvider.TestApp.x86.csproj", "{F39C84F2-60C2-45EB-BC87-0ED095D41C96}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lithnet.CredentialProvider.RegistrationTool", "Lithnet.CredentialProvider.RegistrationTool\Lithnet.CredentialProvider.RegistrationTool.csproj", "{6A9A22A9-A2BB-4329-A0A5-2539E464CE5F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -22,10 +34,34 @@ Global
|
||||
{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7A8A10F9-7D79-4755-BBDD-77C80FDC58ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7A8A10F9-7D79-4755-BBDD-77C80FDC58ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7A8A10F9-7D79-4755-BBDD-77C80FDC58ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7A8A10F9-7D79-4755-BBDD-77C80FDC58ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F60AC10A-337C-46D9-A2DE-1ED48B4AB301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F60AC10A-337C-46D9-A2DE-1ED48B4AB301}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F60AC10A-337C-46D9-A2DE-1ED48B4AB301}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F60AC10A-337C-46D9-A2DE-1ED48B4AB301}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{57F2780E-58F1-4A7B-BCB4-A218733273EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{57F2780E-58F1-4A7B-BCB4-A218733273EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{57F2780E-58F1-4A7B-BCB4-A218733273EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{57F2780E-58F1-4A7B-BCB4-A218733273EA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5019CCEB-AD78-4688-8C11-89A85C4289CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5019CCEB-AD78-4688-8C11-89A85C4289CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5019CCEB-AD78-4688-8C11-89A85C4289CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5019CCEB-AD78-4688-8C11-89A85C4289CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F39C84F2-60C2-45EB-BC87-0ED095D41C96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A9A22A9-A2BB-4329-A0A5-2539E464CE5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A9A22A9-A2BB-4329-A0A5-2539E464CE5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A9A22A9-A2BB-4329-A0A5-2539E464CE5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A9A22A9-A2BB-4329-A0A5-2539E464CE5F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Lithnet.CredentialProvider
|
||||
this.Key = source.Key;
|
||||
this.Type = source.Type;
|
||||
this.FieldTypeGuid = source.FieldTypeGuid;
|
||||
|
||||
this.logger = source.logger;
|
||||
this.state = source.State;
|
||||
this.interactiveState = source.InteractiveState;
|
||||
this.label = source.Label;
|
||||
@@ -54,7 +54,6 @@ namespace Lithnet.CredentialProvider
|
||||
this.options = FieldOptions.None;
|
||||
|
||||
this.Key = key;
|
||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger(this.GetType());
|
||||
}
|
||||
|
||||
internal void AssignCredential(ICredentialProviderCredential credential)
|
||||
@@ -76,6 +75,11 @@ namespace Lithnet.CredentialProvider
|
||||
|
||||
internal ICredentialProviderCredential Credential { get; private set; }
|
||||
|
||||
internal void SetLogger(ILoggerFactory loggerFactory)
|
||||
{
|
||||
this.logger = loggerFactory.CreateLogger(this.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique ID associated with this control
|
||||
/// </summary>
|
||||
|
||||
@@ -13,11 +13,7 @@ namespace Lithnet.CredentialProvider
|
||||
/// </summary>
|
||||
public abstract partial class CredentialProviderBase
|
||||
{
|
||||
internal static ILoggerFactory LoggerFactory { get; set; } = NullLoggerFactory.Instance;
|
||||
|
||||
private readonly ILogger logger;
|
||||
private readonly ILoggerFactory loggerFactory;
|
||||
|
||||
private ICredentialProviderEvents CredentialProviderEvents;
|
||||
private ICredentialProviderUserArray credentialProviderUsers;
|
||||
|
||||
@@ -25,6 +21,8 @@ namespace Lithnet.CredentialProvider
|
||||
private bool notifyOnTileCollectionChange;
|
||||
private List<CredentialProviderCredential1Tile> tiles;
|
||||
|
||||
internal ILoggerFactory LoggerFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GUID of the credential provider
|
||||
/// </summary>
|
||||
@@ -57,14 +55,10 @@ namespace Lithnet.CredentialProvider
|
||||
|
||||
protected CredentialProviderBase()
|
||||
{
|
||||
this.loggerFactory = this.GetLoggerFactory();
|
||||
this.LoggerFactory = this.GetLoggerFactory();
|
||||
|
||||
if (CredentialProviderBase.LoggerFactory != this.loggerFactory)
|
||||
{
|
||||
CredentialProviderBase.LoggerFactory = this.loggerFactory;
|
||||
}
|
||||
|
||||
this.logger = this.loggerFactory.CreateLogger(this.GetType());
|
||||
this.logger = this.LoggerFactory.CreateLogger(this.GetType());
|
||||
var guidAttribute = (GuidAttribute)(this.GetType().GetCustomAttribute(typeof(GuidAttribute)));
|
||||
|
||||
if (guidAttribute == null)
|
||||
@@ -79,7 +73,7 @@ namespace Lithnet.CredentialProvider
|
||||
/// Gets a logger factory. Override this method and provide an implementation of <c ref="ILoggerFactory"/> to enable credential provider logging
|
||||
/// </summary>
|
||||
/// <returns>An ILoggerFactory instance</returns>
|
||||
public virtual ILoggerFactory GetLoggerFactory() { return NullLoggerFactory.Instance; }
|
||||
protected virtual ILoggerFactory GetLoggerFactory() { return NullLoggerFactory.Instance; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if the credential provider supports the <c ref="UsageScenario"/> provided by LogonUI or CredUI
|
||||
@@ -175,6 +169,7 @@ namespace Lithnet.CredentialProvider
|
||||
|
||||
foreach (var control in this.GetControls(this.UsageScenario))
|
||||
{
|
||||
control.SetLogger(this.LoggerFactory);
|
||||
this.Controls.Add(control);
|
||||
}
|
||||
|
||||
@@ -205,7 +200,7 @@ namespace Lithnet.CredentialProvider
|
||||
|
||||
this.logger.LogTrace($"Got supplied user {i}: with name {user.GetQualifiedUserName()} and SID {sid}");
|
||||
|
||||
var credentialProviderUser = new CredentialProviderUser(user);
|
||||
var credentialProviderUser = new CredentialProviderUser(this.LoggerFactory, user);
|
||||
users.Add(credentialProviderUser);
|
||||
|
||||
if (this.ShouldIncludeUserTile(credentialProviderUser))
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Lithnet.CredentialProvider
|
||||
public abstract partial class CredentialProviderCredential1Tile
|
||||
{
|
||||
private protected readonly ILogger logger;
|
||||
|
||||
private protected ICredentialProviderCredentialEvents events;
|
||||
private protected ICredentialProviderCredentialEvents2 events2;
|
||||
|
||||
@@ -21,7 +20,7 @@ namespace Lithnet.CredentialProvider
|
||||
protected CredentialProviderCredential1Tile(CredentialProviderBase credentialProvider)
|
||||
{
|
||||
this.CredentialProvider = credentialProvider;
|
||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger(this.GetType());
|
||||
this.logger = credentialProvider.LoggerFactory.CreateLogger(this.GetType());
|
||||
}
|
||||
|
||||
internal CredentialProviderBase CredentialProvider { get; }
|
||||
@@ -206,15 +205,15 @@ namespace Lithnet.CredentialProvider
|
||||
return response;
|
||||
}
|
||||
|
||||
CredentialSerializer.Logger = this.logger;
|
||||
var serializer = new CredentialSerializer(this.CredentialProvider.LoggerFactory);
|
||||
|
||||
if (credentials is CredentialResponseSecure s)
|
||||
{
|
||||
response.SerializedCredentials = CredentialSerializer.GenerateCredentialSerialization(credentials.Domain, credentials.Username, s.Password, this.UsageScenario == UsageScenario.UnlockWorkstation, this.CredentialProvider.CredentialProviderId);
|
||||
response.SerializedCredentials = serializer.GenerateCredentialSerialization(credentials.Domain, credentials.Username, s.Password, this.UsageScenario == UsageScenario.UnlockWorkstation, this.CredentialProvider.CredentialProviderId);
|
||||
}
|
||||
else if (credentials is CredentialResponseInsecure i)
|
||||
{
|
||||
response.SerializedCredentials = CredentialSerializer.GenerateCredentialSerialization(credentials.Domain, credentials.Username, i.Password, this.UsageScenario == UsageScenario.UnlockWorkstation, this.CredentialProvider.CredentialProviderId);
|
||||
response.SerializedCredentials = serializer.GenerateCredentialSerialization(credentials.Domain, credentials.Username, i.Password, this.UsageScenario == UsageScenario.UnlockWorkstation, this.CredentialProvider.CredentialProviderId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Lithnet.CredentialProvider
|
||||
{
|
||||
public static class CredentialProviderRegistrationServices
|
||||
{
|
||||
public static void DisableCredentialProvider<T>() where T : CredentialProviderBase => DisableCredentialProvider(typeof(T));
|
||||
|
||||
public static void UnregisterCredentialProvider<T>() where T : CredentialProviderBase => UnregisterCredentialProvider(typeof(T));
|
||||
|
||||
public static void RegisterCredentialProvider<T>() where T : CredentialProviderBase => RegisterCredentialProvider(typeof(T));
|
||||
|
||||
public static void EnableCredentialProvider<T>() where T : CredentialProviderBase => EnableCredentialProvider(typeof(T));
|
||||
|
||||
public static void UnregisterCredentialProvider(Type type)
|
||||
{
|
||||
DeleteCredentialProviderRegistration(type);
|
||||
|
||||
if (IsFrameworkType(type))
|
||||
{
|
||||
UnregisterFrameworkAssembly(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnregisterNetCoreAssembly(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterCredentialProvider(Type type)
|
||||
{
|
||||
CreateCredentialProviderRegistration(type);
|
||||
|
||||
if (IsFrameworkType(type))
|
||||
{
|
||||
RegisterFrameworkAssembly(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegisterNetCoreAssembly(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisableCredentialProvider(Type type)
|
||||
{
|
||||
var comGuid = GetComGuid(type);
|
||||
DisableCredentialProvider(comGuid);
|
||||
}
|
||||
|
||||
public static void DisableCredentialProvider(Guid comGuid)
|
||||
{
|
||||
var key = Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{comGuid:B}", true);
|
||||
key?.SetValue("Disabled", 1);
|
||||
}
|
||||
|
||||
|
||||
public static void EnableCredentialProvider(Guid comGuid)
|
||||
{
|
||||
var key = Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{comGuid:B}", true);
|
||||
key?.SetValue("Disabled", 0);
|
||||
}
|
||||
|
||||
public static void EnableCredentialProvider(Type type)
|
||||
{
|
||||
var comGuid = GetComGuid(type);
|
||||
EnableCredentialProvider(comGuid);
|
||||
}
|
||||
|
||||
private static void CreateCredentialProviderRegistration(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
var typeName = GetTypeFullName(t);
|
||||
|
||||
var key = Registry.LocalMachine.CreateSubKey($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{comGuid:B}", true);
|
||||
key.SetValue(null, typeName);
|
||||
}
|
||||
|
||||
private static void DeleteCredentialProviderRegistration(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
|
||||
Registry.LocalMachine.DeleteSubKeyTree($@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{comGuid:B}", false);
|
||||
}
|
||||
|
||||
private static void RegisterNetCoreAssembly(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
var typeName = GetTypeFullName(t);
|
||||
var progId = GetComProgId(t);
|
||||
var assemblyLocation = GetTypeAssemblyLocation(t);
|
||||
|
||||
var dir = Path.GetDirectoryName(assemblyLocation);
|
||||
var assemblyFile = Path.GetFileNameWithoutExtension(assemblyLocation);
|
||||
var comHostLocation = Path.Combine(dir, assemblyFile + ".comhost.dll");
|
||||
|
||||
var rootClsid = Registry.LocalMachine.CreateSubKey($@"Software\Classes\CLSID\{comGuid:B}", true);
|
||||
rootClsid.SetValue(null, "CoreCLR COMHost Server");
|
||||
|
||||
var inprocKey = rootClsid.CreateSubKey("InprocServer32", true);
|
||||
inprocKey.SetValue(null, comHostLocation);
|
||||
inprocKey.SetValue("ThreadingModel", "Both");
|
||||
|
||||
var progIdKey = rootClsid.CreateSubKey("ProgId", true);
|
||||
progIdKey.SetValue(null, progId);
|
||||
|
||||
var progIdRoot = Registry.LocalMachine.CreateSubKey($@"Software\Classes\{progId}", true);
|
||||
progIdRoot.SetValue(null, typeName);
|
||||
var progIdSubKey = progIdRoot.CreateSubKey("CLSID");
|
||||
progIdSubKey.SetValue(null, comGuid.ToString("B"));
|
||||
}
|
||||
|
||||
private static void UnregisterNetCoreAssembly(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
var progId = GetComProgId(t);
|
||||
|
||||
Registry.LocalMachine.DeleteSubKeyTree($@"Software\Classes\CLSID\{comGuid:B}", false);
|
||||
Registry.LocalMachine.DeleteSubKeyTree($@"Software\Classes\{progId}", false);
|
||||
}
|
||||
|
||||
private static void RegisterFrameworkAssembly(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
var typeName = GetTypeFullName(t);
|
||||
var progId = GetComProgId(t);
|
||||
|
||||
var rootClsid = Registry.LocalMachine.CreateSubKey($@"Software\Classes\CLSID\{comGuid:B}", true);
|
||||
rootClsid.SetValue(null, typeName);
|
||||
|
||||
rootClsid.CreateSubKey("Implemented Categories");
|
||||
rootClsid.CreateSubKey(@"Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}");
|
||||
|
||||
var inprocKey = rootClsid.CreateSubKey("InprocServer32", true);
|
||||
inprocKey.SetValue(null, "mscoree.dll");
|
||||
inprocKey.SetValue("ThreadingModel", "Both");
|
||||
inprocKey.SetValue("Class", typeName);
|
||||
inprocKey.SetValue("RuntimeVersion", "v4.0.30319");
|
||||
inprocKey.SetValue("Assembly", GetTypeAssemblyName(t));
|
||||
inprocKey.SetValue("CodeBase", GetTypeAssemblyLocation(t));
|
||||
|
||||
var progIdKey = rootClsid.CreateSubKey("ProgId", true);
|
||||
progIdKey.SetValue(null, progId);
|
||||
|
||||
var progIdRoot = Registry.LocalMachine.CreateSubKey($@"Software\Classes\{progId}", true);
|
||||
progIdRoot.SetValue(null, typeName);
|
||||
var progIdSubKey = progIdRoot.CreateSubKey("CLSID");
|
||||
progIdSubKey.SetValue(null, comGuid.ToString("B"));
|
||||
}
|
||||
|
||||
private static void UnregisterFrameworkAssembly(Type t)
|
||||
{
|
||||
var comGuid = GetComGuid(t);
|
||||
var progId = GetComProgId(t);
|
||||
|
||||
Registry.LocalMachine.DeleteSubKeyTree($@"Software\Classes\CLSID\{comGuid:B}", false);
|
||||
Registry.LocalMachine.DeleteSubKeyTree($@"Software\Classes\{progId}", false);
|
||||
}
|
||||
|
||||
private static string GetTypeAssemblyLocation(Type type)
|
||||
{
|
||||
return type.Assembly.Location;
|
||||
}
|
||||
|
||||
private static string GetTypeAssemblyName(Type type)
|
||||
{
|
||||
return type.Assembly.FullName;
|
||||
}
|
||||
|
||||
private static string GetTypeClassName(Type type)
|
||||
{
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
private static string GetTypeFullName(Type type)
|
||||
{
|
||||
return type.FullName;
|
||||
}
|
||||
|
||||
private static Guid GetComGuid(Type type)
|
||||
{
|
||||
var typeId = type.GetCustomAttributeValue("GuidAttribute");
|
||||
|
||||
if (typeId == null)
|
||||
{
|
||||
throw new ArgumentException($"The type {type.Name} does not have the Guid attribute present");
|
||||
}
|
||||
|
||||
return new Guid(typeId);
|
||||
}
|
||||
|
||||
private static string GetComProgId(Type type)
|
||||
{
|
||||
var typeId = type.GetCustomAttributeValue("ProgIdAttribute");
|
||||
|
||||
if (typeId == null)
|
||||
{
|
||||
throw new ArgumentException($"The type {type.Name} does not have the ProgId attribute present");
|
||||
}
|
||||
|
||||
return typeId;
|
||||
}
|
||||
|
||||
private static bool IsFrameworkType(Type type)
|
||||
{
|
||||
var framework = type.Assembly.GetCustomAttributeValue("TargetFrameworkAttribute");
|
||||
return framework.StartsWith(".NETFramework");
|
||||
}
|
||||
|
||||
private static string GetCustomAttributeValue(this Type type, string attributeName)
|
||||
{
|
||||
var cads = type.GetCustomAttributesData();
|
||||
foreach (CustomAttributeData cad in cads.Where(a => a.AttributeType.Name == attributeName))
|
||||
{
|
||||
return cad.ConstructorArguments.FirstOrDefault().Value as string;
|
||||
}
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
private static string GetCustomAttributeValue(this Assembly assembly, string attributeName)
|
||||
{
|
||||
foreach (CustomAttributeData cad in assembly.GetCustomAttributesData().Where(a => a.AttributeType.Name == attributeName))
|
||||
{
|
||||
return cad.ConstructorArguments.FirstOrDefault().Value as string;
|
||||
}
|
||||
|
||||
return String.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ namespace Lithnet.CredentialProvider
|
||||
private string logonStatus;
|
||||
private string providerId;
|
||||
|
||||
internal CredentialProviderUser(ICredentialProviderUser user)
|
||||
internal CredentialProviderUser(ILoggerFactory loggerFactory, ICredentialProviderUser user)
|
||||
{
|
||||
this.User = user;
|
||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger<CredentialProviderUser>();
|
||||
this.logger = loggerFactory.CreateLogger<CredentialProviderUser>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,20 +3,24 @@ using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Interop
|
||||
{
|
||||
internal static class CredentialSerializer
|
||||
internal class CredentialSerializer
|
||||
{
|
||||
internal static ILogger Logger { get; set; } = NullLogger.Instance;
|
||||
private readonly ILogger logger;
|
||||
|
||||
public static CredentialSerialization GenerateCredentialSerialization(string domain, string username, SecureString password, bool isWorkstationUnlock, Guid providerId)
|
||||
public CredentialSerializer(ILoggerFactory loggerFactory)
|
||||
{
|
||||
this.logger = loggerFactory.CreateLogger<CredentialSerializer>();
|
||||
}
|
||||
|
||||
public CredentialSerialization GenerateCredentialSerialization(string domain, string username, SecureString password, bool isWorkstationUnlock, Guid providerId)
|
||||
{
|
||||
var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A);
|
||||
var pData = 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);
|
||||
|
||||
Logger.LogTrace($"0x{pData.ToString("X16")} - Serializer: Password got packed into ");
|
||||
this.logger.LogTrace($"0x{pData.ToString("X16")} - Serializer: Password got packed into ");
|
||||
|
||||
return new CredentialSerialization()
|
||||
{
|
||||
@@ -27,12 +31,12 @@ namespace Lithnet.CredentialProvider.Interop
|
||||
};
|
||||
}
|
||||
|
||||
public static CredentialSerialization GenerateCredentialSerialization(string domain, string username, string password, bool isWorkstationUnlock, Guid providerId)
|
||||
public CredentialSerialization GenerateCredentialSerialization(string domain, string username, string password, bool isWorkstationUnlock, Guid providerId)
|
||||
{
|
||||
var authPackage = PInvoke.LookupAuthenticationPackage(CredProviderConstants.NEGOSSP_NAME_A);
|
||||
var pData = 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);
|
||||
|
||||
Logger.LogTrace($"0x{pData.ToString("X16")}: Password got packed");
|
||||
this.logger.LogTrace($"0x{pData.ToString("X16")}: Password got packed");
|
||||
|
||||
return new CredentialSerialization()
|
||||
{
|
||||
@@ -43,7 +47,7 @@ namespace Lithnet.CredentialProvider.Interop
|
||||
};
|
||||
}
|
||||
|
||||
private static unsafe IntPtr SerializeKerbLogon(string domain, string username, string password, KerbLogonSubmitType type, out int size)
|
||||
private unsafe IntPtr SerializeKerbLogon(string domain, string username, string password, KerbLogonSubmitType type, out int size)
|
||||
{
|
||||
size = sizeof(KerberosInteractiveUnlockLogon) +
|
||||
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
||||
@@ -86,7 +90,7 @@ namespace Lithnet.CredentialProvider.Interop
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
private static unsafe IntPtr SerializeKerbLogon(string domain, string username, SecureString password, KerbLogonSubmitType type, out int size)
|
||||
private unsafe IntPtr SerializeKerbLogon(string domain, string username, SecureString password, KerbLogonSubmitType type, out int size)
|
||||
{
|
||||
size = sizeof(KerberosInteractiveUnlockLogon) +
|
||||
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
||||
@@ -127,24 +131,24 @@ namespace Lithnet.CredentialProvider.Interop
|
||||
try
|
||||
{
|
||||
buff = Marshal.SecureStringToCoTaskMemUnicode(password);
|
||||
Logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Unprotected password");
|
||||
this.logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Unprotected password");
|
||||
|
||||
IntPtr targetPositionToCopyTo = (IntPtr)(buffer + logon->Password.Buffer.ToInt64());
|
||||
|
||||
Buffer.MemoryCopy(buff.ToPointer(), targetPositionToCopyTo.ToPointer(), logon->Password.Length, password.Length * sizeof(char));
|
||||
|
||||
Logger.LogTrace($"0x{targetPositionToCopyTo.ToString("X16")} - Serializer: Copied unprotected password into LSA string buffer");
|
||||
this.logger.LogTrace($"0x{targetPositionToCopyTo.ToString("X16")} - Serializer: Copied unprotected password into LSA string buffer");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buff != IntPtr.Zero)
|
||||
{
|
||||
Marshal.ZeroFreeCoTaskMemUnicode(buff);
|
||||
Logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Freed Unprotected password");
|
||||
this.logger.LogTrace($"0x{buff.ToString("X16")} - Serializer: Freed Unprotected password");
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogTrace($"0x{((IntPtr)buffer).ToString("X16")} - Serializer: Put password");
|
||||
this.logger.LogTrace($"0x{((IntPtr)buffer).ToString("X16")} - Serializer: Put password");
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Interop
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
internal struct FieldDescriptor
|
||||
{
|
||||
public uint FieldID;
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTargets>AnyCPU</PlatformTargets>
|
||||
<Deterministic>true</Deterministic>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<LangVersion>9</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -14,7 +17,7 @@
|
||||
<Copyright>Copyright 2023 Lithnet Pty Ltd</Copyright>
|
||||
<ProductName>Lithnet Windows Credential Provider</ProductName>
|
||||
<VersionPrefix>1.0.0</VersionPrefix>
|
||||
<VersionSuffix>beta.3</VersionSuffix>
|
||||
<VersionSuffix>beta.26</VersionSuffix>
|
||||
<Authors>Lithnet</Authors>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<AutoIncrementPackageRevision>true</AutoIncrementPackageRevision>
|
||||
@@ -23,10 +26,12 @@
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/lithnet/windows-credential-provider</RepositoryUrl>
|
||||
<SupportUrl>https://github.com/lithnet/windows-credential-provider</SupportUrl>
|
||||
<PackageOutputPath>D:\dev\nuget\packages</PackageOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="6.0.0" Condition="$(TargetFramework) == 'netstandard2.0'" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Lithnet.CredentialProvider.ModuleInit
|
||||
{
|
||||
internal static class AssemblyResolver
|
||||
{
|
||||
private static string basePath;
|
||||
|
||||
[ModuleInitializer]
|
||||
public static void AttachResolver()
|
||||
{
|
||||
Trace.WriteLine("Attaching assembly resolver");
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
basePath = Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
|
||||
}
|
||||
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
var name = new AssemblyName(args.Name);
|
||||
string assyPath = Path.Combine(basePath, $"{name.Name}.dll");
|
||||
Trace.WriteLine($"Request for {args.Name}");
|
||||
|
||||
if (File.Exists(assyPath))
|
||||
{
|
||||
Trace.WriteLine($"Found at {assyPath}");
|
||||
return Assembly.Load(assyPath);
|
||||
}
|
||||
|
||||
Trace.WriteLine($"Assembly {args.Name} not found");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
[AttributeUsage(System.AttributeTargets.Method, Inherited = false)]
|
||||
internal sealed class ModuleInitializerAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
internal static class TestCredentialProviderControlKeys
|
||||
internal static class ControlKeys
|
||||
{
|
||||
internal const string LabelCredentialProvider = "LabelCredentialProvider";
|
||||
internal const string ImageCredentialProvider = "ImageCredentialProvider";
|
||||
@@ -0,0 +1,50 @@
|
||||
# Using the sample credential provider
|
||||
|
||||
## Installing the sample
|
||||
|
||||
In order to install and run the sample app, you have to register the COM component
|
||||
|
||||
Build the EXE, and from an elevated command prompt, change to the bin folder, and run the following commands
|
||||
|
||||
```
|
||||
SETLOCAL
|
||||
SET CLSID={4EB911FA-CA18-40EA-86DF-19AFF5D1DA58}
|
||||
SET BinaryPath=D:\dev\git\lithnet\windows-credential-provider\src\samples\Lithnet.CredentialProvider.Sample.net472.x64\bin\Debug\net472\Lithnet.CredentialProvider.Sample.net472.x64.dll
|
||||
REM %windir%\Microsoft.NET\Framework64\v4.0.30319\regasm /codebase "Lithnet.CredentialProvider.Sample.net472.x64.dll"
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Samples.TestCredentialProvider"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\InprocServer32" /ve /t /REG_SZ /f /d "mscoree.dll"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\InprocServer32" /v "ThreadingModel" /t REG_SZ /f /d "Both"
|
||||
REM REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\InprocServer32" /v "Class" /t REG_SZ /f /d "Both"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\InprocServer32" /v "RuntimeVersion" /t REG_SZ /f /d "v4.0.30319"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\CLSID\%CLSID%\InprocServer32" /v "CodeBase" /t REG_SZ /f /d "%BinaryPath%"
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Classes\Lithnet.CredentialProvider.Sample.net472.x64" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Samples.TestCredentialProvider"
|
||||
REG ADD "HKLM\SOFTWARE\Classes\Lithnet.CredentialProvider.Sample.net472.x64\CLSID" /ve /t REG_SZ /f /d "%CLSID%"
|
||||
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\%CLSID%" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Sample.net472.x64"
|
||||
```
|
||||
|
||||
## Disable the sample
|
||||
|
||||
To disable the credential provider, run the following command.
|
||||
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4eb911fa-ca18-40ea-86df-19aff5d1da58"}" /v "Disabled" /t REG_DWORD /f /d 1
|
||||
```
|
||||
|
||||
## Re-enable the sample
|
||||
To enable the provider again after disabling it, run the following command.
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4eb911fa-ca18-40ea-86df-19aff5d1da58"}" /v "Disabled" /t REG_DWORD /f /d 0
|
||||
```
|
||||
|
||||
## Uninstalling the sample
|
||||
To remove the credential provider, run the following command.
|
||||
|
||||
```
|
||||
%windir%\Microsoft.NET\Framework64\v4.0.30319\regasm /u "Lithnet.CredentialProvider.Sample.net472.x64.dll"
|
||||
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4eb911fa-ca18-40ea-86df-19aff5d1da58"}" /f
|
||||
```
|
||||
@@ -0,0 +1,36 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog;
|
||||
using NLog.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
internal static class InternalLogger
|
||||
{
|
||||
internal static ILoggerFactory LoggerFactory { get; }
|
||||
|
||||
static InternalLogger()
|
||||
{
|
||||
/*
|
||||
This sample uses NLog to capture trace events from the provider, but you can use any
|
||||
logging system compatible with Microsoft.Extensions.Logging;
|
||||
*/
|
||||
|
||||
var config = new NLog.Config.LoggingConfiguration();
|
||||
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
|
||||
|
||||
/*
|
||||
|
||||
Add file based logging if required
|
||||
|
||||
*/
|
||||
|
||||
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "c:\\file.txt" };
|
||||
config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logfile);
|
||||
|
||||
config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logconsole);
|
||||
|
||||
LogManager.Configuration = config;
|
||||
InternalLogger.LoggerFactory = new NLogLoggerFactory(new NLogLoggerProvider(new NLogProviderOptions() { ReplaceLoggerFactory = true }, LogManager.LogFactory));
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x64</Platform>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.26" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+1
-1
@@ -39,7 +39,7 @@ namespace Lithnet.CredentialProvider.Samples {
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lithnet.CredentialProvider.Samples.Resources", typeof(Resources).Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lithnet.CredentialProvider.Sample.Net472.x64.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
+97
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("Lithnet.CredentialProvider.Sample.net472.x64")]
|
||||
[Guid("4eb911fa-ca18-40ea-86df-19aff5d1da58")]
|
||||
public class TestCredentialProviderNet472x64 : CredentialProviderBase
|
||||
{
|
||||
public static void SelfRegister()
|
||||
{
|
||||
CredentialProviderRegistrationServices.RegisterCredentialProvider<TestCredentialProviderNet472x64>();
|
||||
}
|
||||
|
||||
protected override ILoggerFactory GetLoggerFactory()
|
||||
{
|
||||
return InternalLogger.LoggerFactory;
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
var password = new SecurePasswordTextboxControl(ControlKeys.Password, "Password");
|
||||
|
||||
if (cpus == UsageScenario.ChangePassword)
|
||||
{
|
||||
var confirmPassword = new SecurePasswordTextboxControl(ControlKeys.ConfirmPassword, "Confirm password");
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return password;
|
||||
yield return confirmPassword;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", confirmPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new CredentialProviderLabelControl(ControlKeys.LabelCredentialProvider, "Login with showcase credential provider");
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageCredentialProvider, "Credential provider logo", Resources.TileIcon);
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageUserTile, "User tile image", Resources.TileIcon);
|
||||
|
||||
yield return new LargeLabelControl(ControlKeys.LabelLargeHeading, "The is our showcase credential provider");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelSmallHeading, "Let's see what we can do");
|
||||
|
||||
yield return new CheckboxControl(ControlKeys.Checkbox, "A checkbox");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelCheckboxValue, "The check box is currently unchecked");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkCheckboxValue, "Click this link to change the check box value in code behind");
|
||||
|
||||
yield return new ComboboxControl(ControlKeys.Combobox, "Items to choose from:");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelComboboxSelectedItem, "This is the currently selected item: <none>");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxAdd, "Add a random item to the combo box");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxRemove, "Remove the last item from the combo box");
|
||||
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkUsername, "Click this link to generate a random username");
|
||||
|
||||
yield return password;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", password);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUsageScenarioSupported(UsageScenario cpus, CredUIWinFlags dwFlags)
|
||||
{
|
||||
switch (cpus)
|
||||
{
|
||||
case UsageScenario.Logon:
|
||||
case UsageScenario.UnlockWorkstation:
|
||||
case UsageScenario.CredUI:
|
||||
case UsageScenario.ChangePassword:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeGenericTile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateGenericTile()
|
||||
{
|
||||
return new TestCredentialProviderTile(this);
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return new TestCredentialProviderTile(this, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -15,7 +15,7 @@ namespace Lithnet.CredentialProvider.Samples
|
||||
private SmallLabelControl CheckboxStateControl;
|
||||
private SmallLabelControl ComboboxStateControl;
|
||||
|
||||
private ILogger logger = Program.LoggerFactory.CreateLogger<TestCredentialProviderTile>();
|
||||
private ILogger logger = InternalLogger.LoggerFactory.CreateLogger<TestCredentialProviderTile>();
|
||||
|
||||
public TestCredentialProviderTile(CredentialProviderBase credentialProvider) : base(credentialProvider)
|
||||
{
|
||||
@@ -65,29 +65,29 @@ namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
if (UsageScenario == UsageScenario.ChangePassword)
|
||||
{
|
||||
PasswordConfirmControl = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.ConfirmPassword);
|
||||
PasswordConfirmControl = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.ConfirmPassword);
|
||||
}
|
||||
|
||||
PasswordControl = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.Password);
|
||||
CheckboxControl = Controls.GetControl<CheckboxControl>(TestCredentialProviderControlKeys.Checkbox);
|
||||
CheckboxStateControl = Controls.GetControl<SmallLabelControl>(TestCredentialProviderControlKeys.LabelCheckboxValue);
|
||||
PasswordControl = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.Password);
|
||||
CheckboxControl = Controls.GetControl<CheckboxControl>(ControlKeys.Checkbox);
|
||||
CheckboxStateControl = Controls.GetControl<SmallLabelControl>(ControlKeys.LabelCheckboxValue);
|
||||
|
||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkCheckboxValue).OnClick = () =>
|
||||
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkCheckboxValue).OnClick = () =>
|
||||
{
|
||||
CheckboxControl.IsChecked = !CheckboxControl.IsChecked;
|
||||
};
|
||||
|
||||
CheckboxControl.PropertyChanged += CheckboxControl_PropertyChanged;
|
||||
|
||||
UsernameControl = Controls.GetControl<TextboxControl>(TestCredentialProviderControlKeys.Username);
|
||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkUsername).OnClick = () =>
|
||||
UsernameControl = Controls.GetControl<TextboxControl>(ControlKeys.Username);
|
||||
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkUsername).OnClick = () =>
|
||||
{
|
||||
Username = Guid.NewGuid().ToString();
|
||||
};
|
||||
|
||||
ComboboxStateControl = Controls.GetControl<SmallLabelControl>(TestCredentialProviderControlKeys.LabelComboboxSelectedItem);
|
||||
ComboboxStateControl = Controls.GetControl<SmallLabelControl>(ControlKeys.LabelComboboxSelectedItem);
|
||||
|
||||
ComboboxControl = Controls.GetControl<ComboboxControl>(TestCredentialProviderControlKeys.Combobox);
|
||||
ComboboxControl = Controls.GetControl<ComboboxControl>(ControlKeys.Combobox);
|
||||
ComboboxControl.PropertyChanged += ComboboxControl_PropertyChanged;
|
||||
ComboboxControl.ComboBoxItems.Add("Item 1");
|
||||
ComboboxControl.ComboBoxItems.Add("Item 2");
|
||||
@@ -95,12 +95,12 @@ namespace Lithnet.CredentialProvider.Samples
|
||||
ComboboxControl.SelectedItemIndex = 0;
|
||||
|
||||
int count = 3;
|
||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkComboboxAdd).OnClick = () =>
|
||||
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkComboboxAdd).OnClick = () =>
|
||||
{
|
||||
ComboboxControl.ComboBoxItems.Add($"Item {++count}");
|
||||
};
|
||||
|
||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkComboboxRemove).OnClick = () =>
|
||||
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkComboboxRemove).OnClick = () =>
|
||||
{
|
||||
if (ComboboxControl.ComboBoxItems.Count > 0)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ namespace Lithnet.CredentialProvider.Samples
|
||||
domain = Environment.MachineName;
|
||||
}
|
||||
|
||||
var spassword = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.Password).Password;
|
||||
var spassword = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.Password).Password;
|
||||
|
||||
if (!IsChecked)
|
||||
{
|
||||
+7
-7
@@ -7,10 +7,10 @@ In order to install and run the sample app, you have to register the COM compone
|
||||
Build the EXE, and from an elevated command prompt, change to the bin folder, and run the following commands
|
||||
|
||||
```
|
||||
%windir%\Microsoft.NET\Framework64\v4.0.30319\regasm /codebase "Lithnet.CredentialProvider.Samples.exe"
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\regasm /codebase "Lithnet.CredentialProvider.Sample.net472.x86.dll"
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /f
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Samples.TestCredentialProvider"
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /f
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Sample.net472.x86"
|
||||
```
|
||||
|
||||
## Disable the sample
|
||||
@@ -18,19 +18,19 @@ REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credentia
|
||||
To disable the credential provider, run the following command.
|
||||
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /v "Disabled" /t REG_DWORD /f /d 1
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /v "Disabled" /t REG_DWORD /f /d 1
|
||||
```
|
||||
|
||||
## Re-enable the sample
|
||||
To enable the provider again after disabling it, run the following command.
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /v "Disabled" /t REG_DWORD /f /d 0
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /v "Disabled" /t REG_DWORD /f /d 0
|
||||
```
|
||||
|
||||
## Uninstalling the sample
|
||||
To remove the credential provider, run the following command.
|
||||
|
||||
```
|
||||
%windir%\Microsoft.NET\Framework64\v4.0.30319\regasm /u "Lithnet.CredentialProvider.Samples.exe"
|
||||
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /f
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\regasm /u "Lithnet.CredentialProvider.Sample.net472.x86.dll"
|
||||
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /f
|
||||
```
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x86</Platform>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\InternalLogger.cs" Link="InternalLogger.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\ControlKeys.cs" Link="ControlKeys.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\TestCredentialProviderTile.cs" Link="TestCredentialProviderTile.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.25" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Lithnet.CredentialProvider.Sample.Net472.x64.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap TileIcon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("TileIcon", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="TileIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\TileIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
+100
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("Lithnet.CredentialProvider.Sample.net472.x86")]
|
||||
[Guid("c9055c88-03f9-4a12-8e33-1ee75826a4a6")]
|
||||
public class TestCredentialProviderNet472x86 : CredentialProviderBase
|
||||
{
|
||||
private static readonly ILogger logger = InternalLogger.LoggerFactory.CreateLogger<TestCredentialProviderNet472x86>();
|
||||
|
||||
public static void SelfRegister()
|
||||
{
|
||||
CredentialProviderRegistrationServices.RegisterCredentialProvider<TestCredentialProviderNet472x86>();
|
||||
}
|
||||
|
||||
protected override ILoggerFactory GetLoggerFactory()
|
||||
{
|
||||
return InternalLogger.LoggerFactory;
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
|
||||
var password = new SecurePasswordTextboxControl(ControlKeys.Password, "Password");
|
||||
|
||||
if (cpus == UsageScenario.ChangePassword)
|
||||
{
|
||||
var confirmPassword = new SecurePasswordTextboxControl(ControlKeys.ConfirmPassword, "Confirm password");
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return password;
|
||||
yield return confirmPassword;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", confirmPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new CredentialProviderLabelControl(ControlKeys.LabelCredentialProvider, "Login with showcase credential provider");
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageCredentialProvider, "Credential provider logo", Resources.TileIcon);
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageUserTile, "User tile image", Resources.TileIcon);
|
||||
|
||||
yield return new LargeLabelControl(ControlKeys.LabelLargeHeading, "The is our showcase credential provider");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelSmallHeading, "Let's see what we can do");
|
||||
|
||||
yield return new CheckboxControl(ControlKeys.Checkbox, "A checkbox");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelCheckboxValue, "The check box is currently unchecked");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkCheckboxValue, "Click this link to change the check box value in code behind");
|
||||
|
||||
yield return new ComboboxControl(ControlKeys.Combobox, "Items to choose from:");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelComboboxSelectedItem, "This is the currently selected item: <none>");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxAdd, "Add a random item to the combo box");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxRemove, "Remove the last item from the combo box");
|
||||
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkUsername, "Click this link to generate a random username");
|
||||
|
||||
yield return password;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", password);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUsageScenarioSupported(UsageScenario cpus, CredUIWinFlags dwFlags)
|
||||
{
|
||||
switch (cpus)
|
||||
{
|
||||
case UsageScenario.Logon:
|
||||
case UsageScenario.UnlockWorkstation:
|
||||
case UsageScenario.CredUI:
|
||||
case UsageScenario.ChangePassword:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeGenericTile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateGenericTile()
|
||||
{
|
||||
return new TestCredentialProviderTile(this);
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return new TestCredentialProviderTile(this, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Using the sample credential provider
|
||||
|
||||
## Installing the sample
|
||||
|
||||
In order to install and run the sample app, you have to register the COM component
|
||||
|
||||
Build the EXE, and from an elevated command prompt, change to the bin folder, and run the following commands
|
||||
|
||||
```
|
||||
regsvr32 "Lithnet.CredentialProvider.Sample.net6.0.x64.comhost.dll"
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4cd12d80-9259-4f38-94dc-1828080ad9ff}" /f
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4cd12d80-9259-4f38-94dc-1828080ad9ff}" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Sample.net6.0.x64"
|
||||
```
|
||||
|
||||
## Disable the sample
|
||||
|
||||
To disable the credential provider, run the following command.
|
||||
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4cd12d80-9259-4f38-94dc-1828080ad9ff}" /v "Disabled" /t REG_DWORD /f /d 1
|
||||
```
|
||||
|
||||
## Re-enable the sample
|
||||
To enable the provider again after disabling it, run the following command.
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4cd12d80-9259-4f38-94dc-1828080ad9ff}" /v "Disabled" /t REG_DWORD /f /d 0
|
||||
```
|
||||
|
||||
## Uninstalling the sample
|
||||
To remove the credential provider, run the following command.
|
||||
|
||||
```
|
||||
regsvr32 /u "Lithnet.CredentialProvider.Sample.net6.0.x64.comhost.dll"
|
||||
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{4cd12d80-9259-4f38-94dc-1828080ad9ff}" /f
|
||||
```
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x64</Platform>
|
||||
<EnableComHosting>true</EnableComHosting>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\TileIcon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\InternalLogger.cs" Link="InternalLogger.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\ControlKeys.cs" Link="ControlKeys.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\TestCredentialProviderTile.cs" Link="TestCredentialProviderTile.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\TileIcon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.25" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
+105
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("Lithnet.CredentialProvider.Sample.net6.0.x64")]
|
||||
[Guid("4cd12d80-9259-4f38-94dc-1828080ad9ff")]
|
||||
public class TestCredentialProviderNet60x64 : CredentialProviderBase
|
||||
{
|
||||
private static readonly ILogger logger = InternalLogger.LoggerFactory.CreateLogger<TestCredentialProviderNet60x64>();
|
||||
|
||||
public static void SelfRegister()
|
||||
{
|
||||
CredentialProviderRegistrationServices.RegisterCredentialProvider<TestCredentialProviderNet60x64>();
|
||||
}
|
||||
|
||||
protected override ILoggerFactory GetLoggerFactory()
|
||||
{
|
||||
return InternalLogger.LoggerFactory;
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
|
||||
var password = new SecurePasswordTextboxControl(ControlKeys.Password, "Password");
|
||||
|
||||
if (cpus == UsageScenario.ChangePassword)
|
||||
{
|
||||
var confirmPassword = new SecurePasswordTextboxControl(ControlKeys.ConfirmPassword, "Confirm password");
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return password;
|
||||
yield return confirmPassword;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", confirmPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new CredentialProviderLabelControl(ControlKeys.LabelCredentialProvider, "Login with showcase credential provider");
|
||||
|
||||
var image = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Lithnet.CredentialProvider.Sample.net6.0.x64.Resources.TileIcon.png"));
|
||||
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageCredentialProvider, "Credential provider logo", image);
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageUserTile, "User tile image", image);
|
||||
|
||||
yield return new LargeLabelControl(ControlKeys.LabelLargeHeading, "The is our showcase credential provider");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelSmallHeading, "Let's see what we can do");
|
||||
|
||||
yield return new CheckboxControl(ControlKeys.Checkbox, "A checkbox");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelCheckboxValue, "The check box is currently unchecked");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkCheckboxValue, "Click this link to change the check box value in code behind");
|
||||
|
||||
yield return new ComboboxControl(ControlKeys.Combobox, "Items to choose from:");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelComboboxSelectedItem, "This is the currently selected item: <none>");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxAdd, "Add a random item to the combo box");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxRemove, "Remove the last item from the combo box");
|
||||
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkUsername, "Click this link to generate a random username");
|
||||
|
||||
yield return password;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", password);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUsageScenarioSupported(UsageScenario cpus, CredUIWinFlags dwFlags)
|
||||
{
|
||||
switch (cpus)
|
||||
{
|
||||
case UsageScenario.Logon:
|
||||
case UsageScenario.UnlockWorkstation:
|
||||
case UsageScenario.CredUI:
|
||||
case UsageScenario.ChangePassword:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeGenericTile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateGenericTile()
|
||||
{
|
||||
return new TestCredentialProviderTile(this);
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return new TestCredentialProviderTile(this, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Using the sample credential provider
|
||||
|
||||
## Installing the sample
|
||||
|
||||
In order to install and run the sample app, you have to register the COM component
|
||||
|
||||
Build the EXE, and from an elevated command prompt, change to the bin folder, and run the following commands
|
||||
|
||||
```
|
||||
regsvr32 "Lithnet.CredentialProvider.Sample.net6.0.x86.comhost.dll"
|
||||
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{90592593-f4d3-4f62-aa83-9cf1f7b590e0}" /f
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{90592593-f4d3-4f62-aa83-9cf1f7b590e0}" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Sample.net6.0.x86"
|
||||
```
|
||||
|
||||
## Disable the sample
|
||||
|
||||
To disable the credential provider, run the following command.
|
||||
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{90592593-f4d3-4f62-aa83-9cf1f7b590e0}" /v "Disabled" /t REG_DWORD /f /d 1
|
||||
```
|
||||
|
||||
## Re-enable the sample
|
||||
To enable the provider again after disabling it, run the following command.
|
||||
```
|
||||
REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{90592593-f4d3-4f62-aa83-9cf1f7b590e0}" /v "Disabled" /t REG_DWORD /f /d 0
|
||||
```
|
||||
|
||||
## Uninstalling the sample
|
||||
To remove the credential provider, run the following command.
|
||||
|
||||
```
|
||||
regsvr32 /u "Lithnet.CredentialProvider.Sample.net6.0.x86.comhost.dll"
|
||||
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{90592593-f4d3-4f62-aa83-9cf1f7b590e0}" /f
|
||||
```
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x86</Platform>
|
||||
<EnableComHosting>true</EnableComHosting>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\TileIcon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\InternalLogger.cs" Link="InternalLogger.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\ControlKeys.cs" Link="ControlKeys.cs" />
|
||||
<Compile Include="..\Lithnet.CredentialProvider.Sample.net472.x64\TestCredentialProviderTile.cs" Link="TestCredentialProviderTile.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\TileIcon.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lithnet.CredentialProvider" Version="1.0.0-beta.25" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
+104
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("Lithnet.CredentialProvider.Sample.net6.0.x86")]
|
||||
[Guid("90592593-f4d3-4f62-aa83-9cf1f7b590e0")]
|
||||
public class TestCredentialProviderNet60x86 : CredentialProviderBase
|
||||
{
|
||||
private static readonly ILogger logger = InternalLogger.LoggerFactory.CreateLogger<TestCredentialProviderNet60x86>();
|
||||
|
||||
public static void SelfRegister()
|
||||
{
|
||||
CredentialProviderRegistrationServices.RegisterCredentialProvider<TestCredentialProviderNet60x86>();
|
||||
}
|
||||
|
||||
protected override ILoggerFactory GetLoggerFactory()
|
||||
{
|
||||
return InternalLogger.LoggerFactory;
|
||||
}
|
||||
|
||||
public override IEnumerable<ControlBase> GetControls(UsageScenario cpus)
|
||||
{
|
||||
|
||||
var password = new SecurePasswordTextboxControl(ControlKeys.Password, "Password");
|
||||
|
||||
if (cpus == UsageScenario.ChangePassword)
|
||||
{
|
||||
var confirmPassword = new SecurePasswordTextboxControl(ControlKeys.ConfirmPassword, "Confirm password");
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return password;
|
||||
yield return confirmPassword;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", confirmPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
var image = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Lithnet.CredentialProvider.Sample.net6.0.x86.Resources.TileIcon.png"));
|
||||
|
||||
yield return new CredentialProviderLabelControl(ControlKeys.LabelCredentialProvider, "Login with showcase credential provider");
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageCredentialProvider, "Credential provider logo", image);
|
||||
yield return new CredentialProviderLogoControl(ControlKeys.ImageUserTile, "User tile image", image);
|
||||
|
||||
yield return new LargeLabelControl(ControlKeys.LabelLargeHeading, "The is our showcase credential provider");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelSmallHeading, "Let's see what we can do");
|
||||
|
||||
yield return new CheckboxControl(ControlKeys.Checkbox, "A checkbox");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelCheckboxValue, "The check box is currently unchecked");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkCheckboxValue, "Click this link to change the check box value in code behind");
|
||||
|
||||
yield return new ComboboxControl(ControlKeys.Combobox, "Items to choose from:");
|
||||
yield return new SmallLabelControl(ControlKeys.LabelComboboxSelectedItem, "This is the currently selected item: <none>");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxAdd, "Add a random item to the combo box");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkComboboxRemove, "Remove the last item from the combo box");
|
||||
|
||||
yield return new TextboxControl(ControlKeys.Username, "Username");
|
||||
yield return new CommandLinkControl(ControlKeys.CommandLinkUsername, "Click this link to generate a random username");
|
||||
|
||||
yield return password;
|
||||
yield return new SubmitButtonControl(ControlKeys.ButtonSubmit, "Submit", password);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUsageScenarioSupported(UsageScenario cpus, CredUIWinFlags dwFlags)
|
||||
{
|
||||
switch (cpus)
|
||||
{
|
||||
case UsageScenario.Logon:
|
||||
case UsageScenario.UnlockWorkstation:
|
||||
case UsageScenario.CredUI:
|
||||
case UsageScenario.ChangePassword:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldIncludeGenericTile()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateGenericTile()
|
||||
{
|
||||
return new TestCredentialProviderTile(this);
|
||||
}
|
||||
|
||||
public override CredentialProviderCredential1Tile CreateUserTile(CredentialProviderUser user)
|
||||
{
|
||||
return new TestCredentialProviderTile(this, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x64</Platform>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
public static class CredUI
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct CREDUI_INFO
|
||||
{
|
||||
public int cbSize;
|
||||
public IntPtr hwndParent;
|
||||
public string pszMessageText;
|
||||
public string pszCaptionText;
|
||||
public IntPtr hbmBanner;
|
||||
}
|
||||
|
||||
[DllImport("credui.dll", CharSet = CharSet.Auto)]
|
||||
public static extern int CredUIPromptForWindowsCredentials(
|
||||
ref CREDUI_INFO uiInfo,
|
||||
int authError,
|
||||
ref uint authPackage,
|
||||
IntPtr InAuthBuffer,
|
||||
uint InAuthBufferSize,
|
||||
out IntPtr refOutAuthBuffer,
|
||||
out uint refOutAuthBufferSize,
|
||||
ref bool fSave,
|
||||
uint flags
|
||||
);
|
||||
|
||||
public static void Prompt(string caption, string message)
|
||||
{
|
||||
var uiInfo = new CREDUI_INFO()
|
||||
{
|
||||
pszCaptionText = caption,
|
||||
pszMessageText = message
|
||||
};
|
||||
|
||||
uiInfo.cbSize = Marshal.SizeOf(uiInfo);
|
||||
|
||||
uint authPackage = 0;
|
||||
|
||||
var save = false;
|
||||
|
||||
CredUIPromptForWindowsCredentials(
|
||||
ref uiInfo,
|
||||
0,
|
||||
ref authPackage,
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
out IntPtr outCredBuffer,
|
||||
out uint outCredSize,
|
||||
ref save,
|
||||
0
|
||||
);
|
||||
|
||||
Marshal.FreeCoTaskMem(outCredBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<Platform>x86</Platform>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.1.1" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog;
|
||||
using NLog.Extensions.Logging;
|
||||
|
||||
namespace Lithnet.CredentialProvider.Samples
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
internal static ILoggerFactory LoggerFactory { get; }
|
||||
|
||||
static Program()
|
||||
{
|
||||
/*
|
||||
This sample uses NLog to capture trace events from the provider, but you can use any
|
||||
logging system compatible with Microsoft.Extensions.Logging;
|
||||
*/
|
||||
|
||||
var config = new NLog.Config.LoggingConfiguration();
|
||||
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
|
||||
|
||||
/*
|
||||
|
||||
Add file based logging if required
|
||||
|
||||
*/
|
||||
|
||||
// var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "c:\\file.txt" };
|
||||
//config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logfile);
|
||||
|
||||
config.AddRule(NLog.LogLevel.Trace, NLog.LogLevel.Fatal, logconsole);
|
||||
|
||||
LogManager.Configuration = config;
|
||||
Program.LoggerFactory = new NLogLoggerFactory(new NLogLoggerProvider(new NLogProviderOptions() { ReplaceLoggerFactory = true }, LogManager.LogFactory));
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
CredUI.Prompt("Login with Cred UI", "Select your favorite credential provider");
|
||||
Console.WriteLine("Done! Press any key to exit");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user