Provided by: libmail-srs-perl_0.31-9_all bug

NAME

       Mail::SRS - Interface to Sender Rewriting Scheme

SYNOPSIS

               use Mail::SRS;
               my $srs = new Mail::SRS(
                       Secret     => [ .... ],    # scalar or array
                       MaxAge     => 49,          # days
                       HashLength => 4,           # base64 characters: 4 x 6bits
                       HashMin    => 4,           # base64 characters
                               );
               my $srsaddress = $srs->forward($sender, $alias);
               my $sender = $srs->reverse($srsaddress);

DESCRIPTION

       The Sender Rewriting Scheme preserves .forward functionality in an SPF-compliant world.

       SPF requires the SMTP client IP to match the envelope sender (return-path). When a message is forwarded
       through an intermediate server, that intermediate server may need to rewrite the return-path to remain
       SPF compliant. If the message bounces, that intermediate server needs to validate the bounce and forward
       the bounce to the original sender.

       SRS provides a convention for return-path rewriting which allows multiple forwarding servers to compact
       the return-path. SRS also provides an authentication mechanism to ensure that purported bounces are not
       arbitrarily forwarded.

       SRS is documented at http://spf.pobox.com/srs.html and many points about the scheme are discussed at
       http://www.anarres.org/projects/srs/

       For a better understanding of this code and how it functions, please read this document and run the
       interactive walkthrough in eg/simple.pl in this distribution. To run this from the build directory, type
       "make teach".

