Skip to content

Commit

Permalink
Merge pull request #497 from ikedas/issue-487-trial2 by ikedas
Browse files Browse the repository at this point in the history
WWSympa: Deprecate sympa_altemails cookie #487
  • Loading branch information
ikedas authored Dec 22, 2018
2 parents 4a844b4 + b37b32a commit cd4b0ec
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 188 deletions.
15 changes: 6 additions & 9 deletions doc/auth.conf.pod
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,12 @@ example, the canonic email is C<mail>.

=item C<alternative_email_attribute>

The name of the attribute for the alternate email in your directory: for
instance C<alternate_email>, C<mailalternateaddress>, ... You make a list of
these attributes separated by commas (C<,>).

With this list, Sympa creates a cookie which contains various information:
Whether the user is authenticated via LDAP or not, their alternate email.
Storing the alternate email is interesting when you want to canonify your
preferences and subscriptions, that is to say you want to use a unique
address in C<user_table> and C<subscriber_table>, which is the canonic email.
I<Obsoleted>.

On Sympa 6.2.38 or earlier, web interface provided a cookie named
C<sympa_altemails> which contained attribute values specified by this
parameter along with authenticated email address.
This feature was deprecated.

=item C<scope>

Expand Down
13 changes: 0 additions & 13 deletions src/cgi/wwsympa.fcgi.in
Original file line number Diff line number Diff line change
Expand Up @@ -1682,8 +1682,6 @@ while ($query = CGI::Fast->new) {

$session->set_cookie($cookie_domain, $param->{'user'}{'cookie_delay'},
$param->{'use_ssl'});
# Set/delete cookie for alt_emails.
$session->set_cookie_extern($cookie_domain, $param->{'use_ssl'});

if ($param->{'user'}{'email'}) {
$session->{'auth'} ||= 'classic';
Expand Down Expand Up @@ -3251,14 +3249,6 @@ sub do_login {
}
);

# Save alt_emails in session store.
my $alt_emails = $data->{'alt_emails'};
$session->{'alt_emails'} = join ',',
map { sprintf '%s:%s', $_, $alt_emails->{$_} }
sort keys %{$alt_emails || {}};
wwslog('info', 'alternative emails = %s', $session->{'alt_emails'})
if $session->{'alt_emails'};

if ($session->{'lang'}) {
# user did choose a specific language before being logged. Apply it
# as a user pref.
Expand Down Expand Up @@ -3907,8 +3897,6 @@ sub is_ldap_user {
next;
}

my @alternative_conf =
split(/,/, $ldap->{'alternative_email_attribute'});
my $attrs = $ldap->{'email_attribute'};

if (Sympa::Tools::Text::valid_email($auth)) {
Expand Down Expand Up @@ -3993,7 +3981,6 @@ sub do_logout {

delete $param->{'user'};
$session->{'email'} = 'nobody';
delete $session->{'alt_emails'};

if ( $session->{'cas_server'}
and $Conf::Conf{'auth_services'}{$robot}[$session->{'cas_server'}]) {
Expand Down
20 changes: 9 additions & 11 deletions src/lib/Conf.pm
Original file line number Diff line number Diff line change
Expand Up @@ -933,17 +933,15 @@ sub _load_auth {
'suffix' => '.+',
'bind_dn' => '.+',
'bind_password' => '.+',
'get_dn_by_uid_filter' => '.+',
'get_dn_by_email_filter' => '.+',
'email_attribute' => Sympa::Regexps::ldap_attrdesc(),
'alternative_email_attribute' => Sympa::Regexps::ldap_attrdesc()
. '(\s*,\s*'
. Sympa::Regexps::ldap_attrdesc() . ')*',
'scope' => 'base|one|sub',
'authentication_info_url' => 'http(s)?:/.*',
'use_tls' => 'starttls|ldaps|none',
'use_ssl' => '1', # Obsoleted
'use_start_tls' => '1', # Obsoleted
'get_dn_by_uid_filter' => '.+',
'get_dn_by_email_filter' => '.+',
'email_attribute' => Sympa::Regexps::ldap_attrdesc(),
'alternative_email_attribute' => '.*', # Obsoleted
'scope' => 'base|one|sub',
'authentication_info_url' => 'http(s)?:/.*',
'use_tls' => 'starttls|ldaps|none',
'use_ssl' => '1', # Obsoleted
'use_start_tls' => '1', # Obsoleted
'ssl_version' => 'sslv2/3|sslv2|sslv3|tlsv1|tlsv1_[123]',
'ssl_ciphers' => '[\w:]+',
'ssl_cert' => '.+',
Expand Down
181 changes: 60 additions & 121 deletions src/lib/Sympa/WWW/Auth.pm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ package Sympa::WWW::Auth;
use strict;
use warnings;
use Digest::MD5;
BEGIN { eval 'use Net::LDAP::Util'; }

use Sympa;
use Conf;
Expand Down Expand Up @@ -73,9 +74,8 @@ sub check_auth {
$user = {'email' => $canonic};
}
return {
'user' => $user,
'auth' => 'ldap',
'alt_emails' => {$canonic => 'ldap'}
'user' => $user,
'auth' => 'ldap',
};

} else {
Expand Down Expand Up @@ -160,9 +160,8 @@ sub authentication {
Sympa::User::update_global_user($email,
{wrong_login_count => 0});
return {
'user' => $user,
'auth' => 'classic',
'alt_emails' => {$email => 'classic'}
'user' => $user,
'auth' => 'classic',
};
}
} elsif ($auth_service->{'auth_type'} eq 'ldap') {
Expand All @@ -176,9 +175,8 @@ sub authentication {
Sympa::User::update_global_user($canonic,
{wrong_login_count => 0});
return {
'user' => $user,
'auth' => 'ldap',
'alt_emails' => {$email => 'ldap'}
'user' => $user,
'auth' => 'ldap',
};
}
}
Expand All @@ -192,151 +190,95 @@ sub authentication {
unless $ENV{'SYMPA_SOAP'};
$log->syslog('err', 'Incorrect password for user %s', $email);

my $param; #FIXME FIXME: not used.
$param->{'init_email'} = $email;
return undef;
}

sub ldap_authentication {
my ($robot, $ldap, $auth, $pwd, $whichfilter) = @_;
my $mesg;
$log->syslog('debug2', '(%s, %s, %s)', $auth, '****', $whichfilter);
$log->syslog('debug3', 'Password used: %s', $pwd);

unless (Sympa::search_fullpath($robot, 'auth.conf')) {
return undef;
}

## No LDAP entry is defined in auth.conf
if ($#{$Conf::Conf{'auth_services'}{$robot}} < 0) {
$log->syslog('notice', 'Skipping empty auth.conf');
$log->syslog('debug2', '(%s, %s, %s, *, %s)', @_[0 .. 2, 4]);
my $robot = shift;
my $ldap = shift;
my $auth = shift;
my $pwd = shift;
my $whichfilter = shift;

die 'bug in logic. Ask developer' unless $ldap->{auth_type} eq 'ldap';
unless ($Net::LDAP::Util::VERSION) {
$log->syslog('err', 'Net::LDAP::Util required. Install it');
return undef;
}

# only ldap service are to be applied here
return undef unless ($ldap->{'auth_type'} eq 'ldap');
# Skip ldap auth mechanism if an email address was provided and it does
# not match the corresponding regexp.
return undef
if $auth =~ /\@/
and defined $ldap->{regexp}
and $auth !~ /$ldap->{regexp}/i;

# skip ldap auth service if the an email address was provided
# and this email address does not match the corresponding regexp
return undef if ($auth =~ /@/ && $auth !~ /$ldap->{'regexp'}/i);
my $entry;

my @alt_attrs =
split /\s*,\s*/, ($ldap->{'alternative_email_attribute'} || '');
my $attr = $ldap->{'email_attribute'};
my $filter;
if ($whichfilter eq 'uid_filter') {
$filter = $ldap->{'get_dn_by_uid_filter'};
} elsif ($whichfilter eq 'email_filter') {
$filter = $ldap->{'get_dn_by_email_filter'};
}
$filter =~ s/\[sender\]/$auth/ig;
my $escaped_auth = Net::LDAP::Util::escape_filter_value($auth);
$filter =~ s/\[sender\]/$escaped_auth/ig;

## bind in order to have the user's DN
# Get the user's entry.
my $db = Sympa::Database->new('LDAP', %$ldap);

unless ($db and $db->connect()) {
$log->syslog('err', 'Unable to connect to the LDAP server "%s"',
$ldap->{'host'});
unless ($db and $db->connect) {
$log->syslog('err', 'Unable to connect to the LDAP Server "%s": %s',
$ldap->{host}, ($db and $db->error));
return undef;
}

$mesg = $db->do_operation(
my $mesg = $db->do_operation(
'search',
base => $ldap->{'suffix'},
filter => "$filter",
filter => $filter,
scope => $ldap->{'scope'},
timeout => $ldap->{'timeout'}
);

unless ($mesg and $mesg->count()) {
$log->syslog('notice',
'No entry in the LDAP Directory Tree of %s for %s',
$ldap->{'host'}, $auth);
$db->disconnect();
unless ($mesg and $entry = $mesg->shift_entry) {
$log->syslog(
'notice', 'Authentication for "%s" failed: %s',
$auth, $mesg ? 'No entry' : $db->error
);
$db->disconnect;
return undef;
}
$db->disconnect;

my $refhash = $mesg->as_struct();
my (@DN) = keys(%$refhash);
$db->disconnect();

## bind with the DN and the pwd

# Then set the bind_dn and password according to the current user
# Bind again with user's DN and the password.
$db = Sympa::Database->new(
'LDAP',
%$ldap,
bind_dn => $DN[0],
bind_dn => $entry->dn,
bind_password => $pwd,
);

unless ($db and $db->connect()) {
$log->syslog('err', 'Unable to connect to the LDAP server "%s"',
$ldap->{'host'});
return undef;
}

$mesg = $db->do_operation(
'search',
base => $ldap->{'suffix'},
filter => "$filter",
scope => $ldap->{'scope'},
timeout => $ldap->{'timeout'}
);

unless ($mesg and $mesg->count()) {
$log->syslog('notice', "No entry in the LDAP Directory Tree of %s",
$ldap->{'host'});
$db->disconnect();
unless ($db and $db->connect) {
$log->syslog('notice', 'Authentication for "%s" failed: %s',
$auth, ($db and $db->error));
return undef;
}

## To get the value of the canonic email and the alternative email
my (@emails, @alt_emails);

#FIXME FIXME: After all, $param->{'alt_emails'} is never used!
my $param = Sympa::Tools::Data::dup_var($ldap);
## Keep previous alt emails not from LDAP source
my $previous = {};
foreach my $alt (keys %{$param->{'alt_emails'}}) {
$previous->{$alt} = $param->{'alt_emails'}{$alt}
if ($param->{'alt_emails'}{$alt} ne 'ldap');
}
$param->{'alt_emails'} = {};

my $entry = $mesg->entry(0);

my $values = $entry->get_value($attr, alloptions => 1);
@emails =
map { lc $_ }
grep {$_} map { @{$values->{$_}} } sort keys %{$values || {}};

@alt_emails = map {
my $values = $entry->get_value($_, alloptions => 1);
map { lc $_ }
grep {$_} map { @{$values->{$_}} } sort keys %{$values || {}};
} @alt_attrs;

foreach my $email (@emails, @alt_emails) {
$param->{'alt_emails'}{$email} = 'ldap';
$db->disconnect;

# If the identifier provided was a valid email, return the provided email.
# Otherwise, return the canonical email guessed after the login.
my $do_canonicalize =
Conf::get_robot_conf($robot, 'ldap_force_canonical_email')
|| !Sympa::Tools::Text::valid_email($auth);
if ($do_canonicalize and $ldap->{email_attribute}) {
my $values =
$entry->get_value($ldap->{email_attribute}, alloptions => 1);
($auth) =
grep { Sympa::Tools::Text::valid_email($_) }
map { @{$values->{$_}} } sort keys %{$values || {}};
}

## Restore previous emails
foreach my $alt (keys %{$previous}) {
$param->{'alt_emails'}{$alt} = $previous->{$alt};
}

$db->disconnect() or $log->syslog('notice', 'Unable to unbind');
$log->syslog('debug3', 'Canonic: %s', $emails[0]);
## If the identifier provided was a valid email, return the provided
## email.
## Otherwise, return the canonical email guessed after the login.
if (Sympa::Tools::Text::valid_email($auth)
and not Conf::get_robot_conf($robot, 'ldap_force_canonical_email')) {
return $auth;
} else {
return $emails[0];
}
$log->syslog('debug3', 'Canonic: %s', $auth);
return undef unless Sympa::Tools::Text::valid_email($auth);
return $auth;
}

# fetch user email using their cas net_id and the paragrapah number in auth.conf
Expand Down Expand Up @@ -376,9 +318,6 @@ sub get_email_by_net_id {
my $filter = $ldap->{'get_email_by_uid_filter'};
$filter =~ s/\[([\w-]+)\]/$attributes->{$1}/ig;

# my @alt_attrs =
# split /\s*,\s*/, $ldap->{'alternative_email_attribute'} || '';

my $mesg = $db->do_operation(
'search',
base => $ldap->{'suffix'},
Expand Down
37 changes: 3 additions & 34 deletions src/lib/Sympa/WWW/Session.pm
Original file line number Diff line number Diff line change
Expand Up @@ -678,39 +678,8 @@ sub decrypt_session_id {

# Old name:
# cookielib::set_cookie_extern(), Sympa::CookieLib::set_cookie_extern().
sub set_cookie_extern {
$log->syslog('debug', '(%s, %s, %s)', @_);
my $self = shift;
my $dom = shift;
my $use_ssl = shift;

my $value = $self->{'alt_emails'} || '';
# Most of browsers allow body of Set-Cookie field at shortest 4093 o,
# and value of cookie may not be longer than length below.
if (3800 < length $value) {
$log->syslog(
'info',
'Cookie value "%s...%s" is too long (%d). Ignored',
substr($value, 0, 25),
substr($value, -25),
length $value
);
undef $value;
}

my $cookie = CGI::Cookie->new(
-name => 'sympa_altemails',
-domain => (($dom eq 'localhost') ? '' : $dom),
-path => '/',
-secure => $use_ssl,
-httponly => 0,
-value => ($value || 'delete'),
($value ? () : (-expires => '-1d')),
);

# Send cookie to the client.
printf "Set-Cookie: %s\n", $cookie->as_string;
}
# DEPRECATED: No longer used.
#sub set_cookie_extern;

###############################
# Subroutines to read cookies #
Expand Down Expand Up @@ -1000,7 +969,7 @@ TBD.
=item set_cookie_extern ( $cookie_domain, [ $use_ssl ] )
I<Instance method>.
TBD.
Deprecated.
=back
Expand Down

0 comments on commit cd4b0ec

Please sign in to comment.