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_scripting.hxx"
26
27 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/lang/XComponent.hpp>
30 #include <com/sun/star/lang/WrappedTargetException.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/beans/UnknownPropertyException.hpp>
34 #include <com/sun/star/container/XNameReplace.hpp>
35 #include <com/sun/star/util/XChangesBatch.hpp>
36 #include <com/sun/star/util/XMacroExpander.hpp>
37 #include <com/sun/star/util/XStringSubstitution.hpp>
38 #include <com/sun/star/awt/XDialog.hpp>
39 #include <com/sun/star/security/AccessControlException.hpp>
40 #include <com/sun/star/security/RuntimePermission.hpp>
41 #include <drafts/com/sun/star/script/framework/storage/XScriptStorageManager.hpp>
42 #include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp>
43 #include "ScriptSecurityManager.hxx"
44 #include <util/util.hxx>
45 #include <util/scriptingconstants.hxx>
46 #include <tools/diagnose_ex.h>
47
48 using namespace ::rtl;
49 using namespace ::osl;
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::drafts::com::sun::star::script::framework;
53
54 // is this in the utils?
55 const char* const SCRIPTSTORAGEMANAGER_SERVICE =
56 "/singletons/drafts.com.sun.star.script.framework.storage.theScriptStorageManager";
57
58 namespace scripting_securitymgr
59 {
60
61 static OUString s_configProv = ::rtl::OUString::createFromAscii(
62 "com.sun.star.configuration.ConfigurationProvider");
63
64 static OUString s_configAccess = ::rtl::OUString::createFromAscii(
65 "com.sun.star.configuration.ConfigurationAccess");
66
67 static OUString s_configUpdate = ::rtl::OUString::createFromAscii(
68 "com.sun.star.configuration.ConfigurationUpdateAccess");
69
70 static OUString s_securityDialog = ::rtl::OUString::createFromAscii(
71 "com.sun.star.script.framework.security.SecurityDialog");
72
73 static const int PERMISSION_NEVER = 0;
74 static const int PERMISSION_PATHLIST = 1;
75 static const int PERMISSION_ALWAYS = 2;
76
77 static const int ALLOW_RUN = 1;
78 static const int ADD_TO_PATH = 2;
79
80 //*************************************************************************
81 // ScriptSecurityManager Constructor
ScriptSecurityManager(const Reference<XComponentContext> & xContext)82 ScriptSecurityManager::ScriptSecurityManager(
83 const Reference< XComponentContext > & xContext ) throw ( RuntimeException )
84 : m_xContext( xContext, UNO_SET_THROW )
85 {
86 OSL_TRACE( "< ScriptSecurityManager ctor called >\n" );
87
88 // get the service manager from the context
89 Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );
90
91 // create an instance of the ConfigurationProvider
92 m_xConfigProvFactory.set( xMgr->createInstanceWithContext( s_configProv, m_xContext ), UNO_QUERY_THROW );
93 }
94
addScriptStorage(rtl::OUString scriptStorageURL,sal_Int32 storageID)95 void ScriptSecurityManager::addScriptStorage( rtl::OUString scriptStorageURL,
96 sal_Int32 storageID)
97 throw ( RuntimeException )
98 {
99 Permission_Hash::const_iterator ph_it = m_permissionSettings.find( scriptStorageURL );
100 if ( ph_it != m_permissionSettings.end() )
101 {
102 OSL_TRACE( "ScriptSecurityManager::addScriptStorage: already called for %s",
103 ::rtl::OUStringToOString( scriptStorageURL,
104 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
105 return;
106 }
107 StoragePerm newPerm;
108 newPerm.scriptStorageURL=scriptStorageURL;
109 newPerm.storageID=storageID;
110
111 // we err on the side of caution!!
112 newPerm.execPermission=sal_False;
113
114 //need to check if storage has any scripts
115 try
116 {
117 // we have some scripts so read config & decide on that basis
118 // Setup flags: m_runMacroSetting, m_warning, m_confirmationRequired,
119 readConfiguration();
120 }
121 catch ( RuntimeException & rte )
122 {
123 OSL_TRACE( "ScriptSecurityManager::addScriptStorage: caught RuntimeException: %s",
124 ::rtl::OUStringToOString( rte.Message,
125 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
126 throw RuntimeException(
127 OUSTR( "ScriptSecurityManager::addScriptStorage: caught RuntimeException" ).concat( rte.Message ),
128 Reference< XInterface >() );
129 }
130
131 switch( m_runMacroSetting )
132 {
133 case PERMISSION_NEVER: // never
134 {
135 OSL_TRACE("never run");
136 break;
137 }
138 case PERMISSION_PATHLIST: // according to path list
139 {
140 OSL_TRACE("according to path");
141 // check path
142 rtl::OUString path = scriptStorageURL.copy( 0, scriptStorageURL.lastIndexOf( '/' ) );
143 OSL_TRACE( "no of elts in path list = %d",
144 (int)m_secureURL.getLength() );
145 bool match = isSecureURL( path );
146 if( match && ( m_warning == sal_True ) )
147 {
148 OSL_TRACE("path match & warning dialog");
149 int result = (int)executeStandardDialog();
150 OSL_TRACE("result = %d", (int)result);
151 if ( (result&ALLOW_RUN) == ALLOW_RUN )
152 {
153 newPerm.execPermission=sal_True;
154 }
155 break;
156 }
157 else if ( match )
158 {
159 OSL_TRACE("path match & no warning dialog");
160 newPerm.execPermission=sal_True;
161 break;
162 }
163 else if( m_confirmationRequired == sal_True )
164 {
165 OSL_TRACE("no path match & confirmation dialog");
166 int result = (int)executePathDialog( path );
167 OSL_TRACE("result = %d", (int)result);
168 if ( (result&ALLOW_RUN) == ALLOW_RUN )
169 {
170 newPerm.execPermission=sal_True;
171 }
172 if ( (result&ADD_TO_PATH) == ADD_TO_PATH )
173 {
174 /* if checkbox clicked then need to add path to registry*/
175 addToSecurePaths(path);
176 }
177 }
178 break;
179 }
180 case PERMISSION_ALWAYS: // always
181 if( m_warning == sal_True )
182 {
183 OSL_TRACE("always & warning dialog");
184 short result = executeStandardDialog();
185 if ( (result&ALLOW_RUN) == ALLOW_RUN )
186 {
187 newPerm.execPermission=sal_True;
188 }
189 }
190 else
191 {
192 OSL_TRACE("always & no warning dialog");
193 newPerm.execPermission=sal_True;
194 }
195 break;
196 default:
197 //
198 throw RuntimeException(
199 OUSTR( "ScriptSecurityManager::addScriptStorage got invalid OfficeBasic setting"),
200 Reference< XInterface > ());
201 }
202
203 if ( newPerm.execPermission == sal_True )
204 {
205 OSL_TRACE("setting exec permission to true for %s",
206 ::rtl::OUStringToOString( scriptStorageURL,
207 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
208 }
209 else
210 {
211 OSL_TRACE("setting exec permission to false for %s",
212 ::rtl::OUStringToOString( scriptStorageURL,
213 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
214 }
215
216 m_permissionSettings[ scriptStorageURL ] = newPerm;
217 }
218
isSecureURL(const OUString & path)219 bool ScriptSecurityManager::isSecureURL( const OUString & path )
220 {
221 bool match = false;
222 OSL_TRACE( "no of elts in path list = %d",
223 (int)m_secureURL.getLength() );
224 OSL_TRACE("document path: %s",
225 ::rtl::OUStringToOString( path,
226 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
227 int length = m_secureURL.getLength();
228 for( int j = 0; j < length ; j++ )
229 {
230 OSL_TRACE("path list element: %s",
231 ::rtl::OUStringToOString( m_secureURL[j],
232 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
233 #ifdef WIN32
234 OSL_TRACE("case insensitive comparison");
235 if( path.equalsIgnoreAsciiCase( m_secureURL[j] ) )
236 #else
237 OSL_TRACE("case sensitive comparison");
238 if( path.equals( m_secureURL[j] ) )
239 #endif
240 {
241 match = true;
242 break;
243 }
244 }
245 return match;
246 }
247
executeStandardDialog()248 short ScriptSecurityManager::executeStandardDialog()
249 throw ( RuntimeException )
250 {
251 OUString dummyString;
252 return executeDialog( dummyString );
253 }
254
executePathDialog(const OUString & path)255 short ScriptSecurityManager::executePathDialog( const OUString & path )
256 throw ( RuntimeException )
257 {
258 return executeDialog( path );
259 }
260
executeDialog(const OUString & path)261 short ScriptSecurityManager::executeDialog( const OUString & path )
262 throw ( RuntimeException )
263 {
264 Sequence < Any > aArgs;
265 if( path.getLength() != 0 )
266 {
267 OSL_TRACE("reallocing");
268 aArgs.realloc(1);
269 aArgs[ 0 ] <<= path;
270 }
271 short result;
272 try
273 {
274 Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );
275 Reference< awt::XDialog > xDialog(
276 xMgr->createInstanceWithArgumentsAndContext( s_securityDialog, aArgs, m_xContext ),
277 UNO_QUERY_THROW );
278 result = xDialog->execute();
279 Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY_THROW );
280 xComponent->dispose();
281 }
282 catch ( RuntimeException & rte )
283 {
284 throw RuntimeException(
285 OUSTR( "ScriptSecurityManager::executeDialog: caught RuntimeException: ").concat( rte.Message ),
286 Reference< XInterface > ());
287 }
288 catch ( Exception & e )
289 {
290 throw RuntimeException(
291 OUSTR( "ScriptSecurityManager::executeDialog: caught Exception: ").concat( e.Message ),
292 Reference< XInterface > ());
293 }
294 return result;
295 }
296
297 /**
298 * checks to see whether the requested ScriptPermission is allowed.
299 * This was modelled after the Java AccessController, but at this time
300 * we can't see a good reason not to return a bool, rather than throw
301 * an exception if the request is not granted (as is the case in Java).
302 */
checkPermission(const OUString & scriptStorageURL,const OUString & permissionRequest)303 void ScriptSecurityManager::checkPermission( const OUString & scriptStorageURL,
304 const OUString & permissionRequest )
305 throw ( RuntimeException, lang::IllegalArgumentException, security::AccessControlException )
306 {
307 if( permissionRequest.equals( OUString::createFromAscii( "execute" ) ) )
308 {
309 OSL_TRACE(
310 "ScriptSecurityManager::checkPermission: execute permission request for %s",
311 ::rtl::OUStringToOString( scriptStorageURL,
312 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
313 Permission_Hash::const_iterator ph_it = m_permissionSettings.find( scriptStorageURL );
314 Permission_Hash::const_iterator ph_itend =
315 m_permissionSettings.end();
316 if ( ph_it != ph_itend )
317 {
318 if ( ph_it->second.execPermission )
319 {
320 return;
321 }
322 else
323 {
324 OSL_TRACE( "permission refused" );
325 Any aPermission;
326 security::RuntimePermission permission;
327 permission.Name = OUString::createFromAscii( "execute" ).concat( scriptStorageURL );
328 aPermission <<= permission;
329 throw security::AccessControlException(
330 OUString::createFromAscii( "ScriptSecurityManager::checkPermission: no execute permission for URL" ).concat( scriptStorageURL ),
331 Reference< XInterface > (), aPermission );
332 }
333 }
334 // we should never get here!!
335 throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference< XInterface > (), 0 );
336 }
337 // inappropriate permission request
338 throw lang::IllegalArgumentException( OUString::createFromAscii( "ScriptSecurityManager::checkPermission: storageURL not found" ), Reference< XInterface > (), 1 );
339 }
340
removePermissionSettings(::rtl::OUString & scriptStorageURL)341 void ScriptSecurityManager::removePermissionSettings ( ::rtl::OUString & scriptStorageURL )
342 {
343 Permission_Hash::const_iterator ph_it =
344 m_permissionSettings.find( scriptStorageURL );
345
346 if ( ph_it == m_permissionSettings.end() )
347 {
348 OSL_TRACE( "Entry for storage url %s doesn't exist in map",
349 ::rtl::OUStringToOString( scriptStorageURL,
350 RTL_TEXTENCODING_ASCII_US ).pData->buffer);
351 return;
352 }
353
354 // erase the entry from the hash
355 m_permissionSettings.erase( scriptStorageURL );
356
357 }
358
readConfiguration()359 void ScriptSecurityManager::readConfiguration()
360 throw ( RuntimeException)
361 {
362 try
363 {
364 beans::PropertyValue configPath;
365 configPath.Name = ::rtl::OUString::createFromAscii( "nodepath" );
366 configPath.Value <<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
367 Sequence < Any > aargs( 1 );
368 aargs[ 0 ] <<= configPath;
369 ENSURE_OR_THROW( m_xConfigProvFactory.is(),
370 "ScriptSecurityManager::readConfiguration: ConfigProviderFactory no longer valid!" );
371 // get the XPropertySet interface from the ConfigurationAccess service
372 Reference < beans::XPropertySet > xPropSet( m_xConfigProvFactory->createInstanceWithArguments( s_configAccess, aargs ), UNO_QUERY_THROW );
373
374 m_confirmationRequired = sal_True;
375 OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "Confirmation" ) ) >>= m_confirmationRequired );
376 if ( m_confirmationRequired == sal_True )
377 {
378 OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is true" );
379 }
380 else
381 {
382 OSL_TRACE( "ScriptSecurityManager:readConfiguration: confirmation is false" );
383 }
384
385 m_warning = true;
386 OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "Warning" ) ) >>= m_warning );
387
388 if ( m_warning == sal_True )
389 {
390 OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is true" );
391 }
392 else
393 {
394 OSL_TRACE( "ScriptSecurityManager:readConfiguration: warning is false" );
395 }
396
397 m_runMacroSetting = sal_True;
398 OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "OfficeBasic" ) ) >>= m_runMacroSetting );
399 OSL_TRACE( "ScriptSecurityManager:readConfiguration: OfficeBasic = %d", m_runMacroSetting );
400
401 m_secureURL = ::rtl::OUString();
402 OSL_VERIFY( xPropSet->getPropertyValue( OUSTR( "SecureURL" ) ) >>= m_secureURL );
403 }
404 catch ( beans::UnknownPropertyException & upe )
405 {
406 throw RuntimeException(
407 OUSTR( "ScriptSecurityManager:readConfiguration: Attempt to read unknown property: " ).concat( upe.Message ),
408 Reference< XInterface > () );
409 }
410 catch ( lang::WrappedTargetException & wte )
411 {
412 throw RuntimeException(
413 OUSTR( "ScriptSecurityManager:readConfiguration: wrapped target exception? :" ).concat( wte.Message ),
414 Reference< XInterface > () );
415 }
416 catch ( Exception & e )
417 {
418 OSL_TRACE( "Unknown exception in readconf: %s",
419 ::rtl::OUStringToOString(e.Message ,
420 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
421 throw RuntimeException(
422 OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ).concat( e.Message ),
423 Reference< XInterface > () );
424 }
425 #ifdef _DEBUG
426 catch ( ... )
427 {
428 OSL_TRACE( "Completely Unknown exception in readconf!!!!!!");
429 throw RuntimeException(
430 OUSTR( "ScriptSecurityManager:readConfiguration: exception? :" ),
431 Reference< XInterface > () );
432 }
433 #endif
434
435 int length = m_secureURL.getLength();
436
437 // PathSubstitution needed to interpret variables found in config
438 Reference< lang::XMultiComponentFactory > xMgr( m_xContext->getServiceManager(), UNO_SET_THROW );
439 Reference< XInterface > xInterface = );
440 Reference< util::XStringSubstitution > xStringSubstitution(
441 xMgr->createInstanceWithContext(
442 ::rtl::OUString::createFromAscii( "com.sun.star.util.PathSubstitution" ), m_xContext
443 ),
444 UNO_QUERY_THROW
445 );
446 for( int i = 0; i < length; i++ )
447 {
448 OSL_TRACE( "ScriptSecurityManager:readConfiguration path = %s",
449 ::rtl::OUStringToOString(m_secureURL[i] ,
450 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
451
452 OSL_TRACE( "ScriptSecurityManager: subpath = %s",
453 ::rtl::OUStringToOString(
454 xStringSubstitution->substituteVariables( m_secureURL[i], true ),
455 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
456 m_secureURL[i] = xStringSubstitution->substituteVariables( m_secureURL[i], true );
457 }
458 #ifdef _DEBUG
459 int length2 = m_secureURL.getLength();
460 for( int j = 0; j < length2 ; j++ )
461 {
462 OSL_TRACE( "ScriptSecurityManager: path = %s",
463 ::rtl::OUStringToOString(m_secureURL[j] ,
464 RTL_TEXTENCODING_ASCII_US ).pData->buffer );
465 }
466 #endif
467 }
468
addToSecurePaths(const OUString & path)469 void ScriptSecurityManager::addToSecurePaths( const OUString & path )
470 throw ( RuntimeException )
471 {
472 OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths" );
473 beans::PropertyValue configPath;
474 configPath.Name = ::rtl::OUString::createFromAscii( "nodepath" );
475 configPath.Value <<= ::rtl::OUString::createFromAscii( "org.openoffice.Office.Common/Security/Scripting" );
476 Sequence < Any > aargs( 1 );
477 aargs[ 0 ] <<= configPath;
478 Reference < container::XNameReplace > xNameReplace(
479 m_xConfigProvFactory->createInstanceWithArguments( s_configUpdate, aargs ), UNO_QUERY_THROW );
480 Reference < util::XChangesBatch > xChangesBatch( xNameReplace, UNO_QUERY_THROW );
481
482 OSL_TRACE( "--->ScriptSecurityManager::addToSecurePaths: after if stuff" );
483 Reference < beans::XPropertySet > xPropSet( xInterface, UNO_QUERY );
484 css::uno::Sequence< rtl::OUString > newSecureURL;
485 Any value;
486 OUString pathListPropName = OUSTR ( "SecureURL" );
487 value=xPropSet->getPropertyValue( pathListPropName );
488 if ( sal_False == ( value >>= newSecureURL ) )
489 {
490 throw RuntimeException(
491 OUSTR( "ScriptSecurityManager::addToSecurePaths: can't get SecureURL setting" ),
492 Reference< XInterface > () );
493 }
494 try
495 {
496 sal_Int32 length = newSecureURL.getLength();
497 newSecureURL.realloc( length + 1 );
498 newSecureURL[ length ] = path;
499 Any aNewSecureURL;
500 aNewSecureURL <<= newSecureURL;
501 xNameReplace->replaceByName( pathListPropName, aNewSecureURL );
502 xChangesBatch->commitChanges();
503 m_secureURL = newSecureURL;
504 }
505 catch ( Exception & e )
506 {
507 OSL_TRACE( "Error updating secure paths: " );
508 throw RuntimeException(
509 OUSTR( "ScriptSecurityManager::addToSecurePaths: error updating SecureURL setting" ).concat( e.Message ),
510 Reference< XInterface > () );
511 }
512 }
513
514 //*************************************************************************
515 // ScriptSecurityManager Destructor
~ScriptSecurityManager()516 ScriptSecurityManager::~ScriptSecurityManager()
517 {
518 OSL_TRACE( "< ScriptSecurityManager dtor called >\n" );
519 }
520
521 } // Namespace
522