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