1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sfx2.hxx" 26 27 #include "sfx2/docmacromode.hxx" 28 #include "sfx2/signaturestate.hxx" 29 #include "sfx2/docfile.hxx" 30 31 /** === begin UNO includes === **/ 32 #include <com/sun/star/document/MacroExecMode.hpp> 33 #include <com/sun/star/task/ErrorCodeRequest.hpp> 34 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp> 35 #include <com/sun/star/task/InteractionClassification.hpp> 36 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> 37 /** === end UNO includes === **/ 38 39 #include <comphelper/componentcontext.hxx> 40 #include <comphelper/processfactory.hxx> 41 #include <framework/interaction.hxx> 42 #include <osl/file.hxx> 43 #include <rtl/ref.hxx> 44 #include <unotools/securityoptions.hxx> 45 #include <svtools/sfxecode.hxx> 46 #include <tools/diagnose_ex.h> 47 #include <tools/urlobj.hxx> 48 49 //........................................................................ 50 namespace sfx2 51 { 52 //........................................................................ 53 54 /** === begin UNO using === **/ 55 using ::com::sun::star::uno::Reference; 56 using ::com::sun::star::task::XInteractionHandler; 57 using ::com::sun::star::uno::Any; 58 using ::com::sun::star::task::XInteractionHandler; 59 using ::com::sun::star::uno::Sequence; 60 using ::com::sun::star::task::XInteractionContinuation; 61 using ::com::sun::star::task::XInteractionRequest; 62 using ::com::sun::star::task::DocumentMacroConfirmationRequest; 63 using ::com::sun::star::task::ErrorCodeRequest; 64 using ::com::sun::star::uno::Exception; 65 using ::com::sun::star::security::XDocumentDigitalSignatures; 66 using ::com::sun::star::security::DocumentSignatureInformation; 67 using ::com::sun::star::embed::XStorage; 68 using ::com::sun::star::task::InteractionClassification_QUERY; 69 using ::com::sun::star::document::XEmbeddedScripts; 70 using ::com::sun::star::uno::UNO_SET_THROW; 71 using ::com::sun::star::script::XLibraryContainer; 72 using ::com::sun::star::container::XNameAccess; 73 using ::com::sun::star::uno::UNO_QUERY_THROW; 74 /** === end UNO using === **/ 75 namespace MacroExecMode = ::com::sun::star::document::MacroExecMode; 76 77 //==================================================================== 78 //= DocumentMacroMode_Data 79 //==================================================================== 80 struct DocumentMacroMode_Data 81 { 82 IMacroDocumentAccess& m_rDocumentAccess; 83 sal_Bool m_bMacroDisabledMessageShown; 84 sal_Bool m_bDocMacroDisabledMessageShown; 85 DocumentMacroMode_Datasfx2::DocumentMacroMode_Data86 DocumentMacroMode_Data( IMacroDocumentAccess& rDocumentAccess ) 87 :m_rDocumentAccess( rDocumentAccess ) 88 ,m_bMacroDisabledMessageShown( sal_False ) 89 ,m_bDocMacroDisabledMessageShown( sal_False ) 90 { 91 } 92 }; 93 94 //==================================================================== 95 //= helper 96 //==================================================================== 97 namespace 98 { 99 //................................................................ lcl_showGeneralSfxErrorOnce(const Reference<XInteractionHandler> & rxHandler,const sal_Int32 nSfxErrorCode,sal_Bool & rbAlreadyShown)100 void lcl_showGeneralSfxErrorOnce( const Reference< XInteractionHandler >& rxHandler, const sal_Int32 nSfxErrorCode, sal_Bool& rbAlreadyShown ) 101 { 102 if ( rbAlreadyShown ) 103 return; 104 105 ErrorCodeRequest aErrorCodeRequest; 106 aErrorCodeRequest.ErrCode = nSfxErrorCode; 107 108 SfxMedium::CallApproveHandler( rxHandler, makeAny( aErrorCodeRequest ), sal_False ); 109 rbAlreadyShown = sal_True; 110 } 111 112 //................................................................ lcl_showMacrosDisabledError(const Reference<XInteractionHandler> & rxHandler,sal_Bool & rbAlreadyShown)113 void lcl_showMacrosDisabledError( const Reference< XInteractionHandler >& rxHandler, sal_Bool& rbAlreadyShown ) 114 { 115 lcl_showGeneralSfxErrorOnce( rxHandler, ERRCODE_SFX_MACROS_SUPPORT_DISABLED, rbAlreadyShown ); 116 } 117 118 //................................................................ lcl_showDocumentMacrosDisabledError(const Reference<XInteractionHandler> & rxHandler,sal_Bool & rbAlreadyShown)119 void lcl_showDocumentMacrosDisabledError( const Reference< XInteractionHandler >& rxHandler, sal_Bool& rbAlreadyShown ) 120 { 121 lcl_showGeneralSfxErrorOnce( rxHandler, ERRCODE_SFX_DOCUMENT_MACRO_DISABLED, rbAlreadyShown ); 122 } 123 124 //................................................................ lcl_showMacroWarning(const Reference<XInteractionHandler> & rxHandler,const::rtl::OUString & rDocumentLocation)125 sal_Bool lcl_showMacroWarning( const Reference< XInteractionHandler >& rxHandler, 126 const ::rtl::OUString& rDocumentLocation ) 127 { 128 DocumentMacroConfirmationRequest aRequest; 129 aRequest.DocumentURL = rDocumentLocation; 130 return SfxMedium::CallApproveHandler( rxHandler, makeAny( aRequest ), sal_True ); 131 } 132 } 133 134 //==================================================================== 135 //= DocumentMacroMode 136 //==================================================================== 137 //-------------------------------------------------------------------- DocumentMacroMode(IMacroDocumentAccess & rDocumentAccess)138 DocumentMacroMode::DocumentMacroMode( IMacroDocumentAccess& rDocumentAccess ) 139 :m_pData( new DocumentMacroMode_Data( rDocumentAccess ) ) 140 { 141 } 142 143 //-------------------------------------------------------------------- ~DocumentMacroMode()144 DocumentMacroMode::~DocumentMacroMode() 145 { 146 } 147 148 //-------------------------------------------------------------------- allowMacroExecution()149 sal_Bool DocumentMacroMode::allowMacroExecution() 150 { 151 m_pData->m_rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::ALWAYS_EXECUTE_NO_WARN ); 152 return sal_True; 153 } 154 155 //-------------------------------------------------------------------- disallowMacroExecution()156 sal_Bool DocumentMacroMode::disallowMacroExecution() 157 { 158 m_pData->m_rDocumentAccess.setCurrentMacroExecMode( MacroExecMode::NEVER_EXECUTE ); 159 return sal_False; 160 } 161 162 /** Change the indicated macro execution mode depending on the current macro security level. 163 * 164 * @param nMacroExecutionMode current execution mode (must be one of MacroExecMode::USE_XXX). 165 * 166 * Changes nMacroExecutionMode according to the current security options, if applicable. 167 */ adjustMacroExecModeSecurity(sal_uInt16 & nMacroExecutionMode)168 static void adjustMacroExecModeSecurity(sal_uInt16 &nMacroExecutionMode) 169 { 170 if ( ( nMacroExecutionMode == MacroExecMode::USE_CONFIG ) 171 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION ) 172 || ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION ) 173 ) 174 { 175 SvtSecurityOptions aOpt; 176 switch ( aOpt.GetMacroSecurityLevel() ) 177 { 178 case 3: 179 nMacroExecutionMode = MacroExecMode::FROM_LIST_NO_WARN; 180 break; 181 case 2: 182 nMacroExecutionMode = MacroExecMode::FROM_LIST_AND_SIGNED_WARN; 183 break; 184 case 1: 185 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE; 186 break; 187 case 0: 188 nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE_NO_WARN; 189 break; 190 default: 191 OSL_ENSURE( sal_False, "DocumentMacroMode::adjustMacroMode: unexpected macro security level!" ); 192 nMacroExecutionMode = MacroExecMode::NEVER_EXECUTE; 193 } 194 195 } 196 } 197 198 //-------------------------------------------------------------------- adjustMacroMode(const Reference<XInteractionHandler> & rxInteraction)199 sal_Bool DocumentMacroMode::adjustMacroMode( const Reference< XInteractionHandler >& rxInteraction ) 200 { 201 sal_uInt16 nMacroExecutionMode = m_pData->m_rDocumentAccess.getCurrentMacroExecMode(); 202 203 if ( SvtSecurityOptions().IsMacroDisabled() ) 204 { 205 // no macro should be executed at all 206 lcl_showMacrosDisabledError( rxInteraction, m_pData->m_bMacroDisabledMessageShown ); 207 return disallowMacroExecution(); 208 } 209 210 // get setting from configuration if required 211 enum AutoConfirmation 212 { 213 eNoAutoConfirm, 214 eAutoConfirmApprove, 215 eAutoConfirmReject 216 }; 217 AutoConfirmation eAutoConfirm( eNoAutoConfirm ); 218 219 adjustMacroExecModeSecurity(nMacroExecutionMode); 220 if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION ) 221 eAutoConfirm = eAutoConfirmReject; 222 else if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION ) 223 eAutoConfirm = eAutoConfirmApprove; 224 225 if ( nMacroExecutionMode == MacroExecMode::NEVER_EXECUTE ) 226 return sal_False; 227 228 if ( nMacroExecutionMode == MacroExecMode::ALWAYS_EXECUTE_NO_WARN ) 229 return sal_True; 230 231 try 232 { 233 ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() ); 234 235 // get document location from medium name and check whether it is a trusted one 236 // the service is created ohne document version, since it is not of interest here 237 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); 238 Reference< XDocumentDigitalSignatures > xSignatures; 239 if ( aContext.createComponent( "com.sun.star.security.DocumentDigitalSignatures", xSignatures ) ) 240 { 241 INetURLObject aURLReferer( sReferrer ); 242 243 ::rtl::OUString aLocation; 244 if ( aURLReferer.removeSegment() ) 245 aLocation = aURLReferer.GetMainURL( INetURLObject::NO_DECODE ); 246 247 if ( aLocation.getLength() && xSignatures->isLocationTrusted( aLocation ) ) 248 { 249 return allowMacroExecution(); 250 } 251 } 252 253 // at this point it is clear that the document is not in the secure location 254 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN ) 255 { 256 lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown ); 257 return disallowMacroExecution(); 258 } 259 260 // check whether the document is signed with trusted certificate 261 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST ) 262 { 263 // the trusted macro check will also retrieve the signature state ( small optimization ) 264 sal_Bool bHasTrustedMacroSignature = m_pData->m_rDocumentAccess.hasTrustedScriptingSignature( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN ); 265 266 sal_uInt16 nSignatureState = m_pData->m_rDocumentAccess.getScriptingSignatureState(); 267 if ( nSignatureState == SIGNATURESTATE_SIGNATURES_BROKEN ) 268 { 269 // the signature is broken, no macro execution 270 if ( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN ) 271 m_pData->m_rDocumentAccess.showBrokenSignatureWarning( rxInteraction ); 272 273 return disallowMacroExecution(); 274 } 275 else if ( bHasTrustedMacroSignature ) 276 { 277 // there is trusted macro signature, allow macro execution 278 return allowMacroExecution(); 279 } 280 else if ( nSignatureState == SIGNATURESTATE_SIGNATURES_OK 281 || nSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED ) 282 { 283 // there is valid signature, but it is not from the trusted author 284 return disallowMacroExecution(); 285 } 286 } 287 288 // at this point it is clear that the document is neither in secure location nor signed with trusted certificate 289 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN ) 290 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN ) 291 ) 292 { 293 if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN ) 294 lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown ); 295 296 return disallowMacroExecution(); 297 } 298 } 299 catch ( Exception& ) 300 { 301 if ( ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN ) 302 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN ) 303 || ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN ) 304 ) 305 { 306 return disallowMacroExecution(); 307 } 308 } 309 310 // conformation is required 311 sal_Bool bSecure = sal_False; 312 313 if ( eAutoConfirm == eNoAutoConfirm ) 314 { 315 ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() ); 316 317 ::rtl::OUString aSystemFileURL; 318 if ( osl::FileBase::getSystemPathFromFileURL( sReferrer, aSystemFileURL ) == osl::FileBase::E_None ) 319 sReferrer = aSystemFileURL; 320 321 bSecure = lcl_showMacroWarning( rxInteraction, sReferrer ); 322 } 323 else 324 bSecure = ( eAutoConfirm == eAutoConfirmApprove ); 325 326 return ( bSecure ? allowMacroExecution() : disallowMacroExecution() ); 327 } 328 329 //-------------------------------------------------------------------- isMacroExecutionDisallowed() const330 sal_Bool DocumentMacroMode::isMacroExecutionDisallowed() const 331 { 332 return m_pData->m_rDocumentAccess.getCurrentMacroExecMode() == MacroExecMode::NEVER_EXECUTE; 333 } 334 335 //-------------------------------------------------------------------- hasMacroLibrary() const336 sal_Bool DocumentMacroMode::hasMacroLibrary() const 337 { 338 sal_Bool bHasMacroLib = sal_False; 339 try 340 { 341 Reference< XEmbeddedScripts > xScripts( m_pData->m_rDocumentAccess.getEmbeddedDocumentScripts() ); 342 Reference< XLibraryContainer > xContainer; 343 if ( xScripts.is() ) 344 xContainer.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW ); 345 346 if ( xContainer.is() ) 347 { 348 // a library container exists; check if it's empty 349 350 // if there are libraries except the "Standard" library 351 // we assume that they are not empty (because they have been created by the user) 352 if ( !xContainer->hasElements() ) 353 bHasMacroLib = sal_False; 354 else 355 { 356 ::rtl::OUString aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); 357 Sequence< ::rtl::OUString > aElements = xContainer->getElementNames(); 358 if ( aElements.getLength() ) 359 { 360 if ( aElements.getLength() > 1 || !aElements[0].equals( aStdLibName ) ) 361 bHasMacroLib = sal_True; 362 else 363 { 364 // usually a "Standard" library is always present (design) 365 // for this reason we must check if it's empty 366 // 367 // Note: Since #i73229#, this is not true anymore. There's no default 368 // "Standard" lib anymore. Wouldn't it be time to get completely 369 // rid of the "Standard" thingie - this shouldn't be necessary 370 // anymore, should it? 371 // 2007-01-25 / frank.schoenheit@sun.com 372 Reference < XNameAccess > xLib; 373 Any aAny = xContainer->getByName( aStdLibName ); 374 aAny >>= xLib; 375 if ( xLib.is() ) 376 bHasMacroLib = xLib->hasElements(); 377 } 378 } 379 } 380 } 381 } 382 catch( const Exception& ) 383 { 384 DBG_UNHANDLED_EXCEPTION(); 385 } 386 387 return bHasMacroLib; 388 } 389 390 //-------------------------------------------------------------------- storageHasMacros(const Reference<XStorage> & rxStorage)391 sal_Bool DocumentMacroMode::storageHasMacros( const Reference< XStorage >& rxStorage ) 392 { 393 sal_Bool bHasMacros = sal_False; 394 if ( rxStorage.is() ) 395 { 396 try 397 { 398 static const ::rtl::OUString s_sBasicStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) ); 399 static const ::rtl::OUString s_sScriptsStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ) ); 400 401 bHasMacros =( ( rxStorage->hasByName( s_sBasicStorageName ) 402 && rxStorage->isStorageElement( s_sBasicStorageName ) 403 ) 404 || ( rxStorage->hasByName( s_sScriptsStorageName ) 405 && rxStorage->isStorageElement( s_sScriptsStorageName ) 406 ) 407 ); 408 } 409 catch ( const Exception& ) 410 { 411 DBG_UNHANDLED_EXCEPTION(); 412 } 413 } 414 return bHasMacros; 415 } 416 417 //-------------------------------------------------------------------- checkMacrosOnLoading(const Reference<XInteractionHandler> & rxInteraction)418 sal_Bool DocumentMacroMode::checkMacrosOnLoading( const Reference< XInteractionHandler >& rxInteraction ) 419 { 420 sal_Bool bAllow = sal_False; 421 if ( SvtSecurityOptions().IsMacroDisabled() ) 422 { 423 // no macro should be executed at all 424 bAllow = disallowMacroExecution(); 425 } 426 else 427 { 428 if ( m_pData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() ) 429 { 430 bAllow = adjustMacroMode( rxInteraction ); 431 } 432 else if ( !isMacroExecutionDisallowed() ) 433 { 434 // There are no macros (yet) but we want to be careful anyway 435 sal_uInt16 nMacroExecutionMode = m_pData->m_rDocumentAccess.getCurrentMacroExecMode(); 436 adjustMacroExecModeSecurity(nMacroExecutionMode); 437 switch (nMacroExecutionMode) { 438 case MacroExecMode::NEVER_EXECUTE: 439 case MacroExecMode::USE_CONFIG: 440 case MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION: 441 case MacroExecMode::FROM_LIST_NO_WARN: 442 case MacroExecMode::FROM_LIST_AND_SIGNED_WARN: 443 case MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN: 444 bAllow = sal_False; 445 break; 446 case MacroExecMode::FROM_LIST: 447 case MacroExecMode::ALWAYS_EXECUTE: 448 case MacroExecMode::ALWAYS_EXECUTE_NO_WARN: 449 case MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION: 450 bAllow = sal_True; 451 break; 452 } 453 } 454 } 455 return bAllow; 456 } 457 458 //........................................................................ 459 } // namespace sfx2 460 //........................................................................ 461