[LEMONLDAP-217] add a captcha feature to the portal
This commit is contained in:
parent
208b9f0f07
commit
5264202231
3
Makefile
3
Makefile
|
@ -317,6 +317,9 @@ install_manager_site: install_conf_dir
|
|||
|
||||
install_portal_site: install_conf_dir
|
||||
# Portal install
|
||||
@mkdir -p $(PORTALDIR)/captcha_output/
|
||||
@mkdir -p $(DATADIR)/captcha/data
|
||||
@chmod -R 777 $(DATADIR)/captcha $(PORTALDIR)/captcha_output/
|
||||
@install -v -d $(RPORTALDIR) $(RPORTALSKINSDIR) \
|
||||
$(RPORTALDIR)/skins/ \
|
||||
$(RCRONDIR) $(RCONFDIR)
|
||||
|
|
|
@ -93,6 +93,8 @@ sub portalTab {
|
|||
73 => 'PORTAL_RADIUSCONNECTFAILED',
|
||||
74 => 'PORTAL_MUST_SUPPLY_OLD_PASSWORD',
|
||||
75 => 'PORTAL_FORBIDDENIP',
|
||||
76 => 'PORTAL_CAPTCHAERROR',
|
||||
77 => 'PORTAL_CAPTCHAEMPTY',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ WriteMakefile(
|
|||
},
|
||||
PREREQ_PM => {
|
||||
'Apache::Session' => 0,
|
||||
'CGI' => 3.08,
|
||||
'Authen::Captcha' => 0,
|
||||
'CGI' => 3.08,
|
||||
'File::Basename' => 0,
|
||||
'HTML::Template' => 0,
|
||||
'Lemonldap::NG::Common' => '1.2.0',
|
||||
|
|
|
@ -65,7 +65,16 @@ if (
|
|||
DISPLAY_MAILSENT => 0,
|
||||
DISPLAY_PASSWORD_FORM => 0,
|
||||
);
|
||||
}
|
||||
|
||||
# Display captcha if it's enabled
|
||||
if ( $portal->{captcha_enabled} ) {
|
||||
$template->param(
|
||||
CAPTCHA_IMG => $portal->{captcha_img},
|
||||
CAPTCHA_CODE => $portal->{captcha_img},
|
||||
CAPTCHA_SIZE => $portal->{captcha_size}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# Display mail confirmation resent form
|
||||
if ( $portal->{error} == PE_MAILCONFIRMATION_ALREADY_SENT ) {
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
<tr><th><lang en="Mail" fr="Adresse mail"/></th>
|
||||
<td><input name="mail" type="text" value="<TMPL_VAR NAME="MAIL">"/></td>
|
||||
</tr>
|
||||
|
||||
<img src="<TMPL_VAR NAME=CAPTCHA_IMG>" />
|
||||
<lang en="Enter the captcha: " fr="Entrez le captcha: " />
|
||||
<input type="text" NAME="captcha_user_code" size="<TMPL_VAR NAME=CAPTCHA_SIZE>" />
|
||||
<input type="hidden" NAME="captcha_code" value="<TMPL_VAR NAME=CAPTCHA_CODE>" />
|
||||
|
||||
<tr><td colspan="2">
|
||||
<div class="buttons">
|
||||
<button type="submit" class="positive">
|
||||
|
|
|
@ -203,6 +203,16 @@ sub display {
|
|||
LOGIN_INFO => $self->loginInfo(),
|
||||
);
|
||||
|
||||
# Display captcha if it's enabled
|
||||
if ( $self->{captcha_enabled} ) {
|
||||
%templateParams = (
|
||||
%templateParams,
|
||||
CAPTCHA_IMG => $self->{captcha_img},
|
||||
CAPTCHA_CODE => $self->{captcha_code},
|
||||
CAPTCHA_SIZE => $self->{captcha_size}
|
||||
);
|
||||
}
|
||||
|
||||
# Show password form if password policy error
|
||||
if (
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ use POSIX;
|
|||
# - extractMailInfo
|
||||
# - getMailUser
|
||||
# - storeMailSession
|
||||
# - initCaptcha
|
||||
# - checkCaptcha
|
||||
# - sendConfirmationMail
|
||||
# - changePassword
|
||||
# - sendPasswordMail
|
||||
|
@ -50,15 +52,17 @@ sub process {
|
|||
|
||||
$self->{error} = $self->_subProcess(
|
||||
qw(smtpInit userDBInit passwordDBInit extractMailInfo
|
||||
getMailUser setSessionInfo setMacros setGroups
|
||||
setPersistentSessionInfo setLocalGroups storeMailSession
|
||||
sendConfirmationMail changePassword sendPasswordMail)
|
||||
getMailUser initCaptcha checkCaptcha setSessionInfo
|
||||
setMacros setGroups setPersistentSessionInfo setLocalGroups
|
||||
storeMailSession sendConfirmationMail changePassword sendPasswordMail)
|
||||
);
|
||||
|
||||
return (
|
||||
(
|
||||
$self->{error} <= 0
|
||||
or $self->{error} == PE_PASSWORD_OK
|
||||
or $self->{error} == PE_CAPTCHAERROR
|
||||
or $self->{error} == PE_CAPTCHAEMPTY
|
||||
or $self->{error} == PE_MAILCONFIRMOK
|
||||
or $self->{error} == PE_MAILOK
|
||||
) ? 0 : 1
|
||||
|
|
|
@ -12,6 +12,7 @@ use Exporter 'import';
|
|||
|
||||
use warnings;
|
||||
use MIME::Base64;
|
||||
use Authen::Captcha;
|
||||
use Lemonldap::NG::Common::CGI;
|
||||
use CGI::Cookie;
|
||||
require POSIX;
|
||||
|
@ -145,6 +146,8 @@ use constant {
|
|||
PE_RADIUSCONNECTFAILED => 73,
|
||||
PE_MUST_SUPPLY_OLD_PASSWORD => 74,
|
||||
PE_FORBIDDENIP => 75,
|
||||
PE_CAPTCHAERROR => 76,
|
||||
PE_CAPTCHAEMPTY => 77,
|
||||
|
||||
# Portal messages
|
||||
PM_USER => 0,
|
||||
|
@ -193,7 +196,7 @@ our @EXPORT = qw( PE_IMG_NOK PE_IMG_OK PE_INFO PE_REDIRECT PE_DONE PE_OK
|
|||
PE_MISSINGREQATTR PE_BADPARTNER PE_MAILCONFIRMATION_ALREADY_SENT
|
||||
PE_PASSWORDFORMEMPTY PE_CAS_SERVICE_NOT_ALLOWED PE_MAILFIRSTACCESS
|
||||
PE_MAILNOTFOUND PE_PASSWORDFIRSTACCESS PE_MAILCONFIRMOK
|
||||
PE_MUST_SUPPLY_OLD_PASSWORD PE_FORBIDDENIP
|
||||
PE_MUST_SUPPLY_OLD_PASSWORD PE_FORBIDDENIP PE_CAPTCHAERROR PE_CAPTCHAEMPTY
|
||||
PM_USER PM_DATE PM_IP PM_SESSIONS_DELETED PM_OTHER_SESSIONS
|
||||
PM_REMOVE_OTHER_SESSIONS PM_PP_GRACE PM_PP_EXP_WARNING
|
||||
PM_SAML_IDPSELECT PM_SAML_IDPCHOOSEN PM_REMEMBERCHOICE PM_SAML_SPLOGOUT
|
||||
|
@ -459,7 +462,13 @@ sub new {
|
|||
'(' . join( '|', split( /\s+/, $self->{trustedDomains} ) ) . ')';
|
||||
$self->{trustedDomains} =~ s/\./\\./g;
|
||||
}
|
||||
|
||||
|
||||
# init the captcha feature if it's enabled
|
||||
if ( $self->{captcha_enabled} ) {
|
||||
eval $self->initCaptcha();
|
||||
$self->{captcha_initialized} = 1 unless $@ ;
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
@ -636,6 +645,12 @@ sub setDefaultValues {
|
|||
$self->{ldapPasswordResetAttribute} ||= "pwdReset";
|
||||
$self->{ldapPasswordResetAttributeValue} ||= "TRUE";
|
||||
$self->{mailOnPasswordChange} ||= 0;
|
||||
|
||||
# Captcha parameters
|
||||
$self->{captcha_enabled} = 0;
|
||||
$self->{captcha_size} = 6;
|
||||
$self->{captcha_output} = '/usr/local/lemonldap-ng/htdocs/portal/captcha_output/';
|
||||
$self->{captcha_data} = '/usr/local/lemonldap-ng/data/captcha/data/';
|
||||
|
||||
# Notification
|
||||
$self->{notificationWildcard} ||= "allusers";
|
||||
|
@ -745,6 +760,22 @@ sub buildHiddenForm {
|
|||
return $val;
|
||||
}
|
||||
|
||||
## @method void initCaptcha()
|
||||
# init captcha module and generate captcha
|
||||
sub initCaptcha {
|
||||
my $self = shift;
|
||||
opendir(OUTPUT, $self->{captcha_output}) or $self->lmLog("Can't open captcha output dir", "error");
|
||||
opendir(DATA, $self->{captcha_data}) or $self->lmLog("Can't open captcha data dir", "error");
|
||||
foreach(readdir(OUTPUT)) {
|
||||
system("rm -f $_ &>/dev/null")
|
||||
or $self->lmLog("Can't clean captcha output dir!", "warn");
|
||||
}
|
||||
$self->{captcha} = Authen::Captcha->new(data_folder => $self->{captcha_data}, output_folder => $self->{captcha_output});
|
||||
$self->{captcha_code} = $self->{captcha}->generate_code($self->{captcha_size});
|
||||
$self->{captcha_img} = "/captcha_output/" . $self->{captcha_code} . ".png";
|
||||
closedir(DATA) and closedir(OUTPUT);
|
||||
}
|
||||
|
||||
## @method boolean isTrustedUrl(string url)
|
||||
# Check if an URL's domain name is declared in LL::NG config or is declared as trusted domain
|
||||
# @param url Parameter url
|
||||
|
|
|
@ -47,6 +47,29 @@ sub extractFormInfo {
|
|||
&& ( $self->{confirmpassword} = $self->param('confirmpassword') ) );
|
||||
}
|
||||
|
||||
if ( $self->{captcha_enabled} ) {
|
||||
my $captcha_user_code;
|
||||
if ( $self->param('captcha_user_code') && $self->param('captcha_code') ) {
|
||||
$captcha_user_code = $self->param('captcha_user_code');
|
||||
$self->{captcha_code} = $self->param('captcha_code');
|
||||
}
|
||||
$self->{captcha_result} = $self->checkCaptcha($captcha_user_code, $self->{captcha_code});
|
||||
}
|
||||
if ( $self->{captcha_result} != 1 ) {
|
||||
if ( $self->{captcha_result} == -3 or $self->{captcha_result} == -2 ) {
|
||||
$self->lmLog("Captcha failed: wrong code", "error");
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
elsif ( $self->{captcha_result} == 0 ) {
|
||||
$self->lmLog("Captcha failed: code not checked (file error)", "error");
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
elsif ( $self->{captcha_result} == -1 ) {
|
||||
$self->lmLog("Captcha failed: code has expired", "error");
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
}
|
||||
|
||||
# Other parameters
|
||||
$self->{timezone} = $self->param('timezone');
|
||||
$self->{userControl} ||= '^[\w\.\-@]+$';
|
||||
|
@ -88,4 +111,18 @@ sub setAuthSessionInfo {
|
|||
PE_OK;
|
||||
}
|
||||
|
||||
## @method int checkCaptcha(code, ccode)
|
||||
# Check captcha auth
|
||||
# @return a constant
|
||||
# @param code that user enter in the form
|
||||
# @param captcha code generated by Authen::Captcha
|
||||
sub checkCaptcha {
|
||||
my ($self, $code, $ccode) = splice @_ ;
|
||||
opendir(OUTPUT, $self->{captcha_output}) or $self->lmLog("Can't open captcha output dir", "error");
|
||||
opendir(DATA, $self->{captcha_data}) or $self->lmLog("Can't open captcha data dir", "error");
|
||||
$self->{captcha_result} = $self->{captcha}->check_code($code, $ccode);
|
||||
closedir(OUTPUT) && closedir(DATA);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
@ -206,6 +206,8 @@ sub error_fr {
|
|||
'La connexion au serveur Radius a échoué',
|
||||
"L'ancien mot de passe est obligatoire",
|
||||
'Vous venez d\'une adresse IP qui n\'est pas accréditée',
|
||||
'Mauvais code',
|
||||
'Vous devez entrez le captcha'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -290,6 +292,8 @@ sub error_en {
|
|||
'Radius connection has failed',
|
||||
'Old password is required',
|
||||
'You came from an unaccredited IP address',
|
||||
'Wrong code',
|
||||
'You have to tape the captcha'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -374,7 +378,8 @@ sub error_ro {
|
|||
'Un e-mail a fost trimis',
|
||||
'Radius connection has failed',
|
||||
'Old password is required',
|
||||
'You came from an unaccredited IP address',
|
||||
'You came from an unaccredited IP address','Bad cod',
|
||||
'trebuie să introduceţi CAPTCHA'
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user