Skip to Content.
Sympa Menu

en - [sympa-users] Sympa login with certificates without Emailaddress

Subject: The mailing list for listmasters using Sympa

List archive

Chronological Thread  
  • From: "O. Menkens, privat" <address@concealed>
  • To: address@concealed
  • Subject: [sympa-users] Sympa login with certificates without Emailaddress
  • Date: Mon, 21 Nov 2011 16:50:41 +0100

Hi,

at our company (Fraunhofer) we use smartcards for authentication, that do not have the email address of the owner in its SSL_CLIENT_CERT. Instead, it contains just the DN of the user. Thus this DN has to be looked up via our corporate LDAP directory, to get the user email, that belongs to it.
When I activate the client certificates in the apache configuration, the sympa server fails to authenticate. As long as the client certificates are enabled (and a smartcard is present), it is even impossible to login manually.

After some experimentation and code analysis, I have created a patch for wwsympa.fcgi, that allows to use our smartcards for authentication.

I've attached the patch for sympa 6.1.7 (basically a new function "get_email_from_ldap" with lots of code copied from "is_ldap_user"). Perhaps a sympa developer can review it and put it into the code repository (?)

Olaf Menkens.

P.S.: When reviewing the LDAP related code, I stumbled across "create_db" in LDAPSource.pm. As far as I understand the code, this function does not make sense in LDAP context, so perhaps you might want to delete it ?
--- wwsympa.fcgi.orig 2011-11-03 18:56:07.000000000 +0100
+++ wwsympa.fcgi 2011-11-21 16:45:26.000000000 +0100
@@ -1164,6 +1164,13 @@
## mod_ssl -- address@concealed
$param->{'user'}{'email'} =
lc(Crypt::OpenSSL::X509->new_from_string($ENV{SSL_CLIENT_CERT})->email());
}
+ # Still no email found? Try to get email address from LDAP
using DN:
+ # (code added by Olaf Menkens, November 2011)
+ if ((! $param->{'user'}{'email'}) and
+ exists($ENV{'SSL_CLIENT_S_DN'}) and
+ my $email =
&get_email_from_ldap($ENV{'SSL_CLIENT_S_DN'})) {
+ $param->{'user'}{'email'} = lc($email);
+ }

if($param->{user}{email}) {
$session->{'email'}= $param->{user}{email} ;
@@ -3424,7 +3431,7 @@
return;
}
}
-
+
sub is_ldap_user {
my $auth = shift; ## User email or UID
&wwslog('debug2',"is_ldap_user ($auth)");
@@ -3462,7 +3469,7 @@
my $ds = new Datasource('LDAP', $param);

unless (defined $ds && ($ldap_anonymous = $ds->connect())) {
- &do_log('err',"Unable to connect to the LDAP server '%s'",
$ldap->{'ldap_host'});
+ &do_log('err',"Unable to connect to the LDAP server '%s'",
$ldap->{'host'});
next;
}

@@ -3497,6 +3504,93 @@
}
}

+ ## get the email address from LDAP, given the DN (from the SSL_CLIENT_CERT).
+ ## function added by Olaf Menkens, Fraunhofer IAIS
+ sub get_email_from_ldap {
+ my $dn = shift; ## DN to check
+ &wwslog('debug2',"called for '%s'", $dn);
+
+ unless (&tools::get_filename('etc',{}, 'auth.conf', $robot)) {
+ return undef;
+ }
+
+ ## List all LDAP servers first
+ my @ldap_servers;
+ foreach my $ldap (@{$Conf{'auth_services'}{$robot}}){
+ next unless ($ldap->{'auth_type'} eq 'ldap');
+ push @ldap_servers, $ldap;
+ }
+
+ return undef unless ($#ldap_servers >= 0);
+
+ unless (eval "require Net::LDAP") {
+ &wwslog ('err',"Unable to use LDAP library, Net::LDAP
required,install perl-ldap (CPAN) first");
+ return undef;
+ }
+ require Net::LDAP;
+
+ my ($ldap_anonymous,$filter);
+
+ LDAPSERVER: foreach my $ldap (@ldap_servers){
+
+ # skip ldap auth service if the dn does not match regexp auth
service parameter
+ next unless ($dn =~ /$ldap->{'regexp'}/i);
+
+ # check whether dn is below suffix:
+ my @dnparts = split /\//, lc($dn);
+ shift @dnparts; # SSL_CLIENT_S_DN starts with /
+ my @sufparts = reverse(split /,\s*/, lc($ldap->{'suffix'}));
+ while (my $sufp = shift(@sufparts)) {
+ my $dnp = shift(@dnparts);
+ if ($sufp ne $dnp) {
+ &wwslog('err',"CERT DN '%s' not below LDAP
suffix '%s'", $dn, $ldap->{'suffix'});
+ next LDAPSERVER;
+ }
+ }
+ $filter = pop(@dnparts);
+ # $filter should be "CN=<Name>"
+
+ my $param = &tools::dup_var($ldap);
+ my $ds = new Datasource('LDAP', $param);
+
+ unless (defined $ds && ($ldap_anonymous = $ds->connect())) {
+ &do_log('err',"Unable to connect to the LDAP server
'%s'", $ldap->{'host'});
+ next;
+ }
+
+ my $mesg = $ldap_anonymous->search(base => $ldap->{'suffix'} ,
+ filter => "$filter",
+ scope => $ldap->{'scope'},
+ attrs =>
$ldap->{'email_attribute'},
+ timeout => $ldap->{'timeout'}
);
+
+ if ($mesg->count() == 0) {
+ &wwslog('notice','No entry in the Ldap Directory Tree
of %s for %s',$ldap->{'host'},$filter);
+ $ds->disconnect();
+ next LDAPSERVER;
+ }
+ elsif ($mesg->count() > 1) {
+ &wwslog('notice','Multiple entries in the Ldap
Directory Tree of %s for %s',$ldap->{'host'},$filter);
+ $ds->disconnect();
+ last LDAPSERVER;
+ }
+
+ my $entry = $mesg->pop_entry();
+ my $email = $entry->get_value ( $ldap->{'email_attribute'} );
+
+ unless (&tools::valid_email($email)){
+ &wwslog('error','User %s has invalid email "%s"',
$filter, $email);
+ $ds->disconnect();
+ return undef;
+ }
+ &wwslog('debug2',"Found email address '%s' for '%s' on
'%s'.",$email, $filter, $param->{'ldap_host'});
+ $ds->disconnect();
+ return $email;
+ }
+ &wwslog('error',"Could not find email for '%s'", $dn);
+ return undef;
+ }
+
## send back login form
sub do_loginrequest {
&wwslog('info','do_loginrequest');


  • [sympa-users] Sympa login with certificates without Emailaddress, O. Menkens, privat, 11/21/2011

Archive powered by MHonArc 2.6.19+.

Top of Page