Recap of the verification that there was no backdoor in the Horde 4 packages

By Gunnar Wrobel (22.2.2012, 23:00 UTC)

When we discovered the successful attack on two weeks ago we were of course frantic to determine which packages had been affected in addition to the one Horde 3 archive Jan identified as modified initially.

For the Horde 4 packages we had no hashes to verify the file integrity though. While PEAR supports signing of packages via GPG that seems to be a feature which is virtually unused. For one thing not that many PHP based projects use PEAR packaging and in addition there is no way to automatically verify package integrity on the user side when installing via PEAR. So we also didn't consider signing our packages when switching to installing Horde via PEAR.

Obviously you gain a different perspective on that issue once a hacker implanted a backdoor in some of your packages. Of course we invested a lot of time into securing our infrastructure now to ensure that such an event never happens again. On our side the file integrity is constantly monitored now. But we will also have to investigate how we can improve the PEAR based installation procedure so that it also allows for the required amount of security on the user side.

But if we had no hashes how did we ensure the Horde 4 packages were indeed unmodified? Git to the rescue! As we tag all our releases it was a matter of creating a short script to automatically compare the current state of the packages on our PEAR server against the state we had within git.

Without further ado - here is the script I used:


git reset --hard HEAD
git clean -f -d

STAMP=`date +%y%m%d-%H%M`
mkdir ../diffs-$STAMP
mkdir -p ../validate-$STAMP/
mkdir -p ../validate-$STAMP/rebuild

