Commit 05d80b59 authored by IKEDA Soji's avatar IKEDA Soji
Browse files

Refactoring feature of sympa_altemails cookie.

- Cookie threw back by clients will no longer be used: Value of cookie will be kept in session store.

It is not obvious that this feature is really used. Maybe deprecated in the future.
parent 79e1656b
......@@ -1438,17 +1438,7 @@ while ($query = CGI::Fast->new) {
}
}
 
##Cookie extern : sympa_altemails
## !!
$param->{'alt_emails'} =
Sympa::WWW::Session::check_cookie_extern($ENV{'HTTP_COOKIE'},
$Conf::Conf{'cookie'}, $param->{'user'}{'email'});
if ($param->{'user'}{'email'}) {
#$param->{'auth'} =
# $param->{'alt_emails'}{$param->{'user'}{'email'}}
# || 'classic';
if (Sympa::User::is_global_user($param->{'user'}{'email'})) {
$param->{'user'} =
Sympa::User::get_global_user($param->{'user'}{'email'});
......@@ -1626,6 +1616,35 @@ while ($query = CGI::Fast->new) {
$param->{'title_clear_txt'} = $param->{'title'};
}
 
$param->{'is_user_allowed_to'} = sub {
my $permission = shift;
my $list = shift;
return 0 unless $permission and $list;
$list = Sympa::List->new($list, $robot)
unless ref $list eq 'Sympa::List';
my $result = Sympa::Scenario::request_action(
$list,
$permission,
$param->{'auth_method'},
{ 'sender' => $param->{'user'}{'email'},
'remote_host' => $param->{'remote_host'},
'remote_addr' => $param->{'remote_addr'}
}
);
return 0
unless ref($result) eq 'HASH'
and $result->{'action'} ne 'reject';
return 0
if $permission eq 'subscribe'
and $list->is_list_member($param->{'user'}{'email'});
return 0
if $permission eq 'archive.web_access'
and not defined $list->{'admin'}{'archive'};
return 1;
};
# Store oauth_token in session if present and no user so that it
# will not be lost during login process
my $oauth_token = $in{'oauth_token'} || '';
......@@ -1635,97 +1654,21 @@ while ($query = CGI::Fast->new) {
## store in session table this session contexte
$session->store();
 
## Do not manage cookies at this level if content was already sent
# Do not manage cookies at this level if content was already sent.
unless (
$param->{'bypass'} eq 'extreme'
#XXX|| $param->{'action'} eq 'css'
|| $maintenance_mode
|| $rss || $ajax
) {
my $delay = $param->{'user'}{'cookie_delay'};
unless (defined $delay) {
$delay = $Conf::Conf{'cookie_expire'};
}
$param->{'bypass'} eq 'extreme' or $maintenance_mode or $rss or $ajax
) {
$session->renew unless $param->{'use_ssl'};
 
if ($delay == 0) {
$delay = 'session';
}
$session->renew() unless $param->{'use_ssl'};
unless (
$session->set_cookie(
$param->{'cookie_domain'},
$delay, $param->{'use_ssl'}
)
) {
wwslog('notice', 'Could not set HTTP cookie');
}
$param->{'is_user_allowed_to'} = sub {
my $permission = shift;
my $list = shift;
return 0 unless $permission and $list;
$list = Sympa::List->new($list, $robot)
unless ref $list eq 'Sympa::List';
my $result = Sympa::Scenario::request_action(
$list,
$permission,
$param->{'auth_method'},
{ 'sender' => $param->{'user'}{'email'},
'remote_host' => $param->{'remote_host'},
'remote_addr' => $param->{'remote_addr'}
}
);
$session->set_cookie($param->{'cookie_domain'},
$param->{'user'}{'cookie_delay'}, $param->{'use_ssl'});
# Set/delete cookie for alt_emails.
$session->set_cookie_extern($param->{'cookie_domain'},
$param->{'use_ssl'});
 
return 0
unless ref($result) eq 'HASH'
and $result->{'action'} ne 'reject';
return 0
if $permission eq 'subscribe'
and $list->is_list_member($param->{'user'}{'email'});
return 0
if $permission eq 'archive.web_access'
and not defined $list->{'admin'}{'archive'};
return 1;
};
# Set cookies unless client use https authentication
if ($param->{'user'}{'email'}) {
if ($param->{'user'}{'email'} ne 'x509') { #FIXME FIXME FIXME
$session->{'auth'} ||= 'classic';
$param->{'cookie_set'} = 1;
###Cookie extern : sympa_altemails
my $number = 0;
foreach my $element (keys %{$param->{'alt_emails'}}) {
$number++ if ($element);
}
unless ($number == 0) {
unless (
Sympa::WWW::Session::set_cookie_extern(
$Conf::Conf{'cookie'},
$param->{'cookie_domain'},
%{$param->{'alt_emails'}}
)
) {
wwslog('notice',
'Could not set HTTP cookie for external_auth');
}
}
}
$session->{'auth'} ||= 'classic';
}
# elsif ($ENV{'HTTP_COOKIE'} =~ /sympauser\=/) {
# cookielib::set_cookie('unknown', $Conf::Conf{'cookie'},
# $param->{'cookie_domain'}, 'now');
# }
}
 
## Available languages
......@@ -1923,19 +1866,6 @@ sub wwslog {
$wwsmsg = "[list $param->{'list'}] " . $wwsmsg
if $param->{'list'};
 
if ($param->{'alt_emails'}) {
my @alts;
foreach my $alt (keys %{$param->{'alt_emails'}}) {
push @alts, $alt
unless ($alt eq $param->{'user'}{'email'});
}
if ($#alts >= 0) {
my $alt_list = join ',', @alts;
$wwsmsg = "[alt $alt_list] " . $wwsmsg;
}
}
$wwsmsg = "[user $param->{'user'}{'email'}] " . $wwsmsg
if $param->{'user'}{'email'};
 
......@@ -3254,38 +3184,13 @@ sub do_login {
}
);
 
## Set alt_email
if ($data->{'alt_emails'}) {
foreach my $k (keys %{$data->{'alt_emails'}}) {
$param->{'alt_emails'}{$k} = $data->{'alt_emails'}{$k};
}
}
unless ($param->{'alt_emails'}{$email}) {
unless (
Sympa::WWW::Session::set_cookie_extern(
$Conf::Conf{'cookie'}, $param->{'cookie_domain'},
%{$param->{'alt_emails'}}
)
) {
wwslog('notice', 'Could not set HTTP cookie for external_auth');
web_db_log(
{ 'parameters' => $param->{'cookie_domain'} . ','
. join(',',
map {"$_ => $param->{'alt_emails'}{$_}"}
keys %{$param->{'alt_emails'} || {}}),
'target_email' => $in{'email'},
'status' => 'error',
'error_type' => 'cookie'
}
);
return undef;
}
}
## Current authentication mode
#$param->{'auth'} =
# $param->{'alt_emails'}{$param->{'user'}{'email'}} || 'classic';
# 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
......@@ -4006,7 +3911,8 @@ sub do_redirect {
sub _redirect {
my $redirect_to = shift;
 
$session->set_cookie($param->{'cookie_domain'}, 'session');
$session->set_cookie($param->{'cookie_domain'}, 'session',
$param->{'use_ssl'});
print "Status: 302 Moved\n";
print "Location: $redirect_to\n\n";
$param->{'bypass'} = 'extreme';
......@@ -4019,6 +3925,7 @@ 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'}]) {
......
......@@ -8,6 +8,9 @@
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
# Copyright 2018 The Sympa Community. See the AUTHORS.md file at the
# top-level directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -539,49 +542,38 @@ sub get_session_cookie {
## Set user $email cookie, ckecksum use $secret, expire=(now|session|#sec)
## domain=(localhost|<a domain>)
sub set_cookie {
my ($self, $http_domain, $expires, $use_ssl) = @_;
$log->syslog('debug', '(%s, %s, secure= %s)',
$http_domain, $expires, $use_ssl);
$log->syslog('debug', '(%s, %s, %s, %s)', @_);
my $self = shift;
my $dom = shift;
my $expires = shift;
my $use_ssl = shift;
$expires = $Conf::Conf{'cookie_expire'} unless defined $expires;
my $expiration;
if ($expires =~ /now/i) {
if ($expires eq '0' or $expires eq 'session') {
$expiration = '';
} elsif ($expires =~ /now/i) { #FIXME: Perhaps never used.
## 10 years ago
$expiration = '-10y';
} else {
$expiration = '+' . $expires . 'm';
}
if ($http_domain eq 'localhost') {
$http_domain = "";
}
my $value = encrypt_session_id($self->{'id_session'});
my $cookie;
if ($expires =~ /session/i) {
$cookie = CGI::Cookie->new(
-name => 'sympa_session',
-value => $value,
-domain => $http_domain,
-path => '/',
-secure => $use_ssl,
-httponly => 1
);
} else {
$cookie = CGI::Cookie->new(
-name => 'sympa_session',
-value => $value,
-expires => $expiration,
-domain => $http_domain,
-path => '/',
-secure => $use_ssl,
-httponly => 1
);
}
my $cookie = CGI::Cookie->new(
-name => 'sympa_session',
-domain => (($dom eq 'localhost') ? '' : $dom),
-path => '/',
-secure => $use_ssl,
-httponly => 1,
-value => $value,
($expiration ? (-expires => $expiration) : ()),
);
## Send cookie to the client
# Send cookie to the client.
printf "Set-Cookie: %s\n", $cookie->as_string;
return 1;
}
# Build an HTTP cookie value to be sent to a SOAP client
......@@ -681,62 +673,43 @@ sub decrypt_session_id {
## returns Message Authentication Check code
# Old name: cookielib::get_mac(), Sympa::CookieLib::get_mac().
sub _get_mac {
my $email = shift;
my $secret = shift;
$log->syslog('debug3', '(%s, %s)', $email, $secret);
unless ($secret) {
$log->syslog('err',
'Failure missing server secret for cookie MD5 digest');
return undef;
}
unless ($email) {
$log->syslog('err',
'Failure missing email address or cookie MD5 digest');
return undef;
}
my $md5 = Digest::MD5->new;
$md5->reset;
$md5->add($email . $secret);
return substr(unpack("H*", $md5->digest), -8);
}
# DEPRECATED: No longer used.
#sub _get_mac;
# Old name:
# cookielib::set_cookie_extern(), Sympa::CookieLib::set_cookie_extern().
sub set_cookie_extern {
my ($secret, $http_domain, %alt_emails) = @_;
my $cookie;
my $value;
my @mails;
foreach my $mail (keys %alt_emails) {
my $string = $mail . ':' . $alt_emails{$mail};
push(@mails, $string);
}
my $emails = join(',', @mails);
$value = sprintf '%s&%s', $emails, _get_mac($emails, $secret);
if ($http_domain eq 'localhost') {
$http_domain = "";
$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;
}
$cookie = CGI::Cookie->new(
-name => 'sympa_altemails',
-value => $value,
-expires => '+1y',
-domain => $http_domain,
-path => '/'
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
# Send cookie to the client.
printf "Set-Cookie: %s\n", $cookie->as_string;
#$log->syslog('notice','%s',$cookie->as_string);
return 1;
}
###############################
......@@ -767,28 +740,8 @@ sub _generic_get_cookie {
# Old name:
# cookielib::check_cookie_extern(), Sympa::CookieLib::check_cookie_extern().
sub check_cookie_extern {
my ($http_cookie, $secret, $user_email) = @_;
my $extern_value = _generic_get_cookie($http_cookie, 'sympa_altemails');
if ($extern_value and $extern_value =~ /^(\S+)&(\w+)$/) {
return undef unless (_get_mac($1, $secret) eq $2);
my %alt_emails;
foreach my $element (split(/,/, $1)) {
my @array = split(/:/, $element);
$alt_emails{$array[0]} = $array[1];
}
my $e = lc($user_email);
unless ($alt_emails{$e}) {
return undef;
}
return (\%alt_emails);
}
return undef;
}
# DEPRECATED: No longer used.
#sub check_cookie_extern;
# input user agent string and IP. return 1 if suspected to be a crawler.
# initial version based on rawlers_dtection.conf file only
......@@ -1017,7 +970,7 @@ Stores session into session store.
=item check_cookie_extern ( )
I<Function>.
TBD.
Deprecated.
=item decrypt_session_id ( )
......@@ -1037,6 +990,16 @@ TBD.
=item purge_old_sessions ( )
I<Function>.
Deprecated.
=item set_cookie ( $cookie_domain, $expires, [ $use_ssl ] )
I<Instance method>.
TBD.
=item set_cookie_extern ( $cookie_domain, [ $use_ssl ] )
I<Instance method>.
TBD.
=back
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment