2014-03-06 9 views
6

Perl (또는 아마도 XS 모듈)로 작성된 웹 서버에 대해 NTLM 인증을 구현하려고합니다. 이들 모두는하지만, 그들은 아무런 기능을 제공하지, 완벽하게 정상적으로 메시지를 생성하는 것Perl의 NTLM 인증

c -> s: GET 
s -> c: 401, WWW-Authenticate: NTLM 
c -> s: GET, Authorization: NTLM [Type1 Message] 
s -> c: 401, WWW-Authenticate: NTLM [Type2 Message] 
c -> s: GET, Authorization: NTLM [Type3 Message] 

IF s.Check([Type3 Message]): 
    s -> c: 200 
ELSE: 
    s -> c: 401 

내가 모두 Authen::Perl::NTLMAuthen::NTLM::HTTP를 사용한 타입 3 메시지를 생성하려면 : 나의 이해는 다음과 같은 방식으로 작동해야한다는 것입니다 Type3 메시지를 확인하십시오.

다음 단계는 Win32::IntAuth을 사용하여 NTLM 토큰을 인증하는 것입니다. 은 내가 곤경에 처한 곳입니다. 개발자 및 기타 정보 검색에서이 모듈은 NTLM 바이너리 토큰을 인증 할 수 있어야합니다.

이 모듈은 일부 Win32 API 호출 즉, AcquireCredntialsHandle, AcceptSecurityContext, CompleteAuthToken 및 ImpersonateSecurityContext를 래핑합니다.

불행하게도 내 모든 시도 횟수 NTLM 토큰을 인증 중 하나를 내 NTLM 토큰을 제안하는 저를 선도 SEC_E_INVALID_TOKEN 또는 SEC_E_INSUFFICIENT_MEMORY가 정확하지와 AcceptSecurityContext를에 실패했습니다. 아래는 내 방법을 보여주는 데 도움이되는 몇 가지 코드 스 니펫입니다.

# other code 
... 
if (not defined $headers->header('Authorization')) { 
    initHandshake($response); 
} else { 
    my $authHeader = $headers->header('Authorization'); 
    if ($authHeader =~ m/^NTLM\s(.+)$/i) { 
     my $message = $1; 
     if (length($message) == 56) { 
      handleType1($response, $message); 
     } else { 
      handleType3($response, $message); 
     } 
    } else { 
     printf "ERROR - Unable to pull out an NTLM message.\n"; 
     print $authHeader . "\n"; 
    } 
} 
... 
sub handleType3 { 
    my $response = shift(); 
    my $message = shift(); 
    print "handleType3 - ", $message, "\n"; 
    my $auth = Win32::IntAuth->new(debug => 1); 
    my $token = $auth->get_token_upn(decode_base64($message)) or die 
          "Couldn'timpersonate user, ", $auth->last_err_txt(); 
    print "Hurrargh. User ", $auth->get_username(), " authed!\n"; 
    $response->status(200); 
} 
.. 

전체 코드

여기에서 볼 수 있습니다 : 나는 (내가 거기에 버그를 가지고 있다고 생각합니다)에서 Win32 :: IntAuth을 bastardizing하여이 작업을 얻을 수 있었다 http://codepad.org/cpMWnFru

+1

나도이 작업을 수행하는 방법을 알고 싶습니다! –

답변

3

. 기본적으로 나는 2 형 토큰의 작성 중에 생성 된 부분 컨텍스트를 유지하지 않은,이 및 Win32 :: IntAuth에 오류가 있다는 사실 : 그것은 년후으로이 토큰 오류의 원인이 된

my $buf_size  = 4096; 
my $sec_inbuf = pack("L L P$buf_size", $buf_size, SECBUFFER_TOKEN, $token); 

가 따라서 토큰의 정확한 길이는 다음과 같습니다.

my $sec_inbuf = pack("L L P" . length($token), length($token), SECBUFFER_TOKEN, $token); 

올바른 결과를 나타냅니다.

앞의 코드

로 변경되었습니다

credentials = Win32->AcquireCredentialsHandle(...) 
challenge = Win32->AcceptSecurityContext(credentials, token, globalCtx ? globalCtx : 0, ...) 

는 희망이 비슷한 보트에있을 수 있습니다 사람들을 도와줍니다 :

... 
sub handleType1 { 
    my $response = shift(); 
    my $message = shift();        
    print "handleType1 - |", ${$message}, "|\n"; 
    my $challenge = acceptSecurityContext(${$message}); 
    ${$response}->status(401); 
    ${$response}->header("WWW-Authenticate" => "NTLM " . $challenge); 
} 
... 
sub handleType3 { 
    my $response = shift();    
    my $message = shift(); 
    print "handleType3 - ", ${$message}, "\n"; 
    if (acceptSecurityContext(${$message})) { 
     ${$response}->status(200); 
    } else { 
     ${$response}->status(401); 
    } 
} 
... 

AcceptSecurityContext를이 pseudoish 코드를 다음 기능입니다. 전체 데모를 원하시면 저에게 연락하십시오.