3

I'm trying since a couple of days to establish a TLS connection to a SMTP server in PHP via fsockopen() on my newly installed Ubuntu server. I#ve tried almost everything and googled for hours but still I didn't get it working.

The PHP code looks as follows:

$fp = fsockopen("tls://smtp.xxxx.com", 25, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
 // some other stuff
}  

The output is just (0), i.e., $errstr = null and $errno = 0.

OpenSSL is installed and enabled:

OpenSSL support: enabled
OpenSSL Library Version: OpenSSL 0.9.8o 01 Jun 2010
OpenSSL Header Version: OpenSSL 0.9.8o 01 Jun 2010

and the following stream socket transports are registered: tcp, udp, unix, udg, ssl, sslv3, sslv2, tls.

The port is open as a telnet from the console works.

Any ideas what's wrong or how I could at least get some more debug output?

Thanks, Markus

Markus Lanthaler
  • 31
  • 1
  • 1
  • 2
  • You have error logging turned on in `/etc/php/apache2/php.ini`? What does it say in the error logs? – Femi Jul 15 '11 at 14:08
  • Yes, it's enabled. The error in the apache error log is: [Fri Jul 15 15:50:07 2011] [error] [client 95.233.109.135] PHP Warning: fsockopen(): unable to connect to tls://smtp.gmail.com:587 (Unknown error) in /var/www/test.php on line 3 I just tested it. If I execute the script from the commandline via "php test.php" it works. – Markus Lanthaler Jul 15 '11 at 14:12

3 Answers3

6

With gmail, the ssl connection port had ssl from the get-go, but the tls port, you connected plain, and had to start tls manually with a STARTTLS command. I'm guessing this is the same. Here's and example to gmail so you can see what's going on. The EHLO command shows the STARTTLS command while if you start with ssl from the begining, it goes strait to the AUTH XOAUTH command list.

<?php
function get($socket,$length=1024){
    $send = '';
    $sr = fgets($socket,$length);
    while( $sr ){
        $send .= $sr;
        if( $sr[3] != '-' ){ break; }
        $sr = fgets($socket,$length);
    }
    return $send;
}
function put($socket,$cmd,$length=1024){
    fputs($socket,$cmd."\r\n",$length);
}
if (!($smtp = fsockopen("smtp.gmail.com", 587, $errno, $errstr, 15))) {
    die("Unable to connect");
}
echo "<pre>\n";
echo get($smtp); // should return a 220 if you want to check

$cmd = "EHLO ${_SERVER['HTTP_HOST']}";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp); // 250

$cmd = "STARTTLS";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp); // 220
if(false == stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)){
    // fclose($smtp); // unsure if you need to close as I haven't run into a security fail at this point
    die("unable to start tls encryption");
}

$cmd = "EHLO ".$_SERVER['HTTP_HOST'];
echo $cmd;
put($smtp,$cmd);
echo get($smtp); // 250

$cmd = "QUIT";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp);

echo "</pre>";

fclose($smtp);
craniumonempty
  • 3,525
  • 2
  • 20
  • 18
5

Your connection doesn't make much sense. By using the TLS handler, you want TLS to be established BEFORE any data goes. But port 25 is standard SMTP, which can only establish TLS AFTER you've initially connected via an unencrypted regular connection. Once that initial connection is established, then you can enable TLS with the STARTTLS command to tell the SMTP server to switch over.

If you want TLS from the get-go, then use port 465, which is ssl/tls from the start.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • Doesn't work with port 465 or 587 either but it works if I call the script directly from the command line via instead of accessing it through Apache (which has a static, public IP btw.) – Markus Lanthaler Jul 15 '11 at 14:16
  • Try just `fsockopen('smtp.xxx.com', 25)` without specifying any protocol. if that connects, but the tls version doesn't, then it's something goofy with the SSL stuff. – Marc B Jul 15 '11 at 14:18
  • That works, but as soon as I add the tls:// at the beginning it doesn't work anymore through Apache, but continues to work from the command line. – Markus Lanthaler Jul 15 '11 at 14:30
  • Another test would be to connect to an SSH server (plain ssl protocol) and see if that does anything. If the same thing happens, then there's something with your config that prevents Apache from using the SSL library properly, or something is blocking that type of outgoing connection from Apache. – Marc B Jul 15 '11 at 14:33
  • I tried to access Google's homepage via SSL, that works without problems: fsockopen("ssl://www.google.com", 443, $errno, $errstr, 30); – Markus Lanthaler Jul 15 '11 at 14:40
  • 1
    Found this: http://forums.powweb.com/showthread.php?t=73406 start with plaintext connection, then switch over to TLS with stream_socket_enable_crypto(). – Marc B Jul 15 '11 at 15:39
  • Thanks Marc, but that's not an option. I really have to solve the problem as otherwise the library I'm using to send mails doesn't work. – Markus Lanthaler Jul 15 '11 at 16:47
0

If it works from the command line but not from within Apache then there is probably some difference between the PHP configuration: do a diff between /etc/php/apache2/php.ini and /etc/php/cli/php.ini and see what might have changed.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • Good tip. But there aren't much differences. I did a diff, the only differences is that I don't allow short tags at the Apache one and different memory limits. – Markus Lanthaler Jul 15 '11 at 14:32