<?php
//require_once('curl.php');  // własna wersja biblioteki cURL (przydatna w przypadku braku takowej w systemie)

define('DEF_NTLM_MAX_EXECUTION_TIME_LIMIT',60);  // maksymalny czas pracy skryptu (1 minuta)
define('DEF_NTLM_COMMUNICATION_DELAY',100);      // opóźnienie w mikrosekundach podczas komunikacji z użyciem plików
define('DEF_NTLM_POST_ID_NAME','_NTLM_ID_');     // nazwa zmiennej przekazywanej w POST zawierającej id sesji

//define('DEF_NTLM_THIS_SCRIPT_URL','http://intranet/this/script/url/auth.php');  // należy podać właściwy adres URL skryptu, jeśli ten wyliczany przez funkcję ntlm_computeThisScriptUrl() jest nieprawidłowy


// rozpoznanie uruchomienia skryptu z poziomu przeglądarki (przez cURL) od uruchomienia go poprzez include/require
if (isset($_SERVER['REQUEST_URI']) && preg_match('/\b'.basename(__FILE__).'$/i',$_SERVER['REQUEST_URI']))
{
  global 
$sessid;

  function 
ntlm_proxyRequest($ch,$data)
  {
    return 
strrev($data);
  }

  function 
ntlm_onExit()
  {
    static 
$cleaned=false;
    if (
$cleaned) return;
    global 
$sessid;
    
ntlm_closeHandler($sessid);
    
$cleaned=true;
  }

  if (isset(
$_POST[DEF_NTLM_POST_ID_NAME]))
  {
    
set_time_limit(DEF_NTLM_MAX_EXECUTION_TIME_LIMIT);
    
register_shutdown_function('ntlm_onExit');
    
$sessid=$_POST[DEF_NTLM_POST_ID_NAME];
    while (
true)
    {
      
$data=ntlm_receiveData($sessid,1);
      if (!
$data) break;
      
$data=ntlm_proxyRequest($ch,$data);
      
ntlm_sendData($sessid,2,$data);
    }
  }
  else
    echo 
basename(__FILE__);
  exit;
}


function 
checkLogin($data)
{
  
$sessid=session_id();
  if (!
$sessid) die('Require session_start();');

  
ntlm_openHandler($sessid);
  
$ch=curl_init();
  
curl_setopt($ch,CURLOPT_URL,ntlm_computeThisScriptUrl());
  
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  
curl_setopt($ch,CURLOPT_FRESH_CONNECT,1);
  
curl_setopt($ch,CURLOPT_HEADER,0);
  
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Connection: close'));
  
curl_setopt($ch,CURLOPT_POST,1);
  
curl_setopt($ch,CURLOPT_POSTFIELDS,DEF_NTLM_POST_ID_NAME.'='.$sessid);
  
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,2);
  if (
defined('CURLOPT_TIMEOUT_MS'))
    
curl_setopt($ch,CURLOPT_TIMEOUT_MS,250);
  else
    
curl_setopt($ch,CURLOPT_TIMEOUT,1);
  
curl_exec($ch);
  
curl_close($ch);

  for (
$etap=0;$etap<3;$etap++)
  {
    echo 
"Sending <b><i>$data</i></b><br>";
    
ntlm_sendData($sessid,0,$data);
    
$data=ntlm_receiveData($sessid,3);
    echo 
"Receiving <b><i>$data</i></b><br><br>";
  }
  
ntlm_sendData($sessid,0,'');
  echo 
"Done.";
  return 
true;
}

function 
ntlm_getmicrotime()
{
  
$time=explode(' ',microtime(),2);
  return (float)
$time[1]+(float)$time[0];
}

function 
ntlm_computeThisScriptUrl()
{
  if (
defined('DEF_NTLM_THIS_SCRIPT_URL') && DEF_NTLM_THIS_SCRIPT_URL)
    return 
DEF_NTLM_THIS_SCRIPT_URL;
  
$dir=str_replace('\\','/',dirname($_SERVER['SCRIPT_FILENAME']));
  
$cwd=str_replace('\\','/',getcwd());
  
$auth=str_replace('\\','/',__FILE__);
  
$offset=strlen($_SERVER['SCRIPT_FILENAME'])-strlen($_SERVER['SCRIPT_NAME']);
  return 
"http".(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!='off'?'s':'')."://".$_SERVER['HTTP_HOST'].substr(ntlm_exchangeCommonSufix($cwd,$dir,$auth),$offset);
}

