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: ScriptSecurityManager.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_scripting.hxx"
34 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/lang/XComponent.hpp>
37 #include <com/sun/star/lang/WrappedTargetException.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/UnknownPropertyException.hpp>
41 #include <com/sun/star/container/XNameReplace.hpp>
42 #include <com/sun/star/util/XChangesBatch.hpp>
43 #include <com/sun/star/util/XMacroExpander.hpp>
44 #include <com/sun/star/util/XStringSubstitution.hpp>
45 #include <com/sun/star/awt/XDialog.hpp>
46 #include <com/sun/star/security/AccessControlException.hpp>
47 #include <com/sun/star/security/RuntimePermission.hpp>
48 #include <drafts/com/sun/star/script/framework/storage/XScriptStorageManager.hpp>
49 #include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp>
50 #include "ScriptSecurityManager.hxx"
51 #include <util/util.hxx>
52 #include <util/scriptingconstants.hxx>
55 using namespace ::rtl
;
56 using namespace ::osl
;
57 using namespace ::com::sun::star
;
58 using namespace ::com::sun::star::uno
;
59 using namespace ::drafts::com::sun::star::script::framework
;
61 // is this in the utils?
62 const char* const SCRIPTSTORAGEMANAGER_SERVICE
=
63 "/singletons/drafts.com.sun.star.script.framework.storage.theScriptStorageManager";
65 namespace scripting_securitymgr
68 static OUString s_configProv
= ::rtl::OUString::createFromAscii(
69 "com.sun.star.configuration.ConfigurationProvider");
71 static OUString s_configAccess
= ::rtl::OUString::createFromAscii(
72 "com.sun.star.configuration.ConfigurationAccess");
74 static OUString s_configUpdate
= ::rtl::OUString::createFromAscii(
75 "com.sun.star.configuration.ConfigurationUpdateAccess");
77 static OUString s_securityDialog
= ::rtl::OUString::createFromAscii(
78 "com.sun.star.script.framework.security.SecurityDialog");
80 static const int PERMISSION_NEVER
= 0;
81 static const int PERMISSION_PATHLIST
= 1;
82 static const int PERMISSION_ALWAYS
= 2;
84 static const int ALLOW_RUN
= 1;
85 static const int ADD_TO_PATH
= 2;
87 //*************************************************************************
88 // ScriptSecurityManager Constructor
89 ScriptSecurityManager::ScriptSecurityManager(
90 const Reference
< XComponentContext
> & xContext
) throw ( RuntimeException
)
91 : m_xContext( xContext
)
93 OSL_TRACE( "< ScriptSecurityManager ctor called >\n" );
94 validateXRef( m_xContext
,
95 "ScriptSecurityManager::ScriptSecurityManager: invalid context" );
97 // get the service manager from the context
98 Reference
< lang::XMultiComponentFactory
> xMgr
= m_xContext
->getServiceManager();
100 "ScriptSecurityManager::ScriptSecurityManager: cannot get ServiceManager" );
102 // create an instance of the ConfigurationProvider
103 Reference
< XInterface
> xInterface
= xMgr
->createInstanceWithContext(
104 s_configProv
, m_xContext
);
105 validateXRef( xInterface
,
106 "ScriptSecurityManager::ScriptSecurityManager: cannot get ConfigurationProvider" );
107 // create an instance of the ConfigurationAccess for accessing the
108 // scripting security settings
109 m_xConfigProvFactory
= Reference
< lang::XMultiServiceFactory
> ( xInterface
, UNO_QUERY
);
110 validateXRef( m_xConfigProvFactory
,
111 "ScriptSecurityManager::ScriptSecurityManager: cannot get XMultiServiceFactory interface from ConfigurationProvider" );
115 void ScriptSecurityManager::addScriptStorage( rtl::OUString scriptStorageURL
,
117 throw ( RuntimeException
)
119 Permission_Hash::const_iterator ph_it
= m_permissionSettings
.find( scriptStorageURL
);
120 if ( ph_it
!= m_permissionSettings
.end() )
122 OSL_TRACE( "ScriptSecurityManager::addScriptStorage: already called for %s",
123 ::rtl::OUStringToOString( scriptStorageURL
,
124 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
128 newPerm
.scriptStorageURL
=scriptStorageURL
;
129 newPerm
.storageID
=storageID
;
131 // we err on the side of caution!!
132 newPerm
.execPermission
=sal_False
;
134 //need to check if storage has any scripts
137 /* need to replace this with something better, now logical names are
140 Reference< XInterface > xInterface;
141 Any a = m_xContext->getValueByName(
142 OUString::createFromAscii( SCRIPTSTORAGEMANAGER_SERVICE ) );
143 if ( sal_False == ( a >>= xInterface ) )
145 throw RuntimeException(
146 OUSTR( "ScriptSecurityManager::addScriptStorage: could not obtain ScriptStorageManager singleton" ),
147 Reference< XInterface >() );
149 validateXRef( xInterface,
150 "ScriptSecurityManager::addScriptStorage: cannot get Storage service" );
151 Reference< storage::XScriptStorageManager > xScriptStorageManager(
152 xInterface, UNO_QUERY_THROW );
153 Reference< XInterface > xScriptStorage =
154 xScriptStorageManager->getScriptStorage( storageID );
155 validateXRef( xScriptStorage,
156 "ScriptNameResolverImpl::getStorageInstance: cannot get Script Storage service" );
157 Reference< storage::XScriptInfoAccess > xScriptInfoAccess =
158 Reference< storage::XScriptInfoAccess > ( xScriptStorage,
160 Sequence< ::rtl::OUString > logicalNames = xScriptInfoAccess->getScriptLogicalNames();
161 if( !logicalNames.getLength() ) // we have no logical names
166 // we have some scripts so read config & decide on that basis
167 // Setup flags: m_runMacroSetting, m_warning, m_confirmationRequired,
170 catch ( RuntimeException
& rte
)
172 OSL_TRACE( "ScriptSecurityManager::addScriptStorage: caught RuntimeException: %s",
173 ::rtl::OUStringToOString( rte
.Message
,
174 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
175 throw RuntimeException(
176 OUSTR( "ScriptSecurityManager::addScriptStorage: caught RuntimeException" ).concat( rte
.Message
),
177 Reference
< XInterface
>() );
180 switch( m_runMacroSetting
)
182 case PERMISSION_NEVER
: // never
184 OSL_TRACE("never run");
187 case PERMISSION_PATHLIST
: // according to path list
189 OSL_TRACE("according to path");
191 rtl::OUString path
= scriptStorageURL
.copy( 0, scriptStorageURL
.lastIndexOf( '/' ) );
192 OSL_TRACE( "no of elts in path list = %d",
193 (int)m_secureURL
.getLength() );
194 bool match
= isSecureURL( path
);
195 if( match
&& ( m_warning
== sal_True
) )
197 OSL_TRACE("path match & warning dialog");
198 int result
= (int)executeStandardDialog();
199 OSL_TRACE("result = %d", (int)result
);
200 if ( (result
&ALLOW_RUN
) == ALLOW_RUN
)
202 newPerm
.execPermission
=sal_True
;
208 OSL_TRACE("path match & no warning dialog");
209 newPerm
.execPermission
=sal_True
;
212 else if( m_confirmationRequired
== sal_True
)
214 OSL_TRACE("no path match & confirmation dialog");
215 int result
= (int)executePathDialog( path
);
216 OSL_TRACE("result = %d", (int)result
);
217 if ( (result
&ALLOW_RUN
) == ALLOW_RUN
)
219 newPerm
.execPermission
=sal_True
;
221 if ( (result
&ADD_TO_PATH
) == ADD_TO_PATH
)
223 /* if checkbox clicked then need to add path to registry*/
224 addToSecurePaths(path
);
229 case PERMISSION_ALWAYS
: // always
230 if( m_warning
== sal_True
)
232 OSL_TRACE("always & warning dialog");
233 short result
= executeStandardDialog();
234 if ( (result
&ALLOW_RUN
) == ALLOW_RUN
)
236 newPerm
.execPermission
=sal_True
;
241 OSL_TRACE("always & no warning dialog");
242 newPerm
.execPermission
=sal_True
;
247 throw RuntimeException(
248 OUSTR( "ScriptSecurityManager::addScriptStorage got invalid OfficeBasic setting"),
249 Reference
< XInterface
> ());
252 if ( newPerm
.execPermission
== sal_True
)
254 OSL_TRACE("setting exec permission to true for %s",
255 ::rtl::OUStringToOString( scriptStorageURL
,
256 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
260 OSL_TRACE("setting exec permission to false for %s",
261 ::rtl::OUStringToOString( scriptStorageURL
,
262 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
265 m_permissionSettings
[ scriptStorageURL
] = newPerm
;
268 bool ScriptSecurityManager::isSecureURL( const OUString
& path
)
271 OSL_TRACE( "no of elts in path list = %d",
272 (int)m_secureURL
.getLength() );
273 OSL_TRACE("document path: %s",
274 ::rtl::OUStringToOString( path
,
275 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
276 int length
= m_secureURL
.getLength();
277 for( int j
= 0; j
< length
; j
++ )
279 OSL_TRACE("path list element: %s",
280 ::rtl::OUStringToOString( m_secureURL
[j
],
281 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
283 OSL_TRACE("case insensitive comparison");
284 if( path
.equalsIgnoreAsciiCase( m_secureURL
[j
] ) )
286 OSL_TRACE("case sensitive comparison");
287 if( path
.equals( m_secureURL
[j
] ) )
297 short ScriptSecurityManager::executeStandardDialog()
298 throw ( RuntimeException
)
300 OUString dummyString
;
301 return executeDialog( dummyString
);
304 short ScriptSecurityManager::executePathDialog( const OUString
& path
)
305 throw ( RuntimeException
)
307 return executeDialog( path
);
310 short ScriptSecurityManager::executeDialog( const OUString
& path
)
311 throw ( RuntimeException
)
313 Sequence
< Any
> aArgs
;
314 if( path
.getLength() != 0 )
316 OSL_TRACE("reallocing");
323 Reference
< lang::XMultiComponentFactory
> xMgr
= m_xContext
->getServiceManager();
325 "ScriptSecurityManager::executeDialog: cannot get ServiceManager" );
326 Reference
< XInterface
> xInterface
=
327 xMgr
->createInstanceWithArgumentsAndContext( s_securityDialog
,
329 validateXRef( xInterface
, "ScriptSecurityManager::executeDialog: Can't create SecurityDialog" );
330 Reference
< awt::XDialog
> xDialog( xInterface
, UNO_QUERY_THROW
);
331 result
= xDialog
->execute();
332 Reference
< lang::XComponent
> xComponent( xInterface
, UNO_QUERY_THROW
);
333 validateXRef( xInterface
, "ScriptSecurityManager::executeDialog: Can't get XComponent to dispose dialog" );
334 xComponent
->dispose();
336 catch ( RuntimeException
& rte
)
338 throw RuntimeException(
339 OUSTR( "ScriptSecurityManager::executeDialog: caught RuntimeException: ").concat( rte
.Message
),
340 Reference
< XInterface
> ());
342 catch ( Exception
& e
)
344 throw RuntimeException(
345 OUSTR( "ScriptSecurityManager::executeDialog: caught Exception: ").concat( e
.Message
),
346 Reference
< XInterface
> ());
352 * checks to see whether the requested ScriptPermission is allowed.
353 * This was modelled after the Java AccessController, but at this time
354 * we can't see a good reason not to return a bool, rather than throw
355 * an exception if the request is not granted (as is the case in Java).
357 void ScriptSecurityManager::checkPermission( const OUString
& scriptStorageURL
,
358 const OUString
& permissionRequest
)
359 throw ( RuntimeException
, lang::IllegalArgumentException
, security::AccessControlException
)
361 if( permissionRequest
.equals( OUString::createFromAscii( "execute" ) ) )
364 "ScriptSecurityManager::checkPermission: execute permission request for %s",
365 ::rtl::OUStringToOString( scriptStorageURL
,
366 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
367 Permission_Hash::const_iterator ph_it
= m_permissionSettings
.find( scriptStorageURL
);
368 Permission_Hash::const_iterator ph_itend
=
369 m_permissionSettings
.end();
370 if ( ph_it
!= ph_itend
)
372 if ( ph_it
->second
.execPermission
)
378 OSL_TRACE( "permission refused" );
380 security::RuntimePermission permission
;
381 permission
.Name
= OUString::createFromAscii( "execute" ).concat( scriptStorageURL
);
382 aPermission
<<= permission
;
383 throw security::AccessControlException(
384 OUString::createFromAscii( "ScriptSecurityManager::checkPermission: no execute permission for URL" ).concat( scriptStorageURL
),
385 Reference
< XInterface
> (), aPermission
);
388 // we should never get here!!
389 throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference
< XInterface
> (), 0 );
391 // inappropriate permission request
392 throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference
< XInterface
> (), 1 );
395 void ScriptSecurityManager::removePermissionSettings ( ::rtl::OUString
& scriptStorageURL
)
397 Permission_Hash::const_iterator ph_it
=
398 m_permissionSettings
.find( scriptStorageURL
);
400 if ( ph_it
== m_permissionSettings
.end() )
402 OSL_TRACE( "Entry for storage url %s doesn't exist in map",
403 ::rtl::OUStringToOString( scriptStorageURL
,
404 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
408 // erase the entry from the hash
409 m_permissionSettings
.erase( scriptStorageURL
);
413 void ScriptSecurityManager::readConfiguration()
414 throw ( RuntimeException
)
416 Reference
< XInterface
> xInterface
;
419 beans::PropertyValue configPath
;
420 configPath
.Name
= ::rtl::OUString::createFromAscii( "nodepath" );
421 configPath
.Value
<<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
422 Sequence
< Any
> aargs( 1 );
423 aargs
[ 0 ] <<= configPath
;
424 validateXRef( m_xConfigProvFactory
,
425 "ScriptSecurityManager::readConfiguration: ConfigProviderFactory no longer valid!" );
426 xInterface
= m_xConfigProvFactory
->createInstanceWithArguments( s_configAccess
,
428 validateXRef( xInterface
,
429 "ScriptSecurityManager::readConfiguration: cannot get ConfigurationAccess" );
430 // get the XPropertySet interface from the ConfigurationAccess service
431 Reference
< beans::XPropertySet
> xPropSet( xInterface
, UNO_QUERY
);
434 value
=xPropSet
->getPropertyValue( OUSTR( "Confirmation" ) );
435 if ( sal_False
== ( value
>>= m_confirmationRequired
) )
437 throw RuntimeException(
438 OUSTR( "ScriptSecurityManager:readConfiguration: can't get Confirmation setting" ),
439 Reference
< XInterface
> () );
441 if ( m_confirmationRequired
== sal_True
)
443 OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is true" );
447 OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is false" );
449 value
=xPropSet
->getPropertyValue( OUSTR( "Warning" ) );
450 if ( sal_False
== ( value
>>= m_warning
) )
452 throw RuntimeException(
453 OUSTR( "ScriptSecurityManager:readConfiguration: can't get Warning setting" ),
454 Reference
< XInterface
> () );
456 if ( m_warning
== sal_True
)
458 OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is true" );
462 OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is false" );
464 value
=xPropSet
->getPropertyValue( OUSTR( "OfficeBasic" ) );
465 if ( sal_False
== ( value
>>= m_runMacroSetting
) )
467 throw RuntimeException(
468 OUSTR( "ScriptSecurityManager:readConfiguration: can't get OfficeBasic setting" ),
469 Reference
< XInterface
> () );
471 OSL_TRACE( "ScriptSecurityManager:readConfiguration: OfficeBasic = %d", m_runMacroSetting
);
472 value
=xPropSet
->getPropertyValue( OUSTR( "SecureURL" ) );
473 if ( sal_False
== ( value
>>= m_secureURL
) )
475 throw RuntimeException(
476 OUSTR( "ScriptSecurityManager:readConfiguration: can't get SecureURL setting" ),
477 Reference
< XInterface
> () );
480 catch ( beans::UnknownPropertyException
& upe
)
482 throw RuntimeException(
483 OUSTR( "ScriptSecurityManager:readConfiguration: Attempt to read unknown property: " ).concat( upe
.Message
),
484 Reference
< XInterface
> () );
486 catch ( lang::WrappedTargetException
& wte
)
488 throw RuntimeException(
489 OUSTR( "ScriptSecurityManager:readConfiguration: wrapped target exception? :" ).concat( wte
.Message
),
490 Reference
< XInterface
> () );
492 catch ( Exception
& e
)
494 OSL_TRACE( "Unknown exception in readconf: %s",
495 ::rtl::OUStringToOString(e
.Message
,
496 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
497 throw RuntimeException(
498 OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ).concat( e
.Message
),
499 Reference
< XInterface
> () );
504 OSL_TRACE( "Completely Unknown exception in readconf!!!!!!");
505 throw RuntimeException(
506 OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ),
507 Reference
< XInterface
> () );
511 int length
= m_secureURL
.getLength();
513 // PathSubstitution needed to interpret variables found in config
514 Reference
< lang::XMultiComponentFactory
> xMgr
= m_xContext
->getServiceManager();
516 "ScriptSecurityManager::readConfiguration: cannot get XMultiComponentFactory" );
517 xInterface
= xMgr
->createInstanceWithContext(
518 ::rtl::OUString::createFromAscii(
519 "com.sun.star.util.PathSubstitution"), m_xContext
);
520 validateXRef( xInterface
,
521 "ScriptSecurityManager::readConfiguration: cannot get ConfigurationProvider" );
522 Reference
< util::XStringSubstitution
> xStringSubstitution(
523 xInterface
, UNO_QUERY
);
524 validateXRef( xStringSubstitution
,
525 "ScriptSecurityManager::readConfiguration: cannot get ConfigurationProvider" );
526 for( int i
= 0; i
< length
; i
++ )
528 OSL_TRACE( "ScriptSecurityManager:readConfiguration path = %s",
529 ::rtl::OUStringToOString(m_secureURL
[i
] ,
530 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
532 OSL_TRACE( "ScriptSecurityManager: subpath = %s",
533 ::rtl::OUStringToOString(
534 xStringSubstitution
->substituteVariables( m_secureURL
[i
], true ),
535 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
536 m_secureURL
[i
] = xStringSubstitution
->substituteVariables( m_secureURL
[i
], true );
539 int length2
= m_secureURL
.getLength();
540 for( int j
= 0; j
< length2
; j
++ )
542 OSL_TRACE( "ScriptSecurityManager: path = %s",
543 ::rtl::OUStringToOString(m_secureURL
[j
] ,
544 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
549 void ScriptSecurityManager::addToSecurePaths( const OUString
& path
)
550 throw ( RuntimeException
)
552 OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths" );
553 beans::PropertyValue configPath
;
554 configPath
.Name
= ::rtl::OUString::createFromAscii( "nodepath" );
555 configPath
.Value
<<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
556 Sequence
< Any
> aargs( 1 );
557 aargs
[ 0 ] <<= configPath
;
558 Reference
< XInterface
> xInterface
= m_xConfigProvFactory
->createInstanceWithArguments( s_configUpdate
,
560 validateXRef( xInterface
,
561 "ScriptSecurityManager::addToSecurePaths: ScriptSecurityManager: cannot get ConfigurationUpdateAccess" );
562 Reference
< container::XNameReplace
> xNameReplace( xInterface
, UNO_QUERY
);
563 validateXRef( xNameReplace
,
564 "ScriptSecurityManager::addToSecurePaths: ScriptSecurityManager: cannot get XNameReplace" );
565 Reference
< util::XChangesBatch
> xChangesBatch( xInterface
, UNO_QUERY
);
566 validateXRef( xChangesBatch
,
567 "ScriptSecurityManager::addToSecurePaths: cannot get XChangesBatch" );
569 OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths: after if stuff" );
570 Reference
< beans::XPropertySet
> xPropSet( xInterface
, UNO_QUERY
);
571 css::uno::Sequence
< rtl::OUString
> newSecureURL
;
573 OUString pathListPropName
= OUSTR ( "SecureURL" );
574 value
=xPropSet
->getPropertyValue( pathListPropName
);
575 if ( sal_False
== ( value
>>= newSecureURL
) )
577 throw RuntimeException(
578 OUSTR( "ScriptSecurityManager::addToSecurePaths: can't get SecureURL setting" ),
579 Reference
< XInterface
> () );
583 sal_Int32 length
= newSecureURL
.getLength();
584 newSecureURL
.realloc( length
+ 1 );
585 newSecureURL
[ length
] = path
;
587 aNewSecureURL
<<= newSecureURL
;
588 xNameReplace
->replaceByName( pathListPropName
, aNewSecureURL
);
589 xChangesBatch
->commitChanges();
590 m_secureURL
= newSecureURL
;
592 catch ( Exception
& e
)
594 OSL_TRACE( "Error updating secure paths: " );
595 throw RuntimeException(
596 OUSTR( "ScriptSecurityManager::addToSecurePaths: error updating SecureURL setting" ).concat( e
.Message
),
597 Reference
< XInterface
> () );
601 //*************************************************************************
602 // ScriptSecurityManager Destructor
603 ScriptSecurityManager::~ScriptSecurityManager()
605 OSL_TRACE( "< ScriptSecurityManager dtor called >\n" );