xref: /aoo4110/main/sfx2/source/doc/docmacromode.cxx (revision b1cdbd2c)
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 	//--------------------------------------------------------------------
adjustMacroMode(const Reference<XInteractionHandler> & rxInteraction)163     sal_Bool DocumentMacroMode::adjustMacroMode( const Reference< XInteractionHandler >& rxInteraction )
164     {
165         sal_uInt16 nMacroExecutionMode = m_pData->m_rDocumentAccess.getCurrentMacroExecMode();
166 
167         if ( SvtSecurityOptions().IsMacroDisabled() )
168         {
169             // no macro should be executed at all
170             lcl_showMacrosDisabledError( rxInteraction, m_pData->m_bMacroDisabledMessageShown );
171             return disallowMacroExecution();
172         }
173 
174         // get setting from configuration if required
175         enum AutoConfirmation
176         {
177             eNoAutoConfirm,
178             eAutoConfirmApprove,
179             eAutoConfirmReject
180         };
181         AutoConfirmation eAutoConfirm( eNoAutoConfirm );
182 
183         if  (   ( nMacroExecutionMode == MacroExecMode::USE_CONFIG )
184             ||  ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
185             ||  ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
186             )
187         {
188             SvtSecurityOptions aOpt;
189             switch ( aOpt.GetMacroSecurityLevel() )
190             {
191                 case 3:
192                     nMacroExecutionMode = MacroExecMode::FROM_LIST_NO_WARN;
193                     break;
194                 case 2:
195                     nMacroExecutionMode = MacroExecMode::FROM_LIST_AND_SIGNED_WARN;
196                     break;
197                 case 1:
198                     nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE;
199                     break;
200                 case 0:
201                     nMacroExecutionMode = MacroExecMode::ALWAYS_EXECUTE_NO_WARN;
202                     break;
203                 default:
204                     OSL_ENSURE( sal_False, "DocumentMacroMode::adjustMacroMode: unexpected macro security level!" );
205                     nMacroExecutionMode = MacroExecMode::NEVER_EXECUTE;
206             }
207 
208             if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_REJECT_CONFIRMATION )
209                 eAutoConfirm = eAutoConfirmReject;
210             else if ( nMacroExecutionMode == MacroExecMode::USE_CONFIG_APPROVE_CONFIRMATION )
211                 eAutoConfirm = eAutoConfirmApprove;
212         }
213 
214         if ( nMacroExecutionMode == MacroExecMode::NEVER_EXECUTE )
215             return sal_False;
216 
217         if ( nMacroExecutionMode == MacroExecMode::ALWAYS_EXECUTE_NO_WARN )
218             return sal_True;
219 
220         try
221         {
222             ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() );
223 
224             // get document location from medium name and check whether it is a trusted one
225             // the service is created ohne document version, since it is not of interest here
226             ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
227             Reference< XDocumentDigitalSignatures > xSignatures;
228             if ( aContext.createComponent( "com.sun.star.security.DocumentDigitalSignatures", xSignatures ) )
229             {
230                 INetURLObject aURLReferer( sReferrer );
231 
232                 ::rtl::OUString aLocation;
233                 if ( aURLReferer.removeSegment() )
234                     aLocation = aURLReferer.GetMainURL( INetURLObject::NO_DECODE );
235 
236                 if ( aLocation.getLength() && xSignatures->isLocationTrusted( aLocation ) )
237                 {
238                     return allowMacroExecution();
239                 }
240             }
241 
242             // at this point it is clear that the document is not in the secure location
243             if ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
244             {
245                 lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown );
246                 return disallowMacroExecution();
247             }
248 
249             // check whether the document is signed with trusted certificate
250             if ( nMacroExecutionMode != MacroExecMode::FROM_LIST )
251             {
252                 // the trusted macro check will also retrieve the signature state ( small optimization )
253                 sal_Bool bHasTrustedMacroSignature = m_pData->m_rDocumentAccess.hasTrustedScriptingSignature( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN );
254 
255                 sal_uInt16 nSignatureState = m_pData->m_rDocumentAccess.getScriptingSignatureState();
256                 if ( nSignatureState == SIGNATURESTATE_SIGNATURES_BROKEN )
257                 {
258                     // the signature is broken, no macro execution
259                     if ( nMacroExecutionMode != MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
260                         m_pData->m_rDocumentAccess.showBrokenSignatureWarning( rxInteraction );
261 
262                     return disallowMacroExecution();
263                 }
264                 else if ( bHasTrustedMacroSignature )
265                 {
266                     // there is trusted macro signature, allow macro execution
267                     return allowMacroExecution();
268                 }
269                 else if ( nSignatureState == SIGNATURESTATE_SIGNATURES_OK
270                        || nSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED )
271                 {
272                     // there is valid signature, but it is not from the trusted author
273                     return disallowMacroExecution();
274                 }
275             }
276 
277             // at this point it is clear that the document is neither in secure location nor signed with trusted certificate
278             if  (   ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
279                 ||  ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
280                 )
281             {
282                 if  ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
283                     lcl_showDocumentMacrosDisabledError( rxInteraction, m_pData->m_bDocMacroDisabledMessageShown );
284 
285                 return disallowMacroExecution();
286             }
287         }
288         catch ( Exception& )
289         {
290             if  (   ( nMacroExecutionMode == MacroExecMode::FROM_LIST_NO_WARN )
291                 ||  ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_WARN )
292                 ||  ( nMacroExecutionMode == MacroExecMode::FROM_LIST_AND_SIGNED_NO_WARN )
293                 )
294             {
295                 return disallowMacroExecution();
296             }
297         }
298 
299         // conformation is required
300         sal_Bool bSecure = sal_False;
301 
302         if ( eAutoConfirm == eNoAutoConfirm )
303         {
304             ::rtl::OUString sReferrer( m_pData->m_rDocumentAccess.getDocumentLocation() );
305 
306             ::rtl::OUString aSystemFileURL;
307             if ( osl::FileBase::getSystemPathFromFileURL( sReferrer, aSystemFileURL ) == osl::FileBase::E_None )
308                 sReferrer = aSystemFileURL;
309 
310             bSecure = lcl_showMacroWarning( rxInteraction, sReferrer );
311         }
312         else
313             bSecure = ( eAutoConfirm == eAutoConfirmApprove );
314 
315         return ( bSecure ? allowMacroExecution() : disallowMacroExecution() );
316     }
317 
318 	//--------------------------------------------------------------------
isMacroExecutionDisallowed() const319     sal_Bool DocumentMacroMode::isMacroExecutionDisallowed() const
320     {
321         return m_pData->m_rDocumentAccess.getCurrentMacroExecMode() == MacroExecMode::NEVER_EXECUTE;
322     }
323 
324     //--------------------------------------------------------------------
hasMacroLibrary() const325     sal_Bool DocumentMacroMode::hasMacroLibrary() const
326     {
327         sal_Bool bHasMacroLib = sal_False;
328         try
329         {
330             Reference< XEmbeddedScripts > xScripts( m_pData->m_rDocumentAccess.getEmbeddedDocumentScripts() );
331             Reference< XLibraryContainer > xContainer;
332             if ( xScripts.is() )
333                 xContainer.set( xScripts->getBasicLibraries(), UNO_QUERY_THROW );
334 
335             if ( xContainer.is() )
336             {
337                 // a library container exists; check if it's empty
338 
339 			    // if there are libraries except the "Standard" library
340 			    // we assume that they are not empty (because they have been created by the user)
341 			    if ( !xContainer->hasElements() )
342                     bHasMacroLib = sal_False;
343                 else
344 			    {
345 				    ::rtl::OUString aStdLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
346 				    Sequence< ::rtl::OUString > aElements = xContainer->getElementNames();
347 				    if ( aElements.getLength() )
348 				    {
349 					    if ( aElements.getLength() > 1 || !aElements[0].equals( aStdLibName ) )
350 						    bHasMacroLib = sal_True;
351 					    else
352 					    {
353 						    // usually a "Standard" library is always present (design)
354 						    // for this reason we must check if it's empty
355                             //
356                             // Note: Since #i73229#, this is not true anymore. There's no default
357                             // "Standard" lib anymore. Wouldn't it be time to get completely
358                             // rid of the "Standard" thingie - this shouldn't be necessary
359                             // anymore, should it?
360                             // 2007-01-25 / frank.schoenheit@sun.com
361 						    Reference < XNameAccess > xLib;
362 						    Any aAny = xContainer->getByName( aStdLibName );
363 						    aAny >>= xLib;
364 						    if ( xLib.is() )
365 							    bHasMacroLib = xLib->hasElements();
366 					    }
367 				    }
368 			    }
369 		    }
370         }
371         catch( const Exception& )
372         {
373             DBG_UNHANDLED_EXCEPTION();
374         }
375 
376         return bHasMacroLib;
377     }
378 
379 	//--------------------------------------------------------------------
storageHasMacros(const Reference<XStorage> & rxStorage)380     sal_Bool DocumentMacroMode::storageHasMacros( const Reference< XStorage >& rxStorage )
381     {
382 	    sal_Bool bHasMacros = sal_False;
383 	    if ( rxStorage.is() )
384 	    {
385 		    try
386 		    {
387                 static const ::rtl::OUString s_sBasicStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Basic" ) ) );
388                 static const ::rtl::OUString s_sScriptsStorageName( ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ) );
389 
390                 bHasMacros =(   (   rxStorage->hasByName( s_sBasicStorageName )
391                                 &&  rxStorage->isStorageElement( s_sBasicStorageName )
392                                 )
393                             ||  (   rxStorage->hasByName( s_sScriptsStorageName )
394                                 &&  rxStorage->isStorageElement( s_sScriptsStorageName )
395                                 )
396                             );
397 		    }
398 		    catch ( const Exception& )
399 		    {
400 			    DBG_UNHANDLED_EXCEPTION();
401 		    }
402 	    }
403         return bHasMacros;
404     }
405 
406 	//--------------------------------------------------------------------
checkMacrosOnLoading(const Reference<XInteractionHandler> & rxInteraction)407     sal_Bool DocumentMacroMode::checkMacrosOnLoading( const Reference< XInteractionHandler >& rxInteraction )
408     {
409         sal_Bool bAllow = sal_False;
410         if ( SvtSecurityOptions().IsMacroDisabled() )
411         {
412             // no macro should be executed at all
413             bAllow = disallowMacroExecution();
414         }
415         else
416         {
417             if ( m_pData->m_rDocumentAccess.documentStorageHasMacros() || hasMacroLibrary() )
418             {
419                 bAllow = adjustMacroMode( rxInteraction );
420             }
421             else if ( !isMacroExecutionDisallowed() )
422             {
423                 // if macros will be added by the user later, the security check is obsolete
424                 bAllow = allowMacroExecution();
425             }
426         }
427         return bAllow;
428     }
429 
430 //........................................................................
431 } // namespace sfx2
432 //........................................................................
433