I don't know if this would be of any use to anyone else - probably not but you never know... perhaps it will at least serve as inspiration for how to access LDAP...

I threw together an external authentication script for pure-ftpd that shares Zimbra's user accounts for the purpose of hosting virtual domains and thought I'd share.

Anyway, here's some free code if anybody cares... Merry Christmas


Code:
#!/usr/bin/perl
# Filename: ftp-auth-handler
#
# PureFTPD Custom Authentication via Zimbra LDAP for Virtual Web Hosting
################################################################################
# 					<edward.nigma@gmail.com>	12.08.05
#
# Add the following to your /etc/pure-ftpd.conf:
#	ExtAuth                       /var/run/ftpd.sock
#
# Usage:
#	pure-authd -s /var/run/ftpd.sock -r /usr/local/src/ftp-auth-handler &
#
# ACL Config File:
#	List user e-mail addresses one line at a time that are permitted to 
#	access the webspace of the domain they below to in the config file 
#	specified below. Custom home directories may be specified with a colon
#	if you'd like to override the defaults...
#
#	Example:
#		billy@bob.com		<-- will be sent to /home/virtualdomains/bob.com
#		john@john.com		<-- will be sent to /home/virtualdomains/john.com
#		sam@john.com:/home/sam	<-- will be sent to /home/sam
#
#	(If leo@bob.com attempts a login, it will fail even with a
#	 correct password because they are not included in the list)
#

use strict;
use Net::LDAP;

# Configuration Below
my $ldaphost = "127.0.0.1";	# zimbra server ip for ldap
my $virtualuser = "virtualdomains";	# real user for virtual accounts
my $uid = "1000";	# uid of real user for virtual accounts
my $gid = "1000";	# gid of real user for virtual accounts
my $configfile = "/usr/local/src/ftp-auth-handler.conf";	# acl config file location

# Declare our other values
my $auth = 0; my $priv = 0; my $customdir;
my $email = $ENV{'AUTHD_ACCOUNT'};
my $password = $ENV{'AUTHD_PASSWORD'};
my $domain = (split(/\@/, $email))[1];	
my $username = (split(/\@/, $email))[0];
my @dc = split(/\./, $domain);
my $dclist = join(',dc=', @dc);

# Check ACL list
open(CONFIG, $configfile);
while(<CONFIG>) {
	my $confline = $_;
	$confline =~ s/\n//g;
	my $confuser = (split(/:/, $confline))[0];
	my $confdir = (split(/:/, $confline))[1];	
	if ($confuser eq $email) { $priv = 1; if ($confdir) { $customdir = $confdir; } }
}
close(CONFIG);

# Attempt to bind with FTP login if ACL permits
if ($priv) {
	my $ldap = Net::LDAP->new($ldaphost) or die($@);
	my $mesg = $ldap->bind("uid=$username,ou=people,dc=$dclist", password => $password);
	$ldap->unbind;
	if ($mesg->code) {
		$auth = 0;
	} else {
		$auth = 1;
	}
}

# If sucessful tell PureFTPD to permit entry
if (($auth) && ($priv)) {
	print "auth_ok:1\n";
	print "uid:$uid\n";
	print "gid:$gid\n";
	if ($customdir) {
		print "dir:$customdir\n"; 
	} else { 
		print "dir:/home/$virtualuser/$domain\n";
	}
} else {
	print "auth_ok:0\n";
}
print "end\n";