310 lines
12 KiB
PHP
310 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Horde_ActiveSync_Policies::
|
|
*
|
|
* @license http://www.horde.org/licenses/gpl GPLv2
|
|
*
|
|
* @copyright 2010-2020 Horde LLC (http://www.horde.org)
|
|
* @author Michael J Rubinsky <mrubinsk@horde.org>
|
|
* @package ActiveSync
|
|
*/
|
|
/**
|
|
* Horde_ActiveSync_Policies:: Wraps all functionality related to generating
|
|
* the XML or WBXML for EAS Policies.
|
|
*
|
|
* @license http://www.horde.org/licenses/gpl GPLv2
|
|
*
|
|
* @copyright 2010-2020 Horde LLC (http://www.horde.org)
|
|
* @author Michael J Rubinsky <mrubinsk@horde.org>
|
|
* @package ActiveSync
|
|
*/
|
|
class Horde_ActiveSync_Policies
|
|
{
|
|
/* Policy configuration keys */
|
|
const POLICY_PIN = 'DevicePasswordEnabled';
|
|
const POLICY_AEFVALUE = 'MaxInactivityTimeDeviceLock';
|
|
const POLICY_CODEFREQ = 'codewordfrequency';
|
|
const POLICY_MINLENGTH = 'MinDevicePasswordLength';
|
|
const POLICY_COMPLEXITY = 'AlphanumericDevicePasswordRequired';
|
|
// 12.0
|
|
//const POLICY_PWDRECOVERY = 'passwordrecovery';
|
|
//const POLICY_PWDEXPIRATION = 'passwordexpiration';
|
|
//const POLICY_PWDHISTORY = 'passwordhistory';
|
|
const POLICY_ENCRYPTION = 'DeviceEncryptionEnabled';
|
|
const POLICY_ATC = 'AttachmentsEnabled';
|
|
const POLICY_MAXATCSIZE = 'MaxAttachmentSize';
|
|
const POLICY_MAXFAILEDATTEMPTS = 'MaxDevicePasswordFailedAttempts';
|
|
// 12.1
|
|
const POLICY_ALLOW_SDCARD = 'AllowStorageCard';
|
|
const POLICY_ALLOW_CAMERA = 'AllowCamera';
|
|
const POLICY_ALLOW_SMS = 'AllowTextMessaging';
|
|
const POLICY_ALLOW_WIFI = 'AllowWiFi';
|
|
const POLICY_ALLOW_BLUETOOTH = 'AllowBluetooth';
|
|
const POLICY_ALLOW_POPIMAP = 'AllowPOPIMAPEmail';
|
|
const POLICY_ALLOW_BROWSER = 'AllowBrowser';
|
|
const POLICY_REQUIRE_SMIME_SIGNED = 'RequireSignedSMIMEMessages';
|
|
const POLICY_REQUIRE_SMIME_ENCRYPTED = 'RequireEncryptedSMIMEMessages';
|
|
const POLICY_DEVICE_ENCRYPTION = 'RequireDeviceEncryption';
|
|
const POLICY_ALLOW_HTML = 'AllowHTMLEmail';
|
|
const POLICY_MAX_EMAIL_AGE = 'MaxEmailAgeFilter';
|
|
//const POLICY_MAX_EMAIL_TRUNCATION = 'maxemailtruncation';
|
|
//const POLICY_MAX_HTMLEMAIL_TRUNCATION = 'maxhtmlemailtruncation';
|
|
const POLICY_ROAMING_NOPUSH = 'RequireManualSyncWhenRoaming';
|
|
|
|
/**
|
|
* Default policy values used in both 12.0 and 12.1
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_defaults = array(
|
|
self::POLICY_PIN => false,
|
|
self::POLICY_AEFVALUE => '0',
|
|
self::POLICY_MAXFAILEDATTEMPTS => '5',
|
|
self::POLICY_CODEFREQ => '0',
|
|
self::POLICY_MINLENGTH => '5',
|
|
);
|
|
|
|
/**
|
|
* Deafaults for 12.0 policies.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_defaults_twelve = array(
|
|
self::POLICY_ATC => '1',
|
|
self::POLICY_ENCRYPTION => '0',
|
|
self::POLICY_MAXATCSIZE => '5000000',
|
|
self::POLICY_COMPLEXITY => '0',
|
|
//self::POLICY_PWDRECOVERY => '0',
|
|
//self::POLICY_PWDEXPIRATION => '0',
|
|
//self::POLICY_PWDHISTORY => '0',
|
|
);
|
|
|
|
/**
|
|
* Defaults used only in 12.1
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_defaults_twelveone = array(
|
|
// 1 == Allow/Yes, 0 == Disallow/No.
|
|
self::POLICY_ALLOW_SDCARD => '1',
|
|
self::POLICY_ALLOW_CAMERA => '1',
|
|
self::POLICY_ALLOW_SMS => '1',
|
|
self::POLICY_ALLOW_WIFI => '1',
|
|
self::POLICY_ALLOW_BLUETOOTH => '1',
|
|
self::POLICY_ALLOW_POPIMAP => '1',
|
|
self::POLICY_ALLOW_BROWSER => '1',
|
|
self::POLICY_REQUIRE_SMIME_ENCRYPTED => '0',
|
|
self::POLICY_REQUIRE_SMIME_SIGNED => '0',
|
|
self::POLICY_DEVICE_ENCRYPTION => '0',
|
|
self::POLICY_ALLOW_HTML => '1',
|
|
self::POLICY_MAX_EMAIL_AGE => '0',
|
|
self::POLICY_ROAMING_NOPUSH => '0',
|
|
);
|
|
|
|
/**
|
|
* Explicitly set policies.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_overrides;
|
|
|
|
/**
|
|
* Output stream
|
|
*
|
|
* @var Horde_ActiveSync_Wbxml_Encoder
|
|
*/
|
|
protected $_encoder;
|
|
|
|
/**
|
|
* EAS version to support.
|
|
*
|
|
* @var long
|
|
*/
|
|
protected $_version;
|
|
|
|
/**
|
|
* Local cache of all policies to send.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_policies = array();
|
|
|
|
/**
|
|
* Const'r
|
|
*
|
|
* @param Horde_ActiveSync_Wbxml_Encoder $encoder The output stream encoder
|
|
* @param float $version The EAS Version.
|
|
* @param array $policies The policy array.
|
|
*/
|
|
public function __construct(
|
|
Horde_ActiveSync_Wbxml_Encoder $encoder = null,
|
|
$version = Horde_ActiveSync::VERSION_TWELVEONE,
|
|
array $policies = array())
|
|
{
|
|
$this->_encoder = $encoder;
|
|
if ($version >= Horde_ActiveSync::VERSION_TWELVE) {
|
|
$this->_defaults = array_merge($this->_defaults, $this->_defaults_twelve);
|
|
}
|
|
if ($version >= Horde_ActiveSync::VERSION_TWELVEONE) {
|
|
$this->_defaults = array_merge($this->_defaults, $this->_defaults_twelveone);
|
|
}
|
|
|
|
$this->_version = $version;
|
|
$this->_overrides = $policies;
|
|
}
|
|
|
|
/**
|
|
* Return a list of all configurable policy names.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getAvailablePolicies()
|
|
{
|
|
return array_keys($this->_defaults);
|
|
}
|
|
|
|
/**
|
|
* Determine if the requested policy settings are available for the current
|
|
* version being used.
|
|
*
|
|
* @return boolean True if policies are available in current version, false
|
|
* otherwise.
|
|
*/
|
|
public function validatePolicyVersion()
|
|
{
|
|
$policies = $this->_getPolicies();
|
|
|
|
// Validate the version against the required policies.
|
|
if ($this->_version < Horde_ActiveSync::VERSION_TWELVEONE) {
|
|
foreach ($policies as $key => $value) {
|
|
if (!empty($this->_defaults_twelveone[$key]) &&
|
|
$this->_defaults_twelveone[$key] != $value) {
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Output the policies as XML. Only used in EAS Version 2.5. This method
|
|
* only outputs the 2.5 compatible policies.
|
|
*
|
|
* @throws Horde_ActiveSync_Exception
|
|
*/
|
|
public function toXml()
|
|
{
|
|
if (empty($this->_encoder)) {
|
|
throw new Horde_ActiveSync_Exception('No output stream');
|
|
}
|
|
|
|
$policies = array_merge($this->_defaults, $this->_overrides);
|
|
|
|
$xml = '<wap-provisioningdoc><characteristic type="SecurityPolicy">'
|
|
. '<parm name="4131" value="' . ($policies[self::POLICY_PIN] ? 0 : 1) . '"/>'
|
|
. '</characteristic>';
|
|
if ($policies[self::POLICY_PIN]) {
|
|
$xml .= '<characteristic type="Registry">'
|
|
. '<characteristic type="HKLM\Comm\Security\Policy\LASSD\AE\{50C13377-C66D-400C-889E-C316FC4AB374}">'
|
|
. '<parm name="AEFrequencyType" value="' . (!empty($policies[self::POLICY_AEFVALUE]) ? 1 : 0) . '"/>'
|
|
. (!empty($policies[self::POLICY_AEFVALUE]) ? '<parm name="AEFrequencyValue" value="' . $policies[self::POLICY_AEFVALUE] . '"/>' : '')
|
|
. '</characteristic>';
|
|
|
|
if (!empty($policies[self::POLICY_MAXFAILEDATTEMPTS])) {
|
|
$xml .= '<characteristic type="HKLM\Comm\Security\Policy\LASSD"><parm name="DeviceWipeThreshold" value="' . $policies[self::POLICY_MAXFAILEDATTEMPTS] . '"/></characteristic>';
|
|
}
|
|
if (!empty($policies[self::POLICY_CODEFREQ])) {
|
|
$xml .= '<characteristic type="HKLM\Comm\Security\Policy\LASSD"><parm name="CodewordFrequency" value="' . $policies[self::POLICY_CODEFREQ] . '"/></characteristic>';
|
|
}
|
|
if (!empty($policies[self::POLICY_MINLENGTH])) {
|
|
$xml .= '<characteristic type="HKLM\Comm\Security\Policy\LASSD\LAP\lap_pw"><parm name="MinimumPasswordLength" value="' . $policies[self::POLICY_MINLENGTH] . '"/></characteristic>';
|
|
}
|
|
if ($policies[self::POLICY_COMPLEXITY] !== false) {
|
|
$xml .= '<characteristic type="HKLM\Comm\Security\Policy\LASSD\LAP\lap_pw"><parm name="PasswordComplexity" value="' . $policies[self::POLICY_COMPLEXITY] . '"/></characteristic>';
|
|
}
|
|
$xml .= '</characteristic>';
|
|
}
|
|
$xml .= '</wap-provisioningdoc>';
|
|
|
|
$this->_encoder->content($xml);
|
|
}
|
|
|
|
|
|
/**
|
|
* Output the policies as WBXML. Used in EAS Versions >= 12.0
|
|
*/
|
|
public function toWbxml()
|
|
{
|
|
if (empty($this->_encoder)) {
|
|
throw new Horde_ActiveSync_Exception('No output stream');
|
|
}
|
|
|
|
$policies = $this->_getPolicies();
|
|
|
|
$this->_encoder->startTag('Provision:EASProvisionDoc');
|
|
|
|
$this->_sendPolicy(self::POLICY_PIN, $policies[self::POLICY_PIN] ? '1' : '0');
|
|
if ($policies[self::POLICY_PIN]) {
|
|
$this->_sendPolicy(self::POLICY_COMPLEXITY, $policies[self::POLICY_COMPLEXITY], true);
|
|
$this->_sendPolicy(self::POLICY_MINLENGTH, $policies[self::POLICY_MINLENGTH], true);
|
|
$this->_sendPolicy(self::POLICY_MAXFAILEDATTEMPTS, $policies[self::POLICY_MAXFAILEDATTEMPTS], true);
|
|
$this->_sendPolicy(self::POLICY_COMPLEXITY, $policies[self::POLICY_COMPLEXITY] >= 1 ? '1' : '0', true);
|
|
}
|
|
$this->_sendPolicy(self::POLICY_ENCRYPTION, $policies[self::POLICY_ENCRYPTION], true);
|
|
$this->_sendPolicy(self::POLICY_ATC, $policies[self::POLICY_ATC], false);
|
|
$this->_sendPolicy(self::POLICY_AEFVALUE, $policies[self::POLICY_AEFVALUE], true);
|
|
$this->_sendPolicy(self::POLICY_MAXATCSIZE, $policies[self::POLICY_MAXATCSIZE], true);
|
|
if ($this->_version > Horde_ActiveSync::VERSION_TWELVE) {
|
|
$this->_sendPolicy(self::POLICY_ALLOW_SDCARD, $policies[self::POLICY_ALLOW_SDCARD], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_CAMERA, $policies[self::POLICY_ALLOW_CAMERA], true);
|
|
$this->_sendPolicy(self::POLICY_DEVICE_ENCRYPTION, $policies[self::POLICY_DEVICE_ENCRYPTION], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_WIFI, $policies[self::POLICY_ALLOW_WIFI], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_SMS, $policies[self::POLICY_ALLOW_SMS], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_POPIMAP, $policies[self::POLICY_ALLOW_POPIMAP], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_BLUETOOTH, $policies[self::POLICY_ALLOW_BLUETOOTH], true);
|
|
$this->_sendPolicy(self::POLICY_ROAMING_NOPUSH, $policies[self::POLICY_ROAMING_NOPUSH], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_HTML, $policies[self::POLICY_ALLOW_HTML], true);
|
|
$this->_sendPolicy(self::POLICY_MAX_EMAIL_AGE, $policies[self::POLICY_MAX_EMAIL_AGE], true);
|
|
$this->_sendPolicy(self::POLICY_REQUIRE_SMIME_SIGNED, $policies[self::POLICY_REQUIRE_SMIME_SIGNED], true);
|
|
$this->_sendPolicy(self::POLICY_REQUIRE_SMIME_ENCRYPTED, $policies[self::POLICY_REQUIRE_SMIME_ENCRYPTED], true);
|
|
$this->_sendPolicy(self::POLICY_ALLOW_BROWSER, $policies[self::POLICY_ALLOW_BROWSER], true);
|
|
}
|
|
|
|
$this->_encoder->endTag();
|
|
}
|
|
|
|
/**
|
|
* Output a single policy value
|
|
*
|
|
* @param string $policy The policy name
|
|
* @param mixed $value The policy value
|
|
* @param boolean $nodefault Don't send the policy if the value is default.
|
|
*/
|
|
protected function _sendPolicy($policy, $value, $nodefault = false)
|
|
{
|
|
if ($nodefault && $value == $this->_defaults[$policy]) {
|
|
return;
|
|
}
|
|
if ($value === false) {
|
|
$value = 0;
|
|
} elseif ($value === true) {
|
|
$value = 1;
|
|
}
|
|
$this->_encoder->startTag('Provision:' . $policy);
|
|
$this->_encoder->content($value);
|
|
$this->_encoder->endTag();
|
|
}
|
|
|
|
protected function _getPolicies()
|
|
{
|
|
if (empty($this->_policies)) {
|
|
$this->_policies = array_merge($this->_defaults, $this->_overrides);
|
|
}
|
|
|
|
return $this->_policies;
|
|
}
|
|
|
|
}
|