Archive

Author Archive

PHP SSH2: Bindings for the libssh2 library

December 8th, 2010 2 comments

PHP has bindings to the libssh2 library which provide access to resources (shell, remote exec, tunneling, file transfer) on a remote machine using a secure cryptographic transport. This tutorial will show you how to make SSH2 connections from PHP to execute commands over SSH. This requires the SSH2 PECL extension to be installed on your machine.

Installing PHP-SSH2

In the latest Debian/Ubuntu builds you can install PHP-SSH2 using apt.

$ sudo aptitude install libssh2-php

Compile from source.

You can find the latest PHP-SSH2 source files here. You will require libssh2 dev files to compile the PHP-SSH2 module.

First install the libssh2 dev files.

$ sudo aptitude install libssh2-1-dev

Now download the php-ssh2 source file and compile it.

$ wget http://pecl.php.net/get/ssh2-0.11.2.tgz
$ tar xfz ssh2-0.11.2.tgz
$ cd ssh2-0.11.2
$ phpize && ./configure && make
$ sudo make install

You might require to copy the ‘ssh2.so’ file to proper path to call the dl() function.

Working With PHP-SSH2

Working with php-ssh2 is fairly straightforward. The ssh2_connect function will establish a connection to a remote SSH server. Once connected, the client should verify the server’s hostkey using ssh2_fingerprint(), then authenticate using either password or public key.

First make a SSH connection..

$hostname = 'example.com';
 
$con = @ssh2_connect($hostname, 22);
if(!$con) die('Cannot Connect...');

The ssh2_connect will return a resource on success that we will pass to the next functions.

Now we have to authenticate as a user. You either use a username and password or use public key and private key for authentication.

Authentication using username and password.

$username = 'username';
$password = 'secret';
 
if(!@ssh2_auth_password($con, $username, $password))
  die('Authentication Failed...');

Authentication using a public key. If privkeyfile is encrypted (which it should be), the passphrase must be provided.

$hostname = 'example.com';
$username = 'username';
$passphrase = 'secret';
 
$con = @ssh2_connect($hostname, 22, array('hostkey'=>'ssh-dss'));
if(!$con) die('Cannot Connect...');
 
if(!@ssh2_auth_pubkey_file($con, $username, '/home/$username/.ssh/id_dsa.pub', '/home/$username/.ssh/id_dsa', $passphrase))
  die('Authentication Failed...');

Now that we are connected and authenticated, we can send a command:

$stream = @ssh2_exec($con, "ls -la" );
 
stream_set_blocking($stream, true);
 
while ($buf = fread($stream,4096)) {
    $data .= $buf;
}
fclose($stream);
 
print $data;

The ssh2_exec function will return a stream on success. The command may not finish before the function return if the stream is not set to blocking mode. You may have to set the stream to blocking mode in order to get any output from the command.

Using sudo in commands

The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device.

$stream = @ssh2_exec($con, "echo $password | sudo -S $cmd" );

The Shell Mode

The ssh2_shell will open a shell at the remote end and allocate a stream for it. Using ssh_exec, one could execute only one command at a time. However, ssh_shell, offers greater flexibility.

Here is an example:

$shell = ssh2_shell($con, 'xterm');
fwrite( $shell, "cd /dir_one\n");
fwrite( $shell, "ls -la\n");
fwrite( $shell, "cd /dir_two\n");
fwrite( $shell, "ls -la\n");
 
stream_set_blocking($shell, true);
while($line = fgets($shell)) {
        flush();
        echo $line;
}
fclose($shell);

Using SCP to transfer files

The ssh2_scp_send function will copy a file from the local filesystem to the remote server using the SCP protocol.

$username = 'username';
$password = 'secret';
 
$con = @ssh2_connect($hostname, 22);
if(!$con) die('Cannot Connect...');
 
if(!@ssh2_auth_password($con, $username, $password))
  die('Authentication Failed...');
 
ssh2_scp_send($con, '/tmp/httpd.conf', '/usr/local/apache2/conf/httpd.conf', 0644);

The ssh2_scp_recv function copy a file from the remote server to the local filesystem using the SCP protocol.

ssh2_scp_recv($con, '/usr/local/apache2/conf/httpd.conf', '/tmp/httpd.conf');

