diff --git a/fastcgi-server/man/llng-fastcgi-server.1p b/fastcgi-server/man/llng-fastcgi-server.1p index dea827ce1..960a19d0e 100644 --- a/fastcgi-server/man/llng-fastcgi-server.1p +++ b/fastcgi-server/man/llng-fastcgi-server.1p @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "llng-fastcgi-server 1" -.TH llng-fastcgi-server 1 "2019-06-13" "perl v5.28.1" "User Contributed Perl Documentation" +.TH llng-fastcgi-server 1 "2019-06-27" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff --git a/lemonldap-ng-common/META.json b/lemonldap-ng-common/META.json index 97c960d89..5ab71f6e3 100644 --- a/lemonldap-ng-common/META.json +++ b/lemonldap-ng-common/META.json @@ -4,13 +4,13 @@ "Xavier Guimard , Clément Oudot " ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Lemonldap-NG-Common", "no_index" : { @@ -41,7 +41,8 @@ "DBI" : "0", "LWP::Protocol::https" : "0", "Net::LDAP" : "0", - "SOAP::Lite" : "0" + "SOAP::Lite" : "0", + "String::Random" : "0" }, "requires" : { "Apache::Session" : "0", diff --git a/lemonldap-ng-common/META.yml b/lemonldap-ng-common/META.yml index c7f834dc5..77f5403c1 100644 --- a/lemonldap-ng-common/META.yml +++ b/lemonldap-ng-common/META.yml @@ -9,7 +9,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: open_source meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -28,6 +28,7 @@ recommends: LWP::Protocol::https: '0' Net::LDAP: '0' SOAP::Lite: '0' + String::Random: '0' requires: Apache::Session: '0' Cache::Cache: '0' diff --git a/lemonldap-ng-common/Makefile.PL b/lemonldap-ng-common/Makefile.PL index 0c0af0207..86745216a 100644 --- a/lemonldap-ng-common/Makefile.PL +++ b/lemonldap-ng-common/Makefile.PL @@ -34,6 +34,7 @@ WriteMakefile( 'Convert::Base32' => 0, 'Cookie::Baker::XS' => 0, 'Crypt::URandom' => 0, + 'String::Random' => 0, 'DBI' => 0, 'Net::LDAP' => 0, 'SOAP::Lite' => 0, diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Cli.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Cli.pm index 8426faa0b..0985795dd 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Cli.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Cli.pm @@ -31,6 +31,9 @@ sub info { my $conf = $self->confAccess->getConf( { cfgNum => $self->cfgNum, raw => 1 } ) or die $Lemonldap::NG::Common::Conf::msg; + $conf->{cfgAuthorIP} ||= "No IP provided"; + $conf->{cfgDate} ||= 0; + $conf->{cfgLog} ||= "No log provided"; print qq{ Num : $conf->{cfgNum} Author : $conf->{cfgAuthor} diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Crypto.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Crypto.pm index 84e4156f3..627e96b83 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Crypto.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Crypto.pm @@ -12,9 +12,27 @@ use strict; use Crypt::Rijndael; use MIME::Base64; use Digest::MD5 qw(md5); +use String::Random; use bytes; our $VERSION = '2.1.0'; +my ( $newIv, $randG ); + +BEGIN { + eval { require Crypt::URandom; Crypt::URandom::urandom(16) }; + if ($@) { + $newIv = sub { return md5( rand() . time . {} ) }; + $randG = sub { + my $a = 256; + $a = unpack( "C", Crypt::URandom::urandom(1) ) while ( $a > $_[0] ); + return $a; + }; + } + else { + $newIv = sub { return Crypt::URandom::urandom(16) }; + $randG = sub { return int( rand( $_[0] ) ) }; + } +} our $msg; @@ -41,11 +59,11 @@ sub new { # @param key that secondary key # @return Crypt::Rijndael object sub _getCipher { - my ( $self, $key ) = @_; + my ( $self, $key, $iv ) = @_; $key ||= ""; - $self->{ciphers}->{$key} ||= + my $cipher = Crypt::Rijndael->new( md5( $self->{key}, $key ), $self->{mode} ); - return $self->{ciphers}->{$key}; + return $cipher; } ## @method string encrypt(string data) @@ -53,13 +71,19 @@ sub _getCipher { # @param data data to encrypt # @return encrypted data in Base64 format sub encrypt { - my ( $self, $data ) = @_; + my ( $self, $data, $low ) = @_; # pad $data so that its length be multiple of 16 bytes my $l = bytes::length($data) % 16; $data .= "\0" x ( 16 - $l ) unless ( $l == 0 ); - eval { $data = encode_base64( $self->_getCipher->encrypt($data), '' ); }; + my $iv = $low ? md5( rand() . time . {} ) : $newIv->(); + my $hmac = md5($data); + eval { + $data = + encode_base64( + $iv . $hmac . $self->_getCipher->set_iv($iv)->encrypt($data), '' ); + }; if ($@) { $msg = "Crypt::Rijndael error : $@"; return undef; @@ -81,11 +105,21 @@ sub decrypt { $data =~ s/%2F/\//ig; $data =~ s/%3D/=/ig; $data =~ s/%0A/\n/ig; - eval { $data = $self->_getCipher->decrypt( decode_base64($data) ); }; + $data = decode_base64($data); + my $iv; + $iv = bytes::substr( $data, 0, 16 ); + my $hmac = bytes::substr( $data, 16, 16 ); + $data = bytes::substr( $data, 32 ); + eval { $data = $self->_getCipher->set_iv($iv)->decrypt($data); }; + if ($@) { $msg = "Crypt::Rijndael error : $@"; return undef; } + if ( md5($data) ne $hmac ) { + $msg = "Bad MAC"; + return undef; + } else { $msg = ''; @@ -141,15 +175,30 @@ sub _cryptHex { "Lemonldap::NG::Common::Crypto::${sub}Hex error : data length must be multiple of 32"; return undef; } + my $iv; + if ( $sub eq 'encrypt' ) { + $iv = $newIv->(); + } $data = pack "H*", $data; - eval { $data = $self->_getCipher($key)->$sub($data); }; + if ( $sub eq 'decrypt' ) { + $iv = bytes::substr( $data, 0, 16 ); + $data = bytes::substr( $data, 16 ); + } + eval { $data = $self->_getCipher($key)->set_iv($iv)->$sub($data); }; if ($@) { $msg = "Crypt::Rijndael error : $@"; return undef; } + if ( $sub eq 'encrypt' ) { + $data = $iv . $data; + } $msg = ""; $data = unpack "H*", $data; return $data; } +sub srandom { + return String::Random->new( rand_gen => $randG ); +} + 1; diff --git a/lemonldap-ng-common/t/35-Common-Crypto.t b/lemonldap-ng-common/t/35-Common-Crypto.t index f926a55b7..3d682d7f6 100644 --- a/lemonldap-ng-common/t/35-Common-Crypto.t +++ b/lemonldap-ng-common/t/35-Common-Crypto.t @@ -5,7 +5,7 @@ # change 'tests => 1' to 'tests => last_test_to_print'; -use Test::More tests => 21; +use Test::More tests => 22; use Digest::MD5 qw(md5 md5_hex md5_base64); use strict; @@ -30,7 +30,11 @@ foreach my $i ( 1 .. 17 ) { my $s = ''; $s = join( '', map { chr( int( rand(94) ) + 33 ) } ( 1 .. $i ) ); ok( $c->decrypt( $c->encrypt($s) ) eq $s, - "Test of base64 encrypting with $i characters string" ); + "Test of base64 encrypting with $i characters string" ) + or diag "Source: $s\nCypher: " + . $c->encrypt($s) + . "\nUncipher:" + . $c->decrypt( $c->encrypt($s) ); } my $data = md5_hex(rand); @@ -42,6 +46,9 @@ ok( # Test a long value, and replace carriage return by %0A my $long = "f5a1f72e7ab2f7712855a068af0066f36bfcf2c87e6feb9cf4200da1868e1dfe"; -my $cryptedlong = -"Da6sYxp9NCXv8+8TirqHmPWwTQHyEGmkCBGCLCX/81dPSMwIQVQNV7X9KG3RrKZfyRmzJR6DZYdU%0Ab75+VH3+CA=="; -ok( $c->decrypt($cryptedlong) eq $long, "Test of long value encrypting" ); +ok( $c->decrypt( $c->encrypt($long) ) eq $long, + "Test of long value encrypting" ); +ok( + $c->decryptHex( $c->encryptHex($long) ) eq $long, + "Test of long value encrypting (hex)" +); diff --git a/lemonldap-ng-handler/META.json b/lemonldap-ng-handler/META.json index 75c7816ba..7e2724114 100644 --- a/lemonldap-ng-handler/META.json +++ b/lemonldap-ng-handler/META.json @@ -4,13 +4,13 @@ "Xavier Guimard , Clément Oudot " ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Lemonldap-NG-Handler", "no_index" : { diff --git a/lemonldap-ng-handler/META.yml b/lemonldap-ng-handler/META.yml index a98a2862d..85ea19e16 100644 --- a/lemonldap-ng-handler/META.yml +++ b/lemonldap-ng-handler/META.yml @@ -11,7 +11,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: open_source meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm index 94b75db63..de428884e 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm @@ -103,7 +103,7 @@ sub build_jail { # Import crypto methods for jail sub encrypt { - return &Lemonldap::NG::Handler::Main::tsv->{cipher}->encrypt(@_); + return &Lemonldap::NG::Handler::Main::tsv->{cipher}->encrypt( $_[0], 1 ); } sub token { diff --git a/lemonldap-ng-manager/META.json b/lemonldap-ng-manager/META.json index 2118d932e..f2525b956 100644 --- a/lemonldap-ng-manager/META.json +++ b/lemonldap-ng-manager/META.json @@ -4,13 +4,13 @@ "Xavier Guimard , Clément Oudot " ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Lemonldap-NG-Manager", "no_index" : { diff --git a/lemonldap-ng-manager/META.yml b/lemonldap-ng-manager/META.yml index f5812ae4a..df2febb1d 100644 --- a/lemonldap-ng-manager/META.yml +++ b/lemonldap-ng-manager/META.yml @@ -9,7 +9,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: open_source meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm index 51f2a392a..35b6bb1a8 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm @@ -11,7 +11,7 @@ sub perlExpr { [ '&encrypt', '&token' ] ); $cpt->share_from( 'Lemonldap::NG::Common::Safelib', $Lemonldap::NG::Common::Safelib::functions ); - $cpt->reval("BEGIN { warnings->unimport; } $val"); + $cpt->reval("BEGIN { 'warnings'->unimport; } $val"); my $err = join( '', grep( { $_ =~ /Undefined subroutine/ ? () : $_; } split( /\n/, $@, 0 ) ) diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm index 029b5294c..f0e7e8691 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm @@ -18,7 +18,7 @@ sub perlExpr { [ '&encrypt', '&token' ] ); $cpt->share_from( 'Lemonldap::NG::Common::Safelib', $Lemonldap::NG::Common::Safelib::functions ); - $cpt->reval("BEGIN { warnings->unimport; } $val"); + $cpt->reval("BEGIN { 'warnings'->unimport; } $val"); my $err = join( '', grep { $_ =~ /Undefined subroutine/ ? () : $_ } split( /\n/, $@ ) ); return $err ? ( 1, "__badExpression__: $err" ) : (1); diff --git a/lemonldap-ng-manager/scripts/lmConfigEditor b/lemonldap-ng-manager/scripts/lmConfigEditor index 1d2ab7968..a1ac31089 100644 --- a/lemonldap-ng-manager/scripts/lmConfigEditor +++ b/lemonldap-ng-manager/scripts/lmConfigEditor @@ -3,6 +3,7 @@ use Lemonldap::NG::Common::Conf; use Lemonldap::NG::Common::Conf::Constants; use Lemonldap::NG::Manager::Conf::Parser; +use Lemonldap::NG::Handler::Main::Jail; use Data::Dumper; use English qw(-no_match_vars); use File::Temp; diff --git a/lemonldap-ng-manager/site/htdocs/static/languages/fr.json b/lemonldap-ng-manager/site/htdocs/static/languages/fr.json index f892856ad..ff9819daf 100644 --- a/lemonldap-ng-manager/site/htdocs/static/languages/fr.json +++ b/lemonldap-ng-manager/site/htdocs/static/languages/fr.json @@ -301,7 +301,7 @@ "hideTree":"Masquer l'arbre", "httpOnly":"Protection contre javascript", "https":"HTTPS", -"impersonation":"Usurpation d'identité", +"impersonation":"Simulation d'identité", "impersonationRule":"Règle d'utilisation", "impersonationIdRule":"Règle d'utilisation des identités", "impersonationHiddenAttributes":"Attributs masqués", diff --git a/lemonldap-ng-portal/META.json b/lemonldap-ng-portal/META.json index 02a406fe6..199d9626c 100644 --- a/lemonldap-ng-portal/META.json +++ b/lemonldap-ng-portal/META.json @@ -4,13 +4,13 @@ "Xavier Guimard , Clément Oudot " ], "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Lemonldap-NG-Portal", "no_index" : { @@ -57,7 +57,6 @@ "Net::OpenID::Consumer" : "0", "Net::OpenID::Server" : "0", "SOAP::Lite" : "0", - "String::Random" : "0", "Unicode::String" : "0", "Web::ID" : "0" }, diff --git a/lemonldap-ng-portal/META.yml b/lemonldap-ng-portal/META.yml index 7ae93269a..3f9183181 100644 --- a/lemonldap-ng-portal/META.yml +++ b/lemonldap-ng-portal/META.yml @@ -13,7 +13,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: open_source meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -43,7 +43,6 @@ recommends: Net::OpenID::Consumer: '0' Net::OpenID::Server: '0' SOAP::Lite: '0' - String::Random: '0' Unicode::String: '0' Web::ID: '0' requires: diff --git a/lemonldap-ng-portal/Makefile.PL b/lemonldap-ng-portal/Makefile.PL index 5bc2d44d8..df8f6e215 100644 --- a/lemonldap-ng-portal/Makefile.PL +++ b/lemonldap-ng-portal/Makefile.PL @@ -28,7 +28,6 @@ WriteMakefile( 'Net::OpenID::Consumer' => 0, 'Net::OpenID::Server' => 0, 'SOAP::Lite' => 0, - 'String::Random' => 0, 'Unicode::String' => 0, 'Web::ID' => 0, }, diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Ext2F.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Ext2F.pm index 0fdd372d5..ef315efda 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Ext2F.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Ext2F.pm @@ -2,7 +2,6 @@ package Lemonldap::NG::Portal::2F::Ext2F; use strict; use Mouse; -use String::Random; use Lemonldap::NG::Portal::Main::Constants qw( PE_BADCREDENTIALS PE_ERROR @@ -38,7 +37,7 @@ sub init { $self->error("Missing 'ext2FSendCommand' parameter, aborting"); return 0; } - $self->random( String::Random->new ); + $self->random( Lemonldap::NG::Common::Crypto::srandom() ); $self->logo( $self->conf->{ext2fLogo} ) if ( $self->conf->{ext2fLogo} ); return $self->SUPER::init(); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Mail2F.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Mail2F.pm index f2cea52e8..6d3aea4f4 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Mail2F.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Mail2F.pm @@ -2,7 +2,6 @@ package Lemonldap::NG::Portal::2F::Mail2F; use strict; use Mouse; -use String::Random; use Lemonldap::NG::Portal::Main::Constants qw( PE_BADCREDENTIALS PE_ERROR @@ -23,7 +22,7 @@ has prefix => ( is => 'ro', default => 'mail' ); has random => ( is => 'rw', default => sub { - return String::Random->new; + return Lemonldap::NG::Common::Crypto::srandom(); } ); 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 efb2002b1..8c6a474a6 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm @@ -10,6 +10,7 @@ use Lemonldap::NG::Portal::Main::Constants qw( PE_ERROR PE_LOGOUT_OK PE_OK + PE_BADURL PE_SENDRESPONSE ); @@ -55,6 +56,18 @@ sub init { }, ['GET'] ); + + # Add CAS Services, so we can check service= parameter on logout + foreach my $casSrv ( keys %{ $self->conf->{casAppMetaDataOptions} } ) { + if ( my $serviceUrl = + $self->conf->{casAppMetaDataOptions}->{$casSrv} + ->{casAppMetaDataOptionsService} ) + { + push @{ $self->p->{additionalTrustedDomains} }, $serviceUrl; + $self->logger->debug( + "CAS Service $serviceUrl added in trusted domains"); + } + } return $res; } @@ -265,6 +278,19 @@ sub run { $logout_service = '' if ( $self->p->checkXSSAttack( 'service', $logout_service ) ); + # If we use access control, check that the service URL is trusted + if ( $self->conf->{casAccessControlPolicy} =~ /^(error|faketicket)$/i ) + { + if ( $logout_service + and not $self->p->isTrustedUrl($logout_service) ) + { + $self->userLogger->error( + "Untrusted service URL $logout_service" + . "specified for CAS Logout" ); + return PE_BADURL; + } + } + # Delete linked CAS sessions $self->deleteCasSecondarySessions($session_id); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm index ada284b3b..9f7b6c923 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm @@ -8,7 +8,6 @@ use Lemonldap::NG::Common::UserAgent; use Lemonldap::NG::Common::FormEncode; use XML::Simple; use MIME::Base64; -use String::Random; use HTTP::Request; # SOAP call use POSIX qw(strftime); # Convert SAML2 date into timestamp use Time::Local; # Convert SAML2 date into timestamp diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm index 0d9e829dc..5ac0357ef 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm @@ -8,7 +8,6 @@ package Lemonldap::NG::Portal::Lib::SMTP; use strict; use Mouse; use JSON qw(from_json); -use String::Random; use MIME::Entity; use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP qw(); @@ -24,7 +23,7 @@ our $transport; has random => ( is => 'rw', default => sub { - return String::Random->new; + return Lemonldap::NG::Common::Crypto::srandom(); } ); has charset => ( 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 5987de0b5..767e42510 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm @@ -39,6 +39,7 @@ has _jsRedirect => ( is => 'rw' ); # TrustedDomain regexp has trustedDomainsRe => ( is => 'rw' ); +has additionalTrustedDomains => ( is => 'rw', default => sub { [] } ); # Lists to store plugins entry-points my @entryPoints; @@ -269,53 +270,6 @@ sub reloadConf { unless $self->{_sfEngine} = $self->loadPlugin( $self->conf->{'sfEngine'} ); - # Initialize trusted domain regexp - if ( $self->conf->{trustedDomains} - and $self->conf->{trustedDomains} =~ /^\s*\*\s*$/ ) - { - $self->trustedDomainsRe(qr#^https?://#); - } - else { - my $re = Regexp::Assemble->new(); - if ( my $td = $self->conf->{trustedDomains} ) { - $td =~ s/^\s*(.*?)\s*/$1/; - foreach ( split( /\s+/, $td ) ) { - next unless ($td); - s#^\.#([^/]+\.)?#; - $self->logger->debug("Domain $_ added in trusted domains"); - s/\./\\./g; - - # This regexp is valid for the followings hosts: - # - $td - # - $domainlabel.$td - # $domainlabel is build looking RFC2396 - # (see Regexp::Common::URI::RFC2396) - $_ =~ - s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g; - $re->add("$_"); - } - } - my $p = $self->conf->{portal}; - $p =~ s#https?://([^/]*).*$#$1#; - $re->add( quotemeta($p) ); - foreach my $vhost ( keys %{ $self->conf->{locationRules} } ) { - $self->logger->debug("Vhost $vhost added in trusted domains"); - $re->add( quotemeta($vhost) ); - $self->conf->{vhostOptions} ||= {}; - if ( my $tmp = - $self->conf->{vhostOptions}->{$vhost}->{vhostAliases} ) - { - foreach my $alias ( split /\s+/, $tmp ) { - $self->logger->debug( - "Alias $alias added in trusted domains"); - $re->add( quotemeta($alias) ); - } - } - } - my $tmp = 'https?://' . $re->as_string . '(?::\d+)?(?:/|$)'; - $self->trustedDomainsRe(qr/$tmp/); - } - # Compile macros in _macros, groups in _groups foreach my $type (qw(macros groups)) { $self->{"_$type"} = {}; @@ -344,6 +298,59 @@ sub reloadConf { $self->loadPlugin($plugin) or return $self->fail; } + # Initialize trusted domain regexp + if ( $self->conf->{trustedDomains} + and $self->conf->{trustedDomains} =~ /^\s*\*\s*$/ ) + { + $self->trustedDomainsRe(qr#^https?://#); + } + else { + my $re = Regexp::Assemble->new(); + if ( my $td = $self->conf->{trustedDomains} ) { + $td =~ s/^\s*(.*?)\s*/$1/; + foreach ( split( /\s+/, $td ) ) { + next unless ($td); + s#^\.#([^/]+\.)?#; + $self->logger->debug("Domain $_ added in trusted domains"); + s/\./\\./g; + + # This regexp is valid for the followings hosts: + # - $td + # - $domainlabel.$td + # $domainlabel is build looking RFC2396 + # (see Regexp::Common::URI::RFC2396) + $_ =~ + s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g; + $re->add("$_"); + } + } + foreach ( @{ $self->{additionalTrustedDomains} }, + $self->conf->{portal} ) + { + my $p = $_; + $p =~ s#https?://([^/]*).*$#$1#; + $re->add( quotemeta($p) ); + } + foreach my $vhost ( keys %{ $self->conf->{locationRules} } ) { + $self->logger->debug("Vhost $vhost added in trusted domains"); + $re->add( quotemeta($vhost) ); + $self->conf->{vhostOptions} ||= {}; + if ( my $tmp = + $self->conf->{vhostOptions}->{$vhost}->{vhostAliases} ) + { + foreach my $alias ( split /\s+/, $tmp ) { + $self->logger->debug( + "Alias $alias added in trusted domains"); + $re->add( quotemeta($alias) ); + } + } + } + + my $tmp = 'https?://' . $re->as_string . '(?::\d+)?(?:/|$)'; + $self->trustedDomainsRe(qr/$tmp/); + + } + # Clean $req->pdata after authentication push @{ $self->endAuth }, sub { unless ( $_[0]->pdata->{keepPdata} ) { diff --git a/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-Logout-30.t b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-Logout-30.t index d647cf252..3bece21d1 100644 --- a/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-Logout-30.t +++ b/lemonldap-ng-portal/t/31-Auth-and-issuer-CAS-Logout-30.t @@ -152,7 +152,7 @@ ok( $res->{cn} eq 'Frédéric Accents', 'UTF-8 values' ) or explain( $res, 'cn => Frédéric Accents' ); count(3); -# Logout initiated by CAS +# Logout initiated by CAS, try with invalid service URL first switch ('issuer'); ok( $res = $issuer->_get( @@ -164,7 +164,22 @@ ok( 'Query SP for logout' ); count(1); -expectRedirection( $res, 'http://url.test/' ); +ok( $res->[2]->[0] =~ m%%, ' PE37 found' ); +count(1); + +# Logout initiated by CAS, try with valid service URL +ok( + $res = $issuer->_get( + '/cas/logout', + query => 'service=http://auth.sp.com/', + cookie => "lemonldap=$idpId,llngcasserver=idp", + accept => 'text/html' + ), + 'Query SP for logout' +); +count(1); + +expectRedirection( $res, 'http://auth.sp.com/' ); # Verify that user has been disconnected ok( $res = $issuer->_get( '/', cookie => "lemonldap=$idpId" ), 'Query IdP' ); @@ -192,8 +207,13 @@ sub issuer { issuerDBCASActivation => 1, casAttr => 'uid', casAttributes => { cn => 'cn', uid => 'uid', }, - casAccessControlPolicy => 'none', + casAccessControlPolicy => 'error', multiValuesSeparator => ';', + casAppMetaDataOptions => { + sp => { + casAppMetaDataOptionsService => 'http://auth.sp.com', + }, + }, } } ); diff --git a/lemonldap-ng-portal/t/59-Double-cookies-for-a-Single-session.t b/lemonldap-ng-portal/t/59-Double-cookies-for-a-Single-session.t index 25de134f1..8d6d81def 100644 --- a/lemonldap-ng-portal/t/59-Double-cookies-for-a-Single-session.t +++ b/lemonldap-ng-portal/t/59-Double-cookies-for-a-Single-session.t @@ -44,8 +44,8 @@ my $id1 = expectCookie($res); my $id2 = expectCookie( $res, 'lemonldaphttp' ); # Check lemonldap Cookie -ok( $id1 =~ /^\w{64}$/, " -> Get cookie : lemonldap=something" ) - or explain( $res->[1], "Set-Cookie: lemonldap=$id1" ); +ok( $id1 =~ /^\w{64}$/, " -> https cookie is 64 char long" ) + or explain( $id1, '64-char string' ); ok( ${ $res->[1] }[3] =~ /HttpOnly=1/, " -> Cookie 'lemonldap' is HttpOnly" ) or explain( $res->[1] ); ok( ${ $res->[1] }[3] =~ /secure/, " -> Cookie 'lemonldap' is secure" ) @@ -53,8 +53,8 @@ ok( ${ $res->[1] }[3] =~ /secure/, " -> Cookie 'lemonldap' is secure" ) count(3); # Check lemonldaphttp Cookie -ok( $id2 =~ /^\w{64}$/, " -> Get cookie lemonldaphttp=something" ) - or explain( $res->[1], "Set-Cookie: lemonldaphttp=$id2" ); +ok( length($id2) % 32 == 0, " -> http cookie is 96 byte long" ) + or explain( $id2, '\w x 32 string' ); ok( ${ $res->[1] }[5] =~ /HttpOnly=1/, " -> Cookie 'lemonldaphttp' is HttpOnly"