diff --git a/ListadoPfsUsuarios.ps1 b/ListadoPfsUsuarios.ps1 index 9985938..32a22b4 100644 --- a/ListadoPfsUsuarios.ps1 +++ b/ListadoPfsUsuarios.ps1 @@ -49,7 +49,7 @@ Function Add-Lista { [System.Security.Cryptography.X509Certificates.X509Certificate2]$ccc = $null foreach($c in $obj.Value) { $ccc = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new([System.Convert]::FromBase64String($c.crt)) - $ccc.FriendlyName = $c.descr.'#cdata-section' + $ccc.FriendlyName = [System.Web.HttpUtility]::HtmlDecode($c.descr.'#cdata-section') $objTmp = $ccc | Select *, @{N='IsCA'; E={ $fromCA }} ` , @{N='IsServer'; E={ -not $fromCA -and $_.EnhancedKeyUsageList.ObjectId -contains $oidSRV }} ` , @{N='IsClient'; E={ -not $fromCA -and $_.EnhancedKeyUsageList.ObjectId -contains $oidCLI }} ` @@ -105,9 +105,101 @@ Function Add-Lista { } } +Function Get-BeginEndWO { + Param([Parameter(Mandatory=$true, Position=0)][string]$path) + + #OPNsense saves information on how to decrypt it in the xml encrypted file. + #pfSense does'nt. + + #Check if "^Version: OPNsense" exists in the line 2 + [string[]]$text = Get-Content $path -Encoding UTF8 -ErrorAction SilentlyContinue + if ($text[1] -match '^Version: OPNsense') { + [int]$start = 5 + } + else { + [int]$start = 1 + } + + #Remove 1st and last lines + $text[$start..($text.Count-2)] +} + +Function Decrypt { + Param([Parameter(Mandatory=$true,Position=0)][string]$fileIn + ,[Parameter(Mandatory=$true,Position=1)][string]$fileOut + ,[Parameter(Mandatory=$false,Position=2)][string]$pass) + + # If $openSSL is not '', we will look for the openSSL.exe available with openVPN install. + # You can define a value for $openSSL if you have a valid openssl executable path. + [string]$openSSL = '' + if ($openSSL -eq '') { + #Look for openvpn installation + [string]$rutaREG = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN" + if (-not (Test-Path($rutaREG))) { + Write-Host 'No openvpn installation found. openssl.exe is part of the openVPN installation. ' + ` + 'If you have another openssl.exe available path, you can redefine the $openSSL variable at line 92.' -BackgroundColor DarkRed + Exit 3 + } + + $openSSL = ((Get-ItemProperty -Path $rutaREG).exe_path).Replace("openvpn.exe", "openssl.exe") + } + + if ($pass -eq '') { + [System.Security.SecureString]$pwd = Read-Host "Password XML File:" -AsSecureString + $pass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pwd)) + } + + & "$($openSSL)" enc -d -aes-256-cbc -in "$($fileIn)" -out "$($fileOut)" -salt -md md5 -k ''$($pass)'' +} + +Function Get-ConfigFile { + Param([Parameter(Mandatory=$true,Position=0)][string]$filePath ` + ,[Parameter(Mandatory=$true,Position=1)][ref]$xml) + + if (-not (Test-Path -Path $filePath)) { + Write-Host "File '$cfg' not found. Process stopped." -BackgroundColor DarkRed + Exit 1 + } + + [bool]$encrypted = $false + try { + $xml.Value = Get-Content $filePath -Encoding UTF8 + } + catch { + $encrypted = $true + } + + if ($encrypted -eq $true) { + #Encrypted xml file + [string[]]$cifrado = Get-BeginEndWO -path $filePath + $f1Cin = New-TemporaryFile + $f1Cou = New-TemporaryFile + try { + [IO.File]::WriteAllBytes($f1Cin.FullName, [System.Convert]::FromBase64String($cifrado)) + Decrypt -fileIn $f1Cin.FullName -fileOut $f1Cou.FullName + + # Check if file exists + if (-not (Test-Path $f1Cou.FullName) -or (Get-Item $f1Cou.FullName).Length -eq 0) { + Write-Host "Unable to decrypt file. Process stoped." -BackgroundColor DarkRed + Exit 4 + } + + # File exists + $xml.Value = Get-Content $f1Cou.FullName -Encoding UTF8 + } + catch { + Write-Host "Error decrypting xml file: Bad password. Process stoped." -BackgroundColor DarkRed + Exit 5 + } + finally { + Remove-Item $f1Cin.FullName -Force + Remove-Item $f1Cou.FullName -Force + } + } +} Function Usuarios { - [array]$usr = $fxml.pfsense.system.user + [array]$usr = $product.system.user foreach($a in $usr) { if ([bool]($a.PSobject.Properties.name -match 'disabled')) { $a.disabled ='Disabled' @@ -121,7 +213,7 @@ Function Usuarios { # BODY # -# Check if param 0 is assigned +# Look for assigned param 0 if ($FilePath -eq $null -or $FilePath -eq '') { [string]$cfg = "$($env:UserProfile)\Downloads\mydefault_config_file.xml" } @@ -130,23 +222,30 @@ else { [string]$cfg = $FilePath } -if (-not (Test-Path -Path $cfg)) { - Write-Host "File '$cfg' not found. Process stopped." -BackgroundColor DarkRed - Exit 1 -} +#Read XML pfSense config file (UTF8 Encoding) +[xml]$fxml = $null +Get-ConfigFile -filePath $cfg -xml ([ref]$fxml) + +#Check for pfSense/OPNsense products +if ($fxml.ChildNodes.Count -eq 2) { + [System.Xml.XmlElement]$product = $fxml.ChildNodes[1] + if ($product.Name -notin ('pfsense','opnsense')) { + Write-Host 'The xml file does not contains a pfSense or OPNsense backup. Process stoped.' -BackgroundColor DarkRed + Exit 6 + } +} +Remove-Variable fxml -ErrorAction SilentlyContinue -#Read XML pfSense config file -[xml]$fxml = Get-Content $cfg -Encoding Default #Get the CRL revocation list [DateTime]$time0 = '1970-01-01' [array]$listaR = @() -foreach($r in $fxml.pfsense.crl) { +foreach($r in $product.crl) { $listaR += $r.cert | Select @{N='listRev';E={$r.descr.'#cdata-section'}}, caref, refid, reason, @{N='revDate';E={$time0.AddSeconds($_.revoke_time)}} } #UserList -[array]$listaU = $fxml.pfsense.system.user +[array]$listaU = $product.system.user foreach($a in $listaU) { if ([bool]($a.PSobject.Properties.name -match 'disabled')) { $a.disabled ='Disabled' @@ -154,24 +253,25 @@ foreach($a in $listaU) { } #GroupList -[array]$listaG = $fxml.pfsense.system.group | Where-Object { $_.name -ne 'all' } | Select-Object name, member +[array]$listaG = $product.system.group | Where-Object { $_.name -ne 'all' } | Select-Object name, member #Add CA Certificates to $listaC (WITHOUT private keys) [array]$listaC = @() -Add-Lista -lista ([ref]$listaC) -obj ([ref]$fxml.pfsense.ca) -fromCA $true +Add-Lista -lista ([ref]$listaC) -obj ([ref]$product.ca) -fromCA $true #Add user/server certificates to $listaC (WITHOUT private keys) -Add-Lista -lista ([ref]$listaC) -obj ([ref]$fxml.pfsense.cert) -fromCA $false +Add-Lista -lista ([ref]$listaC) -obj ([ref]$product.cert) -fromCA $false #Note: User Certificates created with old pfSense versions can set the EnhancedKeyUsageList property to -Remove-Variable fxml, r, listaR, listaU, listaG +Remove-Variable product, r, listaR, listaU, listaG -ErrorAction SilentlyContinue ### ### Ruta de archivo CSV destino (delimitado por punto y coma) -### (Se abre automáticamente desde Excel Español sin importar) +### (Se abre automáticamente desde Excel Español sin proceso de importación) ### [string]$rutaExportacion = "$($env:userprofile)\Downloads\usuariospfsense.csv" +[char]$csvDelimiter = ';' #List of CA Certificates #Write-Output "`nCA Certificates" @@ -189,7 +289,7 @@ Remove-Variable fxml, r, listaR, listaU, listaG #Export to CSV $listaC | Where-Object {-not ($_.isCA -or $_.isServer)} | ` Select FriendlyName, @{N='revokedOn'; E={[string]($_.revokedOn)}}, revDate, Udisabled, Uexpires, @{N='UGrupos'; E={[string]($_.UGrupos)}}, sSubject, NotBefore, NotAfter, Usuario | ` - Sort-Object -Property FriendlyName, Usuario | Export-Csv -Path $rutaExportacion -NoTypeInformation -Delimiter ';' -Encoding 'UTF8' + Sort-Object -Property FriendlyName, Usuario | Export-Csv -Path $rutaExportacion -NoTypeInformation -Delimiter $csvDelimiter -Encoding 'UTF8' -ErrorAction SilentlyContinue #List of Dupicated SerialNumbers (per CA) @@ -197,4 +297,4 @@ $listaC | Where-Object {-not ($_.isCA -or $_.isServer)} | ` #$listaC | Select sIssuer, SerialNumber, FriendlyName, DnsNameList, sSubject, revokedOn | Group-Object -Property sIssuer, SerialNumber | ` # Where-Object {$_.Count -gt 1} | Select -ExpandProperty Group | ft -$listaC \ No newline at end of file +$listaC