Just a Theory

By David E. Wheeler

iPod Threatens UK Military Security

20 GB iPod

Following up on my screed against the idea of the “iPod security threat”, James Duncan Davidson sent me a link to this story about how the UK military has decided that the iPod is a security threat.

“With USB devices, if you plug it straight into the computer you can bypass passwords and get right on the system,” RAF Wing Commander Peter D’Ardenne told Reuters.

“That’s why we had to plug that gap,” he said, adding that the policy was put into effect when the MoD switched to the USB-friendly Microsoft XP operating system over the past year.

Huh. Do you mean to tell me that if you plug into the USB port of a PC that no one is logged in to, you can get access to the contents of the PC without logging in? You know, that sounds more like a Windows security flaw than an iPod problem. I mean, it’s reasonable for the military to ban external media in order to prevent their personnel and contractors from copying sensitive data onto personal devices for unknown purposes. But this Windows security hole seems, well, huge.

And the truth is that these articles that single out the iPod as a security threat are being disingenuous, in that it’s much easier and much cheaper to use a USB Flash Drive. Furthermore, this banning of storage devices really only keeps honest people honest; those who really want to copy sensitive information to take home will figure out a way to do it if they’re motivated enough.

So yeah, highly sensitive security establishments should ban personal external storage devices to keep honest people honest, but really, they should also fix the real security problem with their operating system of choice.

Looking for the comments? Try the old layout.

Gartner: iPod is a Security Threat

20 GB iPod

Well, this is entertaining. It seems that the Gartner Group has decided that iPods are a significant security threat. I think it’s great that a company like that makes its money by telling people that, yes, you can copy files between your PC and your iPod, and that poses a serious security threat. Please.

The problem, of course, is not the iPod. Or digital cameras. Or floppies. Or CD burners. No, the problem is people. I prefer to build a company that trusts its employees. Novel concept, I know. So here’s the mantra: iPods aren’t security threats; employees are security threats.

Now, I had to think carefully about posting this, because it reminded me, suddenly, of the old gun nut statement that guns don’t kill people, people kill people. The reason why I’m willing to use it for the iPod and not guns, however, has to do with design. Guns are designed to kill. It kind of makes the statement moot. I mean, what would you expect people to do with them? iPods, however, are not designed to breach security. They’re designed to listen to music, to store files, to copy your calendar, etc. Now, whether an individual person decides to use the iPod in breach of a company’s security protocols is a matter independent of the iPod’s design and intended use.

So the mantra holds: iPods aren’t security threats; employees are security threats. But guns, yeah, they’re pretty much designed for killing.

Looking for the comments? Try the old layout.

Apache::TestMB Released!

As I mentioned last week, I’ve been working on a subclass of Module::Build that supports testing with Apache::Test. Today, Geoff announced the release of Apache::Test 1.12. This release includes the new Module::Build subclass, Apache::TestMB. Now anyone using Apache::Test to test their module can convert the build system to Module::Build.

To set an example, I’ve just released MasonX::Interp::WithCallbacks using the new build module. The conversion was simple; in fact, I think that Apache::TestMBis easier to use than Apache::TestMM (which integrates Apache::Test with ExtUtils::MakeMaker). My Makefile.PL had looked like this:

#!perl -w

use strict;
use ExtUtils::MakeMaker;
use File::Spec::Functions qw(catfile catdir);
use constant HAS_APACHE_TEST => eval {require Apache::Test};

# Set up the test suite.
    require Apache::TestMM;
    require Apache::TestRunPerl;
    Apache::TestMM->import(qw(test clean));
} else {
    print "Skipping Apache test setup.\n";

my $clean = join ' ', map { catfile('t', $_) }
  qw(mason TEST logs);

    NAME        => 'MasonX::Interp::WithCallbacks',
    VERSION_FROM    => 'lib/MasonX/Interp/WithCallbacks.pm',
    PREREQ_PM       => { 'HTML::Mason'             => '1.23',
                                'Test::Simple'            => '0.17',
                                'Class::Container'        => '0.09',
                                'Params::CallbackRequest' => '1.11',
    clean               => { FILES => $clean },
    ($] >= 5.005 ?    ## Add these new keywords supported since 5.005
      (ABSTRACT_FROM    => 'lib/MasonX/Interp/WithCallbacks.pm',
        AUTHOR           => 'David Wheeler <david@kineticode.com>') : ()),

The new Build.PL simplifies things quite a bit. It looks like this:

use Module::Build;

my $build_pkg = eval { require Apache::TestMB }
  ? 'Apache::TestMB' : 'Module::Build';

    module_name        => 'MasonX::Interp::WithCallbacks',
    license            => 'perl',
    requires           => { 'HTML::Mason'             => '1.23',
                                'Test::Simple'            => '0.17',
                                'Class::Container'        => '0.09',
                                'Params::CallbackRequest' => '1.11'
    build_requires     => { Test::Simple => '0.17' },
    create_makefile_pl => 'passthrough',
    add_to_cleanup     => ['t/mason'],

Much nicer, eh?

Looking for the comments? Try the old layout.

A Quick Trip to Alamosa

Milagro’s Coffeehouse

Last week, I went on a brief business trip for Kineticode to Alamosa, Colorado. The client was Adams State College, which is planning to use Bricolage to manage all of its content. Alamosa is a sleepy little town of 8,000 people 22 miles north of the border with New Mexico, situated in the largest valley in the world, I’m told. You can get any kind of food you want there, as long as it’s Mexican food, and the high altitude (ca. 2300 m) makes the tequila work wonders on one’s equilibrium.

Mostly I just worked with our clients, but I did manage to take a couple of photos, but I did manage to get a couple of photographs with my Nokia 6600. The “cool” coffeehouse in Alamosa is Milagro’s Coffeehouse, but to judge by their sign, I wasn’t sure I wanted what they were selling.

The flight home

Alamosa has a very small airport. When I flew in on the little prop plane from Great Lakes Airlines, I was one of two passengers. On the way out (I flew through Denver), there were five of us. I thought the engine looked cool out my window, so I turned on my phone (bad David!) and snapped another shot.

Looks like I might be returning to Alamosa soon to do some training. Maybe I’ll be able to get some more pictures; the sunsets are quite lovely there.

Looking for the comments? Try the old layout.

Module::Build + Apache::Test is Nearly Here

Over the last couple of days, I whipped up a new class to be added to the Apache HTTP Test Project. The new class, Apache::TestMB, is actually a subclass of Module::Build, and finally provides support for using Apache::Test with Module::Build. You use it just like Module::Build; however, since a lot of modules choose to install themselves even if Apache isn’t installed (because they can be used both inside and outside of mod_perl, e.g., HTML::Mason), I’m suggesting that Build.PL files look like this:

use Module::Build;

my $build_pkg = eval { require Apache::TestMB }
  ? "Apache::TestMB" : "Module::Build";

my $build = $build_pkg->new(
  module_name => "My::Module",

Pretty simple, huh? To judge by the discussion, it will soon be committed to the Apache::Test repository and released to CPAN. My MasonX::Interp::WithCallbacks module will debut with a new Apache::TestMB-powered Build.PL soon afterward.

Looking for the comments? Try the old layout.

How Do I Know Whether NTPD is Working?

Well, after figuring out how to configure NTPD, it appears to be working well: there are two processes running, and there’s a drift file. However, the drift file just has “0.000” in it, and ntpq doesn’t seem to know much:

% ntpq -p timed out, nothing received
***Request timed out

So, how do I know if it’s working? Is it working? Shouldn’t ntpq -p be more informative?

Looking for the comments? Try the old layout.

More about…

Fun with Module::Build Argument Processing

I’ve spend the better part of the last two days working on a custom subclass of Module::Build to build Bricolage 2.0. It’s going to be a lot nicer than the nasty custom Makefile that Bricolage 1.x uses. The reason I’m creating a custom subclass of Module::Build is to be able to do a lot of the extra stuff that building Bricolage requires. Such as:

  • Copying configuration files from conf/ into blib
  • Copying configuration files from conf/ into t for testing
  • Copying configuration files from comp/ into blib
  • Modifying Bricolage::Util::Config to contain a hard-coded reference to the location of bricolage.conf once Bricolage has been installed
  • Modifying the contents of bricolage.conf to reflect build options (forthcoming)
  • Modifying the contents of httpd.conf to reflect build options (forthcoming)

I’m sure there will be more as Bricolage develops (such as building the database!), but this is enough for now. I’ve also been hacking on Module::Build itself to add features I want. For example, I want users to be able to pass options to Build.PL when they call it, so that it can do silent installs. As it is, you can pass options now, but Module::Build’s option processing lacks flexibility. For example, you can pass options like this:

perl Build.PL opt1=val1 opt2=val2

And Module::Build will store the options in a hash like this:

{ "opt1" => "val1",
  "opt2" => "val2" }

It understands options that use --, too; This invocation

perl Build.PL --opt1 val1 --opt2 val2

produces the same hash. But be careful how you specify arguments! For example, Modul::Build doesn’t understand unary options or options that use both -- and =>! To whit, this invocation

perl Build.PL --loud --opt1=val1 --opt2=val2 --foobar

Yields a hash like this:

{ "loud" => "--opt1=val1",
  "opt2=val2" => "--foobar" }

Certainly not what I would expect! So to get great flexibility, I sent a patch to the Module::Build mail list adding a new parameter to new(): get_options. This is an array reference of options that will be passed to Getopt::Long::GetOptions() before Module::Build parses arguments. It stores the results in the same hash as Module::Build normally does, and options not specified in get_options will be processed by Module::Build just as before. But it gives a whole lot more control over what gets grabbed. For example, if I were to try to get that last example to do what I want, all I’d need to do is pass in the appropriate Getopt::Long specs:

my $build = Module::Build->new(
    module_name => "Spangly",
    get_options => [ "loud+", "opt1=s", "opt2=s", "foobar" ],

Now, the hash yielded is:

{ "loud"   => "1",
  "opt1"   => "val1",
  "opt2"   => "val2",
  "foobar" => "1" }

Isn’t that nicer? And because the full suite of Getopt::Long specification is supported, you can get even fancier:

my $loud = 0;
my $build = Module::Build->new(
    module_name => "Spangly",
    get_options => [ "loud+" => \$loud, "foobar!" ],

Now this invocation:

perl Build.PL --loud --loud --nofoobar

…sets the $loudscalar to 2, while the args hash is simply { "foobar" => "0" }. Cool, eh?

Now I’ve just been discussing the patch with Dave Rolsky on the mail list, and he argues that, while this is a good idea in principal, he’d rather see a data-structure based argument list rather than Getopt::Long’s magical strings. Perhaps Module::Build will end up “Borging” some of the ideas from Getopt::Simple. But either way, I think that better argument processing is on the way for Module::Build.

Looking for the comments? Try the old layout.

More about…

david.wheeler.net Content Migration

I’ve completed the migration of all of the content from my old site, david.wheeler.net. All requests to that domain will get a permanent redirect to this site. Where possible, I tried to make the old URLs redirect to the new URLs. So if you try to connect to david.wheeler.net/osx.html, you should be automatically redirected to www.justatheory.com/computers/os/macosx/my_adventures.html. The same goes for the following documents:

If you happen to notice that I missed anything, comment on this blog entry to let me know.

Looking for the comments? Try the old layout.

NTPD Configuration on FreeBSD and Red Hat Linux

Well, I got no responses to my request for assistance setting up NTPD on FreeBSD, but today I must’ve just been Googling better, because I found the resources I needed.

The most important site I found was the NTP configuration page from Computer Facilities Management at the University of Washington. It was valuable because it provided some simple ntpd.conf file samples that set up ntpd to run only as a client. So no I’m confident that no one will try to connect to my servers and cause any mischief. The CFM NTP page also helpfully pointed out that I could easily enable ntpd on my Red Hat box by typing chkconfig ntpd on.

Another interesting site I found is www.pool.ntp.org. The cool thing about using pool.ntp.org as the time server to synchronize my servers to is that it distributes the load to lots of time servers. So I set up my ntpd.conf files to point first to pool.ntp.org, and then to two geographically close servers.

And finally, this DynDNS page gave me the instruction I needed to get ntpd running on FreeBSD. All I had to do was add xntpd_enable="YES" to /etc/rc.conf. I restarted my box, and now I’m in business!

Looking for the comments? Try the old layout.

More about…

Bricolage 2.0 UML Diagram

I’ve just finished updating the UML diagram for the design of Bricolage 2.0. It’s not completely comprehensive, mainly because the lines would start criss-crossing all over the place and no one would never be able to make any sense of it, including me! Notably, I’ve left out the links to Bricolage::Biz::Site, Bricolage::Biz::Class, Bricolage::Party::Person::User, and Bricolage::Party::Person::Contributor. But it’s pretty clear how they hook up if you study the classes, since they contain the appropriate *_guid attributes. And that’s all those of us who will be writing Bricolage will need.

I’m happy to get this largely done. The technical specification is also largely complete. I’m going to fill in a bit on Bricolage::Client::CLI right now, but otherwise, it will probably be stable for a while. It will change of course, because it’s not completely comprehensive, and there will be things that I haven’t thought about as I’m starting to code. But that’s probably a ways off, as there is quite a lot to get going with right now.

I’m not sure if I’ll update the functional specification anytime soon. It’s really out of date, but would take up quite a lot of time to rewrite, and for what benefit I’m not really sure at this point. The technical spec contains most of the information I need. Perhaps it will be time to update the functional spec once the API is nearing completeness and I start really working on the UI.

In the meantime, it’s time to get back to hacking!

Looking for the comments? Try the old layout.

How do I Configure NTPD?

So I need simple instructions to get NTPD running on FreeBSD. It should function solely as a client, and not accept connections from other servers. I could also use the corresponding instructions for Linux (and don’t say “RPM”!). I’ve found an awful lot of information online about NTPD, but the simple instructions for setting up a secure NTPD to start when the system starts up are sorely lacking. Part of the problem with regards to BSD may be my not yet fully understanding how FreeBSD startup stuff is supposed to work, but I also can’t find simple instructions for how to configure ntptd to operate only as a client.

Links and instructions gladly accepted.

Looking for the comments? Try the old layout.

More about…

bricolage.cc Has a New Server

The Bricolage project has a new server! Thanks to a generous donation from NetStumbler.com, we have a shiny new hosted FreeBSD server. I’ve started building it, and have migrated the Bricolage Web site over today. By tomorrow, DNS records should be updated, and it’ll be rarin’ to go!

While I was at it, I rolled out the new Bricolage API documentation browser. There are now browser available for all of the major stable releases of Bricolage, listed on the old documentation page. The API browser for the current stable release will always be available here. Meanwhile, the documentation will also be generated from the Subversion trunk every morning; you can find those docs here.

We’ll also be able to keep better track of the kind of traffic the site gets thanks to the new stats site, which will also be updated daily.


Looking for the comments? Try the old layout.

More about…

Perl.org Subversion Authentication Woes

It looks like the Perl.org authentication system that handles authentication for svn.bricolage.cc doesn’t properly cache an authentication token. Robert discovered this when a very large merge I was working on from the rev_1_8 branch of Bricolage to trunk was hanging and then timing out on me. The problem was that it was disconnecting from the MySQL server. Odd. At any rate, Robert switched over to an auth system that doesn’t use MySQL so that I could do the merge and then the commit. This morning, he restored the original auth system. I shouldn’t often have to do such a big merge or commit in Bricolage, so hopefully it won’t come up again, but it sure was annoying there for a while.

So for my fellow Bricolage developers who thought that the auth system was down: Sorry, it’s back now. And the trunk is fully updated with all of the changes to rev_1_8, which means that new development in the trunk can begin again in earnest.

Looking for the comments? Try the old layout.

More about…

Blosxom Rewrite Rules

I finally got my mod_rewrite rules working for Blosxom, so now it finally looks like I have a real site! The problem was that %{REQUEST_FILE} wasn’t actually the full file name on the file system, but the request URI! I have no idea why, but once I figured out this problem I was able get ‘round it by using %{DOCUMENT_ROOT}%{REQUEST_URI}. So now my configuration looks like this:

<VirtualHost *>
  DocumentRoot /usr/local/www/doc_roots/justatheory
  ServerAdmin david@justatheory.com
  ServerName justatheory.com
  ServerAlias www.justatheory.com
  CustomLog /usr/local/www/logs/access_log.justatheory combined
  <Directory /usr/local/www/doc_roots/justatheory>
    AddHandler cgi-script .cgi
    Options +ExecCGI
  RewriteEngine on
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
  RewriteRule ^/(.*)$ /blosxom.cgi/$1 [L,QSA]

And all is well. Now, if only I could get the meta plugin working properly…

Looking for the comments? Try the old layout.

How to Extend Bricolage 2.0

Going through the latest version of the Bricolage 2.0 technical specification, I can see at least six ways that developers will easily be able to extend Bricolage:

Write a new task by subclassing Bricolage::Biz::Task
A task can be designed to do just about anything to a single Bricolage object. Hell, you’d be able to look up other objects, too, so anything’s possible. Tasks are run by scheduled jobs, event-triggered actions, or by distribution jobs.
Create a new data type by subclassing Bricolage::Biz::Value and Bricolage::Biz::Type::Value
We’ll support quite a few different value types to start with, but we couldn’t anticipate everything, so this’ll be your chance!
Create a new UI widget by subclassing Bricolage::Widget and Bricolage::Biz::Type::Widget
Maybe your new value requires its own special widget. Or maybe you don’t like the way the existing widgets handle other types of values. So write your own!
Write a new distribution mover by subclassing Bricolage::Biz::Dist::Mover
We’ll start out with file system copy, SFTP, SFTP, and WebDAV distribution movers just as we have in Bricolage 1.8, but there’s always room for more!
Write a new authentication plugin by subclassing Bricolage::Util::Auth
The built-in and LDAP-based authentication systems aren’t doing it for you? You want to authenticate against a different database? Make it so!
Write a new storage back-end by subclassing Bricolage::Store
We’ll have a PostgreSQL back-end from the start, and perhaps SQLite and/or MySQL. But here’s your chance to get Bricolage running on FileMaker Pro just as you’ve always secretly desired!

So have fun with it! When it gets here. Want to help get get here? Subscribe to Bricolage-Devel and chip in!

Looking for the comments? Try the old layout.

More about…

Bricolage Tasks, Jobs, Actions, and Alerts

I’ve been working on the design for what are called distribution jobs and alerts in Bricolage 1.x. There were some good ideas there. Distribution jobs enable users to set up a list of tasks to execute against the files being distributed, such as validating them against a DTD or distributing them via email. It also allowed developers to create fairly simple plugin modules that could be added as new jobs. Alerts are great ways of letting users know that some even has happened, and their rules-based evaluation of event attributes is a powerful way of configuring alerts to be sent only for certain events logged for certain objects.

The problem is that they’re specific solutions to general problems. Distribution job s are an example of scheduling arbitrary tasks to be executed, while alerts are an example of triggering the execution of arbitrary tasks upon the logging of an event. So what I’ve been working on is trying to generalize these ideas into a simpler yet more powerful and flexible architecture. What I’ve come with is this:


Very simply, a task is an object of a class designed to perform a simple, um task. Examples include publishing a document, expiring a document, sending an alert, or validating a file against a DTD. An abstract base class, Bricolage::Biz::Task, will establish the the interface for tasks, although its subclasses may add their own attributes (such as the subject and message of an alert). Each will implement an execute() method that will simply carry out the task on the object passed to it. Some task classes may operate on only one type of object (such as Task::Publish), while others may operate on many or even all Bricolage business classes (such as Task::SendAlert). There is no connection between task classes and events or jobs, except that the object that called the task object’s execute() method will be passed to execute() as a second argument.


An action is an event-triggered series of tasks. New action types can be created that have rules set to be evaluated against the event, just as is currently the case for alert types in Bricolage 1.x. The difference is that rather than being limited to sending alerts, actions types will be associated with one or more task objects, and each of those tasks will be executed in sequence when an action of that type is triggered. This will enable users to, for example, configure an action to republish an index document whenever a story document is published.


A job is a scheduled series of tasks. Users will be able to create new jobs for any single object in Bricolage, associate any number of task objects, and then schedule the job to be run at some specific date and time in the future. This approach will enable users to, for example, schedule a job to send an alert about a given document one year in the future, as a reminder to update the document.


Destinations will be similar to what’s currently in Bricolage 1.x. However, rather than having “job” classes specific to distribution, they’ll be able to specify a list of any tasks that are designed to be executed against an output file. This keeps the interface for tasks identical across all three uses.


Alerts are no longer closely tied to events, since they can sent as part of a scheduled job or as part of a distribution to a destination in addition to when an event is logged. Rather, they will only be created by Bricolage::Biz::Task::SendAlert. So a Bricolage business object can have any number of associated alerts, just as it can have any number of associated events.


The upshot of this redesign, which took me several days of thinking to tease out to be general enough to satisfy me, is that more users will have more of what they need from Bricolage, and developers can more easily add new functionality that’s immediately available to event actions, scheduled jobs, and distribution destinations.

Looking for the comments? Try the old layout.

More about…