PageRenderTime 40ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Associates/SwiftMailer/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php

https://gitlab.com/fiesta-framework/Documentation
PHP | 700 lines | 380 code | 90 blank | 230 comment | 33 complexity | 7194dbddabe9f67d505efbb9f2a85f68 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * This authentication is for Exchange servers. We support version 1 & 2.
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * Handles NTLM authentication.
  13. *
  14. * @author Ward Peeters <ward@coding-tech.com>
  15. */
  16. class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator
  17. {
  18. const NTLMSIG = "NTLMSSP\x00";
  19. const DESCONST = "KGS!@#$%";
  20. /**
  21. * Get the name of the AUTH mechanism this Authenticator handles.
  22. *
  23. * @return string
  24. */
  25. public function getAuthKeyword()
  26. {
  27. return 'NTLM';
  28. }
  29. /**
  30. * Try to authenticate the user with $username and $password.
  31. *
  32. * @param Swift_Transport_SmtpAgent $agent
  33. * @param string $username
  34. * @param string $password
  35. *
  36. * @return bool
  37. */
  38. public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
  39. {
  40. if (!function_exists('mcrypt_module_open')) {
  41. throw new LogicException('The mcrypt functions need to be enabled to use the NTLM authenticator.');
  42. }
  43. if (!function_exists('openssl_random_pseudo_bytes')) {
  44. throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.');
  45. }
  46. if (!function_exists('bcmul')) {
  47. throw new LogicException('The BCMatch functions must be enabled to use the NTLM authenticator.');
  48. }
  49. try {
  50. // execute AUTH command and filter out the code at the beginning
  51. // AUTH NTLM xxxx
  52. $response = base64_decode(substr(trim($this->sendMessage1($agent)), 4));
  53. // extra parameters for our unit cases
  54. $timestamp = func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), "1000"));
  55. $client = func_num_args() > 4 ? func_get_arg(4) : $this->getRandomBytes(8);
  56. // Message 3 response
  57. $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent);
  58. return true;
  59. } catch (Swift_TransportException $e) {
  60. $agent->executeCommand("RSET\r\n", array(250));
  61. return false;
  62. }
  63. }
  64. protected function si2bin($si, $bits = 32)
  65. {
  66. $bin = null;
  67. if ($si >= -pow(2, $bits - 1) && ($si <= pow(2, $bits - 1))) {
  68. // positive or zero
  69. if ($si >= 0) {
  70. $bin = base_convert($si, 10, 2);
  71. // pad to $bits bit
  72. $bin_length = strlen($bin);
  73. if ($bin_length < $bits) {
  74. $bin = str_repeat("0", $bits - $bin_length).$bin;
  75. }
  76. } else {
  77. // negative
  78. $si = -$si - pow(2, $bits);
  79. $bin = base_convert($si, 10, 2);
  80. $bin_length = strlen($bin);
  81. if ($bin_length > $bits) {
  82. $bin = str_repeat("1", $bits - $bin_length).$bin;
  83. }
  84. }
  85. }
  86. return $bin;
  87. }
  88. /**
  89. * Send our auth message and returns the response
  90. *
  91. * @param Swift_Transport_SmtpAgent $agent
  92. * @return string SMTP Response
  93. */
  94. protected function sendMessage1(Swift_Transport_SmtpAgent $agent)
  95. {
  96. $message = $this->createMessage1();
  97. return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), array(334));
  98. }
  99. /**
  100. * Fetch all details of our response (message 2)
  101. *
  102. * @param string $response
  103. * @return array our response parsed
  104. */
  105. protected function parseMessage2($response)
  106. {
  107. $responseHex = bin2hex($response);
  108. $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2;
  109. $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2;
  110. $challenge = $this->hex2bin(substr($responseHex, 48, 16));
  111. $context = $this->hex2bin(substr($responseHex, 64, 16));
  112. $targetInfoH = $this->hex2bin(substr($responseHex, 80, 16));
  113. $targetName = $this->hex2bin(substr($responseHex, $offset, $length));
  114. $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2;
  115. $targetInfoBlock = substr($responseHex, $offset);
  116. list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock);
  117. return array(
  118. $challenge,
  119. $context,
  120. $targetInfoH,
  121. $targetName,
  122. $domainName,
  123. $serverName,
  124. $DNSDomainName,
  125. $DNSServerName,
  126. $this->hex2bin($targetInfoBlock),
  127. $terminatorByte,
  128. );
  129. }
  130. /**
  131. * Read the blob information in from message2
  132. *
  133. * @param $block
  134. * @return array
  135. */
  136. protected function readSubBlock($block)
  137. {
  138. // remove terminatorByte cause it's always the same
  139. $block = substr($block, 0, -8);
  140. $length = strlen($block);
  141. $offset = 0;
  142. $data = array();
  143. while ($offset < $length) {
  144. $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256;
  145. $offset += 8;
  146. $data[] = $this->hex2bin(substr($block, $offset, $blockLength * 2));
  147. $offset += $blockLength * 2;
  148. }
  149. if (count($data) == 3) {
  150. $data[] = $data[2];
  151. $data[2] = '';
  152. }
  153. $data[] = $this->createByte('00');
  154. return $data;
  155. }
  156. /**
  157. * Send our final message with all our data
  158. *
  159. * @param string $response Message 1 response (message 2)
  160. * @param string $username
  161. * @param string $password
  162. * @param string $timestamp
  163. * @param string $client
  164. * @param Swift_Transport_SmtpAgent $agent
  165. * @param bool $v2 Use version2 of the protocol
  166. * @return string
  167. */
  168. protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true)
  169. {
  170. list($domain, $username) = $this->getDomainAndUsername($username);
  171. //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter
  172. list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response);
  173. if (!$v2) {
  174. // LMv1
  175. $lmResponse = $this->createLMPassword($password, $challenge);
  176. // NTLMv1
  177. $ntlmResponse = $this->createNTLMPassword($password, $challenge);
  178. } else {
  179. // LMv2
  180. $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client);
  181. // NTLMv2
  182. $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client);
  183. }
  184. $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse);
  185. return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), array(235));
  186. }
  187. /**
  188. * Create our message 1
  189. *
  190. * @return string
  191. */
  192. protected function createMessage1()
  193. {
  194. return self::NTLMSIG
  195. .$this->createByte('01') // Message 1
  196. .$this->createByte('0702'); // Flags
  197. }
  198. /**
  199. * Create our message 3
  200. *
  201. * @param string $domain
  202. * @param string $username
  203. * @param string $workstation
  204. * @param string $lmResponse
  205. * @param string $ntlmResponse
  206. * @return string
  207. */
  208. protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse)
  209. {
  210. // Create security buffers
  211. $domainSec = $this->createSecurityBuffer($domain, 64);
  212. $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec));
  213. $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2);
  214. $userInfo = $this->readSecurityBuffer(bin2hex($userSec));
  215. $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2);
  216. $workInfo = $this->readSecurityBuffer(bin2hex($workSec));
  217. $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true);
  218. $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec));
  219. $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true);
  220. return self::NTLMSIG
  221. .$this->createByte('03') // TYPE 3 message
  222. .$lmSec // LM response header
  223. .$ntlmSec // NTLM response header
  224. .$domainSec // Domain header
  225. .$userSec // User header
  226. .$workSec // Workstation header
  227. .$this->createByte("000000009a", 8) // session key header (empty)
  228. .$this->createByte('01020000') // FLAGS
  229. .$this->convertTo16bit($domain) // domain name
  230. .$this->convertTo16bit($username) // username
  231. .$this->convertTo16bit($workstation) // workstation
  232. .$lmResponse
  233. .$ntlmResponse;
  234. }
  235. /**
  236. * @param string $timestamp Epoch timestamp in microseconds
  237. * @param string $client Random bytes
  238. * @param string $targetInfo
  239. * @return string
  240. */
  241. protected function createBlob($timestamp, $client, $targetInfo)
  242. {
  243. return $this->createByte('0101')
  244. .$this->createByte('00')
  245. .$timestamp
  246. .$client
  247. .$this->createByte('00')
  248. .$targetInfo
  249. .$this->createByte('00');
  250. }
  251. /**
  252. * Get domain and username from our username
  253. *
  254. * @example DOMAIN\username
  255. *
  256. * @param string $name
  257. * @return array
  258. */
  259. protected function getDomainAndUsername($name)
  260. {
  261. if (strpos($name, '\\') !== false) {
  262. return explode('\\', $name);
  263. }
  264. list($user, $domain) = explode('@', $name);
  265. return array($domain, $user);
  266. }
  267. /**
  268. * Create LMv1 response
  269. *
  270. * @param string $password
  271. * @param string $challenge
  272. * @return string
  273. */
  274. protected function createLMPassword($password, $challenge)
  275. {
  276. // FIRST PART
  277. $password = $this->createByte(strtoupper($password), 14, false);
  278. list($key1, $key2) = str_split($password, 7);
  279. $desKey1 = $this->createDesKey($key1);
  280. $desKey2 = $this->createDesKey($key2);
  281. $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false);
  282. // SECOND PART
  283. list($key1, $key2, $key3) = str_split($constantDecrypt, 7);
  284. $desKey1 = $this->createDesKey($key1);
  285. $desKey2 = $this->createDesKey($key2);
  286. $desKey3 = $this->createDesKey($key3);
  287. return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
  288. }
  289. /**
  290. * Create NTLMv1 response
  291. *
  292. * @param string $password
  293. * @param string $challenge
  294. * @return string
  295. */
  296. protected function createNTLMPassword($password, $challenge)
  297. {
  298. // FIRST PART
  299. $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false);
  300. list($key1, $key2, $key3) = str_split($ntlmHash, 7);
  301. $desKey1 = $this->createDesKey($key1);
  302. $desKey2 = $this->createDesKey($key2);
  303. $desKey3 = $this->createDesKey($key3);
  304. return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
  305. }
  306. /**
  307. * Convert a normal timestamp to a tenth of a microtime epoch time
  308. *
  309. * @param string $time
  310. * @return string
  311. */
  312. protected function getCorrectTimestamp($time)
  313. {
  314. // Get our timestamp (tricky!)
  315. bcscale(0);
  316. $time = number_format($time, 0, '.', ''); // save microtime to string
  317. $time = bcadd($time, "11644473600000"); // add epoch time
  318. $time = bcmul($time, 10000); // tenths of a microsecond.
  319. $binary = $this->si2bin($time, 64); // create 64 bit binary string
  320. $timestamp = "";
  321. for ($i = 0; $i < 8; $i++) {
  322. $timestamp .= chr(bindec(substr($binary, -(($i + 1) * 8), 8)));
  323. }
  324. return $timestamp;
  325. }
  326. /**
  327. * Create LMv2 response
  328. *
  329. * @param string $password
  330. * @param string $username
  331. * @param string $domain
  332. * @param string $challenge NTLM Challenge
  333. * @param string $client Random string
  334. * @return string
  335. */
  336. protected function createLMv2Password($password, $username, $domain, $challenge, $client)
  337. {
  338. $lmPass = '00'; // by default 00
  339. // if $password > 15 than we can't use this method
  340. if (strlen($password) <= 15) {
  341. $ntlmHash = $this->md4Encrypt($password);
  342. $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
  343. $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client);
  344. }
  345. return $this->createByte($lmPass, 24);
  346. }
  347. /**
  348. * Create NTLMv2 response
  349. *
  350. * @param string $password
  351. * @param string $username
  352. * @param string $domain
  353. * @param string $challenge Hex values
  354. * @param string $targetInfo Hex values
  355. * @param string $timestamp
  356. * @param string $client Random bytes
  357. * @return string
  358. * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse
  359. */
  360. protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client)
  361. {
  362. $ntlmHash = $this->md4Encrypt($password);
  363. $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
  364. // create blob
  365. $blob = $this->createBlob($timestamp, $client, $targetInfo);
  366. $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob);
  367. return $ntlmv2Response.$blob;
  368. }
  369. protected function createDesKey($key)
  370. {
  371. $material = array(bin2hex($key[0]));
  372. $len = strlen($key);
  373. for ($i = 1; $i < $len; $i++) {
  374. list($high, $low) = str_split(bin2hex($key[$i]));
  375. $v = $this->castToByte(ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i));
  376. $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte
  377. }
  378. $material[] = str_pad(substr(dechex($this->castToByte(ord($key[6]) << 1)), -2), 2, '0');
  379. // odd parity
  380. foreach ($material as $k => $v) {
  381. $b = $this->castToByte(hexdec($v));
  382. $needsParity = (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5)
  383. ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2)
  384. ^ $this->uRShift($b, 1)) & 0x01) == 0;
  385. list($high, $low) = str_split($v);
  386. if ($needsParity) {
  387. $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1);
  388. } else {
  389. $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe);
  390. }
  391. }
  392. return $this->hex2bin(implode('', $material));
  393. }
  394. /** HELPER FUNCTIONS */
  395. /**
  396. * Create our security buffer depending on length and offset
  397. *
  398. * @param string $value Value we want to put in
  399. * @param int $offset start of value
  400. * @param bool $is16 Do we 16bit string or not?
  401. * @return string
  402. */
  403. protected function createSecurityBuffer($value, $offset, $is16 = false)
  404. {
  405. $length = strlen(bin2hex($value));
  406. $length = $is16 ? $length / 2 : $length;
  407. $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2);
  408. return $length.$length.$this->createByte(dechex($offset), 4);
  409. }
  410. /**
  411. * Read our security buffer to fetch length and offset of our value
  412. *
  413. * @param string $value Securitybuffer in hex
  414. * @return array array with length and offset
  415. */
  416. protected function readSecurityBuffer($value)
  417. {
  418. $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2;
  419. $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2;
  420. return array($length, $offset);
  421. }
  422. /**
  423. * Cast to byte java equivalent to (byte)
  424. *
  425. * @param int $v
  426. * @return int
  427. */
  428. protected function castToByte($v)
  429. {
  430. return (($v + 128) % 256) - 128;
  431. }
  432. /**
  433. * Java unsigned right bitwise
  434. * $a >>> $b
  435. *
  436. * @param int $a
  437. * @param int $b
  438. * @return int
  439. */
  440. protected function uRShift($a, $b)
  441. {
  442. if ($b == 0) {
  443. return $a;
  444. }
  445. return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1));
  446. }
  447. /**
  448. * Right padding with 0 to certain length
  449. *
  450. * @param string $input
  451. * @param int $bytes Length of bytes
  452. * @param bool $isHex Did we provided hex value
  453. * @return string
  454. */
  455. protected function createByte($input, $bytes = 4, $isHex = true)
  456. {
  457. if ($isHex) {
  458. $byte = $this->hex2bin(str_pad($input, $bytes * 2, '00'));
  459. } else {
  460. $byte = str_pad($input, $bytes, "\x00");
  461. }
  462. return $byte;
  463. }
  464. /**
  465. * Create random bytes
  466. *
  467. * @param $length
  468. * @return string
  469. */
  470. protected function getRandomBytes($length)
  471. {
  472. $bytes = openssl_random_pseudo_bytes($length, $strong);
  473. if (false !== $bytes && true === $strong) {
  474. return $bytes;
  475. }
  476. throw new RuntimeException('OpenSSL did not produce a secure random number.');
  477. }
  478. /** ENCRYPTION ALGORITHMS */
  479. /**
  480. * DES Encryption
  481. *
  482. * @param string $value
  483. * @param string $key
  484. * @return string
  485. */
  486. protected function desEncrypt($value, $key)
  487. {
  488. $cipher = mcrypt_module_open(MCRYPT_DES, '', 'ecb', '');
  489. mcrypt_generic_init($cipher, $key, mcrypt_create_iv(mcrypt_enc_get_iv_size($cipher), MCRYPT_DEV_RANDOM));
  490. return mcrypt_generic($cipher, $value);
  491. }
  492. /**
  493. * MD5 Encryption
  494. *
  495. * @param string $key Encryption key
  496. * @param string $msg Message to encrypt
  497. * @return string
  498. */
  499. protected function md5Encrypt($key, $msg)
  500. {
  501. $blocksize = 64;
  502. if (strlen($key) > $blocksize) {
  503. $key = pack('H*', md5($key));
  504. }
  505. $key = str_pad($key, $blocksize, "\0");
  506. $ipadk = $key ^ str_repeat("\x36", $blocksize);
  507. $opadk = $key ^ str_repeat("\x5c", $blocksize);
  508. return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg))));
  509. }
  510. /**
  511. * MD4 Encryption
  512. *
  513. * @param string $input
  514. * @return string
  515. * @see http://php.net/manual/en/ref.hash.php
  516. */
  517. protected function md4Encrypt($input)
  518. {
  519. $input = $this->convertTo16bit($input);
  520. return function_exists('hash') ? $this->hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input);
  521. }
  522. /**
  523. * Convert UTF-8 to UTF-16
  524. *
  525. * @param string $input
  526. * @return string
  527. */
  528. protected function convertTo16bit($input)
  529. {
  530. return iconv('UTF-8', 'UTF-16LE', $input);
  531. }
  532. /**
  533. * Hex2bin replacement for < PHP 5.4
  534. * @param string $hex
  535. * @return string Binary
  536. */
  537. protected function hex2bin($hex)
  538. {
  539. if (function_exists('hex2bin')) {
  540. return hex2bin($hex);
  541. } else {
  542. return pack('H*', $hex);
  543. }
  544. }
  545. /**
  546. * @param string $message
  547. */
  548. protected function debug($message)
  549. {
  550. $message = bin2hex($message);
  551. $messageId = substr($message, 16, 8);
  552. echo substr($message, 0, 16)." NTLMSSP Signature<br />\n";
  553. echo $messageId." Type Indicator<br />\n";
  554. if ($messageId == "02000000") {
  555. $map = array(
  556. 'Challenge',
  557. 'Context',
  558. 'Target Information Security Buffer',
  559. 'Target Name Data',
  560. 'NetBIOS Domain Name',
  561. 'NetBIOS Server Name',
  562. 'DNS Domain Name',
  563. 'DNS Server Name',
  564. 'BLOB',
  565. 'Target Information Terminator',
  566. );
  567. $data = $this->parseMessage2($this->hex2bin($message));
  568. foreach ($map as $key => $value) {
  569. echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."<br />\n";
  570. }
  571. } elseif ($messageId == "03000000") {
  572. $i = 0;
  573. $data[$i++] = substr($message, 24, 16);
  574. list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]);
  575. $data[$i++] = substr($message, 40, 16);
  576. list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]);
  577. $data[$i++] = substr($message, 56, 16);
  578. list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]);
  579. $data[$i++] = substr($message, 72, 16);
  580. list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]);
  581. $data[$i++] = substr($message, 88, 16);
  582. list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]);
  583. $data[$i++] = substr($message, 104, 16);
  584. $data[$i++] = substr($message, 120, 8);
  585. $data[$i++] = substr($message, $targetOffset, $targetLength);
  586. $data[$i++] = substr($message, $userOffset, $userLength);
  587. $data[$i++] = substr($message, $workOffset, $workLength);
  588. $data[$i++] = substr($message, $lmOffset, $lmLength);
  589. $data[$i] = substr($message, $ntmlOffset, $ntmlLength);
  590. $map = array(
  591. 'LM Response Security Buffer',
  592. 'NTLM Response Security Buffer',
  593. 'Target Name Security Buffer',
  594. 'User Name Security Buffer',
  595. 'Workstation Name Security Buffer',
  596. 'Session Key Security Buffer',
  597. 'Flags',
  598. 'Target Name Data',
  599. 'User Name Data',
  600. 'Workstation Name Data',
  601. 'LM Response Data',
  602. 'NTLM Response Data',
  603. );
  604. foreach ($map as $key => $value) {
  605. echo $data[$key].' - '.$this->hex2bin($data[$key]).' ||| '.$value."<br />\n";
  606. }
  607. }
  608. echo "<br /><br />";
  609. }
  610. }