Fix unit test

This commit is contained in:
Christophe Maudoux 2020-12-10 23:29:08 +01:00
commit b1232739a0
137 changed files with 1899 additions and 656 deletions

View File

@ -27,6 +27,9 @@ theses :
* **OAUTH2_USERINFO_ENDPOINT**: ``oauth2/userinfo`` * **OAUTH2_USERINFO_ENDPOINT**: ``oauth2/userinfo``
* **OAUTH2_TOKEN_ENDPOINT**: ``oauth2/token`` * **OAUTH2_TOKEN_ENDPOINT**: ``oauth2/token``
* **OAUTH2_ID_MAP**: ``sub`` * **OAUTH2_ID_MAP**: ``sub``
* **OAUTH2_USERNAME_MAP**: ``sub``
* **OAUTH2_FULLNAME_MAP**: ``name``
* **OAUTH2_EMAIL_MAP**: ``email``
.. danger:: .. danger::

View File

@ -246,7 +246,8 @@ Here are some recommended configurations:
_whatToTrace varchar(64), _whatToTrace varchar(64),
_session_kind varchar(15), _session_kind varchar(15),
user text, user text,
_utime bigint _utime bigint,
ipAddr varchar(64)
); );
CREATE INDEX uid1 ON sessions (_whatToTrace) USING BTREE; CREATE INDEX uid1 ON sessions (_whatToTrace) USING BTREE;
CREATE INDEX _s1 ON sessions (_session_kind); CREATE INDEX _s1 ON sessions (_session_kind);

View File

@ -18,7 +18,7 @@ Just enable it in the manager (section “plugins”).
displayed (by example: ``!$anonymous``) displayed (by example: ``!$anonymous``)
- **Unrestricted users rule**: Rule to define which users can check - **Unrestricted users rule**: Rule to define which users can check
ALL users. ``Identities use rule`` is bypassed. 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 - **Attributes used for searching sessions**: User's attributes used
for searching sessions in backend if ``whatToTrace`` fails. Useful for searching sessions in backend if ``whatToTrace`` fails. Useful
to look for sessions by mail or givenName. Let it blank to search 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 even empty ones
- **Display persistent session data**: Rule to define which users can display - **Display persistent session data**: Rule to define which users can display
persistent session data 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:: .. 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`` \* Search attributes => ``mail uid givenName``

View File

@ -503,6 +503,9 @@ Some options are available:
- Maintenance mode: reject all requests with a maintenance message - Maintenance mode: reject all requests with a maintenance message
- Aliases: list of aliases for this virtual host *(avoid to rewrite - Aliases: list of aliases for this virtual host *(avoid to rewrite
rules,...)* 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, - Type: handler type (normal,
:doc:`ServiceToken Handler<servertoserver>`, :doc:`ServiceToken Handler<servertoserver>`,
:doc:`DevOps Handler<devopshandler>`,...) :doc:`DevOps Handler<devopshandler>`,...)
@ -515,6 +518,30 @@ Some options are available:
seconds. This TTL can be customized for each virtual host. 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:: .. danger::
A same virtual host can serve many locations. Each A same virtual host can serve many locations. Each

View File

@ -10,7 +10,7 @@ extracted from the users database by the
:ref:`users module<start-authentication-users-and-password-databases>`. :ref:`users module<start-authentication-users-and-password-databases>`.
To create a variable, you've just to map a user attributes in LL::NG 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 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. and the second field is the name of the user database field.

View File

@ -25,19 +25,20 @@ Inside this jail, you can access to:
* Information about current request * Information about current request
* Extended functions: * Extended functions:
* date_
* checkLogonHours_
* checkDate_
* basic_ * basic_
* unicode2iso_ * checkDate_
* iso2unicode_ * checkLogonHours_
* groupMatch_ * date_
* listMatch_
* inGroup_
* encrypt_ * encrypt_
* token_ * groupMatch_
* has2f_ (|new| in version 2.0.10)
* inGroup_ (|new| in version 2.0.8)
* isInNet6_ * isInNet6_
* varIsInUri_ * iso2unicode_
* listMatch_ (|new| in version 2.0.7)
* token_
* unicode2iso_
* varIsInUri_ (|new| in version 2.0.7)
.. |new| image:: /documentation/new.png .. |new| image:: /documentation/new.png
@ -238,6 +239,40 @@ Simple usage example:
groupMatch($hGroups, 'description', 'Service 1') 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:
listMatch listMatch

View File

@ -57,6 +57,12 @@ logs, go into Manager, ``General Parameters`` > ``Logging`` >
User log samples 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: Authentication:
:: ::
@ -84,6 +90,12 @@ Logout:
[notice] User dwho has been disconnected from LDAP (81.20.13.21) [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): Access to a CAS application non registered in configuration (when CAS server is open):
:: ::

View File

@ -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. In Perl, ``eq`` means *Equal* and must be used on strings.
``==`` should be used only on numbers ``==`` 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 - Restricting access to specific groups
:: ::
@ -64,6 +74,17 @@ attribute you see there can be used in a rule!
$_auth ne 'Demo' $_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:: .. tip::
@ -71,6 +92,7 @@ attribute you see there can be used in a rule!
strings. ``\b`` means *word Boundary*. (?:) means *non capturing* strings. ``\b`` means *word Boundary*. (?:) means *non capturing*
parenthesis. parenthesis.
Using environment variables Using environment variables
--------------------------- ---------------------------

View File

@ -6,8 +6,8 @@ Presentation
LemonLDAP::NG uses Safe jail to evaluate all expressions: LemonLDAP::NG uses Safe jail to evaluate all expressions:
- Access rule - Access rules
- Header - Headers
- Form replay parameters - Form replay parameters
- Macros - Macros
- Groups - Groups
@ -31,3 +31,19 @@ to disable it.
To do this, go into Manager > General Parameters > Advanced Parameters > To do this, go into Manager > General Parameters > Advanced Parameters >
Security > Use Safe Jail and disable it. 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.

View File

@ -7,15 +7,12 @@ options.
Disk cache (sessions an configuration) Disk cache (sessions an configuration)
-------------------------------------- --------------------------------------
:: You need to set the correct context on the cache directory
chcon -R -t httpd_sys_rw_content_t /var/cache/lemonldap-ng
To persist the rule:
:: ::
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 LDAP
---- ----

View File

@ -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 required even if users are not registered. This is automatically done
when "activation" is simply set to "on". when "activation" is simply set to "on".
.. danger::
Range is tested backward and forward to prevent
positive or negative clock drift.
Enrollment Enrollment
---------- ----------

View File

@ -21,6 +21,8 @@ backups and a rollback plan ready!
------ ------
- New dependency: IO::Socket::Timeout - 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 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>`__) (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>`__ - 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. - 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 Cookie issues with Chrome
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -190,14 +190,14 @@ use macros, local macros,...
.. attention:: .. attention::
- Since many HTTP servers refuse non ascii headers, it is recommended - Since many HTTP servers refuse non ascii headers, it is recommended
to use encode_base64() function to transmit those headers to use encode_base64() function to transmit those headers
- Don't forget to add an empty string as second argument to - Don't forget to add an empty string as second argument to
encode_base64 function to avoid a "newline" characters insertion in encode_base64 function to avoid a "newline" characters insertion in
result 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

View File

@ -8,4 +8,16 @@ sub get_additional_arg {
return $_[0]; 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; 1;

View File

@ -22,7 +22,7 @@ dirName=__pwd__/e2e-tests/conf
checkXSS = 0 checkXSS = 0
portalSkin = bootstrap portalSkin = bootstrap
staticPrefix = /static 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 templateDir = __pwd__/lemonldap-ng-portal/site/templates
portalStatus = 1 portalStatus = 1
totp2fActivation = 1 totp2fActivation = 1
@ -49,7 +49,7 @@ viewerAllowDiff = 1
staticPrefix = /static staticPrefix = /static
instanceName = Demo 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 templateDir = __pwd__/lemonldap-ng-manager/site/templates
[node-handler] [node-handler]

View File

@ -164,6 +164,16 @@
"default": "accept" "default": "accept"
} }
}, },
"vhostOptions":{
"manager.example.com": {
"vhostMaintenance": 0,
"vhostPort": -1,
"vhostHttps": -1,
"vhostAliases": "",
"vhostServiceTokenTTL": -1,
"vhostAccessToTrace": "My::accessToTrace, Doctor, Who","vhostType":"Main"
}
},
"loginHistoryEnabled": 1, "loginHistoryEnabled": 1,
"macros": { "macros": {
"UA" : "$ENV{HTTP_USER_AGENT}", "UA" : "$ENV{HTTP_USER_AGENT}",

View File

@ -196,7 +196,7 @@ staticPrefix = __PORTALSTATICDIR__
templateDir = __PORTALTEMPLATESDIR__ templateDir = __PORTALTEMPLATESDIR__
; languages: available languages for portal interface ; 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) ; II - Optional parameters (overwrite configuration)
@ -383,7 +383,7 @@ staticPrefix = __MANAGERSTATICDIR__
templateDir = __MANAGERTEMPLATESDIR__ templateDir = __MANAGERTEMPLATESDIR__
; languages: available languages for manager interface ; 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 ; Manager modules enabled
; Set here the list of modules you want to see in manager interface ; Set here the list of modules you want to see in manager interface

View File

@ -29,8 +29,8 @@ use constant DEFAULTCONFBACKEND => "File";
use constant DEFAULTCONFBACKENDOPTIONS => ( use constant DEFAULTCONFBACKENDOPTIONS => (
dirName => '/usr/local/lemonldap-ng/data/conf', 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 $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)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/; 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' ); our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -22,7 +22,7 @@ our $specialNodeHash = {
}; };
our $doubleHashKeys = 'issuerDBGetParameters'; 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 $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 $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)'; 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 $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 $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 $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 = { our $authParameters = {
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)], adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],

View File

@ -9,6 +9,7 @@ use strict;
use Encode; use Encode;
use MIME::Base64; use MIME::Base64;
use Lemonldap::NG::Common::IPv6; use Lemonldap::NG::Common::IPv6;
use JSON::XS;
#use AutoLoader qw(AUTOLOAD); #use AutoLoader qw(AUTOLOAD);
@ -18,7 +19,7 @@ our $VERSION = '2.1.0';
# Not that only functions, not methods, can be written here # Not that only functions, not methods, can be written here
our $functions = 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) ## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
@ -64,8 +65,8 @@ sub checkLogonHours {
# Use time_correction # Use time_correction
if ($time_correction) { if ($time_correction) {
my ( $sign, $time ) = ( $time_correction =~ /([+|-]?)(\d+)/ ); my ( $sign, $time ) = ( $time_correction =~ /([+|-]?)(\d+)/ );
if ( $sign =~ /-/ ) { $hourpos -= $time; } if ( $sign =~ /-/ ) { $hourpos -= $time; }
else { $hourpos += $time; } else { $hourpos += $time; }
} }
# Get the corresponding byte # Get the corresponding byte
@ -224,4 +225,26 @@ sub varIsInUri {
: $uri =~ /$wanteduri$attribute/o; : $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; 1;

View File

@ -19,8 +19,9 @@ sub verifyCode {
$self->logger->error('Bad characters in TOTP secret'); $self->logger->error('Bad characters in TOTP secret');
return -1; return -1;
} }
for ( 0 .. $range ) { for ( -$range .. $range ) {
if ( $code eq $self->_code( $s, $_, $interval, $digits ) ) { if ( $code eq $self->_code( $s, $_, $interval, $digits ) ) {
$self->userLogger->info("Codes match at range $_");
return 1; return 1;
} }
} }

View File

@ -63,6 +63,7 @@ t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t
t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t
t/71-Lemonldap-NG-Handler-PSGI-OAuth2.t t/71-Lemonldap-NG-Handler-PSGI-OAuth2.t
t/99-pod.t t/99-pod.t
t/custom.pm
t/lmConf-1.json t/lmConf-1.json
t/sessions/lock/.exists t/sessions/lock/.exists
t/test-psgi-lib.pm t/test-psgi-lib.pm

View File

@ -238,6 +238,8 @@ sub defaultValuesInit {
$conf->{vhostOptions}->{$vhost}->{vhostAuthnLevel}; $conf->{vhostOptions}->{$vhost}->{vhostAuthnLevel};
$class->tsv->{serviceTokenTTL}->{$vhost} = $class->tsv->{serviceTokenTTL}->{$vhost} =
$conf->{vhostOptions}->{$vhost}->{vhostServiceTokenTTL}; $conf->{vhostOptions}->{$vhost}->{vhostServiceTokenTTL};
$class->tsv->{accessToTrace}->{$vhost} =
$conf->{vhostOptions}->{$vhost}->{vhostAccessToTrace};
} }
} }
return 1; return 1;
@ -626,6 +628,9 @@ sub substitute {
# handle inGroup # handle inGroup
$expr =~ s/\binGroup\(([^)]*)\)/listMatch(\$s->{'hGroups'},$1,1)/g; $expr =~ s/\binGroup\(([^)]*)\)/listMatch(\$s->{'hGroups'},$1,1)/g;
# handle has2f
$expr =~ s/\bhas2f\(([^),]*)\)/has2f(\$s,$1)/g;
return $expr; return $expr;
} }

