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/ustrbuf.hxx>
26 #include <cppuhelper/access_control.hxx>
27 #include <cppuhelper/basemutex.hxx>
28 #include <cppuhelper/compbase.hxx>
29 #include <cppuhelper/supportsservice.hxx>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/security/XPolicy.hpp>
33 #include <com/sun/star/security/AllPermission.hpp>
34 #include <com/sun/star/security/RuntimePermission.hpp>
35 #include <com/sun/star/io/FilePermission.hpp>
36 #include <com/sun/star/connection/SocketPermission.hpp>
37 #include <com/sun/star/uno/XComponentContext.hpp>
39 #include <string_view>
40 #include <unordered_map>
43 constexpr OUStringLiteral IMPL_NAME
= u
"com.sun.star.security.comp.stoc.FilePolicy";
45 using namespace ::osl
;
46 using namespace ::cppu
;
47 using namespace ::com::sun::star
;
48 using namespace css::uno
;
52 typedef WeakComponentImplHelper
< security::XPolicy
, lang::XServiceInfo
> t_helper
;
56 : public cppu::BaseMutex
59 Reference
< XComponentContext
> m_xComponentContext
;
62 Sequence
< Any
> m_defaultPermissions
;
63 typedef std::unordered_map
< OUString
, Sequence
< Any
> > t_permissions
;
64 t_permissions m_userPermissions
;
68 virtual void SAL_CALL
disposing() override
;
71 explicit FilePolicy( Reference
< XComponentContext
> const & xComponentContext
);
74 virtual Sequence
< Any
> SAL_CALL
getPermissions(
75 OUString
const & userId
) override
;
76 virtual Sequence
< Any
> SAL_CALL
getDefaultPermissions() override
;
77 virtual void SAL_CALL
refresh() override
;
80 virtual OUString SAL_CALL
getImplementationName() override
;
81 virtual sal_Bool SAL_CALL
supportsService( OUString
const & serviceName
) override
;
82 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
85 FilePolicy::FilePolicy( Reference
< XComponentContext
> const & xComponentContext
)
86 : t_helper( m_aMutex
)
87 , m_xComponentContext( xComponentContext
)
88 , m_ac( xComponentContext
)
92 void FilePolicy::disposing()
94 m_userPermissions
.clear();
95 m_defaultPermissions
= Sequence
< Any
>();
96 m_xComponentContext
.clear();
100 Sequence
< Any
> FilePolicy::getPermissions(
101 OUString
const & userId
)
109 MutexGuard
guard( m_aMutex
);
110 t_permissions::iterator
iFind( m_userPermissions
.find( userId
) );
111 if (m_userPermissions
.end() == iFind
)
113 return Sequence
< Any
>();
117 return iFind
->second
;
121 Sequence
< Any
> FilePolicy::getDefaultPermissions()
129 MutexGuard
guard( m_aMutex
);
130 return m_defaultPermissions
;
137 oslFileHandle m_file
;
140 rtl::ByteSequence m_line
;
145 void back( sal_Unicode c
)
148 static bool isWhiteSpace( sal_Unicode c
)
149 { return (' ' == c
|| '\t' == c
|| '\n' == c
|| '\r' == c
); }
150 void skipWhiteSpace();
152 static bool isCharToken( sal_Unicode c
)
153 { return (';' == c
|| ',' == c
|| '{' == c
|| '}' == c
); }
156 PolicyReader( OUString file
, AccessControl
& ac
);
159 void error( std::u16string_view msg
);
162 OUString
assureToken();
163 OUString
getQuotedToken();
164 OUString
assureQuotedToken();
165 void assureToken( sal_Unicode token
);
168 void PolicyReader::assureToken( sal_Unicode token
)
171 sal_Unicode c
= get();
174 OUString msg
= "expected >" + OUStringChar(c
) + "<!";
178 OUString
PolicyReader::assureQuotedToken()
180 OUString
token( getQuotedToken() );
182 error( u
"unexpected end of file!" );
186 OUString
PolicyReader::getQuotedToken()
189 OUStringBuffer
buf( 32 );
190 sal_Unicode c
= get();
192 error( u
"expected quoting >\"< character!" );
194 while ('\0' != c
&& '\"' != c
)
199 return buf
.makeStringAndClear();
202 OUString
PolicyReader::assureToken()
204 OUString
token( getToken() );
205 if ( token
.isEmpty())
206 error( u
"unexpected end of file!" );
210 OUString
PolicyReader::getToken()
213 sal_Unicode c
= get();
214 if (isCharToken( c
))
215 return OUString( &c
, 1 );
216 OUStringBuffer
buf( 32 );
217 while ('\0' != c
&& !isCharToken( c
) && !isWhiteSpace( c
))
223 return buf
.makeStringAndClear();
226 void PolicyReader::skipWhiteSpace()
233 while (isWhiteSpace( c
)); // seeking next non-whitespace char
235 if ('/' == c
) // C/C++ like comment
238 if ('/' == c
) // C++ like comment
244 while ('\n' != c
&& '\0' != c
); // seek eol/eof
245 skipWhiteSpace(); // cont skip on next line
247 else if ('*' == c
) // C like comment
256 fini
= ('/' == c
|| '\0' == c
);
264 skipWhiteSpace(); // cont skip on next line
268 error( u
"expected C/C++ like comment!" );
271 else if ('#' == c
) // script like comment
277 while ('\n' != c
&& '\0' != c
); // seek eol/eof
278 skipWhiteSpace(); // cont skip on next line
281 else // is token char
287 sal_Unicode
PolicyReader::get()
289 if ('\0' != m_back
) // one char push back possible
291 sal_Unicode c
= m_back
;
295 else if (m_pos
== m_line
.getLength()) // provide newline as whitespace
300 else if (m_pos
> m_line
.getLength()) // read new line
303 oslFileError rc
= ::osl_isEndOfFile( m_file
, &eof
);
304 if (osl_File_E_None
!= rc
)
305 error( u
"checking eof failed!" );
309 rc
= ::osl_readLine( m_file
, reinterpret_cast< sal_Sequence
** >( &m_line
) );
310 if (osl_File_E_None
!= rc
)
311 error( u
"read line failed!" );
313 if (! m_line
.getLength()) // empty line read
315 m_pos
= 1; // read new line next time
320 return (m_line
.getConstArray()[ m_pos
++ ]);
323 void PolicyReader::error( std::u16string_view msg
)
325 throw RuntimeException(
326 "error processing file \"" + m_fileName
+
327 "\" [line " + OUString::number(m_linepos
) +
328 ", column " + OUString::number(m_pos
) +
332 PolicyReader::PolicyReader( OUString fileName
, AccessControl
& ac
)
333 : m_fileName(std::move( fileName
))
335 , m_pos( 1 ) // force readline
338 ac
.checkFilePermission( m_fileName
, "read" );
339 if (osl_File_E_None
!= ::osl_openFile( m_fileName
.pData
, &m_file
, osl_File_OpenFlag_Read
))
341 throw RuntimeException( "cannot open file \"" + m_fileName
+ "\"!" );
345 PolicyReader::~PolicyReader()
347 if ( ::osl_closeFile( m_file
) != osl_File_E_None
) {
352 constexpr OUStringLiteral s_grant
= u
"grant";
353 constexpr OUStringLiteral s_user
= u
"user";
354 constexpr OUStringLiteral s_permission
= u
"permission";
355 constexpr OUStringLiteral s_openBrace
= u
"{";
356 constexpr OUStringLiteral s_closingBrace
= u
"}";
358 constexpr OUStringLiteral s_filePermission
= u
"com.sun.star.io.FilePermission";
359 constexpr OUStringLiteral s_socketPermission
= u
"com.sun.star.connection.SocketPermission";
360 constexpr OUStringLiteral s_runtimePermission
= u
"com.sun.star.security.RuntimePermission";
361 constexpr OUStringLiteral s_allPermission
= u
"com.sun.star.security.AllPermission";
364 void FilePolicy::refresh()
366 // read out file (the .../file-name value had originally been set in
367 // cppu::add_access_control_entries (cppuhelper/source/servicefactory.cxx)
368 // depending on various UNO_AC* bootstrap variables that are no longer
369 // supported, so this is effectively dead code):
371 m_xComponentContext
->getValueByName(
372 "/implementations/" + IMPL_NAME
+ "/file-name" ) >>= fileName
;
373 if ( fileName
.isEmpty() )
375 throw RuntimeException(
376 "name of policy file unknown!",
377 static_cast<OWeakObject
*>(this) );
380 PolicyReader
reader( fileName
, m_ac
);
383 Sequence
< Any
> defaultPermissions
;
384 t_permissions userPermissions
;
386 OUString
token( reader
.getToken() );
387 while (!token
.isEmpty())
389 if ( token
!= s_grant
)
390 reader
.error( u
"expected >grant< token!" );
392 token
= reader
.assureToken();
393 if ( token
== s_user
) // next token is user-id
395 userId
= reader
.assureQuotedToken();
396 token
= reader
.assureToken();
398 if ( token
!= s_openBrace
)
399 reader
.error( u
"expected opening brace >{<!" );
400 token
= reader
.assureToken();
402 while ( token
!= s_closingBrace
)
404 if ( token
!= s_permission
)
405 reader
.error( u
"expected >permission< or closing brace >}<!" );
407 token
= reader
.assureToken(); // permission type
409 if ( token
== s_filePermission
) // FilePermission
411 OUString
url( reader
.assureQuotedToken() );
412 reader
.assureToken( ',' );
413 OUString
actions( reader
.assureQuotedToken() );
414 perm
<<= io::FilePermission( url
, actions
);
416 else if ( token
== s_socketPermission
) // SocketPermission
418 OUString
host( reader
.assureQuotedToken() );
419 reader
.assureToken( ',' );
420 OUString
actions( reader
.assureQuotedToken() );
421 perm
<<= connection::SocketPermission( host
, actions
);
423 else if ( token
== s_runtimePermission
) // RuntimePermission
425 OUString
name( reader
.assureQuotedToken() );
426 perm
<<= security::RuntimePermission( name
);
428 else if ( token
== s_allPermission
) // AllPermission
430 perm
<<= security::AllPermission();
434 reader
.error( u
"expected permission type!" );
437 reader
.assureToken( ';' );
440 if (!userId
.isEmpty())
442 Sequence
< Any
> perms( userPermissions
[ userId
] );
443 sal_Int32 len
= perms
.getLength();
444 perms
.realloc( len
+1 );
445 perms
.getArray()[ len
] = perm
;
446 userPermissions
[ userId
] = perms
;
450 sal_Int32 len
= defaultPermissions
.getLength();
451 defaultPermissions
.realloc( len
+1 );
452 defaultPermissions
.getArray()[ len
] = perm
;
455 token
= reader
.assureToken(); // next permissions token
458 reader
.assureToken( ';' ); // semi
459 token
= reader
.getToken(); // next grant token
463 MutexGuard
guard( m_aMutex
);
464 m_defaultPermissions
= defaultPermissions
;
465 m_userPermissions
= userPermissions
;
469 OUString
FilePolicy::getImplementationName()
474 sal_Bool
FilePolicy::supportsService( OUString
const & serviceName
)
476 return cppu::supportsService(this, serviceName
);
479 Sequence
< OUString
> FilePolicy::getSupportedServiceNames()
481 return { "com.sun.star.security.Policy" };
486 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
487 com_sun_star_security_comp_stoc_FilePolicy_get_implementation(
488 css::uno::XComponentContext
*context
,
489 css::uno::Sequence
<css::uno::Any
> const &)
491 return cppu::acquire(new FilePolicy(context
));
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */