Fix unit test
This commit is contained in:
commit
b1232739a0
|
@ -27,6 +27,9 @@ theses :
|
|||
* **OAUTH2_USERINFO_ENDPOINT**: ``oauth2/userinfo``
|
||||
* **OAUTH2_TOKEN_ENDPOINT**: ``oauth2/token``
|
||||
* **OAUTH2_ID_MAP**: ``sub``
|
||||
* **OAUTH2_USERNAME_MAP**: ``sub``
|
||||
* **OAUTH2_FULLNAME_MAP**: ``name``
|
||||
* **OAUTH2_EMAIL_MAP**: ``email``
|
||||
|
||||
|
||||
.. danger::
|
||||
|
|
|
@ -246,7 +246,8 @@ Here are some recommended configurations:
|
|||
_whatToTrace varchar(64),
|
||||
_session_kind varchar(15),
|
||||
user text,
|
||||
_utime bigint
|
||||
_utime bigint,
|
||||
ipAddr varchar(64)
|
||||
);
|
||||
CREATE INDEX uid1 ON sessions (_whatToTrace) USING BTREE;
|
||||
CREATE INDEX _s1 ON sessions (_session_kind);
|
||||
|
|
|
@ -18,7 +18,7 @@ Just enable it in the manager (section “plugins”).
|
|||
displayed (by example: ``!$anonymous``)
|
||||
- **Unrestricted users rule**: Rule to define which users can check
|
||||
ALL users. ``Identities use rule`` is bypassed.
|
||||
- **Hidden attributes**: Attributes not displayed
|
||||
- **Hidden attributes**: Session attributes not displayed
|
||||
- **Attributes used for searching sessions**: User's attributes used
|
||||
for searching sessions in backend if ``whatToTrace`` fails. Useful
|
||||
to look for sessions by mail or givenName. Let it blank to search
|
||||
|
@ -31,11 +31,27 @@ Just enable it in the manager (section “plugins”).
|
|||
even empty ones
|
||||
- **Display persistent session data**: Rule to define which users can display
|
||||
persistent session data
|
||||
- **Hidden headers**: Sent headers whose value is masked except for unrestricted users.
|
||||
Key is a Virtualhost name and value represents a headers list.
|
||||
A blank value obfuscates ALL relative Virtualhost sent headers.
|
||||
Note that just valued hearders are masked.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
By examples :
|
||||
By example:
|
||||
|
||||
\* test1.example.com => ``Auth-User mail``
|
||||
Just 'Auth-User' and 'mail' headers are masked if valued.
|
||||
|
||||
\* test2.example.com => '' ALL valued headers are masked.
|
||||
|
||||
Unrestricted users can see the masked headers.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
By example:
|
||||
|
||||
\* Search attributes => ``mail uid givenName``
|
||||
|
||||
|
|
|
@ -503,6 +503,9 @@ Some options are available:
|
|||
- Maintenance mode: reject all requests with a maintenance message
|
||||
- Aliases: list of aliases for this virtual host *(avoid to rewrite
|
||||
rules,...)*
|
||||
- Access to trace: can be used for overwriting REMOTE_CUSTOM with a custom function.
|
||||
Provide a comma separated parameters list with custom function path and args.
|
||||
By example: My::accessToTrace, Doctor, Who
|
||||
- Type: handler type (normal,
|
||||
:doc:`ServiceToken Handler<servertoserver>`,
|
||||
:doc:`DevOps Handler<devopshandler>`,...)
|
||||
|
@ -515,6 +518,30 @@ Some options are available:
|
|||
seconds. This TTL can be customized for each virtual host.
|
||||
|
||||
|
||||
.. attention::
|
||||
|
||||
A hash reference containing $req, $session, $vhost, $custom and an array reference
|
||||
with provided parameters is passed to the custom function.
|
||||
|
||||
::
|
||||
|
||||
package My;
|
||||
|
||||
sub accessToTrace {
|
||||
my $hash = shift;
|
||||
my $custom = $hash->{custom};
|
||||
my $req = $hash->{req};
|
||||
my $vhost = $hash->{vhost};
|
||||
my $custom = $hash->{custom};
|
||||
my $params = $hash->{params};
|
||||
my $session = $hash->{session};
|
||||
|
||||
return "$custom alias $params->[0]_$params->[1]:$session->{groups}";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
.. danger::
|
||||
|
||||
A same virtual host can serve many locations. Each
|
||||
|
|
|
@ -10,7 +10,7 @@ extracted from the users database by the
|
|||
:ref:`users module<start-authentication-users-and-password-databases>`.
|
||||
|
||||
To create a variable, you've just to map a user attributes in LL::NG
|
||||
using ``Variables`` » ``Exported variables``. For each variable, The
|
||||
using ``Variables`` » ``Exported variables``. For each variable, the
|
||||
first field is the name which will be used in rules, macros or headers
|
||||
and the second field is the name of the user database field.
|
||||
|
||||
|
|
|
@ -25,19 +25,20 @@ Inside this jail, you can access to:
|
|||
* Information about current request
|
||||
* Extended functions:
|
||||
|
||||
* date_
|
||||
* checkLogonHours_
|
||||
* checkDate_
|
||||
* basic_
|
||||
* unicode2iso_
|
||||
* iso2unicode_
|
||||
* groupMatch_
|
||||
* listMatch_
|
||||
* inGroup_
|
||||
* checkDate_
|
||||
* checkLogonHours_
|
||||
* date_
|
||||
* encrypt_
|
||||
* token_
|
||||
* groupMatch_
|
||||
* has2f_ (|new| in version 2.0.10)
|
||||
* inGroup_ (|new| in version 2.0.8)
|
||||
* isInNet6_
|
||||
* varIsInUri_
|
||||
* iso2unicode_
|
||||
* listMatch_ (|new| in version 2.0.7)
|
||||
* token_
|
||||
* unicode2iso_
|
||||
* varIsInUri_ (|new| in version 2.0.7)
|
||||
|
||||
|
||||
.. |new| image:: /documentation/new.png
|
||||
|
@ -238,6 +239,40 @@ Simple usage example:
|
|||
|
||||
groupMatch($hGroups, 'description', 'Service 1')
|
||||
|
||||
|
||||
.. _has2f:
|
||||
|
||||
has2f
|
||||
~~~~~
|
||||
|
||||
.. versionadded:: 2.0.10
|
||||
|
||||
This function tests if the current user has registered a second factor. The following types are supported:
|
||||
|
||||
* :doc:`TOTP<totp2f>`
|
||||
* :doc:`U2F<u2f>`
|
||||
* :doc:`UBK<yubikey2f>`
|
||||
|
||||
Example::
|
||||
|
||||
has2f()
|
||||
has2f('UBK')
|
||||
has2f('UBK') or has2f('TOTP')
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
Do **NOT** use this test to check if the user has **used** their second factor for logging in!
|
||||
This test only checks if the user has registered a second factor. Regardless of their **current**
|
||||
authentication level. It can be used to simplify second factor activation rules.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Before version 2.0.10, you need to use the following syntax ::
|
||||
|
||||
$_2fDevices =~ /"type":\s*"TOTP"/s
|
||||
|
||||
.. _listMatch:
|
||||
|
||||
listMatch
|
||||
|
|
|
@ -57,6 +57,12 @@ logs, go into Manager, ``General Parameters`` > ``Logging`` >
|
|||
User log samples
|
||||
----------------
|
||||
|
||||
.. note::
|
||||
|
||||
The user name set in user log messages is configured with `whatToTrace` parameter, except
|
||||
for messages corresponding to failed authentification, whe the user name logged is the
|
||||
login used by the user.
|
||||
|
||||
Authentication:
|
||||
|
||||
::
|
||||
|
@ -84,6 +90,12 @@ Logout:
|
|||
|
||||
[notice] User dwho has been disconnected from LDAP (81.20.13.21)
|
||||
|
||||
Password change:
|
||||
|
||||
::
|
||||
|
||||
[notice] Password changed for dwho (81.20.13.21)
|
||||
|
||||
Access to a CAS application non registered in configuration (when CAS server is open):
|
||||
|
||||
::
|
||||
|
|
|
@ -27,6 +27,16 @@ attribute you see there can be used in a rule!
|
|||
In Perl, ``eq`` means *Equal* and must be used on strings.
|
||||
``==`` should be used only on numbers
|
||||
|
||||
.. danger::
|
||||
|
||||
In Perl, ``@`` character means an array and ``%`` a hash!
|
||||
If you want to write a macro with these characters, you have to escape them like this:
|
||||
|
||||
::
|
||||
|
||||
$my_email = "$uid\@my-domain.com"
|
||||
$percent = "$rate\%more"
|
||||
|
||||
- Restricting access to specific groups
|
||||
|
||||
::
|
||||
|
@ -64,6 +74,17 @@ attribute you see there can be used in a rule!
|
|||
|
||||
$_auth ne 'Demo'
|
||||
|
||||
- Checking if the user has a an **available** second factor.
|
||||
|
||||
::
|
||||
|
||||
# Since 2.0.10
|
||||
has2f()
|
||||
has2f('TOTP')
|
||||
has2f('TOTP') or has2f('U2F')
|
||||
|
||||
# Before 2.0.10
|
||||
$_2fDevices =~ /"type":\s*"TOTP"/s
|
||||
|
||||
.. tip::
|
||||
|
||||
|
@ -71,6 +92,7 @@ attribute you see there can be used in a rule!
|
|||
strings. ``\b`` means *word Boundary*. (?:) means *non capturing*
|
||||
parenthesis.
|
||||
|
||||
|
||||
Using environment variables
|
||||
---------------------------
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ Presentation
|
|||
|
||||
LemonLDAP::NG uses Safe jail to evaluate all expressions:
|
||||
|
||||
- Access rule
|
||||
- Header
|
||||
- Access rules
|
||||
- Headers
|
||||
- Form replay parameters
|
||||
- Macros
|
||||
- Groups
|
||||
|
@ -31,3 +31,19 @@ to disable it.
|
|||
|
||||
To do this, go into Manager > General Parameters > Advanced Parameters >
|
||||
Security > Use Safe Jail and disable it.
|
||||
|
||||
|
||||
Assignment test
|
||||
===============
|
||||
|
||||
Presentation
|
||||
------------
|
||||
|
||||
Perl comparaisons are done by using ``eq`` for strings or ``==`` for integers.
|
||||
To avoid an unwanted assignment like ``$authLevel = 5`` (BAD EXPRESSION!),
|
||||
you can enable ``Avoid assignment in expressions`` option.
|
||||
|
||||
To do this, go into Manager > General Parameters > Advanced Parameters >
|
||||
Security > Avoid assignment in expressions and enable it.
|
||||
|
||||
DISABLE by default.
|
|
@ -7,15 +7,12 @@ options.
|
|||
Disk cache (sessions an configuration)
|
||||
--------------------------------------
|
||||
|
||||
::
|
||||
|
||||
chcon -R -t httpd_sys_rw_content_t /var/cache/lemonldap-ng
|
||||
|
||||
To persist the rule:
|
||||
You need to set the correct context on the cache directory
|
||||
|
||||
::
|
||||
|
||||
semanage fcontext -a -t http_sys_content_t /var/cache/lemonldap-ng
|
||||
semanage fcontext --add -t httpd_cache_t -f a '/var/cache/lemonldap-ng(/.*)?'
|
||||
restorecon -R /var/cache/lemonldap-ng/
|
||||
|
||||
LDAP
|
||||
----
|
||||
|
|
|
@ -74,6 +74,12 @@ In the manager (advanced parameters), you just have to enable it:
|
|||
required even if users are not registered. This is automatically done
|
||||
when "activation" is simply set to "on".
|
||||
|
||||
|
||||
.. danger::
|
||||
|
||||
Range is tested backward and forward to prevent
|
||||
positive or negative clock drift.
|
||||
|
||||
Enrollment
|
||||
----------
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ backups and a rollback plan ready!
|
|||
------
|
||||
|
||||
- New dependency: IO::Socket::Timeout
|
||||
- TOTP check tolerates forward AND backward clock drift (totp2fRange)
|
||||
- Avoid assignment in expressions option is disabled by default
|
||||
|
||||
2.0.9
|
||||
-----
|
||||
|
@ -31,7 +33,7 @@ backups and a rollback plan ready!
|
|||
(see also `#2244 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/2244>`__)
|
||||
- SAML SOAP calls are now using ``text/xml`` instead of ``application/xml`` as the MIME Content Type, as required by `the SOAP standard <https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383526>`__
|
||||
- Incremental lock times values can now be set in BruteForceProtection plugin through Manager.
|
||||
It must be a list of comma separated values. Default values are ``5, 15, 60, 300, 600``
|
||||
It MUST be a list of comma separated values. Default values are ``5, 15, 60, 300, 600``
|
||||
|
||||
Cookie issues with Chrome
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -190,14 +190,14 @@ use macros, local macros,...
|
|||
|
||||
.. attention::
|
||||
|
||||
|
||||
|
||||
- Since many HTTP servers refuse non ascii headers, it is recommended
|
||||
to use encode_base64() function to transmit those headers
|
||||
- Don't forget to add an empty string as second argument to
|
||||
encode_base64 function to avoid a "newline" characters insertion in
|
||||
result
|
||||
- Header names must contain only letters and "-" character
|
||||
- Header names must contain only letters and "-" character.
|
||||
With Nginx, you can bypass this restriction by using
|
||||
``underscores_in_headers on;`` directive
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,4 +8,16 @@ sub get_additional_arg {
|
|||
return $_[0];
|
||||
}
|
||||
|
||||
sub accessToTrace {
|
||||
my $hash = shift;
|
||||
my $custom = $hash->{custom};
|
||||
my $req = $hash->{req};
|
||||
my $vhost = $hash->{vhost};
|
||||
my $custom = $hash->{custom};
|
||||
my $params = $hash->{params};
|
||||
my $session = $hash->{session};
|
||||
|
||||
return "$custom alias $params->[0]_$params->[1]:$session->{groups} with $session->{$params->[2]}";
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -22,7 +22,7 @@ dirName=__pwd__/e2e-tests/conf
|
|||
checkXSS = 0
|
||||
portalSkin = bootstrap
|
||||
staticPrefix = /static
|
||||
languages = fr, en, vi, it, ar, de, zh, nl, es, pt, ro, tr
|
||||
languages = fr, en, vi, it, ar, de, zh, nl, es, pt, ro, tr, zh_TW
|
||||
templateDir = __pwd__/lemonldap-ng-portal/site/templates
|
||||
portalStatus = 1
|
||||
totp2fActivation = 1
|
||||
|
@ -49,7 +49,7 @@ viewerAllowDiff = 1
|
|||
|
||||
staticPrefix = /static
|
||||
instanceName = Demo
|
||||
languages = fr, en, vi, ar, de, it, zh, tr
|
||||
languages = fr, en, vi, ar, it, zh, tr, zh_TW, es
|
||||
templateDir = __pwd__/lemonldap-ng-manager/site/templates
|
||||
|
||||
[node-handler]
|
||||
|
|
|
@ -164,6 +164,16 @@
|
|||
"default": "accept"
|
||||
}
|
||||
},
|
||||
"vhostOptions":{
|
||||
"manager.example.com": {
|
||||
"vhostMaintenance": 0,
|
||||
"vhostPort": -1,
|
||||
"vhostHttps": -1,
|
||||
"vhostAliases": "",
|
||||
"vhostServiceTokenTTL": -1,
|
||||
"vhostAccessToTrace": "My::accessToTrace, Doctor, Who","vhostType":"Main"
|
||||
}
|
||||
},
|
||||
"loginHistoryEnabled": 1,
|
||||
"macros": {
|
||||
"UA" : "$ENV{HTTP_USER_AGENT}",
|
||||
|
|
|
@ -196,7 +196,7 @@ staticPrefix = __PORTALSTATICDIR__
|
|||
templateDir = __PORTALTEMPLATESDIR__
|
||||
|
||||
; languages: available languages for portal interface
|
||||
languages = en, fr, vi, it, ar, de, fi, tr, pl
|
||||
languages = en, fr, vi, it, ar, de, fi, tr, pl, zh_TW, es
|
||||
|
||||
; II - Optional parameters (overwrite configuration)
|
||||
|
||||
|
@ -383,7 +383,7 @@ staticPrefix = __MANAGERSTATICDIR__
|
|||
templateDir = __MANAGERTEMPLATESDIR__
|
||||
|
||||
; languages: available languages for manager interface
|
||||
languages = fr, en, it, vi, ar, tr, pl
|
||||
languages = en, fr, it, vi, ar, tr, pl, zh_TW, es
|
||||
|
||||
; Manager modules enabled
|
||||
; Set here the list of modules you want to see in manager interface
|
||||
|
|
|
@ -29,8 +29,8 @@ use constant DEFAULTCONFBACKEND => "File";
|
|||
use constant DEFAULTCONFBACKENDOPTIONS => (
|
||||
dirName => '/usr/local/lemonldap-ng/data/conf',
|
||||
);
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:State|User|XSS)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)s)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:State|User|XSS)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|wsdlServer)$/;
|
||||
|
||||
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ our $specialNodeHash = {
|
|||
};
|
||||
|
||||
our $doubleHashKeys = 'issuerDBGetParameters';
|
||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|ombModule)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
|
||||
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
|
||||
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
|
||||
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)';
|
||||
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
|
||||
|
@ -30,7 +30,7 @@ our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)
|
|||
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:uth(?:orizationCodeExpiration|nLevel)|llow(?:PasswordGrant|Offline)|ccessTokenExpiration|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|(?:ExportedVar|Macro)s)';
|
||||
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ign(?:S[LS]OMessage|atureMethod)|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
|
||||
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:S(?:ign(?:S[LS]OMessage|atureMethod)|essionNotOnOrAfterTimeout)|N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|AuthnLevel|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)';
|
||||
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
|
||||
our $virtualHostKeys = '(?:vhost(?:A(?:ccessToTrace|uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
|
||||
|
||||
our $authParameters = {
|
||||
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],
|
||||
|
|
|
@ -9,6 +9,7 @@ use strict;
|
|||
use Encode;
|
||||
use MIME::Base64;
|
||||
use Lemonldap::NG::Common::IPv6;
|
||||
use JSON::XS;
|
||||
|
||||
#use AutoLoader qw(AUTOLOAD);
|
||||
|
||||
|
@ -18,7 +19,7 @@ our $VERSION = '2.1.0';
|
|||
# Not that only functions, not methods, can be written here
|
||||
our $functions =
|
||||
[
|
||||
qw(&checkLogonHours &date &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri)
|
||||
qw(&checkLogonHours &date &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri &has2f)
|
||||
];
|
||||
|
||||
## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
|
||||
|
@ -64,8 +65,8 @@ sub checkLogonHours {
|
|||
# Use time_correction
|
||||
if ($time_correction) {
|
||||
my ( $sign, $time ) = ( $time_correction =~ /([+|-]?)(\d+)/ );
|
||||
if ( $sign =~ /-/ ) { $hourpos -= $time; }
|
||||
else { $hourpos += $time; }
|
||||
if ( $sign =~ /-/ ) { $hourpos -= $time; }
|
||||
else { $hourpos += $time; }
|
||||
}
|
||||
|
||||
# Get the corresponding byte
|
||||
|
@ -224,4 +225,26 @@ sub varIsInUri {
|
|||
: $uri =~ /$wanteduri$attribute/o;
|
||||
}
|
||||
|
||||
my $json = JSON::XS->new;
|
||||
|
||||
sub has2f {
|
||||
my ( $session, $type ) = @_;
|
||||
return 0 unless ( $session->{_2fDevices} );
|
||||
|
||||
my $_2fDevices = eval { $json->decode( $session->{_2fDevices} ); };
|
||||
return 0 if ( $@ or ref($_2fDevices) ne "ARRAY" );
|
||||
|
||||
my $length = scalar @{$_2fDevices};
|
||||
|
||||
# Empty array
|
||||
return 0 unless $length;
|
||||
|
||||
# Array has one value and we did not specify a type, succeed
|
||||
if ($type) {
|
||||
my @found = grep { lc( $_->{type} ) eq lc($type) } @{$_2fDevices};
|
||||
return ( @found ? 1 : 0 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -19,8 +19,9 @@ sub verifyCode {
|
|||
$self->logger->error('Bad characters in TOTP secret');
|
||||
return -1;
|
||||
}
|
||||
for ( 0 .. $range ) {
|
||||
for ( -$range .. $range ) {
|
||||
if ( $code eq $self->_code( $s, $_, $interval, $digits ) ) {
|
||||
$self->userLogger->info("Codes match at range $_");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t
|
|||
t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t
|
||||
t/71-Lemonldap-NG-Handler-PSGI-OAuth2.t
|
||||
t/99-pod.t
|
||||
t/custom.pm
|
||||
t/lmConf-1.json
|
||||
t/sessions/lock/.exists
|
||||
t/test-psgi-lib.pm
|
||||
|
|
|
@ -238,6 +238,8 @@ sub defaultValuesInit {
|
|||
$conf->{vhostOptions}->{$vhost}->{vhostAuthnLevel};
|
||||
$class->tsv->{serviceTokenTTL}->{$vhost} =
|
||||
$conf->{vhostOptions}->{$vhost}->{vhostServiceTokenTTL};
|
||||
$class->tsv->{accessToTrace}->{$vhost} =
|
||||
$conf->{vhostOptions}->{$vhost}->{vhostAccessToTrace};
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
@ -626,6 +628,9 @@ sub substitute {
|
|||
# handle inGroup
|
||||
$expr =~ s/\binGroup\(([^)]*)\)/listMatch(\$s->{'hGroups'},$1,1)/g;
|
||||
|
||||
# handle has2f
|
||||
$expr =~ s/\bhas2f\(([^),]*)\)/has2f(\$s,$1)/g;
|
||||
|
||||
return $expr;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ sub checkType {
|
|||
sub run {
|
||||
my ( $class, $req, $rule, $protection ) = @_;
|
||||
my ( $id, $session );
|
||||
my $vhost = $class->resolveAlias($req);
|
||||
|
||||
return $class->DECLINED unless ( $class->is_initial_req($req) );
|
||||
|
||||
|
@ -149,9 +150,41 @@ sub run {
|
|||
|
||||
# ACCOUNTING (1. Inform web server)
|
||||
$class->set_user( $req, $session->{ $class->tsv->{whatToTrace} } );
|
||||
$class->set_custom( $req, $session->{ $class->tsv->{customToTrace} } )
|
||||
if $class->tsv->{customToTrace}
|
||||
and $session->{ $class->tsv->{customToTrace} };
|
||||
|
||||
my $custom;
|
||||
$custom = $session->{ $class->tsv->{customToTrace} }
|
||||
if ( $class->tsv->{customToTrace}
|
||||
and $session->{ $class->tsv->{customToTrace} } );
|
||||
if ( $class->tsv->{accessToTrace}->{$vhost} ) {
|
||||
my ( $function, @params ) = split /\s*,\s*/,
|
||||
$class->tsv->{accessToTrace}->{$vhost};
|
||||
if ( $function =~ qr/^(?:\w+(?:::\w+)*(?:\s+\w+(?:::\w+)*)*)?$/ ) {
|
||||
my $c = eval {
|
||||
no strict 'refs';
|
||||
&{$function}( {
|
||||
req => $req,
|
||||
vhost => $vhost,
|
||||
session => $session,
|
||||
custom => $custom,
|
||||
params => \@params
|
||||
}
|
||||
);
|
||||
};
|
||||
if ($@) {
|
||||
$class->logger->error(
|
||||
"Failed to overwrite customToTrace: $@");
|
||||
}
|
||||
else {
|
||||
$class->logger->debug("Overwrite customToTrace with: $c");
|
||||
$custom = $c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$class->logger->error(
|
||||
"accessToTrace: Bad custom function name");
|
||||
}
|
||||
}
|
||||
$class->set_custom( $req, $custom ) if $custom;
|
||||
|
||||
# AUTHORIZATION
|
||||
return ( $class->forbidden( $req, $session ), $session )
|
||||
|
@ -794,10 +827,14 @@ sub localUnlog {
|
|||
if ( $id //= $class->fetchId($req) ) {
|
||||
|
||||
# Delete local cache
|
||||
if ( $class->tsv->{refLocalStorage}
|
||||
and $class->tsv->{refLocalStorage}->get($id) )
|
||||
{
|
||||
$class->tsv->{refLocalStorage}->remove($id);
|
||||
if ( $class->tsv->{sessionCacheModule} ) {
|
||||
my $module = $class->tsv->{sessionCacheModule};
|
||||
my $options = $class->tsv->{sessionCacheOptions};
|
||||
eval "use $module;";
|
||||
my $cache = $module->new($options);
|
||||
if ( $cache->get($id) ) {
|
||||
$cache->remove($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# change 'tests => 1' to 'tests => last_test_to_print';
|
||||
|
||||
use strict;
|
||||
use Test::More tests => 13;
|
||||
use Test::More tests => 17;
|
||||
require 't/test.pm';
|
||||
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
||||
|
||||
|
@ -60,3 +60,39 @@ ok(
|
|||
ok( $res = &$code, "Function works" );
|
||||
ok( $res == 1, 'Get good result' );
|
||||
|
||||
$sub = "sub { return(has2f(\$_[0],\$_[1])) }";
|
||||
$code = $jail->jail_reval($sub);
|
||||
ok(
|
||||
( defined($code) and ref($code) eq 'CODE' ),
|
||||
'checkDate extended function is defined'
|
||||
);
|
||||
is(
|
||||
$code->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
"TOTP"
|
||||
),
|
||||
1,
|
||||
"Function works"
|
||||
);
|
||||
is(
|
||||
$code->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
"UBK"
|
||||
),
|
||||
0,
|
||||
"Function works"
|
||||
);
|
||||
is(
|
||||
$code->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
),
|
||||
1,
|
||||
"Function works"
|
||||
);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
# change 'tests => 1' to 'tests => last_test_to_print';
|
||||
|
||||
use Test::More tests => 9;
|
||||
use Test::More tests => 13;
|
||||
require 't/test.pm';
|
||||
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
|
||||
|
||||
|
@ -54,3 +54,40 @@ $listMatch = $jail->jail_reval($sub5);
|
|||
ok( ( defined($listMatch) and ref($listMatch) eq 'CODE' ),
|
||||
'listMatch function is defined' );
|
||||
ok( &$listMatch eq '0', 'Get good result' );
|
||||
|
||||
# Test has2f method
|
||||
my $sub6 = "sub { return(has2f(\$_[0],\$_[1])) }";
|
||||
my $has2f = $jail->jail_reval($sub6);
|
||||
ok(
|
||||
( defined($has2f) and ref($has2f) eq 'CODE' ),
|
||||
'checkDate extended function is defined'
|
||||
);
|
||||
is(
|
||||
$has2f->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
"TOTP"
|
||||
),
|
||||
1,
|
||||
"Function works"
|
||||
);
|
||||
is(
|
||||
$has2f->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
),
|
||||
1,
|
||||
"Function works"
|
||||
);
|
||||
is(
|
||||
$has2f->( {
|
||||
_2fDevices =>
|
||||
"[{\"name\":\"MyTOTP\",\"_secret\":\"g5fsxwf4d34biemlojsbbvhgtskrssos\",\"epoch\":1602173208,\"type\":\"TOTP\"}]"
|
||||
},
|
||||
"UBK"
|
||||
),
|
||||
0,
|
||||
"Function works"
|
||||
);
|
||||
|
|
|
@ -4,7 +4,10 @@ use MIME::Base64;
|
|||
use Data::Dumper;
|
||||
use URI::Escape;
|
||||
|
||||
require 't/test-psgi-lib.pm';
|
||||
BEGIN {
|
||||
require 't/test-psgi-lib.pm';
|
||||
require 't/custom.pm';
|
||||
}
|
||||
|
||||
init('Lemonldap::NG::Handler::Server::Nginx');
|
||||
|
||||
|
@ -31,6 +34,28 @@ count(4);
|
|||
# Authentified queries
|
||||
# --------------------
|
||||
|
||||
# Authorized query
|
||||
ok(
|
||||
$res =
|
||||
$client->_get( '/', undef, 'test4.example.com', "lemonldap=$sessionId" ),
|
||||
'Authentified query'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
|
||||
count(2);
|
||||
|
||||
# Check headers
|
||||
%h = @{ $res->[1] };
|
||||
ok(
|
||||
$h{'Lm-Remote-Custom'} eq
|
||||
'dwho@badwolf.org alias Doctor_Who:users; timelords by using Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1',
|
||||
'Lm-Remote-Custom is overwriten'
|
||||
)
|
||||
or explain(
|
||||
\%h,
|
||||
'Lm-Remote-Custom => "dwho@badwolf.org alias Doctor_Who:users; timelords by using Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1"'
|
||||
);
|
||||
count(1);
|
||||
|
||||
# Authorized query
|
||||
ok( $res = $client->_get( '/', undef, undef, "lemonldap=$sessionId" ),
|
||||
'Authentified query' );
|
||||
|
@ -43,7 +68,11 @@ ok( $h{'Headername1'} eq 'Auth-User', 'Headername1 is set to "Auth-User"' )
|
|||
or explain( \%h, 'Headername1 => "Auth-User"' );
|
||||
ok( $h{'Headervalue1'} eq 'dwho', 'Headervalue1 is set to "dwho"' )
|
||||
or explain( \%h, 'Headervalue1 => "dwho"' );
|
||||
count(2);
|
||||
ok(
|
||||
$h{'Lm-Remote-Custom'} eq 'dwho@badwolf.org',
|
||||
'Lm-Remote-Custom is set "dwho@badwolf.org"'
|
||||
) or explain( \%h, 'Lm-Remote-User => "dwho@badwolf.org"' );
|
||||
count(3);
|
||||
|
||||
# Request an URI protected by custom function -> allowed
|
||||
ok(
|
||||
|
|
|
@ -4,6 +4,7 @@ use MIME::Base64;
|
|||
|
||||
BEGIN {
|
||||
require 't/test-psgi-lib.pm';
|
||||
require 't/custom.pm';
|
||||
}
|
||||
|
||||
init('Lemonldap::NG::Handler::PSGI');
|
||||
|
@ -39,7 +40,6 @@ ok(
|
|||
'Authentified query'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
|
||||
|
||||
count(2);
|
||||
|
||||
# Denied query
|
||||
|
@ -50,7 +50,6 @@ ok(
|
|||
'Denied query'
|
||||
);
|
||||
ok( $res->[0] == 403, 'Code is 403' ) or explain( $res->[0], 403 );
|
||||
|
||||
count(2);
|
||||
|
||||
# Bad cookie
|
||||
|
@ -67,11 +66,9 @@ ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
|||
unlink(
|
||||
't/sessions/lock/Apache-Session-e5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock'
|
||||
);
|
||||
|
||||
count(2);
|
||||
|
||||
done_testing( count() );
|
||||
|
||||
clean();
|
||||
|
||||
sub Lemonldap::NG::Handler::PSGI::handler {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package My;
|
||||
|
||||
sub accessToTrace {
|
||||
my $hash = shift;
|
||||
my $custom = $hash->{custom};
|
||||
my $req = $hash->{req};
|
||||
my $vhost = $hash->{vhost};
|
||||
my $custom = $hash->{custom};
|
||||
my $params = $hash->{params};
|
||||
my $session = $hash->{session};
|
||||
|
||||
return
|
||||
"$custom alias $params->[0]_$params->[1]:$session->{groups} by using $session->{ $params->[2] }";
|
||||
}
|
||||
|
||||
1;
|
|
@ -59,6 +59,9 @@
|
|||
"^/logout": "logout_sso",
|
||||
"default": "accept"
|
||||
},
|
||||
"test4.example.com": {
|
||||
"default": "accept"
|
||||
},
|
||||
"*.example.org": {
|
||||
"^/orgdeny": "deny",
|
||||
"default": "accept"
|
||||
|
@ -74,15 +77,20 @@
|
|||
}
|
||||
},
|
||||
"macros": {
|
||||
"_whatToTrace": "$_auth eq 'SAML' ? \"$_user\\@$_idpConfKey\" : \"$_user\""
|
||||
"_whatToTrace": "$_auth eq 'SAML' ? \"$_user\\@$_idpConfKey\" : \"$_user\"",
|
||||
"UA": "$ENV{HTTP_USER_AGENT}"
|
||||
},
|
||||
"portal": "http://auth.example.com/",
|
||||
"reloadUrls": {},
|
||||
"userDB": "Demo",
|
||||
"vhostOptions": {
|
||||
"test2.example.com": {
|
||||
"vhostAuthnLevel": 5
|
||||
}
|
||||
"vhostAuthnLevel": 5
|
||||
},
|
||||
"test4.example.com": {
|
||||
"vhostAccessToTrace": "My::accessToTrace, Doctor, Who, UA"
|
||||
}
|
||||
},
|
||||
"whatToTrace": "_whatToTrace"
|
||||
"whatToTrace": "_whatToTrace",
|
||||
"customToTrace": "mail"
|
||||
}
|
||||
|
|
|
@ -196,17 +196,20 @@ site/htdocs/static/js/viewer.min.js.map
|
|||
site/htdocs/static/languages/ar.json
|
||||
site/htdocs/static/languages/de.json
|
||||
site/htdocs/static/languages/en.json
|
||||
site/htdocs/static/languages/es.json
|
||||
site/htdocs/static/languages/fr.json
|
||||
site/htdocs/static/languages/it.json
|
||||
site/htdocs/static/languages/pl.json
|
||||
site/htdocs/static/languages/tr.json
|
||||
site/htdocs/static/languages/vi.json
|
||||
site/htdocs/static/languages/zh.json
|
||||
site/htdocs/static/languages/zh_TW.json
|
||||
site/htdocs/static/logos/ar.png
|
||||
site/htdocs/static/logos/bootstrap.png
|
||||
site/htdocs/static/logos/custom.png
|
||||
site/htdocs/static/logos/de.png
|
||||
site/htdocs/static/logos/en.png
|
||||
site/htdocs/static/logos/es.png
|
||||
site/htdocs/static/logos/favicon.ico
|
||||
site/htdocs/static/logos/fr.png
|
||||
site/htdocs/static/logos/it.png
|
||||
|
@ -216,6 +219,7 @@ site/htdocs/static/logos/pl.png
|
|||
site/htdocs/static/logos/tr.png
|
||||
site/htdocs/static/logos/vi.png
|
||||
site/htdocs/static/logos/zh.png
|
||||
site/htdocs/static/logos/zh_TW.png
|
||||
site/htdocs/static/reverseTree.json
|
||||
site/htdocs/static/struct.json
|
||||
site/templates/2ndfa.tpl
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# Sessions.pm to manage sessions
|
||||
package Lemonldap::NG::Manager;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use JSON;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package Lemonldap::NG::Manager::2ndFA;
|
||||
|
||||
use 5.10.0;
|
||||
use utf8;
|
||||
use strict;
|
||||
use Mouse;
|
||||
|
@ -12,9 +11,11 @@ use Lemonldap::NG::Common::Conf::ReConstants;
|
|||
|
||||
use feature 'state';
|
||||
|
||||
extends 'Lemonldap::NG::Manager::Plugin',
|
||||
'Lemonldap::NG::Common::Conf::AccessLib',
|
||||
'Lemonldap::NG::Common::Session::REST';
|
||||
extends qw(
|
||||
Lemonldap::NG::Manager::Plugin
|
||||
Lemonldap::NG::Common::Session::REST
|
||||
Lemonldap::NG::Common::Conf::AccessLib
|
||||
);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
# This module implements all the methods that responds to '/api/*' requests
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
|
||||
extends 'Lemonldap::NG::Manager::Plugin',
|
||||
'Lemonldap::NG::Common::Conf::RESTServer',
|
||||
'Lemonldap::NG::Common::Session::REST';
|
||||
extends qw(
|
||||
Lemonldap::NG::Manager::Plugin
|
||||
Lemonldap::NG::Common::Session::REST
|
||||
Lemonldap::NG::Common::Conf::RESTServer
|
||||
);
|
||||
|
||||
use Lemonldap::NG::Manager::Api::2F;
|
||||
use Lemonldap::NG::Manager::Api::Misc;
|
||||
|
|
|
@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use JSON;
|
||||
|
|
|
@ -4,6 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use strict;
|
||||
use Lemonldap::NG::Manager::Build::Attributes;
|
||||
use Lemonldap::NG::Manager::Build::CTrees;
|
||||
|
||||
|
@ -26,7 +27,7 @@ sub _getDefaultValues {
|
|||
my $defaultAttrs = Lemonldap::NG::Manager::Build::Attributes::attributes();
|
||||
my $attrs = {};
|
||||
|
||||
foreach $attr (@allAttrs) {
|
||||
foreach my $attr (@allAttrs) {
|
||||
$attrs->{$attr} = $defaultAttrs->{$attr}->{default}
|
||||
if ( defined $defaultAttrs->{$attr}
|
||||
&& defined $defaultAttrs->{$attr}->{default} );
|
||||
|
@ -39,7 +40,7 @@ sub _hasAllowedAttributes {
|
|||
my ( $self, $attributes, $rootNode ) = @_;
|
||||
my @allowedAttributes = $self->_listAttributes($rootNode);
|
||||
|
||||
foreach $attribute ( keys %{$attributes} ) {
|
||||
foreach my $attribute ( keys %{$attributes} ) {
|
||||
if ( length( ref($attribute) ) ) {
|
||||
return {
|
||||
res => "ko",
|
||||
|
|
|
@ -4,11 +4,10 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Manager::Conf::Parser;
|
||||
use Data::Dumper;
|
||||
|
||||
extends 'Lemonldap::NG::Manager::Api::Common';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Manager::Conf::Parser;
|
||||
|
|
|
@ -5,6 +5,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use strict;
|
||||
use Mouse;
|
||||
extends 'Lemonldap::NG::Manager::Api::Common';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Manager::Conf::Parser;
|
||||
|
|
|
@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Manager::Conf::Parser;
|
||||
|
|
|
@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
|
|||
|
||||
package Lemonldap::NG::Manager::Api;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
|
||||
|
|
|
@ -22,10 +22,9 @@ sub perlExpr {
|
|||
grep( { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return -1, "__badExpression__: $err" if $err;
|
||||
return -1, "__badExpression__: $err" if $err and $conf->{'useSafeJail'};
|
||||
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/
|
||||
? ( -1, '__badExpressionAssignment__' )
|
||||
: 1;
|
||||
&& $conf->{'avoidAssignment'} ? ( 1, '__badExpressionAssignment__' ) : 1;
|
||||
}
|
||||
|
||||
sub types {
|
||||
|
@ -642,6 +641,10 @@ sub attributes {
|
|||
'default' => 'TOTP,U2F,Yubikey',
|
||||
'type' => 'text'
|
||||
},
|
||||
'avoidAssignment' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
},
|
||||
'browsersDontStorePassword' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
|
@ -891,6 +894,18 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => '_loginHistory _session_id hGroups',
|
||||
'type' => 'text'
|
||||
},
|
||||
'checkUserHiddenHeaders' => {
|
||||
'keyMsgFail' => '__badHostname__',
|
||||
'keyTest' => qr/^\S+$/,
|
||||
'test' => {
|
||||
'keyMsgFail' => '__badHeaderName__',
|
||||
'keyTest' => qr/^(?=[^\-])[\w\-\s]+(?<=[^-])$/,
|
||||
'test' => sub {
|
||||
return perlExpr(@_);
|
||||
}
|
||||
},
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'checkUserIdRule' => {
|
||||
'default' => 1,
|
||||
'test' => sub {
|
||||
|
@ -1906,6 +1921,9 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
'mail2fLogo' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'mail2fSessionKey' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'mail2fSubject' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -4144,6 +4162,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
|||
'utotp2fLogo' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'vhostAccessToTrace' => {
|
||||
'default' => '',
|
||||
'type' => 'text'
|
||||
},
|
||||
'vhostAliases' => {
|
||||
'default' => '',
|
||||
'type' => 'text'
|
||||
|
|
|
@ -27,9 +27,10 @@ sub perlExpr {
|
|||
my $err = join( '',
|
||||
grep { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_ }
|
||||
split( /\n/, $@ ) );
|
||||
return ( -1, "__badExpression__: $err" ) if $err;
|
||||
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/
|
||||
? ( -1, "__badExpressionAssignment__" )
|
||||
return ( -1, "__badExpression__: $err" )
|
||||
if ( $err && $conf->{useSafeJail} );
|
||||
return ( $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/ && $conf->{avoidAssignment} )
|
||||
? ( 1, "__badExpressionAssignment__" )
|
||||
: 1;
|
||||
}
|
||||
|
||||
|
@ -516,6 +517,17 @@ sub attributes {
|
|||
documentation => 'Display empty headers rule',
|
||||
flags => 'p',
|
||||
},
|
||||
checkUserHiddenHeaders => {
|
||||
type => 'keyTextContainer',
|
||||
keyTest => qr/^\S+$/,
|
||||
keyMsgFail => '__badHostname__',
|
||||
test => {
|
||||
keyTest => qr/^(?=[^\-])[\w\-\s]+(?<=[^-])$/,
|
||||
keyMsgFail => '__badHeaderName__',
|
||||
test => sub { return perlExpr(@_) },
|
||||
},
|
||||
documentation => 'Header values to hide if not empty',
|
||||
},
|
||||
globalLogoutRule => {
|
||||
type => 'boolOrExpr',
|
||||
default => 0,
|
||||
|
@ -1062,6 +1074,13 @@ sub attributes {
|
|||
documentation => 'Activate Safe jail',
|
||||
flags => 'hp',
|
||||
},
|
||||
avoidAssignment => {
|
||||
default => 0,
|
||||
type => 'bool',
|
||||
help => 'safejail.html',
|
||||
documentation => 'Avoid assignment in expressions',
|
||||
flags => 'hp',
|
||||
},
|
||||
whatToTrace => {
|
||||
type => 'lmAttrOrMacro',
|
||||
default => 'uid',
|
||||
|
@ -1878,6 +1897,10 @@ sub attributes {
|
|||
type => 'text',
|
||||
documentation => 'Custom logo for Mail 2F',
|
||||
},
|
||||
mail2fSessionKey => {
|
||||
type => 'text',
|
||||
documentation => 'Session parameter where mail is stored',
|
||||
},
|
||||
|
||||
# External second factor
|
||||
ext2fActivation => {
|
||||
|
@ -2239,8 +2262,9 @@ sub attributes {
|
|||
type => 'int',
|
||||
default => -1,
|
||||
},
|
||||
vhostAliases => { type => 'text', default => '' },
|
||||
vhostType => {
|
||||
vhostAccessToTrace => { type => 'text', default => '' },
|
||||
vhostAliases => { type => 'text', default => '' },
|
||||
vhostType => {
|
||||
type => 'select',
|
||||
select => [
|
||||
{ k => 'AuthBasic', v => 'AuthBasic' },
|
||||
|
|
|
@ -27,10 +27,10 @@ sub cTrees {
|
|||
help => 'configvhost.html#options',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'vhostPort', 'vhostHttps',
|
||||
'vhostMaintenance', 'vhostAliases',
|
||||
'vhostType', 'vhostAuthnLevel',
|
||||
'vhostServiceTokenTTL'
|
||||
'vhostPort', 'vhostHttps',
|
||||
'vhostMaintenance', 'vhostAliases',
|
||||
'vhostAccessToTrace', 'vhostType',
|
||||
'vhostAuthnLevel', 'vhostServiceTokenTTL'
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -271,7 +271,7 @@ sub tree {
|
|||
'managerDn', 'managerPassword',
|
||||
'ldapTimeout', 'ldapIOTimeout',
|
||||
'ldapVersion', 'ldapRaw',
|
||||
'ldapCAFile', 'ldapCAPath',
|
||||
'ldapCAFile', 'ldapCAPath',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -553,10 +553,8 @@ sub tree {
|
|||
title => 'logParams',
|
||||
help => 'logs.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'whatToTrace', 'customToTrace',
|
||||
'hiddenAttributes'
|
||||
]
|
||||
nodes =>
|
||||
[ 'whatToTrace', 'customToTrace', 'hiddenAttributes' ]
|
||||
},
|
||||
{
|
||||
title => 'cookieParams',
|
||||
|
@ -772,7 +770,6 @@ sub tree {
|
|||
{
|
||||
title => 'checkUsers',
|
||||
help => 'checkuser.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'checkUser',
|
||||
'checkUserIdRule',
|
||||
|
@ -783,6 +780,7 @@ sub tree {
|
|||
'checkUserDisplayEmptyHeaders',
|
||||
'checkUserDisplayEmptyValues',
|
||||
'checkUserDisplayPersistentInfo',
|
||||
'checkUserHiddenHeaders'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -900,6 +898,7 @@ sub tree {
|
|||
'mail2fTimeout', 'mail2fSubject',
|
||||
'mail2fBody', 'mail2fAuthnLevel',
|
||||
'mail2fLabel', 'mail2fLogo',
|
||||
'mail2fSessionKey',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -991,6 +990,7 @@ sub tree {
|
|||
'key',
|
||||
'trustedDomains',
|
||||
'useSafeJail',
|
||||
'avoidAssignment',
|
||||
'checkXSS',
|
||||
'requireToken',
|
||||
'formTimeout',
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# Read methods are inherited from Lemonldap::NG::Common::Conf::RESTServer
|
||||
package Lemonldap::NG::Manager::Conf;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Common::Conf::Constants;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package Lemonldap::NG::Manager::Conf::Tests;
|
||||
|
||||
use strict;
|
||||
use utf8;
|
||||
use Lemonldap::NG::Common::Regexp;
|
||||
use Lemonldap::NG::Handler::Main;
|
||||
|
@ -449,7 +450,7 @@ sub tests {
|
|||
"RSA_SHA1" )
|
||||
{
|
||||
undef $allsha1;
|
||||
break;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -461,7 +462,7 @@ sub tests {
|
|||
->{samlSPMetaDataOptionsSignatureMethod} ne "RSA_SHA1" )
|
||||
{
|
||||
undef $allsha1;
|
||||
break;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -865,8 +866,7 @@ sub tests {
|
|||
$appUrl =~ m#^(https?://[^/]+)(/.*)?$#;
|
||||
my $appHost = $1;
|
||||
unless ($appHost) {
|
||||
push @msg,
|
||||
"$clientConfKey CAS Application has no Service URL";
|
||||
push @msg, "$casConfKey CAS Application has no Service URL";
|
||||
$res = 0;
|
||||
next;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package Lemonldap::NG::Manager::Notifications;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use JSON qw(from_json to_json);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package Lemonldap::NG::Manager::Sessions;
|
||||
|
||||
use 5.10.0;
|
||||
use utf8;
|
||||
use strict;
|
||||
use Mouse;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package Lemonldap::NG::Manager::Viewer;
|
||||
|
||||
use 5.10.0;
|
||||
use strict;
|
||||
use utf8;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Common::Conf::Constants;
|
||||
|
|
|
@ -577,7 +577,9 @@ llapp.controller 'TreeCtrl', [
|
|||
d = $q.defer()
|
||||
d.notify 'Trying to get datas'
|
||||
$scope.waiting = true
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{node.cnodes}").then (response) ->
|
||||
console.log "Trying to get key #{node.cnodes}"
|
||||
uri = encodeURI node.cnodes
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{uri}").then (response) ->
|
||||
data = response.data
|
||||
# Manage datas errors
|
||||
if not data
|
||||
|
@ -759,7 +761,13 @@ llapp.controller 'TreeCtrl', [
|
|||
d.reject response.statusLine
|
||||
$scope.waiting = false
|
||||
else
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{if node.get then node.get else node.title}").then (response) ->
|
||||
uri = ''
|
||||
if node.get
|
||||
console.log "Trying to get key #{node.get}"
|
||||
uri = encodeURI node.get
|
||||
else
|
||||
console.log "Trying to get title #{node.title}"
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{if node.get then uri else node.title}").then (response) ->
|
||||
# Set default value if response is null or if asked by server
|
||||
data = response.data
|
||||
if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null
|
||||
|
|
|
@ -258,7 +258,9 @@ llapp.controller 'TreeCtrl', [
|
|||
d = $q.defer()
|
||||
d.notify 'Trying to get datas'
|
||||
$scope.waiting = true
|
||||
$http.get("#{window.viewPrefix}#{$scope.currentCfg.cfgNum}/#{node.cnodes}").then (response) ->
|
||||
console.log "Trying to get key #{node.cnodes}"
|
||||
uri = encodeURI node.cnodes
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{uri}").then (response) ->
|
||||
data = response.data
|
||||
# Manage datas errors
|
||||
if not data
|
||||
|
@ -360,7 +362,13 @@ llapp.controller 'TreeCtrl', [
|
|||
d.reject response.statusLine
|
||||
$scope.waiting = false
|
||||
else
|
||||
$http.get("#{window.viewPrefix}#{$scope.currentCfg.cfgNum}/#{if node.get then node.get else node.title}").then (response) ->
|
||||
uri = ''
|
||||
if node.get
|
||||
console.log "Trying to get key #{node.get}"
|
||||
uri = encodeURI node.get
|
||||
else
|
||||
console.log "Trying to get title #{node.title}"
|
||||
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{if node.get then uri else node.title}").then (response) ->
|
||||
# Set default value if response is null or if asked by server
|
||||
data = response.data
|
||||
if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1327,6 +1327,12 @@ function templates(tpl,key) {
|
|||
"id" : tpl+"s/"+key+"/"+"vhostAliases",
|
||||
"title" : "vhostAliases"
|
||||
},
|
||||
{
|
||||
"default" : "",
|
||||
"get" : tpl+"s/"+key+"/"+"vhostAccessToTrace",
|
||||
"id" : tpl+"s/"+key+"/"+"vhostAccessToTrace",
|
||||
"title" : "vhostAccessToTrace"
|
||||
},
|
||||
{
|
||||
"default" : "Main",
|
||||
"get" : tpl+"s/"+key+"/"+"vhostType",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -718,11 +718,13 @@ This file contains:
|
|||
return _download(node);
|
||||
};
|
||||
_download = function(node) {
|
||||
var d;
|
||||
var d, uri;
|
||||
d = $q.defer();
|
||||
d.notify('Trying to get datas');
|
||||
$scope.waiting = true;
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + node.cnodes).then(function(response) {
|
||||
console.log("Trying to get key " + node.cnodes);
|
||||
uri = encodeURI(node.cnodes);
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + uri).then(function(response) {
|
||||
var a, data, len, o;
|
||||
data = response.data;
|
||||
if (!data) {
|
||||
|
@ -900,7 +902,7 @@ This file contains:
|
|||
}, readError);
|
||||
};
|
||||
$scope.getKey = function(node) {
|
||||
var d, i, len, n, o, ref, tmp;
|
||||
var d, i, len, n, o, ref, tmp, uri;
|
||||
d = $q.defer();
|
||||
if (!node.data) {
|
||||
$scope.waiting = true;
|
||||
|
@ -923,7 +925,14 @@ This file contains:
|
|||
return $scope.waiting = false;
|
||||
});
|
||||
} else {
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + (node.get ? node.get : node.title)).then(function(response) {
|
||||
uri = '';
|
||||
if (node.get) {
|
||||
console.log("Trying to get key " + node.get);
|
||||
uri = encodeURI(node.get);
|
||||
} else {
|
||||
console.log("Trying to get title " + node.title);
|
||||
}
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + (node.get ? uri : node.title)).then(function(response) {
|
||||
var data;
|
||||
data = response.data;
|
||||
if ((data.value === null || (data.error && data.error.match(/setDefault$/))) && node['default'] !== null) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
// Generated by CoffeeScript 1.12.8
|
||||
|
||||
/*
|
||||
LemonLDAP::NG Viewer client
|
||||
|
@ -328,11 +328,13 @@ This file contains:
|
|||
return _download(node);
|
||||
};
|
||||
_download = function(node) {
|
||||
var d;
|
||||
var d, uri;
|
||||
d = $q.defer();
|
||||
d.notify('Trying to get datas');
|
||||
$scope.waiting = true;
|
||||
$http.get("" + window.viewPrefix + $scope.currentCfg.cfgNum + "/" + node.cnodes).then(function(response) {
|
||||
console.log("Trying to get key " + node.cnodes);
|
||||
uri = encodeURI(node.cnodes);
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + uri).then(function(response) {
|
||||
var a, data, l, len;
|
||||
data = response.data;
|
||||
if (!data) {
|
||||
|
@ -420,7 +422,7 @@ This file contains:
|
|||
}
|
||||
};
|
||||
$scope.getKey = function(node) {
|
||||
var d, i, l, len, n, ref, tmp;
|
||||
var d, i, l, len, n, ref, tmp, uri;
|
||||
d = $q.defer();
|
||||
if (!node.data) {
|
||||
$scope.waiting = true;
|
||||
|
@ -443,7 +445,14 @@ This file contains:
|
|||
return $scope.waiting = false;
|
||||
});
|
||||
} else {
|
||||
$http.get("" + window.viewPrefix + $scope.currentCfg.cfgNum + "/" + (node.get ? node.get : node.title)).then(function(response) {
|
||||
uri = '';
|
||||
if (node.get) {
|
||||
console.log("Trying to get key " + node.get);
|
||||
uri = encodeURI(node.get);
|
||||
} else {
|
||||
console.log("Trying to get title " + node.title);
|
||||
}
|
||||
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + (node.get ? uri : node.title)).then(function(response) {
|
||||
var data;
|
||||
data = response.data;
|
||||
if ((data.value === null || (data.error && data.error.match(/setDefault$/))) && node['default'] !== null) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -75,6 +75,7 @@
|
|||
"auto":"تلقائي",
|
||||
"autoSignin":"Auto Signin",
|
||||
"autoSigninRules":"القواعد",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"العودة إلى البوابة",
|
||||
"badCasProxyId":"معرف خدمة بروكسي كاس غير صالح",
|
||||
"badChoiceKey":"اسم مفتاح سيئ في قائمة الاختيارات",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"اسم النطاق سيئ",
|
||||
"badEncoding":"تشفير خاطئ",
|
||||
"badExpression":"تعبير خاطئ",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":" حقل الهيدر خاطئ",
|
||||
"badHostname":"اسم الخادم خاطئ",
|
||||
"badLdapUri":"\n URI LDAP خاطئ",
|
||||
|
@ -207,6 +208,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"اختيارالإعدادات",
|
||||
"chooseLogo":"اختيار الشعار",
|
||||
|
@ -494,6 +496,7 @@
|
|||
"mail2fAuthnLevel":"مستوى إثبات الهوية",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"شعار",
|
||||
"mail2fSessionKey":"مفتاح الجلسة الذي يحتوي على عنوان البريد الإلكتروني",
|
||||
"mailBody":"محتوى البريد الناجح",
|
||||
"mailCharset":"charset",
|
||||
"mailConfirmBody":"تأكيد محتوى البريد",
|
||||
|
@ -586,7 +589,7 @@
|
|||
"offlineSessions":"Offline sessions",
|
||||
"oldValue":"قيمة قديمة",
|
||||
"on":"تنشيط",
|
||||
"oidcAttribute":"OIDC Attribute",
|
||||
"oidcAttribute":"خاصيات OIDC",
|
||||
"oidcAuthnLevel":"مستوى إثبات الهوية",
|
||||
"oidcConsents":"OpenID Connect Consents",
|
||||
"oidcOP":" أوبين أيدي كونيكت بروفيدر",
|
||||
|
@ -1004,6 +1007,7 @@
|
|||
"verifyU2FKey":"Verify U2F key",
|
||||
"verifyTOTPKey":"Verify TOTP key",
|
||||
"version":"الإصدار",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"اسماء مستعارة",
|
||||
"vhostAuthnLevel":"مستوى إثبات الهوية واجب",
|
||||
"vhostHttps":"إتش تي تي بي س",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Automatic",
|
||||
"autoSignin":"Auto Signin",
|
||||
"autoSigninRules":"Regeln",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Back to portal",
|
||||
"badCasProxyId":"Bad CAS proxied service identifier",
|
||||
"badChoiceKey":"Bad key name in Choice menu",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Ungültiger Domainname",
|
||||
"badEncoding":"Ungültige Codierung",
|
||||
"badExpression":"Bad expression",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Bad header name",
|
||||
"badHostname":"Ungültiger Hostname",
|
||||
"badLdapUri":"Bad LDAP URI",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"Choice parameters",
|
||||
"chooseLogo":"Choose logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Authentication level",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Session key containing mail address",
|
||||
"mailBody":"Success mail content",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Confirmation mail content",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Verify U2F key",
|
||||
"verifyTOTPKey":"Verify TOTP key",
|
||||
"version":"Version",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Aliases",
|
||||
"vhostAuthnLevel":"Required authentication level",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Automatic",
|
||||
"autoSignin":"Auto Signin",
|
||||
"autoSigninRules":"Rules",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Back to portal",
|
||||
"badCasProxyId":"Bad CAS proxied service identifier",
|
||||
"badChoiceKey":"Bad key name in Choice menu",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Bad domain name",
|
||||
"badEncoding":"Bad encoding",
|
||||
"badExpression":"Bad expression",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Bad header name",
|
||||
"badHostname":"Bad hostname",
|
||||
"badLdapUri":"Bad LDAP URI",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"Choice parameters",
|
||||
"chooseLogo":"Choose logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Authentication level",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Session key containing mail address",
|
||||
"mailBody":"Success mail content",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Confirmation mail content",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Verify U2F key",
|
||||
"verifyTOTPKey":"Verify TOTP key",
|
||||
"version":"Version",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Aliases",
|
||||
"vhostAuthnLevel":"Required authentication level",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Automatique",
|
||||
"autoSignin":"Connexion automatique",
|
||||
"autoSigninRules":"Règles",
|
||||
"avoidAssignment":"Eviter une affectation dans les expressions",
|
||||
"backtoportal":"Retour au portail",
|
||||
"badCasProxyId":"Mauvais identifiant de service proxy CAS",
|
||||
"badChoiceKey":"Mauvais nom de clef dans le menu Choice",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Mauvais nom de domaine",
|
||||
"badEncoding":"Mauvais encodage",
|
||||
"badExpression":"Mauvaise expression",
|
||||
"badExpressionAssignment":"Expression contenant une affectation",
|
||||
"badExpressionAssignment":"Expression contenant une affectation. Vous pouvez utliser \\x3D pour éviter cet avertissement.",
|
||||
"badHeaderName":"Mauvais nom d'en-tête",
|
||||
"badHostname":"Mauvais nom d'hôte",
|
||||
"badLdapUri":"Mauvaise URI LDAP",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Afficher les données de session persistante",
|
||||
"checkUserDisplayEmptyHeaders":"Afficher les entêtes nuls",
|
||||
"checkUserDisplayEmptyValues":"Afficher les valeurs nulles",
|
||||
"checkUserHiddenHeaders":"Entêtes masqués",
|
||||
"checkUserSearchAttributes":"Attributs utilisés pour rechercher les sessions",
|
||||
"choiceParams":"Paramètres des choix",
|
||||
"chooseLogo":"Choisir le logo",
|
||||
|
@ -373,7 +375,7 @@
|
|||
"impersonationMergeSSOgroups":"Fusionner les groupes SSO réels et usurpés",
|
||||
"impersonationSkipEmptyValues":"Ignorer les valeurs nulles",
|
||||
"impersonationUnrestrictedUsersRule":"Règle des utilisateurs non restreints",
|
||||
"incompleteForm":"Des champs requis manquent",
|
||||
"incompleteForm":"Des champs requis sont manquants",
|
||||
"index":"Index",
|
||||
"infoFormMethod":"Méthode du formulaire d'information",
|
||||
"invalidSessionData":"Donnée de session invalide",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Niveau de l'authentification",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Clef de session contenant l'adresse email",
|
||||
"mailBody":"Contenu du message de succès",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Contenu du message de confirmation",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Vérifier la clef U2F",
|
||||
"verifyTOTPKey":"Vérifier la clef TOTP",
|
||||
"version":"Version",
|
||||
"vhostAccessToTrace":"Accès à tracer",
|
||||
"vhostAliases":"Alias",
|
||||
"vhostAuthnLevel":"Niveau d'authentification requis",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Automatico",
|
||||
"autoSignin":"Accesso automatico",
|
||||
"autoSigninRules":"Regole",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Torna al portale",
|
||||
"badCasProxyId":"Identificatore di servizio difettoso CAS proxy",
|
||||
"badChoiceKey":"Nome chiave errato nel menu Scelta",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Nome di dominio errato",
|
||||
"badEncoding":"Codifica errata",
|
||||
"badExpression":"Espressione errata",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Nome intestazione errato",
|
||||
"badHostname":"Hostname errato",
|
||||
"badLdapUri":"LDAP URI errata",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Mostra valori vuoti",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"Scelta parametri",
|
||||
"chooseLogo":"Scegli logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Livello di autenticazione",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Chiave di sessione contenente l'indirizzo di posta",
|
||||
"mailBody":"Successo contenuto di posta",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Contenuto della mail di conferma",
|
||||
|
@ -585,7 +588,7 @@
|
|||
"offlineSessions":"Offline sessions",
|
||||
"oldValue":"Vecchio valore",
|
||||
"on":"On",
|
||||
"oidcAttribute":"OIDC Attribute",
|
||||
"oidcAttribute":"Attributo OIDC",
|
||||
"oidcAuthnLevel":"Livello di autenticazione",
|
||||
"oidcConsents":"OpenID Connect Consents",
|
||||
"oidcOP":"Provider di OpenID Connect",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Verifica la chiave U2F",
|
||||
"verifyTOTPKey":"Verifica la chiave TOTP",
|
||||
"version":"Versioni",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Alias",
|
||||
"vhostAuthnLevel":"Livello di autenticazione richiesto",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Automatycznie",
|
||||
"autoSignin":"Zaloguj się automatycznie",
|
||||
"autoSigninRules":"Zasady",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Powrót do portalu",
|
||||
"badCasProxyId":"Nieprawidłowy identyfikator usługi proxy CAS",
|
||||
"badChoiceKey":"Błędna nazwa klucza w menu Wybór",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Błędna nazwa domeny",
|
||||
"badEncoding":"Błędne kodowanie",
|
||||
"badExpression":"Błędne wyrażenie",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Błędna nazwa nagłówka",
|
||||
"badHostname":"Błędna nazwa hosta",
|
||||
"badLdapUri":"Błędny identyfikator URI LDAP",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Wyświetl puste nagłówki",
|
||||
"checkUserDisplayEmptyValues":"Wyświetl puste wartości",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Atrybuty używane do wyszukiwania sesji",
|
||||
"choiceParams":"Parametry wyboru",
|
||||
"chooseLogo":"Wybierz logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Poziom uwierzytelnienia",
|
||||
"mail2fLabel":"Etykieta",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Klucz sesji zawierający adres e-mail",
|
||||
"mailBody":"Treść wiadomości o powodzeniu",
|
||||
"mailCharset":"Zestaw znaków",
|
||||
"mailConfirmBody":"Treść wiadomości potwierdzającej",
|
||||
|
@ -585,7 +588,7 @@
|
|||
"offlineSessions":"Sesje offline",
|
||||
"oldValue":"Stara wartość",
|
||||
"on":"Włączone",
|
||||
"oidcAttribute":"OIDC Attribute",
|
||||
"oidcAttribute":"Atrybut OIDC",
|
||||
"oidcAuthnLevel":"Poziom uwierzytelnienia",
|
||||
"oidcConsents":"Zgoda na OpenID Connect",
|
||||
"oidcOP":"Dostawca OpenID Connect",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Sprawdź klucz U2F",
|
||||
"verifyTOTPKey":"Sprawdź klucz TOTP",
|
||||
"version":"Wersja",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Aliasy",
|
||||
"vhostAuthnLevel":"Wymagany poziom uwierzytelnienia",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
"ADPwdMaxAge":"Parola maksimum sınırı",
|
||||
"advancedParams":"Gelişmiş parametreler",
|
||||
"allowedMarkups":"İzin verilen biçimlendirmeler:",
|
||||
"always":"Always",
|
||||
"always":"Her zaman",
|
||||
"apacheParams":"Apache parametreleri",
|
||||
"apacheAuthnLevel":"Doğrulama seviyesi",
|
||||
"application":"Uygulama",
|
||||
|
@ -55,7 +55,7 @@
|
|||
"appsInThisCat":"Bu kategorideki uygulamalar",
|
||||
"array":"Array",
|
||||
"attributesAndMacros":"Nitelikler ve Makrolar",
|
||||
"attributeName":"Attribute name",
|
||||
"attributeName":"Nitelik adı",
|
||||
"authAndUserdb":"Yetkilendirme ve kullanıcı veri tabanı",
|
||||
"authChain":"Doğrulama zinciri",
|
||||
"authChoice":"Kimlik doğrulama tercihi",
|
||||
|
@ -75,6 +75,7 @@
|
|||
"auto":"Otomatik",
|
||||
"autoSignin":"Otomatik Oturum Açma",
|
||||
"autoSigninRules":"Kurallar",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Portala geri dön",
|
||||
"badCasProxyId":"Hatalı CAS vekil servis tanımlayıcısı",
|
||||
"badChoiceKey":"Tercih menüsünde hatalı anahtar adı",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Hatalı etki alanı adı",
|
||||
"badEncoding":"Hatalı kodlama",
|
||||
"badExpression":"Hatalı ifade",
|
||||
"badExpressionAssignment":"İfade bir atama içeriyor",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Hatalı başlık adı",
|
||||
"badHostname":"Hatalı konak adı",
|
||||
"badLdapUri":"Hatalı LDAP URI",
|
||||
|
@ -100,7 +101,7 @@
|
|||
"badValue":"Hatalı değer",
|
||||
"badVariableName":"Hatalı değişken adı",
|
||||
"blackList":"Kara liste",
|
||||
"bool":"Boolean",
|
||||
"bool":"Mantıksal",
|
||||
"browse":"Göz at",
|
||||
"browsersDontStorePassword":"Kullanıcı parolasını tarayıcılarda saklamaktan kaçının",
|
||||
"browserIdAuthnLevel":"Doğrulama seviyesi",
|
||||
|
@ -193,7 +194,7 @@
|
|||
"cfgVersion":"Yapılandırma sürümü",
|
||||
"checkXSS":"XSS saldırılarını kontrol et",
|
||||
"clickHereToForce":"Zorlamak için buraya tıklayın",
|
||||
"claimName":"Claim name",
|
||||
"claimName":"İstek adı",
|
||||
"checkboxes":"Onay kutuları",
|
||||
"checkState":"Aktivasyon",
|
||||
"checkStateSecret":"Paylaşılan sır",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Kalıcı oturum verisini görüntüle",
|
||||
"checkUserDisplayEmptyHeaders":"Boş başlıkları görüntüle",
|
||||
"checkUserDisplayEmptyValues":"Boş değerleri görüntüle",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler",
|
||||
"choiceParams":"Tercih parametreleri",
|
||||
"chooseLogo":"Logo seçin",
|
||||
|
@ -377,7 +379,7 @@
|
|||
"index":"Dizin",
|
||||
"infoFormMethod":"Bilgi formu için metot",
|
||||
"invalidSessionData":"Geçersiz oturum verisi",
|
||||
"int":"Integer",
|
||||
"int":"Sayı",
|
||||
"internalReference":"Dahili referans",
|
||||
"ipAddr":"IP adresi",
|
||||
"ipAddresses":"IP adresleri",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Doğrulama seviyesi",
|
||||
"mail2fLabel":"Etiket",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Oturum anahtarı e-posta adresini içeriyor",
|
||||
"mailBody":"Başarılı e-posta içeriği",
|
||||
"mailCharset":"Karakter seti",
|
||||
"mailConfirmBody":"Doğrulama e-postası içeriği",
|
||||
|
@ -526,7 +529,7 @@
|
|||
"name":"Ad",
|
||||
"needConfirmation":"Yeni bir yapılandırma mevcut. Bunu kaydetmeye zorlamak için 'kaydet' butonunun yanındaki onay kutusuna tıklayın.",
|
||||
"networkProblem":"Ağ problemi",
|
||||
"never":"Never",
|
||||
"never":"Asla",
|
||||
"newApp":"Yeni uygulama",
|
||||
"newChain":"Yeni zincir",
|
||||
"newCat":"Yeni kategori",
|
||||
|
@ -585,7 +588,7 @@
|
|||
"offlineSessions":"Çevrimdışı oturumlar",
|
||||
"oldValue":"Eski değer",
|
||||
"on":"Açık",
|
||||
"oidcAttribute":"OIDC Attribute",
|
||||
"oidcAttribute":"OIDC niteliği",
|
||||
"oidcAuthnLevel":"Doğrulama seviyesi",
|
||||
"oidcConsents":"OpenID Connect İzinleri",
|
||||
"oidcOP":"OpenID Connect Sağlayıcısı",
|
||||
|
@ -999,10 +1002,11 @@
|
|||
"value":"Değer",
|
||||
"values":"Değerler",
|
||||
"variables":"Değişkenler",
|
||||
"variableName":"Variable name",
|
||||
"variableName":"Değişken adı",
|
||||
"verifyU2FKey":"U2F anahtarını doğrula",
|
||||
"verifyTOTPKey":"TOTP anahtarını doğrula",
|
||||
"version":"Sürüm",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Takma adlar",
|
||||
"vhostAuthnLevel":"Gereken doğrulama seviyesi",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"Tự động",
|
||||
"autoSignin":"Auto Signin",
|
||||
"autoSigninRules":"Quy tắc",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"Quay lại cổng thông tin",
|
||||
"badCasProxyId":"Dịch vụ định danh đệm bởi CAS không hợp lệ",
|
||||
"badChoiceKey":"Tên khoá không hợp lệ trong trình đơn Chọn",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"Tên miền không hợp lệ",
|
||||
"badEncoding":"Mã hoá không hợp lệ",
|
||||
"badExpression":"Biểu thức không hợp lệ",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"Tên tiêu đề không hợp lệ",
|
||||
"badHostname":"Tên máy chủ không hợp lệ",
|
||||
"badLdapUri":"URI LDAP không đúng",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"Các tham số lựa chọn",
|
||||
"chooseLogo":"Chọn logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"Mức xác thực",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Khóa phiên chứa địa chỉ thư",
|
||||
"mailBody":"Nội dung thư thành công",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Xác nhận nội dung thư",
|
||||
|
@ -585,7 +588,7 @@
|
|||
"offlineSessions":"Offline sessions",
|
||||
"oldValue":"Giá trị cũ",
|
||||
"on":"Vào",
|
||||
"oidcAttribute":"OIDC Attribute",
|
||||
"oidcAttribute":"thuộc tính OIDC",
|
||||
"oidcAuthnLevel":"Mức xác thực",
|
||||
"oidcConsents":"OpenID Connect Consents",
|
||||
"oidcOP":"Bộ cung cấp Kết nối OpenID",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Verify U2F key",
|
||||
"verifyTOTPKey":"Verify TOTP key",
|
||||
"version":"Phiên bản",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Bí danh",
|
||||
"vhostAuthnLevel":"Mức xác thực bắt buộc",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
"auto":"自动",
|
||||
"autoSignin":"Auto Signin",
|
||||
"autoSigninRules":"Rules",
|
||||
"avoidAssignment":"Avoid assignment in expressions",
|
||||
"backtoportal":"返回 portal",
|
||||
"badCasProxyId":"无效的 CAS proxied service identifier",
|
||||
"badChoiceKey":"选择菜单的无效 key ",
|
||||
|
@ -83,7 +84,7 @@
|
|||
"badDomainName":"无效的域名",
|
||||
"badEncoding":"无效的编码",
|
||||
"badExpression":"无效的表达式",
|
||||
"badExpressionAssignment":"Expression containing an assignment",
|
||||
"badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
|
||||
"badHeaderName":"无效的头部名称",
|
||||
"badHostname":"无效的主机名",
|
||||
"badLdapUri":"无效的 LDAP URI ",
|
||||
|
@ -206,6 +207,7 @@
|
|||
"checkUserDisplayPersistentInfo":"Display persistent session data",
|
||||
"checkUserDisplayEmptyHeaders":"Display empty headers",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"checkUserHiddenHeaders":"Hidden headers",
|
||||
"checkUserSearchAttributes":"Attributes used for searching sessions",
|
||||
"choiceParams":"Choice parameters",
|
||||
"chooseLogo":"Choose logo",
|
||||
|
@ -493,6 +495,7 @@
|
|||
"mail2fAuthnLevel":"认证等级",
|
||||
"mail2fLabel":"Label",
|
||||
"mail2fLogo":"Logo",
|
||||
"mail2fSessionKey":"Session key containing mail address",
|
||||
"mailBody":"Success mail content",
|
||||
"mailCharset":"Charset",
|
||||
"mailConfirmBody":"Confirmation mail content",
|
||||
|
@ -1003,6 +1006,7 @@
|
|||
"verifyU2FKey":"Verify U2F key",
|
||||
"verifyTOTPKey":"Verify TOTP key",
|
||||
"version":"Version",
|
||||
"vhostAccessToTrace":"Access to trace",
|
||||
"vhostAliases":"Aliases",
|
||||
"vhostAuthnLevel":"Required authentication level",
|
||||
"vhostHttps":"HTTPS",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 273 B |
Binary file not shown.
After Width: | Height: | Size: 7.2 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -25,30 +25,29 @@ ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
|||
|
||||
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
|
||||
or print STDERR Dumper($resBody);
|
||||
|
||||
ok( $resBody->{needConfirm} == 1, "JSON response contains \"needConfirm:1\"" )
|
||||
or print STDERR Dumper($resBody);
|
||||
|
||||
ok(
|
||||
@{ $resBody->{details}->{__warnings__} } == 3,
|
||||
'JSON response contains 3 warnings'
|
||||
@{ $resBody->{details}->{__warnings__} } == 4,
|
||||
'JSON response contains 4 warnings'
|
||||
) or print STDERR Dumper($resBody);
|
||||
count(6);
|
||||
|
||||
foreach my $i ( 0 .. 2 ) {
|
||||
foreach my $i ( 0 .. 3 ) {
|
||||
ok(
|
||||
$resBody->{details}->{__warnings__}->[$i]->{message} =~
|
||||
/\b(unprotected|cross-domain-authentication|retries)\b/,
|
||||
"Warning with 'unprotect', 'CDA' or 'retries' found"
|
||||
/\b(unprotected|cross-domain-authentication|retries|__badExpressionAssignment__)\b/,
|
||||
"Warning with 'unprotect', 'CDA', 'assignment' or 'retries' found"
|
||||
) or print STDERR Dumper($resBody);
|
||||
count(1);
|
||||
}
|
||||
count(4);
|
||||
ok(
|
||||
@{ $resBody->{details}->{__needConfirmation__} } == 2,
|
||||
'JSON response contains 2 needConfirmation'
|
||||
@{ $resBody->{details}->{__needConfirmation__} } == 1,
|
||||
'JSON response contains 1 needConfirmation'
|
||||
) or print STDERR Dumper($resBody);
|
||||
ok(
|
||||
@{ $resBody->{details}->{__changes__} } == 23,
|
||||
'JSON response contains 23 changes'
|
||||
@{ $resBody->{details}->{__changes__} } == 24,
|
||||
'JSON response contains 24 changes'
|
||||
) or print STDERR Dumper($resBody);
|
||||
|
||||
#print STDERR Dumper($resBody);
|
||||
|
@ -89,7 +88,7 @@ while ( my $c = shift @{ $resBody->{details}->{__changes__} } ) {
|
|||
}
|
||||
}
|
||||
ok( !@changes, 'All changes detected' ) or $bug = 1;
|
||||
|
||||
count(1);
|
||||
if ($bug) {
|
||||
print STDERR 'Expected not found: '
|
||||
. Dumper( \@changes )
|
||||
|
@ -99,8 +98,6 @@ if ($bug) {
|
|||
|
||||
#print STDERR Dumper(\@changes,\@cmsg);
|
||||
|
||||
count(6);
|
||||
|
||||
# TODO: check result of this
|
||||
ok( $res = &client->jsonResponse('/diff/1/2'), 'Diff called' );
|
||||
my ( @c1, @c2 );
|
||||
|
@ -108,8 +105,8 @@ ok( ( @c1 = sort keys %{ $res->[0] } ), 'diff() detects changes in conf 1' );
|
|||
ok( ( @c2 = sort keys %{ $res->[1] } ), 'diff() detects changes in conf 2' );
|
||||
ok( @c1 == 12, '12 keys changed in conf 1' )
|
||||
or print STDERR "Expect: 12 keys, get: " . join( ', ', @c1 ) . "\n";
|
||||
ok( @c2 == 16, '16 keys changed or created in conf 2' )
|
||||
or print STDERR "Expect: 16 keys, get: " . join( ',', @c2 ) . "\n";
|
||||
ok( @c2 == 17, '17 keys changed or created in conf 2' )
|
||||
or print STDERR "Expect: 17 keys, get: " . join( ',', @c2 ) . "\n";
|
||||
count(5);
|
||||
|
||||
unlink $confFiles->[1];
|
||||
|
@ -242,6 +239,11 @@ sub changes {
|
|||
{
|
||||
'confCompacted' => '1',
|
||||
'removedKeys' => 'some; keys'
|
||||
},
|
||||
{
|
||||
'new' => 1,
|
||||
'key' => 'avoidAssignment',
|
||||
'old' => '0'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1597,6 +1597,12 @@
|
|||
"title": "useSafeJail",
|
||||
"type": "bool",
|
||||
"data": 1
|
||||
}, {
|
||||
"default": 0,
|
||||
"id": "avoidAssignment",
|
||||
"title": "avoidAssignment",
|
||||
"type": "bool",
|
||||
"data": 1
|
||||
}, {
|
||||
"default": 1,
|
||||
"id": "checkXSS",
|
||||
|
|
|
@ -373,6 +373,7 @@ site/htdocs/static/common/ro.png
|
|||
site/htdocs/static/common/tr.png
|
||||
site/htdocs/static/common/vi.png
|
||||
site/htdocs/static/common/zh.png
|
||||
site/htdocs/static/common/zh_TW.png
|
||||
site/htdocs/static/languages/ar.json
|
||||
site/htdocs/static/languages/de.json
|
||||
site/htdocs/static/languages/en.json
|
||||
|
@ -387,6 +388,7 @@ site/htdocs/static/languages/ro.json
|
|||
site/htdocs/static/languages/tr.json
|
||||
site/htdocs/static/languages/vi.json
|
||||
site/htdocs/static/languages/zh.json
|
||||
site/htdocs/static/languages/zh_TW.json
|
||||
site/templates/bootstrap/2fchoice.tpl
|
||||
site/templates/bootstrap/2fregisters.tpl
|
||||
site/templates/bootstrap/captcha.tpl
|
||||
|
@ -456,6 +458,7 @@ site/templates/common/bullet_go.png
|
|||
site/templates/common/key.png
|
||||
site/templates/common/mail/ar.json
|
||||
site/templates/common/mail/en.json
|
||||
site/templates/common/mail/es.json
|
||||
site/templates/common/mail/fi.json
|
||||
site/templates/common/mail/fr.json
|
||||
site/templates/common/mail/it.json
|
||||
|
@ -463,6 +466,7 @@ site/templates/common/mail/ms.json
|
|||
site/templates/common/mail/tr.json
|
||||
site/templates/common/mail/vi.json
|
||||
site/templates/common/mail/zh_CN.json
|
||||
site/templates/common/mail/zh_TW.json
|
||||
site/templates/common/mail_2fcode.tpl
|
||||
site/templates/common/mail_certificateConfirm.tpl
|
||||
site/templates/common/mail_certificateReset.tpl
|
||||
|
@ -481,6 +485,7 @@ t/01-AuthDemo.t
|
|||
t/01-CSP-and-CORS-headers.t
|
||||
t/01-Handler-redirection-and-URL-check-by-portal.t
|
||||
t/01-pdata.t
|
||||
t/01-Unauth-Logout.t
|
||||
t/02-Password-Demo-Local-noPpolicy.t
|
||||
t/02-Password-Demo-Local-Ppolicy.t
|
||||
t/02-Password-Demo.t
|
||||
|
@ -657,6 +662,7 @@ t/64-StayConnected-with-History.t
|
|||
t/65-AutoSignin.t
|
||||
t/66-CDA-already-auth.t
|
||||
t/66-CDA-PSGI-Try.t
|
||||
t/66-CDA-with-doubleCookies.t
|
||||
t/66-CDA-with-REST.t
|
||||
t/66-CDA-with-SOAP.t
|
||||
t/66-CDA.t
|
||||
|
@ -686,6 +692,7 @@ t/69-FavApps.t
|
|||
t/70-2F-TOTP-8-with-global-storage.t
|
||||
t/70-2F-TOTP-and-U2F-with-TTL-and-JSON.t
|
||||
t/70-2F-TOTP-with-History-and-Refresh.t
|
||||
t/70-2F-TOTP-with-Range.t
|
||||
t/70-2F-TOTP-with-TTL-and-JSON.t
|
||||
t/70-2F-TOTP-with-TTL-and-XML.t
|
||||
t/70-2F-TOTP-with-TTL.t
|
||||
|
@ -705,6 +712,7 @@ t/76-2F-Ext-with-CodeActivation.t
|
|||
t/76-2F-Ext-with-GrantSession.t
|
||||
t/76-2F-Ext-with-History.t
|
||||
t/77-2F-Extra.t
|
||||
t/77-2F-Mail-SessionKey.t
|
||||
t/77-2F-Mail-with-global-storage.t
|
||||
t/77-2F-Mail.t
|
||||
t/78-2F-Upgrade-Many.t
|
||||
|
|
|
@ -40,11 +40,20 @@ has ott => (
|
|||
}
|
||||
);
|
||||
|
||||
has sessionKey => (
|
||||
is => 'rw',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
return $_[0]->{conf}->{mail2fSessionKey}
|
||||
|| $_[0]->{conf}->{mailSessionKey};
|
||||
}
|
||||
);
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
$self->{conf}->{mail2fCodeRegex} ||= '\d{6}';
|
||||
unless ( $self->conf->{mailSessionKey} ) {
|
||||
$self->error("Missing 'mailSessionKey' parameter, aborting");
|
||||
unless ( $self->sessionKey ) {
|
||||
$self->error("Missing session key parameter, aborting");
|
||||
return 0;
|
||||
}
|
||||
$self->prefix( $self->conf->{sfPrefix} )
|
||||
|
@ -65,7 +74,7 @@ sub run {
|
|||
$self->logger->debug("Generated two-factor code: $code");
|
||||
$self->ott->updateToken( $token, __mail2fcode => $code );
|
||||
|
||||
my $dest = $req->{sessionInfo}->{ $self->conf->{mailSessionKey} };
|
||||
my $dest = $req->{sessionInfo}->{ $self->sessionKey };
|
||||
unless ($dest) {
|
||||
$self->logger->error( "Could not find mail attribute for login "
|
||||
. $req->{sessionInfo}->{_user} );
|
||||
|
|
|
@ -4,13 +4,18 @@ use strict;
|
|||
use Mouse;
|
||||
|
||||
# Add constants used by this module
|
||||
use Lemonldap::NG::Portal::Main::Constants
|
||||
qw(PE_OK PE_FORBIDDENIP PE_USERNOTFOUND);
|
||||
use Lemonldap::NG::Portal::Lib::Slave;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_OK
|
||||
PE_FORBIDDENIP
|
||||
PE_USERNOTFOUND
|
||||
);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Main::Auth';
|
||||
extends qw(
|
||||
Lemonldap::NG::Portal::Main::Auth
|
||||
Lemonldap::NG::Portal::Lib::Slave
|
||||
);
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
|
|
|
@ -455,7 +455,7 @@ sub userModifyPassword {
|
|||
return PE_LDAPERROR;
|
||||
}
|
||||
|
||||
$self->{portal}->userLogger->notice("Password changed for $dn");
|
||||
$self->{portal}->logger->notice("Password changed for $dn");
|
||||
|
||||
# Rebind as manager for next LDAP operations if we were bound as user
|
||||
$self->bind() if $asUser;
|
||||
|
@ -588,8 +588,7 @@ sub userModifyPassword {
|
|||
return PE_WRONGMANAGERACCOUNT
|
||||
if ( $mesg->code == 50 || $mesg->code == 8 );
|
||||
if ( $mesg->code == 0 ) {
|
||||
$self->{portal}
|
||||
->userLogger->notice("Password changed $self->{portal}->{user}");
|
||||
$self->{portal}->logger->notice("Password changed for $dn");
|
||||
|
||||
# Rebind as manager for next LDAP operations if we were bound as user
|
||||
$self->bind() if $asUser;
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
# Slave common functions
|
||||
package Lemonldap::NG::Portal::Lib::Slave;
|
||||
|
||||
use Exporter;
|
||||
use base qw(Exporter);
|
||||
use strict;
|
||||
use Mouse;
|
||||
|
||||
our @EXPORT = qw(checkIP checkHeader);
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
# RUNNING METHODS
|
||||
|
@ -49,4 +47,4 @@ sub checkHeader {
|
|||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
1;
|
||||
|
|
|
@ -161,28 +161,29 @@ sub setPortalRoutes {
|
|||
|
||||
# psgi.js
|
||||
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
||||
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
||||
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
||||
|
||||
# portal.css
|
||||
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
||||
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
||||
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
||||
|
||||
# lmerror
|
||||
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
||||
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
||||
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
||||
|
||||
# Core REST API
|
||||
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
|
||||
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
|
||||
->addAuthRoute( ping => 'authenticated', ['GET'] )
|
||||
|
||||
# Refresh session
|
||||
->addAuthRoute( refresh => 'refresh', ['GET'] )
|
||||
|
||||
->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
|
||||
->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
|
||||
->addUnauthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
|
||||
|
||||
# Logout
|
||||
->addAuthRoute( logout => 'logout', ['GET'] );
|
||||
->addAuthRoute( logout => 'logout', ['GET'] )
|
||||
->addUnauthRoute( logout => 'unauthLogout', ['GET'] );
|
||||
|
||||
# Default routes must point to routines declared above
|
||||
$self->defaultAuthRoute('');
|
||||
|
@ -239,9 +240,11 @@ sub reloadConf {
|
|||
|
||||
# Initialize templateDir
|
||||
$self->{templateDir} =
|
||||
$self->conf->{templateDir} . '/' . $self->conf->{portalSkin};
|
||||
$self->conf->{templateDir} . '/' . $self->conf->{portalSkin}
|
||||
if ( $self->conf->{templateDir} and $self->conf->{portalSkin} );
|
||||
unless ( -d $self->{templateDir} ) {
|
||||
$self->error("Template dir $self->{templateDir} doesn't exist");
|
||||
$self->error("Template dir $self->{templateDir} doesn't exist")
|
||||
if ref( $self->{templateDir} ) eq 'SCALAR';
|
||||
return $self->fail;
|
||||
}
|
||||
$self->templateDir(
|
||||
|
@ -526,7 +529,11 @@ sub loadModule {
|
|||
$self->error("Unable to build $module object: $@");
|
||||
return 0;
|
||||
}
|
||||
( $obj and $obj->init ) or return 0;
|
||||
unless ( $obj and $obj->init ) {
|
||||
$self->error("$module init failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
$self->loadedModules->{$module} = $obj;
|
||||
return $obj;
|
||||
}
|
||||
|
|
|
@ -179,6 +179,27 @@ sub checkLogout {
|
|||
PE_OK;
|
||||
}
|
||||
|
||||
sub checkUnauthLogout {
|
||||
my ( $self, $req ) = @_;
|
||||
if ( defined $req->param('logout') ) {
|
||||
$self->userLogger->info('Unauthenticated logout request');
|
||||
$self->logger->debug('Cleaning pdata');
|
||||
$self->logger->debug("Removing $self->{conf}->{cookieName} cookie");
|
||||
$req->pdata({});
|
||||
$req->addCookie(
|
||||
$self->cookie(
|
||||
name => $self->conf->{cookieName},
|
||||
domain => $self->conf->{domain},
|
||||
secure => $self->conf->{securedCookie},
|
||||
expires => 'Wed, 21 Oct 2015 00:00:00 GMT',
|
||||
value => 0
|
||||
)
|
||||
);
|
||||
$req->steps( [ sub { PE_LOGOUT_OK } ] );
|
||||
}
|
||||
PE_OK;
|
||||
}
|
||||
|
||||
sub authLogout {
|
||||
my ( $self, $req ) = @_;
|
||||
my $res = $self->_authentication->authLogout($req);
|
||||
|
@ -349,7 +370,7 @@ sub authenticate {
|
|||
$req->steps( [
|
||||
'setSessionInfo', 'setMacros',
|
||||
'setPersistentSessionInfo', 'storeHistory',
|
||||
@{ $self->afterData }, sub { PE_BADCREDENTIALS }
|
||||
@{ $self->afterData }, sub { PE_BADCREDENTIALS }
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -133,10 +133,11 @@ sub login {
|
|||
return $self->do(
|
||||
$req,
|
||||
[
|
||||
'controlUrl', @{ $self->beforeAuth },
|
||||
$self->authProcess, @{ $self->betweenAuthAndData },
|
||||
$self->sessionData, @{ $self->afterData },
|
||||
$self->validSession, @{ $self->endAuth },
|
||||
'checkUnauthLogout', 'controlUrl', # Fix 2342
|
||||
@{ $self->beforeAuth }, $self->authProcess,
|
||||
@{ $self->betweenAuthAndData }, $self->sessionData,
|
||||
@{ $self->afterData }, $self->validSession,
|
||||
@{ $self->endAuth }
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -146,11 +147,11 @@ sub postLogin {
|
|||
return $self->do(
|
||||
$req,
|
||||
[
|
||||
'restoreArgs', 'controlUrl',
|
||||
@{ $self->beforeAuth }, $self->authProcess,
|
||||
@{ $self->betweenAuthAndData }, $self->sessionData,
|
||||
@{ $self->afterData }, $self->validSession,
|
||||
@{ $self->endAuth },
|
||||
'checkUnauthLogout', 'restoreArgs', # Fix 2342
|
||||
'controlUrl', @{ $self->beforeAuth },
|
||||
$self->authProcess, @{ $self->betweenAuthAndData },
|
||||
$self->sessionData, @{ $self->afterData },
|
||||
$self->validSession, @{ $self->endAuth }
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -232,6 +233,24 @@ sub logout {
|
|||
);
|
||||
}
|
||||
|
||||
sub unauthLogout {
|
||||
my ( $self, $req ) = @_;
|
||||
$self->userLogger->info('Unauthenticated logout request');
|
||||
$self->logger->debug('Cleaning pdata');
|
||||
$self->logger->debug("Removing $self->{conf}->{cookieName} cookie");
|
||||
$req->pdata( {} );
|
||||
$req->addCookie(
|
||||
$self->cookie(
|
||||
name => $self->conf->{cookieName},
|
||||
domain => $self->conf->{domain},
|
||||
secure => $self->conf->{securedCookie},
|
||||
expires => 'Wed, 21 Oct 2015 00:00:00 GMT',
|
||||
value => 0
|
||||
)
|
||||
);
|
||||
return $self->do( $req, [ sub { PE_LOGOUT_OK } ] );
|
||||
}
|
||||
|
||||
# RUNNING METHODS
|
||||
# ---------------
|
||||
|
||||
|
@ -1051,7 +1070,7 @@ sub registerLogin {
|
|||
}
|
||||
|
||||
my $history = $req->sessionInfo->{_loginHistory} ||= {};
|
||||
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
|
||||
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
|
||||
$history->{$type} ||= [];
|
||||
$self->logger->debug("Current login saved into $type");
|
||||
|
||||
|
|
|
@ -84,6 +84,10 @@ sub _modifyPassword {
|
|||
my $res = $self->modifyPassword( $req, $req->data->{newpassword} );
|
||||
if ( $res == PE_PASSWORD_OK ) {
|
||||
$self->logger->debug( 'Update password in session for ' . $req->user );
|
||||
my $userlog = $req->sessionInfo->{ $self->conf->{whatToTrace} };
|
||||
my $iplog = $req->sessionInfo->{ipAddr};
|
||||
$self->userLogger->notice("Password changed for $userlog ($iplog)")
|
||||
if ( defined $userlog and $iplog );
|
||||
my $infos;
|
||||
|
||||
# Store new password if asked
|
||||
|
|
|
@ -18,9 +18,8 @@ our $VERSION = '2.1.0';
|
|||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
$self->ldap
|
||||
and $self->filter
|
||||
and $self->Lemonldap::NG::Portal::Password::Base::init;
|
||||
return ( $self->Lemonldap::NG::Portal::Password::Base::init
|
||||
and $self->Lemonldap::NG::Portal::Lib::LDAP::init );
|
||||
}
|
||||
|
||||
# Confirmation is done by Lib::Net::LDAP::userModifyPassword
|
||||
|
|
|
@ -4,6 +4,7 @@ use strict;
|
|||
use Mouse;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_APACHESESSIONERROR
|
||||
PE_ERROR
|
||||
PE_OK
|
||||
);
|
||||
|
||||
|
@ -37,9 +38,18 @@ sub changeUrldc {
|
|||
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName};
|
||||
}
|
||||
else {
|
||||
$cdaInfos->{cookie_value} =
|
||||
$req->{sessionInfo}->{_httpSession};
|
||||
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
|
||||
if ( $req->{sessionInfo}->{_httpSession} ) {
|
||||
$cdaInfos->{cookie_value} =
|
||||
$req->{sessionInfo}->{_httpSession};
|
||||
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
|
||||
}
|
||||
else {
|
||||
$self->logger->error(
|
||||
"Session does not contain _httpSession field. "
|
||||
. "Portal must be accessed over HTTPS when using CDA with double cookie"
|
||||
);
|
||||
return PE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
my $cdaSession =
|
||||
|
|
|
@ -23,7 +23,7 @@ sub init {
|
|||
}
|
||||
$self->addUnauthRoute( checkstate => 'check', ['GET'] )
|
||||
->addAuthRoute( checkstate => 'check', ['GET'] );
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ sub check {
|
|||
# - "buildCookie" useless here
|
||||
$req->steps( [
|
||||
'getUser', 'authenticate',
|
||||
@{ $self->p->betweenAuthAndData }, $self->sessionData,
|
||||
@{ $self->p->betweenAuthAndData }, $self->p->sessionData,
|
||||
@{ $self->p->afterData }, 'storeHistory',
|
||||
@{ $self->p->endAuth }
|
||||
]
|
||||
|
|
|
@ -115,7 +115,9 @@ sub display {
|
|||
$self->userLogger->info("Using spoofed SSO groups if exist")
|
||||
if ( $self->conf->{impersonationRule} );
|
||||
|
||||
$attrs = $self->_removePersistentAttributes($attrs)
|
||||
$attrs =
|
||||
$self->_removeKeys( $attrs, $self->persistentAttrs,
|
||||
'Remove persistent session attributes...' )
|
||||
unless $self->displayPersistentInfoRule->( $req, $req->userData );
|
||||
|
||||
# Create an array of hashes and dispatch attributes for template loop
|
||||
|
@ -180,8 +182,7 @@ sub check {
|
|||
LOGIN => '',
|
||||
TOKEN => $token,
|
||||
};
|
||||
return $self->p->sendJSONresponse( $req, $params )
|
||||
if ( $req->wantJSON );
|
||||
return $self->p->sendJSONresponse( $req, $params ) if $req->wantJSON;
|
||||
return $self->p->sendHtml( $req, 'checkuser', params => $params )
|
||||
if $msg;
|
||||
}
|
||||
|
@ -195,7 +196,7 @@ sub check {
|
|||
$user = '';
|
||||
$attrs = {};
|
||||
return $self->p->sendError( $req, 'Malformed user', 400 )
|
||||
if ( $req->wantJSON );
|
||||
if $req->wantJSON;
|
||||
return $self->p->sendHtml(
|
||||
$req,
|
||||
'checkuser',
|
||||
|
@ -219,7 +220,7 @@ sub check {
|
|||
if ( !$user or $user eq $req->{user} ) {
|
||||
$self->userLogger->info("checkUser requested for himself");
|
||||
$self->userLogger->info("Using spoofed SSO groups if exist")
|
||||
if ( $self->conf->{impersonationRule} );
|
||||
if $self->conf->{impersonationRule};
|
||||
$attrs = $req->userData;
|
||||
$user = $req->{user};
|
||||
}
|
||||
|
@ -262,7 +263,10 @@ sub check {
|
|||
}
|
||||
|
||||
# Check identities rule
|
||||
$self->logger->info("\"$user\" is an unrestricted user!") if $unUser;
|
||||
$self->logger->info( '"'
|
||||
. $savedUserData->{ $self->conf->{whatToTrace} }
|
||||
. '" is an unrestricted user!' )
|
||||
if $unUser;
|
||||
unless ( $unUser || $self->idRule->( $req, $attrs ) ) {
|
||||
$self->userLogger->warn(
|
||||
"checkUser requested for an invalid user ($user)");
|
||||
|
@ -279,8 +283,10 @@ sub check {
|
|||
$attrs = {};
|
||||
}
|
||||
else {
|
||||
$msg = 'checkUser' . $self->merged;
|
||||
$attrs = $self->_removePersistentAttributes($attrs)
|
||||
$msg = 'checkUser' . $self->merged;
|
||||
$attrs =
|
||||
$self->_removeKeys( $attrs, $self->persistentAttrs,
|
||||
'Remove persistent session attributes...' )
|
||||
unless $self->displayPersistentInfoRule->( $req, $savedUserData );
|
||||
|
||||
if ($computed) {
|
||||
|
@ -320,17 +326,23 @@ sub check {
|
|||
$self->_createArray( $req, $attrs, $savedUserData ) );
|
||||
}
|
||||
|
||||
if ( $self->p->checkXSSAttack( 'CheckUser URL', $url ) ) {
|
||||
$url = '';
|
||||
$auth = 'VHnotFound';
|
||||
}
|
||||
|
||||
# Check if user is allowed to access submitted URL and compute headers
|
||||
if ( $url and %$attrs ) {
|
||||
|
||||
# Check url format
|
||||
$url = $self->_urlFormat($url);
|
||||
my $originalUrl;
|
||||
( $url, $originalUrl ) = $self->_resolveURL( $req, $url );
|
||||
|
||||
# User is allowed ?
|
||||
$self->logger->debug(
|
||||
"checkUser requested for user: $attrs->{ $self->{conf}->{whatToTrace} } and URL: $url"
|
||||
"checkUser requested for user: $attrs->{ $self->{conf}->{whatToTrace} } and URL: $url | alias: $originalUrl"
|
||||
);
|
||||
$auth = $self->_authorization( $req, $url, $attrs );
|
||||
$auth = $self->_authorization( $req, $originalUrl, $attrs );
|
||||
if ( $auth >= 0 ) {
|
||||
$auth = $auth ? "allowed" : "forbidden";
|
||||
$self->logger->debug(
|
||||
|
@ -338,7 +350,8 @@ sub check {
|
|||
. "$auth to access to $url" );
|
||||
|
||||
# Return VirtualHost headers
|
||||
$array_hdrs = $self->_headers( $req, $url, $attrs, $savedUserData );
|
||||
$array_hdrs =
|
||||
$self->_headers( $req, $originalUrl, $attrs, $savedUserData );
|
||||
}
|
||||
else {
|
||||
$auth = 'VHnotFound';
|
||||
|
@ -352,17 +365,14 @@ sub check {
|
|||
|
||||
# TODO:
|
||||
my $params = {
|
||||
PORTAL => $self->conf->{portal},
|
||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||
SKIN => $self->p->getSkin($req),
|
||||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => $msg,
|
||||
ALERTE => ( $msg eq 'checkUser' ? 'alert-info' : 'alert-warning' ),
|
||||
LOGIN => $user,
|
||||
URL => (
|
||||
$self->p->checkXSSAttack( 'URL', $url ) ? ""
|
||||
: $url
|
||||
),
|
||||
PORTAL => $self->conf->{portal},
|
||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||
SKIN => $self->p->getSkin($req),
|
||||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => $msg,
|
||||
ALERTE => ( $msg eq 'checkUser' ? 'alert-info' : 'alert-warning' ),
|
||||
LOGIN => $user,
|
||||
URL => $url,
|
||||
ALLOWED => $auth,
|
||||
ALERTE_AUTH => $alert_auth,
|
||||
HEADERS => $array_hdrs,
|
||||
|
@ -370,7 +380,8 @@ sub check {
|
|||
MACROS => $array_attrs->[1],
|
||||
GROUPS => $array_attrs->[0],
|
||||
TOKEN => (
|
||||
$self->ottRule->( $req, {} ) ? $self->ott->createToken()
|
||||
$self->ottRule->( $req, {} )
|
||||
? $self->ott->createToken()
|
||||
: ''
|
||||
)
|
||||
};
|
||||
|
@ -380,17 +391,24 @@ sub check {
|
|||
return $self->p->sendHtml( $req, 'checkuser', params => $params );
|
||||
}
|
||||
|
||||
sub _urlFormat {
|
||||
my ( $self, $url ) = @_;
|
||||
$url = 'http://' . $url unless ( $url =~ m#^https?://[^/]*.*#i );
|
||||
my ( $proto, $vhost, $appuri ) = $url =~ m#^(https?://)([^/]*)(.*)#i;
|
||||
sub _resolveURL {
|
||||
my ( $self, $req, $url ) = @_;
|
||||
my ($proto) = $url =~ m#^(https?://).*#i;
|
||||
my ( $vhost, $appuri ) = $url =~ m#^(?:https?://)?([^/]*)(.*)#i;
|
||||
my ($port) = $vhost =~ m#^.+(:\d+)$#;
|
||||
|
||||
$port ||= '';
|
||||
$vhost =~ s/:\d+$//;
|
||||
$vhost .= $self->conf->{domain} unless ( $vhost =~ /\./ );
|
||||
$proto =
|
||||
$self->p->HANDLER->_isHttps( $req, $vhost ) ? 'https://' : 'http://'
|
||||
unless $proto;
|
||||
$self->logger->debug( 'VHost is ' . uc( ( split( /:/, $proto ) )[0] ) );
|
||||
my $originalVhost = $self->p->HANDLER->resolveAlias($vhost);
|
||||
|
||||
return lc("$proto$vhost$port") . "$appuri";
|
||||
return (
|
||||
lc("$proto$vhost$port") . $appuri,
|
||||
lc("$proto$originalVhost$port") . $appuri
|
||||
);
|
||||
}
|
||||
|
||||
sub _userData {
|
||||
|
@ -407,12 +425,9 @@ sub _userData {
|
|||
: push @$steps, 'setLocalGroups';
|
||||
$req->steps($steps);
|
||||
if ( my $error = $self->p->process($req) ) {
|
||||
if ( $error == PE_BADCREDENTIALS ) {
|
||||
$self->userLogger->warn(
|
||||
'checkUser requested for an invalid user ('
|
||||
. $req->{user}
|
||||
. ")" );
|
||||
}
|
||||
$self->userLogger->warn(
|
||||
'checkUser requested for an invalid user (' . $req->{user} . ")" )
|
||||
if ( $error == PE_BADCREDENTIALS );
|
||||
$self->logger->debug("Process returned error: $error");
|
||||
return $req->error(PE_BADCREDENTIALS);
|
||||
}
|
||||
|
@ -468,16 +483,48 @@ sub _headers {
|
|||
$vhost =~ s/:\d+$//;
|
||||
$req->{env}->{HTTP_HOST} = $vhost;
|
||||
$self->p->HANDLER->headersInit( $self->{conf} );
|
||||
my $headers = $self->p->HANDLER->checkHeaders( $req, $attrs );
|
||||
|
||||
# Remove hidden headers relative to VHost if required
|
||||
unless ( $self->unrestrictedUsersRule->( $req, $savedUserData ) ) {
|
||||
my $keysToRemove = '';
|
||||
$keysToRemove = '__all__'
|
||||
if exists $self->conf->{checkUserHiddenHeaders}->{$vhost};
|
||||
$keysToRemove = $self->conf->{checkUserHiddenHeaders}->{$vhost}
|
||||
if ( $keysToRemove
|
||||
&& $self->conf->{checkUserHiddenHeaders}->{$vhost} =~ /\w+/ );
|
||||
|
||||
if ( $keysToRemove eq '__all__' ) {
|
||||
$self->logger->debug(
|
||||
"Overwrite for VirtualHost: $vhost ALL valued header(s)...");
|
||||
@$headers = map {
|
||||
$_->{value} =~ /\w+/
|
||||
? { key => $_->{key}, value => '******' }
|
||||
: $_
|
||||
} @$headers;
|
||||
}
|
||||
else {
|
||||
$self->logger->debug(
|
||||
"Mask hidden header(s) for VirtualHost: $vhost");
|
||||
my $hash = { map { $_->{key} => $_->{value} } @$headers };
|
||||
$hash = $self->_removeKeys( $hash, $keysToRemove,
|
||||
"Overwrite valued \"$keysToRemove\" header(s)...", 1 );
|
||||
@$headers = (
|
||||
map { { key => $_, value => $hash->{$_} } }
|
||||
sort keys %$hash
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# Remove empty headers if required
|
||||
unless ( $self->displayEmptyHeadersRule->( $req, $savedUserData ) ) {
|
||||
$self->logger->debug("Remove empty headers...");
|
||||
@$headers = grep $_->{value} =~ /.+/, @$headers;
|
||||
}
|
||||
$self->logger->debug(
|
||||
"Return \"$attrs->{ $self->{conf}->{whatToTrace} }\" headers");
|
||||
return $self->p->HANDLER->checkHeaders( $req, $attrs )
|
||||
if ( $self->displayEmptyHeadersRule->( $req, $savedUserData ) );
|
||||
|
||||
$self->logger->debug("Remove empty headers");
|
||||
my @headers = grep $_->{value} =~ /.+/,
|
||||
@{ $self->p->HANDLER->checkHeaders( $req, $attrs ) };
|
||||
|
||||
return \@headers;
|
||||
return $headers;
|
||||
}
|
||||
|
||||
sub _createArray {
|
||||
|
@ -511,7 +558,7 @@ sub _dispatchAttributes {
|
|||
my ( $grps, $mcrs, $others ) = ( [], [], [] );
|
||||
my $macros = $self->{conf}->{macros};
|
||||
|
||||
$self->logger->debug("Dispatching attributes...");
|
||||
$self->logger->debug("Dispatch attributes...");
|
||||
while (@$attrs) {
|
||||
my $element = shift @$attrs;
|
||||
$self->logger->debug( "Processing element: $element->{key} => "
|
||||
|
@ -539,9 +586,9 @@ sub _dispatchAttributes {
|
|||
|
||||
# Sort real and spoofed attributes if required
|
||||
if ( $self->sorted ) {
|
||||
$self->logger->debug('Dispatching real and spoofed attributes...');
|
||||
$self->logger->debug('Sort real and spoofed attributes...');
|
||||
my ( $realAttrs, $spoofedAttrs ) = ( [], [] );
|
||||
my $prefix = "$self->{conf}->{impersonationPrefix}";
|
||||
my $prefix = $self->{conf}->{impersonationPrefix};
|
||||
while (@$others) {
|
||||
my $element = shift @$others;
|
||||
$self->logger->debug( "Processing attribute $element->{key} => "
|
||||
|
@ -560,12 +607,22 @@ sub _dispatchAttributes {
|
|||
return [ $grps, $mcrs, $others ];
|
||||
}
|
||||
|
||||
sub _removePersistentAttributes {
|
||||
my ( $self, $attrs ) = @_;
|
||||
my $regex = join '|', split /\s+/, $self->persistentAttrs;
|
||||
sub _removeKeys {
|
||||
my ( $self, $attrs, $hidden, $msg, $mask ) = @_;
|
||||
my $regex = join '|', split /\s+/, $hidden;
|
||||
my @keys = grep /$regex/, keys %$attrs;
|
||||
$self->logger->debug("Remove persistent session attributes");
|
||||
delete @$attrs{@keys};
|
||||
|
||||
$self->logger->debug($msg);
|
||||
if ($mask) {
|
||||
$self->userLogger->info('Hide some headers');
|
||||
foreach (@keys) {
|
||||
$attrs->{$_} = '******' if $attrs->{$_} =~ /\w+/;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->userLogger->info('Remove some headers');
|
||||
delete @$attrs{@keys};
|
||||
}
|
||||
|
||||
return $attrs;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ sub display {
|
|||
sub run {
|
||||
my ( $self, $req ) = @_;
|
||||
my $statut = PE_OK;
|
||||
my $realId = $req->{user};
|
||||
my $realId = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
my $spoofId = $req->param('spoofId') || ''; # ContextSwitching required ?
|
||||
my $unUser = $self->unrestrictedUsersRule->( $req, $req->userData ) || 0;
|
||||
|
||||
|
@ -202,7 +202,7 @@ sub _switchContext {
|
|||
my ( $self, $req, $spoofId, $unUser ) = @_;
|
||||
my $realSessionId = $req->userData->{_session_id};
|
||||
my $realAuthLevel = $req->userData->{authenticationLevel};
|
||||
my $realId = $req->{user};
|
||||
my $realId = $req->userData->{ $self->conf->{whatToTrace} };
|
||||
my $raz = 0;
|
||||
$req->{user} = $spoofId;
|
||||
|
||||
|
|
|
@ -54,9 +54,9 @@ sub run {
|
|||
my ( $self, $req ) = @_;
|
||||
my $user = $req->{userData}->{ $self->conf->{whatToTrace} };
|
||||
|
||||
# Check activation rules
|
||||
# Check activation rule
|
||||
unless ( $self->rule->( $req, $req->userData ) ) {
|
||||
$self->userLogger->info("Global logout not required for $user");
|
||||
$self->userLogger->info("GlobaLogout not allowed for $user");
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
|
@ -116,20 +116,22 @@ sub globalLogout {
|
|||
# Read active sessions from token
|
||||
my $sessions = eval { from_json( $token->{sessions} ) };
|
||||
if ($@) {
|
||||
$self->logger->error("Bad encoding in OTT: $@");
|
||||
$self->logger->error(
|
||||
"GlobalLogout: bad encoding in OTT ($@)");
|
||||
$res = PE_ERROR;
|
||||
}
|
||||
my $as;
|
||||
foreach (@$sessions) {
|
||||
unless ( $as = $self->p->getApacheSession( $_->{id} ) ) {
|
||||
$self->userLogger->info(
|
||||
"GlobalLogout: session $_->{id} expired");
|
||||
next;
|
||||
}
|
||||
my $user = $token->{user};
|
||||
if ( $req->{userData}->{ $self->{conf}->{whatToTrace} } eq
|
||||
$user )
|
||||
{
|
||||
my $user = $token->{user};
|
||||
my $req_user =
|
||||
$req->{userData}->{ $self->{conf}->{whatToTrace} };
|
||||
if ( $req_user eq $user ) {
|
||||
foreach (@$sessions) {
|
||||
unless ( $as = $self->p->getApacheSession( $_->{id} ) )
|
||||
{
|
||||
$self->userLogger->info(
|
||||
"GlobalLogout: session $_->{id} expired");
|
||||
next;
|
||||
}
|
||||
unless ( $req->{userData}->{_session_id} eq $_->{id} ) {
|
||||
$self->userLogger->info(
|
||||
"Remove \"$user\" session: $_->{id}");
|
||||
|
@ -137,11 +139,12 @@ sub globalLogout {
|
|||
$count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->userLogger->warn(
|
||||
"GlobalLogout called with an invalid token");
|
||||
$res = PE_TOKENEXPIRED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->userLogger->warn(
|
||||
"GlobalLogout called with an invalid token: $req_user is NOT $user"
|
||||
);
|
||||
$res = PE_TOKENEXPIRED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -157,7 +160,7 @@ sub globalLogout {
|
|||
}
|
||||
|
||||
return $self->p->do( $req, [ sub { $res } ] ) if $res;
|
||||
$self->userLogger->info("$count remaining session(s) have been removed");
|
||||
$self->userLogger->info("$count remaining session(s) removed");
|
||||
return $self->p->do( $req, [ 'authLogout', 'deleteSession' ] );
|
||||
}
|
||||
|
||||
|
@ -177,16 +180,16 @@ sub activeSessions {
|
|||
$self->module->searchOn( $moduleOptions, $self->conf->{whatToTrace},
|
||||
$user );
|
||||
|
||||
$self->logger->debug('Remove corrupted sessions...');
|
||||
my $corrupted = 0;
|
||||
$self->logger->debug('Remove non-SSO session(s)...');
|
||||
my $other = 0;
|
||||
foreach ( keys %$sessions ) {
|
||||
unless ( $sessions->{$_}->{_session_kind} eq 'SSO' ) {
|
||||
delete $sessions->{$_};
|
||||
$corrupted++;
|
||||
$other++;
|
||||
}
|
||||
}
|
||||
$self->logger->info("$corrupted corrupted session(s) removed")
|
||||
if $corrupted;
|
||||
$self->logger->info("$other non-SSO session(s) removed")
|
||||
if $other;
|
||||
|
||||
$self->logger->debug('Build an array ref with sessions info...');
|
||||
@$activeSessions =
|
||||
|
|
|
@ -72,16 +72,17 @@ sub run {
|
|||
$req, 'simpleInfo', params => { trspan => $msg }
|
||||
)
|
||||
);
|
||||
$self->userLogger->error( 'User '
|
||||
. $req->sessionInfo->{uid}
|
||||
. " was not granted to open session (rule -> $rule)" );
|
||||
$self->userLogger->error( 'User "'
|
||||
. $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
||||
. '" was not granted to open session (rule ->'
|
||||
. "$rule)" );
|
||||
$req->urldc( $self->conf->{portal} );
|
||||
return $req->authResult(PE_SESSIONNOTGRANTED);
|
||||
}
|
||||
else {
|
||||
$self->userLogger->error( 'User '
|
||||
. $req->sessionInfo->{uid}
|
||||
. " was not granted to open session (rule -> "
|
||||
$self->userLogger->error( 'User "'
|
||||
. $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
||||
. '" was not granted to open session (rule -> '
|
||||
. $self->conf->{grantSessionRules}->{$_}
|
||||
. ")" );
|
||||
$req->urldc( $self->conf->{portal} );
|
||||
|
|
|
@ -490,6 +490,11 @@ sub changePwd {
|
|||
return $result;
|
||||
}
|
||||
|
||||
my $userlog = $req->sessionInfo->{ $self->conf->{whatToTrace} };
|
||||
my $iplog = $req->sessionInfo->{ipAddr};
|
||||
$self->userLogger->notice("Password changed for $userlog ($iplog)")
|
||||
if ( defined $userlog and $iplog );
|
||||
|
||||
# Send mail containing the new password
|
||||
$req->data->{mailAddress} ||=
|
||||
$self->p->getFirstValue(
|
||||
|
|
|
@ -182,7 +182,7 @@ sub removeOther {
|
|||
}
|
||||
|
||||
return $self->p->do( $req, [ sub { $res } ] ) if $res;
|
||||
$self->userLogger->info("$count remaining session(s) have been removed");
|
||||
$self->userLogger->info("$count remaining session(s) removed");
|
||||
$req->mustRedirect(1);
|
||||
return $self->p->autoRedirect($req);
|
||||
}
|
||||
|
|
|
@ -40,12 +40,16 @@ sub setSessionInfo {
|
|||
%{ $self->conf->{ldapExportedVars} } );
|
||||
while ( my ( $k, $v ) = each %vars ) {
|
||||
|
||||
my $value = $self->ldap->getLdapValue( $req->data->{ldapentry}, $v );
|
||||
|
||||
# getLdapValue returns an empty string for missing attribute
|
||||
# but we really want to return undef so they don't get stored in session
|
||||
$req->sessionInfo->{$k} =
|
||||
$self->ldap->getLdapValue( $req->data->{ldapentry}, $v ) || undef;
|
||||
}
|
||||
# This has to be a string comparison because "0" is a valid attribute
|
||||
# value. See #2403
|
||||
$value = undef if ( $value eq "" );
|
||||
|
||||
$req->sessionInfo->{$k} = $value;
|
||||
}
|
||||
PE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,18 @@ package Lemonldap::NG::Portal::UserDB::Slave;
|
|||
|
||||
use strict;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Portal::Lib::Slave;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(PE_FORBIDDENIP PE_OK);
|
||||
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_OK
|
||||
PE_FORBIDDENIP
|
||||
);
|
||||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
extends 'Lemonldap::NG::Common::Module';
|
||||
extends qw(
|
||||
Lemonldap::NG::Common::Module
|
||||
Lemonldap::NG::Portal::Lib::Slave
|
||||
);
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
|
|
|
@ -482,7 +482,7 @@ $(window).on 'load', () ->
|
|||
$('#newpassword')[0].setCustomValidity(translate('PE28'))
|
||||
return
|
||||
|
||||
if window.datas.ppolicy?
|
||||
if window.datas.ppolicy? and $('#newpassword').length
|
||||
# Initialize display
|
||||
checkpassword ''
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue