1NAME 2 Mail::SRS - Interface to Sender Rewriting Scheme 3 4SYNOPSIS 5 use Mail::SRS; 6 my $srs = new Mail::SRS( 7 Secret => [ .... ], # scalar or array 8 MaxAge => 49, # days 9 HashLength => 4, # base64 characters: 4 x 6bits 10 HashMin => 4, # base64 characters 11 ); 12 my $srsaddress = $srs->forward($sender, $alias); 13 my $sender = $srs->reverse($srsaddress); 14 15DESCRIPTION 16 The Sender Rewriting Scheme preserves .forward functionality in an 17 SPF-compliant world. 18 19 SPF requires the SMTP client IP to match the envelope sender 20 (return-path). When a message is forwarded through an intermediate 21 server, that intermediate server may need to rewrite the return-path to 22 remain SPF compliant. If the message bounces, that intermediate server 23 needs to validate the bounce and forward the bounce to the original 24 sender. 25 26 SRS provides a convention for return-path rewriting which allows 27 multiple forwarding servers to compact the return-path. SRS also 28 provides an authentication mechanism to ensure that purported bounces 29 are not arbitrarily forwarded. 30 31 SRS is documented at http://spf.pobox.com/srs.html and many points about 32 the scheme are discussed at http://www.anarres.org/projects/srs/ 33 34 For a better understanding of this code and how it functions, please 35 read this document and run the interactive walkthrough in eg/simple.pl 36 in this distribution. To run this from the build directory, type "make 37 teach". 38 39METHODS 40 $srs = new Mail::SRS(...) 41 Construct a new Mail::SRS object and return it. Available parameters 42 are: 43 44 Secret => $string 45 A key for the cryptographic algorithms. This may be an array or a 46 single string. A string is promoted into an array of one element. 47 48 MaxAge 49 The maximum number of days for which a timestamp is considered 50 valid. After this time, the timestamp is invalid. 51 52 HashLength => $integer 53 The number of bytes of base64 encoded data to use for the 54 cryptographic hash. More is better, but makes for longer addresses 55 which might exceed the 64 character length suggested by RFC2821. 56 This defaults to 4, which gives 4 x 6 = 24 bits of cryptographic 57 information, which means that a spammer will have to make 2^24 58 attempts to guarantee forging an SRS address. 59 60 HashMin => $integer 61 The shortest hash which we will allow to pass authentication. Since 62 we allow any valid prefix of the full SHA1 HMAC to pass 63 authentication, a spammer might just suggest a hash of length 0. We 64 require at least HashMin characters, which must all be correct. 65 Naturally, this must be no greater than HashLength and will default 66 to HashLength unless otherwise specified. 67 68 Separator => $character 69 Specify the initial separator to use immediately after the SRS tag. 70 SRS uses the = separator throughout EXCEPT for the initial 71 separator, which may be any of + - or =. 72 73 Some MTAs already have a feature by which text after a + or - is 74 ignored for the purpose of identifying a local recipient. If the 75 initial separator is set to + or -, then an administrator may 76 process all SRS mails by creating users SRS0 and SRS1, and using 77 Mail::SRS in the default delivery rule for these users. 78 79 Some notes on the use and preservation of these separators are found 80 in the perldoc for Mail::SRS::Guarded. 81 82 AlwaysRewrite => $boolean 83 SRS rewriting is not performed by default if the alias host matches 84 the sender host, since it would be unnecessary to do so, and it 85 interacts badly with ezmlm if we do. Set this to true if you want 86 always to rewrite when requested to do so. 87 88 IgnoreTimestamp => $boolean 89 Consider all timestamps to be valid. Defaults to false. It is 90 STRONGLY recommended that this remain false. This parameter is 91 provided so that timestamps may be ignored temporarily after a 92 change in the timestamp format or encoding, until all timestamps in 93 the old encoding would have become invalid. Note that timestamps 94 still form a part of the cryptographic data when this is enabled. 95 96 AllowUnsafeSrs 97 This is a backwards compatibility option for an older version of the 98 protocol where SRS1 was not hash-protected. The 'reverse' method 99 will detect such addresses, and handle them properly. Deployments 100 upgrading from version <=0.27 to any version >=0.28 should enable 101 this for MaxAge+1 days. 102 103 When this option is enabled, all new addresses will be generated 104 with cryptographic protection. 105 106 Some subclasses require other parameters. See their documentation for 107 details. 108 109 $srsaddress = $srs->forward($sender, $alias) 110 Map a sender address into a new sender and a cryptographic cookie. 111 Returns an SRS address to use as the new sender. 112 113 There are alternative subclasses, some of which will return SRS 114 compliant addresses, some will simply return non-SRS but valid RFC821 115 addresses. See the interactive walkthrough for more information on this 116 ("make teach"). 117 118 $sender = $srs->reverse($srsaddress) 119 Reverse the mapping to get back the original address. Validates all 120 cryptographic and timestamp information. Returns the original sender 121 address. This method will die if the address cannot be reversed. 122 123 $srs->compile($sendhost, $senduser) 124 This method, designed to be overridden by subclasses, takes as 125 parameters the original host and user and must compile a new username 126 for the SRS transformed address. It is expected that this new username 127 will be joined on $SRSSEP, and will contain a hash generated from 128 $self->hash_create(...), and possibly a timestamp generated by 129 $self->timestamp_create(). 130 131 $srs->parse($srsuser) 132 This method, designed to be overridden by subclasses, takes an 133 SRS-transformed username as an argument, and must reverse the 134 transformation produced by compile(). It is required to verify any hash 135 and timestamp in the parsed data, using $self->hash_verify($hash, ...) 136 and $self->timestamp_check($timestamp). 137 138 $srs->timestamp_create([$time]) 139 Return a two character timestamp representing 'today', or $time if 140 given. $time is a Unix timestamp (seconds since the aeon). 141 142 This Perl function has been designed to be agnostic as to base, and in 143 practice, base32 is used since it can be reversed even if a remote MTA 144 smashes case (in violation of RFC2821 section 2.4). The agnosticism 145 means that the Perl uses division instead of rightshift, but in Perl 146 that doesn't matter. C implementors should implement this operation as a 147 right shift by 5. 148 149 $srs->timestamp_check($timestamp) 150 Return 1 if a timestamp is valid, undef otherwise. There are 4096 151 possible timestamps, used in a cycle. At any time, $srs->{MaxAge} 152 timestamps in this cycle are valid, the last one being today. A 153 timestamp from the future is not valid, neither is a timestamp from too 154 far into the past. Of course if you go far enough into the future, the 155 cycle wraps around, and there are valid timestamps again, but the 156 likelihood of a random timestamp being valid is 4096/$srs->{MaxAge}, 157 which is usually quite small: 1 in 132 by default. 158 159 $srs->time_check($time) 160 Similar to $srs->timestamp_check($timestamp), but takes a Unix time, and 161 checks that an alias created at that Unix time is still valid. This is 162 designed for use by subclasses with storage backends. 163 164 $srs->hash_create(@data) 165 Returns a cryptographic hash of all data in @data. Any piece of data 166 encoded into an address which must remain inviolate should be hashed, so 167 that when the address is reversed, we can check that this data has not 168 been tampered with. You must provide at least one piece of data to this 169 method (otherwise this system is both cryptographically weak and there 170 may be collision problems with sender addresses). 171 172 $srs->hash_verify($hash, @data) 173 Verify that @data has not been tampered with, given the cryptographic 174 hash previously output by $srs->hash_create(); Returns 1 or undef. All 175 known secrets are tried in order to see if the hash was created with an 176 old secret. 177 178 $srs->set_secret($new, @old) 179 Add a new secret to the rewriter. When an address is returned, all 180 secrets are tried to see if the hash can be validated. Don't use "foo", 181 "secret", "password", "10downing", "god" or "wednesday" as your secret. 182 183 $srs->get_secret() 184 Return the list of secrets. These are secret. Don't publish them. 185 186 $srs->separator() 187 Return the initial separator, which follows the SRS tag. This is only 188 used as the initial separator, for the convenience of administrators who 189 wish to make srs0 and srs1 users on their mail servers and require to 190 use + or - as the user delimiter. All other separators in the SRS 191 address must be "=". 192 193EXPORTS 194 Given :all, this module exports the following variables. 195 196 $SRSSEP 197 The SRS separator. The choice of "=" as internal separator was 198 fairly arbitrary. It cannot be any of the following: 199 200 / + Used in Base64. 201 202 - Used in domains. 203 204 ! % Used in bang paths and source routing. 205 206 : Cannot be used in a Windows NT or Apple filename. 207 208 ; | * 209 Shell or regular expression metacharacters are probably to be 210 avoided. 211 212 $SRS0TAG 213 The SRS0 tag. 214 215 $SRS1TAG 216 The SRS1 tag. 217 218 $SRSTAG 219 Deprecated, equal to $SRS0TAG. 220 221 $SRSWRAP 222 Deprecated, equal to $SRS1TAG. 223 224 $SRSHASHLENGTH 225 The default hash length for the SRS HMAC. 226 227 $SRSMAXAGE 228 The default expiry time for timestamps. 229 230NOTES ON SRS 231 Case Sensitivity 232 RFC2821 states in section 2.4: "The local-part of a mailbox MUST BE 233 treated as case sensitive. Therefore, SMTP implementations MUST take 234 care to preserve the case of mailbox local-parts. [...] In particular, 235 for some hosts the user "smith" is different from the user "Smith". 236 However, exploiting the case sensitivity of mailbox local-parts impedes 237 interoperability and is discouraged." 238 239 SRS does not rely on case sensitivity in the local part. It uses base64 240 for encoding the hash, but allows a case insensitive match, making this 241 approximately equivalent to base36 at worst. It will issue a warning if 242 it detects that a remote MTA has smashed case. The timestamp is encoded 243 in base32. 244 245 The 64 Billion Character Question 246 RFC2821 section 4.5.3.1: Size limits and minimums: 247 248 There are several objects that have required minimum/maximum 249 sizes. Every implementation MUST be able to receive objects 250 of at least these sizes. Objects larger than these sizes 251 SHOULD be avoided when possible. However, some Internet 252 mail constructs such as encoded X.400 addresses [16] will 253 often require larger objects: clients MAY attempt to transmit 254 these, but MUST be prepared for a server to reject them if 255 they cannot be handled by it. To the maximum extent possible, 256 implementation techniques which impose no limits on the length 257 of these objects should be used. 258 259 local-part 260 The maximum total length of a user name or other 261 local-part is 64 characters. 262 263 Clearly, by including 2 domain names and a local-part in the rewritten 264 address, there is no way in which SRS can guarantee to stay under this 265 limit. However, very few systems are known to actively enforce this 266 limit, and those which become known to the developers will be listed 267 here. 268 269 Cisco: PIX MailGuard (firewall gimmick) 270 WebShield [something] (firewall gimmick) 271 272 Invalid SRS Addresses 273 DO NOT MALFORMAT ADDRESSES. This is designed to be an interoperable 274 format. Certain things are allowed, such as changing the semantics of 275 the hash or the timestamp. However, both of these fields must be present 276 and separated by the SRS separator character "=". The purpose of this 277 section is to illustrate that if a malicious party were to malformat an 278 address, he would gain nothing by doing so, nor would the network 279 suffer. 280 281 The SRS protocol is predicated on the fact that the first forwarder 282 provides a cryptographic wrapper on the forward chain for sending mail 283 to the original sender. So what happens if an SRS address is invalid, or 284 faked by a spammer? 285 286 The minimum parsing of existing SRS addresses is done at each hop. If an 287 SRS0 address is not valid or badly formatted, it will not affect the 288 operation of the system: the mail will go out along the forwarder chain, 289 and return to the invalid or badly formatted address. 290 291 If the spammer is not pretending to be the first hop, then he must 292 somehow construct an SRS0 address to embed within his SRS1 address. The 293 cryptographic checks on this SRS0 address will fail at the first 294 forwarder and the mail will be dropped. 295 296 If the spammer is pretending to be the first hop, then SPF should 297 require that any bounces coming back return to his mail server, thus he 298 wins nothing. 299 300 Cryptographic Systems 301 The hash in the address is designed to prevent the forging of reverse 302 addresses by a spammer, who might then use the SRS host as a forwarder. 303 It may only be constructed or validated by a party who knows the secret 304 key. 305 306 The cryptographic system in the default implementation is not mandated. 307 Since nobody else ever needs to interpret the hash, it is reasonable to 308 put any binary data into this field (subject to the possible constraint 309 of case insensitive encoding). 310 311 The SRS maintainers have attempted to provide a good system. It 312 satisfies a simple set of basic requirements: to provide unforgeability 313 of SRS addresses given that every MTA for a domain shares a secret key. 314 We prefer SHA1 over MD5 for political, rather than practical reasons. 315 (Anyone disputing this statement must include an example of a practical 316 weakness in their mail. We would love to see it.) 317 318 If you find a weakness in our system, or you think you know of a better 319 system, please tell us. If your requirements are different, you may 320 override hash_create() and hash_verify() to implement a different system 321 without adversely impacting the network, as long as your addresses still 322 behave as SRS addresses. 323 324 Extending Mail::SRS 325 Write a subclass. You will probably want to override compile() and 326 parse(). If you are more familiar with the internals of SRS, you might 327 want to override hash_create(), hash_verify(), timestamp_create() or 328 timestamp_check(). 329 330CHANGELOG 331 MINOR CHANGES since v0.29 332 timestamp_check now explicitly smashes case when verifying. This means 333 that the base used must be base32, NOT base64. 334 hash_create and hash_verify now explicitly smash case when creating and 335 verifying hashes. This does not have a significant cryptographic impact. 336 337 MAJOR CHANGES since v0.27 338 The SRS1 address format has changed to include cryptographic 339 information. Existing deployments should consider setting AllowUnsafeSrs 340 for MaxAge+1 days. 341 342 MINOR CHANGES since v0.26 343 parse() and compile() are explicitly specified to die() on error. 344 345 MINOR CHANGES since v0.23 346 Update BASE32 according to RFC3548. 347 348 MINOR CHANGES since v0.21 349 Dates are now encoded in base32. 350 Case insensitive MAC validation is now allowed, but will issue a 351 warning. 352 353 MINOR CHANGES since v0.18 354 $SRSTAG and $SRSWRAP are deprecated. 355 Mail::SRS::Reversable is now Mail::SRS::Reversible 356 This should not be a problem since people should not be using it! 357 358 You must use $SRS0RE and $SRS1RE to detect SRS addresses. 359 360 MAJOR CHANGES since v0.15 361 The separator character is now "=". 362 The cryptographic scheme is now HMAC with SHA1. 363 Only a prefix of the MAC is used. 364 365 This API is still a release candidate and should remain relatively 366 stable. 367 368BUGS 369 Email address parsing for quoted addresses is not yet done properly. 370 371 Case insensitive MAC validation should become an option. 372 373TODO 374 Write a testsuite for testing user-defined SRS implementations. 375 376SEE ALSO 377 Mail::SRS::Guarded, Mail::SRS::DB, Mail::SRS::Reversable, "make teach", 378 eg/*, http://www.anarres.org/projects/srs/ 379 380AUTHOR 381 Shevek 382 CPAN ID: SHEVEK 383 cpan@anarres.org 384 http://www.anarres.org/projects/ 385 386COPYRIGHT 387 Copyright (c) 2004 Shevek. All rights reserved. 388 389 This program is free software; you can redistribute it and/or modify it 390 under the same terms as Perl itself. 391 392