METHODS

   $srs = new Mail::SRS(...)
       Construct a new Mail::SRS object and return it. Available parameters are:

       Secret => $string
           A key for the cryptographic algorithms. This may be an array or a single string. A string is promoted
           into an array of one element.

       MaxAge
           The  maximum number of days for which a timestamp is considered valid. After this time, the timestamp
           is invalid.

       HashLength => $integer
           The number of bytes of base64 encoded data to use for the cryptographic hash.  More  is  better,  but
           makes  for  longer  addresses  which  might exceed the 64 character length suggested by RFC2821. This
           defaults to 4, which gives 4 x 6 = 24 bits of cryptographic information, which means that  a  spammer
           will have to make 2^24 attempts to guarantee forging an SRS address.

       HashMin => $integer
           The  shortest hash which we will allow to pass authentication. Since we allow any valid prefix of the
           full SHA1 HMAC to pass authentication, a spammer might just suggest a hash of length 0. We require at
           least HashMin characters, which must all  be  correct.  Naturally,  this  must  be  no  greater  than
           HashLength and will default to HashLength unless otherwise specified.

       Separator => $character
           Specify  the  initial  separator  to  use  immediately  after  the  SRS tag. SRS uses the = separator
           throughout EXCEPT for the initial separator, which may be any of + - or =.

           Some MTAs already have a feature by which text after  a  +  or  -  is  ignored  for  the  purpose  of
           identifying  a  local recipient. If the initial separator is set to + or -, then an administrator may
           process all SRS mails by creating users SRS0 and SRS1, and using Mail::SRS in  the  default  delivery
           rule for these users.

           Some  notes  on  the  use  and  preservation  of  these  separators  are  found  in  the  perldoc for
           Mail::SRS::Guarded.

       AlwaysRewrite => $boolean
           SRS rewriting is not performed by default if the alias host matches the sender host, since  it  would
           be  unnecessary  to  do  so, and it interacts badly with ezmlm if we do. Set this to true if you want
           always to rewrite when requested to do so.

       IgnoreTimestamp => $boolean
           Consider all timestamps to be valid. Defaults to false. It is STRONGLY recommended that  this  remain
           false. This parameter is provided so that timestamps may be ignored temporarily after a change in the
           timestamp  format  or  encoding,  until all timestamps in the old encoding would have become invalid.
           Note that timestamps still form a part of the cryptographic data when this is enabled.

       AllowUnsafeSrs
           This is a backwards compatibility option for an older version of the  protocol  where  SRS1  was  not
           hash-protected.  The  'reverse'  method  will  detect  such  addresses,  and  handle  them  properly.
           Deployments upgrading from version <=0.27 to any version >=0.28 should enable this for MaxAge+1 days.

           When this option is enabled, all new addresses will be generated with cryptographic protection.

       Some subclasses require other parameters. See their documentation for details.

   $srsaddress = $srs->forward($sender, $alias)
       Map a sender address into a new sender and a cryptographic cookie.  Returns an SRS address to use as  the
       new sender.

       There  are  alternative  subclasses,  some of which will return SRS compliant addresses, some will simply
       return non-SRS but valid RFC821 addresses. See the interactive walkthrough for more information  on  this
       ("make teach").

   $sender = $srs->reverse($srsaddress)
       Reverse  the  mapping  to  get  back  the  original  address.  Validates  all cryptographic and timestamp
       information. Returns the original sender address. This method will die if the address cannot be reversed.

   $srs->compile($sendhost, $senduser)
       This method, designed to be overridden by subclasses, takes as parameters the original host and user  and
       must  compile  a new username for the SRS transformed address. It is expected that this new username will
       be joined on $SRSSEP, and will contain a hash generated  from  $self->hash_create(...),  and  possibly  a
       timestamp generated by $self->timestamp_create().

   $srs->parse($srsuser)
       This  method,  designed to be overridden by subclasses, takes an SRS-transformed username as an argument,
       and must reverse the transformation produced by  compile().  It  is  required  to  verify  any  hash  and
       timestamp      in      the      parsed     data,     using     $self->hash_verify($hash,     ...)     and
       $self->timestamp_check($timestamp).

   $srs->timestamp_create([$time])
       Return a two character timestamp representing 'today', or $time if  given.  $time  is  a  Unix  timestamp
       (seconds since the aeon).

       This  Perl function has been designed to be agnostic as to base, and in practice, base32 is used since it
       can be reversed even if a remote MTA smashes case (in violation of RFC2821 section 2.4). The  agnosticism
       means  that the Perl uses division instead of rightshift, but in Perl that doesn't matter. C implementors
       should implement this operation as a right shift by 5.

   $srs->timestamp_check($timestamp)
       Return 1 if a timestamp is valid, undef otherwise. There are 4096 possible timestamps, used in  a  cycle.
       At  any  time,  $srs->{MaxAge}  timestamps in this cycle are valid, the last one being today. A timestamp
       from the future is not valid, neither is a timestamp from too far into the past. Of course if you go  far
       enough  into the future, the cycle wraps around, and there are valid timestamps again, but the likelihood
       of a random timestamp being valid is 4096/$srs->{MaxAge}, which is usually  quite  small:  1  in  132  by
       default.

   $srs->time_check($time)
       Similar  to $srs->timestamp_check($timestamp), but takes a Unix time, and checks that an alias created at
       that Unix time is still valid. This is designed for use by subclasses with storage backends.

   $srs->hash_create(@data)
       Returns a cryptographic hash of all data in @data. Any piece of data encoded into an address  which  must
       remain  inviolate should be hashed, so that when the address is reversed, we can check that this data has
       not been tampered with. You must provide at least one piece of data to this method (otherwise this system
       is both cryptographically weak and there may be collision problems with sender addresses).

   $srs->hash_verify($hash, @data)
       Verify that @data has not  been  tampered  with,  given  the  cryptographic  hash  previously  output  by
       $srs->hash_create();  Returns  1  or  undef.  All known secrets are tried in order to see if the hash was
       created with an old secret.

   $srs->set_secret($new, @old)
       Add a new secret to the rewriter. When an address is returned, all secrets are tried to see if  the  hash
       can  be  validated.  Don't  use  "foo",  "secret",  "password", "10downing", "god" or "wednesday" as your
       secret.

   $srs->get_secret()
       Return the list of secrets. These are secret. Don't publish them.

   $srs->separator()
       Return the initial separator, which follows the SRS tag. This is only used as the initial separator,  for
       the  convenience of administrators who wish to make srs0 and srs1 users on their mail servers and require
       to use + or - as the user delimiter. All other separators in the SRS address must be "=".

