Affichage des articles dont le libellé est NTLM. Afficher tous les articles
Affichage des articles dont le libellé est NTLM. Afficher tous les articles

vendredi 24 octobre 2008

Alternate way to Kerberos NTLM auth in pure PHP [EN]

Regarding to a recent post I put here about Kerberos and Apache, there is a way to replace Kerberos when the Active Directory cannot be properly configured to accept Kerberos connections. You can simulate the NTLM auth process with the browser by 6 steps in PHP :

function get_login() {

   /*
   step:  | type:
   -------|----------------|------------------------------------
   1      | C --> S        | GET ...
   -------|----------------|------------------------------------
   2      | C <-- S        | 401 Unauthorized
          |                | WWW-Authenticate: NTLM
   -------|----------------|------------------------------------
   3      | C --> S        | GET ...
          |                | Authorization: NTLM
          |                | <base64-encoded type-1-message>
   -------|----------------|------------------------------------
   4      | C <-- S        | 401 Unauthorized
          |                | WWW-Authenticate: NTLM
          |                | <base64-encoded type-2-message>
   -------|----------------|------------------------------------
   5      | C --> S        | GET ...
          |                | Authorization: NTLM <base64-encoded type-3-message>
   -------|----------------|------------------------------------
   6      | C <-- S        | 200 Ok
   -------|----------------|------------------------------------
   */

   $headers = apache_request_headers();
   if($headers['Authorization'] == NULL) { // step 1
       header( "HTTP/1.1 401 Unauthorized" ); // step 2
       header( "WWW-Authenticate: NTLM" );
       exit;
   };
   if(isset($headers['Authorization'])
         && substr($headers['Authorization'],0,5) == 'NTLM ') {
            // step 3 to 6
       $chaine=$headers['Authorization'];
       $chaine=substr($chaine, 5); // type1 message
       $chained64=base64_decode($chaine);
       if(ord($chained64{8}) == 1) { // step 3
           // check NTLM flag "0xb2",
          // offset 13 in type-1-message :
           if (ord($chained64[13]) != 178) {
                echo "Please use NTLM compatible browser";
                   return null;
           }
           $retAuth = "NTLMSSP";
           $retAuth .= chr(0).chr(2).chr(0).chr(0);
          $retAuth .= chr(0).chr(0).chr(0).chr(0);
           $retAuth .= chr(0).chr(40).chr(0).chr(0);
          $retAuth .= chr(0).chr(1).chr(130).chr(0);
           $retAuth .= chr(0).chr(0).chr(2).chr(2);
          $retAuth .= chr(2).chr(0).chr(0).chr(0);
           $retAuth .= chr(0).chr(0).chr(0).chr(0);
          $retAuth .= chr(0).chr(0).chr(0).chr(0).chr(0);

           $retAuth64 =base64_encode($retAuth);
           $retAuth64 = trim($retAuth64);
           header( "HTTP/1.1 401 Unauthorized" ); // step 4
           header( "WWW-Authenticate: NTLM $retAuth64" );
           exit;
       }
       else if(ord($chained64{8}) == 3) { // step 5
           $lenght_domain = (ord($chained64[31])*256 + ord($chained64[30]));
           $offset_domain = (ord($chained64[33])*256 + ord($chained64[32]));
           $domain = substr($chained64, $offset_domain, $lenght_domain);
           $lenght_login = (ord($chained64[39])*256 + ord($chained64[38]));
           $offset_login = (ord($chained64[41])*256 + ord($chained64[40]));
           $login = substr($chained64, $offset_login, $lenght_login);
           $lenght_host = (ord($chained64[47])*256 + ord($chained64[46]));
           $offset_host = (ord($chained64[49])*256 + ord($chained64[48]));
           $host = substr($chained64, $offset_host, $lenght_host);
       }

   }
   $login = preg_replace("/(.)(.)/","$1",$login);
   $domain = preg_replace("/(.)(.)/","$1",$domain);
   $login = strtolower($login);
   $domain = strtoupper($domain);
   return array($login,$domain); // step 6 : accept
}