Mercurial > hg > rc1
diff vendor/pear/net_sieve/Sieve.php @ 35:05c4c32948af
.hgignore: add vendor tree
composer.json: new packages
plugins/thunderbird_labels/thunderbird_labels.php: change hook and RFC822 use wrt whitelisting to avoid deprecated stuff
index.php: commented debugging hooks
others: new releases of vendor packages?
author | Charlie Root |
---|---|
date | Thu, 30 Aug 2018 16:21:59 -0400 |
parents | 1e000243b222 |
children |
line wrap: on
line diff
--- a/vendor/pear/net_sieve/Sieve.php Sun May 27 16:53:56 2018 -0400 +++ b/vendor/pear/net_sieve/Sieve.php Thu Aug 30 16:21:59 2018 -0400 @@ -46,25 +46,22 @@ require_once 'Net/Socket.php'; /** - * TODO + * Disconnected state * - * o supportsAuthMech() - */ - -/** - * Disconnected state * @const NET_SIEVE_STATE_DISCONNECTED */ define('NET_SIEVE_STATE_DISCONNECTED', 1, true); /** * Authorisation state + * * @const NET_SIEVE_STATE_AUTHORISATION */ define('NET_SIEVE_STATE_AUTHORISATION', 2, true); /** * Transaction state + * * @const NET_SIEVE_STATE_TRANSACTION */ define('NET_SIEVE_STATE_TRANSACTION', 3, true); @@ -79,6 +76,7 @@ * @author Damian Fernandez Sosa <damlists@cnba.uba.ar> * @author Anish Mistry <amistry@am-productions.biz> * @author Jan Schneider <jan@horde.org> + * @author Neil Munday <neil@mundayweb.com> * @copyright 2002-2003 Richard Heyes * @copyright 2006-2008 Anish Mistry * @license http://www.opensource.org/licenses/bsd-license.php BSD @@ -103,7 +101,8 @@ 'CRAM-MD5', 'EXTERNAL', 'PLAIN' , - 'LOGIN' + 'LOGIN', + 'GSSAPI' ); /** @@ -195,6 +194,20 @@ var $_maxReferralCount = 15; /** + * Kerberos service principal to use for GSSAPI authentication. + * + * @var string + */ + var $_gssapiPrincipal = null; + + /** + * Kerberos service cname to use for GSSAPI authentication. + * + * @var string + */ + var $_gssapiCN = null; + + /** * Constructor. * * Sets up the object, connects to the server and logs in. Stores any @@ -216,11 +229,15 @@ * @param array $options Additional options for * stream_context_create(). * @param mixed $handler A callback handler for the debug output. + * @param string $principal Kerberos service principal to use + * with GSSAPI authentication. + * @param string $cname Kerberos service cname to use + * with GSSAPI authentication. */ function __construct($user = null, $pass = null, $host = 'localhost', $port = 2000, $logintype = '', $euser = '', $debug = false, $bypassAuth = false, $useTLS = true, - $options = null, $handler = null + $options = null, $handler = null, $principal = null, $cname = null ) { $this->_pear = new PEAR(); $this->_state = NET_SIEVE_STATE_DISCONNECTED; @@ -234,6 +251,9 @@ $this->_bypassAuth = $bypassAuth; $this->_useTLS = $useTLS; $this->_options = (array) $options; + $this->_gssapiPrincipal = $principal; + $this->_gssapiCN = $cname; + $this->setDebug($debug, $handler); /* Try to include the Auth_SASL package. If the package is not @@ -277,6 +297,32 @@ } /** + * Sets the Kerberos service principal for use with GSSAPI + * authentication. + * + * @param string $principal The Kerberos service principal + * + * @return void + */ + function setServicePrincipal($principal) + { + $this->_gssapiPrincipal = $principal; + } + + /** + * Sets the Kerberos service CName for use with GSSAPI + * authentication. + * + * @param string $cname The Kerberos service principal + * + * @return void + */ + function setServiceCN($cname) + { + $this->_gssapiCN = $cname; + } + + /** * Connects to the server and logs in. * * @return boolean True on success, PEAR_Error on failure. @@ -328,21 +374,29 @@ if ($this->_bypassAuth) { $this->_state = NET_SIEVE_STATE_TRANSACTION; + + // Reset capabilities + $this->_parseCapability(''); } else { $this->_state = NET_SIEVE_STATE_AUTHORISATION; + $res = $this->_doCmd(); if (is_a($res, 'PEAR_Error')) { return $res; } + + // Reset capabilities (use unattended capabilities) + $this->_parseCapability($res); } - // Explicitly ask for the capabilities in case the connection is - // picked up from an existing connection. - $res = $this->_cmdCapability(); - if (is_a($res, 'PEAR_Error')) { - return $this->_pear->raiseError( - 'Failed to connect, server said: ' . $res->getMessage(), 2 - ); + // Explicitly ask for the capabilities if needed + if (empty($this->_capability['implementation'])) { + $res = $this->_cmdCapability(); + if (is_a($res, 'PEAR_Error')) { + return $this->_pear->raiseError( + 'Failed to connect, server said: ' . $res->getMessage(), 2 + ); + } } // Check if we can enable TLS via STARTTLS. @@ -400,6 +454,7 @@ return $res; } } + $this->_state = NET_SIEVE_STATE_TRANSACTION; return true; @@ -408,15 +463,21 @@ /** * Returns an indexed array of scripts currently on the server. * - * @return array Indexed array of scriptnames. + * @param string $active Will be set to the name of the active script + * + * @return array Indexed array of scriptnames, PEAR_Error on failure */ - function listScripts() + function listScripts(&$active = null) { if (is_array($scripts = $this->_cmdListScripts())) { + if (isset($scripts[1])) { + $active = $scripts[1]; + } + return $scripts[0]; - } else { - return $scripts; } + + return $scripts; } /** @@ -470,9 +531,11 @@ if (is_a($res, 'PEAR_Error')) { return $res; } + if ($makeactive) { return $this->_cmdSetActive($scriptname); } + return true; } @@ -508,6 +571,7 @@ if (is_a($res, 'PEAR_Error')) { return $res; } + return true; } @@ -521,6 +585,7 @@ if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } + return $this->_capability['extensions']; } @@ -560,6 +625,7 @@ if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { return $this->_pear->raiseError('Not currently connected', 7); } + return $this->_capability['sasl']; } @@ -578,6 +644,7 @@ } $method = trim($this->_toUpper($method)); + if (is_array($this->_capability['sasl'])) { foreach ($this->_capability['sasl'] as $sasl) { if ($sasl == $method) { @@ -606,6 +673,7 @@ if (is_a($method, 'PEAR_Error')) { return $method; } + switch ($method) { case 'DIGEST-MD5': return $this->_authDigestMD5($uid, $pwd, $euser); @@ -621,6 +689,9 @@ case 'EXTERNAL': $result = $this->_authEXTERNAL($uid, $pwd, $euser); break; + case 'GSSAPI': + $result = $this->_authGSSAPI($pwd); + break; default : $result = $this->_pear->raiseError( $method . ' is not a supported authentication method' @@ -633,7 +704,6 @@ return $res; } - // Query the server capabilities again now that we are authenticated. if ($this->_pear->isError($res = $this->_cmdCapability())) { return $this->_pear->raiseError( 'Failed to connect, server said: ' . $res->getMessage(), 2 @@ -663,6 +733,66 @@ } /** + * Authenticates the user using the GSSAPI method. + * + * @note the PHP krb5 extension is required and the service principal and cname + * must have been set. + * @see setServicePrincipal() + * + * @return void + */ + function _authGSSAPI() + { + if (!extension_loaded('krb5')) { + return $this->_pear->raiseError('The krb5 extension is required for GSSAPI authentication', 2); + } + + if (!$this->_gssapiPrincipal) { + return $this->_pear->raiseError('No Kerberos service principal set', 2); + } + + if (!$this->_gssapiCN) { + return $this->_pear->raiseError('No Kerberos service CName set', 2); + } + + putenv('KRB5CCNAME=' . $this->_gssapiCN); + + try { + $ccache = new KRB5CCache(); + $ccache->open($this->_gssapiCN); + + $gssapicontext = new GSSAPIContext(); + $gssapicontext->acquireCredentials($ccache); + + $token = ''; + $success = $gssapicontext->initSecContext($this->_gssapiPrincipal, null, null, null, $token); + $token = base64_encode($token); + } + catch (Exception $e) { + return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage()); + } + + $this->_sendCmd("AUTHENTICATE \"GSSAPI\" {" . strlen($token) . "+}"); + + $response = $this->_doCmd($token, true); + + try { + $challenge = base64_decode(substr($response, 1, -1)); + $gssapicontext->unwrap($challenge, $challenge); + $gssapicontext->wrap($challenge, $challenge, true); + } + catch (Exception $e) { + return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage()); + } + + $response = base64_encode($challenge); + + $this->_sendCmd("{" . strlen($response) . "+}"); + + return $this->_sendCmd($response); + } + + /** * Authenticates the user using the LOGIN method. * * @param string $user The userid to authenticate as. @@ -677,10 +807,12 @@ if (is_a($result, 'PEAR_Error')) { return $result; } + $result = $this->_doCmd('"' . base64_encode($user) . '"', true); if (is_a($result, 'PEAR_Error')) { return $result; } + return $this->_doCmd('"' . base64_encode($pass) . '"', true); } @@ -742,10 +874,12 @@ if (is_a($result, 'PEAR_Error')) { return $result; } + $result = $this->_doCmd('', true); if (is_a($result, 'PEAR_Error')) { return $result; } + if ($this->_toUpper(substr($result, 0, 2)) == 'OK') { return; } @@ -769,7 +903,7 @@ * * @return void * - * @since 1.1.7 + * @since 1.1.7 */ function _authEXTERNAL($user, $pass, $euser) { @@ -777,6 +911,7 @@ 'AUTHENTICATE "EXTERNAL" "%s"', base64_encode(strlen($euser) ? $euser : $user) ); + return $this->_sendCmd($cmd); } @@ -797,6 +932,7 @@ if (is_a($res, 'PEAR_Error')) { return $res; } + return true; } @@ -978,11 +1114,15 @@ break; case 'SASL': - $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); + if (!empty($matches[3])) { + $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); + } break; case 'SIEVE': - $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]); + if (!empty($matches[3])) { + $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]); + } break; case 'STARTTLS': @@ -1227,8 +1367,7 @@ if (isset($this->_options['ssl']['crypto_method'])) { $crypto_method = $this->_options['ssl']['crypto_method']; - } - else { + } else { // There is no flag to enable all TLS methods. Net_SMTP // handles enabling TLS similarly. $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT @@ -1250,16 +1389,20 @@ if (!preg_match('/^CYRUS TIMSIEVED V([0-9.]+)/', $this->_capability['implementation'], $matches) || version_compare($matches[1], '2.3.10', '>=') ) { - $this->_doCmd(); + $res = $this->_doCmd(); } - // Query the server capabilities again now that we are under - // encryption. - $res = $this->_cmdCapability(); - if (is_a($res, 'PEAR_Error')) { - return $this->_pear->raiseError( - 'Failed to connect, server said: ' . $res->getMessage(), 2 - ); + // Reset capabilities (use unattended capabilities) + $this->_parseCapability(is_string($res) ? $res : ''); + + // Query the server capabilities again now that we are under encryption. + if (empty($this->_capability['implementation'])) { + $res = $this->_cmdCapability(); + if (is_a($res, 'PEAR_Error')) { + return $this->_pear->raiseError( + 'Failed to connect, server said: ' . $res->getMessage(), 2 + ); + } } return true; @@ -1275,7 +1418,7 @@ function _getLineLength($string) { if (extension_loaded('mbstring')) { - return mb_strlen($string, 'latin1'); + return mb_strlen($string, '8bit'); } else { return strlen($string); }