use ppk file to connect to sftp in PHP - php

I am having trouble connecting to an SFTP server using a .ppk file that are provided.
I have tried this ppk file in Filezilla and it works.
According to one of the comments in another question it is better to use phpseclib but i didnt find any instructions on how to download files from SFTP using a ppk file. Any directions or suggestions?
Here is the code I'm not sure if that will help or not.
include('Net/SSH2.php');
include('Crypt/RSA.php');
include('Net/SFTP.php');
DEFINE('SERVER','sample.sftp.com');
DEFINE('USER','sampleUserName');
DEFINE('KEY','sample_key_22733_priv.ppk');
$sftp = new Net_SFTP(SERVER);
//I guess this password is useless here
//and i will have to use my ppk file here but i don't know how
if (!$sftp->login(USER, 'password')) {
exit('Login Failed');
}
var_dump($sftp->nlist());

phpseclib works perfectly fine with PPK files, assuming they're RSA keys and not DSA keys. Just initialize a Crypt_RSA object and then call loadKey(file_get_contents('path/to/key.ppk')) on that object.
To download files do $sftp->get('/path/to/filename.ext').
Here's your orig code modified to include all this:
<?php
include('Net/SSH2.php');
include('Crypt/RSA.php');
include('Net/SFTP.php');
DEFINE('SERVER','sample.sftp.com');
DEFINE('USER','sampleUserName');
DEFINE('KEY','sample_key_22733_priv.ppk');
$rsa = new Crypt_RSA();
$rsa->loadKey(file_get_contents(KEY));
$sftp = new Net_SFTP(SERVER);
//I guess this password is useless here
//and i will have to use my ppk file here but i don't know how
if (!$sftp->login(USER, $rsa)) {
exit('Login Failed');
}
echo $sftp->get('/path/to/filename.ext');

Update:
As #neubert confirmed, PPK files are supported but you do need to make sure they are RSA as I explained, but you do not need them in OpenSSH format
Convert your PPK to an OpenSSH RSA key. You can convert this using the PuTTYgen executable: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
Once you have it in an RSA key, you can use this with phpseclib: http://phpseclib.sourceforge.net/ssh/auth.html#rsakey

Related

PHP - SFTP uploading file [duplicate]

I have came across many PHP scripts for web FTP clients. I need to implement a SFTP client as a web application in PHP.
Does PHP support for SFTP? I couldn't find any samples.
Can anyone help me with this?
PHP has ssh2 stream wrappers (disabled by default), so you can use sftp connections with any function that supports stream wrappers by using ssh2.sftp:// for protocol, e.g.
file_get_contents('ssh2.sftp://user:pass#example.com:22/path/to/filename');
or - when also using the ssh2 extension
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
$sftp = ssh2_sftp($connection);
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');
See http://php.net/manual/en/wrappers.ssh2.php
On a side note, there is also quite a bunch of questions about this topic already:
https://stackoverflow.com/search?q=sftp+php
The ssh2 functions aren't very good. Hard to use and harder yet to install, using them will guarantee that your code has zero portability. My recommendation would be to use phpseclib, a pure PHP SFTP implementation.
I found that "phpseclib" should help you with this (SFTP and many more features). http://phpseclib.sourceforge.net/
To Put the file to the server, simply call (Code example from http://phpseclib.sourceforge.net/sftp/examples.html#put)
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
// puts a three-byte file named filename.remote on the SFTP server
$sftp->put('filename.remote', 'xxx');
// puts an x-byte file named filename.remote on the SFTP server,
// where x is the size of filename.local
$sftp->put('filename.remote', 'filename.local', NET_SFTP_LOCAL_FILE);
Install Flysystem v1:
composer require league/flysystem-sftp
Then:
use League\Flysystem\Filesystem;
use League\Flysystem\Sftp\SftpAdapter;
$filesystem = new Filesystem(new SftpAdapter([
'host' => 'example.com',
'port' => 22,
'username' => 'username',
'password' => 'password',
'privateKey' => 'path/to/or/contents/of/privatekey',
'root' => '/path/to/root',
'timeout' => 10,
]));
$filesystem->listFiles($path); // get file lists
$filesystem->read($path_to_file); // grab file
$filesystem->put($path); // upload file
....
Read:
https://flysystem.thephpleague.com/v1/docs/
Upgrade to v2:
https://flysystem.thephpleague.com/v2/docs/advanced/upgrade-to-2.0.0/
Install
composer require league/flysystem-sftp:^2.0
Then:
//$filesystem->listFiles($path); // get file lists
$allFiles = $filesystem->listContents($path)
->filter(fn (StorageAttributes $attributes) => $attributes->isFile());
$filesystem->read($path_to_file); // grab file
//$filesystem->put($path); // upload file
$filesystem->write($path);
After messing around with PECL ssh2 I decided to take a look at phpseclib 3 and it worked out of the box. No installation on the server. I used composer to install it and put the code in. It has a ton of useful things and it's free. These are the steps:
Run this composer install on your PHP app folder. I used VS Code and I opened a terminal window (need Composer to be installed on your machine first):
composer require phpseclib/phpseclib:~3.0
Use the basic example from here: https://phpseclib.com/docs/sftp
use phpseclib3\Net\SFTP;
$sftp = new SFTP('localhost');
$sftp->login('username', 'password');
$sftp->put('filename.remote', 'filename.local', SFTP::SOURCE_LOCAL_FILE);
Other useful links: GitHub: https://github.com/phpseclib/phpseclib and website: https://phpseclib.com/
I performed a full-on cop-out and wrote a class which creates a batch file and then calls sftp via a system call. Not the nicest (or fastest) way of doing it but it works for what I need and it didn't require any installation of extra libraries or extensions in PHP.
Could be the way to go if you don't want to use the ssh2 extensions

PHP SSH2 operations failing when attempting to upload file to server

I am currently struggling with using the SSH2 built-in libraries for PHP (running version 5.5). I am trying to upload a file to an SFTP server as the title states however I keep getting a "stream operation failed" error message.
After attempting to debug the code itself the connection works, the sftp resource is assigned an ID correctly, however when fopen is called for writing the file directly to the remote server it fails.
// open Live environment if we are not in dev
$connection = ssh2_connect($this->_settings['source_host'], 22);
$authSuccess = ssh2_auth_password($connection, $this- >_settings['source_user'], $this->_settings['source_password']);
$sftp = ssh2_sftp($connection);
And finally the fopen() call:
if($operation == 'export') {
$handle = fopen("ssh2.sftp://".$sftp."/remotecopy/IN/".$filename, $mode);
}
I added debug messages in my own code to verify if the data from the _settings array is also used correctly and it is, however I can't explain the stream error.
Message: fopen(): Unable to open ssh2.sftp://Resource id #173/PATH GOES HERE/filename.xxx on remote host
Message: fopen(ssh2.sftp://Resource id #173/PATH GOES HERE/filename.xxx): failed to open stream: operation failed
As a note the file does not exist on the remote host but according to my knowledge 'w' mode in PHP fopen() should create the file if it does not exist.
I can't use the other PHP library as our whole project uses the builtin ssh2 libraries and the person in charged told me to not use it as it works fine everywhere else.
i think you'd have an easier time if you used phpseclib, a pure PHP SFTP implementation. eg.
<?php
include('Net/SFTP.php');
$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
exit('Login Failed');
}
// puts a three-byte file named filename.remote on the SFTP server
$sftp->put('filename.remote', 'xxx');
// puts an x-byte file named filename.remote on the SFTP server,
// where x is the size of filename.local
$sftp->put('filename.remote', 'filename.local', NET_SFTP_LOCAL_FILE);
?>
One of the nice things about phpseclib is it's logging so if that doesn't work you can do define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX); after including Net/SFTP.php and then do echo $sftp->getLog() after the point where it fails. That might provide some insight into what's going on if it still isn't working.
The answer was easy, I had incorrectly formatted path on the remote server. After verifying my settings it works just fine.
Thank you all for the hints and help.

Uploading files using SCP using phpseclib

