#-*- perl -*- # # Copyright (C) 2001 Ken'ichi Fukamachi # All rights reserved. This program is free software; you can # redistribute it and/or modify it under the same terms as Perl itself. # # $FML: Credential.pm,v 1.10 2001/05/28 16:17:12 fukachan Exp $ # package FML::Credential; use strict; use vars qw(%Credential @ISA @EXPORT @EXPORT_OK); use Carp; use ErrorStatus qw(errstr error error_set error_clear); =head1 NAME FML::Credential - authenticate the mail sender =head1 SYNOPSIS use FML::Credential; # get the mail sender my $sender = FML::Credential->sender; =head1 DESCRIPTION a collection of utilitity functions to authenticate the sender who kicks off this mail. =head1 METHODS =head2 C bind \%Credential to $self and return it as an object. =cut # Descriptions: usual constructor # bind $self ($me) to \%Credential, so # you can access the same \%Credential through this object. # Arguments: $self # Side Effects: bind $self ($me) to \%Credential # Return Value: object sub new { my ($self) = @_; my ($type) = ref($self) || $self; my $me = \%Credential; return bless $me, $type; } sub DESTROY {} =head2 C return 1 if C<$addr1> and C<$addr2> looks same within some ambiguity. The ambiguity is followed by these rules. 1. C part must be the same case sensitively. 2. C part is case insensitive by definition of C. 3. C part is the same from the top C layer to C<$level>-th sub domain level. XXX RULE 3 IS NOT YET IMPLEMENTED =cut sub is_same_address { my ($self, $xaddr, $yaddr, $level) = @_; my ($xuser, $xdomain) = split(/\@/, $xaddr); my ($yuser, $ydomain) = split(/\@/, $yaddr); # rule 1 if ($xuser ne $yuser) { return 0;} # rule 2 if ("\L$xdomain\E" eq "\L$ydomain\E") { return 1;} # rule 3: not yet 0; } =head2 C return 1 if the sender is a ML member. return 0 if not. =cut # Descriptions: # Arguments: $self $curproc $args # Side Effects: # Return Value: none sub is_member { my ($self, $curproc, $args) = @_; my $status = 0; my $member_maps = $curproc->{ config }->{ member_maps }; my $address = $curproc->{'credential'}->{'sender'}; my ($user, $domain) = split(/\@/, $address); use IO::Adapter; for my $map (split(/\s+/, $member_maps)) { if ($map) { my $obj = new IO::Adapter $map; my $x = $obj->find( $user ); my ($r) = split(/\s+/, $x); if ($self->is_same_address($r, $address)) { $status = 1; # found } last if $x; } } unless ($status) { $self->error_set("user=$user domain=$domain not found"); } $status; } =head2 C C ( == $self->sender() ) matches a system account or not. The system accounts are given as $curproc->{ config }->{ system_accounts }. =cut sub match_system_accounts { my ($self, $curproc, $args) = @_; my $config = $curproc->{ config }; # compare $user part of the sender address my ($user, $domain) = split(/\@/, $self->sender()); # compare $user part with e.g. root, postmaster, ... # XXX always case INSENSITIVE for my $addr (split(/\s+/, $config->{ system_accounts })) { if ($user =~ /^${addr}$/i) { return $addr;} } return ''; } =head2 C return the mail address of the mail sender who kicks off this fml process. =cut # Descriptions: returh the mail sender # Arguments: $self # Side Effects: none # Return Value: mail address sub sender { my ($self) = @_; $Credential{ sender }; } =head2 C XXX NUKE THIS ? =head2 C XXX NUKE THIS ? =cut # Descriptions: # Arguments: $self key # Side Effects: none # Return Value: string sub get { my ($self, $key) = @_; $self->{ $key }; } # Descriptions: # Arguments: $self key value # Side Effects: none # Return Value: string sub set { my ($self, $key, $value) = @_; $self->{ $key } = $value; } =head1 AUTHOR Ken'ichi Fukamachi =head1 COPYRIGHT Copyright (C) 2001 Ken'ichi Fukamachi All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 HISTORY FML::Credential appeared in fml5 mailing list driver package. See C for more details. =cut 1;