diff options
Diffstat (limited to 'stoc/source/security/file_policy.cxx')
-rw-r--r-- | stoc/source/security/file_policy.cxx | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/stoc/source/security/file_policy.cxx b/stoc/source/security/file_policy.cxx new file mode 100644 index 000000000000..e9eb46ac6344 --- /dev/null +++ b/stoc/source/security/file_policy.cxx @@ -0,0 +1,604 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#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/access_control.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 ::osl; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +extern ::rtl_StandardModuleCount g_moduleCount; + +namespace stoc_sec +{ +// 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 ); +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +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; + AccessControl m_ac; + + Sequence< Any > m_defaultPermissions; + typedef std::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_ac( xComponentContext ) + , m_init( false ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +FilePolicy::~FilePolicy() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_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::iterator 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 || '\r' == c); } + void skipWhiteSpace() + SAL_THROW( (RuntimeException) ); + + inline bool isCharToken( sal_Unicode c ) SAL_THROW( () ) + { return (';' == c || ',' == c || '{' == c || '}' == c); } + +public: + PolicyReader( OUString const & file, AccessControl & ac ) + 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; + do + { + c = get(); + } + while (isWhiteSpace( c )); // seeking next non-whitespace char + + if ('/' == c) // C/C++ like comment + { + c = get(); + if ('/' == c) // C++ like comment + { + do + { + c = get(); + } + while ('\n' != c && '\0' != c); // seek eol/eof + skipWhiteSpace(); // cont skip on next line + } + else if ('*' == c) // C like comment + { + bool fini = true; + do + { + c = get(); + if ('*' == c) + { + c = get(); + fini = ('/' == c || '\0' == c); + } + else + { + fini = ('\0' == c); + } + } + while (! fini); + skipWhiteSpace(); // cont skip on next line + } + else + { + error( OUSTR("expected C/C++ like comment!") ); + } + } + else if ('#' == c) // script like comment + { + do + { + c = get(); + } + while ('\n' != c && '\0' != c); // seek eol/eof + skipWhiteSpace(); // cont skip on next line + } + + else // is token char + { + 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, AccessControl & ac ) + SAL_THROW( (RuntimeException) ) + : m_fileName( fileName ) + , m_linepos( 0 ) + , m_pos( 1 ) // force readline + , m_back( '\0' ) +{ + ac.checkFilePermission( m_fileName, OUSTR("read") ); + 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( () ) +{ + if ( ::osl_closeFile( m_file ) != osl_File_E_None ) { + OSL_ASSERT( false ); + } +} + +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, m_ac ); + + // 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 + } + + // 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; +} +} +//################################################################################################## +namespace stoc_bootstrap +{ +//-------------------------------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL filepolicy_create( + Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (Exception) ) +{ + return (OWeakObject *)new stoc_sec::FilePolicy( xComponentContext ); +} +//-------------------------------------------------------------------------------------------------- +Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ) +{ + return stoc_sec::s_serviceNames; +} +//-------------------------------------------------------------------------------------------------- +OUString filepolicy_getImplementationName() SAL_THROW( () ) +{ + return stoc_sec::s_implName; +} +} |