1=head1 NAME 2 3Authen::Passphrase::LANManager - passphrases using the LAN Manager 4hash algorithm 5 6=head1 SYNOPSIS 7 8 use Authen::Passphrase::LANManager; 9 10 $ppr = Authen::Passphrase::LANManager->new( 11 hash_hex => "855c3697d9979e78ac404c4ba2c66533"); 12 13 $ppr = Authen::Passphrase::LANManager->new( 14 passphrase => "passphrase"); 15 16 $ppr = Authen::Passphrase::LANManager->from_rfc2307( 17 "{LANMAN}855c3697d9979e78ac404c4ba2c66533"); 18 19 $hash = $ppr->hash; 20 $hash_hex = $ppr->hash_hex; 21 22 $ppr0 = $ppr->first_half; 23 $ppr1 = $ppr->second_half; 24 25 if($ppr->match($passphrase)) { ... 26 27 $userPassword = $ppr->as_rfc2307; 28 29=head1 DESCRIPTION 30 31An object of this class encapsulates a passphrase hashed using 32the Microsoft LAN Manager hash function. This is a subclass of 33L<Authen::Passphrase>, and this document assumes that the reader is 34familiar with the documentation for that class. 35 36The hash algorithm can be used on up to fourteen Latin-1 characters of 37passphrase. First the passphrase is folded to uppercase, and zero-padded 38to fourteen bytes. Then it is split into two halves. Each seven-byte 39half is used as a 56-bit DES key, to encrypt the fixed plaintext block 40"KGS!@#$%". The eight-byte ciphertexts are concatenated to form the 41sixteen-byte hash. There is no salt. 42 43Because the two halves of the passphrase are hashed separately, it 44is possible to manipulate (e.g., crack) a half hash in isolation. 45See L<Authen::Passphrase::LANManagerHalf>. 46 47I<Warning:> Don't even think about using this seriously. It's an 48exceptionally weak design, flawed in pretty much every respect. 49 50=cut 51 52package Authen::Passphrase::LANManager; 53 54{ use 5.006; } 55use warnings; 56use strict; 57 58use Authen::Passphrase 0.003; 59use Authen::Passphrase::LANManagerHalf; 60use Carp qw(croak); 61 62our $VERSION = "0.008"; 63 64use parent "Authen::Passphrase"; 65 66=head1 CONSTRUCTORS 67 68=over 69 70=item Authen::Passphrase::LANManager->new(ATTR => VALUE, ...) 71 72Generates a new passphrase recogniser object using the LAN Manager 73hash algorithm. The following attributes may be given: 74 75=over 76 77=item B<hash> 78 79The hash, as a string of 16 bytes. 80 81=item B<hash_hex> 82 83The hash, as a string of 32 hexadecimal digits. 84 85=item B<passphrase> 86 87A passphrase that will be accepted. 88 89=back 90 91Either the hash or the passphrase must be given. 92 93=cut 94 95sub new { 96 my $class = shift; 97 my $self = bless({}, $class); 98 my $hash; 99 my $passphrase; 100 while(@_) { 101 my $attr = shift; 102 my $value = shift; 103 if($attr eq "hash") { 104 croak "hash specified redundantly" 105 if defined($hash) || defined($passphrase); 106 $value =~ m#\A[\x00-\xff]{16}\z# 107 or croak "not a valid LAN Manager hash"; 108 $hash = $value; 109 } elsif($attr eq "hash_hex") { 110 croak "hash specified redundantly" 111 if defined($hash) || defined($passphrase); 112 $value =~ m#\A[0-9A-Fa-f]{32}\z# 113 or croak "\"$value\" is not a valid ". 114 "hex LAN Manager hash"; 115 $hash = pack("H*", $value); 116 } elsif($attr eq "passphrase") { 117 croak "passphrase specified redundantly" 118 if defined($hash) || defined($passphrase); 119 $self->_passphrase_acceptable($value) 120 or croak "can't accept a passphrase exceeding". 121 " fourteen bytes"; 122 $passphrase = $value; 123 } else { 124 croak "unrecognised attribute `$attr'"; 125 } 126 } 127 if(defined $passphrase) { 128 $self->{first_half} = 129 Authen::Passphrase::LANManagerHalf 130 ->new(passphrase => substr($passphrase, 0, 7)); 131 $self->{second_half} = 132 Authen::Passphrase::LANManagerHalf 133 ->new(passphrase => 134 length($passphrase) > 7 ? 135 substr($passphrase, 7, 7) : 136 ""); 137 } elsif(defined $hash) { 138 $self->{first_half} = Authen::Passphrase::LANManagerHalf 139 ->new(hash => substr($hash, 0, 8)); 140 $self->{second_half} = Authen::Passphrase::LANManagerHalf 141 ->new(hash => substr($hash, 8, 8)); 142 } else { 143 croak "hash not specified"; 144 } 145 return $self; 146} 147 148=item Authen::Passphrase::LANManager->from_rfc2307(USERPASSWORD) 149 150Generates a LAN Manager passphrase recogniser from the supplied RFC2307 151encoding. The string must consist of "B<{LANMAN}>" (or its synonym 152"B<{LANM}>") followed by the hash in hexadecimal; case is ignored. 153 154=cut 155 156sub from_rfc2307 { 157 my($class, $userpassword) = @_; 158 if($userpassword =~ /\A\{(?i:lanm(?:an)?)\}/) { 159 $userpassword =~ /\A\{.*?\}([0-9a-fA-F]{32})\z/ 160 or croak "malformed {LANMAN} data"; 161 my $hash = $1; 162 return $class->new(hash_hex => $hash); 163 } 164 return $class->SUPER::from_rfc2307($userpassword); 165} 166 167=back 168 169=head1 METHODS 170 171=over 172 173=item $ppr->hash 174 175Returns the hash value, as a string of 16 bytes. 176 177=cut 178 179sub hash { 180 my($self) = @_; 181 return $self->{first_half}->hash.$self->{second_half}->hash; 182} 183 184=item $ppr->hash_hex 185 186Returns the hash value, as a string of 32 hexadecimal digits. 187 188=cut 189 190sub hash_hex { 191 my($self) = @_; 192 return unpack("H*", $self->hash); 193} 194 195=item $ppr->first_half 196 197Returns the hash of the first half of the passphrase, as an 198L<Authen::Passphrase::LANManagerHalf> passphrase recogniser. 199 200=cut 201 202sub first_half { 203 my($self) = @_; 204 return $self->{first_half}; 205} 206 207=item $ppr->second_half 208 209Returns the hash of the second half of the passphrase, as an 210L<Authen::Passphrase::LANManagerHalf> passphrase recogniser. 211 212=cut 213 214sub second_half { 215 my($self) = @_; 216 return $self->{second_half}; 217} 218 219=item $ppr->match(PASSPHRASE) 220 221=item $ppr->as_rfc2307 222 223These methods are part of the standard L<Authen::Passphrase> interface. 224 225=cut 226 227sub _passphrase_acceptable { 228 my($self, $passphrase) = @_; 229 return $passphrase =~ /\A[\x00-\xff]{0,14}\z/; 230} 231 232sub match { 233 my($self, $passphrase) = @_; 234 return $self->_passphrase_acceptable($passphrase) && 235 $self->{first_half}->match(substr($passphrase, 0, 7)) && 236 $self->{second_half}->match( 237 length($passphrase) > 7 ? 238 substr($passphrase, 7, 7) : 239 ""); 240} 241 242sub as_rfc2307 { 243 my($self) = @_; 244 return "{LANMAN}".$self->hash_hex; 245} 246 247=back 248 249=head1 SEE ALSO 250 251L<Authen::Passphrase>, 252L<Authen::Passphrase::LANManagerHalf>, 253L<Crypt::DES> 254 255=head1 AUTHOR 256 257Andrew Main (Zefram) <zefram@fysh.org> 258 259=head1 COPYRIGHT 260 261Copyright (C) 2006, 2007, 2009, 2010, 2012 262Andrew Main (Zefram) <zefram@fysh.org> 263 264=head1 LICENSE 265 266This module is free software; you can redistribute it and/or modify it 267under the same terms as Perl itself. 268 269=cut 270 2711; 272