File Coverage

blib/lib/Apache/Session/Store/LDAP.pm
Criterion Covered Total %
statement 9 68 13.2
branch 0 34 0.0
condition 0 2 0.0
subroutine 3 10 30.0
pod 0 7 0.0
total 12 121 9.9


line stmt bran cond sub pod time code
1             package Apache::Session::Store::LDAP;
2              
3 1     1   4 use strict;
  1         2  
  1         30  
4 1     1   9 use vars qw($VERSION);
  1         1  
  1         37  
5 1     1   649 use Net::LDAP;
  1         150145  
  1         6  
6              
7             $VERSION = '0.3';
8              
9             sub new {
10 0     0 0   my $class = shift;
11 0           return bless {}, $class;
12             }
13              
14             sub insert {
15 0     0 0   my $self = shift;
16 0           my $session = shift;
17 0           $self->{args} = $session->{args};
18              
19 0           my $msg = $self->ldap->add(
20             "cn=$session->{data}->{_session_id}," . $self->{args}->{ldapConfBase},
21             attrs => [
22             objectClass => [ 'top', 'applicationProcess' ],
23             cn => $session->{data}->{_session_id},
24             description => $session->{serialized},
25             ],
26             );
27              
28 0 0         $self->ldap->unbind() && delete $self->{ldap};
29 0 0         $self->logError($msg) if ( $msg->code );
30             }
31              
32             sub update {
33 0     0 0   my $self = shift;
34 0           my $session = shift;
35 0           $self->{args} = $session->{args};
36              
37 0           my $msg = $self->ldap->modify(
38             "cn=$session->{data}->{_session_id}," . $self->{args}->{ldapConfBase},
39             replace => { description => $session->{serialized}, },
40             );
41              
42 0 0         $self->ldap->unbind() && delete $self->{ldap};
43 0 0         $self->logError($msg) if ( $msg->code );
44             }
45              
46             sub materialize {
47 0     0 0   my $self = shift;
48 0           my $session = shift;
49 0           $self->{args} = $session->{args};
50              
51 0           my $msg = $self->ldap->search(
52             base => "cn=$session->{data}->{_session_id},"
53             . $self->{args}->{ldapConfBase},
54             filter => '(objectClass=applicationProcess)',
55             scope => 'base',
56             attrs => ['description'],
57             );
58              
59 0 0         $self->ldap->unbind() && delete $self->{ldap};
60 0 0         $self->logError($msg) if ( $msg->code );
61              
62 0           eval {
63 0           $session->{serialized} = $msg->shift_entry()->get_value('description');
64             };
65              
66 0 0         if ( !defined $session->{serialized} ) {
67 0           die "Object does not exist in data store";
68             }
69             }
70              
71             sub remove {
72 0     0 0   my $self = shift;
73 0           my $session = shift;
74 0           $self->{args} = $session->{args};
75              
76 0           $self->ldap->delete(
77             "cn=$session->{data}->{_session_id}," . $self->{args}->{ldapConfBase} );
78              
79 0 0         $self->ldap->unbind() && delete $self->{ldap};
80             }
81              
82             sub ldap {
83 0     0 0   my $self = shift;
84 0 0         return $self->{ldap} if ( $self->{ldap} );
85              
86             # Parse servers configuration
87 0           my $useTls = 0;
88 0           my $tlsParam;
89 0           my @servers = ();
90 0           foreach my $server ( split /[\s,]+/, $self->{args}->{ldapServer} ) {
91 0 0         if ( $server =~ m{^ldap\+tls://([^/]+)/?\??(.*)$} ) {
92 0           $useTls = 1;
93 0           $server = $1;
94 0   0       $tlsParam = $2 || "";
95             }
96             else {
97 0           $useTls = 0;
98             }
99 0           push @servers, $server;
100             }
101              
102             # Connect
103 0 0         my $ldap = Net::LDAP->new(
    0          
104             \@servers,
105             onerror => undef,
106             (
107             $self->{args}->{ldapPort}
108             ? ( port => $self->{args}->{ldapPort} )
109             : ()
110             ),
111             ) or die( 'Unable to connect to ' . join( ' ', @servers ) );
112              
113             # Start TLS if needed
114 0 0         if ($useTls) {
115 0           my %h = split( /[&=]/, $tlsParam );
116 0 0         $h{cafile} = $self->{args}->{caFile} if ( $self->{args}->{caFile} );
117 0 0         $h{capath} = $self->{args}->{caPath} if ( $self->{args}->{caPath} );
118 0           my $start_tls = $ldap->start_tls(%h);
119 0 0         if ( $start_tls->code ) {
120 0           $self->logError($start_tls);
121 0           return;
122             }
123             }
124              
125             # Bind with credentials
126 0           my $bind = $ldap->bind( $self->{args}->{ldapBindDN},
127             password => $self->{args}->{ldapBindPassword} );
128 0 0         if ( $bind->code ) {
129 0           $self->logError($bind);
130 0           return;
131             }
132              
133 0           $self->{ldap} = $ldap;
134 0           return $ldap;
135             }
136              
137             sub logError {
138 0     0 0   my $self = shift;
139 0           my $ldap_operation = shift;
140 0           die "LDAP error " . $ldap_operation->code . ": " . $ldap_operation->error;
141             }
142              
143             1;
144              
145             =pod
146              
147             =head1 NAME
148              
149             Apache::Session::Store::LDAP - Use LDAP to store persistent objects
150              
151             =head1 SYNOPSIS
152              
153             use Apache::Session::Store::LDAP;
154              
155             my $store = new Apache::Session::Store::LDAP;
156              
157             $store->insert($ref);
158             $store->update($ref);
159             $store->materialize($ref);
160             $store->remove($ref);
161              
162             =head1 DESCRIPTION
163              
164             This module fulfills the storage interface of Apache::Session. The serialized
165             objects are stored in an LDAP directory file using the Net::LDAP Perl module.
166              
167             =head1 OPTIONS
168              
169             This module requires one argument in the usual Apache::Session style. The
170             keys ldapServer, ldapBase, ldapBindDN, ldapBindPassword are required. The key
171             ldapPort is optional. Example:
172              
173             tie %s, 'Apache::Session::LDAP', undef,
174             {
175             ldapServer => 'localhost',
176             ldapBase => 'dc=example,dc=com',
177             ldapBindDN => 'cn=admin,dc=example,dc=com',
178             ldapBindPassword => 'pass',
179             };
180              
181             =head1 AUTHOR
182              
183             Xavier Guimard, Eguimard@E
184              
185             =head1 COPYRIGHT AND LICENSE
186              
187             Copyright (C) 2009, 2012 by Xavier Guimard
188             Copyright (C) 2014 by Clement Oudot
189              
190             This library is free software; you can redistribute it and/or modify
191             it under the same terms as Perl itself, either Perl version 5.10.0 or,
192             at your option, any later version of Perl 5 you may have available.
193              
194             =head1 SEE ALSO
195              
196             L
197              
198             =cut