Beaver.psm1
#Requires -Version 5.0 function Get-StringHash { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateSet('MD5','RIPEMD160','SHA1','SHA256','SHA384','SHA512')] [ValidateNotNullorEmpty()] [string] $hashAlgorithm ) process { $strBuilder = New-Object System.Text.StringBuilder [System.Security.Cryptography.HashAlgorithm]::Create($hashAlgorithm).ComputeHash(` [System.Text.Encoding]::UTF8.GetBytes($text)) | % { [void]$strBuilder.Append($_.ToString("x2")) } return $strBuilder.ToString() } } function Test-CurrentUserInGroup { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $groupName ) process { return ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).` IsInRole($groupName) } } function Get-MaskLength { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [Net.IPAddress] $mask ) process { $bits = "$($mask.GetAddressBytes() | ForEach-Object { [Convert]::ToString($_, 2)})" -replace '[\s0]' return $bits.Length } } function Test-IPInSubnet { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*/*'})] [string] $cidr, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*'})] [string] $ipAddress ) process { $network, [int]$subnetlen = $cidr.Split('/') $a = [uint32[]]$network.Split('.') [uint32] $unetwork = ($a[0] -shl 24) + ($a[1] -shl 16) + ($a[2] -shl 8) + $a[3] $mask = (-bnot [uint32]0) -shl (32 - $subnetlen) $a = [uint32[]]$ipAddress.split('.') [uint32] $uip = ($a[0] -shl 24) + ($a[1] -shl 16) + ($a[2] -shl 8) + $a[3] return ($unetwork -eq ($mask -band $uip)) } } function Add-SignatureToFiles { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $fileMask ) begin { [System.Security.Cryptography.X509Certificates.X509Certificate2] $signingCert = $null } process { try { Write-Verbose -Message 'Finding signing certificate' $signingCert = dir Cert:\CurrentUser\My -CodeSigningCert | Sort NotAfter | Select -Last 1 if ($signingCert) { Write-Verbose -Message ('Found signing certificate: subjectCert = {0} | issuedBy = {1}'` -f $signingCert.Subject, $signingCert.Issuer) $chooseFiles = Get-ChildItem $fileMask foreach ($oneFile in $chooseFiles) { if ((Get-AuthenticodeSignature $oneFile).Status -ne 'Valid') { Write-Verbose -Message ("Sign file: {0}" -f $oneFile) [void] (Set-AuthenticodeSignature $oneFile -Certificate $signingCert ` -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll) } } } else { throw 'Error: no signing certificate found' } } catch { throw; } } } function Send-WakeOnLan { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*.*.*.*'})] [string] $broadcastAddress, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateScript({$_ -like '*-*-*-*-*-*'})] [string] $macAddress ) begin { try { Write-Verbose -Message ('Loading assembly "System.Net"') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Net") Write-Verbose -Message ('Loading assembly "System.Net.Sockets"') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Net.Sockets") Write-Verbose -Message ('Creating UDP socket') $udpClient = New-Object System.Net.Sockets.UdpClient $endPoint = New-Object System.Net.IPEndPoint $([System.Net.IPAddress]::Parse($broadCastAddress)),10000 } catch { throw; } } process { if($udpClient -and $endPoint) { try { [byte[]]$macBytes = $macAddress.split("-") | %{ [byte]"0x$_" } [byte[]]$bytes = New-Object "byte[]" $(6 + 16 * $($macBytes.length)) for ($i = 0; $i -lt 6; $i++) { $bytes[$i] = [byte] 0xff } for ($i = 6; $i -lt $bytes.length; $i += $macBytes.length) { for($j = 0; $j -lt $macBytes.length; $j++) { $bytes[$i + $j] = $macBytes[$j] } } Write-Verbose -Message ('Connect to endpoint') $udpClient.connect($endPoint) Write-Verbose -Message ('Sending magic packet') [void]$udpClient.Send($bytes, $bytes.length) Write-Verbose -Message ('Magic packet was sent') $udpClient.Close() } catch { throw; } } } } function Get-ExpireCertificates { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNull()] [ValidateRange(1, 365)] [int] $expireInDays ) process { return ( Get-Childitem cert: -Recurse | ` Where-Object { ($_.NotAfter -gt (Get-Date).AddDays(-1))` -and ($_.NotAfter -lt (Get-Date).AddDays($expireInDays)) } | ` Select Subject,Thumbprint,@{Name="Expires in (Days)";` Expression={($_.NotAfter).subtract([DateTime]::Now).days}}, ` PSParentPath,SerialNumber,HasPrivateKey,Issuer,Archived,` EnhancedKeyUsageList,NotAfter,NotBefore,DnsNameList | ` Sort "Expires in (Days)" | fl ) } } function New-Password { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNull()] [ValidateRange(1, 128)] [int] $passwordLength, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [ValidateRange(1, 128)] [int] $numbersNonAlphaNumeric ) process { try { Write-Verbose -Message ('Loading assembly "System.Web"') Add-Type -AssemblyName System.Web Write-Verbose -Message ('Generate random passwords with length {0}' -f $passwordLength) return [System.Web.Security.Membership]::GeneratePassword($passwordLength, $numbersNonAlphaNumeric) } catch { throw; } } } function Send-FileOnFTP { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $url, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $localFileName, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $username, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [string] $password, [Parameter(Mandatory = $false, Position = 4, ValueFromPipeline = $false)] [bool] $enableTls = $true ) begin { $fileWithoutPath = Split-Path -Leaf $localFileName $remotePath = $url + '/' + $fileWithoutPath } process { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' Write-Verbose -Message ('Create FtpWebRequest object') try { $ftpWebRequest = [System.Net.FtpWebRequest]::Create($remotePath) $ftpWebRequest = [System.Net.FtpWebRequest]$ftpWebRequest $ftpWebRequest.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $ftpWebRequest.UseBinary = $true $ftpWebRequest.UsePassive = $true $ftpWebRequest.EnableSsl = $enableTls $ftpWebRequest.KeepAlive = $false if($ftpWebRequest) { Write-Verbose -Message ('Add client credentials') $ftpWebRequest.Credentials = New-Object System.Net.NetworkCredential($username, $password) Write-Verbose -Message ('Copy file to request stream') $fileContents = [System.IO.File]::ReadAllBytes($localFileName) $ftpWebRequest.ContentLength = $fileContents.Length Write-Verbose ('Transfer file: {0}' -f $localFileName) $reqStream = $ftpWebRequest.GetRequestStream() $reqStream.Write($fileContents, 0, $fileContents.Length) $reqStream.Close() $response = $ftpWebRequest.GetResponse() Write-Verbose -Message ('Transfer status: {0}' -f $response.StatusDescription) $response.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Uninstall-MSIPackage { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $fqdn, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $appName, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [Management.Automation.PSCredential] $credentials ) begin { $wmiApp = $null $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { Write-Verbose -Message ('WMI Query: {0}' -f $fqdn) try { if($credentials) { $wmiApp = Get-WmiObject -ComputerName $fqdn -Query ` "SELECT * FROM Win32_Product WHERE Name LIKE '%$appName%'" -Credential $credentials } else { $wmiApp = Get-WmiObject -ComputerName $fqdn -Query ` "SELECT * FROM Win32_Product WHERE Name LIKE '%$appName%'" } if($wmiApp) { Write-Verbose -Message ('WMI uninstalling: {0} | {1}' -f $wmiApp.Name, $wmiApp.Version) $wmiApp.Uninstall() } else { throw "WMI finding $appName on $fqdn failed" } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Save-PptAs { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $pptFile, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('PDF','XPS','PNG','JPG','HTML','WMV')] [string] $saveAs ) begin { [string] $outFile = '' $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ('Open PowerPoint application') $ppt = New-Object -ComObject PowerPoint.Application $withWindow = [Microsoft.Office.Core.MsoTriState]::msoFalse Write-Verbose -Message ('Get the slide deck: {0}' -f $pptFile) $slideDeck = $ppt.Presentations.Open($pptFile, [Microsoft.Office.Core.MsoTriState]::msoTrue, ` [Microsoft.Office.Core.MsoTriState]::msoTrue, $withWindow) Write-Verbose -Message ('Presentation has slides: {0}' -f $slideDeck.Slides.Count) Add-Type -AssemblyName Microsoft.Office.Interop.PowerPoint $saveOptions = [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::"ppSaveAs$saveAs" $outFile = [System.IO.Path]::ChangeExtension($pptFile, $saveAs.ToLower()) if (Test-Path $outFile) { Remove-Item $outFile -Force } Write-Verbose -Message ('Save the file: {0}' -f $outFile) $slideDeck.SaveAs($outFile, $saveOptions) Write-Verbose -Message ('Close the slide deck') $slideDeck.Close() $slideDeck = $null Write-Verbose -Message ('Quit the PowerPoint application') $ppt.Quit() $ppt = $null [GC]::Collect(); [GC]::WaitForPendingFinalizers(); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outFile } } function Save-DocAsPdf { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateScript({ Test-Path $_ })] [string] $docFile ) begin { [string] $outFile = '' $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ('Open Word application') $word = New-Object -ComObject Word.Application Write-Verbose -Message ('Open Word document') $doc = $word.Documents.Open($docFile) $outFile = [System.IO.Path]::ChangeExtension($docFile, 'pdf') if (Test-Path $outFile) { Remove-Item $outFile -Force } Write-Verbose -Message ('Save the file: {0}' -f $outFile) $doc.SaveAs($outFile, 17) Write-Verbose -Message ('Close Word document') $doc.Close() $doc = $null Write-Verbose -Message ('Quit the Word application') $word.Quit() $word = $null [GC]::Collect(); [GC]::WaitForPendingFinalizers(); } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outFile } } function Add-SignatureInISE { [CmdletBinding()] param( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $signingCertSubject = 'meduna@pors-sw.cz' ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [System.Security.Cryptography.X509Certificates.X509Certificate2] $signingCert = $null } process { try { $signingCert = dir Cert:\CurrentUser\My -CodeSigningCert | ? { $_.Subject -like "*E=$signingCertSubject*" | ` Sort NotAfter | Select -Last 1 } Write-Verbose -Message ('Found certificate: {0} | {1}' -f ` $signingCert.FriendlyName, $signingCert.SerialNumber) if($signingCert) { $openFiles = $psISE.CurrentPowerShellTab | % { $_.Files } foreach ($oneOpenFile in $openFiles) { $oneFilePath = $oneOpenFile.FullPath $oneFileLine = $oneOpenFile.Editor.CaretLine $oneFileColumn = $oneOpenFile.Editor.CaretColumn if (-not $oneOpenFile.IsSaved) { [void] $oneOpenFile.Save() } if ((@('.ps1','.psm1','.psd1') -contains [System.IO.Path]::GetExtension($oneFilePath)) -and ` ((Get-AuthenticodeSignature $oneFilePath).Status -ne 'Valid')) { [void] $psISE.CurrentPowerShellTab.Files.Remove($oneOpenFile) Write-Verbose -Message ('Sign file: {0}' -f $oneFilePath) [void] (Set-AuthenticodeSignature $oneFilePath -Certificate $signingCert ` -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll) $reloadedFile = $psISE.CurrentPowerShellTab.Files.Add($oneFilePath) $reloadedFile.Editor.SetCaretPosition($oneFileLine, $oneFileColumn) } } } else { throw 'Error: no signing certificate found' } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Clear-ISEHistory { [CmdletBinding()] param() process { $count = $psIse.Options.MruCount $psIse.Options.MruCount = 0 $psIse.Options.MruCount = $count } } function Clear-EventLogs { [CmdletBinding()] param() process { Get-WinEvent -ListLog * | % { Write-Verbose -Message ('Clear windows event log: {0}' -f $_.LogName) Clear-EventLog -LogName $_.LogName -ErrorAction SilentlyContinue } } } function Set-RegistryValue { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $keyPath, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $value, [Parameter(Mandatory = $true, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('string','expandstring','multistring','qword')] [string] $type ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ("Ensure the key exists") if (Test-Path $keyPath) { Write-Verbose -Message ("Key already exists: {0}" -f $keyPath) } else { Write-Verbose -Message ("Creating the whole registry path: {0}" -f $keyPath) [void] (New-Item -Path $keyPath -ItemType Registry -Force) } Write-Verbose -Message ("Set the value") Set-ItemProperty -Path $keyPath -Name $name -Value $value -Type $type -Force } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Add-SybaseODBCProfile { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $user, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $password, [Parameter(Mandatory = $true, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $srvName, [Parameter(Mandatory = $true, Position = 4, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $dbName, [Parameter(Mandatory = $true, Position = 5, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet(12, 16, 17)] [int] $version ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $odbcRootKey = 'HKCU:\SOFTWARE\ODBC\ODBC.INI' } process { try { $sqlAnyLocation = ('HKLM:\SOFTWARE\Sybase\SQL Anywhere\{0}.0' -f $version) Write-Verbose -Message ('Read SQL Anywhere registry key: {0}' -f $sqlAnyLocation) if (Test-Path $sqlAnyLocation) { $installDir = (Get-ItemProperty -Path $sqlAnyLocation -Name Location).Location if (Test-Path $installDir) { Write-Verbose -Message ('Found SQL Anywhere instalation folder: {0}' -f $installDir) Write-Verbose -Message ('Creating ODBC registry values') Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name CommLinks -Value 'TCPIP{}' -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name DatabaseName -Value $dbName -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name Driver -Value ('{0}\Bin32\dbodbc{1}.dll' -f $installDir, $version) -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name Integrated -Value 'NO' -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name PWD -Value $password -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name ServerName -Value $srvName -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\{1}' -f $odbcRootKey, $name) -Name UID -Value $user -Type string -Verbose:$VerbosePreference Set-RegistryValue -KeyPath ('{0}\ODBC Data Sources' -f $odbcRootKey) -Name $name -Value ('SQL Anywhere {0}' -f $version) -Type String -Verbose:$VerbosePreference Write-Verbose -Message ('Creating ODBC registry values done') } else { throw 'SQL Anywhere installation directory not found' } } else { throw 'SQL Anywhere installation not found' } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-DirectoryEntry { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $distinguishedName, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $userName, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $password ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $outDE = $null } process { try { if ($distinguishedName -like 'ldap://*') { Write-Verbose -Message ('Correct invalid DE: {0}' -f $distinguishedName) $distinguishedName = 'LDAP{0}' -f $distinguishedName.Substring(4) } elseif ($distinguishedName -like 'gc://*') { Write-Verbose -Message ('Correct invalid DE: {0}' -f $distinguishedName) $distinguishedName = 'GC{0}' -f $distinguishedName.Substring(2) } if ([string]::IsNullOrEmpty($userName)) { Write-Verbose -Message ('ADSI connecting') $outDE = [ADSI] $distinguishedName } else { Write-Verbose -Message ('System.DirectoryServices.DirectoryEntry connecting') $outDE = New-Object System.DirectoryServices.DirectoryEntry ($distinguishedName, $userName, $password) } if ([string]::IsNullOrEmpty($outDE.Guid)) { if ($outDE) { Write-Verbose -Message ('Disposing invalid DE') $outDE.Close() [GC]::Collect() [GC]::WaitForPendingFinalizers() } $outDE = $null } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } if ($outDE) { $outDE | Add-Member -MemberType NoteProperty -Name BeaverDEUserName -Value $userName -Force $outDE | Add-Member -MemberType NoteProperty -Name BeaverDEPassword -Value $password -Force } return $outDE } } function Get-LocalUsers { [CmdletBinding()] param( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' $psObj = $null } process { try { $adsiObj = Get-DirectoryEntry "WinNT://$computerName" -Verbose:$VerbosePreference Write-Verbose -Message ('Local account ADSI path opened: {0}' -f $adsiObj.Path) $psObj = $adsiObj.Children | ? {$_.SchemaClassName -eq 'user'} | % { $groups = $_.Groups() | % { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) } $_ | Select-Object @{n = 'UserName';e = {$_.Name}},@{n = 'Groups';e = {$groups -join ';'}} } $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $psObj } } function Enable-LocalUser { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $adsiObjPath = 'WinNT://{0}/{1},user' -f $computerName, $name Write-Verbose -Message ('Open local account with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose -Message ('Local account ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose -Message ('Enable local account {0}.' -f $name) $originalUAC = [int] $adsiObj.UserFlags.Value $newUAC = [int] ($originalUAC -band (-bnot ([int] 2))) $adsiObj.UserFlags.Value = $newUAC $adsiRs = $adsiObj.SetInfo() $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Disable-LocalUser { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $adsiObjPath = "WinNT://$computerName/{0},user" -f $name Write-Verbose -Message ('Open local account with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose -Message ('Local account ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose -Message ('Disable local account {0}.' -f $name) $originalUAC = [int] $adsiObj.UserFlags.Value $adsiObj.UserFlags.Value = ($originalUAC -bor 2) $adsiRs = $adsiObj.SetInfo() $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Set-LocalUserPassword { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $oldPassword, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $newPassword, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { $adsiObjPath = 'WinNT://{0}/{1},user' -f $computerName, $name Write-Verbose -Message ('Open local user with ADSI: {0}' -f $adsiObjPath) $adsiObj = $null $adsiObj = Get-DirectoryEntry $adsiObjPath -Verbose:$VerbosePreference Write-Verbose -Message ('Local user ADSI path opened: {0}' -f $adsiObj.Path) Write-Verbose -Message ('Change local user password.') $adsiRs = $adsiObj.ChangePassword($oldPassword, $newPassword) $adsiObj.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Add-MemberLocalGroup { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $memberLogin, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $localGroup, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $localObjType, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ("Going to obtain local group: {0}" -f $localGroup) $localGroupDE = $null $localGroupDE = [ADSI] ('WinNT://{0}/{1},Group' -f $computerName, $localGroup) if($localGroupDE) { $memberADSIPath = 'WinNT://{0}/{1}' -f $computerName, $memberLogin $memberADSIPath = '{0},{1}' -f $memberADSIPath, $localObjType Write-Verbose -Message ("Adding: {0} | {1}" -f $memberLogin, $memberADSIPath) $adsiRs = $null $adsiRs = $localGroupDE.Add($memberADSIPath) $localGroupDE.Close() } } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function New-LocalObject { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $password, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false, Position = 4, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $groups ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}' -f $computerName) -Verbose:$VerbosePreference Write-Verbose -Message ("Going to create or open the new object: {0} = {1}" -f $type, $name) Write-Verbose -Message ("The object does not exist, going to create it.") $newObj = $null $newObj = $localSAM.Create($type, $name) if (-not ([string]::IsNullOrEmpty($newObj.Path))) { if ($type -eq 'user') { if (-not ([string]::IsNullOrEmpty($password))) { Write-Verbose -Message ("Setting password.") $adsiRs = $null $adsiRs = $newObj.SetPassword($password) } } Write-Verbose -Message ("Saving the newly created object.") $adsiRs = $null $adsiRs = $newObj.SetInfo() if (-not ([string]::IsNullOrEmpty($groups))) { $groupList = $groups.Split(',', [System.StringSplitOptions]::RemoveEmptyEntries) Write-Verbose -Message ("Adding the new object to groups: {0}x" -f $groupList.Count) $groupList | % { $oneGroup = $_ Add-MemberLocalGroup $name $oneGroup $type -Verbose:$VerbosePreference } } } $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Remove-LocalObject { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}' -f $computerName) -Verbose:$VerbosePreference Write-Verbose -Message ("Going to delete object: {0} = {1}" -f $type, $name) $adsiRs = $localSAM.Delete($type, $name) $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Test-LocalUserEnabled { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $name, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'SilentContinue' [bool] $isEnabled = $false } process { try { Write-Verbose -Message ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}/{1},user' -f $computerName, $name) -Verbose:$VerbosePreference Write-Verbose ('Local account ADSI path opened: {0}' -f $localSAM.Path) $isEnabled = -not ($originalUAC -band 2) $localSAM.Close() } catch {} finally { $ErrorActionPreference = $eaPreferencesBackup } return $isEnabled } } function Rename-LocalObject { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $oldName, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $newName, [Parameter(Mandatory = $true, Position = 2, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [ValidateSet('user','group')] [string] $type, [Parameter(Mandatory = $false, Position = 3, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $computerName = $env:COMPUTERNAME ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' } process { try { Write-Verbose -Message ("Going to obtain local SAM handle.") $localSAM = $null $localSAM = Get-DirectoryEntry ('WinNT://{0}/{1},user' -f $computerName, $oldName) -Verbose:$VerbosePreference Write-Verbose -Message ('Local account ADSI path opened: {0}' -f $localSAM.Path) Write-Verbose -Message ('Rename local object: from = {0} | to = {1}' -f $oldName, $newName) $localSAM.psbase.rename($newName) $localSAM.Close() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } } } function Get-PasswordCredentials { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $userSamOrUpn, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $password ) begin { $cred = $null } process { $securePwd = ConvertTo-SecureString -String $password -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential $userSamOrUpn, $securePwd return $cred } } function Protect-HmacSha256 { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [Security.SecureString] $password, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [byte[]] $bytesToHmac ) begin { [string] $outHmac = '' [IntPtr] $unmanagedString = [IntPtr]::Zero $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'SilentContinue' } process { try { Write-Verbose -Message ('Signing bytes: {0}' -f $bytesToHmac.Count) $unmanagedString = [Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($password) $outHmac = [BitConverter]::ToString( (New-Object System.Security.Cryptography.HMACSHA256 @(,([Text.Encoding]::UTF8.GetBytes([Runtime.InteropServices.Marshal]::PtrToStringUni($unmanagedString)) * [Math]::Ceiling((64 / $password.Length))))).ComputeHash($bytesToHmac) ) [Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($unmanagedString) } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $outHmac } } function Convert-UserNameToSid { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $userName, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $false)] [ValidateNotNullorEmpty()] [string] $domain ) process { return ((New-Object System.Security.Principal.NTAccount($domain, $userName)).` Translate([System.Security.Principal.SecurityIdentifier])).Value } } function Convert-SidToUserName { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $sidString ) process { return ((New-Object System.Security.Principal.SecurityIdentifier($sidString)).` Translate( [System.Security.Principal.NTAccount])).Value } } function Compress-GZip { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $compressed = $null [byte[]] $sourceToZip = $encoding.GetBytes($text) } process { try { $zippedMem = New-Object IO.MemoryStream $zipper = New-Object IO.Compression.GZipStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Compress, $true) [void] $zipper.Write($sourceToZip, 0, $sourceToZip.Length) $zipper.Close() $zipper.Dispose() $compressed = $zippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return [Convert]::ToBase64String($compressed) } } function Expand-GZip { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $compressedInBase64, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToUnzip = [Convert]::FromBase64String($compressedInBase64) [byte[]] $decompressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream [void] $zippedMem.Write($sourceToUnzip, 0, $sourceToUnzip.Length) [void] $zippedMem.Seek(0, 'Begin') $unzip = New-Object IO.Compression.GZipStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Decompress, $true) $unzippedMem = New-Object IO.MemoryStream [byte[]] $buffer = New-Object byte[] 64 [int] $read = $unzip.Read($buffer, 0, $buffer.Length) while ($read -gt 0) { [void] $unzippedMem.Write($buffer, 0, $read) $read = $unzip.Read($buffer, 0, $buffer.Length) } $unzip.Close() $unzip.Dispose() $decompressed = $unzippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $encoding.GetString($decompressed) } } function Compress-Deflate { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $text, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToZip = $encoding.GetBytes($text) [byte[]] $compressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream $zipper = New-Object IO.Compression.DeflateStream ($zippedMem, ` [System.IO.Compression.CompressionMode]::Compress, $true) [void] $zipper.Write($sourceToZip, 0, $sourceToZip.Length) $zipper.Close() $zipper.Dispose() $compressed = $zippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return [Convert]::ToBase64String($compressed) } } function Expand-Deflate { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullorEmpty()] [string] $compressedInBase64, [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $false)] [ValidateNotNull()] [Text.Encoding] $encoding = [Text.Encoding]::UTF8 ) begin { $eaPreferencesBackup = $ErrorActionPreference $ErrorActionPreference = 'Stop' [byte[]] $sourceToUnzip = [Convert]::FromBase64String($compressedInBase64) [byte[]] $decompressed = $null } process { try { $zippedMem = New-Object IO.MemoryStream [void] $zippedMem.Write($sourceToUnzip, 0, $sourceToUnzip.Length) [void] $zippedMem.Seek(0, 'Begin') $unzip = New-Object IO.Compression.DeflateStream ($zippedMem, [System.IO.Compression.CompressionMode]::Decompress, $true) $unzippedMem = New-Object IO.MemoryStream [byte[]] $buffer = New-Object byte[] 64 [int] $read = $unzip.Read($buffer, 0, $buffer.Length) while ($read -gt 0) { [void] $unzippedMem.Write($buffer, 0, $read) $read = $unzip.Read($buffer, 0, $buffer.Length) } $unzip.Close() $unzip.Dispose() $decompressed = $unzippedMem.ToArray() } catch { throw; } finally { $ErrorActionPreference = $eaPreferencesBackup } return $encoding.GetString($decompressed) } } # SIG # Begin signature block # MIITBQYJKoZIhvcNAQcCoIIS9jCCEvICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUpzjWtjoakos5HSohw9EP6bCt # 2Oqggg5rMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B # AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG # A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh # d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg # Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV # UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu # dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q # WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC # i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4 # ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3 # +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI # fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd # BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG # CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB # Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro # YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV # HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y # MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf # plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y # 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq # IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3 # DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh # dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD # QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE # BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT # eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow # mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0 # jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu # ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh # d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz # C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB # o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO # BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw # Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90 # cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx # oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy # bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV # HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa # 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH # bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73 # BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR # EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW # yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu # e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw # ggXOMIIEtqADAgECAgocYLQHAAAAAAMMMA0GCSqGSIb3DQEBCwUAMEYxFTATBgoJ # kiaJk/IsZAEZFgVsb2NhbDEUMBIGCgmSJomT8ixkARkWBHBvcnMxFzAVBgNVBAMT # DnBvcnMtREItU1JWLUNBMB4XDTE2MDQyNjExNTUwOVoXDTE4MDQyNjExNTUwOVow # gY8xFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEUMBIGCgmSJomT8ixkARkWBHBvcnMx # DjAMBgNVBAsTBUZpcm1hMRQwEgYDVQQLEwtaYW1lc3RuYW5jaTEYMBYGA1UEAxMP # TWlyb3NsYXYgTWVkdW5hMSAwHgYJKoZIhvcNAQkBFhFtZWR1bmFAcG9ycy1zdy5j # ejCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALetZGc/1Qa91Sj5NcbI # FjpqMfJMwEMnvmOzFWqA6+6K9X0732GcgKtyXqw0LitY1XZDEppxBTlivPHXVVsb # Y1cLqWsdICAklMdq9JWybVDSUiPhog5QIm107hx/xBOqdAGoksToFoUOOkrwB6yt # OZXbpiGSs4j7n64Z2zn5dZU5IafaZ4Z2OizLnjaNS+44h3v1FWKnEAVweynu0KSq # DtOi5cXEvbvFIK+/Ey0dzcZXY2vK0INxOlVvRtmJOv+0bRRFv6/Z1GHD8rHsL0oJ # yP5nquvHD3o0ikNpBcAXqEMl1emNxY0Qg4EvZLgOwKbxuE4P2dFulD56pgIISsC1 # XLMCAwEAAaOCAnIwggJuMD0GCSsGAQQBgjcVBwQwMC4GJisGAQQBgjcVCIOEoS6C # 59UEgbWVNoTN0CWG6fw/WYTdhUuHtfBuAgFkAgEEMBMGA1UdJQQMMAoGCCsGAQUF # BwMDMA4GA1UdDwEB/wQEAwIHgDAbBgkrBgEEAYI3FQoEDjAMMAoGCCsGAQUFBwMD # MB0GA1UdDgQWBBTvT3cMkc1mrLf8dyTScnKZkUbvAjAcBgNVHREEFTATgRFtZWR1 # bmFAcG9ycy1zdy5jejAfBgNVHSMEGDAWgBRbhvm5YOeWkaF1Awimwcg3cfuI/zCB # ygYDVR0fBIHCMIG/MIG8oIG5oIG2hoGzbGRhcDovLy9DTj1wb3JzLURCLVNSVi1D # QSxDTj1EQi1TUlYsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENO # PVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cG9ycyxEQz1sb2NhbD9jZXJ0 # aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJp # YnV0aW9uUG9pbnQwgb8GCCsGAQUFBwEBBIGyMIGvMIGsBggrBgEFBQcwAoaBn2xk # YXA6Ly8vQ049cG9ycy1EQi1TUlYtQ0EsQ049QUlBLENOPVB1YmxpYyUyMEtleSUy # MFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9cG9ycyxE # Qz1sb2NhbD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNh # dGlvbkF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAQEAl1Q1umCNlSbkV6pRaweZ # OBYZT2h6chfXaXtNeaELolOmXjzupXeGkykqmuytvKMC7TOZqdT/O1eccwoiBUlj # TTLK7ZKFXSI3ECwAYBpxCqW1pk88pK29jg7htvmPcOWETGWceTASlVnSD8s1bs/9 # 8GYaTqUlLMas47pARTekGdOZV3pSTLJzqC88/W+J3NOQiVTq88vpCcEoobsLYC4x # 2crHSxJCS3dYSsFV6l/Vs0ncOpLxAS3AJQ4yPKNu/EC2mXAnWJ/8DaJ8rtadBALL # UrCP/dfKEHbPwXWjxgU+t/LKzy9nf4ixXubmg0QR1z7eHgqQiR4AWkKVV6GFQIIf # fjGCBAQwggQAAgEBMFQwRjEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRQwEgYKCZIm # iZPyLGQBGRYEcG9yczEXMBUGA1UEAxMOcG9ycy1EQi1TUlYtQ0ECChxgtAcAAAAA # AwwwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZI # hvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcC # ARUwIwYJKoZIhvcNAQkEMRYEFFZdO/NM4/UB7i1iOxhZuWva3tvEMA0GCSqGSIb3 # DQEBAQUABIIBAHji1+6DbF4iYmARWFpXppN2TeHxxCx1Nm35ue/J9R4QX/RnfCOF # RdSzAmZ/tWMurRrKqggTgy4PMxiuYIuZK89SWNaexyt4/SeZ2PDSJ4LcKoQJkFsz # xy5DGOnM3+vtVDhEJlhvQ7Y5UI8DGHjqWK6QqG8ZMo/+wbIc6xvbTnXsAjD8+HlC # KM1VhZtX6Solgi3K2Sjzf7GkoYrFy0lQ6WCGTik6cpwZLRz7fQv3oGT2eWdCqzjI # 8WhtrOhvTqG/KdUBdpiJFDc3ZG452KvFwy8OocyACI9KvQnEQ4fsWipaplEPonK8 # BEV+EF0esKw2fgARwcA7GUAFNwUSMOJnNbuhggILMIICBwYJKoZIhvcNAQkGMYIB # +DCCAfQCAQEwcjBeMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29y # cG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vydmlj # ZXMgQ0EgLSBHMgIQDs/0OMj+vzVuBNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZI # hvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTYwNDI2MTIwNjI2 # WjAjBgkqhkiG9w0BCQQxFgQU8Yu+3PfFt3uMdGQKTACLW9O/wIswDQYJKoZIhvcN # AQEBBQAEggEAADA0fRuloX+aba1EDshA7ND93rfnIphnX75Ht8SadBfSp8lOzeDv # JtQjKugHJWZb8UPtVR+A/0YXQ3QW8qy6zO5gkKMdYqZU+a+MPlbB1nJGre/W2ydk # zlKCkFCndiBF5Tq0HDdR+lcB1IqV6Irh8XlOnAzAYoYoHWFSJl0fhiEO2jYJCKKi # jtnvtOTRRCita5f5ZaQDvdBBF73HY1mdZeibiDrW9CdUoCOBQ8cW1pv+cKsHU8d3 # jaZ+eFSlDbioYHfg49uAtR2LcVBVnhN4kPpwyF+pjn1LQcn8mxI6gZNMvjlBylCr # Xq8OVT1sIQsvGuM5J0rFgcjWOTTkEEFuZQ== # SIG # End signature block |