File Coverage

blib/lib/Kolab/LDAP/Backend/slurpd.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Kolab::LDAP::Backend::slurpd;
2              
3             ##
4             ## Copyright (c) 2003 Code Fusion cc
5             ##
6             ## Writen by Stuart Bingė
7             ## Portions based on work by the following people:
8             ##
9             ## (c) 2003 Tassilo Erlewein
10             ## (c) 2003 Martin Konold
11             ## (c) 2003 Achim Frank
12             ##
13             ##
14             ## This program is free software; you can redistribute it and/or
15             ## modify it under the terms of the GNU General Public License as
16             ## published by the Free Software Foundation; either version 2, or
17             ## (at your option) any later version.
18             ##
19             ## This program is distributed in the hope that it will be useful,
20             ## but WITHOUT ANY WARRANTY; without even the implied warranty of
21             ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22             ## General Public License for more details.
23             ##
24             ## You can view the GNU General Public License, online, at the GNU
25             ## Project's homepage; see .
26             ##
27              
28 1     1   38485 use 5.008;
  1         5  
  1         49  
29 1     1   6 use strict;
  1         2  
  1         36  
30 1     1   5 use warnings;
  1         13  
  1         40  
31 1     1   2519 use IO::Select;
  1         3053  
  1         75  
32 1     1   986 use IO::Socket;
  1         29536  
  1         5  
33 1     1   1111 use Convert::ASN1 qw(:io);
  0            
  0            
