Kurt Keller's Blog

tech notes and more

squirrelmail v1.4 with newer PHP releases

I’ve been using squirrelmail for many years as a fallback solution to read my email when I’m on the go and don’t have a device at hand which allows me to connect directly to my mail server. Granted, squirrelmail does not have the sexiest user interface, it’s rather bare bones. But it does its job well, fast and reliably. Especially when travelling in countries with rather limited internet connectivity I much prefer lean and no-frills over nice and overloaded.

When setting up squirrelmail on a new server, however, I could not log in. It gave me an error code of 0 and no error message at all, but did not let me log in. Checking the actual network traffic I could see that it connected to the IMAP server over TLS and the server certificate was exchanged. But then the connection was reset. Nothing helpful in the logs. The IMAP server at least told me that no authentication was offered.

After hours of digging I found the cause of the problem: PHP. While the old server had PHP version 5.3, the newer server had version 5.6. As I learnt, some settings concerning encrypted network connections changed in PHP v5.6. Certificates are checked, a valid root certificate must be installed and available for validation and the name in the server certificate is checked with the server name used for connecting. The ssl settings are verify_peer, verify_peer_name and allow_self_signed. Actually I’m not using a self-signed certificate on the IMAP server, but I run my own PKI infrastructure and therefor the root CA is not available by default on the system. So either add the root certificate to the default system certificate store or tweak PHP to not check the certificate that carefully. I chose the latter. Unfortunately it is not possible to do this as a configuration option (neither in php.ini, nor in squirrelmail), therefor some code changes in squirrelmail were required.

The code changes which did the trick are a follows:

  1. Search for all places in the php code which call @fsockopen.
  2. The places where the server address is prefixed with tls:// are the ones which need to be changed.
  3. There are two possibilities to change the code:
    1. original code (sample):
      $imap_stream = @fsockopen($imap_server_address, $imap_port, $error_number, $error_string, 15);
    2. first possibility:
      $context = stream_context_create();
      stream_context_set_option($context, "ssl", "allow_self_signed", true);
      stream_context_set_option($context, "ssl", "verify_peer", false);
      stream_context_set_option($context, "ssl", "verify_peer_name", false);
      $imap_stream = stream_socket_client(
            $imap_server_address . ":" . $imap_port,
            $error_number, $error_string, 15,
             STREAM_CLIENT_CONNECT, $context);
      
    3. second possibility:
      $imap_stream = stream_socket_client(
                $imap_server_address . ":" . $imap_port,
                $error_number, $error_string, 15,
                STREAM_CLIENT_CONNECT, stream_context_create(
                array('ssl' => array('verify_peer' => false,
                                        'verify_peer_name' => false,
                                        'allow_self_signed' => true))));
      

Now it works again like a charm. Of course, the code could be changed in a different way, say to add options to squirrelmail to add these settings. Just too much work for the single installation I have. There is also the development version 1.5 of squirrel mail. Possibly that version already has fixes this potential problem. But quite honestly, I didn’t check that. The released version 1.4 comes prepackaged with my OS and I’m just too lazy to create new packages an put them in my repository, just for this single installation.

Some links which were helpful in solving this problem for me:

Share

Leave a Reply