Sun, 19 Feb 2006

Postman/C-client Certificate Problem

When I upgraded my mail server from Woody to Sarge, Postman, my webmail client, stopped working. When trying to log in, I got the following error:

Error: Certificate failure for mail.xerus.org: self signed certificate: /C=US/ST=California/L=Los Angeles/O=Xerus/CN=mail.xerus.org

It turns out that the newer version of C-client, the library that postman uses for IMAP, automatically tries to verify the certificate, even if you have postman configured to connect to the non-SSL port; I guess it calls STARTTLS. Since I'm only using a self-signed certificate, I get the error above.

The solution is to configure postman to not verify the certificate using the novalidate-cert switch in /etc/postman/interdaemon.cfg.

[mail.xerus.org]
imapserver     = mail.xerus.org/novalidate-cert
imapport       = 143
smtpserver     = localhost
;for SMTP authentication. 0=No,1=Must,2=Try
authsmtp       = 0
maildomain     = xerus.org
mailboxprefix  =
remotepath     = ~/mail/
deniedservices =

tech » mail | Permanent Link

Sun, 20 Nov 2005

PayFlow Pro PHP Extension on Debian

This is how I built a php4-pfpro package for Debian. Tested with 4.3.10-2.
# apt-get build-dep php4
# apt-get source php4
Follow this part of the instructions from the PHP Documentation

You will require the appropriate SDK for your platform, which may be downloaded from within the manager interface once you have registered. Once you have downloaded the SDK you should copy the files from the lib directory of the distribution. Copy the header file pfpro.h to /usr/local/include and the library file libpfpro.so to /usr/local/lib.

Edit debian/control. Add the following:

Package: php4-pfpro
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, ${php:Depends}, php4-common (= ${Source-Version})
Description: Verisign's Payflow Pro module for php4
 This package provides a module for Verisign's Payflow Pro for PHP scripts.
 .
 PHP4 is an HTML-embedded scripting language. Much of its syntax is borrowed
 from C, Java and Perl with a couple of unique PHP-specific features thrown
 in. The goal of the language is to allow web developers to write
 dynamically generated pages quickly.

Add the following line to debian/modulelist:
pfpro PayFlowPro
Add the following line to the CFLAGS in the configure-apache-stamp rule in debian/rules:
--with-pfpro=shared,/usr/local \
If you're building apache2 modules, add it to the configure-apache2-stamp rule too, but I haven't tested that. I also had problems building the caudium packages so I removed all of the caudium related stuff from debian/rules.
Here's the full patch.
# ./debian/rules binary

Update 11/06/06: I've updated the Sarge package to 4.3.10-18.
Update 05/05/07: I've updated the Sarge package to 4.3.10-20.

tech | Permanent Link

Using udev and autofs Under Debian with an iPod and Camera

Last week, I set up udev on my desktop machine. udev is the Linux 2.6 way of dynamically managing the /dev directory. It populates /dev only with devices that actually exist, and adds and removes entries as devices are plugged in or removed from the system. In addition, it allows the entries in /dev to be named consistently.

Consistent naming of /dev entries solves a big problem with using USB devices under Linux. Many USB devices use the usb-storage module, appearing as SCSI devices. The problem is that the name the kernel gives to the devices depends on the order in which they are plugged into the system.

For example, I might plug my iPod Shuffle into my computer, and the kernel would name it /dev/sdd. Then I plug in my camera, and the kernel would call it sde. But if I had plugged them in in the opposite order, their names would have been reversed. This makes it difficult to mount them without first checking dmesg to find out what the device has been named.

udev solves this problem by allowing me to tell it what to name a device when it is detected. udev uses information from sysfs to determine which device is plugged in. I have configured udev to name a device whose vendor attribute is "Apple" /dev/ipod and a device whose vendor is "Pentax" /dev/camera. The Debian udev packages put the udev rules in /etc/udev/rules.d. So I created /etc/udev/rules.d/50-custom.rules which contains:
BUS=="scsi", SYSFS{vendor}=="Pentax", NAME{all_partitions}="camera", GROUP="plugdev"
BUS=="scsi", SYSFS{vendor}=="Apple", NAME{all_partitions}="ipod", GROUP="plugdev"

