Apache2-AuthenNTLM
view release on metacpan or search on metacpan
AuthenNTLM.pm view on Meta::CPAN
my ($self, $r) = @_ ;
if (!$self -> {smbhandle})
{
$self -> {lock} = undef ; # reset lock in case anything has gone wrong
$r->log_error("SMB Server connection not open in state 3 for " . $r -> uri) ;
return ;
}
my $rc ;
print STDERR "[$$] AuthenNTLM: Verify user $self->{username} via smb server\n" if ($debug) ;
if ($self -> {basic})
{
$rc = Authen::Smb::Valid_User_Auth ($self -> {smbhandle}, $self->{username}, $self -> {password}) ;
}
else
{
$rc = Authen::Smb::Valid_User_Auth ($self -> {smbhandle}, $self->{username}, $self -> {usernthash}, 1, $self->{userdomain}) ;
}
my $errno = Authen::Smb::SMBlib_errno ;
my $smberr = Authen::Smb::SMBlib_SMB_Error ;
Authen::Smb::Valid_User_Disconnect ($self -> {smbhandle}) if ($self -> {smbhandle}) ;
$self -> {smbhandle} = undef ;
$self -> {lock} = undef ;
if ($rc == &Authen::Smb::NTV_LOGON_ERROR)
{
$r->log_error("Wrong password/user (rc=$rc/$errno/$smberr): $self->{userdomain}\\$self->{username} for " . $r -> uri) ;
print STDERR "[$$] AuthenNTLM: rc = $rc ntlmhash = $self->{usernthash}\n" if ($debug) ;
return ;
}
if ($rc)
{
$r->log_reason("SMB Server error $rc/$errno/$smberr for " . $r -> uri) ;
return ;
}
return 1 ;
}
sub map_user
{
my ($self, $r) = @_ ;
if ($self -> {splitdomainprefix} == 1)
{
return lc("$self->{username}") ;
}
else
{
return lc("$self->{userdomain}\\$self->{username}") ;
}
}
sub substr_unicode
{
my ($data, $off, $len) = @_ ;
my $i = 0 ;
my $end = $off + $len ;
my $result = '' ;
for ($i = $off ; $i < $end ; $i += 2)
{# for now we simply ignore high order byte
$result .= substr ($data, $i, 1) ;
}
return $result ;
}
sub get_msg_data
{
my ($self, $r) = @_ ;
my $auth_line = $r->headers_in->{$r->proxyreq ? 'Proxy-Authorization' : 'Authorization'} ;
$self -> {ntlm} = 0 ;
$self -> {basic} = 0 ;
if ($debug)
{
$auth_line =~ /^(.*?)\s+/ ;
my $type = $1 ;
print STDERR "[$$] AuthenNTLM: Authorization Header "
. (defined($auth_line)?($debug > 1?$auth_line:$type):'<not given>') . "\n" if ($debug) ;
}
if ($self -> {authntlm} && ($auth_line =~ /^NTLM\s+(.*?)$/i))
{
$self -> {ntlm} = 1 ;
}
elsif ($self -> {authbasic} && ($auth_line =~ /^Basic\s+(.*?)$/i))
{
$self -> {basic} = 1 ;
}
else
{
return undef ;
}
my $data = MIME::Base64::decode($1) ;
if ($debug > 1)
{
my @out ;
for (my $i = 0; $i < length($data); $i++)
{
push @out, unpack('C', substr($data, $i, 1)) ;
}
print STDERR "[$$] AuthenNTLM: Got: " . join (' ', @out). "\n" ;
}
return $data ;
}
sub get_msg
{
my ($self, $r) = @_ ;
my $data = $self -> get_msg_data ($r) ;
return undef if (!$data) ;
if ($self -> {ntlm})
{
my ($protocol, $type) = unpack ('Z8C', $data) ;
return $self -> get_msg1 ($r, $data) if ($type == 1) ;
return $self -> get_msg3 ($r, $data) if ($type == 3) ;
return $type ;
}
elsif ($self -> {basic})
{
return $self -> get_basic ($r, $data) ;
}
return undef ;
}
sub get_msg1
{
my ($self, $r, $data) = @_ ;
my ($protocol, $type, $zero, $flags1, $flags2, $zero2, $dom_len, $x1, $dom_off, $x2, $host_len, $x3, $host_off, $x4) = unpack ('Z8Ca3CCa2vvvvvvvv', $data) ;
my $host = $host_off?substr ($data, $host_off, $host_len):'' ;
my $domain = $dom_off?substr ($data, $dom_off, $dom_len):'' ;
$self -> {domain} = $dom_len?$domain:$self -> {defaultdomain} ;
$self -> {host} = $host_len?$host:'' ;
$self -> {accept_unicode} = $flags1 & 0x01;
if ($debug)
{
my @flag1str;
foreach my $i ( sort keys %msgflags1 )
{
push @flag1str, $msgflags1{ $i } if $flags1 & $i;
}
my $flag1str = join( ",", @flag1str );
my @flag2str;
foreach my $i ( sort keys %msgflags2 )
{
push @flag2str, $msgflags2{ $i } if $flags2 & $i;
}
my $flag2str = join( ",", @flag2str );
print STDERR "[$$] AuthenNTLM: protocol=$protocol, type=$type, flags1=$flags1($flag1str), "
. "flags2=$flags2($flag2str), domain length=$dom_len, domain offset=$dom_off, "
. "host length=$host_len, host offset=$host_off, host=$host, domain=$domain\n" ;
}
return $type ;
}
sub set_msg2
{
my ($self, $r, $nonce) = @_ ;
my $charencoding = $self->{ accept_unicode } ? $invflags1{ NEGOTIATE_UNICODE } : $invflags1{ NEGOTIATE_OEM };
my $flags2 = $invflags2{ NEGOTIATE_ALWAYS_SIGN } | $invflags2{ NEGOTIATE_NTLM };
my $data = pack ('Z8Ca7vvCCa2a8a8', 'NTLMSSP', 2, '', 40, 0, $charencoding, $flags2, '', $nonce, '') ;
my $header = 'NTLM '. MIME::Base64::encode($data, '') ;
if ($debug)
{
if ($debug > 1)
{
my @out ;
for (my $i = 0; $i < length($data); $i++)
{
push @out, unpack('C', substr($data, $i, 1)) ;
}
print STDERR "[$$] AuthenNTLM: Send: " . join (' ', @out). "\n" ;
}
print STDERR "[$$] AuthenNTLM: charencoding = $charencoding\n";
print STDERR "[$$] AuthenNTLM: flags2 = $flags2\n";
print STDERR "[$$] AuthenNTLM: nonce=$nonce\n" if ($debug > 1);
print STDERR "[$$] AuthenNTLM: Send header: " . ($debug > 1?$header:'NTLM ...') . "\n" ;
}
return $header;
}
sub get_msg3
{
my ($self, $r, $data) = @_ ;
my ($protocol, $type, $zero,
$lm_len, $l1, $lm_off,
$nt_len, $l3, $nt_off,
$dom_len, $x1, $dom_off,
$user_len, $x3, $user_off,
$host_len, $x5, $host_off,
$msg_len
) = unpack ('Z8Ca3vvVvvVvvVvvVvvVv', $data) ;
my $lm = $lm_off ? substr ($data, $lm_off, $lm_len):'' ;
my $nt = $nt_off ? substr ($data, $nt_off, $nt_len):'' ;
my $user = $user_off ? ($self->{accept_unicode} ? substr_unicode ($data, $user_off, $user_len) : substr( $data, $user_off, $user_len ) ) :'' ;
my $host = $host_off ? ($self->{accept_unicode} ? substr_unicode ($data, $host_off, $host_len) : substr( $data, $host_off, $host_len ) ) :'' ;
my $domain = $dom_off ? ($self->{accept_unicode} ? substr_unicode ($data, $dom_off, $dom_len) : substr( $data, $dom_off, $dom_len ) ) :'' ;
$self -> {userdomain} = $dom_len?$domain:$self -> {defaultdomain} ;
$self -> {username} = $user ;
$self -> {usernthash} = $nt_len ? $nt : $lm;
if ($debug)
{
print STDERR "[$$] AuthenNTLM: protocol=$protocol, type=$type, user=$user, "
. "host=$host, domain=$domain, msg_len=$msg_len\n" ;
}
return $type ;
}
sub get_basic
{
my ($self, $r, $data) = @_ ;
($self -> {username}, $self -> {password}) = split (/:/, $data) ;
my ($domain, $username) = split (/\\|\//, $self -> {username}) ;
if ($username)
{
$self -> {domain} = $domain ;
$self -> {username} = $username ;
}
else
{
$self -> {domain} = $self -> {defaultdomain} ;
}
$self -> {userdomain} = $self -> {domain} ;
if ($debug)
{
print STDERR "[$$] AuthenNTLM: basic auth username = $self->{domain}\\$self->{username}\n" ;
}
return -1 ;
}
sub DESTROY
{
my ($self) = @_ ;
Authen::Smb::Valid_User_Disconnect ($self -> {smbhandle}) if ($self -> {smbhandle}) ;
}
sub handler : method
{
my ($class, $r) = @_ ;
my $type ;
my $nonce = '' ;
my $self ;
my $conn = $r -> connection ;
my $connhdr = $r -> headers_in -> {'Connection'} ;
( run in 1.281 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )