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 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 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 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 247 short ScriptSecurityManager::executeStandardDialog() 248 { 249 OUString dummyString; 250 return executeDialog( dummyString ); 251 } 252 253 short ScriptSecurityManager::executePathDialog( const OUString & path ) 254 { 255 return executeDialog( path ); 256 } 257 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 */ 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 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 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 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 509 ScriptSecurityManager::~ScriptSecurityManager() 510 { 511 OSL_TRACE( "< ScriptSecurityManager dtor called >\n" ); 512 } 513 514 } // Namespace 515