From 713144ea3dc73c01d4c46afd1e8e86e14414c36b Mon Sep 17 00:00:00 2001 From: Yadd Date: Fri, 8 Apr 2022 12:14:47 +0200 Subject: [PATCH] Add new liblemonldap-ng-ssoaas-apache-client-perl package (#2739) --- debian/control | 10 + ...nldap-ng-ssoaas-apache-client-perl.install | 2 + lemonldap-ng-handler/MANIFEST | 1 + .../NG/Handler/ApacheMP2/FCGIClient.pm | 181 +---------------- .../lib/Lemonldap/NG/SSOaaS/Apache/Client.pm | 184 ++++++++++++++++++ 5 files changed, 199 insertions(+), 179 deletions(-) create mode 100644 debian/liblemonldap-ng-ssoaas-apache-client-perl.install create mode 100644 lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm diff --git a/debian/control b/debian/control index 2c9da1a91..c2f5c0e68 100644 --- a/debian/control +++ b/debian/control @@ -138,6 +138,16 @@ Description: Lemonldap::NG FastCGI server Lemonldap::NG FastCGI server provides a Nginx auth_request server that handles also LLNG Portal and Manager. +Package: liblemonldap-ng-ssoaas-apache-client-perl +Architecture: all +Section: web +Depends: ${misc:Depends}, + ${perl:Depends} +Description: Lemonldap::NG SSOaaS client for Apache + Lemonldap::NG is a complete Web-SSO system that provides a SSO-as-a-Service + system, natively usable with Nginx. Lemonldap::NG::SSOaaS::Apache::Client + permits one to enroll an Apache server into Lemonldap::NG's SSOaaS service. + Package: lemonldap-ng-uwsgi-app Architecture: all Section: web diff --git a/debian/liblemonldap-ng-ssoaas-apache-client-perl.install b/debian/liblemonldap-ng-ssoaas-apache-client-perl.install new file mode 100644 index 000000000..584f5aff2 --- /dev/null +++ b/debian/liblemonldap-ng-ssoaas-apache-client-perl.install @@ -0,0 +1,2 @@ +usr/share/perl5/Lemonldap/NG/SSOaaS/Apache +usr/share/man/man3/Lemonldap::NG::SSOaaS::Apache* diff --git a/lemonldap-ng-handler/MANIFEST b/lemonldap-ng-handler/MANIFEST index 7ab477de0..e15677941 100644 --- a/lemonldap-ng-handler/MANIFEST +++ b/lemonldap-ng-handler/MANIFEST @@ -56,6 +56,7 @@ lib/Lemonldap/NG/Handler/Server/OAuth2.pm lib/Lemonldap/NG/Handler/Server/SecureToken.pm lib/Lemonldap/NG/Handler/Server/ServiceToken.pm lib/Lemonldap/NG/Handler/Server/ZimbraPreAuth.pm +lib/Lemonldap/NG/SSOaaS/Apache/Client.pm lib/Plack/Middleware/Auth/LemonldapNG.pm Makefile.PL MANIFEST This list of files diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm index 93e381759..e1ba1daac 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm @@ -1,184 +1,7 @@ -# Apache2 FastCGI client to query remote LL::NG FastCGI server -# package Lemonldap::NG::Handler::ApacheMP2::FCGIClient; -use strict; -use Apache2::Connection; -use Apache2::RequestUtil; -use Apache2::RequestRec; -use Apache2::Const -compile => - qw(FORBIDDEN HTTP_UNAUTHORIZED REDIRECT OK DECLINED DONE SERVER_ERROR AUTH_REQUIRED HTTP_SERVICE_UNAVAILABLE); -use Apache2::Log; -use APR::Table; -use IO::Socket::INET; -use FCGI::Client; -use URI; -use URI::Escape qw(uri_unescape); +use Lemonldap::NG::SSOaaS::Apache::Client; -use constant FORBIDDEN => Apache2::Const::FORBIDDEN; -use constant HTTP_UNAUTHORIZED => Apache2::Const::HTTP_UNAUTHORIZED; -use constant REDIRECT => Apache2::Const::REDIRECT; -use constant DECLINED => Apache2::Const::DECLINED; -use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR; - -our $VERSION = '2.0.15'; - -sub handler { - my ( $class, $r ) = @_; - $r ||= $class; - my ( $uri, $args ) = ( $r->uri, $r->args ); - my $uri_full = $uri . ( $args ? "?$args" : '' ); - my $env = { - - #%ENV, - HTTP_HOST => $r->hostname, - REMOTE_ADDR => ( - $r->connection->can('remote_ip') - ? $r->connection->remote_ip - : $r->connection->client_ip - ), - QUERY_STRING => $args, - REQUEST_URI => $uri_full, - PATH_INFO => '', - SERVER_PORT => $r->get_server_port, - REQUEST_METHOD => $r->method, - }; - - foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) { - if ( my $t = $r->dir_config($_) ) { - $env->{$_} = $t; - } - } - - $r->headers_in->do( - sub { - my $h = shift; - my $k = uc($h); - if ( $k ne 'HOST' ) { - $k =~ s/-/_/g; - $env->{"HTTP_$k"} = $r->headers_in->{$h}; - } - return 1; - } - ); - $uri = URI->new( "http://" . $r->hostname . $r->unparsed_uri ); - $env->{PATH_INFO} = uri_unescape( $uri->path ); - my ( $host, $port ) = ( $r->dir_config('LLNG_SERVER') =~ /^(.*):(\d+)$/ ); - unless ( $host and $port ) { - print STDERR 'Missing or bad LLNG_SERVER'; - return SERVER_ERROR; - } - my $sock = IO::Socket::INET->new( - PeerAddr => $host, - PeerPort => $port, - ) or die $!; - foreach ( keys %$env ) { - delete $env->{$_} unless ( length $env->{$_} ); - } - my ( $stdout, $stderr, $status ) = - FCGI::Client::Connection->new( sock => $sock )->request($env); - my %hdrs = - map { s/\r//g; m/(.*?):\s*(.*)/; $_ ? ( $1, $2 ) : () } split /\n+/, - $stdout; - unless ( $hdrs{Status} =~ /^(\d+)\s+(.*?)$/ ) { - print STDERR "Bad status line $hdrs{Status}\n"; - return SERVER_ERROR; - } - $status = $1; - - if ( ( $status == 302 or $status == 401 ) and $hdrs{Location} ) { - $r->err_headers_out->set( Location => $hdrs{Location} ); - return REDIRECT; - } - - $r->user( $hdrs{'Lm-Remote-User'} ) if $hdrs{'Lm-Remote-User'}; - $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} ) - if $hdrs{'Lm-Remote-Custom'}; - - my $i = 1; - while ( $hdrs{"Headername$i"} ) { - $r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} ) - if $hdrs{"Headervalue$i"}; - $i++; - } - $status = DECLINED if ( $status < 300 ); - - return $status; -} +our @ISA = ('Lemonldap::NG::SSOaaS::Apache::Client'); 1; -__END__ - -=pod - -=encoding utf8 - -=head1 NAME - -Lemonldap::NG::Handler::ApacheMP2::FCGIClient - Apache client for Lemonldap::NG -FastCGI server. - -=head1 SYNOPSIS - -In apache2.conf: - - - PerlHeaderParserHandler Lemonldap::NG::Handler::ApacheMP2::FCGIClient - PerlSetVar LLNG_SERVER 127.0.0.1:9090 - PerlSetVar VHOSTTYPE DevOps - # or PerlSetVar VHOSTTYPE DevOpsST - PerlSetVar RULES_URL http://app.tld/rules.json - PerlSetVar HOST HTTP_HOST - PerlSetVar PORT_REDIRECT SERVER_PORT - PerlSetVar HTTPS_REDIRECT HTTPS - ... - - -=head1 DESCRIPTION - -Lemonldap::NG::Handler::ApacheMP2::FCGIClient is an alternative to -L that replace inside handler. It calls a -remote Lemonldap::NG FastCGI server to get authentication, authorization and -headers. - -=head1 SEE ALSO - -L, -L - -=head1 AUTHORS - -=over - -=item LemonLDAP::NG team L - -=back - -=head1 BUG REPORT - -Use OW2 system to report bug or ask for features: -L - -=head1 DOWNLOAD - -Lemonldap::NG is available at -L - -=head1 COPYRIGHT AND LICENSE - -See COPYING file for details. - -This library is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see L. - -=cut diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm new file mode 100644 index 000000000..4aaa40a21 --- /dev/null +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/SSOaaS/Apache/Client.pm @@ -0,0 +1,184 @@ +# Apache2 FastCGI client to query remote LL::NG FastCGI server +# +package Lemonldap::NG::SSOaaS::Apache::Client; + +use strict; +use Apache2::Connection; +use Apache2::RequestUtil; +use Apache2::RequestRec; +use Apache2::Const -compile => + qw(FORBIDDEN HTTP_UNAUTHORIZED REDIRECT OK DECLINED DONE SERVER_ERROR AUTH_REQUIRED HTTP_SERVICE_UNAVAILABLE); +use Apache2::Log; +use APR::Table; +use IO::Socket::INET; +use FCGI::Client; +use URI; +use URI::Escape qw(uri_unescape); + +use constant FORBIDDEN => Apache2::Const::FORBIDDEN; +use constant HTTP_UNAUTHORIZED => Apache2::Const::HTTP_UNAUTHORIZED; +use constant REDIRECT => Apache2::Const::REDIRECT; +use constant DECLINED => Apache2::Const::DECLINED; +use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR; + +our $VERSION = '2.0.15'; + +sub handler { + my ( $class, $r ) = @_; + $r ||= $class; + my ( $uri, $args ) = ( $r->uri, $r->args ); + my $uri_full = $uri . ( $args ? "?$args" : '' ); + my $env = { + + #%ENV, + HTTP_HOST => $r->hostname, + REMOTE_ADDR => ( + $r->connection->can('remote_ip') + ? $r->connection->remote_ip + : $r->connection->client_ip + ), + QUERY_STRING => $args, + REQUEST_URI => $uri_full, + PATH_INFO => '', + SERVER_PORT => $r->get_server_port, + REQUEST_METHOD => $r->method, + }; + + foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) { + if ( my $t = $r->dir_config($_) ) { + $env->{$_} = $t; + } + } + + $r->headers_in->do( + sub { + my $h = shift; + my $k = uc($h); + if ( $k ne 'HOST' ) { + $k =~ s/-/_/g; + $env->{"HTTP_$k"} = $r->headers_in->{$h}; + } + return 1; + } + ); + $uri = URI->new( "http://" . $r->hostname . $r->unparsed_uri ); + $env->{PATH_INFO} = uri_unescape( $uri->path ); + my ( $host, $port ) = ( $r->dir_config('LLNG_SERVER') =~ /^(.*):(\d+)$/ ); + unless ( $host and $port ) { + print STDERR 'Missing or bad LLNG_SERVER'; + return SERVER_ERROR; + } + my $sock = IO::Socket::INET->new( + PeerAddr => $host, + PeerPort => $port, + ) or die $!; + foreach ( keys %$env ) { + delete $env->{$_} unless ( length $env->{$_} ); + } + my ( $stdout, $stderr, $status ) = + FCGI::Client::Connection->new( sock => $sock )->request($env); + my %hdrs = + map { s/\r//g; m/(.*?):\s*(.*)/; $_ ? ( $1, $2 ) : () } split /\n+/, + $stdout; + unless ( $hdrs{Status} =~ /^(\d+)\s+(.*?)$/ ) { + print STDERR "Bad status line $hdrs{Status}\n"; + return SERVER_ERROR; + } + $status = $1; + + if ( ( $status == 302 or $status == 401 ) and $hdrs{Location} ) { + $r->err_headers_out->set( Location => $hdrs{Location} ); + return REDIRECT; + } + + $r->user( $hdrs{'Lm-Remote-User'} ) if $hdrs{'Lm-Remote-User'}; + $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} ) + if $hdrs{'Lm-Remote-Custom'}; + + my $i = 1; + while ( $hdrs{"Headername$i"} ) { + $r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} ) + if $hdrs{"Headervalue$i"}; + $i++; + } + $status = DECLINED if ( $status < 300 ); + + return $status; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +Lemonldap::NG::SSOaaS::Apache::Client - Apache client for Lemonldap::NG +FastCGI server. + +=head1 SYNOPSIS + +In apache2.conf: + + + PerlHeaderParserHandler Lemonldap::NG::SSOaaS::Apache::Client + PerlSetVar LLNG_SERVER 127.0.0.1:9090 + PerlSetVar VHOSTTYPE DevOps + # or PerlSetVar VHOSTTYPE DevOpsST + PerlSetVar RULES_URL http://app.tld/rules.json + PerlSetVar HOST HTTP_HOST + PerlSetVar PORT_REDIRECT SERVER_PORT + PerlSetVar HTTPS_REDIRECT HTTPS + ... + + +=head1 DESCRIPTION + +Lemonldap::NG::SSOaaS::Apache::Client is an alternative to +L that replace inside handler. It calls a +remote Lemonldap::NG FastCGI server to get authentication, authorization and +headers. + +=head1 SEE ALSO + +L, +L + +=head1 AUTHORS + +=over + +=item LemonLDAP::NG team L + +=back + +=head1 BUG REPORT + +Use OW2 system to report bug or ask for features: +L + +=head1 DOWNLOAD + +Lemonldap::NG is available at +L + +=head1 COPYRIGHT AND LICENSE + +See COPYING file for details. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see L. + +=cut