Cisco VPN Client automatic login - authentication

I need to automate the login process of a Cisco VPN Client version 5.0.07.0440.
I've tried using a command line like this but there is something wrong:
vpnclient.exe connect MyVPNConnection user username pwd password
This starts the connection but then a User Authentication dialog is shown, asking for username, password and domain. Username and password are already filled, domain is not necessary.
To continue I must press the OK button.
Is there a way to not show the dialog and automatically login into the vpn?

Run vpnclient.exe /?:
That way just run
vpnclient.exe connect MyVPNConnection -s < file.txt
file.txt
username
password

Below worked for me Cisco AnyConnect Secure Mobility Client:
Try to connect to VPN for the first time using vpncli.exe and note every keystroke i.e every command, every enter( \n ) you press, username & password you enter.
Copy each command sequentially in .login_info file.
Sample .login_info:
connect unkbown.data-protect.com
\n
\n
KC23452
\n
Note: Replace \n with normal enter, these are the exact steps that I followed while connecting via vpncli.exe. Username and group-name were saved automatically that's the reason the 2nd and 3rd lines are \n ( enter ). Also, the last \n is required.
Go to C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client
Open CMD here
vpncli.exe -s < .login_info

First, we need to use the vpncli.exe command line approach with the -s switch.
It works from command line or script. If you were looking for a solution in C#:
//file = #"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"
var file = vpnInfo.ExecutablePath;
var host = vpnInfo.Host;
var profile = vpnInfo.ProfileName;
var user = vpnInfo.User;
var pass = vpnInfo.Password;
var confirm = "y";
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = file,
Arguments = string.Format("-s"),
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
}
};
proc.OutputDataReceived += (s, a) => stdOut.AppendLine(a.Data);
proc.ErrorDataReceived += (s, a) => stdOut.AppendLine(a.Data);
//make sure it is not running, otherwise connection will fail
var procFilter = new HashSet<string>() { "vpnui", "vpncli" };
var existingProcs = Process.GetProcesses().Where(p => procFilter.Contains(p.ProcessName));
if (existingProcs.Any())
{
foreach (var p in existingProcs)
{
p.Kill();
}
}
proc.Start();
proc.BeginOutputReadLine();
//simulate profile file
var simProfile = string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}"
, Environment.NewLine
, string.Format("connect {0}", host)
, profile
, user
, pass
, confirm
);
proc.StandardInput.Write(simProfile);
proc.StandardInput.Flush();
//todo: these should be a configurable value
var waitTime = 500; //in ms
var maxWait = 10;
var count = 0;
var output = stdOut.ToString();
while (!output.Contains("state: Connected"))
{
output = stdOut.ToString();
if (count > maxWait)
throw new Exception("Unable to connect to VPN.");
count++;
Thread.Sleep(waitTime);
}
stdOut.Append("VPN connection established! ...");
(This might have extra stuff which is not required for you specific case.)

Here is a BAT script for automatic logon using Cisco AnyConnect Secure Mobility Client (version 4.10.03104):
taskkill -im vpnui.exe -f
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe" disconnect
SLEEP 3
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe" -s < credential.txt
SLEEP 8
"%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe"
The file "credential.txt" must contain three lines:
connect <host>
<login>
<password>
where <host> is IP address or hostname of the host to connect, <login> is your login, and <password> is your password. The first line taskkill -im vpnui.exe -f is nesessary for killing the GUI, because when the GUI is running the login through the command line doesn't work. The last line launches the GUI again after successive logon.
The same script written as a VBS file (suitable for Windows Task Sheduler):
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "taskkill -im vpnui.exe -f"
WshShell.Run """%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"" disconnect"
WScript.Sleep 3000
WshShell.Run "cmd /K ""%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"" -s < credential.txt"
WScript.Sleep 8000
WshShell.Run """%PROGRAMFILES(x86)%\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe"""
Save this script as "login.vbs", and assign running it as an "Action" in the Windows Task Sheduler.

Related

How to check SSH command execute or not in PHP?

I am running ssh command using phpseclib. Here if condition showing wrong message. How to check ssh command execution in if condition. My code is:
$command = "sudo rm /path/filename";
if(!$ssh->exec($command)){
$response['success'] = false;
$response['messages'] = 'File delete Failed';
}else{
$response['success'] = true;
$response['messages'] = 'File deleted';
}
Here file deleting successfully. The message only shows wrong. Pls help me in this

How to ask for a user input from a remote server with SSHKit?

I need to ask a user input from a ruby script on a remote server. I managed to perform it with bash with the following code
class ConfirmHandler
def on_data(command, stream_name, data, channel)
puts "data received: #{data}"
if data.to_s =~ /\?$/
prompt = Net::SSH::Prompt.default.start(type: 'confirm')
response = prompt.ask "Please enter your response (y/n)"
channel.send_data "#{response}\n"
end
end
end
require 'sshkit'
require 'sshkit/dsl'
include SSHKit::DSL
on '<ssh-server-name>' do |host|
cmd = <<-CMD
echo 'Do something?';
read response;
echo response=$response
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
When I run this script on my local machine I see
data received: Do something?
Please enter your response (y/n)
data received: response=y
I try to wrap the bash CMD code into a ruby script:
on '<ssh-server-name>' do |host|
cmd = <<-CMD
ruby -e "
puts 'Do something?';
require 'open3';
response = Open3.capture3('read response; echo $response');
puts 'response=' + response.to_s;
"
CMD
capture(cmd.squish , interaction_handler: ConfirmHandler.new)
end
and get the following result:
data received: Do something?
Please enter your response (y/n)
data received: response=["\n", "", #<Process::Status: pid 9081 exit 0>]
I was writing the code above looking at the Interactive commands section on the SSHKit Github home page
How can I capture the user response from a ruby script with SSKKit on the remote server?
I was able to capture the user response from a ruby script on a remote server with the following code:
# ask_response.rb
puts 'Do something?';
response = `read response; echo $response`;
puts 'response=' + response.to_s;
ask_response.rb is a ruby script which is located on a remote server. And locally I run:
on '<ssh-server-name>' do |host|
capture("ruby ask_response.rb" , interaction_handler: ConfirmHandler.new)
end

Cannot have file provisioner working with Terraform on DigitalOcean

I try to use Terraform to create a DigitalOcean node on which consul is installed.
I'm using the following .tf file but it hangs up and do not copy the consul .zip file onto the droplet.
I got the following error message after a couple of minutes:
ssh: handshake failed: ssh: unable to authenticate, attempted methods
[none publickey], no supported methods remain
The droplets are correctly created though. I can login on command line with the key I specified (thus not specifying password). I'm guessing the connection part might be faulty but not sure what I'm missing.
Any idea ?
variable "do_token" {}
# Configure the DigitalOcean Provider
provider "digitalocean" {
token = "${var.do_token}"
}
# Create nodes
resource "digitalocean_droplet" "consul" {
count = "1"
image = "ubuntu-14-04-x64"
name = "consul-${count.index+1}"
region = "lon1"
size = "1gb"
ssh_keys = ["7b:51:d3:e3:ae:6e:c6:e2:61:2d:40:56:17:54:fc:e3"]
connection {
type = "ssh"
user = "root"
agent = true
}
provisioner "file" {
source = "consul_0.7.1_linux_amd64.zip"
destination = "/tmp/consul_0.7.1_linux_amd64.zip"
}
provisioner "remote-exec" {
inline = [
"sudo unzip -d /usr/local/bin /tmp/consul_0.7.1_linux_amd64.zip"
]
}
}
Terraform requires that you specify the private SSH key to use for the connection with private_key You can create a new variable containing the path to your private key for use with Terraform's file interpolation function:
connection {
type = "ssh"
user = "root"
agent = true
private_key = "${file("${var.private_key_path}")}"
}
You face this issue, because you have a ssh key protected by a password. To solve this issue you should generate a key without password.

Expect Scripting Issue Reading From File

I am trying to change the password for a user on a bunch of linux based routers pulling IPs from a list. The iplist.txt is just a list of ips (one per line). This is the code I am trying to use:
#!/usr/bin/expect
set timeout 20
#Edit for User
set user username
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set hosts [split [read $f] "\n"]
close $f
foreach host $hosts {
spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user#$host
expect "assword:"
send "$old\r"
expect ">"
send "user set $user password=$new\r"
expect ">"
send "quit\r"
expect eof
close
}
Which works for the first ip on the list but send this error on the second:
spawn_id: spawn id exp4 not open
I got it to work this way as I wanted:
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user#$line
expect "assword:"
send "$old\r"
expect ">"
send "user set $user password=$new\r"
expect ">"
send "\r"
expect ">"
send "quit\r"
send "\r"
expect eof
}
The next issue I run into is if the device doesn't have the old password or if the linux box cannot reach the device via ssh, it will error out with the same spawn id exp* not open when it gets to that IP and will not continue onto the next IP in the list. Is there anyway I can a statement that says if "assword:" comes up a second time to move onto next IP and if ">" comes up like its supposed to keep going with the script, then add a line after the spawn command that will move to the next IP in list if it doesn't receive the first expect "assword:"?
Any help would be appreciated. I am new to expect, but seems to be a really good tool for mass ssh processes in a script. Just having trouble tweaking it to not error out on 1 job instead of moving to next job upon error.
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user#$line
expect {
"assword:" {
send "$old\r"
expect {
"assword:" {
close
continue
}}
expect {
"*" {
send "user set $user password=$new\r"
expect ">"
send "quit\r"
close
continue
}}}}
expect {
"*" {
close
continue
}}
expect eof
}
Probably a bit dirty scripting, but it works. Now if I can figure out how to export successful, wrong password, and timeout logs so I know if any error-ed out.

JSCH setCommand is not working

No Exception comes and Command is also not making any work based on command mentioned.Here permisson of directory is not created and directory is also not created.Please give your suggestion.
Update :
channelexe.getExitStatus is added but problem is it gives -1, what is the meaning of this ?. I don't know how to find some explaination why command is not doing it's job(update 777 mode of fileDir1) .
String depDir = "/usr/local/FTPReceive/DEPLOYED/fileDir1";
log.info("updateDepositedFilePermission ........ starts");
Session session = new FTPComponent().getSession("");
Channel channel = null;
ChannelSftp channelSftp = null;
try
{
session.connect();
System.out.println("session is alive:" + session.isConnected());
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp) channel;
ChannelExec channelexe = (ChannelExec) session.openChannel("exec");
channelexe.setCommand("chmod 777 -R " + depDir);
channelexe.connect();
System.out.println("channelexe.getExitStatus:"+channelexe.getExitStatus());
}
catch (Exception e1)
{
e1.printStackTrace();
System.out.println("Manual Exception in updateDepositedFilePermission:" + CommonUtil.getExceptionString(e1));
}
channelexe.setCommand("chmod 777 -R " + depDir);
channelexe.setCommand("mkdir /usr/local/fileStore");
channelexe.connect();
A ChannelExec accepts a single command string to invoke on the remote system. Your second call to setCommand() is discarding the chmod command and replacing it with the mkdir command. Assuming the remote shell is bash or similar, you could use shell syntax to construct a command string which runs both commands:
String cmd = "chmod 777 -R " + depDir + " && mkdir /usr/local/fileStore";
channelexe.setCommand(cmd);
No Exception comes...
ChannelExec doesn't throw an exception when a command merely fails. You can call Channel.getExitStatus() to get the exit status of the remote command. The value will be 0 if chmod and mkdir succeeded, or non-zero if they failed. The channel also has functions to read the standard error of the remote command, which will permit you to read any error messages which they output.
The JSCH website has several example programs, including an example of executing a remote command.