Tuesday, 16 July 2013

Publish-AzureServiceProject : The remote server returned an error: (500) Internal Server Error

I had moved offices and started getting this error every time I tried to deploy a PHP cloud service directly using the Powershell Scripts. It took me a whole morning to fix but using Fiddler, I noticed that there was a timeout occurring during upload. This timeout is not reported directly by the script but it retries and when it ultimately fails, you get an error like this:

PS C:\projects\fws2> Publish-AzureServiceProject
VERBOSE: Publishing  to Windows Azure. This may take several minutes...
VERBOSE: 02:15:02 - Preparing runtime deployment for service 'fws2'
VERBOSE: 02:15:02 - Preparing deployment for socket with Subscription ID:
GUID...
VERBOSE: 02:15:25 - Connecting...
VERBOSE: 02:15:33 - Uploading Package to storage service xxx...
Publish-AzureServiceProject : The remote server returned an error: (500) Internal Server Error.
At line:1 char:1
+ Publish-AzureServiceProject
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Publish-AzureServiceProject], StorageException
    + FullyQualifiedErrorId : Microsoft.WindowsAzure.Management.CloudService.Cmdlet.PublishAzureServiceProjectCommand

I don't know if/how you could adjust the timeout or get it to report a much more useful error to the user. This happened because our new office has much slower upload speed than the old office and the timeout is only 90 seconds.

The workaround is not to use the Powershell script Publish-AzureServiceProject but to manually update the deployment from the Azure management portal by browsing to the local cloud_package.cspkg and ServiceConfiguration.Cloud.cscfg files. For reference, Visual Studio uses chunk uploading to get around the timeout problem and since the flag "-PackageOnly" is not yet available on the Publish-AzureServiceProject script, I usually run the script, wait for it to timeout and then upload the package it just created!

Monday, 8 July 2013

Matching encryption and decryption across PHP, Java and .Net

I have already posted some articles about standardising encryption and decryption across various platforms but came across another gotcha. The reality is that there are standards but the default setup and the names for these standards (unsurprisingly) differ and that's what makes it difficult.

I already use the .Net port of the OWASP ESAPI and that was useful because it gave me a known good implementation to work from. Well, I say OWASP but I actually changed it in several ways, firstly to add signed encryption and also to hard-code AES256 rather than having lots of configuration that i didn't actually need.

I managed to write a PHP decryption function which worked with data that was encrypted using .Net but I had problems when I then tried to write an encrypt function in PHP which would produce data that could be decrypted, also in PHP, using the previously written function.

Because I knew that the other functions worked correctly, this helped. Also, the PHP code required from the examples on php.net were brief enough that there weren't too many variables but I still resorted to echoing out the data at each stage to see where something didn't look write. I ended up getting stung with the string padding!

What mcrypt_encrypt does is pad the input data up to the block size of the cipher, in my case MCRYPT_RIJNDAEL_128 but using the null terminator (\0). This is confusing because when it is decrypted, the decrypted string uses the \0 to terminate the string whereas my decryption function was expecting to remove PKCS #7 padding which is added in the .Net implementation from OWASP. This adds a character whose value is equal to the number of padding characters (making it easy to work out how many there are).

My encrypt function didn't have this and fortunately, there was an example on php.net under the comments for mcrypt_encrypt() (thanks Antonio). I ended up with the following PHP:

protected function encrypt($plaintext)
    {
        try
        {
            // PKCS #7 padding for the string so that decryption works!
            $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
            $pad = $block - (strlen($plaintext) % $block);
            $plaintext .= str_repeat(chr($pad), $pad);
 

            // Create key and IV
            $key = $this->pbkdf2(Config('MasterPassword'), Config('MasterSalt'),1000,32);
            $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
            $ivBytes = mcrypt_create_iv($size, MCRYPT_RAND);


            $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $ivBytes);
            $encrypted_combined = $ivBytes . $encrypted;
            return base64_encode($encrypted_combined);
        }
        catch (Exception $e)
        {
            return null;
        }
    }


Note that the pbkdf2 is the password based key derivation function from here: http://en.wikipedia.org/wiki/PBKDF2 There are various implementations available. I'm not sure whether the PHP one works as expected since I ended up using one from someone else's project.

Friday, 5 July 2013

error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

Possibly my best post title to date but I got this error trying to send mail from Yii in PHP via a Gmail relay. It all looks a bit esoteric but like many errors, once explained, it all makes sense.

This relates to Gmail having two SSL/TLS ports. 465 is for SSL (i.e. pre-TLS) and port 587 for TLS. For most people, SSL and TLS are used interchangeably but not here! I was trying to relay via 587 and had, what I thought, was TLS enabled. As it happens, the mail extension for Yii didn't actually support TLS (or I have it configured wrongly) and was attempting to negotiate SSL with a TLS-only port. The error means the server doesn't support SSLv3.

I simply changed the config to use port 465 and we are back in business.

Good Yii Config:

 'mail' => array(
           'class' => 'ext.mail.YiiMail',
           'transportType' => 'smtp',
           'transportOptions'=>array(
                  'host'=>'smtp.gmail.com',
                  'encryption'=>'tls',
                  'username'=>'xxx@gmail.com',
                  'password'=>'xxxxxxxxxxxx',
                  'port'=>465,
            ),
            'logging' => true,
            'dryRun' => false
        ),

Thursday, 4 July 2013

Calling SQL Server with PHP/PDO, be careful with parameter positions

Take the following code:

$command=$connection->createCommand('EXECUTE procSetUserImage :userid, :filename, :ipaddress');
$command->bindValue(':userid', $userid);
$command->bindValue(':filename', $filename);
$command->bindValue(':ipaddress', $_SERVER['REMOTE_ADDR']);


And this stored procedure:

CREATE PROC procSetUserImage @userid INT, @ipaddress VARCHAR(20), @filename VARCHAR(20)

Would you expect it to work? I did but it doesn't, the filename is passed into the ipaddress parameter and vice-versa. This is because the names in the PHP are just substitution placeholders and not symbolic links to the actual parameters in the stored procedures.

In other words make sure you put them in the right order!