summaryrefslogtreecommitdiff
path: root/stoc
diff options
context:
space:
mode:
authorDaniel Boelzle <dbo@openoffice.org>2002-01-25 08:30:07 +0000
committerDaniel Boelzle <dbo@openoffice.org>2002-01-25 08:30:07 +0000
commit7f290fc5220cf6076082be3554a0e6b9825bd326 (patch)
treec443e743b41c1b48b42a0db5e9051b09276fa865 /stoc
parentd33523503fbf067b8201a0b43e19ac881b8f2289 (diff)
#88919# introducing native access controller and file policy implementation
Diffstat (limited to 'stoc')
-rw-r--r--stoc/prj/build.lst1
-rw-r--r--stoc/prj/d.lst1
-rw-r--r--stoc/source/security/access_controller.cxx1204
-rw-r--r--stoc/source/security/file_policy.cxx627
-rw-r--r--stoc/source/security/makefile.mk108
5 files changed, 1941 insertions, 0 deletions
diff --git a/stoc/prj/build.lst b/stoc/prj/build.lst
index 6852b2f24548..54daa54abe96 100644
--- a/stoc/prj/build.lst
+++ b/stoc/prj/build.lst
@@ -4,6 +4,7 @@ tc stoc\source\defaultregistry nmake - all tc_defr NULL
tc stoc\source\implementationregistration nmake - all tc_ireg tc_defr NULL
tc stoc\source\loader nmake - all tc_loa tc_ireg NULL
tc stoc\source\servicemanager nmake - all tc_smgr tc_loa NULL
+tc stoc\source\security nmake - all tc_sec tc_loa NULL
tc stoc\source\simpleregistry nmake - all tc_sreg tc_smgr NULL
tc stoc\source\registry_tdprovider nmake - all tc_regtd tc_sreg NULL
tc stoc\source\tdmanager nmake - all tc_tdmng tc_regtd NULL
diff --git a/stoc/prj/d.lst b/stoc/prj/d.lst
index 9f409b6148a6..5b4a40b9bfc0 100644
--- a/stoc/prj/d.lst
+++ b/stoc/prj/d.lst
@@ -24,6 +24,7 @@ mkdir: %_DEST%\inc%_EXT%\stoc
..\source\servicemanager\smgr.xml %_DEST%\xml%_EXT%\smgr.xml
..\source\simpleregistry\simreg.xml %_DEST%\xml%_EXT%\simreg.xml
..\source\tdmanager\tdmgr.xml %_DEST%\xml%_EXT%\tdmgr.xml
+..\source\security\sec.xml %_DEST%\xml%_EXT%\sec.xml
..\source\typeconv\tcv.xml %_DEST%\xml%_EXT%\tcv.xml
diff --git a/stoc/source/security/access_controller.cxx b/stoc/source/security/access_controller.cxx
new file mode 100644
index 000000000000..2d4d5a89c85e
--- /dev/null
+++ b/stoc/source/security/access_controller.cxx
@@ -0,0 +1,1204 @@
+/*************************************************************************
+ *
+ * $RCSfile: access_controller.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $
+ *
+ * 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 <hash_set>
+#include <hash_map>
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <osl/process.h>
+#include <osl/thread.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <uno/current_context.h>
+
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/compbase3.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+
+#include <com/sun/star/uno/XCurrentContext.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/security/XAccessController.hpp>
+#include <com/sun/star/security/XPolicy.hpp>
+#include <com/sun/star/security/RuntimePermission.hpp>
+#include <com/sun/star/security/AllPermission.hpp>
+#include <com/sun/star/io/FilePermission.hpp>
+#include <com/sun/star/connection/SocketPermission.hpp>
+
+#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;
+
+namespace stoc_security
+{
+
+// static stuff initialized when loading lib
+static OUString s_envType = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
+static OUString s_implName = OUSTR(IMPL_NAME);
+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("<<ALL FILES>>");
+
+//##################################################################################################
+
+//--------------------------------------------------------------------------------------------------
+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
+ : public WeakImplHelper1< security::XAccessControlContext >
+{
+ Reference< security::XAccessControlContext > m_x1, m_x2;
+
+ inline acc_Combiner(
+ Reference< security::XAccessControlContext > const & x1,
+ Reference< security::XAccessControlContext > const & x2 )
+ SAL_THROW( () );
+
+public:
+ virtual ~acc_Combiner()
+ SAL_THROW( () );
+
+ static inline Reference< security::XAccessControlContext > create(
+ Reference< security::XAccessControlContext > const & x1,
+ Reference< security::XAccessControlContext > const & x2 )
+ SAL_THROW( () );
+
+ // XAccessControlContext impl
+ virtual void SAL_CALL checkPermission(
+ Any const & perm )
+ throw (RuntimeException);
+};
+//__________________________________________________________________________________________________
+inline acc_Combiner::acc_Combiner(
+ Reference< security::XAccessControlContext > const & x1,
+ Reference< security::XAccessControlContext > const & x2 )
+ SAL_THROW( () )
+ : m_x1( x1 )
+ , m_x2( x2 )
+{
+ s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt );
+}
+//__________________________________________________________________________________________________
+acc_Combiner::~acc_Combiner()
+ SAL_THROW( () )
+{
+ s_moduleCount.modCnt.release( &s_moduleCount.modCnt );
+}
+//--------------------------------------------------------------------------------------------------
+inline Reference< security::XAccessControlContext > acc_Combiner::create(
+ Reference< security::XAccessControlContext > const & x1,
+ Reference< security::XAccessControlContext > const & x2 )
+ SAL_THROW( () )
+{
+ if (! x1.is())
+ return x2;
+ if (! x2.is())
+ return x1;
+ return new acc_Combiner( x1, x2 );
+}
+//__________________________________________________________________________________________________
+void acc_Combiner::checkPermission(
+ Any const & perm )
+ throw (RuntimeException)
+{
+ m_x1->checkPermission( perm );
+ m_x2->checkPermission( perm );
+}
+
+/** ac context doing permission checks on static user permissions
+*/
+class acc_UserPolicy
+ : public WeakImplHelper1< security::XAccessControlContext >
+{
+ Sequence< Any > m_permissions;
+
+public:
+ inline acc_UserPolicy(
+ Sequence< Any > permissions )
+ SAL_THROW( () )
+ : m_permissions( permissions )
+ {}
+
+ // XAccessControlContext impl
+ virtual void SAL_CALL checkPermission(
+ Any const & perm )
+ throw (RuntimeException);
+};
+//__________________________________________________________________________________________________
+void acc_UserPolicy::checkPermission(
+ Any const & perm )
+ throw (RuntimeException)
+{
+ checkStaticPermissions( m_permissions, perm );
+}
+
+/** current context overriding dynamic ac restriction
+*/
+class acc_CurrentContext
+ : public ImplHelper1< XCurrentContext >
+{
+ oslInterlockedCount m_refcount;
+
+ Reference< XCurrentContext > m_xDelegate;
+ Any m_restriction;
+
+public:
+ inline acc_CurrentContext(
+ Reference< XCurrentContext > const & xDelegate,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ SAL_THROW( () );
+ virtual ~acc_CurrentContext() SAL_THROW( () );
+
+ // XInterface impl
+ virtual void SAL_CALL acquire()
+ throw ();
+ virtual void SAL_CALL release()
+ throw ();
+
+ // XCurrentContext impl
+ virtual Any SAL_CALL getValueByName( OUString const & name )
+ throw (RuntimeException);
+};
+//__________________________________________________________________________________________________
+inline acc_CurrentContext::acc_CurrentContext(
+ Reference< XCurrentContext > const & xDelegate,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ SAL_THROW( () )
+ : m_refcount( 0 )
+ , m_xDelegate( xDelegate )
+{
+ s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt );
+
+ if (xRestriction.is())
+ {
+ m_restriction = makeAny( xRestriction );
+ }
+ // return empty any otherwise on getValueByName(), not null interface
+}
+//__________________________________________________________________________________________________
+acc_CurrentContext::~acc_CurrentContext()
+ SAL_THROW( () )
+{
+ s_moduleCount.modCnt.release( &s_moduleCount.modCnt );
+}
+//__________________________________________________________________________________________________
+void acc_CurrentContext::acquire()
+ throw ()
+{
+ ::osl_incrementInterlockedCount( &m_refcount );
+}
+//__________________________________________________________________________________________________
+void acc_CurrentContext::release()
+ throw ()
+{
+ if (! ::osl_decrementInterlockedCount( &m_refcount ))
+ {
+ delete this;
+ }
+}
+//__________________________________________________________________________________________________
+Any acc_CurrentContext::getValueByName( OUString const & name )
+ throw (RuntimeException)
+{
+ if (name.equals( s_acRestriction ))
+ {
+ return m_restriction;
+ }
+ else if (m_xDelegate.is())
+ {
+ return m_xDelegate->getValueByName( name );
+ }
+ else
+ {
+ return Any();
+ }
+}
+
+//##################################################################################################
+
+//--------------------------------------------------------------------------------------------------
+static inline void dispose( Reference< XInterface > const & x )
+ SAL_THROW( (RuntimeException) )
+{
+ Reference< lang::XComponent > xComp( x, UNO_QUERY );
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+}
+//--------------------------------------------------------------------------------------------------
+static inline Reference< security::XAccessControlContext > getDynamicRestriction(
+ Reference< XCurrentContext > const & xContext )
+ SAL_THROW( (RuntimeException) )
+{
+ Any acc( xContext->getValueByName( s_acRestriction ) );
+ if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass)
+ {
+ // avoid ref-counting
+ OUString const & typeName =
+ *reinterpret_cast< OUString const * >( &acc.pType->pTypeName );
+ if (typeName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.XAccessControlContext") ))
+ {
+ return Reference< security::XAccessControlContext >(
+ *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) );
+ }
+ else // try to query
+ {
+ return Reference< security::XAccessControlContext >::query(
+ *reinterpret_cast< XInterface ** const >( acc.pData ) );
+ }
+ }
+ return Reference< security::XAccessControlContext >();
+}
+//==================================================================================================
+class cc_reset
+{
+ void * m_cc;
+public:
+ inline cc_reset( void * cc ) SAL_THROW( () )
+ : m_cc( cc ) {}
+ inline ~cc_reset() SAL_THROW( () )
+ { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); }
+};
+//==================================================================================================
+class RecursionCheck : public ThreadData
+{
+ typedef hash_set< OUString, OUStringHash > t_set;
+ static void SAL_CALL destroyKeyData( void * );
+
+ inline t_set * getData() SAL_THROW( () )
+ { return reinterpret_cast< t_set * >( ThreadData::getData() ); }
+
+public:
+ inline RecursionCheck() SAL_THROW( () )
+ : ThreadData( (oslThreadKeyCallbackFunction)destroyKeyData )
+ {}
+
+ bool isRecurring( OUString const & userId ) SAL_THROW( () );
+ void mark( OUString const & userId ) SAL_THROW( () );
+ void unmark( OUString const & userId ) SAL_THROW( () );
+};
+//__________________________________________________________________________________________________
+void RecursionCheck::destroyKeyData( void * p )
+{
+ delete reinterpret_cast< t_set * >( p );
+}
+//__________________________________________________________________________________________________
+bool RecursionCheck::isRecurring( OUString const & userId ) SAL_THROW( () )
+{
+ t_set const * s = getData();
+ if (s)
+ {
+ t_set::const_iterator const iFind( s->find( userId ) );
+ return (iFind != s->end());
+ }
+ return false;
+}
+//__________________________________________________________________________________________________
+inline void RecursionCheck::mark( OUString const & userId ) SAL_THROW( () )
+{
+ t_set * s = getData();
+ if (s)
+ {
+ s->insert( userId );
+ }
+ else
+ {
+ t_set * s = new t_set();
+ s->insert( userId );
+ setData( s );
+ }
+}
+//__________________________________________________________________________________________________
+inline void RecursionCheck::unmark( OUString const & userId ) SAL_THROW( () )
+{
+ t_set * s = getData();
+ if (s)
+ {
+ s->erase( userId );
+ }
+}
+//==================================================================================================
+class RecursionMarkGuard
+{
+ RecursionCheck & m_rec_check;
+ OUString const & m_userId;
+
+public:
+ inline RecursionMarkGuard( RecursionCheck & rec_check, OUString const & userId ) SAL_THROW( () )
+ : m_rec_check( rec_check )
+ , m_userId( userId )
+ { m_rec_check.mark( m_userId ); }
+ inline ~RecursionMarkGuard() SAL_THROW( () )
+ { m_rec_check.unmark( m_userId ); }
+};
+
+//##################################################################################################
+
+struct MutexHolder
+{
+ Mutex m_mutex;
+};
+typedef WeakComponentImplHelper3<
+ security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper;
+
+//==================================================================================================
+class AccessController
+ : public MutexHolder
+ , public t_helper
+{
+ Reference< XComponentContext > m_xComponentContext;
+
+ RecursionCheck m_rec_check;
+
+ Reference< security::XPolicy > m_xPolicy;
+ Reference< security::XPolicy > const & getPolicy()
+ SAL_THROW( (RuntimeException) );
+
+ // mode
+ enum { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode;
+
+ // for single-user mode
+ Sequence< Any > m_singleUserPermissions;
+ OUString m_singleUserId;
+ bool m_singleUser_init;
+
+ typedef hash_map< OUString, Sequence< Any >, OUStringHash > t_user2permissions;
+ t_user2permissions m_user2permissions;
+
+ Sequence< Any > getUserPermissions(
+ Reference< XCurrentContext > const & xContext )
+ SAL_THROW( (RuntimeException) );
+
+protected:
+ virtual void SAL_CALL disposing();
+
+public:
+ AccessController( Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( () );
+ virtual ~AccessController()
+ SAL_THROW( () );
+
+ // XInitialization impl
+ virtual void SAL_CALL initialize(
+ Sequence< Any > const & arguments )
+ throw (Exception);
+
+ // XAccessController impl
+ virtual void SAL_CALL checkPermission(
+ Any const & perm )
+ throw (RuntimeException);
+ virtual Any SAL_CALL doRestricted(
+ Reference< security::XAction > const & xAction,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ throw (Exception);
+ virtual Any SAL_CALL doPrivileged(
+ Reference< security::XAction > const & xAction,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ throw (Exception);
+ virtual Reference< security::XAccessControlContext > SAL_CALL getContext()
+ throw (RuntimeException);
+
+ // XServiceInfo impl
+ virtual OUString SAL_CALL getImplementationName()
+ throw (RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
+ throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+};
+//__________________________________________________________________________________________________
+AccessController::AccessController( Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( () )
+ : t_helper( m_mutex )
+ , m_xComponentContext( xComponentContext )
+ , m_mode( ON ) // default
+ , m_singleUser_init( false )
+{
+ s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt );
+
+ OUString mode;
+ if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode)
+ {
+ if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("off") ))
+ {
+ m_mode = OFF;
+ }
+ else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("on") ))
+ {
+ m_mode = ON;
+ }
+ else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dynamic-only") ))
+ {
+ m_mode = DYNAMIC_ONLY;
+ }
+ else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-user") ))
+ {
+ m_xComponentContext->getValueByName(
+ OUSTR("/services/" SERVICE_NAME "/single-user-id") ) >>= m_singleUserId;
+ if (! m_singleUserId.getLength())
+ {
+ throw RuntimeException(
+ OUSTR("expected a user id in component context entry "
+ "\"/services/" SERVICE_NAME "/single-user-id\"!"),
+ (OWeakObject *)this );
+ }
+ m_mode = SINGLE_USER;
+ }
+ else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-default-user") ))
+ {
+ m_mode = SINGLE_DEFAULT_USER;
+ }
+ }
+}
+//__________________________________________________________________________________________________
+AccessController::~AccessController()
+ SAL_THROW( () )
+{
+ s_moduleCount.modCnt.release( &s_moduleCount.modCnt );
+}
+//__________________________________________________________________________________________________
+void AccessController::disposing()
+{
+ m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY?
+ m_xPolicy.clear();
+ m_xComponentContext.clear();
+}
+
+// XInitialization impl
+//__________________________________________________________________________________________________
+void AccessController::initialize(
+ Sequence< Any > const & arguments )
+ throw (Exception)
+{
+ // xxx todo: review for forking
+ // portal forking hack: re-initialize for another user-id
+ if (SINGLE_USER != m_mode) // only if in single-user mode
+ {
+ throw RuntimeException(
+ OUSTR("invalid call: ac must be in \"single-user\" mode!"), (OWeakObject *)this );
+ }
+ OUString userId;
+ arguments[ 0 ] >>= userId;
+ if (! userId.getLength())
+ {
+ throw RuntimeException(
+ OUSTR("expected a user-id as first argument!"), (OWeakObject *)this );
+ }
+ // assured that no sync is necessary: no check happens at this forking time
+ m_singleUserId = userId;
+ m_singleUser_init = false;
+}
+
+//__________________________________________________________________________________________________
+Reference< security::XPolicy > const & AccessController::getPolicy()
+ SAL_THROW( (RuntimeException) )
+{
+ // get policy singleton
+ if (! m_xPolicy.is())
+ {
+ Reference< security::XPolicy > xPolicy;
+ m_xComponentContext->getValueByName(
+ OUSTR("/singletons/com.sun.star.security.thePolicy") ) >>= xPolicy;
+ if (xPolicy.is())
+ {
+ MutexGuard guard( m_mutex );
+ if (! m_xPolicy.is())
+ {
+ m_xPolicy = xPolicy;
+ }
+ }
+ else
+ {
+ throw SecurityException(
+ OUSTR("cannot get policy singleton!"), (OWeakObject *)this );
+ }
+ }
+ return m_xPolicy;
+}
+//__________________________________________________________________________________________________
+Sequence< Any > AccessController::getUserPermissions(
+ Reference< XCurrentContext > const & xContext )
+ SAL_THROW( (RuntimeException) )
+{
+ // this is the only place calling the policy singleton taking care of recurring calls
+
+ 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;
+ {
+ 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();
+ }
+
+ // assign
+ MutexGuard guard( m_mutex );
+ if (! m_singleUser_init)
+ {
+ m_singleUserPermissions = singleUserPermissions;
+ m_singleUser_init = true;
+ }
+ }
+ return m_singleUserPermissions;
+ }
+ case ON:
+ {
+ OUString userId;
+ if (xContext.is())
+ {
+ xContext->getValueByName( OUSTR(USER_CREDS ".id") ) >>= userId;
+ }
+ if (! userId.getLength())
+ {
+ throw SecurityException(
+ OUSTR("cannot determine current user in multi-user ac!"), (OWeakObject *)this );
+ }
+
+ // 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;
+ }
+ }
+ }
+ else
+ {
+ return iFind->second;
+ }
+ }
+ default:
+ OSL_ENSURE( 0, "### this should never be called in this mode!" );
+ return Sequence< Any >();
+ }
+}
+
+// XAccessController impl
+//__________________________________________________________________________________________________
+void AccessController::checkPermission(
+ Any const & perm )
+ throw (RuntimeException)
+{
+ if (OFF == m_mode)
+ return;
+
+ // first dynamic check of ac contexts
+ Reference< XCurrentContext > xContext;
+ ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
+ if (xContext.is())
+ {
+ Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) );
+ if (xACC.is())
+ {
+ xACC->checkPermission( perm );
+ }
+ }
+
+ if (DYNAMIC_ONLY == m_mode)
+ return;
+
+ // then static check
+ checkStaticPermissions( getUserPermissions( xContext ), perm );
+}
+//__________________________________________________________________________________________________
+Any AccessController::doRestricted(
+ Reference< security::XAction > const & xAction,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ throw (Exception)
+{
+ if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
+ return xAction->run();
+
+ Reference< XCurrentContext > xContext;
+ ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
+
+ if (xRestriction.is())
+ {
+ // override restriction
+ Reference< security::XAccessControlContext > xOldRestr;
+ if (xContext.is())
+ {
+ xOldRestr = getDynamicRestriction( xContext );
+ }
+
+ Reference< XCurrentContext > xNewContext( new acc_CurrentContext(
+ xContext, acc_Combiner::create( xRestriction, xOldRestr ) ) );
+ ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
+
+ cc_reset reset( xContext.get() );
+ return xAction->run();
+ }
+ else
+ {
+ return xAction->run();
+ }
+}
+//__________________________________________________________________________________________________
+Any AccessController::doPrivileged(
+ Reference< security::XAction > const & xAction,
+ Reference< security::XAccessControlContext > const & xRestriction )
+ throw (Exception)
+{
+ if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
+ return xAction->run();
+
+ // override restriction
+ Reference< XCurrentContext > xContext;
+ ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
+
+ Reference< XCurrentContext > xNewContext( new acc_CurrentContext(
+ xContext, xRestriction ) );
+ ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
+
+ cc_reset reset( xContext.get() );
+ return xAction->run();
+}
+//__________________________________________________________________________________________________
+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
+
+ Reference< XCurrentContext > xContext;
+ ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
+
+ Reference< security::XAccessControlContext > xDynamic;
+ if (xContext.is())
+ {
+ xDynamic = getDynamicRestriction( xContext );
+ }
+
+ return acc_Combiner::create( xDynamic, new acc_UserPolicy( getUserPermissions( xContext ) ) );
+}
+
+// XServiceInfo impl
+//__________________________________________________________________________________________________
+OUString AccessController::getImplementationName()
+ throw (RuntimeException)
+{
+ return s_implName;
+}
+//__________________________________________________________________________________________________
+sal_Bool AccessController::supportsService( OUString const & serviceName )
+ throw (RuntimeException)
+{
+ OUString const * pNames = s_serviceNames.getConstArray();
+ for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; )
+ {
+ if (serviceName.equals( pNames[ nPos ] ))
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+//__________________________________________________________________________________________________
+Sequence< OUString > AccessController::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return s_serviceNames;
+}
+
+//##################################################################################################
+
+//--------------------------------------------------------------------------------------------------
+static Reference< XInterface > SAL_CALL ac_create(
+ Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( (Exception) )
+{
+ return (OWeakObject *)new AccessController( xComponentContext );
+}
+//--------------------------------------------------------------------------------------------------
+static Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW( () )
+{
+ return s_serviceNames;
+}
+//--------------------------------------------------------------------------------------------------
+static OUString ac_getImplementationName() SAL_THROW( () )
+{
+ return s_implName;
+}
+//--------------------------------------------------------------------------------------------------
+Reference< XInterface > SAL_CALL filepolicy_create(
+ Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( (Exception) );
+//--------------------------------------------------------------------------------------------------
+Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () );
+//--------------------------------------------------------------------------------------------------
+OUString filepolicy_getImplementationName() SAL_THROW( () );
+//--------------------------------------------------------------------------------------------------
+static struct ImplementationEntry s_entries [] =
+{
+ {
+ ac_create, ac_getImplementationName,
+ ac_getSupportedServiceNames, createSingleComponentFactory,
+ &s_moduleCount.modCnt, 0
+ },
+ {
+ filepolicy_create, filepolicy_getImplementationName,
+ filepolicy_getSupportedServiceNames, createSingleComponentFactory,
+ &s_moduleCount.modCnt, 0
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+}
+
+using namespace stoc_security;
+
+extern "C"
+{
+//==================================================================================================
+sal_Bool SAL_CALL component_canUnload( TimeValue * pTime )
+{
+ return s_moduleCount.canUnload( &s_moduleCount, pTime );
+}
+//==================================================================================================
+void SAL_CALL component_getImplementationEnvironment(
+ sal_Char const ** ppEnvTypeName, uno_Environment ** ppEnv )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+//==================================================================================================
+sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ return component_writeInfoHelper( pServiceManager, pRegistryKey, s_entries );
+}
+//==================================================================================================
+void * SAL_CALL component_getFactory(
+ sal_Char const * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, s_entries );
+}
+}
diff --git a/stoc/source/security/file_policy.cxx b/stoc/source/security/file_policy.cxx
new file mode 100644
index 000000000000..8a74248c1920
--- /dev/null
+++ b/stoc/source/security/file_policy.cxx
@@ -0,0 +1,627 @@
+/*************************************************************************
+ *
+ * $RCSfile: file_policy.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $
+ *
+ * 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 <hash_map>
+
+#include <osl/diagnose.h>
+#include <osl/file.h>
+#include <rtl/byteseq.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/implementationentry.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/security/XAccessController.hpp>
+#include <com/sun/star/security/XPolicy.hpp>
+#include <com/sun/star/security/AllPermission.hpp>
+#include <com/sun/star/security/RuntimePermission.hpp>
+#include <com/sun/star/io/FilePermission.hpp>
+#include <com/sun/star/connection/SocketPermission.hpp>
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+#define SERVICE_NAME "com.sun.star.security.Policy"
+#define IMPL_NAME "com.sun.star.security.comp.stoc.FilePolicy"
+
+
+using namespace ::std;
+using namespace ::osl;
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace stoc_security
+{
+
+// static stuff initialized when loading lib
+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;
+
+//##################################################################################################
+
+//--------------------------------------------------------------------------------------------------
+static inline void dispose( Reference< XInterface > const & x )
+ SAL_THROW( (RuntimeException) )
+{
+ Reference< lang::XComponent > xComp( x, UNO_QUERY );
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+}
+
+//##################################################################################################
+
+struct MutexHolder
+{
+ Mutex m_mutex;
+};
+typedef WeakComponentImplHelper2< security::XPolicy, lang::XServiceInfo > t_helper;
+
+//==================================================================================================
+class FilePolicy
+ : public MutexHolder
+ , public t_helper
+{
+ Reference< XComponentContext > m_xComponentContext;
+
+ Sequence< Any > m_defaultPermissions;
+ typedef hash_map< OUString, Sequence< Any >, OUStringHash > t_permissions;
+ t_permissions m_userPermissions;
+ bool m_init;
+
+protected:
+ virtual void SAL_CALL disposing();
+
+public:
+ FilePolicy( Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( () );
+ virtual ~FilePolicy()
+ SAL_THROW( () );
+
+ // XPolicy impl
+ virtual Sequence< Any > SAL_CALL getPermissions(
+ OUString const & userId )
+ throw (RuntimeException);
+ virtual Sequence< Any > SAL_CALL getDefaultPermissions()
+ throw (RuntimeException);
+ virtual void SAL_CALL refresh()
+ throw (RuntimeException);
+
+ // XServiceInfo impl
+ virtual OUString SAL_CALL getImplementationName()
+ throw (RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
+ throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+};
+//__________________________________________________________________________________________________
+FilePolicy::FilePolicy( Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( () )
+ : t_helper( m_mutex )
+ , m_xComponentContext( xComponentContext )
+ , m_init( false )
+{
+ s_moduleCount.modCnt.acquire( &s_moduleCount.modCnt );
+}
+//__________________________________________________________________________________________________
+FilePolicy::~FilePolicy()
+ SAL_THROW( () )
+{
+ s_moduleCount.modCnt.release( &s_moduleCount.modCnt );
+}
+//__________________________________________________________________________________________________
+void FilePolicy::disposing()
+{
+ m_userPermissions.clear();
+ m_defaultPermissions = Sequence< Any >();
+ m_xComponentContext.clear();
+}
+
+//__________________________________________________________________________________________________
+Sequence< Any > FilePolicy::getPermissions(
+ OUString const & userId )
+ throw (RuntimeException)
+{
+ if (! m_init)
+ {
+ refresh();
+ m_init = true;
+ }
+
+ MutexGuard guard( m_mutex );
+ t_permissions::const_iterator const iFind( m_userPermissions.find( userId ) );
+ if (m_userPermissions.end() == iFind)
+ {
+ return Sequence< Any >();
+ }
+ else
+ {
+ return iFind->second;
+ }
+}
+//__________________________________________________________________________________________________
+Sequence< Any > FilePolicy::getDefaultPermissions()
+ throw (RuntimeException)
+{
+ if (! m_init)
+ {
+ refresh();
+ m_init = true;
+ }
+
+ MutexGuard guard( m_mutex );
+ return m_defaultPermissions;
+}
+
+//==================================================================================================
+class PolicyReader
+{
+ OUString m_fileName;
+ oslFileHandle m_file;
+
+ sal_Int32 m_linepos;
+ ByteSequence m_line;
+ sal_Int32 m_pos;
+ sal_Unicode m_back;
+
+ sal_Unicode get()
+ SAL_THROW( (RuntimeException) );
+ inline void back( sal_Unicode c ) SAL_THROW( () )
+ { m_back = c; }
+
+ inline bool isWhiteSpace( sal_Unicode c ) SAL_THROW( () )
+ { return (' ' == c || '\t' == c || '\n' == c); }
+ void skipWhiteSpace()
+ SAL_THROW( (RuntimeException) );
+
+ inline bool isCharToken( sal_Unicode c ) SAL_THROW( () )
+ { return (';' == c || ',' == c || '{' == c || '}' == c); }
+
+public:
+ PolicyReader( OUString const & file )
+ SAL_THROW( (RuntimeException) );
+ ~PolicyReader()
+ SAL_THROW( () );
+
+ void error( OUString const & msg )
+ SAL_THROW( (RuntimeException) );
+
+ OUString getToken()
+ SAL_THROW( (RuntimeException) );
+ OUString assureToken()
+ SAL_THROW( (RuntimeException) );
+ OUString getQuotedToken()
+ SAL_THROW( (RuntimeException) );
+ OUString assureQuotedToken()
+ SAL_THROW( (RuntimeException) );
+ void assureToken( sal_Unicode token )
+ SAL_THROW( (RuntimeException) );
+};
+//__________________________________________________________________________________________________
+void PolicyReader::assureToken( sal_Unicode token )
+ SAL_THROW( (RuntimeException) )
+{
+ skipWhiteSpace();
+ sal_Unicode c = get();
+ if (c == token)
+ return;
+ OUStringBuffer buf( 16 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("expected >") );
+ buf.append( c );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<!") );
+ error( buf.makeStringAndClear() );
+}
+//__________________________________________________________________________________________________
+OUString PolicyReader::assureQuotedToken()
+ SAL_THROW( (RuntimeException) )
+{
+ OUString token( getQuotedToken() );
+ if (! token.getLength())
+ error( OUSTR("unexpected end of file!") );
+ return token;
+}
+//__________________________________________________________________________________________________
+OUString PolicyReader::getQuotedToken()
+ SAL_THROW( (RuntimeException) )
+{
+ skipWhiteSpace();
+ OUStringBuffer buf( 32 );
+ sal_Unicode c = get();
+ if ('\"' != c)
+ error( OUSTR("expected quoting >\"< character!") );
+ c = get();
+ while ('\0' != c && '\"' != c)
+ {
+ buf.append( c );
+ c = get();
+ }
+ return buf.makeStringAndClear();
+}
+//__________________________________________________________________________________________________
+OUString PolicyReader::assureToken()
+ SAL_THROW( (RuntimeException) )
+{
+ OUString token( getToken() );
+ if (! token.getLength())
+ error( OUSTR("unexpected end of file!") );
+ return token;
+}
+//__________________________________________________________________________________________________
+OUString PolicyReader::getToken()
+ SAL_THROW( (RuntimeException) )
+{
+ skipWhiteSpace();
+ sal_Unicode c = get();
+ if (isCharToken( c ))
+ return OUString( &c, 1 );
+ OUStringBuffer buf( 32 );
+ while ('\0' != c && !isCharToken( c ) && !isWhiteSpace( c ))
+ {
+ buf.append( c );
+ c = get();
+ }
+ back( c );
+ return buf.makeStringAndClear();
+}
+//__________________________________________________________________________________________________
+void PolicyReader::skipWhiteSpace()
+ SAL_THROW( (RuntimeException) )
+{
+ sal_Unicode c = get();
+ while (isWhiteSpace( c ))
+ {
+ c = get();
+ }
+ back( c );
+}
+//__________________________________________________________________________________________________
+sal_Unicode PolicyReader::get()
+ SAL_THROW( (RuntimeException) )
+{
+ if ('\0' != m_back) // one char push back possible
+ {
+ sal_Unicode c = m_back;
+ m_back = '\0';
+ return c;
+ }
+ else if (m_pos == m_line.getLength()) // provide newline as whitespace
+ {
+ ++m_pos;
+ return '\n';
+ }
+ else if (m_pos > m_line.getLength()) // read new line
+ {
+ sal_Bool eof;
+ oslFileError rc = ::osl_isEndOfFile( m_file, &eof );
+ if (osl_File_E_None != rc)
+ error( OUSTR("checking eof failed!") );
+ if (eof)
+ return '\0';
+
+ rc = ::osl_readLine( m_file, reinterpret_cast< sal_Sequence ** >( &m_line ) );
+ if (osl_File_E_None != rc)
+ error( OUSTR("read line failed!") );
+ ++m_linepos;
+ if (! m_line.getLength()) // empty line read
+ {
+ m_pos = 1; // read new line next time
+ return '\n';
+ }
+ m_pos = 0;
+ }
+ return (m_line.getConstArray()[ m_pos++ ]);
+}
+//__________________________________________________________________________________________________
+void PolicyReader::error( OUString const & msg )
+ SAL_THROW( (RuntimeException) )
+{
+ OUStringBuffer buf( 32 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("error processing file \"") );
+ buf.append( m_fileName );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" [line ") );
+ buf.append( m_linepos );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", column ") );
+ buf.append( m_pos );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
+ buf.append( msg );
+ throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
+}
+//__________________________________________________________________________________________________
+PolicyReader::PolicyReader( OUString const & fileName )
+ SAL_THROW( (RuntimeException) )
+ : m_fileName( fileName )
+ , m_linepos( 0 )
+ , m_pos( 1 ) // force readline
+ , m_back( '\0' )
+{
+ if (osl_File_E_None != ::osl_openFile( m_fileName.pData, &m_file, osl_File_OpenFlag_Read ))
+ {
+ OUStringBuffer buf( 32 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot open file \"") );
+ buf.append( m_fileName );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
+ throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
+ }
+}
+//__________________________________________________________________________________________________
+PolicyReader::~PolicyReader()
+ SAL_THROW( () )
+{
+ oslFileError rc = ::osl_closeFile( m_file );
+ 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");
+static OUString s_openBrace = OUSTR("{");
+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_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission");
+static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission");
+
+//__________________________________________________________________________________________________
+void FilePolicy::refresh()
+ throw (RuntimeException)
+{
+ // read out file
+ OUString fileName;
+ m_xComponentContext->getValueByName(
+ OUSTR("/implementations/" IMPL_NAME "/file-name") ) >>= fileName;
+ if (! fileName.getLength())
+ {
+ throw RuntimeException(
+ OUSTR("name of policy file unknown!"),
+ (OWeakObject *)this );
+ }
+
+ PolicyReader reader( fileName );
+
+ // fill these two
+ Sequence< Any > defaultPermissions;
+ t_permissions userPermissions;
+
+ OUString token( reader.getToken() );
+ while (token.getLength())
+ {
+ if (! token.equals( s_grant ))
+ reader.error( OUSTR("expected >grant< token!") );
+ OUString userId;
+ token = reader.assureToken();
+ if (token.equals( s_user )) // next token is user-id
+ {
+ userId = reader.assureQuotedToken();
+ token = reader.assureToken();
+ }
+ if (! token.equals( s_openBrace ))
+ reader.error( OUSTR("expected opening brace >{<!") );
+ token = reader.assureToken();
+ // permissions list
+ while (! token.equals( s_closingBrace ))
+ {
+ if (! token.equals( s_permission ))
+ reader.error( OUSTR("expected >permission< or closing brace >}<!") );
+
+ token = reader.assureToken(); // permission type
+ Any perm;
+ if (token.equals( s_filePermission )) // FilePermission
+ {
+ OUString url( reader.assureQuotedToken() );
+ reader.assureToken( ',' );
+ OUString actions( reader.assureQuotedToken() );
+ perm <<= io::FilePermission( url, actions );
+ }
+ else if (token.equals( s_socketPermission )) // SocketPermission
+ {
+ OUString host( reader.assureQuotedToken() );
+ reader.assureToken( ',' );
+ OUString actions( reader.assureQuotedToken() );
+ perm <<= connection::SocketPermission( host, actions );
+ }
+ else if (token.equals( s_runtimePermission )) // RuntimePermission
+ {
+ OUString name( reader.assureQuotedToken() );
+ perm <<= security::RuntimePermission( name );
+ }
+ else if (token.equals( s_allPermission )) // AllPermission
+ {
+ perm <<= security::AllPermission();
+ }
+ else
+ {
+ reader.error( OUSTR("expected permission type!") );
+ }
+
+ reader.assureToken( ';' );
+
+ // insert
+ if (userId.getLength())
+ {
+ Sequence< Any > perms( userPermissions[ userId ] );
+ sal_Int32 len = perms.getLength();
+ perms.realloc( len +1 );
+ perms[ len ] = perm;
+ userPermissions[ userId ] = perms;
+ }
+ else
+ {
+ sal_Int32 len = defaultPermissions.getLength();
+ defaultPermissions.realloc( len +1 );
+ defaultPermissions[ len ] = perm;
+ }
+
+ token = reader.assureToken(); // next permissions token
+ }
+
+ reader.assureToken( ';' ); // semi
+ 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;
+ }
+}
+
+//__________________________________________________________________________________________________
+OUString FilePolicy::getImplementationName()
+ throw (RuntimeException)
+{
+ return s_implName;
+}
+//__________________________________________________________________________________________________
+sal_Bool FilePolicy::supportsService( OUString const & serviceName )
+ throw (RuntimeException)
+{
+ OUString const * pNames = s_serviceNames.getConstArray();
+ for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; )
+ {
+ if (serviceName.equals( pNames[ nPos ] ))
+ {
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+//__________________________________________________________________________________________________
+Sequence< OUString > FilePolicy::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return s_serviceNames;
+}
+
+//##################################################################################################
+
+//--------------------------------------------------------------------------------------------------
+Reference< XInterface > SAL_CALL filepolicy_create(
+ Reference< XComponentContext > const & xComponentContext )
+ SAL_THROW( (Exception) )
+{
+ return (OWeakObject *)new FilePolicy( xComponentContext );
+}
+//--------------------------------------------------------------------------------------------------
+Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () )
+{
+ return s_serviceNames;
+}
+//--------------------------------------------------------------------------------------------------
+OUString filepolicy_getImplementationName() SAL_THROW( () )
+{
+ return s_implName;
+}
+
+}
diff --git a/stoc/source/security/makefile.mk b/stoc/source/security/makefile.mk
new file mode 100644
index 000000000000..27495fb16b81
--- /dev/null
+++ b/stoc/source/security/makefile.mk
@@ -0,0 +1,108 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1 $
+#
+# last change: $Author: dbo $ $Date: 2002-01-25 09:29:35 $
+#
+# 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): _______________________________________
+#
+#
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=stoc
+TARGET=sec
+USE_DEFFILE=TRUE
+NO_BSYMBOLIC=TRUE
+ENABLE_EXCEPTIONS=TRUE
+BOOTSTRAP_SERVICE=TRUE
+COMP1TYPELIST=$(TARGET)
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# ------------------------------------------------------------------
+
+.INCLUDE : ..$/cppumaker.mk
+
+SLOFILES= \
+ $(SLO)$/access_controller.obj \
+ $(SLO)$/file_policy.obj
+
+SHL1TARGET=$(TARGET)
+
+SHL1STDLIBS= \
+ $(CPPULIB) \
+ $(CPPUHELPERLIB) \
+ $(SALLIB)
+SHL1VERSIONMAP=$(TARGET).map
+
+SHL1DEPN=
+SHL1IMPLIB=i$(TARGET)
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+
+.IF "$(debug)" != ""
+# msvc++: no inlining for debugging
+.IF "$(COM)" == "MSC"
+CFLAGS += /Ob0
+.ENDIF
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+