LCOV - code coverage report
Current view: top level - stoc/source/security - access_controller.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 21 292 7.2 %
Date: 2014-11-03 Functions: 9 44 20.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10