Append function to check attributes (#2679)

This commit is contained in:
Christophe Maudoux 2021-12-21 23:20:51 +01:00
parent 49d87eed6f
commit d6f8f27d48
8 changed files with 69 additions and 17 deletions

View File

@ -31,7 +31,7 @@ use constant DEFAULTCONFBACKENDOPTIONS => (
);
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|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|ScopeRule|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 $arrayParameters = qr/^mySessionAuthorizedRWKeys$/;
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)|t(?:ayConnected(?:BypassFG)?|orePassword)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxy(?:AuthServiceImpersonation|UseSoap))|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload))?|State|User|XSS)|rowdsec|da)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|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|to(?:tp2fUserCanRemoveKey|kenUseGlobalStorage)|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
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)|t(?:ayConnected(?:BypassFG)?|orePassword)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload)|CheckSessionAttributes)?|State|User|XSS)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|rowdsec|da)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxy(?:AuthServiceImpersonation|UseSoap))|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|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|to(?:tp2fUserCanRemoveKey|kenUseGlobalStorage)|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -35,6 +35,7 @@ sub defaultValues {
'certificateResetByMailURL' =>
'http://auth.example.com/certificateReset',
'certificateResetByMailValidityDelay' => 0,
'checkDevOpsCheckSessionAttributes' => 1,
'checkDevOpsDisplayNormalizedHeaders' => 1,
'checkDevOpsDownload' => 1,
'checkTime' => 600,
@ -270,6 +271,7 @@ sub defaultValues {
'portalSkin' => 'bootstrap',
'portalUserAttr' => '_user',
'proxyAuthnLevel' => 2,
'proxyAuthServiceChoiceParam' => 'lmAuth',
'radius2fActivation' => 0,
'radius2fTimeout' => 20,
'radiusAuthnLevel' => 3,

View File

@ -870,6 +870,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'default' => 0,
'type' => 'bool'
},
'checkDevOpsCheckSessionAttributes' => {
'default' => 1,
'type' => 'bool'
},
'checkDevOpsDisplayNormalizedHeaders' => {
'default' => 1,
'type' => 'bool'
@ -2996,7 +3000,8 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'type' => 'text'
},
'proxyAuthServiceChoiceParam' => {
'type' => 'text'
'default' => 'lmAuth',
'type' => 'text'
},
'proxyAuthServiceChoiceValue' => {
'type' => 'text'

View File

@ -487,6 +487,12 @@ sub attributes {
documentation => 'Display normalized headers',
flags => 'p',
},
checkDevOpsCheckSessionAttributes => {
default => 1,
type => 'bool',
documentation => 'Check if session attributes exist',
flags => 'p',
},
checkUser => {
default => 0,
type => 'bool',
@ -3642,8 +3648,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
default => 3,
documentation => 'Radius authentication level',
},
radiusSecret => { type => 'text', },
radiusServer => { type => 'text', },
radiusSecret => { type => 'text' },
radiusServer => { type => 'text' },
# REST
restAuthUrl => { type => 'url' },
@ -3661,7 +3667,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
documentation => 'Name of the remote portal cookie',
flags => 'p',
},
remotePortal => { type => 'text', },
remotePortal => { type => 'text' },
remoteGlobalStorage => {
type => 'PerlModule',
default => 'Lemonldap::NG::Common::Apache::Session::SOAP',
@ -3678,10 +3684,13 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
},
# Proxy
proxyAuthService => { type => 'text', },
proxySessionService => { type => 'text', },
proxyAuthServiceChoiceParam => { type => 'text', },
proxyAuthServiceChoiceValue => { type => 'text', },
proxyAuthService => { type => 'text' },
proxySessionService => { type => 'text' },
proxyAuthServiceChoiceValue => { type => 'text' },
proxyAuthServiceChoiceParam => {
type => 'text',
default => 'lmAuth'
},
proxyAuthServiceImpersonation => {
type => 'bool',
default => 0,

View File

@ -822,7 +822,8 @@ sub tree {
nodes => [
'checkDevOps',
'checkDevOpsDownload',
'checkDevOpsDisplayNormalizedHeaders'
'checkDevOpsDisplayNormalizedHeaders',
'checkDevOpsCheckSessionAttributes'
],
},
{

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -194,6 +194,7 @@ sub parse {
if ($json) {
my $handler = $self->p->HANDLER;
my $vhost = $handler->resolveAlias($req);
my ( $bad_json, $unknown );
# Removed hidden session attributes
foreach my $v ( split /[,\s]+/, $self->conf->{hiddenAttributes} ) {
@ -221,7 +222,6 @@ sub parse {
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
$Lemonldap::NG::Common::Safelib::functions );
my $bad_rule = 0;
foreach ( keys %{ $json->{rules} } ) {
$cpt->reval("BEGIN { 'warnings'->unimport; } $json->{rules}->{$_}");
my $err = join(
@ -236,7 +236,7 @@ sub parse {
if ($err) {
$self->userLogger->error(
"Bad rule: $json->{rules}->{$_} ($err)");
$bad_rule = 1;
$bad_json = 1;
}
}
@ -244,15 +244,20 @@ sub parse {
$handler->headersInit( undef, { $vhost => $json->{headers} } );
$headers = $handler->checkHeaders( $req, $req->userData );
if ( $handler->tsv->{maintenance}->{$vhost} || $bad_rule ) {
# Check attributes if required
if ( $self->conf->{checkDevOpsCheckSessionAttributes} ) {
$unknown = $self->_checkSessionAttrs($json);
$bad_json = 1 if scalar @$unknown;
}
if ( $handler->tsv->{maintenance}->{$vhost} || $bad_json ) {
# Prepare form params
undef $json;
$headers = [];
$alert = 'alert-danger';
$msg = 'PE' . PE_BAD_DEVOPS_FILE;
$self->userLogger->error(
"CheckDevOps: bad 'rules.json' file (headers)");
$self->userLogger->error("CheckDevOps: bad 'rules.json' file");
$handler->tsv->{maintenance}->{$vhost} = 0;
}
else {
@ -320,4 +325,34 @@ sub parse {
return $self->p->sendHtml( $req, 'checkdevops', params => $params );
}
sub _checkSessionAttrs {
my ( $self, $json ) = @_;
my $unknown;
my %sessionAttrs = map { $_ => 1 } (
keys %{ $self->{conf}->{exportedVars} },
keys %{ $self->{conf}->{groups} },
keys %{ $self->{conf}->{macros} }
);
$self->logger->debug(
"Existing session attributes: " . join $self->conf->{multiValuesSeparator},
keys %sessionAttrs );
my @varh = map { ( $json->{headers}->{$_} =~ /\$(\w+)\b/g ) }
keys %{ $json->{headers} };
my @varr = map { ( $json->{rules}->{$_} =~ /\$(\w+)\b/g ) }
keys %{ $json->{rules} };
my %usedAttrs = map { $_ => 1 } ( @varh, @varr );
$self->logger->debug(
"Used attributs: " . join $self->conf->{multiValuesSeparator},
keys %usedAttrs );
@$unknown = map { $sessionAttrs{$_} ? () : $_ } keys %usedAttrs;
$self->logger->debug(
"Unknown attributes: " . join $self->conf->{multiValuesSeparator},
@$unknown )
if scalar @$unknown;
return $unknown;
}
1;