diff --git a/Docs/Commands/Reset-YubikeyFIDO2.md b/Docs/Commands/Reset-YubikeyFIDO2.md index d71d9d2..5c1aea4 100644 --- a/Docs/Commands/Reset-YubikeyFIDO2.md +++ b/Docs/Commands/Reset-YubikeyFIDO2.md @@ -1,4 +1,4 @@ ---- +--- external help file: powershellYK.dll-Help.xml Module Name: powershellYK online version: @@ -13,7 +13,7 @@ Reset a Yubikey FIDO2 device to factory settings. ## SYNTAX ``` -Reset-YubikeyFIDO2 [] +Reset-YubikeyFIDO2 [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION @@ -31,6 +31,36 @@ Resets the Yubikey FIDO2 device to factory settings. ## PARAMETERS +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). diff --git a/Docs/Commands/Set-YubikeyFIDO2.md b/Docs/Commands/Set-YubikeyFIDO2.md index 422c21c..5bc98c1 100644 --- a/Docs/Commands/Set-YubikeyFIDO2.md +++ b/Docs/Commands/Set-YubikeyFIDO2.md @@ -1,4 +1,4 @@ ---- +--- external help file: powershellYK.dll-Help.xml Module Name: powershellYK online version: @@ -12,11 +12,6 @@ Allows settings FIDO2 options. ## SYNTAX -### Set new PIN -``` -Set-YubikeyFIDO2 -NewPIN [-SetPIN] [] -``` - ### Set PIN minimum length ``` Set-YubikeyFIDO2 -MinimumPINLength [] @@ -27,8 +22,13 @@ Set-YubikeyFIDO2 -MinimumPINLength [] Set-YubikeyFIDO2 -MinimumPINRelyingParty [] ``` +### Set PIN +``` +Set-YubikeyFIDO2 [-SetPIN] [-OldPIN ] -NewPIN [] +``` + ## DESCRIPTION -{{ Fill in the Description }} +Allows the setting of PIN code and minimum PIN length. ## EXAMPLES @@ -99,7 +99,7 @@ New PIN ```yaml Type: SecureString -Parameter Sets: Set new PIN +Parameter Sets: Set PIN Aliases: Required: True @@ -109,12 +109,27 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -OldPIN +Old PIN, required to change the PIN code. + +```yaml +Type: SecureString +Parameter Sets: Set PIN +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -SetPIN Easy access to Set new PIN ```yaml Type: SwitchParameter -Parameter Sets: Set new PIN +Parameter Sets: Set PIN Aliases: Required: False diff --git a/Module/Cmdlets/Fido/ResetYubikeyFIDO2.cs b/Module/Cmdlets/Fido/ResetYubikeyFIDO2.cs index 35d711e..cab2517 100644 --- a/Module/Cmdlets/Fido/ResetYubikeyFIDO2.cs +++ b/Module/Cmdlets/Fido/ResetYubikeyFIDO2.cs @@ -4,10 +4,11 @@ using powershellYK.FIDO2; using powershellYK.support; using Yubico.YubiKey.Fido2.Commands; +using powershellYK.Exceptions; namespace powershellYK.Cmdlets.Fido { - [Cmdlet(VerbsCommon.Reset, "YubikeyFIDO2")] + [Cmdlet(VerbsCommon.Reset, "YubikeyFIDO2", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)] public class ResetYubikeyFIDO2Cmdlet : Cmdlet { @@ -30,13 +31,29 @@ protected override void BeginProcessing() protected override void ProcessRecord() { - using (var fido2Session = new Fido2Session((YubiKeyDevice)YubiKeyModule._yubikey!)) + if (ShouldProcess("Yubikey FIDO2", "Reset")) { - ResetCommand resetCommand = new Yubico.YubiKey.Fido2.Commands.ResetCommand(); - ResetResponse reply = fido2Session.Connection.SendCommand(resetCommand); - if (reply.Status != ResponseStatus.Success) + using (var fido2Session = new Fido2Session((YubiKeyDevice)YubiKeyModule._yubikey!)) { - WriteWarning($"Failed to reset FIDO2 credentials: {reply.Status}, Yubikey needs to be inserted within the last 5 seconds."); + ResetCommand resetCommand = new Yubico.YubiKey.Fido2.Commands.ResetCommand(); + WriteWarning("Please touch the Yubikey to allow the reset."); + ResetResponse reply = fido2Session.Connection.SendCommand(resetCommand); + switch (reply.Status) + { + default: + throw new Exception("Unknown status. (Update ResetYubikeyFIDO2Cmdlet)"); + + case ResponseStatus.Failed: + throw new Exception("Please touch the Yubikey to allow the reset."); + + case ResponseStatus.ConditionsNotSatisfied: + throw new Exception($"Failed to reset, Yubikey needs to be inserted within the last 5 seconds."); + + case ResponseStatus.Success: + break; + } + WriteWarning("Restart FIDO2 Application by removing and reinserting the Yubikey."); + YubiKeyModule._fido2PIN = null; } } } diff --git a/Module/Cmdlets/Fido/SetYubikeyFIDO2.cs b/Module/Cmdlets/Fido/SetYubikeyFIDO2.cs index 78e5afb..d186f51 100644 --- a/Module/Cmdlets/Fido/SetYubikeyFIDO2.cs +++ b/Module/Cmdlets/Fido/SetYubikeyFIDO2.cs @@ -5,19 +5,20 @@ using powershellYK.support; using System.Security; using powershellYK.support.validators; +using System.Collections.ObjectModel; +using Yubico.YubiKey.Piv; +using Microsoft.VisualBasic; namespace powershellYK.Cmdlets.Fido { [Cmdlet(VerbsCommon.Set, "YubikeyFIDO2")] - public class SetYubikeyFIDO2Cmdlet : PSCmdlet + public class SetYubikeyFIDO2Cmdlet : PSCmdlet, IDynamicParameters { - [Parameter(Mandatory = false, ParameterSetName = "Set new PIN", ValueFromPipeline = false, HelpMessage = "Easy access to Set new PIN")] + [Parameter(Mandatory = false, ParameterSetName = "Set PIN", ValueFromPipeline = false, HelpMessage = "Easy access to Set new PIN")] public SwitchParameter SetPIN; - [ValidateYubikeyPIN(4,8)] - [Parameter(Mandatory = true, ParameterSetName = "Set new PIN", ValueFromPipeline = false, HelpMessage = "New PIN")] - public SecureString NewPIN { get; set; } = new SecureString(); + [ValidateRange(4, 63)] [Parameter(Mandatory = true, ParameterSetName = "Set PIN minimum length", ValueFromPipeline = false, HelpMessage = "Set the minimum length of the PIN")] public int? MinimumPINLength { get; set; } @@ -25,6 +26,56 @@ public class SetYubikeyFIDO2Cmdlet : PSCmdlet [Parameter(Mandatory = true, ParameterSetName = "Send MinimumPIN to RelyingParty", ValueFromPipeline = false, HelpMessage = "To which RelyingParty should minimum PIN be sent")] public string? MinimumPINRelyingParty { get; set; } + public object GetDynamicParameters() + { + try { YubiKeyModule.ConnectYubikey(); } catch { } + + Collection oldPIN, newPIN; + if (YubiKeyModule._yubikey is not null) + { + using (var fido2Session = new Fido2Session((YubiKeyDevice)YubiKeyModule._yubikey!)) + { + // if no minimum pin length is set, then set it to 63. + int minPinLength = fido2Session.AuthenticatorInfo.MinimumPinLength ?? 4; + // Verify that the yubikey FIDO2 has a PIN already set. If there is a PIN set then make sure we get the old PIN. + if (fido2Session.AuthenticatorInfo.Options!.Any(x => x.Key == AuthenticatorOptions.clientPin && x.Value == true) && (YubiKeyModule._fido2PIN is null)) { + oldPIN = new Collection() { + new ParameterAttribute() { Mandatory = true, HelpMessage = "Old PIN, required to change the PIN code.", ParameterSetName = "Set PIN", ValueFromPipeline = false}, + new ValidateYubikeyPIN(4, 63) + }; + } + else + { + oldPIN = new Collection() { + new ParameterAttribute() { Mandatory = false, HelpMessage = "Old PIN, required to change the PIN code.", ParameterSetName = "Set PIN", ValueFromPipeline = false}, + new ValidateYubikeyPIN(4, 63) + }; + } + + newPIN = new Collection() { + new ParameterAttribute() { Mandatory = true, HelpMessage = "New PIN code to set for the FIDO2 module.", ParameterSetName = "Set PIN", ValueFromPipeline = false}, + new ValidateYubikeyPIN(minPinLength, 63) + }; + } + } + else + { + oldPIN = new Collection() { + new ParameterAttribute() { Mandatory = false, HelpMessage = "Old PIN, required to change the PIN code.", ParameterSetName = "Set PIN", ValueFromPipeline = false}, + new ValidateYubikeyPIN(4, 63) + }; + newPIN = new Collection() { + new ParameterAttribute() { Mandatory = true, HelpMessage = "New PIN code to set for the FIDO2 module.", ParameterSetName = "Set PIN", ValueFromPipeline = false}, + new ValidateYubikeyPIN(4, 63) + }; + } + var runtimeDefinedParameterDictionary = new RuntimeDefinedParameterDictionary(); + var runtimeDefinedOldPIN = new RuntimeDefinedParameter("OldPIN", typeof(SecureString), oldPIN); + var runtimeDefinedNewPIN = new RuntimeDefinedParameter("NewPIN", typeof(SecureString), newPIN); + runtimeDefinedParameterDictionary.Add("OldPIN", runtimeDefinedOldPIN); + runtimeDefinedParameterDictionary.Add("NewPIN", runtimeDefinedNewPIN); + return runtimeDefinedParameterDictionary; + } protected override void BeginProcessing() { @@ -68,8 +119,14 @@ protected override void ProcessRecord() throw new Exception("Changing minimum PIN not possible with this yubikey hardware."); } break; - case "Set new PIN": - YubiKeyModule._fido2PINNew = NewPIN; + case "Set PIN": + + if (this.MyInvocation.BoundParameters.ContainsKey("OldPIN")) + { + YubiKeyModule._fido2PIN = (SecureString)this.MyInvocation.BoundParameters["OldPIN"]; + } + + YubiKeyModule._fido2PINNew = (SecureString)this.MyInvocation.BoundParameters["NewPIN"]; try { if (fido2Session.AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.clientPin) == OptionValue.False) @@ -85,13 +142,14 @@ protected override void ProcessRecord() } catch (Exception e) { + YubiKeyModule._fido2PIN = null; throw new Exception(e.Message, e); } finally { YubiKeyModule._fido2PINNew = null; } - YubiKeyModule._fido2PIN = NewPIN; + YubiKeyModule._fido2PIN = (SecureString)this.MyInvocation.BoundParameters["NewPIN"]; break; case "Send MinimumPIN to RelyingParty": var rpidList = new List(1); diff --git a/Module/powershellYK.csproj b/Module/powershellYK.csproj index 93ef83e..66edaf7 100644 --- a/Module/powershellYK.csproj +++ b/Module/powershellYK.csproj @@ -2,7 +2,7 @@ net8.0 - 0.0.15.4 + 0.0.16.0 enable enable true @@ -36,7 +36,7 @@ - + diff --git a/Module/support/YKKeyCollector.cs b/Module/support/YKKeyCollector.cs index 53f8f27..bfd99a4 100644 --- a/Module/support/YKKeyCollector.cs +++ b/Module/support/YKKeyCollector.cs @@ -25,15 +25,17 @@ public bool YKKeyCollectorDelegate(KeyEntryData keyEntryData) switch (keyEntryData.Request) { default: - throw new Exception("Unknown request."); - //return false; + throw new Exception("Unknown request. (Update YKKeyCollector)"); case KeyEntryRequest.AuthenticatePivManagementKey: throw new Exception("Incorrect Management Key."); - //return false; case KeyEntryRequest.VerifyOathPassword: throw new Exception("Incorrect Password."); + + case KeyEntryRequest.ChangeFido2Pin: + throw new Exception("Failed to change FIDO2 PIN."); + case KeyEntryRequest.VerifyFido2Pin: case KeyEntryRequest.VerifyPivPin: if (!(keyEntryData.RetriesRemaining is null))