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
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider", "Lithnet.CredentialProvider\Lithnet.CredentialProvider.csproj", "{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lithnet.CredentialProvider", "Lithnet.CredentialProvider\Lithnet.CredentialProvider.csproj", "{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}"
|
||||||
EndProject
|
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}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9E97082E-4E8D-4E8B-A320-40E2A1494C74}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{9C07477C-ABB8-4DE5-B69C-3F8719D952C6}.Release|Any CPU.Build.0 = 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
|
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{967DF0EB-F85A-4006-A3BF-0C558753A9DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{163E16D0-9FF3-40D3-AE96-3F221C922AA3}.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}.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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Lithnet.CredentialProvider
|
|||||||
this.Key = source.Key;
|
this.Key = source.Key;
|
||||||
this.Type = source.Type;
|
this.Type = source.Type;
|
||||||
this.FieldTypeGuid = source.FieldTypeGuid;
|
this.FieldTypeGuid = source.FieldTypeGuid;
|
||||||
|
this.logger = source.logger;
|
||||||
this.state = source.State;
|
this.state = source.State;
|
||||||
this.interactiveState = source.InteractiveState;
|
this.interactiveState = source.InteractiveState;
|
||||||
this.label = source.Label;
|
this.label = source.Label;
|
||||||
@@ -54,7 +54,6 @@ namespace Lithnet.CredentialProvider
|
|||||||
this.options = FieldOptions.None;
|
this.options = FieldOptions.None;
|
||||||
|
|
||||||
this.Key = key;
|
this.Key = key;
|
||||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger(this.GetType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AssignCredential(ICredentialProviderCredential credential)
|
internal void AssignCredential(ICredentialProviderCredential credential)
|
||||||
@@ -76,6 +75,11 @@ namespace Lithnet.CredentialProvider
|
|||||||
|
|
||||||
internal ICredentialProviderCredential Credential { get; private set; }
|
internal ICredentialProviderCredential Credential { get; private set; }
|
||||||
|
|
||||||
|
internal void SetLogger(ILoggerFactory loggerFactory)
|
||||||
|
{
|
||||||
|
this.logger = loggerFactory.CreateLogger(this.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the unique ID associated with this control
|
/// Gets the unique ID associated with this control
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,11 +13,7 @@ namespace Lithnet.CredentialProvider
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class CredentialProviderBase
|
public abstract partial class CredentialProviderBase
|
||||||
{
|
{
|
||||||
internal static ILoggerFactory LoggerFactory { get; set; } = NullLoggerFactory.Instance;
|
|
||||||
|
|
||||||
private readonly ILogger logger;
|
private readonly ILogger logger;
|
||||||
private readonly ILoggerFactory loggerFactory;
|
|
||||||
|
|
||||||
private ICredentialProviderEvents CredentialProviderEvents;
|
private ICredentialProviderEvents CredentialProviderEvents;
|
||||||
private ICredentialProviderUserArray credentialProviderUsers;
|
private ICredentialProviderUserArray credentialProviderUsers;
|
||||||
|
|
||||||
@@ -25,6 +21,8 @@ namespace Lithnet.CredentialProvider
|
|||||||
private bool notifyOnTileCollectionChange;
|
private bool notifyOnTileCollectionChange;
|
||||||
private List<CredentialProviderCredential1Tile> tiles;
|
private List<CredentialProviderCredential1Tile> tiles;
|
||||||
|
|
||||||
|
internal ILoggerFactory LoggerFactory { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the GUID of the credential provider
|
/// Gets the GUID of the credential provider
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -57,14 +55,10 @@ namespace Lithnet.CredentialProvider
|
|||||||
|
|
||||||
protected CredentialProviderBase()
|
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)));
|
var guidAttribute = (GuidAttribute)(this.GetType().GetCustomAttribute(typeof(GuidAttribute)));
|
||||||
|
|
||||||
if (guidAttribute == null)
|
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
|
/// Gets a logger factory. Override this method and provide an implementation of <c ref="ILoggerFactory"/> to enable credential provider logging
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An ILoggerFactory instance</returns>
|
/// <returns>An ILoggerFactory instance</returns>
|
||||||
public virtual ILoggerFactory GetLoggerFactory() { return NullLoggerFactory.Instance; }
|
protected virtual ILoggerFactory GetLoggerFactory() { return NullLoggerFactory.Instance; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating if the credential provider supports the <c ref="UsageScenario"/> provided by LogonUI or CredUI
|
/// 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))
|
foreach (var control in this.GetControls(this.UsageScenario))
|
||||||
{
|
{
|
||||||
|
control.SetLogger(this.LoggerFactory);
|
||||||
this.Controls.Add(control);
|
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}");
|
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);
|
users.Add(credentialProviderUser);
|
||||||
|
|
||||||
if (this.ShouldIncludeUserTile(credentialProviderUser))
|
if (this.ShouldIncludeUserTile(credentialProviderUser))
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ namespace Lithnet.CredentialProvider
|
|||||||
public abstract partial class CredentialProviderCredential1Tile
|
public abstract partial class CredentialProviderCredential1Tile
|
||||||
{
|
{
|
||||||
private protected readonly ILogger logger;
|
private protected readonly ILogger logger;
|
||||||
|
|
||||||
private protected ICredentialProviderCredentialEvents events;
|
private protected ICredentialProviderCredentialEvents events;
|
||||||
private protected ICredentialProviderCredentialEvents2 events2;
|
private protected ICredentialProviderCredentialEvents2 events2;
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ namespace Lithnet.CredentialProvider
|
|||||||
protected CredentialProviderCredential1Tile(CredentialProviderBase credentialProvider)
|
protected CredentialProviderCredential1Tile(CredentialProviderBase credentialProvider)
|
||||||
{
|
{
|
||||||
this.CredentialProvider = credentialProvider;
|
this.CredentialProvider = credentialProvider;
|
||||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger(this.GetType());
|
this.logger = credentialProvider.LoggerFactory.CreateLogger(this.GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CredentialProviderBase CredentialProvider { get; }
|
internal CredentialProviderBase CredentialProvider { get; }
|
||||||
@@ -206,15 +205,15 @@ namespace Lithnet.CredentialProvider
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
CredentialSerializer.Logger = this.logger;
|
var serializer = new CredentialSerializer(this.CredentialProvider.LoggerFactory);
|
||||||
|
|
||||||
if (credentials is CredentialResponseSecure s)
|
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)
|
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
|
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 logonStatus;
|
||||||
private string providerId;
|
private string providerId;
|
||||||
|
|
||||||
internal CredentialProviderUser(ICredentialProviderUser user)
|
internal CredentialProviderUser(ILoggerFactory loggerFactory, ICredentialProviderUser user)
|
||||||
{
|
{
|
||||||
this.User = user;
|
this.User = user;
|
||||||
this.logger = CredentialProviderBase.LoggerFactory.CreateLogger<CredentialProviderUser>();
|
this.logger = loggerFactory.CreateLogger<CredentialProviderUser>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -3,20 +3,24 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
|
|
||||||
namespace Lithnet.CredentialProvider.Interop
|
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 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()
|
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 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()
|
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) +
|
size = sizeof(KerberosInteractiveUnlockLogon) +
|
||||||
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
||||||
@@ -86,7 +90,7 @@ namespace Lithnet.CredentialProvider.Interop
|
|||||||
return pBuffer;
|
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) +
|
size = sizeof(KerberosInteractiveUnlockLogon) +
|
||||||
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
Encoding.Unicode.GetMaxByteCount(domain.Length) +
|
||||||
@@ -127,24 +131,24 @@ namespace Lithnet.CredentialProvider.Interop
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
buff = Marshal.SecureStringToCoTaskMemUnicode(password);
|
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());
|
IntPtr targetPositionToCopyTo = (IntPtr)(buffer + logon->Password.Buffer.ToInt64());
|
||||||
|
|
||||||
Buffer.MemoryCopy(buff.ToPointer(), targetPositionToCopyTo.ToPointer(), logon->Password.Length, password.Length * sizeof(char));
|
Buffer.MemoryCopy(buff.ToPointer(), targetPositionToCopyTo.ToPointer(), logon->Password.Length, password.Length * sizeof(char));
|
||||||
|
|
||||||
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
|
finally
|
||||||
{
|
{
|
||||||
if (buff != IntPtr.Zero)
|
if (buff != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Marshal.ZeroFreeCoTaskMemUnicode(buff);
|
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;
|
return pBuffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Lithnet.CredentialProvider.Interop
|
namespace Lithnet.CredentialProvider.Interop
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||||
internal struct FieldDescriptor
|
internal struct FieldDescriptor
|
||||||
{
|
{
|
||||||
public uint FieldID;
|
public uint FieldID;
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<PlatformTargets>AnyCPU</PlatformTargets>
|
<PlatformTargets>AnyCPU</PlatformTargets>
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@@ -14,7 +17,7 @@
|
|||||||
<Copyright>Copyright 2023 Lithnet Pty Ltd</Copyright>
|
<Copyright>Copyright 2023 Lithnet Pty Ltd</Copyright>
|
||||||
<ProductName>Lithnet Windows Credential Provider</ProductName>
|
<ProductName>Lithnet Windows Credential Provider</ProductName>
|
||||||
<VersionPrefix>1.0.0</VersionPrefix>
|
<VersionPrefix>1.0.0</VersionPrefix>
|
||||||
<VersionSuffix>beta.3</VersionSuffix>
|
<VersionSuffix>beta.26</VersionSuffix>
|
||||||
<Authors>Lithnet</Authors>
|
<Authors>Lithnet</Authors>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<AutoIncrementPackageRevision>true</AutoIncrementPackageRevision>
|
<AutoIncrementPackageRevision>true</AutoIncrementPackageRevision>
|
||||||
@@ -23,10 +26,12 @@
|
|||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<RepositoryUrl>https://github.com/lithnet/windows-credential-provider</RepositoryUrl>
|
<RepositoryUrl>https://github.com/lithnet/windows-credential-provider</RepositoryUrl>
|
||||||
<SupportUrl>https://github.com/lithnet/windows-credential-provider</SupportUrl>
|
<SupportUrl>https://github.com/lithnet/windows-credential-provider</SupportUrl>
|
||||||
|
<PackageOutputPath>D:\dev\nuget\packages</PackageOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
<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'" />
|
<PackageReference Include="System.Drawing.Common" Version="6.0.0" Condition="$(TargetFramework) == 'netstandard2.0'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</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
|
namespace Lithnet.CredentialProvider.Samples
|
||||||
{
|
{
|
||||||
internal static class TestCredentialProviderControlKeys
|
internal static class ControlKeys
|
||||||
{
|
{
|
||||||
internal const string LabelCredentialProvider = "LabelCredentialProvider";
|
internal const string LabelCredentialProvider = "LabelCredentialProvider";
|
||||||
internal const string ImageCredentialProvider = "ImageCredentialProvider";
|
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 {
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
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;
|
resourceMan = temp;
|
||||||
}
|
}
|
||||||
return resourceMan;
|
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 CheckboxStateControl;
|
||||||
private SmallLabelControl ComboboxStateControl;
|
private SmallLabelControl ComboboxStateControl;
|
||||||
|
|
||||||
private ILogger logger = Program.LoggerFactory.CreateLogger<TestCredentialProviderTile>();
|
private ILogger logger = InternalLogger.LoggerFactory.CreateLogger<TestCredentialProviderTile>();
|
||||||
|
|
||||||
public TestCredentialProviderTile(CredentialProviderBase credentialProvider) : base(credentialProvider)
|
public TestCredentialProviderTile(CredentialProviderBase credentialProvider) : base(credentialProvider)
|
||||||
{
|
{
|
||||||
@@ -65,29 +65,29 @@ namespace Lithnet.CredentialProvider.Samples
|
|||||||
{
|
{
|
||||||
if (UsageScenario == UsageScenario.ChangePassword)
|
if (UsageScenario == UsageScenario.ChangePassword)
|
||||||
{
|
{
|
||||||
PasswordConfirmControl = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.ConfirmPassword);
|
PasswordConfirmControl = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.ConfirmPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordControl = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.Password);
|
PasswordControl = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.Password);
|
||||||
CheckboxControl = Controls.GetControl<CheckboxControl>(TestCredentialProviderControlKeys.Checkbox);
|
CheckboxControl = Controls.GetControl<CheckboxControl>(ControlKeys.Checkbox);
|
||||||
CheckboxStateControl = Controls.GetControl<SmallLabelControl>(TestCredentialProviderControlKeys.LabelCheckboxValue);
|
CheckboxStateControl = Controls.GetControl<SmallLabelControl>(ControlKeys.LabelCheckboxValue);
|
||||||
|
|
||||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkCheckboxValue).OnClick = () =>
|
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkCheckboxValue).OnClick = () =>
|
||||||
{
|
{
|
||||||
CheckboxControl.IsChecked = !CheckboxControl.IsChecked;
|
CheckboxControl.IsChecked = !CheckboxControl.IsChecked;
|
||||||
};
|
};
|
||||||
|
|
||||||
CheckboxControl.PropertyChanged += CheckboxControl_PropertyChanged;
|
CheckboxControl.PropertyChanged += CheckboxControl_PropertyChanged;
|
||||||
|
|
||||||
UsernameControl = Controls.GetControl<TextboxControl>(TestCredentialProviderControlKeys.Username);
|
UsernameControl = Controls.GetControl<TextboxControl>(ControlKeys.Username);
|
||||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkUsername).OnClick = () =>
|
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkUsername).OnClick = () =>
|
||||||
{
|
{
|
||||||
Username = Guid.NewGuid().ToString();
|
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.PropertyChanged += ComboboxControl_PropertyChanged;
|
||||||
ComboboxControl.ComboBoxItems.Add("Item 1");
|
ComboboxControl.ComboBoxItems.Add("Item 1");
|
||||||
ComboboxControl.ComboBoxItems.Add("Item 2");
|
ComboboxControl.ComboBoxItems.Add("Item 2");
|
||||||
@@ -95,12 +95,12 @@ namespace Lithnet.CredentialProvider.Samples
|
|||||||
ComboboxControl.SelectedItemIndex = 0;
|
ComboboxControl.SelectedItemIndex = 0;
|
||||||
|
|
||||||
int count = 3;
|
int count = 3;
|
||||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkComboboxAdd).OnClick = () =>
|
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkComboboxAdd).OnClick = () =>
|
||||||
{
|
{
|
||||||
ComboboxControl.ComboBoxItems.Add($"Item {++count}");
|
ComboboxControl.ComboBoxItems.Add($"Item {++count}");
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.GetControl<CommandLinkControl>(TestCredentialProviderControlKeys.CommandLinkComboboxRemove).OnClick = () =>
|
Controls.GetControl<CommandLinkControl>(ControlKeys.CommandLinkComboboxRemove).OnClick = () =>
|
||||||
{
|
{
|
||||||
if (ComboboxControl.ComboBoxItems.Count > 0)
|
if (ComboboxControl.ComboBoxItems.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -140,7 +140,7 @@ namespace Lithnet.CredentialProvider.Samples
|
|||||||
domain = Environment.MachineName;
|
domain = Environment.MachineName;
|
||||||
}
|
}
|
||||||
|
|
||||||
var spassword = Controls.GetControl<SecurePasswordTextboxControl>(TestCredentialProviderControlKeys.Password).Password;
|
var spassword = Controls.GetControl<SecurePasswordTextboxControl>(ControlKeys.Password).Password;
|
||||||
|
|
||||||
if (!IsChecked)
|
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
|
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\{c9055c88-03f9-4a12-8e33-1ee75826a4a6}" /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}" /ve /t REG_SZ /f /d "Lithnet.CredentialProvider.Sample.net472.x86"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Disable the sample
|
## 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.
|
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
|
## Re-enable the sample
|
||||||
To enable the provider again after disabling it, run the following command.
|
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
|
## Uninstalling the sample
|
||||||
To remove the credential provider, run the following command.
|
To remove the credential provider, run the following command.
|
||||||
|
|
||||||
```
|
```
|
||||||
%windir%\Microsoft.NET\Framework64\v4.0.30319\regasm /u "Lithnet.CredentialProvider.Samples.exe"
|
%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\{1A3993B6-EB2B-44BB-A788-7AB1711DFF16}" /f
|
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