Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
pgnd _
lemonldap-ng
Commits
d2d9988b
Commit
d2d9988b
authored
Apr 25, 2020
by
Christophe Maudoux
🐛
Browse files
Merge branch 'v2.0'
parents
19724434
cd53d785
Changes
146
Hide whitespace changes
Inline
Side-by-side
COPYING
View file @
d2d9988b
...
...
@@ -96,6 +96,12 @@ Comment: downloaded from
.
Author is unknown and license may be W3C or public-domain
Files: lemonldap-ng-portal/site/htdocs/static/common/modules/GitHub.png
Copyright: GitHub
License: MIT
Comment: downloaded from
https://commons.wikimedia.org/wiki/File:Octicons-mark-github.svg
Files: lemonldap-ng-portal/site/htdocs/static/bootstrap/u2f.png
Copyright: Bautsch <https://commons.wikimedia.org/wiki/User:Bautsch>
License: CC0-1.0
...
...
_example/etc/api-apache2.4.conf
View file @
d2d9988b
...
...
@@ -62,6 +62,12 @@
DocumentRoot
__
MANAGERAPIDIR__
<
Location
/>
# By default, access to this VHost is denied
# If you want to enable the manager APIs, you MUST
# implement a robust authentication scheme to protect this
# VHost since LemonLDAP::NG provides no protection to the
# Manager APIs yet
Require
all
denied
<
IfModule
mod_deflate
.
c
>
...
...
_example/etc/api-apache2.X.conf
View file @
d2d9988b
...
...
@@ -62,6 +62,12 @@
DocumentRoot
__
MANAGERAPIDIR__
<
Location
/>
# By default, access to this VHost is denied
# If you want to enable the manager APIs, you MUST
# implement a robust authentication scheme to protect this
# VHost since LemonLDAP::NG provides no protection to the
# Manager APIs yet
<
IfVersion
>=
2
.
3
>
Require
all
denied
</
IfVersion
>
...
...
_example/etc/api-apache2.conf
View file @
d2d9988b
...
...
@@ -62,6 +62,12 @@
DocumentRoot
__
MANAGERAPIDIR__
<
Location
/>
# By default, access to this VHost is denied
# If you want to enable the manager APIs, you MUST
# implement a robust authentication scheme to protect this
# VHost since LemonLDAP::NG provides no protection to the
# Manager APIs yet
Order
Deny
,
Allow
Deny
from
all
...
...
_example/etc/api-nginx.conf
View file @
d2d9988b
server
{
listen
__
PORT__
;
listen
[::]:
__
PORT__
;
server_name
manager
-
api
.
__
DNSDOMAIN__
;
root
__
MANAGERAPIDIR__
;
# Use "lm_app" format to get username in nginx.log (see nginx-lmlog.conf)
...
...
@@ -36,8 +37,14 @@ server {
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
# Access control
# By default, access to this VHost is denied
# If you want to enable the manager APIs, you MUST
# implement a robust authentication scheme to protect this
# VHost since LemonLDAP::NG provides no protection to the
# Manager APIs yet
#
#allow 127.0.0.0/8;
#allow ::1/128;
deny
all
;
}
...
...
_example/etc/handler-nginx.conf
View file @
d2d9988b
...
...
@@ -18,6 +18,7 @@ include __CONFDIR__/nginx-lmlog.conf;
server
{
listen
__
PORT__
;
listen
[::]:
__
PORT__
;
server_name
reload
.
__
DNSDOMAIN__
;
root
/
var
/
www
/
html
;
...
...
@@ -31,7 +32,8 @@ server {
#real_ip_header X-Forwarded-For;
location
= /
reload
{
allow
127
.
0
.
0
.
1
;
allow
127
.
0
.
0
.
1
/
8
;
allow
::
1
/
128
;
deny
all
;
# FastCGI configuration
...
...
@@ -55,7 +57,8 @@ server {
# Uncomment this if status is enabled
#location = /status {
# allow 127.0.0.1;
# allow 127.0.0.1/8;
# allow ::1/128;
# deny all;
# # FastCGI configuration
# include /etc/nginx/fastcgi_params;
...
...
_example/etc/manager-nginx.conf
View file @
d2d9988b
server
{
listen
__
PORT__
;
listen
[::]:
__
PORT__
;
server_name
manager
.
__
DNSDOMAIN__
;
root
__
MANAGERSITEDIR__
;
# Use "lm_app" format to get username in nginx.log (see nginx-lmlog.conf)
...
...
@@ -43,6 +44,7 @@ server {
index
manager
.
psgi
;
try_files
$
uri
$
uri
/ =
404
;
allow
127
.
0
.
0
.
0
/
8
;
allow
::
1
/
128
;
deny
all
;
}
...
...
_example/etc/portal-nginx.conf
View file @
d2d9988b
...
...
@@ -12,6 +12,7 @@ upstream llng_portal_upstream {
server
{
listen
__
PORT__
;
listen
[::]:
__
PORT__
;
server_name
auth
.
__
DNSDOMAIN__
;
root
__
PORTALSITEDIR__
;
# Use "lm_app" format to get username in nginx.log (see nginx-lmlog.conf)
...
...
_example/etc/test-nginx.conf
View file @
d2d9988b
server
{
listen
__
PORT__
;
listen
[::]:
__
PORT__
;
server_name
test1
.
__
DNSDOMAIN__
test2
.
__
DNSDOMAIN__
;
root
__
TESTDIR__
;
...
...
@@ -113,7 +114,8 @@ server {
}
#location = /status {
# allow 127.0.0.1;
# allow 127.0.0.1/8;
# allow ::1/128;
# deny all;
# include /etc/nginx/fastcgi_params;
# fastcgi_pass unix:__FASTCGISOCKDIR__/llng-fastcgi.sock;
...
...
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Constants.pm
View file @
d2d9988b
...
...
@@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
use
constant
SESSIONSEXPLORERSECTION
=>
"
sessionsExplorer
";
use
constant
APPLYSECTION
=>
"
apply
";
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)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|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)|
ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|
oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|
AllowOffline|
Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|
c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:Empty(?:Header|Value)s|PersistentInfo))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|da)|
p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|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)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|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)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|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(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|
c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|
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)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/
;
our
@sessionTypes
=
(
'
remoteGlobal
',
'
global
',
'
localSession
',
'
persistent
',
'
saml
',
'
oidc
',
'
cas
'
);
...
...
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm
View file @
d2d9988b
...
...
@@ -8,7 +8,7 @@ sub defaultValues {
'
activeTimer
'
=>
1
,
'
ADPwdExpireWarning
'
=>
0
,
'
ADPwdMaxAge
'
=>
0
,
'
apacheAuthnLevel
'
=>
4
,
'
apacheAuthnLevel
'
=>
3
,
'
applicationList
'
=>
{
'
default
'
=>
{
'
catname
'
=>
'
Default category
',
...
...
@@ -36,6 +36,9 @@ sub defaultValues {
'
http://auth.example.com/certificateReset
',
'
certificateResetByMailValidityDelay
'
=>
0
,
'
checkTime
'
=>
600
,
'
checkUserDisplayEmptyHeaders
'
=>
0
,
'
checkUserDisplayEmptyValues
'
=>
0
,
'
checkUserDisplayPersistentInfo
'
=>
0
,
'
checkUserHiddenAttributes
'
=>
'
_loginHistory _session_id hGroups
',
'
checkUserIdRule
'
=>
1
,
'
checkXSS
'
=>
1
,
...
...
@@ -80,6 +83,9 @@ sub defaultValues {
'
failedLoginNumber
'
=>
5
,
'
favAppsMaxNumber
'
=>
3
,
'
formTimeout
'
=>
120
,
'
githubAuthnLevel
'
=>
1
,
'
githubScope
'
=>
'
user:email
',
'
githubUserField
'
=>
'
login
',
'
globalLogoutRule
'
=>
0
,
'
globalLogoutTimer
'
=>
1
,
'
globalStorage
'
=>
'
Apache::Session::File
',
...
...
@@ -326,6 +332,9 @@ sub defaultValues {
'
sfRemovedNotifTitle
'
=>
'
Second factor notification
',
'
sfRequired
'
=>
0
,
'
showLanguages
'
=>
1
,
'
singleIP
'
=>
0
,
'
singleSession
'
=>
0
,
'
singleUserByIP
'
=>
0
,
'
slaveAuthnLevel
'
=>
2
,
'
slaveExportedVars
'
=>
{},
'
SMTPServer
'
=>
'',
...
...
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/RESTServer.pm
View file @
d2d9988b
...
...
@@ -733,7 +733,7 @@ sub sfExtra {
$tmp
->
{
id
}
=
"
sfExtra/
$mod
";
$tmp
->
{
type
}
=
'
sfExtra
';
$tmp
->
{
data
}
->
{
$_
}
=
$val
->
{
$mod
}
->
{
$_
}
foreach
(
qw(type rule logo label)
);
foreach
(
qw(type rule logo
level
label)
);
my
$over
=
$val
->
{
$mod
}
->
{
over
}
//
{};
$tmp
->
{
data
}
->
{
over
}
=
[
map
{
[
$_
,
$over
->
{
$_
}
]
}
keys
%$over
];
push
@$res
,
$tmp
;
...
...
lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/ReConstants.pm
View file @
d2d9988b
...
...
@@ -27,7 +27,7 @@ our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaData
our
$casAppMetaDataNodeKeys
=
'
casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|(?:ExportedVar|Macro)s)
';
our
$casSrvMetaDataNodeKeys
=
'
casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)
';
our
$oidcOPMetaDataNodeKeys
=
'
oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))
';
our
$oidcRPMetaDataNodeKeys
=
'
oidcRPMetaData(?:Options(?:A(?:(?:uthorizationCode|ccessToken)Expiration|llow
Offline
)|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(?:(?:uthorizationCode|ccessToken)Expiration|llow
(?:PasswordGrant|Offline)|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(?:ignS[LS]OMessage|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(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)
';
our
$virtualHostKeys
=
'
(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)
';
...
...
@@ -42,6 +42,7 @@ our $authParameters = {
dbiParams
=>
[
qw(dbiAuthnLevel dbiExportedVars dbiAuthChain dbiAuthUser dbiAuthPassword dbiUserChain dbiUserUser dbiUserPassword dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot dbiAuthPasswordHash dbiDynamicHashEnabled dbiDynamicHashValidSchemes dbiDynamicHashValidSaltedSchemes dbiDynamicHashNewPasswordScheme)
],
demoParams
=>
[
qw(demoExportedVars)
],
facebookParams
=>
[
qw(facebookAuthnLevel facebookExportedVars facebookAppId facebookAppSecret facebookUserField)
],
githubParams
=>
[
qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)
],
gpgParams
=>
[
qw(gpgAuthnLevel gpgDb)
],
kerberosParams
=>
[
qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain)
],
ldapParams
=>
[
qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)
],
...
...
lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm
View file @
d2d9988b
...
...
@@ -72,6 +72,7 @@ sub encodings { $_[0]->env->{HTTP_ACCEPT_ENCODING} }
sub
languages
{
$_
[
0
]
->
env
->
{
HTTP_ACCEPT_LANGUAGE
}
}
sub
authorization
{
$_
[
0
]
->
env
->
{
HTTP_AUTHORIZATION
}
}
sub
hostname
{
$_
[
0
]
->
env
->
{
HTTP_HOST
}
}
sub
origin
{
$_
[
0
]
->
env
->
{
HTTP_ORIGIN
}
}
sub
referer
{
$_
[
0
]
->
env
->
{
REFERER
}
}
sub
query_string
{
$_
[
0
]
->
env
->
{
QUERY_STRING
}
}
...
...
lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm
View file @
d2d9988b
...
...
@@ -8,7 +8,7 @@ sub run {
my
(
$class
,
$req
,
$rule
,
$protection
)
=
@_
;
my
$uri
=
$req
->
{
env
}
->
{
REQUEST_URI
};
my
$cn
=
$class
->
tsv
->
{
cookieName
};
my
(
$id
,
$ret
,
$session
);
my
(
$id
,
$session
);
if
(
$uri
=~
s/[\?&;]${cn}cda=(\w+)$//oi
)
{
if
(
$id
=
$class
->
fetchId
(
$req
)
and
$session
=
$class
->
retrieveSession
(
$req
,
$id
)
)
...
...
@@ -48,10 +48,8 @@ sub run {
return
$class
->
REDIRECT
;
}
}
(
$ret
,
$session
)
=
$class
->
Lemonldap::NG::Handler::Main::
run
(
$req
,
$rule
,
$protection
);
return
$ret
;
return
$class
->
Lemonldap::NG::Handler::Main::
run
(
$req
,
$rule
,
$protection
);
}
## @rmethod protected hash getCDAInfos(id)
...
...
lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm
View file @
d2d9988b
...
...
@@ -172,7 +172,9 @@ sub tplParams {
sub
javascript
{
my
(
$self
,
$req
)
=
@_
;
my
$res
=
eval
{
$self
->
hLoadedPlugins
->
{
viewer
}
->
diffRule
->
(
$req
,
$req
->
{
userData
}
);
$self
->
hLoadedPlugins
->
{
viewer
}
&&
$self
->
hLoadedPlugins
->
{
viewer
}
->
diffRule
->
(
$req
,
$req
->
{
userData
}
);
}
||
0
;
print
STDERR
$@
if
$@
;
my
$impPrefix
=
$self
->
{
impersonationPrefix
}
||
'
real_
';
...
...
lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Api/2F.pm
View file @
d2d9988b
...
...
@@ -353,7 +353,7 @@ sub _checkType {
return
{
res
=>
"
ko
",
code
=>
40
5
,
code
=>
40
0
,
msg
=>
"
Invalid input: Type
\"
$type
\"
does not exist. Allowed values for type are:
\"
U2F
\"
,
\"
TOTP
\"
or
\"
UBK
\"
"
}
...
...
lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Api/Common.pm
View file @
d2d9988b
...
...
@@ -20,17 +20,16 @@ sub _isSimpleKeyValueHash {
return
1
;
}
sub
_
s
etDefaultValues
{
my
(
$self
,
$attrs
,
$rootNode
)
=
@_
;
sub
_
g
etDefaultValues
{
my
(
$self
,
$rootNode
)
=
@_
;
my
@allAttrs
=
$self
->
_listAttributes
(
$rootNode
);
my
$defaultAttrs
=
Lemonldap::NG::Manager::Build::Attributes::
attributes
();
my
$attrs
=
{};
foreach
$attr
(
@allAttrs
)
{
unless
(
defined
$attrs
->
{
$attr
}
)
{
$attrs
->
{
$attr
}
=
$defaultAttrs
->
{
$attr
}
->
{
default
}
if
(
defined
$defaultAttrs
->
{
$attr
}
&&
defined
$defaultAttrs
->
{
$attr
}
->
{
default
}
);
}
$attrs
->
{
$attr
}
=
$defaultAttrs
->
{
$attr
}
->
{
default
}
if
(
defined
$defaultAttrs
->
{
$attr
}
&&
defined
$defaultAttrs
->
{
$attr
}
->
{
default
}
);
}
return
$attrs
;
...
...
@@ -47,7 +46,7 @@ sub _hasAllowedAttributes {
msg
=>
"
Invalid input: Attribute
$attribute
is not a string.
"
};
}
unless
(
grep
{
/^
$attribute
$/
}
@allowedAttributes
)
{
unless
(
grep
{
$_
eq
$attribute
}
@allowedAttributes
)
{
return
{
res
=>
"
ko
",
msg
=>
"
Invalid input: Attribute
$attribute
does not exist.
"
...
...
@@ -76,4 +75,41 @@ sub _listNodeAttributes {
return
@attributes
;
}
sub
_translateOptionApiToConf
{
my
(
$self
,
$optionName
,
$prefix
)
=
@_
;
# For consistency
$optionName
=~
s/^clientId$/clientID/
;
return
$prefix
.
"
MetaDataOptions
"
.
(
ucfirst
$optionName
);
}
sub
_translateOptionConfToApi
{
my
(
$self
,
$optionName
)
=
@_
;
$optionName
=~
s/^(\w+)MetaDataOptions//
;
$optionName
=
lcfirst
$optionName
;
# iDToken looks ugly
$optionName
=~
s/^iDToken/IDToken/
;
# For consistency
$optionName
=~
s/^clientID/clientId/
;
return
$optionName
;
}
sub
_getRegexpFromPattern
{
my
(
$self
,
$pattern
)
=
@_
;
return
unless
(
$pattern
=~
/[\w\.\-\*]+/
);
# . is allowed, and must be escaped
$pattern
=~
s/\./\\\./g
;
$pattern
=~
s/\*/\.\*/g
;
# anchor string, unless * was provided
$pattern
=
"
^
$pattern
\$
"
if
(
$pattern
=~
/\*/
);
return
qr/$pattern/
;
}
1
;
lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Api/Providers/OidcRp.pm
View file @
d2d9988b
...
...
@@ -7,6 +7,7 @@ package Lemonldap::NG::Manager::Api;
use
5.10.0
;
use
utf8
;
use
Mouse
;
use
Lemonldap::NG::Manager::Conf::
Parser
;
extends
'
Lemonldap::NG::Manager::Api::Common
';
...
...
@@ -40,9 +41,14 @@ sub findOidcRpByConfKey {
:
(
defined
$req
->
params
('
pattern
')
?
$req
->
params
('
pattern
')
:
undef
)
);
return
$self
->
sendError
(
$req
,
'
Invalid input: pattern is missing
',
40
5
)
return
$self
->
sendError
(
$req
,
'
Invalid input: pattern is missing
',
40
0
)
unless
(
defined
$pattern
);
unless
(
$pattern
=
$self
->
_getRegexpFromPattern
(
$pattern
)
)
{
return
$self
->
sendError
(
$req
,
'
Invalid input: pattern is invalid
',
400
);
}
$self
->
logger
->
debug
(
"
[API] Find OIDC RPs by confKey regexp
$pattern
requested
");
...
...
@@ -67,7 +73,7 @@ sub findOidcRpByClientId {
)
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
40
5
)
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
40
0
)
unless
(
defined
$clientId
);
$self
->
logger
->
debug
("
[API] Find OIDC RPs by clientId
$clientId
requested
");
...
...
@@ -87,15 +93,31 @@ sub addOidcRp {
my
(
$self
,
$req
)
=
@_
;
my
$add
=
$req
->
jsonBodyToObj
;
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
5
)
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
0
)
unless
(
$add
);
return
$self
->
sendError
(
$req
,
'
Invalid input: confKey is missing
',
40
5
)
return
$self
->
sendError
(
$req
,
'
Invalid input: confKey is missing
',
40
0
)
unless
(
defined
$add
->
{
confKey
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
405
)
return
$self
->
sendError
(
$req
,
'
Invalid input: confKey is not a string
',
400
)
if
(
ref
$add
->
{
confKey
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
400
)
unless
(
defined
$add
->
{
clientId
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is not a string
',
400
)
if
(
ref
$add
->
{
clientId
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: redirectUris is missing
',
400
)
unless
(
defined
$add
->
{
redirectUris
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: redirectUris must be an array
',
400
)
unless
(
ref
(
$add
->
{
redirectUris
}
)
eq
"
ARRAY
"
);
$self
->
logger
->
debug
(
"
[API] Add OIDC RP with confKey
$add
->{confKey} and clientId
$add
->{clientId} requested
"
);
...
...
@@ -106,25 +128,29 @@ sub addOidcRp {
return
$self
->
sendError
(
$req
,
"
Invalid input: An OIDC RP with confKey
$add
->{confKey} already exists
",
40
5
40
9
)
if
(
defined
$self
->
_getOidcRpByConfKey
(
$conf
,
$add
->
{
confKey
}
)
);
return
$self
->
sendError
(
$req
,
"
Invalid input: An OIDC RP with clientId
$add
->{clientId} already exists
",
40
5
40
9
)
if
(
defined
$self
->
_getOidcRpByClientId
(
$conf
,
$add
->
{
clientId
}
)
);
$add
->
{
options
}
=
{}
unless
(
defined
$add
->
{
options
}
);
$add
->
{
options
}
->
{
oidcRPMetaDataOptionsClientID
}
=
$add
->
{
clientId
};
$add
->
{
options
}
->
{
clientId
}
=
$add
->
{
clientId
};
$add
->
{
options
}
->
{
redirectUris
}
=
$add
->
{
redirectUris
};
my
$res
=
$self
->
_pushOidcRp
(
$conf
,
$add
->
{
confKey
},
$add
,
1
);
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
5
)
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
0
)
unless
(
$res
->
{
res
}
eq
'
ok
'
);
return
$self
->
sendJSONresponse
(
$req
,
{
message
=>
"
Successful operation
"
}
);
return
$self
->
sendJSONresponse
(
$req
,
{
message
=>
"
Successful operation
"
},
code
=>
201
);
}
sub
updateOidcRp
{
...
...
@@ -134,7 +160,7 @@ sub updateOidcRp {
my
$update
=
$req
->
jsonBodyToObj
;
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
5
)
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
0
)
unless
(
$update
);
$self
->
logger
->
debug
(
...
...
@@ -154,16 +180,15 @@ sub updateOidcRp {
# check if new clientID exists already
my
$res
=
$self
->
_isNewOidcRpClientIdUnique
(
$conf
,
$confKey
,
$update
);
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
5
)
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
9
)
unless
(
$res
->
{
res
}
eq
'
ok
'
);
$res
=
$self
->
_pushOidcRp
(
$conf
,
$confKey
,
$update
,
0
);
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
5
)
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
0
)
unless
(
$res
->
{
res
}
eq
'
ok
'
);
return
$self
->
sendJSONresponse
(
$req
,
{
message
=>
"
Successful operation
"
}
);
return
$self
->
sendJSONresponse
(
$req
,
undef
,
code
=>
204
);
}
sub
replaceOidcRp
{
...
...
@@ -173,11 +198,31 @@ sub replaceOidcRp {
my
$replace
=
$req
->
jsonBodyToObj
;
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
5
)
return
$self
->
sendError
(
$req
,
"
Invalid input:
"
.
$req
->
error
,
40
0
)
unless
(
$replace
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
405
)
return
$self
->
sendError
(
$req
,
'
Invalid input: confKey is missing
',
400
)
unless
(
defined
$replace
->
{
confKey
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: confKey is not a string
',
400
)
if
(
ref
$replace
->
{
confKey
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is missing
',
400
)
unless
(
defined
$replace
->
{
clientId
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: clientId is not a string
',
400
)
if
(
ref
$replace
->
{
clientId
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: redirectUris is missing
',
400
)
unless
(
defined
$replace
->
{
redirectUris
}
);
return
$self
->
sendError
(
$req
,
'
Invalid input: redirectUris must be an array
',
400
)
unless
(
ref
(
$replace
->
{
redirectUris
}
)
eq
"
ARRAY
"
);
$self
->
logger
->
debug
(
"
[API] OIDC RP
$confKey
configuration replace requested
");
...
...
@@ -192,15 +237,18 @@ sub replaceOidcRp {
# check if new clientID exists already
my
$res
=
$self
->
_isNewOidcRpClientIdUnique
(
$conf
,
$confKey
,
$replace
);
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
5
)
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
9
)
unless
(
$res
->
{
res
}
eq
'
ok
'
);
$replace
->
{
options
}
=
{}
unless
(
defined
$replace
->
{
options
}
);
$replace
->
{
options
}
->
{
clientId
}
=
$replace
->
{
clientId
};
$replace
->
{
options
}
->
{
redirectUris
}
=
$replace
->
{
redirectUris
};
$res
=
$self
->
_pushOidcRp
(
$conf
,
$confKey
,
$replace
,
1
);
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
5
)
return
$self
->
sendError
(
$req
,
$res
->
{
msg
},
40
0
)
unless
(
$res
->
{
res
}
eq
'
ok
'
);
return
$self
->
sendJSONresponse
(
$req
,
{
message
=>
"
Successful operation
"
}
);
return
$self
->
sendJSONresponse
(
$req
,
undef
,
code
=>
204
);
}
sub
deleteOidcRp
{
...
...
@@ -222,12 +270,12 @@ sub deleteOidcRp {
delete
$conf
->
{
oidcRPMetaDataOptions
}
->
{
$confKey
};
delete
$conf
->
{
oidcRPMetaDataExportedVars
}
->
{
$confKey
};
delete
$conf
->
{
oidcRPMetaDataOptionsExtraClaims
}
->
{
$confKey
};
delete
$conf
->
{
oidcRPMetaDataMacros
}
->
{
$confKey
};
# Save configuration
$self
->
_confAcc
->
saveConf
(
$conf
);
return
$self
->
sendJSONresponse
(
$req
,
{
message
=>
"
Successful operation
"
}
);
return
$self
->
sendJSONresponse
(
$req
,
undef
,
code
=>
204
);
}
sub
_getOidcRpByConfKey
{
...
...
@@ -244,16 +292,37 @@ sub _getOidcRpByConfKey {
my
$exportedVars
=
$conf
->
{
oidcRPMetaDataExportedVars
}
->
{
$confKey
};
# Get extra claim
my
$extraClaim
=
$conf
->
{
oidcRPMetaDataOptionsExtraClaims
}
->
{
$confKey
};
my
$extraClaims
=
$conf
->
{
oidcRPMetaDataOptionsExtraClaims
}
->
{
$confKey
};
# Get macros
my
$macros
=
$conf
->
{
oidcRPMetaDataMacros
}
->
{
$confKey
}
||
{};
# Get options
my
$options
=
$conf
->
{
oidcRPMetaDataOptions
}
->
{
$confKey
};
my
$options
=
{};
for
my
$configOption
(
keys
%
{
$conf
->
{
oidcRPMetaDataOptions
}
->
{
$confKey
}
}
)
{
# redirectUris is handled as an array
if
(
$configOption
eq
"
oidcRPMetaDataOptionsRedirectUris
"
)
{
$options
->
{
$self
->
_translateOptionConfToApi
(
$configOption
)
}
=
[
split
(
/\s+/
,
$conf
->
{
oidcRPMetaDataOptions
}
->
{
$confKey
}
->
{
$configOption
}
)
];
}
else
{
$options
->
{
$self
->
_translateOptionConfToApi
(
$configOption
)
}
=
$conf
->
{
oidcRPMetaDataOptions
}
->
{
$confKey
}
->
{
$configOption
};
}
}
return
{