Redirecting stdin/stdout to/from a remote host via ssh - perl

I'm trying to write a perl script that redirects its stdin to a remote machine and at the same time redirects the stdout of the remote machine to its stdout:
callingProgram <--> myScript <--> sshTunnelToRemote
See this question and bdonlan's answer for the purpose of the script.
First I tried to use the open2() function from the IPC library but for reasons described here it doesn't seem to be a good approach, I didn't even get a simple grep command working.
My second idea was to use the Net::SSH::Perl or the Expect libraries but they're not available on the machine where the script is supposed to be executed and I can't install libraries there.
So my question is what could be a simple way to achieve what I want? Solutions using [ba]sh or even C++ are also possible. The targeted platform is Solaris 10.

Seems like you could probably get away with nothing more than system() — don't pass the data from your stdin to ssh's stdin and from your stdout to ssh's stdout; just let ssh inherit your stdin and stdout. Unless you need to modify the data in transit somehow.

cpanminus can do this for you
Running:
cd ~/bin
curl -LO http://xrl.us/cpanm
chmod +x cpanm
Now you can try your problem using the right tools (e.g. Net::SSH::Perl).
The power of perl is cpan, and cpanminus gives you the ability to install whatever you need even if you don't have permission to install to the system-wide libraries.
Read the module documentation for the full details.

Related

Can I setuid a perl script?

I made a perl script to change owner of a file owned by some other user. Script is complete. My administrator save that in /sbin directory and set uid for it using chmod u+s name_of_script. But when I run this script it gives me error that chown operation is not permitted. I made a C program and it works by following same steps. So my question is if setuid is working for perl then I should not get that error because C code did not give me any error. So can i setuid for perl script or I should go with c code.
Don't tell me to ask administrator to change owner each time. Actually in server I have user name staging and I am hosting a joomla site in it. Now when I install some plugin then files related to that plugin are owned by www-data. So that's why I do not want to go to admin each time. Or you can give me some other solution also regarding my problem.
Many unix systems (probably most modern ones) ignore the suid bit on interpreter scripts, as it opens up too many security holes.
However, if you are using perl < 5.12.0, you can run perl scripts with setuid set, and they will run as root. How it works is that when the normal perl interpreter runs, and detects that the file you are trying to execute has the setuid bit set, and it then executes a program called suidperl. Suidperl takes care of elevating the user's privileges, and starting up the perl interpreter in a super-secure mode. suidperl is itself running with setuid root.
One of the consequences of this is that taint mode is turned on automatically. Other additional checks are also performed. You will probably see messages like:
Insecure $ENV{PATH} while running setuid at ./foobar.pl line 3.
perlsec provides some good information about securing such scripts.
suidperl is often not installed by default. You may have to install it via a separate package. If it is not installed then you get this message:
Can't do setuid (cannot exec sperl)
Having said all of that - you would be much better off using sudo to execute actions with elevated privileges. It is much more secure as you can specify exactly what is allowed to be executed via the sudoers file.
As of perl 5.12.0, suidperl was dropped. As a result, if you want to run a perl script on perl >= 5.12.0 with setuid set, you would have to write your own C wrapper. Again I recommend sudo as a better alternative.
No, you cannot use setuid aka chmod +s on scripts. The script's interpreter would be the thing that would actually need to be setuid, but doing that is a really bad idea. REALLY bad.
If you absolutely must have something written in Perl as setuid, the typical thing to do would be to make a small C wrapper that is setuid and executes the Perl script after starting. This gives you the best of both worlds in having a small and limited setuid script but still have a scripting language available to do the work.
If you have a sudo configuration that allows it (as most desktop linux distributions do for normal users), you can start your perl script with this line:
#!/usr/bin/env -S -i MYVAR=foo sudo --preserve-env perl -w -T
Then in your script before you use system() or backticks explicitly set your $ENV{PATH} (to de-taint it):
$ENV{PATH} = '/usr/bin';
Other environment variable that your script explicitly mentions or that get implicitly used by perl itself will have to be similarly de-tainted (see man perlsec).
This will probably (again depending on your exact sudo configuration) get you to the point where you only have to type in your root password once (per terminal) to run the script.
To avoid having to type your password at all you can add a line like this to the bottom of /etc/sudoers:
myusername ALL=(ALL) NOPASSWD:ALL
Of course you'd want to be careful with this on a multi-user system.
The -S options to env splits the string into separate arguments (making it possible to use options and combinations of programs like sudo/perl with the shebang mechanism). You can use -vS instead to see what it's doing.
The -i option to env clears the environment entirely.
MYVAR=foo introduces an environment variable definition.
The --preserve-env option to sudo will preserve MYVAR and others.
sudo sets up a minimal environment for you when it finds e.g. PATH to be missing.
The -i option to env and --preserve-env option to sudo may both be omitted and you'll probably end up with a slightly more extensive list of variables from your original environment including some X-related ones (presumably the ones the sudo configuration considers safe). --preserve-env without -i will end up passing along your entire unsanitized environment.
The -w and -T options to perl are generally advisable for scripts running as root.

