1#
2# Samba LM/NT Hash Generating Library.
3# Slightly modified to fit in with Webmin
4#
5# Copyright(C) 2001 Benjamin Kuit <bj@it.uts.edu.au>
6#
7
8# Works out if local system has the module Digest::MD4, and uses it
9# if it does, otherwise uses ported version of the md4 algorithm
10# Performance is a lot better with Digest::MD4, so its recommended to
11# get Digest::MD4 installed if you intend to generate a lot of hashes
12# in a small amount of time.
13my $HaveDigestMD4;
14
15BEGIN {
16	$HaveDigestMD4 = 0;
17	if ( eval "require 'Digest/MD4.pm';" ) {
18		$HaveDigestMD4 = 1;
19	}
20}
21
22# lmhash PASSWORD
23# Generates lanman password hash for a given password, returns the hash
24#
25# Extracted and ported from SAMBA/source/libsmb/smbencrypt.c:nt_lm_owf_gen
26sub lmhash($) {
27	my ( $pass ) = @_;
28	my ( @p16 );
29
30	$pass = substr($pass||"",0,129);
31	$pass =~ tr/a-z/A-Z/;
32	$pass = substr($pass,0,14);
33	@p16 = E_P16($pass);
34	return join("", map {sprintf("%02X",$_);} @p16);
35}
36
37# nthash PASSWORD
38# Generates nt md4 password hash for a given password, returns the hash
39#
40# Extracted and ported from SAMBA/source/libsmb/smbencrypt.c:nt_lm_owf_gen
41sub nthash($) {
42	my ( $pass ) = @_;
43	my ( $hex );
44	my ( $digest );
45	$pass = substr($pass||"",0,128);
46	$pass =~ s/(.)/$1\000/sg;
47	$hex = "";
48	if ( $HaveDigestMD4 ) {
49		eval {
50			$digest = new Digest::MD4;
51			$digest->reset();
52			$digest->add($pass);
53			$hex = $digest->hexdigest();
54			$hex =~ tr/a-z/A-Z/;
55		};
56		$HaveDigestMD4 = 0 unless ( $hex );
57	}
58	$hex = sprintf("%02X"x16,mdfour($pass)) unless ( $hex );
59	return $hex;
60}
61
62# ntlmgen PASSWORD, LMHASH, NTHASH
63# Generate lanman and nt md4 password hash for given password, and assigns
64# values to arguments. Combined function of lmhash and nthash
65sub ntlmgen {
66	my ( $nthash, $lmhash );
67	$nthash = nthash($_[0]);
68	$lmhash = lmhash($_[0]);
69	if ( $#_ == 2 ) {
70		$_[1] = $lmhash;
71		$_[2] = $nthash;
72	}
73	return ( $lmhash, $nthash );
74}
75
76# Support functions
77# Ported from SAMBA/source/lib/md4.c:F,G and H respectfully
78sub F { my ( $X, $Y, $Z ) = @_; return ($X&$Y) | ((~$X)&$Z); }
79sub G { my ( $X, $Y, $Z) = @_; return ($X&$Y) | ($X&$Z) | ($Y&$Z); }
80sub H { my ($X, $Y, $Z) = @_; return $X^$Y^$Z; }
81
82# Needed? because perl seems to choke on overflowing when doing bitwise
83# operations on numbers larger than 32 bits. Well, it did on my machine =)
84sub add32 {
85	my ( @v ) = @_;
86	my ( $ret, @sum );
87	foreach ( @v ) {
88		$_ = [ ($_&0xffff0000)>>16, ($_&0xffff) ];
89	}
90	@sum = ();
91	foreach ( @v ) {
92		$sum[0] += $_->[0];
93		$sum[1] += $_->[1];
94	}
95	$sum[0] += ($sum[1]&0xffff0000)>>16;
96	$sum[1] &= 0xffff;
97	$sum[0] &= 0xffff;
98	$ret = ($sum[0]<<16) | $sum[1];
99	return $ret;
100}
101# Ported from SAMBA/source/lib/md4.c:lshift
102# Renamed to prevent clash with SAMBA/source/libsmb/smbdes.c:lshift
103sub md4lshift {
104	my ($x, $s) = @_;
105	$x &= 0xFFFFFFFF;
106	return (($x<<$s)&0xFFFFFFFF) | ($x>>(32-$s));
107}
108# Ported from SAMBA/source/lib/md4.c:ROUND1
109sub ROUND1 {
110	my($a,$b,$c,$d,$k,$s,@X) = @_;
111	$_[0] = md4lshift(add32($a,F($b,$c,$d),$X[$k]), $s);
112	return $_[0];
113}
114# Ported from SAMBA/source/lib/md4.c:ROUND2
115sub ROUND2 {
116	my ($a,$b,$c,$d,$k,$s,@X) = @_;
117	$_[0] = md4lshift(add32($a,G($b,$c,$d),$X[$k],0x5A827999), $s);
118	return $_[0];
119}
120# Ported from SAMBA/source/lib/md4.c:ROUND3
121sub ROUND3 {
122	my ($a,$b,$c,$d,$k,$s,@X) = @_;
123	$_[0] = md4lshift(add32($a,H($b,$c,$d),$X[$k],0x6ED9EBA1), $s);
124	return $_[0];
125}
126# Ported from SAMBA/source/lib/md4.c:mdfour64
127sub mdfour64 {
128	my ( $A, $B, $C, $D, @M ) = @_;
129	my ( $AA, $BB, $CC, $DD );
130	my ( @X );
131	@X = (map { $_?$_:0 } @M)[0..15];
132	$AA=$A; $BB=$B; $CC=$C; $DD=$D;
133        ROUND1($A,$B,$C,$D,  0,  3, @X);  ROUND1($D,$A,$B,$C,  1,  7, @X);
134        ROUND1($C,$D,$A,$B,  2, 11, @X);  ROUND1($B,$C,$D,$A,  3, 19, @X);
135        ROUND1($A,$B,$C,$D,  4,  3, @X);  ROUND1($D,$A,$B,$C,  5,  7, @X);
136        ROUND1($C,$D,$A,$B,  6, 11, @X);  ROUND1($B,$C,$D,$A,  7, 19, @X);
137        ROUND1($A,$B,$C,$D,  8,  3, @X);  ROUND1($D,$A,$B,$C,  9,  7, @X);
138        ROUND1($C,$D,$A,$B, 10, 11, @X);  ROUND1($B,$C,$D,$A, 11, 19, @X);
139        ROUND1($A,$B,$C,$D, 12,  3, @X);  ROUND1($D,$A,$B,$C, 13,  7, @X);
140        ROUND1($C,$D,$A,$B, 14, 11, @X);  ROUND1($B,$C,$D,$A, 15, 19, @X);
141        ROUND2($A,$B,$C,$D,  0,  3, @X);  ROUND2($D,$A,$B,$C,  4,  5, @X);
142        ROUND2($C,$D,$A,$B,  8,  9, @X);  ROUND2($B,$C,$D,$A, 12, 13, @X);
143        ROUND2($A,$B,$C,$D,  1,  3, @X);  ROUND2($D,$A,$B,$C,  5,  5, @X);
144        ROUND2($C,$D,$A,$B,  9,  9, @X);  ROUND2($B,$C,$D,$A, 13, 13, @X);
145        ROUND2($A,$B,$C,$D,  2,  3, @X);  ROUND2($D,$A,$B,$C,  6,  5, @X);
146        ROUND2($C,$D,$A,$B, 10,  9, @X);  ROUND2($B,$C,$D,$A, 14, 13, @X);
147        ROUND2($A,$B,$C,$D,  3,  3, @X);  ROUND2($D,$A,$B,$C,  7,  5, @X);
148        ROUND2($C,$D,$A,$B, 11,  9, @X);  ROUND2($B,$C,$D,$A, 15, 13, @X);
149        ROUND3($A,$B,$C,$D,  0,  3, @X);  ROUND3($D,$A,$B,$C,  8,  9, @X);
150        ROUND3($C,$D,$A,$B,  4, 11, @X);  ROUND3($B,$C,$D,$A, 12, 15, @X);
151        ROUND3($A,$B,$C,$D,  2,  3, @X);  ROUND3($D,$A,$B,$C, 10,  9, @X);
152        ROUND3($C,$D,$A,$B,  6, 11, @X);  ROUND3($B,$C,$D,$A, 14, 15, @X);
153        ROUND3($A,$B,$C,$D,  1,  3, @X);  ROUND3($D,$A,$B,$C,  9,  9, @X);
154        ROUND3($C,$D,$A,$B,  5, 11, @X);  ROUND3($B,$C,$D,$A, 13, 15, @X);
155        ROUND3($A,$B,$C,$D,  3,  3, @X);  ROUND3($D,$A,$B,$C, 11,  9, @X);
156        ROUND3($C,$D,$A,$B,  7, 11, @X);  ROUND3($B,$C,$D,$A, 15, 15, @X);
157	# We want to change the arguments, so assign them to $_[0] markers
158	# rather than to $A..$D
159	$_[0] = add32($A,$AA); $_[1] = add32($B,$BB);
160	$_[2] = add32($C,$CC); $_[3] = add32($D,$DD);
161	@X = map { 0 } (1..16);
162}
163
164# Ported from SAMBA/source/lib/md4.c:copy64
165sub copy64 {
166	my ( @in ) = @_;
167	my ( $i, @M );
168	for $i ( 0..15 ) {
169		$M[$i] = ($in[$i*4+3]<<24) | ($in[$i*4+2]<<16) |
170                        ($in[$i*4+1]<<8) | ($in[$i*4+0]<<0);
171	}
172	return @M;
173}
174# Ported from SAMBA/source/lib/md4.c:copy4
175sub copy4 {
176	my ( $x ) = @_;
177	my ( @out );
178        $out[0] = $x&0xFF;
179        $out[1] = ($x>>8)&0xFF;
180        $out[2] = ($x>>16)&0xFF;
181        $out[3] = ($x>>24)&0xFF;
182	@out = map { $_?$_:0 } @out;
183	return @out;
184}
185# Ported from SAMBA/source/lib/md4.c:mdfour
186sub mdfour {
187	my ( @in ) = unpack("C*",$_[0]);
188	my ( $b, @A, @M, @buf, @out );
189	$b = scalar @in * 8;
190	@A = ( 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 );
191	while (scalar @in > 64 ) {
192		@M = copy64( @in );
193		mdfour64( @A, @M );
194		@in = @in[64..$#in];
195	}
196	@buf = ( @in, 0x80, map {0} (1..128) )[0..127];
197	if ( scalar @in <= 55 ) {
198		@buf[56..59] = copy4( $b );
199		@M = copy64( @buf );
200		mdfour64( @A, @M );
201	}
202	else {
203		@buf[120..123] = copy4( $b );
204		@M = copy64( @buf );
205		mdfour64( @A, @M );
206		@M = copy64( @buf[64..$#buf] );
207		mdfour64( @A, @M );
208	}
209	@out[0..3] = copy4($A[0]);
210	@out[4..7] = copy4($A[1]);
211	@out[8..11] = copy4($A[2]);
212	@out[12..15] = copy4($A[3]);
213	return @out;
214}
215# Contants used in lanlam hash calculations
216# Ported from SAMBA/source/libsmb/smbdes.c:perm1[56]
217my @perm1 = (57, 49, 41, 33, 25, 17,  9,
218              1, 58, 50, 42, 34, 26, 18,
219             10,  2, 59, 51, 43, 35, 27,
220             19, 11,  3, 60, 52, 44, 36,
221             63, 55, 47, 39, 31, 23, 15,
222              7, 62, 54, 46, 38, 30, 22,
223             14,  6, 61, 53, 45, 37, 29,
224             21, 13,  5, 28, 20, 12,  4);
225# Ported from SAMBA/source/libsmb/smbdes.c:perm2[48]
226my @perm2 = (14, 17, 11, 24,  1,  5,
227              3, 28, 15,  6, 21, 10,
228             23, 19, 12,  4, 26,  8,
229             16,  7, 27, 20, 13,  2,
230             41, 52, 31, 37, 47, 55,
231             30, 40, 51, 45, 33, 48,
232             44, 49, 39, 56, 34, 53,
233             46, 42, 50, 36, 29, 32);
234# Ported from SAMBA/source/libsmb/smbdes.c:perm3[64]
235my @perm3 = (58, 50, 42, 34, 26, 18, 10,  2,
236             60, 52, 44, 36, 28, 20, 12,  4,
237             62, 54, 46, 38, 30, 22, 14,  6,
238             64, 56, 48, 40, 32, 24, 16,  8,
239             57, 49, 41, 33, 25, 17,  9,  1,
240             59, 51, 43, 35, 27, 19, 11,  3,
241             61, 53, 45, 37, 29, 21, 13,  5,
242             63, 55, 47, 39, 31, 23, 15,  7);
243# Ported from SAMBA/source/libsmb/smbdes.c:perm4[48]
244my @perm4 = (   32,  1,  2,  3,  4,  5,
245                 4,  5,  6,  7,  8,  9,
246                 8,  9, 10, 11, 12, 13,
247                12, 13, 14, 15, 16, 17,
248                16, 17, 18, 19, 20, 21,
249                20, 21, 22, 23, 24, 25,
250                24, 25, 26, 27, 28, 29,
251                28, 29, 30, 31, 32,  1);
252# Ported from SAMBA/source/libsmb/smbdes.c:perm5[32]
253my @perm5 = (      16,  7, 20, 21,
254                   29, 12, 28, 17,
255                    1, 15, 23, 26,
256                    5, 18, 31, 10,
257                    2,  8, 24, 14,
258                   32, 27,  3,  9,
259                   19, 13, 30,  6,
260                   22, 11,  4, 25);
261# Ported from SAMBA/source/libsmb/smbdes.c:perm6[64]
262my @perm6 =( 40,  8, 48, 16, 56, 24, 64, 32,
263             39,  7, 47, 15, 55, 23, 63, 31,
264             38,  6, 46, 14, 54, 22, 62, 30,
265             37,  5, 45, 13, 53, 21, 61, 29,
266             36,  4, 44, 12, 52, 20, 60, 28,
267             35,  3, 43, 11, 51, 19, 59, 27,
268             34,  2, 42, 10, 50, 18, 58, 26,
269             33,  1, 41,  9, 49, 17, 57, 25);
270# Ported from SAMBA/source/libsmb/smbdes.c:sc[16]
271my @sc = (1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1);
272# Ported from SAMBA/source/libsmb/smbdes.c:sbox[8][4][16]
273# Side note, I used cut and paste for all these numbers, I did NOT
274# type them all in =)
275my @sbox = ([[14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7],
276             [ 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8],
277             [ 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0],
278             [15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13]],
279            [[15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10],
280             [ 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5],
281             [ 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15],
282             [13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9]],
283            [[10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8],
284             [13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1],
285             [13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7],
286             [ 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12]],
287            [[ 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15],
288             [13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9],
289             [10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4],
290             [ 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14]],
291            [[ 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9],
292             [14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6],
293             [ 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14],
294             [11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3]],
295            [[12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11],
296             [10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8],
297             [ 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6],
298             [ 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13]],
299            [[ 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1],
300             [13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6],
301             [ 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2],
302             [ 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12]],
303            [[13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7],
304             [ 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2],
305             [ 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8],
306             [ 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11]]);
307
308# Ported from SAMBA/source/libsmb/smbdes.c:xor
309# Hack: Split arguments in half and then xor's first half of arguments to
310# second half of arguments. Probably proper way of doing this would
311# be to used referenced variables
312sub mxor {
313	my ( @in ) = @_;
314	my ( $i, $off, @ret );
315	$off = int($#in/2);
316	for $i ( 0..$off ) {
317		$ret[$i] = $in[$i] ^ $in[$i+$off+1];
318	}
319	return @ret;
320}
321
322# Ported from SAMBA/source/libsmb/smbdes.c:str_to_key
323sub str_to_key {
324	my ( @str ) = @_;
325	my ( $i, @key );
326	@str = map { $_?$_:0 } @str;
327	$key[0] = $str[0]>>1;
328        $key[1] = (($str[0]&0x01)<<6) | ($str[1]>>2);
329        $key[2] = (($str[1]&0x03)<<5) | ($str[2]>>3);
330        $key[3] = (($str[2]&0x07)<<4) | ($str[3]>>4);
331        $key[4] = (($str[3]&0x0F)<<3) | ($str[4]>>5);
332        $key[5] = (($str[4]&0x1F)<<2) | ($str[5]>>6);
333        $key[6] = (($str[5]&0x3F)<<1) | ($str[6]>>7);
334        $key[7] = $str[6]&0x7F;
335        for $i (0..7) {
336                $key[$i] = ($key[$i]<<1);
337        }
338	return @key;
339}
340# Ported from SAMBA/source/libsmb/smbdes.c:permute
341# Would probably be better to pass in by reference
342sub permute {
343	my ( @a ) = @_;
344	my ( $i, $n, @in, @p, @out );
345
346	# Last argument is the count of the perm values
347	$n = $a[$#a];
348	@in = @a[0..($#a-$n-1)];
349	@p = @_[($#a-$n)..($#a-1)];
350
351	for $i ( 0..($n-1) ) {
352		$out[$i] = $in[$p[$i]-1]?1:0;
353	}
354	return @out;
355}
356
357# Ported from SAMBA/source/libsmb/smbdes.c:lshift
358# Lazy shifting =)
359sub lshift {
360	my ( $count, @d ) = @_;
361	$count %= ($#d+1);
362	@d = (@d,@d)[$count..($#d+$count)];
363	return @d;
364}
365
366# Ported from SAMBA/source/libsmb/smbdes.c:dohash
367sub dohash {
368	my ( @a ) = @_;
369	my ( @in, @key, $forw, @pk1, @c, @d, @ki, @cd, $i, @pd1, @l, @r, @rl, @out );
370
371	@in = @a[0..63];
372	@key = @a[64..($#_-1)];
373	$forw = $a[$#a];
374
375	@pk1 = permute( @key, @perm1, 56 );
376
377	@c = @pk1[0..27];
378	@d = @pk1[28..55];
379
380	for $i ( 0..15 ) {
381		@c = lshift( $sc[$i], @c );
382		@d = lshift( $sc[$i], @d );
383
384		@cd = map { $_?1:0 } ( @c, @d );
385		$ki[$i] = [ permute( @cd, @perm2, 48 ) ];
386	}
387
388	@pd1 = permute( @in, @perm3, 64 );
389
390	@l = @pd1[0..31];
391	@r = @pd1[32..63];
392
393	for $i ( 0..15 ) {
394		my ( $j, $k, @b, @er, @erk, @cb, @pcb, @r2 );
395		@er = permute( @r, @perm4, 48 );
396		@erk = mxor(@er, @{ @ki[$forw?$i:(15-$i)] });
397
398		for $j ( 0..7 ) {
399			for $k ( 0..5 ) {
400				$b[$j][$k] = $erk[$j*6 + $k];
401			}
402		}
403		for $j ( 0..7 ) {
404			my ( $m, $n );
405			$m = ($b[$j][0]<<1) | $b[$j][5];
406			$n = ($b[$j][1]<<3) | ($b[$j][2]<<2) | ($b[$j][3]<<1) | $b[$j][4];
407
408			for $k ( 0..3 ) {
409				$b[$j][$k]=($sbox[$j][$m][$n] & (1<<(3-$k)))?1:0;
410			}
411		}
412		for $j ( 0..7 ) {
413			for $k ( 0..3 ) {
414				$cb[$j*4+$k]=$b[$j][$k];
415			}
416		}
417		@pcb = permute( @cb, @perm5, 32);
418		@r2 = mxor(@l,@pcb);
419		@l = @r[0..31];
420		@r = @r2[0..31];
421	}
422	@rl = ( @r, @l );
423	@out = permute( @rl, @perm6, 64 );
424	return @out;
425}
426
427# Ported from SAMBA/source/libsmb/smbdes.c:smbhash
428sub smbhash{
429	my ( @in, @key, $forw, @outb, @out, @inb, @keyb, @key2, $i );
430	@in = @_[0..7];
431	@key = @_[8..14];
432	$forw = $_[$#_];
433
434	@key2 = str_to_key(@key);
435
436	for $i ( 0..63 ) {
437		$inb[$i] = ( $in[$i/8] & (1<<(7-($i%8)))) ? 1:0;
438		$keyb[$i] = ( $key2[$i/8] & (1<<(7-($i%8)))) ? 1:0;
439		$outb[$i] = 0;
440	}
441	@outb = dohash(@inb,@keyb,$forw);
442	for $i ( 0..7 ) {
443		$out[$i] = 0;
444	}
445	for $i ( 0..64 ) {
446		if ( $outb[$i] )  {
447			$out[$i/8] |= (1<<(7-($i%8)));
448		}
449	}
450	return @out;
451}
452
453# Ported from SAMBA/source/libsmb/smbdes.c:E_P16
454sub E_P16 {
455	my ( @p16, @p14, @sp8 );
456	@p16 = map { 0 } (1..16);
457	@p14 = unpack("C*",$_[0]);
458	@sp8 = ( 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 );
459	@p16 = (smbhash(@sp8,@p14[0..6],1),smbhash(@sp8,@p14[7..13],1));
460	return @p16;
461}
462
4631;
464
465__END__
466
467=head1 NAME
468
469Crypt::SmbHash - Perl-only implementation of lanman and nt md4 hash functions, for use in Samba style smbpasswd entries
470
471=head1 SYNOPSIS
472
473  use Crypt::SmbHash;
474
475  ntlmgen SCALAR, LMSCALAR, NTSCALAR;
476
477=head1 DESCRIPTION
478
479This module generates Lanman and NT MD4 style password hashes, using
480perl-only code for portability. The module aids in the administration
481of Samba style systems.
482
483In the Samba distribution, authentication is referred to a private
484smbpasswd file. Entries have similar forms to the following:
485
486username:unixuid:LM:NT
487
488Where LM and NT are one-way password hashes of the same password.
489
490ntlmgen generates the hashes given in the first argument, and places
491the result in the second and third arguments.
492
493Example:
494To generate a smbpasswd entry:
495
496   #!/usr/local/bin/perl
497   use Crypt::SmbHash;
498   $username = $ARGV[0];
499   $password = $ARGV[1];
500   if ( !$password ) {
501           print "Not enough arguments\n";
502	   print "Usage: $0 username password\n";
503	   exit 1;
504   }
505   $uid = (getpwnam($username))[2];
506   my ($login,undef,$uid) = getpwnam($ARGV[0]);
507   ntlmgen $password, $lm, $nt;
508   printf "%s:%d:%s:%s:[%-11s]:LCT-%08X\n", $login, $uid, $lm, $nt, "U", time;
509
510
511ntlmgen returns returns the hash values in a list context, so the alternative
512method of using it is:
513
514   ( $lm, $nt ) = ntlmgen $password;
515
516The functions lmhash and nthash are used by ntlmgen to generate the
517hashes, and are available when requested:
518
519   use Crypt::SmbHash qw(lmhash nthash)
520   $lm = lmhash($pass);
521   $nt = nthash($pass);
522
523=head1 MD4
524
525The algorithm used in nthash requires the md4 algorithm. This algorithm
526is included in this module for completeness, but because it is written
527in all-perl code ( rather than in C ), it's not very quick.
528
529However if you have the Digest::MD4 module installed, Crypt::SmbHash will
530try to use that module instead, making it much faster.
531
532A simple test compared calling nthash without Digest::MD4 installed, and
533with, this showed that using nthash on a system with Digest::MD4 installed
534proved to be over 90 times faster.
535
536=head1 AUTHOR
537
538Ported from Samba by Benjamin Kuit <lt>bj@it.uts.edu.au<gt>.
539
540Samba is Copyright(C) Andrew Tridgell 1997-1998
541
542Because this module is a direct port of code within the Samba
543distribution, it follows the same license, that is:
544
545   This program is free software; you can redistribute it and/or modify
546   it under the terms of the GNU General Public License as published by
547   the Free Software Foundation; either version 2 of the License, or
548   (at your option) any later version.
549
550   This program is distributed in the hope that it will be useful,
551   but WITHOUT ANY WARRANTY; without even the implied warranty of
552   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
553   GNU General Public License for more details.
554
555=cut
556