for package in `cat ../pear-recovery-packages.txt | grep -v ".tar$"`
  if [ "x${PPATH/Horde_*/}" == "x" ]; then
  if [ "x${PPATH/groupware*/}" == "x" ]; then
  if [ "x${PPATH/webmail*/}" == "x" ]; then
  PRESENT=`git tag -l $TAG`
  if [ "x$PRESENT" == "x" ]; then
      echo "======================================================================"
      echo "Tag $TAG for package $package is missing!"
      echo "======================================================================"
      echo "$package: TAG MISSING" >> ../status-$STAMP
      rm *.tgz                                                                                                               
      rm -rf ../validate-$STAMP/*
      rm -rf ../validate-$STAMP/rebuild/*
      GIT=`git checkout $TAG`
      horde-components -z $PPATH --keep-version
      if [ -e $package ]; then
          cp *.tgz ../validate-$STAMP/
          cp ../$package ../validate-$STAMP/rebuild/
          tar -C ../validate-$STAMP/ -x -z -f ../validate-$STAMP/*.tgz
          tar -C ../validate-$STAMP/rebuild/ -x -z -f ../validate-$STAMP/rebuild/*.tgz
          DIFF=`diff -Naur ../validate-$STAMP/${package/.tgz/} ../validate-$STAMP/rebuild/${package/.tgz/}`
          if [ "x$DIFF" != "x" ]; then
              echo "======================================================================"
              echo "Diff for package $package detected!"
              diff -Naur ../validate-$STAMP/${package/.tgz/} ../validate-$STAMP/rebuild/${package/.tgz/} > ..$
              echo "======================================================================"
              echo "$package: DIFF" >> ../status-$STAMP
              echo "======================================================================"
              echo "$package CLEAN!!!"
              echo "======================================================================"
              echo "$package: CLEAN" >> ../status-$STAMP
          echo "======================================================================"
          echo "Failed rebuilding package $package!"
          echo "======================================================================"
          echo "$package: FAILED REBUILDING" >> ../status-$STAMP

The script walks through the list of packages we had on the PEAR
server, moves back in time within ou

Truncated by Planet Horde, read more at the original (another 1487 bytes)

Horde 5 is coming / Horde 3 support ends

By Ralf Lang (22.2.2012, 11:21 UTC)

The spring 2012 release of the Horde Application Suite and Framework will probably be called Horde 5. In a recent discussion the majority of developers agreed on a new major revision for some changes that some view as minor backward compatibility break. Currently planned features include:

  • New standard UI for „traditional view“
  • Move of Ajax code from specific apps to a common framework
  • Release of a small inventory management app (sesha)
  • complete configuration via UI (likely)
  • Webmail: Write support for smartphone view
  • Calendar: Resource calendar support for ajax view

At the same time, Horde 3 will no longer receive any support. Horde 3 has been around since 2005 and really has reached its end of life.

Since the Horde 4 release, The Horde 3 family of applications has only received critical bugfixes and security updates, the last being released this february. You should really consider updating to Horde 4 – the transition from Horde 3 to Horde 4 has been tested and done by numerous people and the transition from Horde 4 to Horde 5 should run smoothly as both releases are PEAR based.

I have already removed all things horde3 from OpenSUSE-Factory. OpenSUSE 12.2 will not ship Horde 3 any longer. Depending on packaging progress, openSUSE 12.2 will very likely ship Horde 5 or the most recent Horde 4 release. Horde 4 maintainence will continue.

Horde 3 Packages in the server:php:applications repository (see here) will be available at least until openSUSE 12.1 runs out of maintainence. I won’t give these much attention though. Please also note Eleusis Password Manager will be dropped with currently no planned replacement.

Horde Config: How to fill dropdowns with application data with configspecial

By Ralf Lang (22.2.2012, 10:34 UTC)

Horde provides system wide customisation and configuration of applications through php configuration files. These files can be edited by hand or written from an administrator config UI. This ui is automatically generated from a file called conf.xml located in your $application/config/ directory.

The config xml allows dropdowns, multiselect fields, tick boxes, radio buttons and even conditionally adding or removing a field or inserting a valid php expression.

For example a  dropdown box in the horde base application’s config is generated by this snippet:


How does that work?

calls the horde api. the „application“ part tells you which application’s api to call. You can either reference an application by its registry name (horde, imp, kronolith, turba…) or by its api name (horde,mail, calendar, addressbook)

What’s the difference? When you call turba, you get turba. When you call addressbook, you can hook into whatever application provides addressbook. For example, spam handling and ticket queues have been implemented by multiple applications. You can even implement your own handlers for any existing api.

The called application must have a method configSpecialValues() in its lib/Application.php class file. This method gets called and its only parameter is the „name“ property from the xml. In our example it’s „sources“. This method will return an array of source names to use in your config screen.

     * Returns values for  configuration settings.
     * @param string $what  The configuration setting to return.
     * @return array  The values for the requested configuration setting.

    public function configSpecialValues($what)
        switch ($what) {
        case sources:
            try {
                $addressbooks = Turba::getAddressBooks(Horde_Perms::READ);
            } catch (Horde_Exception $e) {
                return array();
            foreach ($addressbooks as &$addressbook) {
                $addressbook = $addressbook['title'];

            $addressbooks[''] = _("None");
            return $addressbooks;

Et voila – you have a list of addressbooks to choose from.

Distributed applications with Horde 4

By Ralf Lang (18.2.2012, 21:31 UTC)


Horde’s powerful RPC API has been used numerous times to allow integration of horde-based data into external applications or remote sites. It also provides an easy to set up basis for distributed applications with headless workers. In this article I will give you a brief introduction on how to build a scalable distributed architecture based on Horde 4.

Distributed Architecture


  •  You want your application to be scalable over several hosts. We call the controlling instance the master and the reacting instances the workers.
  •  You don’t want to keep a lot of state on the worker. Adding or removing a worker instance should not require complicated setup. Most cloud layers like OpenStack assume worker instances to be virtually stateless. The master is the single source of truth and should be able to rebuild any broken or lost worker setup from stored information.
  • You are working in a hostile environment, e.g. the internet. Firewall only allows select ports and data has to travel over lines you cannot trust. You want to resort to https transport with real certificates.

The master:

I won’t go into too many  details on the master setup this time. Create a basic app from the skeleton as the horde wiki describes. Separate a communication driver for worker Api calls from the driving logic in your app and don’t couple them too tightly. Usually you want small commits of changes to both the master’s idea and the worker’s reality and you want to check back if everything worked out. This doesn’t scale well on large-scale changes though.

Sometimes you want to make complex changes to the „truth“ or „theory“ in the master’s db before you commit them to the worker world out there.

Accessing the worker from the master:

The core piece of your communication with the worker are just a few lines of code

   protected function callWorker(WorkerInstance $worker, $callMethod, array $parameters = array()) {
       try {
            $http = new Horde_Http_Client(array('request.username' => $worker->rpcuser, 'request.password' => $worker->rpcuserpass, 'request.timeout' => 20 ));
            $response = Horde_Rpc::request(
                    'https://' . $worker->worker_hostname . '/' . $worker->worker_subdir .'/rpc.php',
        catch (Exception $e) {
            throw new Appname_Exception($e);
        return $response;

This is a dumbed down version for demonstration purposes. You might want to model WorkerInstance based on Horde_Rdo, the horde ORM layer. It is desirable to evaluate lazy relations and lazy attributes. This has important performance implications but more on this in another post. We’re also selling consulting

Worker setup:

We want a stateless worker instance. Obviously, this is theory. Truth is: You need a unique IP and you probably want a unique hostname. Nowadays cloud layers can provide that level of configuration. How about a horde instance without db?


You want the worker to talk under a specific api name. Add a block to your registry.local.php

 'myvpnworkerworker' => array (
        'name' => _("someworkerfooname"), /* we can even drop the _() as nobody will localize this */
        'provides' => 'myvpnworkerapp',


This is stripped down to just the important lines
$conf['auth']['params']['htpasswd_file'] = '/not/in/webroot/passwords.secret';
 $conf['auth']['params']['encryption'] = 'plain'; /* In real world, you want to use some encryption instead */
 $conf['auth']['driver'] = 'http'; /* We want authentication by http layer after all */

We want the server to be stateless and not to rely on external data. We don’t want a local mysqld running and we don’t want a remote ldap either. We will store the credentials in a .htpasswd style file. For demonstration purposes, we use plain authentication.

The file would look like this:

passwd.passwd would look like this: 


We also want to get rid of any components which cannot work without an sql backend


Truncated by Planet Horde, read more at the original (another 4692 bytes)

Horde on CeBIT 2012

By Gunnar Wrobel (2.2.2012, 23:00 UTC)

It is official now: Horde gets a booth on CeBIT 2012! Sponsored by Linux New Media the company behind the Linux Magazine. Thanks! Simply awesome!

Hope to see you there!

Wiki time

By Gunnar Wrobel (1.2.2012, 01:00 UTC)

Tonight it has been wiki time. The article on IMP from the English wikipedia was a mere stub and I expanded it with a little bit of history. I will hopefully find the time to continue this later. I recently did the same for the Horde article.

In addition I updated the list of Horde deployments in our Horde wiki. I also added a list of Horde hosting providers and a list of alternate installation methods for Horde. I couldn't refrain from adding a short abstract on why we only offer PEAR with Horde 4 to the latter article.

Of course corrections and additions are very welcome!

Horde is calling you

By Gunnar Wrobel (30.1.2012, 23:00 UTC)

Yes, it's late... and I should either sleep or try to work for a final hour before collapsing onto a pillow. But instead I feel like writing a few lines. And calling strangers in the US...

I don't know the people I call there. But it is fun, I train my english, and on top they are usually happy about my call.

What we talk about? I explain them what a provider is. And why I'm actually unable to help them. Which maybe helpful information in its own right.

Of course these people called the Horde LLC before. The Horde webmail is running on so many servers around the world that we get a constant stream of requests for help from users that mistake Horde for their service provider. Usually we get a handful of e-mails every day asking whether we could reset the password, restart the server, or in general just "HELP!!!". Once in a week the line

I can't log in. My username is ABC, my password is XYZ.
reminds us how easy phishing is.

E-Mails are simple: sending out a friendly response with a link to one of our most successful wiki pages is an easy thing to do.

Phone calls are a different matter though. The phone number for calling us in the US has been set up by MojoLingo based on Adhearsion a while back. And of course we get a certain number of "I can't get my mail!" calls as well. We usually didn't answer these until MojoLingo helped us with setting up Voip access so that calls into the US generate negligible costs.

So I can sit here, run SipDroid on my little droid and call into US when I need a break or have a minute to spare. A few more pleas for help that do not get lost unanswered.

In case you ever get called by a stranger with a weird German accent after your Horde webmail broke you probably didn't read this blog post.

A Look Back, A Look Ahead

By Michael Rubinsky (27.12.2011, 20:44 UTC)
A look back at the last year and an update to my personal development roadmap.

Service_Weather for Developers Part 1

By Michael Rubinsky (23.12.2011, 19:07 UTC)
Basic HOWTO use Horde_Service_Weather for developers.


By Michael Rubinsky (22.12.2011, 15:48 UTC)
New weather API abstraction in Horde.