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_stoc.hxx" 30 31 #include <vector> 32 #include <memory> 33 34 #include <osl/diagnose.h> 35 #include <osl/interlck.h> 36 #include <osl/mutex.hxx> 37 #include <osl/thread.hxx> 38 39 #include <rtl/ustrbuf.hxx> 40 #include <rtl/string.hxx> 41 42 #include <uno/current_context.h> 43 44 #include <cppuhelper/implbase1.hxx> 45 #include <cppuhelper/compbase3.hxx> 46 #include <cppuhelper/factory.hxx> 47 #include <cppuhelper/implementationentry.hxx> 48 49 #include <com/sun/star/uno/XCurrentContext.hpp> 50 #include <com/sun/star/uno/DeploymentException.hpp> 51 #include <com/sun/star/lang/DisposedException.hpp> 52 #include <com/sun/star/lang/XComponent.hpp> 53 #include <com/sun/star/lang/XServiceInfo.hpp> 54 #include <com/sun/star/lang/XInitialization.hpp> 55 #include <com/sun/star/security/XAccessController.hpp> 56 #include <com/sun/star/security/XPolicy.hpp> 57 58 #include "lru_cache.h" 59 #include "permissions.h" 60 61 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 62 #define SERVICE_NAME "com.sun.star.security.AccessController" 63 #define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController" 64 #define USER_CREDS "access-control.user-credentials" 65 66 67 using namespace ::std; 68 using namespace ::osl; 69 using namespace ::cppu; 70 using namespace ::com::sun::star; 71 using namespace ::com::sun::star::uno; 72 using ::rtl::OUString; 73 using ::rtl::OUStringBuffer; 74 using ::rtl::OString; 75 76 extern ::rtl_StandardModuleCount g_moduleCount; 77 78 namespace stoc_sec 79 { 80 // static stuff initialized when loading lib 81 static OUString s_envType = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); 82 static OUString s_implName = OUSTR(IMPL_NAME); 83 static OUString s_serviceName = OUSTR(SERVICE_NAME); 84 static OUString s_acRestriction = OUSTR("access-control.restriction"); 85 86 static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); 87 88 //################################################################################################## 89 90 /** ac context intersects permissions of two ac contexts 91 */ 92 class acc_Intersection 93 : public WeakImplHelper1< security::XAccessControlContext > 94 { 95 Reference< security::XAccessControlContext > m_x1, m_x2; 96 97 inline acc_Intersection( 98 Reference< security::XAccessControlContext > const & x1, 99 Reference< security::XAccessControlContext > const & x2 ) 100 SAL_THROW( () ); 101 102 public: 103 virtual ~acc_Intersection() 104 SAL_THROW( () ); 105 106 static inline Reference< security::XAccessControlContext > create( 107 Reference< security::XAccessControlContext > const & x1, 108 Reference< security::XAccessControlContext > const & x2 ) 109 SAL_THROW( () ); 110 111 // XAccessControlContext impl 112 virtual void SAL_CALL checkPermission( 113 Any const & perm ) 114 throw (RuntimeException); 115 }; 116 //__________________________________________________________________________________________________ 117 inline acc_Intersection::acc_Intersection( 118 Reference< security::XAccessControlContext > const & x1, 119 Reference< security::XAccessControlContext > const & x2 ) 120 SAL_THROW( () ) 121 : m_x1( x1 ) 122 , m_x2( x2 ) 123 { 124 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 125 } 126 //__________________________________________________________________________________________________ 127 acc_Intersection::~acc_Intersection() 128 SAL_THROW( () ) 129 { 130 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 131 } 132 //-------------------------------------------------------------------------------------------------- 133 inline Reference< security::XAccessControlContext > acc_Intersection::create( 134 Reference< security::XAccessControlContext > const & x1, 135 Reference< security::XAccessControlContext > const & x2 ) 136 SAL_THROW( () ) 137 { 138 if (! x1.is()) 139 return x2; 140 if (! x2.is()) 141 return x1; 142 return new acc_Intersection( x1, x2 ); 143 } 144 //__________________________________________________________________________________________________ 145 void acc_Intersection::checkPermission( 146 Any const & perm ) 147 throw (RuntimeException) 148 { 149 m_x1->checkPermission( perm ); 150 m_x2->checkPermission( perm ); 151 } 152 153 /** ac context unifies permissions of two ac contexts 154 */ 155 class acc_Union 156 : public WeakImplHelper1< security::XAccessControlContext > 157 { 158 Reference< security::XAccessControlContext > m_x1, m_x2; 159 160 inline acc_Union( 161 Reference< security::XAccessControlContext > const & x1, 162 Reference< security::XAccessControlContext > const & x2 ) 163 SAL_THROW( () ); 164 165 public: 166 virtual ~acc_Union() 167 SAL_THROW( () ); 168 169 static inline Reference< security::XAccessControlContext > create( 170 Reference< security::XAccessControlContext > const & x1, 171 Reference< security::XAccessControlContext > const & x2 ) 172 SAL_THROW( () ); 173 174 // XAccessControlContext impl 175 virtual void SAL_CALL checkPermission( 176 Any const & perm ) 177 throw (RuntimeException); 178 }; 179 //__________________________________________________________________________________________________ 180 inline acc_Union::acc_Union( 181 Reference< security::XAccessControlContext > const & x1, 182 Reference< security::XAccessControlContext > const & x2 ) 183 SAL_THROW( () ) 184 : m_x1( x1 ) 185 , m_x2( x2 ) 186 { 187 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 188 } 189 //__________________________________________________________________________________________________ 190 acc_Union::~acc_Union() 191 SAL_THROW( () ) 192 { 193 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 194 } 195 //-------------------------------------------------------------------------------------------------- 196 inline Reference< security::XAccessControlContext > acc_Union::create( 197 Reference< security::XAccessControlContext > const & x1, 198 Reference< security::XAccessControlContext > const & x2 ) 199 SAL_THROW( () ) 200 { 201 if (! x1.is()) 202 return Reference< security::XAccessControlContext >(); // unrestricted 203 if (! x2.is()) 204 return Reference< security::XAccessControlContext >(); // unrestricted 205 return new acc_Union( x1, x2 ); 206 } 207 //__________________________________________________________________________________________________ 208 void acc_Union::checkPermission( 209 Any const & perm ) 210 throw (RuntimeException) 211 { 212 try 213 { 214 m_x1->checkPermission( perm ); 215 } 216 catch (security::AccessControlException &) 217 { 218 m_x2->checkPermission( perm ); 219 } 220 } 221 222 /** ac context doing permission checks on static permissions 223 */ 224 class acc_Policy 225 : public WeakImplHelper1< security::XAccessControlContext > 226 { 227 PermissionCollection m_permissions; 228 229 public: 230 inline acc_Policy( 231 PermissionCollection const & permissions ) 232 SAL_THROW( () ); 233 virtual ~acc_Policy() 234 SAL_THROW( () ); 235 236 // XAccessControlContext impl 237 virtual void SAL_CALL checkPermission( 238 Any const & perm ) 239 throw (RuntimeException); 240 }; 241 //__________________________________________________________________________________________________ 242 inline acc_Policy::acc_Policy( 243 PermissionCollection const & permissions ) 244 SAL_THROW( () ) 245 : m_permissions( permissions ) 246 { 247 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 248 } 249 //__________________________________________________________________________________________________ 250 acc_Policy::~acc_Policy() 251 SAL_THROW( () ) 252 { 253 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 254 } 255 //__________________________________________________________________________________________________ 256 void acc_Policy::checkPermission( 257 Any const & perm ) 258 throw (RuntimeException) 259 { 260 m_permissions.checkPermission( perm ); 261 } 262 263 /** current context overriding dynamic ac restriction 264 */ 265 class acc_CurrentContext 266 : public ImplHelper1< XCurrentContext > 267 { 268 oslInterlockedCount m_refcount; 269 270 Reference< XCurrentContext > m_xDelegate; 271 Any m_restriction; 272 273 public: 274 inline acc_CurrentContext( 275 Reference< XCurrentContext > const & xDelegate, 276 Reference< security::XAccessControlContext > const & xRestriction ) 277 SAL_THROW( () ); 278 virtual ~acc_CurrentContext() SAL_THROW( () ); 279 280 // XInterface impl 281 virtual void SAL_CALL acquire() 282 throw (); 283 virtual void SAL_CALL release() 284 throw (); 285 286 // XCurrentContext impl 287 virtual Any SAL_CALL getValueByName( OUString const & name ) 288 throw (RuntimeException); 289 }; 290 //__________________________________________________________________________________________________ 291 inline acc_CurrentContext::acc_CurrentContext( 292 Reference< XCurrentContext > const & xDelegate, 293 Reference< security::XAccessControlContext > const & xRestriction ) 294 SAL_THROW( () ) 295 : m_refcount( 0 ) 296 , m_xDelegate( xDelegate ) 297 { 298 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 299 300 if (xRestriction.is()) 301 { 302 m_restriction = makeAny( xRestriction ); 303 } 304 // return empty any otherwise on getValueByName(), not null interface 305 } 306 //__________________________________________________________________________________________________ 307 acc_CurrentContext::~acc_CurrentContext() 308 SAL_THROW( () ) 309 { 310 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 311 } 312 //__________________________________________________________________________________________________ 313 void acc_CurrentContext::acquire() 314 throw () 315 { 316 ::osl_incrementInterlockedCount( &m_refcount ); 317 } 318 //__________________________________________________________________________________________________ 319 void acc_CurrentContext::release() 320 throw () 321 { 322 if (! ::osl_decrementInterlockedCount( &m_refcount )) 323 { 324 delete this; 325 } 326 } 327 //__________________________________________________________________________________________________ 328 Any acc_CurrentContext::getValueByName( OUString const & name ) 329 throw (RuntimeException) 330 { 331 if (name.equals( s_acRestriction )) 332 { 333 return m_restriction; 334 } 335 else if (m_xDelegate.is()) 336 { 337 return m_xDelegate->getValueByName( name ); 338 } 339 else 340 { 341 return Any(); 342 } 343 } 344 345 //################################################################################################## 346 347 //-------------------------------------------------------------------------------------------------- 348 static inline void dispose( Reference< XInterface > const & x ) 349 SAL_THROW( (RuntimeException) ) 350 { 351 Reference< lang::XComponent > xComp( x, UNO_QUERY ); 352 if (xComp.is()) 353 { 354 xComp->dispose(); 355 } 356 } 357 //-------------------------------------------------------------------------------------------------- 358 static inline Reference< security::XAccessControlContext > getDynamicRestriction( 359 Reference< XCurrentContext > const & xContext ) 360 SAL_THROW( (RuntimeException) ) 361 { 362 if (xContext.is()) 363 { 364 Any acc( xContext->getValueByName( s_acRestriction ) ); 365 if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass) 366 { 367 // avoid ref-counting 368 OUString const & typeName = 369 *reinterpret_cast< OUString const * >( &acc.pType->pTypeName ); 370 if (typeName.equalsAsciiL( 371 RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.XAccessControlContext") )) 372 { 373 return Reference< security::XAccessControlContext >( 374 *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) ); 375 } 376 else // try to query 377 { 378 return Reference< security::XAccessControlContext >::query( 379 *reinterpret_cast< XInterface ** const >( acc.pData ) ); 380 } 381 } 382 } 383 return Reference< security::XAccessControlContext >(); 384 } 385 //================================================================================================== 386 class cc_reset 387 { 388 void * m_cc; 389 public: 390 inline cc_reset( void * cc ) SAL_THROW( () ) 391 : m_cc( cc ) {} 392 inline ~cc_reset() SAL_THROW( () ) 393 { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); } 394 }; 395 396 //################################################################################################## 397 398 struct MutexHolder 399 { 400 Mutex m_mutex; 401 }; 402 typedef WeakComponentImplHelper3< 403 security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper; 404 405 //================================================================================================== 406 class AccessController 407 : public MutexHolder 408 , public t_helper 409 { 410 Reference< XComponentContext > m_xComponentContext; 411 412 Reference< security::XPolicy > m_xPolicy; 413 Reference< security::XPolicy > const & getPolicy() 414 SAL_THROW( (RuntimeException) ); 415 416 // mode 417 enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode; 418 419 PermissionCollection m_defaultPermissions; 420 // for single-user mode 421 PermissionCollection m_singleUserPermissions; 422 OUString m_singleUserId; 423 bool m_defaultPerm_init; 424 bool m_singleUser_init; 425 // for multi-user mode 426 lru_cache< OUString, PermissionCollection, ::rtl::OUStringHash, equal_to< OUString > > 427 m_user2permissions; 428 429 ThreadData m_rec; 430 typedef vector< pair< OUString, Any > > t_rec_vec; 431 inline void clearPostPoned() SAL_THROW( () ); 432 void checkAndClearPostPoned() SAL_THROW( (RuntimeException) ); 433 434 PermissionCollection getEffectivePermissions( 435 Reference< XCurrentContext > const & xContext, 436 Any const & demanded_perm ) 437 SAL_THROW( (RuntimeException) ); 438 439 protected: 440 virtual void SAL_CALL disposing(); 441 442 public: 443 AccessController( Reference< XComponentContext > const & xComponentContext ) 444 SAL_THROW( (RuntimeException) ); 445 virtual ~AccessController() 446 SAL_THROW( () ); 447 448 // XInitialization impl 449 virtual void SAL_CALL initialize( 450 Sequence< Any > const & arguments ) 451 throw (Exception); 452 453 // XAccessController impl 454 virtual void SAL_CALL checkPermission( 455 Any const & perm ) 456 throw (RuntimeException); 457 virtual Any SAL_CALL doRestricted( 458 Reference< security::XAction > const & xAction, 459 Reference< security::XAccessControlContext > const & xRestriction ) 460 throw (Exception); 461 virtual Any SAL_CALL doPrivileged( 462 Reference< security::XAction > const & xAction, 463 Reference< security::XAccessControlContext > const & xRestriction ) 464 throw (Exception); 465 virtual Reference< security::XAccessControlContext > SAL_CALL getContext() 466 throw (RuntimeException); 467 468 // XServiceInfo impl 469 virtual OUString SAL_CALL getImplementationName() 470 throw (RuntimeException); 471 virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) 472 throw (RuntimeException); 473 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() 474 throw (RuntimeException); 475 }; 476 //__________________________________________________________________________________________________ 477 AccessController::AccessController( Reference< XComponentContext > const & xComponentContext ) 478 SAL_THROW( (RuntimeException) ) 479 : t_helper( m_mutex ) 480 , m_xComponentContext( xComponentContext ) 481 , m_mode( ON ) // default 482 , m_defaultPerm_init( false ) 483 , m_singleUser_init( false ) 484 , m_rec( 0 ) 485 { 486 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 487 488 OUString mode; 489 if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode) 490 { 491 if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("off") )) 492 { 493 m_mode = OFF; 494 } 495 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("on") )) 496 { 497 m_mode = ON; 498 } 499 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dynamic-only") )) 500 { 501 m_mode = DYNAMIC_ONLY; 502 } 503 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-user") )) 504 { 505 m_xComponentContext->getValueByName( 506 OUSTR("/services/" SERVICE_NAME "/single-user-id") ) >>= m_singleUserId; 507 if (! m_singleUserId.getLength()) 508 { 509 throw RuntimeException( 510 OUSTR("expected a user id in component context entry " 511 "\"/services/" SERVICE_NAME "/single-user-id\"!"), 512 (OWeakObject *)this ); 513 } 514 m_mode = SINGLE_USER; 515 } 516 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-default-user") )) 517 { 518 m_mode = SINGLE_DEFAULT_USER; 519 } 520 } 521 522 // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process) 523 if (ON == m_mode || DYNAMIC_ONLY == m_mode) 524 { 525 sal_Int32 cacheSize = 0; // multi-user cache size 526 if (! (m_xComponentContext->getValueByName( 527 OUSTR("/services/" SERVICE_NAME "/user-cache-size") ) >>= cacheSize)) 528 { 529 cacheSize = 128; // reasonable default? 530 } 531 #ifdef __CACHE_DIAGNOSE 532 cacheSize = 2; 533 #endif 534 m_user2permissions.setSize( cacheSize ); 535 } 536 } 537 //__________________________________________________________________________________________________ 538 AccessController::~AccessController() 539 SAL_THROW( () ) 540 { 541 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 542 } 543 //__________________________________________________________________________________________________ 544 void AccessController::disposing() 545 { 546 m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY? 547 m_xPolicy.clear(); 548 m_xComponentContext.clear(); 549 } 550 551 // XInitialization impl 552 //__________________________________________________________________________________________________ 553 void AccessController::initialize( 554 Sequence< Any > const & arguments ) 555 throw (Exception) 556 { 557 // xxx todo: review for forking 558 // portal forking hack: re-initialize for another user-id 559 if (SINGLE_USER != m_mode) // only if in single-user mode 560 { 561 throw RuntimeException( 562 OUSTR("invalid call: ac must be in \"single-user\" mode!"), (OWeakObject *)this ); 563 } 564 OUString userId; 565 arguments[ 0 ] >>= userId; 566 if (! userId.getLength()) 567 { 568 throw RuntimeException( 569 OUSTR("expected a user-id as first argument!"), (OWeakObject *)this ); 570 } 571 // assured that no sync is necessary: no check happens at this forking time 572 m_singleUserId = userId; 573 m_singleUser_init = false; 574 } 575 576 //__________________________________________________________________________________________________ 577 Reference< security::XPolicy > const & AccessController::getPolicy() 578 SAL_THROW( (RuntimeException) ) 579 { 580 // get policy singleton 581 if (! m_xPolicy.is()) 582 { 583 Reference< security::XPolicy > xPolicy; 584 m_xComponentContext->getValueByName( 585 OUSTR("/singletons/com.sun.star.security.thePolicy") ) >>= xPolicy; 586 if (xPolicy.is()) 587 { 588 MutexGuard guard( m_mutex ); 589 if (! m_xPolicy.is()) 590 { 591 m_xPolicy = xPolicy; 592 } 593 } 594 else 595 { 596 throw SecurityException( 597 OUSTR("cannot get policy singleton!"), (OWeakObject *)this ); 598 } 599 } 600 return m_xPolicy; 601 } 602 603 #ifdef __DIAGNOSE 604 static void dumpPermissions( 605 PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW( () ) 606 { 607 OUStringBuffer buf( 48 ); 608 if (userId.getLength()) 609 { 610 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> dumping permissions of user \"") ); 611 buf.append( userId ); 612 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\":") ); 613 } 614 else 615 { 616 buf.appendAscii( 617 RTL_CONSTASCII_STRINGPARAM("> dumping default permissions:") ); 618 } 619 OString str( ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 620 OSL_TRACE( str.getStr() ); 621 Sequence< OUString > permissions( collection.toStrings() ); 622 OUString const * p = permissions.getConstArray(); 623 for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos ) 624 { 625 OString str( ::rtl::OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) ); 626 OSL_TRACE( str.getStr() ); 627 } 628 OSL_TRACE( "> permission dump done" ); 629 } 630 #endif 631 632 633 //__________________________________________________________________________________________________ 634 inline void AccessController::clearPostPoned() SAL_THROW( () ) 635 { 636 delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); 637 m_rec.setData( 0 ); 638 } 639 //__________________________________________________________________________________________________ 640 void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) ) 641 { 642 // check postponed permissions 643 auto_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) ); 644 m_rec.setData( 0 ); // takeover ownership 645 OSL_ASSERT( rec.get() ); 646 if (rec.get()) 647 { 648 t_rec_vec const & vec = *rec.get(); 649 switch (m_mode) 650 { 651 case SINGLE_USER: 652 { 653 OSL_ASSERT( m_singleUser_init ); 654 for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) 655 { 656 pair< OUString, Any > const & p = vec[ nPos ]; 657 OSL_ASSERT( m_singleUserId.equals( p.first ) ); 658 m_singleUserPermissions.checkPermission( p.second ); 659 } 660 break; 661 } 662 case SINGLE_DEFAULT_USER: 663 { 664 OSL_ASSERT( m_defaultPerm_init ); 665 for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) 666 { 667 pair< OUString, Any > const & p = vec[ nPos ]; 668 OSL_ASSERT( !p.first.getLength() ); // default-user 669 m_defaultPermissions.checkPermission( p.second ); 670 } 671 break; 672 } 673 case ON: 674 { 675 for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) 676 { 677 pair< OUString, Any > const & p = vec[ nPos ]; 678 PermissionCollection const * pPermissions; 679 // lookup policy for user 680 { 681 MutexGuard guard( m_mutex ); 682 pPermissions = m_user2permissions.lookup( p.first ); 683 } 684 OSL_ASSERT( pPermissions ); 685 if (pPermissions) 686 { 687 pPermissions->checkPermission( p.second ); 688 } 689 } 690 break; 691 } 692 default: 693 OSL_ENSURE( 0, "### this should never be called in this ac mode!" ); 694 break; 695 } 696 } 697 } 698 //__________________________________________________________________________________________________ 699 /** this is the only function calling the policy singleton and thus has to take care 700 of recurring calls! 701 702 @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call 703 which will be postponed for recurring calls 704 */ 705 PermissionCollection AccessController::getEffectivePermissions( 706 Reference< XCurrentContext > const & xContext, 707 Any const & demanded_perm ) 708 SAL_THROW( (RuntimeException) ) 709 { 710 OUString userId; 711 712 switch (m_mode) 713 { 714 case SINGLE_USER: 715 { 716 if (m_singleUser_init) 717 return m_singleUserPermissions; 718 userId = m_singleUserId; 719 break; 720 } 721 case SINGLE_DEFAULT_USER: 722 { 723 if (m_defaultPerm_init) 724 return m_defaultPermissions; 725 break; 726 } 727 case ON: 728 { 729 if (xContext.is()) 730 { 731 xContext->getValueByName( OUSTR(USER_CREDS ".id") ) >>= userId; 732 } 733 if (! userId.getLength()) 734 { 735 throw SecurityException( 736 OUSTR("cannot determine current user in multi-user ac!"), (OWeakObject *)this ); 737 } 738 739 // lookup policy for user 740 MutexGuard guard( m_mutex ); 741 PermissionCollection const * pPermissions = m_user2permissions.lookup( userId ); 742 if (pPermissions) 743 return *pPermissions; 744 break; 745 } 746 default: 747 OSL_ENSURE( 0, "### this should never be called in this ac mode!" ); 748 return PermissionCollection(); 749 } 750 751 // call on policy 752 // iff this is a recurring call for the default user, then grant all permissions 753 t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() ); 754 if (rec) // tls entry exists => this is recursive call 755 { 756 if (demanded_perm.hasValue()) 757 { 758 // enqueue 759 rec->push_back( pair< OUString, Any >( userId, demanded_perm ) ); 760 } 761 #ifdef __DIAGNOSE 762 OUStringBuffer buf( 48 ); 763 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> info: recurring call of user \"") ); 764 buf.append( userId ); 765 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"") ); 766 OString str( 767 ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 768 OSL_TRACE( str.getStr() ); 769 #endif 770 return PermissionCollection( new AllPermission() ); 771 } 772 else // no tls 773 { 774 rec = new t_rec_vec; 775 m_rec.setData( rec ); 776 } 777 778 try // calls on API 779 { 780 // init default permissions 781 if (! m_defaultPerm_init) 782 { 783 PermissionCollection defaultPermissions( 784 getPolicy()->getDefaultPermissions() ); 785 // assign 786 MutexGuard guard( m_mutex ); 787 if (! m_defaultPerm_init) 788 { 789 m_defaultPermissions = defaultPermissions; 790 m_defaultPerm_init = true; 791 } 792 #ifdef __DIAGNOSE 793 dumpPermissions( m_defaultPermissions ); 794 #endif 795 } 796 797 PermissionCollection ret; 798 799 // init user permissions 800 switch (m_mode) 801 { 802 case SINGLE_USER: 803 { 804 ret = PermissionCollection( 805 getPolicy()->getPermissions( userId ), m_defaultPermissions ); 806 { 807 // assign 808 MutexGuard guard( m_mutex ); 809 if (m_singleUser_init) 810 { 811 ret = m_singleUserPermissions; 812 } 813 else 814 { 815 m_singleUserPermissions = ret; 816 m_singleUser_init = true; 817 } 818 } 819 #ifdef __DIAGNOSE 820 dumpPermissions( ret, userId ); 821 #endif 822 break; 823 } 824 case SINGLE_DEFAULT_USER: 825 { 826 ret = m_defaultPermissions; 827 break; 828 } 829 case ON: 830 { 831 ret = PermissionCollection( 832 getPolicy()->getPermissions( userId ), m_defaultPermissions ); 833 { 834 // cache 835 MutexGuard guard( m_mutex ); 836 m_user2permissions.set( userId, ret ); 837 } 838 #ifdef __DIAGNOSE 839 dumpPermissions( ret, userId ); 840 #endif 841 break; 842 } 843 default: 844 break; 845 } 846 847 // check postponed 848 checkAndClearPostPoned(); 849 return ret; 850 } 851 catch (security::AccessControlException & exc) // wrapped into DeploymentException 852 { 853 clearPostPoned(); // safety: exception could have happened before checking postponed? 854 OUStringBuffer buf( 64 ); 855 buf.appendAscii( 856 RTL_CONSTASCII_STRINGPARAM("deployment error (AccessControlException occured): ") ); 857 buf.append( exc.Message ); 858 throw DeploymentException( buf.makeStringAndClear(), exc.Context ); 859 } 860 catch (RuntimeException &) 861 { 862 // dont check postponed, just cleanup 863 clearPostPoned(); 864 delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); 865 m_rec.setData( 0 ); 866 throw; 867 } 868 catch (Exception &) 869 { 870 // check postponed permissions first 871 // => AccessControlExceptions are errors, user exceptions not! 872 checkAndClearPostPoned(); 873 throw; 874 } 875 catch (...) 876 { 877 // dont check postponed, just cleanup 878 clearPostPoned(); 879 throw; 880 } 881 } 882 883 // XAccessController impl 884 //__________________________________________________________________________________________________ 885 void AccessController::checkPermission( 886 Any const & perm ) 887 throw (RuntimeException) 888 { 889 if (rBHelper.bDisposed) 890 { 891 throw lang::DisposedException( 892 OUSTR("checkPermission() call on disposed AccessController!"), (OWeakObject *)this ); 893 } 894 895 if (OFF == m_mode) 896 return; 897 898 // first dynamic check of ac contexts 899 Reference< XCurrentContext > xContext; 900 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); 901 Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) ); 902 if (xACC.is()) 903 { 904 xACC->checkPermission( perm ); 905 } 906 907 if (DYNAMIC_ONLY == m_mode) 908 return; 909 910 // then static check 911 getEffectivePermissions( xContext, perm ).checkPermission( perm ); 912 } 913 //__________________________________________________________________________________________________ 914 Any AccessController::doRestricted( 915 Reference< security::XAction > const & xAction, 916 Reference< security::XAccessControlContext > const & xRestriction ) 917 throw (Exception) 918 { 919 if (rBHelper.bDisposed) 920 { 921 throw lang::DisposedException( 922 OUSTR("doRestricted() call on disposed AccessController!"), (OWeakObject *)this ); 923 } 924 925 if (OFF == m_mode) // optimize this way, because no dynamic check will be performed 926 return xAction->run(); 927 928 if (xRestriction.is()) 929 { 930 Reference< XCurrentContext > xContext; 931 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); 932 933 // override restriction 934 Reference< XCurrentContext > xNewContext( 935 new acc_CurrentContext( xContext, acc_Intersection::create( 936 xRestriction, getDynamicRestriction( xContext ) ) ) ); 937 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); 938 cc_reset reset( xContext.get() ); 939 return xAction->run(); 940 } 941 else 942 { 943 return xAction->run(); 944 } 945 } 946 //__________________________________________________________________________________________________ 947 Any AccessController::doPrivileged( 948 Reference< security::XAction > const & xAction, 949 Reference< security::XAccessControlContext > const & xRestriction ) 950 throw (Exception) 951 { 952 if (rBHelper.bDisposed) 953 { 954 throw lang::DisposedException( 955 OUSTR("doPrivileged() call on disposed AccessController!"), (OWeakObject *)this ); 956 } 957 958 if (OFF == m_mode) // no dynamic check will be performed 959 { 960 return xAction->run(); 961 } 962 963 Reference< XCurrentContext > xContext; 964 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); 965 966 Reference< security::XAccessControlContext > xOldRestr( 967 getDynamicRestriction( xContext ) ); 968 969 if (xOldRestr.is()) // previous restriction 970 { 971 // override restriction 972 Reference< XCurrentContext > xNewContext( 973 new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) ); 974 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); 975 cc_reset reset( xContext.get() ); 976 return xAction->run(); 977 } 978 else // no previous restriction => never current restriction 979 { 980 return xAction->run(); 981 } 982 } 983 //__________________________________________________________________________________________________ 984 Reference< security::XAccessControlContext > AccessController::getContext() 985 throw (RuntimeException) 986 { 987 if (rBHelper.bDisposed) 988 { 989 throw lang::DisposedException( 990 OUSTR("getContext() call on disposed AccessController!"), (OWeakObject *)this ); 991 } 992 993 if (OFF == m_mode) // optimize this way, because no dynamic check will be performed 994 { 995 return new acc_Policy( PermissionCollection( new AllPermission() ) ); 996 } 997 998 Reference< XCurrentContext > xContext; 999 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); 1000 1001 return acc_Intersection::create( 1002 getDynamicRestriction( xContext ), 1003 new acc_Policy( getEffectivePermissions( xContext, Any() ) ) ); 1004 } 1005 1006 // XServiceInfo impl 1007 //__________________________________________________________________________________________________ 1008 OUString AccessController::getImplementationName() 1009 throw (RuntimeException) 1010 { 1011 return s_implName; 1012 } 1013 //__________________________________________________________________________________________________ 1014 sal_Bool AccessController::supportsService( OUString const & serviceName ) 1015 throw (RuntimeException) 1016 { 1017 OUString const * pNames = s_serviceNames.getConstArray(); 1018 for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) 1019 { 1020 if (serviceName.equals( pNames[ nPos ] )) 1021 { 1022 return sal_True; 1023 } 1024 } 1025 return sal_False; 1026 } 1027 //__________________________________________________________________________________________________ 1028 Sequence< OUString > AccessController::getSupportedServiceNames() 1029 throw (RuntimeException) 1030 { 1031 return s_serviceNames; 1032 } 1033 } 1034 //################################################################################################## 1035 namespace stoc_bootstrap { 1036 //-------------------------------------------------------------------------------------------------- 1037 Reference< XInterface > SAL_CALL ac_create( 1038 Reference< XComponentContext > const & xComponentContext ) 1039 SAL_THROW( (Exception) ) 1040 { 1041 return (OWeakObject *)new stoc_sec::AccessController( xComponentContext ); 1042 } 1043 //-------------------------------------------------------------------------------------------------- 1044 Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW( () ) 1045 { 1046 return stoc_sec::s_serviceNames; 1047 } 1048 //-------------------------------------------------------------------------------------------------- 1049 OUString ac_getImplementationName() SAL_THROW( () ) 1050 { 1051 return stoc_sec::s_implName; 1052 } 1053 //-------------------------------------------------------------------------------------------------- 1054 Reference< XInterface > SAL_CALL filepolicy_create( 1055 Reference< XComponentContext > const & xComponentContext ) 1056 SAL_THROW( (Exception) ); 1057 //-------------------------------------------------------------------------------------------------- 1058 Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ); 1059 //-------------------------------------------------------------------------------------------------- 1060 OUString filepolicy_getImplementationName() SAL_THROW( () ); 1061 } 1062