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