diff options
author | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2011-03-20 14:17:52 (GMT) |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2011-03-20 14:17:52 (GMT) |
commit | 6640df17e23dc034ce60924cdcca762f3f555f41 (patch) | |
tree | 231941b0ae86201ef655091261a9b3b7a1097ffa /lib | |
parent | bb6a22f3ff17c3dbc087f29b8bcf799ee0503be9 (diff) | |
download | perl-Kolab-6640df17e23dc034ce60924cdcca762f3f555f41.tar.gz |
Fix indentation to be consistent
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kolab.pm | 67 | ||||
-rw-r--r-- | lib/Kolab/Conf.pm | 9 | ||||
-rw-r--r-- | lib/Kolab/Cyrus.pm | 70 | ||||
-rw-r--r-- | lib/Kolab/LDAP.pm | 460 | ||||
-rw-r--r-- | lib/Kolab/LDAP/Backend.pm | 8 | ||||
-rw-r--r-- | lib/Kolab/LDAP/Backend/ad.pm | 174 | ||||
-rw-r--r-- | lib/Kolab/LDAP/Backend/fds.pm | 191 | ||||
-rw-r--r-- | lib/Kolab/LDAP/Backend/slurpd.pm | 148 | ||||
-rw-r--r-- | lib/Kolab/LDAP/Backend/syncrepl.pm | 430 | ||||
-rw-r--r-- | lib/Kolab/Util.pm | 6 |
10 files changed, 797 insertions, 766 deletions
diff --git a/lib/Kolab.pm b/lib/Kolab.pm index 0445bd4..0c743bf 100644 --- a/lib/Kolab.pm +++ b/lib/Kolab.pm @@ -41,7 +41,7 @@ our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( %config - $reloadOk + $reloadOk &reloadConfig &reload &log @@ -103,7 +103,7 @@ sub reloadConfig # Return if we should only read the base information. if ($globals_only) { - return; + return; } # Determine the root of the kolab installation, and read `kolab.globals' @@ -114,8 +114,8 @@ sub reloadConfig $tempval = (getpwnam($config{'kolab_musr'}))[7]; if (! defined $tempval) { $config{'log_level'} = KOLAB_WARN; - &log('C', 'Unable to determine the kolab user main directory', KOLAB_ERROR); - $error = 1; + &log('C', 'Unable to determine the kolab user main directory', KOLAB_ERROR); + $error = 1; } # Now read `kolab.conf', overwriting values read from `kolab.globals' @@ -130,56 +130,56 @@ sub reloadConfig $config{'kolab_uid'} = (getpwnam($config{'kolab_musr'}))[2]; if (!defined $config{'kolab_uid'}) { &log('C', "Unable to determine the uid of user '$config{'kolab_musr'}'", KOLAB_ERROR); - $error = 1; + $error = 1; } $config{'kolab_gid'} = (getgrnam($config{'kolab_mgrp'}))[2]; if (!defined $config{'kolab_gid'}) { &log('C', "Unable to determine the gid of user '$config{'kolab_mgrp'}'", KOLAB_ERROR); - $error = 1; + $error = 1; } $config{'kolab_n_uid'} = (getpwnam($config{'kolab_usr'}))[2]; if (!defined $config{'kolab_n_uid'}) { &log('C', "Unable to determine the uid of user '$config{'kolab_usr'}", KOLAB_ERROR); - $error = 1; + $error = 1; } $config{'kolab_n_gid'} = (getgrnam($config{'kolab_grp'}))[2]; if (!defined $config{'kolab_n_gid'}) { &log('C', "Unable to determine the gid of user $config{'kolab_grp'}", KOLAB_ERROR); - $error = 1; + $error = 1; } $config{'kolab_r_uid'} = (getpwnam($config{'kolab_rusr'}))[2]; if (!defined $config{'kolab_r_uid'}) { &log('C', "Unable to determine the uid of user '$config{'kolab_rusr'}'", KOLAB_ERROR); - $error = 1; + $error = 1; } $config{'kolab_r_gid'} = (getgrnam($config{'kolab_rgrp'}))[2]; if (!defined $config{'kolab_r_gid'}) { &log('C', "Unable to determine the gid of user '$config{'kolab_rgrp'}'", KOLAB_ERROR); - $error = 1; + $error = 1; } # Make sure the critical variables we need were defined in kolab.conf if (!exists $config{'bind_dn'} || !exists $config{'bind_pw'} || !exists $config{'ldap_uri'} || !exists $config{'base_dn'}) { &log('C', "One or more required configuration variables (`bind_dn', `bind_pw', `ldap_uri' and/or `base_dn') are missing in `kolab.conf'", KOLAB_ERROR); - $error = 1; + $error = 1; } # Make a hash of the bind password available too if( !exists $config{'bind_pw_hash'} ) { - my $hashcmd = $config{'hashmethod'} . " '".$config{'bind_pw'}."'"; - $config{'bind_pw_hash'} = `$hashcmd`; - chomp($config{'bind_pw_hash'}); + my $hashcmd = $config{'hashmethod'} . " '".$config{'bind_pw'}."'"; + $config{'bind_pw_hash'} = `$hashcmd`; + chomp($config{'bind_pw_hash'}); } # Retrieve the LDAP values of the main kolab object to complete our config hash if (!($tempval = URI->new($config{'ldap_uri'}))) { &log('C', "Unable to parse ldap_uri `" . $config{'ldap_uri'} . "'", KOLAB_ERROR); - $error = 1; + $error = 1; } else { $config{'ldap_ip'} = $tempval->host; $config{'ldap_port'} = $tempval->port; @@ -196,13 +196,13 @@ sub reloadConfig if (!($ldap = Net::LDAP->new($config{'ldap_uri'}, verify => 'none' ))) { &log('C', "Unable to connect to LDAP server `" . $config{'ldap_ip'} . ":" . $config{'ldap_port'} . "'", KOLAB_ERROR); - $error = 1; + $error = 1; } $mesg = $ldap->bind($config{'bind_dn'}, password => $config{'bind_pw'}) if $ldap; if ($ldap && $mesg->code) { &log('C', "Unable to bind to DN `" . $config{'bind_dn'} . "'", KOLAB_ERROR); - $error = 1; + $error = 1; } #$ldap = Kolab::LDAP::create( @@ -221,20 +221,20 @@ sub reloadConfig if (!$mesg->code) { $ldapobject = $mesg->pop_entry; foreach $tempval ($ldapobject->attributes) { - my $vals = $ldapobject->get_value($tempval, asref => 1 ); - if( !ref($vals) ) { - # Not a ref at all??? - &log('C', "Attribute $tempval does not exist", KOLAB_WARN ); - } elsif( @{$vals} == 1 ) { - $config{lc($tempval)} = $vals->[0]; - } else { - $config{lc($tempval)} = $vals; - } + my $vals = $ldapobject->get_value($tempval, asref => 1 ); + if( !ref($vals) ) { + # Not a ref at all??? + &log('C', "Attribute $tempval does not exist", KOLAB_WARN ); + } elsif( @{$vals} == 1 ) { + $config{lc($tempval)} = $vals->[0]; + } else { + $config{lc($tempval)} = $vals; + } } } else { &log('C', "Unable to find kolab object `" . $config{'kolab_dn'} . "'", KOLAB_ERROR); # exit(1); - $error = 1; + $error = 1; } } else { &log('C', "Unable to read configuration data from LDAP", KOLAB_WARN); @@ -283,7 +283,7 @@ sub reloadConfig if (($config{'directory_mode'} eq 'syncrepl') && !defined $config{'syncrepl_cookie_file'}) { &log('C', "Configuration variable `syncrepl_cookie_file' is missing ". "in `kolab.globals' or `kolab.globals' while using `syncrepl' directory_mode", KOLAB_ERROR); - $error = 1; + $error = 1; } # `conn_refresh_period' specifies how many minutes to wait before forceably @@ -313,7 +313,7 @@ sub reloadConfig if (!($tempval = URI->new($config{'user_ldap_uri'}))) { &log('C', "Unable to parse user_ldap_uri `" . $config{'user_ldap_uri'} . "'", KOLAB_ERROR); # exit(1); - $error = 1; + $error = 1; } else { $config{'user_ldap_ip'} = $tempval->host; $config{'user_ldap_port'} = $tempval->port; @@ -342,12 +342,11 @@ sub reloadConfig $config{'user_field_guid'} = 'objectGUID' if (!exists $config{'user_field_guid'}); $config{'user_field_quota'} = 'userquota' if (!exists $config{'user_field_quota'}); } else { - # slurd/default + # slurpd/default $config{'user_field_deleted'} = 'kolabdeleteflag' if (!exists $config{'user_field_deleted'}); $config{'user_field_modified'} = 'modifytimestamp' if (!exists $config{'user_field_modified'}); $config{'user_field_guid'} = 'entryUUID' if (!exists $config{'user_field_guid'}); $config{'user_field_quota'} = 'cyrus-userquota' if (!exists $config{'user_field_quota'}); - } # The `sf_XXX' variables are the shared folder equivalents of the `user_XXX' variables @@ -356,7 +355,7 @@ sub reloadConfig if (!($tempval = URI->new($config{'sf_ldap_uri'}))) { &log('C', "Unable to parse sf_ldap_uri `" . $config{'sf_ldap_uri'} . "'", KOLAB_ERROR); # exit(1); - $error = 1; + $error = 1; } else { $config{'sf_ldap_ip'} = $tempval->host; $config{'sf_ldap_port'} = $tempval->port; @@ -383,14 +382,14 @@ sub reloadConfig $config{'sf_field_quota'} = 'cyrus-userquota' if (!exists $config{'sf_field_quota'}); } - # The `group_XXX' variables are the distribution list/groups + # The `group_XXX' variables are the distribution list/groups # equivalents of the `user_XXX' variables $config{'group_ldap_uri'} = $config{'ldap_uri'} if (!exists $config{'group_ldap_uri'}); if (!($tempval = URI->new($config{'group_ldap_uri'}))) { &log('C', "Unable to parse group_ldap_uri `" . $config{'group_ldap_uri'} . "'", KOLAB_ERROR); # exit(1); - $error = 1; + $error = 1; } else { $config{'group_ldap_ip'} = $tempval->host; $config{'group_ldap_port'} = $tempval->port; diff --git a/lib/Kolab/Conf.pm b/lib/Kolab/Conf.pm index 8ca62ca..69e39f6 100644 --- a/lib/Kolab/Conf.pm +++ b/lib/Kolab/Conf.pm @@ -227,7 +227,7 @@ sub build { } else { # Modifier functions SWITCH: { - # Join function + # Join function $fct eq 'join' && do { if (ref $Kolab::config{$attr} eq "ARRAY") { my @vals = @{$Kolab::config{$attr}} ; @@ -260,11 +260,10 @@ sub build { ($skip == 0) && print $config $_; } } - + $template->close; $config->close; - if (-f $cfg) { my $cfgtemp = $config->filename; my $rc = `diff -q $cfg $cfgtemp`; @@ -369,7 +368,7 @@ sub getCyrusGroups foreach (@$userlist) { my $uid = $_; my $umesg = $ldap->search( base => $uid, - scope => 'base', + scope => 'base', filter => '(objectClass=*)' ); if ( $umesg && $umesg->code() <= 0 && $umesg->count() == 1 ) { my $mail; @@ -549,7 +548,7 @@ sub loadMetaTemplates my ($found_end, $target, $permissions, $ownership); while (<TEMPLATE>) { $line = $_; - + if (!$found_end) { $found_end = $line =~ /^KOLAB_META_END$/; if (!$found_end && $line) { diff --git a/lib/Kolab/Cyrus.pm b/lib/Kolab/Cyrus.pm index 4973add..f4462af 100644 --- a/lib/Kolab/Cyrus.pm +++ b/lib/Kolab/Cyrus.pm @@ -63,7 +63,7 @@ sub create if (!$cyrus) { Kolab::log('Y', 'Unable to connect to local Cyrus admin interface', KOLAB_ERROR); - return 0; + return 0; } if (!$cyrus->authenticate( @@ -72,7 +72,7 @@ sub create 'Mechanism' => 'LOGIN', )) { Kolab::log('Y', "Unable to authenticate with Cyrus admin interface, Error = `" . $cyrus->error . "'", KOLAB_ERROR); - return 0; + return 0; } return $cyrus; @@ -84,10 +84,10 @@ sub createUid my $sf = shift || 0; my $seperator = '/'; my $uidprefix = 'user'; - if ($sf) { - $seperator = '.'; + if ($sf) { + $seperator = '.'; $uidprefix = 'shared'; - } + } return $uidprefix . $seperator . $user; # return 'user' . ($sf ? '.' : '/') . $user; } @@ -124,21 +124,21 @@ sub createCalendar my @mailboxes = $cyrus->list("user/$user/*\@$domain"); my %info; foreach my $mailbox (@mailboxes) { - my $u = @{$mailbox}[0]; - %info = $cyrus->info($u, ('/vendor/kolab/folder-type')); - my $key = '/mailbox/{' . $u . '}/vendor/kolab/folder-type'; - if (exists($info{$key}) && $info{$key} eq 'event.default') { - $calendar = $u; - } + my $u = @{$mailbox}[0]; + %info = $cyrus->info($u, ('/vendor/kolab/folder-type')); + my $key = '/mailbox/{' . $u . '}/vendor/kolab/folder-type'; + if (exists($info{$key}) && $info{$key} eq 'event.default') { + $calendar = $u; + } } if ($calendar) { Kolab::log('Y', "Skipping calendar creation for $user\@$domain as $calendar is a default calendar.", KOLAB_DEBUG); } else { Kolab::log('Y', "Creating default calendar for $user\@$domain.", KOLAB_DEBUG); - createMailbox($cyrus, $folder, 0); - setFolderType($cyrus, $folder, 0, 'event.default'); - setACL($cyrus, $folder, 0, $acl); + createMailbox($cyrus, $folder, 0); + setFolderType($cyrus, $folder, 0, 'event.default'); + setACL($cyrus, $folder, 0, $acl); Kolab::log('Y', "Successfully created default calendar for $user\@$domain.", KOLAB_DEBUG); } } @@ -152,24 +152,24 @@ sub setQuota my $cyruid = &createUid($uid, $sf); if( $quota < 0 ) { - return; + return; } (my $root, my %quota) = $cyrus->quotaroot($cyruid); my $setquota = $quota{'STORAGE'}[1]; if (!defined($setquota) || ($setquota != $quota)) { - if( $quota == 0 ) { - Kolab::log('Y', "Removing quota from mailbox `$cyruid'"); - if (!$cyrus->setquota($cyruid)) { - Kolab::log('Y', "Unable to remove quota for mailbox `$cyruid', Error = `" . $cyrus->error . "'", KOLAB_WARN); - } - } else { - Kolab::log('Y', "Setting quota of mailbox `$cyruid' to $quota"); - if (!$cyrus->setquota($cyruid, 'STORAGE', $quota)) { - Kolab::log('Y', "Unable to set quota for mailbox `$cyruid', Error = `" . $cyrus->error . "'", KOLAB_WARN); - } - } + if( $quota == 0 ) { + Kolab::log('Y', "Removing quota from mailbox `$cyruid'"); + if (!$cyrus->setquota($cyruid)) { + Kolab::log('Y', "Unable to remove quota for mailbox `$cyruid', Error = `" . $cyrus->error . "'", KOLAB_WARN); + } + } else { + Kolab::log('Y', "Setting quota of mailbox `$cyruid' to $quota"); + if (!$cyrus->setquota($cyruid, 'STORAGE', $quota)) { + Kolab::log('Y', "Unable to set quota for mailbox `$cyruid', Error = `" . $cyrus->error . "'", KOLAB_WARN); + } + } } } @@ -224,15 +224,15 @@ sub setACL } sub setFolderType { - my $cyrus = shift; - my $uid = shift; - my $sf = shift || 0; - my $foldertype = shift || 'mail'; - my $cyruid = &createUid($uid, $sf); - - if (!$cyrus->mboxconfig($cyruid, '/vendor/kolab/folder-type', $foldertype)) { - Kolab::log('Y', "Unable to set the folder type for mailbox `$cyruid' to `$foldertype', Error = `" . $cyrus->error . "'", KOLAB_WARN); - } + my $cyrus = shift; + my $uid = shift; + my $sf = shift || 0; + my $foldertype = shift || 'mail'; + my $cyruid = &createUid($uid, $sf); + + if (!$cyrus->mboxconfig($cyruid, '/vendor/kolab/folder-type', $foldertype)) { + Kolab::log('Y', "Unable to set the folder type for mailbox `$cyruid' to `$foldertype', Error = `" . $cyrus->error . "'", KOLAB_WARN); + } } 1; diff --git a/lib/Kolab/LDAP.pm b/lib/Kolab/LDAP.pm index 8756be0..794e737 100644 --- a/lib/Kolab/LDAP.pm +++ b/lib/Kolab/LDAP.pm @@ -81,7 +81,7 @@ sub startup Kolab::log('L', 'Starting up'); if (!$db_statedir && $statedir) { - $db_statedir = $statedir; + $db_statedir = $statedir; } } @@ -187,15 +187,15 @@ sub graveyardRessurect my $oldgyarduid = $$gyard_db{$guid} || ''; if ($oldgyarduid) { - # The object needs to be resurrected! - if ($oldgyarduid ne $uid) { - Kolab::log('L', "Resurrected object `$uid' already exists as `$oldgyarduid'; refusing to create", KOLAB_WARN); - } else { - Kolab::log('L', "Object `$uid' has been resurrected", KOLAB_DEBUG); - } - # Remove the object from the graveyard - delete $$gyard_db{$guid}; - delete $$gyard_ts_db{$guid}; + # The object needs to be resurrected! + if ($oldgyarduid ne $uid) { + Kolab::log('L', "Resurrected object `$uid' already exists as `$oldgyarduid'; refusing to create", KOLAB_WARN); + } else { + Kolab::log('L', "Object `$uid' has been resurrected", KOLAB_DEBUG); + } + # Remove the object from the graveyard + delete $$gyard_db{$guid}; + delete $$gyard_ts_db{$guid}; } graveyardClose(%$gyard_db, %$gyard_ts_db); @@ -313,25 +313,25 @@ sub create my $ldap; if( $pt == 636 ) { - # Use SSL - $ldap = Net::LDAPS->new( - $ip, - port => $pt, - version => 3, - timeout => 20, - async => $as, - verify => 'none', - onerror => \&ldap_error - ); + # Use SSL + $ldap = Net::LDAPS->new( + $ip, + port => $pt, + version => 3, + timeout => 20, + async => $as, + verify => 'none', + onerror => \&ldap_error + ); } else { - $ldap = Net::LDAP->new( - $ip, - port => $pt, - version => 3, - timeout => 20, - async => $as, - onerror => \&ldap_error - ); + $ldap = Net::LDAP->new( + $ip, + port => $pt, + version => 3, + timeout => 20, + async => $as, + onerror => \&ldap_error + ); } if (!$ldap) { Kolab::log('L', "Unable to connect to LDAP server `$ip:$pt'", KOLAB_ERROR); @@ -393,43 +393,45 @@ sub isDeleted my $object = shift; my $p = shift || 'user'; my $del = $object->get_value($Kolab::config{$p . '_field_deleted'}, asref => 1 ); - #foreach (@$del) { - # return 1 if lc($_) eq lc($Kolab::config{'fqdnhostname'}); - #} - #return 0; +# foreach (@$del) { +# return 1 if lc($_) eq lc($Kolab::config{'fqdnhostname'}); +# } +# return 0; return $#$del > 0; } # Map from Kolab ACLs to Cyrus ACLs sub mapAcls { - my $acls = shift; - my $sf = shift || 0; - my @acls = map { - my ($uid,$perm) = split(/\s+/,$_,2); - Kolab::log('L', "Kolab::LDAP::mapAcls() uid=$uid perm=$perm", KOLAB_DEBUG); - my $post = 0; - if( $perm =~ /(.*)\/post/ ) { - $perm = $1; - $post = 1; + my $acls = shift; + my $sf = shift || 0; + my @acls = map { + my ($uid,$perm) = split(/\s+/,$_,2); + Kolab::log('L', "Kolab::LDAP::mapAcls() uid=$uid perm=$perm", KOLAB_DEBUG); + my $post = 0; + if( $perm =~ /(.*)\/post/ ) { + $perm = $1; + $post = 1; + } + Kolab::log('L', "Kolab::LDAP::mapAcls() uid=$uid perm=$perm post=$post", KOLAB_DEBUG); + if( lc $perm eq 'none' ) { $_ = "$uid none"; } + elsif( lc $perm eq 'post' ) { $_ = "$uid p"; } + elsif( lc $perm eq 'read' ) { $_ = "$uid lrs"; } + elsif( lc $perm eq 'read anon' ) { $_ = "$uid lr"; } + elsif( lc $perm eq 'read hidden' ) { $_ = "$uid rs"; } + elsif( lc $perm eq 'append' ) { $_ = "$uid lrsip"; } + elsif( lc $perm eq 'write' ) { if( $sf ) { $_ = "$uid lrsiwdp"; } else { $_ = "$uid lrsiwcdp"; } } + elsif( lc $perm eq 'all' ) { if( $sf ) { $_ = "$uid lrsiwdap"; } else { $_ = "$uid lrsiwcdap"; } } + else { $_ = "$uid $perm"; } # passthrough + + if( $post ) { $_ .= 'p'; } + Kolab::log('L', "Kolab::LDAP::mapAcls() acl=$_", KOLAB_DEBUG); + } @$acls; + + if( $sf ) { + push(@$acls, "manager lrsiwcdap"); } - Kolab::log('L', "Kolab::LDAP::mapAcls() uid=$uid perm=$perm post=$post", KOLAB_DEBUG); - if( lc $perm eq 'none' ) { $_ = "$uid none"; } - elsif( lc $perm eq 'post' ) { $_ = "$uid p"; } - elsif( lc $perm eq 'read' ) { $_ = "$uid lrs"; } - elsif( lc $perm eq 'read anon' ) { $_ = "$uid lr"; } - elsif( lc $perm eq 'read hidden' ) { $_ = "$uid rs"; } - elsif( lc $perm eq 'append' ) { $_ = "$uid lrsip"; } - elsif( lc $perm eq 'write' ) { if( $sf ) { $_ = "$uid lrsiwdp"; } else { $_ = "$uid lrsiwcdp"; } } - elsif( lc $perm eq 'all' ) { if( $sf ) { $_ = "$uid lrsiwdap"; } else { $_ = "$uid lrsiwcdap"; } } - else { $_ = "$uid $perm"; } # passthrough - if( $post ) { $_ .= 'p'; } - Kolab::log('L', "Kolab::LDAP::mapAcls() acl=$_", KOLAB_DEBUG); - } @$acls; - if( $sf ) { - push(@$acls, "manager lrsiwcdap"); - } - Kolab::log('L', "Kolab::LDAP::mapAcls() acls=".join(", ", @$acls), KOLAB_DEBUG); - return $acls; + Kolab::log('L', "Kolab::LDAP::mapAcls() acls=".join(", ", @$acls), KOLAB_DEBUG); + return $acls; } sub createObject @@ -459,7 +461,7 @@ sub createObject ." because it is deleted", KOLAB_DEBUG); return; } - if( ($kolabhomeserver && $kolabhomeserver ne lc($Kolab::config{'fqdnhostname'})) + if( ($kolabhomeserver && $kolabhomeserver ne lc($Kolab::config{'fqdnhostname'})) || $kolabimapserver && $kolabimapserver ne lc(hostfqdn()) ) { # We are not on the home server if( $p eq 'sf' ) { @@ -593,28 +595,30 @@ sub createObject } sub createMasterLDAP { - my $uri = $Kolab::config{'ldap_master_uri'}; - - my $masterldap = Net::LDAP->new( - $uri, - version => 3, - timeout => 20, - verify => 'none', - onerror => 'undef' ); - if( defined( $masterldap ) ) { - my $mesg = $masterldap->bind( - $Kolab::config{'bind_dn'}, - password => $Kolab::config{'bind_pw'}); - if ($mesg->code) { - Kolab::log('L', "Unable to bind to `$uri', LDAP Error = `" - .$mesg->error."'", KOLAB_ERROR); - undef( $masterldap ); + my $uri = $Kolab::config{'ldap_master_uri'}; + + my $masterldap = Net::LDAP->new( + $uri, + version => 3, + timeout => 20, + verify => 'none', + onerror => 'undef' ); + + if( defined( $masterldap ) ) { + my $mesg = $masterldap->bind( + $Kolab::config{'bind_dn'}, + password => $Kolab::config{'bind_pw'}); + + if ($mesg->code) { + Kolab::log('L', "Unable to bind to `$uri', LDAP Error = `" + .$mesg->error."'", KOLAB_ERROR); + undef( $masterldap ); + } + } else { + Kolab::log('L', "Unable to connect to `$uri'" + , KOLAB_ERROR); } - } else { - Kolab::log('L', "Unable to connect to `$uri'" - , KOLAB_ERROR); - } - return $masterldap; + return $masterldap; } sub deleteObject @@ -623,7 +627,7 @@ sub deleteObject # deletion, as we nuke the mailbox # # The graveyard code will handle the case of an object `going missing'. - + my $ldap = shift; my $cyrus = shift; my $object = shift; @@ -639,83 +643,83 @@ sub deleteObject if ($remfromldap) { my $dn = $object->dn; - my $del = $object->get_value($Kolab::config{$p . '_field_deleted'}, asref => 1); - my $masterldap; - if( $Kolab::config{'ldap_master_uri'} eq $Kolab::config{'ldap_uri'} ) { - # We are already connected to the LDAP master, just go ahead - $masterldap = $ldap; - } else { - $masterldap = createMasterLDAP; - } - if( !defined( $masterldap ) ) { - # Problem here, could not connect to master! - Kolab::log('L', "Unable to remove DN `$dn', master LDAP server not available", KOLAB_WARN); - return 0; - } - if( lc ($Kolab::config{'is_master'}) eq 'true' && ref($del) eq 'ARRAY' && scalar(@$del) == 1 ) { - # Ok we are the last one and the master - if( $Kolab::config{'kolab_remove_objectclass'} ) { - # Remove the kolab-related objectClasses - # Some people find it useful to integrate Kolab - # with an existing LDAP database and when a Kolab - # object is to be deleted, it should just remove - # the Kolab stuff and leave the rest of the object - # in the database. - # - # This is what we do here. - # Warning: All attributes in the kolab-related - # objectclasses will be deleted! - # - # PENDING(steffen): Only remove attributes that _have_ to - # be removed. - Kolab::log('L', "Removing Kolab objectClasses from DN `$dn'"); - my $schema = $masterldap->schema( $dn ); - # PENDING(steffen): Dont hardcode objectClasses - foreach my $c qw(kolabInetOrgPerson kolabGroupOfNames) { - my @may = map $_->{name}, $schema->may($c); - my @must = map $_->{name}, $schema->must($c); - foreach my $attr (@must,@may,split(' ',$Kolab::config{'kolab_remove_attributes'})) { - # Remove attributes - Kolab::log('L', "Removing attribute $attr", KOLAB_WARN); - my $mesg = $masterldap->modify( $dn, - delete => $attr ); - if ($mesg && $mesg->code ) { - Kolab::log('L', "Unable to remove attribute $attr from DN `$dn': ".$mesg->error, KOLAB_WARN); - } - } - # Remove objectClass - my $mesg = $masterldap->modify( $dn, - delete => { 'objectClass' => $c } ); - if ($mesg && $mesg->code ) { - Kolab::log('L', "Unable to remove Kolab objectClas $_ from DN `$dn': ".$mesg->error, KOLAB_WARN); - } - } - } else { - # Default behaviour, delete the object - Kolab::log('L', "Removing DN `$dn'"); - my $mesg = $masterldap->delete($dn); - if ($mesg && $mesg->code ) { - Kolab::log('L', "Unable to remove DN `$dn': ".$mesg->error, KOLAB_WARN); - } - } - } elsif( lc ($Kolab::config{'is_master'}) eq 'false' ) { - # Just remove us from the kolabdeleteflag - # master does not perform this step as it should - # be the last to delete and remove the object - Kolab::log('L', "Removing ".$Kolab::config{'fqdnhostname'}." from ". - $Kolab::config{$p . '_field_deleted'}." in `$dn'"); - my $mesg = $masterldap->modify( $dn, delete => - { $Kolab::config{$p . '_field_deleted'} => - $Kolab::config{'fqdnhostname'} } ); - if ($mesg && $mesg->code) { - Kolab::log('L', "Unable to remove ".$Kolab::config{'fqdnhostname'} - ." from kolabdeleteflag in `$dn': ".$mesg->error, KOLAB_WARN); - } - } - if( $ldap != $masterldap ) { - # Disconnect from master if we are the slave - $masterldap->disconnect; - } + my $del = $object->get_value($Kolab::config{$p . '_field_deleted'}, asref => 1); + my $masterldap; + if( $Kolab::config{'ldap_master_uri'} eq $Kolab::config{'ldap_uri'} ) { + # We are already connected to the LDAP master, just go ahead + $masterldap = $ldap; + } else { + $masterldap = createMasterLDAP; + } + if( !defined( $masterldap ) ) { + # Problem here, could not connect to master! + Kolab::log('L', "Unable to remove DN `$dn', master LDAP server not available", KOLAB_WARN); + return 0; + } + if( lc ($Kolab::config{'is_master'}) eq 'true' && ref($del) eq 'ARRAY' && scalar(@$del) == 1 ) { + # Ok we are the last one and the master + if( $Kolab::config{'kolab_remove_objectclass'} ) { + # Remove the kolab-related objectClasses + # Some people find it useful to integrate Kolab + # with an existing LDAP database and when a Kolab + # object is to be deleted, it should just remove + # the Kolab stuff and leave the rest of the object + # in the database. + # + # This is what we do here. + # Warning: All attributes in the kolab-related + # objectclasses will be deleted! + # + # PENDING(steffen): Only remove attributes that _have_ to + # be removed. + Kolab::log('L', "Removing Kolab objectClasses from DN `$dn'"); + my $schema = $masterldap->schema( $dn ); + # PENDING(steffen): Dont hardcode objectClasses + foreach my $c qw(kolabInetOrgPerson kolabGroupOfNames) { + my @may = map $_->{name}, $schema->may($c); + my @must = map $_->{name}, $schema->must($c); + foreach my $attr (@must,@may,split(' ',$Kolab::config{'kolab_remove_attributes'})) { + # Remove attributes + Kolab::log('L', "Removing attribute $attr", KOLAB_WARN); + my $mesg = $masterldap->modify( $dn, + delete => $attr ); + if ($mesg && $mesg->code ) { + Kolab::log('L', "Unable to remove attribute $attr from DN `$dn': ".$mesg->error, KOLAB_WARN); + } + } + # Remove objectClass + my $mesg = $masterldap->modify( $dn, + delete => { 'objectClass' => $c } ); + if ($mesg && $mesg->code ) { + Kolab::log('L', "Unable to remove Kolab objectClas $_ from DN `$dn': ".$mesg->error, KOLAB_WARN); + } + } + } else { + # Default behaviour, delete the object + Kolab::log('L', "Removing DN `$dn'"); + my $mesg = $masterldap->delete($dn); + if ($mesg && $mesg->code ) { + Kolab::log('L', "Unable to remove DN `$dn': ".$mesg->error, KOLAB_WARN); + } + } + } elsif( lc ($Kolab::config{'is_master'}) eq 'false' ) { + # Just remove us from the kolabdeleteflag + # master does not perform this step as it should + # be the last to delete and remove the object + Kolab::log('L', "Removing ".$Kolab::config{'fqdnhostname'}." from ". + $Kolab::config{$p . '_field_deleted'}." in `$dn'"); + my $mesg = $masterldap->modify( $dn, delete => + { $Kolab::config{$p . '_field_deleted'} => + $Kolab::config{'fqdnhostname'} } ); + if ($mesg && $mesg->code) { + Kolab::log('L', "Unable to remove ".$Kolab::config{'fqdnhostname'} + ." from kolabdeleteflag in `$dn': ".$mesg->error, KOLAB_WARN); + } + } + if( $ldap != $masterldap ) { + # Disconnect from master if we are the slave + $masterldap->disconnect; + } } my $hooksdir = $Kolab::config{'kolab_hooksdir'} . '/delete'; @@ -724,12 +728,12 @@ sub deleteObject closedir(DIR); foreach my $hook (@hooks) { - system($Kolab::config{'kolab_hooksdir'} . '/delete/' . $hook . " $uid"); - if ($?==0) { - Kolab::log('L', "Successfully ran hook $hook for user $uid.", KOLAB_DEBUG); - } else { - Kolab::log('L', "Failed running hook $hook for user $uid.", KOLAB_ERROR); - } + system($Kolab::config{'kolab_hooksdir'} . '/delete/' . $hook . " $uid"); + if ($?==0) { + Kolab::log('L', "Successfully ran hook $hook for user $uid.", KOLAB_DEBUG); + } else { + Kolab::log('L', "Failed running hook $hook for user $uid.", KOLAB_ERROR); + } } if (!$uid) { @@ -755,8 +759,8 @@ sub sync $group_timestamp = syncBasic($cyrus, 'group', '', $group_timestamp, 0); if( !$cyrus ) { - # We could not connect, bail out for now - return 0; + # We could not connect, bail out for now + return 0; } # Check that all mailboxes correspond to LDAP objects Kolab::log('L', 'Synchronising mailboxes'); @@ -783,7 +787,7 @@ sub sync # an error when iterating through the objects (Lost connection, invalid DNs) foreach $guid (keys %$uid_db) { if (defined $$uid_db{$guid} && exists $objects{$$uid_db{$guid}}) { - graveyardStore($guid, $$uid_db{$guid}); + graveyardStore($guid, $$uid_db{$guid}); } } uidcacheClose(%$uid_db); @@ -792,7 +796,7 @@ sub sync my $newuid; foreach $newuid (keys %newuid_db) { - uidcacheStore($newuid, $newuid_db{$newuid}); + uidcacheStore($newuid, $newuid_db{$newuid}); } syncDomains(); @@ -804,26 +808,26 @@ sub sync # so we have to hack it ourselves sub parse_generalized_time { - my $ts = shift; - # YYYYMMDDHHMMSSZ - if( $ts =~ /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z/ ) { - my $t = 0; - eval { $t = timegm($6,$5,$4,$3,$2-1,$1); }; - return $t; - } else { - return 0; - } + my $ts = shift; + # YYYYMMDDHHMMSSZ + if( $ts =~ /(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)Z/ ) { + my $t = 0; + eval { $t = timegm($6,$5,$4,$3,$2-1,$1); }; + return $t; + } else { + return 0; + } } # Returns the largest of two string-rep. # of LDAP generalizedTime sub max_generalized_time { - my $ts1 = shift; - my $ts2 = shift; - if( parse_generalized_time($ts1) > - parse_generalized_time($ts2) ) { return $ts1; } - else { return $ts2; } + my $ts1 = shift; + my $ts2 = shift; + if( parse_generalized_time($ts1) > + parse_generalized_time($ts2) ) { return $ts1; } + else { return $ts2; } } sub syncBasic @@ -866,7 +870,7 @@ sub syncBasic ); if ( UNIVERSAL::isa( $ldapmesg, 'Net::LDAP::Search') && $ldapmesg->code() <= 0) { - while( $ldapobject = $ldapmesg->pop_entry ) { + while( $ldapobject = $ldapmesg->pop_entry ) { deleteObject($ldap, $cyrus, $ldapobject, 1, $p); } } else { @@ -875,14 +879,15 @@ sub syncBasic # Now check that all objects in LDAP have corresponding mailboxes # This also resurrects any missing users, if neccessary - my $filter; - if( $ts eq "" ) { - $filter = '(&(objectClass=' . $Kolab::config{$p . '_object_class'} . ")$add)", - } else { - $filter = '(&(objectClass=' . $Kolab::config{$p . '_object_class'} . ")(" - .$Kolab::config{$p.'_field_modified'}.">=$ts)$add)"; - } - Kolab::log('L', "filter is $filter", KOLAB_DEBUG); + my $filter; + if( $ts eq "" ) { + $filter = '(&(objectClass=' . $Kolab::config{$p . '_object_class'} . ")$add)", + } else { + $filter = '(&(objectClass=' . $Kolab::config{$p . '_object_class'} . ")(" + .$Kolab::config{$p.'_field_modified'}.">=$ts)$add)"; + } + + Kolab::log('L', "filter is $filter", KOLAB_DEBUG); $ldapmesg = $ldap->search( base => $dn, scope => 'sub', @@ -890,16 +895,16 @@ sub syncBasic attrs => [ '*', $Kolab::config{$p . '_field_guid'}, - $Kolab::config{$p . '_field_modified'}, + $Kolab::config{$p . '_field_modified'}, $Kolab::config{$p . '_field_quota'}, $Kolab::config{$p . '_field_deleted'}, ], ); if ( UNIVERSAL::isa( $ldapmesg, 'Net::LDAP::Search') && $ldapmesg->code() <= 0) { - while( $ldapobject = $ldapmesg->pop_entry ) { + while( $ldapobject = $ldapmesg->pop_entry ) { createObject($ldap, $cyrus, $ldapobject, 1, $p, $doacls); - $ts = max_generalized_time($ts,$ldapobject->get_value($Kolab::config{$p . '_field_modified'})); + $ts = max_generalized_time($ts,$ldapobject->get_value($Kolab::config{$p . '_field_modified'})); } } else { Kolab::log('L', "Unable to locate `$p' objects in DN `$dn'", KOLAB_WARN); @@ -937,12 +942,12 @@ sub syncDomains $ldapmesg = $ldap->search( base => 'cn=internal,' . $Kolab::config{'base_dn'}, scope => 'one', - filter => '(&(objectClass=kolabInetOrgPerson)(cn=calendar))', - attrs => [ - 'objectClass', - 'uid', - ], - ); + filter => '(&(objectClass=kolabInetOrgPerson)(cn=calendar))', + attrs => [ + 'objectClass', + 'uid', + ], + ); if ( UNIVERSAL::isa( $ldapmesg, 'Net::LDAP::Search') && $ldapmesg->count() > 0) { Kolab::log('L', "Identified old calendar user with DN `$dn'", KOLAB_DEBUG); @@ -950,44 +955,44 @@ sub syncDomains $ldap->moddn($dn, newrdn => $cn, deleteoldrdn => 1); Kolab::log('L', "Renamed old calendar user with DN `$dn' to DN `$cn'", KOLAB_INFO); } else { - Kolab::log('L', "Unable to locate old calendar user with DN `$dn'", KOLAB_DEBUG); + Kolab::log('L', "Unable to locate old calendar user with DN `$dn'", KOLAB_DEBUG); } if( ref($Kolab::config{'postfix-mydestination'}) eq 'ARRAY' ) { - @domains = @{$Kolab::config{'postfix-mydestination'}}; + @domains = @{$Kolab::config{'postfix-mydestination'}}; } else { - @domains =( $Kolab::config{'postfix-mydestination'} ); + @domains =( $Kolab::config{'postfix-mydestination'} ); } my $sha_pw = hash_pw($Kolab::config{'calendar_pw'}); foreach $domain (@domains) { - $uid = $Kolab::config{'calendar_id'} . '@' . $domain; - $dn = 'cn=' . $uid . ',cn=internal,' . $Kolab::config{'base_dn'}; - $ldapmesg = $ldap->search( - base => $dn, - scope => 'one', - filter => '(&(objectClass=kolabInetOrgPerson))', + $uid = $Kolab::config{'calendar_id'} . '@' . $domain; + $dn = 'cn=' . $uid . ',cn=internal,' . $Kolab::config{'base_dn'}; + $ldapmesg = $ldap->search( + base => $dn, + scope => 'one', + filter => '(&(objectClass=kolabInetOrgPerson))', attrs => [ 'objectClass', 'uid', - ], - ); - if ( UNIVERSAL::isa( $ldapmesg, 'Net::LDAP::Search') && $ldapmesg->code() <= 0) { - Kolab::log('L', "Calendar user for domain `$domain' exists", KOLAB_DEBUG); - } else { - $ldapobject = Net::LDAP::Entry->new; - $ldapobject->replace('cn' => $uid, - 'sn' => 'n/a n/a', - 'uid' => $uid, - 'userPassword' => $sha_pw, - 'objectclass' => ['top','inetorgperson','kolabinetorgperson']); - $ldapobject->dn($dn); - $ldapobject->update($ldap); - undef $ldapobject; - Kolab::log('L', "Created new calendar user with DN `$dn' for domain `$domain'", KOLAB_INFO); - } - } + ], + ); + if ( UNIVERSAL::isa( $ldapmesg, 'Net::LDAP::Search') && $ldapmesg->code() <= 0) { + Kolab::log('L', "Calendar user for domain `$domain' exists", KOLAB_DEBUG); + } else { + $ldapobject = Net::LDAP::Entry->new; + $ldapobject->replace('cn' => $uid, + 'sn' => 'n/a n/a', + 'uid' => $uid, + 'userPassword' => $sha_pw, + 'objectclass' => ['top','inetorgperson','kolabinetorgperson']); + $ldapobject->dn($dn); + $ldapobject->update($ldap); + undef $ldapobject; + Kolab::log('L', "Created new calendar user with DN `$dn' for domain `$domain'", KOLAB_INFO); + } + } } # Taken from Samba::LDAP::User.pm @@ -1016,7 +1021,6 @@ sub ldap_error { Kolab::log('L', $errstr, KOLAB_ERROR); } - 1; __END__ # Below is stub documentation for your module. You'd better edit it! diff --git a/lib/Kolab/LDAP/Backend.pm b/lib/Kolab/LDAP/Backend.pm index ba1c9d5..ef72171 100644 --- a/lib/Kolab/LDAP/Backend.pm +++ b/lib/Kolab/LDAP/Backend.pm @@ -63,10 +63,10 @@ sub load my $backend; if (!defined $non_directory) { - $p .= '_' if ($p); - $backend = $Kolab::config{$p . 'directory_mode'}; + $p .= '_' if ($p); + $backend = $Kolab::config{$p . 'directory_mode'}; } else { - $backend = $p; + $backend = $p; } return if (exists($backends{$backend})); @@ -105,7 +105,7 @@ sub run my $func = $run{$backend}; unless (eval '&$func') { $func = 'Kolab::LDAP::Backend::' . $backend . '::run'; - Kolab::log('B', "Error in function `$func': $@, exiting", KOLAB_ERROR); + Kolab::log('B', "Error in function `$func': $@, exiting", KOLAB_ERROR); exit(1); } } diff --git a/lib/Kolab/LDAP/Backend/ad.pm b/lib/Kolab/LDAP/Backend/ad.pm index 668b67f..33f0789 100644 --- a/lib/Kolab/LDAP/Backend/ad.pm +++ b/lib/Kolab/LDAP/Backend/ad.pm @@ -48,7 +48,7 @@ our %EXPORT_TAGS = ( our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( - + ); our $VERSION = '0.9'; @@ -80,35 +80,35 @@ sub changeCallback my $issearch = $mesg->isa("Net::LDAP::Search"); if (!$issearch) { - Kolab::log('AD', 'mesg is not a search object, testing code...', KOLAB_DEBUG); - if ($mesg->code == 88) { - Kolab::log('AD', 'changeCallback() -> Exit code received, returning', KOLAB_DEBUG); - return; - } elsif ($mesg->code) { - Kolab::log('AD', "mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); - &abort; - } + Kolab::log('AD', 'mesg is not a search object, testing code...', KOLAB_DEBUG); + if ($mesg->code == 88) { + Kolab::log('AD', 'changeCallback() -> Exit code received, returning', KOLAB_DEBUG); + return; + } elsif ($mesg->code) { + Kolab::log('AD', "mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); + &abort; + } } else { - Kolab::log('AD', 'mesg is a search object, not testing code', KOLAB_DEBUG); + Kolab::log('AD', 'mesg is a search object, not testing code', KOLAB_DEBUG); } if (!$entry) { - Kolab::log('AD', 'changeCallback() called with a null entry', KOLAB_DEBUG); - return; + Kolab::log('AD', 'changeCallback() called with a null entry', KOLAB_DEBUG); + return; } elsif (!$entry->isa("Net::LDAP::Entry")) { - Kolab::log('AD', 'changeCallback() called with an invalid entry', KOLAB_DEBUG); - return; + Kolab::log('AD', 'changeCallback() called with an invalid entry', KOLAB_DEBUG); + return; } if (!Kolab::LDAP::isObject($entry, $Kolab::config{'user_object_class'})) { - Kolab::log('AD', "Entry is not a `" . $Kolab::config{'user_object_class'} . "', returning", KOLAB_DEBUG); - return; + Kolab::log('AD', "Entry is not a `" . $Kolab::config{'user_object_class'} . "', returning", KOLAB_DEBUG); + return; } my $deleted = $entry->get_value($Kolab::config{'user_field_deleted'}) || 0; if ($deleted) { - Kolab::LDAP::deleteObject($ldap, $cyrus, $entry); - return; + Kolab::LDAP::deleteObject($ldap, $cyrus, $entry); + return; } Kolab::LDAP::createObject($ldap, $cyrus, $entry); @@ -123,8 +123,8 @@ sub run $SIG{'TERM'} = \&shutdown; END { - alarm 0; - Kolab::LDAP::destroy($ldap); + alarm 0; + Kolab::LDAP::destroy($ldap); } my $mesg; @@ -136,81 +136,81 @@ sub run Kolab::log('AD', 'Cyrus connection established', KOLAB_DEBUG); while (1) { - Kolab::log('AD', 'Creating LDAP connection to AD server', KOLAB_DEBUG); - - $ldap = Kolab::LDAP::create( - $Kolab::config{'user_ldap_ip'}, - $Kolab::config{'user_ldap_port'}, - $Kolab::config{'user_bind_dn'}, - $Kolab::config{'user_bind_pw'}, - 1 - ); - - if (!$ldap) { - Kolab::log('AD', 'Sleeping 5 seconds...'); - sleep 5; - next; - } - - Kolab::log('AD', 'LDAP connection established', KOLAB_DEBUG); - - Kolab::LDAP::ensureAsync($ldap); - - Kolab::log('AD', 'Async checked', KOLAB_DEBUG); - - my $ctrl = Net::LDAP::Control->new( - type => '1.2.840.113556.1.4.528', - critical => 'true' - ); + Kolab::log('AD', 'Creating LDAP connection to AD server', KOLAB_DEBUG); + + $ldap = Kolab::LDAP::create( + $Kolab::config{'user_ldap_ip'}, + $Kolab::config{'user_ldap_port'}, + $Kolab::config{'user_bind_dn'}, + $Kolab::config{'user_bind_pw'}, + 1 + ); - Kolab::log('AD', 'Control created', KOLAB_DEBUG); + if (!$ldap) { + Kolab::log('AD', 'Sleeping 5 seconds...'); + sleep 5; + next; + } - my @userdns = split(/;/, $Kolab::config{'user_dn_list'}); - my $userdn; + Kolab::log('AD', 'LDAP connection established', KOLAB_DEBUG); - Kolab::log('AD', 'User DN list = ' . $Kolab::config{'user_dn_list'}, KOLAB_DEBUG); + Kolab::LDAP::ensureAsync($ldap); - if (length(@userdns) == 0) { - Kolab::log('AD', 'No user DNs specified, exiting', KOLAB_ERROR); - exit(1); - } + Kolab::log('AD', 'Async checked', KOLAB_DEBUG); - foreach $userdn (@userdns) { - Kolab::log('AD', "Registering change notification on DN `$userdn'"); - - $mesg = $ldap->search ( - base => $userdn, - scope => 'one', - control => [ $ctrl ], - callback => \&changeCallback, - filter => '(objectClass=*)', - attrs => [ - '*', - $Kolab::config{'user_field_guid'}, - $Kolab::config{'user_field_modified'}, - $Kolab::config{'user_field_quota'}, - $Kolab::config{'user_field_deleted'}, - ], + my $ctrl = Net::LDAP::Control->new( + type => '1.2.840.113556.1.4.528', + critical => 'true' ); - Kolab::log('AD', "Change notification registered on `$userdn'"); - } - - eval { - local $SIG{ALRM} = sub { - alarm 0; - Kolab::log('AD', 'Connection refresh period expired; tearing down connection'); - - Kolab::LDAP::destroy($ldap); - next; + Kolab::log('AD', 'Control created', KOLAB_DEBUG); + + my @userdns = split(/;/, $Kolab::config{'user_dn_list'}); + my $userdn; + + Kolab::log('AD', 'User DN list = ' . $Kolab::config{'user_dn_list'}, KOLAB_DEBUG); + + if (length(@userdns) == 0) { + Kolab::log('AD', 'No user DNs specified, exiting', KOLAB_ERROR); + exit(1); + } + + foreach $userdn (@userdns) { + Kolab::log('AD', "Registering change notification on DN `$userdn'"); + + $mesg = $ldap->search ( + base => $userdn, + scope => 'one', + control => [ $ctrl ], + callback => \&changeCallback, + filter => '(objectClass=*)', + attrs => [ + '*', + $Kolab::config{'user_field_guid'}, + $Kolab::config{'user_field_modified'}, + $Kolab::config{'user_field_quota'}, + $Kolab::config{'user_field_deleted'}, + ], + ); + + Kolab::log('AD', "Change notification registered on `$userdn'"); + } + + eval { + local $SIG{ALRM} = sub { + alarm 0; + Kolab::log('AD', 'Connection refresh period expired; tearing down connection'); + + Kolab::LDAP::destroy($ldap); + next; + }; + + Kolab::log('AD', 'Waiting for changes (refresh period = ' . $Kolab::config{'conn_refresh_period'} . ' minutes)...'); + alarm $Kolab::config{'conn_refresh_period'} * 60; + $mesg->sync; + alarm 0; }; - - Kolab::log('AD', 'Waiting for changes (refresh period = ' . $Kolab::config{'conn_refresh_period'} . ' minutes)...'); - alarm $Kolab::config{'conn_refresh_period'} * 60; - $mesg->sync; - alarm 0; - }; - } + } # End of while 1; } diff --git a/lib/Kolab/LDAP/Backend/fds.pm b/lib/Kolab/LDAP/Backend/fds.pm index 1c5b68a..16044d7 100644 --- a/lib/Kolab/LDAP/Backend/fds.pm +++ b/lib/Kolab/LDAP/Backend/fds.pm @@ -35,15 +35,15 @@ our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( - &startup - &run + &startup + &run ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( - + ); our $VERSION = '0.1'; @@ -73,36 +73,36 @@ sub changeCallback my $entry = shift || 0; my $issearch = $mesg->isa("Net::LDAP::Search"); - + Kolab::log('FDS', "issearch=" . $issearch , KOLAB_DEBUG); if (!$issearch) { - Kolab::log('FDS', 'mesg is not a search object, testing code...', KOLAB_DEBUG); - if ($mesg->code == 88) { - Kolab::log('FDS', 'changeCallback() -> Exit code received, returning', KOLAB_DEBUG); - return; - } elsif ($mesg->code) { - Kolab::log('FDS', "mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); - &abort; - } + Kolab::log('FDS', 'mesg is not a search object, testing code...', KOLAB_DEBUG); + if ($mesg->code == 88) { + Kolab::log('FDS', 'changeCallback() -> Exit code received, returning', KOLAB_DEBUG); + return; + } elsif ($mesg->code) { + Kolab::log('FDS', "mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); + &abort; + } } else { - Kolab::log('FDS', 'mesg is a search object, not testing code', KOLAB_DEBUG); + Kolab::log('FDS', 'mesg is a search object, not testing code', KOLAB_DEBUG); } Kolab::log('FDS', "entry=" . $entry , KOLAB_DEBUG); - + if (!$entry) { - Kolab::log('FDS', 'changeCallback() called with a null entry', KOLAB_DEBUG); - goto FOO; - return; + Kolab::log('FDS', 'changeCallback() called with a null entry', KOLAB_DEBUG); + goto FOO; + return; } elsif (!$entry->isa("Net::LDAP::Entry")) { - Kolab::log('FDS', 'changeCallback() called with an invalid entry', KOLAB_DEBUG); - return; + Kolab::log('FDS', 'changeCallback() called with an invalid entry', KOLAB_DEBUG); + return; } if (!Kolab::LDAP::isObject($entry, $Kolab::config{'user_object_class'}) && !Kolab::LDAP::isObject($entry, 'kolab')) { - Kolab::log('FDS', "Entry is not a `" . $Kolab::config{'user_object_class'} . "' or kolab configuration object, returning", KOLAB_DEBUG); - return; + Kolab::log('FDS', "Entry is not a `" . $Kolab::config{'user_object_class'} . "' or kolab configuration object, returning", KOLAB_DEBUG); + return; } FOO: @@ -122,99 +122,102 @@ FOO: } sub run { - # This should be called from a separate thread, as we set our - # own interrupt handlers here + # This should be called from a separate thread, as we set our + # own interrupt handlers here - $SIG{'INT'} = \&shutdown; - $SIG{'TERM'} = \&shutdown; + $SIG{'INT'} = \&shutdown; + $SIG{'TERM'} = \&shutdown; - END { - alarm 0; - Kolab::LDAP::destroy($ldap); - } + END { + alarm 0; + Kolab::LDAP::destroy($ldap); + } - my $mesg; + my $mesg; - Kolab::log('FDS', 'Listener starting up'); + Kolab::log('FDS', 'Listener starting up'); - $cyrus = Kolab::Cyrus::create; + $cyrus = Kolab::Cyrus::create; - Kolab::log('FDS', 'Cyrus connection established', KOLAB_DEBUG); + Kolab::log('FDS', 'Cyrus connection established', KOLAB_DEBUG); - while (1) { - Kolab::log('FDS', 'Creating LDAP connection to FDS server', KOLAB_DEBUG); + while (1) { + Kolab::log('FDS', 'Creating LDAP connection to FDS server', KOLAB_DEBUG); - $ldap = Kolab::LDAP::create($Kolab::config{'user_ldap_ip'}, - $Kolab::config{'user_ldap_port'}, - $Kolab::config{'user_bind_dn'}, - $Kolab::config{'user_bind_pw'}, - 1 - ); - if (!$ldap) { - Kolab::log('FDS', 'Sleeping 5 seconds...'); - sleep 5; - next; - } + $ldap = Kolab::LDAP::create( + $Kolab::config{'user_ldap_ip'}, + $Kolab::config{'user_ldap_port'}, + $Kolab::config{'user_bind_dn'}, + $Kolab::config{'user_bind_pw'}, + 1 + ); - Kolab::log('FDS', 'LDAP connection established', KOLAB_DEBUG); + if (!$ldap) { + Kolab::log('FDS', 'Sleeping 5 seconds...'); + sleep 5; + next; + } - Kolab::LDAP::ensureAsync($ldap); + Kolab::log('FDS', 'LDAP connection established', KOLAB_DEBUG); - Kolab::log('FDS', 'Async checked', KOLAB_DEBUG); + Kolab::LDAP::ensureAsync($ldap); - my $ctrl = Net::LDAP::Control->new( - # type => '1.2.840.113556.1.4.528', - type => '2.16.840.1.113730.3.4.3', - critical => 'true' - ); + Kolab::log('FDS', 'Async checked', KOLAB_DEBUG); - Kolab::log('FDS', 'Control created', KOLAB_DEBUG); + my $ctrl = Net::LDAP::Control->new( +# type => '1.2.840.113556.1.4.528', + type => '2.16.840.1.113730.3.4.3', + critical => 'true' + ); - my @userdns = split(/;/, $Kolab::config{'user_dn_list'}); - my $userdn; + Kolab::log('FDS', 'Control created', KOLAB_DEBUG); - Kolab::log('FDS', 'User DN list = ' . $Kolab::config{'user_dn_list'}, KOLAB_DEBUG); + my @userdns = split(/;/, $Kolab::config{'user_dn_list'}); + my $userdn; - if (length(@userdns) == 0) { - Kolab::log('FDS', 'No user DNs specified, exiting', KOLAB_ERROR); - exit(1); - } + Kolab::log('FDS', 'User DN list = ' . $Kolab::config{'user_dn_list'}, KOLAB_DEBUG); - foreach $userdn (@userdns) { - Kolab::log('FDS', "Registering change notification on DN `$userdn'"); - - $mesg = $ldap->search (base => $userdn, - scope => 'one', - control => [ $ctrl ], - callback => \&changeCallback, - filter => '(objectClass=*)', - attrs => [ '*', - $Kolab::config{'user_field_guid'}, - $Kolab::config{'user_field_modified'}, - $Kolab::config{'user_field_quota'}, - $Kolab::config{'user_field_deleted'}, - ], - ); - -# $status = ldap_create_persistentsearch_control($ld,$changetypes,$changesonly,$return_echg_ctrls,$ctrl_iscritical,$ctrlp); - - Kolab::log('FDS', "Change notification registered on `$userdn'"); - } + if (length(@userdns) == 0) { + Kolab::log('FDS', 'No user DNs specified, exiting', KOLAB_ERROR); + exit(1); + } - eval { - local $SIG{ALRM} = sub { - alarm 0; - Kolab::log('FDS', 'Connection refresh period expired; tearing down connection'); + foreach $userdn (@userdns) { + Kolab::log('FDS', "Registering change notification on DN `$userdn'"); - Kolab::LDAP::destroy($ldap); - next; - }; + $mesg = $ldap->search ( + base => $userdn, + scope => 'one', + control => [ $ctrl ], + callback => \&changeCallback, + filter => '(objectClass=*)', + attrs => [ '*', + $Kolab::config{'user_field_guid'}, + $Kolab::config{'user_field_modified'}, + $Kolab::config{'user_field_quota'}, + $Kolab::config{'user_field_deleted'}, + ], + ); - Kolab::log('FDS', 'Waiting for changes (refresh period = ' . $Kolab::config{'conn_refresh_period'} . ' minutes)...'); - alarm $Kolab::config{'conn_refresh_period'} * 60; - $mesg->sync; - alarm 0; - }; +# $status = ldap_create_persistentsearch_control($ld,$changetypes,$changesonly,$return_echg_ctrls,$ctrl_iscritical,$ctrlp); + + Kolab::log('FDS', "Change notification registered on `$userdn'"); + } + + eval { + local $SIG{ALRM} = sub { + alarm 0; + Kolab::log('FDS', 'Connection refresh period expired; tearing down connection'); + + Kolab::LDAP::destroy($ldap); + next; + }; + + Kolab::log('FDS', 'Waiting for changes (refresh period = ' . $Kolab::config{'conn_refresh_period'} . ' minutes)...'); + alarm $Kolab::config{'conn_refresh_period'} * 60; + $mesg->sync; + alarm 0; + }; } 1; diff --git a/lib/Kolab/LDAP/Backend/slurpd.pm b/lib/Kolab/LDAP/Backend/slurpd.pm index 8f7cb7a..26b83bb 100644 --- a/lib/Kolab/LDAP/Backend/slurpd.pm +++ b/lib/Kolab/LDAP/Backend/slurpd.pm @@ -44,15 +44,15 @@ our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( - &startup - &run - ) ] + &startup + &run + ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( - + ); our $VERSION = '0.9'; @@ -234,37 +234,39 @@ sub run my $listenport = $Kolab::config{'slurpd_port'}; my $listenaddr = $Kolab::config{'slurpd_addr'} || "127.0.0.1"; - TRYCONNECT: + +TRYCONNECT: Kolab::log('SD', "Opening listen server on $listenaddr:$listenport"); $server = IO::Socket::INET->new( - LocalPort => $listenport, - Proto => "tcp", - ReuseAddr => 1, - Type => SOCK_STREAM, - LocalAddr => $listenaddr, - Listen => 10 - ); + LocalPort => $listenport, + Proto => "tcp", + ReuseAddr => 1, + Type => SOCK_STREAM, + LocalAddr => $listenaddr, + Listen => 10 + ); + if (!$server) { Kolab::log('SD', "Unable to open TCP listen server on $listenaddr:$listenport, Error = $@", KOLAB_ERROR); - sleep 1; - goto TRYCONNECT; + sleep 1; + goto TRYCONNECT; } Kolab::log('SD', 'Listen server opened, waiting for incoming connections'); while ($conn = $server->accept()) { - # PENDING: Only accept connections from localhost and - # hosts listed in the kolabhost attribute + # PENDING: Only accept connections from localhost and + # hosts listed in the kolabhost attribute - my($peerport, $peeraddr) = sockaddr_in($conn->peername); - $peeraddr = inet_ntoa( $peeraddr ); + my($peerport, $peeraddr) = sockaddr_in($conn->peername); + $peeraddr = inet_ntoa( $peeraddr ); Kolab::log('SD', "Incoming connection accepted, peer=$peeraddr"); - if( $Kolab::config{'slurpd_accept_addr'} && $peeraddr ne $Kolab::config{'slurpd_accept_addr'} ) { - Kolab::log('SD', "Unauthorized connection from $peeraddr, closing connection", KOLAB_WARN); - $conn->close; - undef $conn; - next; - } + if( $Kolab::config{'slurpd_accept_addr'} && $peeraddr ne $Kolab::config{'slurpd_accept_addr'} ) { + Kolab::log('SD', "Unauthorized connection from $peeraddr, closing connection", KOLAB_WARN); + $conn->close; + undef $conn; + next; + } my $select = IO::Select->new($conn); @@ -274,25 +276,25 @@ sub run my $offset = 0; if (!($select->can_read(0)) && $changes) { - Kolab::log('SD', 'Change detected w/ no pending LDAP messages; waiting a second...'); - if( !($select->can_read(1)) ) { - $changes = 0; - Kolab::log('SD', 'Change detected w/ no pending LDAP messages; reloading services if needed'); - my $kidpid = fork(); - unless (defined $kidpid) { - die("can't fork: $!"); - } - if ($kidpid == 0 ) { - # child - Kolab::LDAP::sync; - exit(0); - } - waitpid($kidpid, 0); - Kolab::log('SD', "Running $Kolab::config{'kolabconf_script'}"); - system($Kolab::config{'kolabconf_script'}) == 0 - or Kolab::log('SD', "Failed to run $Kolab::config{'kolabconf_script'}: $?", KOLAB_ERROR); - Kolab::log('SD', "$Kolab::config{'kolabconf_script'} complete"); - } + Kolab::log('SD', 'Change detected w/ no pending LDAP messages; waiting a second...'); + if( !($select->can_read(1)) ) { + $changes = 0; + Kolab::log('SD', 'Change detected w/ no pending LDAP messages; reloading services if needed'); + my $kidpid = fork(); + unless (defined $kidpid) { + die("can't fork: $!"); + } + if ($kidpid == 0 ) { + # child + Kolab::LDAP::sync; + exit(0); + } + waitpid($kidpid, 0); + Kolab::log('SD', "Running $Kolab::config{'kolabconf_script'}"); + system($Kolab::config{'kolabconf_script'}) == 0 + or Kolab::log('SD', "Failed to run $Kolab::config{'kolabconf_script'}: $?", KOLAB_ERROR); + Kolab::log('SD', "$Kolab::config{'kolabconf_script'} complete"); + } } Kolab::log('SD', 'Waiting for LDAP updates'); @@ -300,12 +302,12 @@ sub run for ($ready = 1; $conn && $ready; $ready = $select->can_read(0)) { Kolab::log('SD', 'Reading ASN', KOLAB_DEBUG); my $newoffset = asn_read($conn, $pdu, $offset); - if( !$conn->connected() or $offset == $newoffset ) { - Kolab::log('SD', 'Connection closed', KOLAB_DEBUG); - $conn->close; - undef $conn; - } - $offset = $newoffset; + if( !$conn->connected() or $offset == $newoffset ) { + Kolab::log('SD', 'Connection closed', KOLAB_DEBUG); + $conn->close; + undef $conn; + } + $offset = $newoffset; defined($offset) or $offset = 0; } @@ -313,29 +315,29 @@ sub run $request = $LDAPRequest->decode($pdu); if (!$request) { Kolab::log('SD', "Unable to decode slurpd request, Error = `" . $LDAPRequest->error . "'", KOLAB_ERROR); - $conn->close if $conn; - undef $conn; - undef $pdu; + $conn->close if $conn; + undef $conn; + undef $pdu; } else { - $_ = getRequestType($request); - Kolab::log('SD', "Request $_ received", KOLAB_DEBUG); - undef $pdu; - - SWITCH: { - if (/^bindRequest/) { $pdu = responseBind($request); last SWITCH; } - if (/addRequest/) { $pdu = responseAdd($request); $changes = 1; last SWITCH; } - if (/delRequest/) { $pdu = responseDel($request); $changes = 1; last SWITCH; } - if (/modifyRequest/) { $pdu = responseMod($request); $changes = 1; last SWITCH; } - if (/modDNRequest/) { $pdu = responseModDN($request); $changes = 1; last SWITCH; } - - if( $conn ) { - Kolab::log('SD', 'Unknown request, connection closed', KOLAB_DEBUG); - $conn->close; - undef $conn; - } - } - } - } + $_ = getRequestType($request); + Kolab::log('SD', "Request $_ received", KOLAB_DEBUG); + undef $pdu; + + SWITCH: { + if (/^bindRequest/) { $pdu = responseBind($request); last SWITCH; } + if (/addRequest/) { $pdu = responseAdd($request); $changes = 1; last SWITCH; } + if (/delRequest/) { $pdu = responseDel($request); $changes = 1; last SWITCH; } + if (/modifyRequest/) { $pdu = responseMod($request); $changes = 1; last SWITCH; } + if (/modDNRequest/) { $pdu = responseModDN($request); $changes = 1; last SWITCH; } + + if( $conn ) { + Kolab::log('SD', 'Unknown request, connection closed', KOLAB_DEBUG); + $conn->close; + undef $conn; + } + } + } + } if ($pdu) { Kolab::log('SD', 'Writing response', KOLAB_DEBUG); @@ -343,8 +345,8 @@ sub run $response = $LDAPResponse->decode($pdu); if (!$response) { Kolab::log('SD', "Unable to decode slurpd request, Error = `" . $LDAPRequest->error . "'"); - $conn->close; - undef $conn; + $conn->close; + undef $conn; } } } diff --git a/lib/Kolab/LDAP/Backend/syncrepl.pm b/lib/Kolab/LDAP/Backend/syncrepl.pm index b4d1e27..5283262 100644 --- a/lib/Kolab/LDAP/Backend/syncrepl.pm +++ b/lib/Kolab/LDAP/Backend/syncrepl.pm @@ -22,9 +22,9 @@ use warnings; use Kolab; use Kolab::LDAP; use Net::LDAP qw( - LDAP_USER_CANCELED - LDAP_SYNC_REFRESH_ONLY - LDAP_SYNC_REFRESH_AND_PERSIST + LDAP_USER_CANCELED + LDAP_SYNC_REFRESH_ONLY + LDAP_SYNC_REFRESH_AND_PERSIST ); use Net::LDAP::Control; use Net::LDAP::Control::SyncRequest; @@ -38,64 +38,65 @@ our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( - &startup - &run - ) ] + &startup + &run + ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( - + ); our $VERSION = '0.3'; -sub mode { - LDAP_SYNC_REFRESH_ONLY; - #LDAP_SYNC_REFRESH_AND_PERSIST; +sub mode { + LDAP_SYNC_REFRESH_ONLY; +# LDAP_SYNC_REFRESH_AND_PERSIST; } # calling without args means: get, # giving an argument means: set sub cookie { - my($cookie) = @_; - my $syncrepl_cookie_file = $Kolab::config{'syncrepl_cookie_file'} || '/tmp/kolab_syncrepl_cookie_file'; - if(defined($cookie)) { - if(!open(COOKIE_FILE, '>', $syncrepl_cookie_file)) { - Kolab::log("SYNCREPL', 'Cannot open file `".$syncrepl_cookie_file. - "' for writing: $!", KOLAB_DEBUG); - &abort; - } - Kolab::log("SYNCREPL', 'Writing cookie to file: ".$cookie, KOLAB_DEBUG); - print COOKIE_FILE $cookie; - close(COOKIE_FILE); - return $cookie; - } else { - #create if it doesn't exists - if(! -f $syncrepl_cookie_file) { - open COOKIE_FILE, '>', $syncrepl_cookie_file; + my($cookie) = @_; + my $syncrepl_cookie_file = $Kolab::config{'syncrepl_cookie_file'} || '/tmp/kolab_syncrepl_cookie_file'; + if(defined($cookie)) { + if(!open(COOKIE_FILE, '>', $syncrepl_cookie_file)) { + Kolab::log("SYNCREPL', 'Cannot open file `".$syncrepl_cookie_file. + "' for writing: $!", KOLAB_DEBUG); + &abort; + } + + Kolab::log("SYNCREPL', 'Writing cookie to file: ".$cookie, KOLAB_DEBUG); + print COOKIE_FILE $cookie; + close(COOKIE_FILE); + return $cookie; + } else { + #create if it doesn't exists + if(! -f $syncrepl_cookie_file) { + open COOKIE_FILE, '>', $syncrepl_cookie_file; + close COOKIE_FILE; + } + if(!open(COOKIE_FILE, '+<', $syncrepl_cookie_file)) { + Kolab::log("SYNCREPL', 'Cannot open file `".$syncrepl_cookie_file. + "' for reading: $!", KOLAB_DEBUG); + &abort; + } + read COOKIE_FILE, $cookie, 1024, 0; close COOKIE_FILE; + #an empty file means no cookie: + $cookie = undef if !$cookie; + return $cookie; } - if(!open(COOKIE_FILE, '+<', $syncrepl_cookie_file)) { - Kolab::log("SYNCREPL', 'Cannot open file `".$syncrepl_cookie_file. - "' for reading: $!", KOLAB_DEBUG); - &abort; - } - read COOKIE_FILE, $cookie, 1024, 0; - close COOKIE_FILE; - #an empty file means no cookie: - $cookie = undef if !$cookie; - return $cookie; - } } sub startup { 1; } sub shutdown { - Kolab::log('SYNCREPL', 'Shutting down'); - exit(0); + Kolab::log('SYNCREPL', 'Shutting down'); + exit(0); } sub abort @@ -105,178 +106,201 @@ sub abort } sub run { - # This should be called from a separate thread, as we set our - # own interrupt handlers here - - $SIG{'INT'} = \&shutdown; - $SIG{'TERM'} = \&shutdown; - - END { - alarm 0; - Kolab::LDAP::destroy($ldap); - } - my $mesg; - - while (1) { - Kolab::log('SYNCREPL', 'Creating LDAP connection to LDAP server', KOLAB_DEBUG); - - $ldap = Kolab::LDAP::create($Kolab::config{'user_ldap_ip'}, - $Kolab::config{'user_ldap_port'}, - $Kolab::config{'user_bind_dn'}, - $Kolab::config{'user_bind_pw'}, - 1 - ); - if (!$ldap) { - Kolab::log('SYNCREPL', 'Sleeping 5 seconds...'); - sleep 5; - next; + # This should be called from a separate thread, as we set our + # own interrupt handlers here + + $SIG{'INT'} = \&shutdown; + $SIG{'TERM'} = \&shutdown; + + END { + alarm 0; + Kolab::LDAP::destroy($ldap); } - $disconnected = 0; - - Kolab::log('SYNCREPL', 'LDAP connection established', KOLAB_DEBUG); - - Kolab::LDAP::ensureAsync($ldap); - Kolab::log('SYNCREPL', 'Async checked', KOLAB_DEBUG); - - while($ldap and not $disconnected) { - my $ctrl = Net::LDAP::Control::SyncRequest->new( - mode => Kolab::LDAP::Backend::syncrepl::mode(), - cookie => Kolab::LDAP::Backend::syncrepl::cookie(), - reloadHint => 0); - Kolab::log('SYNCREPL', 'Control created: mode='.$ctrl->mode(). - '; cookie='.$ctrl->cookie(). - '; reloadHint='.$ctrl->reloadHint(), KOLAB_DEBUG); - - #search - my $mesg = $ldap->search(base => $Kolab::config{'base_dn'}, - scope => 'sub', - control => [ $ctrl ], - callback => \&searchCallback, # call for each entry - filter => "(objectClass=*)", - attrs => [ '*', - $Kolab::config{'user_field_guid'}, - $Kolab::config{'user_field_modified'}, - $Kolab::config{'user_field_quota'}, - $Kolab::config{'user_field_deleted'}, - ], - ); - Kolab::log('SYNCREPL', 'Search created', KOLAB_DEBUG); - $mesg->sync; - Kolab::log('SYNCREPL', "Finished Net::LDAP::Search::sync sleeping 10s", KOLAB_DEBUG); - sleep 10; + my $mesg; + + while (1) { + Kolab::log('SYNCREPL', 'Creating LDAP connection to LDAP server', KOLAB_DEBUG); + + $ldap = Kolab::LDAP::create( + $Kolab::config{'user_ldap_ip'}, + $Kolab::config{'user_ldap_port'}, + $Kolab::config{'user_bind_dn'}, + $Kolab::config{'user_bind_pw'}, + 1 + ); + + if (!$ldap) { + Kolab::log('SYNCREPL', 'Sleeping 5 seconds...'); + sleep 5; + next; + } + + $disconnected = 0; + + Kolab::log('SYNCREPL', 'LDAP connection established', KOLAB_DEBUG); + + Kolab::LDAP::ensureAsync($ldap); + Kolab::log('SYNCREPL', 'Async checked', KOLAB_DEBUG); + + while($ldap and not $disconnected) { + my $ctrl = Net::LDAP::Control::SyncRequest->new( + mode => Kolab::LDAP::Backend::syncrepl::mode(), + cookie => Kolab::LDAP::Backend::syncrepl::cookie(), + reloadHint => 0 + ); + + Kolab::log('SYNCREPL', 'Control created: mode='.$ctrl->mode(). + '; cookie='.$ctrl->cookie(). + '; reloadHint='.$ctrl->reloadHint(), KOLAB_DEBUG); + + #search + my $mesg = $ldap->search( + base => $Kolab::config{'base_dn'}, + scope => 'sub', + control => [ $ctrl ], + callback => \&searchCallback, # call for each entry + filter => "(objectClass=*)", + attrs => [ + '*', + $Kolab::config{'user_field_guid'}, + $Kolab::config{'user_field_modified'}, + $Kolab::config{'user_field_quota'}, + $Kolab::config{'user_field_deleted'}, + ], + ); + + Kolab::log('SYNCREPL', 'Search created', KOLAB_DEBUG); + $mesg->sync; + Kolab::log('SYNCREPL', "Finished Net::LDAP::Search::sync sleeping 10s", KOLAB_DEBUG); + sleep 10; + } } - } - 1; + 1; } #search callback sub searchCallback { - my $mesg = shift; - my $param2 = shift; # might be entry or intermediate - my @controls = $mesg->control; - my @sync_controls = (); - if($param2 && $param2->isa("Net::LDAP::Entry")) { - Kolab::log('SYNCREPL', 'Received Search Entry', KOLAB_DEBUG); - #retrieve Sync State Control - foreach my $ctrl (@controls) { - push(@sync_controls, $ctrl) - if $ctrl->isa('Net::LDAP::Control::SyncState'); - } - if(@sync_controls>1) { - Kolab::log('SYNCREPL', 'Got search entry with multiple Sync State controls', - KOLAB_DEBUG); - return; - } - if(!@sync_controls) { - Kolab::log('SYNCREPL', 'Got search entry without Sync State control', - KOLAB_DEBUG); - return; - } - if(!$sync_controls[0]->entryUUID) { - Kolab::log('SYNCREPL', 'Got empty entryUUID', KOLAB_DEBUG); - return; - } - Kolab::log('SYNCREPL', 'Search Entry has Sync State Control: '. - 'state='.$sync_controls[0]->state(). - '; entryUUID='.unpack("H*",$sync_controls[0]->entryUUID()). - '; cookie='.(defined($sync_controls[0]->cookie()) ? $sync_controls[0]->cookie() : 'UNDEF') - , KOLAB_DEBUG); - if(defined($sync_controls[0]->cookie)) { - Kolab::LDAP::Backend::syncrepl::cookie($sync_controls[0]->cookie); - Kolab::log('SYNCREPL',"New cookie: ".Kolab::LDAP::Backend::syncrepl::cookie(), - KOLAB_DEBUG); - } - Kolab::log('SYNCREPL', "Entry (".$param2->changetype."): ".$param2->dn(), KOLAB_DEBUG); - } elsif($param2 && $param2->isa("Net::LDAP::Reference")) { - Kolab::log('SYNCREPL', 'Received Search Reference', KOLAB_DEBUG); - return; - #if it not first control? - } elsif($controls[0] and $controls[0]->isa('Net::LDAP::Control::SyncDone')) { - Kolab::log('SYNCREPL', 'Received Sync Done Control: '. - 'cookie='.(defined($controls[0]->cookie()) ? $controls[0]->cookie() : 'UNDEF'). - '; refreshDeletes='.$controls[0]->refreshDeletes(), KOLAB_DEBUG); - #we have a new cookie - if(defined($controls[0]->cookie()) - and not $controls[0]->cookie() eq '' - and not $controls[0]->cookie() eq Kolab::LDAP::Backend::syncrepl::cookie()) { - Kolab::LDAP::Backend::syncrepl::cookie($controls[0]->cookie()); - Kolab::log('SYNCREPL', "New cookie: ". - Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); - Kolab::log('SYNCREPL', "Calling Kolab::LDAP::sync", KOLAB_DEBUG); - Kolab::LDAP::sync; - system($Kolab::config{'kolabconf_script'}) == 0 - || Kolab::log('SD', "Failed to run kolabconf: $?", KOLAB_ERROR); - Kolab::log('SYNCREPL', "Finished Kolab::LDAP::sync sleeping 1s", KOLAB_DEBUG); - sleep 1; # we get too many bogus change notifications! - } - } elsif($param2 && $param2->isa("Net::LDAP::Intermediate")) { - Kolab::log('SYNCREPL', 'Received Intermediate Message', KOLAB_DEBUG); - my $attrs = $param2->{asn}; - if($attrs->{newcookie}) { - Kolab::LDAP::Backend::syncrepl::cookie($attrs->{newcookie}); - Kolab::log('SYNCREPL', "New cookie: ". - Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); - } elsif(my $refreshInfos = ($attrs->{refreshDelete} || $attrs->{refreshPresent})) { - Kolab::LDAP::Backend::syncrepl::cookie($refreshInfos->{cookie}) - if defined($refreshInfos->{cookie}); - Kolab::log('SYNCREPL', - (defined($refreshInfos->{cookie}) ? 'New ' : 'Empty '). - "cookie from ". - ($attrs->{refreshDelete} ? 'refreshDelete' : 'refreshPresent'). - " (refreshDone=".$refreshInfos->{refreshDone}."): ". - Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); - } elsif(my $syncIdSetInfos = $attrs->{syncIdSet}) { - Kolab::LDAP::Backend::syncrepl::cookie($syncIdSetInfos->{cookie}) - if defined($syncIdSetInfos->{cookie}); - Kolab::log('SYNCREPL', - (defined($syncIdSetInfos->{cookie}) ? 'Empty ' : 'New '). - "cookie from syncIdSet". - " (refreshDeletes=".$syncIdSetInfos->{refreshDeletes}."): ". - Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); - foreach my $syncUUID ($syncIdSetInfos->{syncUUIDs}) { - Kolab::log('SYNCREPL', 'entryUUID='. - unpack("H*",$syncUUID), KOLAB_DEBUG); - } - } - } elsif($mesg->code) { - if ($mesg->code == 1) { - Kolab::log('SYNCREPL', 'Communication Error: disconnecting', KOLAB_DEBUG); - $disconnected = 1; - return 0; - } elsif ($mesg->code == LDAP_USER_CANCELED) { - Kolab::log('SYNCREPL', 'searchCallback() -> Exit code received, returning', KOLAB_DEBUG); + my $mesg = shift; + my $param2 = shift; # might be entry or intermediate + my @controls = $mesg->control; + my @sync_controls = (); + if($param2 && $param2->isa("Net::LDAP::Entry")) { + Kolab::log('SYNCREPL', 'Received Search Entry', KOLAB_DEBUG); + + #retrieve Sync State Control + foreach my $ctrl (@controls) { + push(@sync_controls, $ctrl) + if $ctrl->isa('Net::LDAP::Control::SyncState'); + } + + if(@sync_controls>1) { + Kolab::log('SYNCREPL', 'Got search entry with multiple Sync State controls', + KOLAB_DEBUG); + return; + } + + if(!@sync_controls) { + Kolab::log('SYNCREPL', 'Got search entry without Sync State control', + KOLAB_DEBUG); + return; + } + + if(!$sync_controls[0]->entryUUID) { + Kolab::log('SYNCREPL', 'Got empty entryUUID', KOLAB_DEBUG); + return; + } + + Kolab::log('SYNCREPL', 'Search Entry has Sync State Control: '. + 'state='.$sync_controls[0]->state(). + '; entryUUID='.unpack("H*",$sync_controls[0]->entryUUID()). + '; cookie='.(defined($sync_controls[0]->cookie()) ? $sync_controls[0]->cookie() : 'UNDEF') + , KOLAB_DEBUG); + + if(defined($sync_controls[0]->cookie)) { + Kolab::LDAP::Backend::syncrepl::cookie($sync_controls[0]->cookie); + Kolab::log('SYNCREPL',"New cookie: ".Kolab::LDAP::Backend::syncrepl::cookie(), + KOLAB_DEBUG); + } + + Kolab::log('SYNCREPL', "Entry (".$param2->changetype."): ".$param2->dn(), KOLAB_DEBUG); + } elsif($param2 && $param2->isa("Net::LDAP::Reference")) { + Kolab::log('SYNCREPL', 'Received Search Reference', KOLAB_DEBUG); return; - } elsif ($mesg->code == 4096) { - Kolab::log('SYNCREPL', 'Refresh required', KOLAB_DEBUG); - Kolab::LDAP::Backend::syncrepl::cookie(''); + #if it not first control? + } elsif($controls[0] and $controls[0]->isa('Net::LDAP::Control::SyncDone')) { + Kolab::log('SYNCREPL', 'Received Sync Done Control: '. + 'cookie='.(defined($controls[0]->cookie()) ? $controls[0]->cookie() : 'UNDEF'). + '; refreshDeletes='.$controls[0]->refreshDeletes(), KOLAB_DEBUG); + + #we have a new cookie + if(defined($controls[0]->cookie()) + and not $controls[0]->cookie() eq '' + and not $controls[0]->cookie() eq Kolab::LDAP::Backend::syncrepl::cookie()) { + + Kolab::LDAP::Backend::syncrepl::cookie($controls[0]->cookie()); + Kolab::log('SYNCREPL', "New cookie: ". + Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); + + Kolab::log('SYNCREPL', "Calling Kolab::LDAP::sync", KOLAB_DEBUG); + Kolab::LDAP::sync; + system($Kolab::config{'kolabconf_script'}) == 0 + || Kolab::log('SD', "Failed to run kolabconf: $?", KOLAB_ERROR); + + Kolab::log('SYNCREPL', "Finished Kolab::LDAP::sync sleeping 1s", KOLAB_DEBUG); + sleep 1; # we get too many bogus change notifications! + } + } elsif($param2 && $param2->isa("Net::LDAP::Intermediate")) { + Kolab::log('SYNCREPL', 'Received Intermediate Message', KOLAB_DEBUG); + my $attrs = $param2->{asn}; + if($attrs->{newcookie}) { + Kolab::LDAP::Backend::syncrepl::cookie($attrs->{newcookie}); + Kolab::log('SYNCREPL', "New cookie: ". + Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); + + } elsif(my $refreshInfos = ($attrs->{refreshDelete} || $attrs->{refreshPresent})) { + Kolab::LDAP::Backend::syncrepl::cookie($refreshInfos->{cookie}) + if defined($refreshInfos->{cookie}); + + Kolab::log('SYNCREPL', + (defined($refreshInfos->{cookie}) ? 'New ' : 'Empty '). + "cookie from ". + ($attrs->{refreshDelete} ? 'refreshDelete' : 'refreshPresent'). + " (refreshDone=".$refreshInfos->{refreshDone}."): ". + Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); + } elsif(my $syncIdSetInfos = $attrs->{syncIdSet}) { + Kolab::LDAP::Backend::syncrepl::cookie($syncIdSetInfos->{cookie}) + if defined($syncIdSetInfos->{cookie}); + + Kolab::log('SYNCREPL', + (defined($syncIdSetInfos->{cookie}) ? 'Empty ' : 'New '). + "cookie from syncIdSet". + " (refreshDeletes=".$syncIdSetInfos->{refreshDeletes}."): ". + Kolab::LDAP::Backend::syncrepl::cookie(), KOLAB_DEBUG); + + foreach my $syncUUID ($syncIdSetInfos->{syncUUIDs}) { + Kolab::log('SYNCREPL', 'entryUUID='. + unpack("H*",$syncUUID), KOLAB_DEBUG); + } + } + } elsif($mesg->code) { + if ($mesg->code == 1) { + Kolab::log('SYNCREPL', 'Communication Error: disconnecting', KOLAB_DEBUG); + $disconnected = 1; + return 0; + } elsif ($mesg->code == LDAP_USER_CANCELED) { + Kolab::log('SYNCREPL', 'searchCallback() -> Exit code received, returning', KOLAB_DEBUG); + return; + } elsif ($mesg->code == 4096) { + Kolab::log('SYNCREPL', 'Refresh required', KOLAB_DEBUG); + Kolab::LDAP::Backend::syncrepl::cookie(''); + } else { + Kolab::log('SYNCREPL', "searchCallback: mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); + &abort; + } } else { - Kolab::log('SYNCREPL', "searchCallback: mesg->code = `" . $mesg->code . "', mesg->msg = `" . $mesg->error . "'", KOLAB_DEBUG); - &abort; - } - } else { - Kolab::log('SYNCREPL', 'Received something else', KOLAB_DEBUG); - } - return 0; + Kolab::log('SYNCREPL', 'Received something else', KOLAB_DEBUG); + } + return 0; } 1; diff --git a/lib/Kolab/Util.pm b/lib/Kolab/Util.pm index f115eeb..85612eb 100644 --- a/lib/Kolab/Util.pm +++ b/lib/Kolab/Util.pm @@ -99,9 +99,9 @@ sub readConfig $sep = '\s' if ($sep eq ' ' || $sep eq '#'); my $fd; - if (!($fd = IO::File->new($file, 'r'))) { - superLog( "Warning: Could not read $file"); - return %cfg; + if (!($fd = IO::File->new($file, 'r'))) { + superLog( "Warning: Could not read $file"); + return %cfg; } foreach (<$fd>) { |