The NAME{all_partitions} part tells udev to create device entries for all of the block device's partitions, so it will create /dev/ipod[1-15] and /dev/camera[1-15], allowing me to mount the FAT partitions on each. See Daniel Drake's guide to writing udev rules for more information on configuring udev.

Now that my iPod and camera are consistently named, I'd like to be able to access them from within gtkpod and digikam, the applications I use to manage the files on them, respectively, without having to manually mount them. While gtkpod has an option to mount the iPod, digikam does not. I have my camera set up in digikam as a generic USB mass storage device, for which you just need to configure a directory to browse.

Following the debian-administration.org tutorial, I set up autofs to automatically mount the usb devices when they are accessed, and unmount them when they're no longer being used. So after installing the autofs package, I added the following line to /etc/auto.master:
/var/autofs/removable /etc/auto.removable --timeout=2

And in /etc/auto.removable, I put:
ipod -fstype=vfat,rw,gid=46,umask=002 :/dev/ipod1
camera -fstype=vfat,rw,gid=46,umask=002 :/dev/camera1


Then I made /media/ipod a symlink to /var/autofs/removable/ipod and /media/camera a symlink to /var/autofs/removable/camera. When I access /media/camera, automount automatically mounts /dev/camera1 as /var/autofs/removable/camera if it has been created by udev. After it hasn't been accessed for two seconds, it will be unmounted (which might take a little while if there are buffers which haven't been flushed out to the drive).

Update (8/12/06): I fixed the rules to use the proper equality test, == rather than =, which newer versions of udev require. Thanks to Andrew Schulman for pointing this out.

tech | Permanent Link

Thu, 17 Nov 2005

Make Pretty Charts with PHP/SWF Charts

PHP/SWF Charts is a PHP script and flash file that can build great looking charts. The flash part does all the work. The PHP script just generates the HTML tags to embed the flash file. It can generate a number of different types of charts including line, column, and pie charts.

We're using it at Postica to generate charts for our customers showing statistics on the number of spam and malware blocked, for example.

tech | Permanent Link

What The Hell Is Wrong With Google Analytics?

Google Analytics, their new hosted web stats application based on Urchin, seems to be completely broken. Every time I log in, I get the following message.

Analytics has been successfully installed and data is being gathered now. Your first reports will be ready within twelve hours.

The problem is that I added the Google javascript to my site three days ago. I want my pretty graphs, damn it.

tech | Permanent Link

Thu, 27 Oct 2005

Using a Verisign SSL Certificate with mod-ssl

I received a Verisign-signed SSL certificate today. When trying to install it under Apache/mod-ssl, I got the following errors:
[Thu Oct 27 12:18:26 2005] [error] mod_ssl: Init: Unable to read server certificate from file /www/.../www.example.com.crt (OpenSSL library error follows)
[Thu Oct 27 12:18:26 2005] [error] OpenSSL: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
[Thu Oct 27 12:18:26 2005] [error] OpenSSL: error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error

I got a similar error when trying to inspect the certificate using openssl directly:
$ openssl x509 -in www.example.com.crt -noout -text
unable to load certificate
32741:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:946:
32741:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:304:Type=X509_CINF
32741:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_D2I:nested asn1 error:tasn_dec.c:566:Field=cert_info, Type=X509
32741:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:82:

Thanks to Dr. Henson on the OpenSSL mailing list, I discovered the the certificate was packed in the PKCS#7 format. So, after converting the certificate using the following command, openssl was able to read the certificate:
openssl pkcs7 -in www.example.com.crt -print_certs -out www.example.com.crt.new

tech | Permanent Link

Sat, 08 Oct 2005

Oracle Buys Innobase

Oracle announced yesterday that they've purchased Innobase. There aren't too many details yet.

Innobase is the Finnish company which developed the InnoDB engine for MySQL. InnoDB brought MySQL many of the features necessary for deployment in non-trivial installations, including support for transactions, row-level locking, and foreign key constraints. These are some of the features that would allow MySQL to be used in place of a commercial database such as Oracle. With the imminent release of MySQL 5.0, which includes support for stored procedures, triggers, and views, even more applications could be built on MySQL.

