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