From 38f626d165f27202f39faa8e24f6dec7e66a5578 Mon Sep 17 00:00:00 2001 From: Daniel Boelzle Date: Mon, 4 Mar 2002 16:43:21 +0000 Subject: #88919# access controller implementation and bugfixes --- stoc/source/security/access_controller.cxx | 587 ++++++++---------------- stoc/source/security/file_policy.cxx | 68 +-- stoc/source/security/lru_cache.h | 313 +++++++++++++ stoc/source/security/makefile.mk | 19 +- stoc/source/security/permissions.cxx | 685 +++++++++++++++++++++++++++++ stoc/source/security/permissions.h | 139 ++++++ 6 files changed, 1339 insertions(+), 472 deletions(-) create mode 100644 stoc/source/security/lru_cache.h create mode 100644 stoc/source/security/permissions.cxx create mode 100644 stoc/source/security/permissions.h (limited to 'stoc/source') diff --git a/stoc/source/security/access_controller.cxx b/stoc/source/security/access_controller.cxx index 2d4d5a89c85e..ce6728d2ef6d 100644 --- a/stoc/source/security/access_controller.cxx +++ b/stoc/source/security/access_controller.cxx @@ -2,9 +2,9 @@ * * $RCSfile: access_controller.cxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $ + * last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -60,13 +60,15 @@ ************************************************************************/ #include -#include #include #include -#include +#include #include + #include +#include + #include #include @@ -80,26 +82,26 @@ #include #include #include -#include -#include -#include -#include + +#include "lru_cache.h" +#include "permissions.h" #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) #define SERVICE_NAME "com.sun.star.security.AccessController" #define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController" #define USER_CREDS "access-control.user-credentials" -// xxx todo deliver dll, ingo using namespace ::std; using namespace ::osl; -using namespace ::rtl; using namespace ::cppu; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; -namespace stoc_security +namespace stoc_sec { // static stuff initialized when loading lib @@ -109,323 +111,10 @@ static OUString s_serviceName = OUSTR(SERVICE_NAME); static OUString s_acRestriction = OUSTR("access-control.restriction"); static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); -rtl_StandardModuleCount s_moduleCount = MODULE_COUNT_INIT; - -static OUString s_filePermission = OUSTR("com.sun.star.io.FilePermission"); -static OUString s_socketPermission = OUSTR("com.sun.star.connection,SocketPermission"); -static OUString s_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission"); -static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission"); -static OUString s_allFiles = OUSTR("<>"); +::rtl_StandardModuleCount s_moduleCount = MODULE_COUNT_INIT; //################################################################################################## -//-------------------------------------------------------------------------------------------------- -static inline bool implies_actions( - OUString const & granted_actions, OUString const & demanded_actions ) - SAL_THROW( () ) -{ - // on average it makes no sense to build up a hash_set, because I think commonly there - // only one demanded action, so tokenize every granted actions for every demanded action - - sal_Int32 n = 0; - do - { - OUString demanded( demanded_actions.getToken( 0, ',', n ) ); - bool found = false; - sal_Int32 n2 = 0; - do - { - OUString granted( granted_actions.getToken( 0, ',', n2 ) ); - if (demanded.equals( granted )) - { - found = true; - break; - } - } - while (n2 >= 0); // all granted - if (! found) - return false; - } - while (n >= 0); // all demanded - // all actions in - return true; -} -//-------------------------------------------------------------------------------------------------- -static inline bool endsWith( OUString const & s, char const * p, sal_Int32 n ) -{ - sal_Int32 nPos = s.getLength(); - if (nPos < n) - return false; - sal_Unicode const * b = s.pData->buffer; - while (n) - { - if (b[ --nPos ] != p[ --n ]) - return false; - } - return true; -} - -//-------------------------------------------------------------------------------------------------- -static OUString const & getWorkingDir() SAL_THROW( () ) -{ - static OUString * s_workingDir = 0; - if (! s_workingDir) - { - OUString workingDir; - ::osl_getProcessWorkingDir( &workingDir.pData ); - - MutexGuard guard( Mutex::getGlobalMutex() ); - if (! s_workingDir) - { - static OUString s_dir( workingDir ); - s_workingDir = &s_dir; - } - } - return *s_workingDir; -} -//-------------------------------------------------------------------------------------------------- -static inline OUString makeAbsolutePath( OUString const & url ) SAL_THROW( () ) -{ - if (url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") )) - { - OUStringBuffer buf( 64 ); - buf.append( getWorkingDir() ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/*") ); - return buf.makeStringAndClear(); - } - if (url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("-") )) - { - OUStringBuffer buf( 64 ); - buf.append( getWorkingDir() ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/-") ); - return buf.makeStringAndClear(); - } - if (0 == url.compareToAscii( RTL_CONSTASCII_STRINGPARAM("file:///") )) // file url - return url; - // else relative path - OUString out; - oslFileError rc = ::osl_getAbsoluteFileURL( - getWorkingDir().pData, url.pData, &out.pData ); - return (osl_File_E_None == rc ? out : url); -} -// FilePermission -//-------------------------------------------------------------------------------------------------- -static inline bool implies( - Any const & granted, io::FilePermission const & demanded ) - SAL_THROW( () ) -{ - // avoid string ref-counting - OUString const & granted_typeName = - *reinterpret_cast< OUString const * >( &granted.pType->pTypeName ); - if (granted_typeName.equals( s_allPermission )) - return true; - if (! granted_typeName.equals( s_filePermission )) - return false; - - io::FilePermission const & granted_perm = - *reinterpret_cast< io::FilePermission const * >( granted.pData ); - - // check actions - if (! implies_actions( granted_perm.Actions, demanded.Actions )) - return false; - - // check url - if (granted_perm.URL.equals( s_allFiles )) - return true; - if (demanded.URL.equals( s_allFiles )) - return false; - if (granted_perm.URL.equals( demanded.URL )) - return true; - // make absolute pathes - OUString granted_url( makeAbsolutePath( granted_perm.URL ) ); - OUString demanded_url( makeAbsolutePath( demanded.URL ) ); - if (granted_url.equals( demanded_url )) - return true; - if (granted_url.getLength() > demanded_url.getLength()) - return false; - // check /- wildcard: all files and recursive in that path - if (endsWith( granted_url, RTL_CONSTASCII_STRINGPARAM("/-") )) - { - // demanded url must start with granted path (including path trailing path sep) - sal_Int32 len = granted_url.getLength() -1; - return (0 == demanded_url.compareTo( granted_url, len )); - } - // check /* wildcard: all files in that path (not recursive!) - if (endsWith( granted_url, RTL_CONSTASCII_STRINGPARAM("/*") )) - { - // demanded url must start with granted path (including path trailing path sep) - sal_Int32 len = granted_url.getLength() -1; - return ((0 == demanded_url.compareTo( granted_url, len )) && - (0 > demanded_url.indexOf( '/', len ))); // in addition, no deeper pathes - } - - return false; -} -// SocketPermission -//-------------------------------------------------------------------------------------------------- -static inline bool implies( - Any const & granted, connection::SocketPermission const & demanded ) - SAL_THROW( () ) -{ - // avoid string ref-counting - OUString const & granted_typeName = - *reinterpret_cast< OUString const * >( &granted.pType->pTypeName ); - if (granted_typeName.equals( s_allPermission )) - return true; - if (! granted_typeName.equals( s_socketPermission )) - return false; - - connection::SocketPermission const & granted_perm = - *reinterpret_cast< connection::SocketPermission const * >( granted.pData ); - // check actions - if (! implies_actions( granted_perm.Actions, demanded.Actions )) - return false; - // check host - // xxx todo - if (granted_perm.Host == demanded.Host) - return true; - - return false; -} -// RuntimePermission -//-------------------------------------------------------------------------------------------------- -static inline bool implies( - Any const & granted, security::RuntimePermission const & demanded ) - SAL_THROW( () ) -{ - // avoid string ref-counting - OUString const & granted_typeName = - *reinterpret_cast< OUString const * >( &granted.pType->pTypeName ); - if (granted_typeName.equals( s_allPermission )) - return true; - if (! granted_typeName.equals( s_runtimePermission )) - return false; - security::RuntimePermission const & granted_perm = - *reinterpret_cast< security::RuntimePermission const * >( granted.pData ); - return (sal_False != (granted_perm.Name == demanded.Name)); -} -// AllPermission -//-------------------------------------------------------------------------------------------------- -static inline bool implies( - Any const & granted, security::AllPermission const & demanded ) - SAL_THROW( () ) -{ - // avoid string ref-counting - OUString const & granted_typeName = - *reinterpret_cast< OUString const * >( &granted.pType->pTypeName ); - return (sal_False != granted_typeName.equals( s_allPermission )); -} - -//-------------------------------------------------------------------------------------------------- -template< typename permission_type > -static inline bool implies( - Sequence< Any > const & granted_permissions, permission_type const & demanded ) - SAL_THROW( () ) -{ - Any const * granted = granted_permissions.getConstArray(); - sal_Int32 nCount = granted_permissions.getLength(); - for ( sal_Int32 nPos = 0; nPos < nCount; ++nPos ) - { - if (implies( granted[ nPos ], demanded )) - return true; - } - return false; -} -//-------------------------------------------------------------------------------------------------- -static void checkStaticPermissions( - Sequence< Any > const & granted_permissions, Any const & demanded_permission ) - SAL_THROW( (RuntimeException) ) -{ - Type const & demanded_type = demanded_permission.getValueType(); - - // supported permission types - if (demanded_type.equals( ::getCppuType( (io::FilePermission const *)0 ) )) - { - io::FilePermission const & demanded = - *reinterpret_cast< io::FilePermission const * >( demanded_permission.pData ); - if (implies( granted_permissions, demanded )) - return; - OUStringBuffer buf( 48 ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") ); - buf.append( demanded_type.getTypeName() ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (url=\"") ); - buf.append( demanded.URL ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); - buf.append( demanded.Actions ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); - throw security::AccessControlException( - buf.makeStringAndClear(), Reference< XInterface >(), demanded_permission ); - } - else if (demanded_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) )) - { - connection::SocketPermission const & demanded = - *reinterpret_cast< connection::SocketPermission const * >( demanded_permission.pData ); - if (implies( granted_permissions, demanded )) - return; - OUStringBuffer buf( 48 ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") ); - buf.append( demanded_type.getTypeName() ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (host=\"") ); - buf.append( demanded.Host ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); - buf.append( demanded.Actions ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); - throw security::AccessControlException( - buf.makeStringAndClear(), Reference< XInterface >(), demanded_permission ); - } - else if (demanded_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) )) - { - security::RuntimePermission const & demanded = - *reinterpret_cast< security::RuntimePermission const * >( demanded_permission.pData ); - if (implies( granted_permissions, demanded )) - return; - OUStringBuffer buf( 48 ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") ); - buf.append( demanded_type.getTypeName() ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (name=\"") ); - buf.append( demanded.Name ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); - throw security::AccessControlException( - buf.makeStringAndClear(), Reference< XInterface >(), demanded_permission ); - } - else if (demanded_type.equals( ::getCppuType( (security::AllPermission const *)0 ) )) - { - security::AllPermission const & demanded = - *reinterpret_cast< security::AllPermission const * >( demanded_permission.pData ); - if (implies( granted_permissions, demanded )) - return; - throw security::AccessControlException( - OUSTR("access denied: com.sun.star.security.AllPermission"), - Reference< XInterface >(), demanded_permission ); - } - else - { - OUStringBuffer buf( 48 ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("checking for unsupported permission type: ") ); - buf.append( demanded_type.getTypeName() ); - throw RuntimeException( - buf.makeStringAndClear(), Reference< XInterface >() ); - } -} - -/** ac context granting all permissions -*/ -class acc_allPermissions - : public WeakImplHelper1< security::XAccessControlContext > -{ -public: - // XAccessControlContext impl - virtual void SAL_CALL checkPermission( - Any const & perm ) - throw (RuntimeException); -}; -//__________________________________________________________________________________________________ -void acc_allPermissions::checkPermission( - Any const & perm ) - throw (RuntimeException) -{ - // no restriction; allow all -} /** ac context combiner combining two ac contexts */ class acc_Combiner @@ -460,13 +149,13 @@ inline acc_Combiner::acc_Combiner( : m_x1( x1 ) , m_x2( x2 ) { - s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); } //__________________________________________________________________________________________________ acc_Combiner::~acc_Combiner() SAL_THROW( () ) { - s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); } //-------------------------------------------------------------------------------------------------- inline Reference< security::XAccessControlContext > acc_Combiner::create( @@ -489,19 +178,19 @@ void acc_Combiner::checkPermission( m_x2->checkPermission( perm ); } -/** ac context doing permission checks on static user permissions +/** ac context doing permission checks on static permissions */ -class acc_UserPolicy +class acc_Policy : public WeakImplHelper1< security::XAccessControlContext > { - Sequence< Any > m_permissions; + PermissionCollection m_permissions; public: - inline acc_UserPolicy( - Sequence< Any > permissions ) - SAL_THROW( () ) - : m_permissions( permissions ) - {} + inline acc_Policy( + PermissionCollection const & permissions ) + SAL_THROW( () ); + virtual ~acc_Policy() + SAL_THROW( () ); // XAccessControlContext impl virtual void SAL_CALL checkPermission( @@ -509,11 +198,25 @@ public: throw (RuntimeException); }; //__________________________________________________________________________________________________ -void acc_UserPolicy::checkPermission( +inline acc_Policy::acc_Policy( + PermissionCollection const & permissions ) + SAL_THROW( () ) + : m_permissions( permissions ) +{ + s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +acc_Policy::~acc_Policy() + SAL_THROW( () ) +{ + s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void acc_Policy::checkPermission( Any const & perm ) throw (RuntimeException) { - checkStaticPermissions( m_permissions, perm ); + m_permissions.checkPermission( perm ); } /** current context overriding dynamic ac restriction @@ -551,7 +254,7 @@ inline acc_CurrentContext::acc_CurrentContext( : m_refcount( 0 ) , m_xDelegate( xDelegate ) { - s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); if (xRestriction.is()) { @@ -563,7 +266,7 @@ inline acc_CurrentContext::acc_CurrentContext( acc_CurrentContext::~acc_CurrentContext() SAL_THROW( () ) { - s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); } //__________________________________________________________________________________________________ void acc_CurrentContext::acquire() @@ -648,7 +351,7 @@ public: //================================================================================================== class RecursionCheck : public ThreadData { - typedef hash_set< OUString, OUStringHash > t_set; + typedef hash_set< OUString, ::rtl::OUStringHash > t_set; static void SAL_CALL destroyKeyData( void * ); inline t_set * getData() SAL_THROW( () ) @@ -675,7 +378,20 @@ bool RecursionCheck::isRecurring( OUString const & userId ) SAL_THROW( () ) if (s) { t_set::const_iterator const iFind( s->find( userId ) ); - return (iFind != s->end()); + bool ret= (iFind != s->end()); +#ifdef __DIAGNOSE + if (ret) + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> info: recurring call of user \"") ); + buf.append( userId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"") ); + OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } +#endif + return ret; } return false; } @@ -743,15 +459,17 @@ class AccessController // mode enum { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode; + PermissionCollection m_defaultUserPermissions; // for single-user mode - Sequence< Any > m_singleUserPermissions; + PermissionCollection m_singleUserPermissions; OUString m_singleUserId; + bool m_defaultUser_init; bool m_singleUser_init; + // for multi-user mode + lru_cache< OUString, PermissionCollection, ::rtl::OUStringHash, equal_to< OUString > > + m_user2permissions; - typedef hash_map< OUString, Sequence< Any >, OUStringHash > t_user2permissions; - t_user2permissions m_user2permissions; - - Sequence< Any > getUserPermissions( + PermissionCollection getEffectivePermissions( Reference< XCurrentContext > const & xContext ) SAL_THROW( (RuntimeException) ); @@ -760,7 +478,7 @@ protected: public: AccessController( Reference< XComponentContext > const & xComponentContext ) - SAL_THROW( () ); + SAL_THROW( (RuntimeException) ); virtual ~AccessController() SAL_THROW( () ); @@ -794,13 +512,14 @@ public: }; //__________________________________________________________________________________________________ AccessController::AccessController( Reference< XComponentContext > const & xComponentContext ) - SAL_THROW( () ) + SAL_THROW( (RuntimeException) ) : t_helper( m_mutex ) , m_xComponentContext( xComponentContext ) , m_mode( ON ) // default + , m_defaultUser_init( false ) , m_singleUser_init( false ) { - s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); OUString mode; if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode) @@ -835,12 +554,27 @@ AccessController::AccessController( Reference< XComponentContext > const & xComp m_mode = SINGLE_DEFAULT_USER; } } + + // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process) + if (ON == m_mode || DYNAMIC_ONLY == m_mode) + { + sal_Int32 cacheSize; // multi-user cache size + if (! (m_xComponentContext->getValueByName( + OUSTR("/services/" SERVICE_NAME "/user-cache-size") ) >>= cacheSize)) + { + cacheSize = 128; // reasonable default? + } +#ifdef __CACHE_DIAGNOSE + cacheSize = 2; +#endif + m_user2permissions.setSize( cacheSize ); + } } //__________________________________________________________________________________________________ AccessController::~AccessController() SAL_THROW( () ) { - s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); } //__________________________________________________________________________________________________ void AccessController::disposing() @@ -901,36 +635,80 @@ Reference< security::XPolicy > const & AccessController::getPolicy() } return m_xPolicy; } + +#ifdef __DIAGNOSE +static void dumpPermissions( + OUString const & userId, PermissionCollection const & collection ) SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + if (userId.getLength()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> dumping effective permissions of user \"") ); + buf.append( userId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\":") ); + } + else + { + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("> dumping permission collection of default user:") ); + } + OString str( ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + Sequence< OUString > permissions( collection.toStrings() ); + OUString const * p = permissions.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos ) + { + OString str( ::rtl::OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } + OSL_TRACE( "> permission dump done" ); +} +#endif //__________________________________________________________________________________________________ -Sequence< Any > AccessController::getUserPermissions( +PermissionCollection AccessController::getEffectivePermissions( Reference< XCurrentContext > const & xContext ) SAL_THROW( (RuntimeException) ) { // this is the only place calling the policy singleton taking care of recurring calls + // init default permissions + if (! m_defaultUser_init) + { + // call on policy + // iff this is a recurring call for the default user, then grant all permissions + if (m_rec_check.isRecurring( OUString() )) + return PermissionCollection( new AllPermission() ); + RecursionMarkGuard rec_guard( m_rec_check, OUString() ); // mark possible recursion + PermissionCollection defaultUserPermissions( + getPolicy()->getDefaultPermissions() ); +#ifdef __DIAGNOSE + dumpPermissions( OUSTR("default"), defaultUserPermissions ); +#endif + // assign + MutexGuard guard( m_mutex ); + if (! m_defaultUser_init) + { + m_defaultUserPermissions = defaultUserPermissions; + m_defaultUser_init = true; + } + } + switch (m_mode) { case SINGLE_USER: - case SINGLE_DEFAULT_USER: { if (! m_singleUser_init) { // call on policy // iff this is a recurring call for the same user, then grant all permissions if (m_rec_check.isRecurring( m_singleUserId )) - { - Any allPerm( makeAny( security::AllPermission() ) ); - return Sequence< Any >( &allPerm, 1 ); - } - Sequence< Any > singleUserPermissions; - { + return PermissionCollection( new AllPermission() ); RecursionMarkGuard rec_guard( m_rec_check, m_singleUserId ); // mark possible recursion - if (SINGLE_USER == m_mode) - singleUserPermissions = getPolicy()->getPermissions( m_singleUserId ); - else - singleUserPermissions = getPolicy()->getDefaultPermissions(); - } - + PermissionCollection singleUserPermissions( + getPolicy()->getPermissions( m_singleUserId ), m_defaultUserPermissions ); +#ifdef __DIAGNOSE + dumpPermissions( m_singleUserId, singleUserPermissions ); +#endif // assign MutexGuard guard( m_mutex ); if (! m_singleUser_init) @@ -941,6 +719,10 @@ Sequence< Any > AccessController::getUserPermissions( } return m_singleUserPermissions; } + case SINGLE_DEFAULT_USER: + { + return m_defaultUserPermissions; + } case ON: { OUString userId; @@ -955,50 +737,33 @@ Sequence< Any > AccessController::getUserPermissions( } // lookup policy for user - ClearableMutexGuard guard( m_mutex ); - t_user2permissions::const_iterator iFind( m_user2permissions.find( userId ) ); - if (m_user2permissions.end() == iFind) { - guard.clear(); - - // call on policy - // iff this is a recurring call for the same user, then grant all permissions - if (m_rec_check.isRecurring( userId )) - { - Any allPerm( makeAny( security::AllPermission() ) ); - return Sequence< Any >( &allPerm, 1 ); - } - Sequence< Any > permissions; - { - RecursionMarkGuard rec_guard( m_rec_check, userId ); // mark possible recursion - permissions = getPolicy()->getPermissions( userId ); - } - - { - // assign - MutexGuard guard( m_mutex ); - t_user2permissions::const_iterator iFind( m_user2permissions.find( userId ) ); - if (m_user2permissions.end() != iFind) // inserted in the meantime - { - return iFind->second; - } - else // insert new - { - pair< t_user2permissions::iterator, bool > insertion( m_user2permissions.insert( - t_user2permissions::value_type( userId, permissions ) ) ); - OSL_ASSERT( insertion.second ); - return permissions; - } - } + MutexGuard guard( m_mutex ); + PermissionCollection const * pPermissions = m_user2permissions.lookup( userId ); + if (pPermissions) + return *pPermissions; } - else + + // call on policy + // iff this is a recurring call for the same user, then grant all permissions + if (m_rec_check.isRecurring( userId )) + return PermissionCollection( new AllPermission() ); + RecursionMarkGuard rec_guard( m_rec_check, userId ); // mark possible recursion + PermissionCollection permissions( + getPolicy()->getPermissions( userId ), m_defaultUserPermissions ); +#ifdef __DIAGNOSE + dumpPermissions( userId, permissions ); +#endif { - return iFind->second; + // cache + MutexGuard guard( m_mutex ); + m_user2permissions.set( userId, permissions ); } + return permissions; } default: OSL_ENSURE( 0, "### this should never be called in this mode!" ); - return Sequence< Any >(); + return PermissionCollection(); } } @@ -1027,7 +792,7 @@ void AccessController::checkPermission( return; // then static check - checkStaticPermissions( getUserPermissions( xContext ), perm ); + getEffectivePermissions( xContext ).checkPermission( perm ); } //__________________________________________________________________________________________________ Any AccessController::doRestricted( @@ -1087,7 +852,7 @@ Reference< security::XAccessControlContext > AccessController::getContext() throw (RuntimeException) { if (OFF == m_mode) // optimize this way, because no dynamic check will be performed - return new acc_allPermissions(); // dummy granting all permissions + return new acc_Policy( PermissionCollection( new AllPermission() ) ); Reference< XCurrentContext > xContext; ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); @@ -1098,7 +863,7 @@ Reference< security::XAccessControlContext > AccessController::getContext() xDynamic = getDynamicRestriction( xContext ); } - return acc_Combiner::create( xDynamic, new acc_UserPolicy( getUserPermissions( xContext ) ) ); + return acc_Combiner::create( xDynamic, new acc_Policy( getEffectivePermissions( xContext ) ) ); } // XServiceInfo impl @@ -1174,14 +939,12 @@ static struct ImplementationEntry s_entries [] = } -using namespace stoc_security; - extern "C" { //================================================================================================== -sal_Bool SAL_CALL component_canUnload( TimeValue * pTime ) +sal_Bool SAL_CALL component_canUnload( TimeValue * time ) { - return s_moduleCount.canUnload( &s_moduleCount, pTime ); + return ::stoc_sec::s_moduleCount.canUnload( &::stoc_sec::s_moduleCount, time ); } //================================================================================================== void SAL_CALL component_getImplementationEnvironment( @@ -1191,14 +954,14 @@ void SAL_CALL component_getImplementationEnvironment( } //================================================================================================== sal_Bool SAL_CALL component_writeInfo( - void * pServiceManager, void * pRegistryKey ) + lang::XMultiServiceFactory * smgr, registry::XRegistryKey * key ) { - return component_writeInfoHelper( pServiceManager, pRegistryKey, s_entries ); + return component_writeInfoHelper( smgr, key, ::stoc_sec::s_entries ); } //================================================================================================== void * SAL_CALL component_getFactory( - sal_Char const * pImplName, void * pServiceManager, void * pRegistryKey ) + sal_Char const * implName, lang::XMultiServiceFactory * smgr, registry::XRegistryKey * key ) { - return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, s_entries ); + return component_getFactoryHelper( implName, smgr, key, ::stoc_sec::s_entries ); } } diff --git a/stoc/source/security/file_policy.cxx b/stoc/source/security/file_policy.cxx index 8a74248c1920..595b84906f50 100644 --- a/stoc/source/security/file_policy.cxx +++ b/stoc/source/security/file_policy.cxx @@ -2,9 +2,9 @@ * * $RCSfile: file_policy.cxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $ + * last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -90,7 +90,7 @@ using namespace ::cppu; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; -namespace stoc_security +namespace stoc_sec { // static stuff initialized when loading lib @@ -98,7 +98,7 @@ static OUString s_implName = OUSTR(IMPL_NAME); static OUString s_serviceName = OUSTR(SERVICE_NAME); static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); -extern rtl_StandardModuleCount s_moduleCount; +extern ::rtl_StandardModuleCount s_moduleCount; //################################################################################################## @@ -166,13 +166,13 @@ FilePolicy::FilePolicy( Reference< XComponentContext > const & xComponentContext , m_xComponentContext( xComponentContext ) , m_init( false ) { - s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt ); } //__________________________________________________________________________________________________ FilePolicy::~FilePolicy() SAL_THROW( () ) { - s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); + s_moduleCount.modCnt.release( &s_moduleCount.modCnt ); } //__________________________________________________________________________________________________ void FilePolicy::disposing() @@ -416,30 +416,6 @@ PolicyReader::~PolicyReader() OSL_ASSERT( osl_File_E_None == rc ); } -//-------------------------------------------------------------------------------------------------- -static inline Sequence< Any > concat( - Sequence< Any > const & seq1, - Sequence< Any > const & seq2 ) - SAL_THROW( () ) -{ - if (! seq2.getLength()) - return seq1; - if (! seq1.getLength()) - return seq2; - - Sequence< Any > seq( seq1 ); - sal_Int32 len1 = seq1.getLength(); - sal_Int32 len2 = seq2.getLength(); - seq.realloc( len1 + len2 ); - Any * p_seq = seq.getArray(); - Any const * p_seq2 = seq2.getConstArray(); - while (len2--) - { - p_seq[ len1 + len2 ] = p_seq2[ len2 ]; - } - return seq; -} - static OUString s_grant = OUSTR("grant"); static OUString s_user = OUSTR("user"); static OUString s_permission = OUSTR("permission"); @@ -448,7 +424,7 @@ static OUString s_closingBrace = OUSTR("}"); static OUString s_semi = OUSTR(";"); static OUString s_filePermission = OUSTR("com.sun.star.io.FilePermission"); -static OUString s_socketPermission = OUSTR("com.sun.star.connection,SocketPermission"); +static OUString s_socketPermission = OUSTR("com.sun.star.connection.SocketPermission"); static OUString s_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission"); static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission"); @@ -549,32 +525,10 @@ void FilePolicy::refresh() token = reader.getToken(); // next grant token } - // add default permissions to all user permissions - if (defaultPermissions.getLength()) - { - t_permissions userPermissions2; - t_permissions::const_iterator iPos( userPermissions.begin() ); - t_permissions::const_iterator iEnd( userPermissions.end() ); - while (iPos != iEnd) - { - pair< t_permissions::iterator, bool > insertion( - userPermissions2.insert( t_permissions::value_type( - iPos->first, concat( iPos->second, defaultPermissions ) ) ) ); - OSL_ASSERT( insertion.second ); - ++iPos; - } - // assign new ones - MutexGuard guard( m_mutex ); - m_defaultPermissions = defaultPermissions; - m_userPermissions = userPermissions2; - } - else // no default permissions - { - // assign new ones - MutexGuard guard( m_mutex ); - m_defaultPermissions = defaultPermissions; - m_userPermissions = userPermissions; - } + // assign new ones + MutexGuard guard( m_mutex ); + m_defaultPermissions = defaultPermissions; + m_userPermissions = userPermissions; } //__________________________________________________________________________________________________ diff --git a/stoc/source/security/lru_cache.h b/stoc/source/security/lru_cache.h new file mode 100644 index 000000000000..3d52685198f4 --- /dev/null +++ b/stoc/source/security/lru_cache.h @@ -0,0 +1,313 @@ +/************************************************************************* + * + * $RCSfile: lru_cache.h,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifndef _STOC_SEC_LRU_CACHE_H_ +#define _STOC_SEC_LRU_CACHE_H_ + +#include + +// __CACHE_DIAGNOSE works only for OUString keys +#ifdef __CACHE_DIAGNOSE +#include +#include +#include +#include +#endif + + +namespace stoc_sec +{ + +/** Implementation of a least recently used (lru) cache. +*/ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +class lru_cache +{ + struct Entry + { + t_key m_key; + t_val m_val; + Entry * m_pred; + Entry * m_succ; + }; + typedef ::std::hash_map< t_key, Entry *, t_hashKey, t_equalKey > t_key2element; + t_key2element m_key2element; + ::std::size_t m_size; + + Entry * m_block; + mutable Entry * m_head; + mutable Entry * m_tail; + inline void toFront( Entry * entry ) const SAL_THROW( () ); + +public: + /** Default Ctor. Does not cache. + */ + inline lru_cache() SAL_THROW( () ); + /** Ctor. + + @param size number of elements to be cached; default param set to 128 + */ + inline lru_cache( ::std::size_t size ) SAL_THROW( () ); + + /** Destructor: releases all cached elements and keys. + */ + inline ~lru_cache() SAL_THROW( () ); + + /** Retrieves a pointer to value in cache. Returns 0, if none was found. + + @param key a key + @return pointer to value or 0 + */ + inline t_val const * lookup( t_key const & key ) const SAL_THROW( () ); + + /** Sets a value to be cached for given key. + + @param key a key + @param val a value + */ + inline void set( t_key const & key, t_val const & val ) SAL_THROW( () ); + + /** Tests whether a value is cached for given key. + + @param key a key + @return true, if value is cached + */ + inline bool has( t_key const & key ) const SAL_THROW( () ); + + /** Clears the cache, releasing all cached elements and keys. + */ + inline void clear() SAL_THROW( () ); + + /** Sets the number of elements to be cached. This will clear previous entries. + + @param cacheSize number of elements to be cached + */ + inline void setSize( ::std::size_t size ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::setSize( + ::std::size_t size ) SAL_THROW( () ) +{ + m_key2element.clear(); + delete [] m_block; + m_block = 0; + m_size = size; + + if (0 < m_size) + { + m_block = new Entry[ m_size ]; + m_head = m_block; + m_tail = m_block + m_size -1; + for ( ::std::size_t nPos = m_size; nPos--; ) + { + m_block[ nPos ].m_pred = m_block + nPos -1; + m_block[ nPos ].m_succ = m_block + nPos +1; + } + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lru_cache( + ::std::size_t size ) SAL_THROW( () ) + : m_size( 0 ) + , m_block( 0 ) +{ + setSize( size ); +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lru_cache() SAL_THROW( () ) + : m_size( 0 ) + , m_block( 0 ) +{ +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::~lru_cache() + SAL_THROW( () ) +{ + delete [] m_block; +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::toFront( + Entry * entry ) const SAL_THROW( () ) +{ + if (entry != m_head) + { + // cut out element + if (entry == m_tail) + { + m_tail = entry->m_pred; + } + else + { + entry->m_succ->m_pred = entry->m_pred; + entry->m_pred->m_succ = entry->m_succ; + } + // push to front + m_head->m_pred = entry; + entry->m_succ = m_head; + m_head = entry; + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline bool lru_cache< t_key, t_val, t_hashKey, t_equalKey >::has( + t_key const & key ) const SAL_THROW( () ) +{ + t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + return (iFind != m_key2element.end()); +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline t_val const * lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lookup( + t_key const & key ) const SAL_THROW( () ) +{ + if (0 < m_size) + { + t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + if (iFind != m_key2element.end()) + { + Entry * entry = iFind->second; + toFront( entry ); +#ifdef __CACHE_DIAGNOSE + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> retrieved element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" from cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +#endif + return &entry->m_val; + } + } + return 0; +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::set( + t_key const & key, t_val const & val ) SAL_THROW( () ) +{ + if (0 < m_size) + { + t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + + Entry * entry; + if (iFind == m_key2element.end()) + { + entry = m_tail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (entry->m_key.getLength()) + { + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> kicking element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" from cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } +#endif + m_key2element.erase( entry->m_key ); + entry->m_key = key; + ::std::pair< t_key2element::iterator, bool > insertion( + m_key2element.insert( t_key2element::value_type( key, entry ) ) ); +#ifdef __CACHE_DIAGNOSE + OSL_ENSURE( insertion.second, "### inserting new cache entry failed?!" ); +#endif + } + else + { + entry = iFind->second; +#ifdef __CACHE_DIAGNOSE + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> replacing element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" in cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +#endif + } + entry->m_val = val; + toFront( entry ); + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::clear() SAL_THROW( () ) +{ + m_key2element.clear(); + for ( ::std::size_t nPos = m_size; nPos--; ) + { + m_block[ nPos ].m_key = t_key(); + m_block[ nPos ].m_val = t_val(); + } +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> cleared cache\n" ); +#endif +} + +} + +#endif diff --git a/stoc/source/security/makefile.mk b/stoc/source/security/makefile.mk index 27495fb16b81..42f7ff3102ec 100644 --- a/stoc/source/security/makefile.mk +++ b/stoc/source/security/makefile.mk @@ -2,9 +2,9 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.1 $ +# $Revision: 1.2 $ # -# last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $ +# last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ # # The Contents of this file are made available subject to the terms of # either of the following licenses @@ -78,14 +78,16 @@ COMP1TYPELIST=$(TARGET) .INCLUDE : ..$/cppumaker.mk SLOFILES= \ + $(SLO)$/permissions.obj \ $(SLO)$/access_controller.obj \ $(SLO)$/file_policy.obj SHL1TARGET=$(TARGET) SHL1STDLIBS= \ - $(CPPULIB) \ $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(CPPULIB) \ $(SALLIB) SHL1VERSIONMAP=$(TARGET).map @@ -96,10 +98,21 @@ SHL1DEF=$(MISC)$/$(SHL1TARGET).def DEF1NAME=$(SHL1TARGET) .IF "$(debug)" != "" + # msvc++: no inlining for debugging .IF "$(COM)" == "MSC" CFLAGS += /Ob0 .ENDIF + +# some diagnose +.IF "$(diag)" == "full" +CFLAGS += -D__DIAGNOSE -D__CACHE_DIAGNOSE +.ELIF "$(diag)" == "cache" +CFLAGS += -D__CACHE_DIAGNOSE +.ELIF "$(diag)" != "" +CFLAGS += -D__DIAGNOSE +.ENDIF + .ENDIF # --- Targets ------------------------------------------------------ diff --git a/stoc/source/security/permissions.cxx b/stoc/source/security/permissions.cxx new file mode 100644 index 000000000000..c33626ff24cf --- /dev/null +++ b/stoc/source/security/permissions.cxx @@ -0,0 +1,685 @@ +/************************************************************************* + * + * $RCSfile: permissions.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "permissions.h" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace ::std; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace stoc_sec +{ + +// static stuff initialized when loading lib +static OUString s_filePermission = OUSTR("com.sun.star.io.FilePermission"); +static OUString s_socketPermission = OUSTR("com.sun.star.connection,SocketPermission"); +static OUString s_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission"); +static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission"); +static OUString s_allFiles = OUSTR("<>"); + +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +static inline sal_Int32 makeMask( + OUString const & items, char const * const * strings ) SAL_THROW( () ) +{ + sal_Int32 mask = 0; + + sal_Int32 n = 0; + do + { + OUString item( items.getToken( 0, ',', n ).trim() ); + if (! item.getLength()) + continue; + sal_Int32 nPos = 0; + while (strings[ nPos ]) + { + if (item.equalsAscii( strings[ nPos ] )) + { + mask |= (0x80000000 >> nPos); + break; + } + ++nPos; + } +#ifdef _DEBUG + if (! strings[ nPos ]) + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("### ignoring unknown socket action: ") ); + buf.append( item ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } +#endif + } + while (n >= 0); // all items + return mask; +} +//-------------------------------------------------------------------------------------------------- +static inline OUString makeStrings( + sal_Int32 mask, char const * const * strings ) SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + while (mask) + { + if (0x80000000 & mask) + { + buf.appendAscii( *strings ); + if (mask << 1) // more items following + buf.append( (sal_Unicode)',' ); + } + mask = (mask << 1); + ++strings; + } + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class SocketPermission : public Permission +{ + static char const * s_actions []; + sal_Int32 m_actions; + + OUString m_host; + sal_Int32 m_lowerPort; + sal_Int32 m_upperPort; + mutable OUString m_ip; + mutable bool m_resolveErr; + mutable bool m_resolvedHost; + bool m_wildCardHost; + + inline bool resolveHost() const SAL_THROW( () ); + +public: + SocketPermission( + connection::SocketPermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ); + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +char const * SocketPermission::s_actions [] = { "accept", "connect", "listen", "resolve", 0 }; +//__________________________________________________________________________________________________ +SocketPermission::SocketPermission( + connection::SocketPermission const & perm, + ::rtl::Reference< Permission > const & next ) + SAL_THROW( () ) + : Permission( SOCKET, next ) + , m_actions( makeMask( perm.Actions, s_actions ) ) + , m_host( perm.Host ) + , m_lowerPort( 0 ) + , m_upperPort( 65535 ) + , m_resolveErr( false ) + , m_resolvedHost( false ) + , m_wildCardHost( perm.Host.getLength() && '*' == perm.Host.pData->buffer[ 0 ] ) +{ + // separate host from portrange + sal_Int32 colon = m_host.indexOf( ':' ); + if (colon >= 0) // port [range] given + { + sal_Int32 minus = m_host.indexOf( '-', colon +1 ); + if (minus < 0) + { + m_lowerPort = m_upperPort = m_host.copy( colon +1 ).toInt32(); + } + else if (minus == (colon +1)) // -N + { + m_upperPort = m_host.copy( minus +1 ).toInt32(); + } + else if (minus == (m_host.getLength() -1)) // N- + { + m_lowerPort = m_host.copy( colon +1, m_host.getLength() -1 -colon -1 ).toInt32(); + } + else // A-B + { + m_lowerPort = m_host.copy( colon +1, minus - colon -1 ).toInt32(); + m_upperPort = m_host.copy( minus +1, m_host.getLength() -minus -1 ).toInt32(); + } + m_host = m_host.copy( 0, colon ); + } +} +//__________________________________________________________________________________________________ +inline bool SocketPermission::resolveHost() const SAL_THROW( () ) +{ + if (m_resolveErr) + return false; + + if (! m_resolvedHost) + { + // dns lookup + SocketAddr addr; + SocketAddr::resolveHostname( m_host, addr ); + OUString ip; + m_resolveErr = (::osl_Socket_E_None != ::osl_getDottedInetAddrOfSocketAddr( + addr.getHandle(), &ip.pData )); + if (m_resolveErr) + return false; + + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! m_resolvedHost) + { + m_ip = ip; + m_resolvedHost = true; + } + } + return m_resolvedHost; +} +//__________________________________________________________________________________________________ +bool SocketPermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (SOCKET != perm.m_type) + return false; + SocketPermission const & demanded = static_cast< SocketPermission const & >( perm ); + + // check actions + if ((m_actions & demanded.m_actions) != demanded.m_actions) + return false; + + // check ports + if (demanded.m_lowerPort < m_lowerPort) + return false; + if (demanded.m_upperPort > m_upperPort) + return false; + + // quick check host (DNS names: RFC 1034/1035) + if (m_host.equalsIgnoreAsciiCase( demanded.m_host )) + return true; + // check for host wildcards + if (m_wildCardHost) + { + OUString const & demanded_host = demanded.m_host; + if (demanded_host.getLength() <= m_host.getLength()) + return false; + sal_Int32 len = m_host.getLength() -1; // skip star + return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength( + demanded_host.getStr() + demanded_host.getLength() - len, len, + m_host.pData->buffer + 1, len )); + } + if (demanded.m_wildCardHost) + return false; + + // compare IP addresses + if (! resolveHost()) + return false; + if (! demanded.resolveHost()) + return false; + return (sal_False != m_ip.equals( demanded.m_ip )); +} +//__________________________________________________________________________________________________ +OUString SocketPermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + // host + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.connection.SocketPermission (host=\"") ); + buf.append( m_host ); + if (m_resolvedHost) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[") ); + buf.append( m_ip ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("]") ); + } + // port + if (0 != m_lowerPort || 65535 != m_upperPort) + { + buf.append( (sal_Unicode)':' ); + if (m_lowerPort > 0) + buf.append( m_lowerPort ); + if (m_upperPort > m_lowerPort) + { + buf.append( (sal_Unicode)'-' ); + if (m_upperPort < 65535) + buf.append( m_upperPort ); + } + } + // actions + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); + buf.append( makeStrings( m_actions, s_actions ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class FilePermission : public Permission +{ + static char const * s_actions []; + sal_Int32 m_actions; + + OUString m_url; + bool m_allFiles; + +public: + FilePermission( + io::FilePermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ); + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +char const * FilePermission::s_actions [] = { "read", "write", "execute", "delete", 0 }; +//-------------------------------------------------------------------------------------------------- +static OUString const & getWorkingDir() SAL_THROW( () ) +{ + static OUString * s_workingDir = 0; + if (! s_workingDir) + { + OUString workingDir; + ::osl_getProcessWorkingDir( &workingDir.pData ); + + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_workingDir) + { + static OUString s_dir( workingDir ); + s_workingDir = &s_dir; + } + } + return *s_workingDir; +} +//__________________________________________________________________________________________________ +FilePermission::FilePermission( + io::FilePermission const & perm, + ::rtl::Reference< Permission > const & next ) + SAL_THROW( () ) + : Permission( FILE, next ) + , m_actions( makeMask( perm.Actions, s_actions ) ) + , m_url( perm.URL ) + , m_allFiles( sal_False != perm.URL.equals( s_allFiles ) ) +{ + if (! m_allFiles) + { + if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") )) + { + OUStringBuffer buf( 64 ); + buf.append( getWorkingDir() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/*") ); + m_url = buf.makeStringAndClear(); + } + else if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("-") )) + { + OUStringBuffer buf( 64 ); + buf.append( getWorkingDir() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/-") ); + m_url = buf.makeStringAndClear(); + } + else if (0 != m_url.compareToAscii( RTL_CONSTASCII_STRINGPARAM("file:///") )) + { + // relative path + OUString out; + oslFileError rc = ::osl_getAbsoluteFileURL( + getWorkingDir().pData, perm.URL.pData, &out.pData ); + m_url = (osl_File_E_None == rc ? out : perm.URL); // fallback + } + } +} +//__________________________________________________________________________________________________ +bool FilePermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (FILE != perm.m_type) + return false; + FilePermission const & demanded = static_cast< FilePermission const & >( perm ); + + // check actions + if ((m_actions & demanded.m_actions) != demanded.m_actions) + return false; + + // check url + if (m_allFiles) + return true; + if (demanded.m_allFiles) + return false; + + if (m_url.equals( demanded.m_url )) + return true; + if (m_url.getLength() > demanded.m_url.getLength()) + return false; + // check /- wildcard: all files and recursive in that path + if (1 < m_url.getLength() && + 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/-" )) + { + // demanded url must start with granted path (including path trailing path sep) + sal_Int32 len = m_url.getLength() -1; + return (0 == demanded.m_url.compareTo( m_url, len )); + } + // check /* wildcard: all files in that path (not recursive!) + if (1 < m_url.getLength() && + 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/*" )) + { + // demanded url must start with granted path (including path trailing path sep) + sal_Int32 len = m_url.getLength() -1; + return ((0 == demanded.m_url.compareTo( m_url, len )) && + (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes + } + return false; +} +//__________________________________________________________________________________________________ +OUString FilePermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + // url + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.io.FilePermission (url=\"") ); + buf.append( m_url ); + // actions + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); + buf.append( makeStrings( m_actions, s_actions ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class RuntimePermission : public Permission +{ + OUString m_name; + +public: + inline RuntimePermission( + security::RuntimePermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : Permission( RUNTIME, next ) + , m_name( perm.Name ) + {} + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +bool RuntimePermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (RUNTIME != perm.m_type) + return false; + RuntimePermission const & demanded = static_cast< RuntimePermission const & >( perm ); + + // check name + return (sal_False != m_name.equals( demanded.m_name )); +} +//__________________________________________________________________________________________________ +OUString RuntimePermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.RuntimePermission (name=\"") ); + buf.append( m_name ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +bool AllPermission::implies( Permission const & ) const SAL_THROW( () ) +{ + return true; +} +//__________________________________________________________________________________________________ +OUString AllPermission::toString() const SAL_THROW( () ) +{ + return OUSTR("com.sun.star.security.AllPermission"); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +PermissionCollection::PermissionCollection( + Sequence< Any > const & permissions, PermissionCollection const & addition ) + SAL_THROW( (RuntimeException) ) + : m_head( addition.m_head ) +{ + Any const * perms = permissions.getConstArray(); + for ( sal_Int32 nPos = permissions.getLength(); nPos--; ) + { + Any const & perm = perms[ nPos ]; + Type const & perm_type = perm.getValueType(); + + // supported permission types + if (perm_type.equals( ::getCppuType( (io::FilePermission const *)0 ) )) + { + m_head = new FilePermission( + *reinterpret_cast< io::FilePermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) )) + { + m_head = new SocketPermission( + *reinterpret_cast< connection::SocketPermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) )) + { + m_head = new RuntimePermission( + *reinterpret_cast< security::RuntimePermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (security::AllPermission const *)0 ) )) + { + m_head = new AllPermission( m_head ); + } + else + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "checking for unsupported permission type: ") ); + buf.append( perm_type.getTypeName() ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + OSL_ASSERT( 0 ); + } + } +} +//__________________________________________________________________________________________________ +Sequence< OUString > PermissionCollection::toStrings() const SAL_THROW( () ) +{ + vector< OUString > strings; + strings.reserve( 8 ); + ::rtl::Reference< Permission > perm( m_head ); + while (perm.is()) + { + strings.push_back( perm->toString() ); + perm = perm->m_next; + } + return Sequence< OUString >( &strings[ 0 ], strings.size() ); +} +//__________________________________________________________________________________________________ +inline static bool __implies( + ::rtl::Reference< Permission > const & head, Permission const & demanded ) SAL_THROW( () ) +{ + ::rtl::Reference< Permission > perm( head ); + while (perm.is()) + { + if (perm->implies( demanded )) + return true; + perm = perm->m_next; + } + return false; +} +//__________________________________________________________________________________________________ +bool PermissionCollection::implies( Permission const & perm ) const SAL_THROW( () ) +{ + return __implies( m_head, perm ); +} + +#ifdef __DIAGNOSE +//-------------------------------------------------------------------------------------------------- +static void demanded_diag( + Permission const & perm ) + SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("demanding ") ); + buf.append( perm.toString() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ok.") ); + ::rtl::OString str( + ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +} +#endif +//-------------------------------------------------------------------------------------------------- +static void throwAccessControlException( + Permission const & perm, Any const & demanded_perm ) + SAL_THROW( (security::AccessControlException) ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") ); + buf.append( perm.toString() ); + throw security::AccessControlException( + buf.makeStringAndClear(), Reference< XInterface >(), demanded_perm ); + OSL_ASSERT( 0 ); +} +//================================================================================================== +void PermissionCollection::checkPermission( Any const & perm ) + SAL_THROW( (RuntimeException) ) +{ + Type const & demanded_type = perm.getValueType(); + + // supported permission types + // stack object of SimpleReferenceObject are ok, as long as they are not + // assigned to a ::rtl::Reference<> (=> delete this) + if (demanded_type.equals( ::getCppuType( (io::FilePermission const *)0 ) )) + { + FilePermission demanded( + *reinterpret_cast< io::FilePermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) )) + { + SocketPermission demanded( + *reinterpret_cast< connection::SocketPermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) )) + { + RuntimePermission demanded( + *reinterpret_cast< security::RuntimePermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (security::AllPermission const *)0 ) )) + { + AllPermission demanded; + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("checking for unsupported permission type: ") ); + buf.append( demanded_type.getTypeName() ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + OSL_ASSERT( 0 ); + } +} + +} diff --git a/stoc/source/security/permissions.h b/stoc/source/security/permissions.h new file mode 100644 index 000000000000..43166683a5ec --- /dev/null +++ b/stoc/source/security/permissions.h @@ -0,0 +1,139 @@ +/************************************************************************* + * + * $RCSfile: permissions.h,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: dbo $ $Date: 2002-03-04 17:43:21 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifndef _STOC_SEC_PERMISSIONS_H_ +#define _STOC_SEC_PERMISSIONS_H_ + +#include +#include +#include +#include + +#include +#include +#include + + +namespace stoc_sec +{ + +extern ::rtl_StandardModuleCount s_moduleCount; + +//================================================================================================== +class Permission : public ::salhelper::SimpleReferenceObject +{ +public: + ::rtl::Reference< Permission > m_next; + // mode + enum t_type { ALL, RUNTIME, SOCKET, FILE } m_type; + + inline Permission( + t_type type, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : m_next( next ) + , m_type( type ) + {} + + virtual bool implies( Permission const & perm ) const SAL_THROW( () ) = 0; + virtual ::rtl::OUString toString() const SAL_THROW( () ) = 0; +}; +//================================================================================================== +class AllPermission : public Permission +{ +public: + inline AllPermission( + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : Permission( ALL, next ) + {} + + virtual bool implies( Permission const & ) const SAL_THROW( () ); + virtual ::rtl::OUString toString() const SAL_THROW( () ); +}; + +//================================================================================================== +class PermissionCollection +{ + ::rtl::Reference< Permission > m_head; +public: + inline PermissionCollection() SAL_THROW( () ) + {} + inline PermissionCollection( PermissionCollection const & collection ) SAL_THROW( () ) + : m_head( collection.m_head ) + {} + inline PermissionCollection( ::rtl::Reference< Permission > const & single ) SAL_THROW( () ) + : m_head( single ) + {} + PermissionCollection( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const & permissions, + PermissionCollection const & addition = PermissionCollection() ) + SAL_THROW( (::com::sun::star::uno::RuntimeException) ); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > toStrings() const SAL_THROW( () ); + + bool implies( Permission const & ) const SAL_THROW( () ); + void checkPermission( ::com::sun::star::uno::Any const & perm ) + SAL_THROW( (::com::sun::star::uno::RuntimeException) ); +}; + +} + +#endif -- cgit