Commit ac375bca authored by david.verdin's avatar david.verdin
Browse files

[feature] max_wrong_password robot parameter (default 19) now Sympa block...

[feature] max_wrong_password robot parameter (default 19) now Sympa block account after this number of wrong account submition is reached. Needed to block brut force attack. 



git-svn-id: https://subversion.renater.fr/sympa/trunk@6355 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent 83af7344
......@@ -254,11 +254,12 @@ my %list_cache;
## DB fields with numeric type
## We should not do quote() for these while inserting data
my %numeric_field = ('cookie_delay_user' => 1,
'bounce_score_subscriber' => 1,
'subscribed_subscriber' => 1,
'included_subscriber' => 1,
'subscribed_admin' => 1,
'included_admin' => 1,
'bounce_score_subscriber' => 1,
'subscribed_subscriber' => 1,
'included_subscriber' => 1,
'subscribed_admin' => 1,
'included_admin' => 1,
'wrong_login_count' => 1,
);
## List parameters defaults
......@@ -4786,7 +4787,7 @@ sub get_user_db {
$additional = ',' . $Conf::Conf{'db_additional_user_fields'};
}
$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);
$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, wrong_login_count_user AS wrong_login_count, last_login_host_user AS last_login_host FROM user_table WHERE email_user = %s ", $additional, $dbh->quote($who);
push @sth_stack, $sth;
......@@ -6616,7 +6617,8 @@ sub update_user_db {
email => 'email_user',
data => 'data_user',
last_login_date => 'last_login_date_user',
last_login_host => 'last_login_host_user'
last_login_host => 'last_login_host_user',
wrong_login_count => 'wrong_login_count_user'
);
## Check database connection
......@@ -6626,8 +6628,12 @@ sub update_user_db {
## Update each table
my @set_list;
while (($field, $value) = each %{$values}) {
next unless ($map_field{$field});
unless ($map_field{$field}) {
do_log('error',"unkown field $field in map_field internal error");
next;
};
my $set;
if ($numeric_field{$map_field{$field}}) {
......@@ -6639,11 +6645,13 @@ sub update_user_db {
push @set_list, $set;
}
return undef
unless @set_list;
return undef unless @set_list;
## Update field
# my $statement2 = sprintf "UPDATE user_table SET %s WHERE (email_user=%s)",$setlist,dbh->quote($who);
# do_log('trace', 'statement2 : %s', $statement2);
$statement = sprintf "UPDATE user_table SET %s WHERE (email_user=%s)"
, join(',', @set_list), $dbh->quote($who);
......
......@@ -1321,6 +1321,12 @@ our @params = (
name => 'alias_manager',
default => Sympa::Constants::SBINDIR . '/alias_manager.pl',
},
{
name => 'max_wrong_password',
default => '19',
vhost => '1',
file => 'sympa.conf',
},
{
name => 'dkim_feature',
default => 'off',
......
......@@ -5,6 +5,8 @@
[%|loc%]You requested an account creation on this list server.[%END%]
[% ELSIF login_error == 'wrong_password' %]
[%|loc%]The password you submitted is wrong. Maybe you forgot it?[%END%]
[% ELSIF login_error == 'password_reset' %]
[%|loc%]Too many wrong password were sumitted for this account. Your account as been blocked in order to protect you agains attacks. You must renew renew your password in order to login.[%END%]
[% ELSIF login_error == 'missing_password' %]
[%|loc%]You missed the password, please submit again. Maybe you forgot it?[%END%]
[% ELSIF login_error == 'ticket_sent' %]
......
......@@ -55,18 +55,17 @@ sub password_fingerprint{
if( &tools::valid_email($auth)) {
return &authentication($robot, $auth,$pwd);
}else{
## This is an UID
foreach my $ldap (@{$Conf{'auth_services'}{$robot}}){
# only ldap service are to be applied here
next unless ($ldap->{'auth_type'} eq 'ldap');
$canonic = &ldap_authentication($robot, $ldap, $auth,$pwd,'uid_filter');
last if ($canonic); ## Stop at first match
}
if ($canonic){
foreach my $ldap (@{$Conf{'auth_services'}{$robot}}){
# only ldap service are to be applied here
next unless ($ldap->{'auth_type'} eq 'ldap');
$canonic = &ldap_authentication($robot, $ldap, $auth,$pwd,'uid_filter');
last if ($canonic); ## Stop at first match
}
if ($canonic){
unless($user = &List::get_user_db($canonic)){
$user = {'email' => $canonic};
}
......@@ -118,6 +117,13 @@ sub authentication {
$user->{'password'} = '';
}
if ($user->{'wrong_login_count'} > &Conf::get_robot_conf($robot, 'max_wrong_password')){
# too many wrong login attemp
&List::update_user_db($email,{wrong_login_count => $user->{'wrong_login_count'}+1}) ;
&report::reject_report_web('user','too_many_wrong_login',{}) unless ($ENV{'SYMPA_SOAP'});
&do_log('err','login is blocked : too many wrong password submission for %s', $email);
return undef;
}
foreach my $auth_service (@{$Conf{'auth_services'}{$robot}}){
next if ($auth_service->{'auth_type'} eq 'authentication_info_url');
next if ($email !~ /$auth_service->{'regexp'}/i);
......@@ -126,9 +132,10 @@ sub authentication {
## Only 'user_table' and 'ldap' backends will need that Sympa collects the user passwords
## Other backends are Single Sign-On solutions
if ($auth_service->{'auth_type'} eq 'user_table') {
my $fingerprint = &password_fingerprint ($pwd);
my $fingerprint = &password_fingerprint ($pwd);
if ($fingerprint eq $user->{'password'}) {
&List::update_user_db($email,{wrong_login_count => 0}) ;
return {'user' => $user,
'auth' => 'classic',
'alt_emails' => {$email => 'classic'}
......@@ -139,6 +146,7 @@ sub authentication {
unless($user = &List::get_user_db($canonic)){
$user = {'email' => $canonic};
}
&List::update_user_db($canonic,{wrong_login_count => 0}) ;
return {'user' => $user,
'auth' => 'ldap',
'alt_emails' => {$email => 'ldap'}
......@@ -147,22 +155,9 @@ sub authentication {
}
}
## If web context and password has never been changed
## Then prompt user
# xxxxxxxxxxxxx to be removed
# unless ($ENV{'SYMPA_SOAP'}) {
# foreach my $auth_service (@{$Conf{'auth_services'}{$robot}}){
# next unless ($email !~ /$auth_service->{'regexp'}/i);
# next unless (($email =~ /$auth_service->{'negative_regexp'}/i)&&($auth_service->{'negative_regexp'}));
# if ($auth_service->{'auth_type'} eq 'user_table') {
# if ($user->{'password'} =~ /^init/i) {
# &report::reject_report_web('user','init_passwd',{});
# last;
# }
# }
# }
# }
# increment wrong login count.
&List::update_user_db($email,{wrong_login_count =>$user->{'wrong_login_count'}+1}) ;
&report::reject_report_web('user','incorrect_passwd',{}) unless ($ENV{'SYMPA_SOAP'});
&do_log('err','authentication: incorrect password for user %s', $email);
......
......@@ -2937,7 +2937,6 @@ sub do_ticket {
}
}
 
##authentication of the sender
my $data;
unless($data = &Auth::check_auth($robot, $in{'email'},$in{'passwd'})){
&do_log('notice', "Authentication failed\n");
......@@ -2945,9 +2944,12 @@ sub do_ticket {
'target_email' => $in{'email'},
'status' => 'error',
'error_type' => 'authentication'});
$param->{'login_error'} = 'wrong_password';
my $unauthenticated_user = &List::get_user_db($in{'email'});
if ($unauthenticated_user->{'wrong_login_count'} > &Conf::get_robot_conf($robot, 'max_wrong_password')){
$param->{'login_error'} = 'password_reset';
}else{
$param->{'login_error'} = 'wrong_password';
}
if ($in{'previous_action'}) {
delete $in{'passwd'};
$in{'list'} = $in{'previous_list'};
......@@ -2966,7 +2968,7 @@ sub do_ticket {
$session->{'email'} = $email;
$session->{'unauthenticated_email'} = '';
 
&List::update_user_db($param->{'user'}{'email'},{last_login_date =>time(),last_login_host=>$ip }) ;
&List::update_user_db($param->{'user'}{'email'},{last_login_date =>time(),last_login_host=>$ip, wrong_login_count =>0}) ;
## Set alt_email
if ($data->{'alt_emails'}) {
......@@ -3027,7 +3029,6 @@ sub do_ticket {
 
}
 
## Login WWSympa
sub do_sso_login {
&wwslog('info', 'do_sso_login(%s)', $in{'auth_service_name'});
......@@ -5127,7 +5128,8 @@ sub do_subrequest {
}
 
if (&List::is_user_db($param->{'user'}{'email'})) {
unless ( &List::update_user_db($param->{'user'}{'email'}, {'password' => $in{'newpasswd1'}} )) {
unless ( &List::update_user_db($param->{'user'}{'email'}, {'password' => $in{'newpasswd1'},'wrong_login_count' => 0} )) {
&report::reject_report_web('intern','update_user_db_failed',{'user'=>$param->{'user'}{'email'}},$param->{'action'},'',$param->{'user'}{'email'},$robot);
&wwslog('info','do_setpasswd: update failed');
&web_db_log({'status' => 'error',
......@@ -5135,8 +5137,10 @@ sub do_subrequest {
return undef;
}
}else {
unless ( &List::add_user_db({'email' => $param->{'user'}{'email'},
'password' => $in{'newpasswd1'}} )) {
'password' => $in{'newpasswd1'},
'wrong_login_count' => 0} )) {
&report::reject_report_web('intern','add_user_db_failed',{'user'=>$param->{'user'}{'email'}},$param->{'action'},'',$param->{'user'}{'email'},$robot);
&wwslog('info','do_setpasswd: update failed');
&web_db_log({'status' => 'error',
......
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