1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docmacromode.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "sfx2/docmacromode.hxx"
35 #include "sfx2/signaturestate.hxx"
36 #include "sfx2/docfile.hxx"
38 /** === begin UNO includes === **/
39 #include <com/sun/star/document/MacroExecMode.hpp>
40 #include <com/sun/star/task/ErrorCodeRequest.hpp>
41 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
42 #include <com/sun/star/task/InteractionClassification.hpp>
43 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
44 #include <com/sun/star/script/XLibraryQueryExecutable.hpp>
45 /** === end UNO includes === **/
47 #include <comphelper/componentcontext.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <framework/interaction.hxx>
50 #include <osl/file.hxx>
51 #include <rtl/ref.hxx>
52 #include <svtools/securityoptions.hxx>
53 #include <svtools/sfxecode.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <tools/urlobj.hxx>
57 //........................................................................
60 //........................................................................
62 /** === begin UNO using === **/
63 using ::com::sun::star::uno::Reference
;
64 using ::com::sun::star::task::XInteractionHandler
;
65 using ::com::sun::star::uno::Any
;
66 using ::com::sun::star::task::XInteractionHandler
;
67 using ::com::sun::star::uno::Sequence
;
68 using ::com::sun::star::task::XInteractionContinuation
;
69 using ::com::sun::star::task::XInteractionRequest
;
70 using ::com::sun::star::task::DocumentMacroConfirmationRequest
;
71 using ::com::sun::star::task::ErrorCodeRequest
;
72 using ::com::sun::star::uno::Exception
;
73 using ::com::sun::star::security::XDocumentDigitalSignatures
;
74 using ::com::sun::star::security::DocumentSignatureInformation
;
75 using ::com::sun::star::embed::XStorage
;
76 using ::com::sun::star::task::InteractionClassification_QUERY
;
77 using ::com::sun::star::document::XEmbeddedScripts
;
78 using ::com::sun::star::uno::UNO_SET_THROW
;
79 using ::com::sun::star::script::XLibraryContainer
;
80 using ::com::sun::star::script::XLibraryQueryExecutable
;
81 using ::com::sun::star::container::XNameAccess
;
82 using ::com::sun::star::uno::UNO_QUERY_THROW
;
83 using ::com::sun::star::uno::UNO_QUERY
;
84 /** === end UNO using === **/
85 namespace MacroExecMode
= ::com::sun::star::document::MacroExecMode
;
87 //====================================================================
88 //= DocumentMacroMode_Data
89 //====================================================================
90 struct DocumentMacroMode_Data
92 IMacroDocumentAccess
& m_rDocumentAccess
;
93 sal_Bool m_bMacroDisabledMessageShown
;
94 sal_Bool m_bDocMacroDisabledMessageShown
;
96 DocumentMacroMode_Data( IMacroDocumentAccess
& rDocumentAccess
)
97 :m_rDocumentAccess( rDocumentAccess
)
98 ,m_bMacroDisabledMessageShown( sal_False
)
99 ,m_bDocMacroDisabledMessageShown( sal_False
)
104 //====================================================================
106 //====================================================================
109 //................................................................
110 void lcl_showGeneralSfxErrorOnce( const Reference
< XInteractionHandler
>& rxHandler
, const sal_Int32 nSfxErrorCode
, sal_Bool
& rbAlreadyShown
)
112 if ( rbAlreadyShown
)
115 ErrorCodeRequest aErrorCodeRequest
;
116 aErrorCodeRequest
.ErrCode
= nSfxErrorCode
;
118 SfxMedium::CallApproveHandler( rxHandler
, makeAny( aErrorCodeRequest
), sal_False
);
119 rbAlreadyShown
= sal_True
;
122 //................................................................
123 void lcl_showMacrosDisabledError( const Reference
< XInteractionHandler
>& rxHandler
, sal_Bool
& rbAlreadyShown
)
125 lcl_showGeneralSfxErrorOnce( rxHandler
, ERRCODE_SFX_MACROS_SUPPORT_DISABLED
, rbAlreadyShown
);
128 //................................................................
129 void lcl_showDocumentMacrosDisabledError( const Reference
< XInteractionHandler
>& rxHandler
, sal_Bool
& rbAlreadyShown
)
131 lcl_showGeneralSfxErrorOnce( rxHandler
, ERRCODE_SFX_DOCUMENT_MACRO_DISABLED
, rbAlreadyShown
);
134 //................................................................
135 sal_Bool
lcl_showMacroWarning( const Reference
< XInteractionHandler
>& rxHandler
,
136 const ::rtl::OUString
& rDocumentLocation
)
138 DocumentMacroConfirmationRequest aRequest
;
139 aRequest
.DocumentURL
= rDocumentLocation
;
140 return SfxMedium::CallApproveHandler( rxHandler
, makeAny( aRequest
), sal_True
);
144 //====================================================================
145 //= DocumentMacroMode
146 //====================================================================
147 //--------------------------------------------------------------------
148 DocumentMacroMode::DocumentMacroMode( IMacroDocumentAccess
& rDocumentAccess
)
149 :m_pData( new DocumentMacroMode_Data( rDocumentAccess
) )
153 //--------------------------------------------------------------------
154 DocumentMacroMode::~DocumentMacroMode()
158 //--------------------------------------------------------------------
159 sal_Bool
DocumentMacroMode::allowMacroExecution()
161 m_pData
->m_rDocumentAccess
.setCurrentMacroExecMode( MacroExecMode::ALWAYS_EXECUTE_NO_WARN
);
165 //--------------------------------------------------------------------
166 sal_Bool
DocumentMacroMode::disallowMacroExecution()
168 m_pData
->m_rDocumentAccess
.setCurrentMacroExecMode( MacroExecMode::NEVER_EXECUTE
);
172 //--------------------------------------------------------------------
173 sal_Bool
DocumentMacroMode::adjustMacroMode( const Reference
< XInteractionHandler
>& rxInteraction
)
175 sal_uInt16 nMacroExecutionMode
= m_pData
->m_rDocumentAccess
.getCurrentMacroExecMode();
177 if ( SvtSecurityOptions().IsMacroDisabled() )
179 // no macro should be executed at all
180 lcl_showMacrosDisabledError( rxInteraction
, m_pData
->m_bMacroDisabledMessageShown
);
181 return disallowMacroExecution();
184 // get setting from configuration if required
185 enum AutoConfirmation
191 AutoConfirmation
eAutoConfirm( eNoAutoConfirm
);
193 if ( ( nMacroExecutionMode
== MacroExecMode::USE_CONFIG
)
194 || ( nMacroExecutionMode
== MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION
)
195 || ( nMacroExecutionMode
== MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION
)
198 SvtSecurityOptions aOpt
;
199 switch ( aOpt
.GetMacroSecurityLevel() )
202 nMacroExecutionMode
= MacroExecMode::FROM_LIST_NO_WARN
;
205 nMacroExecutionMode
= MacroExecMode::FROM_LIST_AND_SIGNED_WARN
;
208 nMacroExecutionMode
= MacroExecMode::ALWAYS_EXECUTE
;
211 nMacroExecutionMode
= MacroExecMode::ALWAYS_EXECUTE_NO_WARN
;
214 OSL_ENSURE( sal_False
, "DocumentMacroMode::adjustMacroMode: unexpected macro security level!" );
215 nMacroExecutionMode
= MacroExecMode::NEVER_EXECUTE
;
218 if ( nMacroExecutionMode
== MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION
)
219 eAutoConfirm
= eAutoConfirmReject
;
220 else if ( nMacroExecutionMode
== MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION
)
221 eAutoConfirm
= eAutoConfirmApprove
;
224 if ( nMacroExecutionMode
== MacroExecMode::NEVER_EXECUTE
)
227 if ( nMacroExecutionMode
== MacroExecMode::ALWAYS_EXECUTE_NO_WARN
)
232 ::rtl::OUString
sReferrer( m_pData
->m_rDocumentAccess
.getDocumentLocation() );
234 // get document location from medium name and check whether it is a trusted one
235 // the service is created ohne document version, since it is not of interest here
236 ::comphelper::ComponentContext
aContext( ::comphelper::getProcessServiceFactory() );
237 Reference
< XDocumentDigitalSignatures
> xSignatures
;
238 if ( aContext
.createComponent( "com.sun.star.security.DocumentDigitalSignatures", xSignatures
) )
240 INetURLObject
aURLReferer( sReferrer
);
242 ::rtl::OUString aLocation
;
243 if ( aURLReferer
.removeSegment() )
244 aLocation
= aURLReferer
.GetMainURL( INetURLObject::NO_DECODE
);
246 if ( aLocation
.getLength() && xSignatures
->isLocationTrusted( aLocation
) )
248 return allowMacroExecution();
252 // at this point it is clear that the document is not in the secure location
253 if ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_NO_WARN
)
255 lcl_showDocumentMacrosDisabledError( rxInteraction
, m_pData
->m_bDocMacroDisabledMessageShown
);
256 return disallowMacroExecution();
259 // check whether the document is signed with trusted certificate
260 if ( nMacroExecutionMode
!= MacroExecMode::FROM_LIST
)
262 // the trusted macro check will also retrieve the signature state ( small optimization )
263 sal_Bool bHasTrustedMacroSignature
= m_pData
->m_rDocumentAccess
.hasTrustedScriptingSignature( nMacroExecutionMode
!= MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN
);
265 sal_uInt16 nSignatureState
= m_pData
->m_rDocumentAccess
.getScriptingSignatureState();
266 if ( nSignatureState
== SIGNATURESTATE_SIGNATURES_BROKEN
)
268 // the signature is broken, no macro execution
269 if ( nMacroExecutionMode
!= MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN
)
270 m_pData
->m_rDocumentAccess
.showBrokenSignatureWarning( rxInteraction
);
272 return disallowMacroExecution();
274 else if ( bHasTrustedMacroSignature
)
276 // there is trusted macro signature, allow macro execution
277 return allowMacroExecution();
279 else if ( nSignatureState
== SIGNATURESTATE_SIGNATURES_OK
280 || nSignatureState
== SIGNATURESTATE_SIGNATURES_NOTVALIDATED
)
282 // there is valid signature, but it is not from the trusted author
283 return disallowMacroExecution();
287 // at this point it is clear that the document is neither in secure location nor signed with trusted certificate
288 if ( ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN
)
289 || ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_AND_SIGNED_WARN
)
292 if ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_AND_SIGNED_WARN
)
293 lcl_showDocumentMacrosDisabledError( rxInteraction
, m_pData
->m_bDocMacroDisabledMessageShown
);
295 return disallowMacroExecution();
300 if ( ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_NO_WARN
)
301 || ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_AND_SIGNED_WARN
)
302 || ( nMacroExecutionMode
== MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN
)
305 return disallowMacroExecution();
309 // conformation is required
310 sal_Bool bSecure
= sal_False
;
312 if ( eAutoConfirm
== eNoAutoConfirm
)
314 ::rtl::OUString
sReferrer( m_pData
->m_rDocumentAccess
.getDocumentLocation() );
316 ::rtl::OUString aSystemFileURL
;
317 if ( osl::FileBase::getSystemPathFromFileURL( sReferrer
, aSystemFileURL
) == osl::FileBase::E_None
)
318 sReferrer
= aSystemFileURL
;
320 bSecure
= lcl_showMacroWarning( rxInteraction
, sReferrer
);
323 bSecure
= ( eAutoConfirm
== eAutoConfirmApprove
);
325 return ( bSecure
? allowMacroExecution() : disallowMacroExecution() );
328 //--------------------------------------------------------------------
329 sal_Bool
DocumentMacroMode::isMacroExecutionDisallowed() const
331 return m_pData
->m_rDocumentAccess
.getCurrentMacroExecMode() == MacroExecMode::NEVER_EXECUTE
;
334 //--------------------------------------------------------------------
335 sal_Bool
DocumentMacroMode::hasMacroLibrary() const
337 sal_Bool bHasMacroLib
= sal_False
;
340 Reference
< XEmbeddedScripts
> xScripts( m_pData
->m_rDocumentAccess
.getEmbeddedDocumentScripts() );
341 Reference
< XLibraryContainer
> xContainer
;
343 xContainer
.set( xScripts
->getBasicLibraries(), UNO_QUERY_THROW
);
345 if ( xContainer
.is() )
347 // a library container exists; check if it's empty
349 // if there are libraries except the "Standard" library
350 // we assume that they are not empty (because they have been created by the user)
351 if ( !xContainer
->hasElements() )
352 bHasMacroLib
= sal_False
;
355 ::rtl::OUString
aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
356 Sequence
< ::rtl::OUString
> aElements
= xContainer
->getElementNames();
357 if ( aElements
.getLength() )
359 if ( aElements
.getLength() > 1 || !aElements
[0].equals( aStdLibName
) )
360 bHasMacroLib
= sal_True
;
363 // usually a "Standard" library is always present (design)
364 // for this reason we must check if it's empty
366 // Note: Since #i73229#, this is not true anymore. There's no default
367 // "Standard" lib anymore. Wouldn't it be time to get completely
368 // rid of the "Standard" thingie - this shouldn't be necessary
369 // anymore, should it?
370 // 2007-01-25 / frank.schoenheit@sun.com
371 Reference
< XLibraryQueryExecutable
> xLib( xContainer
, UNO_QUERY
);
373 bHasMacroLib
= xLib
->HasExecutableCode( aStdLibName
);
379 catch( const Exception
& )
381 DBG_UNHANDLED_EXCEPTION();
387 //--------------------------------------------------------------------
388 sal_Bool
DocumentMacroMode::storageHasMacros( const Reference
< XStorage
>& rxStorage
)
390 sal_Bool bHasMacros
= sal_False
;
391 if ( rxStorage
.is() )
395 static const ::rtl::OUString
s_sBasicStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) );
396 static const ::rtl::OUString
s_sScriptsStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ) );
398 bHasMacros
=( ( rxStorage
->hasByName( s_sBasicStorageName
)
399 && rxStorage
->isStorageElement( s_sBasicStorageName
)
401 || ( rxStorage
->hasByName( s_sScriptsStorageName
)
402 && rxStorage
->isStorageElement( s_sScriptsStorageName
)
406 catch ( const Exception
& )
408 DBG_UNHANDLED_EXCEPTION();
414 //--------------------------------------------------------------------
415 sal_Bool
DocumentMacroMode::checkMacrosOnLoading( const Reference
< XInteractionHandler
>& rxInteraction
)
417 sal_Bool bAllow
= sal_False
;
418 if ( SvtSecurityOptions().IsMacroDisabled() )
420 // no macro should be executed at all
421 bAllow
= disallowMacroExecution();
425 if ( m_pData
->m_rDocumentAccess
.documentStorageHasMacros() || hasMacroLibrary() )
427 bAllow
= adjustMacroMode( rxInteraction
);
429 else if ( !isMacroExecutionDisallowed() )
431 // if macros will be added by the user later, the security check is obsolete
432 bAllow
= allowMacroExecution();
438 //........................................................................
440 //........................................................................