View File

@ -105,6 +105,7 @@ sub checkType {
sub run { sub run {
my ( $class, $req, $rule, $protection ) = @_; my ( $class, $req, $rule, $protection ) = @_;
my ( $id, $session ); my ( $id, $session );
my $vhost = $class->resolveAlias($req);
return $class->DECLINED unless ( $class->is_initial_req($req) ); return $class->DECLINED unless ( $class->is_initial_req($req) );
@ -149,9 +150,41 @@ sub run {
# ACCOUNTING (1. Inform web server) # ACCOUNTING (1. Inform web server)
$class->set_user( $req, $session->{ $class->tsv->{whatToTrace} } ); $class->set_user( $req, $session->{ $class->tsv->{whatToTrace} } );
$class->set_custom( $req, $session->{ $class->tsv->{customToTrace} } )
if $class->tsv->{customToTrace} my $custom;
and $session->{ $class->tsv->{customToTrace} }; $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 # AUTHORIZATION
return ( $class->forbidden( $req, $session ), $session ) return ( $class->forbidden( $req, $session ), $session )
@ -794,10 +827,14 @@ sub localUnlog {
if ( $id //= $class->fetchId($req) ) { if ( $id //= $class->fetchId($req) ) {
# Delete local cache # Delete local cache
if ( $class->tsv->{refLocalStorage} if ( $class->tsv->{sessionCacheModule} ) {
and $class->tsv->{refLocalStorage}->get($id) ) my $module = $class->tsv->{sessionCacheModule};
{ my $options = $class->tsv->{sessionCacheOptions};
$class->tsv->{refLocalStorage}->remove($id); eval "use $module;";
my $cache = $module->new($options);
if ( $cache->get($id) ) {
$cache->remove($id);
}
} }
} }
} }

View File

@ -6,7 +6,7 @@
# change 'tests => 1' to 'tests => last_test_to_print'; # change 'tests => 1' to 'tests => last_test_to_print';
use strict; use strict;
use Test::More tests => 13; use Test::More tests => 17;
require 't/test.pm'; require 't/test.pm';
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') } BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') }
@ -60,3 +60,39 @@ ok(
ok( $res = &$code, "Function works" ); ok( $res = &$code, "Function works" );
ok( $res == 1, 'Get good result' ); 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"
);

View File

@ -5,7 +5,7 @@
# change 'tests => 1' to 'tests => last_test_to_print'; # change 'tests => 1' to 'tests => last_test_to_print';
use Test::More tests => 9; use Test::More tests => 13;
require 't/test.pm'; require 't/test.pm';
BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') } 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' ), ok( ( defined($listMatch) and ref($listMatch) eq 'CODE' ),
'listMatch function is defined' ); 'listMatch function is defined' );
ok( &$listMatch eq '0', 'Get good result' ); 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"
);

View File

@ -4,7 +4,10 @@ use MIME::Base64;
use Data::Dumper; use Data::Dumper;
use URI::Escape; 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'); init('Lemonldap::NG::Handler::Server::Nginx');
@ -31,6 +34,28 @@ count(4);
# Authentified queries # 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 # Authorized query
ok( $res = $client->_get( '/', undef, undef, "lemonldap=$sessionId" ), ok( $res = $client->_get( '/', undef, undef, "lemonldap=$sessionId" ),
'Authentified query' ); 'Authentified query' );
@ -43,7 +68,11 @@ ok( $h{'Headername1'} eq 'Auth-User', 'Headername1 is set to "Auth-User"' )
or explain( \%h, 'Headername1 => "Auth-User"' ); or explain( \%h, 'Headername1 => "Auth-User"' );
ok( $h{'Headervalue1'} eq 'dwho', 'Headervalue1 is set to "dwho"' ) ok( $h{'Headervalue1'} eq 'dwho', 'Headervalue1 is set to "dwho"' )
or explain( \%h, 'Headervalue1 => "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 # Request an URI protected by custom function -> allowed
ok( ok(

View File

@ -4,6 +4,7 @@ use MIME::Base64;
BEGIN { BEGIN {
require 't/test-psgi-lib.pm'; require 't/test-psgi-lib.pm';
require 't/custom.pm';
} }
init('Lemonldap::NG::Handler::PSGI'); init('Lemonldap::NG::Handler::PSGI');
@ -39,7 +40,6 @@ ok(
'Authentified query' 'Authentified query'
); );
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 ); ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
count(2); count(2);
# Denied query # Denied query
@ -50,7 +50,6 @@ ok(
'Denied query' 'Denied query'
); );
ok( $res->[0] == 403, 'Code is 403' ) or explain( $res->[0], 403 ); ok( $res->[0] == 403, 'Code is 403' ) or explain( $res->[0], 403 );
count(2); count(2);
# Bad cookie # Bad cookie
@ -67,11 +66,9 @@ ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
unlink( unlink(
't/sessions/lock/Apache-Session-e5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock' 't/sessions/lock/Apache-Session-e5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock'
); );
count(2); count(2);
done_testing( count() ); done_testing( count() );
clean(); clean();
sub Lemonldap::NG::Handler::PSGI::handler { sub Lemonldap::NG::Handler::PSGI::handler {

View File

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

View File

@ -59,6 +59,9 @@
"^/logout": "logout_sso", "^/logout": "logout_sso",
"default": "accept" "default": "accept"
}, },
"test4.example.com": {
"default": "accept"
},
"*.example.org": { "*.example.org": {
"^/orgdeny": "deny", "^/orgdeny": "deny",
"default": "accept" "default": "accept"
@ -74,15 +77,20 @@
} }
}, },
"macros": { "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/", "portal": "http://auth.example.com/",
"reloadUrls": {}, "reloadUrls": {},
"userDB": "Demo", "userDB": "Demo",
"vhostOptions": { "vhostOptions": {
"test2.example.com": { "test2.example.com": {
"vhostAuthnLevel": 5 "vhostAuthnLevel": 5
} },
"test4.example.com": {
"vhostAccessToTrace": "My::accessToTrace, Doctor, Who, UA"
}
}, },
"whatToTrace": "_whatToTrace" "whatToTrace": "_whatToTrace",
"customToTrace": "mail"
} }

View File

@ -196,17 +196,20 @@ site/htdocs/static/js/viewer.min.js.map
site/htdocs/static/languages/ar.json site/htdocs/static/languages/ar.json
site/htdocs/static/languages/de.json site/htdocs/static/languages/de.json
site/htdocs/static/languages/en.json site/htdocs/static/languages/en.json
site/htdocs/static/languages/es.json
site/htdocs/static/languages/fr.json site/htdocs/static/languages/fr.json
site/htdocs/static/languages/it.json site/htdocs/static/languages/it.json
site/htdocs/static/languages/pl.json site/htdocs/static/languages/pl.json
site/htdocs/static/languages/tr.json site/htdocs/static/languages/tr.json
site/htdocs/static/languages/vi.json site/htdocs/static/languages/vi.json
site/htdocs/static/languages/zh.json site/htdocs/static/languages/zh.json
site/htdocs/static/languages/zh_TW.json
site/htdocs/static/logos/ar.png site/htdocs/static/logos/ar.png
site/htdocs/static/logos/bootstrap.png site/htdocs/static/logos/bootstrap.png
site/htdocs/static/logos/custom.png site/htdocs/static/logos/custom.png
site/htdocs/static/logos/de.png site/htdocs/static/logos/de.png
site/htdocs/static/logos/en.png site/htdocs/static/logos/en.png
site/htdocs/static/logos/es.png
site/htdocs/static/logos/favicon.ico site/htdocs/static/logos/favicon.ico
site/htdocs/static/logos/fr.png site/htdocs/static/logos/fr.png
site/htdocs/static/logos/it.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/tr.png
site/htdocs/static/logos/vi.png site/htdocs/static/logos/vi.png
site/htdocs/static/logos/zh.png site/htdocs/static/logos/zh.png
site/htdocs/static/logos/zh_TW.png
site/htdocs/static/reverseTree.json site/htdocs/static/reverseTree.json
site/htdocs/static/struct.json site/htdocs/static/struct.json
site/templates/2ndfa.tpl site/templates/2ndfa.tpl

View File

@ -10,7 +10,7 @@
# Sessions.pm to manage sessions # Sessions.pm to manage sessions
package Lemonldap::NG::Manager; package Lemonldap::NG::Manager;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use JSON; use JSON;

View File

@ -1,6 +1,5 @@
package Lemonldap::NG::Manager::2ndFA; package Lemonldap::NG::Manager::2ndFA;
use 5.10.0;
use utf8; use utf8;
use strict; use strict;
use Mouse; use Mouse;
@ -12,9 +11,11 @@ use Lemonldap::NG::Common::Conf::ReConstants;
use feature 'state'; use feature 'state';
extends 'Lemonldap::NG::Manager::Plugin', extends qw(
'Lemonldap::NG::Common::Conf::AccessLib', Lemonldap::NG::Manager::Plugin
'Lemonldap::NG::Common::Session::REST'; Lemonldap::NG::Common::Session::REST
Lemonldap::NG::Common::Conf::AccessLib
);
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';

View File

@ -1,13 +1,15 @@
# This module implements all the methods that responds to '/api/*' requests # This module implements all the methods that responds to '/api/*' requests
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
extends 'Lemonldap::NG::Manager::Plugin', extends qw(
'Lemonldap::NG::Common::Conf::RESTServer', Lemonldap::NG::Manager::Plugin
'Lemonldap::NG::Common::Session::REST'; Lemonldap::NG::Common::Session::REST
Lemonldap::NG::Common::Conf::RESTServer
);
use Lemonldap::NG::Manager::Api::2F; use Lemonldap::NG::Manager::Api::2F;
use Lemonldap::NG::Manager::Api::Misc; use Lemonldap::NG::Manager::Api::Misc;

View File

@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use JSON; use JSON;

View File

