PSTrueCrypt.psm1
using namespace 'System.Management.Automation' using module .\src\CIM\PSTrueCrypt.CIM.psm1 using module .\src\Storage\PSTrueCrypt.Storage.psm1 using module .\src\Utility\PSTrueCrypt.Utility.psm1 using module .\src\Writer\PSTrueCrypt.Writer.psm1 using module .\src\PSTrueCrypt.CommandLine.psm1 $SUT = $False #.ExternalHelp PSTrueCrypt-help.xml function Mount-TrueCrypt { [CmdletBinding(PositionalBinding=$False)] Param ( [Parameter(Mandatory = $False)] [array]$KeyfilePath, [Parameter(Mandatory = $False)] [System.Security.SecureString]$Password ) DynamicParam { return Get-DynamicParameterValues -IsSystemUnderTest:$SUT } begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } process { try { $Container = Get-RegistrySubKeys | Get-SubKeyByPropertyValue -Name $PSBoundParameters.Name | Read-Container } catch [ItemNotFoundException] { Out-Error 'NoPSTrueCryptContainerFound' -Action Stop } # construct arguments for expression and insert token in for password... [string]$Expression = Get-TrueCryptMountParams -TrueCryptContainerPath $Container.Location -PreferredMountDrive $Container.MountLetter -Product $Container.Product -KeyfilePath $KeyfilePath -Timestamp $Container.Timestamp # if no password was given, then we need to start the process for of prompting for one... if ([string]::IsNullOrEmpty($Password) -eq $True) { $WasConsolePromptingPrior # check to see if session is in admin mode for console prompting... if (Test-IsAdmin -eq $True) { $WasConsolePromptingPrior = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds" | Select-Object -ExpandProperty ConsolePrompting Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds" -Name ConsolePrompting -Value $True } [securestring]$Password = Read-Host -Prompt "Enter password" -AsSecureString } # this method of handling password securely has been mentioned at the following links: # https://msdn.microsoft.com/en-us/library/system.security.securestring(v=vs.110).aspx # https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.securestringtobstr(v=vs.110).aspx # https://msdn.microsoft.com/en-us/library/system.intptr(v=vs.110).aspx # https://msdn.microsoft.com/en-us/library/ewyktcaa(v=vs.110).aspx try { # Create IntPassword and dispose $Password... [System.IntPtr]$IntPassword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) } catch [System.NotSupportedException] { # The current computer is not running Windows 2000 Service Pack 3 or later. Out-Error 'NotSupportedException' } catch [System.OutOfMemoryException] { # OutOfMemoryException Out-Error 'OutOfMemoryException' } finally { $Password.Dispose() } Start-CimLogicalDiskWatch $Container.KeyId -InstanceType 'Creation' try { # Execute Expression Invoke-Expression ($Expression -f [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($IntPassword)) } catch [System.Exception] { Out-Error 'UnknownException', 'EnsureFileRecommendment' } finally { # TODO: this is crashing CLS. Is this to be called when dismount is done? Perhaps TrueCrypt is # holding on to this pointer while container is open. # [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemAnsi($IntPassword) } # if console prompting was set to false prior to this module, then set it back to false... if ($WasConsolePromptingPrior -eq $False) { Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds" -Name ConsolePrompting -Value $False } if($KeyfilePath -ne $null) { Edit-HistoryFile } } end { Invoke-EndBlock -IsSystemUnderTest:$SUT } } #.ExternalHelp PSTrueCrypt-help.xml function Dismount-TrueCrypt { [CmdletBinding()] Param() DynamicParam { return Get-DynamicParameterValues -IsSystemUnderTest:$SUT } begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } process { $Container = Get-RegistrySubKeys | Get-SubKeyByPropertyValue -Name $PSBoundParameters.Name | Read-Container Start-CimLogicalDiskWatch $Container.KeyId -InstanceType 'Deletion' # construct arguments and execute expression... [string]$Expression = Get-TrueCryptDismountParams -Drive $Container.MountLetter -Product $Container.Product Invoke-Expression $Expression } end { Invoke-EndBlock -IsSystemUnderTest:$SUT } } #.ExternalHelp PSTrueCrypt-help.xml function Dismount-TrueCryptForceAll { Invoke-DismountAll -Product TrueCrypt Invoke-DismountAll -Product VeraCrypt } # internal function function Invoke-DismountAll { [CmdletBinding()] Param ( [ValidateSet("TrueCrypt", "VeraCrypt")] [string]$Product ) # construct arguments for Force dismount(s)... [string]$Expression = Get-TrueCryptDismountParams -Product $Product try { Invoke-Expression $Expression $HasXCryptDismountFailed = $False } catch { $HasXCryptDismountFailed = $True } finally { if($HasXCryptDismountFailed -eq $False) { Out-Information 'AllProductContainersDismounted' -Format $Product } else { Out-Error 'DismountException' -Format $Product } } } #.ExternalHelp PSTrueCrypt-help.xml function New-PSTrueCryptContainer { [CmdletBinding()] Param ( [Parameter(Mandatory = $True, Position = 1)] [ValidateNotNullOrEmpty()] [string]$Name, [Parameter(Mandatory = $True, Position = 2)] [ValidateNotNullOrEmpty()] [string]$Location, [Parameter(Mandatory = $True, Position = 3)] [ValidatePattern("^[a-zA-Z]$")] [string]$MountLetter, [Parameter(Mandatory = $True, Position = 4)] [ValidateSet("TrueCrypt", "VeraCrypt")] [string]$Product, [switch]$Timestamp ) begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } process { $SubKeyName = Get-RegistrySubKeys | Get-SubKeyByPropertyValue -Name $Name if(-not ($SubKeyName) ) { $Decision = Get-Confirmation -Message "New-PSTrueCryptContainer will add a new subkey in the following of your registry: HKCU:\SOFTWARE\PSTrueCrypt" try { if ($Decision -eq $True) { New-Container -Name $Name -Location $Location -MountLetter $MountLetter -Product $Product -Timestamp:$Timestamp.IsPresent Out-Information 'NewContainerOperationSucceeded' -Format $Name } else { Out-Warning 'NewContainerOperationCancelled' } } catch [System.UnauthorizedAccessException] { # TODO: append to this message of options for a solution. solution will be determined if the user is in an elevated CLS. Out-Error 'UnauthorizedAccessException' } } else { Out-Warning 'ContainerNameAlreadyExists' -Format $Name } } end { Invoke-EndBlock -IsSystemUnderTest:$SUT } } #.ExternalHelp PSTrueCrypt-help.xml function Edit-PSTrueCryptContainer { [CmdletBinding(PositionalBinding=$False)] Param ( [Parameter(Mandatory = $False)] [string]$NewName, [Parameter(Mandatory = $False)] [string]$Location, [Parameter(Mandatory = $False)] [ValidatePattern("^[a-zA-Z]$")] [string]$MountLetter, [Parameter(Mandatory = $False)] [ValidateSet("TrueCrypt", "VeraCrypt")] [string]$Product, [switch]$Timestamp ) DynamicParam { return Get-DynamicParameterValues -IsSystemUnderTest:$SUT } begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } process { $Container = Get-RegistrySubKeys | Get-SubKeyByPropertyValue -Name $PSBoundParameters.Name | Read-Container if($Container) { $ProposedParameterValues = [PSCustomObject]@{ Name = ($NewName, $Container.Name, 1 -notmatch "^$")[0] Location = ($Location, $Container.Location, 1 -notmatch "^$")[0] MountLetter = ($MountLetter, $Container.MountLetter, 1 -notmatch "^$")[0] Product = ($Product, $Container.Product, 1 -notmatch "^$")[0] Timestamp = $Timestamp.IsPresent } Format-Table @{Label="Name";Expression={($_.Name)}},` @{Label="Location";Expression={($_.Location)}},` @{Label="MountLetter";Expression={($_.MountLetter)}},` @{Label="Product";Expression={($_.Product)}},` @{Label="Timestamp";Expression={($_.Timestamp)}}` -AutoSize -InputObject $ProposedParameterValues $Decision = Get-Confirmation -Message ("Edit-PSTrueCryptContainer will set "+$Container.Name+" with the above values.") try { if ($Decision -eq $True) { Write-Container -KeyId $Container.KeyId ` -Name $ProposedParameterValues.Name ` -Location $ProposedParameterValues.Location ` -MountLetter $ProposedParameterValues.MountLetter ` -Product $ProposedParameterValues.Product ` -Timestamp $ProposedParameterValues.Timestamp Out-Information 'EditContainerOperationSucceeded' -Format $ProposedParameterValues.Name } else { Out-Warning 'EditContainerOperationCancelled' } } catch [System.UnauthorizedAccessException] { Out-Error 'UnauthorizedAccessException' } } else { Out-Error 'NoPSTrueCryptContainerFound' } } end { Invoke-EndBlock -IsSystemUnderTest:$SUT } } #.ExternalHelp PSTrueCrypt-help.xml function Remove-PSTrueCryptContainer { [CmdletBinding()] Param () # value is selected from DynamicParam block DynamicParam { return Get-DynamicParameterValues -IsSystemUnderTest:$SUT } begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } process { try { $Decision = Get-Confirmation -Message ("Remove-PSTrueCryptContainer will remove the "+$PSBoundParameters.Name+" from your registry: HKCU:\SOFTWARE\PSTrueCrypt") if ($Decision -eq $True) { Get-RegistrySubKeys | Remove-SubKeyByPropertyValue -Name $PSBoundParameters.Name Out-Information 'ContainerSettingsDeleted' } else { Out-Information 'RemoveContainerOperationCancelled' } } catch [System.ObjectDisposedException] { #The RegistryKey being manipulated is closed (closed keys cannot be accessed). Out-Error 'ObjectDisposedException' } catch [System.ArgumentException],[System.ArgumentNullException] { #subkey does not specify a valid registry key, and throwOnMissingSubKey is true. #subkey is null. Out-Error 'UnableToFindPSTrueCryptContainer' -Format $PSBoundParameters.Name } catch [System.Security.SecurityException] { #The user does not have the permissions required to delete the key. Out-Error 'SecurityException' -Recommendment 'SecurityRecommendment' } catch [System.InvalidOperationException] { # subkey has child subkeys. Out-Error 'InvalidOperationException' } catch [System.UnauthorizedAccessException] { #The user does not have the necessary registry rights. Out-Error 'UnauthorizedRegistryAccessException' } catch { Out-Error 'UnknownException' } } end { Invoke-EndBlock -IsSystemUnderTest:$SUT } } #.ExternalHelp PSTrueCrypt-help.xml function Show-PSTrueCryptContainers { [CmdletBinding()] Param () begin { Invoke-BeginBlock -IsSystemUnderTest:$SUT } end { try { Restart-LogicalDiskCheck $SortedContainers = Get-RegistrySubKeys | ` Read-Container | ` Sort-Object -Property @{ Expression = {$_.Name} } Format-Table @{Label="Name";Expression={($_.Name)}},` @{Label="Location";Expression={($_.Location)}},` @{Label="MountLetter";Expression={($_.MountLetter)}},` @{Label="Product";Expression={($_.Product)}},` @{Label="Timestamp";Expression={($_.Timestamp)}},` @{Label="IsMounted";Expression={($_.IsMounted)}},` @{Label="Last Activity";Expression={[DateTime]($_.LastActivity)}}` -AutoSize -InputObject $SortedContainers } catch [System.NullReferenceException] { Out-Information 'NoPSTrueCryptContainerFound' } finally { Invoke-EndBlock -IsSystemUnderTest:$SUT } } } Set-Alias -Name mt -Value Mount-TrueCrypt Set-Alias -Name dmt -Value Dismount-TrueCrypt Set-Alias -Name dmt* -Value Dismount-TrueCryptForceAll Start-SystemCheck |