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

Generated by: LCOV version 1.11