@ -4,6 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use strict;
use Lemonldap::NG::Manager::Build::Attributes; use Lemonldap::NG::Manager::Build::Attributes;
use Lemonldap::NG::Manager::Build::CTrees; use Lemonldap::NG::Manager::Build::CTrees;
@ -26,7 +27,7 @@ sub _getDefaultValues {
my $defaultAttrs = Lemonldap::NG::Manager::Build::Attributes::attributes(); my $defaultAttrs = Lemonldap::NG::Manager::Build::Attributes::attributes();
my $attrs = {}; my $attrs = {};
foreach $attr (@allAttrs) { foreach my $attr (@allAttrs) {
$attrs->{$attr} = $defaultAttrs->{$attr}->{default} $attrs->{$attr} = $defaultAttrs->{$attr}->{default}
if ( defined $defaultAttrs->{$attr} if ( defined $defaultAttrs->{$attr}
&& defined $defaultAttrs->{$attr}->{default} ); && defined $defaultAttrs->{$attr}->{default} );
@ -39,7 +40,7 @@ sub _hasAllowedAttributes {
my ( $self, $attributes, $rootNode ) = @_; my ( $self, $attributes, $rootNode ) = @_;
my @allowedAttributes = $self->_listAttributes($rootNode); my @allowedAttributes = $self->_listAttributes($rootNode);
foreach $attribute ( keys %{$attributes} ) { foreach my $attribute ( keys %{$attributes} ) {
if ( length( ref($attribute) ) ) { if ( length( ref($attribute) ) ) {
return { return {
res => "ko", res => "ko",

View File

@ -4,11 +4,10 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Manager::Conf::Parser; use Lemonldap::NG::Manager::Conf::Parser;
use Data::Dumper;
extends 'Lemonldap::NG::Manager::Api::Common'; extends 'Lemonldap::NG::Manager::Api::Common';

View File

@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Manager::Conf::Parser; use Lemonldap::NG::Manager::Conf::Parser;

View File

@ -5,6 +5,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use strict;
use Mouse; use Mouse;
extends 'Lemonldap::NG::Manager::Api::Common'; extends 'Lemonldap::NG::Manager::Api::Common';

View File

@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Manager::Conf::Parser; use Lemonldap::NG::Manager::Conf::Parser;

View File

@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Manager::Conf::Parser; use Lemonldap::NG::Manager::Conf::Parser;

View File

@ -4,7 +4,7 @@ our $VERSION = '2.1.0';
package Lemonldap::NG::Manager::Api; package Lemonldap::NG::Manager::Api;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;

View File

@ -22,10 +22,9 @@ sub perlExpr {
grep( { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_; } grep( { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_; }
split( /\n/, $@, 0 ) ) split( /\n/, $@, 0 ) )
); );
return -1, "__badExpression__: $err" if $err; return -1, "__badExpression__: $err" if $err and $conf->{'useSafeJail'};
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/ return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/
? ( -1, '__badExpressionAssignment__' ) && $conf->{'avoidAssignment'} ? ( 1, '__badExpressionAssignment__' ) : 1;
: 1;
} }
sub types { sub types {
@ -642,6 +641,10 @@ sub attributes {
'default' => 'TOTP,U2F,Yubikey', 'default' => 'TOTP,U2F,Yubikey',
'type' => 'text' 'type' => 'text'
}, },
'avoidAssignment' => {
'default' => 0,
'type' => 'bool'
},
'browsersDontStorePassword' => { 'browsersDontStorePassword' => {
'default' => 0, 'default' => 0,
'type' => 'bool' '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', 'default' => '_loginHistory _session_id hGroups',
'type' => 'text' 'type' => 'text'
}, },
'checkUserHiddenHeaders' => {
'keyMsgFail' => '__badHostname__',
'keyTest' => qr/^\S+$/,
'test' => {
'keyMsgFail' => '__badHeaderName__',
'keyTest' => qr/^(?=[^\-])[\w\-\s]+(?<=[^-])$/,
'test' => sub {
return perlExpr(@_);
}
},
'type' => 'keyTextContainer'
},
'checkUserIdRule' => { 'checkUserIdRule' => {
'default' => 1, 'default' => 1,
'test' => sub { 'test' => sub {
@ -1906,6 +1921,9 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
'mail2fLogo' => { 'mail2fLogo' => {
'type' => 'text' 'type' => 'text'
}, },
'mail2fSessionKey' => {
'type' => 'text'
},
'mail2fSubject' => { 'mail2fSubject' => {
'type' => 'text' 'type' => 'text'
}, },
@ -4144,6 +4162,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'utotp2fLogo' => { 'utotp2fLogo' => {
'type' => 'text' 'type' => 'text'
}, },
'vhostAccessToTrace' => {
'default' => '',
'type' => 'text'
},
'vhostAliases' => { 'vhostAliases' => {
'default' => '', 'default' => '',
'type' => 'text' 'type' => 'text'

View File

@ -27,9 +27,10 @@ sub perlExpr {
my $err = join( '', my $err = join( '',
grep { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_ } grep { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_ }
split( /\n/, $@ ) ); split( /\n/, $@ ) );
return ( -1, "__badExpression__: $err" ) if $err; return ( -1, "__badExpression__: $err" )
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/ if ( $err && $conf->{useSafeJail} );
? ( -1, "__badExpressionAssignment__" ) return ( $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/ && $conf->{avoidAssignment} )
? ( 1, "__badExpressionAssignment__" )
: 1; : 1;
} }
@ -516,6 +517,17 @@ sub attributes {
documentation => 'Display empty headers rule', documentation => 'Display empty headers rule',
flags => 'p', 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 => { globalLogoutRule => {
type => 'boolOrExpr', type => 'boolOrExpr',
default => 0, default => 0,
@ -1062,6 +1074,13 @@ sub attributes {
documentation => 'Activate Safe jail', documentation => 'Activate Safe jail',
flags => 'hp', flags => 'hp',
}, },
avoidAssignment => {
default => 0,
type => 'bool',
help => 'safejail.html',
documentation => 'Avoid assignment in expressions',
flags => 'hp',
},
whatToTrace => { whatToTrace => {
type => 'lmAttrOrMacro', type => 'lmAttrOrMacro',
default => 'uid', default => 'uid',
@ -1878,6 +1897,10 @@ sub attributes {
type => 'text', type => 'text',
documentation => 'Custom logo for Mail 2F', documentation => 'Custom logo for Mail 2F',
}, },
mail2fSessionKey => {
type => 'text',
documentation => 'Session parameter where mail is stored',
},
# External second factor # External second factor
ext2fActivation => { ext2fActivation => {
@ -2239,8 +2262,9 @@ sub attributes {
type => 'int', type => 'int',
default => -1, default => -1,
}, },
vhostAliases => { type => 'text', default => '' }, vhostAccessToTrace => { type => 'text', default => '' },
vhostType => { vhostAliases => { type => 'text', default => '' },
vhostType => {
type => 'select', type => 'select',
select => [ select => [
{ k => 'AuthBasic', v => 'AuthBasic' }, { k => 'AuthBasic', v => 'AuthBasic' },

View File

@ -27,10 +27,10 @@ sub cTrees {
help => 'configvhost.html#options', help => 'configvhost.html#options',
form => 'simpleInputContainer', form => 'simpleInputContainer',
nodes => [ nodes => [
'vhostPort', 'vhostHttps', 'vhostPort', 'vhostHttps',
'vhostMaintenance', 'vhostAliases', 'vhostMaintenance', 'vhostAliases',
'vhostType', 'vhostAuthnLevel', 'vhostAccessToTrace', 'vhostType',
'vhostServiceTokenTTL' 'vhostAuthnLevel', 'vhostServiceTokenTTL'
], ],
}, },
], ],

View File

@ -271,7 +271,7 @@ sub tree {
'managerDn', 'managerPassword', 'managerDn', 'managerPassword',
'ldapTimeout', 'ldapIOTimeout', 'ldapTimeout', 'ldapIOTimeout',
'ldapVersion', 'ldapRaw', 'ldapVersion', 'ldapRaw',
'ldapCAFile', 'ldapCAPath', 'ldapCAFile', 'ldapCAPath',
] ]
}, },
{ {
@ -553,10 +553,8 @@ sub tree {
title => 'logParams', title => 'logParams',
help => 'logs.html', help => 'logs.html',
form => 'simpleInputContainer', form => 'simpleInputContainer',
nodes => [ nodes =>
'whatToTrace', 'customToTrace', [ 'whatToTrace', 'customToTrace', 'hiddenAttributes' ]
'hiddenAttributes'
]
}, },
{ {
title => 'cookieParams', title => 'cookieParams',
@ -772,7 +770,6 @@ sub tree {
{ {
title => 'checkUsers', title => 'checkUsers',
help => 'checkuser.html', help => 'checkuser.html',
form => 'simpleInputContainer',
nodes => [ nodes => [
'checkUser', 'checkUser',
'checkUserIdRule', 'checkUserIdRule',
@ -783,6 +780,7 @@ sub tree {
'checkUserDisplayEmptyHeaders', 'checkUserDisplayEmptyHeaders',
'checkUserDisplayEmptyValues', 'checkUserDisplayEmptyValues',
'checkUserDisplayPersistentInfo', 'checkUserDisplayPersistentInfo',
'checkUserHiddenHeaders'
] ]
}, },
{ {
@ -900,6 +898,7 @@ sub tree {
'mail2fTimeout', 'mail2fSubject', 'mail2fTimeout', 'mail2fSubject',
'mail2fBody', 'mail2fAuthnLevel', 'mail2fBody', 'mail2fAuthnLevel',
'mail2fLabel', 'mail2fLogo', 'mail2fLabel', 'mail2fLogo',
'mail2fSessionKey',
] ]
}, },
{ {
@ -991,6 +990,7 @@ sub tree {
'key', 'key',
'trustedDomains', 'trustedDomains',
'useSafeJail', 'useSafeJail',
'avoidAssignment',
'checkXSS', 'checkXSS',
'requireToken', 'requireToken',
'formTimeout', 'formTimeout',

View File

@ -6,7 +6,7 @@
# Read methods are inherited from Lemonldap::NG::Common::Conf::RESTServer # Read methods are inherited from Lemonldap::NG::Common::Conf::RESTServer
package Lemonldap::NG::Manager::Conf; package Lemonldap::NG::Manager::Conf;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Common::Conf::Constants; use Lemonldap::NG::Common::Conf::Constants;

View File

@ -1,5 +1,6 @@
package Lemonldap::NG::Manager::Conf::Tests; package Lemonldap::NG::Manager::Conf::Tests;
use strict;
use utf8; use utf8;
use Lemonldap::NG::Common::Regexp; use Lemonldap::NG::Common::Regexp;
use Lemonldap::NG::Handler::Main; use Lemonldap::NG::Handler::Main;
@ -449,7 +450,7 @@ sub tests {
"RSA_SHA1" ) "RSA_SHA1" )
{ {
undef $allsha1; undef $allsha1;
break; last;
} }
} }
} }
@ -461,7 +462,7 @@ sub tests {
->{samlSPMetaDataOptionsSignatureMethod} ne "RSA_SHA1" ) ->{samlSPMetaDataOptionsSignatureMethod} ne "RSA_SHA1" )
{ {
undef $allsha1; undef $allsha1;
break; last;
} }
} }
} }
@ -865,8 +866,7 @@ sub tests {
$appUrl =~ m#^(https?://[^/]+)(/.*)?$#; $appUrl =~ m#^(https?://[^/]+)(/.*)?$#;
my $appHost = $1; my $appHost = $1;
unless ($appHost) { unless ($appHost) {
push @msg, push @msg, "$casConfKey CAS Application has no Service URL";
"$clientConfKey CAS Application has no Service URL";
$res = 0; $res = 0;
next; next;
} }

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Manager::Notifications; package Lemonldap::NG::Manager::Notifications;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);

View File

@ -1,6 +1,5 @@
package Lemonldap::NG::Manager::Sessions; package Lemonldap::NG::Manager::Sessions;
use 5.10.0;
use utf8; use utf8;
use strict; use strict;
use Mouse; use Mouse;

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Manager::Viewer; package Lemonldap::NG::Manager::Viewer;
use 5.10.0; use strict;
use utf8; use utf8;
use Mouse; use Mouse;
use Lemonldap::NG::Common::Conf::Constants; use Lemonldap::NG::Common::Conf::Constants;

View File

@ -577,7 +577,9 @@ llapp.controller 'TreeCtrl', [
d = $q.defer() d = $q.defer()
d.notify 'Trying to get datas' d.notify 'Trying to get datas'
$scope.waiting = true $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 data = response.data
# Manage datas errors # Manage datas errors
if not data if not data
@ -759,7 +761,13 @@ llapp.controller 'TreeCtrl', [
d.reject response.statusLine d.reject response.statusLine
$scope.waiting = false $scope.waiting = false
else 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 # Set default value if response is null or if asked by server
data = response.data data = response.data
if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null

View File

@ -258,7 +258,9 @@ llapp.controller 'TreeCtrl', [
d = $q.defer() d = $q.defer()
d.notify 'Trying to get datas' d.notify 'Trying to get datas'
$scope.waiting = true $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 data = response.data
# Manage datas errors # Manage datas errors
if not data if not data
@ -360,7 +362,13 @@ llapp.controller 'TreeCtrl', [
d.reject response.statusLine d.reject response.statusLine
$scope.waiting = false $scope.waiting = false
else 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 # Set default value if response is null or if asked by server
data = response.data data = response.data
if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null 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

View File

@ -1327,6 +1327,12 @@ function templates(tpl,key) {
"id" : tpl+"s/"+key+"/"+"vhostAliases", "id" : tpl+"s/"+key+"/"+"vhostAliases",
"title" : "vhostAliases" "title" : "vhostAliases"
}, },
{
"default" : "",
"get" : tpl+"s/"+key+"/"+"vhostAccessToTrace",
"id" : tpl+"s/"+key+"/"+"vhostAccessToTrace",
"title" : "vhostAccessToTrace"
},
{ {
"default" : "Main", "default" : "Main",
"get" : tpl+"s/"+key+"/"+"vhostType", "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

View File

@ -718,11 +718,13 @@ This file contains:
return _download(node); return _download(node);
}; };
_download = function(node) { _download = function(node) {
var d; var d, uri;
d = $q.defer(); d = $q.defer();
d.notify('Trying to get datas'); d.notify('Trying to get datas');
$scope.waiting = true; $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; var a, data, len, o;
data = response.data; data = response.data;
if (!data) { if (!data) {
@ -900,7 +902,7 @@ This file contains:
}, readError); }, readError);
}; };
$scope.getKey = function(node) { $scope.getKey = function(node) {
var d, i, len, n, o, ref, tmp; var d, i, len, n, o, ref, tmp, uri;
d = $q.defer(); d = $q.defer();
if (!node.data) { if (!node.data) {
$scope.waiting = true; $scope.waiting = true;
@ -923,7 +925,14 @@ This file contains:
return $scope.waiting = false; return $scope.waiting = false;
}); });
} else { } 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; var data;
data = response.data; data = response.data;
if ((data.value === null || (data.error && data.error.match(/setDefault$/))) && node['default'] !== null) { 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

View File

@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.12.7 // Generated by CoffeeScript 1.12.8
/* /*
LemonLDAP::NG Viewer client LemonLDAP::NG Viewer client
@ -328,11 +328,13 @@ This file contains:
return _download(node); return _download(node);
}; };
_download = function(node) { _download = function(node) {
var d; var d, uri;
d = $q.defer(); d = $q.defer();
d.notify('Trying to get datas'); d.notify('Trying to get datas');
$scope.waiting = true; $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; var a, data, l, len;
data = response.data; data = response.data;
if (!data) { if (!data) {
@ -420,7 +422,7 @@ This file contains:
} }
}; };
$scope.getKey = function(node) { $scope.getKey = function(node) {
var d, i, l, len, n, ref, tmp; var d, i, l, len, n, ref, tmp, uri;
d = $q.defer(); d = $q.defer();
if (!node.data) { if (!node.data) {
$scope.waiting = true; $scope.waiting = true;
@ -443,7 +445,14 @@ This file contains:
return $scope.waiting = false; return $scope.waiting = false;
}); });
} else { } 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; var data;
data = response.data; data = response.data;
if ((data.value === null || (data.error && data.error.match(/setDefault$/))) && node['default'] !== null) { 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

View File

@ -75,6 +75,7 @@
"auto":"تلقائي", "auto":"تلقائي",
"autoSignin":"Auto Signin", "autoSignin":"Auto Signin",
"autoSigninRules":"القواعد", "autoSigninRules":"القواعد",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"العودة إلى البوابة", "backtoportal":"العودة إلى البوابة",
"badCasProxyId":"معرف خدمة بروكسي كاس غير صالح", "badCasProxyId":"معرف خدمة بروكسي كاس غير صالح",
"badChoiceKey":"اسم مفتاح سيئ في قائمة الاختيارات", "badChoiceKey":"اسم مفتاح سيئ في قائمة الاختيارات",
@ -83,7 +84,7 @@
"badDomainName":"اسم النطاق سيئ", "badDomainName":"اسم النطاق سيئ",
"badEncoding":"تشفير خاطئ", "badEncoding":"تشفير خاطئ",
"badExpression":"تعبير خاطئ", "badExpression":"تعبير خاطئ",
"badExpressionAssignment":"Expression containing an assignment", "badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
"badHeaderName":" حقل الهيدر خاطئ", "badHeaderName":" حقل الهيدر خاطئ",
"badHostname":"اسم الخادم خاطئ", "badHostname":"اسم الخادم خاطئ",
"badLdapUri":"\n URI LDAP خاطئ", "badLdapUri":"\n URI LDAP خاطئ",
@ -207,6 +208,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values", "checkUserDisplayEmptyValues":"Display empty values",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"اختيارالإعدادات", "choiceParams":"اختيارالإعدادات",
"chooseLogo":"اختيار الشعار", "chooseLogo":"اختيار الشعار",
@ -494,6 +496,7 @@
"mail2fAuthnLevel":"مستوى إثبات الهوية", "mail2fAuthnLevel":"مستوى إثبات الهوية",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"شعار", "mail2fLogo":"شعار",
"mail2fSessionKey":"مفتاح الجلسة الذي يحتوي على عنوان البريد الإلكتروني",
"mailBody":"محتوى البريد الناجح", "mailBody":"محتوى البريد الناجح",
"mailCharset":"charset", "mailCharset":"charset",
"mailConfirmBody":"تأكيد محتوى البريد", "mailConfirmBody":"تأكيد محتوى البريد",
@ -586,7 +589,7 @@
"offlineSessions":"Offline sessions", "offlineSessions":"Offline sessions",
"oldValue":"قيمة قديمة", "oldValue":"قيمة قديمة",
"on":"تنشيط", "on":"تنشيط",
"oidcAttribute":"OIDC Attribute", "oidcAttribute":"خاصيات OIDC",
"oidcAuthnLevel":"مستوى إثبات الهوية", "oidcAuthnLevel":"مستوى إثبات الهوية",
"oidcConsents":"OpenID Connect Consents", "oidcConsents":"OpenID Connect Consents",
"oidcOP":" أوبين أيدي كونيكت بروفيدر", "oidcOP":" أوبين أيدي كونيكت بروفيدر",
@ -1004,6 +1007,7 @@
"verifyU2FKey":"Verify U2F key", "verifyU2FKey":"Verify U2F key",
"verifyTOTPKey":"Verify TOTP key", "verifyTOTPKey":"Verify TOTP key",
"version":"الإصدار", "version":"الإصدار",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"اسماء مستعارة", "vhostAliases":"اسماء مستعارة",
"vhostAuthnLevel":"مستوى إثبات الهوية واجب", "vhostAuthnLevel":"مستوى إثبات الهوية واجب",
"vhostHttps":"إتش تي تي بي س", "vhostHttps":"إتش تي تي بي س",

View File

@ -75,6 +75,7 @@
"auto":"Automatic", "auto":"Automatic",
"autoSignin":"Auto Signin", "autoSignin":"Auto Signin",
"autoSigninRules":"Regeln", "autoSigninRules":"Regeln",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Back to portal", "backtoportal":"Back to portal",
"badCasProxyId":"Bad CAS proxied service identifier", "badCasProxyId":"Bad CAS proxied service identifier",
"badChoiceKey":"Bad key name in Choice menu", "badChoiceKey":"Bad key name in Choice menu",
@ -83,7 +84,7 @@
"badDomainName":"Ungültiger Domainname", "badDomainName":"Ungültiger Domainname",
"badEncoding":"Ungültige Codierung", "badEncoding":"Ungültige Codierung",
"badExpression":"Bad expression", "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", "badHeaderName":"Bad header name",
"badHostname":"Ungültiger Hostname", "badHostname":"Ungültiger Hostname",
"badLdapUri":"Bad LDAP URI", "badLdapUri":"Bad LDAP URI",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values", "checkUserDisplayEmptyValues":"Display empty values",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters", "choiceParams":"Choice parameters",
"chooseLogo":"Choose logo", "chooseLogo":"Choose logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Authentication level", "mail2fAuthnLevel":"Authentication level",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Session key containing mail address",
"mailBody":"Success mail content", "mailBody":"Success mail content",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Confirmation mail content", "mailConfirmBody":"Confirmation mail content",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Verify U2F key", "verifyU2FKey":"Verify U2F key",
"verifyTOTPKey":"Verify TOTP key", "verifyTOTPKey":"Verify TOTP key",
"version":"Version", "version":"Version",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Aliases", "vhostAliases":"Aliases",
"vhostAuthnLevel":"Required authentication level", "vhostAuthnLevel":"Required authentication level",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"Automatic", "auto":"Automatic",
"autoSignin":"Auto Signin", "autoSignin":"Auto Signin",
"autoSigninRules":"Rules", "autoSigninRules":"Rules",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Back to portal", "backtoportal":"Back to portal",
"badCasProxyId":"Bad CAS proxied service identifier", "badCasProxyId":"Bad CAS proxied service identifier",
"badChoiceKey":"Bad key name in Choice menu", "badChoiceKey":"Bad key name in Choice menu",
@ -83,7 +84,7 @@
"badDomainName":"Bad domain name", "badDomainName":"Bad domain name",
"badEncoding":"Bad encoding", "badEncoding":"Bad encoding",
"badExpression":"Bad expression", "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", "badHeaderName":"Bad header name",
"badHostname":"Bad hostname", "badHostname":"Bad hostname",
"badLdapUri":"Bad LDAP URI", "badLdapUri":"Bad LDAP URI",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values", "checkUserDisplayEmptyValues":"Display empty values",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters", "choiceParams":"Choice parameters",
"chooseLogo":"Choose logo", "chooseLogo":"Choose logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Authentication level", "mail2fAuthnLevel":"Authentication level",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Session key containing mail address",
"mailBody":"Success mail content", "mailBody":"Success mail content",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Confirmation mail content", "mailConfirmBody":"Confirmation mail content",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Verify U2F key", "verifyU2FKey":"Verify U2F key",
"verifyTOTPKey":"Verify TOTP key", "verifyTOTPKey":"Verify TOTP key",
"version":"Version", "version":"Version",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Aliases", "vhostAliases":"Aliases",
"vhostAuthnLevel":"Required authentication level", "vhostAuthnLevel":"Required authentication level",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"Automatique", "auto":"Automatique",
"autoSignin":"Connexion automatique", "autoSignin":"Connexion automatique",
"autoSigninRules":"Règles", "autoSigninRules":"Règles",
"avoidAssignment":"Eviter une affectation dans les expressions",
"backtoportal":"Retour au portail", "backtoportal":"Retour au portail",
"badCasProxyId":"Mauvais identifiant de service proxy CAS", "badCasProxyId":"Mauvais identifiant de service proxy CAS",
"badChoiceKey":"Mauvais nom de clef dans le menu Choice", "badChoiceKey":"Mauvais nom de clef dans le menu Choice",
@ -83,7 +84,7 @@
"badDomainName":"Mauvais nom de domaine", "badDomainName":"Mauvais nom de domaine",
"badEncoding":"Mauvais encodage", "badEncoding":"Mauvais encodage",
"badExpression":"Mauvaise expression", "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", "badHeaderName":"Mauvais nom d'en-tête",
"badHostname":"Mauvais nom d'hôte", "badHostname":"Mauvais nom d'hôte",
"badLdapUri":"Mauvaise URI LDAP", "badLdapUri":"Mauvaise URI LDAP",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Afficher les données de session persistante", "checkUserDisplayPersistentInfo":"Afficher les données de session persistante",
"checkUserDisplayEmptyHeaders":"Afficher les entêtes nuls", "checkUserDisplayEmptyHeaders":"Afficher les entêtes nuls",
"checkUserDisplayEmptyValues":"Afficher les valeurs nulles", "checkUserDisplayEmptyValues":"Afficher les valeurs nulles",
"checkUserHiddenHeaders":"Entêtes masqués",
"checkUserSearchAttributes":"Attributs utilisés pour rechercher les sessions", "checkUserSearchAttributes":"Attributs utilisés pour rechercher les sessions",
"choiceParams":"Paramètres des choix", "choiceParams":"Paramètres des choix",
"chooseLogo":"Choisir le logo", "chooseLogo":"Choisir le logo",
@ -373,7 +375,7 @@
"impersonationMergeSSOgroups":"Fusionner les groupes SSO réels et usurpés", "impersonationMergeSSOgroups":"Fusionner les groupes SSO réels et usurpés",
"impersonationSkipEmptyValues":"Ignorer les valeurs nulles", "impersonationSkipEmptyValues":"Ignorer les valeurs nulles",
"impersonationUnrestrictedUsersRule":"Règle des utilisateurs non restreints", "impersonationUnrestrictedUsersRule":"Règle des utilisateurs non restreints",
"incompleteForm":"Des champs requis manquent", "incompleteForm":"Des champs requis sont manquants",
"index":"Index", "index":"Index",
"infoFormMethod":"Méthode du formulaire d'information", "infoFormMethod":"Méthode du formulaire d'information",
"invalidSessionData":"Donnée de session invalide", "invalidSessionData":"Donnée de session invalide",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Niveau de l'authentification", "mail2fAuthnLevel":"Niveau de l'authentification",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Clef de session contenant l'adresse email",
"mailBody":"Contenu du message de succès", "mailBody":"Contenu du message de succès",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Contenu du message de confirmation", "mailConfirmBody":"Contenu du message de confirmation",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Vérifier la clef U2F", "verifyU2FKey":"Vérifier la clef U2F",
"verifyTOTPKey":"Vérifier la clef TOTP", "verifyTOTPKey":"Vérifier la clef TOTP",
"version":"Version", "version":"Version",
"vhostAccessToTrace":"Accès à tracer",
"vhostAliases":"Alias", "vhostAliases":"Alias",
"vhostAuthnLevel":"Niveau d'authentification requis", "vhostAuthnLevel":"Niveau d'authentification requis",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"Automatico", "auto":"Automatico",
"autoSignin":"Accesso automatico", "autoSignin":"Accesso automatico",
"autoSigninRules":"Regole", "autoSigninRules":"Regole",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Torna al portale", "backtoportal":"Torna al portale",
"badCasProxyId":"Identificatore di servizio difettoso CAS proxy", "badCasProxyId":"Identificatore di servizio difettoso CAS proxy",
"badChoiceKey":"Nome chiave errato nel menu Scelta", "badChoiceKey":"Nome chiave errato nel menu Scelta",
@ -83,7 +84,7 @@
"badDomainName":"Nome di dominio errato", "badDomainName":"Nome di dominio errato",
"badEncoding":"Codifica errata", "badEncoding":"Codifica errata",
"badExpression":"Espressione 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", "badHeaderName":"Nome intestazione errato",
"badHostname":"Hostname errato", "badHostname":"Hostname errato",
"badLdapUri":"LDAP URI errata", "badLdapUri":"LDAP URI errata",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Mostra valori vuoti", "checkUserDisplayEmptyValues":"Mostra valori vuoti",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Scelta parametri", "choiceParams":"Scelta parametri",
"chooseLogo":"Scegli logo", "chooseLogo":"Scegli logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Livello di autenticazione", "mail2fAuthnLevel":"Livello di autenticazione",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Chiave di sessione contenente l'indirizzo di posta",
"mailBody":"Successo contenuto di posta", "mailBody":"Successo contenuto di posta",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Contenuto della mail di conferma", "mailConfirmBody":"Contenuto della mail di conferma",
@ -585,7 +588,7 @@
"offlineSessions":"Offline sessions", "offlineSessions":"Offline sessions",
"oldValue":"Vecchio valore", "oldValue":"Vecchio valore",
"on":"On", "on":"On",
"oidcAttribute":"OIDC Attribute", "oidcAttribute":"Attributo OIDC",
"oidcAuthnLevel":"Livello di autenticazione", "oidcAuthnLevel":"Livello di autenticazione",
"oidcConsents":"OpenID Connect Consents", "oidcConsents":"OpenID Connect Consents",
"oidcOP":"Provider di OpenID Connect", "oidcOP":"Provider di OpenID Connect",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Verifica la chiave U2F", "verifyU2FKey":"Verifica la chiave U2F",
"verifyTOTPKey":"Verifica la chiave TOTP", "verifyTOTPKey":"Verifica la chiave TOTP",
"version":"Versioni", "version":"Versioni",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Alias", "vhostAliases":"Alias",
"vhostAuthnLevel":"Livello di autenticazione richiesto", "vhostAuthnLevel":"Livello di autenticazione richiesto",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"Automatycznie", "auto":"Automatycznie",
"autoSignin":"Zaloguj się automatycznie", "autoSignin":"Zaloguj się automatycznie",
"autoSigninRules":"Zasady", "autoSigninRules":"Zasady",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Powrót do portalu", "backtoportal":"Powrót do portalu",
"badCasProxyId":"Nieprawidłowy identyfikator usługi proxy CAS", "badCasProxyId":"Nieprawidłowy identyfikator usługi proxy CAS",
"badChoiceKey":"Błędna nazwa klucza w menu Wybór", "badChoiceKey":"Błędna nazwa klucza w menu Wybór",
@ -83,7 +84,7 @@
"badDomainName":"Błędna nazwa domeny", "badDomainName":"Błędna nazwa domeny",
"badEncoding":"Błędne kodowanie", "badEncoding":"Błędne kodowanie",
"badExpression":"Błędne wyrażenie", "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", "badHeaderName":"Błędna nazwa nagłówka",
"badHostname":"Błędna nazwa hosta", "badHostname":"Błędna nazwa hosta",
"badLdapUri":"Błędny identyfikator URI LDAP", "badLdapUri":"Błędny identyfikator URI LDAP",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Wyświetl puste nagłówki", "checkUserDisplayEmptyHeaders":"Wyświetl puste nagłówki",
"checkUserDisplayEmptyValues":"Wyświetl puste wartości", "checkUserDisplayEmptyValues":"Wyświetl puste wartości",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Atrybuty używane do wyszukiwania sesji", "checkUserSearchAttributes":"Atrybuty używane do wyszukiwania sesji",
"choiceParams":"Parametry wyboru", "choiceParams":"Parametry wyboru",
"chooseLogo":"Wybierz logo", "chooseLogo":"Wybierz logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Poziom uwierzytelnienia", "mail2fAuthnLevel":"Poziom uwierzytelnienia",
"mail2fLabel":"Etykieta", "mail2fLabel":"Etykieta",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Klucz sesji zawierający adres e-mail",
"mailBody":"Treść wiadomości o powodzeniu", "mailBody":"Treść wiadomości o powodzeniu",
"mailCharset":"Zestaw znaków", "mailCharset":"Zestaw znaków",
"mailConfirmBody":"Treść wiadomości potwierdzającej", "mailConfirmBody":"Treść wiadomości potwierdzającej",
@ -585,7 +588,7 @@
"offlineSessions":"Sesje offline", "offlineSessions":"Sesje offline",
"oldValue":"Stara wartość", "oldValue":"Stara wartość",
"on":"Włączone", "on":"Włączone",
"oidcAttribute":"OIDC Attribute", "oidcAttribute":"Atrybut OIDC",
"oidcAuthnLevel":"Poziom uwierzytelnienia", "oidcAuthnLevel":"Poziom uwierzytelnienia",
"oidcConsents":"Zgoda na OpenID Connect", "oidcConsents":"Zgoda na OpenID Connect",
"oidcOP":"Dostawca OpenID Connect", "oidcOP":"Dostawca OpenID Connect",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Sprawdź klucz U2F", "verifyU2FKey":"Sprawdź klucz U2F",
"verifyTOTPKey":"Sprawdź klucz TOTP", "verifyTOTPKey":"Sprawdź klucz TOTP",
"version":"Wersja", "version":"Wersja",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Aliasy", "vhostAliases":"Aliasy",
"vhostAuthnLevel":"Wymagany poziom uwierzytelnienia", "vhostAuthnLevel":"Wymagany poziom uwierzytelnienia",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -45,7 +45,7 @@
"ADPwdMaxAge":"Parola maksimum sınırı", "ADPwdMaxAge":"Parola maksimum sınırı",
"advancedParams":"Gelişmiş parametreler", "advancedParams":"Gelişmiş parametreler",
"allowedMarkups":"İzin verilen biçimlendirmeler:", "allowedMarkups":"İzin verilen biçimlendirmeler:",
"always":"Always", "always":"Her zaman",
"apacheParams":"Apache parametreleri", "apacheParams":"Apache parametreleri",
"apacheAuthnLevel":"Doğrulama seviyesi", "apacheAuthnLevel":"Doğrulama seviyesi",
"application":"Uygulama", "application":"Uygulama",
@ -55,7 +55,7 @@
"appsInThisCat":"Bu kategorideki uygulamalar", "appsInThisCat":"Bu kategorideki uygulamalar",
"array":"Array", "array":"Array",
"attributesAndMacros":"Nitelikler ve Makrolar", "attributesAndMacros":"Nitelikler ve Makrolar",
"attributeName":"Attribute name", "attributeName":"Nitelik adı",
"authAndUserdb":"Yetkilendirme ve kullanıcı veri tabanı", "authAndUserdb":"Yetkilendirme ve kullanıcı veri tabanı",
"authChain":"Doğrulama zinciri", "authChain":"Doğrulama zinciri",
"authChoice":"Kimlik doğrulama tercihi", "authChoice":"Kimlik doğrulama tercihi",
@ -75,6 +75,7 @@
"auto":"Otomatik", "auto":"Otomatik",
"autoSignin":"Otomatik Oturum Açma", "autoSignin":"Otomatik Oturum Açma",
"autoSigninRules":"Kurallar", "autoSigninRules":"Kurallar",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Portala geri dön", "backtoportal":"Portala geri dön",
"badCasProxyId":"Hatalı CAS vekil servis tanımlayıcısı", "badCasProxyId":"Hatalı CAS vekil servis tanımlayıcısı",
"badChoiceKey":"Tercih menüsünde hatalı anahtar adı", "badChoiceKey":"Tercih menüsünde hatalı anahtar adı",
@ -83,7 +84,7 @@
"badDomainName":"Hatalı etki alanı adı", "badDomainName":"Hatalı etki alanı adı",
"badEncoding":"Hatalı kodlama", "badEncoding":"Hatalı kodlama",
"badExpression":"Hatalı ifade", "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ı", "badHeaderName":"Hatalı başlık adı",
"badHostname":"Hatalı konak adı", "badHostname":"Hatalı konak adı",
"badLdapUri":"Hatalı LDAP URI", "badLdapUri":"Hatalı LDAP URI",
@ -100,7 +101,7 @@
"badValue":"Hatalı değer", "badValue":"Hatalı değer",
"badVariableName":"Hatalı değişken adı", "badVariableName":"Hatalı değişken adı",
"blackList":"Kara liste", "blackList":"Kara liste",
"bool":"Boolean", "bool":"Mantıksal",
"browse":"Göz at", "browse":"Göz at",
"browsersDontStorePassword":"Kullanıcı parolasını tarayıcılarda saklamaktan kaçının", "browsersDontStorePassword":"Kullanıcı parolasını tarayıcılarda saklamaktan kaçının",
"browserIdAuthnLevel":"Doğrulama seviyesi", "browserIdAuthnLevel":"Doğrulama seviyesi",
@ -193,7 +194,7 @@
"cfgVersion":"Yapılandırma sürümü", "cfgVersion":"Yapılandırma sürümü",
"checkXSS":"XSS saldırılarını kontrol et", "checkXSS":"XSS saldırılarını kontrol et",
"clickHereToForce":"Zorlamak için buraya tıklayın", "clickHereToForce":"Zorlamak için buraya tıklayın",
"claimName":"Claim name", "claimName":"İstek adı",
"checkboxes":"Onay kutuları", "checkboxes":"Onay kutuları",
"checkState":"Aktivasyon", "checkState":"Aktivasyon",
"checkStateSecret":"Paylaşılan sır", "checkStateSecret":"Paylaşılan sır",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Kalıcı oturum verisini görüntüle", "checkUserDisplayPersistentInfo":"Kalıcı oturum verisini görüntüle",
"checkUserDisplayEmptyHeaders":"Boş başlıkları görüntüle", "checkUserDisplayEmptyHeaders":"Boş başlıkları görüntüle",
"checkUserDisplayEmptyValues":"Boş değerleri görüntüle", "checkUserDisplayEmptyValues":"Boş değerleri görüntüle",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler", "checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler",
"choiceParams":"Tercih parametreleri", "choiceParams":"Tercih parametreleri",
"chooseLogo":"Logo seçin", "chooseLogo":"Logo seçin",
@ -377,7 +379,7 @@
"index":"Dizin", "index":"Dizin",
"infoFormMethod":"Bilgi formu için metot", "infoFormMethod":"Bilgi formu için metot",
"invalidSessionData":"Geçersiz oturum verisi", "invalidSessionData":"Geçersiz oturum verisi",
"int":"Integer", "int":"Sayı",
"internalReference":"Dahili referans", "internalReference":"Dahili referans",
"ipAddr":"IP adresi", "ipAddr":"IP adresi",
"ipAddresses":"IP adresleri", "ipAddresses":"IP adresleri",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Doğrulama seviyesi", "mail2fAuthnLevel":"Doğrulama seviyesi",
"mail2fLabel":"Etiket", "mail2fLabel":"Etiket",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Oturum anahtarı e-posta adresini içeriyor",
"mailBody":"Başarılı e-posta içeriği", "mailBody":"Başarılı e-posta içeriği",
"mailCharset":"Karakter seti", "mailCharset":"Karakter seti",
"mailConfirmBody":"Doğrulama e-postası içeriği", "mailConfirmBody":"Doğrulama e-postası içeriği",
@ -526,7 +529,7 @@
"name":"Ad", "name":"Ad",
"needConfirmation":"Yeni bir yapılandırma mevcut. Bunu kaydetmeye zorlamak için 'kaydet' butonunun yanındaki onay kutusuna tıklayın.", "needConfirmation":"Yeni bir yapılandırma mevcut. Bunu kaydetmeye zorlamak için 'kaydet' butonunun yanındaki onay kutusuna tıklayın.",
"networkProblem":"Ağ problemi", "networkProblem":"Ağ problemi",
"never":"Never", "never":"Asla",
"newApp":"Yeni uygulama", "newApp":"Yeni uygulama",
"newChain":"Yeni zincir", "newChain":"Yeni zincir",
"newCat":"Yeni kategori", "newCat":"Yeni kategori",
@ -585,7 +588,7 @@
"offlineSessions":"Çevrimdışı oturumlar", "offlineSessions":"Çevrimdışı oturumlar",
"oldValue":"Eski değer", "oldValue":"Eski değer",
"on":"Açık", "on":"Açık",
"oidcAttribute":"OIDC Attribute", "oidcAttribute":"OIDC niteliği",
"oidcAuthnLevel":"Doğrulama seviyesi", "oidcAuthnLevel":"Doğrulama seviyesi",
"oidcConsents":"OpenID Connect İzinleri", "oidcConsents":"OpenID Connect İzinleri",
"oidcOP":"OpenID Connect Sağlayıcısı", "oidcOP":"OpenID Connect Sağlayıcısı",
@ -999,10 +1002,11 @@
"value":"Değer", "value":"Değer",
"values":"Değerler", "values":"Değerler",
"variables":"Değişkenler", "variables":"Değişkenler",
"variableName":"Variable name", "variableName":"Değişken adı",
"verifyU2FKey":"U2F anahtarını doğrula", "verifyU2FKey":"U2F anahtarını doğrula",
"verifyTOTPKey":"TOTP anahtarını doğrula", "verifyTOTPKey":"TOTP anahtarını doğrula",
"version":"Sürüm", "version":"Sürüm",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Takma adlar", "vhostAliases":"Takma adlar",
"vhostAuthnLevel":"Gereken doğrulama seviyesi", "vhostAuthnLevel":"Gereken doğrulama seviyesi",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"Tự động", "auto":"Tự động",
"autoSignin":"Auto Signin", "autoSignin":"Auto Signin",
"autoSigninRules":"Quy tắc", "autoSigninRules":"Quy tắc",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"Quay lại cổng thông tin", "backtoportal":"Quay lại cổng thông tin",
"badCasProxyId":"Dịch vụ định danh đệm bởi CAS không hợp lệ", "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", "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ệ", "badDomainName":"Tên miền không hợp lệ",
"badEncoding":"Mã hoá không hợp lệ", "badEncoding":"Mã hoá không hợp lệ",
"badExpression":"Biểu thức 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ệ", "badHeaderName":"Tên tiêu đề không hợp lệ",
"badHostname":"Tên máy chủ không hợp lệ", "badHostname":"Tên máy chủ không hợp lệ",
"badLdapUri":"URI LDAP không đúng", "badLdapUri":"URI LDAP không đúng",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values", "checkUserDisplayEmptyValues":"Display empty values",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Các tham số lựa chọn", "choiceParams":"Các tham số lựa chọn",
"chooseLogo":"Chọn logo", "chooseLogo":"Chọn logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"Mức xác thực", "mail2fAuthnLevel":"Mức xác thực",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Khóa phiên chứa địa chỉ thư",
"mailBody":"Nội dung thư thành công", "mailBody":"Nội dung thư thành công",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Xác nhận nội dung thư", "mailConfirmBody":"Xác nhận nội dung thư",
@ -585,7 +588,7 @@
"offlineSessions":"Offline sessions", "offlineSessions":"Offline sessions",
"oldValue":"Giá trị cũ", "oldValue":"Giá trị cũ",
"on":"Vào", "on":"Vào",
"oidcAttribute":"OIDC Attribute", "oidcAttribute":"thuộc tính OIDC",
"oidcAuthnLevel":"Mức xác thực", "oidcAuthnLevel":"Mức xác thực",
"oidcConsents":"OpenID Connect Consents", "oidcConsents":"OpenID Connect Consents",
"oidcOP":"Bộ cung cấp Kết nối OpenID", "oidcOP":"Bộ cung cấp Kết nối OpenID",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Verify U2F key", "verifyU2FKey":"Verify U2F key",
"verifyTOTPKey":"Verify TOTP key", "verifyTOTPKey":"Verify TOTP key",
"version":"Phiên bản", "version":"Phiên bản",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Bí danh", "vhostAliases":"Bí danh",
"vhostAuthnLevel":"Mức xác thực bắt buộc", "vhostAuthnLevel":"Mức xác thực bắt buộc",
"vhostHttps":"HTTPS", "vhostHttps":"HTTPS",

View File

@ -75,6 +75,7 @@
"auto":"自动", "auto":"自动",
"autoSignin":"Auto Signin", "autoSignin":"Auto Signin",
"autoSigninRules":"Rules", "autoSigninRules":"Rules",
"avoidAssignment":"Avoid assignment in expressions",
"backtoportal":"返回 portal", "backtoportal":"返回 portal",
"badCasProxyId":"无效的 CAS proxied service identifier", "badCasProxyId":"无效的 CAS proxied service identifier",
"badChoiceKey":"选择菜单的无效 key ", "badChoiceKey":"选择菜单的无效 key ",
@ -83,7 +84,7 @@
"badDomainName":"无效的域名", "badDomainName":"无效的域名",
"badEncoding":"无效的编码", "badEncoding":"无效的编码",
"badExpression":"无效的表达式", "badExpression":"无效的表达式",
"badExpressionAssignment":"Expression containing an assignment", "badExpressionAssignment":"Expression containing an assignment. You can use \\x3D to avoid this warning.",
"badHeaderName":"无效的头部名称", "badHeaderName":"无效的头部名称",
"badHostname":"无效的主机名", "badHostname":"无效的主机名",
"badLdapUri":"无效的 LDAP URI ", "badLdapUri":"无效的 LDAP URI ",
@ -206,6 +207,7 @@
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Display persistent session data",
"checkUserDisplayEmptyHeaders":"Display empty headers", "checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values", "checkUserDisplayEmptyValues":"Display empty values",
"checkUserHiddenHeaders":"Hidden headers",
"checkUserSearchAttributes":"Attributes used for searching sessions", "checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters", "choiceParams":"Choice parameters",
"chooseLogo":"Choose logo", "chooseLogo":"Choose logo",
@ -493,6 +495,7 @@
"mail2fAuthnLevel":"认证等级", "mail2fAuthnLevel":"认证等级",
"mail2fLabel":"Label", "mail2fLabel":"Label",
"mail2fLogo":"Logo", "mail2fLogo":"Logo",
"mail2fSessionKey":"Session key containing mail address",
"mailBody":"Success mail content", "mailBody":"Success mail content",
"mailCharset":"Charset", "mailCharset":"Charset",
"mailConfirmBody":"Confirmation mail content", "mailConfirmBody":"Confirmation mail content",
@ -1003,6 +1006,7 @@
"verifyU2FKey":"Verify U2F key", "verifyU2FKey":"Verify U2F key",
"verifyTOTPKey":"Verify TOTP key", "verifyTOTPKey":"Verify TOTP key",
"version":"Version", "version":"Version",
"vhostAccessToTrace":"Access to trace",
"vhostAliases":"Aliases", "vhostAliases":"Aliases",
"vhostAuthnLevel":"Required authentication level", "vhostAuthnLevel":"Required authentication level",
"vhostHttps":"HTTPS", "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

View File

@ -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\"" ) ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
or print STDERR Dumper($resBody); or print STDERR Dumper($resBody);
ok( $resBody->{needConfirm} == 1, "JSON response contains \"needConfirm:1\"" ) ok( $resBody->{needConfirm} == 1, "JSON response contains \"needConfirm:1\"" )
or print STDERR Dumper($resBody); or print STDERR Dumper($resBody);
ok( ok(
@{ $resBody->{details}->{__warnings__} } == 3, @{ $resBody->{details}->{__warnings__} } == 4,
'JSON response contains 3 warnings' 'JSON response contains 4 warnings'
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
count(6);
foreach my $i ( 0 .. 2 ) { foreach my $i ( 0 .. 3 ) {
ok( ok(
$resBody->{details}->{__warnings__}->[$i]->{message} =~ $resBody->{details}->{__warnings__}->[$i]->{message} =~
/\b(unprotected|cross-domain-authentication|retries)\b/, /\b(unprotected|cross-domain-authentication|retries|__badExpressionAssignment__)\b/,
"Warning with 'unprotect', 'CDA' or 'retries' found" "Warning with 'unprotect', 'CDA', 'assignment' or 'retries' found"
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
count(1);
} }
count(4);
ok( ok(
@{ $resBody->{details}->{__needConfirmation__} } == 2, @{ $resBody->{details}->{__needConfirmation__} } == 1,
'JSON response contains 2 needConfirmation' 'JSON response contains 1 needConfirmation'
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
ok( ok(
@{ $resBody->{details}->{__changes__} } == 23, @{ $resBody->{details}->{__changes__} } == 24,
'JSON response contains 23 changes' 'JSON response contains 24 changes'
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
#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; ok( !@changes, 'All changes detected' ) or $bug = 1;
count(1);
if ($bug) { if ($bug) {
print STDERR 'Expected not found: ' print STDERR 'Expected not found: '
. Dumper( \@changes ) . Dumper( \@changes )
@ -99,8 +98,6 @@ if ($bug) {
#print STDERR Dumper(\@changes,\@cmsg); #print STDERR Dumper(\@changes,\@cmsg);
count(6);
# TODO: check result of this # TODO: check result of this
ok( $res = &client->jsonResponse('/diff/1/2'), 'Diff called' ); ok( $res = &client->jsonResponse('/diff/1/2'), 'Diff called' );
my ( @c1, @c2 ); 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( ( @c2 = sort keys %{ $res->[1] } ), 'diff() detects changes in conf 2' );
ok( @c1 == 12, '12 keys changed in conf 1' ) ok( @c1 == 12, '12 keys changed in conf 1' )
or print STDERR "Expect: 12 keys, get: " . join( ', ', @c1 ) . "\n"; or print STDERR "Expect: 12 keys, get: " . join( ', ', @c1 ) . "\n";
ok( @c2 == 16, '16 keys changed or created in conf 2' ) ok( @c2 == 17, '17 keys changed or created in conf 2' )
or print STDERR "Expect: 16 keys, get: " . join( ',', @c2 ) . "\n"; or print STDERR "Expect: 17 keys, get: " . join( ',', @c2 ) . "\n";
count(5); count(5);
unlink $confFiles->[1]; unlink $confFiles->[1];
@ -242,6 +239,11 @@ sub changes {
{ {
'confCompacted' => '1', 'confCompacted' => '1',
'removedKeys' => 'some; keys' 'removedKeys' => 'some; keys'
},
{
'new' => 1,
'key' => 'avoidAssignment',
'old' => '0'
} }
]; ];
} }

View File

@ -1597,6 +1597,12 @@
"title": "useSafeJail", "title": "useSafeJail",
"type": "bool", "type": "bool",
"data": 1 "data": 1
}, {
"default": 0,
"id": "avoidAssignment",
"title": "avoidAssignment",
"type": "bool",
"data": 1
}, { }, {
"default": 1, "default": 1,
"id": "checkXSS", "id": "checkXSS",

View File

@ -373,6 +373,7 @@ site/htdocs/static/common/ro.png
site/htdocs/static/common/tr.png site/htdocs/static/common/tr.png
site/htdocs/static/common/vi.png site/htdocs/static/common/vi.png
site/htdocs/static/common/zh.png site/htdocs/static/common/zh.png
site/htdocs/static/common/zh_TW.png
site/htdocs/static/languages/ar.json site/htdocs/static/languages/ar.json
site/htdocs/static/languages/de.json site/htdocs/static/languages/de.json
site/htdocs/static/languages/en.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/tr.json
site/htdocs/static/languages/vi.json site/htdocs/static/languages/vi.json
site/htdocs/static/languages/zh.json site/htdocs/static/languages/zh.json
site/htdocs/static/languages/zh_TW.json
site/templates/bootstrap/2fchoice.tpl site/templates/bootstrap/2fchoice.tpl
site/templates/bootstrap/2fregisters.tpl site/templates/bootstrap/2fregisters.tpl
site/templates/bootstrap/captcha.tpl site/templates/bootstrap/captcha.tpl
@ -456,6 +458,7 @@ site/templates/common/bullet_go.png
site/templates/common/key.png site/templates/common/key.png
site/templates/common/mail/ar.json site/templates/common/mail/ar.json
site/templates/common/mail/en.json site/templates/common/mail/en.json
site/templates/common/mail/es.json
site/templates/common/mail/fi.json site/templates/common/mail/fi.json
site/templates/common/mail/fr.json site/templates/common/mail/fr.json
site/templates/common/mail/it.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/tr.json
site/templates/common/mail/vi.json site/templates/common/mail/vi.json
site/templates/common/mail/zh_CN.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_2fcode.tpl
site/templates/common/mail_certificateConfirm.tpl site/templates/common/mail_certificateConfirm.tpl
site/templates/common/mail_certificateReset.tpl site/templates/common/mail_certificateReset.tpl
@ -481,6 +485,7 @@ t/01-AuthDemo.t
t/01-CSP-and-CORS-headers.t t/01-CSP-and-CORS-headers.t
t/01-Handler-redirection-and-URL-check-by-portal.t t/01-Handler-redirection-and-URL-check-by-portal.t
t/01-pdata.t t/01-pdata.t
t/01-Unauth-Logout.t
t/02-Password-Demo-Local-noPpolicy.t t/02-Password-Demo-Local-noPpolicy.t
t/02-Password-Demo-Local-Ppolicy.t t/02-Password-Demo-Local-Ppolicy.t
t/02-Password-Demo.t t/02-Password-Demo.t
@ -657,6 +662,7 @@ t/64-StayConnected-with-History.t
t/65-AutoSignin.t t/65-AutoSignin.t
t/66-CDA-already-auth.t t/66-CDA-already-auth.t
t/66-CDA-PSGI-Try.t t/66-CDA-PSGI-Try.t
t/66-CDA-with-doubleCookies.t
t/66-CDA-with-REST.t t/66-CDA-with-REST.t
t/66-CDA-with-SOAP.t t/66-CDA-with-SOAP.t
t/66-CDA.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-8-with-global-storage.t
t/70-2F-TOTP-and-U2F-with-TTL-and-JSON.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-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-JSON.t
t/70-2F-TOTP-with-TTL-and-XML.t t/70-2F-TOTP-with-TTL-and-XML.t
t/70-2F-TOTP-with-TTL.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-GrantSession.t
t/76-2F-Ext-with-History.t t/76-2F-Ext-with-History.t
t/77-2F-Extra.t t/77-2F-Extra.t
t/77-2F-Mail-SessionKey.t
t/77-2F-Mail-with-global-storage.t t/77-2F-Mail-with-global-storage.t
t/77-2F-Mail.t t/77-2F-Mail.t
t/78-2F-Upgrade-Many.t t/78-2F-Upgrade-Many.t

View File

@ -40,11 +40,20 @@ has ott => (
} }
); );
has sessionKey => (
is => 'rw',
lazy => 1,
default => sub {
return $_[0]->{conf}->{mail2fSessionKey}
|| $_[0]->{conf}->{mailSessionKey};
}
);
sub init { sub init {
my ($self) = @_; my ($self) = @_;
$self->{conf}->{mail2fCodeRegex} ||= '\d{6}'; $self->{conf}->{mail2fCodeRegex} ||= '\d{6}';
unless ( $self->conf->{mailSessionKey} ) { unless ( $self->sessionKey ) {
$self->error("Missing 'mailSessionKey' parameter, aborting"); $self->error("Missing session key parameter, aborting");
return 0; return 0;
} }
$self->prefix( $self->conf->{sfPrefix} ) $self->prefix( $self->conf->{sfPrefix} )
@ -65,7 +74,7 @@ sub run {
$self->logger->debug("Generated two-factor code: $code"); $self->logger->debug("Generated two-factor code: $code");
$self->ott->updateToken( $token, __mail2fcode => $code ); $self->ott->updateToken( $token, __mail2fcode => $code );
my $dest = $req->{sessionInfo}->{ $self->conf->{mailSessionKey} }; my $dest = $req->{sessionInfo}->{ $self->sessionKey };
unless ($dest) { unless ($dest) {
$self->logger->error( "Could not find mail attribute for login " $self->logger->error( "Could not find mail attribute for login "
. $req->{sessionInfo}->{_user} ); . $req->{sessionInfo}->{_user} );

View File

@ -4,13 +4,18 @@ use strict;
use Mouse; use Mouse;
# Add constants used by this module # Add constants used by this module
use Lemonldap::NG::Portal::Main::Constants use Lemonldap::NG::Portal::Main::Constants qw(
qw(PE_OK PE_FORBIDDENIP PE_USERNOTFOUND); PE_OK
use Lemonldap::NG::Portal::Lib::Slave; PE_FORBIDDENIP
PE_USERNOTFOUND
);
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Auth'; extends qw(
Lemonldap::NG::Portal::Main::Auth
Lemonldap::NG::Portal::Lib::Slave
);
# INITIALIZATION # INITIALIZATION

View File

@ -455,7 +455,7 @@ sub userModifyPassword {
return PE_LDAPERROR; 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 # Rebind as manager for next LDAP operations if we were bound as user
$self->bind() if $asUser; $self->bind() if $asUser;
@ -588,8 +588,7 @@ sub userModifyPassword {
return PE_WRONGMANAGERACCOUNT return PE_WRONGMANAGERACCOUNT
if ( $mesg->code == 50 || $mesg->code == 8 ); if ( $mesg->code == 50 || $mesg->code == 8 );
if ( $mesg->code == 0 ) { if ( $mesg->code == 0 ) {
$self->{portal} $self->{portal}->logger->notice("Password changed for $dn");
->userLogger->notice("Password changed $self->{portal}->{user}");
# Rebind as manager for next LDAP operations if we were bound as user # Rebind as manager for next LDAP operations if we were bound as user
$self->bind() if $asUser; $self->bind() if $asUser;

View File

@ -5,11 +5,9 @@
# Slave common functions # Slave common functions
package Lemonldap::NG::Portal::Lib::Slave; package Lemonldap::NG::Portal::Lib::Slave;
use Exporter;
use base qw(Exporter);
use strict; use strict;
use Mouse;
our @EXPORT = qw(checkIP checkHeader);
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
# RUNNING METHODS # RUNNING METHODS
@ -49,4 +47,4 @@ sub checkHeader {
return 0; return 0;
} }
1; 1;

View File

@ -161,28 +161,29 @@ sub setPortalRoutes {
# psgi.js # psgi.js
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] ) ->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] ) ->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
# portal.css # portal.css
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] ) ->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] ) ->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
# lmerror # lmerror
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) ->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) ->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
# Core REST API # Core REST API
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] ) ->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
->addAuthRoute( ping => 'authenticated', ['GET'] ) ->addAuthRoute( ping => 'authenticated', ['GET'] )
# Refresh session # Refresh session
->addAuthRoute( refresh => 'refresh', ['GET'] ) ->addAuthRoute( refresh => 'refresh', ['GET'] )
->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] ) ->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
->addUnauthRoute( '*' => 'corsPreflight', ['OPTIONS'] ) ->addUnauthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
# Logout # Logout
->addAuthRoute( logout => 'logout', ['GET'] ); ->addAuthRoute( logout => 'logout', ['GET'] )
->addUnauthRoute( logout => 'unauthLogout', ['GET'] );
# Default routes must point to routines declared above # Default routes must point to routines declared above
$self->defaultAuthRoute(''); $self->defaultAuthRoute('');
@ -239,9 +240,11 @@ sub reloadConf {
# Initialize templateDir # Initialize templateDir
$self->{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} ) { 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; return $self->fail;
} }
$self->templateDir( $self->templateDir(
@ -526,7 +529,11 @@ sub loadModule {
$self->error("Unable to build $module object: $@"); $self->error("Unable to build $module object: $@");
return 0; 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; $self->loadedModules->{$module} = $obj;
return $obj; return $obj;
} }

View File

@ -179,6 +179,27 @@ sub checkLogout {
PE_OK; 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 { sub authLogout {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $res = $self->_authentication->authLogout($req); my $res = $self->_authentication->authLogout($req);
@ -349,7 +370,7 @@ sub authenticate {
$req->steps( [ $req->steps( [
'setSessionInfo', 'setMacros', 'setSessionInfo', 'setMacros',
'setPersistentSessionInfo', 'storeHistory', 'setPersistentSessionInfo', 'storeHistory',
@{ $self->afterData }, sub { PE_BADCREDENTIALS } @{ $self->afterData }, sub { PE_BADCREDENTIALS }
] ]
); );

View File

@ -133,10 +133,11 @@ sub login {
return $self->do( return $self->do(
$req, $req,
[ [
'controlUrl', @{ $self->beforeAuth }, 'checkUnauthLogout', 'controlUrl', # Fix 2342
$self->authProcess, @{ $self->betweenAuthAndData }, @{ $self->beforeAuth }, $self->authProcess,
$self->sessionData, @{ $self->afterData }, @{ $self->betweenAuthAndData }, $self->sessionData,
$self->validSession, @{ $self->endAuth }, @{ $self->afterData }, $self->validSession,
@{ $self->endAuth }
] ]
); );
} }
@ -146,11 +147,11 @@ sub postLogin {
return $self->do( return $self->do(
$req, $req,
[ [
'restoreArgs', 'controlUrl', 'checkUnauthLogout', 'restoreArgs', # Fix 2342
@{ $self->beforeAuth }, $self->authProcess, 'controlUrl', @{ $self->beforeAuth },
@{ $self->betweenAuthAndData }, $self->sessionData, $self->authProcess, @{ $self->betweenAuthAndData },
@{ $self->afterData }, $self->validSession, $self->sessionData, @{ $self->afterData },
@{ $self->endAuth }, $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 # RUNNING METHODS
# --------------- # ---------------
@ -1051,7 +1070,7 @@ sub registerLogin {
} }
my $history = $req->sessionInfo->{_loginHistory} ||= {}; my $history = $req->sessionInfo->{_loginHistory} ||= {};
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login'; my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
$history->{$type} ||= []; $history->{$type} ||= [];
$self->logger->debug("Current login saved into $type"); $self->logger->debug("Current login saved into $type");

View File

@ -84,6 +84,10 @@ sub _modifyPassword {
my $res = $self->modifyPassword( $req, $req->data->{newpassword} ); my $res = $self->modifyPassword( $req, $req->data->{newpassword} );
if ( $res == PE_PASSWORD_OK ) { if ( $res == PE_PASSWORD_OK ) {
$self->logger->debug( 'Update password in session for ' . $req->user ); $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; my $infos;
# Store new password if asked # Store new password if asked

View File

@ -18,9 +18,8 @@ our $VERSION = '2.1.0';
sub init { sub init {
my ($self) = @_; my ($self) = @_;
$self->ldap return ( $self->Lemonldap::NG::Portal::Password::Base::init
and $self->filter and $self->Lemonldap::NG::Portal::Lib::LDAP::init );
and $self->Lemonldap::NG::Portal::Password::Base::init;
} }
# Confirmation is done by Lib::Net::LDAP::userModifyPassword # Confirmation is done by Lib::Net::LDAP::userModifyPassword

View File

@ -4,6 +4,7 @@ use strict;
use Mouse; use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_APACHESESSIONERROR PE_APACHESESSIONERROR
PE_ERROR
PE_OK PE_OK
); );
@ -37,9 +38,18 @@ sub changeUrldc {
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName}; $cdaInfos->{cookie_name} = $self->{conf}->{cookieName};
} }
else { else {
$cdaInfos->{cookie_value} = if ( $req->{sessionInfo}->{_httpSession} ) {
$req->{sessionInfo}->{_httpSession}; $cdaInfos->{cookie_value} =
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http"; $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 = my $cdaSession =

View File

@ -23,7 +23,7 @@ sub init {
} }
$self->addUnauthRoute( checkstate => 'check', ['GET'] ) $self->addUnauthRoute( checkstate => 'check', ['GET'] )
->addAuthRoute( checkstate => 'check', ['GET'] ); ->addAuthRoute( checkstate => 'check', ['GET'] );
return 1; return 1;
} }
@ -49,7 +49,7 @@ sub check {
# - "buildCookie" useless here # - "buildCookie" useless here
$req->steps( [ $req->steps( [
'getUser', 'authenticate', 'getUser', 'authenticate',
@{ $self->p->betweenAuthAndData }, $self->sessionData, @{ $self->p->betweenAuthAndData }, $self->p->sessionData,
@{ $self->p->afterData }, 'storeHistory', @{ $self->p->afterData }, 'storeHistory',
@{ $self->p->endAuth } @{ $self->p->endAuth }
] ]

View File

@ -115,7 +115,9 @@ sub display {
$self->userLogger->info("Using spoofed SSO groups if exist") $self->userLogger->info("Using spoofed SSO groups if exist")
if ( $self->conf->{impersonationRule} ); if ( $self->conf->{impersonationRule} );
$attrs = $self->_removePersistentAttributes($attrs) $attrs =
$self->_removeKeys( $attrs, $self->persistentAttrs,
'Remove persistent session attributes...' )
unless $self->displayPersistentInfoRule->( $req, $req->userData ); unless $self->displayPersistentInfoRule->( $req, $req->userData );
# Create an array of hashes and dispatch attributes for template loop # Create an array of hashes and dispatch attributes for template loop
@ -180,8 +182,7 @@ sub check {
LOGIN => '', LOGIN => '',
TOKEN => $token, TOKEN => $token,
}; };
return $self->p->sendJSONresponse( $req, $params ) return $self->p->sendJSONresponse( $req, $params ) if $req->wantJSON;
if ( $req->wantJSON );
return $self->p->sendHtml( $req, 'checkuser', params => $params ) return $self->p->sendHtml( $req, 'checkuser', params => $params )
if $msg; if $msg;
} }
@ -195,7 +196,7 @@ sub check {
$user = ''; $user = '';
$attrs = {}; $attrs = {};
return $self->p->sendError( $req, 'Malformed user', 400 ) return $self->p->sendError( $req, 'Malformed user', 400 )
if ( $req->wantJSON ); if $req->wantJSON;
return $self->p->sendHtml( return $self->p->sendHtml(
$req, $req,
'checkuser', 'checkuser',
@ -219,7 +220,7 @@ sub check {
if ( !$user or $user eq $req->{user} ) { if ( !$user or $user eq $req->{user} ) {
$self->userLogger->info("checkUser requested for himself"); $self->userLogger->info("checkUser requested for himself");
$self->userLogger->info("Using spoofed SSO groups if exist") $self->userLogger->info("Using spoofed SSO groups if exist")
if ( $self->conf->{impersonationRule} ); if $self->conf->{impersonationRule};
$attrs = $req->userData; $attrs = $req->userData;
$user = $req->{user}; $user = $req->{user};
} }
@ -262,7 +263,10 @@ sub check {
} }
# Check identities rule # 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 ) ) { unless ( $unUser || $self->idRule->( $req, $attrs ) ) {
$self->userLogger->warn( $self->userLogger->warn(
"checkUser requested for an invalid user ($user)"); "checkUser requested for an invalid user ($user)");
@ -279,8 +283,10 @@ sub check {
$attrs = {}; $attrs = {};
} }
else { else {
$msg = 'checkUser' . $self->merged; $msg = 'checkUser' . $self->merged;
$attrs = $self->_removePersistentAttributes($attrs) $attrs =
$self->_removeKeys( $attrs, $self->persistentAttrs,
'Remove persistent session attributes...' )
unless $self->displayPersistentInfoRule->( $req, $savedUserData ); unless $self->displayPersistentInfoRule->( $req, $savedUserData );
if ($computed) { if ($computed) {
@ -320,17 +326,23 @@ sub check {
$self->_createArray( $req, $attrs, $savedUserData ) ); $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 # Check if user is allowed to access submitted URL and compute headers
if ( $url and %$attrs ) { if ( $url and %$attrs ) {
# Check url format # Check url format
$url = $self->_urlFormat($url); my $originalUrl;
( $url, $originalUrl ) = $self->_resolveURL( $req, $url );
# User is allowed ? # User is allowed ?
$self->logger->debug( $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 ) { if ( $auth >= 0 ) {
$auth = $auth ? "allowed" : "forbidden"; $auth = $auth ? "allowed" : "forbidden";
$self->logger->debug( $self->logger->debug(
@ -338,7 +350,8 @@ sub check {
. "$auth to access to $url" ); . "$auth to access to $url" );
# Return VirtualHost headers # Return VirtualHost headers
$array_hdrs = $self->_headers( $req, $url, $attrs, $savedUserData ); $array_hdrs =
$self->_headers( $req, $originalUrl, $attrs, $savedUserData );
} }
else { else {
$auth = 'VHnotFound'; $auth = 'VHnotFound';
@ -352,17 +365,14 @@ sub check {
# TODO: # TODO:
my $params = { my $params = {
PORTAL => $self->conf->{portal}, PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req), SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages}, LANGS => $self->conf->{showLanguages},
MSG => $msg, MSG => $msg,
ALERTE => ( $msg eq 'checkUser' ? 'alert-info' : 'alert-warning' ), ALERTE => ( $msg eq 'checkUser' ? 'alert-info' : 'alert-warning' ),
LOGIN => $user, LOGIN => $user,
URL => ( URL => $url,
$self->p->checkXSSAttack( 'URL', $url ) ? ""
: $url
),
ALLOWED => $auth, ALLOWED => $auth,
ALERTE_AUTH => $alert_auth, ALERTE_AUTH => $alert_auth,
HEADERS => $array_hdrs, HEADERS => $array_hdrs,
@ -370,7 +380,8 @@ sub check {
MACROS => $array_attrs->[1], MACROS => $array_attrs->[1],
GROUPS => $array_attrs->[0], GROUPS => $array_attrs->[0],
TOKEN => ( 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 ); return $self->p->sendHtml( $req, 'checkuser', params => $params );
} }
sub _urlFormat { sub _resolveURL {
my ( $self, $url ) = @_; my ( $self, $req, $url ) = @_;
$url = 'http://' . $url unless ( $url =~ m#^https?://[^/]*.*#i ); my ($proto) = $url =~ m#^(https?://).*#i;
my ( $proto, $vhost, $appuri ) = $url =~ m#^(https?://)([^/]*)(.*)#i; my ( $vhost, $appuri ) = $url =~ m#^(?:https?://)?([^/]*)(.*)#i;
my ($port) = $vhost =~ m#^.+(:\d+)$#; my ($port) = $vhost =~ m#^.+(:\d+)$#;
$port ||= ''; $port ||= '';
$vhost =~ s/:\d+$//; $vhost =~ s/:\d+$//;
$vhost .= $self->conf->{domain} unless ( $vhost =~ /\./ ); $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 { sub _userData {
@ -407,12 +425,9 @@ sub _userData {
: push @$steps, 'setLocalGroups'; : push @$steps, 'setLocalGroups';
$req->steps($steps); $req->steps($steps);
if ( my $error = $self->p->process($req) ) { if ( my $error = $self->p->process($req) ) {
if ( $error == PE_BADCREDENTIALS ) { $self->userLogger->warn(
$self->userLogger->warn( 'checkUser requested for an invalid user (' . $req->{user} . ")" )
'checkUser requested for an invalid user (' if ( $error == PE_BADCREDENTIALS );
. $req->{user}
. ")" );
}
$self->logger->debug("Process returned error: $error"); $self->logger->debug("Process returned error: $error");
return $req->error(PE_BADCREDENTIALS); return $req->error(PE_BADCREDENTIALS);
} }
@ -468,16 +483,48 @@ sub _headers {
$vhost =~ s/:\d+$//; $vhost =~ s/:\d+$//;
$req->{env}->{HTTP_HOST} = $vhost; $req->{env}->{HTTP_HOST} = $vhost;
$self->p->HANDLER->headersInit( $self->{conf} ); $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( $self->logger->debug(
"Return \"$attrs->{ $self->{conf}->{whatToTrace} }\" headers"); "Return \"$attrs->{ $self->{conf}->{whatToTrace} }\" headers");
return $self->p->HANDLER->checkHeaders( $req, $attrs )
if ( $self->displayEmptyHeadersRule->( $req, $savedUserData ) );
$self->logger->debug("Remove empty headers"); return $headers;
my @headers = grep $_->{value} =~ /.+/,
@{ $self->p->HANDLER->checkHeaders( $req, $attrs ) };
return \@headers;
} }
sub _createArray { sub _createArray {
@ -511,7 +558,7 @@ sub _dispatchAttributes {
my ( $grps, $mcrs, $others ) = ( [], [], [] ); my ( $grps, $mcrs, $others ) = ( [], [], [] );
my $macros = $self->{conf}->{macros}; my $macros = $self->{conf}->{macros};
$self->logger->debug("Dispatching attributes..."); $self->logger->debug("Dispatch attributes...");
while (@$attrs) { while (@$attrs) {
my $element = shift @$attrs; my $element = shift @$attrs;
$self->logger->debug( "Processing element: $element->{key} => " $self->logger->debug( "Processing element: $element->{key} => "
@ -539,9 +586,9 @@ sub _dispatchAttributes {
# Sort real and spoofed attributes if required # Sort real and spoofed attributes if required
if ( $self->sorted ) { if ( $self->sorted ) {
$self->logger->debug('Dispatching real and spoofed attributes...'); $self->logger->debug('Sort real and spoofed attributes...');
my ( $realAttrs, $spoofedAttrs ) = ( [], [] ); my ( $realAttrs, $spoofedAttrs ) = ( [], [] );
my $prefix = "$self->{conf}->{impersonationPrefix}"; my $prefix = $self->{conf}->{impersonationPrefix};
while (@$others) { while (@$others) {
my $element = shift @$others; my $element = shift @$others;
$self->logger->debug( "Processing attribute $element->{key} => " $self->logger->debug( "Processing attribute $element->{key} => "
@ -560,12 +607,22 @@ sub _dispatchAttributes {
return [ $grps, $mcrs, $others ]; return [ $grps, $mcrs, $others ];
} }
sub _removePersistentAttributes { sub _removeKeys {
my ( $self, $attrs ) = @_; my ( $self, $attrs, $hidden, $msg, $mask ) = @_;
my $regex = join '|', split /\s+/, $self->persistentAttrs; my $regex = join '|', split /\s+/, $hidden;
my @keys = grep /$regex/, keys %$attrs; 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; return $attrs;
} }

View File

@ -140,7 +140,7 @@ sub display {
sub run { sub run {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $statut = PE_OK; my $statut = PE_OK;
my $realId = $req->{user}; my $realId = $req->userData->{ $self->conf->{whatToTrace} };
my $spoofId = $req->param('spoofId') || ''; # ContextSwitching required ? my $spoofId = $req->param('spoofId') || ''; # ContextSwitching required ?
my $unUser = $self->unrestrictedUsersRule->( $req, $req->userData ) || 0; my $unUser = $self->unrestrictedUsersRule->( $req, $req->userData ) || 0;
@ -202,7 +202,7 @@ sub _switchContext {
my ( $self, $req, $spoofId, $unUser ) = @_; my ( $self, $req, $spoofId, $unUser ) = @_;
my $realSessionId = $req->userData->{_session_id}; my $realSessionId = $req->userData->{_session_id};
my $realAuthLevel = $req->userData->{authenticationLevel}; my $realAuthLevel = $req->userData->{authenticationLevel};
my $realId = $req->{user}; my $realId = $req->userData->{ $self->conf->{whatToTrace} };
my $raz = 0; my $raz = 0;
$req->{user} = $spoofId; $req->{user} = $spoofId;

View File

@ -54,9 +54,9 @@ sub run {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $user = $req->{userData}->{ $self->conf->{whatToTrace} }; my $user = $req->{userData}->{ $self->conf->{whatToTrace} };
# Check activation rules # Check activation rule
unless ( $self->rule->( $req, $req->userData ) ) { 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; return PE_OK;
} }
@ -116,20 +116,22 @@ sub globalLogout {
# Read active sessions from token # Read active sessions from token
my $sessions = eval { from_json( $token->{sessions} ) }; my $sessions = eval { from_json( $token->{sessions} ) };
if ($@) { if ($@) {
$self->logger->error("Bad encoding in OTT: $@"); $self->logger->error(
"GlobalLogout: bad encoding in OTT ($@)");
$res = PE_ERROR; $res = PE_ERROR;
} }
my $as; my $as;
foreach (@$sessions) { my $user = $token->{user};
unless ( $as = $self->p->getApacheSession( $_->{id} ) ) { my $req_user =
$self->userLogger->info( $req->{userData}->{ $self->{conf}->{whatToTrace} };
"GlobalLogout: session $_->{id} expired"); if ( $req_user eq $user ) {
next; foreach (@$sessions) {
} unless ( $as = $self->p->getApacheSession( $_->{id} ) )
my $user = $token->{user}; {
if ( $req->{userData}->{ $self->{conf}->{whatToTrace} } eq $self->userLogger->info(
$user ) "GlobalLogout: session $_->{id} expired");
{ next;
}
unless ( $req->{userData}->{_session_id} eq $_->{id} ) { unless ( $req->{userData}->{_session_id} eq $_->{id} ) {
$self->userLogger->info( $self->userLogger->info(
"Remove \"$user\" session: $_->{id}"); "Remove \"$user\" session: $_->{id}");
@ -137,11 +139,12 @@ sub globalLogout {
$count++; $count++;
} }
} }
else { }
$self->userLogger->warn( else {
"GlobalLogout called with an invalid token"); $self->userLogger->warn(
$res = PE_TOKENEXPIRED; "GlobalLogout called with an invalid token: $req_user is NOT $user"
} );
$res = PE_TOKENEXPIRED;
} }
} }
else { else {
@ -157,7 +160,7 @@ sub globalLogout {
} }
return $self->p->do( $req, [ sub { $res } ] ) if $res; 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' ] ); return $self->p->do( $req, [ 'authLogout', 'deleteSession' ] );
} }
@ -177,16 +180,16 @@ sub activeSessions {
$self->module->searchOn( $moduleOptions, $self->conf->{whatToTrace}, $self->module->searchOn( $moduleOptions, $self->conf->{whatToTrace},
$user ); $user );
$self->logger->debug('Remove corrupted sessions...'); $self->logger->debug('Remove non-SSO session(s)...');
my $corrupted = 0; my $other = 0;
foreach ( keys %$sessions ) { foreach ( keys %$sessions ) {
unless ( $sessions->{$_}->{_session_kind} eq 'SSO' ) { unless ( $sessions->{$_}->{_session_kind} eq 'SSO' ) {
delete $sessions->{$_}; delete $sessions->{$_};
$corrupted++; $other++;
} }
} }
$self->logger->info("$corrupted corrupted session(s) removed") $self->logger->info("$other non-SSO session(s) removed")
if $corrupted; if $other;
$self->logger->debug('Build an array ref with sessions info...'); $self->logger->debug('Build an array ref with sessions info...');
@$activeSessions = @$activeSessions =

View File

@ -72,16 +72,17 @@ sub run {
$req, 'simpleInfo', params => { trspan => $msg } $req, 'simpleInfo', params => { trspan => $msg }
) )
); );
$self->userLogger->error( 'User ' $self->userLogger->error( 'User "'
. $req->sessionInfo->{uid} . $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
. " was not granted to open session (rule -> $rule)" ); . '" was not granted to open session (rule ->'
. "$rule)" );
$req->urldc( $self->conf->{portal} ); $req->urldc( $self->conf->{portal} );
return $req->authResult(PE_SESSIONNOTGRANTED); return $req->authResult(PE_SESSIONNOTGRANTED);
} }
else { else {
$self->userLogger->error( 'User ' $self->userLogger->error( 'User "'
. $req->sessionInfo->{uid} . $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
. " was not granted to open session (rule -> " . '" was not granted to open session (rule -> '
. $self->conf->{grantSessionRules}->{$_} . $self->conf->{grantSessionRules}->{$_}
. ")" ); . ")" );
$req->urldc( $self->conf->{portal} ); $req->urldc( $self->conf->{portal} );

View File

@ -490,6 +490,11 @@ sub changePwd {
return $result; 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 # Send mail containing the new password
$req->data->{mailAddress} ||= $req->data->{mailAddress} ||=
$self->p->getFirstValue( $self->p->getFirstValue(

View File

@ -182,7 +182,7 @@ sub removeOther {
} }
return $self->p->do( $req, [ sub { $res } ] ) if $res; 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); $req->mustRedirect(1);
return $self->p->autoRedirect($req); return $self->p->autoRedirect($req);
} }

View File

@ -40,12 +40,16 @@ sub setSessionInfo {
%{ $self->conf->{ldapExportedVars} } ); %{ $self->conf->{ldapExportedVars} } );
while ( my ( $k, $v ) = each %vars ) { while ( my ( $k, $v ) = each %vars ) {
my $value = $self->ldap->getLdapValue( $req->data->{ldapentry}, $v );
# getLdapValue returns an empty string for missing attribute # getLdapValue returns an empty string for missing attribute
# but we really want to return undef so they don't get stored in session # but we really want to return undef so they don't get stored in session
$req->sessionInfo->{$k} = # This has to be a string comparison because "0" is a valid attribute
$self->ldap->getLdapValue( $req->data->{ldapentry}, $v ) || undef; # value. See #2403
} $value = undef if ( $value eq "" );
$req->sessionInfo->{$k} = $value;
}
PE_OK; PE_OK;
} }

View File

@ -7,12 +7,18 @@ package Lemonldap::NG::Portal::UserDB::Slave;
use strict; use strict;
use Mouse; 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'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Common::Module'; extends qw(
Lemonldap::NG::Common::Module
Lemonldap::NG::Portal::Lib::Slave
);
# INITIALIZATION # INITIALIZATION

View File

@ -482,7 +482,7 @@ $(window).on 'load', () ->
$('#newpassword')[0].setCustomValidity(translate('PE28')) $('#newpassword')[0].setCustomValidity(translate('PE28'))
return return
if window.datas.ppolicy? if window.datas.ppolicy? and $('#newpassword').length
# Initialize display # Initialize display
checkpassword '' checkpassword ''

Some files were not shown because too many files have changed in this diff Show More