[LEMONLDAP-217] add a captcha feature to the portal

This commit is contained in:
Sandro Cazzaniga 2012-07-04 12:33:03 +00:00
parent 208b9f0f07
commit 5264202231
10 changed files with 116 additions and 8 deletions

View File

@ -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)

View File

@ -93,6 +93,8 @@ sub portalTab {
73 => 'PORTAL_RADIUSCONNECTFAILED',
74 => 'PORTAL_MUST_SUPPLY_OLD_PASSWORD',
75 => 'PORTAL_FORBIDDENIP',
76 => 'PORTAL_CAPTCHAERROR',
77 => 'PORTAL_CAPTCHAEMPTY',
};
}

View File

@ -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',

View File

@ -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 ) {

View File

@ -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">

View File

@ -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 (

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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'
];
}