Merge remote-tracking branch 'origin/master' into maxbes/lemonldap-ng-fix-1882-remove-oidcServiceMetaDataIssuer
This commit is contained in:
commit
0466a2c8cc
|
@ -5,6 +5,11 @@
|
|||
# ~/CN=(?<CN>[^/]+) $CN;
|
||||
#}
|
||||
|
||||
# FastCGI backend definition
|
||||
upstream llng_portal_upstream {
|
||||
server unix:__FASTCGISOCKDIR__/llng-fastcgi.sock;
|
||||
}
|
||||
|
||||
server {
|
||||
listen __PORT__;
|
||||
server_name auth.__DNSDOMAIN__;
|
||||
|
@ -30,7 +35,7 @@ server {
|
|||
|
||||
# FastCGI configuration
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_pass unix:__FASTCGISOCKDIR__/llng-fastcgi.sock;
|
||||
fastcgi_pass llng_portal_upstream;
|
||||
fastcgi_param LLTYPE psgi;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_split_path_info ^(.*\.psgi)(/.*)$;
|
||||
|
@ -47,6 +52,30 @@ server {
|
|||
# Uncomment this if you use Auth SSL:
|
||||
#uwsgi_param SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn;
|
||||
|
||||
# REST/SOAP functions for sessions management (disabled by default)
|
||||
location ~ ^/index.psgi/adminSessions {
|
||||
fastcgi_pass llng_portal_upstream;
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for sessions access (disabled by default)
|
||||
location ~ ^/index.psgi/sessions {
|
||||
fastcgi_pass llng_portal_upstream;
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for configuration access (disabled by default)
|
||||
location ~ ^/index.psgi/config {
|
||||
fastcgi_pass llng_portal_upstream;
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for notification insertion (disabled by default)
|
||||
location ~ ^/index.psgi/notification {
|
||||
fastcgi_pass llng_portal_upstream;
|
||||
deny all;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
index index.psgi;
|
||||
|
@ -61,26 +90,6 @@ server {
|
|||
alias __PORTALSTATICDIR__;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for sessions management (disabled by default)
|
||||
location /index.psgi/adminSessions {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for sessions access (disabled by default)
|
||||
location /index.psgi/sessions {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for configuration access (disabled by default)
|
||||
location /index.psgi/config {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# REST/SOAP functions for notification insertion (disabled by default)
|
||||
location /index.psgi/notification {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# DEBIAN
|
||||
# If install was made with USEDEBIANLIBS (official releases), uncomment this
|
||||
#location /javascript/ {
|
||||
|
|
|
@ -1153,7 +1153,7 @@ lemonldap-ng (1.2.3) stable; urgency=low
|
|||
urn:/Lemonldap::NG::Common::CGI::SOAPService
|
||||
* [LEMONLDAP-546] - Form replay: POST request is not sent
|
||||
* [LEMONLDAP-541] - Handler SOAP errors : setAttributes is not an
|
||||
authorizated function
|
||||
authorized function
|
||||
* [LEMONLDAP-547] - Update Browseable documentation in case of SAML in use
|
||||
* [LEMONLDAP-565] - Update META.yml files
|
||||
* [LEMONLDAP-581] - Clean Perl dependencies
|
||||
|
|
|
@ -98,7 +98,7 @@ Then, go in <code>OpenID parameters</code>:
|
|||
</li>
|
||||
<li class="level1"><div class="li"> <strong>Secret token</strong>: used to check integrity of OpenID response.</div>
|
||||
</li>
|
||||
<li class="level1"><div class="li"> <strong>Authorizated domain</strong>:</div>
|
||||
<li class="level1"><div class="li"> <strong>Authorized domain</strong>:</div>
|
||||
<ul>
|
||||
<li class="level2"><div class="li"> <strong>List type</strong>: choose white list to define allowed domains or black list to define forbidden domains</div>
|
||||
</li>
|
||||
|
|
|
@ -97,7 +97,7 @@ Sessions for connected users <em>(used by <a href="authproxy.html" class="wikili
|
|||
Authorizations for connected users (always enabled):
|
||||
</p>
|
||||
<ul>
|
||||
<li class="level1"><div class="li"> GET /mysession/?authorizationfor=<base64-encoded-url>: ask if url is authorizated</div>
|
||||
<li class="level1"><div class="li"> GET /mysession/?authorizationfor=<base64-encoded-url>: ask if url is authorized</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ To configure sessions, go in Manager, <code>General Parameters</code> » <code>S
|
|||
<h1 class="sectionedit2" id="command-line_tools">Command-line tools</h1>
|
||||
<div class="level1">
|
||||
<ul>
|
||||
<li class="level1"><div class="li"> LLNG Portal provides a simple tool to delete a session: <code>llngDeleteSession</code>. To use it, simply give it the user identifier <em>(wildcard are authorizated)</em>:</div>
|
||||
<li class="level1"><div class="li"> LLNG Portal provides a simple tool to delete a session: <code>llngDeleteSession</code>. To use it, simply give it the user identifier <em>(wildcard are authorized)</em>:</div>
|
||||
</li>
|
||||
</ul>
|
||||
<pre class="code shell"># Delete all sessions opened by user "dwho"
|
||||
|
|
|
@ -68,7 +68,7 @@ SOAP functions are not accessible by network by default. SOAP functions are prot
|
|||
</li>
|
||||
<li class="level2"><div class="li"> <strong>isAuthorizedURI(cookieValue,url)</strong>: check if user is granted to access to the function</div>
|
||||
</li>
|
||||
<li class="level2"><div class="li"> <strong>getMenuApplications(cookieValue)</strong>: return a list of authorizated applications (based on menu calculation)</div>
|
||||
<li class="level2"><div class="li"> <strong>getMenuApplications(cookieValue)</strong>: return a list of authorized applications (based on menu calculation)</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -18,16 +18,24 @@ sub defaultValues {
|
|||
'authChoiceParam' => 'lmAuth',
|
||||
'authentication' => 'Demo',
|
||||
'available2F' => 'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,Yubikey,Radius',
|
||||
'available2FSelfRegistration' => 'TOTP,U2F,Yubikey',
|
||||
'bruteForceProtectionMaxAge' => 300,
|
||||
'bruteForceProtectionMaxFailed' => 3,
|
||||
'bruteForceProtectionTempo' => 30,
|
||||
'captcha_mail_enabled' => 1,
|
||||
'captcha_register_enabled' => 1,
|
||||
'captcha_size' => 6,
|
||||
'casAccessControlPolicy' => 'none',
|
||||
'casAuthnLevel' => 1,
|
||||
'checkTime' => 600,
|
||||
'available2FSelfRegistration' => 'TOTP,U2F,Yubikey',
|
||||
'bruteForceProtectionMaxAge' => 300,
|
||||
'bruteForceProtectionMaxFailed' => 3,
|
||||
'bruteForceProtectionTempo' => 30,
|
||||
'captcha_mail_enabled' => 1,
|
||||
'captcha_register_enabled' => 1,
|
||||
'captcha_size' => 6,
|
||||
'casAccessControlPolicy' => 'none',
|
||||
'casAuthnLevel' => 1,
|
||||
'certificateResetByMailCeaAttribute' => 'description',
|
||||
'certificateResetByMailCertificateAttribute' =>
|
||||
'userCertificate;binary',
|
||||
'certificateResetByMailReplyTo' => 'noreply@example.com',
|
||||
'certificateResetByMailSender' => 'noreply@example.com',
|
||||
'certificateResetByMailURL' =>
|
||||
'http://auth.example.com/certificateReset',
|
||||
'certificateResetByMailValidityDelay' => 0,
|
||||
'checkTime' => 600,
|
||||
'checkUserHiddenAttributes' => '_loginHistory _session_id hGroups',
|
||||
'checkUserIdRule' => 1,
|
||||
'checkXSS' => 1,
|
||||
|
@ -210,6 +218,7 @@ sub defaultValues {
|
|||
'portalAntiFrame' => 1,
|
||||
'portalCheckLogins' => 1,
|
||||
'portalDisplayAppslist' => 1,
|
||||
'portalDisplayCertificateResetByMail' => 0,
|
||||
'portalDisplayChangePassword' => '$_auth =~ /^(LDAP|DBI|Demo)$/',
|
||||
'portalDisplayFavApps' => 1,
|
||||
'portalDisplayGeneratePassword' => 1,
|
||||
|
|
|
@ -11,8 +11,8 @@ our $VERSION = '2.1.0';
|
|||
|
||||
## @cmethod Lemonldap::NG::Common::PSGI::SOAPService new(object obj,string @func)
|
||||
# Constructor
|
||||
# @param $obj object which will be called for SOAP authorizated methods
|
||||
# @param @func authorizated methods
|
||||
# @param $obj object which will be called for SOAP authorized methods
|
||||
# @param @func authorized methods
|
||||
# @return Lemonldap::NG::Common::PSGI::SOAPService object
|
||||
sub new {
|
||||
my ( $class, $obj, $req, @func ) = @_;
|
||||
|
@ -24,7 +24,7 @@ sub new {
|
|||
# Call the wanted function with the object given to the constructor.
|
||||
# AUTOLOAD() is a magic method called by Perl interpreter fon non existent
|
||||
# functions. Here, we use it to call the wanted function (given by $AUTOLOAD)
|
||||
# if it is authorizated
|
||||
# if it is authorized
|
||||
# @return data provided by the exported function
|
||||
sub AUTOLOAD {
|
||||
my $self = shift;
|
||||
|
|
|
@ -19,6 +19,7 @@ lib/Lemonldap/NG/Handler/Lib/PSGI.pm
|
|||
lib/Lemonldap/NG/Handler/Lib/SecureToken.pm
|
||||
lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm
|
||||
lib/Lemonldap/NG/Handler/Lib/Status.pm
|
||||
lib/Lemonldap/NG/Handler/Lib/StatusConstants.pm
|
||||
lib/Lemonldap/NG/Handler/Lib/ZimbraPreAuth.pm
|
||||
lib/Lemonldap/NG/Handler/Main.pm
|
||||
lib/Lemonldap/NG/Handler/Main/Init.pm
|
||||
|
|
|
@ -96,6 +96,7 @@ sub set_custom {
|
|||
sub set_header_in {
|
||||
my ( $class, $request, %headers ) = @_;
|
||||
while ( my ( $h, $v ) = each %headers ) {
|
||||
utf8::downgrade($v);
|
||||
$request->env->{'psgi.r'}->headers_in->set( $h => $v );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,10 @@ sub portalConsts {
|
|||
'91' => 'PE_OID_SERVICE_NOT_ALLOWED',
|
||||
'92' => 'PE_GET_SERVICE_NOT_ALLOWED',
|
||||
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
|
||||
'94' => 'PE_ISSUERMISSINGREQATTR'
|
||||
'94' => 'PE_ISSUERMISSINGREQATTR',
|
||||
'95' => 'PE_RESETCERTIFICATE_INVALID',
|
||||
'96' => 'PE_RESETCERTIFICATE_FOREMPTY',
|
||||
'97' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ count(4);
|
|||
# Authentified queries
|
||||
# --------------------
|
||||
|
||||
# Authorizated query
|
||||
# Authorized query
|
||||
ok( $res = $client->_get( '/', undef, undef, "lemonldap=$sessionId" ),
|
||||
'Authentified query' );
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
|
|
|
@ -19,7 +19,7 @@ ok(
|
|||
'test3.example.com', "lemonldap=$sessionId",
|
||||
VHOSTTYPE => 'DevOps'
|
||||
),
|
||||
'Authorizated query'
|
||||
'Authorized query'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
@ -30,7 +30,7 @@ ok(
|
|||
'test3.example.com', "lemonldap=$sessionId",
|
||||
VHOSTTYPE => 'DevOps'
|
||||
),
|
||||
'Authorizated query'
|
||||
'Authorized query'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
|
|
@ -32,7 +32,7 @@ count(4);
|
|||
# Authentified queries
|
||||
# --------------------
|
||||
|
||||
# Authorizated query
|
||||
# Authorized query
|
||||
ok(
|
||||
$res =
|
||||
$client->_get( '/', undef, 'test.example.org', "lemonldap=$sessionId" ),
|
||||
|
|
|
@ -754,6 +754,42 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
},
|
||||
'certificateResetByMailCeaAttribute' => {
|
||||
'default' => 'description',
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailCertificateAttribute' => {
|
||||
'default' => 'userCertificate;binary',
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailReplyTo' => {
|
||||
'default' => 'noreply@example.com',
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailSender' => {
|
||||
'default' => 'noreply@example.com',
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailStep1Body' => {
|
||||
'type' => 'longtext'
|
||||
},
|
||||
'certificateResetByMailStep1Subject' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailStep2Body' => {
|
||||
'type' => 'longtext'
|
||||
},
|
||||
'certificateResetByMailStep2Subject' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'certificateResetByMailURL' => {
|
||||
'default' => 'http://auth.example.com/certificateReset',
|
||||
'type' => 'url'
|
||||
},
|
||||
'certificateResetByMailValidityDelay' => {
|
||||
'default' => 0,
|
||||
'type' => 'int'
|
||||
},
|
||||
'cfgAuthor' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -2324,6 +2360,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => 1,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'portalDisplayCertificateResetByMail' => {
|
||||
'default' => 0,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'portalDisplayChangePassword' => {
|
||||
'default' => '$_auth =~ /^(LDAP|DBI|Demo)$/',
|
||||
'type' => 'boolOrExpr'
|
||||
|
|
|
@ -498,7 +498,7 @@ EOF
|
|||
printf STDERR $format, $self->handlerStatusConstantsFile;
|
||||
|
||||
# Handler Status file
|
||||
my $content = <<EOF;
|
||||
$content = <<EOF;
|
||||
# This file is generated by $module. Don't modify it by hand
|
||||
package Lemonldap::NG::Handler::Lib::StatusConstants;
|
||||
|
||||
|
|
|
@ -963,6 +963,11 @@ sub attributes {
|
|||
type => 'boolOrExpr',
|
||||
documentation => 'Display logout tab in portal',
|
||||
},
|
||||
portalDisplayCertificateResetByMail => {
|
||||
type => 'boolOrExpr',
|
||||
default => 0,
|
||||
documentation => 'Display Certificate Reset by mail tab in portal',
|
||||
},
|
||||
portalDisplayRegister => {
|
||||
default => 1,
|
||||
type => 'bool',
|
||||
|
@ -1420,6 +1425,53 @@ sub attributes {
|
|||
default => 'http://auth.example.com/resetpwd',
|
||||
documentation => 'URL of password reset page',
|
||||
},
|
||||
# Certificate reset by mail
|
||||
certificateResetByMailCeaAttribute => {
|
||||
type => 'text',
|
||||
default => 'description'
|
||||
},
|
||||
certificateResetByMailCertificateAttribute => {
|
||||
type => 'text',
|
||||
default => 'userCertificate;binary',
|
||||
|
||||
},
|
||||
certificateResetByMailStep1Body => {
|
||||
type => 'longtext',
|
||||
documentation => 'Custom Certificate reset mail body',
|
||||
},
|
||||
|
||||
certificateResetByMailStep2Body => {
|
||||
type => 'longtext',
|
||||
documentation => 'Custom confirm Certificate reset mail body',
|
||||
},
|
||||
certificateResetByMailStep2Subject => {
|
||||
type => 'text',
|
||||
documentation => 'Mail subject for reset confirmation',
|
||||
},
|
||||
certificateResetByMailStep1Subject => {
|
||||
type => 'text',
|
||||
documentation => 'Mail subject for certificate reset email',
|
||||
},
|
||||
|
||||
certificateResetByMailURL => {
|
||||
type => 'url',
|
||||
default => 'http://auth.example.com/certificateReset',
|
||||
documentation => 'URL of certificate reset page',
|
||||
},
|
||||
certificateResetByMailSender => {
|
||||
type => 'text',
|
||||
default => 'noreply@example.com',
|
||||
documentation => 'URL of certificate reset page',
|
||||
},
|
||||
certificateResetByMailReplyTo => {
|
||||
type => 'text',
|
||||
default => 'noreply@example.com',
|
||||
documentation => 'URL of certificate reset page',
|
||||
},
|
||||
certificateResetByMailValidityDelay => {
|
||||
type => 'int',
|
||||
default => 0
|
||||
},
|
||||
|
||||
# Registration
|
||||
registerConfirmSubject => {
|
||||
|
|
|
@ -102,7 +102,9 @@ sub portalConstants {
|
|||
PE_GET_SERVICE_NOT_ALLOWED => 92,
|
||||
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
|
||||
PE_ISSUERMISSINGREQATTR => 94,
|
||||
|
||||
PE_RESETCERTIFICATE_INVALID => 95,
|
||||
PE_RESETCERTIFICATE_FOREMPTY => 96,
|
||||
PE_RESETCERTIFICATE_FIRSTACCESS => 97,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,8 @@ sub tree {
|
|||
'portalCheckLogins',
|
||||
'portalDisplayResetPassword',
|
||||
'passwordResetAllowedRetries',
|
||||
'portalDisplayRegister'
|
||||
'portalDisplayRegister',
|
||||
'portalDisplayCertificateResetByMail',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -91,7 +92,6 @@ sub tree {
|
|||
'passwordPolicyMinUpper',
|
||||
'passwordPolicyMinDigit',
|
||||
'portalDisplayPasswordPolicy',
|
||||
'portalDisplayGeneratePassword',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -660,11 +660,41 @@ sub tree {
|
|||
title => 'mailOther',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'mailUrl', 'mailTimeout',
|
||||
'mailUrl',
|
||||
'mailTimeout',
|
||||
'portalDisplayGeneratePassword',
|
||||
'randomPasswordRegexp',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title => 'certificateResetByMailManagement',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [ {
|
||||
title => 'certifcateMailContent',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'certificateResetByMailSender',
|
||||
'certificateResetByMailReplyTo',
|
||||
'certificateResetByMailStep1Subject',
|
||||
'certificateResetByMailStep1Body',
|
||||
'certificateResetByMailStep2Subject',
|
||||
'certificateResetByMailStep2Body'
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
title => 'mailOther',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'certificateResetByMailURL',
|
||||
'certificateResetByMailCeaAttribute',
|
||||
'certificateResetByMailCertificateAttribute',
|
||||
'certificateResetByMailValidityDelay'
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title => 'register',
|
||||
|
|
|
@ -141,7 +141,20 @@
|
|||
"casStorageOptions":" خيارات وحدة جلسات كاس",
|
||||
"categoryName":"اسم الفئة",
|
||||
"cda":"نطاقات متعددة",
|
||||
"contentSecurityPolicy":"السياسة الأمنية للمحتوى",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Content security policy",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Hidden attributes",
|
||||
"contextSwitchingIdRule":"Identities use rule",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"CAS sessions module options",
|
||||
"categoryName":"Category name",
|
||||
"cda":"Mehrere Domains",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Content security policy",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Hidden attributes",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"CAS sessions module options",
|
||||
"categoryName":"Category name",
|
||||
"cda":"Multiple domains",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Content security policy",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Hidden attributes",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"Options du module des sessions CAS",
|
||||
"categoryName":"Nom de la catégorie",
|
||||
"cda":"Domaines multiples",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Politique de sécurité de contenu",
|
||||
"contextSwitching":"Endossement d'identité",
|
||||
"contextSwitchingHiddenAttributes":"Attributs masqués",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"Opzioni del modulo sessioni CAS",
|
||||
"categoryName":"Nome della categoria",
|
||||
"cda":"Domini multipli",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Politica di protezione dei contenuti",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Attributi nascosti",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"Các tùy chọn mô-đun phiên CAS",
|
||||
"categoryName":"Tên thể loại",
|
||||
"cda":"Nhiều tên miền",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Chính sách bảo mật nội dung",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Hidden attributes",
|
||||
|
|
|
@ -141,6 +141,19 @@
|
|||
"casStorageOptions":"CAS 会话模块选项",
|
||||
"categoryName":"分类名称",
|
||||
"cda":"Multiple domains",
|
||||
"certifcateMailContent":"Certificate mail content",
|
||||
"certificateResetByMailManagement":"Certificate reset management",
|
||||
"certificateResetByMailURL":"Reset page URL",
|
||||
"certificateResetByMailCeaAttribute":"Certificate attibute name",
|
||||
"certificateResetByMailCertificateAttribute":"Certificate attribute name",
|
||||
"certificateResetByMailSender":"Mail sender",
|
||||
"certificateResetByMailReplyTo":"Reply address",
|
||||
"certificateResetByMailStep1Subject":"Certificate reset mail subject",
|
||||
"certificateResetByMailStep1Body":"Certificate reset mail content",
|
||||
"certificateResetByMailStep2Subject":"Confirmation mail subject",
|
||||
"certificateResetByMailStep2Body":"Confirmation mail content",
|
||||
"certificateResetByMailValidityDelay":"Minimum duration before expiration",
|
||||
"portalDisplayCertificateResetByMail":"Reset your Certificate",
|
||||
"contentSecurityPolicy":"Content security policy",
|
||||
"contextSwitching":"Switch context another user",
|
||||
"contextSwitchingHiddenAttributes":"Hidden attributes",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -47,6 +47,7 @@ lib/Lemonldap/NG/Portal/Auth/SSL.pm
|
|||
lib/Lemonldap/NG/Portal/Auth/Twitter.pm
|
||||
lib/Lemonldap/NG/Portal/Auth/WebID.pm
|
||||
lib/Lemonldap/NG/Portal/CDC.pm
|
||||
lib/Lemonldap/NG/Portal/CertificateResetByMail/LDAP.pm
|
||||
lib/Lemonldap/NG/Portal/Issuer/CAS.pm
|
||||
lib/Lemonldap/NG/Portal/Issuer/Get.pm
|
||||
lib/Lemonldap/NG/Portal/Issuer/OpenID.pm
|
||||
|
@ -101,6 +102,7 @@ lib/Lemonldap/NG/Portal/Password/REST.pm
|
|||
lib/Lemonldap/NG/Portal/Plugins/AutoSignin.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CDA.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CertificateResetByMail.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/CheckUser.pm
|
||||
lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm
|
||||
|
@ -364,6 +366,7 @@ site/htdocs/static/languages/zh.json
|
|||
site/templates/bootstrap/2fchoice.tpl
|
||||
site/templates/bootstrap/2fregisters.tpl
|
||||
site/templates/bootstrap/casBack2Url.tpl
|
||||
site/templates/bootstrap/certificateReset.tpl
|
||||
site/templates/bootstrap/checklogins.tpl
|
||||
site/templates/bootstrap/checkuser.tpl
|
||||
site/templates/bootstrap/choice.tpl
|
||||
|
@ -431,6 +434,7 @@ site/templates/common/mail/it.json
|
|||
site/templates/common/mail/vi.json
|
||||
site/templates/common/mail/zh_CN.json
|
||||
site/templates/common/mail_2fcode.tpl
|
||||
site/templates/common/mail_certificatReset.tpl
|
||||
site/templates/common/mail_confirm.tpl
|
||||
site/templates/common/mail_footer.tpl
|
||||
site/templates/common/mail_header.tpl
|
||||
|
@ -563,6 +567,7 @@ t/43-MailPasswordReset-LDAP.t
|
|||
t/43-MailPasswordReset-with-captcha.t
|
||||
t/43-MailPasswordReset-with-token.t
|
||||
t/43-MailPasswordReset.t
|
||||
t/44-CertificateResetByMail-LDAP.t
|
||||
t/50-IssuerGet.t
|
||||
t/59-Double-cookies-for-a-Single-session.t
|
||||
t/59-Double-cookies-for-Double-sessions.t
|
||||
|
|
|
@ -301,12 +301,18 @@ sub run {
|
|||
}
|
||||
|
||||
# Delete TOTP 2F device
|
||||
my $TOTPName;
|
||||
foreach (@$_2fDevices) {
|
||||
$TOTPName = $_->{name} if $_->{epoch} eq $epoch;
|
||||
}
|
||||
@$_2fDevices = grep { $_->{epoch} ne $epoch } @$_2fDevices;
|
||||
$self->logger->debug(
|
||||
"Delete 2F Device : { type => 'TOTP', epoch => $epoch }");
|
||||
"Delete 2F Device : { type => 'TOTP', epoch => $epoch, name => $TOTPName }"
|
||||
);
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _2fDevices => to_json($_2fDevices) } );
|
||||
$self->userLogger->notice('TOTP deletion succeed');
|
||||
$self->userLogger->notice(
|
||||
"TOTP $TOTPName unregistration succeeds for $user");
|
||||
return [
|
||||
200,
|
||||
[ 'Content-Type' => 'application/json', 'Content-Length' => 12, ],
|
||||
|
|
|
@ -288,12 +288,18 @@ sub run {
|
|||
}
|
||||
|
||||
# Delete U2F device
|
||||
my $keyName;
|
||||
foreach (@$_2fDevices) {
|
||||
$keyName = $_->{name} if $_->{epoch} eq $epoch;
|
||||
}
|
||||
@$_2fDevices = grep { $_->{epoch} ne $epoch } @$_2fDevices;
|
||||
$self->logger->debug(
|
||||
"Delete 2F Device : { type => 'U2F', epoch => $epoch }");
|
||||
"Delete 2F Device : { type => 'U2F', epoch => $epoch, name => $keyName }"
|
||||
);
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _2fDevices => to_json($_2fDevices) } );
|
||||
$self->userLogger->notice('U2F key unregistration succeed');
|
||||
$self->userLogger->notice(
|
||||
"U2F key $keyName unregistration succeeds for $user");
|
||||
return [
|
||||
200,
|
||||
[ 'Content-Type' => 'application/json', 'Content-Length' => 12, ],
|
||||
|
|
|
@ -181,12 +181,18 @@ sub run {
|
|||
}
|
||||
|
||||
# Delete Yubikey device
|
||||
my $UBKName;
|
||||
foreach (@$_2fDevices) {
|
||||
$UBKName = $_->{name} if $_->{epoch} eq $epoch;
|
||||
}
|
||||
@$_2fDevices = grep { $_->{epoch} ne $epoch } @$_2fDevices;
|
||||
$self->logger->debug(
|
||||
"Delete 2F Device : { type => 'UBK', epoch => $epoch }");
|
||||
"Delete 2F Device : { type => 'UBK', epoch => $epoch, name => $UBKName }"
|
||||
);
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _2fDevices => to_json($_2fDevices) } );
|
||||
$self->userLogger->notice('Yubikey deletion succeed');
|
||||
$self->userLogger->notice(
|
||||
"Yubikey $UBKName unregistration succeeds for $user");
|
||||
return [
|
||||
200,
|
||||
[ 'Content-Type' => 'application/json', 'Content-Length' => 12, ],
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package Lemonldap::NG::Portal::CertificateResetByMail::LDAP;
|
||||
|
||||
use strict;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_LDAPCONNECTFAILED
|
||||
PE_LDAPERROR
|
||||
PE_OK
|
||||
PE_ERROR
|
||||
);
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Lib::LDAP';
|
||||
|
||||
our $VERSION = '2.0.0';
|
||||
|
||||
# RUNNING METHODS
|
||||
|
||||
# PRIVATE METHODS
|
||||
sub modifCertificate {
|
||||
|
||||
my $self = shift;
|
||||
my $newcertif = shift;
|
||||
my $usercertif = shift;
|
||||
my $req = shift;
|
||||
my $ceaAttribute = $self->conf->{certificateResetByMailCeaAttribute}
|
||||
|| "description";
|
||||
my $certificateAttribute =
|
||||
$self->conf->{certificateResetByMailCertificateAttribute}
|
||||
|| "userCertificate;binary";
|
||||
|
||||
# Set the dn unless done before
|
||||
#
|
||||
#
|
||||
my $dn;
|
||||
if ( $req->userData->{_dn} ) {
|
||||
$dn = $req->userData->{_dn};
|
||||
$self->logger->debug("Get DN from request data: $dn");
|
||||
}
|
||||
else {
|
||||
$dn = $req->sessionInfo->{_dn};
|
||||
$self->logger->debug("Get DN from session data: $dn");
|
||||
}
|
||||
unless ($dn) {
|
||||
$self->logger->error('"dn" is not set, aborting password modification');
|
||||
return PE_ERROR;
|
||||
}
|
||||
|
||||
#my $dn = "uid=" . $req->{user}. "," . $self->conf->{ldapBase};
|
||||
|
||||
my $result = $self->ldap->modify(
|
||||
$dn,
|
||||
replace => [
|
||||
$ceaAttribute => $newcertif,
|
||||
"$certificateAttribute" => [$usercertif]
|
||||
]
|
||||
);
|
||||
|
||||
unless ( $result->code == 0 ) {
|
||||
$self->logger->debug( "LDAP modify Error: " . $result->code );
|
||||
$self->ldap->unbind;
|
||||
$self->{flags}->{ldapActive} = 0;
|
||||
$self->ldap->unbind;
|
||||
return PE_LDAPERROR;
|
||||
}
|
||||
|
||||
$self->logger->debug("$ceaAttribute set to $newcertif");
|
||||
|
||||
return PE_OK;
|
||||
|
||||
}
|
||||
|
||||
1;
|
|
@ -255,7 +255,7 @@ sub run {
|
|||
unless ( $rule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->warn( 'User '
|
||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} }
|
||||
. "was not authorized to access to $rp" );
|
||||
. " was not authorized to access to $rp" );
|
||||
return PE_UNAUTHORIZEDPARTNER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -388,7 +388,7 @@ sub run {
|
|||
unless ( $rule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->warn( 'User '
|
||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} }
|
||||
. "was not authorizated to access to $sp" );
|
||||
. " was not authorized to access to $sp" );
|
||||
return PE_UNAUTHORIZEDPARTNER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,9 @@ use constant {
|
|||
PE_GET_SERVICE_NOT_ALLOWED => 92,
|
||||
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
|
||||
PE_ISSUERMISSINGREQATTR => 94,
|
||||
PE_RESETCERTIFICATE_INVALID => 95,
|
||||
PE_RESETCERTIFICATE_FOREMPTY => 96,
|
||||
PE_RESETCERTIFICATE_FIRSTACCESS => 97,
|
||||
};
|
||||
|
||||
sub portalConsts {
|
||||
|
@ -191,7 +194,10 @@ sub portalConsts {
|
|||
'91' => 'PE_OID_SERVICE_NOT_ALLOWED',
|
||||
'92' => 'PE_GET_SERVICE_NOT_ALLOWED',
|
||||
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
|
||||
'94' => 'PE_ISSUERMISSINGREQATTR'
|
||||
'94' => 'PE_ISSUERMISSINGREQATTR',
|
||||
'95' => 'PE_RESETCERTIFICATE_INVALID',
|
||||
'96' => 'PE_RESETCERTIFICATE_FOREMPTY',
|
||||
'97' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -289,7 +295,10 @@ our @EXPORT_OK = (
|
|||
'PE_OID_SERVICE_NOT_ALLOWED',
|
||||
'PE_GET_SERVICE_NOT_ALLOWED',
|
||||
'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
|
||||
'PE_ISSUERMISSINGREQATTR'
|
||||
'PE_ISSUERMISSINGREQATTR',
|
||||
'PE_RESETCERTIFICATE_INVALID',
|
||||
'PE_RESETCERTIFICATE_FOREMPTY',
|
||||
'PE_RESETCERTIFICATE_FIRSTACCESS'
|
||||
);
|
||||
our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, 'import' ], );
|
||||
|
||||
|
|
|
@ -291,7 +291,12 @@ sub display {
|
|||
# 3 Authentication has been refused OR first access
|
||||
$skinfile = 'login';
|
||||
my $login = $self->userId($req);
|
||||
$login = '' if ( $login eq 'anonymous' );
|
||||
if ( $login eq 'anonymous' ) {
|
||||
$login = '';
|
||||
}
|
||||
elsif ( $req->user ) {
|
||||
$login = $req->{user};
|
||||
}
|
||||
%templateParams = (
|
||||
AUTH_ERROR => $req->error,
|
||||
AUTH_ERROR_TYPE => $req->error_type,
|
||||
|
@ -302,6 +307,8 @@ sub display {
|
|||
ASK_LOGINS => $req->param('checkLogins') || 0,
|
||||
DISPLAY_RESETPASSWORD => $self->conf->{portalDisplayResetPassword},
|
||||
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
|
||||
DISPLAY_UPDATECERTIF => $self->conf->{portalDisplayCertificateResetByMail},
|
||||
MAILCERTIF_URL => $self->conf->{certificateResetByMailURL},
|
||||
MAIL_URL => $self->conf->{mailUrl},
|
||||
REGISTER_URL => $self->conf->{registerUrl},
|
||||
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||
|
|
|
@ -74,6 +74,8 @@ sub enabledPlugins {
|
|||
# Check if register is enabled
|
||||
push @res, '::Plugins::Register'
|
||||
if ( $conf->{registerDB} and $conf->{registerDB} ne 'Null' );
|
||||
push @res, '::Plugins::CertificateResetByMail'
|
||||
if ( $conf->{portalDisplayCertificateResetByMail});
|
||||
|
||||
# Check if custom plugins are required
|
||||
# TODO: change this name
|
||||
|
|
|
@ -509,6 +509,9 @@ sub buildCookie {
|
|||
);
|
||||
}
|
||||
}
|
||||
$self->userLogger->notice(
|
||||
"User $req->{user} successfully authenticated at level $req->{sessionInfo}->{authenticationLevel}"
|
||||
);
|
||||
PE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ sub error_type {
|
|||
PE_MAILOK, PE_LOGOUT_OK,
|
||||
PE_MAILFIRSTACCESS, PE_PASSWORDFIRSTACCESS,
|
||||
PE_MAILCONFIRMOK, PE_REGISTERFIRSTACCESS,
|
||||
PE_RESETCERTIFICATE_FIRSTACCESS,
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -107,7 +108,7 @@ sub error_type {
|
|||
PE_CONFIRM, PE_MAILFORMEMPTY,
|
||||
PE_MAILCONFIRMATION_ALREADY_SENT, PE_PASSWORDFORMEMPTY,
|
||||
PE_CAPTCHAEMPTY, PE_REGISTERFORMEMPTY,
|
||||
PE_PP_CHANGE_AFTER_RESET
|
||||
PE_PP_CHANGE_AFTER_RESET, PE_RESETCERTIFICATE_FOREMPTY,
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,794 @@
|
|||
package Lemonldap::NG::Portal::Plugins::CertificateResetByMail;
|
||||
|
||||
use strict;
|
||||
use Encode;
|
||||
use Mouse;
|
||||
use Net::SSLeay;
|
||||
use DateTime::Format::RFC3339;
|
||||
use Digest::SHA qw(sha256_hex);
|
||||
use MIME::Base64;
|
||||
use POSIX qw(strftime);
|
||||
use Lemonldap::NG::Common::FormEncode;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_BADCREDENTIALS
|
||||
PE_BADMAILTOKEN
|
||||
PE_CAPTCHAEMPTY
|
||||
PE_CAPTCHAERROR
|
||||
PE_MAILCONFIRMATION_ALREADY_SENT
|
||||
PE_MAILCONFIRMOK
|
||||
PE_MAILERROR
|
||||
PE_MAILFIRSTACCESS
|
||||
PE_MAILFORMEMPTY
|
||||
PE_MAILNOTFOUND
|
||||
PE_MAILOK
|
||||
PE_MALFORMEDUSER
|
||||
PE_NOTOKEN
|
||||
PE_OK
|
||||
PE_PASSWORDFIRSTACCESS
|
||||
PE_PASSWORDFORMEMPTY
|
||||
PE_PASSWORD_OK
|
||||
PE_TOKENEXPIRED
|
||||
PE_USERNOTFOUND
|
||||
PE_RESETCERTIFICATE_INVALID
|
||||
PE_RESETCERTIFICATE_FOREMPTY
|
||||
PE_RESETCERTIFICATE_FIRSTACCESS
|
||||
);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Main::Plugin',
|
||||
'Lemonldap::NG::Portal::Lib::SMTP', 'Lemonldap::NG::Portal::Lib::_tokenRule';
|
||||
|
||||
# PROPERTIES
|
||||
|
||||
# Mail timeout token generator
|
||||
# Form timout token generator (used even if requireToken is not set)
|
||||
has ott => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my $ott =
|
||||
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
||||
$ott->timeout( $_[0]->conf->{formTimeout} );
|
||||
return $ott;
|
||||
}
|
||||
);
|
||||
|
||||
# Sub module (Demo, LDAP,...)
|
||||
has registerModule => ( is => 'rw' );
|
||||
|
||||
# Captcha generator
|
||||
has captcha => ( is => 'rw' );
|
||||
|
||||
# certificate reset url
|
||||
|
||||
has certificateResetUrl => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my $p = $_[0]->conf->{portal};
|
||||
$p =~ s#/*$##;
|
||||
return "$p/certificateReset";
|
||||
}
|
||||
);
|
||||
|
||||
# Mail timeout token generator
|
||||
has mailott => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my $ott =
|
||||
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
|
||||
$ott->cache(0);
|
||||
$ott->timeout( $_[0]->conf->{registerTimeout}
|
||||
|| $_[0]->conf->{timeout} );
|
||||
return $ott;
|
||||
}
|
||||
);
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
|
||||
# Declare REST route
|
||||
$self->addUnauthRoute(
|
||||
certificateReset => 'certificateReset',
|
||||
[ 'POST', 'GET' ]
|
||||
);
|
||||
|
||||
# Initialize Captcha if needed
|
||||
if ( $self->conf->{captcha_mail_enabled} ) {
|
||||
$self->captcha( $self->p->loadModule('::Lib::Captcha') ) or return 0;
|
||||
}
|
||||
|
||||
# Load registered module
|
||||
$self->registerModule(
|
||||
$self->p->loadPlugin(
|
||||
'::CertificateResetByMail::' . $self->conf->{registerDB}
|
||||
)
|
||||
) or return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
# RUNNIG METHODS
|
||||
|
||||
# Handle reset requests
|
||||
sub certificateReset {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
$self->p->controlUrl($req);
|
||||
|
||||
# Check parameters
|
||||
$req->error( $self->_certificateReset($req) );
|
||||
|
||||
# Display form
|
||||
my ( $tpl, $prms ) = $self->display($req);
|
||||
return $self->p->sendHtml( $req, $tpl, params => $prms );
|
||||
}
|
||||
|
||||
sub _certificateReset {
|
||||
my ( $self, $req ) = @_;
|
||||
my ( $mailToken, %tplPrms );
|
||||
|
||||
# CertificatReset FORM => modifyCertificate()
|
||||
if (
|
||||
$req->method =~ /^POST$/i
|
||||
|
||||
and ( $req->uploads->{certif} )
|
||||
)
|
||||
{
|
||||
|
||||
my $upload = $req->uploads->{certif};
|
||||
|
||||
return $self->modifyCertificate($req);
|
||||
}
|
||||
|
||||
# FIRST FORM
|
||||
$mailToken = $req->data->{mailToken} = $req->param('mail_token');
|
||||
unless ( $req->param('mail') || $mailToken ) {
|
||||
$self->setSecurity($req);
|
||||
return PE_MAILFIRSTACCESS if ( $req->method eq 'GET' );
|
||||
return PE_MAILFORMEMPTY;
|
||||
}
|
||||
|
||||
my $searchByMail = 1;
|
||||
|
||||
# OTHER FORMS
|
||||
if ($mailToken) {
|
||||
$self->logger->debug("Token given for certificate reset: $mailToken");
|
||||
|
||||
# Check if token is valid
|
||||
my $mailSession =
|
||||
$self->p->getApacheSession( $mailToken, kind => "TOKEN" );
|
||||
unless ($mailSession) {
|
||||
$self->userLogger->warn('Bad reset token');
|
||||
return PE_BADMAILTOKEN;
|
||||
}
|
||||
|
||||
$req->{user} = $mailSession->data->{user};
|
||||
$req->data->{mailAddress} =
|
||||
$mailSession->data->{ $self->conf->{mailSessionKey} };
|
||||
$self->logger->debug( 'User associated to: ' . $req->{user} );
|
||||
|
||||
# Restore pdata if any
|
||||
$req->pdata( $mailSession->data->{_pdata} || {} );
|
||||
$mailSession->remove;
|
||||
$searchByMail = 0 unless ( $req->{user} =~ /\@/ );
|
||||
}
|
||||
|
||||
# Check for values posted
|
||||
else {
|
||||
|
||||
# Use submitted value
|
||||
$req->{user} = $req->param('mail');
|
||||
|
||||
# Check if token exists
|
||||
my $token;
|
||||
if ( $self->ottRule->( $req, {} ) or $self->captcha ) {
|
||||
$token = $req->param('token');
|
||||
unless ($token) {
|
||||
$self->setSecurity($req);
|
||||
$self->userLogger->warn('Reset try without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
# Captcha for register form
|
||||
if ( $self->captcha ) {
|
||||
my $captcha = $req->param('captcha');
|
||||
|
||||
unless ($captcha) {
|
||||
$self->userLogger->notice('Reset try with captcha not filled');
|
||||
|
||||
# Set captcha or token
|
||||
$self->setSecurity($req);
|
||||
return PE_CAPTCHAEMPTY;
|
||||
}
|
||||
|
||||
# Check captcha
|
||||
unless ( $self->captcha->validateCaptcha( $token, $captcha ) ) {
|
||||
$self->userLogger->info('Captcha failed: wrong code');
|
||||
|
||||
# Set captcha or token
|
||||
$self->setSecurity($req);
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
$self->logger->debug('Captcha code verified');
|
||||
}
|
||||
elsif ( $self->ottRule->( $req, {} ) ) {
|
||||
unless ( $self->ott->getToken($token) ) {
|
||||
$self->setSecurity($req);
|
||||
$self->userLogger->warn('Reset try with expired/bad token');
|
||||
return PE_TOKENEXPIRED;
|
||||
}
|
||||
}
|
||||
unless ( $req->{user} =~ /$self->{conf}->{userControl}/o ) {
|
||||
$self->setSecurity($req);
|
||||
return PE_MALFORMEDUSER;
|
||||
}
|
||||
}
|
||||
|
||||
# Search user in database
|
||||
$req->steps( [
|
||||
'getUser', 'setSessionInfo',
|
||||
'setMacros', 'setGroups',
|
||||
'setPersistentSessionInfo', 'setLocalGroups'
|
||||
]
|
||||
);
|
||||
if ( my $error = $self->p->process( $req, useMail => $searchByMail ) ) {
|
||||
if ( $error == PE_USERNOTFOUND or $error == PE_BADCREDENTIALS ) {
|
||||
$self->userLogger->warn( 'Reset asked for an unvalid user ('
|
||||
. $req->param('mail')
|
||||
. ')' );
|
||||
|
||||
# To avoid mail enumeration, return OK
|
||||
# unless portalErrorOnMailNotFound is set
|
||||
|
||||
if ( $self->conf->{portalErrorOnMailNotFound} ) {
|
||||
$self->setSecurity($req);
|
||||
return PE_MAILNOTFOUND;
|
||||
}
|
||||
|
||||
my $mailTimeout =
|
||||
$self->conf->{mailTimeout} || $self->conf->{timeout};
|
||||
my $expTimestamp = time() + $mailTimeout;
|
||||
$req->data->{expMailDate} =
|
||||
strftime( '%d/%m/%Y', localtime $expTimestamp );
|
||||
$req->data->{expMailTime} =
|
||||
strftime( '%H:%M', localtime $expTimestamp );
|
||||
return PE_MAILCONFIRMOK;
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
# Build temporary session
|
||||
my $mailSession = $self->getCertificateSession( $req->{user} );
|
||||
unless ( $mailSession or $mailToken ) {
|
||||
|
||||
# Create a new session
|
||||
|
||||
my $infos = {};
|
||||
|
||||
# Set _utime for session autoremove
|
||||
# Use default session timeout and mail session timeout to compute it
|
||||
my $time = time();
|
||||
my $timeout = $self->conf->{timeout};
|
||||
my $mailTimeout = $self->conf->{mailTimeout} || $timeout;
|
||||
|
||||
$infos->{_utime} = $time + ( $mailTimeout - $timeout );
|
||||
|
||||
# Store expiration timestamp for further use
|
||||
$infos->{mailSessionTimeoutTimestamp} = $time + $mailTimeout;
|
||||
|
||||
# Store start timestamp for further use
|
||||
$infos->{mailSessionStartTimestamp} = $time;
|
||||
|
||||
# Store mail
|
||||
$infos->{ $self->conf->{mailSessionKey} } =
|
||||
$self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
|
||||
# Store user
|
||||
$infos->{user} = $req->{user};
|
||||
|
||||
# Store type
|
||||
$infos->{_type} = 'certificate';
|
||||
|
||||
# Store pdata
|
||||
$infos->{_pdata} = $req->pdata;
|
||||
|
||||
# create session
|
||||
$mailSession =
|
||||
$self->p->getApacheSession( undef, kind => "TOKEN", info => $infos );
|
||||
|
||||
$req->id( $mailSession->id );
|
||||
}
|
||||
elsif ($mailSession) {
|
||||
$self->logger->debug( 'Mail session found: ' . $mailSession->id );
|
||||
$req->id( $mailSession->id );
|
||||
$req->data->{mailAlreadySent} = 1;
|
||||
}
|
||||
|
||||
# Send confirmation mail
|
||||
unless ($mailToken) {
|
||||
|
||||
# Mail session expiration date
|
||||
my $expTimestamp = $mailSession->data->{mailSessionTimeoutTimestamp};
|
||||
|
||||
$self->logger->debug("Mail expiration timestamp: $expTimestamp");
|
||||
|
||||
$req->data->{expMailDate} =
|
||||
strftime( '%d/%m/%Y', localtime $expTimestamp );
|
||||
$req->data->{expMailTime} =
|
||||
strftime( '%H:%M', localtime $expTimestamp );
|
||||
|
||||
# Mail session start date
|
||||
my $startTimestamp = $mailSession->data->{mailSessionStartTimestamp};
|
||||
|
||||
$self->logger->debug("Mail start timestamp: $startTimestamp");
|
||||
$req->data->{startMailDate} =
|
||||
strftime( '%d/%m/%Y', localtime $startTimestamp );
|
||||
$req->data->{startMailTime} =
|
||||
strftime( '%H:%M', localtime $startTimestamp );
|
||||
|
||||
# Ask if user wants an another confirmation email
|
||||
if ( $req->data->{mailAlreadySent}
|
||||
and not $req->param('resendconfirmation') )
|
||||
{
|
||||
$self->userLogger->notice(
|
||||
'Reset mail already sent to ' . $req->{user} );
|
||||
|
||||
# Return mail already sent only if it is allowed at previous step
|
||||
|
||||
if ( $self->conf->{portalErrorOnMailNotFound} ) {
|
||||
$self->setSecurity($req);
|
||||
return PE_MAILCONFIRMATION_ALREADY_SENT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Get mail address
|
||||
$req->data->{mailAddress} ||=
|
||||
$self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
return PE_MAILERROR unless ( $req->data->{mailAddress} );
|
||||
|
||||
# Build confirmation url
|
||||
my $req_url = $req->data->{_url};
|
||||
my $skin = $self->p->getSkin($req);
|
||||
my $url =
|
||||
$self->certificateResetUrl . '?'
|
||||
. build_urlencoded(
|
||||
mail_token => $req->{id},
|
||||
skin => $skin,
|
||||
( $req_url ? ( url => $req_url ) : () ),
|
||||
);
|
||||
|
||||
# Build mail content
|
||||
$tplPrms{MAIN_LOGO} = $self->conf->{portalMainLogo};
|
||||
my $tr = $self->translate($req);
|
||||
my $subject = $self->conf->{certificateResetByMailStep1Subject};
|
||||
unless ($subject) {
|
||||
$subject = 'certificateResetByMailStep1Subject';
|
||||
$tr->( \$subject );
|
||||
}
|
||||
my $body;
|
||||
my $html;
|
||||
if ( $self->conf->{certificateResetByMailStep1Body} ) {
|
||||
|
||||
# We use a specific text message, no html
|
||||
$body = $self->conf->{certificateResetByMailStep1Body};
|
||||
}
|
||||
else {
|
||||
|
||||
# Use HTML template
|
||||
$body = $self->loadTemplate(
|
||||
'mail_confirm',
|
||||
filter => $tr,
|
||||
params => \%tplPrms
|
||||
);
|
||||
$html = 1;
|
||||
}
|
||||
|
||||
# Replace variables in body
|
||||
$body =~ s/\$expMailDate/$req->data->{expMailDate}/ge;
|
||||
$body =~ s/\$expMailTime/$req->data->{expMailTime}/ge;
|
||||
$body =~ s/\$url/$url/g;
|
||||
$body =~ s/\$(\w+)/$req->{sessionInfo}->{$1} || ''/ge;
|
||||
|
||||
# Send mail
|
||||
unless (
|
||||
$self->sendmail(
|
||||
$req->data->{mailAddress}, $subject, $body, $html
|
||||
)
|
||||
)
|
||||
{
|
||||
$self->logger->debug('Unable to send reset mail');
|
||||
|
||||
# Don't return an error here to avoid enumeration
|
||||
}
|
||||
return PE_MAILCONFIRMOK;
|
||||
}
|
||||
|
||||
# User has a valid mailToken, allow to reset certificate
|
||||
# A token is required
|
||||
$self->ott->setToken(
|
||||
$req,
|
||||
{
|
||||
%{ $req->sessionInfo }, certificateResetAllowed => 1
|
||||
}
|
||||
);
|
||||
return PE_RESETCERTIFICATE_FIRSTACCESS if ( $req->method eq 'GET' );
|
||||
return PE_RESETCERTIFICATE_FOREMPTY;
|
||||
}
|
||||
|
||||
sub modifyCertificate {
|
||||
my ( $self, $req ) = @_;
|
||||
my %tplPrms;
|
||||
my $nbio;
|
||||
my $x509;
|
||||
my $notAfter;
|
||||
|
||||
$self->logger->debug('Change your Certificate form response');
|
||||
|
||||
if ( my $token = $req->param('token') ) {
|
||||
$req->sessionInfo( $self->ott->getToken($token) );
|
||||
unless ( $req->sessionInfo ) {
|
||||
$self->userLogger->warn(
|
||||
'User tries to change certificate with an invalid or expired token'
|
||||
);
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
# These 2 cases means that a user tries to reset certificate without
|
||||
# following valid links!!!
|
||||
else {
|
||||
$self->userLogger->error(
|
||||
'User tries to reset certificate without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
|
||||
unless ( $req->sessionInfo->{certificateResetAllowed} ) {
|
||||
$self->userLogger->error(
|
||||
'User tries to use another token to reset certificate');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
|
||||
#Updload certificate
|
||||
my $upload = $req->uploads->{certif};
|
||||
|
||||
unless ( $upload->size > 0 ) { return PE_RESETCERTIFICATE_FOREMPTY; }
|
||||
|
||||
# Get Certificate
|
||||
|
||||
my $file = $upload->path;
|
||||
$self->userLogger->debug( "Temporaly file " . $file );
|
||||
|
||||
# Convert certificate file uploaded on DER format with openssl library
|
||||
|
||||
#my $certifbase64 =`openssl x509 -outform der -in $file -out $file`;
|
||||
|
||||
# load certificate from file with openssl library
|
||||
$nbio = Net::SSLeay::BIO_new_file( $file, 'r' ) or die $!;
|
||||
|
||||
# for PEM certificate
|
||||
$x509 = Net::SSLeay::PEM_read_bio_X509($nbio);
|
||||
|
||||
Net::SSLeay::BIO_free($nbio);
|
||||
unless ($x509) {
|
||||
$self->userLogger->debug( "Unable to decode certificate for user "
|
||||
. Net::SSLeay::ERR_error_string( Net::SSLeay::ERR_get_error() ) );
|
||||
|
||||
#return PE_CERTIFICATE_INVALID;
|
||||
return PE_RESETCERTIFICATE_INVALID;
|
||||
}
|
||||
$self->userLogger->debug("Certificate decoded successfully");
|
||||
$notAfter = Net::SSLeay::P_ASN1_TIME_get_isotime(
|
||||
Net::SSLeay::X509_get_notAfter($x509) );
|
||||
|
||||
my $x509issuer = Net::SSLeay::X509_NAME_oneline(
|
||||
Net::SSLeay::X509_get_issuer_name($x509) );
|
||||
|
||||
my $x509serial = Net::SSLeay::P_ASN1_INTEGER_get_hex(
|
||||
Net::SSLeay::X509_get_serialNumber($x509) );
|
||||
|
||||
$self->userLogger->debug(
|
||||
"Certificate will expire after $notAfter, Issuer $x509issuer and serialNumber $x509serial"
|
||||
);
|
||||
|
||||
# Check Certificate Validity befor store
|
||||
if (
|
||||
$self->checkCertificateValidity( $notAfter,
|
||||
$self->conf->{certificateResetByMailValidityDelay} ) == 0
|
||||
)
|
||||
{
|
||||
$self->userLogger->debug(
|
||||
"Your cettificate is no longer valid in $self->conf->{certificateValidityDelay}"
|
||||
);
|
||||
return PE_RESETCERTIFICATE_INVALID;
|
||||
|
||||
#return PE_PASSWORD_MISMATCH;
|
||||
}
|
||||
|
||||
# Build serial number hex exemple f3:08:52:63:28:29:fa:e2
|
||||
|
||||
my @numberstring = split //, lc($x509serial);
|
||||
my $serial = "";
|
||||
for ( my $i = 0 ; $i <= $#numberstring ; $i += 2 ) {
|
||||
$serial = $serial . $numberstring[$i] . $numberstring[ $i + 1 ];
|
||||
if ( $i + 2 < $#numberstring ) { $serial = $serial . ":"; }
|
||||
}
|
||||
|
||||
# format issuer in the good format example "CN=CA,OU=CISIRH,O=MINEFI,L=Paris,ST=France,C=FR"
|
||||
|
||||
my @issuertab = split /\//, $x509issuer;
|
||||
shift(@issuertab);
|
||||
my $issuer = join( ",", reverse(@issuertab) );
|
||||
|
||||
#$issuer = lc($issuer);
|
||||
|
||||
my $certificatExactAssertion =
|
||||
'{ serialNumber ' . $serial . ', issuer rdnSequence:"' . $issuer . '" }';
|
||||
$self->userLogger->debug( "Description:: " . $certificatExactAssertion );
|
||||
|
||||
# Get attribut userCertificate;binary value
|
||||
|
||||
my $cert = $self->certificateHash($file);
|
||||
|
||||
# modif the ldap certificate attribute
|
||||
|
||||
$req->user( $req->{sessionInfo}->{_user} );
|
||||
my $result =
|
||||
$self->registerModule->modifCertificate( $certificatExactAssertion,
|
||||
$cert, $req );
|
||||
$self->{user} = undef;
|
||||
|
||||
# Mail token can be used only one time, delete the session if all is ok
|
||||
#
|
||||
return $result unless ( $result == PE_OK );
|
||||
|
||||
# Send mail to notify the certificate reset sucessfully
|
||||
$req->data->{mailAddress} ||=
|
||||
$self->p->getFirstValue(
|
||||
$req->{sessionInfo}->{ $self->conf->{mailSessionKey} } );
|
||||
|
||||
# Build mail content
|
||||
$tplPrms{MAIN_LOGO} = $self->conf->{portalMainLogo};
|
||||
my $tr = $self->translate($req);
|
||||
my $subject = $self->conf->{certificateResetByMailStep2Subject};
|
||||
unless ($subject) {
|
||||
$subject = 'certificateResetByMailStep2Subject';
|
||||
$tr->( \$subject );
|
||||
}
|
||||
my $body;
|
||||
my $html;
|
||||
if ( $self->conf->{certificateResetByMailStep2Body} ) {
|
||||
|
||||
# We use a specific text message, no html
|
||||
$body = $self->conf->{certificateResetByMailStep2Body};
|
||||
}
|
||||
else {
|
||||
|
||||
# Use HTML template
|
||||
$body = $self->loadTemplate(
|
||||
'mail_certificatReset',
|
||||
filter => $tr,
|
||||
params => \%tplPrms
|
||||
);
|
||||
$html = 1;
|
||||
}
|
||||
|
||||
# Replace variables in body
|
||||
$body =~ s/\$(\w+)/$req->{sessionInfo}->{$1} || ''/ge;
|
||||
|
||||
# Send mail
|
||||
return PE_MAILERROR
|
||||
unless $self->sendmail( $req->data->{mailAddress}, $subject, $body,
|
||||
$html );
|
||||
|
||||
return PE_MAILOK;
|
||||
}
|
||||
|
||||
sub setSecurity {
|
||||
my ( $self, $req ) = @_;
|
||||
if ( $self->captcha ) {
|
||||
$self->captcha->setCaptcha($req);
|
||||
}
|
||||
elsif ( $self->ottRule->( $req, {} ) ) {
|
||||
$self->ott->setToken($req);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub display {
|
||||
my ( $self, $req ) = @_;
|
||||
$self->logger->debug( 'Display called with code: ' . $req->error );
|
||||
my %tplPrm = (
|
||||
SKIN_PATH => $self->conf->{staticPrefix},
|
||||
SKIN => $self->p->getSkin($req),
|
||||
SKIN_BG => $self->conf->{portalSkinBackground},
|
||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||
AUTH_ERROR => $req->error,
|
||||
AUTH_ERROR_TYPE => $req->error_type,
|
||||
AUTH_URL => $req->data->{_url},
|
||||
CHOICE_VALUE => $req->{_authChoice},
|
||||
EXPMAILDATE => $req->data->{expMailDate},
|
||||
EXPMAILTIME => $req->data->{expMailTime},
|
||||
STARTMAILDATE => $req->data->{startMailDate},
|
||||
STARTMAILTIME => $req->data->{startMailTime},
|
||||
MAILALREADYSENT => $req->data->{mailAlreadySent},
|
||||
MAIL => (
|
||||
$self->p->checkXSSAttack( 'mail', $req->{user} )
|
||||
? ''
|
||||
: $req->{user}
|
||||
),
|
||||
DISPLAY_FORM => 0,
|
||||
DISPLAY_RESEND_FORM => 0,
|
||||
DISPLAY_CONFIRMMAILSENT => 0,
|
||||
DISPLAY_MAILSENT => 0,
|
||||
DISPLAY_CERTIF_FORM => 0,
|
||||
);
|
||||
if ( $req->data->{mailToken}
|
||||
and
|
||||
not $self->p->checkXSSAttack( 'mail_token', $req->data->{mailToken} ) )
|
||||
{
|
||||
$tplPrm{MAIL_TOKEN} = $req->data->{mailToken};
|
||||
}
|
||||
|
||||
# Display captcha if it's enabled
|
||||
if ( $req->captcha ) {
|
||||
$tplPrm{CAPTCHA_SRC} = $req->captcha;
|
||||
$tplPrm{CAPTCHA_SIZE} = $self->conf->{captcha_size};
|
||||
}
|
||||
if ( $req->token ) {
|
||||
$tplPrm{TOKEN} = $req->token;
|
||||
}
|
||||
|
||||
# Display form the first time
|
||||
if ( (
|
||||
$req->error == PE_MAILFORMEMPTY
|
||||
or $req->error == PE_MAILFIRSTACCESS
|
||||
or $req->error == PE_MAILNOTFOUND
|
||||
or $req->error == PE_CAPTCHAERROR
|
||||
or $req->error == PE_CAPTCHAEMPTY
|
||||
)
|
||||
and not $req->data->{mailToken}
|
||||
)
|
||||
{
|
||||
$self->logger->debug('Display form');
|
||||
$tplPrm{DISPLAY_FORM} = 1;
|
||||
}
|
||||
|
||||
# Display mail confirmation resent form
|
||||
elsif ( $req->error == PE_MAILCONFIRMATION_ALREADY_SENT ) {
|
||||
$self->logger->debug('Display resend form');
|
||||
$tplPrm{DISPLAY_RESEND_FORM} = 1;
|
||||
}
|
||||
|
||||
# Display confirmation mail sent
|
||||
elsif ( $req->error == PE_MAILCONFIRMOK ) {
|
||||
$self->logger->debug('Display "confirm mail sent"');
|
||||
$tplPrm{DISPLAY_CONFIRMMAILSENT} = 1;
|
||||
}
|
||||
|
||||
# Display mail sent
|
||||
elsif ( $req->error == PE_MAILOK ) {
|
||||
$self->logger->debug('Display "mail sent"');
|
||||
$tplPrm{DISPLAY_MAILSENT} = 1;
|
||||
}
|
||||
|
||||
# Display Certificate Reset form
|
||||
elsif ( $req->data->{mailToken}
|
||||
and $req->error != PE_MAILERROR
|
||||
and $req->error != PE_BADMAILTOKEN
|
||||
and $req->error != PE_MAILOK )
|
||||
{
|
||||
$self->logger->debug('Display certificate reset form');
|
||||
$tplPrm{DISPLAY_CERTIF_FORM} = 1;
|
||||
}
|
||||
|
||||
# Display Certificate Reset form again if certificate invalid
|
||||
elsif ($req->error == PE_RESETCERTIFICATE_FOREMPTY
|
||||
|| $req->error == PE_RESETCERTIFICATE_INVALID )
|
||||
{
|
||||
$self->logger->debug('Display Certificate Reset form');
|
||||
$tplPrm{DISPLAY_CERTIF_FORM} = 1;
|
||||
}
|
||||
|
||||
return 'certificateReset', \%tplPrm;
|
||||
}
|
||||
|
||||
#tring getCertifResetSession (string mail)
|
||||
# Check if a certificate reset session exists
|
||||
# @param mail the value of the mail key in session
|
||||
# @return the first session id found or nothing if no session
|
||||
sub getCertificateSession {
|
||||
my ( $self, $user ) = @_;
|
||||
|
||||
my $moduleOptions = $self->conf->{globalStorageOptions} || {};
|
||||
$moduleOptions->{backend} = $self->conf->{globalStorage};
|
||||
my $module = "Lemonldap::NG::Common::Apache::Session";
|
||||
|
||||
# Search on modifyaccount sessions
|
||||
my $sessions = $module->searchOn( $moduleOptions, "user", $user );
|
||||
|
||||
# Browse found sessions to check if it's a modifyaccount session
|
||||
foreach my $id ( keys %$sessions ) {
|
||||
my $certificateResetSession =
|
||||
$self->p->getApacheSession( $id, ( kind => "TOKEN" ) );
|
||||
next unless ($certificateResetSession);
|
||||
return $certificateResetSession
|
||||
if ( $certificateResetSession->data->{_type}
|
||||
and $certificateResetSession->data->{_type} =~ /^certificate$/ );
|
||||
}
|
||||
|
||||
# No modifyaccount session found, return empty string
|
||||
return "";
|
||||
}
|
||||
|
||||
# Use Certificate Update parameter to send mail
|
||||
|
||||
sub sendmail {
|
||||
|
||||
my ( $self, $mail, $subject, $body, $html ) = @_;
|
||||
|
||||
$self->{mailFrom} = $self->conf->{certificateResetByMailSender};
|
||||
$self->{mailReplyTo} = $self->conf->{certificateResetByMailReplyTo};
|
||||
|
||||
return $self->send_mail( $mail, $subject, $body, $html );
|
||||
}
|
||||
|
||||
sub checkCertificateValidity {
|
||||
|
||||
my ( $self, $notAfter, $delay ) = @_;
|
||||
my $dtNow; # now in format DateTime
|
||||
my $days; # difference between NotAfter and now
|
||||
|
||||
my $f = DateTime::Format::RFC3339->new();
|
||||
|
||||
my $dtNotAfter = $f->parse_datetime($notAfter);
|
||||
$self->userLogger->debug("Not After Date: $dtNotAfter");
|
||||
|
||||
$dtNow = DateTime->now;
|
||||
$days = $dtNotAfter->delta_days($dtNow)->delta_days;
|
||||
$dtNow->add_duration( DateTime::Duration->new( days => $delay ) );
|
||||
|
||||
# test if ( now + $validity ) > certificate_expiration
|
||||
if ( DateTime::compare( $dtNow, $dtNotAfter ) >= 0 ) {
|
||||
|
||||
# certificate is about to expire
|
||||
$self->userLogger->debug(
|
||||
"Certificate is about to expire or already expired");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
# certificate is still valid
|
||||
$self->userLogger->debug("Certificate is still valid for $days days");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub certificateHash {
|
||||
|
||||
my ( $self, $file ) = @_;
|
||||
my $cert;
|
||||
|
||||
{
|
||||
local $/ = undef; # Slurp mode
|
||||
open CERT, "$file" or die;
|
||||
$cert = <CERT>;
|
||||
close CERT;
|
||||
}
|
||||
|
||||
# Normalize certificate
|
||||
$cert =~ s/-----(BEGIN|END) CERTIFICATE-----//gi;
|
||||
$cert =~ s/["]//gi;
|
||||
$cert = decode_base64($cert);
|
||||
|
||||
#$self->userLogger->debug( "UserBinary::".$cert);
|
||||
return $cert;
|
||||
}
|
||||
|
||||
1;
|
|
@ -36,7 +36,7 @@
|
|||
# - Authorizations for connected users (always):
|
||||
# * GET /mysession/?whoami : get "my" uid
|
||||
# * GET /mysession/?authorizationfor=<base64-encoded-url>: ask if url is
|
||||
# authorizated
|
||||
# authorized
|
||||
# * PUT /mysession/<type> : update some
|
||||
# persistent data
|
||||
# (restricted)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.8
|
||||
// Generated by CoffeeScript 1.12.7
|
||||
|
||||
/*
|
||||
LemonLDAP::NG TOTP registration script
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
|
||||
"PE-7":"لقد تم قطع اتصالك",
|
||||
"PE-6":"تم تغير كلمة المرور بنجاح",
|
||||
"PE0":"تمت مصادقة المستخدم",
|
||||
|
@ -84,6 +85,10 @@
|
|||
"PE92":"Access not granted on GET service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"قبول",
|
||||
"accessDenied":"ليس لديك إذن بالدخول لهذا التطبيق",
|
||||
|
@ -274,5 +279,8 @@
|
|||
"yourPhone":"رقم هاتفك",
|
||||
"yourProfile":"ملفك الشخصي",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,10 @@
|
|||
"PE92":"Zugang zum GET-Service nicht genehmigt",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
|
||||
"2fRegRequired":"Dieser Dienst benötigt Zwei-Faktor-Authentifizierung. Bitte legen Sie ein Gerät an und gehen dann zum Portal zurück.",
|
||||
"accept":"Akzeptieren",
|
||||
"accessDenied":"Sie haben keine Zugriffsberechtigung für diese Anwendung",
|
||||
|
@ -274,5 +278,8 @@
|
|||
"yourPhone":"Ihre Telefonnummer",
|
||||
"yourProfile":"Ihr Profil",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Access not granted on GET service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Accept",
|
||||
"accessDenied":"You have no access authorization for this application",
|
||||
|
@ -111,6 +114,7 @@
|
|||
"checkUser":"Check user SSO profile",
|
||||
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
|
||||
"checkUserComputeSession":"Computed session data!",
|
||||
"certificateReset":"Reset my certificate",
|
||||
"choose2f":"Choose your second factor",
|
||||
"chooseApp":"Choose an application your are allowed to access to",
|
||||
"clickHere":"Please click here",
|
||||
|
@ -158,6 +162,7 @@
|
|||
"lastLogins":"Last logins",
|
||||
"lastName":"Last name",
|
||||
"linkValidUntil":"This message contains a link to reset your password, this link is valid until ",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"loginHistory":"Login history",
|
||||
"login":"Login",
|
||||
"logout":"Logout",
|
||||
|
@ -218,6 +223,7 @@
|
|||
"resendConfirmMail":"Resend confirmation mail?",
|
||||
"resentConfirm":"Do you want the confirmation mail to be resent?",
|
||||
"resetFavApps":"Reset my favorite Apps.",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"resetPwd":"Reset my password",
|
||||
"rest2f":"Verification code",
|
||||
"rightsReloadNeedsLogout": "Rights reloads need to logout and login again",
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Acceso no autorizado al servicio GET",
|
||||
"PE93":"Acceso no concedido al servicio de SUPLANTACIÓN",
|
||||
"PE94":"Un atributo obligatorio no está presente",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"Este servicio necesita la autenticación de dos factores. Registre un dispositivo ahora, luego reingrese al portal.",
|
||||
"accept":"Aceptar",
|
||||
"accessDenied":"No está autorizado a acceder a esta aplicación",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Su número telefónico",
|
||||
"yourProfile":"Su perfil",
|
||||
"yourTotpKey":"Su llave TOTP",
|
||||
"yubikey2f":"Yubikey"
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Access not granted on GET service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Hyväksy",
|
||||
"accessDenied":"Sinulla ei ole käyttöoikeutta tähän sovellukseen",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Puhelinnumerosi",
|
||||
"yourProfile":"Profiilisi",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Accès non autorisé au service GET",
|
||||
"PE93":"Accès non autorisé au service d'Usurpation d'Identité",
|
||||
"PE94":"Un attribut exigé n'est pas disponible",
|
||||
"PE95":"votre certificat est invalid ou expire bientot.Veuillez contacter votre administrateur",
|
||||
"PE96":"Veuillez selectionner votre nouveau certificat",
|
||||
"PE97":"Veuillez selectionner votre nouveau certificat",
|
||||
"2fRegRequired":"Ce service requiert une authentification à deux facteurs. Enregistrez un équipement ici et retournez au portail.",
|
||||
"accept":"Accepter",
|
||||
"accessDenied":"Vous n'avez pas les droits d'accès à cette application",
|
||||
|
@ -274,5 +277,9 @@
|
|||
"yourPhone":"Votre numéro de téléphone",
|
||||
"yourProfile":"Vos informations personnelles",
|
||||
"yourTotpKey":"Votre clef TOTP",
|
||||
"yubikey2f":"Yubikey"
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Votre certificat à été bien réinitialisé",
|
||||
"linkValidUntilCertif":"Ce message contient un lien pour réinitialiser votre certificat, ce lien est valide jusqu'au ",
|
||||
"certificateReset":"Réinitialiser votre certificat"
|
||||
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Accesso non concesso sul servizio GET",
|
||||
"PE93":"Accesso non concesso sul servizio IMPERSONATION",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"Questo servizio richiede un'autenticazione a doppio fattore. Registrare un dispositivo ora, quindi tornare al portale.",
|
||||
"accept":"Accetta",
|
||||
"accessDenied":"Non hai un'autorizzazione di accesso per questa applicazione",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Numero di telefono",
|
||||
"yourProfile":"Il tuo profilo",
|
||||
"yourTotpKey":"La tua chiave TOTP",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Onbevoegde toegang tot de GET-service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Accept",
|
||||
"accessDenied":"You have no access authorization for this application",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Acesso não autorizado ao serviço GET",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"Um atributo exigido não está disponível",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Accept",
|
||||
"accessDenied":"You have no access authorization for this application",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Access not granted on GET service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Accept",
|
||||
"accessDenied":"You have no access authorization for this application",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Truy cập không được cấp trên dịch vụ GET",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"Một thuộc tính bắt buộc không có sẵn",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Chấp nhận",
|
||||
"accessDenied":"Bạn không có quyền truy cập vào ứng dụng này",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"Số điện thoại của bạn",
|
||||
"yourProfile":"Profile của bạn",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
"PE92":"Access not granted on GET service",
|
||||
"PE93":"Access not granted on IMPERSONATION service",
|
||||
"PE94":"A required attribute is not available",
|
||||
"PE95":"Your certificate is invalid or expires soon",
|
||||
"PE96":"Please select your new certificate",
|
||||
"PE97":"Please select your new certificate",
|
||||
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
|
||||
"accept":"Accept 方法",
|
||||
"accessDenied":"您无权访问此应用",
|
||||
|
@ -274,5 +277,8 @@
|
|||
"yourPhone":"您的电话号码",
|
||||
"yourProfile":"您的档案",
|
||||
"yourTotpKey":"Your TOTP key",
|
||||
"yubikey2f":"Yubikey"
|
||||
}
|
||||
"yubikey2f":"Yubikey",
|
||||
"resetCertificateOK":"Your certificate was reset sucessfully",
|
||||
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
|
||||
"certificateReset":"Reset my certificate"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
<TMPL_INCLUDE NAME="header.tpl">
|
||||
|
||||
<div id="mailcontent" class="container">
|
||||
|
||||
<TMPL_IF NAME="AUTH_ERROR">
|
||||
<div class="message message-<TMPL_VAR NAME="AUTH_ERROR_TYPE"> alert">
|
||||
<span trmsg="<TMPL_VAR NAME="AUTH_ERROR">"></span>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_FORM">
|
||||
<div class="card">
|
||||
<form action="#" method="post" class="login" role="form">
|
||||
<div class="form">
|
||||
|
||||
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
|
||||
<input type="hidden" name="url" value="<TMPL_VAR NAME="AUTH_URL">" />
|
||||
<TMPL_IF NAME="CHOICE_VALUE">
|
||||
<input type="hidden" id="authKey" name="<TMPL_VAR NAME="CHOICE_PARAM">" value="<TMPL_VAR NAME="CHOICE_VALUE">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<h3 trspan="certificateReset"> Reset Your Certificate</h3>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-envelope"></i> </span>
|
||||
</div>
|
||||
<input name="mail" type="text" value="<TMPL_VAR NAME="MAIL">" class="form-control" trplaceholder="mail" required />
|
||||
</div>
|
||||
|
||||
<TMPL_IF NAME=CAPTCHA_SRC>
|
||||
<div class="form-group">
|
||||
<img src="<TMPL_VAR NAME=CAPTCHA_SRC>" class="img-thumbnail" />
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-eye"></i> </span>
|
||||
</div>
|
||||
<input type="text" name="captcha" size="<TMPL_VAR NAME=CAPTCHA_SIZE>" class="form-control" trplaceholder="captcha" required autocomplete="off" />
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
<TMPL_IF NAME="TOKEN">
|
||||
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<button type="submit" class="btn btn-success">
|
||||
<span class="fa fa-envelope-open"></span>
|
||||
<span trspan="sendPwd">Send me a link</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_RESEND_FORM">
|
||||
<div class="card">
|
||||
<form action="#" method="post" class="login" role="form">
|
||||
<div class="form">
|
||||
|
||||
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
|
||||
<input type="hidden" name="url" value="<TMPL_VAR NAME="AUTH_URL">" />
|
||||
<TMPL_IF NAME="CHOICE_VALUE">
|
||||
<input type="hidden" id="authKey" name="<TMPL_VAR NAME="CHOICE_PARAM">" value="<TMPL_VAR NAME="CHOICE_VALUE">" />
|
||||
</TMPL_IF>
|
||||
<TMPL_IF NAME="MAIL">
|
||||
<input type="hidden" value="<TMPL_VAR NAME="MAIL">" name="mail">
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="TOKEN">
|
||||
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<h3 trspan="resendConfirmMail">Resend confirmation mail?</h3>
|
||||
|
||||
<p class="alert alert-info">
|
||||
<span trspan="pwdResetAlreadyIssued">A Certificate reset request was already issued on</span>
|
||||
<TMPL_VAR NAME="STARTMAILDATE">.
|
||||
<span trspan="resentConfirm">Do you want the confirmation mail to be resent?</span>
|
||||
</p>
|
||||
|
||||
<TMPL_IF NAME=CAPTCHA_SRC>
|
||||
<div class="form-group">
|
||||
<img src="<TMPL_VAR NAME=CAPTCHA_SRC>" class="img-thumbnail" />
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-eye"></i> </span>
|
||||
</div>
|
||||
<input type="text" name="captcha" size="<TMPL_VAR NAME=CAPTCHA_SIZE>" class="form-control" trplaceholder="captcha" required autocomplete="off"/>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<input id="resendconfirmation" type="checkbox" name="resendconfirmation" aria-describedby="resendconfirmationlabel" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="form-control">
|
||||
<label for="resendconfirmation" id="resendconfirmationlabel" trspan="confirmPwd">Yes , resend the mail</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success">
|
||||
<span class="fa fa-envelope-open"></span>
|
||||
<span trspan="submit">Submit</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_CERTIF_FORM">
|
||||
<div class="card" id="password">
|
||||
<form action="#" method="post" enctype="multipart/form-data" class="password" role="form">
|
||||
<div class="form">
|
||||
|
||||
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
|
||||
<input type="hidden" name="url" value="<TMPL_VAR NAME="AUTH_URL">" />
|
||||
<TMPL_IF NAME="CHOICE_VALUE">
|
||||
<input type="hidden" id="authKey" name="<TMPL_VAR NAME="CHOICE_PARAM">" value="<TMPL_VAR NAME="CHOICE_VALUE">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="TOKEN">
|
||||
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<h3 trspan="certificateReset">Reset your Certificate</h3>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-upload"></i> </span>
|
||||
</div>
|
||||
<input name="certif" type="file" class="form-control" accept=".pem, .crt,application/x-pem-file", trplaceholder="UploadCertificate" required />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success">
|
||||
<span class="fa fa-envelope-open"></span>
|
||||
<span trspan="submit">Submit</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_CONFIRMMAILSENT">
|
||||
<div class="card">
|
||||
<form action="#" method="post" class="login" role="form">
|
||||
<div class="form">
|
||||
<h3 trspan="mailSent2">A message has been sent to your mail address.</h3>
|
||||
<p class="alert alert-info">
|
||||
<span trspan="linkValidUntilCertif">This message contains a link to reset your certificate. This link is valid until </span>
|
||||
<TMPL_VAR NAME="EXPMAILDATE">.
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_MAILSENT">
|
||||
<div class="card">
|
||||
<form action="#" method="post" class="login" role="form">
|
||||
<div class="form">
|
||||
<h3 trspan="resetCertificateOK">A confirmation has been sent to your mail address.</h3>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="<TMPL_VAR NAME="PORTAL_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="CHOICE_VALUE">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="CHOICE_VALUE"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>" class="btn btn-primary" role="button">
|
||||
<span class="fa fa-home"></span>
|
||||
<span trspan="back2Portal">Go back to portal</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<TMPL_INCLUDE NAME="footer.tpl">
|
|
@ -53,6 +53,13 @@
|
|||
<span trspan="resetPwd">Reset my password</span>
|
||||
</a>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_UPDATECERTIF">
|
||||
<a class="btn btn-primary" href="<TMPL_VAR NAME="MAILCERTIF_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>">
|
||||
<span class="fa fa-refresh"></span>
|
||||
<span trspan="certificateReset">Reset my certificate</span>
|
||||
</a>
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="DISPLAY_REGISTER">
|
||||
<a class="btn btn-secondary" href="<TMPL_VAR NAME="REGISTER_URL">?skin=<TMPL_VAR NAME="SKIN"><TMPL_IF NAME="key">&<TMPL_VAR NAME="CHOICE_PARAM">=<TMPL_VAR NAME="key"></TMPL_IF><TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>">
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset",
|
||||
"accountCreated":"تم إنشاء حسابك و إرسال كلمة المرور المؤقتة إلى بريدك الإلكتروني.",
|
||||
"autoMail":"تم إرسال هذا البريد تلقائيا ",
|
||||
"click2Register":"انقر هنا لتأكيد تسجيل حسابك",
|
||||
|
@ -15,4 +16,4 @@
|
|||
"requestIssuedFromIP":"الطلب قد أرسل من عنوان الآي بي",
|
||||
"yourLoginCodeIs":"Your login code is",
|
||||
"yourLoginIs":"تسجيل الدخول الخاص بك هو"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset",
|
||||
"accountCreated":"Your account has been created, your temporary password has been sent to your mail address.",
|
||||
"autoMail":"This mail was sent automatically",
|
||||
"click2Register":"Click here to confirm your account registration",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset,"
|
||||
"accountCreated":"Tunnus on luotu, väliaikainen salasana on lähetetty sähköpostiisi.",
|
||||
"autoMail":"Tämä sähköpostiviesti lähetetään automaattisesti",
|
||||
"click2Register":"Klikkaa tästä vahvistaaksesi käyttäjätunnuksesi rekisteröinnin",
|
||||
|
@ -15,4 +16,4 @@
|
|||
"requestIssuedFromIP":"The request was issued from IP",
|
||||
"yourLoginCodeIs":"Your login code is",
|
||||
"yourLoginIs":"Your login is"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Votre certificat a été réinitialisé avec succés",
|
||||
"accountCreated":"Votre compte a été créé, un mot de passe temporaire a été envoyé à votre adresse mail.",
|
||||
"autoMail":"Ceci est un message automatique",
|
||||
"click2Register":"Cliquez ici pour confirmer l'enregistrement de votre compte",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset",
|
||||
"accountCreated":"Il tuo account è stato creato, una password temporanea è stata inviata al tuo indirizzo di posta elettronica.",
|
||||
"autoMail":"Questa mail é stata inviata automaticamente",
|
||||
"click2Register":"Clicca qui per confermare la registrazione del tuo account",
|
||||
|
@ -15,4 +16,4 @@
|
|||
"requestIssuedFromIP":"La richiesta è stata emessa da IP",
|
||||
"yourLoginCodeIs":"Il tuo codice di accesso è",
|
||||
"yourLoginIs":"Il tuo login é"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset",
|
||||
"accountCreated":"Tài khoản của bạn đã được tạo, mật khẩu tạm thời vừa được gửi đến địa chỉ thư điện tử của bạn.",
|
||||
"autoMail":"Thư này đã được gửi tự động",
|
||||
"click2Register":"Nhấn ở đây để xác nhận việc đăng ký tài khoản của bạn",
|
||||
|
@ -15,4 +16,4 @@
|
|||
"requestIssuedFromIP":"Yêu cầu được gửi đi từ địa chỉ IP",
|
||||
"yourLoginCodeIs":"Your login code is",
|
||||
"yourLoginIs":"Đăng nhập của bạn là"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"resetCertificat":"Your certificate was reset",
|
||||
"accountCreated":"您的账户已被创建,初始密码已发送至您的邮箱",
|
||||
"autoMail":"此邮件是自动发送的",
|
||||
"click2Register":"请点击此处已确认您的账户注册",
|
||||
|
@ -15,4 +16,4 @@
|
|||
"requestIssuedFromIP":"此请求来自IP地址",
|
||||
"yourLoginCodeIs":"Your login code is",
|
||||
"yourLoginIs":"您登陆的账户是"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<TMPL_INCLUDE NAME="mail_header.tpl">
|
||||
|
||||
<p>
|
||||
<span trspan="hello">Hello</span> $cn,<br />
|
||||
<br />
|
||||
<span trspan="certificatReset">Your certificate was reset sucessfully.</span>
|
||||
</p>
|
||||
|
||||
<TMPL_INCLUDE NAME="mail_footer.tpl">
|
|
@ -117,7 +117,7 @@ m#iframe src="http://auth.idp.com(/saml/relaySingleLogoutPOST)\?(relay=.*?)"#s,
|
|||
ok(
|
||||
getHeader( $res, 'Content-Security-Policy' ) =~
|
||||
/child-src auth.idp.com/,
|
||||
' Frame is authorizated'
|
||||
' Frame is authorized'
|
||||
)
|
||||
or explain( $res->[1],
|
||||
'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
|
@ -132,7 +132,7 @@ m#iframe src="http://auth.idp.com(/saml/relaySingleLogoutPOST)\?(relay=.*?)"#s,
|
|||
'Get iframe'
|
||||
);
|
||||
ok( getHeader( $res, 'Content-Security-Policy' ) !~ /frame-ancestors/,
|
||||
' Framing authorizated' )
|
||||
' Framing authorized' )
|
||||
or explain( $res->[1], 'No frame-ancestors' );
|
||||
( $host, $url, $query ) =
|
||||
expectAutoPost( $res, 'auth.sp.com', '/saml/proxySingleLogout',
|
||||
|
|
|
@ -126,7 +126,7 @@ m#iframe src="http://auth.sp.com(/saml/proxySingleLogout)\?(SAMLRequest=.*?)"#,
|
|||
my $query = $2;
|
||||
ok(
|
||||
getHeader( $res, 'Content-Security-Policy' ) =~ /child-src auth.sp.com/,
|
||||
'Frame is authorizated'
|
||||
'Frame is authorized'
|
||||
)
|
||||
or explain( $res->[1],
|
||||
'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
|
|
|
@ -209,7 +209,7 @@ count(1);
|
|||
my $url = $1;
|
||||
$query = $2;
|
||||
ok( getHeader( $res, 'Content-Security-Policy' ) =~ /child-src auth.idp.com/,
|
||||
'Frame is authorizated' )
|
||||
'Frame is authorized' )
|
||||
or
|
||||
explain( $res->[1], 'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
count(1);
|
||||
|
|
|
@ -209,7 +209,7 @@ count(1);
|
|||
my $url = $1;
|
||||
$query = $2;
|
||||
ok( getHeader( $res, 'Content-Security-Policy' ) =~ /child-src auth.idp.com/,
|
||||
'Frame is authorizated' )
|
||||
'Frame is authorized' )
|
||||
or
|
||||
explain( $res->[1], 'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
count(1);
|
||||
|
|
|
@ -177,7 +177,7 @@ count(1);
|
|||
my $url = $1;
|
||||
$query = $2;
|
||||
ok( getHeader( $res, 'Content-Security-Policy' ) =~ /child-src auth.idp.com/,
|
||||
'Frame is authorizated' )
|
||||
'Frame is authorized' )
|
||||
or
|
||||
explain( $res->[1], 'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
count(1);
|
||||
|
|
|
@ -169,7 +169,7 @@ count(1);
|
|||
my $url = $1;
|
||||
$query = $2;
|
||||
ok( getHeader( $res, 'Content-Security-Policy' ) =~ /child-src auth.idp.com/,
|
||||
'Frame is authorizated' )
|
||||
'Frame is authorized' )
|
||||
or
|
||||
explain( $res->[1], 'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
count(1);
|
||||
|
|
|
@ -262,7 +262,7 @@ SKIP: {
|
|||
ok(
|
||||
getHeader( $res, 'Content-Security-Policy' ) =~
|
||||
/child-src auth.idp.com/,
|
||||
'Frame is authorizated'
|
||||
'Frame is authorized'
|
||||
)
|
||||
or explain( $res->[1],
|
||||
'Content-Security-Policy => ...child-src auth.idp.com' );
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
use File::Copy;
|
||||
|
||||
BEGIN {
|
||||
eval {
|
||||
require 't/test-lib.pm';
|
||||
require 't/smtp.pm';
|
||||
};
|
||||
}
|
||||
|
||||
my ( $res, $user );
|
||||
my $maintests = 6;
|
||||
|
||||
SKIP: {
|
||||
eval
|
||||
'require Email::Sender::Simple; use GD::SecurityImage;use Image::Magick;';
|
||||
if ($@) {
|
||||
skip 'Missing dependencies ' . $@, $maintests;
|
||||
|
||||
}
|
||||
|
||||
skip 'LLNGTESTLDAP is not set', $maintests unless ( $ENV{LLNGTESTLDAP} );
|
||||
require 't/test-ldap.pm';
|
||||
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'debug',
|
||||
useSafeJail => 1,
|
||||
portalDisplayRegister => 1,
|
||||
authentication => 'SSL',
|
||||
userDB => 'LDAP',
|
||||
passwordDB => 'LDAP',
|
||||
registerDB => 'LDAP',
|
||||
ldapServer => 'ldap://127.0.0.1:19389/',
|
||||
ldapBase => 'ou=users,dc=example,dc=com',
|
||||
managerDn => 'cn=admin,dc=example,dc=com',
|
||||
managerPassword => 'admin',
|
||||
captcha_mail_enabled => 0,
|
||||
portalDisplayCertificateResetByMail => 1,
|
||||
certificateResetByMailCeaAttribute => 'description',
|
||||
certificateResetByMailCertificateAttribute =>
|
||||
'userCertificate;binary',
|
||||
certificateResetByMailStep1Body =>
|
||||
'Click here <a href="$url"> to confirm your mail. It will expire $expMailDate',
|
||||
certificateResetByMailStep2Body =>
|
||||
'Certificate Reset sucessfully!',
|
||||
certificateValidityDelay => 30
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Test form
|
||||
# ------------------------
|
||||
ok( $res = $client->_get( '/certificateReset', accept => 'text/html' ),
|
||||
'Reset form', );
|
||||
my ( $host, $url, $query ) = expectForm( $res, '#', undef, 'mail' );
|
||||
|
||||
$query = 'mail=dwho%40badwolf.org';
|
||||
|
||||
# Post email
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/certificateReset', IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Post mail'
|
||||
);
|
||||
|
||||
ok( mail() =~ m#a href="http://auth.example.com/certificateReset\?(.*?)"#,
|
||||
'Found link in mail' );
|
||||
$query = $1;
|
||||
my $querymail = $query;
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/certificateReset',
|
||||
query => $query,
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Post mail token received by mail'
|
||||
);
|
||||
|
||||
# print STDERR Dumper($res);
|
||||
|
||||
( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' );
|
||||
ok( $res->[2]->[0] =~ /certif/s, ' Ask for a new certificate file' );
|
||||
|
||||
#print STDERR Dumper($query);
|
||||
my %inputs = split( /[=&]/, $query );
|
||||
my %querytab = split( /[=&]/, $querymail );
|
||||
|
||||
# Create the certificate file
|
||||
my $cert = "-----BEGIN CERTIFICATE-----
|
||||
MIIDdzCCAl+gAwIBAgIJAKGx8siw7lkRMA0GCSqGSIb3DQEBCwUAMFExCzAJBgNV
|
||||
BAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBBcmlzMREwDwYDVQQK
|
||||
DAhMaW5hZ29yYTEOMAwGA1UECwwFTElOSUQwIBcNMTkwNzA0MTcyNjI4WhgPMjEx
|
||||
OTA2MTAxNzI2MjhaMFExCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAM
|
||||
BgNVBAcMBVBBcmlzMREwDwYDVQQKDAhMaW5hZ29yYTEOMAwGA1UECwwFTElOSUQw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3iyeNE2vpURgdY7xwxS16
|
||||
xUJANPuMSrCfy1E/xpCtbP02zK0B11DkT81AnTHgvsWYuiubR1P3Phhh+JLsLRho
|
||||
Grzu9xjaiKXQ+kT1cAiq6skZljphykXBfKUb73W9CPntHL/zl3XyIfu+dWyCGbqa
|
||||
jHw0Llomi8JqU/XKB6XAYumsV3QzFMM7ECm5HeV3BxfIBwoIOwfwINDUrAGS3h4k
|
||||
WH/iiqwG7uSuADupSfdmOrvE7rYZupPas4YATX1m5hmON++9pRRFVEoNeOV1qyGY
|
||||
G7swH1uoO2hAgwKIw0vinft/pJLqe3qhrJwNCIZFHaDEx/PRERFeeEH9/6HSz5kt
|
||||
AgMBAAGjUDBOMB0GA1UdDgQWBBTFv6pQT/9IBWEAGhILGCcweVfHmTAfBgNVHSME
|
||||
GDAWgBTFv6pQT/9IBWEAGhILGCcweVfHmTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
|
||||
DQEBCwUAA4IBAQBFYneMW5etMnsA3/PdvOqx/ijBF98aKlB4U4IKZpdDRAcsstdL
|
||||
BSsHRQbHXtb9VdlDWvUnNg5DmjsA8DkOXKXGPGM9ncu9tQi9EoInbOJTMaEsIr2j
|
||||
zrLj6PHTvazy+6Au+R/9N5u3WQtq/Z2xoN/+bbQ1dyjXgQmBZFizHP32l5AdgBDT
|
||||
jF7xMHxJ6Jxz9lkI+d9v0TzpxTStsaC+pbDfoouNc2deZkv84YTIrD0EPSHFDH5d
|
||||
u5i9b+lrWZeCtpVEPzSYpnBwGfepbZAzfVRKJm7wZPCe7KxqMGXQLVBkD8oN7vA1
|
||||
lkRrWfQftwmLyNIu3HfSgXlgAZS30ymfbzBU
|
||||
-----END CERTIFICATE-----";
|
||||
|
||||
open my $FH2, '>', '/tmp/v296ZJQ_kG';
|
||||
print {$FH2} "$cert";
|
||||
close $FH2;
|
||||
|
||||
$res = $client->app->( {
|
||||
'plack.request.query' => bless( {
|
||||
'skin' => $querytab{'skin'},
|
||||
'mail_token' => $querytab{'mail_token'}
|
||||
},
|
||||
'Hash::MultiValue'
|
||||
),
|
||||
'PATH_INFO' => '/certificateReset',
|
||||
'HTTP_ACCEPT' =>
|
||||
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'HTTP_ORIGIN' => 'http://auth.example.com',
|
||||
'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||
'REQUEST_SCHEME' => 'http',
|
||||
'HTTP_CACHE_CONTROL' => 'max-age=0',
|
||||
|
||||
'plack.request.merged' => bless( {
|
||||
'skin' => $querytab{'skin'},
|
||||
'mail_token' => $querytab{'mail_token'},
|
||||
'url' => '',
|
||||
'token' => $inputs{'token'}
|
||||
},
|
||||
'Hash::MultiValue'
|
||||
),
|
||||
'REMOTE_PORT' => '36674',
|
||||
'QUERY_STRING' => $querymail,
|
||||
'SERVER_SIGNATURE' => '',
|
||||
'psgix.input.buffered' => 1,
|
||||
'HTTP_UPGRADE_INSECURE_REQUESTS' => '1',
|
||||
'CONTENT_TYPE' =>
|
||||
'multipart/form-data; boundary=----WebKitFormBoundarybabRY9u6K9tERoLr',
|
||||
'plack.request.upload' => bless( {
|
||||
'certif' => bless( {
|
||||
'headers' => bless( {
|
||||
'content-disposition' =>
|
||||
'form-data; name="certif"; filename="user.pem"',
|
||||
'content-type' =>
|
||||
'application/x-x509-ca-cert',
|
||||
'::std_case' => {
|
||||
'content-disposition' =>
|
||||
'Content-Disposition'
|
||||
}
|
||||
},
|
||||
'HTTP::Headers'
|
||||
),
|
||||
'filename' => 'user.pem',
|
||||
'tempname' => '/tmp/v296ZJQ_kG',
|
||||
'size' => 1261
|
||||
},
|
||||
'Plack::Request::Upload'
|
||||
)
|
||||
},
|
||||
'Hash::MultiValue'
|
||||
),
|
||||
'psgi.streaming' => 1,
|
||||
'plack.request.body' => bless( {
|
||||
'skin' => 'bootstrap',
|
||||
'url' => '',
|
||||
'token' => $inputs{'token'}
|
||||
},
|
||||
'Hash::MultiValue'
|
||||
),
|
||||
'SCRIPT_URL' => '/certificateReset',
|
||||
'SERVER_NAME' => 'auth.example.com',
|
||||
'HTTP_REFERER' => 'http://auth.example.com/certificateReset?'
|
||||
. $querymail,
|
||||
'HTTP_CONNECTION' => 'close',
|
||||
'CONTENT_LENGTH' => '1759',
|
||||
'SCRIPT_URI' => 'http://auth.example.com/certificateReset',
|
||||
'plack.cookie.parsed' => {
|
||||
'llnglanguage' => 'fr'
|
||||
},
|
||||
'SERVER_PORT' => '80',
|
||||
'SERVER_NAME' => 'auth.example.com',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||
'SCRIPT_NAME' => '',
|
||||
'HTTP_USER_AGENT' =>
|
||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||
'HTTP_COOKIE' => 'llnglanguage=fr',
|
||||
'REMOTE_ADDR' => '127.0.0.1',
|
||||
'REQUEST_URI' => '/certificateReset?' . $querymail,
|
||||
'plack.cookie.string' => 'llnglanguage=fr',
|
||||
'SERVER_ADDR' => '127.0.0.1',
|
||||
'psgi.url_scheme' => 'http',
|
||||
'psgix.harakiri' => '',
|
||||
'HTTP_HOST' => 'auth.example.com'
|
||||
}
|
||||
);
|
||||
|
||||
ok( mail() =~ /Certificate Reset sucessfully/, 'Certificate was changed' );
|
||||
|
||||
}
|
||||
count($maintests);
|
||||
stopLdapServer() if $ENV{LLNGTESTLDAP};
|
||||
done_testing( count() );
|
Loading…
Reference in New Issue