看板初始化提交
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles CRAM-MD5 authentication.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Transport_Esmtp_Auth_CramMd5Authenticator implements Swift_Transport_Esmtp_Authenticator
|
||||
{
|
||||
/**
|
||||
* Get the name of the AUTH mechanism this Authenticator handles.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKeyword()
|
||||
{
|
||||
return 'CRAM-MD5';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to authenticate the user with $username and $password.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
|
||||
{
|
||||
try {
|
||||
$challenge = $agent->executeCommand("AUTH CRAM-MD5\r\n", array(334));
|
||||
$challenge = base64_decode(substr($challenge, 4));
|
||||
$message = base64_encode(
|
||||
$username.' '.$this->_getResponse($password, $challenge)
|
||||
);
|
||||
$agent->executeCommand(sprintf("%s\r\n", $message), array(235));
|
||||
|
||||
return true;
|
||||
} catch (Swift_TransportException $e) {
|
||||
$agent->executeCommand("RSET\r\n", array(250));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a CRAM-MD5 response from a server challenge.
|
||||
*
|
||||
* @param string $secret
|
||||
* @param string $challenge
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function _getResponse($secret, $challenge)
|
||||
{
|
||||
if (strlen($secret) > 64) {
|
||||
$secret = pack('H32', md5($secret));
|
||||
}
|
||||
|
||||
if (strlen($secret) < 64) {
|
||||
$secret = str_pad($secret, 64, chr(0));
|
||||
}
|
||||
|
||||
$k_ipad = substr($secret, 0, 64) ^ str_repeat(chr(0x36), 64);
|
||||
$k_opad = substr($secret, 0, 64) ^ str_repeat(chr(0x5C), 64);
|
||||
|
||||
$inner = pack('H32', md5($k_ipad.$challenge));
|
||||
$digest = md5($k_opad.$inner);
|
||||
|
||||
return $digest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles LOGIN authentication.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Transport_Esmtp_Auth_LoginAuthenticator implements Swift_Transport_Esmtp_Authenticator
|
||||
{
|
||||
/**
|
||||
* Get the name of the AUTH mechanism this Authenticator handles.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKeyword()
|
||||
{
|
||||
return 'LOGIN';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to authenticate the user with $username and $password.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
|
||||
{
|
||||
try {
|
||||
$agent->executeCommand("AUTH LOGIN\r\n", array(334));
|
||||
$agent->executeCommand(sprintf("%s\r\n", base64_encode($username)), array(334));
|
||||
$agent->executeCommand(sprintf("%s\r\n", base64_encode($password)), array(235));
|
||||
|
||||
return true;
|
||||
} catch (Swift_TransportException $e) {
|
||||
$agent->executeCommand("RSET\r\n", array(250));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* This authentication is for Exchange servers. We support version 1 & 2.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles NTLM authentication.
|
||||
*
|
||||
* @author Ward Peeters <ward@coding-tech.com>
|
||||
*/
|
||||
class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator
|
||||
{
|
||||
const NTLMSIG = "NTLMSSP\x00";
|
||||
const DESCONST = 'KGS!@#$%';
|
||||
|
||||
/**
|
||||
* Get the name of the AUTH mechanism this Authenticator handles.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKeyword()
|
||||
{
|
||||
return 'NTLM';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to authenticate the user with $username and $password.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
|
||||
{
|
||||
if (!function_exists('openssl_random_pseudo_bytes') || !function_exists('openssl_encrypt')) {
|
||||
throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.');
|
||||
}
|
||||
|
||||
if (!function_exists('bcmul')) {
|
||||
throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.');
|
||||
}
|
||||
|
||||
try {
|
||||
// execute AUTH command and filter out the code at the beginning
|
||||
// AUTH NTLM xxxx
|
||||
$response = base64_decode(substr(trim($this->sendMessage1($agent)), 4));
|
||||
|
||||
// extra parameters for our unit cases
|
||||
$timestamp = func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000'));
|
||||
$client = func_num_args() > 4 ? func_get_arg(4) : $this->getRandomBytes(8);
|
||||
|
||||
// Message 3 response
|
||||
$this->sendMessage3($response, $username, $password, $timestamp, $client, $agent);
|
||||
|
||||
return true;
|
||||
} catch (Swift_TransportException $e) {
|
||||
$agent->executeCommand("RSET\r\n", array(250));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function si2bin($si, $bits = 32)
|
||||
{
|
||||
$bin = null;
|
||||
if ($si >= -pow(2, $bits - 1) && ($si <= pow(2, $bits - 1))) {
|
||||
// positive or zero
|
||||
if ($si >= 0) {
|
||||
$bin = base_convert($si, 10, 2);
|
||||
// pad to $bits bit
|
||||
$bin_length = strlen($bin);
|
||||
if ($bin_length < $bits) {
|
||||
$bin = str_repeat('0', $bits - $bin_length).$bin;
|
||||
}
|
||||
} else {
|
||||
// negative
|
||||
$si = -$si - pow(2, $bits);
|
||||
$bin = base_convert($si, 10, 2);
|
||||
$bin_length = strlen($bin);
|
||||
if ($bin_length > $bits) {
|
||||
$bin = str_repeat('1', $bits - $bin_length).$bin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send our auth message and returns the response.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
*
|
||||
* @return string SMTP Response
|
||||
*/
|
||||
protected function sendMessage1(Swift_Transport_SmtpAgent $agent)
|
||||
{
|
||||
$message = $this->createMessage1();
|
||||
|
||||
return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), array(334));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all details of our response (message 2).
|
||||
*
|
||||
* @param string $response
|
||||
*
|
||||
* @return array our response parsed
|
||||
*/
|
||||
protected function parseMessage2($response)
|
||||
{
|
||||
$responseHex = bin2hex($response);
|
||||
$length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2;
|
||||
$offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2;
|
||||
$challenge = $this->hex2bin(substr($responseHex, 48, 16));
|
||||
$context = $this->hex2bin(substr($responseHex, 64, 16));
|
||||
$targetInfoH = $this->hex2bin(substr($responseHex, 80, 16));
|
||||
$targetName = $this->hex2bin(substr($responseHex, $offset, $length));
|
||||
$offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2;
|
||||
$targetInfoBlock = substr($responseHex, $offset);
|
||||
list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock);
|
||||
|
||||
return array(
|
||||
$challenge,
|
||||
$context,
|
||||
$targetInfoH,
|
||||
$targetName,
|
||||
$domainName,
|
||||
$serverName,
|
||||
$DNSDomainName,
|
||||
$DNSServerName,
|
||||
$this->hex2bin($targetInfoBlock),
|
||||
$terminatorByte,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the blob information in from message2.
|
||||
*
|
||||
* @param $block
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function readSubBlock($block)
|
||||
{
|
||||
// remove terminatorByte cause it's always the same
|
||||
$block = substr($block, 0, -8);
|
||||
|
||||
$length = strlen($block);
|
||||
$offset = 0;
|
||||
$data = array();
|
||||
while ($offset < $length) {
|
||||
$blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256;
|
||||
$offset += 8;
|
||||
$data[] = $this->hex2bin(substr($block, $offset, $blockLength * 2));
|
||||
$offset += $blockLength * 2;
|
||||
}
|
||||
|
||||
if (count($data) == 3) {
|
||||
$data[] = $data[2];
|
||||
$data[2] = '';
|
||||
}
|
||||
|
||||
$data[] = $this->createByte('00');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send our final message with all our data.
|
||||
*
|
||||
* @param string $response Message 1 response (message 2)
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $timestamp
|
||||
* @param string $client
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param bool $v2 Use version2 of the protocol
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true)
|
||||
{
|
||||
list($domain, $username) = $this->getDomainAndUsername($username);
|
||||
//$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter
|
||||
list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response);
|
||||
|
||||
if (!$v2) {
|
||||
// LMv1
|
||||
$lmResponse = $this->createLMPassword($password, $challenge);
|
||||
// NTLMv1
|
||||
$ntlmResponse = $this->createNTLMPassword($password, $challenge);
|
||||
} else {
|
||||
// LMv2
|
||||
$lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client);
|
||||
// NTLMv2
|
||||
$ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client);
|
||||
}
|
||||
|
||||
$message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse);
|
||||
|
||||
return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), array(235));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create our message 1.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createMessage1()
|
||||
{
|
||||
return self::NTLMSIG
|
||||
.$this->createByte('01') // Message 1
|
||||
.$this->createByte('0702'); // Flags
|
||||
}
|
||||
|
||||
/**
|
||||
* Create our message 3.
|
||||
*
|
||||
* @param string $domain
|
||||
* @param string $username
|
||||
* @param string $workstation
|
||||
* @param string $lmResponse
|
||||
* @param string $ntlmResponse
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse)
|
||||
{
|
||||
// Create security buffers
|
||||
$domainSec = $this->createSecurityBuffer($domain, 64);
|
||||
$domainInfo = $this->readSecurityBuffer(bin2hex($domainSec));
|
||||
$userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2);
|
||||
$userInfo = $this->readSecurityBuffer(bin2hex($userSec));
|
||||
$workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2);
|
||||
$workInfo = $this->readSecurityBuffer(bin2hex($workSec));
|
||||
$lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true);
|
||||
$lmInfo = $this->readSecurityBuffer(bin2hex($lmSec));
|
||||
$ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true);
|
||||
|
||||
return self::NTLMSIG
|
||||
.$this->createByte('03') // TYPE 3 message
|
||||
.$lmSec // LM response header
|
||||
.$ntlmSec // NTLM response header
|
||||
.$domainSec // Domain header
|
||||
.$userSec // User header
|
||||
.$workSec // Workstation header
|
||||
.$this->createByte('000000009a', 8) // session key header (empty)
|
||||
.$this->createByte('01020000') // FLAGS
|
||||
.$this->convertTo16bit($domain) // domain name
|
||||
.$this->convertTo16bit($username) // username
|
||||
.$this->convertTo16bit($workstation) // workstation
|
||||
.$lmResponse
|
||||
.$ntlmResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $timestamp Epoch timestamp in microseconds
|
||||
* @param string $client Random bytes
|
||||
* @param string $targetInfo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createBlob($timestamp, $client, $targetInfo)
|
||||
{
|
||||
return $this->createByte('0101')
|
||||
.$this->createByte('00')
|
||||
.$timestamp
|
||||
.$client
|
||||
.$this->createByte('00')
|
||||
.$targetInfo
|
||||
.$this->createByte('00');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get domain and username from our username.
|
||||
*
|
||||
* @example DOMAIN\username
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDomainAndUsername($name)
|
||||
{
|
||||
if (strpos($name, '\\') !== false) {
|
||||
return explode('\\', $name);
|
||||
}
|
||||
|
||||
if (false !== strpos($name, '@')) {
|
||||
list($user, $domain) = explode('@', $name);
|
||||
|
||||
return array($domain, $user);
|
||||
}
|
||||
|
||||
// no domain passed
|
||||
return array('', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create LMv1 response.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $challenge
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createLMPassword($password, $challenge)
|
||||
{
|
||||
// FIRST PART
|
||||
$password = $this->createByte(strtoupper($password), 14, false);
|
||||
list($key1, $key2) = str_split($password, 7);
|
||||
|
||||
$desKey1 = $this->createDesKey($key1);
|
||||
$desKey2 = $this->createDesKey($key2);
|
||||
|
||||
$constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false);
|
||||
|
||||
// SECOND PART
|
||||
list($key1, $key2, $key3) = str_split($constantDecrypt, 7);
|
||||
|
||||
$desKey1 = $this->createDesKey($key1);
|
||||
$desKey2 = $this->createDesKey($key2);
|
||||
$desKey3 = $this->createDesKey($key3);
|
||||
|
||||
return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create NTLMv1 response.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $challenge
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createNTLMPassword($password, $challenge)
|
||||
{
|
||||
// FIRST PART
|
||||
$ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false);
|
||||
list($key1, $key2, $key3) = str_split($ntlmHash, 7);
|
||||
|
||||
$desKey1 = $this->createDesKey($key1);
|
||||
$desKey2 = $this->createDesKey($key2);
|
||||
$desKey3 = $this->createDesKey($key3);
|
||||
|
||||
return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a normal timestamp to a tenth of a microtime epoch time.
|
||||
*
|
||||
* @param string $time
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCorrectTimestamp($time)
|
||||
{
|
||||
// Get our timestamp (tricky!)
|
||||
$time = number_format($time, 0, '.', ''); // save microtime to string
|
||||
$time = bcadd($time, '11644473600000', 0); // add epoch time
|
||||
$time = bcmul($time, 10000, 0); // tenths of a microsecond.
|
||||
|
||||
$binary = $this->si2bin($time, 64); // create 64 bit binary string
|
||||
$timestamp = '';
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$timestamp .= chr(bindec(substr($binary, -(($i + 1) * 8), 8)));
|
||||
}
|
||||
|
||||
return $timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create LMv2 response.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $username
|
||||
* @param string $domain
|
||||
* @param string $challenge NTLM Challenge
|
||||
* @param string $client Random string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createLMv2Password($password, $username, $domain, $challenge, $client)
|
||||
{
|
||||
$lmPass = '00'; // by default 00
|
||||
// if $password > 15 than we can't use this method
|
||||
if (strlen($password) <= 15) {
|
||||
$ntlmHash = $this->md4Encrypt($password);
|
||||
$ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
|
||||
|
||||
$lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client);
|
||||
}
|
||||
|
||||
return $this->createByte($lmPass, 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create NTLMv2 response.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $username
|
||||
* @param string $domain
|
||||
* @param string $challenge Hex values
|
||||
* @param string $targetInfo Hex values
|
||||
* @param string $timestamp
|
||||
* @param string $client Random bytes
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse
|
||||
*/
|
||||
protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client)
|
||||
{
|
||||
$ntlmHash = $this->md4Encrypt($password);
|
||||
$ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain));
|
||||
|
||||
// create blob
|
||||
$blob = $this->createBlob($timestamp, $client, $targetInfo);
|
||||
|
||||
$ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob);
|
||||
|
||||
return $ntlmv2Response.$blob;
|
||||
}
|
||||
|
||||
protected function createDesKey($key)
|
||||
{
|
||||
$material = array(bin2hex($key[0]));
|
||||
$len = strlen($key);
|
||||
for ($i = 1; $i < $len; ++$i) {
|
||||
list($high, $low) = str_split(bin2hex($key[$i]));
|
||||
$v = $this->castToByte(ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i));
|
||||
$material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte
|
||||
}
|
||||
$material[] = str_pad(substr(dechex($this->castToByte(ord($key[6]) << 1)), -2), 2, '0');
|
||||
|
||||
// odd parity
|
||||
foreach ($material as $k => $v) {
|
||||
$b = $this->castToByte(hexdec($v));
|
||||
$needsParity = (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5)
|
||||
^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2)
|
||||
^ $this->uRShift($b, 1)) & 0x01) == 0;
|
||||
|
||||
list($high, $low) = str_split($v);
|
||||
if ($needsParity) {
|
||||
$material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1);
|
||||
} else {
|
||||
$material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->hex2bin(implode('', $material));
|
||||
}
|
||||
|
||||
/** HELPER FUNCTIONS */
|
||||
|
||||
/**
|
||||
* Create our security buffer depending on length and offset.
|
||||
*
|
||||
* @param string $value Value we want to put in
|
||||
* @param int $offset start of value
|
||||
* @param bool $is16 Do we 16bit string or not?
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createSecurityBuffer($value, $offset, $is16 = false)
|
||||
{
|
||||
$length = strlen(bin2hex($value));
|
||||
$length = $is16 ? $length / 2 : $length;
|
||||
$length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2);
|
||||
|
||||
return $length.$length.$this->createByte(dechex($offset), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read our security buffer to fetch length and offset of our value.
|
||||
*
|
||||
* @param string $value Securitybuffer in hex
|
||||
*
|
||||
* @return array array with length and offset
|
||||
*/
|
||||
protected function readSecurityBuffer($value)
|
||||
{
|
||||
$length = floor(hexdec(substr($value, 0, 4)) / 256) * 2;
|
||||
$offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2;
|
||||
|
||||
return array($length, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast to byte java equivalent to (byte).
|
||||
*
|
||||
* @param int $v
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function castToByte($v)
|
||||
{
|
||||
return (($v + 128) % 256) - 128;
|
||||
}
|
||||
|
||||
/**
|
||||
* Java unsigned right bitwise
|
||||
* $a >>> $b.
|
||||
*
|
||||
* @param int $a
|
||||
* @param int $b
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function uRShift($a, $b)
|
||||
{
|
||||
if ($b == 0) {
|
||||
return $a;
|
||||
}
|
||||
|
||||
return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Right padding with 0 to certain length.
|
||||
*
|
||||
* @param string $input
|
||||
* @param int $bytes Length of bytes
|
||||
* @param bool $isHex Did we provided hex value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createByte($input, $bytes = 4, $isHex = true)
|
||||
{
|
||||
if ($isHex) {
|
||||
$byte = $this->hex2bin(str_pad($input, $bytes * 2, '00'));
|
||||
} else {
|
||||
$byte = str_pad($input, $bytes, "\x00");
|
||||
}
|
||||
|
||||
return $byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create random bytes.
|
||||
*
|
||||
* @param $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getRandomBytes($length)
|
||||
{
|
||||
$bytes = openssl_random_pseudo_bytes($length, $strong);
|
||||
|
||||
if (false !== $bytes && true === $strong) {
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
throw new RuntimeException('OpenSSL did not produce a secure random number.');
|
||||
}
|
||||
|
||||
/** ENCRYPTION ALGORITHMS */
|
||||
|
||||
/**
|
||||
* DES Encryption.
|
||||
*
|
||||
* @param string $value An 8-byte string
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function desEncrypt($value, $key)
|
||||
{
|
||||
// 1 == OPENSSL_RAW_DATA - but constant is only available as of PHP 5.4.
|
||||
return substr(openssl_encrypt($value, 'DES-ECB', $key, 1), 0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5 Encryption.
|
||||
*
|
||||
* @param string $key Encryption key
|
||||
* @param string $msg Message to encrypt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function md5Encrypt($key, $msg)
|
||||
{
|
||||
$blocksize = 64;
|
||||
if (strlen($key) > $blocksize) {
|
||||
$key = pack('H*', md5($key));
|
||||
}
|
||||
|
||||
$key = str_pad($key, $blocksize, "\0");
|
||||
$ipadk = $key ^ str_repeat("\x36", $blocksize);
|
||||
$opadk = $key ^ str_repeat("\x5c", $blocksize);
|
||||
|
||||
return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg))));
|
||||
}
|
||||
|
||||
/**
|
||||
* MD4 Encryption.
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see http://php.net/manual/en/ref.hash.php
|
||||
*/
|
||||
protected function md4Encrypt($input)
|
||||
{
|
||||
$input = $this->convertTo16bit($input);
|
||||
|
||||
return function_exists('hash') ? $this->hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTF-8 to UTF-16.
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function convertTo16bit($input)
|
||||
{
|
||||
return iconv('UTF-8', 'UTF-16LE', $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hex2bin replacement for < PHP 5.4.
|
||||
*
|
||||
* @param string $hex
|
||||
*
|
||||
* @return string Binary
|
||||
*/
|
||||
protected function hex2bin($hex)
|
||||
{
|
||||
if (function_exists('hex2bin')) {
|
||||
return hex2bin($hex);
|
||||
} else {
|
||||
return pack('H*', $hex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
protected function debug($message)
|
||||
{
|
||||
$message = bin2hex($message);
|
||||
$messageId = substr($message, 16, 8);
|
||||
echo substr($message, 0, 16)." NTLMSSP Signature<br />\n";
|
||||
echo $messageId." Type Indicator<br />\n";
|
||||
|
||||
if ($messageId == '02000000') {
|
||||
$map = array(
|
||||
'Challenge',
|
||||
'Context',
|
||||
'Target Information Security Buffer',
|
||||
'Target Name Data',
|
||||
'NetBIOS Domain Name',
|
||||
'NetBIOS Server Name',
|
||||
'DNS Domain Name',
|
||||
'DNS Server Name',
|
||||
'BLOB',
|
||||
'Target Information Terminator',
|
||||
);
|
||||
|
||||
$data = $this->parseMessage2($this->hex2bin($message));
|
||||
|
||||
foreach ($map as $key => $value) {
|
||||
echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."<br />\n";
|
||||
}
|
||||
} elseif ($messageId == '03000000') {
|
||||
$i = 0;
|
||||
$data[$i++] = substr($message, 24, 16);
|
||||
list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]);
|
||||
|
||||
$data[$i++] = substr($message, 40, 16);
|
||||
list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]);
|
||||
|
||||
$data[$i++] = substr($message, 56, 16);
|
||||
list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]);
|
||||
|
||||
$data[$i++] = substr($message, 72, 16);
|
||||
list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]);
|
||||
|
||||
$data[$i++] = substr($message, 88, 16);
|
||||
list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]);
|
||||
|
||||
$data[$i++] = substr($message, 104, 16);
|
||||
$data[$i++] = substr($message, 120, 8);
|
||||
$data[$i++] = substr($message, $targetOffset, $targetLength);
|
||||
$data[$i++] = substr($message, $userOffset, $userLength);
|
||||
$data[$i++] = substr($message, $workOffset, $workLength);
|
||||
$data[$i++] = substr($message, $lmOffset, $lmLength);
|
||||
$data[$i] = substr($message, $ntmlOffset, $ntmlLength);
|
||||
|
||||
$map = array(
|
||||
'LM Response Security Buffer',
|
||||
'NTLM Response Security Buffer',
|
||||
'Target Name Security Buffer',
|
||||
'User Name Security Buffer',
|
||||
'Workstation Name Security Buffer',
|
||||
'Session Key Security Buffer',
|
||||
'Flags',
|
||||
'Target Name Data',
|
||||
'User Name Data',
|
||||
'Workstation Name Data',
|
||||
'LM Response Data',
|
||||
'NTLM Response Data',
|
||||
);
|
||||
|
||||
foreach ($map as $key => $value) {
|
||||
echo $data[$key].' - '.$this->hex2bin($data[$key]).' ||| '.$value."<br />\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo '<br /><br />';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles PLAIN authentication.
|
||||
*
|
||||
* @author Chris Corbyn
|
||||
*/
|
||||
class Swift_Transport_Esmtp_Auth_PlainAuthenticator implements Swift_Transport_Esmtp_Authenticator
|
||||
{
|
||||
/**
|
||||
* Get the name of the AUTH mechanism this Authenticator handles.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKeyword()
|
||||
{
|
||||
return 'PLAIN';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to authenticate the user with $username and $password.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password)
|
||||
{
|
||||
try {
|
||||
$message = base64_encode($username.chr(0).$username.chr(0).$password);
|
||||
$agent->executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), array(235));
|
||||
|
||||
return true;
|
||||
} catch (Swift_TransportException $e) {
|
||||
$agent->executeCommand("RSET\r\n", array(250));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of SwiftMailer.
|
||||
* (c) 2004-2009 Chris Corbyn
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles XOAUTH2 authentication.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 587, 'tls')
|
||||
* ->setAuthMode('XOAUTH2')
|
||||
* ->setUsername('YOUR_EMAIL_ADDRESS')
|
||||
* ->setPassword('YOUR_ACCESS_TOKEN');
|
||||
* </code>
|
||||
*
|
||||
* @author xu.li<AthenaLightenedMyPath@gmail.com>
|
||||
*
|
||||
* @see https://developers.google.com/google-apps/gmail/xoauth2_protocol
|
||||
*/
|
||||
class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator
|
||||
{
|
||||
/**
|
||||
* Get the name of the AUTH mechanism this Authenticator handles.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthKeyword()
|
||||
{
|
||||
return 'XOAUTH2';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to authenticate the user with $email and $token.
|
||||
*
|
||||
* @param Swift_Transport_SmtpAgent $agent
|
||||
* @param string $email
|
||||
* @param string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token)
|
||||
{
|
||||
try {
|
||||
$param = $this->constructXOAuth2Params($email, $token);
|
||||
$agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", array(235));
|
||||
|
||||
return true;
|
||||
} catch (Swift_TransportException $e) {
|
||||
$agent->executeCommand("RSET\r\n", array(250));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the auth parameter.
|
||||
*
|
||||
* @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism
|
||||
*/
|
||||
protected function constructXOAuth2Params($email, $token)
|
||||
{
|
||||
return base64_encode("user=$email\1auth=Bearer $token\1\1");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user