SCP a directory

You will need to write your own functions using ssh2_scp_send and ssh2_scp_recv for recursive file transfer. Here is a quick and dirty recursive scp function.

function ssh2_scp_send_recursive($con, $local_path, $remote_path)
{
    if(substr($local_path,-1) !== '/'){$local_path .= '/';}
    if ($handle = opendir($local_path)){
        while (false !== ($file = readdir($handle))){
            if($file == "." || $file == "..") continue;
            if (filetype($local_path.$file) === 'dir'){
                clearstatcache();
                ssh2_exec($con, "mkdir -p " . $remote_path . $file);
                ssh2_scp_send_($con, $local_path . $file, $remote_path);
            } else {
                ssh2_scp_send($con, $local_path . $file, $remote_path . $file);
            }
        }
        closedir($handle);
    }
}

Refer the PHP-SSH2 manual for more details.

Happy SSHing. :-)

Categories: PHP Tags:

Sending Emails Via Gmail SMTP With Python

December 3rd, 2010 No comments

python
This is the third post in the article series “Playing With Python And Gmail”. This will be a tutorial on how to send mails using Python smtplib through Gmail SMTP.

The smtplib module defines an SMTP client session object that can be used to send mail to any Internet machine with an SMTP or ESMTP listener daemon.

[vinod@mercury ~]$ python
Python 2.5.2 (r252:60911, Jan 24 2010, 14:53:14)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import smtplib

The first step is to create a SMTP connection to the server. The smtplib.SMTP class encapsulates an SMTP connection. It has methods that support a full repertoire of SMTP and ESMTP operations. If the optional host and port parameters are given, the SMTP connect() method is called with those parameters during initialization. An SMTPConnectError is raised if the specified host doesn’t respond correctly. The optional timeout parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used).

Remember Google’s SMTP server is ‘smtp.gmail.com’ and the port is 587.

>>> session = smtplib.SMTP('smtp.gmail.com', 587)

Next we will identify ourself to an ESMTP server using EHLO. The SMTP HELO clause is the stage of the SMTP protocol where a SMTP server introduce them selves to each other. EHLO is just like HELO except that the server’s response text provides computer-readable information about the server’s abilities.

>>> session.ehlo()
(250, 'mx.google.com at your service, [x.x.x.x]\nSIZE 35651584\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES')

Next we call SMTP.starttls function to put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted. You should then call ehlo() again.

If keyfile and certfile are provided, these are passed to the socket module’s ssl() function.If there has been no previous EHLO or HELO command this session, this method tries ESMTP EHLO first.

>>> session.starttls()
(220, '2.0.0 Ready to start TLS')
>>> session.ehlo
>
>>>

OK, now we are safe to login to the server using SMTP.login(user, password). After successful login we use SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]) to send mails via Gmail.

>>> session.login('username@gmail.com', 'topsecret')
(235, '2.7.0 Accepted')

We will cerate some SMTP headers before sending our mail.

headers = ["from: " + sender,
           "subject: " + subject,
           "to: " + recipient,
           "mime-version: 1.0",
           "content-type: text/html"]
headers = "\r\n".join(headers)

Finally send our mail

session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)

Sample code

#!/usr/bin/python
import smtplib
 
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
 
sender = 'you@gmail.com'
recipient = 'user@example.com'
subject = 'Gmail SMTP Test'
body = 'blah blah blah'
 
"Sends an e-mail to the specified recipient."
 
body = "" + body + ""
 
headers = ["From: " + sender,
           "Subject: " + subject,
           "To: " + recipient,
           "MIME-Version: 1.0",
           "Content-Type: text/html"]
headers = "\r\n".join(headers)
 
session = smtplib.SMTP(server, port)
 
session.ehlo()
session.starttls()
session.ehlo
session.login(sender, password)
 
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
session.quit()

Sending Attachments

The email package is a library for managing email messages, including MIME and other RFC 2822-based message documents. The central class in the email package is the Message class, imported from the email.message module. It is the base class for the email object model. Message provides the core functionality for setting and querying header fields, and for accessing message bodies. This is the base class for all the MIME-specific subclasses of Message. Ordinarily you won’t create instances specifically of MIMEBase, although you could. MIMEBase is provided primarily as a convenient base class for more specific MIME-aware subclasses.

