Update ooo320-m1
[ooovba.git] / stoc / source / security / access_controller.cxx
blob32dc1712b0fd32f565e3d05e50ef99e5850a562c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: access_controller.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include <vector>
35 #include <memory>
37 #include <osl/diagnose.h>
38 #include <osl/interlck.h>
39 #include <osl/mutex.hxx>
40 #include <osl/thread.hxx>
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/string.hxx>
45 #include <uno/current_context.h>
47 #include <cppuhelper/implbase1.hxx>
48 #include <cppuhelper/compbase3.hxx>
49 #include <cppuhelper/factory.hxx>
50 #include <cppuhelper/implementationentry.hxx>
52 #include <com/sun/star/uno/XCurrentContext.hpp>
53 #include <com/sun/star/uno/DeploymentException.hpp>
54 #include <com/sun/star/lang/DisposedException.hpp>
55 #include <com/sun/star/lang/XComponent.hpp>
56 #include <com/sun/star/lang/XServiceInfo.hpp>
57 #include <com/sun/star/lang/XInitialization.hpp>
58 #include <com/sun/star/security/XAccessController.hpp>
59 #include <com/sun/star/security/XPolicy.hpp>
61 #include "lru_cache.h"
62 #include "permissions.h"
64 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
65 #define SERVICE_NAME "com.sun.star.security.AccessController"
66 #define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController"
67 #define USER_CREDS "access-control.user-credentials"
70 using namespace ::std;
71 using namespace ::osl;
72 using namespace ::cppu;
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::uno;
75 using ::rtl::OUString;
76 using ::rtl::OUStringBuffer;
77 using ::rtl::OString;
79 extern ::rtl_StandardModuleCount g_moduleCount;
81 namespace stoc_sec
83 // static stuff initialized when loading lib
84 static OUString s_envType = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
85 static OUString s_implName = OUSTR(IMPL_NAME);
86 static OUString s_serviceName = OUSTR(SERVICE_NAME);
87 static OUString s_acRestriction = OUSTR("access-control.restriction");
89 static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 );
91 //##################################################################################################
93 /** ac context intersects permissions of two ac contexts
95 class acc_Intersection
96 : public WeakImplHelper1< security::XAccessControlContext >
98 Reference< security::XAccessControlContext > m_x1, m_x2;
100 inline acc_Intersection(
101 Reference< security::XAccessControlContext > const & x1,
102 Reference< security::XAccessControlContext > const & x2 )
103 SAL_THROW( () );
105 public:
106 virtual ~acc_Intersection()
107 SAL_THROW( () );
109 static inline Reference< security::XAccessControlContext > create(
110 Reference< security::XAccessControlContext > const & x1,
111 Reference< security::XAccessControlContext > const & x2 )
112 SAL_THROW( () );
114 // XAccessControlContext impl
115 virtual void SAL_CALL checkPermission(
116 Any const & perm )
117 throw (RuntimeException);
119 //__________________________________________________________________________________________________
120 inline acc_Intersection::acc_Intersection(
121 Reference< security::XAccessControlContext > const & x1,
122 Reference< security::XAccessControlContext > const & x2 )
123 SAL_THROW( () )
124 : m_x1( x1 )
125 , m_x2( x2 )
127 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
129 //__________________________________________________________________________________________________
130 acc_Intersection::~acc_Intersection()
131 SAL_THROW( () )
133 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
135 //--------------------------------------------------------------------------------------------------
136 inline Reference< security::XAccessControlContext > acc_Intersection::create(
137 Reference< security::XAccessControlContext > const & x1,
138 Reference< security::XAccessControlContext > const & x2 )
139 SAL_THROW( () )
141 if (! x1.is())
142 return x2;
143 if (! x2.is())
144 return x1;
145 return new acc_Intersection( x1, x2 );
147 //__________________________________________________________________________________________________
148 void acc_Intersection::checkPermission(
149 Any const & perm )
150 throw (RuntimeException)
152 m_x1->checkPermission( perm );
153 m_x2->checkPermission( perm );
156 /** ac context unifies permissions of two ac contexts
158 class acc_Union
159 : public WeakImplHelper1< security::XAccessControlContext >
161 Reference< security::XAccessControlContext > m_x1, m_x2;
163 inline acc_Union(
164 Reference< security::XAccessControlContext > const & x1,
165 Reference< security::XAccessControlContext > const & x2 )
166 SAL_THROW( () );
168 public:
169 virtual ~acc_Union()
170 SAL_THROW( () );
172 static inline Reference< security::XAccessControlContext > create(
173 Reference< security::XAccessControlContext > const & x1,
174 Reference< security::XAccessControlContext > const & x2 )
175 SAL_THROW( () );
177 // XAccessControlContext impl
178 virtual void SAL_CALL checkPermission(
179 Any const & perm )
180 throw (RuntimeException);
182 //__________________________________________________________________________________________________
183 inline acc_Union::acc_Union(
184 Reference< security::XAccessControlContext > const & x1,
185 Reference< security::XAccessControlContext > const & x2 )
186 SAL_THROW( () )
187 : m_x1( x1 )
188 , m_x2( x2 )
190 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
192 //__________________________________________________________________________________________________
193 acc_Union::~acc_Union()
194 SAL_THROW( () )
196 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
198 //--------------------------------------------------------------------------------------------------
199 inline Reference< security::XAccessControlContext > acc_Union::create(
200 Reference< security::XAccessControlContext > const & x1,
201 Reference< security::XAccessControlContext > const & x2 )
202 SAL_THROW( () )
204 if (! x1.is())
205 return Reference< security::XAccessControlContext >(); // unrestricted
206 if (! x2.is())
207 return Reference< security::XAccessControlContext >(); // unrestricted
208 return new acc_Union( x1, x2 );
210 //__________________________________________________________________________________________________
211 void acc_Union::checkPermission(
212 Any const & perm )
213 throw (RuntimeException)
217 m_x1->checkPermission( perm );
219 catch (security::AccessControlException &)
221 m_x2->checkPermission( perm );
225 /** ac context doing permission checks on static permissions
227 class acc_Policy
228 : public WeakImplHelper1< security::XAccessControlContext >
230 PermissionCollection m_permissions;
232 public:
233 inline acc_Policy(
234 PermissionCollection const & permissions )
235 SAL_THROW( () );
236 virtual ~acc_Policy()
237 SAL_THROW( () );
239 // XAccessControlContext impl
240 virtual void SAL_CALL checkPermission(
241 Any const & perm )
242 throw (RuntimeException);
244 //__________________________________________________________________________________________________
245 inline acc_Policy::acc_Policy(
246 PermissionCollection const & permissions )
247 SAL_THROW( () )
248 : m_permissions( permissions )
250 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
252 //__________________________________________________________________________________________________
253 acc_Policy::~acc_Policy()
254 SAL_THROW( () )
256 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
258 //__________________________________________________________________________________________________
259 void acc_Policy::checkPermission(
260 Any const & perm )
261 throw (RuntimeException)
263 m_permissions.checkPermission( perm );
266 /** current context overriding dynamic ac restriction
268 class acc_CurrentContext
269 : public ImplHelper1< XCurrentContext >
271 oslInterlockedCount m_refcount;
273 Reference< XCurrentContext > m_xDelegate;
274 Any m_restriction;
276 public:
277 inline acc_CurrentContext(
278 Reference< XCurrentContext > const & xDelegate,
279 Reference< security::XAccessControlContext > const & xRestriction )
280 SAL_THROW( () );
281 virtual ~acc_CurrentContext() SAL_THROW( () );
283 // XInterface impl
284 virtual void SAL_CALL acquire()
285 throw ();
286 virtual void SAL_CALL release()
287 throw ();
289 // XCurrentContext impl
290 virtual Any SAL_CALL getValueByName( OUString const & name )
291 throw (RuntimeException);
293 //__________________________________________________________________________________________________
294 inline acc_CurrentContext::acc_CurrentContext(
295 Reference< XCurrentContext > const & xDelegate,
296 Reference< security::XAccessControlContext > const & xRestriction )
297 SAL_THROW( () )
298 : m_refcount( 0 )
299 , m_xDelegate( xDelegate )
301 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
303 if (xRestriction.is())
305 m_restriction = makeAny( xRestriction );
307 // return empty any otherwise on getValueByName(), not null interface
309 //__________________________________________________________________________________________________
310 acc_CurrentContext::~acc_CurrentContext()
311 SAL_THROW( () )
313 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
315 //__________________________________________________________________________________________________
316 void acc_CurrentContext::acquire()
317 throw ()
319 ::osl_incrementInterlockedCount( &m_refcount );
321 //__________________________________________________________________________________________________
322 void acc_CurrentContext::release()
323 throw ()
325 if (! ::osl_decrementInterlockedCount( &m_refcount ))
327 delete this;
330 //__________________________________________________________________________________________________
331 Any acc_CurrentContext::getValueByName( OUString const & name )
332 throw (RuntimeException)
334 if (name.equals( s_acRestriction ))
336 return m_restriction;
338 else if (m_xDelegate.is())
340 return m_xDelegate->getValueByName( name );
342 else
344 return Any();
348 //##################################################################################################
350 //--------------------------------------------------------------------------------------------------
351 static inline void dispose( Reference< XInterface > const & x )
352 SAL_THROW( (RuntimeException) )
354 Reference< lang::XComponent > xComp( x, UNO_QUERY );
355 if (xComp.is())
357 xComp->dispose();
360 //--------------------------------------------------------------------------------------------------
361 static inline Reference< security::XAccessControlContext > getDynamicRestriction(
362 Reference< XCurrentContext > const & xContext )
363 SAL_THROW( (RuntimeException) )
365 if (xContext.is())
367 Any acc( xContext->getValueByName( s_acRestriction ) );
368 if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass)
370 // avoid ref-counting
371 OUString const & typeName =
372 *reinterpret_cast< OUString const * >( &acc.pType->pTypeName );
373 if (typeName.equalsAsciiL(
374 RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.XAccessControlContext") ))
376 return Reference< security::XAccessControlContext >(
377 *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) );
379 else // try to query
381 return Reference< security::XAccessControlContext >::query(
382 *reinterpret_cast< XInterface ** const >( acc.pData ) );
386 return Reference< security::XAccessControlContext >();
388 //==================================================================================================
389 class cc_reset
391 void * m_cc;
392 public:
393 inline cc_reset( void * cc ) SAL_THROW( () )
394 : m_cc( cc ) {}
395 inline ~cc_reset() SAL_THROW( () )
396 { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); }
399 //##################################################################################################
401 struct MutexHolder
403 Mutex m_mutex;
405 typedef WeakComponentImplHelper3<
406 security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper;
408 //==================================================================================================
409 class AccessController
410 : public MutexHolder
411 , public t_helper
413 Reference< XComponentContext > m_xComponentContext;
415 Reference< security::XPolicy > m_xPolicy;
416 Reference< security::XPolicy > const & getPolicy()
417 SAL_THROW( (RuntimeException) );
419 // mode
420 enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode;
422 PermissionCollection m_defaultPermissions;
423 // for single-user mode
424 PermissionCollection m_singleUserPermissions;
425 OUString m_singleUserId;
426 bool m_defaultPerm_init;
427 bool m_singleUser_init;
428 // for multi-user mode
429 lru_cache< OUString, PermissionCollection, ::rtl::OUStringHash, equal_to< OUString > >
430 m_user2permissions;
432 ThreadData m_rec;
433 typedef vector< pair< OUString, Any > > t_rec_vec;
434 inline void clearPostPoned() SAL_THROW( () );
435 void checkAndClearPostPoned() SAL_THROW( (RuntimeException) );
437 PermissionCollection getEffectivePermissions(
438 Reference< XCurrentContext > const & xContext,
439 Any const & demanded_perm )
440 SAL_THROW( (RuntimeException) );
442 protected:
443 virtual void SAL_CALL disposing();
445 public:
446 AccessController( Reference< XComponentContext > const & xComponentContext )
447 SAL_THROW( (RuntimeException) );
448 virtual ~AccessController()
449 SAL_THROW( () );
451 // XInitialization impl
452 virtual void SAL_CALL initialize(
453 Sequence< Any > const & arguments )
454 throw (Exception);
456 // XAccessController impl
457 virtual void SAL_CALL checkPermission(
458 Any const & perm )
459 throw (RuntimeException);
460 virtual Any SAL_CALL doRestricted(
461 Reference< security::XAction > const & xAction,
462 Reference< security::XAccessControlContext > const & xRestriction )
463 throw (Exception);
464 virtual Any SAL_CALL doPrivileged(
465 Reference< security::XAction > const & xAction,
466 Reference< security::XAccessControlContext > const & xRestriction )
467 throw (Exception);
468 virtual Reference< security::XAccessControlContext > SAL_CALL getContext()
469 throw (RuntimeException);
471 // XServiceInfo impl
472 virtual OUString SAL_CALL getImplementationName()
473 throw (RuntimeException);
474 virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
475 throw (RuntimeException);
476 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
477 throw (RuntimeException);
479 //__________________________________________________________________________________________________
480 AccessController::AccessController( Reference< XComponentContext > const & xComponentContext )
481 SAL_THROW( (RuntimeException) )
482 : t_helper( m_mutex )
483 , m_xComponentContext( xComponentContext )
484 , m_mode( ON ) // default
485 , m_defaultPerm_init( false )
486 , m_singleUser_init( false )
487 , m_rec( 0 )
489 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
491 OUString mode;
492 if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode)
494 if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("off") ))
496 m_mode = OFF;
498 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("on") ))
500 m_mode = ON;
502 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dynamic-only") ))
504 m_mode = DYNAMIC_ONLY;
506 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-user") ))
508 m_xComponentContext->getValueByName(
509 OUSTR("/services/" SERVICE_NAME "/single-user-id") ) >>= m_singleUserId;
510 if (! m_singleUserId.getLength())
512 throw RuntimeException(
513 OUSTR("expected a user id in component context entry "
514 "\"/services/" SERVICE_NAME "/single-user-id\"!"),
515 (OWeakObject *)this );
517 m_mode = SINGLE_USER;
519 else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-default-user") ))
521 m_mode = SINGLE_DEFAULT_USER;
525 // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process)
526 if (ON == m_mode || DYNAMIC_ONLY == m_mode)
528 sal_Int32 cacheSize = 0; // multi-user cache size
529 if (! (m_xComponentContext->getValueByName(
530 OUSTR("/services/" SERVICE_NAME "/user-cache-size") ) >>= cacheSize))
532 cacheSize = 128; // reasonable default?
534 #ifdef __CACHE_DIAGNOSE
535 cacheSize = 2;
536 #endif
537 m_user2permissions.setSize( cacheSize );
540 //__________________________________________________________________________________________________
541 AccessController::~AccessController()
542 SAL_THROW( () )
544 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
546 //__________________________________________________________________________________________________
547 void AccessController::disposing()
549 m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY?
550 m_xPolicy.clear();
551 m_xComponentContext.clear();
554 // XInitialization impl
555 //__________________________________________________________________________________________________
556 void AccessController::initialize(
557 Sequence< Any > const & arguments )
558 throw (Exception)
560 // xxx todo: review for forking
561 // portal forking hack: re-initialize for another user-id
562 if (SINGLE_USER != m_mode) // only if in single-user mode
564 throw RuntimeException(
565 OUSTR("invalid call: ac must be in \"single-user\" mode!"), (OWeakObject *)this );
567 OUString userId;
568 arguments[ 0 ] >>= userId;
569 if (! userId.getLength())
571 throw RuntimeException(
572 OUSTR("expected a user-id as first argument!"), (OWeakObject *)this );
574 // assured that no sync is necessary: no check happens at this forking time
575 m_singleUserId = userId;
576 m_singleUser_init = false;
579 //__________________________________________________________________________________________________
580 Reference< security::XPolicy > const & AccessController::getPolicy()
581 SAL_THROW( (RuntimeException) )
583 // get policy singleton
584 if (! m_xPolicy.is())
586 Reference< security::XPolicy > xPolicy;
587 m_xComponentContext->getValueByName(
588 OUSTR("/singletons/com.sun.star.security.thePolicy") ) >>= xPolicy;
589 if (xPolicy.is())
591 MutexGuard guard( m_mutex );
592 if (! m_xPolicy.is())
594 m_xPolicy = xPolicy;
597 else
599 throw SecurityException(
600 OUSTR("cannot get policy singleton!"), (OWeakObject *)this );
603 return m_xPolicy;
606 #ifdef __DIAGNOSE
607 static void dumpPermissions(
608 PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW( () )
610 OUStringBuffer buf( 48 );
611 if (userId.getLength())
613 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> dumping permissions of user \"") );
614 buf.append( userId );
615 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\":") );
617 else
619 buf.appendAscii(
620 RTL_CONSTASCII_STRINGPARAM("> dumping default permissions:") );
622 OString str( ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
623 OSL_TRACE( str.getStr() );
624 Sequence< OUString > permissions( collection.toStrings() );
625 OUString const * p = permissions.getConstArray();
626 for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos )
628 OString str( ::rtl::OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) );
629 OSL_TRACE( str.getStr() );
631 OSL_TRACE( "> permission dump done" );
633 #endif
636 //__________________________________________________________________________________________________
637 inline void AccessController::clearPostPoned() SAL_THROW( () )
639 delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
640 m_rec.setData( 0 );
642 //__________________________________________________________________________________________________
643 void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) )
645 // check postponed permissions
646 auto_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) );
647 m_rec.setData( 0 ); // takeover ownership
648 OSL_ASSERT( rec.get() );
649 if (rec.get())
651 t_rec_vec const & vec = *rec.get();
652 switch (m_mode)
654 case SINGLE_USER:
656 OSL_ASSERT( m_singleUser_init );
657 for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
659 pair< OUString, Any > const & p = vec[ nPos ];
660 OSL_ASSERT( m_singleUserId.equals( p.first ) );
661 m_singleUserPermissions.checkPermission( p.second );
663 break;
665 case SINGLE_DEFAULT_USER:
667 OSL_ASSERT( m_defaultPerm_init );
668 for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
670 pair< OUString, Any > const & p = vec[ nPos ];
671 OSL_ASSERT( !p.first.getLength() ); // default-user
672 m_defaultPermissions.checkPermission( p.second );
674 break;
676 case ON:
678 for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
680 pair< OUString, Any > const & p = vec[ nPos ];
681 PermissionCollection const * pPermissions;
682 // lookup policy for user
684 MutexGuard guard( m_mutex );
685 pPermissions = m_user2permissions.lookup( p.first );
687 OSL_ASSERT( pPermissions );
688 if (pPermissions)
690 pPermissions->checkPermission( p.second );
693 break;
695 default:
696 OSL_ENSURE( 0, "### this should never be called in this ac mode!" );
697 break;
701 //__________________________________________________________________________________________________
702 /** this is the only function calling the policy singleton and thus has to take care
703 of recurring calls!
705 @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call
706 which will be postponed for recurring calls
708 PermissionCollection AccessController::getEffectivePermissions(
709 Reference< XCurrentContext > const & xContext,
710 Any const & demanded_perm )
711 SAL_THROW( (RuntimeException) )
713 OUString userId;
715 switch (m_mode)
717 case SINGLE_USER:
719 if (m_singleUser_init)
720 return m_singleUserPermissions;
721 userId = m_singleUserId;
722 break;
724 case SINGLE_DEFAULT_USER:
726 if (m_defaultPerm_init)
727 return m_defaultPermissions;
728 break;
730 case ON:
732 if (xContext.is())
734 xContext->getValueByName( OUSTR(USER_CREDS ".id") ) >>= userId;
736 if (! userId.getLength())
738 throw SecurityException(
739 OUSTR("cannot determine current user in multi-user ac!"), (OWeakObject *)this );
742 // lookup policy for user
743 MutexGuard guard( m_mutex );
744 PermissionCollection const * pPermissions = m_user2permissions.lookup( userId );
745 if (pPermissions)
746 return *pPermissions;
747 break;
749 default:
750 OSL_ENSURE( 0, "### this should never be called in this ac mode!" );
751 return PermissionCollection();
754 // call on policy
755 // iff this is a recurring call for the default user, then grant all permissions
756 t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() );
757 if (rec) // tls entry exists => this is recursive call
759 if (demanded_perm.hasValue())
761 // enqueue
762 rec->push_back( pair< OUString, Any >( userId, demanded_perm ) );
764 #ifdef __DIAGNOSE
765 OUStringBuffer buf( 48 );
766 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> info: recurring call of user \"") );
767 buf.append( userId );
768 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"") );
769 OString str(
770 ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
771 OSL_TRACE( str.getStr() );
772 #endif
773 return PermissionCollection( new AllPermission() );
775 else // no tls
777 rec = new t_rec_vec;
778 m_rec.setData( rec );
781 try // calls on API
783 // init default permissions
784 if (! m_defaultPerm_init)
786 PermissionCollection defaultPermissions(
787 getPolicy()->getDefaultPermissions() );
788 // assign
789 MutexGuard guard( m_mutex );
790 if (! m_defaultPerm_init)
792 m_defaultPermissions = defaultPermissions;
793 m_defaultPerm_init = true;
795 #ifdef __DIAGNOSE
796 dumpPermissions( m_defaultPermissions );
797 #endif
800 PermissionCollection ret;
802 // init user permissions
803 switch (m_mode)
805 case SINGLE_USER:
807 ret = PermissionCollection(
808 getPolicy()->getPermissions( userId ), m_defaultPermissions );
810 // assign
811 MutexGuard guard( m_mutex );
812 if (m_singleUser_init)
814 ret = m_singleUserPermissions;
816 else
818 m_singleUserPermissions = ret;
819 m_singleUser_init = true;
822 #ifdef __DIAGNOSE
823 dumpPermissions( ret, userId );
824 #endif
825 break;
827 case SINGLE_DEFAULT_USER:
829 ret = m_defaultPermissions;
830 break;
832 case ON:
834 ret = PermissionCollection(
835 getPolicy()->getPermissions( userId ), m_defaultPermissions );
837 // cache
838 MutexGuard guard( m_mutex );
839 m_user2permissions.set( userId, ret );
841 #ifdef __DIAGNOSE
842 dumpPermissions( ret, userId );
843 #endif
844 break;
846 default:
847 break;
850 // check postponed
851 checkAndClearPostPoned();
852 return ret;
854 catch (security::AccessControlException & exc) // wrapped into DeploymentException
856 clearPostPoned(); // safety: exception could have happened before checking postponed?
857 OUStringBuffer buf( 64 );
858 buf.appendAscii(
859 RTL_CONSTASCII_STRINGPARAM("deployment error (AccessControlException occured): ") );
860 buf.append( exc.Message );
861 throw DeploymentException( buf.makeStringAndClear(), exc.Context );
863 catch (RuntimeException &)
865 // dont check postponed, just cleanup
866 clearPostPoned();
867 delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
868 m_rec.setData( 0 );
869 throw;
871 catch (Exception &)
873 // check postponed permissions first
874 // => AccessControlExceptions are errors, user exceptions not!
875 checkAndClearPostPoned();
876 throw;
878 catch (...)
880 // dont check postponed, just cleanup
881 clearPostPoned();
882 throw;
886 // XAccessController impl
887 //__________________________________________________________________________________________________
888 void AccessController::checkPermission(
889 Any const & perm )
890 throw (RuntimeException)
892 if (rBHelper.bDisposed)
894 throw lang::DisposedException(
895 OUSTR("checkPermission() call on disposed AccessController!"), (OWeakObject *)this );
898 if (OFF == m_mode)
899 return;
901 // first dynamic check of ac contexts
902 Reference< XCurrentContext > xContext;
903 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
904 Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) );
905 if (xACC.is())
907 xACC->checkPermission( perm );
910 if (DYNAMIC_ONLY == m_mode)
911 return;
913 // then static check
914 getEffectivePermissions( xContext, perm ).checkPermission( perm );
916 //__________________________________________________________________________________________________
917 Any AccessController::doRestricted(
918 Reference< security::XAction > const & xAction,
919 Reference< security::XAccessControlContext > const & xRestriction )
920 throw (Exception)
922 if (rBHelper.bDisposed)
924 throw lang::DisposedException(
925 OUSTR("doRestricted() call on disposed AccessController!"), (OWeakObject *)this );
928 if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
929 return xAction->run();
931 if (xRestriction.is())
933 Reference< XCurrentContext > xContext;
934 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
936 // override restriction
937 Reference< XCurrentContext > xNewContext(
938 new acc_CurrentContext( xContext, acc_Intersection::create(
939 xRestriction, getDynamicRestriction( xContext ) ) ) );
940 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
941 cc_reset reset( xContext.get() );
942 return xAction->run();
944 else
946 return xAction->run();
949 //__________________________________________________________________________________________________
950 Any AccessController::doPrivileged(
951 Reference< security::XAction > const & xAction,
952 Reference< security::XAccessControlContext > const & xRestriction )
953 throw (Exception)
955 if (rBHelper.bDisposed)
957 throw lang::DisposedException(
958 OUSTR("doPrivileged() call on disposed AccessController!"), (OWeakObject *)this );
961 if (OFF == m_mode) // no dynamic check will be performed
963 return xAction->run();
966 Reference< XCurrentContext > xContext;
967 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
969 Reference< security::XAccessControlContext > xOldRestr(
970 getDynamicRestriction( xContext ) );
972 if (xOldRestr.is()) // previous restriction
974 // override restriction
975 Reference< XCurrentContext > xNewContext(
976 new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) );
977 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
978 cc_reset reset( xContext.get() );
979 return xAction->run();
981 else // no previous restriction => never current restriction
983 return xAction->run();
986 //__________________________________________________________________________________________________
987 Reference< security::XAccessControlContext > AccessController::getContext()
988 throw (RuntimeException)
990 if (rBHelper.bDisposed)
992 throw lang::DisposedException(
993 OUSTR("getContext() call on disposed AccessController!"), (OWeakObject *)this );
996 if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
998 return new acc_Policy( PermissionCollection( new AllPermission() ) );
1001 Reference< XCurrentContext > xContext;
1002 ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
1004 return acc_Intersection::create(
1005 getDynamicRestriction( xContext ),
1006 new acc_Policy( getEffectivePermissions( xContext, Any() ) ) );
1009 // XServiceInfo impl
1010 //__________________________________________________________________________________________________
1011 OUString AccessController::getImplementationName()
1012 throw (RuntimeException)
1014 return s_implName;
1016 //__________________________________________________________________________________________________
1017 sal_Bool AccessController::supportsService( OUString const & serviceName )
1018 throw (RuntimeException)
1020 OUString const * pNames = s_serviceNames.getConstArray();
1021 for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; )
1023 if (serviceName.equals( pNames[ nPos ] ))
1025 return sal_True;
1028 return sal_False;
1030 //__________________________________________________________________________________________________
1031 Sequence< OUString > AccessController::getSupportedServiceNames()
1032 throw (RuntimeException)
1034 return s_serviceNames;
1037 //##################################################################################################
1038 namespace stoc_bootstrap {
1039 //--------------------------------------------------------------------------------------------------
1040 Reference< XInterface > SAL_CALL ac_create(
1041 Reference< XComponentContext > const & xComponentContext )
1042 SAL_THROW( (Exception) )
1044 return (OWeakObject *)new stoc_sec::AccessController( xComponentContext );
1046 //--------------------------------------------------------------------------------------------------
1047 Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW( () )
1049 return stoc_sec::s_serviceNames;
1051 //--------------------------------------------------------------------------------------------------
1052 OUString ac_getImplementationName() SAL_THROW( () )
1054 return stoc_sec::s_implName;
1056 //--------------------------------------------------------------------------------------------------
1057 Reference< XInterface > SAL_CALL filepolicy_create(
1058 Reference< XComponentContext > const & xComponentContext )
1059 SAL_THROW( (Exception) );
1060 //--------------------------------------------------------------------------------------------------
1061 Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () );
1062 //--------------------------------------------------------------------------------------------------
1063 OUString filepolicy_getImplementationName() SAL_THROW( () );