How do you carry out remote debug when running perl as CGI together with Apache?

Seems most are using the traditional way of print for debugging purpose, is there anyone that uses remote debug for perl in linux?
There are reasonably straightforward directions here: http://search.cpan.org/dist/Enbugger/lib/Enbugger.pod#From_gdb
Though that presupposes you have a long-running perl process (mod_perl, fastcgi, etc) that wasn't expecting to be run under the debugger. If you are just using vanilla CGI, you can configure your webserver to run perl -d and set the debugger to remote debugging via its TTY or RemotePort options. Or go ahead and use Enbugger in your actual perl code as in the directions above (again, setting TTY or RemotePort).
What sort of debugging? An actual perl debugger or using warn() with tail -f /var/log/apache/error.log?
In the end i would suggest swicting to Log::Log4perl. Unless you need an actual step by step debugger.
You you need an actual debugger, you likely won't want to use Apache in the mix. You can run your cgi from the command line and pass arguments CGI.pm.

How do use perl to trigger another perl scipt running on another machine?

Need a way to have a perl script running on one machine run a perl script running on another.
The remote machine config is:
CentOS-5.5,
it's on the same network is the requesting machine,
has a DNS,
ports-open(SSH,HTTP)
Questions, feedback, comments -- just comment, thanks!!
Is this what you want?
system("ssh user#remotemachine perl <remote script's full path>");
will run the script on remote machine.
you may want to ssh without password, check: http://linuxproblem.org/art_9.html
As #Nylon Smile mentioned, you can use system to invoke the system's ssh client. If you want to do this without relying on external binaries (in particular because you want to handle password authentication differently), try Net::SSH::Perl, available from CPAN.
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new('host');
$ssh->login('username', 'password');
my ($stdout, $stderr, $exit_code) = $ssh->cmd(
'perl some_script.pl --with=some_args',
'optionally, some stdin for that script'
);
Net::SSH::Perl can be a bit of a pain to install, but there are several other CPAN modules (most of which rely on an installed OpenSSH) and are a bit easier to deal with while providing a similar api. See also Net::SSH and Net::OpenSSH.
The above answers are fine for a one-off, but if you're doing this sort of thing a lot, you may want to look into some sort of messaging system like AMPQ (e.g. RabbitMQ) and set up queue listeners.

How to open ssh session and execute commands from a Perl script?

I have a Perl script running on a Windows machine. I need this script to open a ssh session to a remote Unix machine, and to be able to execute certain commands on that Unix machine and to be able to get the output returned from these commands.
These commands are generated during the run-time of the script, and there are many of them executed at different times.
How can I do it?
Approach 1: Use CYGWIN: http://perlwin32ssh.blogspot.com/2007/07/test_4418.html
Approach 2: Use Net::SSH::W32Perl module.
This is one thread discussing how to install it: http://code.activestate.com/lists/perl-win32-users/29180/ (It seems to require downloading custom version of the module)
This thread should help with the problems arising from dependencies on math libraries needed for ssh calculations: http://www.issociate.de/board/post/494356/I%27m_trying_to_install_%27Net::SSH::Perl%27_on_a_Windows_Box..html
Caveat emptor: I never installed this, the above is just result of some analysis of google results.
#!/usr/bin/perl
system("ssh foo 'ls -l'");
Or go through the hassle of using ptmx(4) on the local side and ssh -t for remote.

Alternative module of Net::SSH::Expect or how to connect remote server and get the output of command

I want to use Net::SSH::Expect in my unix box but unfortunately, it is not available and I am not able to convince the admin to install any perl module. Do you know how could I connect to a remote server using expect.
I know that I can archive that by using python but python is also not avai in my unix box.
Second attempt: though I use expect and shell scripting but the output is missing which is my original problem :Missing output when running system command
Please advise me any alternative module of Net::SSH::Expect so I can check its availibility in my unix box. Or any other way to connect remote server, execute some command and get the output ?
Million thanks.
You do not need your system administrator to install a module in order for you to run it. You can download and install it locally, and use local::lib to use it (as discussed in earlier questions on this site).
Alternatively, have you simply tried:
my $output = `ssh username#host command arguments`;