Commit 15884636 authored by Yadd's avatar Yadd
Browse files

#166 in progress:

 - Lemonldap::NG::Common::Apache::Session is used as Apache::Session module and provides a way to choose _session_id
parent 20ab38f9
/etc/lemonldap-ng/lemonldap-ng.ini
/etc/lemonldap-ng/for_etc_hosts
/usr/share/perl5/Lemonldap/NG/Common*
/usr/share/man/man3/Lemonldap::NG::Common*
/usr/share/perl5/auto/Lemonldap/NG/Common
/usr/share/perl5/Lemonldap/NG/Common*
/usr/share/lemonldap-ng/ressources
/usr/share/lemonldap-ng/bin/convertConfig
/usr/share/lemonldap-ng/bin/lmMigrateConfFiles2ini
......
......@@ -8,239 +8,294 @@
package Lemonldap::NG::Common::Apache::Session;
use strict;
use Storable qw(thaw);
our $VERSION = 0.21;
BEGIN {
sub Apache::Session::searchOn {
my ( $class, $args, $selectField, $value, @fields ) = @_;
my %res = ();
$class->get_key_from_all_sessions(
$args,
sub {
my $entry = shift;
my $id = shift;
return undef unless ( $entry->{$selectField} eq $value );
if (@fields) {
$res{$id}->{$_} = $entry->{$_} foreach (@fields);
}
else {
$res{$id} = $entry;
}
undef;
}
);
return \%res;
}
sub Apache::Session::searchLt {
my ( $class, $args, $selectField, $value, @fields ) = @_;
my %res = ();
$class->get_key_from_all_sessions(
$args,
sub {
my $entry = shift;
my $id = shift;
return undef unless ( $entry->{$selectField} < $value );
if (@fields) {
$res{$id}->{$_} = $entry->{$_} foreach (@fields);
}
else {
$res{$id} = $entry;
}
undef;
}
);
return \%res;
use AutoLoader 'AUTOLOAD';
use Apache::Session;
use base qw(Apache::Session);
our $VERSION = 0.3;
sub _load {
my $backend = shift;
unless ( $backend->can('populate') ) {
eval "require $backend"
or die $@;
}
}
sub Apache::Session::get_key_from_all_sessions {
die "This Apache module is not supported by Lemonldap::NG";
sub populate {
my $self = shift;
my $backend = $self->{args}->{backend};
_load($backend);
$backend .= "::populate";
{
no strict 'refs';
$self = $self->$backend(@_);
}
if ( $self->{args}->{setId} ) {
$self->{generate} = \&setId;
$self->{validate} = sub { 1 };
}
return $self;
}
sub Apache::Session::MySQL::get_key_from_all_sessions {
my ( $class, $args, $data ) = @_;
__END__
my $dbh =
DBI->connect( $args->{DataSource}, $args->{UserName},
$args->{Password} )
or die("$!$@");
my $sth = $dbh->prepare('SELECT id,a_session from sessions');
$sth->execute;
my %res;
while ( my @row = $sth->fetchrow_array ) {
if ( ref($data) eq 'CODE' ) {
my $tmp = &$data( thaw( $row[1] ), $row[0] );
$res{ $row[0] } = $tmp if ( defined($tmp) );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = thaw( $row[1] );
$res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data);
sub setId {
my $session = shift;
$session->{data}->{_session_id} = $session->{args}->{setId};
}
sub searchOn {
my ( $class, $args, $selectField, $value, @fields ) = splice @_;
my $backend = $args->{backend};
_load($backend);
if ( $backend->can('searchOn') ) {
$backend .= '::searchOn';
return $class->$backend( $args, $selectField, $value, @fields );
}
my %res = ();
$class->get_key_from_all_sessions(
$args,
sub {
my $entry = shift;
my $id = shift;
return undef unless ( $entry->{$selectField} eq $value );
if (@fields) {
$res{$id}->{$_} = $entry->{$_} foreach (@fields);
}
else {
$res{ $row[0] } = thaw( $row[1] );
$res{$id} = $entry;
}
undef;
}
return \%res;
}
*Apache::Session::Postgres::get_key_from_all_sessions =
\&Apache::Session::MySQL::get_key_from_all_sessions;
*Apache::Session::Oracle::get_key_from_all_sessions =
\&Apache::Session::MySQL::get_key_from_all_sessions;
*Apache::Session::Sybase::get_key_from_all_sessions =
\&Apache::Session::MySQL::get_key_from_all_sessions;
*Apache::Session::Informix::get_key_from_all_sessions =
\&Apache::Session::MySQL::get_key_from_all_sessions;
sub Apache::Session::File::get_key_from_all_sessions {
my ( $class, $args, $data ) = @_;
$args->{Directory} ||= '/tmp';
unless ( opendir DIR, $args->{Directory} ) {
die "Cannot open directory $args->{Directory}\n";
}
my @t =
grep { -f "$args->{Directory}/$_" and /^[A-Za-z0-9@\-]+$/ }
readdir(DIR);
closedir DIR;
my %res;
for my $f (@t) {
open F, "$args->{Directory}/$f";
my $row = join '', <F>;
if ( ref($data) eq 'CODE' ) {
$res{$f} = &$data( thaw($row), $f );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = thaw($row);
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
);
return \%res;
}
sub searchLt {
my ( $class, $args, $selectField, $value, @fields ) = splice @_;
my %res = ();
$class->get_key_from_all_sessions(
$args,
sub {
my $entry = shift;
my $id = shift;
return undef unless ( $entry->{$selectField} < $value );
if (@fields) {
$res{$id}->{$_} = $entry->{$_} foreach (@fields);
}
else {
$res{$f} = thaw($row);
$res{$id} = $entry;
}
undef;
}
return \%res;
}
sub Apache::Session::PHP::get_key_from_all_sessions {
require Apache::Session::Serialize::PHP;
my ( $class, $args, $data ) = @_;
my $directory = $args->{SavePath} || '/tmp';
unless ( opendir DIR, $args->{SavePath} ) {
die "Cannot open directory $args->{SavePath}\n";
}
my @t =
grep { -f "$args->{SavePath}/$_" and /^sess_[A-Za-z0-9@\-]+$/ }
readdir(DIR);
closedir DIR;
my %res;
for my $f (@t) {
open F, "$args->{SavePath}/$f";
my $row = join '', <F>;
if ( ref($data) eq 'CODE' ) {
$res{$f} =
&$data( Apache::Session::Serialize::PHP::unserialize($row),
$f );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Apache::Session::Serialize::PHP::unserialize($row);
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$f} = Apache::Session::Serialize::PHP::unserialize($row);
}
);
return \%res;
}
sub get_key_from_all_sessions {
my $class = shift;
#my ( $class, $args, $data ) = splice @_;
my $backend = $_[0]->{backend};
_load($backend);
if ( $backend->can('get_key_from_all_sessions') ) {
$backend .= '::get_key_from_all_sessions';
return $class->$backend(@_);
}
if ( $backend =~
/^Apache::Session::(?:MySQL|Postgres|Oracle|Sybase|Informix)$/ )
{
return $class->_dbiGKFAS(@_);
}
elsif ( $backend =~ /^Apache::Session::(?:NoSQL|Redis|Cassandra)$/ ) {
return $class->_NoSQLGKFAS(@_);
}
elsif ( $backend =~ /^Apache::Session::(File|PHP|DBFile|LDAP)$/ ) {
no strict 'refs';
my $tmp = "_${1}GKFAS";
return $class->$tmp(@_);
}
else {
die "$backend can not provide session exploration";
}
}
sub _dbiGKFAS {
my ( $class, $args, $data ) = @_;
require Storable;
my $dbh =
DBI->connect( $args->{DataSource}, $args->{UserName}, $args->{Password} )
or die("$!$@");
my $sth = $dbh->prepare('SELECT id,a_session from sessions');
$sth->execute;
my %res;
while ( my @row = $sth->fetchrow_array ) {
if ( ref($data) eq 'CODE' ) {
my $tmp = &$data( Storable::thaw( $row[1] ), $row[0] );
$res{ $row[0] } = $tmp if ( defined($tmp) );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Storable::thaw( $row[1] );
$res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{ $row[0] } = Storable::thaw( $row[1] );
}
return \%res;
}
return \%res;
}
sub Apache::Session::DB_File::get_key_from_all_sessions {
my ( $class, $args, $data ) = @_;
sub _FileGKFAS {
my ( $class, $args, $data ) = @_;
$args->{Directory} ||= '/tmp';
require Storable;
if ( !tied %{ $class->{dbm} } ) {
my $rv = tie %{ $class->{dbm} }, 'DB_File', $args->{FileName};
if ( !$rv ) {
die "Could not open dbm file " . $args->{FileName} . ": $!";
}
unless ( opendir DIR, $args->{Directory} ) {
die "Cannot open directory $args->{Directory}\n";
}
my @t =
grep { -f "$args->{Directory}/$_" and /^[A-Za-z0-9@\-]+$/ } readdir(DIR);
closedir DIR;
my %res;
for my $f (@t) {
open F, "$args->{Directory}/$f";
my $row = join '', <F>;
if ( ref($data) eq 'CODE' ) {
$res{$f} = &$data( Storable::thaw($row), $f );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Storable::thaw($row);
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$f} = Storable::thaw($row);
}
}
return \%res;
}
sub _PHPGKFAS {
require Apache::Session::Serialize::PHP;
my ( $class, $args, $data ) = @_;
my $directory = $args->{SavePath} || '/tmp';
unless ( opendir DIR, $args->{SavePath} ) {
die "Cannot open directory $args->{SavePath}\n";
}
my @t =
grep { -f "$args->{SavePath}/$_" and /^sess_[A-Za-z0-9@\-]+$/ }
readdir(DIR);
closedir DIR;
my %res;
for my $f (@t) {
open F, "$args->{SavePath}/$f";
my $row = join '', <F>;
if ( ref($data) eq 'CODE' ) {
$res{$f} =
&$data( Apache::Session::Serialize::PHP::unserialize($row), $f );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Apache::Session::Serialize::PHP::unserialize($row);
$res{$f}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$f} = Apache::Session::Serialize::PHP::unserialize($row);
}
}
return \%res;
}
my %res;
foreach my $k ( keys %{ $class->{dbm} } ) {
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( thaw( $class->{dbm}->{$k} ), $k );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = thaw( $class->{dbm}->{$k} );
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$k} = thaw( $class->{dbm}->{$k} );
}
sub _DB_FileGKFAS {
my ( $class, $args, $data ) = @_;
require Storable;
if ( !tied %{ $class->{dbm} } ) {
my $rv = tie %{ $class->{dbm} }, 'DB_File', $args->{FileName};
if ( !$rv ) {
die "Could not open dbm file " . $args->{FileName} . ": $!";
}
return \%res;
}
sub Apache::Session::LDAP::get_key_from_all_sessions {
my ( $class, $args, $data ) = @_;
my $ldap = Apache::Session::Store::LDAP::ldap( { args => $args } );
my $msg = $ldap->search(
base => $args->{ldapConfBase},
filter => '(objectClass=applicationProcess)',
scope => 'base',
attrs => [ 'cn', 'description' ],
);
Apache::Session::Store::LDAP->logError($msg) if ( $msg->code );
my %res;
foreach my $entry ( $msg->entries ) {
my ( $k, $v ) =
( $entry->get_value('cn'), $entry->get_value('description') );
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( thaw($v), $k );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = thaw($v);
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$k} = thaw($v);
}
}
my %res;
foreach my $k ( keys %{ $class->{dbm} } ) {
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( Storable::thaw( $class->{dbm}->{$k} ), $k );
}
return \%res;
}
sub Apache::Session::NoSQL::get_key_from_all_sessions {
require Redis;
require MIME::Base64;
my ( $class, $args, $data ) = @_;
die "Only Redis is supported" unless ( $args->{Driver} eq 'Redis' );
my $redis = Redis->new(%$args);
my @keys = $redis->keys('*');
my %res;
foreach my $k (@keys) {
my $v =
eval { thaw( MIME::Base64::decode_base64( $redis->get($k) ) ) };
next if ($@);
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( $v, $k );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
$res{$k}->{$_} = $v->{$_} foreach (@$data);
}
else {
$res{$k} = $v;
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Storable::thaw( $class->{dbm}->{$k} );
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$k} = Storable::thaw( $class->{dbm}->{$k} );
}
}
return \%res;
}
sub _LDAPGKFAS {
my ( $class, $args, $data ) = @_;
require Storable;
my $ldap = Apache::Session::Store::LDAP::ldap( { args => $args } );
my $msg = $ldap->search(
base => $args->{ldapConfBase},
filter => '(objectClass=applicationProcess)',
scope => 'base',
attrs => [ 'cn', 'description' ],
);
Apache::Session::Store::LDAP->logError($msg) if ( $msg->code );
my %res;
foreach my $entry ( $msg->entries ) {
my ( $k, $v ) =
( $entry->get_value('cn'), $entry->get_value('description') );
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( Storable::thaw($v), $k );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
my $tmp = Storable::thaw($v);
$res{$k}->{$_} = $tmp->{$_} foreach (@$data);
}
else {
$res{$k} = Storable::thaw($v);
}
}
return \%res;
}
sub _NoSQLGKFAS {
require Redis;
require MIME::Base64;
require Storable;
my ( $class, $args, $data ) = @_;
die "Only Redis is supported" unless ( $args->{Driver} eq 'Redis' );
my $redis = Redis->new(%$args);
my @keys = $redis->keys('*');
my %res;
foreach my $k (@keys) {
my $v = eval {
Storable::thaw( MIME::Base64::decode_base64( $redis->get($k) ) );
};
next if ($@);
if ( ref($data) eq 'CODE' ) {
$res{$k} = &$data( $v, $k );
}
elsif ($data) {
$data = [$data] unless ( ref($data) );
$res{$k}->{$_} = $v->{$_} foreach (@$data);
}
else {
$res{$k} = $v;
}
return \%res;
}
return \%res;
}
1;
......@@ -64,8 +64,12 @@ sub new {
$self->{managerSkin} ||= 'default';
# Now try to load Apache::Session module
eval "use $globalStorage";
unless ( $globalStorage->can('populate') ) {
eval "require $globalStorage";
$class->abort( "Unable to load $globalStorage", $@ ) if ($@);
}
%{ $self->{globalStorageOptions} } = %$globalStorageOptions;
$self->{globalStorageOptions}->{backend} = $globalStorage;
# Check if we use X-FORWARDED-FOR header for IP
$self->{ipField} =
......@@ -128,8 +132,8 @@ sub list {
$count = 0;
# Parse all sessions to store first letter
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},
sub {
my $entry = shift;
next if ( $entry->{_httpSessionType} );
......@@ -179,8 +183,8 @@ sub doubleIp {
my ( $byUid, $byIp, $res, $count );
# Parse all sessions
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},
sub {
my $entry = shift;
my $id = shift;
......@@ -246,8 +250,8 @@ sub fullip {
$reip =~ s/\\\*/\.\*/g;
# Parse all sessions and store only if IP match regexp
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},
sub {
my $entry = shift;
my $id = shift;
......@@ -296,8 +300,8 @@ sub fulluid {
$reuser =~ s/\\\*/\.\*/g;
# Parse all sessions to find user that match regexp
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},
sub {
my $entry = shift;
my $id = shift;
......@@ -600,8 +604,8 @@ sub session {
sub uidByIp {
my ( $self, $ip ) = splice @_;
my ( $byUser, $res );
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},
sub {
my $entry = shift;
my $id = shift;
......@@ -634,8 +638,8 @@ sub uidByIp {
sub uid {
my ( $self, $uid ) = splice @_;
my ( $byIp, $res );
$globalStorage->get_key_from_all_sessions(
$globalStorageOptions,
Lemonldap::NG::Common::Apache::Session->get_key_from_all_sessions(
$self->{globalStorageOptions},