diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm index a48c3d50c..506258bab 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm @@ -29,11 +29,14 @@ sub new { $self->env->{PATH_INFO} =~ s|^$tmp|/|; $self->{uri} = uri_unescape( $self->env->{REQUEST_URI} ); $self->{uri} =~ s|//+|/|g; + $self->{datas} = {}; $self->{error} = 0; $self->{respHeaders} = []; - return $self; + return bless( $self, $_[0] ); } +sub datas { $_[0]->{datas} } + sub uri { $_[0]->{uri} } sub userData { diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST index 5deb4a160..40fc4a5c0 100644 --- a/lemonldap-ng-handler/MANIFEST +++ b/lemonldap-ng-handler/MANIFEST @@ -9,6 +9,7 @@ lib/Lemonldap/NG/Handler/ApacheMP2/CDA.pm lib/Lemonldap/NG/Handler/ApacheMP2/DevOps.pm lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm lib/Lemonldap/NG/Handler/ApacheMP2/Menu.pm +lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm lib/Lemonldap/NG/Handler/ApacheMP2/SecureToken.pm lib/Lemonldap/NG/Handler/ApacheMP2/ServiceToken.pm lib/Lemonldap/NG/Handler/ApacheMP2/ZimbraPreAuth.pm @@ -48,7 +49,6 @@ META.yml README t/01-Lemonldap-NG-Handler-Main.t t/05-Lemonldap-NG-Handler-Reload.t -t/10-Lemonldap-NG-Handler-SharedConf.t t/12-Lemonldap-NG-Handler-Jail.t t/13-Lemonldap-NG-Handler-Fake-Safe.t t/50-Lemonldap-NG-Handler-SecureToken.t diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm index 330726303..abab47680 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm @@ -4,6 +4,7 @@ package Lemonldap::NG::Handler::ApacheMP2; use strict; +use Lemonldap::NG::Handler::ApacheMP2::Request; use Lemonldap::NG::Handler::ApacheMP2::Main; @@ -13,30 +14,31 @@ our $VERSION = '2.0.0'; sub handler { shift if ($#_); - my ($res) = getClass(@_)->run(@_); - return $res; + return launch( 'run', @_ ); } sub logout { shift if ($#_); - return getClass(@_)->unlog(@_); + return launch( 'unlog', @_ ); } sub status { shift if ($#_); - return getClass(@_)->getStatus(@_); + return launch( 'getStatus', @_ ); } # Internal method to get class to load -sub getClass { - my $type = Lemonldap::NG::Handler::ApacheMP2::Main->checkType(@_); +sub launch { + my ( $sub, $r ) = @_; + my $req = Lemonldap::NG::Handler::Apache2::Request->new($r); + my $type = Lemonldap::NG::Handler::ApacheMP2::Main->checkType($req); if ( my $t = $_[0]->dir_config('VHOSTTYPE') ) { $type = $t; } my $class = "Lemonldap::NG::Handler::ApacheMP2::$type"; eval "require $class"; die $@ if ($@); - return $class; + return $class->$sub($req); } 1; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm index 211342784..4fb806fed 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Main.pm @@ -43,33 +43,6 @@ our $request; # Apache2::RequestRec object for current request #*run = \&Lemonldap::NG::Handler::Main::run; -## @rmethod protected int redirectFilter(string url, Apache2::Filter f) -# Launch the current HTTP request then redirects the user to $url. -# Used by logout_app and logout_app_sso targets -# @param $url URL to redirect the user -# @param $f Current Apache2::Filter object -# @return Constant $class->OK -sub redirectFilter { - my $class = shift; - my $url = shift; - my $f = shift; - unless ( $f->ctx ) { - - # Here, we can use Apache2 functions instead of set_header_out - # since this function is used only with Apache2. - $f->r->status( $class->REDIRECT ); - $f->r->status_line("303 See Other"); - $f->r->headers_out->unset('Location'); - $f->r->err_headers_out->set( 'Location' => $url ); - $f->ctx(1); - } - while ( $f->read( my $buffer, 1024 ) ) { - } - $class->updateStatus( $f->r, '$class->REDIRECT', - $class->datas->{ $class->tsv->{whatToTrace} }, 'filter' ); - return $class->OK; -} - __PACKAGE__->init(); # INTERNAL METHODS @@ -99,36 +72,21 @@ sub setServerSignature { }; } -sub newRequest { - my ( $class, $r ) = @_; - $request = $r; -} - ## @method void set_user(string user) # sets remote_user # @param user string username sub set_user { - my ( $class, $user ) = @_; - $request->user($user); -} - -## @method string header_in(string header) -# returns request header value -# @param header string request header -# @return request header value -sub header_in { - my ( $class, $header ) = @_; - $header ||= $class; # to use header_in as a method or as a function - return $request->headers_in->{$header}; + my ( $class, $request, $user ) = @_; + $request->env->{'psgi.r'}->user($user); } ## @method void set_header_in(hash headers) # sets or modifies request headers # @param headers hash containing header names => header value sub set_header_in { - my ( $class, %headers ) = @_; + my ( $class, $request, %headers ) = @_; while ( my ( $h, $v ) = each %headers ) { - $request->headers_in->set( $h => $v ); + $request->env->{'psgi.r'}->headers_in->set( $h => $v ); } } @@ -138,11 +96,11 @@ sub set_header_in { # header 'Auth-User' is removed, 'Auth_User' be removed also # @param headers array with header names to remove sub unset_header_in { - my ( $class, @headers ) = @_; + my ( $class, $request, @headers ) = @_; foreach my $h1 (@headers) { $h1 = lc $h1; $h1 =~ s/-/_/g; - $request->headers_in->do( + $request->env->{'psgi.r'}->headers_in->do( sub { my $h = shift; my $h2 = lc $h; @@ -158,120 +116,65 @@ sub unset_header_in { # sets response headers # @param headers hash containing header names => header value sub set_header_out { - my ( $class, %headers ) = @_; + my ( $class, $request, %headers ) = @_; while ( my ( $h, $v ) = each %headers ) { - $request->err_headers_out->set( $h => $v ); + $request->env->{'psgi.r'}->err_headers_out->set( $h => $v ); } } -## @method string hostname() -# returns host, as set by full URI or Host header -# @return host string Host value -sub hostname { - my $class = shift; - return $request->hostname; -} - -## @method string remote_ip -# returns client IP address -# @return IP_Addr string client IP -sub remote_ip { - my $class = shift; - my $remote_ip = ( - $request->connection->can('remote_ip') - ? $request->connection->remote_ip - : $request->connection->client_ip - ); - return $remote_ip; -} - ## @method boolean is_initial_req # returns true unless the current request is a subrequest # @return is_initial_req boolean sub is_initial_req { - my $class = shift; - return $request->is_initial_req; -} - -## @method string args(string args) -# gets the query string -# @return args string Query string -sub args { - my $class = shift; - return $request->args(); -} - -## @method string uri -# returns the path portion of the URI, normalized, i.e. : -# * URL decoded (characters encoded as %XX are decoded, -# except ? in order not to merge path and query string) -# * references to relative path components "." and ".." are resolved -# * two or more adjacent slashes are merged into a single slash -# @return path portion of the URI, normalized -sub uri { - my $class = shift; - my $uri = $request->uri; - $uri =~ s#//+#/#g; - $uri =~ s#\?#%3F#g; - return $uri; -} - -## @method string uri_with_args -# returns the URI, with arguments and with path portion normalized -# @return URI with normalized path portion -sub uri_with_args { - my $class = shift; - return uri . ( $request->args ? "?" . $request->args : "" ); -} - -## @method string unparsed_uri -# returns the full original request URI, with arguments -# @return full original request URI, with arguments -sub unparsed_uri { - my $class = shift; - return $request->unparsed_uri; -} - -## @method string get_server_port -# returns the port the server is receiving the current request on -# @return port string server port -sub get_server_port { - my $class = shift; - return $request->get_server_port; -} - -## @method string method -# returns the port the server is receiving the current request on -# @return port string server port -sub method { - my $class = shift; - return $request->method; -} - -## Return environment variables as hash -sub env { - return \%ENV; + return $_[1]->env->{'psgi.r'}->is_initial_req; } ## @method void print(string data) # write data in HTTP response body # @param data Text to add in response body sub print { - my ( $class, $data ) = @_; - $request->print($data); + my ( $class, $request, $data ) = @_; + $request->env->{'psgi.r'}->print($data); } 1; __END__ +## @rmethod protected int redirectFilter(string url, Apache2::Filter f) +# Launch the current HTTP request then redirects the user to $url. +# Used by logout_app and logout_app_sso targets +# @param $url URL to redirect the user +# @param $f Current Apache2::Filter object +# @return Constant $class->OK +sub redirectFilter { + my $class = shift; + my $url = shift; + my $f = shift; + unless ( $f->ctx ) { + + # Here, we can use Apache2 functions instead of set_header_out + # since this function is used only with Apache2. + $f->r->status( $class->REDIRECT ); + $f->r->status_line("303 See Other"); + $f->r->headers_out->unset('Location'); + $f->r->err_headers_out->set( 'Location' => $url ); + $f->ctx(1); + } + while ( $f->read( my $buffer, 1024 ) ) { + } + $class->updateStatus( $f->r, '$class->REDIRECT', + $class->datas->{ $class->tsv->{whatToTrace} }, 'filter' ); + return $class->OK; +} + ## @method void addToHtmlHead(string data) # add data at end of html head # @param data Text to add in html head sub addToHtmlHead { use APR::Bucket (); use APR::Brigade (); - my ( $class, $data ) = @_; + my ( $class, $request, $data ) = @_; $request->add_output_filter( sub { my $f = shift; @@ -322,7 +225,7 @@ sub flatten_bb { # add or modify parameters in POST request body # @param $params hashref containing name => value sub setPostParams { - my ( $class, $params ) = @_; + my ( $class, $request, $params ) = @_; $request->add_input_filter( sub { my $f = shift; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm new file mode 100644 index 000000000..f5147ed98 --- /dev/null +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm @@ -0,0 +1,49 @@ +package Lemonldap::NG::Handler::ApacheMP2::Request; + +use strict; +use base 'Plack::Request'; +use Plack::Util; +use URI; +use URI::Escape; + +# Build Plack::Request (inspired from Plack::Handler::Apache2) +sub new { + my ( $class, $r ) = @_; + + # Apache populates ENV: + $r->subprocess_env; + my $env = { + %ENV, + 'psgi.version' => [ 1, 1 ], + 'psgi.url_scheme' => ( $ENV{HTTPS} || 'off' ) =~ /^(?:on|1)$/i + ? 'https' + : 'http', + 'psgi.input' => $r, + 'psgi.errors' => *STDERR, + 'psgi.multithread' => Plack::Util::FALSE, + 'psgi.multiprocess' => Plack::Util::TRUE, + 'psgi.run_once' => Plack::Util::FALSE, + 'psgi.streaming' => Plack::Util::TRUE, + 'psgi.nonblocking' => Plack::Util::FALSE, + 'psgix.harakiri' => Plack::Util::TRUE, + 'psgix.cleanup' => Plack::Util::TRUE, + 'psgix.cleanup.handlers' => [], + 'psqi.r' => $r, + }; + if ( defined( my $HTTP_AUTHORIZATION = $r->headers_in->{Authorization} ) ) { + $env->{HTTP_AUTHORIZATION} = $HTTP_AUTHORIZATION; + } + my $uri = URI->new( "http://" . $r->hostname . $r->{env}->{REQUEST_URI} ); + $env->{PATH_INFO} = uri_unescape( $uri->path ); + + my $self = Plack::Request->new($env); + bless $self, $class; + return $self; +} + +sub datas { + my($self) = @_; + return $self->{datas} ||= {}; +} + +1; 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 d690b7c95..6a0fefc4b 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm @@ -24,8 +24,8 @@ our @EXPORT_OK = @EXPORT; # using indefinitely a session id disclosed accidentally or maliciously. # @return session id sub fetchId { - my $class = shift; - if ( my $creds = $class->header_in('Authorization') ) { + my ( $class, $req ) = @_; + if ( my $creds = $req->env->{'HTTP_AUTHORIZATION'} ) { $creds =~ s/^Basic\s+//; my @date = localtime; my $day = $date[5] * 366 + $date[7]; @@ -41,17 +41,19 @@ sub fetchId { # and if needed, ask portal to create it through a SOAP request # @return true if the session was found, false else sub retrieveSession { - my ( $class, $id ) = @_; + my ( $class, $req, $id ) = @_; # First check if session already exists - if ( my $res = $class->Lemonldap::NG::Handler::Main::retrieveSession($id) ) + if ( my $res = + $class->Lemonldap::NG::Handler::Main::retrieveSession( $req, $id ) ) { return $res; } # Then ask portal to create it - if ( $class->createSession($id) ) { - return $class->Lemonldap::NG::Handler::Main::retrieveSession($id); + if ( $class->createSession( $req, $id ) ) { + return $class->Lemonldap::NG::Handler::Main::retrieveSession( $req, + $id ); } else { return 0; @@ -62,12 +64,12 @@ sub retrieveSession { # Ask portal to create it through a SOAP request # @return true if the session is created, else false sub createSession { - my ( $class, $id ) = @_; + my ( $class, $req, $id ) = @_; # Add client IP as X-Forwarded-For IP in SOAP request - my $xheader = $class->header_in('X-Forwarded-For'); + my $xheader = $req->env->{'HTTP_X_FORWARDED_FOR'}; $xheader .= ", " if ($xheader); - $xheader .= $class->remote_ip; + $xheader .= $req->{env}->{REMOTE_ADDR}; #my $soapHeaders = HTTP::Headers->new( "X-Forwarded-For" => $xheader ); ## TODO: use adminSession or sessions @@ -76,7 +78,7 @@ sub createSession { # default_headers => $soapHeaders #)->uri('urn:Lemonldap/NG/Common/PSGI/SOAPService'); - my $creds = $class->header_in('Authorization'); + my $creds = $req->env->{'HTTP_AUTHORIZATION'}; $creds =~ s/^Basic\s+//; my ( $user, $pwd ) = ( decode_base64($creds) =~ /^(.*?):(.*)$/ ); $class->logger->debug("AuthBasic authentication for user: $user"); @@ -84,18 +86,18 @@ sub createSession { #my $soapRequest = $soapClient->getCookies( $user, $pwd, $id ); my $url = $class->tsv->{portal}->() . "/sessions/global/$id?auth"; $url =~ s#//sessions/#/sessions/#g; - my $req = HTTP::Request->new( POST => $url ); - $req->header( 'X-Forwarded-For' => $xheader ); - $req->header( 'Content-Type' => 'application/x-www-form-urlencoded' ); - $req->header( Accept => 'application/json' ); - $req->content( + my $get = HTTP::Request->new( POST => $url ); + $get->header( 'X-Forwarded-For' => $xheader ); + $get->header( 'Content-Type' => 'application/x-www-form-urlencoded' ); + $get->header( Accept => 'application/json' ); + $get->content( build_urlencoded( user => $user, password => $pwd, secret => $class->tsv->{cipher}->encrypt(time) ) ); - my $resp = $class->ua->request($req); + my $resp = $class->ua->request($get); if ( $resp->is_success ) { $class->userLogger->notice("Good REST authentication for $user"); @@ -130,9 +132,9 @@ sub createSession { ## @rmethod protected void hideCookie() # Hide user credentials to the protected application sub hideCookie { - my $class = shift; + my ( $class, $req ) = @_; $class->logger->debug("removing Authorization header"); - $class->unset_header_in('Authorization'); + $class->unset_header_in( $req, 'Authorization' ); } ## @rmethod protected int goToPortal(string url, string arg) @@ -142,12 +144,13 @@ sub hideCookie { # @param $arg optionnal GET parameters # @return Apache2::Const::REDIRECT or Apache2::Const::AUTH_REQUIRED sub goToPortal { - my ( $class, $url, $arg ) = @_; + my ( $class, $req, $url, $arg ) = @_; if ($arg) { - return $class->Lemonldap::NG::Handler::Main::goToPortal( $url, $arg ); + return $class->Lemonldap::NG::Handler::Main::goToPortal( $req, $url, + $arg ); } else { - $class->set_header_out( + $class->set_header_out( $req, 'WWW-Authenticate' => 'Basic realm="LemonLDAP::NG"' ); return $class->AUTH_REQUIRED; } 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 22c202f4b..747873ba8 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/CDA.pm @@ -6,11 +6,12 @@ our $VERSION = '2.0.0'; sub run { my ( $class, $req, $rule, $protection ) = @_; - my $uri = $class->unparsed_uri; + my $uri = $req->{env}->{REQUEST_URI}; my $cn = $class->tsv->{cookieName}; my ( $id, $session ); if ( $uri =~ s/[\?&;]${cn}cda=(\w+)$//oi ) { - if ( $id = $class->fetchId and $session = $class->retrieveSession($id) ) + if ( $id = $class->fetchId($req) + and $session = $class->retrieveSession( $req, $id ) ) { $class->logger->info( 'CDA asked for an already available session, skipping'); @@ -19,19 +20,20 @@ sub run { my $cdaid = $1; $class->logger->debug("CDA request with id $cdaid"); - my $cdaInfos = $class->getCDAInfos($cdaid); + my $cdaInfos = $class->getCDAInfos( $req, $cdaid ); unless ( $cdaInfos->{cookie_value} and $cdaInfos->{cookie_name} ) { $class->logger->error("CDA request for id $cdaid is not valid"); return $class->FORBIDDEN; } - my $redirectUrl = $class->_buildUrl($uri); + my $redirectUrl = $class->_buildUrl( $req, $uri ); my $redirectHttps = ( $redirectUrl =~ m/^https/ ); $class->set_header_out( + $req, 'Location' => $redirectUrl, 'Set-Cookie' => $cdaInfos->{cookie_name} . "=" . 'c:' . $class->tsv->{cipher}->encrypt( - $cdaInfos->{cookie_value} . ' ' . $class->resolveAlias + $cdaInfos->{cookie_value} . ' ' . $class->resolveAlias($req) ) . "; path=/" . ( $redirectHttps ? "; secure" : "" ) @@ -53,7 +55,7 @@ sub run { # Tries to retrieve the CDA session, get infos and delete session # @return CDA session infos sub getCDAInfos { - my ( $class, $id ) = @_; + my ( $class, $req, $id ) = @_; my $infos = {}; # Get the session diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm index c94157a5b..f0da4d364 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm @@ -16,33 +16,36 @@ sub ua { } sub grant { - my ( $class, $session, $uri, $cond, $vhost ) = @_; - $vhost ||= $class->resolveAlias; + my ( $class, $req, $session, $uri, $cond, $vhost ) = @_; + $vhost ||= $class->resolveAlias($req); $class->tsv->{lastVhostUpdate} //= {}; unless ( $class->tsv->{defaultCondition}->{$vhost} and ( time() - $class->tsv->{lastVhostUpdate}->{$vhost} < 600 ) ) { - $class->loadVhostConfig($vhost); + $class->loadVhostConfig( $req, $vhost ); } - return $class->Lemonldap::NG::Handler::Main::grant( $session, $uri, $cond, - $vhost ); + return $class->Lemonldap::NG::Handler::Main::grant( $req, $session, $uri, + $cond, $vhost ); } sub loadVhostConfig { - my ( $class, $vhost ) = @_; + my ( $class, $req, $vhost ) = @_; my $json; if ( $class->tsv->{useSafeJail} ) { my $base = $class->localConfig->{loopBackUrl} - || "http://127.0.0.1:" . $class->get_server_port; - my $req = HTTP::Request->new( GET => "$base/rules.json" ); - $req->header( Host => $vhost ); - my $resp = $class->ua->request($req); + || "http://127.0.0.1:" . $req->{env}->{SERVER_PORT}; + my $get = HTTP::Request->new( GET => "$base/rules.json" ); + $get->header( Host => $vhost ); + my $resp = $class->ua->request($get); if ( $resp->is_success ) { eval { $json = from_json( $resp->content ) }; if ($@) { $class->logger->error( "Bad rules.json for $vhost, skipping ($@)"); } + else { + $class->logger->info("Compiling rules.json for $vhost"); + } } } else { 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 43e85cf1d..57a327143 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/SecureToken.pm @@ -33,13 +33,13 @@ BEGIN { sub run { my $class = shift; my $r = $_[0]; - my $ret = $class->SUPER::run(); + my $ret = $class->SUPER::run($r); # Continue only if user is authorized return $ret unless ( $ret == $class->OK ); # Get current URI - my $uri = Lemonldap::NG::Handler::API->uri_with_args($r); + my $uri = $r->{env}->{REQUEST_URI}; # Catch Secure Token parameters my $localConfig = $class->localConfig; @@ -101,7 +101,7 @@ sub run { return $class->_returnError( $r, $secureTokenAllowOnError ) unless $key; # Header location - $class->set_header_in( $secureTokenHeader => $key ); + $class->set_header_in( $r, $secureTokenHeader => $key ); # Remove token eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} ); diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm index 2cac628d6..5f1fdc295 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ServiceToken.pm @@ -5,9 +5,9 @@ use strict; our $VERSION = '2.0.0'; sub fetchId { - my ($class) = @_; - my $token = $class->header_in('X-Llng-Token'); - return $class->Lemonldap::NG::Handler::Main::fetchId() unless ($token); + my ( $class, $req ) = @_; + my $token = $req->{env}->{HTTP_X_LLNG_TOKEN}; + return $class->Lemonldap::NG::Handler::Main::fetchId($req) unless ($token); $class->logger->debug('Found token header'); my $s = $class->tsv->{cipher}->decrypt($token); my ( $t, $_session_id, @vhosts ) = split /:/, $s; @@ -19,7 +19,7 @@ sub fetchId { $class->userLogger->warn('Expired token'); return 0; } - my $vh = $class->resolveAlias; + my $vh = $class->resolveAlias($req); unless ( grep { $_ eq $vh } @vhosts ) { $class->userLogger->error( "$vh not authorizated in token (" . join( ', ', @vhosts ) . ')' ); diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ZimbraPreAuth.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ZimbraPreAuth.pm index 10f8ff3bd..4a579260b 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ZimbraPreAuth.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/ZimbraPreAuth.pm @@ -22,7 +22,7 @@ sub run { return $ret unless ( $ret == $class->OK ); # Get current URI - my $uri = $class->uri_with_args($req); + my $uri = $req->{env}->{REQUEST_URI}; # Get Zimbra parameters my $localConfig = $class->localConfig; @@ -52,7 +52,7 @@ sub run { # Build URL my $zimbra_url = - $class->_buildZimbraPreAuthUrl( $zimbraPreAuthKey, $zimbraUrl, + $class->_buildZimbraPreAuthUrl( $req, $zimbraPreAuthKey, $zimbraUrl, $class->datas->{$zimbraAccountKey}, $zimbraBy, $timeout ); @@ -72,7 +72,7 @@ sub run { # @param timeout Timout # @return Zimbra PreAuth URL sub _buildZimbraPreAuthUrl { - my ( $class, $key, $url, $account, $by, $timeout ) = @_; + my ( $class, $req, $key, $url, $account, $by, $timeout ) = @_; # Expiration time is calculated with _utime and timeout my $expires = 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 3173d4c0a..32009c556 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Jail.pm @@ -4,7 +4,6 @@ use strict; use Safe; use Lemonldap::NG::Common::Safelib; #link protected safe Safe object -use constant SAFEWRAP => ( Safe->can("wrap_code_ref") ? 1 : 0 ); use Mouse; has customFunctions => ( is => 'rw', isa => 'Maybe[Str]' ); @@ -66,16 +65,10 @@ sub build_jail { $self->jail->share_from( 'Lemonldap::NG::Common::Safelib', $Lemonldap::NG::Common::Safelib::functions ); - $self->jail->share_from( - $api, - [ - qw( &hostname &remote_ip &uri &uri_with_args - &unparsed_uri &args &method &header_in &env ) - ] - ); $self->jail->share_from( __PACKAGE__, [ @t, '&encrypt', '&token' ] ); $self->jail->share_from( 'MIME::Base64', ['&encode_base64'] ); - $self->jail->share_from( 'Lemonldap::NG::Handler::Main', ['$_v'] ); + + #$self->jail->share_from( 'Lemonldap::NG::Handler::Main', ['$_v'] ); # Initialize cryptographic functions to be able to use them in jail. eval { token('a') }; @@ -142,7 +135,7 @@ sub share_from { } ## @imethod protected jail_reval() -# Build and return restricted eval command with SAFEWRAP, if activated +# Build and return restricted eval command # @return evaluation of $reval or $reval2 sub jail_reval { my ( $self, $reval ) = @_; @@ -151,14 +144,7 @@ sub jail_reval { # the "no safe wrap" reval my $res; - eval { - $res = ( - SAFEWRAP - and $self->useSafeJail - ? $self->jail->wrap_code_ref( $self->jail->reval($reval) ) - : $self->jail->reval($reval) - ); - }; + eval { $res = ( $self->jail->reval($reval) ) }; if ($@) { $self->error($@); return undef; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Reload.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Reload.pm index 0627ecfb0..1c63b3351 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Reload.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Reload.pm @@ -462,12 +462,11 @@ sub conditionSub { eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} ); return ( sub { - $Lemonldap::NG::Handler::ApacheMP2::Main::request - ->add_output_filter( + $_[0]->add_output_filter( sub { return $class->redirectFilter( $u, @_ ); } - ); + ); 1; }, 0 @@ -481,8 +480,7 @@ sub conditionSub { #TODO: check this $class->localUnlog; - $Lemonldap::NG::Handler::ApacheMP2::Main::request - ->add_output_filter( + $_[0]->add_output_filter( sub { my $r = $_[0]->r; return $class->redirectFilter( @@ -492,7 +490,7 @@ sub conditionSub { @_ ); } - ); + ); 1; }, 0 @@ -535,12 +533,12 @@ sub substitute { # substitute special vars, just for retro-compatibility $expr =~ s/\$date\b/&date/sg; - $expr =~ s/\$vhost\b/&hostname/sg; - $expr =~ s/\$ip\b/&remote_ip/sg; + $expr =~ s/\$vhost\b/\$ENV{HTTP_HOST}/sg; + $expr =~ s/\$ip\b/\$ENV{REMOTE_ADDR}/sg; # substitute vars with session datas, excepts special vars $_ and $\d+ - $expr =~ s/\$(?!ENV)(_*[a-zA-Z]\w*)/\$session->{$1}/sg; - $expr =~ s/\$ENV\{/&env()->\{/g; + $expr =~ s/\$(?!ENV)(_*[a-zA-Z]\w*)/\$s->{$1}/sg; + $expr =~ s/\$ENV\{/\$r->{env}->\{/g; return $expr; } @@ -548,7 +546,7 @@ sub substitute { sub buildSub { my ( $class, $val ) = @_; my $res = - $class->tsv->{jail}->jail_reval("sub{my \$session=\$_[0];return($val)}"); + $class->tsv->{jail}->jail_reval("sub{my (\$r,\$s)=\@_;return($val)}"); unless ($res) { $class->logger->error( $class->tsv->{jail}->error ); } diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm index 67f3e4c8e..a786dcb09 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm @@ -23,37 +23,35 @@ sub handler { sub logout { my $class; $class = $#_ ? shift : __PACKAGE__; - $class->newRequest( $_[0] ); - return $class->unlog(); + return $class->unlog(@_); } sub status { my $class; $class = $#_ ? shift : __PACKAGE__; - $class->newRequest( $_[0] ); - return $class->getStatus(); + return $class->getStatus(@_); } # Public methods # Return Handler::Lib::Status output sub getStatus { - my ($class) = @_; + my ( $class, $req ) = @_; $class->logger->debug("Request for status"); my $statusPipe = $class->tsv->{statusPipe}; my $statusOut = $class->tsv->{statusOut}; - return $class->abort("$class: status page can not be displayed") + return $class->abort( $req, "$class: status page can not be displayed" ) unless ( $statusPipe and $statusOut ); - print $statusPipe "STATUS" - . ( $class->args ? " " . $class->args : '' ) . "\n"; + print $statusPipe "STATUS" . ( $req->{env}->{QUERY_STRING} || '' ) . "\n"; my $buf; while (<$statusOut>) { last if (/^END$/); $buf .= $_; } - $class->set_header_out( ( "Content-Type" => "text/html; charset=UTF-8" ) ); - $class->print($buf); + $class->set_header_out( $req, + "Content-Type" => "text/html; charset=UTF-8" ); + $class->print( $req, $buf ); return $class->OK; } @@ -62,12 +60,11 @@ sub getStatus { sub checkType { my ( $class, $req ) = @_; - $class->newRequest($req); if ( time() - $class->lastCheck > $class->checkTime ) { die("$class: No configuration found") unless ( $class->checkConf ); } - my $vhost = $class->resolveAlias; + my $vhost = $class->resolveAlias($req); return ( defined $class->tsv->{type}->{$vhost} ) ? $class->tsv->{type}->{$vhost} : 'Main'; @@ -84,14 +81,14 @@ sub run { my ( $class, $req, $rule, $protection ) = @_; my ( $id, $session ); - return $class->DECLINED unless ( $class->is_initial_req ); + return $class->DECLINED unless ( $class->is_initial_req($req) ); # Direct return if maintenance mode is active - if ( $class->checkMaintenanceMode ) { + if ( $class->checkMaintenanceMode($req) ) { if ( $class->tsv->{useRedirectOnError} ) { $class->logger->debug("Go to portal with maintenance error code"); - return $class->goToError( '/', $class->MAINTENANCE ); + return $class->goToError( $req, '/', $class->MAINTENANCE ); } else { $class->logger->debug("Return maintenance error code"); @@ -100,25 +97,25 @@ sub run { } # Cross domain authentication - my $uri = $class->unparsed_uri; + my $uri = $req->{env}->{REQUEST_URI}; - $uri = $class->uri_with_args; + $uri = $req->{env}->{REQUEST_URI}; my ($cond); ( $cond, $protection ) = $class->conditionSub($rule) if ($rule); - $protection = $class->isUnprotected($uri) || 0 + $protection = $class->isUnprotected( $req, $uri ) || 0 unless ( defined $protection ); if ( $protection == $class->SKIP ) { $class->logger->debug("Access control skipped"); - $class->updateStatus('SKIP'); - $class->hideCookie; - $class->cleanHeaders; + $class->updateStatus( $req, 'SKIP' ); + $class->hideCookie($req); + $class->cleanHeaders($req); return $class->OK; } # Try to recover cookie and user session - if ( $id = $class->fetchId - and $session = $class->retrieveSession($id) ) + if ( $id = $class->fetchId($req) + and $session = $class->retrieveSession( $req, $id ) ) { # AUTHENTICATION done @@ -127,24 +124,25 @@ sub run { my $kc = keys %{$session}; # in order to detect new local macro # ACCOUNTING (1. Inform web server) - $class->set_user( $session->{ $class->tsv->{whatToTrace} } ); + $class->set_user( $req, $session->{ $class->tsv->{whatToTrace} } ); # AUTHORIZATION - return ( $class->forbidden($session), $session ) - unless ( $class->grant( $session, $uri, $cond ) ); - $class->updateStatus( 'OK', $session->{ $class->tsv->{whatToTrace} } ); + return ( $class->forbidden( $req, $session ), $session ) + unless ( $class->grant( $req, $session, $uri, $cond ) ); + $class->updateStatus( $req, 'OK', + $session->{ $class->tsv->{whatToTrace} } ); # ACCOUNTING (2. Inform remote application) - $class->sendHeaders($session); + $class->sendHeaders( $req, $session ); # Store local macros if ( keys %$session > $kc ) { $class->logger->debug("Update local cache"); - $class->session->update( $session, { updateCache => 2 } ); + $req->datas->{session}->update( $session, { updateCache => 2 } ); } # Hide Lemonldap::NG cookie - $class->hideCookie; + $class->hideCookie($req); # Log access granted $class->logger->debug( "User " @@ -152,8 +150,8 @@ sub run { . " was granted to access to $uri" ); # Catch POST rules - $class->postOutputFilter( $session, $uri ); - $class->postInputFilter( $session, $uri ); + $class->postOutputFilter( $req, $session, $uri ); + $class->postInputFilter( $req, $session, $uri ); return ( $class->OK, $session ); } @@ -162,9 +160,9 @@ sub run { # Ignore unprotected URIs $class->logger->debug("No valid session but unprotected access"); - $class->updateStatus('UNPROTECT'); - $class->hideCookie; - $class->cleanHeaders; + $class->updateStatus( $req, 'UNPROTECT' ); + $class->hideCookie($req); + $class->cleanHeaders($req); return $class->OK; } @@ -175,8 +173,8 @@ sub run { unless ($id); # if the cookie was fetched, a log is sent by retrieveSession() - $class->updateStatus( $id ? 'EXPIRED' : 'REDIRECT' ); - return $class->goToPortal( $class->unparsed_uri ); + $class->updateStatus( $req, $id ? 'EXPIRED' : 'REDIRECT' ); + return $class->goToPortal( $req, $req->{env}->{REQUEST_URI} ); } } @@ -184,10 +182,10 @@ sub run { # Call localUnlog() then goToPortal() to unlog the current user. # @return Constant value returned by goToPortal() sub unlog { - my $class = shift; - $class->localUnlog(@_); - $class->updateStatus('LOGOUT'); - return $class->goToPortal( '/', 'logout=1' ); + my ( $class, $req ) = @_; + $class->localUnlog( $req, @_ ); + $class->updateStatus( $req, 'LOGOUT' ); + return $class->goToPortal( $req, '/', 'logout=1' ); } # INTERNAL METHODS @@ -198,12 +196,14 @@ sub unlog { # @param optional user string Username to log, if undefined defaults to remote IP # @param optional url string URL to log, if undefined defaults to request URI sub updateStatus { - my ( $class, $action, $user, $url ) = @_; + my ( $class, $req, $action, $user, $url ) = @_; my $statusPipe = $class->tsv->{statusPipe} or return; - $user ||= $class->remote_ip; - $url ||= $class->uri_with_args; + $user ||= $req->{env}->{REMOTE_ADDR}; + $url ||= $req->{env}->{REQUEST_URI}; eval { - print $statusPipe "$user => " . $class->hostname . "$url $action\n"; + print $statusPipe "$user => " + . $req->{env}->{HTTP_HOST} + . "$url $action\n"; }; } @@ -220,8 +220,8 @@ sub lmLog { # Check if we are in maintenance mode # @return true if maintenance mode sub checkMaintenanceMode { - my $class = shift; - my $vhost = $class->resolveAlias; + my ( $class, $req ) = @_; + my $vhost = $class->resolveAlias($req); my $_maintenance = ( defined $class->tsv->{maintenance}->{$vhost} ) ? $class->tsv->{maintenance}->{$vhost} @@ -240,10 +240,10 @@ sub checkMaintenanceMode { # @param $cond optional Function granting access # @return True if the user is granted to access to the current URL sub grant { - my ( $class, $session, $uri, $cond, $vhost ) = @_; - return $cond->($session) if ($cond); + my ( $class, $req, $session, $uri, $cond, $vhost ) = @_; + return $cond->( $req, $session ) if ($cond); - $vhost ||= $class->resolveAlias; + $vhost ||= $class->resolveAlias($req); if ( my $level = $class->tsv->{authnLevel}->{$vhost} ) { if ( $session->{authenticationLevel} < $level ) { $session->{_upgrade} = 1; @@ -260,7 +260,8 @@ sub grant { $class->logger->debug( 'Regexp "' . $class->tsv->{locationConditionText}->{$vhost}->[$i] . '" match' ); - return $class->tsv->{locationCondition}->{$vhost}->[$i]->($session); + return $class->tsv->{locationCondition}->{$vhost}->[$i] + ->( $req, $session ); } } unless ( $class->tsv->{defaultCondition}->{$vhost} ) { @@ -270,7 +271,7 @@ sub grant { return 0; } $class->logger->debug("$vhost: Apply default rule"); - return $class->tsv->{defaultCondition}->{$vhost}->($session); + return $class->tsv->{defaultCondition}->{$vhost}->( $req, $session ); } ## @rmethod protected int forbidden(string uri) @@ -279,33 +280,33 @@ sub grant { # @param $uri URI # @return Constant $class->FORBIDDEN sub forbidden { - my ( $class, $session, $vhost ) = @_; - my $uri = $class->unparsed_uri; - $vhost ||= $class->resolveAlias; + my ( $class, $req, $session, $vhost ) = @_; + my $uri = $req->{env}->{REQUEST_URI}; + $vhost ||= $class->resolveAlias($req); if ( $session->{_logout} ) { - $class->updateStatus( 'LOGOUT', + $class->updateStatus( $req, 'LOGOUT', $session->{ $class->tsv->{whatToTrace} } ); my $u = $session->{_logout}; - $class->localUnlog; - return $class->goToPortal( $u, 'logout=1' ); + $class->localUnlog($req); + return $class->goToPortal( $req, $u, 'logout=1' ); } if ( $session->{_upgrade} ) { - return $class->goToPortal( $class->unparsed_uri, undef, - '/upgradesession' ); + return $class->goToPortal( $req, $uri, undef, '/upgradesession' ); } # Log forbidding $class->userLogger->notice( "User " . $session->{ $class->tsv->{whatToTrace} } . " was forbidden to access to $vhost$uri" ); - $class->updateStatus( 'REJECT', $session->{ $class->tsv->{whatToTrace} } ); + $class->updateStatus( $req, 'REJECT', + $session->{ $class->tsv->{whatToTrace} } ); # Redirect or Forbidden? if ( $class->tsv->{useRedirectOnForbidden} ) { $class->logger->debug("Use redirect for forbidden access"); - return $class->goToError( $uri, 403 ); + return $class->goToError( $req, $uri, 403 ); } else { $class->logger->debug("Return forbidden access"); @@ -316,16 +317,16 @@ sub forbidden { ## @rmethod protected void hideCookie() # Hide Lemonldap::NG cookie to the protected application. sub hideCookie { - my $class = shift; + my ( $class, $req ) = @_; $class->logger->debug("removing cookie"); - my $cookie = $class->header_in('Cookie'); + my $cookie = $req->env->{HTTP_COOKIE}; my $cn = $class->tsv->{cookieName}; $cookie =~ s/$cn(http)?=[^,;]*[,;\s]*//og; if ($cookie) { - $class->set_header_in( 'Cookie' => $cookie ); + $class->set_header_in( $req, 'Cookie' => $cookie ); } else { - $class->unset_header_in('Cookie'); + $class->unset_header_in( $req, 'Cookie' ); } } @@ -333,8 +334,8 @@ sub hideCookie { # Encode URl in the format used by Lemonldap::NG::Portal for redirections. # @return Base64 encoded string sub encodeUrl { - my ( $class, $url ) = @_; - $url = $class->_buildUrl($url) if ( $url !~ m#^https?://# ); + my ( $class, $req, $url ) = @_; + $url = $class->_buildUrl( $req, $url ) if ( $url !~ m#^https?://# ); return encode_base64( $url, '' ); } @@ -344,24 +345,26 @@ sub encodeUrl { # @param $arg optionnal GET parameters # @return Constant $class->REDIRECT sub goToPortal { - my ( $class, $url, $arg, $path ) = @_; + my ( $class, $req, $url, $arg, $path ) = @_; $path ||= ''; my ( $ret, $msg ); - my $urlc_init = $class->encodeUrl($url); + my $urlc_init = $class->encodeUrl( $req, $url ); $class->logger->debug( - "Redirect " . $class->remote_ip . " to portal (url was $url)" ); - $class->set_header_out( 'Location' => $class->tsv->{portal}->() + "Redirect $req->{env}->{REMOTE_ADDR} to portal (url was $url)"); + $class->set_header_out( $req, + 'Location' => $class->tsv->{portal}->() . "$path?url=$urlc_init" . ( $arg ? "&$arg" : "" ) ); return $class->REDIRECT; } sub goToError { - my ( $class, $url, $code ) = @_; - my $urlc_init = $class->encodeUrl($url); + my ( $class, $req, $url, $code ) = @_; + my $urlc_init = $class->encodeUrl( $req, $url ); $class->logger->debug( - "Redirect " . $class->remote_ip . " to lmError (url was $url)" ); - $class->set_header_out( 'Location' => $class->tsv->{portal}->() + "Redirect $req->{env}->{REMOTE_ADDR} to lmError (url was $url)"); + $class->set_header_out( $req, + 'Location' => $class->tsv->{portal}->() . "/lmerror/$code" . "?url=$urlc_init" ); return $class->REDIRECT; @@ -371,9 +374,9 @@ sub goToError { # Get user cookies and search for Lemonldap::NG cookie. # @return Value of the cookie if found, 0 else sub fetchId { - my $class = shift; - my $t = $class->header_in('Cookie') or return 0; - my $vhost = $class->resolveAlias; + my ( $class, $req ) = @_; + my $t = $req->{env}->{HTTP_COOKIE} or return 0; + my $vhost = $class->resolveAlias($req); my $lookForHttpCookie = ( $class->tsv->{securedCookie} =~ /^(2|3)$/ and !( defined( $class->tsv->{https}->{$vhost} ) ) @@ -404,7 +407,7 @@ sub fetchId { # Tries to retrieve the session whose index is id # @return true if the session was found, false else sub retrieveSession { - my ( $class, $id ) = @_; + my ( $class, $req, $id ) = @_; my $now = time(); # 1. Search if the user was the same as previous (very efficient in @@ -418,7 +421,7 @@ sub retrieveSession { } # 2. Get the session from cache or backend - my $session = $class->session( + my $session = $req->datas->{session} = ( Lemonldap::NG::Common::Session->new( { storageModule => $class->tsv->{sessionStorageModule}, @@ -460,11 +463,11 @@ sub retrieveSession { $class->tsv->{timeoutActivityInterval} ) ) { - $class->session->update( { '_lastSeen' => $now } ); + $req->datas->{session}->update( { '_lastSeen' => $now } ); if ( $session->error ) { $class->logger->error("Cannot update session $id"); - $class->logger->error( $class->session->error ); + $class->logger->error( $req->datas->{session}->error ); } else { $class->logger->debug("Update _lastSeen with $now"); @@ -487,8 +490,8 @@ sub retrieveSession { # @param $s path # @return URL sub _buildUrl { - my ( $class, $s ) = @_; - my $vhost = $class->hostname; + my ( $class, $req, $s ) = @_; + my $vhost = $req->{env}->{HTTP_HOST}; my $_https = ( defined( $class->tsv->{https}->{$vhost} ) ? $class->tsv->{https}->{$vhost} @@ -497,7 +500,7 @@ sub _buildUrl { my $portString = $class->tsv->{port}->{$vhost} || $class->tsv->{port}->{_} - || $class->get_server_port; + || $req->{env}->{SERVER_PORT}; $portString = ( ( $_https && $portString == 443 ) or ( !$_https && $portString == 80 ) @@ -513,8 +516,8 @@ sub _buildUrl { # $class->UNPROTECT if it is unprotected by "unprotect", # SKIP if is is unprotected by "skip" sub isUnprotected { - my ( $class, $uri ) = @_; - my $vhost = $class->resolveAlias; + my ( $class, $req, $uri ) = @_; + my $vhost = $class->resolveAlias($req); for ( my $i = 0 ; $i < ( $class->tsv->{locationCount}->{$vhost} || 0 ) ; @@ -531,12 +534,12 @@ sub isUnprotected { ## @rmethod void sendHeaders() # Launch function compiled by forgeHeadersInit() for the current virtual host sub sendHeaders { - my ( $class, $session ) = @_; - my $vhost = $class->resolveAlias; + my ( $class, $req, $session ) = @_; + my $vhost = $class->resolveAlias($req); if ( defined $class->tsv->{forgeHeaders}->{$vhost} ) { # Log headers in debug mode - my %headers = $class->tsv->{forgeHeaders}->{$vhost}->($session); + my %headers = $class->tsv->{forgeHeaders}->{$vhost}->( $req, $session ); foreach my $h ( sort keys %headers ) { if ( defined( my $v = $headers{$h} ) ) { $class->logger->debug("Send header $h with value $v"); @@ -545,25 +548,26 @@ sub sendHeaders { $class->logger->debug("Send header $h with empty value"); } } - $class->set_header_in(%headers); + $class->set_header_in( $req, %headers ); } } ## @rmethod void cleanHeaders() # Unset HTTP headers, when sendHeaders is skipped sub cleanHeaders { - my $class = shift; - my $vhost = $class->resolveAlias; + my ( $class, $req ) = @_; + my $vhost = $class->resolveAlias($req); if ( defined( $class->tsv->{headerList}->{$vhost} ) ) { - $class->unset_header_in( @{ $class->tsv->{headerList}->{$vhost} } ); + $class->unset_header_in( $req, + @{ $class->tsv->{headerList}->{$vhost} } ); } } ## @rmethod string resolveAlias # returns vhost whose current hostname is an alias sub resolveAlias { - my $class = shift; - my $vhost = $class->hostname; + my ( $class, $req ) = @_; + my $vhost = $req->{env}->{HTTP_HOST}; return $class->tsv->{vhostAlias}->{$vhost} || $vhost; } @@ -575,18 +579,18 @@ sub resolveAlias { # @param $msg Message to log # @return Constant ($class->REDIRECT, $class->SERVER_ERROR) sub abort { - my ( $class, $msg ) = @_; + my ( $class, $req, $msg ) = @_; # If abort is called without a valid request, fall to die eval { - my $uri = $class->unparsed_uri; + my $uri = $req->{env}->{REQUEST_URI}; $class->logger->error($msg); # Redirect or die if ( $class->tsv->{useRedirectOnError} ) { $class->logger->debug("Use redirect for error"); - return $class->goToError( $uri, 500 ); + return $class->goToError( $req, $uri, 500 ); } else { return $class->SERVER_ERROR; @@ -598,9 +602,9 @@ sub abort { ## @rmethod protected void localUnlog() # Delete current user from local cache entry. sub localUnlog { - my ( $class, $id ) = @_; + my ( $class, $req, $id ) = @_; $class->logger->debug('Local handler logout'); - if ( $id //= $class->fetchId ) { + if ( $id //= $class->fetchId($req) ) { # Delete thread datas if ( $class->datas->{_session_id} @@ -608,6 +612,7 @@ sub localUnlog { { $class->datas( {} ); } + delete $req->datas->{session}; # Delete local cache if ( $class->tsv->{refLocalStorage} @@ -622,18 +627,18 @@ sub localUnlog { # Add a javascript to html page in order to fill html form with fake data # @param uri URI to catch sub postOutputFilter { - my ( $class, $session, $uri ) = @_; - my $vhost = $class->resolveAlias; + my ( $class, $req, $session, $uri ) = @_; + my $vhost = $class->resolveAlias($req); if ( defined( $class->tsv->{outputPostData}->{$vhost}->{$uri} ) ) { $class->logger->debug("Filling a html form with fake data"); - $class->unset_header_in("Accept-Encoding"); + $class->unset_header_in( $req, "Accept-Encoding" ); my %postdata = - $class->tsv->{outputPostData}->{$vhost}->{$uri}->($session); + $class->tsv->{outputPostData}->{$vhost}->{$uri}->( $req, $session ); my $formParams = $class->tsv->{postFormParams}->{$vhost}->{$uri}; - my $js = $class->postJavascript( \%postdata, $formParams ); - $class->addToHtmlHead($js); + my $js = $class->postJavascript( $req, \%postdata, $formParams ); + $class->addToHtmlHead( $req, $js ); } } @@ -641,17 +646,18 @@ sub postOutputFilter { # Replace request body with form datas defined in configuration # @param uri URI to catch sub postInputFilter { - my ( $class, $session, $uri ) = @_; - my $vhost = $class->resolveAlias; + my ( $class, $req, $session, $uri ) = @_; + my $vhost = $class->resolveAlias($req); if ( defined( $class->tsv->{inputPostData}->{$vhost}->{$uri} ) ) { $class->logger->debug("Replacing fake data with real form data"); - my %data = $class->tsv->{inputPostData}->{$vhost}->{$uri}->($session); + my %data = + $class->tsv->{inputPostData}->{$vhost}->{$uri}->( $req, $session ); foreach ( keys %data ) { $data{$_} = uri_escape( $data{$_} ); } - $class->setPostParams( \%data ); + $class->setPostParams( $req, \%data ); } } @@ -659,7 +665,7 @@ sub postInputFilter { # build a javascript to fill a html form with fake data # @param data hashref containing input => value sub postJavascript { - my ( $class, $data, $formParams ) = @_; + my ( $class, $req, $data, $formParams ) = @_; my $form = $formParams->{formSelector} || "form"; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/SharedVariables.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/SharedVariables.pm index f41a11a89..2ab4e8d9d 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/SharedVariables.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/SharedVariables.pm @@ -24,7 +24,7 @@ BEGIN { }; # Current sessions properties - our $_v = { session => {}, datas => {}, datasUpdate => {}, }; + our $_v = { datas => {}, datasUpdate => {}, }; # Thread shared accessors foreach ( keys %$_tshv ) { diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/PSGI/Main.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/PSGI/Main.pm index 90ed4bcc3..55bb12c03 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/PSGI/Main.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/PSGI/Main.pm @@ -19,14 +19,6 @@ use constant AUTH_REQUIRED => 401; use constant MAINTENANCE => 503; use constant defaultLogger => 'Lemonldap::NG::Common::Logger::Std'; -our $request; - -## @method void setServerSignature(string sign) -# modifies web server signature -# @param $sign String to add to server signature -sub setServerSignature { -} - ## @method void thread_share(string $variable) # share or not the variable (if authorized by specific module) # @param $variable the name of the variable to share @@ -35,40 +27,27 @@ sub thread_share { # nothing to do in PSGI } -## @method void newRequest($r) -# Store request in global $request variable -# -#@param $r Lemonldap::NG::Common::PSGI::Request -sub newRequest { - my ( $class, $r ) = @_; - $request = $r; +## @method void setServerSignature(string sign) +# modifies web server signature +# @param $sign String to add to server signature +sub setServerSignature { } ## @method void set_user(string user) # sets remote_user in response headers # @param user string username sub set_user { - my ( $class, $user ) = @_; - push @{ $request->{respHeaders} }, 'Lm-Remote-User' => $user; -} - -## @method string header_in(string header) -# returns request header value -# @param header string request header -# @return request header value -sub header_in { - my ( $class, $header ) = @_; - $header ||= $class; # to use header_in as a method or as a function - return $request->{env}->{ cgiName($header) }; + my ( $class, $req, $user ) = @_; + push @{ $req->{respHeaders} }, 'Lm-Remote-User' => $user; } ## @method void set_header_in(hash headers) # sets or modifies request headers # @param headers hash containing header names => header value sub set_header_in { - my ( $class, %headers ) = @_; + my ( $class, $req, %headers ) = @_; while ( my ( $h, $v ) = each %headers ) { - $request->{env}->{ cgiName($h) } = $v; + $req->{env}->{ cgiName($h) } = $v; } } @@ -76,9 +55,9 @@ sub set_header_in { # removes request headers # @param headers array with header names to remove sub unset_header_in { - my ( $class, @headers ) = @_; + my ( $class, $req, @headers ) = @_; foreach my $h (@headers) { - delete $request->{env}->{ cgiName($h) }; + delete $req->{env}->{ cgiName($h) }; } } @@ -86,28 +65,12 @@ sub unset_header_in { # sets response headers # @param headers hash containing header names => header value sub set_header_out { - my ( $class, %headers ) = @_; + my ( $class, $req, %headers ) = @_; while ( my ( $h, $v ) = each %headers ) { - push @{ $request->{respHeaders} }, $h => $v; + push @{ $req->{respHeaders} }, $h => $v; } } -## @method string hostname -# returns host, as set by full URI or Host header -# @return host string Host value -sub hostname { - my $h = $request->{env}->{HTTP_HOST}; - $h =~ s/:\d+//; - return $h; -} - -## @method string remote_ip -# returns client IP address -# @return IP_Addr string client IP -sub remote_ip { - return $request->{env}->{REMOTE_ADDR}; -} - ## @method boolean is_initial_req # always returns true # @return is_initial_req boolean @@ -115,69 +78,12 @@ sub is_initial_req { return 1; } -## @method string args(string args) -# gets the query string -# @return args string Query string -sub args { - return $request->{env}->{QUERY_STRING}; -} - -## @method string uri -# returns the path portion of the URI, normalized, i.e. : -# * URL decoded (characters encoded as %XX are decoded, -# except ? in order not to merge path and query string) -# * references to relative path components "." and ".." are resolved -# * two or more adjacent slashes are merged into a single slash -# @return path portion of the URI, normalized -sub uri { - return $request->uri; -} - -## @method string uri_with_args -# returns the URI, with arguments and with path portion normalized -# @return URI with normalized path portion -sub uri_with_args { - return $request->{env}->{REQUEST_URI}; -} - -## @method string unparsed_uri -# returns the full original request URI, with arguments -# @return full original request URI, with arguments -sub unparsed_uri { - return $request->{env}->{REQUEST_URI}; -} - -## @method string get_server_port -# returns the port the server is receiving the current request on -# @return port string server port -sub get_server_port { - return $request->{env}->{SERVER_PORT}; -} - -## @method string method -# returns the request method -# @return port string server port -sub method { - return $request->{env}->{REQUEST_METHOD}; -} - -## Return FastCGI environment variables as hash -sub env { - return $request->{env}; -} - ## @method void print(string data) # write data in HTTP response body # @param data Text to add in response body sub print { - my ( $class, $data ) = @_; - $request->{respBody} .= $data; -} - -sub cgiName { - my $h = uc(shift); - $h =~ s/-/_/g; - return "HTTP_$h"; + my ( $class, $req, $data ) = @_; + $req->{respBody} .= $data; } sub addToHtmlHead { @@ -188,6 +94,12 @@ sub addToHtmlHead { ; } +sub cgiName { + my $h = uc(shift); + $h =~ s/-/_/g; + return "HTTP_$h"; +} + *setPostParams = *addToHtmlHead; 1; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Server/Main.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Server/Main.pm index 5c13371fb..e9c0a5511 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Server/Main.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Server/Main.pm @@ -18,43 +18,29 @@ use constant defaultLogger => 'Lemonldap::NG::Common::Logger::Syslog'; # sets or modifies request headers # @param headers hash containing header names => header value sub set_header_in { - my ( $class, %headers ) = @_; + my ( $class, $req, %headers ) = @_; for my $k ( keys %headers ) { - $Lemonldap::NG::Handler::PSGI::Main::request->{ cgiName($k) } = - $headers{$k}; + $req->{env}->{ cgiName($k) } = $headers{$k}; } - push @{ $Lemonldap::NG::Handler::PSGI::Main::request->{respHeaders} }, - %headers; + push @{ $req->{respHeaders} }, %headers; } sub unset_header_in { - my ( $class, $header ) = @_; - $Lemonldap::NG::Handler::PSGI::Main::request->{respHeaders} = - [ grep { $_ ne $header } - @{ $Lemonldap::NG::Handler::PSGI::Main::request->{respHeaders} } ]; + my ( $class, $req, $header ) = @_; + $req->{respHeaders} = [ grep { $_ ne $header } @{ $req->{respHeaders} } ]; $header =~ s/-/_/g; - delete $Lemonldap::NG::Handler::PSGI::Main::request->{ cgiName($header) }; + delete $req->{env}->{$header}; + delete $req->{env}->{"HTTP_$header"}; } # Inheritence is broken in this case with Debian >= jessie *checkType = *Lemonldap::NG::Handler::PSGI::Main::checkType; *setServerSignature = *Lemonldap::NG::Handler::PSGI::Main::setServerSignature; *thread_share = *Lemonldap::NG::Handler::PSGI::Main::thread_share; -*newRequest = *Lemonldap::NG::Handler::PSGI::Main::newRequest; *set_user = *Lemonldap::NG::Handler::PSGI::Main::set_user; -*header_in = *Lemonldap::NG::Handler::PSGI::Main::header_in; *set_header_out = *Lemonldap::NG::Handler::PSGI::Main::set_header_out; -*hostname = *Lemonldap::NG::Handler::PSGI::Main::hostname; -*remote_ip = *Lemonldap::NG::Handler::PSGI::Main::remote_ip; *is_initial_req = *Lemonldap::NG::Handler::PSGI::Main::is_initial_req; -*args = *Lemonldap::NG::Handler::PSGI::Main::args; -*env = *Lemonldap::NG::Handler::PSGI::Main::env; -*uri = *Lemonldap::NG::Handler::PSGI::Main::uri; -*uri_with_args = *Lemonldap::NG::Handler::PSGI::Main::uri_with_args; -*unparsed_uri = *Lemonldap::NG::Handler::PSGI::Main::unparsed_uri; -*get_server_port = *Lemonldap::NG::Handler::PSGI::Main::get_server_port; -*method = *Lemonldap::NG::Handler::PSGI::Main::method; *print = *Lemonldap::NG::Handler::PSGI::Main::print; -*cgiName = *Lemonldap::NG::Handler::PSGI::Main::cgiName; *addToHtmlHead = *Lemonldap::NG::Handler::PSGI::Main::addToHtmlHead; +*cgiName = *Lemonldap::NG::Handler::PSGI::Main::cgiName; 1; diff --git a/lemonldap-ng-handler/t/01-Lemonldap-NG-Handler-Main.t b/lemonldap-ng-handler/t/01-Lemonldap-NG-Handler-Main.t index c2f3a2ed1..4c809a8df 100644 --- a/lemonldap-ng-handler/t/01-Lemonldap-NG-Handler-Main.t +++ b/lemonldap-ng-handler/t/01-Lemonldap-NG-Handler-Main.t @@ -3,7 +3,7 @@ use strict; use warnings; require 't/test.pm'; -use Test::More tests => 10; +use Test::More tests => 4; BEGIN { use_ok('Lemonldap::NG::Handler::Main') } # get a standard basic configuration in $args hashref @@ -22,12 +22,13 @@ $ENV{SERVER_NAME} = "test1.example.com"; #open STDERR, '>/dev/null'; my $conf = { - 'cfgNum' => 1, - 'logLevel' => 'error', - 'portal' => 'http://auth.example.com/', - 'globalStorage' => 'Apache::Session::File', - 'post' => {}, - 'locationRules' => { + cfgNum => 1, + logLevel => 'error', + portal => 'http://auth.example.com/', + globalStorage => 'Apache::Session::File', + post => {}, + key => 1, + locationRules => { 'test1.example.com' => { # Basic rules @@ -51,10 +52,3 @@ ok( !$@, 'init' ); ok( $h->configReload($conf), 'Load conf' ); ok( $h->tsv->{portal}->() eq 'http://auth.example.com/', 'portal' ); - -ok( $h->grant( undef, '/s' ), 'basic rule "accept"' ); -ok( !$h->grant( undef, '/no' ), 'basic rule "deny"' ); -ok( $h->grant( undef, '/a/a' ), 'bad ordered rule 1/2' ); -ok( $h->grant( undef, '/a' ), 'bad ordered rule 2/2' ); -ok( !$h->grant( undef, '/b/a' ), 'good ordered rule 1/2' ); -ok( $h->grant( undef, '/b' ), 'good ordered rule 2/2' ); diff --git a/lemonldap-ng-handler/t/10-Lemonldap-NG-Handler-SharedConf.t b/lemonldap-ng-handler/t/10-Lemonldap-NG-Handler-SharedConf.t deleted file mode 100644 index 8d588ea78..000000000 --- a/lemonldap-ng-handler/t/10-Lemonldap-NG-Handler-SharedConf.t +++ /dev/null @@ -1,69 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl Lemonldap-NG-Handler-SharedConf.t' - -######################### - -# change 'tests => 1' to 'tests => last_test_to_print'; - -use Test::More tests => 6; -use Cwd 'abs_path'; -use File::Basename; -use File::Temp; -require 't/test.pm'; - -my $ini = File::Temp->new(); -my $dir = dirname( abs_path($0) ); -my $tmp = File::Temp::tempdir(); - -print $ini "[all] -logger = Lemonldap::NG::Common::Logger::Std -logLevel = error -[configuration] -type=File -dirName=$dir -localStorage=Cache::FileCache -localStorageOptions={ \\ - 'namespace' => 'lemonldap-ng-config',\\ - 'default_expires_in' => 600, \\ - 'directory_umask' => '007', \\ - 'cache_root' => '$tmp', \\ - 'cache_depth' => 0, \\ -} - -"; - -$ini->flush(); - -use Env qw(LLNG_DEFAULTCONFFILE); -$LLNG_DEFAULTCONFFILE = $ini->filename; - -#open STDERR, '>/dev/null'; - -######################### - -# Insert your test code below, the Test::More module is use()ed here so read -# its man page ( perldoc Test::More ) for help writing this test script. - -use_ok('Lemonldap::NG::Handler::Main'); - -my $ret; - -our $apacheRequest; - -my $h = 'Lemonldap::NG::Handler::Test'; - -ok( $h->init(), 'Initialize handler' ); - -ok( $h->checkType($apacheRequest) eq 'Main', 'Get Main type' ); - -ok( $ret = $h->run($apacheRequest), - 'run Handler with basic configuration and no cookie' ); - -ok( $ret = 302, 'Return code is 302' ); - -ok( - $Lemonldap::NG::Handler::Test::header eq -'Location:http://auth.example.com/?url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw==', - 'testing redirection URL from previous run' -) or print STDERR "Got: $Lemonldap::NG::Handler::Test::header\n"; - diff --git a/lemonldap-ng-handler/t/12-Lemonldap-NG-Handler-Jail.t b/lemonldap-ng-handler/t/12-Lemonldap-NG-Handler-Jail.t index 232885e42..f011c43fa 100644 --- a/lemonldap-ng-handler/t/12-Lemonldap-NG-Handler-Jail.t +++ b/lemonldap-ng-handler/t/12-Lemonldap-NG-Handler-Jail.t @@ -6,7 +6,7 @@ # change 'tests => 1' to 'tests => last_test_to_print'; use strict; -use Test::More tests => 12; +use Test::More tests => 9; require 't/test.pm'; BEGIN { use_ok('Lemonldap::NG::Handler::Main::Jail') } @@ -47,12 +47,3 @@ ok( ok( $res = &$code, "Function works" ); ok( $res == 1, 'Get good result' ); -$sub = "sub { return (hostname()) }"; -$code = $jail->jail_reval($sub); -ok( - ( defined($code) and ref($code) eq 'CODE' ), - 'hostname api function is defined' -); -ok( $res = &$code, "Function works $res" ); -ok( $res eq 'test1.example.com', 'Get good result' ); - diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm index 55793d245..366b19a01 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm @@ -1417,7 +1417,7 @@ sub getIDP { foreach ( keys %{ $self->idpList } ) { my $idpConfKey = $self->idpList->{$_}->{confKey}; my $cond = $self->idpRules->{$idpConfKey} or next; - if ( $cond->( $req->sessionInfo ) ) { + if ( $cond->( $req, $req->sessionInfo ) ) { $self->logger->debug( "IDP $idpConfKey resolution rule match"); $idp = $_; 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 d7c573bef..a3e21b50a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/CAS.pm @@ -113,7 +113,11 @@ sub run { return PE_ERROR; } my ( $host, $uri ) = ( $1, $2 ); - if ( $self->p->HANDLER->grant( $req->sessionInfo, $1, undef, $2 ) ) + if ( + $self->p->HANDLER->grant( + $req, $req->sessionInfo, $1, undef, $2 + ) + ) { $self->logger->debug("CAS service $service access allowed"); } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm index a917d0223..6e660c95a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm @@ -295,7 +295,7 @@ sub run { # Check if this RP is authorizated if ( my $rule = $self->rpRules->{$rp} ) { - unless ( $rule->( $req->sessionInfo ) ) { + unless ( $rule->( $req, $req->sessionInfo ) ) { $self->userLogger->warn( 'User ' . $req->sessionInfo->{ $self->conf->{whatToTrace} } . "was not authorizated to access to $rp" ); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm index 63867f607..3fdc18408 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm @@ -324,7 +324,7 @@ sub run { $req->env->{llng_saml_spconfkey} = $spConfKey; if ( my $rule = $self->spRules->{$sp} ) { - unless ( $rule->( $req->sessionInfo ) ) { + unless ( $rule->( $req, $req->sessionInfo ) ) { $self->userLogger->warn( 'User ' . $req->sessionInfo->{ $self->conf->{whatToTrace} } . "was not authorizated to access to $sp" ); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/JSON.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/JSON.pm index 59d285092..a4d45a094 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/JSON.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/JSON.pm @@ -90,7 +90,7 @@ sub getNotifBack { or return $self->sendError( $req, 'Unable to decrypt', 500 ); # Verify that session exists - $req->userData( $self->p->HANDLER->retrieveSession($id) ) + $req->userData( $self->p->HANDLER->retrieveSession( $req, $id ) ) or return $self->sendError( $req, 'Unknown session', 401 ); # Restore datas diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/XML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/XML.pm index bd47834b0..4787f4e7b 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/XML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/Notifications/XML.pm @@ -102,7 +102,7 @@ sub checkForNotifications { next LOOP; } - unless ( $condition->( $req->sessionInfo ) ) { + unless ( $condition->( $req, $req->sessionInfo ) ) { $self->logger->debug( 'Notification condition not authorizated'); @@ -152,7 +152,7 @@ sub getNotifBack { or return $self->sendError( $req, 'Unable to decrypt', 500 ); # Verify that session exists - $req->userData( $self->p->HANDLER->retrieveSession($id) ) + $req->userData( $self->p->HANDLER->retrieveSession( $req, $id ) ) or return $self->sendError( $req, 'Unknown session', 401 ); # Restore datas diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenIDConnect.pm index c0781730a..453156539 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenIDConnect.pm @@ -43,8 +43,6 @@ has ua => ( is => 'rw', lazy => 1, builder => sub { - - # TODO : LWP options to use a proxy for example my $ua = Lemonldap::NG::Common::UserAgent->new( $_[0]->{conf} ); $ua->env_proxy(); return $ua; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index 634a7a07c..19b1864c0 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -377,7 +377,7 @@ sub getSkin { # Load specific skin from skinRules foreach my $rule ( @{ $self->conf->{skinRules} } ) { - if ( $rule->[1]->( $req->sessionInfo ) ) { + if ( $rule->[1]->( $req, $req->sessionInfo ) ) { $skin = $rule->[0]; $self->logger->debug("Skin $skin selected from skin rule"); } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm index 7689b436d..a3620d267 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Menu.pm @@ -111,7 +111,7 @@ sub displayModules { foreach my $module ( @{ $self->menuModules } ) { $self->logger->debug("Check if $module->[0] has to be displayed"); - if ( $module->[1]->() ) { + if ( $module->[1]->( $req, $req->sessionInfo ) ) { my $moduleHash = { $module->[0] => 1 }; if ( $module->[0] eq 'Appslist' ) { $moduleHash->{'APPSLIST_LOOP'} = $self->appslist($req); @@ -465,8 +465,7 @@ sub _filterHash { delete $apphash->{$key} unless ( $self->p->HANDLER->grant( - $req->sessionInfo, - $appuri, undef, $vhost + $req, $req->sessionInfo, $appuri, undef, $vhost ) ); next; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm index d806e33c0..3f8632cfb 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm @@ -344,7 +344,7 @@ sub setMacros { my ( $self, $req ) = @_; foreach ( sort keys %{ $self->_macros } ) { $req->{sessionInfo}->{$_} = - $self->_macros->{$_}->( $req->sessionInfo ); + $self->_macros->{$_}->( $req, $req->sessionInfo ); } PE_OK; } @@ -383,7 +383,7 @@ sub setPersistentSessionInfo { sub setLocalGroups { my ( $self, $req ) = @_; foreach ( sort keys %{ $self->_groups } ) { - if ( $self->_groups->{$_}->( $req->sessionInfo ) ) { + if ( $self->_groups->{$_}->( $req, $req->sessionInfo ) ) { $req->{sessionInfo}->{groups} .= $self->conf->{multiValuesSeparator} . $_; $req->{sessionInfo}->{hGroups}->{$_}->{name} = $_; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm index 1de4aeda0..1d42c07ab 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm @@ -17,9 +17,6 @@ has steps => ( is => 'rw' ); # Authentication result has authResult => ( is => 'rw' ); -# Datas shared between methods -has datas => ( is => 'rw' ); - # Session datas when created has id => ( is => 'rw' ); has sessionInfo => ( is => 'rw' ); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm index e88939093..7aac7148d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm @@ -260,7 +260,7 @@ sub autoRedirect { # Redirection should be made if urldc defined if ( $req->{urldc} ) { - if ( $self->_jsRedirect->() ) { + if ( $self->_jsRedirect->( $req, $req->sessionInfo ) ) { $req->error(PE_REDIRECT); $req->datas->{redirectFormMethod} = "get"; } @@ -490,7 +490,7 @@ sub _deleteSession { ) unless ($preserveCookie); } - HANDLER->localUnlog( $session->id ); + HANDLER->localUnlog( $req, $session->id ); $session->remove; # Create an obsolete cookie to remove it diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm index ce133ba30..fdf5efdb7 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm @@ -48,7 +48,7 @@ sub init { sub _run { my ( $self, $req ) = @_; - return PE_OK unless ( $self->rule->( $req->sessionInfo ) ); + return PE_OK unless ( $self->rule->( $req, $req->sessionInfo ) ); $self->userLogger->info( 'Second factor required (' . $self->prefix . ') for ' diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm index 6f9306439..001ab5146 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm @@ -41,7 +41,7 @@ sub grantSession { } foreach ( sort sortByComment keys %{ $self->rules } ) { $self->logger->debug("Grant session condition \"$_\""); - unless ( $self->rules->{$_}->( $req->sessionInfo ) ) { + unless ( $self->rules->{$_}->( $req, $req->sessionInfo ) ) { $req->userData( {} ); $self->userLogger->error( 'User ' . $req->user diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm index 342f50ead..2f24ebff3 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/RESTServer.pm @@ -316,7 +316,7 @@ sub mysession { # Now check for authorization my $res = - $self->p->HANDLER->grant( $req->userData, $uri, undef, $host ); + $self->p->HANDLER->grant( $req, $req->userData, $uri, undef, $host ); $self->logger->debug(" Result is $res"); return $self->p->sendJSONresponse( $req, { result => $res } ); } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm index 45be219af..4131f4f4d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/SOAPServer.pm @@ -391,7 +391,8 @@ sub isAuthorizedURI { } $req->{sessionInfo} = $session->data; - my $r = $self->p->HANDLER->grant( $req, $uri, undef, $host ); + my $r = + $self->p->HANDLER->grant( $req, $req->{sessionInfo}, $uri, undef, $host ); return $r; }