Scripting VPN Credentials - powershell

I can easily create a VPN connection through the PowerShell command Add-VpnConnection, however it doesn't seem able to specify any credentials (there is no option to specify username/password). As a workaround I tried to use -RememberCredential option in Add-VpnConnection and to pass the credentials by forcing a connection through rasdial command, yet even though the connection succeeds Windows doesn't save the credentials :(
Add-VpnConnection -Name xxxxx ...
rasdial xxxxx user password
rasdial xxxxx /disconnect
Is it possible some way ?

Maybe it is too late, but I had same task and here is solution:
$vpnName = "YourVpnName"
$vpnServerAddress = "YourVpnServerAddress"
$vpnUserName = "YourVpnUserName"
$vpnPassword = "YourVpnPassword"
$vpn = Get-VpnConnection -Name $vpnName
if($vpn -eq $null) {
Add-VpnConnection -Name $vpnName -ServerAddress $vpnServerAddress -TunnelType Pptp -EncryptionLevel Required -PassThru
echo "vpn created"
}
if($vpn.ConnectionStatus -eq "Disconnected"){
$cmd = $env:WINDIR + "\System32\rasdial.exe"
$expression = "$cmd ""$vpnName"" $vpnUserName $vpnPassword"
Invoke-Expression -Command $expression
}

Related

Issues with colon (:) in when next to variable in PowerShell

I am trying to get the following to work so I can automate some SCP uploads I need to do. I believe the problem is how ${user}#${device} is being interpreted.
$user = "user1"
$device = "server1"
Start-Process 'C:\Program Files\PuTTY\pscp.exe' `
-ArgumentList ("c:\temp\myfile.txt ${user}#${device}:/shared/tmp/") -NoNewWindow
I've tried $user#$device (powershell barks about syntax), $user#${device}and ${user}#${device} (these tell me you can't copy from local to local which indicates in is not parsing the :/shared/tmp/ correctly.)
You can also escape the : with `:
"c:\temp\myfile.txt ${user}#${device}`:/shared/tmp/"
As always, unless you have a specific reason for using Start-Process: don't bother. Use the call operator (&) instead.
This worked perfectly fine when I just tested it:
$user = 'user1'
$device = 'server1'
$params = 'c:\temp\myfile.txt', "${user}#${device}:/shared/tmp/"
& 'C:\Program Files\PuTTY\pscp.exe' #params
Try this:
$user = "user1"
$device = "server1"
Start-Process 'C:\Program Files\PuTTY\pscp.exe' `
-ArgumentList ("c:\temp\myfile.txt {$($user)}#{$($device)}:/shared/tmp/") -NoNewWindow
try this:
$user = "user1"
$device = "server1"
$Program='C:\Program Files\PuTTY\pscp.exe'
$Arguments="c:\temp\myfile.txt {0}#{1}:/shared/tmp/ -NoNewWindow" -f $user, $device
Start-Process $Program $Arguments

Create a script which disables a Windows Account on a target host. Only Admin can execute this action

I want to create a PowerShell script which will disable the windows account, the target host name will be provided as an argument. Only admin should be able to execute this task.
This is what I have tried. Could someone please tell me if this approach is right or is there any better way to do this.
param( [Parameter(Mandatory=$true)] [String] $TargetHost ,
[Parameter(Mandatory=$true)] [String] $TargetUserName ,
[String] $User ,
[String] $Password)
# Set up a trap to properly exit on terminating exceptions
trap [Exception] {
write-error $("TRAPPED: " + $_)
exit 1
}
function DeactivateAccount($TargetHost , $TargetUserName ,$User , $Password){
$TargetHost = $TargetHost #Target Host on which windows account deactivation will be done.
$TargetUserName = $TargetUserName #User Name of Target.
$Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() #Domain name of the localhost.
$localHost = [System.Net.Dns]::GetHostName()
$localIP = [System.Net.Dns]::GetHostAddresses("$localHost")
#if TargetHost and LocalHost are same.
if($localHost -like $TargetHost -OR $localIP -like $TargetHost) {
if($Domain -eq [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()){
$process = net user $TargetUsername /domain /active:no #Performs the operation on the domain controller in the computer's primary domain.
} else {
$process = net user $TargetUsername /active:no
}
Write-host " $TargetUsername account deactivated "
}
#If TargetHost is remote Host.
else {
$User = $User #Creds to perform admin function.
$Password = $Password
$SecurePassword = new-Object System.Security.SecureString #Convert password into secure string.
$Password.ToCharArray() | % { $SecurePassword.AppendChar($_) }
$Cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist "$User",$securePassword
$newSession = New-PSSession -ComputerName "$TargetHost" -credential $Cred #Used PSSession for persistent connection and credentials to Specify a user account that has permission to perform this action.
$export_username = Invoke-Command -Session $newSession -ScriptBlock {$username=args[1]} # Invoke-Command command uses the Session parameter(here newSession) to run the commands in same session.
if($Domain -eq [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()){
$process = Invoke-Command -Session $newSession -ScriptBlock {net user $username /domain /active:no}
} else {
$process = Invoke-Command -Session $newSession -ScriptBlock {net user $username /active:no}
}
Write-host " $TargetUsername account deactivated "
Remove-PSSession $newSession # Closes Windows PowerShell sessions.
}
if(-not $?) { # Returns true if last command was successful.
Write-Error "Windows Deactivation Failed!!"
exit 1
}
}
DeactivateAccount($TargetHost , $TargetUserName ,$User , $Password)
Couple of things:
Your meant to show some code to show you tried but since you're new to Powershell I'll let that slide :)
Is it a local windows account you are trying to disable or an AD one? For the purpose of this I'll assume local.
Grab this module: https://gallery.technet.microsoft.com/PowerShell-Module-to-255637a3
The dude basically made a module for exactly what you want to do :)
Note: If you have Powershell 5.1+ you won't need the module they added new cmdlets to do this natively.
Credential-wise I wouldn't worry, Powershell can't bypass windows security, it will execute with the permissions of the user that ran the script unless your script specifically gives credentials for another user in the commands.
Let me know how you get on.

How to log into remote servers?

I currently have a VBScript that reads a list of servers, and attempts to verify the password of a specific userid. The userid is locally on that server. I am checking to see that the password is not set to the default (I want to make sure it was changed to something else).
The "list of servers" can be a mix of IP addresses, hostnames (like Rocky), or fully qualified DNS names (like rocky.bigcompany.com). The servers are a mixture of physical and virtual devices, and may or may not be on a domain.
The existing VBScript I wrote handles all this, and works fine. I'm trying to re-write this same program in Powershell, and It's not working.
Here's the function I have in VBScript that does what I want:
Function LoginToServer(Computer, username, password)
'this function will log into a server
On Error Resume next
Set locator = CreateObject("WbemScripting.SWbemLocator")
Set wmi = locator.ConnectServer(computer, "root\cimv2", username, password)
'check the error code and see if we logged in successfully
LoginRC = Err.Number
If LoginRC <> 0 Then
msg = "Could not log into server: " & CStr(computer) & " With ID: " & CStr(username)
lfo.lmsg "B", "WARN", msg
Else
msg = "Server: " & CStr(computer) & " Logged in successfully as: " & CStr(username)
lfo.lmsg "B", "INFO", msg
End If
wmi.Security_.ImpersonationLevel = 3
'return the code back to calleer
LoginToServer = LoginRC
End Function
… and here's what I've tried to do in PowerShell:
Param($ComputerName = "LocalHost")
$ErrorActionPreference = "Stop"
# Actual Code starts here
Write-Host "Attempting to ping server: $ComputerName"
$IPResult = Test-Connection -ComputerName $ComputerName -Quiet
if ($IPResult -eq "TRUE") {
Write-Host "Ping OK - now attempting to log in"
try {
$ID = "userid"
$PSW = "password"
$password = ConvertTo-SecureString $PSW -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($ID, $password)
$sesh = New-PSSession -ComputerName $ComputerName -Credential $cred
} catch {
Write-Host "Error caught"
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
} finally {
$Time = Get-Date
"$Time Computer: $ComputerName ERROR: $ErrorMessage ITEM: $FailedItem" |
Out-File c:\temp\TestCredScript.log -Append
}
} else {
Write-Host "Could not ping server"
}
How do I log into these remote computers with an ID and Password using PowerShell?
Your two code samples do different things. The VBScript code connects via WMI whereas the PowerShell code tries to establish a PowerShell session. For the latter you need PowerShell Remoting enabled, which you probably don't have.
While you probably may want to enable PSRemoting anyway, you can also use WMI from PowerShell. The Get-WmiObject cmdlet allows you to provide credentials and impersonation level, so you don't need to establish a connection first like you need to do with VBScript (if you want to use explicit credentials).
Example querying the Win32_Process class on a remote computer:
$computer = '...'
$username = 'userid'
$password = 'password'
$pw = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object Management.Automation.PSCredential ($username, $pw)
Get-WmiObject -Computer $computer -Namespace 'root\cimv2' -Class Win32_Process -Impersonation 3 -Credential $cred
See here for further information.

Powershell remote script error Error during CryptAcquireContext

I just run a simple script with invoke-command -computer [servername] -scriptblock {powershell.exe D:\test\script.ps1}
If I run the script manually in the box and then run the remote script again the error does not appear anymore but I don't like having to login manually to the box and run the script to be able fix this error especially with so many servers. Can anyone help me on this. Thanks
Error during CryptAcquireContext. [servername] :
Error msg : The requested operation cannot be completed. The computer must be trusted for delegation and the current user account must be configured to allow delegation.
Error code : 80090345
The script running on the server that gets the error part
$fciv = "D:\test\fciv.exe"
$fcivLog = "D:\test\fcivLog.txt"
$xmlPath = "D:\test\server.xml"
& $fciv -v -bp "\\servername\folder1" -XML $xmlPath | Out-File $fcivLog
Here is a PowerShell function, that should work on PowerShell version 2.0, to calculate MD5 hashes:
function Get-MD5FileHash {
[CmdletBinding()]
param (
[string] $Path
)
$MD5 = [System.Security.Cryptography.MD5]::Create();
$Stream = [System.IO.File]::OpenRead($Path);
$ByteArray = $MD5.ComputeHash($Stream);
[System.BitConverter]::ToString($ByteArray).Replace('-','').ToLower();
$Stream.Dispose();
}
Get-MD5FileHash -Path C:\test\test.xlsx;
I tested it out on PowerShell 4.0 on Windows 8.1, and it works great!
This question is quite old, and a work around has been found. But it still does not resolve the primary issue of delegation for programs using CryptAcquireContext
I had the very same problem with another program (BiosConfigUtility, from HP).
I solved it by allowing delegation between my computer, and remote computers.
To enable delegation on your client :
Enable-WSManCredSSP -Role Client -DelegateComputer host.domain.com -Force
To enable delegation on the remote computer :
Enable-WSManCredSSP -Role Server –Force
See this post : https://devblogs.microsoft.com/scripting/enable-powershell-second-hop-functionality-with-credssp/ for more info
You can always use scheduled tasks instead. This script changes the bios from legacy to uefi boot using biosconfigutility64 (or erase setup password for surplusing). Remotely running it directly will give that cryptacquirecontext error.
# usage: .\hpuefi.ps1 comp1,comp2,comp3
$s = new-pssession $args[0]
$src = 'Y:\hp-bios-new'
$dst = 'c:\users\admin\documents\hp-bios-new'
icm $s { if (! (test-path $using:dst)) { mkdir $using:dst > $null } }
$s | % { copy $src\biosconfigutility64.exe,$src\pass.bin,$src\uefi.bat,$src\uefi.txt $dst -tosession $_ }
icm $s {
# ERROR: Error during CryptAcquireContext. LastError = 0x80090345
# & $using:dst\uefi.bat
# 2>&1 must go last
$action = New-ScheduledTaskAction -Execute 'cmd' -argument '/c c:\users\admin\documents\hp-bios-new\uefi.bat > c:\users\admin\documents\hp-bios-new\uefi.log 2>&1'
Register-ScheduledTask -action $action -taskname uefi -user system > $null
Start-ScheduledTask -TaskName uefi
# wait
while ((Get-ScheduledTask -TaskName uefi).State -ne 'Ready') {
Write-Verbose -Message 'Waiting on scheduled task...' }
Get-ScheduledTask uefi | Get-ScheduledTaskInfo | ft
# remove-scheduledtask uefi
# shutdown /r /t 0
}
uefi.bat:
%~dp0BiosConfigUtility64.exe /set:"%~dp0uefi.txt" /cspwdfile:"%~dp0pass.bin"
exit /b %errorlevel%

rdesktop shell escaping issue

I'm trying to send this:
Get-WmiObject Win32_PNPEntity |Where{$_.DeviceID.StartsWith("PCI\VEN_10DE") -or $_.DeviceID.StartsWith("PCI\VEN_1002")}
over rdesktop like:
rdesktop -a8 209.** -u ** -p ** -s "cmd.exe /K powershell.exe Get-WmiObject Win32_PNPEntity |Where{\$_.DeviceID.StartsWith("PCI\VEN_10DE") -or $_.DeviceID.StartsWith("PCI\VEN_1002")}"
But windows' shell says:
'Where{$_.DeviceID.StartsWith' is not recognized as an internal or externa....
What am I doing wrong?
why not using powershell wmi remoting?
$cred = get-credential
Get-WmiObject Win32_PNPEntity -computerName MyRemoteComputerName - credential $cred |Where{$_.DeviceID.StartsWith("PCI\VEN_10DE") -or $_.DeviceID.StartsWith("PCI\VEN_1002")}
-credential are only needed if the actual user running powershell isn't administrator of remote machine.
Hi I needed to do some thing like this once so i wrote some code that can send any ps code to a remote computes and display the results in the ps window on your pc.
Just remember to enable powershell remoting on both pc's.
function remote-pscode ($ServerName,$UserName,$password,$PSCode)
{
$global:RemoteCode = $args[0]
Write-Host $RemoteCode
$conprops = (Get-Host).UI.RawUI
$buffsize = $conprops.BufferSize
$buffsize.Height = 800
$conprops.BufferSize= $buffsize
# Set the user name you would like to use for the connection
$global:RemoteUserName = $UserName
$global:RemoteServerName = $ServerName
# Set the password you would like to use for the connection
# Check to see if you have a file on you drive c:\cred.txt with a password to use in it,if you don't it will create one
# for you and ask you for the password you would like to use
$global:RemotePassword = convertto-securestring $password -AsPlainText -Force
$global:credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $RemoteUserName,$RemotePassword
#Create a connection to the remote computer , put a list of IPAddresses or Computer Names.
$global:session = new-PSSession -ComputerName $RemoteServerName -Credential $credentials
$ScriptBlock = $executioncontext.invokecommand.NewScriptBlock($RemoteCode)
invoke-command -Session $session -ScriptBlock $ScriptBlock
#Close the sessions that where created
$global:closesession = Get-PSSession
Remove-PSSession -Session $closesession
}
remote-pscode -ServerName "NameOfRemotePC" -UserName "UserName" -password "password" -PSCode "any powershell code you want to send to the remote pc"
Several things here: put your PS commands in a script block (or a script). Also, why don't you simply use wmic.exe ?