File Coverage

blib/lib/Kolab/LDAP/Backend/ad.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Kolab::LDAP::Backend::ad;
2              
3             ##
4             ## Copyright (c) 2003 Code Fusion cc
5             ##
6             ## Writen by Stuart Bingė
7             ##
8             ## This program is free software; you can redistribute it and/or
9             ## modify it under the terms of the GNU General Public License as
10             ## published by the Free Software Foundation; either version 2, or
11             ## (at your option) any later version.
12             ##
13             ## This program is distributed in the hope that it will be useful,
14             ## but WITHOUT ANY WARRANTY; without even the implied warranty of
15             ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16             ## General Public License for more details.
17             ##
18             ## You can view the GNU General Public License, online, at the GNU
19             ## Project's homepage; see .
20             ##
21              
22 1     1   27614 use 5.008;
  1         4  
  1         39  
23 1     1   6 use strict;
  1         2  
  1         35  
24 1     1   4 use warnings;
  1         7  
  1         54  
25 1     1   701 use Kolab;
  0            
  0            
26             use Kolab::Util;
27             use Kolab::LDAP;
28             use Net::LDAP;
29             use Net::LDAP::Control;
30             use vars qw($ldap $cyrus);
31              
32             require Exporter;
33              
34             our @ISA = qw(Exporter);
35              
36             our %EXPORT_TAGS = (
37             'all' => [ qw(
38             &startup
39             &run
40             ) ]
41             );
42              
43             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
44              
45             our @EXPORT = qw(
46              
47             );
48              
49             our $VERSION = sprintf('%d.%02d', q$Revision: 1.1.1.1 $ =~ /(\d+)\.(\d+)/);
50              
51             sub startup { 1; }
52              
53             sub shutdown
54             {
55             Kolab::log('AD', 'Shutting down');
56             exit(0);
57             }
58              
59             sub abort
60             {
61             Kolab::log('AD', 'Aborting');
62             exit(1);
63             }
64              
65             sub changeCallback
66             {
67             Kolab::log('AD', 'Change notification received', KOLAB_DEBUG);
68              
69             ### $_[0] isa Net::LDAP::Message
70             ### $_[1] shouldbea Net::LDAP::Entry
71              
72             my $mesg = shift || 0;
73             my $entry = shift || 0;
74              
75             my $issearch = $mesg->isa("Net::LDAP::Search");
76              
77             if (!$issearch) {
78             Kolab::log('AD', 'mesg is not a search object, testing code...', KOLAB_DEBUG);
79             if ($mesg->code == 88) {
80             Kolab::log('AD', 'changeCallback() -> Exit code received, returning', KOLAB_DEBUG);
81             return;
82             } elsif ($mesg->code) {
83             Kolab::log('AD', "mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG);
84             &abort;
85             }
86             } else {
87             Kolab::log('AD', 'mesg is a search object, not testing code', KOLAB_DEBUG);
88             }
89              
90             if (!$entry) {
91             Kolab::log('AD', 'changeCallback() called with a null entry', KOLAB_DEBUG);
92             return;
93             } elsif (!$entry->isa("Net::LDAP::Entry")) {
94             Kolab::log('AD', 'changeCallback() called with an invalid entry', KOLAB_DEBUG);
95             return;
96             }
97              
98             if (!Kolab::LDAP::isObject($entry, $Kolab::config{'user_object_class'})) {
99             Kolab::log('AD', "Entry is not a `" . $Kolab::config{'user_object_class'} . "', returning", KOLAB_DEBUG);
100             return;
101             }
102              
103             my $deleted = $entry->get_value($Kolab::config{'user_field_deleted'}) || 0;
104             if ($deleted) {
105             Kolab::LDAP::deleteObject($ldap, $cyrus, $entry);
106             return;
107             }
108              
109             Kolab::LDAP::createObject($ldap, $cyrus, $entry);
110             }
111              
112             sub run
113             {
114             # This should be called from a separate thread, as we set our
115             # own interrupt handlers here
116              
117             $SIG{'INT'} = \&shutdown;
118             $SIG{'TERM'} = \&shutdown;
119              
120             END {
121             alarm 0;
122             Kolab::LDAP::destroy($ldap);
123             }
124              
125             my $mesg;
126              
127             Kolab::log('AD', 'Listener starting up');
128              
129             $cyrus = Kolab::Cyrus::create;
130              
131             Kolab::log('AD', 'Cyrus connection established', KOLAB_DEBUG);
132              
133             while (1) {
134             Kolab::log('AD', 'Creating LDAP connection to AD server', KOLAB_DEBUG);
135              
136             $ldap = Kolab::LDAP::create(
137             $Kolab::config{'user_ldap_ip'},
138             $Kolab::config{'user_ldap_port'},
139             $Kolab::config{'user_bind_dn'},
140             $Kolab::config{'user_bind_pw'},
141             1
142             );
143              
144             if (!$ldap) {
145             Kolab::log('AD', 'Sleeping 5 seconds...');
146             sleep 5;
147             next;
148             }
149              
150             Kolab::log('AD', 'LDAP connection established', KOLAB_DEBUG);
151              
152             Kolab::LDAP::ensureAsync($ldap);
153              
154             Kolab::log('AD', 'Async checked', KOLAB_DEBUG);
155              
156             my $ctrl = Net::LDAP::Control->new(
157             type => '1.2.840.113556.1.4.528',
158             critical => 'true'
159             );
160              
161             Kolab::log('AD', 'Control created', KOLAB_DEBUG);
162              
163             my @userdns = split(/;/, $Kolab::config{'user_dn_list'});
164             my $userdn;
165              
166             Kolab::log('AD', 'User DN list = ' . $Kolab::config{'user_dn_list'}, KOLAB_DEBUG);
167              
168             if (length(@userdns) == 0) {
169             Kolab::log('AD', 'No user DNs specified, exiting', KOLAB_ERROR);
170             exit(1);
171             }
172              
173             foreach $userdn (@userdns) {
174             Kolab::log('AD', "Registering change notification on DN `$userdn'");
175              
176             $mesg = $ldap->search (
177             base => $userdn,
178             scope => 'one',
179             control => [ $ctrl ],
180             callback => \&changeCallback,
181             filter => '(objectClass=*)',
182             attrs => [
183             '*',
184             $Kolab::config{'user_field_guid'},
185             $Kolab::config{'user_field_modified'},
186             $Kolab::config{'user_field_quota'},
187             $Kolab::config{'user_field_deleted'},
188             ],
189             );
190              
191             Kolab::log('AD', "Change notification registered on `$userdn'");
192             }
193              
194             eval {
195             local $SIG{ALRM} = sub {
196             alarm 0;
197             Kolab::log('AD', 'Connection refresh period expired; tearing down connection');
198              
199             Kolab::LDAP::destroy($ldap);
200             next;
201             };
202              
203             Kolab::log('AD', 'Waiting for changes (refresh period = ' . $Kolab::config{'conn_refresh_period'} . ' minutes)...');
204             alarm $Kolab::config{'conn_refresh_period'} * 60;
205             $mesg->sync;
206             alarm 0;
207             };
208             }
209              
210             1;
211             }
212              
213             1;
214             __END__