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