EXPORTS

       Given :all, this module exports the following variables.

       $SRSSEP
           The SRS separator. The choice of "=" as internal separator was fairly arbitrary. It cannot be any  of
           the following:

           / + Used in Base64.

           -   Used in domains.

           ! % Used in bang paths and source routing.

           :   Cannot be used in a Windows NT or Apple filename.

           ; | *
               Shell or regular expression metacharacters are probably to be avoided.

       $SRS0TAG
           The SRS0 tag.

       $SRS1TAG
           The SRS1 tag.

       $SRSTAG
           Deprecated, equal to $SRS0TAG.

       $SRSWRAP
           Deprecated, equal to $SRS1TAG.

       $SRSHASHLENGTH
           The default hash length for the SRS HMAC.

       $SRSMAXAGE
           The default expiry time for timestamps.

EXAMPLES OF USAGE

       For people wanting boilerplate and those less familiar with using Perl modules in larger applications.

   Forward Rewriting
               my $srs = new Mail::SRS(...);
               my $address = ...
               my $domain = ...
               my $srsaddress = eval { $srs->forward($srsaddress, $domain); };
               if ($@) {
                       # The rewrite failed
               }
               else {
                       # The rewrite succeeded
               }

   Reverse Rewriting
               my $srs = new Mail::SRS(...);
               my $srsaddress = ...
               my $address = eval { $srs->reverse($srsaddress); };
               if ($@) {
                       # The rewrite failed
               }
               else {
                       # The rewrite succeeded
               }

NOTES ON SRS

   Case Sensitivity
       RFC2821 states in section 2.4: "The local-part of a mailbox MUST BE treated as case sensitive. Therefore,
       SMTP  implementations  MUST  take care to preserve the case of mailbox local-parts. [...]  In particular,
       for some hosts the user "smith" is different  from  the  user  "Smith".   However,  exploiting  the  case
       sensitivity of mailbox local-parts impedes interoperability and is discouraged."

       SRS does not rely on case sensitivity in the local part. It uses base64 for encoding the hash, but allows
       a  case  insensitive  match,  making  this  approximately  equivalent to base36 at worst. It will issue a
       warning if it detects that a remote MTA has smashed case. The timestamp is encoded in base32.

   The 64 Billion Character Question
       RFC2821 section 4.5.3.1: Size limits and minimums:

               There are several objects that have required minimum/maximum
               sizes.  Every implementation MUST be able to receive objects
               of at least these sizes. Objects larger than these sizes
               SHOULD be avoided when possible. However, some Internet
               mail constructs such as encoded X.400 addresses [16] will
               often require larger objects: clients MAY attempt to transmit
               these, but MUST be prepared for a server to reject them if
               they cannot be handled by it. To the maximum extent possible,
               implementation techniques which impose no limits on the length
               of these objects should be used.

               local-part
                       The maximum total length of a user name or other
                       local-part is 64 characters.

       Clearly, by including 2 domain names and a local-part in the rewritten address, there is no way in  which
       SRS  can guarantee to stay under this limit. However, very few systems are known to actively enforce this
       limit, and those which become known to the developers will be listed here.

       Cisco: PIX MailGuard (firewall gimmick)
       WebShield [something] (firewall gimmick)

   Invalid SRS Addresses
       DO NOT MALFORMAT ADDRESSES. This is designed to be an interoperable format. Certain things  are  allowed,
       such  as  changing  the  semantics  of  the  hash or the timestamp. However, both of these fields must be
       present and separated by the SRS separator character "=". The purpose of this section  is  to  illustrate
       that  if a malicious party were to malformat an address, he would gain nothing by doing so, nor would the
       network suffer.

       The SRS protocol is predicated on the fact that the first forwarder provides a cryptographic  wrapper  on
       the  forward chain for sending mail to the original sender. So what happens if an SRS address is invalid,
       or faked by a spammer?

       The minimum parsing of existing SRS addresses is done at each hop. If an SRS0 address  is  not  valid  or
       badly formatted, it will not affect the operation of the system: the mail will go out along the forwarder
       chain, and return to the invalid or badly formatted address.

       If  the  spammer is not pretending to be the first hop, then he must somehow construct an SRS0 address to
       embed within his SRS1 address. The cryptographic checks on this SRS0  address  will  fail  at  the  first
       forwarder and the mail will be dropped.

       If  the  spammer  is pretending to be the first hop, then SPF should require that any bounces coming back
       return to his mail server, thus he wins nothing.

   Cryptographic Systems
       The hash in the address is designed to prevent the forging of reverse addresses by a spammer,  who  might
       then  use  the SRS host as a forwarder.  It may only be constructed or validated by a party who knows the
       secret key.

       The cryptographic system in the default implementation is not mandated.  Since nobody else ever needs  to
       interpret  the  hash,  it  is  reasonable to put any binary data into this field (subject to the possible
       constraint of case insensitive encoding).

       The SRS maintainers have attempted to provide  a  good  system.  It  satisfies  a  simple  set  of  basic
       requirements:  to  provide  unforgeability  of  SRS  addresses given that every MTA for a domain shares a
       secret key.  We prefer SHA1 over MD5 for political, rather than  practical  reasons.   (Anyone  disputing
       this statement must include an example of a practical weakness in their mail. We would love to see it.)

       If  you  find a weakness in our system, or you think you know of a better system, please tell us. If your
       requirements are different, you may override hash_create() and hash_verify()  to  implement  a  different
       system without adversely impacting the network, as long as your addresses still behave as SRS addresses.

   Extending Mail::SRS
       Write a subclass. You will probably want to override compile() and parse(). If you are more familiar with
       the  internals  of  SRS,  you  might want to override hash_create(), hash_verify(), timestamp_create() or
       timestamp_check().

