Public/New-KNSession.ps1
<#
.SYNOPSIS Authentificate on Keenetic device and save session parameters .DESCRIPTION Pass through auth challenge on given device and output result for future use. Please note about session expiration after few minutes of inactivity. .EXAMPLE PS C:\> Get-Credential | New-KNSession -Target https://my.keenetic.com -AsDefaultSession Log onto Keenetic Router on given URL and credentials and save session parameters in memory for further use. .EXAMPLE PS C:\>$Session = New-KNSession -Credential (Get-Credential) Log onto Keenetic Router on default address 'http://my.keenetic.net' and return session parameters as an object. .LINK https://github.com/ryzhovau/keenetic-powershell #> function New-KNSession { [CmdletBinding()] [OutputType([KNSession])] param( # URL to connect, like 'http://192.168.0.1' or 'https://my.keenetic.pro'. Presumes 'http://my.keenetic.net' by default. [System.Uri]$Target = 'http://my.keenetic.net', # User name and password for target device. User must have 'http' tag to interact with core interface. [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [pscredential]$Credential, # Store session parameters to $DefaultKNSession instead of returning object [Switch]$AsDefaultSession ) Begin { function Get-Hash ( [string]$String, [string]$Algo) { $HashEngine = [System.Security.Cryptography.HashAlgorithm]::create($algo) $UTF8 = New-Object -TypeName System.Text.UTF8Encoding [System.BitConverter]::ToString($HashEngine.ComputeHash($utf8.GetBytes($String))).ToLower().Replace('-', '') } } Process { try { # First, we should catch X-NDM-Challenge/X-NDM-Realm headers from 401 response Invoke-WebRequest -Uri "$($Target)auth" -SessionVariable WebSession | Out-Null } catch [System.Net.WebException] { $Response = $_.Exception.Response If ($Response.StatusCode -ne 'Unauthorized') { throw [System.Net.WebException] "Unexpected status received.`n$($_.Exception)" } <# Challenge is to send POST request with following data { login: login, password: sha256(token + md5(login + ':' + realm + ':' + password)) } #> $Token = $Response.Headers["X-NDM-Challenge"] $Realm = $Response.Headers["X-NDM-Realm"] Write-Verbose "X-NDM-Challenge header is $($Token)" Write-Verbose "X-NDM-Realm header is $($Realm)" $MD5Hash = Get-Hash "$($Credential.GetNetworkCredential().UserName):$($Realm):$($Credential.GetNetworkCredential().Password)" 'MD5' $SHA256Hash = Get-Hash "$($Token)$($MD5Hash)" 'SHA256' $PostBody = @{"login"=$Credential.GetNetworkCredential().UserName; "password"=$SHA256Hash} | ConvertTo-Json Write-Verbose "Challenge request body is:`n$($PostBody)" try { Invoke-WebRequest -Uri "$($Target)auth" -WebSession $WebSession -Method Post -Body $PostBody -ContentType 'application/json' | Out-Null } catch { throw [System.Net.WebException] "Logon failed.`n$($_.Exception)" } $KNSession = [KNSession]@{ Target = $Target Credential = $Credential WebSession = $WebSession } if ($AsDefaultSession) { $Global:DefaultKNSession = $KNSession } else { return $KNSession } } } End { } } |