1<?php 2/*********************************************** 3* File : provisioning.php 4* Project : Z-Push 5* Descr : Provides the PROVISIONING command 6* 7* Created : 16.02.2012 8* 9* Copyright 2007 - 2016, 2015 Zarafa Deutschland GmbH 10* 11* This program is free software: you can redistribute it and/or modify 12* it under the terms of the GNU Affero General Public License, version 3, 13* as published by the Free Software Foundation. 14* 15* This program is distributed in the hope that it will be useful, 16* but WITHOUT ANY WARRANTY; without even the implied warranty of 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18* GNU Affero General Public License for more details. 19* 20* You should have received a copy of the GNU Affero General Public License 21* along with this program. If not, see <http://www.gnu.org/licenses/>. 22* 23* Consult LICENSE file for details 24************************************************/ 25 26class Provisioning extends RequestProcessor { 27 28 /** 29 * Handles the Provisioning command 30 * 31 * @param int $commandCode 32 * 33 * @access public 34 * @return boolean 35 */ 36 public function Handle($commandCode) { 37 $status = SYNC_PROVISION_STATUS_SUCCESS; 38 $policystatus = SYNC_PROVISION_POLICYSTATUS_SUCCESS; 39 40 $rwstatus = self::$deviceManager->GetProvisioningWipeStatus(); 41 $rwstatusWiped = false; 42 $deviceInfoSet = false; 43 44 // if this is a regular provisioning require that an authenticated remote user 45 if ($rwstatus < SYNC_PROVISION_RWSTATUS_PENDING) { 46 ZLog::Write(LOGLEVEL_DEBUG, "RequestProcessor::HandleProvision(): Forcing delayed Authentication"); 47 self::Authenticate(); 48 } 49 50 $phase2 = true; 51 52 if(!self::$decoder->getElementStartTag(SYNC_PROVISION_PROVISION)) 53 return false; 54 55 // Loop through Provision request tags. Possible are: 56 // - Remote Wipe 57 // - DeviceInformation 58 // - Policies 59 // Each of them should only be once per request. 60 WBXMLDecoder::ResetInWhile("provisioningMain"); 61 while(WBXMLDecoder::InWhile("provisioningMain")) { 62 $requestName = ""; 63 if (self::$decoder->getElementStartTag(SYNC_PROVISION_REMOTEWIPE)) { 64 $requestName = SYNC_PROVISION_REMOTEWIPE; 65 } 66 if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICIES)) { 67 $requestName = SYNC_PROVISION_POLICIES; 68 } 69 if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEINFORMATION)) { 70 $requestName = SYNC_SETTINGS_DEVICEINFORMATION; 71 } 72 73 if (!$requestName) 74 break; 75 76 //set is available for OOF, device password and device information 77 switch ($requestName) { 78 case SYNC_PROVISION_REMOTEWIPE: 79 if(!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) 80 return false; 81 82 $instatus = self::$decoder->getElementContent(); 83 84 if(!self::$decoder->getElementEndTag()) 85 return false; 86 87 if(!self::$decoder->getElementEndTag()) 88 return false; 89 90 $phase2 = false; 91 $rwstatusWiped = true; 92 //TODO check - do it after while(1) finished? 93 break; 94 95 case SYNC_PROVISION_POLICIES: 96 if(!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICY)) 97 return false; 98 99 if(!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYTYPE)) 100 return false; 101 102 $policytype = self::$decoder->getElementContent(); 103 if ($policytype != 'MS-WAP-Provisioning-XML' && $policytype != 'MS-EAS-Provisioning-WBXML') { 104 $status = SYNC_PROVISION_STATUS_SERVERERROR; 105 } 106 if(!self::$decoder->getElementEndTag()) //policytype 107 return false; 108 109 if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYKEY)) { 110 $devpolicykey = self::$decoder->getElementContent(); 111 112 if(!self::$decoder->getElementEndTag()) 113 return false; 114 115 if(!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) 116 return false; 117 118 $instatus = self::$decoder->getElementContent(); 119 120 if(!self::$decoder->getElementEndTag()) 121 return false; 122 123 $phase2 = false; 124 } 125 126 if(!self::$decoder->getElementEndTag()) //policy 127 return false; 128 129 if(!self::$decoder->getElementEndTag()) //policies 130 return false; 131 break; 132 133 case SYNC_SETTINGS_DEVICEINFORMATION: 134 // AS14.1 and later clients pass Device Information on the initial Provision request 135 if (!self::$decoder->getElementStartTag(SYNC_SETTINGS_SET)) 136 return false; 137 $deviceInfoSet = true; 138 $deviceinformation = new SyncDeviceInformation(); 139 $deviceinformation->Decode(self::$decoder); 140 $deviceinformation->Status = SYNC_SETTINGSSTATUS_SUCCESS; 141 self::$deviceManager->SaveDeviceInformation($deviceinformation); 142 if (!self::$decoder->getElementEndTag()) // SYNC_SETTINGS_SET 143 return false; 144 if (!self::$decoder->getElementEndTag()) // SYNC_SETTINGS_DEVICEINFORMATION 145 return false; 146 break; 147 148 default: 149 //TODO: a special status code needed? 150 ZLog::Write(LOGLEVEL_WARN, sprintf ("This property ('%s') is not allowed to be used in a provision request", $requestName)); 151 } 152 153 } 154 155 if(!self::$decoder->getElementEndTag()) //provision 156 return false; 157 158 if (PROVISIONING !== true) { 159 ZLog::Write(LOGLEVEL_INFO, "No policies deployed to device"); 160 $policystatus = SYNC_PROVISION_POLICYSTATUS_NOPOLICY; 161 } 162 163 self::$encoder->StartWBXML(); 164 165 //set the new final policy key in the device manager 166 // START ADDED dw2412 Android provisioning fix 167 if (!$phase2) { 168 $policykey = self::$deviceManager->GenerateProvisioningPolicyKey(); 169 self::$deviceManager->SetProvisioningPolicyKey($policykey); 170 self::$topCollector->AnnounceInformation("Policies deployed", true); 171 } 172 else { 173 // just create a temporary key (i.e. iPhone OS4 Beta does not like policykey 0 in response) 174 $policykey = self::$deviceManager->GenerateProvisioningPolicyKey(); 175 } 176 // END ADDED dw2412 Android provisioning fix 177 178 self::$encoder->startTag(SYNC_PROVISION_PROVISION); 179 { 180 self::$encoder->startTag(SYNC_PROVISION_STATUS); 181 self::$encoder->content($status); 182 self::$encoder->endTag(); 183 184 if ($deviceInfoSet) { 185 self::$encoder->startTag(SYNC_SETTINGS_DEVICEINFORMATION); 186 self::$encoder->startTag(SYNC_SETTINGS_STATUS); 187 self::$encoder->content($deviceinformation->Status); 188 self::$encoder->endTag(); //SYNC_SETTINGS_STATUS 189 self::$encoder->endTag(); //SYNC_SETTINGS_DEVICEINFORMATION 190 } 191 192 self::$encoder->startTag(SYNC_PROVISION_POLICIES); 193 self::$encoder->startTag(SYNC_PROVISION_POLICY); 194 195 if(isset($policytype)) { 196 self::$encoder->startTag(SYNC_PROVISION_POLICYTYPE); 197 self::$encoder->content($policytype); 198 self::$encoder->endTag(); 199 } 200 201 self::$encoder->startTag(SYNC_PROVISION_STATUS); 202 self::$encoder->content($policystatus); 203 self::$encoder->endTag(); 204 205 self::$encoder->startTag(SYNC_PROVISION_POLICYKEY); 206 self::$encoder->content($policykey); 207 self::$encoder->endTag(); 208 209 if ($phase2 && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { 210 self::$encoder->startTag(SYNC_PROVISION_DATA); 211 if ($policytype == 'MS-WAP-Provisioning-XML') { 212 self::$encoder->content('<wap-provisioningdoc><characteristic type="SecurityPolicy"><parm name="4131" value="1"/><parm name="4133" value="1"/></characteristic></wap-provisioningdoc>'); 213 } 214 elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { 215 self::$encoder->startTag(SYNC_PROVISION_EASPROVISIONDOC); 216 217 // get the provisioning object and log the loaded policy values 218 $prov = self::$deviceManager->GetProvisioningObject(true); 219 if (!$prov->Check()) 220 throw new FatalException("Invalid policies!"); 221 222 self::$deviceManager->SavePolicyHashAndName($prov); 223 $prov->Encode(self::$encoder); 224 self::$encoder->endTag(); 225 } 226 else { 227 ZLog::Write(LOGLEVEL_WARN, "Wrong policy type"); 228 self::$topCollector->AnnounceInformation("Policytype not supported", true); 229 return false; 230 } 231 self::$topCollector->AnnounceInformation("Updated provisiong", true); 232 233 self::$encoder->endTag();//data 234 } 235 self::$encoder->endTag();//policy 236 self::$encoder->endTag(); //policies 237 } 238 239 //wipe data if a higher RWSTATUS is requested 240 if ($rwstatus > SYNC_PROVISION_RWSTATUS_OK && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { 241 self::$encoder->startTag(SYNC_PROVISION_REMOTEWIPE, false, true); 242 self::$deviceManager->SetProvisioningWipeStatus(($rwstatusWiped)?SYNC_PROVISION_RWSTATUS_WIPED:SYNC_PROVISION_RWSTATUS_REQUESTED); 243 self::$topCollector->AnnounceInformation(sprintf("Remote wipe %s", ($rwstatusWiped)?"executed":"requested"), true); 244 } 245 246 self::$encoder->endTag();//provision 247 248 return true; 249 } 250} 251