| 1 | #!/usr/bin/perl |
| 2 | # $Cambridge: exim/src/util/cramtest.pl,v 1.1 2004/10/07 10:39:03 ph10 Exp $ |
| 3 | |
| 4 | # This script is contributed by Vadim Vygonets to aid in debugging CRAM-MD5 |
| 5 | # authentication. |
| 6 | |
| 7 | # A patch was contributed by Jon Warbrick to upgrade it to use the Digest::MD5 |
| 8 | # module instead of the deprecated MD5 module. |
| 9 | |
| 10 | # The script prompts for three data values: a user name, a password, and the |
| 11 | # challenge as sent out by an SMTP server. The challenge is a base-64 string. |
| 12 | # It should be copied (cut-and-pasted) literally as the third data item. The |
| 13 | # output of the program is the base-64 string that is to be returned as the |
| 14 | # response to the challenge. Using the example in RFC 2195: |
| 15 | # |
| 16 | # User: tim |
| 17 | # Password: tanstaaftanstaaf |
| 18 | # Challenge: PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+ |
| 19 | # dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw |
| 20 | # |
| 21 | # The last line is what you you would send back to the server. |
| 22 | |
| 23 | |
| 24 | # Copyright (c) 2002 |
| 25 | # Vadim Vygonets <vadik-exim@vygo.net>. All rights reserved. |
| 26 | # Public domain is OK with me. |
| 27 | |
| 28 | use MIME::Base64; |
| 29 | use DIGEST::MD5; |
| 30 | |
| 31 | print "User: "; |
| 32 | chop($user = <>); |
| 33 | print "Password: "; |
| 34 | chop($passwd = <>); |
| 35 | print "Challenge: "; |
| 36 | chop($chal = <>); |
| 37 | $chal =~ s/^334 //; |
| 38 | |
| 39 | $context = new Digest::MD5; |
| 40 | if (length($passwd) > 64) { |
| 41 | $context->add($passwd); |
| 42 | $passwd = $context->digest(); |
| 43 | $context->reset(); |
| 44 | } |
| 45 | |
| 46 | @passwd = unpack("C*", pack("a64", $passwd)); |
| 47 | for ($i = 0; $i < 64; $i++) { |
| 48 | $pass_ipad[$i] = $passwd[$i] ^ 0x36; |
| 49 | $pass_opad[$i] = $passwd[$i] ^ 0x5C; |
| 50 | } |
| 51 | $context->add(pack("C64", @pass_ipad), decode_base64($chal)); |
| 52 | $digest = $context->digest(); |
| 53 | $context->reset(); |
| 54 | $context->add(pack("C64", @pass_opad), $digest); |
| 55 | $digest = $context->digest(); |
| 56 | |
| 57 | print encode_base64($user . " " . unpack("H*", $digest)); |
| 58 | |
| 59 | # End |