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 ) 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 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 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 248 short ScriptSecurityManager::executeStandardDialog() 249 throw ( RuntimeException ) 250 { 251 OUString dummyString; 252 return executeDialog( dummyString ); 253 } 254 255 short ScriptSecurityManager::executePathDialog( const OUString & path ) 256 throw ( RuntimeException ) 257 { 258 return executeDialog( path ); 259 } 260 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 */ 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 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 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 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 516 ScriptSecurityManager::~ScriptSecurityManager() 517 { 518 OSL_TRACE( "< ScriptSecurityManager dtor called >\n" ); 519 } 520 521 } // Namespace 522