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