芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/public_html/avenida/views/Auth.zip
PK HqY2r SASL.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Client implementation of various SASL mechanisms * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('PEAR.php'); class Auth_SASL { /** * Factory class. Returns an object of the request * type. * * @param string $type One of: Anonymous * Plain * CramMD5 * DigestMD5 * SCRAM-* (any mechanism of the SCRAM family) * Types are not case sensitive */ public static function factory($type) { switch (strtolower($type)) { case 'anonymous': $filename = 'Auth/SASL/Anonymous.php'; $classname = 'Auth_SASL_Anonymous'; break; case 'login': $filename = 'Auth/SASL/Login.php'; $classname = 'Auth_SASL_Login'; break; case 'plain': $filename = 'Auth/SASL/Plain.php'; $classname = 'Auth_SASL_Plain'; break; case 'external': $filename = 'Auth/SASL/External.php'; $classname = 'Auth_SASL_External'; break; case 'crammd5': // $msg = 'Deprecated mechanism name. Use IANA-registered name: CRAM-MD5.'; // trigger_error($msg, E_USER_DEPRECATED); case 'cram-md5': $filename = 'Auth/SASL/CramMD5.php'; $classname = 'Auth_SASL_CramMD5'; break; case 'digestmd5': // $msg = 'Deprecated mechanism name. Use IANA-registered name: DIGEST-MD5.'; // trigger_error($msg, E_USER_DEPRECATED); case 'digest-md5': // $msg = 'DIGEST-MD5 is a deprecated SASL mechanism as per RFC-6331. Using it could be a security risk.'; // trigger_error($msg, E_USER_NOTICE); $filename = 'Auth/SASL/DigestMD5.php'; $classname = 'Auth_SASL_DigestMD5'; break; default: $scram = '/^SCRAM-(.{1,9})$/i'; if (preg_match($scram, $type, $matches)) { $hash = $matches[1]; $filename = dirname(__FILE__) .'/SASL/SCRAM.php'; $classname = 'Auth_SASL_SCRAM'; $parameter = $hash; break; } return PEAR::raiseError('Invalid SASL mechanism type'); break; } require_once($filename); if (isset($parameter)) $obj = new $classname($parameter); else $obj = new $classname(); return $obj; } } ?> PK HqY= = SASL/Plain.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of PLAIN SASL mechanism * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Plain extends Auth_SASL_Common { /** * Returns PLAIN response * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $authzid Autorization id * @return string PLAIN Response */ function getResponse($authcid, $pass, $authzid = '') { return $authzid . chr(0) . $authcid . chr(0) . $pass; } } ?> PK HqYvRr, , SASL/External.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of EXTERNAL SASL mechanism * * @author Christoph Schulz
* @access public * @version 1.0.3 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_External extends Auth_SASL_Common { /** * Returns EXTERNAL response * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $authzid Autorization id * @return string EXTERNAL Response */ function getResponse($authcid, $pass, $authzid = '') { return $authzid; } } ?> PK HqY%ׅtg! g! SASL/DigestMD5.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of DIGEST-MD5 SASL mechanism * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_DigestMD5 extends Auth_SASL_Common { /** * Provides the (main) client response for DIGEST-MD5 * requires a few extra parameters than the other * mechanisms, which are unavoidable. * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $challenge The digest challenge sent by the server * @param string $hostname The hostname of the machine you're connecting to * @param string $service The servicename (eg. imap, pop, acap etc) * @param string $authzid Authorization id (username to proxy as) * @return string The digest response (NOT base64 encoded) * @access public */ function getResponse($authcid, $pass, $challenge, $hostname, $service, $authzid = '') { $challenge = $this->_parseChallenge($challenge); $authzid_string = ''; if ($authzid != '') { $authzid_string = ',authzid="' . $authzid . '"'; } if (!empty($challenge)) { $cnonce = $this->_getCnonce(); $digest_uri = sprintf('%s/%s', $service, $hostname); $response_value = $this->_getResponseValue($authcid, $pass, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $authzid); if ($challenge['realm']) { return sprintf('username="%s",realm="%s"' . $authzid_string . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['realm'], $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); } else { return sprintf('username="%s"' . $authzid_string . ',nonce="%s",cnonce="%s",nc=00000001,qop=auth,digest-uri="%s",response=%s,maxbuf=%d', $authcid, $challenge['nonce'], $cnonce, $digest_uri, $response_value, $challenge['maxbuf']); } } else { return PEAR::raiseError('Invalid digest challenge'); } } /** * Parses and verifies the digest challenge* * * @param string $challenge The digest challenge * @return array The parsed challenge as an assoc * array in the form "directive => value". * @access private */ function _parseChallenge($challenge) { $tokens = array(); while (preg_match('/^([a-z-]+)=("[^"]+(? PK HqY< O O SASL/Login.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * This is technically not a SASL mechanism, however * it's used by Net_Sieve, Net_Cyrus and potentially * other protocols , so here is a good place to abstract * it. * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Login extends Auth_SASL_Common { /** * Pseudo SASL LOGIN mechanism * * @param string $user Username * @param string $pass Password * @return string LOGIN string */ function getResponse($user, $pass) { return sprintf('LOGIN %s %s', $user, $pass); } } ?>PK HqYP(~T T SASL/CramMD5.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of CRAM-MD5 SASL mechanism * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_CramMD5 extends Auth_SASL_Common { /** * Implements the CRAM-MD5 SASL mechanism * This DOES NOT base64 encode the return value, * you will need to do that yourself. * * @param string $user Username * @param string $pass Password * @param string $challenge The challenge supplied by the server. * this should be already base64_decoded. * * @return string The string to pass back to the server, of the form * "
". This is NOT base64_encoded. */ function getResponse($user, $pass, $challenge) { return $user . ' ' . $this->_HMAC_MD5($pass, $challenge); } } ?>PK HqYќ0 0 SASL/SCRAM.phpnu [ * @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_SCRAM extends Auth_SASL_Common { /** * Construct a SCRAM-H client where 'H' is a cryptographic hash function. * * @param string $hash The name cryptographic hash function 'H' as registered by IANA in the "Hash Function Textual * Names" registry. * @link http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml "Hash Function Textual * Names" * format of core PHP hash function. * @access public */ function __construct($hash) { // Though I could be strict, I will actually also accept the naming used in the PHP core hash framework. // For instance "sha1" is accepted, while the registered hash name should be "SHA-1". $hash = strtolower($hash); $hashes = array('md2' => 'md2', 'md5' => 'md5', 'sha-1' => 'sha1', 'sha1' => 'sha1', 'sha-224' > 'sha224', 'sha224' > 'sha224', 'sha-256' => 'sha256', 'sha256' => 'sha256', 'sha-384' => 'sha384', 'sha384' => 'sha384', 'sha-512' => 'sha512', 'sha512' => 'sha512'); if (function_exists('hash_hmac') && isset($hashes[$hash])) { $this->hash = create_function('$data', 'return hash("' . $hashes[$hash] . '", $data, TRUE);'); $this->hmac = create_function('$key,$str,$raw', 'return hash_hmac("' . $hashes[$hash] . '", $str, $key, $raw);'); } elseif ($hash == 'md5') { $this->hash = create_function('$data', 'return md5($data, true);'); $this->hmac = array($this, '_HMAC_MD5'); } elseif (in_array($hash, array('sha1', 'sha-1'))) { $this->hash = create_function('$data', 'return sha1($data, true);'); $this->hmac = array($this, '_HMAC_SHA1'); } else return PEAR::raiseError('Invalid SASL mechanism type'); } /** * Provides the (main) client response for SCRAM-H. * * @param string $authcid Authentication id (username) * @param string $pass Password * @param string $challenge The challenge sent by the server. * If the challenge is NULL or an empty string, the result will be the "initial response". * @param string $authzid Authorization id (username to proxy as) * @return string|false The response (binary, NOT base64 encoded) * @access public */ public function getResponse($authcid, $pass, $challenge = NULL, $authzid = NULL) { $authcid = $this->_formatName($authcid); if (empty($authcid)) { return false; } if (!empty($authzid)) { $authzid = $this->_formatName($authzid); if (empty($authzid)) { return false; } } if (empty($challenge)) { return $this->_generateInitialResponse($authcid, $authzid); } else { return $this->_generateResponse($challenge, $pass); } } /** * Prepare a name for inclusion in a SCRAM response. * * @param string $username a name to be prepared. * @return string the reformated name. * @access private */ private function _formatName($username) { // TODO: prepare through the SASLprep profile of the stringprep algorithm. // See RFC-4013. $username = str_replace('=', '=3D', $username); $username = str_replace(',', '=2C', $username); return $username; } /** * Generate the initial response which can be either sent directly in the first message or as a response to an empty * server challenge. * * @param string $authcid Prepared authentication identity. * @param string $authzid Prepared authorization identity. * @return string The SCRAM response to send. * @access private */ private function _generateInitialResponse($authcid, $authzid) { $init_rep = ''; $gs2_cbind_flag = 'n,'; // TODO: support channel binding. $this->gs2_header = $gs2_cbind_flag . (!empty($authzid)? 'a=' . $authzid : '') . ','; // I must generate a client nonce and "save" it for later comparison on second response. $this->cnonce = $this->_getCnonce(); // XXX: in the future, when mandatory and/or optional extensions are defined in any updated RFC, // this message can be updated. $this->first_message_bare = 'n=' . $authcid . ',r=' . $this->cnonce; return $this->gs2_header . $this->first_message_bare; } /** * Parses and verifies a non-empty SCRAM challenge. * * @param string $challenge The SCRAM challenge * @return string|false The response to send; false in case of wrong challenge or if an initial response has not * been generated first. * @access private */ private function _generateResponse($challenge, $password) { // XXX: as I don't support mandatory extension, I would fail on them. // And I simply ignore any optional extension. $server_message_regexp = "#^r=([\x21-\x2B\x2D-\x7E]+),s=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?),i=([0-9]*)(,[A-Za-z]=[^,])*$#"; if (!isset($this->cnonce, $this->gs2_header) || !preg_match($server_message_regexp, $challenge, $matches)) { return false; } $nonce = $matches[1]; $salt = base64_decode($matches[2]); if (!$salt) { // Invalid Base64. return false; } $i = intval($matches[3]); $cnonce = substr($nonce, 0, strlen($this->cnonce)); if ($cnonce <> $this->cnonce) { // Invalid challenge! Are we under attack? return false; } $channel_binding = 'c=' . base64_encode($this->gs2_header); // TODO: support channel binding. $final_message = $channel_binding . ',r=' . $nonce; // XXX: no extension. // TODO: $password = $this->normalize($password); // SASLprep profile of stringprep. $saltedPassword = $this->hi($password, $salt, $i); $this->saltedPassword = $saltedPassword; $clientKey = call_user_func($this->hmac, $saltedPassword, "Client Key", TRUE); $storedKey = call_user_func($this->hash, $clientKey, TRUE); $authMessage = $this->first_message_bare . ',' . $challenge . ',' . $final_message; $this->authMessage = $authMessage; $clientSignature = call_user_func($this->hmac, $storedKey, $authMessage, TRUE); $clientProof = $clientKey ^ $clientSignature; $proof = ',p=' . base64_encode($clientProof); return $final_message . $proof; } /** * SCRAM has also a server verification step. On a successful outcome, it will send additional data which must * absolutely be checked against this function. If this fails, the entity which we are communicating with is probably * not the server as it has not access to your ServerKey. * * @param string $data The additional data sent along a successful outcome. * @return bool Whether the server has been authenticated. * If false, the client must close the connection and consider to be under a MITM attack. * @access public */ public function processOutcome($data) { $verifier_regexp = '#^v=((?:[A-Za-z0-9/+]{4})*(?:[A-Za-z0-9]{3}=|[A-Xa-z0-9]{2}==)?)$#'; if (!isset($this->saltedPassword, $this->authMessage) || !preg_match($verifier_regexp, $data, $matches)) { // This cannot be an outcome, you never sent the challenge's response. return false; } $verifier = $matches[1]; $proposed_serverSignature = base64_decode($verifier); $serverKey = call_user_func($this->hmac, $this->saltedPassword, "Server Key", true); $serverSignature = call_user_func($this->hmac, $serverKey, $this->authMessage, TRUE); return ($proposed_serverSignature === $serverSignature); } /** * Hi() call, which is essentially PBKDF2 (RFC-2898) with HMAC-H() as the pseudorandom function. * * @param string $str The string to hash. * @param string $hash The hash value. * @param int $i The iteration count. * @access private */ private function hi($str, $salt, $i) { $int1 = "\0\0\0\1"; $ui = call_user_func($this->hmac, $str, $salt . $int1, true); $result = $ui; for ($k = 1; $k < $i; $k++) { $ui = call_user_func($this->hmac, $str, $ui, true); $result = $result ^ $ui; } return $result; } /** * Creates the client nonce for the response * * @return string The cnonce value * @access private * @author Richard Heyes
*/ private function _getCnonce() { // TODO: I reused the nonce function from the DigestMD5 class. // I should probably make this a protected function in Common. if (@file_exists('/dev/urandom') && $fd = @fopen('/dev/urandom', 'r')) { return base64_encode(fread($fd, 32)); } elseif (@file_exists('/dev/random') && $fd = @fopen('/dev/random', 'r')) { return base64_encode(fread($fd, 32)); } else { $str = ''; for ($i=0; $i<32; $i++) { $str .= chr(mt_rand(0, 255)); } return base64_encode($str); } } } ?> PK HqYT SASL/Common.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Common functionality to SASL mechanisms * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ class Auth_SASL_Common { /** * Function which implements HMAC MD5 digest * * @param string $key The secret key * @param string $data The data to hash * @param bool $raw_output Whether the digest is returned in binary or hexadecimal format. * * @return string The HMAC-MD5 digest */ function _HMAC_MD5($key, $data, $raw_output = FALSE) { if (strlen($key) > 64) { $key = pack('H32', md5($key)); } if (strlen($key) < 64) { $key = str_pad($key, 64, chr(0)); } $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); $inner = pack('H32', md5($k_ipad . $data)); $digest = md5($k_opad . $inner, $raw_output); return $digest; } /** * Function which implements HMAC-SHA-1 digest * * @param string $key The secret key * @param string $data The data to hash * @param bool $raw_output Whether the digest is returned in binary or hexadecimal format. * @return string The HMAC-SHA-1 digest * @author Jehan
* @access protected */ protected function _HMAC_SHA1($key, $data, $raw_output = FALSE) { if (strlen($key) > 64) { $key = sha1($key, TRUE); } if (strlen($key) < 64) { $key = str_pad($key, 64, chr(0)); } $k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); $k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); $inner = pack('H40', sha1($k_ipad . $data)); $digest = sha1($k_opad . $inner, $raw_output); return $digest; } } ?> PK HqYJ} } SASL/Anonymous.phpnu [ | // +-----------------------------------------------------------------------+ // // $Id$ /** * Implmentation of ANONYMOUS SASL mechanism * * @author Richard Heyes
* @access public * @version 1.0 * @package Auth_SASL */ require_once('Auth/SASL/Common.php'); class Auth_SASL_Anonymous extends Auth_SASL_Common { /** * Not much to do here except return the token supplied. * No encoding, hashing or encryption takes place for this * mechanism, simply one of: * o An email address * o An opaque string not containing "@" that can be interpreted * by the sysadmin * o Nothing * * We could have some logic here for the second option, but this * would by no means create something interpretable. * * @param string $token Optional email address or string to provide * as trace information. * @return string The unaltered input token */ function getResponse($token = '') { return $token; } } ?>PK HqY2r SASL.phpnu [ PK HqY= = SASL/Plain.phpnu [ PK HqYvRr, , ! SASL/External.phpnu [ PK HqY%ׅtg! g! - SASL/DigestMD5.phpnu [ PK HqY< O O O SASL/Login.phpnu [ PK HqYP(~T T +\ SASL/CramMD5.phpnu [ PK HqYќ0 0 i SASL/SCRAM.phpnu [ PK HqYT SASL/Common.phpnu [ PK HqYJ} } M SASL/Anonymous.phpnu [ PK