/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_stoc.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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("\"< 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_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 >{permission< or closing brace >} 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; } }