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 257 : 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_atomic_increment( &m_refcount );
305 0 : }
306 : //__________________________________________________________________________________________________
307 0 : void acc_CurrentContext::release()
308 : throw ()
309 : {
310 0 : if (! ::osl_atomic_decrement( &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 259 : Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW(())
1033 : {
1034 259 : Sequence< OUString > aSNS( 1 );
1035 259 : aSNS.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICE_NAME));
1036 259 : return aSNS;
1037 : }
1038 : //--------------------------------------------------------------------------------------------------
1039 3368 : OUString ac_getImplementationName() SAL_THROW(())
1040 : {
1041 3368 : 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 771 : }
1052 :
1053 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|