Merge branch 'v2.0'

This commit is contained in:
Christophe Maudoux 2019-07-23 16:00:25 +02:00
commit c82fc0f572
49 changed files with 4915 additions and 101 deletions

View File

@ -23,7 +23,7 @@ use constant HANDLERSECTION => "handler";
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(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|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(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|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|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|RequirePKCE|Public)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|p(?:ortal(?:ErrorOn(?:ExpiredSession|MailNotFound)|DisplayRe(?:setPassword|gister)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl)|oginHistoryEnabled)|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)|no(?:tif(?:ication(?:Server)?|y(?:Deleted|Other))|AjaxHook)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|rest(?:(?:Session|Config)Server|ExportSecretKeys)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs)|bruteForceProtection)$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -698,6 +698,25 @@ sub combModules {
return $self->sendJSONresponse( $req, $res );
}
sub sfExtra {
my ( $self, $req, $key ) = @_;
return $self->sendError( $req, 'Subkeys forbidden for sfExtra', 400 )
if ($key);
my $val = $self->getConfKey( $req, 'sfExtra' ) // {};
my $res = [];
foreach my $mod ( keys %$val ) {
my $tmp;
$tmp->{title} = $mod;
$tmp->{id} = "sfExtra/$mod";
$tmp->{type} = 'sfExtra';
$tmp->{data}->{$_} = $val->{$mod}->{$_} foreach (qw(type rule));
my $over = $val->{$mod}->{over} // {};
$tmp->{data}->{over} = [ map { [ $_, $over->{$_} ] } keys %$over ];
push @$res, $tmp;
}
return $self->sendJSONresponse( $req, $res );
}
# 33 - Root queries
# -----------

View File

@ -22,7 +22,7 @@ our $specialNodeHash = {
};
our $doubleHashKeys = 'issuerDBGetParameters';
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|c(?:as(?:StorageOption|Attribute)|ustomAddParam|ombModule)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|c(?:as(?:StorageOption|Attribute)|ustomAddParam|ombModule)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|ExportedVars)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';

View File

@ -57,7 +57,6 @@ sub deleteNotification {
'REST service "delete notification" called without all parameters');
return 0;
}
$self->logger->debug(
"REST service deleteNotification called for uid $uid and reference $myref"
);
@ -73,7 +72,8 @@ sub deleteNotification {
foreach my $ref ( keys %$user ) {
my $json = from_json( $user->{$ref}, { allow_nonref => 1 } );
$json = [$json] unless ( ref($json) eq 'ARRAY' );
# Browse notification in file
foreach my $notif (@$json) {

View File

@ -37,7 +37,7 @@ sub AUTOLOAD {
return $tmp;
}
elsif ( $AUTOLOAD ne 'DESTROY' ) {
die "$AUTOLOAD is not an authorizated function";
die "$AUTOLOAD is not an authorized function";
}
1;
}

View File

@ -3223,6 +3223,26 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'default' => '::2F::Engines::Default',
'type' => 'text'
},
'sfExtra' => {
'keyTest' => qr/^\w+$/,
'select' => [ {
'k' => 'Mail2F',
'v' => 'E-Mail'
},
{
'k' => 'REST',
'v' => 'REST'
},
{
'k' => 'Ext2F',
'v' => 'External'
}
],
'test' => sub {
1;
},
'type' => 'sfExtraContainer'
},
'sfRemovedMsgRule' => {
'default' => 0,
'type' => 'boolOrExpr'

View File

@ -3294,6 +3294,17 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
{ k => 'Custom', v => 'customModule' },
],
},
sfExtra => {
type => 'sfExtraContainer',
keyTest => qr/^\w+$/,
test => sub { 1 },
documentation => 'Extra second factors',
select => [
{ k => 'Mail2F', v => 'E-Mail' },
{ k => 'REST', v => 'REST' },
{ k => 'Ext2F', v => 'External' },
],
},
# Custom auth modules
customAuth => {

View File

@ -787,6 +787,7 @@ sub tree {
],
},
'sfRequired',
'sfExtra',
]
},
{

View File

@ -69,7 +69,7 @@ sub addRoutes {
qw(virtualHosts samlIDPMetaDataNodes samlSPMetaDataNodes
applicationList oidcOPMetaDataNodes oidcRPMetaDataNodes
casSrvMetaDataNodes casAppMetaDataNodes
authChoiceModules grantSessionRules combModules
authChoiceModules grantSessionRules combModules sfExtra
openIdIDPList)
]
},

View File

