Commit c6072b04 authored by sikeda's avatar sikeda
Browse files

[dev] Small refactoring. New package Sympa::Ticket to handle one-time tickets.


git-svn-id: https://subversion.renater.fr/sympa/branches/sympa-6.2-branch@12596 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent 5d1ecf9e
......@@ -81,6 +81,7 @@ use Sympa::Spool::Incoming;
use Sympa::Spool::Moderation;
use Sympa::Spool::Request;
use Sympa::Template;
use Sympa::Ticket;
use tools;
use Sympa::Tools::Data;
use Sympa::Tools::File;
......@@ -3547,7 +3548,7 @@ sub do_ticket {
wwslog('info', '(%s)', $in{'ticket'});
 
$param->{'ticket_context'} =
Sympa::Auth::get_one_time_ticket($robot, $in{'ticket'}, $ip);
Sympa::Ticket::load($robot, $in{'ticket'}, $ip);
$param->{'ticket_context'}{'printable_date'} =
$language->gettext_strftime("%d %b %Y at %H:%M:%S",
localtime($param->{'ticket_context'}{'date'}));
......@@ -4015,14 +4016,13 @@ sub do_sso_login {
$param->{'init_email'} = $email;
 
## Replace sendpassword with one time ticket
$param->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket(
$param->{'one_time_ticket'} = Sympa::Ticket::create(
$in{'email'},
$robot,
'sso_login/confirmemail?auth_service_name='
. $in{'auth_service_name'},
$ip
);
);
 
unless (sendssopasswd($email)) {
Sympa::Report::reject_report_web('user',
......@@ -4084,8 +4084,7 @@ sub do_sso_login {
 
## Validate the ticket
my $ticket_output =
Sympa::Auth::get_one_time_ticket($robot, $in{'ticket'},
$ip);
Sympa::Ticket::load($robot, $in{'ticket'}, $ip);
unless ($ticket_output->{'result'} eq 'success') {
Sympa::Report::reject_report_web('user', 'auth_failed',
{}, $param->{'action'});
......@@ -4770,8 +4769,7 @@ sub do_requestpasswd {
}
wwslog('debug', 'Sending one time ticket for %s', $in{'email'});
$param->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket($in{'email'}, $robot,
'choosepasswd', $ip);
Sympa::Ticket::create($in{'email'}, $robot, 'choosepasswd', $ip);
$param->{'request_from_host'} = $ip;
unless ($param->{'newuser'} = Sympa::User::get_global_user($in{'email'}))
{
......@@ -6373,7 +6371,7 @@ sub do_subrequest {
tools::escape_chars($param->{'newuser'}{'email'});
}
# Need to send a password by email
$param->{'one_time_ticket'} = Sympa::Auth::create_one_time_ticket(
$param->{'one_time_ticket'} = Sympa::Ticket::create(
$in{'email'}, $robot,
'subscribe/' . $list->{'name'},
$param->{'request_from_host'}
......@@ -13019,23 +13017,25 @@ sub _prepare_edit_form {
foreach my $v (@{$p->{'value'}}) {
if ($v->{'name'} eq 'reception') {
foreach my $x (keys %{$v->{'value'}}) {
$v->{'value'}{$x}{'title'} = Sympa::ListOpt::get_title(
$v->{'value'}{$x}{'title'} =
Sympa::ListOpt::get_title(
$x,
'reception',
Sympa::is_listmaster(
$list, $param->{'user'}{'email'}
)
);
);
}
} elsif ($v->{'name'} eq 'visibility') {
foreach my $x (keys %{$v->{'value'}}) {
$v->{'value'}{$x}{'title'} = Sympa::ListOpt::get_title(
$v->{'value'}{$x}{'title'} =
Sympa::ListOpt::get_title(
$x,
'visibility',
Sympa::is_listmaster(
$list, $param->{'user'}{'email'}
)
);
);
}
}
}
......
......@@ -114,6 +114,7 @@ nobase_modules_DATA = \
Sympa/Spool/Request.pm \
Sympa/Task.pm \
Sympa/Template.pm \
Sympa/Ticket.pm \
tools.pm \
Sympa/Tools/Data.pm \
Sympa/Tools/DKIM.pm \
......
......@@ -50,13 +50,13 @@ use English qw(-no_match_vars);
use Scalar::Util qw();
use Sympa::Alarm;
use Sympa::Auth;
use Sympa::Bulk;
use Conf;
use Sympa::Constants;
use Sympa::Language;
use Sympa::Log;
use Sympa::Message::Template;
use Sympa::Ticket;
use tools;
use Sympa::Tools::Data;
use Sympa::Tools::Text;
......@@ -830,8 +830,8 @@ sub send_notify_to_listmaster {
foreach my $email (@listmasters) {
my $cdata = Sympa::Tools::Data::dup_var($data);
$cdata->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket($email, $robot_id,
'get_pending_lists', $cdata->{'ip'});
Sympa::Ticket::create($email, $robot_id, 'get_pending_lists',
$cdata->{'ip'});
push @tosend,
{
email => $email,
......@@ -946,19 +946,19 @@ sub send_notify_to_user {
if ($operation eq 'ticket_to_signoff') {
$param->{one_time_ticket} =
Sympa::Auth::create_one_time_ticket($user, $robot_id,
Sympa::Ticket::create($user, $robot_id,
'signoff/' . $list->{'name'},
$param->{ip})
or return undef;
} elsif ($operation eq 'ticket_to_family_signoff') {
$param->{one_time_ticket} =
Sympa::Auth::create_one_time_ticket($user, $robot_id,
Sympa::Ticket::create($user, $robot_id,
'family_signoff/' . $param->{family} . '/' . $user,
$param->{ip})
or return undef;
} elsif ($operation eq 'ticket_to_send') {
$param->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket($user, $robot_id,
Sympa::Ticket::create($user, $robot_id,
'change_email/' . $param->{email},
$param->{ip})
or return undef;
......
......@@ -27,19 +27,15 @@ package Sympa::Auth;
use strict;
use warnings;
use Digest::MD5;
use POSIX qw();
use Sympa;
use Conf;
use Sympa::Database;
use Sympa::DatabaseManager;
use Sympa::Log;
use Sympa::Report;
use Sympa::Robot;
use Sympa::Session;
use tools;
use Sympa::Tools::Data;
use Sympa::Tools::Time;
use Sympa::User;
my $log = Sympa::Log->instance;
......@@ -469,145 +465,10 @@ sub remote_app_check_password {
return;
}
# 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 $ticket = Sympa::Session::get_random();
#$log->syslog('info', '(%s, %s, %s, %s) Value = %s',
# $email, $robot, $data_string, $remote_addr, $ticket);
my $date = time;
my $sdm = Sympa::DatabaseManager->instance;
unless (
$sdm
and $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->syslog(
'err',
'Unable to insert new one time ticket for user %s, robot %s in the database',
$email,
$robot
);
return undef;
}
return $ticket;
}
# read one_time_ticket from table and remove it
sub get_one_time_ticket {
$log->syslog('debug2', '(%s, %s, %s)', @_);
my $robot = shift;
my $ticket_number = shift;
my $addr = shift;
my $sth;
my $sdm = Sympa::DatabaseManager->instance;
unless (
$sdm
and $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->syslog('err',
'Unable to retrieve one time ticket %s from database',
$ticket_number);
return {'result' => 'error'};
}
my $ticket = $sth->fetchrow_hashref('NAME_lc');
$sth->finish;
unless ($ticket) {
$log->syslog('info', 'Unable to find one time ticket %s', $ticket);
return {'result' => 'not_found'};
}
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 =
Sympa::Tools::Time::duration_conv(
Conf::get_robot_conf($robot, 'one_time_ticket_lifetime') || 0);
if ($lockout eq 'one_time' and $ticket->{'status'} ne 'open') {
$result = 'closed';
$log->syslog('info', 'Ticket %s from %s has been used before (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
} elsif ($lockout eq 'remote_addr'
and $ticket->{'status'} ne $addr
and $ticket->{'status'} ne 'open') {
$result = 'closed';
$log->syslog('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->syslog('info', 'Ticket %s from %s refused because expired (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
$result = 'expired';
} else {
$result = 'success';
}
# Moved to Sympa::Ticket::create().
#sub create_one_time_ticket;
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->syslog('err',
'Unable to set one time ticket %s status to %s',
$ticket_number, $addr);
} elsif (!$sth->rows) {
# ticket may be removed by task.
$log->syslog('info', 'Unable to find one time ticket %s',
$ticket_number);
return {'result' => 'not_found'};
}
}
$log->syslog('info', 'Ticket: %s; Result: %s', $ticket_number, $result);
return {
'result' => $result,
'date' => $ticket->{'date'},
'email' => $ticket->{'email'},
'remote_addr' => $ticket->{'remote_addr'},
'robot' => $robot,
'data' => $ticket->{'data'},
'status' => $ticket->{'status'}
};
}
# Moved to Sympa::Tickect::load().
#sub get_one_time_ticket;
1;
......@@ -37,7 +37,6 @@ use Storable qw();
use URI::Escape qw();
use Sympa;
use Sympa::Auth;
use Sympa::Bulk;
use Conf;
use Sympa::ConfDef;
......@@ -59,6 +58,7 @@ use Sympa::Scenario;
use SDM;
use Sympa::Task;
use Sympa::Template;
use Sympa::Ticket;
use tools;
use Sympa::Tools::Data;
use Sympa::Tools::File;
......@@ -1662,15 +1662,14 @@ sub send_notify_to_owner {
$param->{'escaped_who'} = $param->{'who'};
$param->{'escaped_who'} =~ s/\s/\%20/g;
foreach my $owner (@rcpt) {
$param->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket(
$param->{'one_time_ticket'} = Sympa::Ticket::create(
$owner,
$robot,
'search/'
. $self->{'name'} . '/'
. $param->{'escaped_who'},
$param->{'ip'}
);
);
unless (
Sympa::send_file(
$self, 'listowner_notification', [$owner], $param
......@@ -1694,7 +1693,7 @@ sub send_notify_to_owner {
$param->{'escaped_who'} =~ s/\s/\%20/g;
foreach my $owner (@rcpt) {
$param->{'one_time_ticket'} =
Sympa::Auth::create_one_time_ticket($owner, $robot,
Sympa::Ticket::create($owner, $robot,
'subindex/' . $self->{'name'},
$param->{'ip'});
unless (
......
......@@ -103,7 +103,7 @@ sub new {
# create a new session context
$self->{'new_session'} =
1; ## Tag this session as new, ie no data in the DB exist
$self->{'id_session'} = get_random();
$self->{'id_session'} = Sympa::Tools::Password::get_random();
$self->{'email'} = 'nobody';
$self->{'remote_addr'} = $ENV{'REMOTE_ADDR'};
$self->{'date'} = $self->{'refresh_date'} = $self->{'start_date'} =
......@@ -389,7 +389,7 @@ sub renew {
}
## Renew the session ID in order to prevent session hijacking
$new_id = get_random();
$new_id = Sympa::Tools::Password::get_random();
## Do refresh the session ID when remote address was changed or refresh
## interval was past. Conditions also are checked by SQL so that
......@@ -757,10 +757,8 @@ sub soap_cookie2 {
return $cookie->as_string;
}
sub get_random {
## Concatenates two integers for a better entropy.
return sprintf '%07d%07d', int(rand(10**7)), int(rand(10**7));
}
# Moved to Sympa::Tools::Password::get_random().
#sub get_random;
## Return the session object content, as a hashref
sub as_hashref {
......
......@@ -29,10 +29,10 @@ use warnings;
use Time::HiRes qw();
use Sympa;
use Sympa::Auth;
use Sympa::Log;
use Sympa::Message::Template;
use Sympa::Spool::Moderation;
use Sympa::Ticket;
use base qw(Sympa::Spindle);
......@@ -187,7 +187,7 @@ sub _send_confirm_to_editor {
# create a one time ticket that will be used as un md5 URL credential
unless (
$param->{'one_time_ticket'} = Sympa::Auth::create_one_time_ticket(
$param->{'one_time_ticket'} = Sympa::Ticket::create(
$recipient, $list->{'domain'},
'modindex/' . $list->{'name'}, 'mail'
)
......
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id$
# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# 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 GIP RENATER
#
# 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
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
package Sympa::Ticket;
use strict;
use warnings;
use POSIX qw();
use Conf;
use Sympa::DatabaseManager;
use Sympa::Log;
use Sympa::Tools::Password;
use Sympa::Tools::Time;
my $log = Sympa::Log->instance;
# Create new entry in one_time_ticket table using a rand as id so later
# access is authenticated.
# Old name: Sympa::Auth::create_one_time_ticket().
sub create {
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 $ticket = Sympa::Tools::Password::get_random();
#$log->syslog('info', '(%s, %s, %s, %s) Value = %s',
# $email, $robot, $data_string, $remote_addr, $ticket);
my $date = time;
my $sdm = Sympa::DatabaseManager->instance;
unless (
$sdm
and $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->syslog(
'err',
'Unable to insert new one time ticket for user %s, robot %s in the database',
$email,
$robot
);
return undef;
}
return $ticket;
}
# Read one_time_ticket from table and remove it.
# Old name: Sympa::Auth::create_one_time_ticket().
sub load {
$log->syslog('debug2', '(%s, %s, %s)', @_);
my $robot = shift;
my $ticket_number = shift;
my $addr = shift;
my $sth;
my $sdm = Sympa::DatabaseManager->instance;
unless (
$sdm
and $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->syslog('err',
'Unable to retrieve one time ticket %s from database',
$ticket_number);
return {'result' => 'error'};
}
my $ticket = $sth->fetchrow_hashref('NAME_lc');
$sth->finish;
unless ($ticket) {
$log->syslog('info', 'Unable to find one time ticket %s', $ticket);
return {'result' => 'not_found'};
}
my $result;
my $printable_date =
POSIX::strftime('%Y-%m-%d %H:%M:%S', localtime $ticket->{'date'});
my $lockout = Conf::get_robot_conf($robot, 'one_time_ticket_lockout')
|| 'open';
my $lifetime =
Sympa::Tools::Time::duration_conv(
Conf::get_robot_conf($robot, 'one_time_ticket_lifetime') || 0);
if ($lockout eq 'one_time' and $ticket->{'status'} ne 'open') {
$result = 'closed';
$log->syslog('info', 'Ticket %s from %s has been used before (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
} elsif ($lockout eq 'remote_addr'
and $ticket->{'status'} ne $addr
and $ticket->{'status'} ne 'open') {
$result = 'closed';
$log->syslog('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->syslog('info', 'Ticket %s from %s refused because expired (%s)',
$ticket_number, $ticket->{'email'}, $printable_date);
$result = 'expired';
} else {
$result = 'success';
}
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->syslog('err',
'Unable to set one time ticket %s status to %s',
$ticket_number, $addr);
} elsif (!$sth->rows) {
# ticket may be removed by task.
$log->syslog('info', 'Unable to find one time ticket %s',
$ticket_number);
return {'result' => 'not_found'};
}
}
$log->syslog('info', 'Ticket: %s; Result: %s', $ticket_number, $result);
return {
'result' => $result,
'date' => $ticket->{'date'},
'email' => $ticket->{'email'},
'remote_addr' => $ticket->{'remote_addr'},
'robot' => $robot,
'data' => $ticket->{'data'},
'status' => $ticket->{'status'}
};
}
1;
......@@ -88,6 +88,12 @@ sub decrypt_password {
return ($cipher->decrypt(MIME::Base64::decode($inpasswd)));
}
# Old name: Sympa::Session::get_random().
sub get_random {
# Concatenates two integers for a better entropy.
return sprintf '%07d%07d', int(rand(10**7)), int(rand(10**7));
}
my @validation_messages = (
{gettext_id => 'Not between %d and %d characters'},
{gettext_id => 'Not %d characters or greater'},
......
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