All pastes #414858 Raw Edit

Unnamed

public text v1 · immutable
#414858 ·published 2007-03-29 10:46 UTC
rendered paste body
     1 # <@LICENSE>
      2 # Copyright 2004 Apache Software Foundation
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #     http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 # </@LICENSE>
     16
     17 =head1 NAME
     18
     19 Mail::SpamAssassin::Conf::LDAP - load SpamAssassin scores from LDAP database
     20
     21 =head1 SYNOPSIS
     22
     23   (see Mail::SpamAssassin)
     24
     25
     26 =head1 DESCRIPTION
     27
     28 Mail::SpamAssassin is a module to identify spam using text analysis and
     29 several internet-based realtime blacklists.
     30
     31 This class is used internally by SpamAssassin to load scores from an LDAP
     32 database.  Please refer to the C<Mail::SpamAssassin> documentation for public
     33 interfaces.
     34
     35 =head1 METHODS
     36
     37 =over 4
     38
     39 =cut
     40
     41 package Mail::SpamAssassin::Conf::LDAP;
     42
     43 use Mail::SpamAssassin::Logger;
     44
     45 use strict;
     46 use warnings;
     47 use bytes;
     48 use Carp;
     49
     50 use vars qw{
     51   @ISA
     52 };
     53
     54 @ISA = qw();
     55
     56 ###########################################################################
     57
     58 sub new {
     59   my $class = shift;
     60   $class = ref($class) || $class;
     61   my ($main) = @_;
     62
     63   my $self = {
     64     'main'              => $main
     65   };
     66
     67   bless ($self, $class);
     68   $self;
     69 }
     70
     71 ###########################################################################
     72
     73 sub load_modules {              # static
     74   dbg("ldap: loading Net::LDAP and URI");
     75   eval {
     76     require Net::LDAP; # actual server connection
     77     require URI;       # parse server connection dsn
     78   };
     79
     80   # do any other preloading that will speed up operation
     81 }
     82
     83 ###########################################################################
     84
     85 =item $f->load ($username)
     86
     87 Read configuration paramaters from LDAP server and parse scores from it.
     88
     89 =cut
     90
     91 sub load {
     92    my ($self, $username) = @_;
     93
     94    my $url = $self->{main}->{conf}->{user_scores_dsn}; # an ldap URI
     95    dbg("ldap: URL is $url");
     96    if(!defined($url) || $url eq '') {
     97      dbg("ldap: No URL defined; skipping LDAP");
     98      return;
     99    }
    100
    101    eval {
    102      # make sure we can see croak messages from DBI
    103      local $SIG{'__DIE__'} = sub { warn "$_[0]"; };
    104      require Net::LDAP;
    105      require URI;
    106      load_with_ldap($self, $username, $url);
    107    };
    108
    109    if ($@) {
    110      warn "ldap: failed to load user scores from LDAP server, ignored\n";
    111    }
    112 }
    113
    114 sub load_with_ldap {
    115   my ($self, $username, $url) = @_;
    116
    117 #       ldapurl    = scheme "://" [hostport] ["/"
    118 #                    [dn ["?" [attributes] ["?" [scope]
    119 #                    ["?" [filter] ["?" extensions]]]]]]
    120
    121   my $uri = URI->new("$url");
    122
    123   my $host   = $uri->host;
    124   if (!defined($host) || $host eq '') {
    125     dbg("ldap: No server specified, assuming localhost");
    126     $host = "localhost";
    127   }
    128   my $port   = $uri->port;
    129   my $base   = $uri->dn;
    130   my @attr   = $uri->attributes;
    131   my $scope  = $uri->scope;
    132   my $filter = $uri->filter;
    133   my %extn   = $uri->extensions; # unused
    134
    135   $filter =~ s/__USERNAME__/$username/g;
    136   dbg("ldap: host=$host, port=$port, base='$base', attr=${attr[0]}, scope=$scope, filter='$filter'");
    137
    138   my $main = $self->{main};
    139   my $ldapuser = $main->{conf}->{user_scores_ldap_username};
    140   my $ldappass = $main->{conf}->{user_scores_ldap_password};
    141
    142   if(!$ldapuser) {
    143       undef($ldapuser);
    144   } else {
    145       dbg("ldap: user='$ldapuser'");
    146   }
    147
    148   if(!$ldappass) {
    149       undef($ldappass);
    150   } else {
    151       # don't log this to avoid leaking sensitive info
    152       # dbg("ldap: pass='$ldappass'");
    153   }
    154
    155   my $f_attribute = $attr[0];
    156
    157   my $ldap = Net::LDAP->new ("$host:$port", onerror => "warn");
    158   if (!defined($ldapuser) && !defined($ldappass)) {
    159     $ldap->bind;
    160   } else {
    161     $ldap->bind($ldapuser, password => $ldappass);
    162   }
    163
    164   my $result = $ldap->search( base => $base,
    165                               filter => $filter,
    166                               scope => $scope,
    167                               attrs => \@attr
    168                             );
    169
    170   my $conf = '';
    171   foreach my $entry ($result->all_entries) {
    172     my @v = $entry->get_value($f_attribute);
    173     foreach my $v (@v) {
    174       dbg("ldap: retrieving prefs for $username: $v");
    175       $conf .= $v."\n";
    176     }
    177   }
    178   $main->{conf}->{main} = $main;
    179   $main->{conf}->parse_scores_only($conf);
    180   delete $main->{conf}->{main};
    181   return;
    182 }
    183
    184 ###########################################################################
    185
    186 sub sa_die { Mail::SpamAssassin::sa_die(@_); }
    187
    188 ###########################################################################
    189
    190 1;