| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | include_once 'util.php'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | require_once 'class.certificate.php'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | // Green, everything was good | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | define('SMIME_STATUS_SUCCESS', 0); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | // Orange, CA is missing or OCSP is not available | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | define('SMIME_STATUS_PARTIAL', 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | // Red, something really went wrong | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | define('SMIME_STATUS_FAIL', 2); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | // Blue, info message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | define('SMIME_STATUS_INFO', 3); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | define('SMIME_SUCCESS', 0); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | define('SMIME_NOPUB', 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | define('SMIME_CERT_EXPIRED', 2); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | define('SMIME_ERROR', 3); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | define('SMIME_REVOKED', 4); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | define('SMIME_CA', 5); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | define('SMIME_DECRYPT_SUCCESS', 6); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | define('SMIME_DECRYPT_FAILURE', 7); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | define('SMIME_UNLOCK_CERT', 8); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | define('SMIME_OCSP_NOSUPPORT', 9); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | define('SMIME_OCSP_DISABLED', 10); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | define('SMIME_OCSP_FAILED', 11); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | define('SMIME_DECRYPT_CERT_MISMATCH', 12); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | define('SMIME_USER_DETECT_FAILURE', 13); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | // OpenSSL Error Constants | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | // openssl_error_string() returns error codes when an operation fails, since we return custom error strings | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | // in our plugin we keep a list of openssl error codes in these defines | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | define('OPENSSL_CA_VERIFY_FAIL', '21075075'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | define('OPENSSL_RECIPIENT_CERTIFICATE_MISMATCH', '21070073'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | class Pluginsmime extends Plugin { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  | 	 * decrypted/verified message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | 	private $message = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  | 	 * Default MAPI Message Store. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | 	private $store; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  | 	 * Last openssl error string. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | 	private $openssl_error = ""; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | 	 * Cipher to use. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | 	private $cipher = PLUGIN_SMIME_CIPHER; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | 	 * Called to initialize the plugin and register for hooks. | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 59 |  |  | 	 */ | 
            
                                                                        
                            
            
                                    
            
            
                | 60 |  |  | 	public function init() { | 
            
                                                                        
                            
            
                                    
            
            
                | 61 |  |  | 		$this->registerHook('server.core.settings.init.before'); | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  | 		$this->registerHook('server.util.parse_smime.signed'); | 
            
                                                                        
                            
            
                                    
            
            
                | 63 |  |  | 		$this->registerHook('server.util.parse_smime.encrypted'); | 
            
                                                                        
                            
            
                                    
            
            
                | 64 |  |  | 		$this->registerHook('server.module.itemmodule.open.after'); | 
            
                                                                        
                            
            
                                    
            
            
                | 65 |  |  | 		$this->registerHook('server.core.operations.submitmessage'); | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  | 		$this->registerHook('server.upload_attachment.upload'); | 
            
                                                                        
                            
            
                                    
            
            
                | 67 |  |  | 		$this->registerHook('server.module.createmailitemmodule.beforesend'); | 
            
                                                                        
                            
            
                                    
            
            
                | 68 |  |  | 		$this->registerHook('server.index.load.custom'); | 
            
                                                                        
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 70 |  |  | 		if (version_compare(phpversion(), '5.4', '<')) { | 
            
                                                                        
                            
            
                                    
            
            
                | 71 |  |  | 			$this->cipher = OPENSSL_CIPHER_AES_256_CBC; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  | 	 * Default message store. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  | 	 * @return object MAPI Message store | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  | 	public function getStore() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  | 		if (!$this->store) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  | 			$this->store = $GLOBALS['mapisession']->getDefaultMessageStore(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  | 		return $this->store; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  | 	 * Process the incoming events that where fired by the client. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  | 	 * @param string $eventID Identifier of the hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  | 	 * @param array  $data    Reference to the data of the triggered hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  | 	public function execute($eventID, &$data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  | 		switch ($eventID) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  | 			// Register plugin | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  | 			case 'server.core.settings.init.before': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  | 				$this->onBeforeSettingsInit($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  | 				// Verify a signed or encrypted message when an email is opened | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  | 			case 'server.util.parse_smime.signed': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  | 				$this->onSignedMessage($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  | 			case 'server.util.parse_smime.encrypted': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  | 				$this->onEncrypted($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  | 				// Add S/MIME property, which is send to the client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  | 			case 'server.module.itemmodule.open.after': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  | 				$this->onAfterOpen($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  | 				// Catch uploaded certificate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  | 			case 'server.upload_attachment.upload': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  | 				$this->onUploadCertificate($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  | 				// Sign email before sending | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  | 			case 'server.core.operations.submitmessage': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  | 				$this->onBeforeSend($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  | 				// Verify that we have public certificates for all recipients | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  | 			case 'server.module.createmailitemmodule.beforesend': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | 				$this->onCertificateCheck($data); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  | 			case 'server.index.load.custom': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  | 				if ($data['name'] === 'smime_passphrase') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  | 					include 'templates/passphrase.tpl.php'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  | 					exit; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  | 				if ($data['name'] === 'smime_passphrasecheck') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  | 					// No need to do anything, this is just used to trigger | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  | 					// the browser's autofill save password dialog. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  | 					exit; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  | 	 * Function checks if public certificate exists for all recipients and creates an error | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  | 	 * message for the frontend which includes the email address of the missing public | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  | 	 * certificates. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  | 	 * If my own certificate is missing, a different error message is shown which informs the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  | 	 * user that his own public certificate is missing and required for reading encrypted emails | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  | 	 * in the 'Sent items' folder. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  | 	 * @param array $data Reference to the data of the triggered hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  | 	public function onCertificateCheck($data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  | 		$entryid = $data['entryid']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  | 		// FIXME: unittests, save trigger will pass $entryid is 0 (which will open the root folder and not the message we want) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  | 		if ($entryid === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  | 		if (!isset($data['action']['props']['smime']) || empty($data['action']['props']['smime'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  | 		$message = mapi_msgstore_openentry($data['store'], $entryid); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  | 		$module = $data['moduleObject']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  | 		$data['success'] = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  | 		$messageClass = mapi_getprops($message, [PR_MESSAGE_CLASS]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  | 		$messageClass = $messageClass[PR_MESSAGE_CLASS]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  | 		if ($messageClass !== 'IPM.Note.SMIME' && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  | 			$messageClass !== 'IPM.Note.SMIME.SignedEncrypt' && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  | 			$messageClass !== 'IPM.Note.deferSMIME' && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  | 			$messageClass !== 'IPM.Note.deferSMIME.SignedEncrypt') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  | 		$recipients = $data['action']['props']['smime']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  | 		$missingCerts = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  | 		foreach ($recipients as $recipient) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  | 			$email = $recipient['email']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  | 			if (!$this->pubcertExists($email, $recipient['internal'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  | 				array_push($missingCerts, $email); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  | 		if (empty($missingCerts)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  | 		function missingMyself($email) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  | 			return $GLOBALS['mapisession']->getSMTPAddress() === $email; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  | 		if (array_filter($missingCerts, "missingMyself") === []) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  | 			$errorMsg = _('Missing public certificates for the following recipients: ') . implode(', ', $missingCerts) . _('. Please contact your system administrator for details'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  | 		else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  | 			$errorMsg = _("Your public certificate is not installed. Without this certificate, you will not be able to read encrypted messages you have sent to others."); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  | 		$module->sendFeedback(false, ["type" => ERROR_GENERAL, "info" => ['display_message' => $errorMsg]]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  | 		$data['success'] = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  | 	 * Function which verifies a message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  | 	 * TODO: Clean up flow | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  | 	 * @param mixed $message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  | 	 * @param mixed $eml | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  | 	public function verifyMessage($message, $eml) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  | 		$userProps = mapi_getprops($message, [PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_NAME]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  | 		$tmpUserCert = $this->createTempFile('smime_cert_'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  | 		$tmpMessageFile = $this->createTempFile('smime_msg_'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  | 		$tmpOutCert = $this->createTempFile('smime_out_'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  | 		file_put_contents($tmpMessageFile, $eml); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  | 		[$fromGAB, $availableCerts] = $this->collectGabCertificate($userProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  | 		if (!$fromGAB && isset($GLOBALS['operations'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  | 			$emailAddr = $this->resolveSenderEmail($message, $userProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  | 			if (!empty($emailAddr)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  | 				$availableCerts = array_merge($availableCerts, $this->getUserStoreCertificates($emailAddr)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  | 		try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  | 			$verification = $this->verifyUsingCertificates($availableCerts, $tmpMessageFile, $tmpOutCert, $tmpUserCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  | 			if ($verification['status'] === 'retry') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  | 				$verification = $this->verifyUsingMessageCertificate($tmpMessageFile, $tmpOutCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  | 			if ($verification['status'] === 'import' && !$fromGAB && !empty($verification['parsedImportCert'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  | 				$this->importVerifiedCertificate($verification['importCert'], $verification['parsedImportCert']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  | 		finally { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  | 			$this->cleanupTempFiles([$tmpOutCert, $tmpMessageFile, $tmpUserCert]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  | 	 * Retrieve public certificate from the GAB when available for the sender. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  | 	 * @param array $userProps Sender related MAPI properties. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  | 	 * @return array Two-element array with GAB flag and certificate list. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  | 	private function collectGabCertificate(array $userProps) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  | 		$certificates = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  | 		$fromGAB = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  | 		if (!isset($userProps[PR_SENT_REPRESENTING_ENTRYID])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  | 			return [$fromGAB, $certificates]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  | 		try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  | 			$user = mapi_ab_openentry($GLOBALS['mapisession']->getAddressbook(), $userProps[PR_SENT_REPRESENTING_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  | 			$gabCert = $this->getGABCert($user); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  | 			if (!empty($gabCert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  | 				$fromGAB = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  | 				$certificates[] = $gabCert; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  | 		catch (MAPIException $exception) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  | 			$exception->setHandled(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  | 			$msg = "[smime] Unable to open PR_SENT_REPRESENTING_ENTRYID. Maybe %s was does not exists or deleted from server."; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  | 			Log::write(LOGLEVEL_ERROR, sprintf($msg, $userProps[PR_SENT_REPRESENTING_NAME] ?? '')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  | 			error_log("[smime] Unable to open PR_SENT_REPRESENTING_NAME: " . var_export($userProps[PR_SENT_REPRESENTING_NAME] ?? null, true)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  | 			$this->message['success'] = SMIME_NOPUB; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  | 			$this->message['info'] = SMIME_USER_DETECT_FAILURE; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  | 		return [$fromGAB, $certificates]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  | 	 * Derive sender SMTP address through message or fallback properties. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  | 	 * @param mixed $message MAPI message resource. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  | 	 * @param array $userProps Sender related MAPI properties. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  | 	 * @return string|null SMTP address when resolved, null otherwise. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  | 	private function resolveSenderEmail($message, array $userProps) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  | 		$senderAddressArray = $this->getSenderAddress($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  | 		$senderProps = $senderAddressArray['props'] ?? []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  | 		$addressType = $senderProps['address_type'] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  | 		$emailAddr = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  | 		if ($addressType === 'SMTP') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  | 			$emailAddr = $senderProps['email_address'] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  | 		else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  | 			$emailAddr = $senderProps['smtp_address'] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  | 		if (!empty($emailAddr)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  | 			return $emailAddr; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  | 		if (!empty($userProps[PR_SENT_REPRESENTING_NAME])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  | 			return $userProps[PR_SENT_REPRESENTING_NAME]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  | 		$searchKeys = mapi_getprops($message, [PR_SEARCH_KEY, PR_SENT_REPRESENTING_SEARCH_KEY]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  | 		$searchKey = $searchKeys[PR_SEARCH_KEY] ?? $searchKeys[PR_SENT_REPRESENTING_SEARCH_KEY] ?? null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  | 		if ($searchKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  | 			$parts = explode(':', (string) $searchKey, 2); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  | 			if (count($parts) === 2) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  | 				return trim(strtolower($parts[1])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  | 		return null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  | 	 * Fetch and decode public certificates stored in the user store for an address. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  | 	 * @param string $emailAddr SMTP address of the sender. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  | 	 * @return array List of decoded certificates. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  | 	private function getUserStoreCertificates($emailAddr) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  | 		$userCerts = $this->getPublicKey($emailAddr, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  | 		if (!is_array($userCerts)) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  | 			return []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  | 		$decoded = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  | 		foreach ($userCerts as $cert) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  | 			$decodedCert = base64_decode((string) $cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  | 			if (!empty($decodedCert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  | 				$decoded[] = $decodedCert; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  | 		return $decoded; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  | 	 * Attempt verification using certificates already known to the system. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  | 	 * @param array  $certs        Candidate certificates in PEM format. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  | 	 * @param string $messageFile  Temporary file containing the message payload. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  | 	 * @param string $outCertFile  Temporary file to receive the extracted certificate. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  | 	 * @param string $tmpUserCert  Temporary file for passing certificates to OpenSSL. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  | 	 * @return array Verification result metadata. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  | 	private function verifyUsingCertificates(array $certs, $messageFile, $outCertFile, $tmpUserCert) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  | 		if (empty($certs)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  | 			return ['status' => 'retry', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => null]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 364 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 365 |  |  | 		$caBundle = explode(';', PLUGIN_SMIME_CACERTS); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 366 |  |  | 		$caCerts = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 367 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 368 |  |  | 		foreach ($certs as $cert) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 369 |  |  | 			if (empty($cert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 370 |  |  | 				continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 371 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 372 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 373 |  |  | 			file_put_contents($tmpUserCert, $cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 374 |  |  | 			$this->clear_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 375 |  |  | 			$signedOk = openssl_pkcs7_verify($messageFile, PKCS7_NOINTERN, $outCertFile, $caBundle, $tmpUserCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 376 |  |  | 			$opensslError = $this->extract_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 377 |  |  | 			$this->validateSignedMessage($signedOk, $opensslError); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 378 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 379 |  |  | 			if (!$signedOk || $opensslError === OPENSSL_CA_VERIFY_FAIL) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 380 |  |  | 				continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 381 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 382 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 383 |  |  | 			$importCert = file_get_contents($outCertFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 384 |  |  | 			if ($importCert === false || $importCert === '') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 385 |  |  | 				continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 386 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 387 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 388 |  |  | 			$parsedImport = openssl_x509_parse($importCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 389 |  |  | 			$parsedUser = openssl_x509_parse($cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 390 |  |  | 			$caCerts = $caCerts ?? $this->extractCAs($messageFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 391 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 392 |  |  | 			if ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 393 |  |  | 				is_array($parsedImport) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 394 |  |  | 				is_array($parsedUser) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 395 |  |  | 				($parsedImport['validTo'] ?? '') > ($parsedUser['validTo'] ?? '') && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 396 |  |  | 				($parsedImport['validFrom'] ?? '') > ($parsedUser['validFrom'] ?? '') && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 397 |  |  | 				getCertEmail($parsedImport) === getCertEmail($parsedUser) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 398 |  |  | 				verifyOCSP($importCert, $caCerts, $this->message) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 399 |  |  | 			) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 400 |  |  | 				return [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 401 |  |  | 					'status' => 'import', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 402 |  |  | 					'importCert' => $importCert, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 403 |  |  | 					'parsedImportCert' => $parsedImport, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 404 |  |  | 					'caCerts' => $caCerts, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 405 |  |  | 				]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 406 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 407 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 408 |  |  | 			verifyOCSP($cert, $caCerts, $this->message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 409 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 410 |  |  | 			return ['status' => 'skip', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => $caCerts]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 411 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 412 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 413 |  |  | 		return ['status' => 'retry', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => null]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 414 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 415 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 416 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 417 |  |  | 	 * Fallback verification that relies on the certificate bundled with the message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 418 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 419 |  |  | 	 * @param string $messageFile Temporary file containing the message payload. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 420 |  |  | 	 * @param string $outCertFile Temporary file for certificate extraction. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 421 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 422 |  |  | 	 * @return array Verification result metadata. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 423 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 424 |  |  | 	private function verifyUsingMessageCertificate($messageFile, $outCertFile) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 425 |  |  | 		$caBundle = explode(';', PLUGIN_SMIME_CACERTS); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 426 |  |  | 		$this->clear_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 427 |  |  | 		$signedOk = openssl_pkcs7_verify($messageFile, PKCS7_NOSIGS, $outCertFile, $caBundle); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 428 |  |  | 		$opensslError = $this->extract_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 429 |  |  | 		$this->validateSignedMessage($signedOk, $opensslError); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 430 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 431 |  |  | 		if (!$signedOk || $opensslError === OPENSSL_CA_VERIFY_FAIL) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 432 |  |  | 			$this->handleMissingPublicKey(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 433 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 434 |  |  | 			return ['status' => 'skip', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => null]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 435 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 436 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 437 |  |  | 		$importCert = file_get_contents($outCertFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 438 |  |  | 		if ($importCert === false || $importCert === '') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 439 |  |  | 			return ['status' => 'skip', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => null]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 440 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 441 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 442 |  |  | 		$parsedImport = openssl_x509_parse($importCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 443 |  |  | 		$caCerts = $this->extractCAs($messageFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 444 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 445 |  |  | 		if (!is_array($parsedImport) || !verifyOCSP($importCert, $caCerts, $this->message)) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 446 |  |  | 			return ['status' => 'skip', 'importCert' => null, 'parsedImportCert' => null, 'caCerts' => $caCerts]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 447 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 448 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 449 |  |  | 		return ['status' => 'import', 'importCert' => $importCert, 'parsedImportCert' => $parsedImport, 'caCerts' => $caCerts]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 450 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 451 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 452 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 453 |  |  | 	 * Import a verified certificate into the user store with force-overwrite semantics. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 454 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 455 |  |  | 	 * @param string $rawCertificate Certificate body in PEM format. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 456 |  |  | 	 * @param array  $parsedCertificate Parsed certificate meta data from OpenSSL. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 457 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 458 |  |  | 	private function importVerifiedCertificate($rawCertificate, array $parsedCertificate) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 459 |  |  | 		$certEmail = getCertEmail($parsedCertificate); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 460 |  |  | 		if (!empty($certEmail)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 461 |  |  | 			$this->importCertificate($rawCertificate, $parsedCertificate, 'public', true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 462 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 463 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 464 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 465 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 466 |  |  | 	 * Record diagnostics when a message cannot be verified due to missing keys. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 467 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 468 |  |  | 	private function handleMissingPublicKey() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 469 |  |  | 		Log::write(LOGLEVEL_INFO, sprintf("[smime] Unable to verify message without public key, openssl error: '%s'", $this->openssl_error)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 470 |  |  | 		$this->message['success'] = SMIME_STATUS_FAIL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 471 |  |  | 		$this->message['info'] = SMIME_CA; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 472 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 473 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 474 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 475 |  |  | 	 * Remove temporary files with defensive existence checks. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 476 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 477 |  |  | 	 * @param array $paths Paths scheduled for cleanup. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 478 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 479 |  |  | 	private function cleanupTempFiles(array $paths) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 480 |  |  | 		foreach ($paths as $path) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 481 |  |  | 			if (is_string($path) && $path !== '' && file_exists($path)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 482 |  |  | 				@unlink($path); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 483 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 484 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 485 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 486 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 487 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 488 |  |  | 	 * Create a unique temp file using the supplied prefix. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 489 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 490 |  |  | 	 * @param string $prefix File name prefix. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 491 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 492 |  |  | 	 * @return string Path to the created temp file. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 493 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 494 |  |  | 	private function createTempFile($prefix) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 495 |  |  | 		return tempnam(sys_get_temp_dir(), $prefix); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 496 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 497 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 498 |  |  | 	public function join_xph(&$prop, $msg) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 499 |  |  | 		$a = mapi_getprops($msg, [PR_TRANSPORT_MESSAGE_HEADERS]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 500 |  |  | 		$a = $a === false ? "" : ($a[PR_TRANSPORT_MESSAGE_HEADERS] ?? ""); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 501 |  |  | 		$prop[PR_TRANSPORT_MESSAGE_HEADERS] = | 
            
                                                                                                            
                            
            
                                    
            
            
                | 502 |  |  | 			"# Outer headers:\n" . ($prop[PR_TRANSPORT_MESSAGE_HEADERS] ?? "") . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 503 |  |  | 			"# Inner headers:\n" . $a; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 504 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 505 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 506 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 507 |  |  | 	 * Function which decrypts an encrypted message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 508 |  |  | 	 * The key should be unlocked and stored in the EncryptionStore for a successful decrypt | 
            
                                                                                                            
                            
            
                                    
            
            
                | 509 |  |  | 	 * If the key isn't in the session, we give the user a message to unlock his certificate. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 510 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 511 |  |  | 	 * @param mixed $data array of data from hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 512 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 513 |  |  | 	public function onEncrypted($data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 514 |  |  | 		// Cert unlocked, decode message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 515 |  |  | 		$this->message['success'] = SMIME_STATUS_INFO; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 516 |  |  | 		$this->message['info'] = SMIME_DECRYPT_FAILURE; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 517 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 518 |  |  | 		$this->message['type'] = 'encrypted'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 519 |  |  | 		$encryptionStore = EncryptionStore::getInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 520 |  |  | 		$pass = $encryptionStore->get('smime'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 521 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 522 |  |  | 		$tmpFile = tempnam(sys_get_temp_dir(), true); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 523 |  |  | 		// Write mime header. Because it's not provided in the attachment, otherwise openssl won't parse it | 
            
                                                                                                            
                            
            
                                    
            
            
                | 524 |  |  | 		$fp = fopen($tmpFile, 'w'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 525 |  |  | 		fwrite($fp, "Content-Type: application/pkcs7-mime; name=\"smime.p7m\"; smime-type=enveloped-data\n"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 526 |  |  | 		fwrite($fp, "Content-Transfer-Encoding: base64\nContent-Disposition: attachment; filename=\"smime.p7m\"\n"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 527 |  |  | 		fwrite($fp, "Content-Description: S/MIME Encrypted Message\n\n"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 528 |  |  | 		fwrite($fp, chunk_split(base64_encode((string) $data['data']), 72) . "\n"); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 529 |  |  | 		fclose($fp); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 530 |  |  | 		if (isset($pass) && !empty($pass)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 531 |  |  | 			$certs = readPrivateCert($this->getStore(), $pass, false); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 532 |  |  | 			// create random file for saving the encrypted and body message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 533 |  |  | 			$tmpDecrypted = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 534 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 535 |  |  | 			$decryptStatus = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 536 |  |  | 			// If multiple private certs were decrypted with supplied password | 
            
                                                                                                            
                            
            
                                    
            
            
                | 537 |  |  | 			if (!$certs['cert'] && count($certs) > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 538 |  |  | 				foreach ($certs as $cert) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 539 |  |  | 					$this->clear_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 540 |  |  | 					$decryptStatus = openssl_pkcs7_decrypt($tmpFile, $tmpDecrypted, $cert['cert'], [$cert['pkey'], $pass]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 541 |  |  | 					if ($decryptStatus !== false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 542 |  |  | 						break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 543 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 544 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 545 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 546 |  |  | 			else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 547 |  |  | 				$this->clear_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 548 |  |  | 				$decryptStatus = openssl_pkcs7_decrypt($tmpFile, $tmpDecrypted, $certs['cert'], [$certs['pkey'], $pass]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 549 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 550 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 551 |  |  | 			$ossl_error = $this->extract_openssl_error(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 552 |  |  | 			$content = file_get_contents($tmpDecrypted); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 553 |  |  | 			// Handle OL empty body Outlook Signed & Encrypted mails. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 554 |  |  | 			// The S/MIME plugin has to extract the body from the signed message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 555 |  |  | 			if (str_contains($content, 'signed-data')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 556 |  |  | 				$this->message['type'] = 'encryptsigned'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 557 |  |  | 				$olcert = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 558 |  |  | 				$olmsg = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 559 |  |  | 				openssl_pkcs7_verify($tmpDecrypted, PKCS7_NOVERIFY, $olcert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 560 |  |  | 				openssl_pkcs7_verify($tmpDecrypted, PKCS7_NOVERIFY, $olcert, [], $olcert, $olmsg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 561 |  |  | 				$content = file_get_contents($olmsg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 562 |  |  | 				unlink($olmsg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 563 |  |  | 				unlink($olcert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 564 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 565 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 566 |  |  | 			$copyProps = mapi_getprops($data['message'], [PR_MESSAGE_DELIVERY_TIME, PR_SENDER_ENTRYID, PR_SENT_REPRESENTING_ENTRYID, PR_TRANSPORT_MESSAGE_HEADERS]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 567 |  |  | 			mapi_inetmapi_imtomapi($GLOBALS['mapisession']->getSession(), $data['store'], $GLOBALS['mapisession']->getAddressbook(), $data['message'], $content, ['parse_smime_signed' => true]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 568 |  |  | 			$this->join_xph($copyProps, $data['message']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 569 |  |  | 			// Manually set time back to the received time, since mapi_inetmapi_imtomapi overwrites this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 570 |  |  | 			mapi_setprops($data['message'], $copyProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 571 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 572 |  |  | 			// remove temporary files | 
            
                                                                                                            
                            
            
                                    
            
            
                | 573 |  |  | 			unlink($tmpFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 574 |  |  | 			unlink($tmpDecrypted); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 575 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 576 |  |  | 			// mapi_inetmapi_imtomapi removes the PR_MESSAGE_CLASS = 'IPM.Note.SMIME.MultipartSigned' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 577 |  |  | 			// So we need to check if the message was also signed by looking at the MIME_TAG in the eml | 
            
                                                                                                            
                            
            
                                    
            
            
                | 578 |  |  | 			if (str_contains($content, 'multipart/signed') || str_contains($content, 'signed-data')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 579 |  |  | 				$this->message['type'] = 'encryptsigned'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 580 |  |  | 				$this->verifyMessage($data['message'], $content); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 581 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 582 |  |  | 			elseif ($decryptStatus) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 583 |  |  | 				$this->message['info'] = SMIME_DECRYPT_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 584 |  |  | 				$this->message['success'] = SMIME_STATUS_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 585 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 586 |  |  | 			elseif ($ossl_error === OPENSSL_RECIPIENT_CERTIFICATE_MISMATCH) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 587 |  |  | 				error_log("[smime] Error when decrypting email, openssl error: " . print_r($this->openssl_error, true)); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 588 |  |  | 				Log::Write(LOGLEVEL_ERROR, sprintf("[smime] Error when decrypting email, openssl error: '%s'", $this->openssl_error)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 589 |  |  | 				$this->message['info'] = SMIME_DECRYPT_CERT_MISMATCH; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 590 |  |  | 				$this->message['success'] = SMIME_STATUS_FAIL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 591 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 592 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 593 |  |  | 		else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 594 |  |  | 			// it might also be a signed message only. Verify it. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 595 |  |  | 			$msg = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 596 |  |  | 			$ret = openssl_pkcs7_verify($tmpFile, PKCS7_NOVERIFY, null, [], null, $msg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 597 |  |  | 			$content = file_get_contents($msg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 598 |  |  | 			unlink($tmpFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 599 |  |  | 			unlink($msg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 600 |  |  | 			if ($ret === true && !empty($content)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 601 |  |  | 				$copyProps = mapi_getprops($data['message'], [PR_MESSAGE_DELIVERY_TIME, PR_SENDER_ENTRYID, PR_SENT_REPRESENTING_ENTRYID, PR_TRANSPORT_MESSAGE_HEADERS]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 602 |  |  | 				mapi_inetmapi_imtomapi( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 603 |  |  | 					$GLOBALS['mapisession']->getSession(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 604 |  |  | 					$data['store'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 605 |  |  | 					$GLOBALS['mapisession']->getAddressbook(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 606 |  |  | 					$data['message'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 607 |  |  | 					$content, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 608 |  |  | 					['parse_smime_signed' => true] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 609 |  |  | 				); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 610 |  |  | 				$this->join_xph($copyProps, $data['message']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 611 |  |  | 				// Manually set time back to the received time, since mapi_inetmapi_imtomapi overwrites this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 612 |  |  | 				mapi_setprops($data['message'], $copyProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 613 |  |  | 				$this->message['type'] = 'encryptsigned'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 614 |  |  | 				$this->message['info'] = SMIME_DECRYPT_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 615 |  |  | 				$this->message['success'] = SMIME_STATUS_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 616 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 617 |  |  | 			else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 618 |  |  | 				$this->message['info'] = SMIME_UNLOCK_CERT; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 619 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 620 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 621 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 622 |  |  | 		if (!encryptionStoreExpirationSupport()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 623 |  |  | 			withPHPSession(function () use ($encryptionStore) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 624 |  |  | 				$encryptionStore->add('smime', ''); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 625 |  |  | 			}); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 626 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 627 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 628 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 629 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 630 |  |  | 	 * Function which calls verifyMessage to verify if the message isn't malformed during transport. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 631 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 632 |  |  | 	 * @param mixed $data array of data from hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 633 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 634 |  |  | 	public function onSignedMessage($data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 635 |  |  | 		$this->message['type'] = 'signed'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 636 |  |  | 		$this->verifyMessage($data['message'], $data['data']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 637 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 638 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 639 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 640 |  |  | 	 * General function which parses the openssl_pkcs7_verify return value and the errors generated by | 
            
                                                                                                            
                            
            
                                    
            
            
                | 641 |  |  | 	 * openssl_error_string(). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 642 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 643 |  |  | 	 * @param mixed $openssl_return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 644 |  |  | 	 * @param mixed $openssl_errors | 
            
                                                                                                            
                            
            
                                    
            
            
                | 645 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 646 |  |  | 	public function validateSignedMessage($openssl_return, $openssl_errors) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 647 |  |  | 		if ($openssl_return === -1) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 648 |  |  | 			$this->message['info'] = SMIME_ERROR; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 649 |  |  | 			$this->message['success'] = SMIME_STATUS_FAIL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 650 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 651 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 652 |  |  | 			// Verification was successful | 
            
                                                                                                            
                            
            
                                    
            
            
                | 653 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 654 |  |  | 		if ($openssl_return) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 655 |  |  | 			$this->message['info'] = SMIME_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 656 |  |  | 			$this->message['success'] = SMIME_STATUS_SUCCESS; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 657 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 658 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 659 |  |  | 			// Verification was not successful, display extra information. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 660 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 661 |  |  | 		$this->message['success'] = SMIME_STATUS_FAIL; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 662 |  |  | 		if ($openssl_errors === OPENSSL_CA_VERIFY_FAIL) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 663 |  |  | 			$this->message['info'] = SMIME_CA; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 664 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 665 |  |  | 		else { // Catch general errors | 
            
                                                                                                            
                            
            
                                    
            
            
                | 666 |  |  | 			$this->message['info'] = SMIME_ERROR; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 667 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 668 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 669 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 670 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 671 |  |  | 	 * Set smime key in $data array, which is send back to client | 
            
                                                                                                            
                            
            
                                    
            
            
                | 672 |  |  | 	 * Since we can't create this array key in the hooks: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 673 |  |  | 	 * 'server.util.parse_smime.signed' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 674 |  |  | 	 * 'server.util.parse_smime.encrypted'. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 675 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 676 |  |  | 	 * TODO: investigate if we can move away from this hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 677 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 678 |  |  | 	 * @param mixed $data | 
            
                                                                                                            
                            
            
                                    
            
            
                | 679 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 680 |  |  | 	public function onAfterOpen($data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 681 |  |  | 		if (isset($this->message) && !empty($this->message)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 682 |  |  | 			$data['data']['item']['props']['smime'] = $this->message; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 683 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 684 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 685 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 686 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 687 |  |  | 	 * Handles the uploaded certificate in the settingsmenu in grommunio Web | 
            
                                                                                                            
                            
            
                                    
            
            
                | 688 |  |  | 	 * - Opens the certificate with provided passphrase | 
            
                                                                                                            
                            
            
                                    
            
            
                | 689 |  |  | 	 * - Checks if it can be used for signing/decrypting | 
            
                                                                                                            
                            
            
                                    
            
            
                | 690 |  |  | 	 * - Verifies that the email address is equal to the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 691 |  |  | 	 * - Verifies that the certificate isn't expired and inform user. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 692 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 693 |  |  | 	 * @param mixed $data | 
            
                                                                                                            
                            
            
                                    
            
            
                | 694 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 695 |  |  | 	public function onUploadCertificate($data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 696 |  |  | 		if ($data['sourcetype'] !== 'certificate') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 697 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 698 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 699 |  |  | 		$passphrase = $_POST['passphrase']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 700 |  |  | 		$saveCert = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 701 |  |  | 		$tmpname = $data['tmpname']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 702 |  |  | 		$message = ''; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 703 |  |  | 		$imported = false; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 704 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 705 |  |  | 		$certificate = file_get_contents($tmpname); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 706 |  |  | 		$emailAddress = $GLOBALS['mapisession']->getSMTPAddress(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 707 |  |  | 		[$message, $publickey, $publickeyData, $imported] = validateUploadedPKCS($certificate, $passphrase, $emailAddress); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 708 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 709 |  |  | 		// All checks completed successful | 
            
                                                                                                            
                            
            
                                    
            
            
                | 710 |  |  | 		// Store private cert in users associated store (check for duplicates) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 711 |  |  | 		if ($imported) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 712 |  |  | 			$certMessage = getMAPICert($this->getStore()); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 713 |  |  | 			// TODO: update to serialNumber check | 
            
                                                                                                            
                            
            
                                    
            
            
                | 714 |  |  | 			if ($certMessage && $certMessage[0][PR_MESSAGE_DELIVERY_TIME] == $publickeyData['validTo_time_t']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 715 |  |  | 				$message = _('Certificate is already stored on the server'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 716 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 717 |  |  | 			else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 718 |  |  | 				$saveCert = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 719 |  |  | 				$root = mapi_msgstore_openentry($this->getStore()); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 720 |  |  | 				// Remove old certificate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 721 |  |  | 				/* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 722 |  |  | 				if($certMessage) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 723 |  |  | 					// Delete private key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 724 |  |  | 					mapi_folder_deletemessages($root, array($certMessage[PR_ENTRYID])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 725 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 726 |  |  | 					// Delete public key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 727 |  |  | 					$pubCert = getMAPICert($this->getStore, 'WebApp.Security.Public', getCertEmail($certMessage)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 728 |  |  | 					if($pubCert) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 729 |  |  | 						mapi_folder_deletemessages($root, array($pubCert[PR_ENTRYID])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 730 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 731 |  |  | 					$message = _('New certificate uploaded'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 732 |  |  | 				} else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 733 |  |  | 					$message = _('Certificate uploaded'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 734 |  |  | 				}*/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 735 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 736 |  |  | 				$this->importCertificate($certificate, $publickeyData, 'private'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 737 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 738 |  |  | 				// Check if the user has a public key in the GAB. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 739 |  |  | 				$store_props = mapi_getprops($this->getStore(), [PR_USER_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 740 |  |  | 				$user = mapi_ab_openentry($GLOBALS['mapisession']->getAddressbook(), $store_props[PR_USER_ENTRYID]); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 741 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 742 |  |  | 				$this->importCertificate($publickey, $publickeyData, 'public', true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 743 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 744 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 745 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 746 |  |  | 		$returnfiles = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 747 |  |  | 		$returnfiles[] = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 748 |  |  | 			'props' => [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 749 |  |  | 				'attach_num' => -1, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 750 |  |  | 				'size' => $data['size'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 751 |  |  | 				'name' => $data['name'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 752 |  |  | 				'cert' => $saveCert, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 753 |  |  | 				'cert_warning' => $message, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 754 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 755 |  |  | 		]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 756 |  |  | 		$data['returnfiles'] = $returnfiles; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 757 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 758 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 759 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 760 |  |  | 	 * This function handles the 'beforesend' hook which is triggered before sending the email. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 761 |  |  | 	 * If the PR_MESSAGE_CLASS is set to a signed email (IPM.Note.SMIME.Multipartsigned), this function | 
            
                                                                                                            
                            
            
                                    
            
            
                | 762 |  |  | 	 * will convert the mapi message to RFC822, sign the eml and attach the signed email to the mapi message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 763 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 764 |  |  | 	 * @param mixed $data from php hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 765 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 766 |  |  | 	public function onBeforeSend(&$data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 767 |  |  | 		$store = $data['store']; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 768 |  |  | 		$message = $data['message']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 769 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 770 |  |  | 		// Retrieve message class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 771 |  |  | 		$props = mapi_getprops($message, [PR_MESSAGE_CLASS]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 772 |  |  | 		$messageClass = $props[PR_MESSAGE_CLASS]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 773 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 774 |  |  | 		if (!isset($messageClass)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 775 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 776 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 777 |  |  | 		if (stripos((string) $messageClass, 'IPM.Note.deferSMIME') === false && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 778 |  |  | 			stripos((string) $messageClass, 'IPM.Note.SMIME') === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 779 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 780 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 781 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 782 |  |  | 		// FIXME: for now return when we are going to sign but we don't have the passphrase set | 
            
                                                                                                            
                            
            
                                    
            
            
                | 783 |  |  | 		// This should never happen sign | 
            
                                                                                                            
                            
            
                                    
            
            
                | 784 |  |  | 		$encryptionStore = EncryptionStore::getInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 785 |  |  | 		if (($messageClass === 'IPM.Note.deferSMIME.SignedEncrypt' || | 
            
                                                                                                            
                            
            
                                    
            
            
                | 786 |  |  | 			$messageClass === 'IPM.Note.deferSMIME.MultipartSigned' || | 
            
                                                                                                            
                            
            
                                    
            
            
                | 787 |  |  | 			$messageClass === 'IPM.Note.SMIME.SignedEncrypt' || | 
            
                                                                                                            
                            
            
                                    
            
            
                | 788 |  |  | 			$messageClass === 'IPM.Note.SMIME.MultipartSigned') && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 789 |  |  | 			!$encryptionStore->get('smime')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 790 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 791 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 792 |  |  | 		// NOTE: setting message class to IPM.Note, so that mapi_inetmapi_imtoinet converts the message to plain email | 
            
                                                                                                            
                            
            
                                    
            
            
                | 793 |  |  | 		// and doesn't fail when handling the attachments. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 794 |  |  | 		mapi_setprops($message, [PR_MESSAGE_CLASS => 'IPM.Note']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 795 |  |  | 		mapi_savechanges($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 796 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 797 |  |  | 		// Read the message as RFC822-formatted e-mail stream. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 798 |  |  | 		$emlMessageStream = mapi_inetmapi_imtoinet($GLOBALS['mapisession']->getSession(), $GLOBALS['mapisession']->getAddressbook(), $message, []); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 799 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 800 |  |  | 		// Remove all attachments, since they are stored in the attached signed message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 801 |  |  | 		$atable = mapi_message_getattachmenttable($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 802 |  |  | 		$rows = mapi_table_queryallrows($atable, [PR_ATTACH_MIME_TAG, PR_ATTACH_NUM]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 803 |  |  | 		foreach ($rows as $row) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 804 |  |  | 			$attnum = $row[PR_ATTACH_NUM]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 805 |  |  | 			mapi_message_deleteattach($message, $attnum); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 806 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 807 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 808 |  |  | 		// create temporary files | 
            
                                                                                                            
                            
            
                                    
            
            
                | 809 |  |  | 		$tmpSendEmail = tempnam(sys_get_temp_dir(), true); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 810 |  |  | 		$tmpSendSmimeEmail = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 811 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 812 |  |  | 		// Save message stream to a file | 
            
                                                                                                            
                            
            
                                    
            
            
                | 813 |  |  | 		$stat = mapi_stream_stat($emlMessageStream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 814 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 815 |  |  | 		$fhandle = fopen($tmpSendEmail, 'w'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 816 |  |  | 		$buffer = null; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 817 |  |  | 		for ($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 818 |  |  | 			// Write stream | 
            
                                                                                                            
                            
            
                                    
            
            
                | 819 |  |  | 			$buffer = mapi_stream_read($emlMessageStream, BLOCK_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 820 |  |  | 			fwrite($fhandle, $buffer, strlen($buffer)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 821 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 822 |  |  | 		fclose($fhandle); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 823 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 824 |  |  | 		// Create attachment for S/MIME message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 825 |  |  | 		$signedAttach = mapi_message_createattach($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 826 |  |  | 		$smimeProps = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 827 |  |  | 			PR_ATTACH_LONG_FILENAME => 'smime.p7m', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 828 |  |  | 			PR_DISPLAY_NAME => 'smime.p7m', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 829 |  |  | 			PR_ATTACH_METHOD => ATTACH_BY_VALUE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 830 |  |  | 			PR_ATTACH_MIME_TAG => 'multipart/signed', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 831 |  |  | 			PR_ATTACHMENT_HIDDEN => true, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 832 |  |  | 		]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 833 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 834 |  |  | 		// Sign then Encrypt email | 
            
                                                                                                            
                            
            
                                    
            
            
                | 835 |  |  | 		switch ($messageClass) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 836 |  |  | 			case 'IPM.Note.deferSMIME.SignedEncrypt': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 837 |  |  | 			case 'IPM.Note.SMIME.SignedEncrypt': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 838 |  |  | 				$tmpFile = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 839 |  |  | 				$this->sign($tmpSendEmail, $tmpFile, $message, $signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 840 |  |  | 				$this->encrypt($tmpFile, $tmpSendSmimeEmail, $message, $signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 841 |  |  | 				unlink($tmpFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 842 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 843 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 844 |  |  | 			case 'IPM.Note.deferSMIME.MultipartSigned': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 845 |  |  | 			case 'IPM.Note.SMIME.MultipartSigned': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 846 |  |  | 				$this->sign($tmpSendEmail, $tmpSendSmimeEmail, $message, $signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 847 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 848 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 849 |  |  | 			case 'IPM.Note.deferSMIME': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 850 |  |  | 			case 'IPM.Note.SMIME': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 851 |  |  | 				$this->encrypt($tmpSendEmail, $tmpSendSmimeEmail, $message, $signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 852 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 853 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 854 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 855 |  |  | 		// Save the signed message as attachment of the send email | 
            
                                                                                                            
                            
            
                                    
            
            
                | 856 |  |  | 		$stream = mapi_openproperty($signedAttach, PR_ATTACH_DATA_BIN, IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 857 |  |  | 		$handle = fopen($tmpSendSmimeEmail, 'r'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 858 |  |  | 		while (!feof($handle)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 859 |  |  | 			$contents = fread($handle, BLOCK_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 860 |  |  | 			mapi_stream_write($stream, $contents); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 861 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 862 |  |  | 		fclose($handle); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 863 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 864 |  |  | 		mapi_stream_commit($stream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 865 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 866 |  |  | 		// remove tmp files | 
            
                                                                                                            
                            
            
                                    
            
            
                | 867 |  |  | 		unlink($tmpSendSmimeEmail); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 868 |  |  | 		unlink($tmpSendEmail); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 869 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 870 |  |  | 		mapi_savechanges($signedAttach); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 871 |  |  | 		mapi_savechanges($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 872 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 873 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 874 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 875 |  |  | 	 * Function to sign an email. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 876 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 877 |  |  | 	 * @param string $infile       File eml to be encrypted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 878 |  |  | 	 * @param string $outfile      File | 
            
                                                                                                            
                            
            
                                    
            
            
                | 879 |  |  | 	 * @param object $message      Mapi Message Object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 880 |  |  | 	 * @param object $signedAttach | 
            
                                                                                                            
                            
            
                                    
            
            
                | 881 |  |  | 	 * @param array  $smimeProps | 
            
                                                                                                            
                            
            
                                    
            
            
                | 882 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 883 |  |  | 	public function sign(&$infile, &$outfile, &$message, &$signedAttach, $smimeProps) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 884 |  |  | 		// Set mesageclass back to IPM.Note.SMIME.MultipartSigned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 885 |  |  | 		mapi_setprops($message, [PR_MESSAGE_CLASS => 'IPM.Note.SMIME.MultipartSigned']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 886 |  |  | 		mapi_setprops($signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 887 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 888 |  |  | 		// Obtain private certificate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 889 |  |  | 		$encryptionStore = EncryptionStore::getInstance(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 890 |  |  | 		// Only the newest one is returned | 
            
                                                                                                            
                            
            
                                    
            
            
                | 891 |  |  | 		$certs = readPrivateCert($this->getStore(), $encryptionStore->get('smime')); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 892 |  |  | 		// Retrieve intermediate CA's for verification, if available | 
            
                                                                                                            
                            
            
                                    
            
            
                | 893 |  |  | 		$flags = PKCS7_DETACHED | PKCS7_TEXT; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 894 |  |  | 		if (isset($certs['extracerts'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 895 |  |  | 			$tmpFile = tempnam(sys_get_temp_dir(), true); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 896 |  |  | 			file_put_contents($tmpFile, implode('', $certs['extracerts'])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 897 |  |  | 			$ok = openssl_pkcs7_sign($infile, $outfile, $certs['cert'], [$certs['pkey'], ''], [], $flags, $tmpFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 898 |  |  | 			if (!$ok) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 899 |  |  | 				Log::Write(LOGLEVEL_ERROR, sprintf("[smime] Unable to sign message with intermediate certificates, openssl error: '%s'", @openssl_error_string())); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 900 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 901 |  |  | 			unlink($tmpFile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 902 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 903 |  |  | 		else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 904 |  |  | 			$ok = openssl_pkcs7_sign($infile, $outfile, $certs['cert'], [$certs['pkey'], ''], [], $flags); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 905 |  |  | 			if (!$ok) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 906 |  |  | 				Log::Write(LOGLEVEL_ERROR, sprintf("[smime] Unable to sign message, openssl error: '%s'", @openssl_error_string())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 907 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 908 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 909 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 910 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 911 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 912 |  |  | 	 * Function to encrypt an email. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 913 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 914 |  |  | 	 * @param string $infile       File eml to be encrypted | 
            
                                                                                                            
                            
            
                                    
            
            
                | 915 |  |  | 	 * @param string $outfile      File | 
            
                                                                                                            
                            
            
                                    
            
            
                | 916 |  |  | 	 * @param object $message      Mapi Message Object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 917 |  |  | 	 * @param object $signedAttach | 
            
                                                                                                            
                            
            
                                    
            
            
                | 918 |  |  | 	 * @param array  $smimeProps | 
            
                                                                                                            
                            
            
                                    
            
            
                | 919 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 920 |  |  | 	public function encrypt(&$infile, &$outfile, &$message, &$signedAttach, $smimeProps) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 921 |  |  | 		mapi_setprops($message, [PR_MESSAGE_CLASS => 'IPM.Note.SMIME']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 922 |  |  | 		$smimeProps[PR_ATTACH_MIME_TAG] = "application/pkcs7-mime"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 923 |  |  | 		mapi_setprops($signedAttach, $smimeProps); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 924 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 925 |  |  | 		$publicCerts = $this->getPublicKeyForMessage($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 926 |  |  | 		// Always append our own certificate, so that the mail can be decrypted in 'Sent items' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 927 |  |  | 		// Prefer GAB public certificate above MAPI Store certificate. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 928 |  |  | 		$email = $GLOBALS['mapisession']->getSMTPAddress(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 929 |  |  | 		$user = $this->getGABUser($email); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 930 |  |  | 		$cert = $this->getGABCert($user); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 931 |  |  | 		if (empty($cert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 932 |  |  | 			$cert = base64_decode($this->getPublicKey($email)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 933 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 934 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 935 |  |  | 		if (!empty($cert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 936 |  |  | 			array_push($publicCerts, $cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 937 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 938 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 939 |  |  | 		$ok = openssl_pkcs7_encrypt($infile, $outfile, $publicCerts, [], 0, $this->cipher); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 940 |  |  | 		if (!$ok) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 941 |  |  | 			error_log("[smime] unable to encrypt message, openssl error: " . print_r(@openssl_error_string(), true)); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 942 |  |  | 			Log::Write(LOGLEVEL_ERROR, sprintf("[smime] unable to encrypt message, openssl error: '%s'", @openssl_error_string())); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 943 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 944 |  |  | 		$tmpEml = file_get_contents($outfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 945 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 946 |  |  | 		// Grab the base64 data, since MAPI requires it saved as decoded base64 string. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 947 |  |  | 		// FIXME: we can do better here | 
            
                                                                                                            
                            
            
                                    
            
            
                | 948 |  |  | 		$matches = explode("\n\n", $tmpEml); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 949 |  |  | 		$base64 = str_replace("\n", "", $matches[1]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 950 |  |  | 		file_put_contents($outfile, base64_decode($base64)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 951 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 952 |  |  | 		// Empty the body | 
            
                                                                                                            
                            
            
                                    
            
            
                | 953 |  |  | 		mapi_setprops($message, [PR_BODY => ""]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 954 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 955 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 956 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 957 |  |  | 	 * Function which fetches the public certificates for all recipients (TO/CC/BCC) of a message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 958 |  |  | 	 * Always get the certificate of an address which expires last. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 959 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 960 |  |  | 	 * @param object $message Mapi Message Object | 
            
                                                                                                            
                            
            
                                    
            
            
                | 961 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 962 |  |  | 	 * @return array of public certificates | 
            
                                                                                                            
                            
            
                                    
            
            
                | 963 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 964 |  |  | 	public function getPublicKeyForMessage($message) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 965 |  |  | 		$recipientTable = mapi_message_getrecipienttable($message); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 966 |  |  | 		$recips = mapi_table_queryallrows($recipientTable, [PR_SMTP_ADDRESS, PR_RECIPIENT_TYPE, PR_ADDRTYPE], [RES_OR, [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 967 |  |  | 			[RES_PROPERTY, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 968 |  |  | 				[ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 969 |  |  | 					RELOP => RELOP_EQ, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 970 |  |  | 					ULPROPTAG => PR_RECIPIENT_TYPE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 971 |  |  | 					VALUE => MAPI_BCC, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 972 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 973 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 974 |  |  | 			[RES_PROPERTY, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 975 |  |  | 				[ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 976 |  |  | 					RELOP => RELOP_EQ, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 977 |  |  | 					ULPROPTAG => PR_RECIPIENT_TYPE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 978 |  |  | 					VALUE => MAPI_CC, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 979 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 980 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 981 |  |  | 			[RES_PROPERTY, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 982 |  |  | 				[ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 983 |  |  | 					RELOP => RELOP_EQ, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 984 |  |  | 					ULPROPTAG => PR_RECIPIENT_TYPE, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 985 |  |  | 					VALUE => MAPI_TO, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 986 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 987 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 988 |  |  | 		]]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 989 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 990 |  |  | 		$publicCerts = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 991 |  |  | 		$storeCert = ''; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 992 |  |  | 		$gabCert = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 993 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 994 |  |  | 		foreach ($recips as $recip) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 995 |  |  | 			$emailAddr = $recip[PR_SMTP_ADDRESS]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 996 |  |  | 			$addrType = $recip[PR_ADDRTYPE]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 997 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 998 |  |  | 			if ($addrType === "ZARAFA" || $addrType === "EX") { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 999 |  |  | 				$user = $this->getGABUser($emailAddr); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1000 |  |  | 				$gabCert = $this->getGABCert($user); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1001 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1002 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1003 |  |  | 			$storeCert = $this->getPublicKey($emailAddr); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1004 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1005 |  |  | 			if (!empty($gabCert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1006 |  |  | 				array_push($publicCerts, $gabCert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1007 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1008 |  |  | 			elseif (!empty($storeCert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1009 |  |  | 				array_push($publicCerts, base64_decode($storeCert)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1010 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1011 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1012 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1013 |  |  | 		return $publicCerts; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1014 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1015 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1016 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1017 |  |  | 	 * Retrieves the public certificates stored in the MAPI UserStore and belonging to the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1018 |  |  | 	 * emailAdddress, returns "" if there is no certificate for that user. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1019 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1020 |  |  | 	 * @param string emailAddress | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1021 |  |  | 	 * @param mixed $emailAddress | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1022 |  |  | 	 * @param mixed $multiple | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1023 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1024 |  |  | 	 * @return string $certificate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1025 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1026 |  |  | 	public function getPublicKey($emailAddress, $multiple = false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1027 |  |  | 		$certificates = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1028 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1029 |  |  | 		$certs = getMAPICert($this->getStore(), 'WebApp.Security.Public', $emailAddress); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1030 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1031 |  |  | 		if ($certs && count($certs) > 0) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1032 |  |  | 			foreach ($certs as $cert) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1033 |  |  | 				$pubkey = mapi_msgstore_openentry($this->getStore(), $cert[PR_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1034 |  |  | 				$certificate = ""; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1035 |  |  | 				if ($pubkey == false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1036 |  |  | 					continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1037 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1038 |  |  | 				// retrieve pkcs#11 certificate from body | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1039 |  |  | 				$stream = mapi_openproperty($pubkey, PR_BODY, IID_IStream, 0, 0); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1040 |  |  | 				$stat = mapi_stream_stat($stream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1041 |  |  | 				mapi_stream_seek($stream, 0, STREAM_SEEK_SET); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1042 |  |  | 				for ($i = 0; $i < $stat['cb']; $i += 1024) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1043 |  |  | 					$certificate .= mapi_stream_read($stream, 1024); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1044 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1045 |  |  | 				array_push($certificates, $certificate); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1046 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1047 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1048 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1049 |  |  | 		return $multiple ? $certificates : ($certificates[0] ?? ''); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1050 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1051 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1052 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1053 |  |  | 	 * Function which is used to check if there is a public certificate for the provided emailAddress. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1054 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1055 |  |  | 	 * @param string emailAddress emailAddres of recipient | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1056 |  |  | 	 * @param bool gabUser is the user of PR_ADDRTYPE == ZARAFA | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1057 |  |  | 	 * @param mixed $emailAddress | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1058 |  |  | 	 * @param mixed $gabUser | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1059 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1060 |  |  | 	 * @return bool true if public certificate exists | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1061 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1062 |  |  | 	public function pubcertExists($emailAddress, $gabUser = false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1063 |  |  | 		if ($gabUser) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1064 |  |  | 			$user = $this->getGABUser($emailAddress); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1065 |  |  | 			$gabCert = $this->getGABCert($user); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1066 |  |  | 			if ($user && !empty($gabCert)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1067 |  |  | 				return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1068 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1069 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1070 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1071 |  |  | 		$root = mapi_msgstore_openentry($this->getStore()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1072 |  |  | 		$table = mapi_folder_getcontentstable($root, MAPI_ASSOCIATED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1073 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1074 |  |  | 		// Restriction for public certificates which are from the recipient of the email, are active and have the correct message_class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1075 |  |  | 		$restrict = [RES_AND, [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1076 |  |  | 			[RES_PROPERTY, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1077 |  |  | 				[ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1078 |  |  | 					RELOP => RELOP_EQ, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1079 |  |  | 					ULPROPTAG => PR_MESSAGE_CLASS, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1080 |  |  | 					VALUE => [PR_MESSAGE_CLASS => "WebApp.Security.Public"], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1081 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1082 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1083 |  |  | 			[RES_PROPERTY, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1084 |  |  | 				[ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1085 |  |  | 					RELOP => RELOP_EQ, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1086 |  |  | 					ULPROPTAG => PR_SUBJECT, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1087 |  |  | 					VALUE => [PR_SUBJECT => $emailAddress], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1088 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1089 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1090 |  |  | 		]]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1091 |  |  | 		mapi_table_restrict($table, $restrict, TBL_BATCH); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1092 |  |  | 		mapi_table_sort($table, [PR_MESSAGE_DELIVERY_TIME => TABLE_SORT_DESCEND], TBL_BATCH); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1093 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1094 |  |  | 		$rows = mapi_table_queryallrows($table, [PR_SUBJECT, PR_ENTRYID, PR_MESSAGE_DELIVERY_TIME, PR_CLIENT_SUBMIT_TIME], $restrict); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1095 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1096 |  |  | 		return !empty($rows); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1097 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1098 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1099 |  |  | 	public function clear_openssl_error() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1100 |  |  | 		while (@openssl_error_string() !== false) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1101 |  |  | 		/* nothing */; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1102 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1104 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1105 |  |  | 	 * Helper functions which extracts the errors from openssl_error_string() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1106 |  |  | 	 * Example error from openssl_error_string(): error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1107 |  |  | 	 * Note that openssl_error_string() returns an error when verifying is successful, this is a bug in PHP https://bugs.php.net/bug.php?id=50713. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1108 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1109 |  |  | 	 * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1110 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1111 |  |  | 	public function extract_openssl_error() { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1112 |  |  | 		$this->openssl_error = ""; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1113 |  |  | 		while (($s = @openssl_error_string()) !== false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1114 |  |  | 			if (strlen($this->openssl_error) == 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1115 |  |  | 				$this->openssl_error = $s; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1116 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1117 |  |  | 			else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1118 |  |  | 				$this->openssl_error .= "\n" . $s; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1119 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1120 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1121 |  |  | 		$openssl_error_code = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1122 |  |  | 		if ($this->openssl_error) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1123 |  |  | 			$openssl_error_list = explode(":", $this->openssl_error); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1124 |  |  | 			$openssl_error_code = $openssl_error_list[1]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1125 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1127 |  |  | 		return $openssl_error_code; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1128 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1129 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1130 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1131 |  |  | 	 * Extract the intermediate certificates from the signed email. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1132 |  |  | 	 * Uses openssl_pkcs7_verify to extract the PKCS#7 blob and then converts the PKCS#7 blob to | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1133 |  |  | 	 * X509 certificates using openssl_pkcs7_read. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1134 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1135 |  |  | 	 * @param string $emlfile - the s/mime message | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1136 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1137 |  |  | 	 * @return array a list of extracted intermediate certificates | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1138 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1139 |  |  | 	public function extractCAs($emlfile) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1140 |  |  | 		$cas = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1141 |  |  | 		$certfile = tempnam(sys_get_temp_dir(), true); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1142 |  |  | 		$outfile = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1143 |  |  | 		$p7bfile = tempnam(sys_get_temp_dir(), true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1144 |  |  | 		openssl_pkcs7_verify($emlfile, PKCS7_NOVERIFY, $certfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1145 |  |  | 		openssl_pkcs7_verify($emlfile, PKCS7_NOVERIFY, $certfile, [], $certfile, $outfile, $p7bfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1147 |  |  | 		$p7b = file_get_contents($p7bfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1148 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1149 |  |  | 		openssl_pkcs7_read($p7b, $cas); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1150 |  |  | 		unlink($certfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1151 |  |  | 		unlink($outfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1152 |  |  | 		unlink($p7bfile); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1153 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1154 |  |  | 		return $cas; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1155 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1157 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1158 |  |  | 	 * Imports certificate in the MAPI Root Associated Folder. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1159 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1160 |  |  | 	 * Private key, always insert certificate | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1161 |  |  | 	 * Public key, check if we already have one stored | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1162 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1163 |  |  | 	 * @param string $cert     certificate body as a string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1164 |  |  | 	 * @param mixed  $certData an array with the parsed certificate data | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1165 |  |  | 	 * @param string $type     certificate type, default 'public' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1166 |  |  | 	 * @param bool   $force    force import the certificate even though we have one already stored in the MAPI Store. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1167 |  |  | 	 *                         FIXME: remove $force in the future and move the check for newer certificate in this function. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1168 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1169 |  |  | 	public function importCertificate($cert, $certData, $type = 'public', $force = false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1170 |  |  | 		$certEmail = getCertEmail($certData); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1171 |  |  | 		if ($this->pubcertExists($certEmail) && !$force && $type !== 'private') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1172 |  |  | 			return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1173 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1174 |  |  | 		$issued_by = ""; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1175 |  |  | 		foreach (array_keys($certData['issuer']) as $key) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1176 |  |  | 			$issued_by .= $key . '=' . $certData['issuer'][$key] . "\n"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1177 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1178 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1179 |  |  | 		$root = mapi_msgstore_openentry($this->getStore()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1180 |  |  | 		$assocMessage = mapi_folder_createmessage($root, MAPI_ASSOCIATED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1181 |  |  | 		// TODO: write these properties down. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1182 |  |  | 		mapi_setprops($assocMessage, [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1183 |  |  | 			PR_SUBJECT => $certEmail, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1184 |  |  | 			PR_MESSAGE_CLASS => $type == 'public' ? 'WebApp.Security.Public' : 'WebApp.Security.Private', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1185 |  |  | 			PR_MESSAGE_DELIVERY_TIME => $certData['validTo_time_t'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1186 |  |  | 			PR_CLIENT_SUBMIT_TIME => $certData['validFrom_time_t'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1187 |  |  | 			PR_SENDER_NAME => $certData['serialNumber'], // serial | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1188 |  |  | 			PR_SENDER_EMAIL_ADDRESS => $issued_by, // Issuer To | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1189 |  |  | 			PR_SUBJECT_PREFIX => '', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1190 |  |  | 			PR_RECEIVED_BY_NAME => $this->fingerprint_cert($cert, 'sha1'), // SHA1 Fingerprint | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1191 |  |  | 			PR_INTERNET_MESSAGE_ID => $this->fingerprint_cert($cert), // MD5 FingerPrint | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1192 |  |  | 		]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1193 |  |  | 		// Save attachment | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1194 |  |  | 		$msgBody = base64_encode($cert); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1195 |  |  | 		$stream = mapi_openproperty($assocMessage, PR_BODY, IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1196 |  |  | 		mapi_stream_setsize($stream, strlen($msgBody)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1197 |  |  | 		mapi_stream_write($stream, $msgBody); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1198 |  |  | 		mapi_stream_commit($stream); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1199 |  |  | 		mapi_message_savechanges($assocMessage); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1200 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1201 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1202 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1203 |  |  | 	 * Function which returns the fingerprint (hash) of the certificate. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1204 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1205 |  |  | 	 * @param string $hash optional hash algorithm | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1206 |  |  | 	 * @param mixed  $body | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1207 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1208 |  |  | 	public function fingerprint_cert($body, $hash = 'md5') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1209 |  |  | 		// TODO: Note for PHP > 5.6 we can use openssl_x509_fingerprint | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1210 |  |  | 		$body = str_replace('-----BEGIN CERTIFICATE-----', '', $body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1211 |  |  | 		$body = str_replace('-----END CERTIFICATE-----', '', $body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1212 |  |  | 		$body = base64_decode($body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1213 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1214 |  |  | 		if ($hash === 'sha1') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1215 |  |  | 			$fingerprint = sha1($body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1216 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1217 |  |  | 		else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1218 |  |  | 			$fingerprint = md5($body); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1219 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1220 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1221 |  |  | 		// Format 1000AB as 10:00:AB | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1222 |  |  | 		return strtoupper(implode(':', str_split($fingerprint, 2))); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1223 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1224 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1225 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1226 |  |  | 	 * Retrieve the GAB User. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1227 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1228 |  |  | 	 * FIXME: ideally this would be a public function in grommunio Web. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1229 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1230 |  |  | 	 * @param string $email the email address of the user | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1231 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1232 |  |  | 	 * @return mixed $user boolean if false else MAPIObject | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1233 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1234 |  |  | 	public function getGABUser($email) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1235 |  |  | 		$addrbook = $GLOBALS["mapisession"]->getAddressbook(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1236 |  |  | 		$userArr = [[PR_DISPLAY_NAME => $email]]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1237 |  |  | 		$user = false; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1238 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1239 |  |  | 		try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1240 |  |  | 			$user = mapi_ab_resolvename($addrbook, $userArr, EMS_AB_ADDRESS_LOOKUP); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1241 |  |  | 			$user = mapi_ab_openentry($addrbook, $user[0][PR_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1242 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1243 |  |  | 		catch (MAPIException $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1244 |  |  | 			$e->setHandled(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1245 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1246 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1247 |  |  | 		return $user; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1248 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1249 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1250 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1251 |  |  | 	 * Retrieve the PR_EMS_AB_X509_CERT. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1252 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1253 |  |  | 	 * @param MAPIObject $user the GAB user | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1254 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1255 |  |  | 	 * @return string $cert the certificate, empty if not found | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1256 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1257 |  |  | 	public function getGABCert($user) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1258 |  |  | 		$cert = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1259 |  |  | 		$userCertArray = mapi_getprops($user, [PR_EMS_AB_X509_CERT]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1260 |  |  | 		if (isset($userCertArray[PR_EMS_AB_X509_CERT])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1261 |  |  | 			$cert = der2pem($userCertArray[PR_EMS_AB_X509_CERT][0]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1262 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1263 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1264 |  |  | 		return $cert; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1265 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1266 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1267 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1268 |  |  | 	 * Called when the core Settings class is initialized and ready to accept sysadmin default | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1269 |  |  | 	 * settings. Registers the sysadmin defaults for the example plugin. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1270 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1271 |  |  | 	 * @param mixed $data Reference to the data of the triggered hook | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1272 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1273 |  |  | 	public function onBeforeSettingsInit(&$data) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1274 |  |  | 		$data['settingsObj']->addSysAdminDefaults([ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1275 |  |  | 			'zarafa' => [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1276 |  |  | 				'v1' => [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1277 |  |  | 					'plugins' => [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1278 |  |  | 						'smime' => [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1279 |  |  | 							'enable' => defined('PLUGIN_SMIME_USER_DEFAULT_ENABLE_SMIME') && PLUGIN_SMIME_USER_DEFAULT_ENABLE_SMIME, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1280 |  |  | 							'passphrase_cache' => defined('PLUGIN_SMIME_PASSPHRASE_REMEMBER_BROWSER') && PLUGIN_SMIME_PASSPHRASE_REMEMBER_BROWSER, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1281 |  |  | 						], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1282 |  |  | 					], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1283 |  |  | 				], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1284 |  |  | 			], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1285 |  |  | 		]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1286 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1287 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1288 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1289 |  |  | 	 * Get sender structure of the MAPI Message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1290 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1291 |  |  | 	 * @param mapimessage $mapiMessage MAPI Message resource from which we need to get the sender | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1292 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1293 |  |  | 	 * @return array with properties | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1294 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1295 |  |  | 	public function getSenderAddress($mapiMessage) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1296 |  |  | 		if (method_exists($GLOBALS['operations'], 'getSenderAddress')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1297 |  |  | 			return $GLOBALS["operations"]->getSenderAddress($mapiMessage); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1298 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1299 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1300 |  |  | 		$messageProps = mapi_getprops($mapiMessage, [PR_SENT_REPRESENTING_ENTRYID, PR_SENDER_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1301 |  |  | 		$senderEntryID = $messageProps[PR_SENT_REPRESENTING_ENTRYID] ?? $messageProps[PR_SENDER_ENTRYID]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1302 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1303 |  |  | 		try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1304 |  |  | 			$senderUser = mapi_ab_openentry($GLOBALS["mapisession"]->getAddressbook(), $senderEntryID); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1305 |  |  | 			if ($senderUser) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1306 |  |  | 				$userprops = mapi_getprops($senderUser, [PR_ADDRTYPE, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_OBJECT_TYPE, PR_RECIPIENT_TYPE, PR_DISPLAY_TYPE, PR_DISPLAY_TYPE_EX, PR_ENTRYID]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1307 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1308 |  |  | 				$senderStructure = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1309 |  |  | 				$senderStructure["props"]['entryid'] = isset($userprops[PR_ENTRYID]) ? bin2hex((string) $userprops[PR_ENTRYID]) : ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1310 |  |  | 				$senderStructure["props"]['display_name'] = $userprops[PR_DISPLAY_NAME] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1311 |  |  | 				$senderStructure["props"]['email_address'] = $userprops[PR_EMAIL_ADDRESS] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1312 |  |  | 				$senderStructure["props"]['smtp_address'] = $userprops[PR_SMTP_ADDRESS] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1313 |  |  | 				$senderStructure["props"]['address_type'] = $userprops[PR_ADDRTYPE] ?? ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1314 |  |  | 				$senderStructure["props"]['object_type'] = $userprops[PR_OBJECT_TYPE]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1315 |  |  | 				$senderStructure["props"]['recipient_type'] = MAPI_TO; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1316 |  |  | 				$senderStructure["props"]['display_type'] = $userprops[PR_DISPLAY_TYPE] ?? MAPI_MAILUSER; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1317 |  |  | 				$senderStructure["props"]['display_type_ex'] = $userprops[PR_DISPLAY_TYPE_EX] ?? MAPI_MAILUSER; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1318 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1319 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1320 |  |  | 		catch (MAPIException $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1321 |  |  | 			error_log(sprintf("[smime] getSenderAddress(): Exception %s", $e)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1322 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1323 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1324 |  |  | 		return $senderStructure; | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 1325 |  |  | 	} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 1326 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 1327 |  |  |  | 
            
                        
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.