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