Merge branch 'v2.0'

This commit is contained in:
Xavier Guimard 2019-04-05 10:10:40 +02:00
commit 01b5951b73
70 changed files with 1931 additions and 148 deletions

View File

@ -551,6 +551,8 @@ launch_protractor:
# Start e2e tests
# NB: you must have protractor installed (using npm install -g protractor)
# and have run update-webdriver at least once and have a node.js > 4.0
# Install test keys
cp -f e2e-tests/persistent/5efe8af397fc3577e05b483aca964f1b.e2e-test e2e-tests/conf/persistents/5efe8af397fc3577e05b483aca964f1b
@E2E_TESTS=$(E2E_TESTS) TESTWEBSERVERPORT=$(TESTWEBSERVERPORT) protractor e2e-tests/protractor-conf.js
stop_web_server:
@ -599,6 +601,7 @@ install_bin: install_conf_dir
@cp -f\
${SRCHANDLERDIR}/eg/scripts/purgeLocalCache \
${SRCPORTALDIR}/site/cron/purgeCentralCache \
${SRCPORTALDIR}/scripts/llngDeleteSession \
${SRCCOMMONDIR}/scripts/convertConfig \
${SRCCOMMONDIR}/scripts/lmMigrateConfFiles2ini \
${SRCCOMMONDIR}/scripts/rotateOidcKeys \

View File

@ -28,7 +28,7 @@ Before release
Replace https://lemonldap-ng.org/documentation/X.X/parameterlist by
/tmp/prmlist.txt content
$ make documentation
- Update changelog:
@ -56,7 +56,7 @@ For major release
- Go on gitlab and create a new tag: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/tags/new
- Change "latest" symlink in dokuwiki
- Change "latest" symlink in dokuwiki
- Edit scripts/doc.pl in trunk to point on the new documentation path

View File

@ -125,7 +125,7 @@
"default" : "accept"
},
"manager.__DNSDOMAIN__" : {
"(?#Configuration)^/(manager\\.html|$)" : "$uid eq \"dwho\"",
"(?#Configuration)^/(manager\\.html|conf|$)" : "$uid eq \"dwho\"",
"(?#Notifications)/notifications" : "$uid eq \"dwho\" or $uid eq \"rtyler\"",
"(?#Sessions)/sessions" : "$uid eq \"dwho\" or $uid eq \"rtyler\"",
"default" : "$uid eq \"dwho\" or $uid eq \"rtyler\""

View File

@ -765,7 +765,7 @@ lemonldap-ng (1.4.0) stable; urgency=low
* [LEMONLDAP-712] - strange behaviour with session cache
* [LEMONLDAP-386] - use LL::NG::Handler instead of custom perl module in apache config
* [LEMONLDAP-430] - httpSession and updateSession + deleteSessionFromLocalStorage optimization
* [LEMONLDAP-591] - Portal should refresh their configuration cache on expiration
* [LEMONLDAP-591] - Portal should refresh their configuration cache on expiration
* [LEMONLDAP-600] - Rewrite object libs with Moo or Mouse
* [LEMONLDAP-636] - Manage exported variables per UserDB module
* [LEMONLDAP-648] - Build French documentation in Makefile
@ -868,7 +868,7 @@ lemonldap-ng (1.3.0) stable; urgency=low
Common
* [LEMONLDAP-412] - Passwrd policy expiration warning time not friendly
displayed
* [LEMONLDAP-493] - Make LL::NG's rpm spec file more portable
* [LEMONLDAP-493] - Make LL::NG's rpm spec file more portable
* [LEMONLDAP-500] - do not burden config in memory with useless things
* [LEMONLDAP-524] - minimize weight of relaystate in SAML session backend
* [LEMONLDAP-559] - Refine useXForwardedForIP option by setting trusted
@ -900,7 +900,7 @@ lemonldap-ng (1.3.0) stable; urgency=low
session
* [LEMONLDAP-613] - Log applied rule in debug mode
* [LEMONLDAP-615] - Add AuthGoogle module
* [LEMONLDAP-617] - [SAML] Allow to skip the IDP selection
* [LEMONLDAP-617] - [SAML] Allow to skip the IDP selection
* [LEMONLDAP-621] - Config storage in JSON file
* [LEMONLDAP-623] - WebID authentication and user DB modules
* [LEMONLDAP-632] - Rename liblemonldap-ng-conf-perl to
@ -1065,7 +1065,7 @@ lemonldap-ng (1.2.0) stable; urgency=low
* [LEMONLDAP-371] - custom function declaration doesn't work through
management UI
* [LEMONLDAP-373] - Field values lost in manager
* [LEMONLDAP-375] - empty query string in redirect url
* [LEMONLDAP-375] - empty query string in redirect url
* [LEMONLDAP-376] - wrong authentication mode stored in session with
authMulti when SSLRequire set to 0
* [LEMONLDAP-380] - Mail reset session not destroyed when password is
@ -1105,7 +1105,7 @@ lemonldap-ng (1.2.0) stable; urgency=low
* [LEMONLDAP-446] - Server error when a password mail reset session is
unavailable and the token is passed to mail.pl
* [LEMONLDAP-447] - Bad identifier in grantSession logs
* [LEMONLDAP-448] - defined(%hash) is deprecated
* [LEMONLDAP-448] - defined(%hash) is deprecated
* [LEMONLDAP-450] - SAML Authn not working with binding HTTP Redirect
* [LEMONLDAP-454] - Replace $ip with client IP in forging HTTP headers
doesn't work
@ -1280,14 +1280,14 @@ lemonldap-ng (1.1.0) stable; urgency=low
* [LEMONLDAP-348] - Possibility to access menu tab with an URL
lemonldap-ng (1.0.6) stable; urgency=low
* [LEMONLDAP-297] - LDAP attributes are not explicitely requested
* [LEMONLDAP-298] - Multi option with # not accepted in Manager
* [LEMONLDAP-304] - Cannot use spaces between values of Multi
authentication
parameter
* [LEMONLDAP-305] - Parameters are not overriden in the first Multi module
* [LEMONLDAP-307] - Base64 encoded IDs can contain more than one "/", but
* [LEMONLDAP-307] - Base64 encoded IDs can contain more than one "/", but
only the first is escaped
lemonldap-ng (1.0.5) stable; urgency=low
@ -1983,7 +1983,7 @@ lemonldap-ng (0.7b11) unstable; urgency=low
* New features:
- Cross Domain Authentication
- SOAP configuration access
- READMEs and documentation update
- READMEs and documentation update
-- Xavier Guimard <x.guimard@free.fr> Tue, 27 Feb 2007 15:01:09 +0100

View File

@ -8,7 +8,7 @@ respawn
pre-start script
[ -x /usr/sbin/llng-fastcgi-server ] || { stop; exit 0; }
end script
end script
exec mkdir /var/run/llng-fastcgi-server; chown www-data:www-data /var/run/llng-fastcgi-server && /usr/sbin/llng-fastcgi-server -u www-data -g www-data -s /var/run/llng-fastcgi-server/llng-fastcgi.sock -p /var/run/llng-fastcgi-server/llng-fastcgi-server.pid

2
debian/tests/runner vendored
View File

@ -30,7 +30,7 @@ for LLLIB in $LIST; do
if [ -f "$SKIPLIST" ]; then
grep -v '^ *#' "$SKIPLIST" |grep -v '^ *$' > "$SKIPTMP"
fi
for T in $(run-parts --list --regex '(^[a-z0-9.]+$)' ${TESTDIR} | \
grep -v -F -f "$SKIPTMP") ; do
if echo "$T" | grep -q '\.t$'

View File

@ -147,7 +147,7 @@
"default" : "accept"
},
"manager.example.com": {
"(?#Configuration)^/(manager\\.html|$)": "$uid eq \"dwho\"",
"(?#Configuration)^/(manager\\.html|conf|$)": "$uid eq \"dwho\"",
"(?#Notifications)^/notifications": "$uid eq \"dwho\" or $uid eq \"rtyler\"",
"(?#Sessions)^/sessions": "$uid eq \"dwho\" or $uid eq \"rtyler\"",
"default": "$uid eq \"dwho\" or $uid eq \"rtyler\""

View File

@ -1 +1 @@
{"_session_kind":"Persistent","_loginHistory":{"successLogin":[{"ipAddr":"127.0.0.1","_utime":1548016089}]},"_2fDevices":"[{\"type\":\"U2F\",\"_keyHandle\":\"CTPeZD3aFrNOY4yVWH4o1MKSn2aLH2OwLOWTtrQSlt_6LtUyki5nzrwBEeuxj7PRSujFZQDaMTfrEb-gr22Qfg\",\"_userKey\":\"BI1MGzKj1C9mMV8PwrYMggQXlItLBNSB19rNnFgUpLMBjAkMW8w3Sqg8s_hUGbdfdWX99duquzIzRLUtRUEvJLo\",\"name\":\"MyU2FKey\",\"epoch\":1548016193},{\"epoch\":1548016213,\"name\":\"MyYubikey\",\"_yubikey\":\"cccccchehfff\",\"type\":\"UBK\"},{\"epoch\":1548018950,\"name\":\"MyU2FKeyBlue\",\"_userKey\":\"BDEa8pQfV9agdvsX63bcwceRTXR_QvDdm5hQ5ZKQUaH4HlOi8ab4fQfl9CIACALWYm0jQcpfaRAcACiSCdwGrnI\",\"_keyHandle\":\"ZD_G6EfDv4FzttWS9RCS80SaSlRTXgtJU9r-1gInsQ4Jj1555r7nnrYhIvRfE4CTyH7NyGrt9fMnMMgByAx97Q\",\"type\":\"U2F\"}]","_session_id":"5efe8af397fc3577e05b483aca964f1b","_session_uid":"dwho","_updateTime":"20190120221550","_utime":1548016089}
{"_session_kind":"Persistent","_loginHistory":{"successLogin":[{"ipAddr":"127.0.0.1","_utime":1548016089}]},"_2fDevices":"[]","_session_id":"5efe8af397fc3577e05b483aca964f1b","_session_uid":"dwho","_updateTime":"20190120221550","_utime":1548016089}

View File

@ -0,0 +1 @@
{"_session_kind":"Persistent","_loginHistory":{"successLogin":[{"ipAddr":"127.0.0.1","_utime":1548016089}]},"_2fDevices":"[{\"type\":\"U2F\",\"_keyHandle\":\"CTPeZD3aFrNOY4yVWH4o1MKSn2aLH2OwLOWTtrQSlt_6LtUyki5nzrwBEeuxj7PRSujFZQDaMTfrEb-gr22Qfg\",\"_userKey\":\"BI1MGzKj1C9mMV8PwrYMggQXlItLBNSB19rNnFgUpLMBjAkMW8w3Sqg8s_hUGbdfdWX99duquzIzRLUtRUEvJLo\",\"name\":\"MyU2FKey\",\"epoch\":1548016193},{\"epoch\":1548016213,\"name\":\"MyYubikey\",\"_yubikey\":\"cccccchehfff\",\"type\":\"UBK\"},{\"epoch\":1548018950,\"name\":\"MyU2FKeyBlue\",\"_userKey\":\"BDEa8pQfV9agdvsX63bcwceRTXR_QvDdm5hQ5ZKQUaH4HlOi8ab4fQfl9CIACALWYm0jQcpfaRAcACiSCdwGrnI\",\"_keyHandle\":\"ZD_G6EfDv4FzttWS9RCS80SaSlRTXgtJU9r-1gInsQ4Jj1555r7nnrYhIvRfE4CTyH7NyGrt9fMnMMgByAx97Q\",\"type\":\"U2F\"}]","_session_id":"5efe8af397fc3577e05b483aca964f1b","_session_uid":"dwho","_updateTime":"20190120221550","_utime":1548016089}

View File

@ -60,7 +60,7 @@ describe('00 Lemonldap::NG', function() {
it('should authenticate with history', function() {
expect(browser.driver.findElement(by.css('[trspan="back2Portal"]')).getText()).toEqual('Retourner au portail');
browser.driver.findElement(by.css('[trspan="back2Portal"]')).click();
// Failed login attempt
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('ohwd');
@ -68,7 +68,7 @@ describe('00 Lemonldap::NG', function() {
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
expect(browser.driver.findElement(by.css('[trmsg="5"]')).getText()).toEqual('Mot de passe ou identifiant incorrect');
browser.driver.findElement(by.css('[trspan="goToPortal"]')).click();
// Login attempt
browser.driver.findElement(by.xpath("//input[@name='user']")).sendKeys('dwho');
browser.driver.findElement(by.xpath("//input[@name='password']")).sendKeys('dwho');
@ -111,4 +111,4 @@ describe('00 Lemonldap::NG', function() {
browser.driver.findElement(by.xpath("//button[@type='submit']")).click();
});
});
});
});

View File

@ -64,7 +64,7 @@ describe('10 Lemonldap::NG', function() {
expect(links[2].getText()).toEqual('Gestionnaire 2ndFA');
expect(links[3].getText()).toEqual('Aller au portail');
expect(browser.driver.findElement(by.css('[trspan="yourNewTotpKey"]')).getText()).toEqual('Votre nouvelle clef TOTP. Testez-la et entrez le code');
// Submit an empty form
browser.driver.findElement(by.id('verify')).click();
expect(browser.driver.findElement(by.css('[trspan="yourNewTotpKey"]')).getText()).toEqual('Remplissez le formulaire');

View File

@ -8,7 +8,7 @@ respawn
pre-start script
[ -x /usr/sbin/llng-fastcgi-server ] || { stop; exit 0; }
end script
end script
exec mkdir __FASTCGISOCKDIR__; chown __USER__:__GROUP__ __FASTCGISOCKDIR__ && /usr/sbin/llng-fastcgi-server -u __USER__ -g __GROUP__ -s __FASTCGISOCKDIR__/llng-fastcgi.sock -p __FASTCGISOCKDIR__/llng-fastcgi-server.pid

View File

@ -48,7 +48,7 @@ our %EXPORT_TAGS = (
APPLYSECTION
NO
$hashParameters
@sessionTypes
@sessionTypes
)
]
);

View File

@ -347,7 +347,7 @@ __DATA__
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
</AttributeAuthorityDescriptor>
</TMPL_UNLESS>
<Organization>
<OrganizationName xml:lang="en"><TMPL_VAR NAME="samlOrganizationName"></OrganizationName>
<OrganizationDisplayName xml:lang="en"><TMPL_VAR NAME="samlOrganizationDisplayName"></OrganizationDisplayName>

View File

@ -481,7 +481,7 @@ Syslog facility. If empty, STDERR will be used for logging
L<http://lemonldap-ng.org/>, L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Handler>,
L<Plack>, L<PSGI>, L<Lemonldap::NG::Common::PSGI::Router>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
=head1 AUTHORS

View File

@ -187,7 +187,7 @@ Example:
# Set headers
$req->respHeaders( "Location" => "http://x.y.z/", Etag => "XYZ", );
# Add header
$req->respHeaders->{"X-Key"} = "Value";
$req->respHeaders->{"X-Key"} = "Value";
=head2 set_param( $key, $value )
@ -220,7 +220,7 @@ contains "application/json" or "text/json").
L<http://lemonldap-ng.org/>, L<Lemonldap::NG::Common::PSGI>,
L<Lemonldap::NG::Hander::PSGI>, L<Plack::Request>,
L<Lemonldap::NG::Portal::Main::Constants>,
L<Lemonldap::NG::Portal::Main::Constants>,
=head1 AUTHORS