34             use Net::LDAP;
35             use Net::LDAP::Constant qw(LDAP_SUCCESS LDAP_PROTOCOL_ERROR);
36             use Net::LDAP::ASN qw(LDAPRequest LDAPResponse LDAPResult);
37             use Kolab;
38             use Kolab::Util;
39             use Kolab::LDAP;
40             use vars qw($conn $server);
41              
42             require Exporter;
43              
44             our @ISA = qw(Exporter);
45              
46             our %EXPORT_TAGS = (
47             'all' => [ qw(
48             &startup
49             &run
50             ) ]
51             );
52              
53             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
54              
55             our @EXPORT = qw(
56              
57             );
58              
59             our $VERSION = sprintf('%d.%02d', q$Revision: 1.1.1.1 $ =~ /(\d+)\.(\d+)/);
60              
61             sub startup { 1; }
62              
63             sub shutdown
64             {
65             Kolab::log('SD', 'Shutting down');
66             exit(0);
67             }
68              
69             sub abort
70             {
71             Kolab::log('SD', 'Aborting');
72             exit(1);
73             }
74              
75             sub PROTOCOLOP_BINDREQUEST () { 0x00 }
76             sub PROTOCOLOP_BINDRESPONSE () { 0x01 }
77             sub PROTOCOLOP_UNBINDREQUEST () { 0x02 }
78             sub PROTOCOLOP_SEARCHREQUEST () { 0x03 }
79             sub PROTOCOLOP_SEARCHRESENTRY () { 0x04 }
80             sub PROTOCOLOP_SEARCHRESDONE () { 0x05 }
81             sub PROTOCOLOP_SEARCHRESREF () { 0x06 }
82             sub PROTOCOLOP_MODIFYREQUEST () { 0x07 }
83             sub PROTOCOLOP_MODIFYRESPONSE () { 0x08 }
84             sub PROTOCOLOP_ADDREQUEST () { 0x09 }
85             sub PROTOCOLOP_ADDRESPONSE () { 0x10 }
86             sub PROTOCOLOP_DELREQUEST () { 0x11 }
87             sub PROTOCOLOP_DELRESPONSE () { 0x12 }
88             sub PROTOCOLOP_MODDNREQUEST () { 0x13 }
89             sub PROTOCOLOP_MODDNRESPONSE () { 0x14 }
90             sub PROTOCOLOP_COMPAREREQUEST () { 0x15 }
91             sub PROTOCOLOP_COMPARERESPONSE () { 0x16 }
92             sub PROTOCOLOP_ABANDONREQUEST () { 0x17 }
93             sub PROTOCOLOP_EXTENDEDREQ () { 0x18 }
94             sub PROTOCOLOP_EXTENDEDRESP () { 0x19 }
95              
96             sub getRequestType
97             {
98             my $op = shift;
99             if ($op->{bindRequest}) { return "bindRequest"; }
100             if ($op->{unbindRequest}) { return "unbindRequest"; }
101             if ($op->{addRequest}) { return "addRequest"; }
102             if ($op->{delRequest}) { return "delRequest"; }
103             if ($op->{modifyRequest}) { return "modifyRequest"; }
104             if ($op->{modDNRequest}) { return "modDNRequest"; }
105             if ($op->{searchRequest}) { return "searchRequest"; }
106             if ($op->{compareRequest}) { return "compareRequest"; }
107             if ($op->{abandonRequest}) { return "abandonRequest"; }
108             if ($op->{extendedRequest}) { return "extendedRequest"; }
109             return "";
110             }
111              
112             sub responseBind
113             {
114             my $req = shift;
115             my $pdu = $LDAPResponse->encode(
116             messageID => $req->{messageID},
117             protocolOp => {
118             choiceID => PROTOCOLOP_BINDRESPONSE,
119             bindResponse => {
120             resultCode => LDAP_SUCCESS,
121             matchedDN => $req->{bindRequest}{name},
122             errorMessage => "",
123             serverSaslCreds => ""
124             }
125             }
126             );
127             if (!$pdu) {
128             Kolab::log('SD', "LDAPResponse error `" . $LDAPResponse->error . "'");
129             &abort;
130             }
131             return $pdu;
132             }
133              
134             sub responseAdd
135             {
136             my $req = shift;
137             my $pdu = $LDAPResponse->encode(
138             messageID => $req->{messageID},
139             protocolOp => {
140             choiceID => PROTOCOLOP_ADDRESPONSE,
141             addResponse => {
142             resultCode => LDAP_SUCCESS,
143             matchedDN => $req->{addRequest}{objectName},
144             errorMessage => ""
145             }
146             }
147             );
148             if (!$pdu) {
149             Kolab::log('SD', "LDAPResponse error `" . $LDAPResponse->error . "'");
150             &abort;
151             }
152             return $pdu;
153             }
154              
155             sub responseDel
156             {
157             my $req = shift;
158             my $pdu = $LDAPResponse->encode(
159             messageID => $req->{messageID},
160             protocolOp => {
161             choiceID => PROTOCOLOP_DELRESPONSE,
162             addResponse => {
163             resultCode => LDAP_SUCCESS,
164             matchedDN => $req->{delRequest},
165             errorMessage => ""
166             }
167             }
168             );
169             if (!$pdu) {
170             Kolab::log('SD', "LDAPResponse error `" . $LDAPResponse->error . "'");
171             &abort;
172             }
173             return $pdu;
174             }
175              
176             sub responseMod
177             {
178             my $req = shift;
179             my $pdu = $LDAPResponse->encode(
180             messageID => $req->{messageID},
181             protocolOp => {
182             choiceID => PROTOCOLOP_MODIFYRESPONSE,
183             addResponse => {
184             resultCode => LDAP_SUCCESS,
185             matchedDN => $req->{modifyRequest}{object},
186             errorMessage => ""
187             }
188             }
189             );
190             if (!$pdu) {
191             Kolab::log('SD', "LDAPResponse error `" . $LDAPResponse->error . "'");
192             &abort;
193             }
194             return $pdu;
195             }
196              
197             sub responseModDN
198             {
199             my $req = shift;
200             my $pdu = $LDAPResponse->encode(
201             messageID => $req->{messageID},
202             protocolOp => {
203             choiceID => PROTOCOLOP_MODDNRESPONSE,
204             addResponse => {
205             resultCode => LDAP_SUCCESS,
206             matchedDN => $req->{modDNRequest}{entry},
207             errorMessage => ""
208             }
209             }
210             );
211             if (!$pdu) {
212             Kolab::log('SD', "LDAPResponse error `" . $LDAPResponse->error . "'");
213             &abort;
214             }
215             return $pdu;
216             }
217              
218             sub run
219             {
220             # This should be called from a separate thread, as we set our
221             # own interrupt handlers here
222              
223             $SIG{'INT'} = \&shutdown;
224             $SIG{'TERM'} = \&shutdown;
225              
226             END {
227             if ($conn) { $conn->close; }
228             if ($server) { $server->close; }
229             }
230              
231             my $request;
232             my $response;
233             my $pdu;
234             my $changes = 0;
235              
236             my $port = $Kolab::config{'slurpd_port'};
237             Kolab::log('SD', "Opening listen server on port $port");
238             $server = IO::Socket::INET->new(
239             LocalPort => $port,
240             Proto => "tcp",
241             ReuseAddr => 1,
242             Type => SOCK_STREAM,
243             LocalAddr => "127.0.0.1",
244             Listen => 10
245             );
246             if (!$server) {
247             Kolab::log('SD', "Unable to open TCP listen server on port $port, Error = $@", KOLAB_ERROR);
248             &abort;
249             }
250              
251             Kolab::log('SD', 'Listen server opened, waiting for incoming connections');
252              
253             while ($conn = $server->accept()) {
254             Kolab::log('SD', 'Incoming connection accepted');
255              
256             my $select = IO::Select->new($conn);
257              
258             while ($conn) {
259             undef $pdu;
260             my $ready;
261             my $offset = 0;
262              
263             if (!($select->can_read(1)) && $changes) {
264             $changes = 0;
265             Kolab::log('SD', 'Change detected w/ no pending LDAP messages; reloading services if needed');
266             Kolab::LDAP::sync;
267             system($Kolab::config{'prefix'} . '/sbin/kolabconf');
268             }
269              
270             Kolab::log('SD', 'Waiting for LDAP updates');
271              
272             for ($ready = 1; $ready; $ready = $select->can_read(1)) {
273             Kolab::log('SD', 'Reading ASN', KOLAB_DEBUG);
274             $offset = asn_read($conn, $pdu, $offset);
275             defined($offset) or $offset = 0;
276             sleep 1;
277             }
278              
279             if ($pdu) {
280             $request = $LDAPRequest->decode($pdu);
281             if (!$request) {
282             Kolab::log('SD', "Unable to decode slurpd request, Error = `" . $LDAPRequest->error . "'", KOLAB_ERROR);
283             &abort;
284             }
285             $_ = getRequestType($request);
286             Kolab::log('SD', "Request $_ received", KOLAB_DEBUG);
287             undef $pdu;
288              
289             SWITCH: {
290             if (/bindRequest/) { $pdu = responseBind($request); last SWITCH; }
291             if (/addRequest/) { $pdu = responseAdd($request); $changes = 1; last SWITCH; }
292             if (/delRequest/) { $pdu = responseDel($request); $changes = 1; last SWITCH; }
293             if (/modifyRequest/) { $pdu = responseMod($request); $changes = 1; last SWITCH; }
294             if (/modDNRequest/) { $pdu = responseModDN($request); $changes = 1; last SWITCH; }
295              
296             $conn->close;
297             undef $conn;
298             }
299             }
300              
301             if ($pdu) {
302             Kolab::log('SD', 'Writing response', KOLAB_DEBUG);
303             syswrite($conn, $pdu, length($pdu));
304             $response = $LDAPResponse->decode($pdu);
305             if (!$response) {
306             Kolab::log('SD', "Unable to decode slurpd request, Error = `" . $LDAPRequest->error . "'");
307             &abort;
308             }
309             }
310             }
311             }
312              
313             $server->close;
314              
315             1;
316             }
317              
318             1;
319             __END__