ZF-4600: Allow Select to be serializable

Description

It's not possible actually to serialize a Zend_Db_Select object, as it encapsulates the adapter instance which cannot be serialized.

Selects should be serilizable as this could use caching queries creation.

I'm working on a patch that acts the same way as Zend_Db_Table_Row : it uses __sleep() to disconnect the select object from the DB. __ wakeup() is used with the registry to look for a Zend_Db_Adapter instance into it to assign it back to the Select object. Additionnaly, a setAdapter() method is also provided.

Comments

Attached a patch that shows how it could work.

Work to do : search for all $this->_adapter calls and throw an exception if not in connected mode.

After talking together with Ralph, here is a patch that is backported to the adapter. The select object then keeps its adapter, that's the adapter which drops its connection object.

Simple managing options are also available, methods would follow and those options should get merged with constructor config optionnal options. protected $_allowSerialization protected $_autoReconnectOnUnserialize

Use Cases :


// default behavior
session_start();
$options = array();

$params = array(
    'host'           => 'somehost',
    'username'       => 'my-name',
    'password'       => 'secret',
    'dbname'         => 'dbname',
    'options'        => $options
);

$db = Zend_Db::factory('Mysqli', $params);
$_SESSION['dbInstance'] = $db;
// ...later, on another page...
$_SESSION['dbInstance']->fetchAll(); // OK

// disallow serialization
$options = array(Zend_Db::ALLOW_SERIALIZATION => false);
$params = array(//.......);
$db = Zend_Db::factory('Mysqli', $params);
$_SESSION['dbInstance'] = $db; // exception

// allow serialization, but do not reconnect SGBD on unserialization
$options = array(Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE => false);
$params = array(//.......);
$db = Zend_Db::factory('Mysqli', $params);
$_SESSION['dbInstance'] = $db; // OK
// ...later, on another page...
$_SESSION['dbInstance']->fetchAll(); // exception

r13136 allows Adapter object to be serialized

Allowing database adapters to be serialized is a security risk, because the username & password are part of the object data in plain text. If you aren't careful where you store the serialized object, you could expose these credentials.

This is why the serialization of {{Zend_Db_Table_Row}} does not serialize the {{Adapter}} object. The developer is required to establish the connection in a secure manner before a {{Row}} object can be used "live" again.

Zend_Db_Table_Row has the added benefit of being able to use the static Zend_Db_Table_Adatper::$_defaultDbAdapter, which allows the object to be serialized and unserialized without being injected to.

I am still chewing on this as well as roping others into the discussion. In general, if people are taking care of their security concerns as the Zend_Session layer, then presumably the username/password in the serialization container is as safe as it is inside the ini file it originated from.

More comments to come I am sure. :)

Julien,

The original patch suggested that it would consult the registry and also Zend_Db_Table_Abstract::getDefaultAdatper() before (i think) attempting to write to the session, was that the case? I did not see this inside Zend_Db_Select (didnt see any code for sleep and wakeup).

-ralph

The final patch doesn't include any serialization paradigm to the select object, but does to the adapter object. See my comment on 22/Oct/08 10:45 AM and http://framework.zend.com/code/changelog/…

What was the reasoning behind not including serialization to the select object? It seems like if the patch above were applied, it would (in most cases), not need the Zend_Db_Adapter to be serialized as well, right?

I dont remember the reason why we did not patch Select but Adapter instead. Affirmative : serializing the Select object would then not need the Adapter to be serialized, just detached.

I think we should probably include the bits of the original patch so that in most cases, the adapter and its credentials dont make their way into an insecure cache. While I think this is probably an edge case, we should at least do our best to provide a solution for this potential information leak.

I am reopening.

Bulk change of all issues last updated before 1st January 2010 as "Won't Fix".

Feel free to re-open and provide a patch if you want to fix this issue.