diff options
-rwxr-xr-x | fripost-adduser | 2 | ||||
-rwxr-xr-x | fripost-newalias | 2 | ||||
-rwxr-xr-x | fripost-newdomain | 4 | ||||
-rwxr-xr-x | fripost-searchalias | 144 | ||||
-rwxr-xr-x | fripost-searchdomain | 153 | ||||
-rwxr-xr-x | fripost-searchuser | 140 | ||||
-rw-r--r-- | lib/Fripost/Schema/Search.pm | 10 | ||||
-rw-r--r-- | lib/Fripost/Schema/Type/Domain.pm | 11 |
8 files changed, 461 insertions, 5 deletions
diff --git a/fripost-adduser b/fripost-adduser index a785f07..633926e 100755 --- a/fripost-adduser +++ b/fripost-adduser @@ -202,7 +202,7 @@ my ($domain, $login); if ($res->count) { print STDERR "Error: Alias $user->{username} already exists. "; print STDERR "(Targetting to "; - print STDERR (join ', ', map { $_->{goto} } ($res->entries)); + print STDERR (join ', ', map { $_->{goto} } $res->entries); say STDERR ".)"; exit 1; } diff --git a/fripost-newalias b/fripost-newalias index 075c43a..b5ad94f 100755 --- a/fripost-newalias +++ b/fripost-newalias @@ -195,7 +195,7 @@ for my $addr (@addr) { else { print STDERR "Error: Alias $addr already exists. "; print STDERR "(Targetting to "; - print STDERR (join ', ', map { $_->{goto} } ($rs->entries)); + print STDERR (join ', ', map { $_->{goto} } $rs->entries); say STDERR ".)"; exit 1; } diff --git a/fripost-newdomain b/fripost-newdomain index 3c877e5..7cbac3b 100755 --- a/fripost-newdomain +++ b/fripost-newdomain @@ -185,7 +185,7 @@ else { if ($res->count) { print STDERR "WARN: Domain `" .$domain{domain}. "' already exists."; my @owners; - map { push @owners, $_->{owner} if defined $_->{owner} } ($res->entries); + map { push @owners, @{$_->{owner}} if defined $_->{owner} } $res->entries; if (@owners) { print STDERR " (Owned by "; print STDERR (join ', ', map { '`' .$_. "'"} @owners); @@ -224,7 +224,7 @@ sub create_alias { if ($res->count) { print STDERR "WARN: Alias $alias{address} already exists."; print STDERR "(Targetting to "; - print STDERR (join ', ', map { $_->{goto} } ($res->entries)); + print STDERR (join ', ', map { $_->{goto} } $res->entries); say STDERR ".)"; return unless grep { $_->{goto} eq $alias{goto} } $res->entries; } diff --git a/fripost-searchalias b/fripost-searchalias new file mode 100755 index 0000000..0775942 --- /dev/null +++ b/fripost-searchalias @@ -0,0 +1,144 @@ +#!/usr/bin/perl + +use 5.010_000; +use strict; +use warnings; +use utf8; + +=head1 NAME + +fripost-searchalias - List matching aliases + +=head1 SYNOPSIS + +B<fripost-searchalias> [B<--debug>] [I<goto> [I<from>]] + +=head1 DESCRIPTION + +B<fripost-seardomain> list virtual aliases matching exactly I<from>, +targetting to I<goto>. +Wildcards I<*> can appear in I<goto> or I<from>, to match zero or more +characters. +If no I<from> is given, list all aliases whose target matches I<goto>. +If neither I<goto> nor I<from> are given, B<fripost-searchalias> list +all existing virtual aliases. + +=head1 OPTIONS + +=over 8 + +=item B<--server_host=>I<host> + +The LDAP URI to connect to. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_dn=>I<binddn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchalias> binds anonymously.) +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_pw=>I<password> + +The password to to bind with. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--base_dn=>I<basedn> + +The root DN for everything done by B<fripost-searchalias>. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--debug> + +Debug mode. + +=back + +=head1 CONFIGURATION + +The configuration is read from the file C<$HOME/.fripost.yml>. +Valid keys include: + +=over 4 + +=item I<server_host> + +The LDAP URI to connect to. Defaults to C<ldap://127.0.0.1:389>. + +=item I<bind_dn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchalias> binds anonymously.) + +=item I<bind_pw> + +The password to to bind with. + +=item I<base_dn> + +The root DN for everything done by B<fripost-searchalias>. + +=back + +=cut + +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Env qw /HOME/; +use File::Spec::Functions; + +use Fripost::Schema; +use Getopt::Long qw /:config noauto_abbrev no_ignore_case + gnu_compat bundling permute nogetopt_compat + auto_version auto_help/; +use Pod::Usage; +use YAML::Syck; + + +## Get command line options +our $conf = LoadFile( catfile ($HOME, '.fripost.yml') ); + +GetOptions( + 'server_host=s' => \$conf->{server_host}, + 'base_dn=s' => \$conf->{base_dn}, + 'bind_dn=s' => \$conf->{bind_dn}, + 'bind_pw=s' => \$conf->{bind_pw}, + 'pretend' => \$conf->{pretend}, + 'debug' => \$conf->{debug}, + 'man' => sub { pod2usage(-exitstatus => 0, + -verbose => 2) } +) or pod2usage(2); + + +# Connect to the LDAP server +my $ldap = Fripost::Schema->new( $conf ); + +my %alias; +$alias{goto} = $ARGV[0] if defined $ARGV[0]; +$alias{address} = $ARGV[1] if defined $ARGV[1]; + +foreach my $alias ($ldap->alias->search( \%alias )->entries) { + say "From: " . (join ', ', @{$alias->{address}}); + say "Goto: " . $alias->{goto}; + say "IsActive: " . $alias->{isActive}; + say "--------------------------------" +} + +$ldap->unbind(); + + +=head1 AUTHOR + +Guilhem Moulin C<< <guilhem at fripost.org> >> + +=head1 COPYRIGHT + +Copyright 2012 Guilhem Moulin. + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify it +under the same terms as perl itself. + +=cut diff --git a/fripost-searchdomain b/fripost-searchdomain new file mode 100755 index 0000000..bbd59a3 --- /dev/null +++ b/fripost-searchdomain @@ -0,0 +1,153 @@ +#!/usr/bin/perl + +use 5.010_000; +use strict; +use warnings; +use utf8; + +=head1 NAME + +fripost-searchdomain - List matching domains + +=head1 SYNOPSIS + +B<fripost-searchdomain> [B<--debug>] [I<domain> [I<owner>]] + +=head1 DESCRIPTION + +B<fripost-seardomain> list virtual domains matching exactly I<domain>, +and whose owner is I<owner>. +Wildcards I<*> can appear in I<domain> or I<owner>, to match zero or more +characters. +If no I<owner> is given, list all domains I<domain>, regardless of the +owner; If I<owner> is the empty string I<''>, list only the non +self-managed domains. +If neither I<domain> nor I<owner> are given, B<fripost-searchdomain> list +all existing virtual domains. + +=head1 OPTIONS + +=over 8 + +=item B<--server_host=>I<host> + +The LDAP URI to connect to. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_dn=>I<binddn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchdomain> binds anonymously.) +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_pw=>I<password> + +The password to to bind with. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--base_dn=>I<basedn> + +The root DN for everything done by B<fripost-searchdomain>. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--debug> + +Debug mode. + +=back + +=head1 CONFIGURATION + +The configuration is read from the file C<$HOME/.fripost.yml>. +Valid keys include: + +=over 4 + +=item I<server_host> + +The LDAP URI to connect to. Defaults to C<ldap://127.0.0.1:389>. + +=item I<bind_dn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchdomain> binds anonymously.) + +=item I<bind_pw> + +The password to to bind with. + +=item I<base_dn> + +The root DN for everything done by B<fripost-searchdomain>. + +=back + +=cut + +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Env qw /HOME/; +use File::Spec::Functions; + +use Fripost::Schema; +use Getopt::Long qw /:config noauto_abbrev no_ignore_case + gnu_compat bundling permute nogetopt_compat + auto_version auto_help/; +use Pod::Usage; +use YAML::Syck; + + +## Get command line options +our $conf = LoadFile( catfile ($HOME, '.fripost.yml') ); + +GetOptions( + 'server_host=s' => \$conf->{server_host}, + 'base_dn=s' => \$conf->{base_dn}, + 'bind_dn=s' => \$conf->{bind_dn}, + 'bind_pw=s' => \$conf->{bind_pw}, + 'pretend' => \$conf->{pretend}, + 'debug' => \$conf->{debug}, + 'man' => sub { pod2usage(-exitstatus => 0, + -verbose => 2) } +) or pod2usage(2); + + +# Connect to the LDAP server +my $ldap = Fripost::Schema->new( $conf ); + +my %domain; +$domain{domain} = $ARGV[0] if defined $ARGV[0]; +$domain{owner} = $ARGV[1] if defined $ARGV[1]; + +foreach my $domain ($ldap->domain->search( \%domain )->entries) { + say "Domain: " . $domain->{domain}; + print "Owner: "; + my $owners = $domain->{owner}; + if (defined $owners) { + say (join ', ', @$owners); + } + else { + say "(none)"; + } + say "IsActive: " . $domain->{isActive}; + say "--------------------------------" +} + +$ldap->unbind(); + + +=head1 AUTHOR + +Guilhem Moulin C<< <guilhem at fripost.org> >> + +=head1 COPYRIGHT + +Copyright 2012 Guilhem Moulin. + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify it +under the same terms as perl itself. + +=cut diff --git a/fripost-searchuser b/fripost-searchuser new file mode 100755 index 0000000..30df331 --- /dev/null +++ b/fripost-searchuser @@ -0,0 +1,140 @@ +#!/usr/bin/perl + +use 5.010_000; +use strict; +use warnings; +use utf8; + +=head1 NAME + +fripost-searchuser - List matching users + +=head1 SYNOPSIS + +B<fripost-searchuser> [B<--debug>] [I<username>] + +=head1 DESCRIPTION + +B<fripost-searchuser> list virtual mailboxes whose username exactly matches +I<username>. +Wildcards I<*> can appear in I<username>, to match zero or more characters. +If no I<username> is given, B<fripost-searchuser> list all existing mailboxes. + +=head1 OPTIONS + +=over 8 + +=item B<--server_host=>I<host> + +The LDAP URI to connect to. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_dn=>I<binddn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchuser> binds anonymously.) +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--bind_pw=>I<password> + +The password to to bind with. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--base_dn=>I<basedn> + +The root DN for everything done by B<fripost-searchuser>. +The default value is read from the configuration file, see B<CONFIGURATION>. + +=item B<--debug> + +Debug mode. + +=back + +=head1 CONFIGURATION + +The configuration is read from the file C<$HOME/.fripost.yml>. +Valid keys include: + +=over 4 + +=item I<server_host> + +The LDAP URI to connect to. Defaults to C<ldap://127.0.0.1:389>. + +=item I<bind_dn> + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B<fripost-searchuser> binds anonymously.) + +=item I<bind_pw> + +The password to to bind with. + +=item I<base_dn> + +The root DN for everything done by B<fripost-searchuser>. + +=back + +=cut + +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Env qw /HOME/; +use File::Spec::Functions; + +use Fripost::Schema; +use Getopt::Long qw /:config noauto_abbrev no_ignore_case + gnu_compat bundling permute nogetopt_compat + auto_version auto_help/; +use Pod::Usage; +use YAML::Syck; + + +## Get command line options +our $conf = LoadFile( catfile ($HOME, '.fripost.yml') ); + +GetOptions( + 'server_host=s' => \$conf->{server_host}, + 'base_dn=s' => \$conf->{base_dn}, + 'bind_dn=s' => \$conf->{bind_dn}, + 'bind_pw=s' => \$conf->{bind_pw}, + 'pretend' => \$conf->{pretend}, + 'debug' => \$conf->{debug}, + 'man' => sub { pod2usage(-exitstatus => 0, + -verbose => 2) } +) or pod2usage(2); + + +# Connect to the LDAP server +my $ldap = Fripost::Schema->new( $conf ); + +my %user; +$user{username} = $ARGV[0] if defined $ARGV[0]; + +foreach my $user ($ldap->user->search( \%user )->entries) { + say "User: " . $user->{username}; + say "Maildir: " . $user->{maildir}; + say "IsActive: " . $user->{isActive}; + say "--------------------------------" +} + +$ldap->unbind(); + + +=head1 AUTHOR + +Guilhem Moulin C<< <guilhem at fripost.org> >> + +=head1 COPYRIGHT + +Copyright 2012 Guilhem Moulin. + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify it +under the same terms as perl itself. + +=cut diff --git a/lib/Fripost/Schema/Search.pm b/lib/Fripost/Schema/Search.pm index 7c0ece6..3dc2efa 100644 --- a/lib/Fripost/Schema/Search.pm +++ b/lib/Fripost/Schema/Search.pm @@ -53,6 +53,12 @@ sub _domainEntry { &_get_values( $entry, \%domain, 'domain', 'dc'); map { &_get_values($entry, \%domain, $_) } qw /isActive owner/; + if (defined $domain{owner}) { + $domain{owner} = [ $domain{owner} ] + unless (ref $domain{owner}) eq 'ARRAY'; + $domain{owner} = [ map { (split /=/, (split /,/, $_, 2)[0], 2)[1] } + @{$domain{owner}} ]; + } return \%domain; } @@ -60,6 +66,10 @@ sub _aliasEntry { my $entry = shift; my %alias; &_get_values( $entry, \%alias, 'address', 'mailLocalAddress'); + if (defined $alias{address}) { + $alias{address} = [ $alias{address} ] + unless (ref $alias{address}) eq 'ARRAY'; + } &_get_values( $entry, \%alias, 'goto', 'mailTarget'); &_get_values( $entry, \%alias, 'isActive'); return \%alias; diff --git a/lib/Fripost/Schema/Type/Domain.pm b/lib/Fripost/Schema/Type/Domain.pm index f85ea87..0d2be17 100644 --- a/lib/Fripost/Schema/Type/Domain.pm +++ b/lib/Fripost/Schema/Type/Domain.pm @@ -14,6 +14,8 @@ our $VERSION = '0.01'; # domain is given, returns all domains. # Filters on values of both keys `domain' and `owner' (unless they are # undefined). +# If `owner' is the empty string, serch for non self-managed domains +# only. sub search { my $self = shift; @@ -26,7 +28,14 @@ sub search { my @filters = ('(ObjectClass=virtualDomain)'); push @filters, "(dc=" .$_[0]->{domain}. ")" if defined $_[0]->{domain}; - push @filters, "(owner=" .$owner. ")" if defined $_[0]->{owner}; + if (defined $_[0]->{owner}) { + if ($_[0]->{owner} eq '') { + push @filters, "(!(owner=*))"; + } + else { + push @filters, "(owner=" .$owner. ")"; + } + } my $filter; if ($#filters == 0) { $filter = $filters[0]; |