View File

@ -88,7 +88,7 @@ sub genRoute {
$routes->{$word} = $dest;
}
else {
die "Type $t unauthorizated in routes";
die "Type $t unauthorized in routes";
}
}
elsif ( $self->can($dest) ) {
@ -322,7 +322,7 @@ bookId parameter will be stored in $req->params('bookId');
$self->addRoute( books => { ':bookId' => { pages => { ':pageId' => 'page' } } }, ['GET'] );
=item to manage simultaneously the 2 previous examples
=item to manage simultaneously the 2 previous examples
$self->addRoute( books => { ':bookId' => { pages => { ':pageId' => 'page' } } }, ['GET'] )
->addRoute( books => { ':bookId' => { '*' => 'book' } }, ['GET'] );
@ -349,7 +349,7 @@ logLevel, staticPrefix, templateDir, links, syslog).
L<http://lemonldap-ng.org/>, L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Handler>,
L<Plack>, L<PSGI>, L<Lemonldap::NG::Common::PSGI>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
=head1 AUTHORS

View File

@ -112,7 +112,7 @@ Returns a list of groups to which user belongs.
L<http://lemonldap-ng.org/>, L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Handler>,
L<Plack>, L<PSGI>, L<Lemonldap::NG::Common::PSGI::Router>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
=head1 AUTHORS

View File

@ -119,7 +119,7 @@ Returns a list of groups to which user belongs.
L<http://lemonldap-ng.org/>, L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Handler>,
L<Plack>, L<PSGI>, L<Lemonldap::NG::Common::PSGI::Router>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
L<Lemonldap::NG::Common::PSGI::Request>, L<HTML::Template>,
=head1 AUTHORS

View File

@ -26,7 +26,7 @@
+-> if protected:
Handler::PSGI::Base::_authAndTrace()
_Common::PSGI::run()_ returns a subroutine
## HTTP responses

View File

