1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/diagnose.h>
23 #include <rtl/byteseq.hxx>
24 #include <rtl/ref.hxx>
25 #include <rtl/ustrbuf.hxx>
27 #include <cppuhelper/access_control.hxx>
28 #include <cppuhelper/compbase.hxx>
29 #include <cppuhelper/implementationentry.hxx>
30 #include <cppuhelper/supportsservice.hxx>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/security/XAccessController.hpp>
34 #include <com/sun/star/security/XPolicy.hpp>
35 #include <com/sun/star/security/AllPermission.hpp>
36 #include <com/sun/star/security/RuntimePermission.hpp>
37 #include <com/sun/star/io/FilePermission.hpp>
38 #include <com/sun/star/connection/SocketPermission.hpp>
40 #include <unordered_map>
42 #define IMPL_NAME "com.sun.star.security.comp.stoc.FilePolicy"
44 using namespace ::osl
;
45 using namespace ::cppu
;
46 using namespace ::com::sun::star
;
47 using namespace css::uno
;
55 typedef WeakComponentImplHelper
< security::XPolicy
, lang::XServiceInfo
> t_helper
;
62 Reference
< XComponentContext
> m_xComponentContext
;
65 Sequence
< Any
> m_defaultPermissions
;
66 typedef std::unordered_map
< OUString
, Sequence
< Any
>, OUStringHash
> t_permissions
;
67 t_permissions m_userPermissions
;
71 virtual void SAL_CALL
disposing() override
;
74 explicit FilePolicy( Reference
< XComponentContext
> const & xComponentContext
);
77 virtual Sequence
< Any
> SAL_CALL
getPermissions(
78 OUString
const & userId
) override
;
79 virtual Sequence
< Any
> SAL_CALL
getDefaultPermissions() override
;
80 virtual void SAL_CALL
refresh() override
;
83 virtual OUString SAL_CALL
getImplementationName() override
;
84 virtual sal_Bool SAL_CALL
supportsService( OUString
const & serviceName
) override
;
85 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
88 FilePolicy::FilePolicy( Reference
< XComponentContext
> const & xComponentContext
)
90 , m_xComponentContext( xComponentContext
)
91 , m_ac( xComponentContext
)
95 void FilePolicy::disposing()
97 m_userPermissions
.clear();
98 m_defaultPermissions
= Sequence
< Any
>();
99 m_xComponentContext
.clear();
103 Sequence
< Any
> FilePolicy::getPermissions(
104 OUString
const & userId
)
112 MutexGuard
guard( m_mutex
);
113 t_permissions::iterator
iFind( m_userPermissions
.find( userId
) );
114 if (m_userPermissions
.end() == iFind
)
116 return Sequence
< Any
>();
120 return iFind
->second
;
124 Sequence
< Any
> FilePolicy::getDefaultPermissions()
132 MutexGuard
guard( m_mutex
);
133 return m_defaultPermissions
;
140 oslFileHandle m_file
;
143 rtl::ByteSequence m_line
;
148 void back( sal_Unicode c
)
151 static bool isWhiteSpace( sal_Unicode c
)
152 { return (' ' == c
|| '\t' == c
|| '\n' == c
|| '\r' == c
); }
153 void skipWhiteSpace();
155 static bool isCharToken( sal_Unicode c
)
156 { return (';' == c
|| ',' == c
|| '{' == c
|| '}' == c
); }
159 PolicyReader( OUString
const & file
, AccessControl
& ac
);
162 void error( OUString
const & msg
);
165 OUString
assureToken();
166 OUString
getQuotedToken();
167 OUString
assureQuotedToken();
168 void assureToken( sal_Unicode token
);
171 void PolicyReader::assureToken( sal_Unicode token
)
174 sal_Unicode c
= get();
177 OUStringBuffer
buf( 16 );
178 buf
.append( "expected >" );
181 error( buf
.makeStringAndClear() );
184 OUString
PolicyReader::assureQuotedToken()
186 OUString
token( getQuotedToken() );
188 error( "unexpected end of file!" );
192 OUString
PolicyReader::getQuotedToken()
195 OUStringBuffer
buf( 32 );
196 sal_Unicode c
= get();
198 error( "expected quoting >\"< character!" );
200 while ('\0' != c
&& '\"' != c
)
205 return buf
.makeStringAndClear();
208 OUString
PolicyReader::assureToken()
210 OUString
token( getToken() );
211 if ( token
.isEmpty())
212 error( "unexpected end of file!" );
216 OUString
PolicyReader::getToken()
219 sal_Unicode c
= get();
220 if (isCharToken( c
))
221 return OUString( &c
, 1 );
222 OUStringBuffer
buf( 32 );
223 while ('\0' != c
&& !isCharToken( c
) && !isWhiteSpace( c
))
229 return buf
.makeStringAndClear();
232 void PolicyReader::skipWhiteSpace()
239 while (isWhiteSpace( c
)); // seeking next non-whitespace char
241 if ('/' == c
) // C/C++ like comment
244 if ('/' == c
) // C++ like comment
250 while ('\n' != c
&& '\0' != c
); // seek eol/eof
251 skipWhiteSpace(); // cont skip on next line
253 else if ('*' == c
) // C like comment
262 fini
= ('/' == c
|| '\0' == c
);
270 skipWhiteSpace(); // cont skip on next line
274 error( "expected C/C++ like comment!" );
277 else if ('#' == c
) // script like comment
283 while ('\n' != c
&& '\0' != c
); // seek eol/eof
284 skipWhiteSpace(); // cont skip on next line
287 else // is token char
293 sal_Unicode
PolicyReader::get()
295 if ('\0' != m_back
) // one char push back possible
297 sal_Unicode c
= m_back
;
301 else if (m_pos
== m_line
.getLength()) // provide newline as whitespace
306 else if (m_pos
> m_line
.getLength()) // read new line
309 oslFileError rc
= ::osl_isEndOfFile( m_file
, &eof
);
310 if (osl_File_E_None
!= rc
)
311 error( "checking eof failed!" );
315 rc
= ::osl_readLine( m_file
, reinterpret_cast< sal_Sequence
** >( &m_line
) );
316 if (osl_File_E_None
!= rc
)
317 error( "read line failed!" );
319 if (! m_line
.getLength()) // empty line read
321 m_pos
= 1; // read new line next time
326 return (m_line
.getConstArray()[ m_pos
++ ]);
329 void PolicyReader::error( OUString
const & msg
)
331 throw RuntimeException(
332 "error processing file \"" + m_fileName
+
333 "\" [line " + OUString::number(m_linepos
) +
334 ", column " + OUString::number(m_pos
) +
338 PolicyReader::PolicyReader( OUString
const & fileName
, AccessControl
& ac
)
339 : m_fileName( fileName
)
341 , m_pos( 1 ) // force readline
344 ac
.checkFilePermission( m_fileName
, "read" );
345 if (osl_File_E_None
!= ::osl_openFile( m_fileName
.pData
, &m_file
, osl_File_OpenFlag_Read
))
347 throw RuntimeException( "cannot open file \"" + m_fileName
+ "\"!" );
351 PolicyReader::~PolicyReader()
353 if ( ::osl_closeFile( m_file
) != osl_File_E_None
) {
358 #define s_grant "grant"
359 #define s_user "user"
360 #define s_permission "permission"
361 #define s_openBrace "{"
362 #define s_closingBrace "}"
364 #define s_filePermission "com.sun.star.io.FilePermission"
365 #define s_socketPermission "com.sun.star.connection.SocketPermission"
366 #define s_runtimePermission "com.sun.star.security.RuntimePermission"
367 #define s_allPermission "com.sun.star.security.AllPermission"
370 void FilePolicy::refresh()
372 // read out file (the .../file-name value had originally been set in
373 // cppu::add_access_control_entries (cppuhelper/source/servicefactory.cxx)
374 // depending on various UNO_AC* bootstrap variables that are no longer
375 // supported, so this is effectively dead code):
377 m_xComponentContext
->getValueByName(
378 "/implementations/" IMPL_NAME
"/file-name" ) >>= fileName
;
379 if ( fileName
.isEmpty() )
381 throw RuntimeException(
382 "name of policy file unknown!",
383 static_cast<OWeakObject
*>(this) );
386 PolicyReader
reader( fileName
, m_ac
);
389 Sequence
< Any
> defaultPermissions
;
390 t_permissions userPermissions
;
392 OUString
token( reader
.getToken() );
393 while (!token
.isEmpty())
395 if ( token
!= s_grant
)
396 reader
.error( "expected >grant< token!" );
398 token
= reader
.assureToken();
399 if ( token
== s_user
) // next token is user-id
401 userId
= reader
.assureQuotedToken();
402 token
= reader
.assureToken();
404 if ( token
!= s_openBrace
)
405 reader
.error( "expected opening brace >{<!" );
406 token
= reader
.assureToken();
408 while ( token
!= s_closingBrace
)
410 if ( token
!= s_permission
)
411 reader
.error( "expected >permission< or closing brace >}<!" );
413 token
= reader
.assureToken(); // permission type
415 if ( token
== s_filePermission
) // FilePermission
417 OUString
url( reader
.assureQuotedToken() );
418 reader
.assureToken( ',' );
419 OUString
actions( reader
.assureQuotedToken() );
420 perm
<<= io::FilePermission( url
, actions
);
422 else if ( token
== s_socketPermission
) // SocketPermission
424 OUString
host( reader
.assureQuotedToken() );
425 reader
.assureToken( ',' );
426 OUString
actions( reader
.assureQuotedToken() );
427 perm
<<= connection::SocketPermission( host
, actions
);
429 else if ( token
== s_runtimePermission
) // RuntimePermission
431 OUString
name( reader
.assureQuotedToken() );
432 perm
<<= security::RuntimePermission( name
);
434 else if ( token
== s_allPermission
) // AllPermission
436 perm
<<= security::AllPermission();
440 reader
.error( "expected permission type!" );
443 reader
.assureToken( ';' );
446 if (!userId
.isEmpty())
448 Sequence
< Any
> perms( userPermissions
[ userId
] );
449 sal_Int32 len
= perms
.getLength();
450 perms
.realloc( len
+1 );
452 userPermissions
[ userId
] = perms
;
456 sal_Int32 len
= defaultPermissions
.getLength();
457 defaultPermissions
.realloc( len
+1 );
458 defaultPermissions
[ len
] = perm
;
461 token
= reader
.assureToken(); // next permissions token
464 reader
.assureToken( ';' ); // semi
465 token
= reader
.getToken(); // next grant token
469 MutexGuard
guard( m_mutex
);
470 m_defaultPermissions
= defaultPermissions
;
471 m_userPermissions
= userPermissions
;
475 OUString
FilePolicy::getImplementationName()
477 return OUString(IMPL_NAME
);
480 sal_Bool
FilePolicy::supportsService( OUString
const & serviceName
)
482 return cppu::supportsService(this, serviceName
);
485 Sequence
< OUString
> FilePolicy::getSupportedServiceNames()
487 Sequence
<OUString
> aSNS
{ "com.sun.star.security.Policy" };
493 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
494 com_sun_star_security_comp_stoc_FilePolicy_get_implementation(
495 css::uno::XComponentContext
*context
,
496 css::uno::Sequence
<css::uno::Any
> const &)
498 return cppu::acquire(new FilePolicy(context
));
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */