27 July 2008

barn swallows: alive and well

Today I saw the four fledgelings perched on a nearby railing. Their parents still bring them food.

When I got home last night, two of them were perched on a door frame near where the nest used to be.

railing

24 July 2008

barn swallows: moving on

When I left for work this morning, the nest appeared to be empty--I didn't even see Stoopy lurking in it. I guess they were all off doing...well, whatever barn swallows do (eat insects and make poop, I suppose).

When I got home from work, I saw that the painters had taken down the nest so that they could paint the entryway. Lame, but at least they waited until the hatchlings had become fledgelings. If that was a deliberate decision, it was a nice one.

This evening as I left for a bike ride, the entire crew swooped past me single file through the entryway, as if to say "hello" (or perhaps "oh god it's a human fly away as fast as you can"--it's a subtle difference). And when I came back, one of the fledgelings was perched on the doorframe close to where the nest used to be.

So I guess they'll be OK. It was nice having them as neighbors for a while.

23 July 2008

fledgeling barn swallows

Maybe they hatched earlier than I thought, because a couple of them were flying a bit today.

When I came home from work, one of them was perched on a rail about 30 feet away from the nest.

Another one was fluttering around a bit near my doorway. He didn't seem comfortable going too far, but he was able to hover and then land on the nest. (That was pretty cool to see.)

A third one was staying in the nest. That one holds his (her?) wings a bit funny--up higher closer to his head. It almost makes him look like an old man with a stoop. I'm wondering if that one is healthy.

When one of the parents came to bring food, Stoopy was the only one I saw stick his head out of the nest. So I can't account for one of the hatchlings. I looked around a bit but didn't find the fourth anywhere nearby on the ground.

Update: I just stepped outside to have a look, and all four hatchlings are back in the nest. They're big enough now that it's pretty crowded.

22 July 2008

barn swallows; bigger and bolder

They're painting my building, so each day I fear that I'll come home to find that the painters have "evicted" the hatchlings (which they probably wouldn't survive). But they were still there again today.

It amazes me how much they've grown in just over a week. wikipedia says that barn swallows fledge (I believe that more-or-less means "leave the nest") after about 18-23 days, so they've got another week or two.

3 of the hatchlings

17 July 2008

php|arch article

I got another article published. In fact, it looks like I made the cover of the June 2008 issue of php|architect. The article is titled "EAV Modeling" and talks about a database design I've used in a couple of recent projects.

Working with the editor on this assignment was a good experience. She made me feel a lot more involved in the process than I did with the Linux Journal article. *shrug*

16 July 2008

barn swallows

About a month ago I started noticing a bird's nest attached to the wall near the door to my apartment. I'd occasionally see a couple of small, orange-and-black birds coming and going. Because of something that happened a couple of days ago, I wanted to find out what kind of birds they were.

A Web search directed me to whatbird.com. This site has a pretty cool search feature allowing you to enter certain characteristics of a bird (size, color, tail shape, etc.), and it'll help you figure out what kind of bird it is. Turns out that my neighbors are barn swallows.

The thing that happened earlier in the week is that their eggs hatched. So now I have about four other new neighbors. I took a few pictures and posted some of the better ones to my flickr account:

closeup

feeding

12 July 2008

PHP frameworks: performance

For some time now I've been trying to figure out what to do about PHP frameworks. Most notably I've been wondering which one would be best for my needs and whether or not it's worth my time learning one. The problem is that there are so many. Zend, Cake, and Symfony appear to be pretty popular (at least, they are frequently mentioned in PHP blogs).

developertutorials.com has a post which highlights a recent performance analysis of Zend, Cake, and CogeIgniter. The concluding sentence is a good summation:

...if you’re building small applications, CakePHP will clearly save you time in development, CodeIgniter will offer massive performance benefits, and Zend will give you a reasonable middle ground.


Still not sure which one I want to try, but I lean a bit toward Zend (although it has received some recent criticism regarding its coding conventions and documentation). I like it that you can use it as a full-blown framework or just import the features you need for your application.

When I get some time, I guess *shrug*

07 July 2008

mod_security

mod_security is an open source Web application firewall which operates as an Apache module. mod_security inspects incoming requests (and, I believe, can also inspect outgoing responses) and take certain actions if a request (or response) matches a pattern. These actions can include logging and/or blocking the request. mod_security works sort of like anti-virus software, in that it comes with a ruleset which can identify common malicious activity (like cross-site scripting and SQL injection attempts). Like anti-virus software, it's necessary to update the ruleset from time to time.

I installed mod_security on a couple of production RHEL5 Web servers lately, and here are a few of my observations.

Installing mod_security is pretty easy and is documented in the mod_security download. I found that I needed to install the following packages to meet some dependencies and to build mod_security:
  • apr-devel
  • gcc-c++
  • httpd-devel
  • pcre and pcre-devel
  • libxml2-devel

I had the support of my managers to put mod_security in full blocking mode, so after copying the rules directory to /etc/httpd/modsecurity.d, I saved the following in /etc/httpd/conf.d/modsecurity.conf:

LoadFile /usr/lib/libxml2.so.2

LoadModule security2_module modules/mod_security2.so
LoadModule unique_id_module modules/mod_unique_id.so

<IfModule mod_security2.c>
Include modsecurity.d/*.conf
Include modsecurity.d/optional_rules/*.conf
</Ifmodule>


The Web servers run a variety of custom Web applications as well as some canned software like Webcalendar and Wordpress. I didn't experience any problems with the custom applications or Webcalendar, but mod_security took issue when someone tried to edit an existing blog post in Wordpress (curiously, there wasn't any trouble when submitting a new post). So I put the following in /etc/httpd/modsecurity.d/modsecurity_crs_15_customrules.conf:

<Directory /path/to/wordpress/wp-admin>
SecRuleEngine Off
</Directory>

I'm in the fortunate (and perhaps unusual) situation of being able to restrict access to the wp-admin directory by IP address, so I don't have the entire Internet hammering at the thing. Looks like blogsecurity.net has a custom mod_security configuration for Wordpress which I just haven't had time to try yet.

Another wrinkle I had was that some command-line Perl programs I run would be blocked because they weren't providing "accept" and "user-agent" request headers. One of these programs looked something like this:

#!/usr/bin/perl -w

use strict;
use HTTP::Request::Common;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new();
my $uri = shift @ARGV;
my $res = $ua->request( GET $uri );
print $res->content();

I had to make the following two changes/addition:

$ua->agent('whinerack');
my $res = $ua->request( GET $uri, accept => 'text/html' );

(Looks like just about any non-blank user-agent will do.)

Another trick I've learned is that instead of using SecRuleEngine Off (like I did for the Wordpress wp-admin directory, which makes mod_security totally ignore that directory), you can use SecRuleEngine DetectionOnly, which makes mod_security log what it would do without actually blocking requests. This can be good for debugging.

And although I haven't needed it, the mod_security documentation suggests a way to whitelist requests from a specific host:

SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,allow


All in all, installing mod_security has been a fairly easy transition, and it's nice having another layer of protection.

06 July 2008

xephem in Ubuntu

I was out with friends last night (4th of July fireworks), and they asked me to identify a bright object in the sky (I used to be an astronomer). I'm really out of practice at that kind of thing, so I speculated that it was Sirius (there was some light cloud cover, and I couldn't see whether or not this object was southeast of Orion, but it was pretty bright). Turns out I was wrong.

There's a really cool desktop ephemeris program called Xephem from the Clear Sky Institute. So I installed that on my Ubuntu desktop this morning to find what that thing was last night. I had to fulfill a few dependencies to compile xephem. Here's what I had to install first (I just explicitly installed the ones in bold--apt-get installed the packages in parentheses as dependencies):
  • libxt-dev (libsm-dev, libice-dev)
  • x11proto-print-dev
  • libxp-dev
  • libxext-dev (x11proto-xext-dev)
  • libxmu-headers (?)
  • libxmu-dev

(I'm not sure I needed libxmu-headers.)

After that I mostly just followed the directions in the INSTALL file from the xephem download. I copied the data directories (auxil, catalogs, etc.) to /usr/share/xephem (a directory I created) and put the following in ~/.xephem/XEphem (xephem didn't seem to want to read /usr/X11R6/lib/X11/app-defaults/XEphem as the INSTALL file suggested):

XEphem.ShareDir: /usr/share/xephem


I also gziped the man page (xephem.1) before copying it to /usr/share/man/man1/xephem.1.gz. And I created /usr/share/doc/xephem-3.7.3/ and copied in the Copyright, INSTALL, and README files.

By the way, that object turned out to be Jupiter. shrug

05 July 2008

apt-get: "kept back"

I have the following (executable) file in /etc/cron.daily on my Ubuntu desktop:

#!/bin/bash

apt-get update
apt-get -s upgrade


This lets me know when updates are available: the -s option lists available updates without running them unattended.

Occasionally I'll get a list saying that some updates have been "kept back." I always have trouble remembering what to do in this case. It's typically just some dependency problem. This issue is addressed in the APT HOWTO on the Debian Web site. In my (limited) experience, this has always been overcome by doing apt-get instal pgkname, where pkgname is the offending package which is being "kept back."

29 June 2008

n800 maemo updates

I got a Nokia n800 Internet tablet a few months ago and installed the Maemo os2008 software platform. I put the n800 in red pill mode to install some packages, and I just left it that way and forgot all about red/blue pill mode.

It didn't take long for me to find that updates just didn't work, but I never put the two things (red pill mode and broken updates) together. Looks like this is a well-known problem (see the bottom of the red pill mode wiki page linked above).

So if you put your n800 in red pill mode and updates don't work (mine complained that it needed to resolve libglade dependencies: it seemed to want to update to a version which was already installed), put it back in blue pill mode and try running updates. That worked for me.

22 June 2008

mcrypt randomness in PHP

The other day I was trying to debug a PHP program which was being really slow. I'm not bright enough to use proper debugging tools (like xdebug), so I just sprinkled in a bucketload of error_log() calls until I figured out what was gumming up the works.

It turned out to be an mcrypt_create_iv() call. Sometimes that call would run in a fraction of a second, and sometimes it would take over a minute, with no discernible pattern. I had pretty much done a copy-and-paste from the mcrypt_module_open() manual page, which shows using the MCRYPT_DEV_RANDOM constant as the second argument to mcrypt_create_iv(). It finally occurred to me to try using the MCRYPT_DEV_URANDOM constant (note the "U"), instead, and the encryptions immediately became consistently fast.

This was happening on a VMWare ESX guest running RHEL4. A Web search or two found a good comparison of /dev/random v. /dev/urandom, and my problem turned out to be a good illustration of /dev/random blocking the caller until sufficient entropy is attained.

21 June 2008

HTML form attack

The other day I came across a post about the HTML form attack.

I don't think I'd seen this before, and I'm not well versed in JavaScript attacks (authors of the planet-websecurity.org blogs would probably point, laugh, and yell "NOOB!"). But when I sort of figured out what it was talking about, it occurred to me that a form on a page which is vulnerable to cross-site scripting could be made to POST to an arbitrary location. Try the following in a JavaScript-enabled browser, and see where it ends up taking you when you click the submit button:

<html>
<body>
<form id="gakkk" action="/good.html">
<input type="submit" />
</form>
<script type="text/javascript">
// <![CDATA[
document.getElementById('gakkk').action = '/bad.html';
// ]]>
</script>
</body>
</html>

20 June 2008

GPG wallet in cygwin

The other day it occurred to me try my password wallet in cygwin. The wallet requires dialog, but cygwin doesn't seem to have a dialog package. So I figured I'd try building it.

dialog requires ncurses, which meant that I needed to install the ncurses-devel cygwin package (using the cygwin setup tool). Then I downloaded the dialog source and did configure && make && make install, and that "just worked" to get dialog in cygwin. And then the wallet "just worked," too.

So if you're running Windows and want to try the password wallet, install cygwin and give a wallet a try.

19 June 2008

AdoDB, PHP, MySQL, SSL

(I'm practicing for an "Unreadable blog post title" contest.)

Here are a few hints on how to use SSL certificates when connecting to MySQL from a PHP program using the AdoDB database abstraction layer. (You may want to see my previous post on setting up SSL certificates for MySQL connections.)

The trick is to use a DSN in the NewADOConnection() call (rather than authenticating with a Connect() call) and to use the mysqli driver (looks like the mysql driver won't work for this). The DSN syntax allows you to supply client flags, and there's a mysqli flag for using SSL certificates.

After creating a CA certificate (we'll say it's at /path/to/ca-cert.pem), make sure that the following item is in the [client] stanza of /etc/my.cnf or the connecting user's ~/.my.cnf on the client host:

ssl-ca=/path/to/ca-cert.pem


Then try the following PHP program:

// these are part of the AdoDB library
require '/path/to/adodb-exceptions.inc.php';
require '/path/to/adodb.inc.php';

/*
* I got the '2048' from running
* printf( "%d\n", MYSQLI_CLIENT_SSL )
* in a PHP program (w/ the mysqli extention installed)
*/
$dsn = 'mysqli://ssluser:sslpass@dbhost/test?clientflags=2048';

$dbh = NewADOConnection($dsn);

$sql = "show status like 'ssl_cipher'";
$res =& $dbh->Execute($sql);
print_r( $res->fields );
$res->Close();
$dbh->Close();


This should generate output similar to like this:

Array
(
[0] => Ssl_cipher
[Variable_name] => Ssl_cipher
[1] => DHE-RSA-AES256-SHA
[Value] => DHE-RSA-AES256-SHA
)

17 June 2008

SSL in MySQL connections

Last week I wanted to figure out how to use SSL certificates in MySQL connections. This is well-documented on the MySQL Web site, but here are a few wrinkles I experienced while figuring out how to get this working (this was with MySQL5 on CentOS5 and RHEL5).

After creating the certificate authority (CA) certificate/keyfile pair, you can specify them in the mysqld section of /etc/my.cnf:
ssl-ca=/etc/pki/CA/ca-cert.pem
ssl-cert=/etc/pki/tls/certs/mysql-server-cert.pem
ssl-key=/etc/pki/tls/private/mysql-server-key.pem


When making certificates for a client connecting locally (e.g., ssluser@localhost), it's important to supply localhost as the "common name" when prompted by openssl. (Yes, it's probably pretty silly to use SSL for a connection over the loopback interface, but you might be in this situation if you were testing.)

If you want to specify the CA (whose signature must appear in client certificates) when setting up a MySQL user (as you might when using the require x509 syntax), the fields should be separated by backslashes ('/'): grant usage on *.* to ssluser@localhost require issuer '/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd/CN=www.example.com/emailAddress=webmaster@example.com';
The following command will more-or-less correctly format the issuer for the grant statement:

openssl x509 -text -in /path/to/ca-cert.pem | grep Issuer \
| cut -d':' -f2 | sed -e 's/, /\//g'


Using issuer and subject items imply x509, and it's an error to try using x509 and issuer.

Depending on the require clause in the grant statement, you can use one or more of the following to connect to the SSL-enabled server:


  1. mysql -u ssluser -p

  2. mysql -u ssluser --ssl-ca=ca-cert.pem -p

  3. mysql -u ssluser --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem -p



If you use require none or omit the require clause, you can use any of the three connection commands. If you use require ssl, you can use #2 or #3. And if you use require x509, you have to use #3 (note that #3 includes the --ssl-ca option). After connecting, type status (or just \s) and make sure that the SSL item says something encryptiony (mine says Cipher in use is DHE-RSA-AES256-SHA).

Unless client certificates are really necessary (extra client-level authentication), it's probably adequate just to use require ssl and to have the client provide the CA certificate (this appears to provide as high a level of encryption as the client certificate does). But note that you still need to generate the server certificate and key, even if you're not using client certificates.

15 June 2008

MIME-decoding email attachments

Occasionally a friend will forward a message to my gmail account, and the forwarded message ends up as a plain-text attachment in the message I receive. If the original message had an attachment, that attachment appears as a MIME-encoded section of the attachment.

If this happens to you, you could try the following. Save the attachment as a text file, and open that file in a text editor. Delete all the lines except the lines which represent the encoded attachment (don't keep the attachment headers, just the lines of text which are 76 characters wide [the last line may be shorter--keep that one, too]). Don't forget to get rid of the lines after the attachment. Save the file as encoded.txt.

Save the following to an executable file called mime_decode somewhere in your $PATH:

#!/usr/bin/perl -w

use strict;
use diagnostics;

use Carp;
use MIME::Base64;

my $usage = "$0 infile outfile";
if ( @ARGV != 2 ) {
die "usage: $usage\n";
}
my ( $infile, $outfile ) = @ARGV;

open my $fh, '<', $infile or croak "cannot read $infile";
my $encoded = join '', <$fh>;
close $fh;

my $decoded = decode_base64($encoded);
open $fh, '>', $outfile or croak "cannot write $outfile";
print {$fh} $decoded;
close $fh;


Then run the following command:

mime_decode encoded.txt decoded


decoded should be the original attachment.

If you know of a standard utility which does this (especially if it doesn't require the user to prune the email message), please leave a comment.

13 June 2008

Gump

As a big Transformers fan and someone who, well, goes to the bathroom, I thought this was pretty cool.

01 June 2008

Fallen Tree

There was a ferocious wind-and-rain storm here a week ago, and it knocked over some trees. I took some pictures of one of the more impressive casualties. I think it was an elm tree, and (judging by the rings) it appears to have been around forty years old. They cut it up to cart it off, and they made a cut just above the roots. It was probably around two feet in diameter at the base.

Here are a couple of the pictures...

another ring detail

gnarled roots

Burning Universal Studios

A couple of years ago I visited L.A. with friends, and we checked out Universal Studios. We took the tour, which included the cheesy-but-fun King Kong attraction.

That part of the tour was destroyed by fire this morning. The same fire damaged the town hall clocktower from the Back to the Future set, and damaged over 40,000 reels of film (fortunately, there are duplicates in another location--someone was awake during the "Make Backups" lecture at film school).

Tourist attractions have had a hard time of it lately.