Wednesday, 4 May 2011

Search Query bug

I've just issued a bug report and patch for a problem with the Search Query class. It's not a huge bug but it prevented me from doing something I needed to do: add some restrictions to a Search Query.

There are two ways of modifying queries in Drupal 7, you can either use a generic "hook_query_alter()" or use "hook_query_TAG_alter()". Tags are a way of telling other modules what a query is about. For example you can have a tag "node_access" which allows modules to add additional restrictions on the query, in this case the Node module connects the query to node_grants.

The Search Query adds a "search_node" or "search_user" tag, unfortunately it adds the tag after the hooks have been called - which is as useful as a chocolate teapot. So I added the patch here: http://drupal.org/node/1146564 which simply moves the place where the tags are added.

Another thing to watch out for: the generic hook_query_alter() is not called on queries that have no tags. This is an efficiency thing as it was discovered early on that this hook was called a lot for no good reason during bootstrap.

Tuesday, 3 May 2011

Field encryption

In the next couple of weeks, along with my field_extract module (which allows developers to extract values from fields more easily), I'll also be uploading the initial version of the field_encrypt module (it works, but big sites would be problematic).

An "encrypted field" module already exists for Drupal 7 which allows you to add a special text field, that is encrypted, to an entity, but that's not what I needed. What I needed was a way of encrypting any field even if it already exists (install the module and choose which fields you'd like to encrypt).

There are a three handy hooks which make this possible: 'hook_field_storage_pre_insert', 'hook_field_storage_pre_update', and 'hook_field_storage_pre_load'; they allow other modules to intercept those actions and save or load a field - replacing the field module actions. So, knowing what fields I want to encrypt, I can intercept all load and save actions with those fields and replace them with my own save/load.

This module is only a first attempt and stores all encrypted data in one table. It would be more efficient to create separate tables for separate fields the way Drupal does. But that's for the future. It also doesn't handle deletion but I don't see that as a major issue for small sites. (There are some other areas where it would, in this initial version, have problems with big sites.)

Having said all that there is still a huge hole in security: In Drupal 7 loaded fields are stored in the "cache_field" table - completely unencrypted. I'll have to solve that too for the current client.

Sorry it's taking me so long after promising these modules but I've been rather busy...

EDIT: As I hate leaving too many loose ends the field_encryption module now checks for the presence of the mcrypt library before letting itself be installed; prevents itself being uninstalled if it is currently encrypting a field (to prevent data loss); and now overrides the standard "cache_field" functionality and encrypts cached field data as well. So it's about as secure as it can get.