One of the main features in which Oracle beats out MySQL is in clustering. MySQL's clustering, the NDB engine is stil rather immature, and from what I understand, not having ever used Oracle, it has some nifty clustering. I'm sure that it has some other cool features that I've heard of. So, are we likely to see some Oracle technology make it's way into MySQL? Or more pressure to purchase licenses where they aren't needed?

tech | Permanent Link

Thu, 06 Oct 2005

Blackberry 7290

I bought a BlackBerry 7290 a couple weeks ago. I mainly wanted it so I could keep tabs on my email, and ssh into servers when I'm away from my desk. Being a BlackBerry, it handles email pretty well, of course. After logging into T-Mobile's web site, it only took a minute or two to add my IMAP account. I just had to enter my email address and password, and it figured out the username, server, and that it should connect to the IMAPS port.

The BlackBerry service frequently logs into my IMAP server and delivers new messages to the handheld (RIM lingo for their phone/PDA devices). Deleting a message on the handheld can optionally delete it on the IMAP server. So far, I've had one incident in which the BlackBerry pulled in a few old messages as new. I'm not sure how it decided to pull in these three or four messages from my inbox of 8900 messages (yeah, I'm do for a cleaning). The BlackBerry mail software is not a full-fledged IMAP client. It's not possible to retrieve mail from folders other than the INBOX, nor even get to old messages already in the INBOX. I may look for a better third-party IMAP client.

Getting an SSH client to work on the BlackBerry was much more frustrating. It supports MIDP, which allows small Java applications to be installed. So immediately after getting the device, I installed midpssh, an open source SSH client. It was unable to connect to any ssh servers, though. Digging through the BlackBerry forums, I tried changing my APN settings, using different gateways and experimenting with entering my username and password vs leaving it blank. Nothing worked. I spent about five hours over the course of four days on the phone with T-Mobile support. I tried using Idokorro SSH, a commercial SSH client, with the same results. I was pretty sure that either something was wrong with my handheld or that my account hadn't been provisioned properly.

T-Mobile won't provide support for third-party applications, even ones provided on their co-branded Handango site, but the third or fourth BlackBerry support guy I talked to suggested that I could set up my BlackBerry as a modem to verify that it is working properly, and that they would be able to help troubleshoot if it wasn't.

So I set up the device as a modem in Windows within VMWare since there's absolutely no support for BlackBerrys under Linux, and I had the same problems. I was able to authenticate and bring up a PPP connection, but any type of network connections other than DNS queries failed. After another hour or so on the phone with T-Mobile, I was told someone would call me back on the next business day. Waiting for the call back, I tried once again to use the device as a modem, and what do you know, it worked. I started up midpssh, and it worked too. I'm sure my account just hadn't been set up properly despite having asked T-Mobile repeatedly to verify that it had been.

It's definitely not speedy to work in an interactive session over GPRS, but it'll do in a pinch.

The BlackBerry comes with a well-featured web browser. It's a full HTML browser which supports JavaScript and CSS. It even supports flash and svg, though I have those disabled.

Another great third-party application is Google's Local for mobile, which provides access to Google Maps (aka Google Local) from a custom J2ME application. I went to visit a friend in Santa Barbara last weekend and I didn't have to print out a Google Map like I usually do. You just step through each turn on the handheld. I used to use Google SMS from my old phone to find a nearby book store or the phone number of a restaurant, but this is much more useful.

I was actually planning on getting the 7105t, which has a normal phone form factor, but having tried to type on the 7105t's 20-key keypad, I'm glad I went for the full keyboard.

tech | Permanent Link

Data URL's

You learn something new every day. Jeremy's linkblog include a link to a data: URL image encoder. I'd never even heard of the data scheme.

The data: scheme allows data to be embedded within an HTML page (or other document that supports URLs). For example, take a look at the source of this image:



Neat, huh?

It's not very efficient since the embedded data can't be cached separately from the page, but it's still kind of cool.

tech | Permanent Link

Sun, 11 Sep 2005

Monitoring MySQL Replication Slaves

Drawing inspiration from the replication chapter of Jeremy and Derek's MySQL book, I recently set up monitoring to measure how far a MySQL slave is behind the master.

I created a simple table to store a timestamp.

CREATE TABLE `heartbeat` (
  `timestamp` datetime NOT NULL default '0000-00-00 00:00:00'
);
INSERT INTO heartbeat SET timestamp = NOW();
Master

The master updates the timestamp every second using a simple PHP script called write_mysql_heartbeat.php.

<?php

$dbHost = 'dbhost';
$dbUser = 'mysql_admin';
$dbPass = 'PASSWORD';
$dbName = 'mysql_admin';

$conn = mysql_connect($dbHost, $dbUser, $dbPass) or die('Failed to connect to database');
mysql_select_db($dbName) or die('Failed to select database: ' . $dbName);

define_syslog_variables();
openlog('mysql_heartbeat', LOG_PERROR | LOG_PID, LOG_DAEMON);

$sql = 'UPDATE heartbeat SET timestamp = now()';
while (true) {
        while (mysql_ping($conn) === false) {
                syslog(LOG_WARNING, 'Lost connection to database.  Will retry in 30 seconds.');
                sleep(30);
        }
        if (! mysql_query($sql, $conn)) {
                syslog(LOG_ERR, 'Failed to insert record: ' . mysql_error());
                die();
        }
        sleep(1);
}

I have restartd make sure that write_mysql_heartbeat.php keeps running with the following entry in /etc/restartd.conf:
write_mysql_heartbeat write_mysql_heartbeat "php4 -q /usr/local/bin/write_mysql_heartbeat.php"

Slave

On the slave side, I wrote a simple munin plugin to check how far the slave is behind the master. Munin is also configured to send alerts through nagios if the slave gets too far behind.

Here's /etc/munin/plugins/mysql_slave_delay:

#!/usr/bin/php4
<?php

$dbHost = 'slave-1';
$dbUser = 'mysql_admin';
$dbPass = 'PASSWORD';
$dbName = 'mysql_admin';

if ($argv[1] == 'config') {
        # The host name this plugin is for. (Can be overridden to have
        # one machine answer for several)

        # The title of the graph
        echo "graph_title MySQL Slave Delay\n";
        # Arguments to "rrdtool graph". In this case, tell it that the
        # lower limit of the graph is '0', and that 1k=1000 (not 1024)
        echo "graph_args --base 1000 -l 0\n";
        # The Y-axis label
        echo "graph_vlabel seconds\n";
        # We want Cur/Min/Avg/Max unscaled (i.e. 0.42 seconds instead of
        # 420 milliseconds)
        echo "graph_scale no\n";
        # Graph category. Defaults to 'other'
        echo "graph_category mysql\n";
        # The fields. "label" is used in the legend. "label" is the only
        # required subfield.
        echo "seconds.label seconds\n";
        # These two are optional. They are only used if you have
        # configured your munin to tell a Nagios-server about any
        # problems
        echo "seconds.warning 30\n";
        echo "seconds.critical 120\n";
        # This one is purely to add an explanation to the web page. The first
        # one is for the graph itself, while the second one is for the field
        # "seconds".
        echo "graph_info This graph shows how many seconds this MySQL slave is behind the master\n";
        echo "seconds.info Number of seconds behind master\n";

        # Last, if run with the "config"-parameter, quit here (don't
        # display any data)
        exit;
}

$conn = mysql_connect($dbHost, $dbUser, $dbPass) or die('Failed to connect to database');
mysql_select_db($dbName) or die('Failed to select database: ' . $dbName);

define_syslog_variables();
openlog('mysql_heartbeat', LOG_PERROR | LOG_PID, LOG_DAEMON);

$sql = 'SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(timestamp) from heartbeat';
if (false === ($result = mysql_query($sql, $conn))) {
        syslog(LOG_ERR, 'Failed to get record: ' . mysql_error());
        die();
}

if (mysql_num_rows($result) != 1) {
        syslog(LOG_ERR, 'Failed to find record for heartbeat: ' . $hostname);
        die();
}
list($delay) = mysql_fetch_array($result);

echo "seconds.value $delay\n";
Output



The slave is falling behind while backups are running. I still need to do something about that.

tech | Permanent Link

Newer Posts | Older Posts

The state is that great fiction by which everyone tries to live at the expense of everyone else. - Frederic Bastiat