@ -793,6 +793,25 @@ sub _scanNodes {
next;
}
# sfExtra: just to replace "over" key
if ( $name eq 'sfExtra' ) {
hdebug(' sfExtra');
$self->newConf->{$name} = {};
foreach my $node ( @{ $leaf->{nodes} } ) {
my $tmp;
$tmp->{$_} = $node->{data}->{$_} foreach (qw(type rule));
$tmp->{over} = {};
foreach ( @{ $node->{data}->{over} } ) {
$tmp->{over}->{ $_->[0] } = $_->[1];
}
$self->newConf->{$name}->{ $node->{title} } = $tmp;
}
# TODO: check changes
$self->confChanged(1);
next;
}
$subNodes //= [];
my $count = 0;
my @old = (

View File

@ -328,6 +328,23 @@ llapp.controller 'TreeCtrl', [
over: []
$scope.execFilters $scope._findScopeByKey 'authParams'
$scope.newSfExtra = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: 'new'
type: 'sfExtra'
data:
type: ''
rule: ''
over: []
$scope.newSfOver = ->
d = $scope.currentNode.data
d.over = [] unless d.over
d.over.push ["new#{id++}", '']
$scope.newCmbOver = ->
d = $scope.currentNode.data
d.over = [] unless d.over
@ -624,16 +641,17 @@ llapp.controller 'TreeCtrl', [
node = scope.$modelValue
# regexp-assemble of:
# authChoice
# keyText
# cmbModule
# virtualHost
# rule
# menuCat
# keyText
# menuApp
# menuCat
# rule
# samlAttribute
# samlIDPMetaDataNode
# samlSPMetaDataNode
return if node.type and node.type.match /^(?:(?:saml(?:(?:ID|S)PMetaDataNod|Attribut)|(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/ then true else false
# sfExtra
# virtualHost
return if node.type and node.type.match /^(?:s(?:aml(?:(?:ID|S)PMetaDataNod|Attribut)e|fExtra)|(?:(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/ then true else false
# RSA keys generation
$scope.newRSAKey = ->

View File

@ -0,0 +1,54 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{currentNode.title}}</h3>
</div>
<table class="table table-striped">
<thead>
<tr>
<th width="25%" trspan="name"></th>
<th width="25%" trspan="type"></th>
<th width="50%" trspan="rule"></th>
<th />
</tr>
</thead>
<tbody>
<tr>
<td>
<input class="form-control" ng-model="currentNode.title" />
</td>
<td>
<select class="form-control" ng-model="currentNode.data.type">
<option ng-repeat="item in _findContainer().select" ng-selected="item.k===currentNode.data.type" value="{{item.k}}">{{item.v}}</option>
</select>
</td>
<td>
<input class="form-control" ng-model="currentNode.data.rule" />
</td>
</tr>
</tbody>
</table>
<h4 trspan="overPrm"></h4>
<table class="table">
<tr ng-repeat="t in currentNode.data.over">
<td>
<input class="form-control" ng-model="t[0]" />
</td>
<td>
<input class="form-control" ng-model="t[1]" />
</td>
<td>
<span class="link text-danger glyphicon glyphicon-minus-sign" ng-click="del(currentNode.data.over,$index)"/>
<span ng-if="$last" class="link text-success glyphicon glyphicon-plus-sign" ng-click="menuClick({title:'newSfOver'})"/>
</td>
</tr>
</table>
</div>
<script type="text/menu">
[{
"title": "newSfOver",
"icon": "plus-sign"
},{
"title": "deleteEntry",
"icon": "minus-sign"
}]
</script>

View File

@ -0,0 +1,40 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{translateTitle(currentNode)}}</h3>
</div>
<table class="table table-striped">
<thead>
<tr>
<th width="25%" trspan="name"></th>
<th width="25%" trspan="type"></th>
<th width="50%" trspan="rule"></th>
<th />
</tr>
</thead>
<tbody>
<tr ng-repeat="s in currentNode.nodes">
<td>
<input class="form-control" ng-model="s.title" />
</td>
<td>
<select class="form-control" ng-model="s.data.type">
<option ng-repeat="item in currentNode.select" ng-selected="item.k==s.data.type" value="{{item.k}}">{{item.v}}</option>
</select>
</td>
<td>
<input class="form-control" ng-model="s.data.rule" />
</td>
<td>
<span class="link text-danger glyphicon glyphicon-minus-sign" ng-click="del(currentNode.nodes,$index)"/>
<span ng-if="$last" class="link text-success glyphicon glyphicon-plus-sign" ng-click="menuClick({title:'newSfExtra'})"/>
</td>
</tr>
</tbody>
</table>
</div>
<script type="text/menu">
[{
"title": "newSfExtra",
"icon": "plus-sign"
}]
</script>

View File

@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.12.7
// Generated by CoffeeScript 1.12.8
/*
LemonLDAP::NG Manager client
@ -382,6 +382,28 @@ This file contains:
});
return $scope.execFilters($scope._findScopeByKey('authParams'));
};
$scope.newSfExtra = function() {
var node;
node = $scope._findContainer();
return node.nodes.push({
id: node.id + "/n" + (id++),
title: 'new',
type: 'sfExtra',
data: {
type: '',
rule: '',
over: []
}
});
};
$scope.newSfOver = function() {
var d;
d = $scope.currentNode.data;
if (!d.over) {
d.over = [];
}
return d.over.push(["new" + (id++), '']);
};
$scope.newCmbOver = function() {
var d;
d = $scope.currentNode.data;
@ -767,7 +789,7 @@ This file contains:
$scope.keyWritable = function(scope) {
var node;
node = scope.$modelValue;
if (node.type && node.type.match(/^(?:(?:saml(?:(?:ID|S)PMetaDataNod|Attribut)|(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/)) {
if (node.type && node.type.match(/^(?:s(?:aml(?:(?:ID|S)PMetaDataNod|Attribut)e|fExtra)|(?:(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/)) {
return true;
} else {
return false;

File diff suppressed because one or more lines are too long

View File

@ -191,6 +191,7 @@
"confSaved":"تم حفظ الهيئة",
"confWasChanged":"تم تغيير الإعدادات",
"connectionTitle":" الاتصال",
"content":"محتوى",
"cookieExpiration":"وقت انتهاء صلاحية ملفات تعريف الارتباط",
"cookieName":"اسم ملف تعريف الارتباط",
"cookieParams":"ملفات تعريف الارتباط",
@ -468,6 +469,8 @@
"newPostVar":"متغير جديد",
"newRSAKey":"مفاتيح جديدة",
"newRule":"قاعدة جديدة",
"newSfOver":"معايير جديدة",
"newSfExtra":"New second factor",
"newValue":"قيمة جديدة",
"next":"التالى",
"nginxCustomHandlers":"معالجات إنجن إكس المخصصة",
@ -738,6 +741,7 @@
"sessionStorage":"تخزين الجلسات",
"sessionTitle":"محتوى الجلسة",
"sfaTitle":"Second Factors Authentication",
"sfExtra":"Additional second factors",
"sfRequired":"Require 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"تفعيل",
@ -872,7 +876,6 @@
"whatToTrace":"المستخدم_البعيد",
"whiteList":"القائمة البيضاء",
"wsdlServer":"WSDL server",
"XMLcontent":"محتوى XML",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"تفعيل",
"yubikey2fAuthnLevel":"مستوى إثبات الهوية",

View File

@ -191,6 +191,7 @@
"confSaved":"Konfiguration gesichert",
"confWasChanged":"Konfiguration wurde geändert",
"connectionTitle":"Verbindung",
"content":"Content",
"cookieExpiration":"Cookie expiration time",
"cookieName":"Cookie Name",
"cookieParams":"Cookies",
@ -467,6 +468,8 @@
"newPostVar":"New variable",
"newRSAKey":"New keys",
"newRule":"New rule",
"newSfOver":"New parameter",
"newSfExtra":"New second factor",
"newValue":"New value",
"next":"Next",
"nginxCustomHandlers":"Custom Nginx handlers",
@ -737,6 +740,7 @@
"sessionStorage":"Sessions Storage",
"sessionTitle":"Session content",
"sfaTitle":"Second Factors Authentication",
"sfExtra":"Additional second factors",
"sfRequired":"Require 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"Activation",
@ -871,7 +875,6 @@
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",
"wsdlServer":"WSDL server",
"XMLcontent":"XML content",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"Activation",
"yubikey2fAuthnLevel":"Authentication level",

View File

@ -191,6 +191,7 @@
"confSaved":"Configuration saved",
"confWasChanged":"Configuration has been changed",
"connectionTitle":"Connection",
"content":"Content",
"cookieExpiration":"Cookie expiration time",
"cookieName":"Cookie Name",
"cookieParams":"Cookies",
@ -467,6 +468,8 @@
"newPostVar":"New variable",
"newRSAKey":"New keys",
"newRule":"New rule",
"newSfOver":"New parameter",
"newSfExtra":"New second factor",
"newValue":"New value",
"next":"Next",
"nginxCustomHandlers":"Custom Nginx handlers",
@ -737,6 +740,7 @@
"sessionStorage":"Sessions Storage",
"sessionTitle":"Session content",
"sfaTitle":"Second Factors Authentication",
"sfExtra":"Additional second factors",
"sfRequired":"Require 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"Activation",
@ -871,7 +875,6 @@
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",
"wsdlServer":"WSDL server",
"XMLcontent":"XML content",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"Activation",
"yubikey2fAuthnLevel":"Authentication level",

View File

@ -191,6 +191,7 @@
"confSaved":"Configuration sauvegardée",
"confWasChanged":"Configuration modifiée entre-temps",
"connectionTitle":"Connexion",
"content":"Contenu",
"cookieExpiration":"Durée de vie du cookie",
"cookieName":"Nom du cookie",
"cookieParams":"Cookies",
@ -467,6 +468,8 @@
"newPostVar":"Nouvelle variable",
"newRSAKey":"Nouvelles clefs",
"newRule":"Nouvelle règle",
"newSfOver":"Nouveau paramètre",
"newSfExtra":"Nouveau second facteur",
"newValue":"Nouvelle valeur",
"next":"Suivante",
"nginxCustomHandlers":"Handlers Nginx personnalisés",
@ -737,6 +740,7 @@
"sessionStorage":"Stockage des sessions",
"sessionTitle":"Contenu de la session",
"sfaTitle":"Seconds Facteurs d'Authentification",
"sfExtra":"Seconds Facteurs additionnels",
"sfRequired":"Exiger 2FA",
"sfRemovedNotification":"Afficher un message si un SF expiré a été supprimé",
"sfRemovedMsgRule":"Activation",
@ -871,7 +875,6 @@
"whatToTrace":"REMOTE_USER",
"whiteList":"Liste blanche",
"wsdlServer":"Serveur WSDL",
"XMLcontent":"Contenu XML",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"Activation",
"yubikey2fAuthnLevel":"Niveau d'authentification",

View File

@ -141,8 +141,8 @@
"cda":"Domini multipli",
"contentSecurityPolicy":"Politica di protezione dei contenuti",
"contextSwitching":"Switch context another user",
"contextSwitchingHiddenAttributes":"Hidden attributes",
"contextSwitchingIdRule":"Identities use rule",
"contextSwitchingHiddenAttributes":"Attributi nascosti",
"contextSwitchingIdRule":"Le identità usano la regola",
"contextSwitchingRule":"Utilizza la regola",
"contextSwitchingStopWithLogout":"Stop by logout",
"cspDefault":"Valore di default",
@ -191,6 +191,7 @@
"confSaved":"Configurazione salvata",
"confWasChanged":"La configurazione é stata modificata",
"connectionTitle":"Connessione",
"content":"Contenuto",
"cookieExpiration":"Tempo di scadenza del cookie",
"cookieName":"Nome del cookie",
"cookieParams":"Cookie",
@ -467,6 +468,8 @@
"newPostVar":"Nuova variabile",
"newRSAKey":"Nuove chiavi",
"newRule":"Nuova regola",
"newSfOver":"Nuovo parametro",
"newSfExtra":"New second factor",
"newValue":"Nuovo valore",
"next":"Seguente",
"nginxCustomHandlers":"Gestori Custom Nginx",
@ -737,6 +740,7 @@
"sessionStorage":"Conservazione di sessioni",
"sessionTitle":"Contenuto della sessione",
"sfaTitle":"Autenticazione a due fattori",
"sfExtra":"Additional second factors",
"sfRequired":"Richiedi 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"Attivazione",
@ -871,7 +875,6 @@
"whatToTrace":"\nREMOTE_USER",
"whiteList":"Lista bianca",
"wsdlServer":"Server WSDL",
"XMLcontent":"Contenuto XML",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"Attivazione",
"yubikey2fAuthnLevel":"Livello di autenticazione",

View File

@ -191,6 +191,7 @@
"confSaved":"Cấu hình được lưu",
"confWasChanged":"Cấu hình đã được thay đổi",
"connectionTitle":"Kết nối",
"content":"Nội dung",
"cookieExpiration":"Thời gian hết hạn cookie",
"cookieName":"Cookie Name",
"cookieParams":"Cookie",
@ -467,6 +468,8 @@
"newPostVar":"Biến mới",
"newRSAKey":"Khóa mới",
"newRule":"Quy tắc mới",
"newSfOver":"Tham số mới",
"newSfExtra":"New second factor",
"newValue":"Giá trị mới",
"next":"Tiếp theo",
"nginxCustomHandlers":"Tùy chỉnh trình xử lý Nginx ",
@ -737,6 +740,7 @@
"sessionStorage":"Sessions lưu trữ",
"sessionTitle":"Nội dung phiên",
"sfaTitle":"Second Factors Authentication",
"sfExtra":"Additional second factors",
"sfRequired":"Require 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"Kích hoạt",
@ -871,7 +875,6 @@
"whatToTrace":"REMOTE_USER",
"whiteList":"Danh sách trắng",
"wsdlServer":"WSDL server",
"XMLcontent":"Nội dung XML",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"Kích hoạt",
"yubikey2fAuthnLevel":"Mức xác thực",

View File

@ -191,6 +191,7 @@
"confSaved":"配置已保存",
"confWasChanged":"配置已经被修改",
"connectionTitle":"连接",
"content":"Content",
"cookieExpiration":"Cookies 失效时间",
"cookieName":"Cookie 名称",
"cookieParams":"Cookies",
@ -467,6 +468,8 @@
"newPostVar":"New variable",
"newRSAKey":"New keys",
"newRule":"New rule",
"newSfOver":"New parameter",
"newSfExtra":"New second factor",
"newValue":"New value",
"next":"Next",
"nginxCustomHandlers":"Custom Nginx handlers",
@ -737,6 +740,7 @@
"sessionStorage":"Sessions Storage",
"sessionTitle":"Session content",
"sfaTitle":"Second Factors Authentication",
"sfExtra":"Additional second factors",
"sfRequired":"Require 2FA",
"sfRemovedNotification":"Display a message if an expired SF is removed",
"sfRemovedMsgRule":"激活",
@ -871,7 +875,6 @@
"whatToTrace":"REMOTE_USER",
"whiteList":"White list",
"wsdlServer":"WSDL 服务器",
"XMLcontent":"XML content",
"yubikey2f":"Yubikey",
"yubikey2fActivation":"激活",
"yubikey2fAuthnLevel":"认证等级",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -109,7 +109,7 @@
<td><input type="text" class="form-control" ng-model="form.condition"/></td>
</tr>
<tr>
<th><span trspan="XMLcontent" /></th>
<th><span trspan="content" /></th>
<td>
<textarea rows=5 class="form-control" ng-model="form.xml"></textarea>
<div class="alert alert-info">

View File

@ -0,0 +1,38 @@
# Verify that bas changes are detected
use Test::More;
use strict;
use JSON;
require 't/test-lib.pm';
my $struct = 't/jsonfiles/17-extra2f.json';
sub body {
return IO::File->new( $struct, 'r' );
}
unlink 't/conf/lmConf-2.json';
mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($res);
ok( $res = &client->_get( '/confs/2/sfExtra', 'application/json' ),
'Get combModules' );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
use Data::Dumper;
print Dumper($resBody);
count(6);
done_testing( count() );
unlink 't/conf/lmConf-2.json';
`rm -rf t/sessions`;

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';
with 'Lemonldap::NG::Portal::Lib::OverConf';
# INITIALIZATION
@ -93,6 +94,37 @@ sub init {
}
}
# Extra 2F modules
$self->logger->debug('Processing Extra 2F modules');
foreach my $extraKey (sort keys %{ $self->conf->{sfExtra} } ) {
my $moduleType = $self->conf->{sfExtra}->{$extraKey}->{type};
next unless ($moduleType);
my %over = %{ $self->conf->{sfExtra}->{$extraKey}->{over} or {} };
$self->logger->debug(
"Loading extra 2F module $extraKey of type $moduleType");
my $m =
$self->loadPlugin( "::2F::$moduleType",
{ sfPrefix => $extraKey, %over } )
or return 0;
# Rule and prefix may be modified by 2F module, reread them
my $rule = $self->conf->{sfExtra}->{$extraKey}->{rule} || 1;
my $prefix = $m->prefix;
# Compile rule
$rule = $self->p->HANDLER->substitute($rule);
unless ( $rule = $self->p->HANDLER->buildSub($rule) ) {
$self->error( 'External 2F rule error: '
. $self->p->HANDLER->tsv->{jail}->error );
return 0;
}
# Store module
push @{ $self->{'sfModules'} }, { p => $prefix, m => $m, r => $rule };
}
unless (
$self->sfReq(
$self->p->HANDLER->buildSub(

View File

@ -16,7 +16,7 @@ extends 'Lemonldap::NG::Portal::Main::SecondFactor';
# INITIALIZATION
has prefix => ( is => 'ro', default => 'ext' );
has prefix => ( is => 'rw', default => 'ext' );
has random => ( is => 'rw' );
sub init {
@ -28,6 +28,8 @@ sub init {
return 0;
}
}
$self->prefix( $self->conf->{sfPrefix} )
if ( $self->conf->{sfPrefix} );
$self->logo( $self->conf->{ext2fLogo} )
if ( $self->conf->{ext2fLogo} );
return $self->SUPER::init();
@ -38,6 +40,8 @@ sub init {
return 0;
}
$self->random( Lemonldap::NG::Common::Crypto::srandom() );
$self->prefix( $self->conf->{sfPrefix} )
if ( $self->conf->{sfPrefix} );
$self->logo( $self->conf->{ext2fLogo} )
if ( $self->conf->{ext2fLogo} );
return $self->SUPER::init();
@ -82,6 +86,7 @@ sub run {
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
TOKEN => $token,
TARGET => '/' . $self->prefix . '2fcheck',
CHECKLOGINS => $checkLogins
}
);

View File

@ -18,7 +18,7 @@ extends 'Lemonldap::NG::Portal::Main::SecondFactor',
# INITIALIZATION
has prefix => ( is => 'ro', default => 'mail' );
has prefix => ( is => 'rw', default => 'mail' );
has random => (
is => 'rw',
default => sub {
@ -47,6 +47,8 @@ sub init {
}
$self->logo( $self->conf->{mail2fLogo} )
if ( $self->conf->{mail2fLogo} );
$self->prefix( $self->conf->{sfPrefix} )
if ( $self->conf->{sfPrefix} );
return $self->SUPER::init();
}

View File

@ -17,7 +17,7 @@ extends 'Lemonldap::NG::Portal::Main::SecondFactor',
# INITIALIZATION
has prefix => ( is => 'ro', default => 'rest' );
has prefix => ( is => 'rw', default => 'rest' );
has initAttrs => ( is => 'rw', default => sub { {} } );
@ -29,6 +29,8 @@ sub init {
$self->logger->error('Missing REST verification URL');
return 0;
}
$self->prefix( $self->conf->{sfPrefix} )
if ( $self->conf->{sfPrefix} );
$self->logo( $self->conf->{rest2fLogo} ) if ( $self->conf->{rest2fLogo} );
foreach my $k ( keys %{ $self->conf->{rest2fInitArgs} } ) {
my $attr = $self->conf->{rest2fInitArgs}->{$k};
@ -92,7 +94,7 @@ sub run {
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
TOKEN => $token,
TARGET => '/rest2fcheck',
TARGET => '/' . $self->prefix . '2fcheck',
CHECKLOGINS => $checkLogins
}
);

View File

@ -3,6 +3,7 @@ package Lemonldap::NG::Portal::Lib::Notifications::JSON;
use strict;
use Mouse;
use JSON qw(from_json);
use Data::Dumper;
our $VERSION = '2.1.0';
@ -82,7 +83,7 @@ sub getNotifBack {
}
if ( $req->param('cancel') ) {
$self->logger->debug('Cancel called -> remove cipher cookie');
$self->logger->debug('Cancel called -> remove ciphered cookie');
$req->addCookie(
$self->p->cookie(
name => $self->conf->{cookieName},
@ -227,14 +228,69 @@ sub toForm {
}
sub notificationServer {
my ( $self, $req ) = @_;
my ( $self, $req, @args ) = @_;
$self->p->logger->debug("REST request for notifications");
return $self->p->sendError( $req, 'Only JSON requests here', 400 )
unless ( $req->wantJSON );
$self->p->logger->debug( "JSON content: " . $req->content );
my ( $res, $err ) =
eval { $self->notifObject->newNotification( $req->content ) };
return $self->p->sendError( $req, $@, 500 ) if ($@);
my ( $res, $err );
if ( $req->method =~ /^POST$/i ) {
$self->p->logger->debug("POST request");
( $res, $err ) =
eval { $self->notifObject->newNotification( $req->content ) };
return $self->p->sendError( $req, $@, 500 ) if ($@);
}
elsif ( $req->method =~ /^GET$/i ) {
$self->p->logger->debug("GET request");
my ( $uid, $ref ) = @args;
my $notifs;
( $notifs, $err ) =
eval { $self->notifObject->getNotifications($uid) };
return $self->p->sendError( $req, $@, 500 ) if ($@);
$res = [];
foreach ( keys %$notifs ) {
$self->p->logger->debug("Found notification $_");
my $json;
eval { $json = from_json( $notifs->{$_}, { allow_nonref => 1 } ) };
return $self->p->sendError( $req, "Unable to decode JSON file: $@",
400 )
if ($@);
$self->p->logger->debug(
"Notification $_: " . Dumper($json) );
if ($ref) {
push(
@$res,
{
"uid" => $json->{uid},
"reference" => $json->{reference},
"date" => $json->{date},
"title" => $json->{title},
"text" => $json->{text}
}
) if ( $json->{reference} =~ /^$ref$/ );
}
else {
push @$res,
{ "uid" => $json->{uid}, "reference" => $json->{reference} };
}
}
}
elsif ( $req->method =~ /^DELETE$/i ) {
$self->p->logger->debug("DELETE request");
my $uid = $req->params('uid');
my $ref = $req->params('reference');
return $self->p->sendError( $req,
"Missing parameters -> uid: $uid / ref: $ref", 400 )
unless ( $uid and $ref );
( $res, $err ) =
eval { $self->notifObject->deleteNotification( $uid, $ref ); };
return $self->p->sendError( $req, $@, 500 ) if ($@);
}
else {
return $self->p->sendError( $req, "Unknown HTTP method: $req->method",
400 );
}
return $self->p->sendError( $req, ( $err ? $err : 'Bad request' ), 400 )
unless ($res);
return $self->p->sendJSONresponse( $req, { result => $res } );

View File

@ -148,7 +148,7 @@ sub getNotifBack {
}
if ( $req->param('cancel') ) {
$self->logger->debug('Cancel called -> remove cipher cookie');
$self->logger->debug('Cancel called -> remove ciphered cookie');
$req->addCookie(
$self->p->cookie(
name => $self->conf->{cookieName},

View File

@ -42,15 +42,24 @@ sub init {
my ($self) = @_;
# Declare new route
$self->addUnauthRoute( 'notifback' => 'getNotifBack', ['POST', 'GET'] );
$self->addUnauthRoute( 'notifback' => 'getNotifBack', [ 'POST', 'GET' ] );
$self->addAuthRoute( 'notifback' => 'getNotifBack', ['POST'] );
if ( $self->conf->{notificationServer} ) {
$self->logger->debug('Notification server enable');
$self->addUnauthRoute(
'notifications' => 'notificationServer',
notifications => 'notificationServer',
['POST']
);
$self->addUnauthRoute(
notifications => { '*' => 'notificationServer' },
['GET']
);
$self->addUnauthRoute(
notifications =>
{ ':uid' => { ':reference' => 'notificationServer' } },
['DELETE']
);
}
# Search for configuration options
@ -142,8 +151,8 @@ sub getNotifBack {
}
sub notificationServer {
my ( $self, $req ) = @_;
return $self->module->notificationServer($req);
my ( $self, $req, @args ) = @_;
return $self->module->notificationServer($req, @args);
}
1;

View File

@ -108,8 +108,8 @@
"changePwd":"غير كلمة المرور الخاصة بك",
"checkLastLogins":"تحقق من آخر تسجيلات دخول الخاصة بي",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"اختر أحد التطبيقات المسموح لك بالدخول إليها",
"clickHere":"الرجاء الضغط هنا",
@ -163,7 +163,7 @@
"mail":"البريد",
"mailSent2":"تم إرسال رسالة إلى عنوان بريدك الإلكتروني.",
"maintenanceMode":"هذا التطبيق في صيانة، يرجى محاولة الاتصال في وقت لاحق",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"اسم",
"newMessages":"رسالة جديدة (رسائل)",
@ -251,7 +251,7 @@
"yourIdentity":"هويتك",
"yourIdentityIs":"هويتك هي",
"yourKeyIsRegistered":"المفتاح الخاص بك تم تسجيله",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"تمت إزالة المفتاح",
"yourKeyIsVerified":"تم اختبار المفتاح الخاص بك بنجاح",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Ändere dein Passwort",
"checkLastLogins":"Überprüfe meine letzten Logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Wählen deinen Ihren zweiten Faktor",
"chooseApp":"Wählen Sie eine Anwendung aus, auf die du zugreifen darfst",
"clickHere":"Bitte hier klicken",
@ -163,7 +163,7 @@
"mail":"E-Mail",
"mailSent2":"Eine Nachricht wurde an deine E-Mail Adresse gesendet.",
"maintenanceMode":"Diese Anwendung ist in Wartung, bitte versuche später eine Verbindung herzustellen",
"maxNumberof2FDevicesReached":"Maximale Anzahl an 2F-Geräten erreicht!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code fehlt",
"name":"Name",
"newMessages":"Neue Nachricht(en)",
@ -251,7 +251,7 @@
"yourIdentity":"Ihre Identität",
"yourIdentityIs":"Ihre Identität ist",
"yourKeyIsRegistered":"Ihr Key wurde registriert",
"yourKeyIsAlreadyRegistered":"Ihr Key ist bereits registriert!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Ihr Key ist bestätigt",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Change your password",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Change your password",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Vaihda salasanasi",
"checkLastLogins":"Tarkista viimeiset kirjautumiseni",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Sähköposti",
"mailSent2":"Viesti on lähetetty sähköpostiisi.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Changez votre mot de passe",
"checkLastLogins":"Voir mes dernières connexions",
"checkUser":"Vérifier le profil SSO d'un utilisateur",
"checkUserMerged":"Vérifier le profil SSO d'un utilisateur. Tout ou partie des groupes SSO réels et simulés sont fusionnés !!!",
"checkUserComputeSession":"Données de session issues d'une évaluation !!!",
"checkUserMerged":"Vérifier le profil SSO d'un utilisateur. Tout ou partie des groupes SSO réels et simulés sont fusionnés !",
"checkUserComputeSession":"Données de session issues d'une évaluation !",
"choose2f":"Choisissez votre second facteur",
"chooseApp":"Choisissez une application à laquelle vous êtes autorisé à accéder",
"clickHere":"Cliquez ici",
@ -163,7 +163,7 @@
"mail":"Adresse mail",
"mailSent2":"Un message a été envoyé à votre adresse mail.",
"maintenanceMode":"Cette application est en maintenance, merci de réessayer plus tard",
"maxNumberof2FDevicesReached":"Nombre maximum de seconds facteurs atteint !!!",
"maxNumberof2FDevicesReached":"Nombre maximum de seconds facteurs atteint !",
"missingCode":"Code manquant",
"name":"Nom",
"newMessages":"Nouveaux messages",
@ -222,7 +222,7 @@
"stayConnected": "Rester connecté sur cet appareil",
"submit":"Envoyer",
"switchContext":"Changer de contexte",
"totpExistingKey":"Un secret TOTP existe déjà !!!",
"totpExistingKey":"Un secret TOTP existe déjà !",
"touchU2fDevice": "Posez votre doigt sur le périphérique U2F",
"touchU2fDeviceOrEnterTotp": "Posez votre doigt sur le périphérique U2F ou entrez le code TOTP",
"type":"Type",
@ -251,7 +251,7 @@
"yourIdentity":"Votre identité",
"yourIdentityIs":"Votre identité est",
"yourKeyIsRegistered":"Votre clef est enregistrée",
"yourKeyIsAlreadyRegistered":"Votre clef est déjà enregistrée !!!",
"yourKeyIsAlreadyRegistered":"Votre clef est déjà enregistrée !",
"yourKeyIsUnregistered":"Votre clef a été supprimée",
"yourKeyIsVerified":"Votre clef est vérifiée",
"yourNewTotpKey":"Votre nouvelle clef TOTP. Testez-la et entrez le code",

View File

@ -108,8 +108,8 @@
"changePwd":"Cambia la tua password",
"checkLastLogins":"Controllare i miei ultimi accessi",
"checkUser":"Controlla il profilo SSO dell'utente",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Scegli il tuo secondo fattore",
"chooseApp":"Scegli un'applicazione alla quale ti è consentito l'accesso",
"clickHere":"Per favore clicka qui",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"Vi é stato inviato un messaggio via mail",
"maintenanceMode":"Questa applicazione è in manutenzione, prova a connetterti più tardi",
"maxNumberof2FDevicesReached":"Raggiunto il numero massimo di dispositivi 2F !!!",
"maxNumberof2FDevicesReached":"Raggiunto il numero massimo di dispositivi 2F !",
"missingCode":"Manca il codice",
"name":"Nome",
"newMessages":"Nuovo(i) messaggio(i)",
@ -251,7 +251,7 @@
"yourIdentity":"Identità",
"yourIdentityIs":"La tua identità é",
"yourKeyIsRegistered":"La vostra chiave è registrata",
"yourKeyIsAlreadyRegistered":"La tua chiave è GIÀ registrata !!!",
"yourKeyIsAlreadyRegistered":"La tua chiave è GIÀ registrata !",
"yourKeyIsUnregistered":"La vostra chiave è stata rimossa",
"yourKeyIsVerified":"La tua chiave é stata testata con successo",
"yourNewTotpKey":"La tua nuova chiave TOTP, per favore provala e inserisci il codice",

View File

@ -108,8 +108,8 @@
"changePwd":"Change your password",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Change your password",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Change your password",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"Please click here",
@ -163,7 +163,7 @@
"mail":"Mail",
"mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Name",
"newMessages":"New message(s)",
@ -251,7 +251,7 @@
"yourIdentity":"Your identity",
"yourIdentityIs":"Your identity is",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"Thay đổi mật khẩu của bạn",
"checkLastLogins":"Kiểm tra lần đăng nhập cuối cùng của bạn",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Chọn một ứng dụng bạn được phép truy cập vào",
"clickHere":"Vui lòng nhấp vào đây",
@ -163,7 +163,7 @@
"mail":"Thư",
"mailSent2":"Một tin nhắn đã được gửi đến địa chỉ thư của bạn.",
"maintenanceMode":"Ứng dụng này đang trong quá trình bảo trì, hãy thử kết nối sau",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"Tên",
"newMessages":"(Các) tin nhắn mới",
@ -251,7 +251,7 @@
"yourIdentity":"Nhận dạng của bạn",
"yourIdentityIs":"Nhận dạng của bạn là",
"yourKeyIsRegistered":"Khóa của bạn đã được đăng ký",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Khóa của bạn đã bị xóa",
"yourKeyIsVerified":"Chìa khóa của bạn đã được kiểm tra thành công",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -108,8 +108,8 @@
"changePwd":"修改您的密码",
"checkLastLogins":"Check my last logins",
"checkUser":"Check user SSO profile",
"checkUserMerged":"Check user SSO profile. Real and Spoofed SSO groups are merged!!!",
"checkUserComputeSession":"Computed session data!!!",
"checkUserMerged":"Check user SSO profile. Some Real and Spoofed SSO groups are merged!",
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"clickHere":"请点击这里",
@ -163,7 +163,7 @@
"mail":"邮件",
"mailSent2":"已经发送一封邮件到您的邮箱",
"maintenanceMode":"程序维护中,请稍后再尝试连接。",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!!!",
"maxNumberof2FDevicesReached":"Maximum number of 2F devices reached!",
"missingCode":"Code is missing",
"name":"名字",
"newMessages":"新消息",
@ -251,7 +251,7 @@
"yourIdentity":"您的标识",
"yourIdentityIs":"您的身份是",
"yourKeyIsRegistered":"Your key is registered",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered !!!",
"yourKeyIsAlreadyRegistered":"Your key is ALREADY registered!",
"yourKeyIsUnregistered":"Your key has been unregistered",
"yourKeyIsVerified":"Your key is verified",
"yourNewTotpKey":"Your new TOTP key, please test it and enter the code",

View File

@ -14,7 +14,7 @@ my $json = '{
"text": "This is a test text"
}';
my $json2 = '{
my $jsonbis = '{
"date": "2016-05-31",
"reference": "testref",
"uid": "dwho",
@ -22,12 +22,31 @@ my $json2 = '{
"text": "This is a second test text"
}';
my $json2 = '{
"date": "2016-05-30",
"reference": "testref2",
"uid": "dwho",
"title": "Test2 title",
"text": "This is a second test text"
}';
my $jsonall = '{
"date": "2016-05-30",
"reference": "testrefall",
"uid": "everyone",
"title": "Testall title",
"text": "This is a test text for all users"
}';
my $content = '{"uid":"dwho"}';
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
useSafeJail => 1,
notification => 1,
notificationServer => 1,
notificationWildcard => 'everyone',
notificationStorage => 'File',
notificationStorageOptions => {
dirName => $main::tmpDir
@ -37,21 +56,87 @@ my $client = LLNG::Manager::Test->new( {
);
my $res;
foreach ( $json, $json2, $jsonall ) {
ok(
$res = $client->_post(
'/notifications', IO::String->new($_),
type => 'application/json',
length => length($_)
),
"POST notification $_"
);
ok( $res->[2]->[0] =~ /"result"\s*:\s*1/, 'Notification has been inserted' )
or print STDERR Dumper( $res->[2]->[0] );
count(2);
}
ok(
$res = $client->_post(
'/notifications', IO::String->new($json),
type => 'application/json',
length => length($json)
$res = $client->_get(
'/notifications/dwho', type => 'application/json',
),
'Create notification'
'List notifications for "dwho"'
);
count(1);
ok( $res->[2]->[0] =~ /"result"\s*:\s*/, 'Result found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"reference":"testref"/, 'First notification found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"reference":"testref2"/, 'Second notification found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"reference":"testrefall"/, 'Third notification found (all users)' )
or print STDERR Dumper( $res->[2]->[0] );
count(5);
ok(
$res = $client->_get(
'/notifications/dwho/testref', type => 'application/json',
),
'List notification with reference "testref"'
);
ok( $res->[2]->[0] =~ /"result"\s*:\s*/, 'Result found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"reference"\s*:\s*"testref"/,
'Notification reference found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"title"\s*:\s*"Test title"/, 'Notification title found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"text"\s*:\s*"This is a test text"/,
'Notification text found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"date"\s*:\s*"2016-05-30"/, 'Notification date found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /"uid"\s*:\s*"dwho"/, 'Notification uid found' )
or print STDERR Dumper( $res->[2]->[0] );
count(7);
ok(
$res = $client->_put(
'/notifications', IO::String->new($content),
type => 'application/json',
length => length($content)
),
'Try to delete notification with bad method'
);
ok( $res->[2]->[0] =~ /"error"\s*:\s*"Bad request"/, 'Bad method is refused' );
count(2);
foreach (qw(testrefall testref2)) {
my $user = $_ eq 'testrefall' ? 'everyone' : 'dwho';
ok(
$res = $client->_delete(
"/notifications/$user/$_", type => 'application/json',
),
"Delete notification $_"
);
ok( $res->[2]->[0] =~ /"result"\s*:\s*1/, 'Notification has been deleted' )
or print STDERR Dumper( $res->[2]->[0] );
count(2);
}
ok(
$res = $client->_post(
'/notifications', IO::String->new($json2),
'/notifications', IO::String->new($jsonbis),
type => 'application/json',
length => length($json2)
length => length($jsonbis)
),
'Try to create the same notification twice'
);

View File

@ -0,0 +1,162 @@
use Test::More;
use strict;
use IO::String;
use Data::Dumper;
require 't/test-lib.pm';
require 't/smtp.pm';
use_ok('Lemonldap::NG::Common::FormEncode');
count(1);
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
'sfExtra' => {
'home' => {
'over' => {
mail2fCodeRegex => '\w{4}',
mail2fLogo => 'home.jpg',
},
'rule' => '$uid eq "dwho" or $uid eq "msmith"',
'type' => 'Mail2F'
},
'work' => {
'over' => {
mail2fLogo => 'work.jpg',
mail2fCodeRegex => '\d{8}',
},
'rule' => '$uid eq "dwho" or $uid eq "rtyler"',
'type' => 'Mail2F'
}
},
}
}
);
# Login with rtyler
# -----------------
ok(
my $res = $client->_post(
'/',
IO::String->new('user=rtyler&password=rtyler'),
length => 27,
accept => 'text/html',
),
'Auth query'
);
count(1);
# Only "work" option is available
my ( $host, $url, $query ) =
expectForm( $res, undef, '/work2fcheck', 'token', 'code' );
ok(
$res->[2]->[0] =~
qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code" autocomplete="off" />%,
'Found EXTCODE input'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( mail() =~ m%<b>(\d{8})</b>%, 'Found 2F code in mail' )
or print STDERR Dumper( mail() );
my $code = $1;
count(1);
$query =~ s/code=/code=${code}/;
ok(
$res = $client->_post(
'/work2fcheck',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Post code'
);
count(1);
my $id = expectCookie($res);
$client->logout($id);
clean_sessions();
# Login with dwho
# ---------------
ok(
my $res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23,
accept => 'text/html',
),
'Auth query'
);
count(1);
# Expect choice page
my ( $host, $url, $query ) =
expectForm( $res, undef, '/2fchoice', 'token', 'checkLogins' );
ok(
$res->[2]->[0] =~
qq%<img src="/static/bootstrap/work.jpg" alt="work2F" title="work2F" />%,
'Found work.png'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok(
$res->[2]->[0] =~
qq%<img src="/static/bootstrap/home.jpg" alt="home2F" title="home2F" />%,
'Found home.png'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
$query .= '&sf=home';
ok(
$res = $client->_post(
'/2fchoice',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Post ext2f choice'
);
count(1);
my ( $host, $url, $query ) =
expectForm( $res, undef, '/home2fcheck', 'token', 'code' );
ok(
$res->[2]->[0] =~
qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code" autocomplete="off" />%,
'Found EXTCODE input'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( mail() =~ m%<b>(\w{4})</b>%, 'Found 2F code in mail' )
or print STDERR Dumper( mail() );
my $code = $1;
count(1);
$query =~ s/code=/code=${code}/;
ok(
$res = $client->_post(
'/home2fcheck',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Post code'
);
count(1);
my $id = expectCookie($res);
$client->logout($id);
clean_sessions();
done_testing( count() );

View File

@ -696,8 +696,9 @@ sub _get {
$args{remote_user} ? ( 'REMOTE_USER' => $args{remote_user} )
: ()
),
'REQUEST_METHOD' => $args{method} || 'GET',
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
'REQUEST_METHOD' => $args{method}
|| 'GET',
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
( $args{query} ? ( QUERY_STRING => $args{query} ) : () ),
'SCRIPT_NAME' => '',
'SERVER_NAME' => 'auth.example.com',
@ -773,7 +774,7 @@ Call C<_get()> with method set to DELETE.
sub _delete {
my ( $self, $path, %args ) = @_;
$args{method} = 'DELETE';
return $self->_get( $path, %args );
$self->_get( $path, %args );
}
=head4 _put( $path, $body, %args )