Commit 311cae8c authored by serge.aumont's avatar serge.aumont
Browse files

***** Replace storage of password with encryption by md5 fingerprint. This

***** make remind password impossible. So now a one time ticket table is created
***** ticket are  sent by email as an authentication token. Ticket can be used 
***** for lost password, create account, moderation request . It should be
***** generalized to all operation that need a email chalenge.
*****
***** sympa.pl --md5_encode_password change password encoding in the database using md5.So IT IS NOT REVERSIBLE,
***** so you should save the database (in a safe place to protect password) 

  -  new login method include now "last login from [HOST] at [date]" information  message
  -  new daily task to remove tickets older than 10d (task parameters in conf.pm): 
       - purge_one_time_ticket_table_task default daily
       - one_time_ticket_table_ttl default 10d




git-svn-id: https://subversion.renater.fr/sympa/trunk@4857 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent c408796d
......@@ -10,6 +10,9 @@ Content-Type: multipart/mixed; boundary="[% boundary %]"
Content-Type: text/plain; charset="UTF-8";
Content-Transfer-Encoding: 8bit
[%|loc(mod_spool_size,list.name)%]they are %1 messages awaiting moderation for list %2.[%END%]
[%|loc(conf.wwsympa_url,one_time_ticket) %]You can browse and accept or refuse them by web : %1/ticket/%2[% END %]
[% IF method == 'md5' -%]
[% IF request_topic -%][%|loc(list.name,conf.wwsympa_url,modkey)%]To tag the attached message in list %1 go to the following page :
......@@ -28,7 +31,7 @@ REJECT [% list.name %] [% modkey %]
[% END %]
[%- END -%]
[%|loc(mod_spool_size)%]Number of messages awaiting moderation for this list : %1[%END%]
--[% boundary %]
Content-Type: message/rfc822
Content-Transfer-Encoding: 8bit
......
......@@ -23,16 +23,10 @@ Subject: [% FILTER qencode %][%|loc(conf.title)%]%1 / your environment[%END%][%E
[%|loc(newuser.password)%]password: %1[%END%]
[% ELSE -%]
[%|loc%]To access your personal environment, you need to login first[%END%]
[%|loc(newuser.email)%]your email address : %1[%END%]
[%|loc(newuser.password)%]your password : %1[%END%]
[%|loc(conf.host,request_from_host,date)%]Someone, probably you, requested to allocate or renew your password for your list server account %1. (This request cames from host %2 at %3).[%END%]
[%|loc%]You may ignore this request or hit the following url in order to choose your password. [%END%]: [% base_url %][% path_cgi %]/ticket/[% one_time_ticket %]
[%|loc%]Changing your password[%END%]
[% base_url %][% path_cgi %]/choosepasswd/[% newuser.escaped_email %]/[% newuser.password %]
[% END %]
[% conf.title %]: [% base_url %][% path_cgi %]
[%END%]
[%|loc(base_url,path_cgi)%]Help on Sympa: %1%2[%END%]/help
......@@ -60,7 +60,9 @@ my @valid_options = qw(
spool queue queuedistribute queueauth queuetask queuebounce queuedigest queueautomatic
queuemod queuetopic queuesubscribe queueoutgoing tmpdir lock_method
loop_command_max loop_command_sampling_delay loop_command_decrease_factor loop_prevention_regex
purge_user_table_task purge_logs_table_task purge_session_table_task session_table_ttl anonymous_session_table_ttl
purge_user_table_task purge_logs_table_task
purge_session_table_task session_table_ttl anonymous_session_table_ttl
purge_one_time_ticket_table_task one_time_ticket_table_ttl
purge_orphan_bounces_task eval_bouncers_task process_bouncers_task
minimum_bouncing_count minimum_bouncing_period bounce_delay
default_bounce_level1_rate default_bounce_level2_rate
......@@ -227,6 +229,8 @@ my %Default_Conf =
'logs_expiration_period' => 3, #3 months
'purge_session_table_task' => 'daily',
'session_table_ttl' => '2d', #
'purge_one_time_ticket_table_task' => 'daily',
'one_time_ticket_table_ttl' => '10d', #
'anonymous_session_table_ttl' => '1h', #
'purge_challenge_table_task' => 'daily',
'challenge_table_ttl' => '5d', #
......@@ -1065,7 +1069,8 @@ sub _load_auth {
'force_email_verify' => '1',
'internal_email_by_netid' => '1',
'netid_http_header' => '\w+',
}
},
'authentication_info_url' => 'http(s)?:/.*'
);
......@@ -1087,7 +1092,10 @@ sub _load_auth {
$line_num++;
next if (/^\s*[\#\;]/o);
if (/^\s*(ldap|cas|user_table|generic_sso)\s*$/io) {
if (/^\s*authentication_info_url\s+(.*\S)\s*$/o){
$Conf{'authentication_info_url'}{$robot} = $1;
next;
}elsif (/^\s*(ldap|cas|user_table|generic_sso)\s*$/io) {
$current_paragraph->{'auth_type'} = lc($1);
}elsif (/^\s*(\S+)\s+(.*\S)\s*$/o){
my ($keyword,$value) = ($1,$2);
......
......@@ -3503,11 +3503,8 @@ sub send_to_editor {
$param->{'request_topic'} = 1;
}
if ($encrypt eq 'smime_crypted') {
## Send a different crypted message to each moderator
foreach my $recipient (@rcpt) {
if ($encrypt eq 'smime_crypted') {
## $msg->body_as_string respecte-t-il le Base64 ??
my $cryptedmsg = &tools::smime_encrypt($msg->head, $msg->body_as_string, $recipient);
unless ($cryptedmsg) {
......@@ -3523,25 +3520,67 @@ sub send_to_editor {
}
print CRYPTED $cryptedmsg;
close CRYPTED;
$param->{'msg_path'} = $crypted_file;
&tt2::allow_absolute_path();
unless ($self->send_file('moderate', $recipient, $self->{'domain'}, $param)) {
&do_log('notice',"Unable to send template 'moderate' to $recipient");
return undef;
}
}
}else{
$param->{'msg_path'} = $file;
}
# create a one time ticket that will be used as un md5 URL credential
unless ($param->{'one_time_ticket'} = &Auth::create_one_time_ticket($recipient,$robot,'modindex/'.$name,'mail')){
&do_log('notice',"Unable to create one_time_ticket for $recipient, service modindex/$name");
}else{
&do_log('notice',"xxxxxxxxxxxxxx ticket : $param->{'one_time_ticket'}");
}
&tt2::allow_absolute_path();
unless ($self->send_file('moderate', \@rcpt, $self->{'domain'}, $param)) {
&do_log('notice',"Unable to send template 'moderate' to $self->{'name'} editors");
unless ($self->send_file('moderate', $recipient, $self->{'domain'}, $param)) {
&do_log('notice',"Unable to send template 'moderate' to $recipient");
return undef;
}
}
# Old code 5.4 and before to be removed in 5.5
# if ($encrypt eq 'smime_crypted') {
#
# ## Send a different crypted message to each moderator
# foreach my $recipient (@rcpt) {
#
# # create a one time ticket that will be used as un md5 URL credential
# $param->{'one_time_ticket'} = &Auth::create_one_time_ticket($in{'email'},$robot,'modindex/'.$name,$ip)
#
# ## $msg->body_as_string respecte-t-il le Base64 ??
# my $cryptedmsg = &tools::smime_encrypt($msg->head, $msg->body_as_string, $recipient);
# unless ($cryptedmsg) {
# &do_log('notice', 'Failed encrypted message for moderator');
# # xxxx send a generic error message : X509 cert missing
# return undef;
# }
#
# my $crypted_file = $Conf{'tmpdir'}.'/'.$self->get_list_id().'.moderate.'.$$;
# unless (open CRYPTED, ">$crypted_file") {
# &do_log('notice', 'Could not create file %s', $crypted_file);
# return undef;
# }
# print CRYPTED $cryptedmsg;
# close CRYPTED;
#
#
# $param->{'msg_path'} = $crypted_file;
#
# &tt2::allow_absolute_path();
# unless ($self->send_file('moderate', $recipient, $self->{'domain'}, $param)) {
# &do_log('notice',"Unable to send template 'moderate' to $recipient");
# return undef;
# }
# }
# }else{
# $param->{'msg_path'} = $file;
#
# &tt2::allow_absolute_path();
# unless ($self->send_file('moderate', \@rcpt, $self->{'domain'}, $param)) {
# &do_log('notice',"Unable to send template 'moderate' to $self->{'name'} editors");
# return undef;
# }
# }
return $modkey;
}
......@@ -4581,9 +4620,9 @@ sub get_user_db {
if ($Conf{'db_type'} eq 'Oracle') {
## "AS" not supported by Oracle
$statement = sprintf "SELECT email_user \"email\", gecos_user \"gecos\", password_user \"password\", cookie_delay_user \"cookie_delay\", lang_user \"lang\", attributes_user \"attributes\" %s,data_user \"data\" FROM user_table WHERE email_user = %s ", $additional, $dbh->quote($who);
$statement = sprintf "SELECT email_user \"email\", gecos_user \"gecos\", password_user \"password\", cookie_delay_user \"cookie_delay\", lang_user \"lang\", attributes_user \"attributes\" %s,data_user \"data\", last_login_date_user \"last_login_date\", last_login_host_user \"last_login_host\" FROM user_table WHERE email_user = %s ", $additional, $dbh->quote($who);
}else {
$statement = sprintf "SELECT email_user AS email, gecos_user AS gecos, password_user AS password, cookie_delay_user AS cookie_delay, lang_user AS lang %s, attributes_user AS attributes, data_user AS data FROM user_table WHERE email_user = %s ", $additional, $dbh->quote($who);
$statement = sprintf "SELECT email_user AS email, gecos_user AS gecos, password_user AS password, cookie_delay_user AS cookie_delay, lang_user AS lang %s, attributes_user AS attributes, data_user AS data, last_login_date_user AS last_login_date, last_login_host_user AS last_login_host FROM user_table WHERE email_user = %s ", $additional, $dbh->quote($who);
}
push @sth_stack, $sth;
......@@ -6162,7 +6201,7 @@ sub update_admin_user {
## Sets new values for the given user in the Database
sub update_user_db {
my($who, $values) = @_;
do_log('debug2', 'List::update_user_db(%s)', $who);
do_log('debug', 'List::update_user_db(%s)', $who);
$who = &tools::clean_email($who);
......@@ -6171,8 +6210,8 @@ sub update_user_db {
return undef;
}
## encrypt password
$values->{'password'} = &tools::crypt_password($values->{'password'}) if ($values->{'password'});
## use md5 fingerprint to store password
$values->{'password'} = &Auth::password_fingerprint($values->{'password'}) if ($values->{'password'});
my ($field, $value);
......@@ -6185,7 +6224,9 @@ sub update_user_db {
lang => 'lang_user',
attributes => 'attributes_user',
email => 'email_user',
data => 'data_user'
data => 'data_user',
last_login_date => 'last_login_date_user',
last_login_host => 'last_login_host_user'
);
## Check database connection
......@@ -6193,11 +6234,6 @@ sub update_user_db {
return undef unless &db_connect();
}
## Crypt password if it was not crypted
if ($values->{'password'} && ($values->{'password'} !~ /^crypt/)) {
$values->{'password'} = &tools::crypt_password($values->{'password'});
}
## Update each table
my @set_list;
while (($field, $value) = each %{$values}) {
......
......@@ -706,7 +706,14 @@ sub probe_db {
'status_logs' => 'varchar(10)',
'error_type_logs' => 'varchar(150)',
'client_logs' => 'varchar(100)',
'daemon_logs' => 'varchar(10)'
'daemon_logs' => 'varchar(10)'},
'one_time_ticket_table' => {'ticket_one_time_ticket' => 'varchar(30)',
'email_one_time_ticket' => 'varchar(100)',
'robot_one_time_ticket' => 'varchar(80)',
'date_one_time_ticket' => 'int(11)',
'data_one_time_ticket' => 'varchar(200)',
'remote_addr_one_time_ticket' => 'varchar(60)',
'status_addr_one_time_ticket' => 'varchar(60)'
},
},
'SQLite' => {'user_table' => {'email_user' => 'varchar(100)',
......@@ -751,7 +758,7 @@ sub probe_db {
'robot_netidmap' => 'varchar(80)'},
'session_table' => {'id_session' => 'varchar(30)',
'start_date_session' => 'integer',
'date_session' => 'int(11)',
'date_session' => 'integer',
'remote_addr_session' => 'varchar(60)',
'robot_session' => 'varchar(80)',
'email_session' => 'varchar(100)',
......@@ -769,7 +776,14 @@ sub probe_db {
'status_logs' => 'varchar(10)',
'error_type_logs' => 'varchar(150)',
'client_logs' => 'varchar(100)',
'daemon_logs' => 'varchar(10)'
'daemon_logs' => 'varchar(10)'},
'one_time_ticket_table' => {'ticket_one_time_ticket' => 'varchar(30)',
'robot_one_time_ticket' => 'varchar(80)',
'email_one_time_ticket' => 'varchar(100)',
'date_one_time_ticket' => 'integer',
'data_one_time_ticket' => 'varchar(200)',
'remote_addr_one_time_ticket' => 'varchar(60)',
'status_addr_one_time_ticket' => 'varchar(60)'
},
},
......@@ -803,7 +817,8 @@ sub probe_db {
'admin_table' => ['robot_admin','list_admin','role_admin','user_admin'],
'netidmap_table' => ['netid_netidmap','serviceid_netidmap','robot_netidmap'],
'logs_table' => ['id_logs'],
'session_table' => ['id_session']
'session_table' => ['id_session'],
'one_time_ticket_table' => ['ticket_one_time_ticket']
);
## List the required INDEXES
......@@ -1444,5 +1459,71 @@ sub to_utf8 {
return $total;
}
# md5_encode_password : Version later than 5.4 uses md5 fingerprint instead of symetric crypto to store password.
# This require to rewrite paassword in database. This upgrade IS NOT REVERSIBLE
sub md5_encode_password {
my $total = 0;
&do_log('notice', 'Upgrade::md5_encode_password() recoding password using md5 fingerprint');
unless (&List::check_db_connect()) {
return undef;
}
my $dbh = &List::db_get_handler();
my $sth;
unless ($sth = $dbh->prepare("SELECT email_user,password_user from user_table")) {
do_log('err','Unable to prepare SQL statement : %s', $dbh->errstr);
return undef;
}
unless ($sth->execute) {
do_log('err','Unable to execute SQL statement : %s', $dbh->errstr);
return undef;
}
my $total = 0;
my $total_md5 = 0 ;
while (my $user = $sth->fetchrow_hashref) {
my $clear_password ;
if ($user->{'password_user'} =~ /^[1-9a-f]{32}/){
do_log('info','password from %s allready encoded as md5 fingerprint',$user->{'password_user'});
$total_md5++ ;
next;
}
if ($user->{'password_user'} =~ /^init(.*)$/) {
$clear_password = $1;
}
elsif ($user->{'password_user'} =~ /^crypt.(.*)$/) {
$clear_password = &tools::decrypt_password($user->{'password_user'});
}else{
$clear_password = $user->{'password_user'};
}
$total++;
## Updating Db
my $statement = sprintf "UPDATE user_table SET password_user='%s' WHERE (email_user='%s')", &tools::md5_fingerprint($clear_password), $user->{'email_user'} ;
unless ($dbh->do($statement)) {
do_log('err','Unable to execute SQL statement "%s" : %s', $statement, $dbh->errstr);
return undef;
}
}
$sth->finish();
do_log('info',"Updating password storage in table user_table using md5 for %d users",$total) ;
if ($total_md5) {
do_log('info',"Found in table user %d password stored using md5, did you run Sympa before upgrading ?", $total_md5 );
}
return $total;
}
## Packages must return true.
1;
title.gettext daily delete tickets older than sympa.conf/one_time_ticket_table_ttl parameter
/ACTION
purge_one_time_ticket_table ()
next ([execution_date]+1d, ACTION)
......@@ -99,4 +99,17 @@ CREATE TABLE session_table (
data_session varchar2(500),
CONSTRAINT ind_session PRIMARY KEY (id_session)
);
CREATE TABLE one_time_ticket_table (
ticket_one_time_ticket varchar2(30),
robot_one_time_ticket varchar2(80),
email_one_time_ticket varchar2(100),
dat_one_time_ticket number,
data_one_time_ticket varchar2(200),
remote_addr_one_time_ticket varchar2(60),
status_addr_one_time_ticket varchar2(60),
CONSTRAINT ind_one_time_ticket PRIMARY KEY (ticket_one_time_ticket)
);
!
......@@ -104,3 +104,17 @@ CREATE TABLE session_table (
CONSTRAINT ind_session PRIMARY KEY (id_session)
);
CREATE INDEX session_idx ON session_table(id_session);
DROP TABLE one_time_ticket_table;
CREATE TABLE one_time_ticket_table (
ticket_one_time_ticket varchar(30),
robot_one_time_ticket varchar(80),
email_one_time_ticket varchar(100),
dat_one_time_ticket bigint,
data_one_time_ticket varchar(200),
remote_addr_one_time_ticket varchar(60),
status_addr_one_time_ticket varchar(60),
CONSTRAINT ind_one_time_ticket PRIMARY KEY (ticket_one_time_ticket)
);
CREATE INDEX one_time_ticket_idx ON one_time_ticket_table(ticket_one_time_ticket);
\ No newline at end of file
......@@ -90,3 +90,14 @@ CREATE TABLE session_table (
)
CREATE INDEX session_idx ON session_table(id_session)
CREATE TABLE one_time_ticket_table (
ticket_one_time_ticket varchar(30),
robot_one_time_ticket varchar(80),
email_one_time_ticket varchar(100),
dat_one_time_ticket integer,
data_one_time_ticket varchar(200),
remote_addr_one_time_ticket varchar(60),
status_addr_one_time_ticket varchar(60),
PRIMARY KEY (ticket_one_time_ticket)
);
CREATE INDEX one_time_ticket_idx ON one_time_ticket_table_table(ticket_one_time_ticket);
\ No newline at end of file
......@@ -141,3 +141,18 @@ go
create index id_session_fk on session_table (id_session)
go
CREATE TABLE one_time_ticket_table (
ticket_one_time_ticket varchar(30),
robot_one_time_ticket varchar(80),
email_one_time_ticket varchar(100),
dat_one_time_ticket int(11),
data_one_time_ticket varchar(200),
remote_addr_one_time_ticket varchar(60),
status_addr_one_time_ticket varchar(60)
constraint ind_one_time_ticket primary key (ticket_one_time_ticket)
)
go
create index ticket_one_time_ticket_fk on one_time_ticket_table (ticket_one_time_ticket)
go
......@@ -93,3 +93,14 @@ CREATE TABLE session_table (
data_session text,
PRIMARY KEY (id_session)
);
CREATE TABLE one_time_ticket_table (
ticket_one_time_ticket varchar(30),
robot_one_time_ticket varchar(80),
email_one_time_ticket varchar(100),
dat_one_time_ticket int(11),
data_one_time_ticket varchar(200),
remote_addr_one_time_ticket varchar(60),
status_addr_one_time_ticket varchar(60),
PRIMARY KEY (ticket_one_time_ticket)
);
......@@ -33,6 +33,7 @@ use File::Path;
use Commands;
use Conf;
use Auth;
use SympaSession;
use Language;
use Log;
use Version;
......@@ -83,6 +84,7 @@ Options:
--dump=list\@dom|ALL : dumps subscribers
--make_alias_file : create file in /tmp with all aliases (usefull when aliases.tpl is changed)
--lowercase : lowercase email addresses in database
--md5_encode_password : rewrite password in database using md5 fingerprint. YOU CAN'T UNDO unless you save this table first
--create_list --robot=robot_name --input_file=/path/to/file.xml
: create a list with the xml file under robot_name
--instantiate_family=family_name --robot=robot_name --input_file=/path/to/file.xml [--close_unknown] [--quiet]
......@@ -119,7 +121,7 @@ encryption.
## Check --dump option
my %options;
unless (&GetOptions(\%main::options, 'dump=s', 'debug|d', ,'log_level=s','foreground', 'service=s','config|f=s',
'lang|l=s', 'mail|m', 'keepcopy|k=s', 'help', 'version', 'import=s','make_alias_file','lowercase',
'lang|l=s', 'mail|m', 'keepcopy|k=s', 'help', 'version', 'import=s','make_alias_file','lowercase','md5_encode_password',
'close_list=s','purge_list=s','create_list','instantiate_family=s','robot=s','add_list=s','modify_list=s','close_family=s','md5_digest=s',
'input_file=s','sync_include=s','upgrade','from=s','to=s','reload_list_config','list=s','quiet','close_unknown')) {
&fatal_err("Unknown options.");
......@@ -135,6 +137,7 @@ $main::options{'batch'} = 1 if ($main::options{'dump'} ||
$main::options{'import'} ||
$main::options{'make_alias_file'} ||
$main::options{'lowercase'} ||
$main::options{'md5_encode_password'} ||
$main::options{'close_list'} ||
$main::options{'purge_list'} ||
$main::options{'create_list'} ||
......@@ -462,6 +465,17 @@ if ($main::options{'dump'}) {
printf STDERR "Total imported subscribers: %d\n", $total;
exit 0;
}elsif ($main::options{'md5_encode_password'}) {
unless ($List::use_db) {
&fatal_err("You don't have a database setup, can't lowercase email addresses");
}
my $total=&Upgrade::md5_encode_password();
printf STDERR "Total password re-encoded using md5: %d\n", $total;
exit 0;
}elsif ($main::options{'lowercase'}) {
unless ($List::use_db) {
......
......@@ -99,7 +99,7 @@ unless ($main::options{'debug'} || $main::options{'foreground'}) {
open(STDERR, ">> /dev/null");
open(STDOUT, ">> /dev/null");
if (open(TTY, "/dev/tty")) {
ioctl(TTY, 0x20007471, 0); # XXX s/b &TIOCNOTTY
ioctl(TTY, 0x20007471, 0); # s/b &TIOCNOTTY
# ioctl(TTY, &TIOCNOTTY, 0);
close(TTY);
}
......@@ -173,6 +173,7 @@ my %global_models = (#'crl_update_task' => 'crl_update',
'purge_user_table_task' => 'purge_user_table',
'purge_logs_table_task' => 'purge_logs_table',
'purge_session_table_task' => 'purge_session_table',
'purge_one_time_ticket_table_task' => 'purge_one_time_ticket_table',
'purge_orphan_bounces_task' => 'purge_orphan_bounces',
'eval_bouncers_task' => 'eval_bouncers',
'process_bouncers_task' =>'process_bouncers',
......@@ -210,6 +211,7 @@ my %commands = ('next' => ['date', '\w*'],
'purge_user_table' => [],
'purge_logs_table' => [],
'purge_session_table' => [],
'purge_one_time_ticket_table' => [],
'purge_orphan_bounces' => [],
'eval_bouncers' => [],
'process_bouncers' => []
......@@ -266,7 +268,7 @@ while (!$end) {
'execution_date' => 'execution_date');
## global tasks
foreach my $key (keys %global_models) {
foreach my $key (keys %global_models) {
unless ($used_models{$global_models{$key}}) {
if ($Conf{$key}) {
my %data = %default_data; # hash of datas necessary to the creation of tasks
......@@ -802,6 +804,7 @@ sub cmd_process {
return purge_user_table ($task, \%context) if ($command eq 'purge_user_table');
return purge_logs_table ($task, \%context) if ($command eq 'purge_logs_table');
return purge_session_table ($task, \%context) if ($command eq 'purge_session_table');
return purge_one_time_ticket_table ($task, \%context) if ($command eq 'purge_one_time_ticket_table');
return sync_include($task, \%context) if ($command eq 'sync_include');
return purge_orphan_bounces ($task, \%context) if ($command eq 'purge_orphan_bounces');
return eval_bouncers ($task, \%context) if ($command eq 'eval_bouncers');
......@@ -1125,6 +1128,19 @@ sub purge_session_table {
return 1;
}
## remove one time ticket table if older than $Conf{'one_time_ticket_table_ttl'}
sub purge_one_time_ticket_table {
do_log('info','task_manager::purge_one_time_ticket_table()');
my $removed = &SympaSession::purge_old_tickets('*');
unless(defined $removed) {
&do_log('err','&SympaSession::purge_old_tickets(): Failed to remove old tickets');
return undef;
}
&do_log('notice','purge_one_time_ticket_table(): %s row removed in one_time_ticket_table',$removed);
return 1;
}
sub purge_user_table {
my ($task, $Rarguments, $context) = @_;
do_log('debug2','purge_user_table()');
......
......@@ -8,13 +8,6 @@ You will need this password to perform privileged operations.[%END%]
<input type="hidden" name="previous_action" value="[% previous_action %]" />
<input type="hidden" name="previous_list" value="[% previous_list %]" />
[% IF init_passwd %]
<input type="hidden" name="passwd" value="[% user.password %]" />
[% ELSE %]
<label for="passwd">[%|loc%]Current password :[%END%]</label>
<input id="passwd" type="password" name="passwd" size="15" />
[% END %]
<br /><br /><label for="newpasswd1">[%|loc%]New password :[%END%]</label><input id="newpasswd1" type="password" name="newpasswd1" size="15" /><br />
<br /><label for="newpasswd2">[%|loc%]New password again :[%END%]</label><input id="newpasswd2" type="password" name="newpasswd2" size="15" /><br />
<br /><input class="MainMenuLinks" type="submit" name="action_setpasswd" value="[%|loc%]Submit[%END%]" />
......
......@@ -18,7 +18,9 @@
[% ELSIF is_subscriber %][%|loc%]Subscriber[%END%]
[% END %]
</div>
[% IF last_login_date %]
<span>[%|loc(last_login_host,last_login_date)%]last login from %1 <br />(%2)</span>[%END%]
[%END%]
[% IF auth_method == 'md5' %]
<form class="text_center" action="[% path_cgi %]" method="post">
......@@ -75,7 +77,7 @@
<input type="hidden" name="action" value="login" />
<label for="email_login">[%|loc%]email address[%END%] :</label><br />
<input type="text" name="email" id="email_login" size="18" value="[% init_email %]" /><br />
<input type="text" name="email" id="email_login" size="28" value="[% unauthenticated_email %]" /><br />
<label for="passwd" >[%|loc%]password[%END%] :</label><br />
<input type="password" name="passwd" id="passwd" size="8" /> &nbsp;&nbsp;
<input class="MainMenuLinks" type="submit" name="action_login" value="[%|loc%]Login[%END%]" />
......@@ -84,10 +86,14 @@
</div>
<br />
[% IF use_passwd == '1' %]
[% IF authentication_info_url %]
<a class="menuLinks" href="[%conf.authentication_info.url%]">[%|loc%]Authentication help[% END %]</a><br />
[% ELSE %]
<a class="menuLinks" href="[% path_cgi %]/sendpasswd/[% escaped_init_email %]">[%|loc%]First login ?[%END%]</a><br />
<a class="menuLinks" href="[% path_cgi %]/remindpasswd">[%|loc%]Lost password ?[%END%]</a>
[% END %]
[% END %]
[% END %]
</div><!-- end div=MenuBlock -->
......
<!-- RCS Identication ; $Revision$ ; $Date$ -->
<br />
[% IF password_sent %]
[%|loc(init_email)%]Your password has been sent to your email address %1.<br />Please check your e-mail box to provide your password below.[%END%]
<br />
[% END %]
[% IF action == 'loginrequest' %]
[%|loc%]You need to login to access your custom WWSympa environment or to perform a privileged operation (one that requires your email address).[%END%]
[%|loc%]In order to perform a privileged operation (one that requires your email address), you need to login.[%END%]
[% ELSE %]
[%|loc%]Most mailing list features require your email. Some mailing lists are hidden to unidentified persons.<br />
In order to benefit from the full services provided by this server, you probably need to identify yourself first.[%END%] <br />
......
<!-- begin notice.tt2 -->
<div class="ContentBlock"> <strong>