CHANGELOG

   MINOR CHANGES since v0.29
       timestamp_check now explicitly smashes case when verifying. This means that the base used must be base32,
       NOT base64.
       hash_create and hash_verify now explicitly smash case when creating and verifying hashes. This does not
       have a significant cryptographic impact.

   MAJOR CHANGES since v0.27
       The SRS1 address format has changed to include cryptographic information. Existing deployments should
       consider setting AllowUnsafeSrs for MaxAge+1 days.

   MINOR CHANGES since v0.26
       parse() and compile() are explicitly specified to die() on error.

   MINOR CHANGES since v0.23
       Update BASE32 according to RFC3548.

   MINOR CHANGES since v0.21
       Dates are now encoded in base32.
       Case insensitive MAC validation is now allowed, but will issue a warning.

   MINOR CHANGES since v0.18
       $SRSTAG and $SRSWRAP are deprecated.
       Mail::SRS::Reversable is now Mail::SRS::Reversible
           This should not be a problem since people should not be using it!

       You must use $SRS0RE and $SRS1RE to detect SRS addresses.

   MAJOR CHANGES since v0.15
       The separator character is now "=".
       The cryptographic scheme is now HMAC with SHA1.
       Only a prefix of the MAC is used.

       This API is still a release candidate and should remain relatively stable.

BUGS

       Email address parsing for quoted addresses is not yet done properly.

       Case insensitive MAC validation should become an option.

TODO

       Write a testsuite for testing user-defined SRS implementations.

SEE ALSO

       Mail::SRS::Guarded,      Mail::SRS::DB,      Mail::SRS::Reversable,       "make       teach",       eg/*,
       http://www.anarres.org/projects/srs/

AUTHOR

               Shevek
               CPAN ID: SHEVEK
               cpan@anarres.org
               http://www.anarres.org/projects/

COPYRIGHT

       Copyright (c) 2004 Shevek. All rights reserved.

       This  program  is  free  software;  you can redistribute it and/or modify it under the same terms as Perl
       itself.

perl v5.36.0                                       2022-11-27                                     Mail::SRS(3pm)