Commit cd4e1f77 authored by sikeda's avatar sikeda
Browse files

[feature] Behavior of one time ticket lock-out is configurable.

Two new robot parameters were introduced:
* one_time_ticket_lockout:
  - "one_time" won't allow access again.  This is previous behavior.
  - "remote_addr" will lock the ticket on remote address accessed at first time.
  - "open" will never lock-out tickets.
* one_time_ticket_lifetime:
  Duration before ticket expires.  Default is "2d", previous hardcoded value.


git-svn-id: https://subversion.renater.fr/sympa/branches/sympa-6.2-branch@11068 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent b7fdda1d
......@@ -3640,7 +3640,7 @@ sub do_ticket {
wwslog('info', '(%s)', $in{'ticket'});
 
$param->{'ticket_context'} =
Auth::get_one_time_ticket($in{'ticket'}, $ip);
Auth::get_one_time_ticket($robot, $in{'ticket'}, $ip);
$param->{'ticket_context'}{'printable_date'} =
$language->gettext_strftime("%d %b %Y at %H:%M:%S",
localtime($param->{'ticket_context'}{'date'}));
......@@ -4172,7 +4172,7 @@ sub do_sso_login {
 
## Validate the ticket
my $ticket_output =
Auth::get_one_time_ticket($in{'ticket'}, $ip);
Auth::get_one_time_ticket($robot, $in{'ticket'}, $ip);
unless ($ticket_output->{'result'} eq 'success') {
report::reject_report_web('user', 'auth_failed', {},
$param->{'action'});
......
......@@ -335,6 +335,7 @@ sub ldap_authentication {
}
# fetch user email using his cas net_id and the paragrapah number in auth.conf
# NOTE: This might be moved to Robot package.
sub get_email_by_net_id {
my $robot = shift;
......@@ -372,7 +373,7 @@ sub get_email_by_net_id {
my $filter = $ldap->{'ldap_get_email_by_uid_filter'};
$filter =~ s/\[([\w-]+)\]/$attributes->{$1}/ig;
# my @alternative_conf = split(/,/,$ldap->{'alternative_email_attribute'});
# my @alternative_conf = split(/,/,$ldap->{'alternative_email_attribute'});
my $emails = $ldap_anonymous->search(
base => $ldap->{'ldap_suffix'},
......@@ -435,21 +436,19 @@ sub remote_app_check_password {
}
}
# no matching application found
Log::do_log('info', '-check_password: unknown application name %s',
Log::do_log('info', 'Unknown application name %s',
$trusted_application_name);
return undef;
}
# create new entry in one_time_ticket table using a rand as id so later access
# is authenticated
#
# create new entry in one_time_ticket table using a rand as id so later
# access is authenticated
sub create_one_time_ticket {
my $email = shift;
my $robot = shift;
my $data_string = shift;
my $remote_addr =
shift; ## Value may be 'mail' if the IP address is not known
my $remote_addr = shift;
## Value may be 'mail' if the IP address is not known
my $ticket = SympaSession::get_random();
Log::do_log('info', '(%s, %s, %s, %s) Value = %s',
......@@ -459,15 +458,15 @@ sub create_one_time_ticket {
my $sth;
unless (
SDM::do_query(
"INSERT INTO one_time_ticket_table (ticket_one_time_ticket, robot_one_time_ticket, email_one_time_ticket, date_one_time_ticket, data_one_time_ticket, remote_addr_one_time_ticket, status_one_time_ticket) VALUES (%s, %s, %s, %d, %s, %s, %s)",
SDM::quote($ticket),
SDM::quote($robot),
SDM::quote($email),
time,
SDM::quote($data_string),
SDM::quote($remote_addr),
SDM::quote('open')
SDM::do_prepared_query(
q{INSERT INTO one_time_ticket_table
(ticket_one_time_ticket, robot_one_time_ticket,
email_one_time_ticket, date_one_time_ticket, data_one_time_ticket,
remote_addr_one_time_ticket, status_one_time_ticket)
VALUES (?, ?, ?, ?, ?, ?, ?)},
$ticket, $robot,
$email, time, $data_string,
$remote_addr, 'open'
)
) {
Log::do_log(
......@@ -482,19 +481,26 @@ sub create_one_time_ticket {
}
# read one_time_ticket from table and remove it
#
sub get_one_time_ticket {
Log::do_log('debug2', '(%s, %s, %s)', @_);
my $robot = shift;
my $ticket_number = shift;
my $addr = shift;
Log::do_log('debug2', '(%s)', $ticket_number);
my $sth;
unless (
$sth = SDM::do_query(
"SELECT ticket_one_time_ticket AS ticket, robot_one_time_ticket AS robot, email_one_time_ticket AS email, date_one_time_ticket AS \"date\", data_one_time_ticket AS data, remote_addr_one_time_ticket AS remote_addr, status_one_time_ticket as status FROM one_time_ticket_table WHERE ticket_one_time_ticket = %s ",
SDM::quote($ticket_number)
$sth = SDM::do_prepared_query(
q{SELECT ticket_one_time_ticket AS ticket,
robot_one_time_ticket AS robot,
email_one_time_ticket AS email,
date_one_time_ticket AS "date",
data_one_time_ticket AS data,
remote_addr_one_time_ticket AS remote_addr,
status_one_time_ticket as status
FROM one_time_ticket_table
WHERE ticket_one_time_ticket = ? AND robot_one_time_ticket = ?},
$ticket_number, $robot
)
) {
Log::do_log('err',
......@@ -504,6 +510,7 @@ sub get_one_time_ticket {
}
my $ticket = $sth->fetchrow_hashref('NAME_lc');
$sth->finish;
unless ($ticket) {
Log::do_log('info', 'Unable to find one time ticket %s', $ticket);
......@@ -513,36 +520,59 @@ sub get_one_time_ticket {
my $result;
my $printable_date =
POSIX::strftime("%d %b %Y at %H:%M:%S", localtime($ticket->{'date'}));
my $lockout = Conf::get_robot_conf($robot, 'one_time_ticket_lockout')
|| 'open';
my $lifetime =
tools::duration_conv(
Conf::get_robot_conf($robot, 'one_time_ticket_lifetime') || 0);
if ($ticket->{'status'} ne 'open') {
if ($lockout eq 'one_time' and $ticket->{'status'} ne 'open') {
$result = 'closed';
Log::do_log('info', 'Ticket %s from %s has been used before (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
} elsif (time - $ticket->{'date'} > 48 * 60 * 60) {
} elsif ($lockout eq 'remote_addr'
and $ticket->{'status'} ne $addr
and $ticket->{'status'} ne 'open') {
$result = 'closed';
Log::do_log('info',
'ticket %s from %s refused because accessed by the other (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
} elsif ($lifetime and $ticket->{'date'} + $lifetime < time) {
Log::do_log('info', 'Ticket %s from %s refused because expired (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
$result = 'expired';
} else {
$result = 'success';
}
unless (
SDM::do_query(
"UPDATE one_time_ticket_table SET status_one_time_ticket = %s WHERE (ticket_one_time_ticket=%s)",
SDM::quote($addr),
SDM::quote($ticket_number)
)
) {
Log::do_log('err', 'Unable to set one time ticket %s status to %s',
$ticket_number, $addr);
if ($result eq 'success') {
unless (
$sth = SDM::do_prepared_query(
q{UPDATE one_time_ticket_table
SET status_one_time_ticket = ?,
WHERE ticket_one_time_ticket = ? AND
robot_one_time_ticket = ?},
$addr, $ticket_number, $robot
)
) {
Log::do_log('err',
'Unable to set one time ticket %s status to %s',
$ticket_number, $addr);
} elsif (!$sth->rows) {
# ticket may be removed by task.
Log::do_log('info', 'Unable to find one time ticket %s',
$ticket_number);
return {'result' => 'not_found'};
}
}
Log::do_log('info', '(%s) Result: %s', $ticket_number, $result);
Log::do_log('info', 'Ticket: %s; Result: %s', $ticket_number, $result);
return {
'result' => $result,
'date' => $ticket->{'date'},
'email' => $ticket->{'email'},
'remote_addr' => $ticket->{'remote_addr'},
'robot' => $ticket->{'robot'},
'robot' => $robot,
'data' => $ticket->{'data'},
'status' => $ticket->{'status'}
};
......
......@@ -1411,8 +1411,18 @@ our @params = (
'file' => 'wwsympa.conf',
'optional' => 1,
},
##{ one_time_ticket_lifetime: not yet implemented. },
##{ one_time_ticket_lockout: not yet implemented. },
{
'name' => 'one_time_ticket_lifetime',
'default' => '2d',
'gettext_id' => 'duration before the one time tickets are expired',
},
{
'name' => 'one_time_ticket_lockout',
'default' => 'one_time',
'gettext_id' => 'Is access to the one time ticket restricted, if any users previously accessed? (one_time | remote_addr | open)',
'edit' => '1',
'vhost' => '1',
},
{ 'name' => 'password_case',
'default' => 'insensitive',
'gettext_id' => 'Password case (insensitive | sensitive)',
......
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