24#include <osl/diagnose.h>
25#include <osl/mutex.hxx>
26#include <osl/thread.hxx>
28#include <rtl/ustrbuf.hxx>
31#include <uno/current_context.h>
32#include <uno/lbnames.h>
39#include <com/sun/star/uno/XCurrentContext.hpp>
40#include <com/sun/star/uno/DeploymentException.hpp>
41#include <com/sun/star/uno/XComponentContext.hpp>
42#include <com/sun/star/lang/DisposedException.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>
53constexpr OUStringLiteral
SERVICE_NAME =
u"com.sun.star.security.AccessController";
54constexpr OUStringLiteral
USER_CREDS =
u"access-control.user-credentials.id";
58using namespace ::
cppu;
60using namespace css::uno;
66OUString s_envType = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
67constexpr OUStringLiteral s_acRestriction =
u"access-control.restriction";
73 :
public WeakImplHelper< security::XAccessControlContext >
75 Reference< security::XAccessControlContext > m_x1, m_x2;
78 Reference< security::XAccessControlContext >
const & x1,
79 Reference< security::XAccessControlContext >
const & x2 );
82 static Reference< security::XAccessControlContext >
create(
83 Reference< security::XAccessControlContext >
const & x1,
84 Reference< security::XAccessControlContext >
const & x2 );
87 virtual void SAL_CALL checkPermission(
88 Any const & perm )
override;
91acc_Intersection::acc_Intersection(
92 Reference< security::XAccessControlContext >
const & x1,
93 Reference< security::XAccessControlContext >
const & x2 )
98Reference< security::XAccessControlContext > acc_Intersection::create(
99 Reference< security::XAccessControlContext >
const & x1,
100 Reference< security::XAccessControlContext >
const & x2 )
106 return new acc_Intersection( x1, x2 );
109void acc_Intersection::checkPermission(
112 m_x1->checkPermission( perm );
113 m_x2->checkPermission( perm );
119 :
public WeakImplHelper< security::XAccessControlContext >
121 Reference< security::XAccessControlContext > m_x1, m_x2;
124 Reference< security::XAccessControlContext >
const & x1,
125 Reference< security::XAccessControlContext >
const & x2 );
128 static Reference< security::XAccessControlContext >
create(
129 Reference< security::XAccessControlContext >
const & x1,
130 Reference< security::XAccessControlContext >
const & x2 );
133 virtual void SAL_CALL checkPermission(
134 Any const & perm )
override;
138 Reference< security::XAccessControlContext >
const & x1,
139 Reference< security::XAccessControlContext >
const & x2 )
144Reference< security::XAccessControlContext > acc_Union::create(
145 Reference< security::XAccessControlContext >
const & x1,
146 Reference< security::XAccessControlContext >
const & x2 )
149 return Reference< security::XAccessControlContext >();
151 return Reference< security::XAccessControlContext >();
152 return new acc_Union( x1, x2 );
155void acc_Union::checkPermission(
160 m_x1->checkPermission( perm );
162 catch (security::AccessControlException &)
164 m_x2->checkPermission( perm );
171 :
public WeakImplHelper< security::XAccessControlContext >
178 : m_permissions(std::move( permissions ))
182 virtual void SAL_CALL checkPermission(
183 Any const & perm )
override;
186void acc_Policy::checkPermission(
189 m_permissions.checkPermission( perm );
194class acc_CurrentContext
195 :
public WeakImplHelper< XCurrentContext >
202 Reference< XCurrentContext >
const & xDelegate,
203 Reference< security::XAccessControlContext >
const & xRestriction );
206 virtual Any SAL_CALL getValueByName( OUString
const &
name )
override;
209acc_CurrentContext::acc_CurrentContext(
210 Reference< XCurrentContext >
const & xDelegate,
211 Reference< security::XAccessControlContext >
const & xRestriction )
214 if (xRestriction.is())
216 m_restriction <<= xRestriction;
221Any acc_CurrentContext::getValueByName( OUString
const &
name )
223 if (
name == s_acRestriction)
225 return m_restriction;
238Reference< security::XAccessControlContext > getDynamicRestriction(
239 Reference< XCurrentContext >
const & xContext )
243 Any acc(xContext->getValueByName(s_acRestriction));
244 if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass)
248 OUString::unacquired( &acc.pType->pTypeName );
249 if (
typeName ==
"com.sun.star.security.XAccessControlContext" )
251 return Reference< security::XAccessControlContext >(
252 *
static_cast< security::XAccessControlContext **
>( acc.pData ) );
256 return Reference< security::XAccessControlContext >::query(
261 return Reference< security::XAccessControlContext >();
268 explicit cc_reset(
void * cc )
271 { ::uno_setCurrentContext( m_cc, s_envType.pData,
nullptr ); }
274typedef WeakComponentImplHelper<
275 security::XAccessController, lang::XServiceInfo, lang::XInitialization >
t_helper;
278class AccessController
284 Reference< security::XPolicy > m_xPolicy;
285 Reference< security::XPolicy >
const & getPolicy();
288 enum class Mode {
Off,
On, DynamicOnly, SingleUser, SingleDefaultUser };
294 OUString m_singleUserId;
295 bool m_defaultPerm_init;
296 bool m_singleUser_init;
302 typedef std::vector< std::pair< OUString, Any > > t_rec_vec;
303 void clearPostPoned();
304 void checkAndClearPostPoned();
307 Reference< XCurrentContext >
const & xContext,
308 Any const & demanded_perm );
311 virtual void SAL_CALL disposing()
override;
314 explicit AccessController( Reference< XComponentContext >
const & xComponentContext );
317 virtual void SAL_CALL initialize(
318 Sequence< Any >
const & arguments )
override;
321 virtual void SAL_CALL checkPermission(
322 Any const & perm )
override;
323 virtual Any SAL_CALL doRestricted(
324 Reference< security::XAction >
const & xAction,
325 Reference< security::XAccessControlContext >
const & xRestriction )
override;
326 virtual Any SAL_CALL doPrivileged(
327 Reference< security::XAction >
const & xAction,
328 Reference< security::XAccessControlContext >
const & xRestriction )
override;
329 virtual Reference< security::XAccessControlContext > SAL_CALL getContext()
override;
337AccessController::AccessController( Reference< XComponentContext >
const & xComponentContext )
341 , m_defaultPerm_init(
false )
342 , m_singleUser_init(
false )
356 else if (
mode ==
"on" )
360 else if (
mode ==
"dynamic-only" )
362 m_mode = Mode::DynamicOnly;
364 else if (
mode ==
"single-user" )
367 "/services/" +
SERVICE_NAME +
"/single-user-id" ) >>= m_singleUserId;
368 if (m_singleUserId.isEmpty())
371 "expected a user id in component context entry "
375 m_mode = Mode::SingleUser;
377 else if (
mode ==
"single-default-user" )
379 m_mode = Mode::SingleDefaultUser;
384 if (Mode::On != m_mode && Mode::DynamicOnly != m_mode)
387 sal_Int32 cacheSize = 0;
389 "/services/" +
SERVICE_NAME +
"/user-cache-size" ) >>= cacheSize))
393#ifdef __CACHE_DIAGNOSE
396 m_user2permissions.setSize( cacheSize );
399void AccessController::disposing()
408void AccessController::initialize(
409 Sequence< Any >
const & arguments )
413 if (Mode::SingleUser != m_mode)
416 "invalid call: ac must be in \"single-user\" mode!", getXWeak() );
419 arguments[ 0 ] >>= userId;
420 if ( userId.isEmpty() )
423 "expected a user-id as first argument!", getXWeak() );
426 m_singleUserId = userId;
427 m_singleUser_init =
false;
431Reference< security::XPolicy >
const & AccessController::getPolicy()
434 if (! m_xPolicy.is())
436 Reference< security::XPolicy > xPolicy;
438 "/singletons/com.sun.star.security.thePolicy" ) >>= xPolicy;
441 throw SecurityException(
442 "cannot get policy singleton!", getXWeak() );
446 if (! m_xPolicy.is())
455static void dumpPermissions(
458 OUStringBuffer buf( 48 );
459 if (!userId.isEmpty())
461 buf.append(
"> dumping permissions of user \"" );
462 buf.append( userId );
467 buf.append(
"> dumping default permissions:" );
469 SAL_INFO(
"stoc", buf.makeStringAndClear() );
470 Sequence< OUString > permissions( collection.toStrings() );
471 OUString
const *
p = permissions.getConstArray();
472 for ( sal_Int32
nPos = 0;
nPos < permissions.getLength(); ++
nPos )
476 SAL_INFO(
"stoc",
"> permission dump done" );
481void AccessController::clearPostPoned()
483 delete static_cast< t_rec_vec *
>( m_rec.getData() );
484 m_rec.setData(
nullptr );
487void AccessController::checkAndClearPostPoned()
490 std::unique_ptr< t_rec_vec > rec(
static_cast< t_rec_vec *
>( m_rec.getData() ) );
491 m_rec.setData(
nullptr );
496 t_rec_vec
const& vec = *rec;
499 case Mode::SingleUser:
501 OSL_ASSERT( m_singleUser_init );
502 for (
const auto &
p : vec)
504 OSL_ASSERT( m_singleUserId ==
p.first );
505 m_singleUserPermissions.checkPermission(
p.second );
509 case Mode::SingleDefaultUser:
511 OSL_ASSERT( m_defaultPerm_init );
512 for (
const auto &
p : vec)
514 OSL_ASSERT(
p.first.isEmpty() );
515 m_defaultPermissions.checkPermission(
p.second );
521 for (
const auto &
p : vec)
527 pPermissions = m_user2permissions.lookup(
p.first );
529 OSL_ASSERT( pPermissions );
538 OSL_FAIL(
"### this should never be called in this ac mode!" );
550 Reference< XCurrentContext >
const & xContext,
551 Any const & demanded_perm )
557 case Mode::SingleUser:
559 if (m_singleUser_init)
560 return m_singleUserPermissions;
561 userId = m_singleUserId;
564 case Mode::SingleDefaultUser:
566 if (m_defaultPerm_init)
567 return m_defaultPermissions;
574 xContext->getValueByName(
USER_CREDS ) >>= userId;
576 if ( userId.isEmpty() )
578 throw SecurityException(
579 "cannot determine current user in multi-user ac!", getXWeak() );
586 return *pPermissions;
590 OSL_FAIL(
"### this should never be called in this ac mode!" );
596 t_rec_vec * rec =
static_cast< t_rec_vec *
>( m_rec.getData() );
599 if (demanded_perm.hasValue())
602 rec->push_back( std::pair< OUString, Any >( userId, demanded_perm ) );
605 SAL_INFO(
"stoc",
"> info: recurring call of user: " << userId );
612 m_rec.setData( rec );
618 if (! m_defaultPerm_init)
621 getPolicy()->getDefaultPermissions() );
624 if (! m_defaultPerm_init)
626 m_defaultPermissions = defaultPermissions;
627 m_defaultPerm_init =
true;
630 dumpPermissions( m_defaultPermissions );
639 case Mode::SingleUser:
642 getPolicy()->getPermissions( userId ), m_defaultPermissions );
646 if (m_singleUser_init)
648 ret = m_singleUserPermissions;
652 m_singleUserPermissions = ret;
653 m_singleUser_init =
true;
657 dumpPermissions( ret, userId );
661 case Mode::SingleDefaultUser:
663 ret = m_defaultPermissions;
669 getPolicy()->getPermissions( userId ), m_defaultPermissions );
673 m_user2permissions.set( userId, ret );
676 dumpPermissions( ret, userId );
685 checkAndClearPostPoned();
688 catch (
const security::AccessControlException & exc)
691 throw DeploymentException(
"deployment error (AccessControlException occurred): " + exc.Message, exc.Context );
697 delete static_cast< t_rec_vec *
>( m_rec.getData() );
698 m_rec.setData(
nullptr );
705 checkAndClearPostPoned();
718void AccessController::checkPermission(
721 if (rBHelper.bDisposed)
723 throw lang::DisposedException(
724 "checkPermission() call on disposed AccessController!", getXWeak() );
727 if (Mode::Off == m_mode)
731 Reference< XCurrentContext > xContext;
732 ::uno_getCurrentContext(
reinterpret_cast<void **
>(&xContext), s_envType.pData,
nullptr );
733 Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) );
736 xACC->checkPermission( perm );
739 if (Mode::DynamicOnly == m_mode)
743 getEffectivePermissions( xContext, perm ).checkPermission( perm );
746Any AccessController::doRestricted(
747 Reference< security::XAction >
const & xAction,
748 Reference< security::XAccessControlContext >
const & xRestriction )
750 if (rBHelper.bDisposed)
752 throw lang::DisposedException(
753 "doRestricted() call on disposed AccessController!", getXWeak() );
756 if (Mode::Off == m_mode)
757 return xAction->run();
759 if (xRestriction.is())
761 Reference< XCurrentContext > xContext;
762 ::uno_getCurrentContext(
reinterpret_cast<void **
>(&xContext), s_envType.pData,
nullptr );
765 Reference< XCurrentContext > xNewContext(
766 new acc_CurrentContext( xContext, acc_Intersection::create(
767 xRestriction, getDynamicRestriction( xContext ) ) ) );
768 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData,
nullptr );
769 cc_reset reset( xContext.get() );
770 return xAction->run();
774 return xAction->run();
778Any AccessController::doPrivileged(
779 Reference< security::XAction >
const & xAction,
780 Reference< security::XAccessControlContext >
const & xRestriction )
782 if (rBHelper.bDisposed)
784 throw lang::DisposedException(
785 "doPrivileged() call on disposed AccessController!", getXWeak() );
788 if (Mode::Off == m_mode)
790 return xAction->run();
793 Reference< XCurrentContext > xContext;
794 ::uno_getCurrentContext(
reinterpret_cast<void **
>(&xContext), s_envType.pData,
nullptr );
796 Reference< security::XAccessControlContext > xOldRestr(
797 getDynamicRestriction( xContext ) );
802 Reference< XCurrentContext > xNewContext(
803 new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) );
804 ::uno_setCurrentContext( xNewContext.get(), s_envType.pData,
nullptr );
805 cc_reset reset( xContext.get() );
806 return xAction->run();
810 return xAction->run();
814Reference< security::XAccessControlContext > AccessController::getContext()
816 if (rBHelper.bDisposed)
818 throw lang::DisposedException(
819 "getContext() call on disposed AccessController!", getXWeak() );
822 if (Mode::Off == m_mode)
827 Reference< XCurrentContext > xContext;
828 ::uno_getCurrentContext(
reinterpret_cast<void **
>(&xContext), s_envType.pData,
nullptr );
830 return acc_Intersection::create(
831 getDynamicRestriction( xContext ),
832 new acc_Policy( getEffectivePermissions( xContext,
Any() ) ) );
837OUString AccessController::getImplementationName()
839 return "com.sun.star.security.comp.stoc.AccessController";
842sal_Bool AccessController::supportsService( OUString
const & serviceName )
847Sequence< OUString > AccessController::getSupportedServiceNames()
855extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
857 css::uno::XComponentContext *context,
858 css::uno::Sequence<css::uno::Any>
const &)
860 return cppu::acquire(
new AccessController(context));
constexpr OUStringLiteral USER_CREDS
constexpr OUStringLiteral SERVICE_NAME
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_security_comp_stoc_AccessController_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
void checkPermission(css::uno::Any const &perm) const
Implementation of a least recently used (lru) cache.
Reference< XComponentContext > m_xDelegate
css::uno::Reference< XComponentContext > m_xComponentContext
local context
#define SAL_INFO(area, stream)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
::cppu::WeakImplHelper< css::script::provider::XScriptProvider, css::script::browse::XBrowseNode, css::lang::XServiceInfo, css::lang::XInitialization, css::container::XNameContainer > t_helper