diff options
author | emkael <emkael@tlen.pl> | 2016-10-31 22:09:16 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2016-10-31 22:09:16 +0100 |
commit | 6181693f1d4b021da8a699c19f5323a17ffab1de (patch) | |
tree | ef5002fb9846c8d8405535d7afbf97ed19dd3371 /lib/phpmailer/extras/ntlm_sasl_client.php | |
parent | 7271d04e72aca36497f5cc04c5083c7c835cc6ca (diff) |
* PHPMailer library
Diffstat (limited to 'lib/phpmailer/extras/ntlm_sasl_client.php')
-rw-r--r-- | lib/phpmailer/extras/ntlm_sasl_client.php | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/phpmailer/extras/ntlm_sasl_client.php b/lib/phpmailer/extras/ntlm_sasl_client.php new file mode 100644 index 0000000..4a08561 --- /dev/null +++ b/lib/phpmailer/extras/ntlm_sasl_client.php @@ -0,0 +1,185 @@ +<?php +/* + * ntlm_sasl_client.php + * + * @(#) $Id: ntlm_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $ + * + */ + +define("SASL_NTLM_STATE_START", 0); +define("SASL_NTLM_STATE_IDENTIFY_DOMAIN", 1); +define("SASL_NTLM_STATE_RESPOND_CHALLENGE", 2); +define("SASL_NTLM_STATE_DONE", 3); +define("SASL_FAIL", -1); +define("SASL_CONTINUE", 1); + +class ntlm_sasl_client_class +{ + public $credentials = array(); + public $state = SASL_NTLM_STATE_START; + + public function initialize(&$client) + { + if (!function_exists($function = "mcrypt_encrypt") + || !function_exists($function = "mhash") + ) { + $extensions = array( + "mcrypt_encrypt" => "mcrypt", + "mhash" => "mhash" + ); + $client->error = "the extension " . $extensions[$function] . + " required by the NTLM SASL client class is not available in this PHP configuration"; + return (0); + } + return (1); + } + + public function ASCIIToUnicode($ascii) + { + for ($unicode = "", $a = 0; $a < strlen($ascii); $a++) { + $unicode .= substr($ascii, $a, 1) . chr(0); + } + return ($unicode); + } + + public function typeMsg1($domain, $workstation) + { + $domain_length = strlen($domain); + $workstation_length = strlen($workstation); + $workstation_offset = 32; + $domain_offset = $workstation_offset + $workstation_length; + return ( + "NTLMSSP\0" . + "\x01\x00\x00\x00" . + "\x07\x32\x00\x00" . + pack("v", $domain_length) . + pack("v", $domain_length) . + pack("V", $domain_offset) . + pack("v", $workstation_length) . + pack("v", $workstation_length) . + pack("V", $workstation_offset) . + $workstation . + $domain + ); + } + + public function NTLMResponse($challenge, $password) + { + $unicode = $this->ASCIIToUnicode($password); + $md4 = mhash(MHASH_MD4, $unicode); + $padded = $md4 . str_repeat(chr(0), 21 - strlen($md4)); + $iv_size = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB); + $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); + for ($response = "", $third = 0; $third < 21; $third += 7) { + for ($packed = "", $p = $third; $p < $third + 7; $p++) { + $packed .= str_pad(decbin(ord(substr($padded, $p, 1))), 8, "0", STR_PAD_LEFT); + } + for ($key = "", $p = 0; $p < strlen($packed); $p += 7) { + $s = substr($packed, $p, 7); + $b = $s . ((substr_count($s, "1") % 2) ? "0" : "1"); + $key .= chr(bindec($b)); + } + $ciphertext = mcrypt_encrypt(MCRYPT_DES, $key, $challenge, MCRYPT_MODE_ECB, $iv); + $response .= $ciphertext; + } + return $response; + } + + public function typeMsg3($ntlm_response, $user, $domain, $workstation) + { + $domain_unicode = $this->ASCIIToUnicode($domain); + $domain_length = strlen($domain_unicode); + $domain_offset = 64; + $user_unicode = $this->ASCIIToUnicode($user); + $user_length = strlen($user_unicode); + $user_offset = $domain_offset + $domain_length; + $workstation_unicode = $this->ASCIIToUnicode($workstation); + $workstation_length = strlen($workstation_unicode); + $workstation_offset = $user_offset + $user_length; + $lm = ""; + $lm_length = strlen($lm); + $lm_offset = $workstation_offset + $workstation_length; + $ntlm = $ntlm_response; + $ntlm_length = strlen($ntlm); + $ntlm_offset = $lm_offset + $lm_length; + $session = ""; + $session_length = strlen($session); + $session_offset = $ntlm_offset + $ntlm_length; + return ( + "NTLMSSP\0" . + "\x03\x00\x00\x00" . + pack("v", $lm_length) . + pack("v", $lm_length) . + pack("V", $lm_offset) . + pack("v", $ntlm_length) . + pack("v", $ntlm_length) . + pack("V", $ntlm_offset) . + pack("v", $domain_length) . + pack("v", $domain_length) . + pack("V", $domain_offset) . + pack("v", $user_length) . + pack("v", $user_length) . + pack("V", $user_offset) . + pack("v", $workstation_length) . + pack("v", $workstation_length) . + pack("V", $workstation_offset) . + pack("v", $session_length) . + pack("v", $session_length) . + pack("V", $session_offset) . + "\x01\x02\x00\x00" . + $domain_unicode . + $user_unicode . + $workstation_unicode . + $lm . + $ntlm + ); + } + + public function start(&$client, &$message, &$interactions) + { + if ($this->state != SASL_NTLM_STATE_START) { + $client->error = "NTLM authentication state is not at the start"; + return (SASL_FAIL); + } + $this->credentials = array( + "user" => "", + "password" => "", + "realm" => "", + "workstation" => "" + ); + $defaults = array(); + $status = $client->GetCredentials($this->credentials, $defaults, $interactions); + if ($status == SASL_CONTINUE) { + $this->state = SASL_NTLM_STATE_IDENTIFY_DOMAIN; + } + unset($message); + return ($status); + } + + public function step(&$client, $response, &$message, &$interactions) + { + switch ($this->state) { + case SASL_NTLM_STATE_IDENTIFY_DOMAIN: + $message = $this->TypeMsg1($this->credentials["realm"], $this->credentials["workstation"]); + $this->state = SASL_NTLM_STATE_RESPOND_CHALLENGE; + break; + case SASL_NTLM_STATE_RESPOND_CHALLENGE: + $ntlm_response = $this->NTLMResponse(substr($response, 24, 8), $this->credentials["password"]); + $message = $this->TypeMsg3( + $ntlm_response, + $this->credentials["user"], + $this->credentials["realm"], + $this->credentials["workstation"] + ); + $this->state = SASL_NTLM_STATE_DONE; + break; + case SASL_NTLM_STATE_DONE: + $client->error = "NTLM authentication was finished without success"; + return (SASL_FAIL); + default: + $client->error = "invalid NTLM authentication step state"; + return (SASL_FAIL); + } + return (SASL_CONTINUE); + } +} |