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