We import MIMEMultipart class, a sub class of MIMEBase to create the enclosing (outer) message.

from email.MIMEMultipart import MIMEMultipart
 
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = recipient
msg['Subject'] = subject

The MIMEImage class is used to create MIME message objects of major image types. We create a MIMEImage object containing out raw image data and attach it to our outer message.

from email.MIMEImage import MIMEImage
 
img = MIMEImage(open("test.gif","rb").read(), _subtype="gif")
 
img.add_header('Content-Disposition', 'attachment; filename="test.gif"')
msg.attach(img)

Finally we create MIMEText object to add some plain text to our mail.The MIMEText class is used to create MIME objects of type text.

from email.MIMEText import MIMEText
 
part = MIMEText('text', "plain")
part.set_payload("Image attached.")
msg.attach(part)

Now send the mail

session.sendmail(sender, recipient, msg.as_string())

You can create MIME objects for audio, application etc. Find the documentation here.

A Simple Example

Send all .gif files in a directory as attachment.

#!/usr/bin/python
import os, re
import sys
import smtplib
 
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
 
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
 
sender = 'you@gmail.com'
password = "secret"
recipient = 'user@example.com'
subject = 'Python emaillib Test'
message = 'Images attached.'
 
directory = "/tmp/images/"
 
def main():
    msg = MIMEMultipart()
    msg['Subject'] = 'Python emaillib Test'
    msg['To'] = recipient
    msg['From'] = sender
 
    files = os.listdir(directory)
    gifsearch = re.compile(".gif", re.IGNORECASE)
    files = filter(gifsearch.search, files)
    for filename in files:
        path = os.path.join(directory, filename)
        if not os.path.isfile(path):
            continue
 
        img = MIMEImage(open(path, 'rb').read(), _subtype="gif")
        img.add_header('Content-Disposition', 'attachment', filename=filename)
        msg.attach(img)
 
    part = MIMEText('text', "plain")
    part.set_payload(message)
    msg.attach(part)
 
    session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
 
    session.ehlo()
    session.starttls()
    session.ehlo
    session.login(sender, password)
 
    session.sendmail(sender, recipient, msg.as_string())
    session.quit()
 
if __name__ == '__main__':
    main()
Categories: PYTHON Tags: , , ,

Decrypt HTTPS Traffic Using Wireshark And Key File

November 16th, 2010 No comments

wireshark-logoWireshark is a useful tool in troubleshooting. Wireshark can decrypt SSL traffic as long as you have the server private key. This can be extremely useful, if you have to debug HTTPS traffic and cannot use HTTP instead.

First we will capture a HTTPS traffic for our testing. Here our HTTPS server’s ip address is 192.168.x.x and the port is default 443. I prefer to use tcpdump for packet capture but you can do it using the Wireshark.

The below command will capture all the encrypted traffic to and from from our server.

$ sudo tcpdump -w /tmp/ssl.pcap  -ni eth0 -s0  host 192.168.x.x port 443

The captured data will go to the ssl.pcap file. Once you have the captured packets in the file open it in the Wireshark. Use the “Follow TCP Stream” options and you can see the encrypted data.

Screenshot-Follow TCP Stream
Next thing we need is the server’s private key. Once you have the key file to decrypt the traffic, just goto “Edit -> Preferences”. Now on the left side menu choose “Protocols -> SSL”. Fill “RSA Key list” field in the format <host>, <port>, <protocol>, <key_file>. ie We will specify the server’s IP address, the port on which the server listens and the path to the server’s private key. The file format needed for the server’s private key is PEM. In our example it is 192.168.x.x, 443, https, /path/to/keyfile.pem.

wireshark
Now Apply the setting and return to main window.

Now if you click on each row you can see a “Decrypted SSL Data (size) “ tab on the bottom of “Packet Bytes” frame. This tab will be shown if there is any decrypted data available.

Screenshot-ssl.pcap - Wireshark-1

You can now use the “Follow SSL Stream” option to view the decrypted data stream.

Screenshot-ssl.pcap - Wireshark

Happy decrypting ;-)

Categories: HOW-TOS Tags: , , , ,