I need to create 2 functions: one to upload files using SFTP and another using SCP. I'm using phpseclib and the put method; I believe I have the SFTP function done.
Now, I'm trying to do the SCP function. Per http://adomas.eu/phpseclib-for-ssh-and-scp-connections-with-php-for-managing-remote-server-and-data-exchange/, it seems like the following are the things I need to do:
In case of SCP:
1. Including the needed file: include('/path/to/needed/file/Net/SFTP.php');
2. Creating object and making connection:
$sftp = new Net_SFTP('host');
if (!$sftp->login('user', 'password')) { exit('Login Failed'); }
3. Reading contents of a file: $contents=$sftp->get('/file/on/remote/host.txt');
4. Copying file over sftp with php from remote to local host: $sftp->get('/file/on/remote/host.txt', '/file/on/local/host.txt');
5. Copying file over sftp with php from local to remote host: $sftp->put('/file/on/remote/host.txt', '/file/on/local/host.txt');
6. Writing contents to remote file: $sftp->get('/file/on/remote/host.txt', 'contents to write');
I need to do #5, but it looks like what I did for SFTP. SFTP and SCP aren't the same, right? Is the same code correct? If not, how do I do SCP?
As noted by neubert, phpseclib has SCP support now through the Net_SCP class.
You instantiate an Net_SCP object by passing it a Net_SSH2 or Net_SSH1 object in the constructor, and can then use the get() and put() methods to download or upload files via SCP.
Here's a simple example script showing me SCPing a file from my local machine to a remote AWS instance.
<?php
set_include_path(get_include_path() .
PATH_SEPARATOR .
'/home/mark/phpseclib');
require_once('Crypt/RSA.php');
require_once('Net/SSH2.php');
require_once('Net/SCP.php');
$key = new Crypt_RSA();
if (!$key->loadKey(file_get_contents('my_aws_key.pem')))
{
throw new Exception("Failed to load key");
}
$ssh = new Net_SSH2('54.72.223.123');
if (!$ssh->login('ubuntu', $key))
{
throw new Exception("Failed to login");
}
$scp = new Net_SCP($ssh);
if (!$scp->put('my_remote_file_name',
'my_local_file_name',
NET_SCP_LOCAL_FILE))
{
throw new Exception("Failed to send file");
}
?>
phpseclib recently added SCP support:
https://github.com/phpseclib/phpseclib/blob/master/phpseclib/Net/SCP.php
Yes, the SCP is completely different protocol to the SFTP.
The phpseclib now supports the SCP in recent versions (since version 0.3.5, released in June 2013).
Alternatively, use the PHP PECL SSH2 functions for SCP upload/download:
https://www.php.net/manual/en/ref.ssh2.php

PHP Exec SCP does not copy the file to the remote server

I need a file from a server to another server (I own both) using PHP. I have the following script:
<?php
exec('scp /home/pat/file1.tst pat#myserver.com:/home/pat/file1.txt');
I get this error:
Disallowed system call: SYS_pipe
What is that error? and how can I fix it?
PHP environment does not allow exec on your server.
This is kinda late, I know, but you might have better luck with phpseclib's pure PHP SCP implementation:
https://raw.github.com/phpseclib/phpseclib/master/phpseclib/Net/SCP.php
Example of how to use it:
<?php
include('Net/SCP.php');
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('bad login');
}
$scp = new Net_SCP($ssh);
$scp->put('abcd', str_repeat('x', 1024*1024));
?>

PHP SSH2 and Amazon EC2 .pem's

I've been looking for a way to use PHP's SSH2 to create a sort of terminal. To connect to Amazon in a normal terminal, you would use something like ssh -i path_to/key.pem ec2.ip-555-xxx.com. In PHP on the other hand, SSH2 has a function ssh2_auth_pubkey_file . But have run into a bit of a wall here, as Amazon only provides me with 1 private key (.pem) file, and the function has arguments for both private and public keys. Ultimately I'd like to have a client upload a .pem file to the server and be able to connect to a local or remote SSH server with PHP SSH2 on Amazon using that .pem file.
.pem is the server certificate for the apache web server, it has nothing to do with ssh. See: https://serverfault.com/questions/9708/what-is-a-pem-file-and-how-does-it-differ-from-other-openssl-generated-key-file-f
Seems it might also be a combo file with public and private keys in it. In any case it will not work for ssh directly, you will need to convert it to normal files.
You have it backward anyway - amazon will not give you the private key, quite the opposite - you give amazon the public key. You generate the private/public key pair locally, then upload the public key into the .ssh/authorize_keys files.
Personally, I'd recommend phpseclib, a pure PHP SSH2 implementation be used:
<?php
include('Net/SSH2.php');
$key = new Crypt_RSA();
//$key->setPassword('whatever');
$key->loadKey(file_get_contents('privatekey'));
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', $key)) {
exit('Login Failed');
}
echo $ssh->exec('ls -la');
?>
This is how you get the private and public keys from .pem within php
$eKey = file_get_contents('/pathto/key.pem');
$key_private = openssl_get_privatekey($eKey);
$keyDet=openssl_pkey_get_details($key_private);
$key_public = openssl_pkey_get_public(array($keyDet['key'],""));
$keyPDet=openssl_pkey_get_details($key_public);

Categories