From 632988787115daef75a4851c6d6d340174f7965b Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 27 Sep 2019 23:13:20 +0200 Subject: [PATCH 01/21] Fix returned values - Propage #1954 --- .../lib/Lemonldap/NG/Handler/Lib/CDA.pm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm index d078258d5..359fe7654 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm @@ -2,13 +2,13 @@ package Lemonldap::NG::Handler::Lib::CDA; use strict; -our $VERSION = '2.0.6'; +our $VERSION = '2.0.7'; sub run { my ( $class, $req, $rule, $protection ) = @_; my $uri = $req->{env}->{REQUEST_URI}; my $cn = $class->tsv->{cookieName}; - my ( $id, $session ); + my ( $id, $ret, $session ); if ( $uri =~ s/[\?&;]${cn}cda=(\w+)$//oi ) { if ( $id = $class->fetchId($req) and $session = $class->retrieveSession( $req, $id ) ) @@ -48,8 +48,10 @@ sub run { return $class->REDIRECT; } } - return $class->Lemonldap::NG::Handler::Main::run( $req, $rule, - $protection ); + ( $ret, $session ) = + $class->Lemonldap::NG::Handler::Main::run( $req, $rule, $protection ); + + return $ret; } ## @rmethod protected hash getCDAInfos(id) From 892516d55ed0baf94a222ad6d6cfd4ab4241e21b Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 12:10:33 +0200 Subject: [PATCH 02/21] Typo --- lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t | 2 +- lemonldap-ng-handler/t/51-Lemonldap-NG-Handler-Zimbra.t | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t b/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t index 8850b8bf7..7384edd5a 100644 --- a/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t +++ b/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t @@ -15,7 +15,7 @@ my $dir = dirname( abs_path($0) ); print $ini "[all] logger = Lemonldap::NG::Common::Logger::Std -logLeval = error +logLevel = error [configuration] type=File dirName=$dir diff --git a/lemonldap-ng-handler/t/51-Lemonldap-NG-Handler-Zimbra.t b/lemonldap-ng-handler/t/51-Lemonldap-NG-Handler-Zimbra.t index e64a8bec1..8ec935e9a 100644 --- a/lemonldap-ng-handler/t/51-Lemonldap-NG-Handler-Zimbra.t +++ b/lemonldap-ng-handler/t/51-Lemonldap-NG-Handler-Zimbra.t @@ -15,6 +15,7 @@ my $dir = dirname( abs_path($0) ); print $ini "[all] logger = Lemonldap::NG::Common::Logger::Std +logLevel = error [configuration] type=File dirName=$dir From 32a0d0944a625659a05048ec1832acbed58b705c Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 12:11:07 +0200 Subject: [PATCH 03/21] Append ZimbraPreAuth handler test (#1954) --- lemonldap-ng-handler/MANIFEST | 1 + .../t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t | 60 +++++++++++++++++++ lemonldap-ng-portal/MANIFEST | 1 + 3 files changed, 62 insertions(+) create mode 100644 lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST index 1b68bd1e4..20a1ce86f 100644 --- a/lemonldap-ng-handler/MANIFEST +++ b/lemonldap-ng-handler/MANIFEST @@ -76,6 +76,7 @@ t/64-Lemonldap-NG-Handler-PSGI-DevOps.t t/65-Lemonldap-NG-Handler-PSGI-ServiceToken.t t/66-Lemonldap-NG-Handler-PSGI-wildcard.t t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t +t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t t/99-pod.t t/lmConf-1.json t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock diff --git a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t new file mode 100644 index 000000000..e645bdc5e --- /dev/null +++ b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t @@ -0,0 +1,60 @@ +use Test::More; + +BEGIN { + require 't/test-psgi-lib.pm'; +} + +my $maintests = 4; + +SKIP: { + eval { require Digest::HMAC_SHA1; }; + if ($@) { + skip 'Digest::HMAC_SHA1 not found', $maintests; + } + init( + 'Lemonldap::NG::Handler::Server', + { + logLevel => 'error', + zimbraPreAuthKey => '1234567890', + vhostOptions => { + 'test1.example.com' => { + vhostHttps => 0, + vhostPort => 80, + vhostMaintenance => 0, + vhostServiceTokenTTL => -1, + }, + }, + exportedHeaders => { + 'test1.example.com' => { + 'Auth-User' => '$uid', + }, + } + } + ); + my $timestamp = time() * 1000; + my $value = + Digest::HMAC_SHA1::hmac_sha1_hex( "dwho|id|0|$timestamp", '1234567890' ); + ok( + $res = $client->_get( + '/zimbrasso', undef, + 'test1.example.com', "lemonldap=$sessionId", + VHOSTTYPE => 'ZimbraPreAuth', + ), + 'Query' + ); + ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 ); + + # Check headers + %h = @{ $res->[1] }; + ok( + $h{'Location'} =~ +m%^/service/preauth\?account=dwho&by=id×tamp=$timestamp&expires=0&preauth=$value$%, + 'Header Location is set to Zimbra URL' + ) or explain( \%h, 'Location => "Zimbra URL' ); + ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) + or explain( \%h, 'Auth-User => "dwho"' ); + count(4); +} + +done_testing( count() ); +clean(); diff --git a/lemonldap-ng-portal/MANIFEST b/lemonldap-ng-portal/MANIFEST index 11ed7872b..7fb3e37fc 100644 --- a/lemonldap-ng-portal/MANIFEST +++ b/lemonldap-ng-portal/MANIFEST @@ -419,6 +419,7 @@ site/templates/common/mail/en.json site/templates/common/mail/fi.json site/templates/common/mail/fr.json site/templates/common/mail/it.json +site/templates/common/mail/ms.json site/templates/common/mail/vi.json site/templates/common/mail/zh_CN.json site/templates/common/mail_2fcode.tpl From 200546b2e4bfddfb69df19aab4ac27b27016affb Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 19:18:53 +0200 Subject: [PATCH 04/21] Fix logger --- .../lib/Lemonldap/NG/Handler/Lib/SecureToken.pm | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm index e46296bd4..c7832e1d6 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm @@ -14,7 +14,7 @@ use strict; use Cache::Memcached; use Apache::Session::Generate::MD5; -our $VERSION = '2.0.6'; +our $VERSION = '2.0.7'; # Shared variables our $secureTokenMemcachedConnection; @@ -32,7 +32,7 @@ BEGIN { # @return Apache2::Const value ($class->OK, $class->FORBIDDEN, $class->REDIRECT or $class->SERVER_ERROR) sub run { my $class = shift; - my $r = $_[0]; + my $r = shift; my ( $ret, $session ) = $class->Lemonldap::NG::Handler::Main::run($r); # Continue only if user is authorized @@ -150,9 +150,7 @@ sub _createMemcachedConnection { # @return Token key sub _setToken { my ( $class, $value, $secureTokenExpiration ) = @_; - my $key = Apache::Session::Generate::MD5::generate(); - my $res = $secureTokenMemcachedConnection->set( $key, $value, $secureTokenExpiration ); @@ -173,7 +171,6 @@ sub _setToken { # @return result sub _deleteToken { my ( $class, $key ) = @_; - my $res = $secureTokenMemcachedConnection->delete($key); unless ($res) { @@ -192,16 +189,13 @@ sub _deleteToken { # @return result sub _isAlive { my ($class) = @_; - return 0 unless defined $secureTokenMemcachedConnection; - my $stats = $secureTokenMemcachedConnection->stats(); if ( $stats and defined $stats->{'total'} ) { my $total_c = $stats->{'total'}->{'connection_structures'}; my $total_i = $stats->{'total'}->{'total_items'}; - - $class->logger->debug->( + $class->logger->debug( "Memcached connection is alive ($total_c connections / $total_i items)" ); From abf27ad7ac04939929dea360301ff9fe4d091e58 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 19:45:07 +0200 Subject: [PATCH 05/21] Fix secureToken with PSGI servers --- .../lib/Lemonldap/NG/Handler/Lib/SecureToken.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm index c7832e1d6..5d5f15c15 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm @@ -106,7 +106,7 @@ sub run { # Remove token eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} ); - if ( $INC{"Apache2/Filter.pm"} ) { + if ( $INC{"Apache2/Filter.pm"} and defined $r->{env}->{'psgi.r'} ) { $r->{env}->{'psgi.r'}->add_output_filter( sub { my $f = shift; From b969f5b876ae7e0a4718fffd90dc4cb18a5075b9 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 19:45:13 +0200 Subject: [PATCH 06/21] Typo --- lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t | 1 - lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t b/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t index 7384edd5a..256b70575 100644 --- a/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t +++ b/lemonldap-ng-handler/t/50-Lemonldap-NG-Handler-SecureToken.t @@ -32,7 +32,6 @@ open STDERR, '>/dev/null'; # Insert your test code below, the Test::More module is used here so read # its man page ( perldoc Test::More ) for help writing this test script. - SKIP: { eval { require Cache::Memcached }; skip diff --git a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t index e645bdc5e..10d345b1c 100644 --- a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t +++ b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t @@ -50,7 +50,7 @@ SKIP: { $h{'Location'} =~ m%^/service/preauth\?account=dwho&by=id×tamp=$timestamp&expires=0&preauth=$value$%, 'Header Location is set to Zimbra URL' - ) or explain( \%h, 'Location => "Zimbra URL' ); + ) or explain( \%h, 'Location => "Zimbra URL"' ); ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) or explain( \%h, 'Auth-User => "dwho"' ); count(4); From d1d6b4f19256e5068728ef23eaf1926776cbe2ea Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 28 Sep 2019 19:46:10 +0200 Subject: [PATCH 07/21] Append SecureToken handler unit test --- lemonldap-ng-handler/MANIFEST | 1 + .../t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t | 3 +- ...69-Lemonldap-NG-Handler-PSGI-SecureToken.t | 59 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST index 20a1ce86f..2b22803ce 100644 --- a/lemonldap-ng-handler/MANIFEST +++ b/lemonldap-ng-handler/MANIFEST @@ -77,6 +77,7 @@ t/65-Lemonldap-NG-Handler-PSGI-ServiceToken.t t/66-Lemonldap-NG-Handler-PSGI-wildcard.t t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t +t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t t/99-pod.t t/lmConf-1.json t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock diff --git a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t index 10d345b1c..3818adada 100644 --- a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t +++ b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t @@ -16,6 +16,7 @@ SKIP: { { logLevel => 'error', zimbraPreAuthKey => '1234567890', + zimbraSsoUrl => 'testsso', vhostOptions => { 'test1.example.com' => { vhostHttps => 0, @@ -36,7 +37,7 @@ SKIP: { Digest::HMAC_SHA1::hmac_sha1_hex( "dwho|id|0|$timestamp", '1234567890' ); ok( $res = $client->_get( - '/zimbrasso', undef, + '/testsso', undef, 'test1.example.com', "lemonldap=$sessionId", VHOSTTYPE => 'ZimbraPreAuth', ), diff --git a/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t new file mode 100644 index 000000000..b8042d8ed --- /dev/null +++ b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t @@ -0,0 +1,59 @@ +use Test::More; + +BEGIN { + require 't/test-psgi-lib.pm'; +} + +my $maintests = 4; + +SKIP: { + eval { require Cache::Memcached; }; + if ($@) { + skip 'Cache::Memcached not found', $maintests; + } + eval { require Apache::Session::Generate::MD5; }; + if ($@) { + skip 'Apache::Session::Generate::MD5 not found', $maintests; + } + init( + 'Lemonldap::NG::Handler::Server', + { + logLevel => 'error', + secureTokenUrls => ['/secured'], + vhostOptions => { + 'test1.example.com' => { + vhostHttps => 0, + vhostPort => 80, + vhostMaintenance => 0, + vhostServiceTokenTTL => -1, + }, + }, + exportedHeaders => { + 'test1.example.com' => { + 'Auth-User' => '$uid', + }, + } + } + ); + + ok( + $res = $client->_get( + '/secured', undef, + 'test1.example.com', "lemonldap=$sessionId", + VHOSTTYPE => 'SecureToken', + ), + 'Auth query' + ); + ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 ); + + # Check headers + %h = @{ $res->[1] }; + ok( $h{'Auth-Token'} =~ m%[0-9a-f]{32}%, 'Header "Auth-Token" found' ) + or explain( \%h, 'Auth-Token => "md5 value"' ); + ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) + or explain( \%h, 'Auth-User => "dwho"' ); + count(4); +} + +done_testing( count() ); +clean(); From b6d517d3d778b6daa2c74979cc5855b52675f5d3 Mon Sep 17 00:00:00 2001 From: Xavier Date: Sun, 29 Sep 2019 08:30:39 +0200 Subject: [PATCH 08/21] Fix tests --- .../t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t index b8042d8ed..b98b0c6f7 100644 --- a/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t +++ b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t @@ -52,8 +52,8 @@ SKIP: { or explain( \%h, 'Auth-Token => "md5 value"' ); ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) or explain( \%h, 'Auth-User => "dwho"' ); - count(4); } +count($maintests); done_testing( count() ); clean(); From 9102cc2acc59076a411efec7cecdeef8cd827ec1 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sun, 29 Sep 2019 12:50:46 +0200 Subject: [PATCH 09/21] Typo --- .../lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm | 4 +--- .../lib/Lemonldap/NG/Handler/Lib/SecureToken.pm | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm index 437129c49..60feaf544 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm @@ -15,6 +15,7 @@ our $VERSION = '2.0.6'; our @ISA = ('Exporter'); our @EXPORT = qw(fetchId retrieveSession createSession hideCookie goToPortal); our @EXPORT_OK = @EXPORT; +our $_ua; ## @rmethod protected fetchId # Get user session id from Authorization header @@ -162,8 +163,6 @@ sub goToPortal { } } -our $_ua; - sub ua { my ($class) = @_; return $_ua if ($_ua); @@ -173,7 +172,6 @@ sub ua { } ); - # TODO: auth basic return $_ua; } diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm index 5d5f15c15..6608c3989 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm @@ -121,7 +121,6 @@ sub run { ); } - # Return $class->OK return $class->OK; } From 8fbbf89d5c65d0b920fc02720be3cd994e39fdab Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sun, 29 Sep 2019 13:14:20 +0200 Subject: [PATCH 10/21] Improve handler unit tests --- .../t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t | 31 +++++++++-- ...69-Lemonldap-NG-Handler-PSGI-SecureToken.t | 54 ++++++++++++++++--- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t index 3818adada..1b8d198aa 100644 --- a/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t +++ b/lemonldap-ng-handler/t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t @@ -4,7 +4,7 @@ BEGIN { require 't/test-psgi-lib.pm'; } -my $maintests = 4; +my $maintests = 8; SKIP: { eval { require Digest::HMAC_SHA1; }; @@ -16,7 +16,8 @@ SKIP: { { logLevel => 'error', zimbraPreAuthKey => '1234567890', - zimbraSsoUrl => 'testsso', + zimbraUrl => '/service/preauthtest', + zimbraSsoUrl => '^/testsso', vhostOptions => { 'test1.example.com' => { vhostHttps => 0, @@ -32,6 +33,26 @@ SKIP: { } } ); + + # Request a non-Zimbra URL + ok( + $res = $client->_get( + '/test', undef, + 'test1.example.com', "lemonldap=$sessionId", + VHOSTTYPE => 'ZimbraPreAuth', + ), + 'Non-Zimbra URL Query' + ); + ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 ); + + # Check headers + %h = @{ $res->[1] }; + ok( !defined $h{'Location'}, 'Location is undefined' ) + or explain( \%h, 'Location => "URL"' ); + ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) + or explain( \%h, 'Auth-User => "dwho"' ); + + # Request Zimbra URL my $timestamp = time() * 1000; my $value = Digest::HMAC_SHA1::hmac_sha1_hex( "dwho|id|0|$timestamp", '1234567890' ); @@ -41,7 +62,7 @@ SKIP: { 'test1.example.com', "lemonldap=$sessionId", VHOSTTYPE => 'ZimbraPreAuth', ), - 'Query' + 'Zimbra URL Query' ); ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 ); @@ -49,13 +70,13 @@ SKIP: { %h = @{ $res->[1] }; ok( $h{'Location'} =~ -m%^/service/preauth\?account=dwho&by=id×tamp=$timestamp&expires=0&preauth=$value$%, +m%^/service/preauthtest\?account=dwho&by=id×tamp=$timestamp&expires=0&preauth=$value$%, 'Header Location is set to Zimbra URL' ) or explain( \%h, 'Location => "Zimbra URL"' ); ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) or explain( \%h, 'Auth-User => "dwho"' ); - count(4); } +count($maintests); done_testing( count() ); clean(); diff --git a/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t index b98b0c6f7..50c62e041 100644 --- a/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t +++ b/lemonldap-ng-handler/t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t @@ -4,7 +4,7 @@ BEGIN { require 't/test-psgi-lib.pm'; } -my $maintests = 4; +my $maintests = 12; SKIP: { eval { require Cache::Memcached; }; @@ -18,9 +18,10 @@ SKIP: { init( 'Lemonldap::NG::Handler::Server', { - logLevel => 'error', - secureTokenUrls => ['/secured'], - vhostOptions => { + logLevel => 'error', + secureTokenUrls => [ '^/secured$', '/test$' ], + secureTokenHeader => 'AuthToken', + vhostOptions => { 'test1.example.com' => { vhostHttps => 0, vhostPort => 80, @@ -36,22 +37,61 @@ SKIP: { } ); + ## Request secured URLs + # First URL ok( $res = $client->_get( '/secured', undef, 'test1.example.com', "lemonldap=$sessionId", VHOSTTYPE => 'SecureToken', ), - 'Auth query' + 'Auth secured URL query 1' ); ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 ); # Check headers %h = @{ $res->[1] }; - ok( $h{'Auth-Token'} =~ m%[0-9a-f]{32}%, 'Header "Auth-Token" found' ) - or explain( \%h, 'Auth-Token => "md5 value"' ); + ok( $h{'AuthToken'} =~ m%[0-9a-f]{32}%, 'Header "AuthToken" found' ) + or explain( \%h, 'AuthToken => "md5 value"' ); ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) or explain( \%h, 'Auth-User => "dwho"' ); + + # Second URL + ok( + $res = $client->_get( + '/try/test', undef, + 'test1.example.com', "lemonldap=$sessionId", + VHOSTTYPE => 'SecureToken', + ), + 'Auth secured URL query 2' + ); + ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 ); + + # Check headers + %h = @{ $res->[1] }; + ok( $h{'AuthToken'} =~ m%[0-9a-f]{32}%, 'Header "AuthToken" found' ) + or explain( \%h, 'AuthToken => "md5 value"' ); + ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) + or explain( \%h, 'Auth-User => "dwho"' ); + + ## Request an unsecured URL + ok( + $res = $client->_get( + '/try', undef, + 'test1.example.com', "lemonldap=$sessionId", + VHOSTTYPE => 'SecureToken', + ), + 'Auth unsecured URL query' + ); + ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 ); + + # Check headers + %h = @{ $res->[1] }; + ok( !defined $h{'AuthToken'}, 'Header "AuthToken" not found' ) + or explain( \%h, 'AuthToken => "md5 value"' ); + ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) + or explain( \%h, 'Auth-User => "dwho"' ); + } count($maintests); From 7534692a874d9ee3da6fdfcd113ddc70f1b48804 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sun, 29 Sep 2019 13:43:35 +0200 Subject: [PATCH 11/21] WIP - Append AuthBasic hanlder unit test --- lemonldap-ng-handler/MANIFEST | 1 + .../70-Lemonldap-NG-Handler-PSGI-AuthBasic.t | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 lemonldap-ng-handler/t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST index 2b22803ce..76fd69c62 100644 --- a/lemonldap-ng-handler/MANIFEST +++ b/lemonldap-ng-handler/MANIFEST @@ -78,6 +78,7 @@ t/66-Lemonldap-NG-Handler-PSGI-wildcard.t t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t +t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t t/99-pod.t t/lmConf-1.json t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock diff --git a/lemonldap-ng-handler/t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t b/lemonldap-ng-handler/t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t new file mode 100644 index 000000000..eee772101 --- /dev/null +++ b/lemonldap-ng-handler/t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t @@ -0,0 +1,68 @@ +use Test::More; +use MIME::Base64; + +BEGIN { + require 't/test-psgi-lib.pm'; +} + +my $maintests = 3; + +init( + 'Lemonldap::NG::Handler::Server', + { + # authentication => 'Demo', + # userDB => 'Same', + # restSessionServer => 1, + logLevel => 'error', + vhostOptions => { + 'test1.example.com' => { + vhostHttps => 0, + vhostPort => 80, + vhostMaintenance => 0, + vhostServiceTokenTTL => -1, + }, + }, + exportedHeaders => { + 'test1.example.com' => { + 'Auth-User' => '$uid', + }, + } + } +); + +ok( + $res = $client->_get( + '/', undef, 'test1.example.com', undef, VHOSTTYPE => 'AuthBasic', + ), + 'Query' +); +ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 302 ); + +# Check headers +%h = @{ $res->[1] }; +ok( + $h{'WWW-Authenticate'} =~ m%^Basic realm="LemonLDAP::NG"$%, + 'Header WWW-Authenticate is set to Basic realm="LemonLDAP::NG"' +) or explain( \%h, 'WWW-Authenticate => realm' ); + +# my $login = encode_base64("dwho:dwho"); +# ok( +# $res = $client->_get( +# '/', undef, 'test1.example.com', undef, +# VHOSTTYPE => 'AuthBasic', +# HTTP_X_FORWARDED_FOR => '127.0.0.1', +# HTTP_AUTHORIZATION => "Basic $login" +# ), +# 'AuthBasic query' +# ); +# +# print STDERR Data::Dumper::Dumper($res); +# +# # Check headers +# %h = @{ $res->[1] }; +# ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' ) +# or explain( \%h, 'Auth-User => "dwho"' ); + +count($maintests); +done_testing( count() ); +clean(); From 461cd51e45d5b7fee9b98d3737b28137243625d4 Mon Sep 17 00:00:00 2001 From: Xavier Date: Sun, 9 Jun 2019 09:11:10 +0200 Subject: [PATCH 12/21] Try to fix #1785 without breaking pdata --- .../lib/Lemonldap/NG/Portal/Issuer/CAS.pm | 6 ++- .../lib/Lemonldap/NG/Portal/Main/Init.pm | 27 +++++++----- .../lib/Lemonldap/NG/Portal/Main/Issuer.pm | 42 +++++++++++++++---- .../lib/Lemonldap/NG/Portal/Main/Process.pm | 26 ++++++++---- .../lib/Lemonldap/NG/Portal/Main/Request.pm | 3 +- .../t/30-Auth-and-issuer-SAML-POST.t | 3 +- 6 files changed, 76 insertions(+), 31 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm index 9040bc417..8384ea8c4 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm @@ -85,7 +85,11 @@ sub storeEnvAndCheckGateway { $self->logger->debug( "Gateway mode requested, redirect without authentication"); $req->response( [ 302, [ Location => $service ], [] ] ); - $req->pdata( {} ); + for my $s ( $self->ipath, $self->ipath . 'Path' ) { + $self->logger->debug("Removing $s from pdata") + if delete $req->pdata->{$s}; + } + return PE_SENDRESPONSE; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm index c6bb1856e..c0a356cfa 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm @@ -140,24 +140,24 @@ sub init { # psgi.js ->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] ) - ->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] ) + ->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] ) # portal.css ->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] ) - ->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] ) + ->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] ) # lmerror ->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) - ->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) + ->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] ) # Core REST API - ->addUnauthRoute( ping => 'pleaseAuth', ['GET'] ) + ->addUnauthRoute( ping => 'pleaseAuth', ['GET'] ) ->addAuthRoute( ping => 'authenticated', ['GET'] ) # Refresh session ->addAuthRoute( refresh => 'refresh', ['GET'] ) - ->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] ) + ->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] ) ->addUnauthRoute( '*' => 'corsPreflight', ['OPTIONS'] ) # Logout @@ -356,11 +356,18 @@ sub reloadConf { # Clean $req->pdata after authentication push @{ $self->endAuth }, sub { - unless ( $_[0]->pdata->{keepPdata} ) { - $self->logger->debug('Cleaning pdata'); - $_[0]->pdata( {} ); - $self->userLogger->notice( $_[0]->user . ' connected' ) - if $_[0]->user; + my $tmp = $_[0]->pdata->{keepPdata} //= []; + foreach my $k ( keys %{ $_[0]->pdata } ) { + unless ( grep { $_ eq $k } @$tmp ) { + $self->logger->debug("Removing $k from pdata"); + delete $_[0]->pdata->{$k}; + } + } + $self->userLogger->notice( $_[0]->user . ' connected' ) if $_[0]->user; + if (@$tmp) { + $self->logger->debug( + 'Add ' . join( ',', @$tmp ) . ' in keepPdata' ); + $_[0]->pdata->{keepPdata} = $tmp; } return PE_OK; }; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm index f9ebdc31b..0f69adc42 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm @@ -34,9 +34,10 @@ has _ott => ( is => 'rw', lazy => 1, default => sub { - my $ott = $_[0]->{p}->loadModule('::Lib::OneTimeToken'); - my $timeout = $_[0]->{conf}->{issuersTimeout} // $_[0]->{conf}->{formTimeout}; - $ott->timeout( $timeout ); + my $ott = $_[0]->{p}->loadModule('::Lib::OneTimeToken'); + my $timeout = $_[0]->{conf}->{issuersTimeout} + // $_[0]->{conf}->{formTimeout}; + $ott->timeout($timeout); return $ott; } ); @@ -86,7 +87,9 @@ sub _redirect { $self->logger->debug('Processing _redirect'); $ir = $req->pdata->{ $self->ipath } ||= $self->storeRequest($req); $req->pdata->{ $self->ipath . 'Path' } = \@path; - $req->pdata->{keepPdata} = 1; + $self->logger->debug( + 'Add ' . $self->ipath . ', ' . $self->ipath . 'Path in keepPdata' ); + push @{ $req->pdata->{keepPdata} }, $self->ipath, $self->ipath . 'Path'; $req->{urldc} = $self->conf->{portal} . '/' . $self->path; } else { @@ -111,8 +114,7 @@ sub _redirect { # Restore urldc if auth doesn't need to dial with browser $self->restoreRequest( $req, $ir ); - delete $req->pdata->{ $self->ipath }; - delete $req->pdata->{ $self->ipath . 'Path' }; + $self->cleanPdata($req); return $self->run( @_, @path ); } : () @@ -135,8 +137,9 @@ sub _forAuthUser { # Clean pdata: keepPdata has been set, so pdata must be cleaned here $self->logger->debug('Cleaning pdata'); - $req->pdata( {} ); - $req->urlNotBase64(1) if ( ref($self) =~ /::CAS$/ ); + $self->cleanPdata($req); + + $req->maybeNotBase64(1) if ( ref($self) =~ /::CAS$/ ); $req->mustRedirect(1); return $self->p->do( $req, @@ -151,6 +154,27 @@ sub _forAuthUser { ); } +sub cleanPdata { + my ( $self, $req ) = @_; + for my $s ( $self->ipath, $self->ipath . 'Path' ) { + if ( $req->pdata->{$s} ) { + $self->logger->debug("Removing $s key from pdata"); + delete $req->pdata->{$s}; + } + } + if ( $req->pdata->{keepPdata} and ref $req->pdata->{keepPdata} ) { + @{ $req->pdata->{keepPdata} } = + grep { + $_ ne $self->ipath + and $_ ne $self->ipath . 'Path' + ? 1 + : ( $self->logger->debug("Removing $_ from keepPdata") and 0 ) + } @{ $req->pdata->{keepPdata} }; + delete $req->pdata->{keepPdata} + unless ( @{ $req->pdata->{keepPdata} } ); + } +} + sub storeRequest { my ( $self, $req ) = @_; $self->logger->debug('Store issuer request'); @@ -191,7 +215,7 @@ qq'