public/cisa/exchange/ConvertFrom-MailAuthenticationRecordDkim.ps1
|
<# .SYNOPSIS Returns structured RFC compliant object from DKIM record .DESCRIPTION Adapted from: - https://cloudbrothers.info/en/powershell-tip-resolve-spf/ - https://github.com/cisagov/ScubaGear/blob/main/PowerShell/ScubaGear/Modules/Providers/ExportEXOProvider.psm1 - https://xkln.net/blog/getting-mx-spf-dmarc-dkim-and-smtp-banners-with-powershell/ - DKIM https://datatracker.ietf.org/doc/html/rfc6376 ``` record : v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPkb8bu8RGWeJGk3hJrouZXIdZ+HTp/azRp8IUOHp5wKvPUAi/54PwuLscUjRk4Rh3hjIkMpKRfJJXPxWbrT7eMLric 7f/S0h+qF4aqIiQqHFCDAYfMnN6V3Wbke2U5EGm0H/cAUYkaf2AtuHJ/rdY/EXaldAm00PgT9QQMez66QIDAQAB; keyType : rsa hash : {sha1, sha256} notes : publicKey : MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPkb8bu8RGWeJGk3hJrouZXIdZ+HTp/azRp8IUOHp5wKvPUAi/54PwuLscUjRk4Rh3hjIkMpKRfJJXPxWbrT7eMLric7f/S0h+qF4aqIiQqHF CDAYfMnN6V3Wbke2U5EGm0H/cAUYkaf2AtuHJ/rdY/EXaldAm00PgT9QQMez66QIDAQAB validBase64 : True services : {*} flags : warnings : ``` .EXAMPLE ConvertFrom-MailAuthenticationRecordDkim -DomainName "microsoft.com" Returns [DKIMRecord] or "Failure to obtain record" .LINK https://maester.dev/docs/commands/ConvertFrom-MailAuthenticationRecordDkim #> function ConvertFrom-MailAuthenticationRecordDkim { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Colors are beautiful')] [OutputType([DKIMRecord], [System.String])] [cmdletbinding()] param( [Parameter(Mandatory)] # Domain name to check. [string]$DomainName, # DNS-server to use for lookup. [ipaddress]$DnsServerIpAddress = "1.1.1.1", # DKIM DNS record Name to retrieve. [Parameter(Mandatory)] [string]$DkimDnsName, # Use a shorter timeout value for the DNS lookup. [switch]$QuickTimeout, # Ignore hosts file for domain lookup. [switch]$NoHostsFile ) begin { #TODO, add additional regexs for additional options, pop selector on call #[DKIMRecord]::new("v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPkb8bu8RGWeJGk3hJrouZXIdZ+HTp/azRp8IUOHp5wKvPUAi/54PwuLscUjRk4Rh3hjIkMpKRfJJXPxWbrT7eMLric7f/S0h+qF4aqIiQqHFCDAYfMnN6V3Wbke2U5EGm0H/cAUYkaf2AtuHJ/rdY/EXaldAm00PgT9QQMez66QIDAQAB;") class DKIMRecord { [string]$record [string]$keyType = "rsa" #k [string[]]$hash = @("sha1", "sha256") #h [string]$notes #n [string]$publicKey #p [bool]$validBase64 [string[]]$services = "*" #s (*,email) [string[]]$flags #t (y,s) [string[]]$warnings hidden $option = [Text.RegularExpressions.RegexOptions]::IgnoreCase hidden $matchRecord = "^v\s*=\s*(?'v'DKIM1)\s*;\s*" hidden $matchKeyType = "k\s*=\s*(?'k'[^;]+)\s*;\s*" hidden $matchPublicKey = "p\s*=\s*(?'p'[^;]+)\s*;\s*" DKIMRecord([string]$record) { $this.record = $record $match = $record -match $this.matchRecord if (-not $match) { $this.warnings = "v: Record does not match version format" break } $p = [regex]::Match($record, $this.matchPublicKey, $this.option) $this.publicKey = ($p.Groups | Where-Object { $_.Name -eq "p" }).Value $bytes = [System.Convert]::FromBase64String(($p.Groups | Where-Object { $_.Name -eq "p" }).Value) $this.validBase64 = $null -ne $bytes } } } process { $matchRecord = "^v\s*=\s*(?'v'DKIM1)\s*;\s*" $dkimSplat = @{ Name = $DkimDnsName Type = "TXT" Server = $DnsServerIpAddress NoHostsFile = $NoHostsFile QuickTimeout = $QuickTimeout ErrorAction = "Stop" } try { Write-Verbose "Domain: $DomainName. Finding DKIM information for $DkimDnsName" if ( $isWindows -or $PSVersionTable.PSEdition -eq "Desktop" ) { $dkimRecord = [DKIMRecord]::new((Resolve-DnsName @dkimSplat | ` Where-Object { $_.Type -eq "TXT" } | ` Where-Object { $_.Strings -match $matchRecord }).Strings) } else { $cmdletCheck = Get-Command "Resolve-Dns" -ErrorAction SilentlyContinue if ($cmdletCheck) { $dkimSplatAlt = @{ Query = $dkimSplat.Name QueryType = $dkimSplat.Type NameServer = $dkimSplat.Server ErrorAction = $dkimSplat.ErrorAction } $record = ((Resolve-Dns @dkimSplatAlt).Answers | ` Where-Object { $_.RecordType -eq "TXT" } | ` Where-Object { $_.Text -imatch $matchRecord }).Text if ($record) { $dkimRecord = [DKIMRecord]::new($record) } else { return "Record does not exist" } } else { Write-Verbose "`nFor non-Windows platforms, please install DnsClient-PS module." Write-Verbose "`n Install-Module DnsClient-PS -Scope CurrentUser`n" -ForegroundColor Yellow return "Missing dependency, Resolve-Dns not available" } } } catch [System.Management.Automation.CommandNotFoundException] { Write-Verbose $_ return "Unsupported platform, Resolve-DnsName not available" } catch { Write-Verbose $_ return "Failure to obtain record" } return $dkimRecord } } |