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