configuring sympa with postfix

Last week I took over the task of migrating sympa from a vserver machine to a xen vm. In the process I upgraded the sympa version and changed the MTA, from sendmail (ahhhhhhhhhh) to postfix. In my opinion sympa is designed to do far too many things just to be a mailing list manager. In particular, it has its own mail spool, it organizes mail delivering (via the MTA) and bounces.

Because of this design, the easiest way to configure it to work with postfix is to use it as a transport and let it do whatever … The problem with this configuration is that postfix doesn’t have any mean to know, for a give domain, which user (mailing list) is legal and which one is not. To get around this problem, one solution is to remove the local recipient check setting local_recipient_maps to empty. However this way, postfix will accept all emails, and subsequently generate a bounce if the local user doesn’t really exists. This can be used my spammers and it’s a very bad idea. The postfix manual explains this very well is bold.

To get around this problem, my simple solution then is to generate a postfix map to give back to postifx a bit more of control over this business.

Now, my local_recipient_maps looks like:

local_recipient_maps = $alias_maps, hash:/etc/postfix/sympa-recipients

and this is a small script I run every now and then to re-generate the hash table.

#!/bin/sh

for i in `ls /var/lib/sympa/expl/sympa.pps.jussieu.fr`; do 
    echo "$i unsed"; 
done > /etc/postfix/sympa-recipients
postmap /etc/postfix/sympa-recipients

/etc/init.d/postfix reload

for reference, this is the error you would get without local_recipient_maps.

sympa postfix / smtpd [12345]: NOQUEUE: reject: RCPT from xxxxxxxxxxx[xxx.xxx.xxx.xxx]: 550 5.1.1 test123@sympa.xxxx.org: Recipi ent address rejected: User unknown in local recipient table; from=me@ ex.org to=test123@sympa.xxxx.org proto=ESMTP helo=


connect mrbs with sympa

Today I wrote a small script to allow mrbs [1] to authenticate with the sympa[2] database. mrbs has a nice feature to use an external command to do authentication. This is a simple script that query the sympa db.

#! /usr/bin/perl
use lib '/usr/lib/sympa/bin';
use wwslib;

unless (require Crypt::CipherSaber) {
    die "Crypt::CipherSaber not installed ; cannot crypt passwords";
}

require 'tools.pl';

use List;

## Load sympa config
&Conf::load('/etc/sympa/sympa.conf') || die 'config_error';
chdir $Conf::Conf{'home'};

($email,$password) = ($ARGV[0],$ARGV[1]);

&List::db_connect() || die "Can't connect to database";
my $dbh = &List::db_get_handler();
my $sql = "SELECT password_user FROM user_table WHERE email_user = '$email'";
my $sth =  $dbh->prepare($sql) || die "Can't prepare SQL statement";
$sth->execute || die "Unable to execute SQL statement";

my $user = $sth->fetchrow_hashref;

$sth->finish();
&List::db_disconnect();

my $dbpass = &tools::decrypt_password($user->{'password_user'});

if ($dbpass eq $password) {
        print "auth succeeded\n";
        exit;
} else {
        print "auth failed\n";
        exit(1);
}

and this is the snippet to add in the mrbs config file. Of course is necessary to configure sudo.

# 'auth_ext' configuration settings
$auth["prog"]   = "sudo -u sympa /usr/local/bin/sympa_pass.pl";
$auth["params"] = "#USERNAME# #PASSWORD#";

Working on this small script I discovered that sympa doesn’t really encrypt passwords, but use this ciphersaber perl library to do a strange base64 encoding of the password. For me this is particularly brain-dead as it add nothing to security and make the tool less interoperable.

If you want to decrypt all sympa password in db db, you just need to use the function below:

&tools::decrypt_password($user->{'password_user'});

[1] http://mrbs.sourceforge.net/ [2] http://www.sympa.org/


trasfering data over the wire with nc

Date

nc, TCP/IP swiss army knife, is an utility to transfer data across the network (actually is much more then that…). If you need to transfer large files inside you private network it might be a good idea to use nc, instead of heavier data transfer protocols (such as nfs, samba, ssh, http…)

Server side :

nc -vvn -l -p 3000 -w 3 | pv -b > outputfile

where -l says to listen and -p 3000 specifies the port.

Client side :

nc -vvn 192.168.0.5 3000 < inputfile

This is pretty straightforward.

To make the process a bit more human friendly I’ve used pv that is a small monitor the progress to show how much data has been transfered.


how to resize a xen image (or any other fs)

Date Tags xen

This is a small recipe to resize a disk image. In this case I wanted to make it bigger.

create a sparse file :

dd if=/dev/zero of=xen.img bs=1k count=1 seek=30M

copy the old file system to the sparse file:

dd if=old-xen.img of=xen.img conv=notrunc

now we resize the fs (reiserfs in this case)

resize_reiserfs xen.img

and we can happily mount it.

mount -o loop xen.img test/

now we have a bigger fs !

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/home/xen.img      30G  338M   30G   2% /home/test

how to add a custom lexer to camlp4

Date Tags ocaml

Adding a custom parser in the old camlp4 (now camlp5) was relatively easy. The new camlp4 is quite different. The problem was discussed in two recent threads in the ocaml mailing list here and here.

The main point is to provide a new Lexer module with a compatible signature with the Camlp4 lexer.

There are 3 camlp4 modules that should be defined, namely Loc, Token and Error. The signature to redefine a camlp4 lexer is

open Camlp4.Sig

type token =
  | KWD of string
  | CHAR of char
  | EOI

exception Error of int * int * string

module Loc   : Loc with type t = int * int
module Token : Token with module Loc = Loc and type t = token
module Error : Error

val mk : unit -> (Loc.t -> char Stream.t -> (Token.t * Loc.t) Stream.t)

I still don’t understand enough about the camlp4 internal to comment about it. I’ve reused the cduce lexer as starting point and added a small lexer for regular expressions.

The complete code (lexer + parser) is Here