Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : #include <vector>
22 : : #include <memory>
23 : :
24 : : #include <osl/diagnose.h>
25 : : #include <osl/interlck.h>
26 : : #include <osl/mutex.hxx>
27 : : #include <osl/thread.hxx>
28 : :
29 : : #include <rtl/ustrbuf.hxx>
30 : : #include <rtl/string.hxx>
31 : :
32 : : #include <uno/current_context.h>
33 : :
34 : : #include <cppuhelper/implbase1.hxx>
35 : : #include <cppuhelper/compbase3.hxx>
36 : : #include <cppuhelper/factory.hxx>
37 : : #include <cppuhelper/implementationentry.hxx>
38 : :
39 : : #include <com/sun/star/uno/XCurrentContext.hpp>
40 : : #include <com/sun/star/uno/DeploymentException.hpp>
41 : : #include <com/sun/star/lang/DisposedException.hpp>
42 : : #include <com/sun/star/lang/XComponent.hpp>
43 : : #include <com/sun/star/lang/XServiceInfo.hpp>
44 : : #include <com/sun/star/lang/XInitialization.hpp>
45 : : #include <com/sun/star/security/XAccessController.hpp>
46 : : #include <com/sun/star/security/XPolicy.hpp>
47 : :
48 : : #include "lru_cache.h"
49 : : #include "permissions.h"
50 : : #include "bootstrapservices.hxx"
51 : :
52 : :
53 : : #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
54 : : #define SERVICE_NAME "com.sun.star.security.AccessController"
55 : : #define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController"
56 : : #define USER_CREDS "access-control.user-credentials"
57 : :
58 : :
59 : : using namespace ::std;
60 : : using namespace ::osl;
61 : : using namespace ::cppu;
62 : : using namespace ::com::sun::star;
63 : : using namespace ::com::sun::star::uno;
64 : : using ::rtl::OUString;
65 : : using ::rtl::OUStringBuffer;
66 : : using ::rtl::OString;
67 : :
68 : : extern ::rtl_StandardModuleCount g_moduleCount;
69 : :
70 : : namespace stoc_sec
71 : : {
72 : : // static stuff initialized when loading lib
73 : 742 : static OUString s_envType = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
74 : : const char s_acRestriction[] = "access-control.restriction";
75 : :
76 : : //##################################################################################################
77 : :
78 : : /** ac context intersects permissions of two ac contexts
79 : : */
80 : : class acc_Intersection
81 : : : public WeakImplHelper1< security::XAccessControlContext >
82 : : {
83 : : Reference< security::XAccessControlContext > m_x1, m_x2;
84 : :
85 : : inline acc_Intersection(
86 : : Reference< security::XAccessControlContext > const & x1,
87 : : Reference< security::XAccessControlContext > const & x2 )
88 : : SAL_THROW(());
89 : :
90 : : public:
91 : : virtual ~acc_Intersection()
92 : : SAL_THROW(());
93 : :
94 : : static inline Reference< security::XAccessControlContext > create(
95 : : Reference< security::XAccessControlContext > const & x1,
96 : : Reference< security::XAccessControlContext > const & x2 )
97 : : SAL_THROW(());
98 : :
99 : : // XAccessControlContext impl
100 : : virtual void SAL_CALL checkPermission(
101 : : Any const & perm )
102 : : throw (RuntimeException);
103 : : };
104 : : //__________________________________________________________________________________________________
105 : 0 : inline acc_Intersection::acc_Intersection(
106 : : Reference< security::XAccessControlContext > const & x1,
107 : : Reference< security::XAccessControlContext > const & x2 )
108 : : SAL_THROW(())
109 : : : m_x1( x1 )
110 : 0 : , m_x2( x2 )
111 : : {
112 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
113 : 0 : }
114 : : //__________________________________________________________________________________________________
115 : 0 : acc_Intersection::~acc_Intersection()
116 : : SAL_THROW(())
117 : : {
118 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
119 [ # # ]: 0 : }
120 : : //--------------------------------------------------------------------------------------------------
121 : 0 : inline Reference< security::XAccessControlContext > acc_Intersection::create(
122 : : Reference< security::XAccessControlContext > const & x1,
123 : : Reference< security::XAccessControlContext > const & x2 )
124 : : SAL_THROW(())
125 : : {
126 [ # # ]: 0 : if (! x1.is())
127 : 0 : return x2;
128 [ # # ]: 0 : if (! x2.is())
129 : 0 : return x1;
130 [ # # ][ # # ]: 0 : return new acc_Intersection( x1, x2 );
131 : : }
132 : : //__________________________________________________________________________________________________
133 : 0 : void acc_Intersection::checkPermission(
134 : : Any const & perm )
135 : : throw (RuntimeException)
136 : : {
137 : 0 : m_x1->checkPermission( perm );
138 : 0 : m_x2->checkPermission( perm );
139 : 0 : }
140 : :
141 : : /** ac context unifies permissions of two ac contexts
142 : : */
143 : : class acc_Union
144 : : : public WeakImplHelper1< security::XAccessControlContext >
145 : : {
146 : : Reference< security::XAccessControlContext > m_x1, m_x2;
147 : :
148 : : inline acc_Union(
149 : : Reference< security::XAccessControlContext > const & x1,
150 : : Reference< security::XAccessControlContext > const & x2 )
151 : : SAL_THROW(());
152 : :
153 : : public:
154 : : virtual ~acc_Union()
155 : : SAL_THROW(());
156 : :
157 : : static inline Reference< security::XAccessControlContext > create(
158 : : Reference< security::XAccessControlContext > const & x1,
159 : : Reference< security::XAccessControlContext > const & x2 )
160 : : SAL_THROW(());
161 : :
162 : : // XAccessControlContext impl
163 : : virtual void SAL_CALL checkPermission(
164 : : Any const & perm )
165 : : throw (RuntimeException);
166 : : };
167 : : //__________________________________________________________________________________________________
168 : 0 : inline acc_Union::acc_Union(
169 : : Reference< security::XAccessControlContext > const & x1,
170 : : Reference< security::XAccessControlContext > const & x2 )
171 : : SAL_THROW(())
172 : : : m_x1( x1 )
173 : 0 : , m_x2( x2 )
174 : : {
175 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
176 : 0 : }
177 : : //__________________________________________________________________________________________________
178 : 0 : acc_Union::~acc_Union()
179 : : SAL_THROW(())
180 : : {
181 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
182 [ # # ]: 0 : }
183 : : //--------------------------------------------------------------------------------------------------
184 : 0 : inline Reference< security::XAccessControlContext > acc_Union::create(
185 : : Reference< security::XAccessControlContext > const & x1,
186 : : Reference< security::XAccessControlContext > const & x2 )
187 : : SAL_THROW(())
188 : : {
189 [ # # ]: 0 : if (! x1.is())
190 : 0 : return Reference< security::XAccessControlContext >(); // unrestricted
191 [ # # ]: 0 : if (! x2.is())
192 : 0 : return Reference< security::XAccessControlContext >(); // unrestricted
193 [ # # ][ # # ]: 0 : return new acc_Union( x1, x2 );
194 : : }
195 : : //__________________________________________________________________________________________________
196 : 0 : void acc_Union::checkPermission(
197 : : Any const & perm )
198 : : throw (RuntimeException)
199 : : {
200 : : try
201 : : {
202 [ # # ][ # # ]: 0 : m_x1->checkPermission( perm );
203 : : }
204 [ # # ]: 0 : catch (security::AccessControlException &)
205 : : {
206 [ # # # # ]: 0 : m_x2->checkPermission( perm );
207 : : }
208 : 0 : }
209 : :
210 : : /** ac context doing permission checks on static permissions
211 : : */
212 : : class acc_Policy
213 : : : public WeakImplHelper1< security::XAccessControlContext >
214 : : {
215 : : PermissionCollection m_permissions;
216 : :
217 : : public:
218 : : inline acc_Policy(
219 : : PermissionCollection const & permissions )
220 : : SAL_THROW(());
221 : : virtual ~acc_Policy()
222 : : SAL_THROW(());
223 : :
224 : : // XAccessControlContext impl
225 : : virtual void SAL_CALL checkPermission(
226 : : Any const & perm )
227 : : throw (RuntimeException);
228 : : };
229 : : //__________________________________________________________________________________________________
230 : 0 : inline acc_Policy::acc_Policy(
231 : : PermissionCollection const & permissions )
232 : : SAL_THROW(())
233 [ # # ]: 0 : : m_permissions( permissions )
234 : : {
235 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
236 : 0 : }
237 : : //__________________________________________________________________________________________________
238 [ # # ]: 0 : acc_Policy::~acc_Policy()
239 : : SAL_THROW(())
240 : : {
241 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
242 [ # # ]: 0 : }
243 : : //__________________________________________________________________________________________________
244 : 0 : void acc_Policy::checkPermission(
245 : : Any const & perm )
246 : : throw (RuntimeException)
247 : : {
248 : 0 : m_permissions.checkPermission( perm );
249 : 0 : }
250 : :
251 : : /** current context overriding dynamic ac restriction
252 : : */
253 : : class acc_CurrentContext
254 : : : public ImplHelper1< XCurrentContext >
255 : : {
256 : : oslInterlockedCount m_refcount;
257 : :
258 : : Reference< XCurrentContext > m_xDelegate;
259 : : Any m_restriction;
260 : :
261 : : public:
262 : : inline acc_CurrentContext(
263 : : Reference< XCurrentContext > const & xDelegate,
264 : : Reference< security::XAccessControlContext > const & xRestriction )
265 : : SAL_THROW(());
266 : : virtual ~acc_CurrentContext() SAL_THROW(());
267 : :
268 : : // XInterface impl
269 : : virtual void SAL_CALL acquire()
270 : : throw ();
271 : : virtual void SAL_CALL release()
272 : : throw ();
273 : :
274 : : // XCurrentContext impl
275 : : virtual Any SAL_CALL getValueByName( OUString const & name )
276 : : throw (RuntimeException);
277 : : };
278 : : //__________________________________________________________________________________________________
279 : 0 : inline acc_CurrentContext::acc_CurrentContext(
280 : : Reference< XCurrentContext > const & xDelegate,
281 : : Reference< security::XAccessControlContext > const & xRestriction )
282 : : SAL_THROW(())
283 : : : m_refcount( 0 )
284 : 0 : , m_xDelegate( xDelegate )
285 : : {
286 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
287 : :
288 [ # # ]: 0 : if (xRestriction.is())
289 : : {
290 [ # # ]: 0 : m_restriction = makeAny( xRestriction );
291 : : }
292 : : // return empty any otherwise on getValueByName(), not null interface
293 : 0 : }
294 : : //__________________________________________________________________________________________________
295 : 0 : acc_CurrentContext::~acc_CurrentContext()
296 : : SAL_THROW(())
297 : : {
298 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
299 [ # # ]: 0 : }
300 : : //__________________________________________________________________________________________________
301 : 0 : void acc_CurrentContext::acquire()
302 : : throw ()
303 : : {
304 : 0 : ::osl_incrementInterlockedCount( &m_refcount );
305 : 0 : }
306 : : //__________________________________________________________________________________________________
307 : 0 : void acc_CurrentContext::release()
308 : : throw ()
309 : : {
310 [ # # ]: 0 : if (! ::osl_decrementInterlockedCount( &m_refcount ))
311 : : {
312 [ # # ]: 0 : delete this;
313 : : }
314 : 0 : }
315 : : //__________________________________________________________________________________________________
316 : 0 : Any acc_CurrentContext::getValueByName( OUString const & name )
317 : : throw (RuntimeException)
318 : : {
319 [ # # ]: 0 : if (name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(s_acRestriction)))
320 : : {
321 : 0 : return m_restriction;
322 : : }
323 [ # # ]: 0 : else if (m_xDelegate.is())
324 : : {
325 : 0 : return m_xDelegate->getValueByName( name );
326 : : }
327 : : else
328 : : {
329 : 0 : return Any();
330 : : }
331 : : }
332 : :
333 : : //##################################################################################################
334 : :
335 : : //--------------------------------------------------------------------------------------------------
336 : : static inline void dispose( Reference< XInterface > const & x )
337 : : SAL_THROW( (RuntimeException) )
338 : : {
339 : : Reference< lang::XComponent > xComp( x, UNO_QUERY );
340 : : if (xComp.is())
341 : : {
342 : : xComp->dispose();
343 : : }
344 : : }
345 : : //--------------------------------------------------------------------------------------------------
346 : 0 : static inline Reference< security::XAccessControlContext > getDynamicRestriction(
347 : : Reference< XCurrentContext > const & xContext )
348 : : SAL_THROW( (RuntimeException) )
349 : : {
350 [ # # ]: 0 : if (xContext.is())
351 : : {
352 [ # # ][ # # ]: 0 : Any acc(xContext->getValueByName(rtl::OUString(s_acRestriction)));
353 [ # # ]: 0 : if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass)
354 : : {
355 : : // avoid ref-counting
356 : : OUString const & typeName =
357 : 0 : *reinterpret_cast< OUString const * >( &acc.pType->pTypeName );
358 [ # # ]: 0 : if ( typeName == "com.sun.star.security.XAccessControlContext" )
359 : : {
360 : : return Reference< security::XAccessControlContext >(
361 [ # # ]: 0 : *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) );
362 : : }
363 : : else // try to query
364 : : {
365 : : return Reference< security::XAccessControlContext >::query(
366 [ # # ]: 0 : *reinterpret_cast< XInterface ** const >( acc.pData ) );
367 : : }
368 [ # # ]: 0 : }
369 : : }
370 : 0 : return Reference< security::XAccessControlContext >();
371 : : }
372 : : //==================================================================================================
373 : : class cc_reset
374 : : {
375 : : void * m_cc;
376 : : public:
377 : 0 : inline cc_reset( void * cc ) SAL_THROW(())
378 : 0 : : m_cc( cc ) {}
379 : 0 : inline ~cc_reset() SAL_THROW(())
380 : 0 : { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); }
381 : : };
382 : :
383 : : //##################################################################################################
384 : :
385 : 0 : struct MutexHolder
386 : : {
387 : : Mutex m_mutex;
388 : : };
389 : : typedef WeakComponentImplHelper3<
390 : : security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper;
391 : :
392 : : //==================================================================================================
393 : : class AccessController
394 : : : public MutexHolder
395 : : , public t_helper
396 : : {
397 : : Reference< XComponentContext > m_xComponentContext;
398 : :
399 : : Reference< security::XPolicy > m_xPolicy;
400 : : Reference< security::XPolicy > const & getPolicy()
401 : : SAL_THROW( (RuntimeException) );
402 : :
403 : : // mode
404 : : enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode;
405 : :
406 : : PermissionCollection m_defaultPermissions;
407 : : // for single-user mode
408 : : PermissionCollection m_singleUserPermissions;
409 : : OUString m_singleUserId;
410 : : bool m_defaultPerm_init;
411 : : bool m_singleUser_init;
412 : : // for multi-user mode
413 : : lru_cache< OUString, PermissionCollection, ::rtl::OUStringHash, equal_to< OUString > >
414 : : m_user2permissions;
415 : :
416 : : ThreadData m_rec;
417 : : typedef vector< pair< OUString, Any > > t_rec_vec;
418 : : inline void clearPostPoned() SAL_THROW(());
419 : : void checkAndClearPostPoned() SAL_THROW( (RuntimeException) );
420 : :
421 : : PermissionCollection getEffectivePermissions(
422 : : Reference< XCurrentContext > const & xContext,
423 : : Any const & demanded_perm )
424 : : SAL_THROW( (RuntimeException) );
425 : :
426 : : protected:
427 : : virtual void SAL_CALL disposing();
428 : :
429 : : public:
430 : : AccessController( Reference< XComponentContext > const & xComponentContext )
431 : : SAL_THROW( (RuntimeException) );
432 : : virtual ~AccessController()
433 : : SAL_THROW(());
434 : :
435 : : // XInitialization impl
436 : : virtual void SAL_CALL initialize(
437 : : Sequence< Any > const & arguments )
438 : : throw (Exception);
439 : :
440 : : // XAccessController impl
441 : : virtual void SAL_CALL checkPermission(
442 : : Any const & perm )
443 : : throw (RuntimeException);
444 : : virtual Any SAL_CALL doRestricted(
445 : : Reference< security::XAction > const & xAction,
446 : : Reference< security::XAccessControlContext > const & xRestriction )
447 : : throw (Exception);
448 : : virtual Any SAL_CALL doPrivileged(
449 : : Reference< security::XAction > const & xAction,
450 : : Reference< security::XAccessControlContext > const & xRestriction )
451 : : throw (Exception);
452 : : virtual Reference< security::XAccessControlContext > SAL_CALL getContext()
453 : : throw (RuntimeException);
454 : :
455 : : // XServiceInfo impl
456 : : virtual OUString SAL_CALL getImplementationName()
457 : : throw (RuntimeException);
458 : : virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
459 : : throw (RuntimeException);
460 : : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
461 : : throw (RuntimeException);
462 : : };
463 : : //__________________________________________________________________________________________________
464 : 0 : AccessController::AccessController( Reference< XComponentContext > const & xComponentContext )
465 : : SAL_THROW( (RuntimeException) )
466 : : : t_helper( m_mutex )
467 : : , m_xComponentContext( xComponentContext )
468 : : , m_mode( ON ) // default
469 : : , m_defaultPerm_init( false )
470 : : , m_singleUser_init( false )
471 [ # # ][ # # ]: 0 : , m_rec( 0 )
[ # # ][ # # ]
472 : : {
473 [ # # ]: 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
474 : :
475 : 0 : OUString mode;
476 [ # # ][ # # ]: 0 : if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode)
[ # # ][ # # ]
477 : : {
478 [ # # ]: 0 : if ( mode == "off" )
479 : : {
480 : 0 : m_mode = OFF;
481 : : }
482 [ # # ]: 0 : else if ( mode == "on" )
483 : : {
484 : 0 : m_mode = ON;
485 : : }
486 [ # # ]: 0 : else if ( mode == "dynamic-only" )
487 : : {
488 : 0 : m_mode = DYNAMIC_ONLY;
489 : : }
490 [ # # ]: 0 : else if ( mode == "single-user" )
491 : : {
492 [ # # ]: 0 : m_xComponentContext->getValueByName(
493 [ # # ][ # # ]: 0 : OUSTR("/services/" SERVICE_NAME "/single-user-id") ) >>= m_singleUserId;
494 [ # # ]: 0 : if (m_singleUserId.isEmpty())
495 : : {
496 : : throw RuntimeException(
497 : : OUSTR("expected a user id in component context entry "
498 : : "\"/services/" SERVICE_NAME "/single-user-id\"!"),
499 [ # # ][ # # ]: 0 : (OWeakObject *)this );
[ # # ]
500 : : }
501 : 0 : m_mode = SINGLE_USER;
502 : : }
503 [ # # ]: 0 : else if ( mode == "single-default-user" )
504 : : {
505 : 0 : m_mode = SINGLE_DEFAULT_USER;
506 : : }
507 : : }
508 : :
509 : : // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process)
510 [ # # ][ # # ]: 0 : if (ON == m_mode || DYNAMIC_ONLY == m_mode)
511 : : {
512 : 0 : sal_Int32 cacheSize = 0; // multi-user cache size
513 [ # # # # ]: 0 : if (! (m_xComponentContext->getValueByName(
514 [ # # ][ # # ]: 0 : OUSTR("/services/" SERVICE_NAME "/user-cache-size") ) >>= cacheSize))
515 : : {
516 : 0 : cacheSize = 128; // reasonable default?
517 : : }
518 : : #ifdef __CACHE_DIAGNOSE
519 : : cacheSize = 2;
520 : : #endif
521 [ # # ]: 0 : m_user2permissions.setSize( cacheSize );
522 : 0 : }
523 : 0 : }
524 : : //__________________________________________________________________________________________________
525 [ # # ][ # # ]: 0 : AccessController::~AccessController()
[ # # ][ # # ]
[ # # ]
526 : : SAL_THROW(())
527 : : {
528 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
529 [ # # ]: 0 : }
530 : : //__________________________________________________________________________________________________
531 : 0 : void AccessController::disposing()
532 : : {
533 : 0 : m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY?
534 : 0 : m_xPolicy.clear();
535 : 0 : m_xComponentContext.clear();
536 : 0 : }
537 : :
538 : : // XInitialization impl
539 : : //__________________________________________________________________________________________________
540 : 0 : void AccessController::initialize(
541 : : Sequence< Any > const & arguments )
542 : : throw (Exception)
543 : : {
544 : : // xxx todo: review for forking
545 : : // portal forking hack: re-initialize for another user-id
546 [ # # ]: 0 : if (SINGLE_USER != m_mode) // only if in single-user mode
547 : : {
548 : : throw RuntimeException(
549 [ # # ][ # # ]: 0 : OUSTR("invalid call: ac must be in \"single-user\" mode!"), (OWeakObject *)this );
[ # # ]
550 : : }
551 : 0 : OUString userId;
552 : 0 : arguments[ 0 ] >>= userId;
553 [ # # ]: 0 : if ( userId.isEmpty() )
554 : : {
555 : : throw RuntimeException(
556 [ # # ][ # # ]: 0 : OUSTR("expected a user-id as first argument!"), (OWeakObject *)this );
[ # # ]
557 : : }
558 : : // assured that no sync is necessary: no check happens at this forking time
559 : 0 : m_singleUserId = userId;
560 : 0 : m_singleUser_init = false;
561 : 0 : }
562 : :
563 : : //__________________________________________________________________________________________________
564 : 0 : Reference< security::XPolicy > const & AccessController::getPolicy()
565 : : SAL_THROW( (RuntimeException) )
566 : : {
567 : : // get policy singleton
568 [ # # ]: 0 : if (! m_xPolicy.is())
569 : : {
570 : 0 : Reference< security::XPolicy > xPolicy;
571 [ # # ]: 0 : m_xComponentContext->getValueByName(
572 [ # # ][ # # ]: 0 : OUSTR("/singletons/com.sun.star.security.thePolicy") ) >>= xPolicy;
[ # # ]
573 [ # # ]: 0 : if (xPolicy.is())
574 : : {
575 [ # # ]: 0 : MutexGuard guard( m_mutex );
576 [ # # ]: 0 : if (! m_xPolicy.is())
577 : : {
578 [ # # ]: 0 : m_xPolicy = xPolicy;
579 [ # # ]: 0 : }
580 : : }
581 : : else
582 : : {
583 : : throw SecurityException(
584 [ # # ][ # # ]: 0 : OUSTR("cannot get policy singleton!"), (OWeakObject *)this );
[ # # ]
585 : 0 : }
586 : : }
587 : 0 : return m_xPolicy;
588 : : }
589 : :
590 : : #ifdef __DIAGNOSE
591 : : static void dumpPermissions(
592 : : PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW(())
593 : : {
594 : : OUStringBuffer buf( 48 );
595 : : if (!userId.isEmpty())
596 : : {
597 : : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> dumping permissions of user \"") );
598 : : buf.append( userId );
599 : : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\":") );
600 : : }
601 : : else
602 : : {
603 : : buf.appendAscii(
604 : : RTL_CONSTASCII_STRINGPARAM("> dumping default permissions:") );
605 : : }
606 : : OString str( ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
607 : : OSL_TRACE( "%s", str.getStr() );
608 : : Sequence< OUString > permissions( collection.toStrings() );
609 : : OUString const * p = permissions.getConstArray();
610 : : for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos )
611 : : {
612 : : OString str( ::rtl::OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) );
613 : : OSL_TRACE( "%s", str.getStr() );
614 : : }
615 : : OSL_TRACE( "> permission dump done" );
616 : : }
617 : : #endif
618 : :
619 : :
620 : : //__________________________________________________________________________________________________
621 : 0 : inline void AccessController::clearPostPoned() SAL_THROW(())
622 : : {
623 [ # # ]: 0 : delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
624 : 0 : m_rec.setData( 0 );
625 : 0 : }
626 : : //__________________________________________________________________________________________________
627 : 0 : void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) )
628 : : {
629 : : // check postponed permissions
630 [ # # ]: 0 : auto_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) );
631 [ # # ]: 0 : m_rec.setData( 0 ); // takeover ownership
632 : : OSL_ASSERT( rec.get() );
633 [ # # ]: 0 : if (rec.get())
634 : : {
635 : 0 : t_rec_vec const & vec = *rec.get();
636 [ # # # # ]: 0 : switch (m_mode)
637 : : {
638 : : case SINGLE_USER:
639 : : {
640 : : OSL_ASSERT( m_singleUser_init );
641 [ # # ]: 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
642 : : {
643 : 0 : pair< OUString, Any > const & p = vec[ nPos ];
644 : : OSL_ASSERT( m_singleUserId.equals( p.first ) );
645 [ # # ]: 0 : m_singleUserPermissions.checkPermission( p.second );
646 : : }
647 : 0 : break;
648 : : }
649 : : case SINGLE_DEFAULT_USER:
650 : : {
651 : : OSL_ASSERT( m_defaultPerm_init );
652 [ # # ]: 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
653 : : {
654 : 0 : pair< OUString, Any > const & p = vec[ nPos ];
655 : : OSL_ASSERT( p.first.isEmpty() ); // default-user
656 [ # # ]: 0 : m_defaultPermissions.checkPermission( p.second );
657 : : }
658 : 0 : break;
659 : : }
660 : : case ON:
661 : : {
662 [ # # ]: 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
663 : : {
664 : 0 : pair< OUString, Any > const & p = vec[ nPos ];
665 : : PermissionCollection const * pPermissions;
666 : : // lookup policy for user
667 : : {
668 [ # # ]: 0 : MutexGuard guard( m_mutex );
669 [ # # ][ # # ]: 0 : pPermissions = m_user2permissions.lookup( p.first );
670 : : }
671 : : OSL_ASSERT( pPermissions );
672 [ # # ]: 0 : if (pPermissions)
673 : : {
674 [ # # ]: 0 : pPermissions->checkPermission( p.second );
675 : : }
676 : : }
677 : 0 : break;
678 : : }
679 : : default:
680 : : OSL_FAIL( "### this should never be called in this ac mode!" );
681 : 0 : break;
682 : : }
683 : 0 : }
684 : 0 : }
685 : : //__________________________________________________________________________________________________
686 : : /** this is the only function calling the policy singleton and thus has to take care
687 : : of recurring calls!
688 : :
689 : : @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call
690 : : which will be postponed for recurring calls
691 : : */
692 : 0 : PermissionCollection AccessController::getEffectivePermissions(
693 : : Reference< XCurrentContext > const & xContext,
694 : : Any const & demanded_perm )
695 : : SAL_THROW( (RuntimeException) )
696 : : {
697 : 0 : OUString userId;
698 : :
699 [ # # # # ]: 0 : switch (m_mode)
700 : : {
701 : : case SINGLE_USER:
702 : : {
703 [ # # ]: 0 : if (m_singleUser_init)
704 [ # # ]: 0 : return m_singleUserPermissions;
705 : 0 : userId = m_singleUserId;
706 : 0 : break;
707 : : }
708 : : case SINGLE_DEFAULT_USER:
709 : : {
710 [ # # ]: 0 : if (m_defaultPerm_init)
711 [ # # ]: 0 : return m_defaultPermissions;
712 : 0 : break;
713 : : }
714 : : case ON:
715 : : {
716 [ # # ]: 0 : if (xContext.is())
717 : : {
718 [ # # ][ # # ]: 0 : xContext->getValueByName( OUSTR(USER_CREDS ".id") ) >>= userId;
[ # # ]
719 : : }
720 [ # # ]: 0 : if ( userId.isEmpty() )
721 : : {
722 : : throw SecurityException(
723 [ # # ][ # # ]: 0 : OUSTR("cannot determine current user in multi-user ac!"), (OWeakObject *)this );
[ # # ]
724 : : }
725 : :
726 : : // lookup policy for user
727 [ # # ]: 0 : MutexGuard guard( m_mutex );
728 [ # # ]: 0 : PermissionCollection const * pPermissions = m_user2permissions.lookup( userId );
729 [ # # ]: 0 : if (pPermissions)
730 [ # # ]: 0 : return *pPermissions;
731 [ # # ][ # # ]: 0 : break;
732 : : }
733 : : default:
734 : : OSL_FAIL( "### this should never be called in this ac mode!" );
735 [ # # ]: 0 : return PermissionCollection();
736 : : }
737 : :
738 : : // call on policy
739 : : // iff this is a recurring call for the default user, then grant all permissions
740 [ # # ]: 0 : t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() );
741 [ # # ]: 0 : if (rec) // tls entry exists => this is recursive call
742 : : {
743 [ # # ]: 0 : if (demanded_perm.hasValue())
744 : : {
745 : : // enqueue
746 [ # # ]: 0 : rec->push_back( pair< OUString, Any >( userId, demanded_perm ) );
747 : : }
748 : : #ifdef __DIAGNOSE
749 : : OUStringBuffer buf( 48 );
750 : : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> info: recurring call of user \"") );
751 : : buf.append( userId );
752 : : buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"") );
753 : : OString str(
754 : : ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
755 : : OSL_TRACE( "%s", str.getStr() );
756 : : #endif
757 [ # # ][ # # ]: 0 : return PermissionCollection( new AllPermission() );
[ # # ][ # # ]
[ # # ][ # # ]
758 : : }
759 : : else // no tls
760 : : {
761 [ # # ][ # # ]: 0 : rec = new t_rec_vec;
762 [ # # ]: 0 : m_rec.setData( rec );
763 : : }
764 : :
765 : : try // calls on API
766 : : {
767 : : // init default permissions
768 [ # # ]: 0 : if (! m_defaultPerm_init)
769 : : {
770 : : PermissionCollection defaultPermissions(
771 [ # # ][ # # ]: 0 : getPolicy()->getDefaultPermissions() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
772 : : // assign
773 [ # # ]: 0 : MutexGuard guard( m_mutex );
774 [ # # ]: 0 : if (! m_defaultPerm_init)
775 : : {
776 [ # # ]: 0 : m_defaultPermissions = defaultPermissions;
777 : 0 : m_defaultPerm_init = true;
778 [ # # ][ # # ]: 0 : }
779 : : #ifdef __DIAGNOSE
780 : : dumpPermissions( m_defaultPermissions );
781 : : #endif
782 : : }
783 : :
784 [ # # ]: 0 : PermissionCollection ret;
785 : :
786 : : // init user permissions
787 [ # # # # ]: 0 : switch (m_mode)
788 : : {
789 : : case SINGLE_USER:
790 : : {
791 : : ret = PermissionCollection(
792 [ # # ][ # # ]: 0 : getPolicy()->getPermissions( userId ), m_defaultPermissions );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
793 : : {
794 : : // assign
795 [ # # ]: 0 : MutexGuard guard( m_mutex );
796 [ # # ]: 0 : if (m_singleUser_init)
797 : : {
798 [ # # ]: 0 : ret = m_singleUserPermissions;
799 : : }
800 : : else
801 : : {
802 [ # # ]: 0 : m_singleUserPermissions = ret;
803 : 0 : m_singleUser_init = true;
804 [ # # ]: 0 : }
805 : : }
806 : : #ifdef __DIAGNOSE
807 : : dumpPermissions( ret, userId );
808 : : #endif
809 : 0 : break;
810 : : }
811 : : case SINGLE_DEFAULT_USER:
812 : : {
813 [ # # ]: 0 : ret = m_defaultPermissions;
814 : 0 : break;
815 : : }
816 : : case ON:
817 : : {
818 : : ret = PermissionCollection(
819 [ # # ][ # # ]: 0 : getPolicy()->getPermissions( userId ), m_defaultPermissions );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
820 : : {
821 : : // cache
822 [ # # ]: 0 : MutexGuard guard( m_mutex );
823 [ # # ][ # # ]: 0 : m_user2permissions.set( userId, ret );
824 : : }
825 : : #ifdef __DIAGNOSE
826 : : dumpPermissions( ret, userId );
827 : : #endif
828 : 0 : break;
829 : : }
830 : : default:
831 : 0 : break;
832 : : }
833 : :
834 : : // check postponed
835 [ # # ]: 0 : checkAndClearPostPoned();
836 [ # # ][ # # ]: 0 : return ret;
837 : : }
838 : 0 : catch (const security::AccessControlException & exc) // wrapped into DeploymentException
839 : : {
840 [ # # ]: 0 : clearPostPoned(); // safety: exception could have happened before checking postponed?
841 : 0 : OUStringBuffer buf( 64 );
842 : : buf.appendAscii(
843 [ # # ]: 0 : RTL_CONSTASCII_STRINGPARAM("deployment error (AccessControlException occurred): ") );
844 [ # # ]: 0 : buf.append( exc.Message );
845 [ # # # # ]: 0 : throw DeploymentException( buf.makeStringAndClear(), exc.Context );
846 : : }
847 : 0 : catch (RuntimeException &)
848 : : {
849 : : // dont check postponed, just cleanup
850 [ # # ]: 0 : clearPostPoned();
851 [ # # # # ]: 0 : delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
852 [ # # ]: 0 : m_rec.setData( 0 );
853 : 0 : throw;
854 : : }
855 : 0 : catch (Exception &)
856 : : {
857 : : // check postponed permissions first
858 : : // => AccessControlExceptions are errors, user exceptions not!
859 [ # # ]: 0 : checkAndClearPostPoned();
860 : 0 : throw;
861 : : }
862 [ # # # # ]: 0 : catch (...)
863 : : {
864 : : // dont check postponed, just cleanup
865 [ # # ]: 0 : clearPostPoned();
866 : 0 : throw;
867 : 0 : }
868 : : }
869 : :
870 : : // XAccessController impl
871 : : //__________________________________________________________________________________________________
872 : 0 : void AccessController::checkPermission(
873 : : Any const & perm )
874 : : throw (RuntimeException)
875 : : {
876 [ # # ]: 0 : if (rBHelper.bDisposed)
877 : : {
878 : : throw lang::DisposedException(
879 [ # # ][ # # ]: 0 : OUSTR("checkPermission() call on disposed AccessController!"), (OWeakObject *)this );
[ # # ]
880 : : }
881 : :
882 [ # # ]: 0 : if (OFF == m_mode)
883 : : return;
884 : :
885 : : // first dynamic check of ac contexts
886 : 0 : Reference< XCurrentContext > xContext;
887 : 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
888 [ # # ]: 0 : Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) );
889 [ # # ]: 0 : if (xACC.is())
890 : : {
891 [ # # ][ # # ]: 0 : xACC->checkPermission( perm );
892 : : }
893 : :
894 [ # # ]: 0 : if (DYNAMIC_ONLY == m_mode)
895 : : return;
896 : :
897 : : // then static check
898 [ # # ][ # # ]: 0 : getEffectivePermissions( xContext, perm ).checkPermission( perm );
[ # # ][ # # ]
[ # # ]
899 : : }
900 : : //__________________________________________________________________________________________________
901 : 0 : Any AccessController::doRestricted(
902 : : Reference< security::XAction > const & xAction,
903 : : Reference< security::XAccessControlContext > const & xRestriction )
904 : : throw (Exception)
905 : : {
906 [ # # ]: 0 : if (rBHelper.bDisposed)
907 : : {
908 : : throw lang::DisposedException(
909 [ # # ][ # # ]: 0 : OUSTR("doRestricted() call on disposed AccessController!"), (OWeakObject *)this );
[ # # ]
910 : : }
911 : :
912 [ # # ]: 0 : if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
913 : 0 : return xAction->run();
914 : :
915 [ # # ]: 0 : if (xRestriction.is())
916 : : {
917 : 0 : Reference< XCurrentContext > xContext;
918 : 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
919 : :
920 : : // override restriction
921 : : Reference< XCurrentContext > xNewContext(
922 : : new acc_CurrentContext( xContext, acc_Intersection::create(
923 [ # # ][ # # ]: 0 : xRestriction, getDynamicRestriction( xContext ) ) ) );
[ # # ][ # # ]
[ # # ][ # # ]
924 [ # # ]: 0 : ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
925 [ # # ]: 0 : cc_reset reset( xContext.get() );
926 [ # # ][ # # ]: 0 : return xAction->run();
927 : : }
928 : : else
929 : : {
930 : 0 : return xAction->run();
931 : : }
932 : : }
933 : : //__________________________________________________________________________________________________
934 : 0 : Any AccessController::doPrivileged(
935 : : Reference< security::XAction > const & xAction,
936 : : Reference< security::XAccessControlContext > const & xRestriction )
937 : : throw (Exception)
938 : : {
939 [ # # ]: 0 : if (rBHelper.bDisposed)
940 : : {
941 : : throw lang::DisposedException(
942 [ # # ][ # # ]: 0 : OUSTR("doPrivileged() call on disposed AccessController!"), (OWeakObject *)this );
[ # # ]
943 : : }
944 : :
945 [ # # ]: 0 : if (OFF == m_mode) // no dynamic check will be performed
946 : : {
947 [ # # ][ # # ]: 0 : return xAction->run();
948 : : }
949 : :
950 : 0 : Reference< XCurrentContext > xContext;
951 : 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
952 : :
953 : : Reference< security::XAccessControlContext > xOldRestr(
954 [ # # ]: 0 : getDynamicRestriction( xContext ) );
955 : :
956 [ # # ]: 0 : if (xOldRestr.is()) // previous restriction
957 : : {
958 : : // override restriction
959 : : Reference< XCurrentContext > xNewContext(
960 [ # # ][ # # ]: 0 : new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) );
[ # # ][ # # ]
[ # # ]
961 [ # # ]: 0 : ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
962 [ # # ]: 0 : cc_reset reset( xContext.get() );
963 [ # # ][ # # ]: 0 : return xAction->run();
964 : : }
965 : : else // no previous restriction => never current restriction
966 : : {
967 [ # # ][ # # ]: 0 : return xAction->run();
968 : 0 : }
969 : : }
970 : : //__________________________________________________________________________________________________
971 : 0 : Reference< security::XAccessControlContext > AccessController::getContext()
972 : : throw (RuntimeException)
973 : : {
974 [ # # ]: 0 : if (rBHelper.bDisposed)
975 : : {
976 : : throw lang::DisposedException(
977 [ # # ][ # # ]: 0 : OUSTR("getContext() call on disposed AccessController!"), (OWeakObject *)this );
[ # # ]
978 : : }
979 : :
980 [ # # ]: 0 : if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
981 : : {
982 [ # # ][ # # ]: 0 : return new acc_Policy( PermissionCollection( new AllPermission() ) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
983 : : }
984 : :
985 : 0 : Reference< XCurrentContext > xContext;
986 : 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
987 : :
988 : : return acc_Intersection::create(
989 : : getDynamicRestriction( xContext ),
990 [ # # ][ # # ]: 0 : new acc_Policy( getEffectivePermissions( xContext, Any() ) ) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
991 : : }
992 : :
993 : : // XServiceInfo impl
994 : : //__________________________________________________________________________________________________
995 : 0 : OUString AccessController::getImplementationName()
996 : : throw (RuntimeException)
997 : : {
998 : 0 : return stoc_bootstrap::ac_getImplementationName();
999 : : }
1000 : : //__________________________________________________________________________________________________
1001 : 0 : sal_Bool AccessController::supportsService( OUString const & serviceName )
1002 : : throw (RuntimeException)
1003 : : {
1004 [ # # ]: 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
1005 : 0 : const OUString * pNames = aSNL.getConstArray();
1006 [ # # ]: 0 : for ( sal_Int32 nPos = aSNL.getLength(); --nPos; )
1007 : : {
1008 [ # # ]: 0 : if (serviceName.equals( pNames[ nPos ] ))
1009 : : {
1010 : 0 : return sal_True;
1011 : : }
1012 : : }
1013 [ # # ]: 0 : return sal_False;
1014 : : }
1015 : : //__________________________________________________________________________________________________
1016 : 0 : Sequence< OUString > AccessController::getSupportedServiceNames()
1017 : : throw (RuntimeException)
1018 : : {
1019 : 0 : return stoc_bootstrap::ac_getSupportedServiceNames();
1020 : : }
1021 : : }
1022 : : //##################################################################################################
1023 : : namespace stoc_bootstrap {
1024 : : //--------------------------------------------------------------------------------------------------
1025 : 0 : Reference< XInterface > SAL_CALL ac_create(
1026 : : Reference< XComponentContext > const & xComponentContext )
1027 : : SAL_THROW( (Exception) )
1028 : : {
1029 [ # # ]: 0 : return (OWeakObject *)new stoc_sec::AccessController( xComponentContext );
1030 : : }
1031 : : //--------------------------------------------------------------------------------------------------
1032 : 756 : Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW(())
1033 : : {
1034 : 756 : Sequence< OUString > aSNS( 1 );
1035 [ + - ][ + - ]: 756 : aSNS.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICE_NAME));
1036 : 756 : return aSNS;
1037 : : }
1038 : : //--------------------------------------------------------------------------------------------------
1039 : 10036 : OUString ac_getImplementationName() SAL_THROW(())
1040 : : {
1041 : 10036 : return OUSTR(IMPL_NAME);
1042 : : }
1043 : : //--------------------------------------------------------------------------------------------------
1044 : : Reference< XInterface > SAL_CALL filepolicy_create(
1045 : : Reference< XComponentContext > const & xComponentContext )
1046 : : SAL_THROW( (Exception) );
1047 : : //--------------------------------------------------------------------------------------------------
1048 : : Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW(());
1049 : : //--------------------------------------------------------------------------------------------------
1050 : : OUString filepolicy_getImplementationName() SAL_THROW(());
1051 [ + - ][ + - ]: 2226 : }
1052 : :
1053 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|