function 
ntlm_exchangeCommonSufix($str1,$str2,$str)
{
  
$len1=strlen($str1);
  
$len2=strlen($str2);
  while (
$len1 && $len2 && $str1[$len1-1]==$str2[$len2-1])
  {
    
$len1--; $len2--;
  }
  
$str1=substr($str1,0,$len1);
  
$str2=substr($str2,0,$len2);
  return 
str_replace($str1,$str2,$str);
}

function 
ntlm_utf16le2utf8($str)
{
  
$output='';
  
$len=strlen($str);
  for (
$i=0;$i<$len;)
  {
    
$word=ord(substr($str,$i++,1))|(ord(substr($str,$i++,1))<<8);
    if     (
$word<0x80)     $ch=chr($word);
    elseif (
$word<0x800)    $ch=chr($word>>6|0xc0).chr($word&0x3f|0x80);
    elseif (
$word<0x10000)  $ch=chr($word>>12|0xe0).chr($word>>6&0x3f|0x80).chr($word&0x3f|0x80);
    elseif (
$word<0x200000$ch=chr($word>>18|0xf0).chr($word>>12&0x3f|0x80).chr($word>>6&0x3f|0x80).chr($word&0x3f|0x80);
    
$output.=$ch;
  }
  return 
$output;
}

function 
ntlm_getRequestHeaders()
{
  
$str='';
  if (
function_exists('apache_request_headers'))
  {
    
$headers=apache_request_headers();
    foreach (
$headers as $key => $value)
      if (!
preg_match('/^(Host|Referer|Cookie)$/i',$key))
        
$str.="$key$value\n";
  }
  else
  {
    foreach (
$_SERVER as $key => $value)
      if (
substr($key,0,5)=='HTTP_')
      {
        
$key=str_replace(' ','-',ucwords(strtolower(str_replace('_',' ',substr($key,5)))));
        if (!
preg_match('/^(Host|Referer|Cookie)$/i',$key))
          
$str.="$key$value\n";
      }
  }
  return 
$str;
}

function 
ntlm_file_get_contents($file)
{
  if (!
file_exists($file)) return false;
  
$fp=fopen($file,'r');
  
$data=fread($fp,filesize($file));
  
fclose($fp);
  return 
$data;
}

function 
ntlm_file_put_contents($file,$data)
{
  
$fp=fopen($file,'w');
  
fwrite($fp,$data);
  
fclose($fp);
  return 
true;
}

function 
ntlm_openHandler($id)
{
  @
ntlm_file_put_contents(dirname(__FILE__).DIRECTORY_SEPARATOR.$id.'.lock',0);
}

function 
ntlm_closeHandler($id)
{
  @
unlink(dirname(__FILE__).DIRECTORY_SEPARATOR.$id.'.lock');
}

function 
ntlm_readAndDeleteFile($file)
{
  while (!
file_exists($file)) usleep(DEF_NTLM_COMMUNICATION_DELAY);
  
$data=@ntlm_file_get_contents($file);
  @
unlink($file);
  return 
$data;
}

function 
ntlm_sendData($id,$round,$data)
{
  
$id=dirname(__FILE__).DIRECTORY_SEPARATOR.$id;
  
$sem=$id.'.lock';
  while (
true)
  {  
    
$counter=@ntlm_file_get_contents($sem);
    if (
$counter==$round) break;
    
usleep(DEF_NTLM_COMMUNICATION_DELAY);
  }
  @
ntlm_file_put_contents($id.'.data',$data);
  @
ntlm_file_put_contents($sem,($round+1)&3);
}

function 
ntlm_receiveData($id,$round)
{
  
$id=dirname(__FILE__).DIRECTORY_SEPARATOR.$id;
  
$sem=$id.'.lock';
  while (
true)
  {  
    
$counter=@ntlm_file_get_contents($sem);
    if (
$counter==$round) break;
    
usleep(DEF_NTLM_COMMUNICATION_DELAY);
  }
  
$data=ntlm_readAndDeleteFile($id.'.data');
  @
ntlm_file_put_contents($sem,($round+1)&3);
  return 
$data;
}


// funkcja zapisująca nagłówki HTTP na potrzeby późniejszej analizy procesu uwierzytelnienia
function debug($msg)
{
  if (
defined('_DEBUG_'))
  {
    
$fp=fopen(dirname(__FILE__).DIRECTORY_SEPARATOR.'debug.txt','a');
    
$msg=ntlm_getmicrotime()."\t".$msg."|";
    
fwrite($fp,$msg);
    
fclose($fp);
  }
}
?>