@ -88,8 +88,10 @@ sub init {
$self->csp(
"default-src 'self' $portal;frame-ancestors 'none';form-action 'self';"
);
$self->brw( $self->{viewerAllowBrowser} || $conf->{viewerAllowBrowser} );
$self->dif( $self->{viewerAllowDiff} || $conf->{viewerAllowDiff} );
$self->brw( $self->{viewerAllowBrowser}
|| $conf->{viewerAllowBrowser}
|| 0 );
$self->dif( $self->{viewerAllowDiff} || $conf->{viewerAllowDiff} || 0 );
$self->defaultRoute( $working[0]->defaultRoute );
# Find out more glyphicones at https://www.w3schools.com/icons/bootstrap_icons_glyphicons.asp
@ -143,8 +145,9 @@ sub tplParams {
sub javascript {
my ($self) = @_;
return
'var formPrefix=staticPrefix+"forms/";var confPrefix=scriptname+"confs/";var viewPrefix=scriptname+"view/";'
. 'var allowDiff=' . $self->dif . ';'
'var formPrefix=staticPrefix+"forms/";var confPrefix=scriptname+"confs/";var viewPrefix=scriptname+"view/";'
. 'var allowDiff='
. $self->dif . ';'
. ( $self->links ? 'var links=' . to_json( $self->links ) . ';' : '' )
. (
$self->menuLinks

View File

@ -2486,7 +2486,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'requireToken' => {
'default' => 1,
'type' => 'bool'
'type' => 'boolOrExpr'
},
'rest2fActivation' => {
'default' => 0,

View File

@ -339,7 +339,7 @@ our %EXPORT_TAGS = (
APPLYSECTION
NO
\$hashParameters
\@sessionTypes
\@sessionTypes
)
]
);
@ -735,7 +735,7 @@ some words for other developpers
if test is not defined for this type or if test must
be more restrictive, set here a regular expression or a subroutine. Arguments
passed to subroutine are (keyValue, newConf, currentKey). It returns 2
arguments: a boolean result and a message (if non empty message will be
arguments: a boolean result and a message (if non empty message will be
displayed as warning or error depending of result);
=item msgFail (optional):

View File

@ -629,7 +629,7 @@ sub attributes {
},
requireToken => {
default => 1,
type => 'bool',
type => 'boolOrExpr',
documentation => 'Enable token for forms',
},
tokenUseGlobalStorage => {

View File

@ -162,7 +162,7 @@ sub zeroConf {
},
"manager.$domain" => {
'default' => '$uid eq "dwho" or $uid eq "rtyler"',
'(?#Configuration)^/(manager\.html|$)' => '$uid eq "dwho"',
'(?#Configuration)^/(manager\.html|conf|$)' => '$uid eq "dwho"',
'(?#Sessions)/sessions' => '$uid eq "dwho" or $uid eq "rtyler"',
'(?#Notifications)/notifications' =>
'$uid eq "dwho" or $uid eq "rtyler"',

View File

@ -11,7 +11,7 @@ use feature 'state';
extends 'Lemonldap::NG::Manager::Conf';
our $VERSION = '2.0.3';
our $VERSION = '2.1.0';
#############################
# I. INITIALIZATION METHODS #

View File

@ -5241,7 +5241,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
if (tooltip) {
tooltip.remove();
tooltip = null;
if (adjustmentTimeout) {
$timeout.cancel(adjustmentTimeout);
@ -5249,7 +5249,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
}
openedTooltips.remove(ttScope);
if (tooltipLinkedScope) {
tooltipLinkedScope.$destroy();
tooltipLinkedScope = null;
@ -7773,4 +7773,4 @@ angular.module('ui.bootstrap.position').run(function() {!angular.$$csp().noInlin
angular.module('ui.bootstrap.datepickerPopup').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibDatepickerpopupCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'); angular.$$uibDatepickerpopupCss = true; });
angular.module('ui.bootstrap.tooltip').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTooltipCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'); angular.$$uibTooltipCss = true; });
angular.module('ui.bootstrap.timepicker').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTimepickerCss && angular.element(document).find('head').prepend('<style type="text/css">.uib-time input{width:50px;}</style>'); angular.$$uibTimepickerCss = true; });
angular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });
angular.module('ui.bootstrap.typeahead').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uibTypeaheadCss && angular.element(document).find('head').prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'); angular.$$uibTypeaheadCss = true; });

View File

@ -383,12 +383,12 @@
if (element.prop('tagName').toLowerCase() === 'table') {
scope.$emptyElm = angular.element($window.document.createElement('tr'));
$trElm = element.find('tr');
//If we can find a tr, then we can use its td children as the empty element colspan.
if ($trElm.length > 0) {
emptyElmColspan = angular.element($trElm).children().length;
} else {
//If not, by setting a huge colspan we make sure it takes full width.
//TODO(jcarter): Check for negative side effects.
emptyElmColspan = 1000000;
@ -1512,7 +1512,7 @@
/**
* Get the event object for touches.
*
*
* @param {MouseEvent|TouchEvent} e MouseEvent or TouchEvent that kicked off dragX method.
* @return {MouseEvent|TouchEvent} Object returned as original event object.
*/
@ -1530,7 +1530,7 @@
/**
* Generate object used to store data about node being moved.
*
*
* {angular.$scope} node Scope of the node that is being moved.
*/
dragInfo: function (node) {
@ -1760,19 +1760,19 @@
pos.nowX = pageX;
pos.nowY = pageY;
//Distance mouse moved between events.
//Distance mouse moved between events.
pos.distX = pos.nowX - pos.lastX;
pos.distY = pos.nowY - pos.lastY;
//Direction mouse was moving.
//Direction mouse was moving.
pos.lastDirX = pos.dirX;
pos.lastDirY = pos.dirY;
//Direction mouse is now moving (on both axis).
//Direction mouse is now moving (on both axis).
pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1;
pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1;
//Axis mouse is now moving on.
//Axis mouse is now moving on.
newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0;
//Do nothing on first move.
@ -1782,7 +1782,7 @@
return;
}
//Calc distance moved on this axis (and direction).
//Calc distance moved on this axis (and direction).
if (pos.dirAx !== newAx) {
pos.distAxX = 0;
pos.distAxY = 0;
@ -1853,4 +1853,4 @@
return res;
}
})();
})();

View File

@ -6,7 +6,7 @@
<span ng-if="!currentCfg.next" trspan="currentConfiguration"></span>
<span ng-if="currentCfg.next" trspan="loadedConfiguration"></span>
<i ng-if="currentCfg.prev">(<a trspan="diffWithPrevious" target="_blank" href="{{scriptname}}/diff.html#!/{{currentCfg.cfgNum}}" role="link"></a>)</i>
</h3>
</TMPL_IF>
</div>

View File

@ -5,7 +5,7 @@
<span ng-if="!currentCfg.next" trspan="currentConfiguration"></span>
<span ng-if="currentCfg.next" trspan="loadedConfiguration"></span>
<i ng-if="currentCfg.prev && allowDiff">(<a trspan="diffWithPrevious" target="_blank" href="{{scriptname}}/viewDiff.html#!/{{currentCfg.cfgNum}}" role="link"></a>)</i>
</h3>
</div>
<table class="table table-striped">

File diff suppressed because one or more lines are too long

View File

@ -37,10 +37,10 @@
</form>
</div>
</div>
</div>
</div>
<!-- Tree -->
<div class="text-center"><p class="badge">{{total}} <span trspan="session_s"></span></p></div>
<div class="region region-sidebar-first">
<section id="block-superfish-1" class="block block-superfish clearfix">
@ -58,7 +58,7 @@
</aside>
<!-- Right(main) div -->
<div id="right" class="col-lg-8 col-md-8 col-sm-7 col-xs-12 scrollable" ng-class="{'hidden-xs':showT&&!showM}">
<div id="right" class="col-lg-8 col-md-8 col-sm-7 col-xs-12 scrollable" ng-class="{'hidden-xs':showT&&!showM}">
<div class="panel panel-default" ng-hide="currentSession===null">
<div class="panel-heading">
<h1 class="panel-title text-center">{{translate("sessionTitle")}} {{currentSession.id}}</h1>

View File

@ -22,7 +22,7 @@
<div class="navbar-collapse" ng-class="{'collapse':!showM}" id="formmenu">
<ul class="nav navbar-nav">
<li><a class="link" ng-click="home()"><i class="glyphicon glyphicon-home"></i></a></li>
<TMPL_IF NAME="ALLOWBROWSER">
<li uib-dropdown>
<a id="navmenu" name="menu" uib-dropdown-toggle data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><i class="glyphicon glyphicon-cog"></i> {{translate('browse')}} <span class="caret"></span></a>
@ -45,7 +45,7 @@
</li>
<li>
<i class="glyphicon glyphicon-lock"></i>
<u>{{translate('readOnlyMode')}}</u>
<u>{{translate('readOnlyMode')}}</u>
</li>
</ul>
</div>
@ -58,7 +58,7 @@
<div class="panel-body">
<iframe id="helpframe" width="100%" height="100%" ng-src="{{translate('/doc/')+'pages/documentation/current/'+helpUrl}}" frameborder="0"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -143,6 +143,7 @@ MANIFEST This list of files
META.json
META.yml
README
scripts/llngDeleteSession
site/coffee/2fregistration.coffee
site/coffee/autoRenew.coffee
site/coffee/confirm.coffee

View File

@ -61,6 +61,9 @@ sub authenticate {
"Unable to refresh entry for " . $self->p->{user} );
}
$req->data->{noerror} = 1;
$self->setSecurity($req);
# Security: never create session here
return $res || PE_DONE;
}

View File

@ -34,16 +34,31 @@ has authnLevel => (
has captcha => ( is => 'rw' );
has ott => ( is => 'rw' );
has ottRule => ( is => 'rw', default => sub { 1 } );
# INITIALIZATION
sub init {
if ( $_[0]->{conf}->{captcha_login_enabled} ) {
$_[0]->captcha( $_[0]->p->loadModule('::Lib::Captcha') ) or return 0;
my ($self) = @_;
my $hd = $self->p->HANDLER;
# Parse OTT activation rule
$self->logger->debug(
"OTT activation rule -> " . $self->conf->{requireToken} );
my $rule =
$hd->buildSub( $hd->substitute( $self->conf->{requireToken} ) );
unless ($rule) {
$self->error( "Bad OTT activation rule -> " . $hd->tsv->{jail}->error );
return 0;
}
elsif ( $_[0]->{conf}->{requireToken} ) {
$_[0]->ott( $_[0]->p->loadModule('::Lib::OneTimeToken') ) or return 0;
$_[0]->ott->timeout( $_[0]->conf->{formTimeout} );
$self->{ottRule} = $rule;
if ( $self->{conf}->{captcha_login_enabled} ) {
$self->captcha( $self->p->loadModule('::Lib::Captcha') ) or return 0;
}
else {
$self->ott( $self->p->loadModule('::Lib::OneTimeToken') ) or return 0;
$self->ott->timeout( $self->conf->{formTimeout} );
}
return 1;
}
@ -96,13 +111,14 @@ sub extractFormInfo {
}
# Security: check for captcha or token
if ( $self->captcha or $self->ott ) {
if ( $self->captcha or $self->ottRule->( $req, $req->env ) ) {
my $token;
unless ( $token = $req->param('token') ) {
$self->userLogger->error('Authentication tried without token');
$self->ott->setToken($req);
return PE_NOTOKEN;
}
if ( $self->captcha ) {
my $code = $req->param('captcha');
unless ($code) {
@ -117,7 +133,7 @@ sub extractFormInfo {
}
$self->logger->debug("Captcha code verified");
}
elsif ( $self->ott ) {
elsif ( $self->ottRule->( $req, $req->env ) ) {
unless ( $req->data->{tokenVerified}
or $self->ott->getToken($token) )
{
@ -169,7 +185,7 @@ sub setSecurity {
}
# Else get token
elsif ( $self->ott ) {
elsif ( $self->ottRule->( $req, $req->env ) ) {
$self->ott->setToken($req);
}
}

View File

@ -363,7 +363,7 @@ sub logout {
my $session_id = $req->{sessionInfo}->{_session_id} || $req->{id};
# Delete linked CAS sessions
$self->deleteCasSecondarySessions($session_id);
$self->deleteCasSecondarySessions($session_id) if ($session_id);
return PE_OK;
}

View File

@ -198,8 +198,8 @@ sub run {
"Override $_ OIDC param by value present in request parameter"
);
$oidc_request->{$_} = $request->{$_};
$self->p->setHiddenFormValue( $req, $_, $request->{$_},
'' );
$self->p->setHiddenFormValue( $req, $_, $request->{$_}, '',
0 );
}
}
@ -855,7 +855,8 @@ sub run {
$self->logger->debug( "OIDC request parameter $param: "
. $oidc_request->{$param} );
$self->p->setHiddenFormValue( $req, $param,
$oidc_request->{$param}, '' );
$oidc_request->{$param},
'', 0 );
}
}

View File

@ -585,7 +585,7 @@ sub run {
$self->logger->debug(
"NameID Content is " . $login->nameIdentifier->content );
# Push mandatory attributes
# Push attributes
my @attributes;
foreach (
@ -605,20 +605,21 @@ sub run {
# Name is required
next unless $name;
# Do not send attribute if not mandatory
unless ($mandatory) {
$self->logger->debug(
"SAML2 attribute $name is not mandatory");
next;
}
# Error if corresponding attribute is not in user session
my $value = $req->{sessionInfo}->{$_};
unless ( defined $value ) {
$self->logger->warn(
"Session key $_ is required to set SAML $name attribute"
);
return PE_SAML_SSO_ERROR;
if ($mandatory) {
$self->logger->error(
"Session key $_ is required to set SAML $name attribute"
);
return PE_SAML_SSO_ERROR;
}
else {
$self->logger->debug(
"SAML2 attribute $name has no value but is not mandatory, skip it"
);
next;
}
}
$self->logger->debug(
@ -1738,13 +1739,77 @@ sub sloServer {
elsif ($response) {
# No SLO response should be here
# else it means SSO session was not closed: launching it
$self->logger->debug(
"SLO response found on an active SSO session, ignoring it");
$req->data->{samlSLOCalled} = 1;
return $self->p->do( $req,
[ @{ $self->p->beforeLogout }, 'deleteSession' ] );
# Process logout response
my $result = $self->processLogoutResponseMsg( $logout, $response );
unless ($result) {
$self->logger->error("Fail to process logout response");
$self->imgnok($req);
}
$self->logger->debug("Logout response is valid");
# Check Destination
$self->imgnok($req)
unless ( $self->checkDestination( $logout->response, $url ) );
# Get SP entityID
my $sp = $logout->remote_providerID();
$self->logger->debug("Found entityID $sp in SAML message");
# SP conf key
my $spConfKey = $self->spList->{$sp}->{confKey};
unless ($spConfKey) {
$self->logger->error("$sp do not match any SP in configuration");
$self->imgnok($req);
}
$self->logger->debug("$sp match $spConfKey SP in configuration");
# Do we check signature?
my $checkSLOMessageSignature =
$self->conf->{samlSPMetaDataOptions}->{$spConfKey}
->{samlSPMetaDataOptionsCheckSLOMessageSignature};
if ($checkSLOMessageSignature) {
unless ( $self->checkSignatureStatus($logout) ) {
$self->logger->error("Signature is not valid");
$self->imgnok($req);
}
else {
$self->logger->debug("Signature is valid");
}
}
else {
$self->logger->debug("Message signature will not be checked");
}
# Store success status for this SLO request
if ($relaystate) {
my $sloStatusSessionInfos = $self->getSamlSession($relaystate);
if ($sloStatusSessionInfos) {
$sloStatusSessionInfos->update( { $spConfKey => 1 } );
$self->logger->debug(
"Store SLO status for $spConfKey in session $relaystate");
}
else {
$self->logger->warn(
"Unable to store SLO status for $spConfKey in session $relaystate"
);
}
}
else {
$self->logger->warn(
"Unable to store SLO status for $spConfKey because there is no RelayState"
);
}
# SLO response is OK
$self->logger->debug("Display OK status for SLO on $spConfKey");
$self->imgok($req);
}
else {

View File

@ -2385,21 +2385,12 @@ sub samldate2timestamp {
sub sendLogoutResponseToServiceProvider {
my ( $self, $req, $logout, $method ) = @_;
my $httpmethod = $self->getFirstHttpMethod(
$self->lassoServer,
$logout->remote_providerID,
Lasso::Constants::MD_PROTOCOL_TYPE_SINGLE_LOGOUT
);
if ( $httpmethod == Lasso::Constants::HTTP_METHOD_NONE ) {
$self->logger->warn( "Provider "
. $logout->remote_providerID
. " has no SingleLogoutService in metadata, staying on portal" );
return $self->p->do( $req, [] );
}
# Logout response
unless ( $self->buildLogoutResponseMsg($logout) ) {
return $self->p->sendError( $req, "Unable to build SLO response", 500 );
$self->logger->warn( "Could not build a logout response for provider "
. $logout->remote_providerID
. ", staying on portal" );
return $self->p->do( $req, [] );
}
# Send response depending on request method
@ -3432,8 +3423,8 @@ Send logout request to a provider
Send logout response issue from a logout request to all other
providers. If information have to be displayed to users, such as
iframe to send HTTP-Redirect or HTTP-POST logout request, then
$self->{_info} will be updated.
iframe to send HTTP-Redirect or HTTP-POST logout request, then
$self->{_info} will be updated.
=head2 checkSignatureStatus

View File

@ -5,7 +5,6 @@ package Lemonldap::NG::Portal::Main::Plugin;
use strict;
use Mouse;
use HTML::Template;
use Data::Dumper;
our $VERSION = '2.1.0';

View File

@ -636,7 +636,7 @@ sub setHiddenFormValue {
if ( defined $val or !( $val & ~$val ) ) {
$key = $prefix . $key;
#$val =~ s/\+/%2B/g;
$val = encode_base64($val) if $base64;
$req->{portalHiddenFormValues}->{$key} = $val;
$self->logger->debug("Store $val in hidden key $key");
}
@ -917,7 +917,6 @@ sub tplParams {
SKIN => $self->getSkin($req),
PORTAL_URL => $self->conf->{portal},
SKIN_PATH => $portalPath . "skins",
ANTIFRAME => $self->conf->{portalAntiFrame},
SKIN_BG => $self->conf->{portalSkinBackground},
( $self->customParameters ? ( %{ $self->customParameters } ) : () ),
%templateParams

View File

@ -158,7 +158,7 @@ L<Lemonldap::NG::Portal> second factor plugins.
# If self registration is enabled and "activation" is set to "enabled",
# replace the rule to detect if user has registered a device key.
# The rule must be like this :
# By example :
# By example :
$self->conf->{u2fActivation} = '$_2fDevices =~ /"type":\s*"U2F"/s'
# Optionally, the rule can be : '$_2fDevices and $_2fDevices =~ /"type":\s*"U2F"/s'
# to avoid warning due to undef variable

View File

@ -9,7 +9,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_MALFORMEDUSER
);
our $VERSION = '2.0.3';
our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';
@ -165,8 +165,10 @@ sub check {
# Check if user is allowed to access submitted URL and compute headers
if ( $url and %$attrs ) {
# Check url format
$url = $self->_urlFormat($url);
# User is allowed ?
$url = 'http://' . $url unless ( $url =~ m#^https?://[^/]*.*# );
$auth = $self->_authorization( $req, $url );
$self->logger->debug(
"checkUser requested for user: $req->{user} and URL: $url");
@ -276,6 +278,19 @@ sub display {
return $self->p->sendHtml( $req, 'checkuser', params => $params, );
}
sub _urlFormat {
my ( $self, $url ) = @_;
$url = 'http://' . $url unless ( $url =~ m#^https?://[^/]*.*# );
my ( $proto, $vhost, $appuri ) = $url =~ m#^(https?://)([^/]*)(.*)#;
my ( $port ) = $vhost =~ m#^.+(:\d+)$#;
$port ||= '';
$vhost =~ s/:\d+$//;
$vhost .= $self->conf->{domain} unless ( $vhost =~ /\./ );
$appuri ||= '/';
return "$proto$vhost$port$appuri";
}
sub _userDatas {
my ( $self, $req ) = @_;
@ -313,9 +328,8 @@ sub _authorization {
my ( $self, $req, $uri ) = @_;
my ( $vhost, $appuri ) = $uri =~ m#^https?://([^/]*)(.*)#;
my $exist = 0;
$vhost =~ s/:\d+$//;
$appuri ||= '/';
$vhost =~ s/:\d+$//;
foreach my $vh ( keys %{ $self->conf->{locationRules} } ) {
if ( $vh eq $vhost ) {
$exist = 1;
@ -333,7 +347,8 @@ sub _authorization {
sub _headers {
my ( $self, $req, $uri ) = @_;
my ( $vhost, $appuri ) = $uri =~ m#^https?://([^/]*)(.*)#;
my ( $vhost ) = $uri =~ m#^https?://([^/]*).*#;
$vhost =~ s/:\d+$//;
$req->{env}->{HTTP_HOST} = $vhost;
$self->p->HANDLER->headersInit( $self->{conf} );

View File

@ -5,7 +5,7 @@ use Mouse;
use Lemonldap::NG::Portal::Main::Constants
qw( PE_OK PE_BADCREDENTIALS PE_IMPERSONATION_SERVICE_NOT_ALLOWED PE_MALFORMEDUSER );
our $VERSION = '2.0.3';
our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';

View File

@ -76,7 +76,7 @@ sub confirm {
$self->p->setHiddenFormValue(
$req,
upgrading => $self->ott->createToken,
''
'', 0
); # Insert token
return $self->p->login($req);
}

View File

@ -0,0 +1,130 @@
#!/usr/bin/perl
#=============================================================================
# Cleaner for LemonLDAP::NG: removes old sessions from Apache::Session
#
# This module is written to be used by cron to clean old sessions from
# Apache::Session. It does not works with Apache::Session::Memcached
#
# This is part of LemonLDAP::NG product, released under GPL
#=============================================================================
use Lemonldap::NG::Common::Conf;
use Lemonldap::NG::Common::Conf::Constants;
use Lemonldap::NG::Common::Apache::Session;
use Lemonldap::NG::Common::Session;
use strict;
use Getopt::Std;
# Options
# -d: debug mode
# -f: force delete of corrupted sessions
our $opt_d;
our $opt_f;
getopts('df');
my $debug = $opt_d;
my $force = $opt_f;
my $nb_purged = 0;
my $nb_error = 0;
unless (@ARGV) {
print STDERR "Usage: $0 <uid>\n";
exit 1;
}
#=============================================================================
# Load configuration
#=============================================================================
my $lmconf = Lemonldap::NG::Common::Conf->new()
or die $Lemonldap::NG::Common::Conf::msg;
my $conf = $lmconf->getConf or die "Unable to get configuration ($!)";
my $localconf = $lmconf->getLocalConf(PORTALSECTION)
or die "Unable to get local configuration ($!)";
if ($localconf) {
$conf->{$_} = $localconf->{$_} foreach ( keys %$localconf );
}
print "Configuration loaded\n" if $debug;
#=============================================================================
# Timeout
#=============================================================================
print "Timeout value: " . $conf->{timeout} . "\n" if $debug;
#=============================================================================
# Apache::Session backends
#=============================================================================
my @backends;
my $module;
# Sessions
if ( defined $conf->{globalStorage} ) {
# Load module
$module = $conf->{globalStorage};
eval "use $module";
die $@ if ($@);
$conf->{globalStorageOptions}->{backend} = $module;
# Add module in managed backends
push @backends, $conf->{globalStorageOptions};
print "Session backend $module will be used\n" if $debug;
}
else {
print STDERR "Unable to find 'globalStorage' configuration key, aborting\n";
exit 1;
}
#=============================================================================
# Load and purge sessions
#=============================================================================
for my $options (@backends) {
next if ( $options->{backend} eq "Apache::Session::Memcached" );
# Get all expired sessions
foreach my $reSession (@ARGV) {
my $sessions =
Lemonldap::NG::Common::Apache::Session->searchOnExpr( $options,
$conf->{whatToTrace}, $reSession );
foreach my $id ( keys %$sessions ) {
my $session = Lemonldap::NG::Common::Session->new(
storageModule => $options->{backend},
storageModuleOptions => $options,
cacheModule => $conf->{localSessionStorage},
cacheModuleOptions => $conf->{localSessionStorageOptions},
id => $id,
);
unless ( $session->data ) {
print "Error while opening session $id\n" if $debug;
print STDERR "Error on session $id\n";
$nb_error++;
next;
}
unless ( $session->remove ) {
print "Error while deleting session $id\n" if $debug;
print STDERR "Error on session $id\n";
$nb_error++;
next;
}
print "Session $id has been purged\n" if $debug;
$nb_purged++;
}
}
}
#=============================================================================
# Exit
#=============================================================================
print "$nb_purged sessions have been purged\n" if $debug;
print STDERR
"$nb_error sessions remaining, try to purge them with force (option -f)\n"
if $nb_error;
my $exit = $nb_error ? 1 : $nb_purged ? 0 : 1;
exit $exit;

View File

@ -228,8 +228,6 @@ $(document).ready ->
datas = getValues()
# Export datas for other scripts
window.datas = datas
if datas['antiframe'] and top != self
top.location.href = location.href
$("#appslist").sortable
axis: "y"

View File

@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.12.8
// Generated by CoffeeScript 1.12.7
/*
LemonLDAP::NG Portal jQuery scripts
@ -226,9 +226,6 @@ LemonLDAP::NG Portal jQuery scripts
var action, al, authMenuTabs, back_url, i, l, lang, langdiv, langs, langs2, len, len1, len2, len3, link, m, menuIndex, menuTabs, method, n, nl, nlangs, re, ref, ref1, ref2;
datas = getValues();
window.datas = datas;
if (datas['antiframe'] && top !== self) {
top.location.href = location.href;
}
$("#appslist").sortable({
axis: "y",
cursor: "move",

File diff suppressed because one or more lines are too long

View File

@ -63,7 +63,7 @@
</div>
</div>
</TMPL_IF>
</form>
</div>

View File

@ -61,11 +61,11 @@
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/idpchoice.min.js"></script>
//else -->
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/idpchoice.js"></script>
<!-- //endif -->
<!-- //endif -->
</div>
</div>
<TMPL_IF NAME="PORTAL_URL">
<div id="logout">
<div class="buttons">
@ -76,7 +76,7 @@
</div>
</div>
</TMPL_IF>
</form>
</div>

View File

@ -47,7 +47,7 @@
<span class="fa fa-envelope-open"></span>
<span trspan="sendPwd">Send me a link</span>
</button>
</div>
</form>
</div>

View File

@ -123,7 +123,7 @@
<TMPL_ELSE>
<div class="col-12">
</TMPL_IF>
<!-- Name and link (mandatory) -->
<h5 class="appname <TMPL_VAR NAME="appid"> card-title">
<TMPL_VAR NAME="appname">

View File

@ -1,7 +1,7 @@
<TMPL_INCLUDE NAME="header.tpl">
<div id="notifcontent" class="container">
<form action="/notifback" method="post" class="notif" role="form">
<TMPL_VAR NAME="HIDDEN_INPUTS">
<TMPL_IF NAME="CHOICE_VALUE">

View File

@ -41,7 +41,7 @@
</div>
</div>
</main>
<div class="buttons">
<a href="<TMPL_VAR NAME="PORTAL_URL">2fregisters" class="btn btn-info" role="button">
<span class="fa fa-shield"></span>

View File

@ -41,7 +41,7 @@
<span class="fa fa-shield"></span>
<span trspan="sfaManager">sfaManager</span>
</a>
<a id="goback" href="<TMPL_VAR NAME="PORTAL_URL">?cancel=1<TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>" class="btn btn-primary" role="button">
<span class="fa fa-home"></span>
<span trspan="goToPortal">Go to portal</span>

View File

@ -38,7 +38,7 @@
<span class="fa fa-shield"></span>
<span trspan="sfaManager">sfaManager</span>
</a>
<a id="goback" href="<TMPL_VAR NAME="PORTAL_URL">?cancel=1<TMPL_IF NAME="AUTH_URL">&url=<TMPL_VAR NAME="AUTH_URL"></TMPL_IF>" class="btn btn-primary" role="button">
<span class="fa fa-home"></span>
<span trspan="goToPortal">Go to portal</span>

View File

@ -22,7 +22,6 @@
"choicetab":"<TMPL_VAR NAME="CHOICE_VALUE">",
"login":"<TMPL_VAR NAME="LOGIN">",
"newwindow":<TMPL_VAR NAME="NEWWINDOW" DEFAULT="0">,
"antiframe":<TMPL_VAR NAME="ANTIFRAME" DEFAULT="1">,
"appslistorder":"<TMPL_VAR NAME="APPSLIST_ORDER">",
"scriptname":"<TMPL_VAR NAME="SCRIPT_NAME">",
"activeTimer":<TMPL_VAR NAME="ACTIVE_TIMER" DEFAULT="0">,

View File

@ -141,7 +141,7 @@ m#iframe src="http://auth.sp.com(/saml/proxySingleLogout)\?(SAMLRequest=.*?)"#,
switch ('issuer');
ok( $res = $issuer->_get( $url, query => $query, accept => 'text/html' ),
'Push SAML response to IdP' );
expectOK($res);
expectRedirection($res, 'http://auth.idp.com/static/common/icons/ok.png');
ok( getHeader( $res, 'Content-Security-Policy' ) !~ /frame-ancestors/,
' Frame can be embedded' )
or explain( $res->[1],

View File

@ -0,0 +1,793 @@
use lib 'inc';
use Test::More;
use strict;
use IO::String;
use LWP::UserAgent;
use LWP::Protocol::PSGI;
use MIME::Base64;
BEGIN {
require 't/test-lib.pm';
require 't/saml-lib.pm';
}
my $maintests = 23;
my $debug = 'error';
my ( $issuer, $sp, $sp2, $res );
my %handlerOR = ( issuer => [], sp => [], sp2 => [] );
# Redefine LWP methods for tests
LWP::Protocol::PSGI->register(
sub {
my $req = Plack::Request->new(@_);
fail('POST should not launch SOAP requests');
count(1);
return [ 500, [], [] ];
}
);
SKIP: {
eval "use Lasso";
if ($@) {
skip 'Lasso not found', $maintests;
}
# Initialization
ok( $issuer = issuer(), 'Issuer portal' );
$handlerOR{issuer} = \@Lemonldap::NG::Handler::Main::_onReload;
switch ('sp');
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
ok( $sp = sp(), 'SP portal' );
$handlerOR{sp} = \@Lemonldap::NG::Handler::Main::_onReload;
ok( $sp2 = sp2(), 'SP2 portal' );
$handlerOR{sp2} = \@Lemonldap::NG::Handler::Main::_onReload;
# Simple SP access
my $res;
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
'Unauth SP request'
);
my ( $host, $url, $query );
ok(
expectCookie( $res, 'lemonldapidp' ) eq
'http://auth.idp.com/saml/metadata',
'IDP cookie defined'
)
or explain(
$res->[1],
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
# Push SAML request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
),
'Launch SAML request to IdP'
);
expectOK($res);
my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
# Try to authenticate to IdP
my $body = $res->[2]->[0];
$body =~ s/^.*?<form.*?>//s;
$body =~ s#</form>.*$##s;
my %fields =
( $body =~ /<input type="hidden".+?name="(.+?)".+?value="(.*?)"/sg );
$fields{user} = $fields{password} = 'french';
use URI::Escape;
$query =
join( '&', map { "$_=" . uri_escape( $fields{$_} ) } keys %fields );
ok(
$res = $issuer->_post(
$url,
IO::String->new($query),
accept => 'text/html',
cookie => $pdata,
length => length($query),
),
'Post authentication'
);
expectOK($res);
my $idpId = expectCookie($res);
( $host, $url, $query ) =
expectForm( $res, 'auth.sp.com', '/saml/proxySingleSignOnPost',
'SAMLResponse', 'RelayState' );
# Post SAML response to SP
switch ('sp');
ok(
$res = $sp->_post(
$url, IO::String->new($query),
accept => 'text/html',
length => length($query),
cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata',
),
'Post SAML response to SP'
);
my $spId = expectCookie($res);
expectRedirection( $res, 'http://test1.example.com/' );
ok( $res = $sp->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP' );
expectOK($res);
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
# Verify UTF-8
ok( $res = $sp->_get("/sessions/global/$spId"), 'Get UTF-8' );
expectOK($res);
ok( $res = eval { JSON::from_json( $res->[2]->[0] ) }, ' GET JSON' )
or print STDERR $@;
ok( $res->{cn} eq 'Frédéric Accents', 'UTF-8 values' )
or explain( $res, 'cn => Frédéric Accents' );
# Simple SP2 access
switch ('sp2');
ok(
$res = $sp2->_get(
'/',
accept => 'text/html',
query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
'Unauth SP2 request'
);
ok(
expectCookie( $res, 'lemonldapidp' ) eq
'http://auth.idp.com/saml/metadata',
'IDP cookie defined'
)
or explain(
$res->[1],
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp2.com; path=/'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
# Push SAML request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
'Launch SAML request to IdP'
);
( $host, $url, $query ) =
expectForm( $res, 'auth.sp2.com', '/saml/proxySingleSignOnPost',
'SAMLResponse', 'RelayState' );
# Post SAML response to SP2
switch ('sp2');
ok(
$res = $sp2->_post(
$url, IO::String->new($query),
accept => 'text/html',
length => length($query),
cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata',
),
'Post SAML response to SP2'
);
my $sp2Id = expectCookie($res);
expectRedirection( $res, 'http://test1.example.com/' );
ok( $res = $sp2->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP2' );
expectOK($res);
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
# Logout initiated by SP
ok(
$res = $sp->_get(
'/',
query => 'logout',
cookie => "lemonldap=$spId",
accept => 'text/html'
),
'Query SP for logout'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleLogout)\?(SAMLRequest=.+)# );
# Push SAML logout request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
'Launch SAML logout request to IdP'
);
# The SP doesn't have an SLO endpoint for its response (Hi Renater!) , in
# this case, the portal should display a nice user message instead of
# erroring.
expectOK($res);
ok( $res->[2]->[0] =~ /trmsg="47"/, 'Found logout message' );
ok(
$res = $issuer->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
switch ('sp2');
ok(
$res = $sp2->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$sp2Id"
),
'User is unfortunately still logged into SP2'
);
expectOK($res);
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
}
count($maintests);
clean_sessions();
done_testing( count() );
sub switch {
my $type = shift;
@Lemonldap::NG::Handler::Main::_onReload = @{
$handlerOR{$type};
};
}
sub issuer {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'idp.com',
portal => 'http://auth.idp.com',
authentication => 'Demo',
userDB => 'Same',
issuerDBSAMLActivation => 1,
samlSPMetaDataOptions => {
'sp.com' => {
samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPMetaDataOptionsSignSSOMessage => 1,
samlSPMetaDataOptionsSignSLOMessage => 1,
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
},
'sp2.com' => {
samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPMetaDataOptionsSignSSOMessage => 1,
samlSPMetaDataOptionsSignSLOMessage => 1,
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
}
},
samlSPMetaDataExportedAttributes => {
'sp.com' => {
cn =>
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
uid =>
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
},
'sp2.com' => {
cn =>
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
uid =>
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
}
},
samlOrganizationDisplayName => "IDP",
samlOrganizationName => "IDP",
samlOrganizationURL => "http://www.idp.com/",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT
csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46
Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnVDNfSEASVIppEBYjDX203ypmURIzU
6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+tBlcnMrkv/40DSUkehQIl2JmlFrl2
Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5NMd0KFa6CwZUUSHJqH5GFy5Y2yl4l
g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQIDAQABAoIBAHnfqjX3eO8SfnP5
NURp90Td2mNHirCn0qLd9NKl1ySMPR1GgeH9SQ7Umu32EcteAUL5dOw2PiTZVmeW
cKINgsWVftXUQcOQ4xIqWKb51QUBdy0FhxrZRSFjWxXt5iYK1PmzHfsax/g1/S9C
RnqtFyjOy1bywkSt9jiy+9YBR2B7BDhLHlILbijWn5zaecaV4YA+L1UK4M/mehdb
+0FVPavbGpnlqBRTY+7YXfZ/mRPCfn5DvO9lW1O0pJMmNdBh9kmm3DxHf6AkK47a
43gO/dRWiWo2rZ/+Jw7uyqOb23U0MydP7kia0p3tzCUBPsrlgnichYG5RNFp0wqy
3VT1TYECgYEA0Y9vENy1jJd+s7WbGrsRtSKxfZgtJr0yjSlQVYrIlwbZSGn+ndxq
V2vVlwIgLX3pz6T40BMfk6SNx08jjy0Sgn6OAM0ILrinno8yWcSAMCmfCU0S/3O1
55bqtcnk4XTHBHzJ5OrnrPaW5ourvJz0lcWEKMg3BXxLzaF6ZRy85nECgYEAwPMD
LNAKLCDrUMyYFOpPyPLe7wvszcFvPipGgerSgFP1c6N7xaMUdHDYqBfuis1khPGF
YcMHeNBYmzX6yEGbp3lrB4PHpUySmTU3mv3u9I05aahInK21gXum3uRkCWyyIF6V
T/qeszl9mVOCp0CC4eG3IMVpaD0UKDEHVhERYCkCgYAjuTPRyA4a3Wh38ilysRkf
q75eDqcDx5Tqg3RyYKo5NK2troP9HSnzpSpQB8i8eI53G0RfFCN5479XjqIdMi3J
mRFUCZ+vd0L7wKVwsBK6Ix49U6o9adhElnGEc9pUpLeYiD1SjMjZr1+iBYVNLeRz
86vH1/mpMbsqXrCis/dvwQKBgGttomHr/w3s0jftget7PirrFrbP0+wHfDGHhjRF
kyhCFtJovrwefYALaIXGtVjw3LusYZA570oT7pGUb2naJZkMYEwR0jG1vZWx7KDO
K6JbkxDB0pPxn7JVL2bAkPYyX8boAohCSOQO6WBZ/8+xem3bp4OGhpa0EyoBik0g
OaVpAoGATj4SyYsE10hGT676iie8zy3fi5IPC3E+x4QlVuusaLtuY8LJA50stjtx
gUa/JAKlZZL+gvzvOviQIxyfIChXOdTt5uiOYkdHJDbAF3NSrji7hrXq4v8UZv75
8hBrwJZIpy6y01dRlrriHmPRtEq1pk7JX2uUg0sP5g4BEcsaCbc=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtR/wgDqWB4Maho5V6TjcL/NbNfjgIh7GcgkrB5RZcVT1GTej
JlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6S8SpeJ1ofp5rBEoD/TIkvU0JOcid
65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRyBIQzB0SIxSpnrsigqNsE1E94toDM
x4wovjHu/9ABAImREV7Sz83OeFF00/sghrjTEJOD/gHf04JCn9MgNOqvSTysr9LX
Wg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5yD41mi+hT8Rh+W8Je8rsiML4VMxz
sb1l9303asw6suo5bLTISKNSbu1nt1NkpNxzywIDAQABAoIBAQCQkbvPPfP+bwC/
IeEk1IO7qkzFWa7czR+safD0jc6OjTdNN4F716Q6yt4zEzLKu8VliiW+C23EBQiD
7asKf4DvdTun0ExVtHDK7aEdeealSlXwz1ZtdypyILbtq1UGo/rR0v4x601rQPl0
IrBmFf6D6FkqleNtLJmxguXpoVfLdYKNwkxH2ux+GOA9r2o5pUCQmJGDap5YWRuQ
uB71ewJjVWujaL3e1ac/5cP7/tqWmgAiOaN8sYdD6+oWOR47bHj8JKcMBSl4y2QC
dL31cGmmf5KqBbtISki3RXfHHjT7E3Z85CbESkKTZlEb1ar3XmepY6Z7V5UO16oz
fFE5R6khAoGBAOl9Qb+qYVVO5ugE65ORjYVeuXykANhM9ssiY5a6zuAakWzw7Zv3
k6PXm9p7azlEXAlTnTXVwHYMyuuzZDvQ8LRV1iBOdPuIkUAmaQ5K9ASD7VcoHexh
k8DAKf9Ln7sTRaMdvgceRNczOmJOBIEpTZkssA/jVGXZsoyTWYl1en/ZAoGBAMaW
RnNbSNprEV2b8UeAJ6i77c4SXwu1I8X2NLtiLScb1ETBjfrdHmdlJglfyd/0gmhH
p/43Ku2iGUoY5KtuOI6QmahrJYQscRQhoj252VXadG6fNWWAlpgdCm9houhHb5BF
3zge/bTr0anUe9EA7Z/ymav12rEouoNjIlhI9C5DAoGATR85a2SMt8/TB0owwdJu
62GpZNkLCmcJkXkvaecUVAOSi2hdI4o4MwMRkK35cbX5rH74y4JqCtQY5pefgP53
sykzDAK+MyMdzxGg2764MRGegI5Yq+5jDmSquo+xF+q6srEtRk6iMG7UVwosBLmu
zuxqzySoiOfKSRKWnYe3SakCgYEAwWMkVkAmETXE4oDzFSsS8/mW2l//mPocTTK3
JWe1CunJ6+8FYbAlZJEW2ngismp8+CoXybNVpbZ+pC7buKoMf6EHUgCNt0pEEFO0
mCG9KSMk0XlPWXpArP9S4yaUq1itpzSz7QYZES+4rIcU0HLz9RgeWFyCTJWaFErc
7laVG9sCgYBKOtk5WlIOP4BxSd2y4cYzohgwTZIs1/2kTEn1u4eH73M1xvAlHHFB
wSF5QXgDKJ8pPAOhNWpdLO/PdtnQn91nOvTNc+ShJZzjdbneUdQVpWpoBf72uA+N
6rIVf1JBUL2p7HFHaGdUZC7KGQ+yv6ZHrE1+7202nuDvJdvGEEdFsQ==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnfKBDG/K0TnGT7Xu8q1N
45sNWvIK91SqNg8nvN2uVeKoHADTcsus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9r
yfSNDhWDWloNkpGEeWif2BnHUu46Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnV
DNfSEASVIppEBYjDX203ypmURIzU6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+t
BlcnMrkv/40DSUkehQIl2JmlFrl2Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5N
Md0KFa6CwZUUSHJqH5GFy5Y2yl4lg8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxI
GQIDAQAB
-----END PUBLIC KEY-----
",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtR/wgDqWB4Maho5V6Tjc
L/NbNfjgIh7GcgkrB5RZcVT1GTejJlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6
S8SpeJ1ofp5rBEoD/TIkvU0JOcid65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRy
BIQzB0SIxSpnrsigqNsE1E94toDMx4wovjHu/9ABAImREV7Sz83OeFF00/sghrjT
EJOD/gHf04JCn9MgNOqvSTysr9LXWg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5
yD41mi+hT8Rh+W8Je8rsiML4VMxzsb1l9303asw6suo5bLTISKNSbu1nt1NkpNxz
ywIDAQAB
-----END PUBLIC KEY-----
",
samlSPMetaDataXML => {
"sp.com" => {
samlSPMetaDataXML => <<EOF
<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
entityID="http://auth.sp.com/saml/metadata">
<SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyValue>
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
<Modulus>
u4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr
+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX
7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGS
RSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9Nqw==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>
<KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyValue>
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
<Modulus>
sRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Us
og3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVL
R+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8r
UWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+w==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/artifact" />
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:entity</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<AssertionConsumerService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp.com/saml/proxySingleSignOnPost" />
<AssertionConsumerService isDefault="false" index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.sp.com/saml/proxySingleSignOnArtifact" />
</SPSSODescriptor>
<Organization>
<OrganizationName xml:lang="en">org</OrganizationName>
<OrganizationDisplayName xml:lang="en">
org</OrganizationDisplayName>
<OrganizationURL xml:lang="en">
http://www.org.com</OrganizationURL>
</Organization>
</EntityDescriptor>
EOF
},
"sp2.com" => {
samlSPMetaDataXML => <<EOF
<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
entityID="http://auth.sp2.com/saml/metadata">
<SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyValue>
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
<Modulus>
u4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr
+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX
7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGS
RSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9Nqw==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>
<KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyValue>
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
<Modulus>
sRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Us
og3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVL
R+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8r
UWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+w==</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</KeyDescriptor>
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp2.com/saml/artifact" />
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:entity</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<AssertionConsumerService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp2.com/saml/proxySingleSignOnPost" />
<AssertionConsumerService isDefault="false" index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.sp2.com/saml/proxySingleSignOnArtifact" />
</SPSSODescriptor>
<Organization>
<OrganizationName xml:lang="en">org</OrganizationName>
<OrganizationDisplayName xml:lang="en">
org</OrganizationDisplayName>
<OrganizationURL xml:lang="en">
http://www.org.com</OrganizationURL>
</Organization>
</EntityDescriptor>
EOF
},
},
}
}
);
}
sub sp {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'sp.com',
portal => 'http://auth.sp.com',
authentication => 'SAML',
userDB => 'Same',
issuerDBSAMLActivation => 0,
restSessionServer => 1,
samlIDPMetaDataExportedAttributes => {
idp => {
mail => "0;mail;;",
uid => "1;uid",
cn => "0;cn"
}
},
samlIDPMetaDataOptions => {
idp => {
samlIDPMetaDataOptionsEncryptionMode => 'none',
samlIDPMetaDataOptionsSSOBinding => 'redirect',
samlIDPMetaDataOptionsSLOBinding => 'redirect',
samlIDPMetaDataOptionsSignSSOMessage => 1,
samlIDPMetaDataOptionsSignSLOMessage => 1,
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
samlIDPMetaDataOptionsForceUTF8 => 1,
}
},
samlIDPMetaDataExportedAttributes => {
idp => {
"uid" => "0;uid;;",
"cn" => "1;cn;;",
},
},
samlIDPMetaDataXML => {
idp => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
}
},
samlOrganizationDisplayName => "SP",
samlOrganizationName => "SP",
samlOrganizationURL => "http://www.sp.com",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
qwIDAQAB
-----END PUBLIC KEY-----
",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
+wIDAQAB
-----END PUBLIC KEY-----
",
samlSPSSODescriptorAuthnRequestsSigned => 1,
},
}
);
}
sub sp2 {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'sp2.com',
portal => 'http://auth.sp2.com',
authentication => 'SAML',
userDB => 'Same',
issuerDBSAMLActivation => 0,
restSessionServer => 1,
samlIDPMetaDataExportedAttributes => {
idp => {
mail => "0;mail;;",
uid => "1;uid",
cn => "0;cn"
}
},
samlIDPMetaDataOptions => {
idp => {
samlIDPMetaDataOptionsEncryptionMode => 'none',
samlIDPMetaDataOptionsSSOBinding => 'redirect',
samlIDPMetaDataOptionsSLOBinding => 'redirect',
samlIDPMetaDataOptionsSignSSOMessage => 1,
samlIDPMetaDataOptionsSignSLOMessage => 1,
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
samlIDPMetaDataOptionsForceUTF8 => 1,
}
},
samlIDPMetaDataExportedAttributes => {
idp => {
"uid" => "0;uid;;",
"cn" => "1;cn;;",
},
},
samlIDPMetaDataXML => {
idp => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
}
},
samlOrganizationDisplayName => "SP",
samlOrganizationName => "SP",
samlOrganizationURL => "http://www.sp2.com",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
qwIDAQAB
-----END PUBLIC KEY-----
",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
+wIDAQAB
-----END PUBLIC KEY-----
",
samlSPSSODescriptorAuthnRequestsSigned => 1,
},
}
);
}

View File

@ -0,0 +1,712 @@
use lib 'inc';
use Test::More;
use strict;
use IO::String;
use LWP::UserAgent;
use LWP::Protocol::PSGI;
use MIME::Base64;
BEGIN {
require 't/test-lib.pm';
require 't/saml-lib.pm';
}
my $maintests = 27;
my $debug = 'error';
my ( $issuer, $sp, $sp2, $res );
my %handlerOR = ( issuer => [], sp => [], sp2 => [] );
# Redefine LWP methods for tests
LWP::Protocol::PSGI->register(
sub {
my $req = Plack::Request->new(@_);
fail('POST should not launch SOAP requests');
count(1);
return [ 500, [], [] ];
}
);
SKIP: {
eval "use Lasso";
if ($@) {
skip 'Lasso not found', $maintests;
}
# Initialization
ok( $issuer = issuer(), 'Issuer portal' );
$handlerOR{issuer} = \@Lemonldap::NG::Handler::Main::_onReload;
switch ('sp');
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
ok( $sp = sp(), 'SP portal' );
$handlerOR{sp} = \@Lemonldap::NG::Handler::Main::_onReload;
ok( $sp2 = sp2(), 'SP2 portal' );
$handlerOR{sp2} = \@Lemonldap::NG::Handler::Main::_onReload;
# Simple SP access
my $res;
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
'Unauth SP request'
);
my ( $host, $url, $query );
ok(
expectCookie( $res, 'lemonldapidp' ) eq
'http://auth.idp.com/saml/metadata',
'IDP cookie defined'
)
or explain(
$res->[1],
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
# Push SAML request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
),
'Launch SAML request to IdP'
);
expectOK($res);
my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
# Try to authenticate to IdP
my $body = $res->[2]->[0];
$body =~ s/^.*?<form.*?>//s;
$body =~ s#</form>.*$##s;
my %fields =
( $body =~ /<input type="hidden".+?name="(.+?)".+?value="(.*?)"/sg );
$fields{user} = $fields{password} = 'french';
use URI::Escape;
$query =
join( '&', map { "$_=" . uri_escape( $fields{$_} ) } keys %fields );
ok(
$res = $issuer->_post(
$url,
IO::String->new($query),
accept => 'text/html',
cookie => $pdata,
length => length($query),
),
'Post authentication'
);
expectOK($res);
my $idpId = expectCookie($res);
( $host, $url, $query ) =
expectForm( $res, 'auth.sp.com', '/saml/proxySingleSignOnPost',
'SAMLResponse', 'RelayState' );
# Post SAML response to SP
switch ('sp');
ok(
$res = $sp->_post(
$url, IO::String->new($query),
accept => 'text/html',
length => length($query),
cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata',
),
'Post SAML response to SP'
);
my $spId = expectCookie($res);
expectRedirection( $res, 'http://test1.example.com/' );
ok( $res = $sp->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP' );
expectOK($res);
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
# Verify UTF-8
ok( $res = $sp->_get("/sessions/global/$spId"), 'Get UTF-8' );
expectOK($res);
ok( $res = eval { JSON::from_json( $res->[2]->[0] ) }, ' GET JSON' )
or print STDERR $@;
ok( $res->{cn} eq 'Frédéric Accents', 'UTF-8 values' )
or explain( $res, 'cn => Frédéric Accents' );
# Simple SP2 access
switch ('sp2');
ok(
$res = $sp2->_get(
'/',
accept => 'text/html',
query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='
),
'Unauth SP2 request'
);
ok(
expectCookie( $res, 'lemonldapidp' ) eq
'http://auth.idp.com/saml/metadata',
'IDP cookie defined'
)
or explain(
$res->[1],
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp2.com; path=/'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
# Push SAML request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
'Launch SAML request to IdP'
);
( $host, $url, $query ) =
expectForm( $res, 'auth.sp2.com', '/saml/proxySingleSignOnPost',
'SAMLResponse', 'RelayState' );
# Post SAML response to SP2
switch ('sp2');
ok(
$res = $sp2->_post(
$url, IO::String->new($query),
accept => 'text/html',
length => length($query),
cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata',
),
'Post SAML response to SP2'
);
my $sp2Id = expectCookie($res);
expectRedirection( $res, 'http://test1.example.com/' );
ok( $res = $sp2->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP2' );
expectOK($res);
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
# Logout initiated by SP
ok(
$res = $sp->_get(
'/',
query => 'logout',
cookie => "lemonldap=$spId",
accept => 'text/html'
),
'Query SP for logout'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleLogout)\?(SAMLRequest=.+)# );
# Push SAML logout request to IdP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
cookie => "lemonldap=$idpId",
),
'Launch SAML logout request to IdP'
);
my $relaypage = $res;
ok( $res->[2]->[0] =~
m%<iframe src="http://auth.sp2.com/saml/proxySingleLogout\?([^"]*)"%
);
my $iframe = $1;
# Load iframe
switch ('sp2');
ok(
$res = $sp2->_get(
'/saml/proxySingleLogout',
query => $iframe,
cookie => "lemonldap=$sp2Id",
accept => 'text/html',
),
'Start logout from SP2'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleLogoutReturn)\?(SAMLResponse=.+)# );
# Get OK icon from IDP
switch ('issuer');
ok(
$res = $issuer->_get(
$url,
query => $query,
accept => 'text/html',
),
'get SAML response from IDP',
);
expectRedirection( $res, "http://auth.idp.com/static/common/icons/ok.png" );
# Post global logout form
( $host, $url, $query ) =
expectForm( $relaypage, 'auth.idp.com',
'/saml/relaySingleLogoutTermination', 'relay' );
ok(
$res = $issuer->_post(
$url,
IO::String->new($query),
accept => 'text/html',
length => length($query),
),
'Post final logout'
);
( $url, $query ) = expectRedirection( $res,
qr#^http://auth.sp.com(/saml/proxySingleLogoutReturn)\?(SAMLResponse=.+)#
);
# Send SAML response to SP
switch ('sp');
ok(
$res = $sp->_get(
$url,
query => $query,
accept => 'text/html',
),
'Send SAML logout response to SP'
);
# Test if logout is done
switch ('issuer');
ok(
$res = $issuer->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
switch ('sp2');
ok(
$res = $sp2->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$sp2Id"
),
'Test if user is reject on SP2'
);
expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
}
count($maintests);
clean_sessions();
done_testing( count() );
sub switch {
my $type = shift;
@Lemonldap::NG::Handler::Main::_onReload = @{
$handlerOR{$type};
};
}
sub issuer {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'idp.com',
portal => 'http://auth.idp.com',
authentication => 'Demo',
userDB => 'Same',
issuerDBSAMLActivation => 1,
samlSPMetaDataOptions => {
'sp.com' => {
samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPMetaDataOptionsSignSSOMessage => 1,
samlSPMetaDataOptionsSignSLOMessage => 1,
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
},
'sp2.com' => {
samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPMetaDataOptionsSignSSOMessage => 1,
samlSPMetaDataOptionsSignSLOMessage => 1,
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
}
},
samlSPMetaDataExportedAttributes => {
'sp.com' => {
cn =>
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
uid =>
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
},
'sp2.com' => {
cn =>
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
uid =>
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
}
},
samlOrganizationDisplayName => "IDP",
samlOrganizationName => "IDP",
samlOrganizationURL => "http://www.idp.com/",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT
csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46
Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnVDNfSEASVIppEBYjDX203ypmURIzU
6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+tBlcnMrkv/40DSUkehQIl2JmlFrl2
Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5NMd0KFa6CwZUUSHJqH5GFy5Y2yl4l
g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQIDAQABAoIBAHnfqjX3eO8SfnP5
NURp90Td2mNHirCn0qLd9NKl1ySMPR1GgeH9SQ7Umu32EcteAUL5dOw2PiTZVmeW
cKINgsWVftXUQcOQ4xIqWKb51QUBdy0FhxrZRSFjWxXt5iYK1PmzHfsax/g1/S9C
RnqtFyjOy1bywkSt9jiy+9YBR2B7BDhLHlILbijWn5zaecaV4YA+L1UK4M/mehdb
+0FVPavbGpnlqBRTY+7YXfZ/mRPCfn5DvO9lW1O0pJMmNdBh9kmm3DxHf6AkK47a
43gO/dRWiWo2rZ/+Jw7uyqOb23U0MydP7kia0p3tzCUBPsrlgnichYG5RNFp0wqy
3VT1TYECgYEA0Y9vENy1jJd+s7WbGrsRtSKxfZgtJr0yjSlQVYrIlwbZSGn+ndxq
V2vVlwIgLX3pz6T40BMfk6SNx08jjy0Sgn6OAM0ILrinno8yWcSAMCmfCU0S/3O1
55bqtcnk4XTHBHzJ5OrnrPaW5ourvJz0lcWEKMg3BXxLzaF6ZRy85nECgYEAwPMD
LNAKLCDrUMyYFOpPyPLe7wvszcFvPipGgerSgFP1c6N7xaMUdHDYqBfuis1khPGF
YcMHeNBYmzX6yEGbp3lrB4PHpUySmTU3mv3u9I05aahInK21gXum3uRkCWyyIF6V
T/qeszl9mVOCp0CC4eG3IMVpaD0UKDEHVhERYCkCgYAjuTPRyA4a3Wh38ilysRkf
q75eDqcDx5Tqg3RyYKo5NK2troP9HSnzpSpQB8i8eI53G0RfFCN5479XjqIdMi3J
mRFUCZ+vd0L7wKVwsBK6Ix49U6o9adhElnGEc9pUpLeYiD1SjMjZr1+iBYVNLeRz
86vH1/mpMbsqXrCis/dvwQKBgGttomHr/w3s0jftget7PirrFrbP0+wHfDGHhjRF
kyhCFtJovrwefYALaIXGtVjw3LusYZA570oT7pGUb2naJZkMYEwR0jG1vZWx7KDO
K6JbkxDB0pPxn7JVL2bAkPYyX8boAohCSOQO6WBZ/8+xem3bp4OGhpa0EyoBik0g
OaVpAoGATj4SyYsE10hGT676iie8zy3fi5IPC3E+x4QlVuusaLtuY8LJA50stjtx
gUa/JAKlZZL+gvzvOviQIxyfIChXOdTt5uiOYkdHJDbAF3NSrji7hrXq4v8UZv75
8hBrwJZIpy6y01dRlrriHmPRtEq1pk7JX2uUg0sP5g4BEcsaCbc=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtR/wgDqWB4Maho5V6TjcL/NbNfjgIh7GcgkrB5RZcVT1GTej
JlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6S8SpeJ1ofp5rBEoD/TIkvU0JOcid
65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRyBIQzB0SIxSpnrsigqNsE1E94toDM
x4wovjHu/9ABAImREV7Sz83OeFF00/sghrjTEJOD/gHf04JCn9MgNOqvSTysr9LX
Wg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5yD41mi+hT8Rh+W8Je8rsiML4VMxz
sb1l9303asw6suo5bLTISKNSbu1nt1NkpNxzywIDAQABAoIBAQCQkbvPPfP+bwC/
IeEk1IO7qkzFWa7czR+safD0jc6OjTdNN4F716Q6yt4zEzLKu8VliiW+C23EBQiD
7asKf4DvdTun0ExVtHDK7aEdeealSlXwz1ZtdypyILbtq1UGo/rR0v4x601rQPl0
IrBmFf6D6FkqleNtLJmxguXpoVfLdYKNwkxH2ux+GOA9r2o5pUCQmJGDap5YWRuQ
uB71ewJjVWujaL3e1ac/5cP7/tqWmgAiOaN8sYdD6+oWOR47bHj8JKcMBSl4y2QC
dL31cGmmf5KqBbtISki3RXfHHjT7E3Z85CbESkKTZlEb1ar3XmepY6Z7V5UO16oz
fFE5R6khAoGBAOl9Qb+qYVVO5ugE65ORjYVeuXykANhM9ssiY5a6zuAakWzw7Zv3
k6PXm9p7azlEXAlTnTXVwHYMyuuzZDvQ8LRV1iBOdPuIkUAmaQ5K9ASD7VcoHexh
k8DAKf9Ln7sTRaMdvgceRNczOmJOBIEpTZkssA/jVGXZsoyTWYl1en/ZAoGBAMaW
RnNbSNprEV2b8UeAJ6i77c4SXwu1I8X2NLtiLScb1ETBjfrdHmdlJglfyd/0gmhH
p/43Ku2iGUoY5KtuOI6QmahrJYQscRQhoj252VXadG6fNWWAlpgdCm9houhHb5BF
3zge/bTr0anUe9EA7Z/ymav12rEouoNjIlhI9C5DAoGATR85a2SMt8/TB0owwdJu
62GpZNkLCmcJkXkvaecUVAOSi2hdI4o4MwMRkK35cbX5rH74y4JqCtQY5pefgP53
sykzDAK+MyMdzxGg2764MRGegI5Yq+5jDmSquo+xF+q6srEtRk6iMG7UVwosBLmu
zuxqzySoiOfKSRKWnYe3SakCgYEAwWMkVkAmETXE4oDzFSsS8/mW2l//mPocTTK3
JWe1CunJ6+8FYbAlZJEW2ngismp8+CoXybNVpbZ+pC7buKoMf6EHUgCNt0pEEFO0
mCG9KSMk0XlPWXpArP9S4yaUq1itpzSz7QYZES+4rIcU0HLz9RgeWFyCTJWaFErc
7laVG9sCgYBKOtk5WlIOP4BxSd2y4cYzohgwTZIs1/2kTEn1u4eH73M1xvAlHHFB
wSF5QXgDKJ8pPAOhNWpdLO/PdtnQn91nOvTNc+ShJZzjdbneUdQVpWpoBf72uA+N
6rIVf1JBUL2p7HFHaGdUZC7KGQ+yv6ZHrE1+7202nuDvJdvGEEdFsQ==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnfKBDG/K0TnGT7Xu8q1N
45sNWvIK91SqNg8nvN2uVeKoHADTcsus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9r
yfSNDhWDWloNkpGEeWif2BnHUu46Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnV
DNfSEASVIppEBYjDX203ypmURIzU6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+t
BlcnMrkv/40DSUkehQIl2JmlFrl2Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5N
Md0KFa6CwZUUSHJqH5GFy5Y2yl4lg8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxI
GQIDAQAB
-----END PUBLIC KEY-----
",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtR/wgDqWB4Maho5V6Tjc
L/NbNfjgIh7GcgkrB5RZcVT1GTejJlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6
S8SpeJ1ofp5rBEoD/TIkvU0JOcid65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRy
BIQzB0SIxSpnrsigqNsE1E94toDMx4wovjHu/9ABAImREV7Sz83OeFF00/sghrjT
EJOD/gHf04JCn9MgNOqvSTysr9LXWg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5
yD41mi+hT8Rh+W8Je8rsiML4VMxzsb1l9303asw6suo5bLTISKNSbu1nt1NkpNxz
ywIDAQAB
-----END PUBLIC KEY-----
",
samlSPMetaDataXML => {
"sp.com" => {
samlSPMetaDataXML =>
samlSPMetaDataXML( 'sp', 'HTTP-Redirect' )
},
"sp2.com" => {
samlSPMetaDataXML =>
samlSPMetaDataXML( 'sp2', 'HTTP-Redirect' )
},
},
}
}
);
}
sub sp {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'sp.com',
portal => 'http://auth.sp.com',
authentication => 'SAML',
userDB => 'Same',
issuerDBSAMLActivation => 0,
restSessionServer => 1,
samlIDPMetaDataExportedAttributes => {
idp => {
mail => "0;mail;;",
uid => "1;uid",
cn => "0;cn"
}
},
samlIDPMetaDataOptions => {
idp => {
samlIDPMetaDataOptionsEncryptionMode => 'none',
samlIDPMetaDataOptionsSSOBinding => 'redirect',
samlIDPMetaDataOptionsSLOBinding => 'redirect',
samlIDPMetaDataOptionsSignSSOMessage => 1,
samlIDPMetaDataOptionsSignSLOMessage => 1,
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
samlIDPMetaDataOptionsForceUTF8 => 1,
}
},
samlIDPMetaDataExportedAttributes => {
idp => {
"uid" => "0;uid;;",
"cn" => "1;cn;;",
},
},
samlIDPMetaDataXML => {
idp => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
}
},
samlOrganizationDisplayName => "SP",
samlOrganizationName => "SP",
samlOrganizationURL => "http://www.sp.com",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
qwIDAQAB
-----END PUBLIC KEY-----
",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
+wIDAQAB
-----END PUBLIC KEY-----
",
samlSPSSODescriptorAuthnRequestsSigned => 1,
},
}
);
}
sub sp2 {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'sp2.com',
portal => 'http://auth.sp2.com',
authentication => 'SAML',
userDB => 'Same',
issuerDBSAMLActivation => 0,
restSessionServer => 1,
samlIDPMetaDataExportedAttributes => {
idp => {
mail => "0;mail;;",
uid => "1;uid",
cn => "0;cn"
}
},
samlIDPMetaDataOptions => {
idp => {
samlIDPMetaDataOptionsEncryptionMode => 'none',
samlIDPMetaDataOptionsSSOBinding => 'redirect',
samlIDPMetaDataOptionsSLOBinding => 'redirect',
samlIDPMetaDataOptionsSignSSOMessage => 1,
samlIDPMetaDataOptionsSignSLOMessage => 1,
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
samlIDPMetaDataOptionsForceUTF8 => 1,
}
},
samlIDPMetaDataExportedAttributes => {
idp => {
"uid" => "0;uid;;",
"cn" => "1;cn;;",
},
},
samlIDPMetaDataXML => {
idp => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
}
},
samlOrganizationDisplayName => "SP",
samlOrganizationName => "SP",
samlOrganizationURL => "http://www.sp2.com",
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
qwIDAQAB
-----END PUBLIC KEY-----
",
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
-----END RSA PRIVATE KEY-----
",
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
-----END RSA PRIVATE KEY-----
",
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
+wIDAQAB
-----END PUBLIC KEY-----
",
samlSPSSODescriptorAuthnRequestsSigned => 1,
},
}
);
}

View File

@ -72,7 +72,7 @@ sub iniCmb {
my $res = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
requireToken => 1,
requireToken => '$ipAddr eq "127.0.0.1"',
useSafeJail => 1,
authentication => 'Combination',
userDB => 'Same',

View File

@ -31,7 +31,7 @@ SKIP: {
userDB => 'Same',
passwordDB => 'Demo',
captcha_mail_enabled => 0,
requireToken => 1,
requireToken => '$ipAddr eq "127.0.0.1"',
portalDisplayResetPassword => 1,
portalMainLogo => 'common/logos/logo_llng_old.png',
}

View File

@ -124,6 +124,7 @@ count(1);
# Request with good VH & user
$query =~
s/url=http%3A%2F%2Ftry.example.com/url=http%3A%2F%2Ftest1.example.com/;
ok(
$res = $client->_post(
'/checkuser',
@ -140,8 +141,65 @@ count(1);
expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok( $res->[2]->[0] =~ m%value="http://test1.example.com/"%, 'Found well formatted url' )
or explain( $res->[2]->[0], 'Well formatted url' );
count(2);
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok(
$res->[2]->[0] =~
m%<div class="alert alert-success"><b><span trspan="allowed"></span></b></div>%,
'Found trspan="allowed"'
) or explain( $res->[2]->[0], 'trspan="allowed"' );
ok( $res->[2]->[0] =~ m%<span trspan="headers">%, 'Found trspan="headers"' )
or explain( $res->[2]->[0], 'trspan="headers"' );
ok( $res->[2]->[0] =~ m%<span trspan="groups_sso">%,
'Found trspan="groups_sso"' )
or explain( $res->[2]->[0], 'trspan="groups_sso"' );
ok( $res->[2]->[0] =~ m%<span trspan="macros">%, 'Found trspan="macros"' )
or explain( $res->[2]->[0], 'trspan="macros"' );
ok( $res->[2]->[0] =~ m%<span trspan="attributes">%,
'Found trspan="attributes"' )
or explain( $res->[2]->[0], 'trspan="attributes"' );
ok( $res->[2]->[0] =~ m%<td class="align-middle">Auth-User</td>%,
'Found Auth-User' )
or explain( $res->[2]->[0], 'Header Key: Auth-User' );
ok( $res->[2]->[0] =~ m%<td class="align-middle">rtyler</td>%, 'Found rtyler' )
or explain( $res->[2]->[0], 'Header Value: rtyler' );
ok( $res->[2]->[0] =~ m%<td class="align-middle">su</td>%, 'Found su' )
or explain( $res->[2]->[0], 'SSO Groups: su' );
ok( $res->[2]->[0] =~ m%<td class="align-middle">_whatToTrace</td>%,
'Found _whatToTrace' )
or explain( $res->[2]->[0], 'Macro Key _whatToTrace' );
ok( $res->[2]->[0] =~ m%<td class="text-left">uid</td>%, 'Found uid' )
or explain( $res->[2]->[0], 'Attribute Value uid' );
count(11);
# Request with short VH url & user
$query =~
s/url=http%3A%2F%2Ftest1.example.com/url=http%3A%2F%2Ftest1:1234/;
ok(
$res = $client->_post(
'/checkuser',
IO::String->new($query),
cookie => "lemonldap=$id",
length => length($query),
accept => 'text/html',
),
'POST checkuser'
);
count(1);
( $host, $url, $query ) =
expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok( $res->[2]->[0] =~ m%value="http://test1.example.com:1234/"%, 'Found well formatted url' )
or explain( $res->[2]->[0], 'Well formatted url' );
count(2);
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok(

View File

@ -170,7 +170,7 @@ to test content _(to launch a `expectForm()` for example)_.
Same as `_get` except that a body is required. $body must be a file handle.
Example with IO::String:
ok(
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),

View File

@ -660,7 +660,7 @@ sub _get {
Same as C<_get> except that a body is required. $body must be a file handle.
Example with IO::String:
ok(
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),

View File

@ -49,7 +49,7 @@
# Main package
#==============================================================================
Name: lemonldap-ng
Version: 2.0.2
Version: 2.0.3
Release: %{?pre_release:0.}1%{?pre_release:.%{pre_release}}%{?dist}
Summary: LemonLDAP-NG WebSSO
License: GPLv2+

View File

@ -12,7 +12,7 @@
use LWP::UserAgent;
use JSON;
my $milestone = '2.0.2';
my $milestone = '2.0.3';
my @cat = ( 'Bug', 'New feature', 'Improvement' );
open F, "$ENV{HOME}/.ow2-token" or die "Unable to get OW2 token ($!)";

View File

@ -78,8 +78,7 @@ for ( my $i = 0 ; $i < NB ; $i++ ) {
print "Result
+-----+-----------+----------+---------+-----------------------------------------+
| Req | Auth form | Post req | Menu | 5 access to test1.example.com
|
| Req | Auth form | Post req | Menu | 5 access to test1.example.com |
+-----+-----------+----------+---------+-----------------------------------------+
";