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