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 ::com::sun::star::uno;
62 : using namespace stoc_sec;
63 :
64 : namespace {
65 :
66 : // static stuff initialized when loading lib
67 0 : 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, std::exception) SAL_OVERRIDE;
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, std::exception)
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, std::exception) SAL_OVERRIDE;
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, std::exception)
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, std::exception) SAL_OVERRIDE;
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, std::exception)
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 () SAL_OVERRIDE;
253 : virtual void SAL_CALL release()
254 : throw () SAL_OVERRIDE;
255 :
256 : // XCurrentContext impl
257 : virtual Any SAL_CALL getValueByName( OUString const & name )
258 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
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, std::exception)
296 : {
297 0 : if (name == 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 0 : static inline Reference< security::XAccessControlContext > getDynamicRestriction(
314 : Reference< XCurrentContext > const & xContext )
315 : SAL_THROW( (RuntimeException) )
316 : {
317 0 : if (xContext.is())
318 : {
319 0 : Any acc(xContext->getValueByName(OUString(s_acRestriction)));
320 0 : if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass)
321 : {
322 : // avoid ref-counting
323 : OUString const & typeName =
324 0 : *reinterpret_cast< OUString const * >( &acc.pType->pTypeName );
325 0 : if ( typeName == "com.sun.star.security.XAccessControlContext" )
326 : {
327 : return Reference< security::XAccessControlContext >(
328 0 : *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) );
329 : }
330 : else // try to query
331 : {
332 : return Reference< security::XAccessControlContext >::query(
333 0 : *reinterpret_cast< XInterface ** const >( acc.pData ) );
334 : }
335 0 : }
336 : }
337 0 : return Reference< security::XAccessControlContext >();
338 : }
339 :
340 : class cc_reset
341 : {
342 : void * m_cc;
343 : public:
344 0 : inline cc_reset( void * cc ) SAL_THROW(())
345 0 : : m_cc( cc ) {}
346 0 : inline ~cc_reset() SAL_THROW(())
347 0 : { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); }
348 : };
349 :
350 :
351 :
352 0 : struct MutexHolder
353 : {
354 : Mutex m_mutex;
355 : };
356 : typedef WeakComponentImplHelper3<
357 : security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper;
358 :
359 :
360 : class AccessController
361 : : public MutexHolder
362 : , public t_helper
363 : {
364 : Reference< XComponentContext > m_xComponentContext;
365 :
366 : Reference< security::XPolicy > m_xPolicy;
367 : Reference< security::XPolicy > const & getPolicy()
368 : SAL_THROW( (RuntimeException) );
369 :
370 : // mode
371 : enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode;
372 :
373 : PermissionCollection m_defaultPermissions;
374 : // for single-user mode
375 : PermissionCollection m_singleUserPermissions;
376 : OUString m_singleUserId;
377 : bool m_defaultPerm_init;
378 : bool m_singleUser_init;
379 : // for multi-user mode
380 : lru_cache< OUString, PermissionCollection, OUStringHash, equal_to< OUString > >
381 : m_user2permissions;
382 :
383 : ThreadData m_rec;
384 : typedef vector< pair< OUString, Any > > t_rec_vec;
385 : inline void clearPostPoned() SAL_THROW(());
386 : void checkAndClearPostPoned() SAL_THROW( (RuntimeException) );
387 :
388 : PermissionCollection getEffectivePermissions(
389 : Reference< XCurrentContext > const & xContext,
390 : Any const & demanded_perm )
391 : SAL_THROW( (RuntimeException) );
392 :
393 : protected:
394 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
395 :
396 : public:
397 : AccessController( Reference< XComponentContext > const & xComponentContext )
398 : SAL_THROW( (RuntimeException) );
399 : virtual ~AccessController()
400 : SAL_THROW(());
401 :
402 : // XInitialization impl
403 : virtual void SAL_CALL initialize(
404 : Sequence< Any > const & arguments )
405 : throw (Exception, std::exception) SAL_OVERRIDE;
406 :
407 : // XAccessController impl
408 : virtual void SAL_CALL checkPermission(
409 : Any const & perm )
410 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
411 : virtual Any SAL_CALL doRestricted(
412 : Reference< security::XAction > const & xAction,
413 : Reference< security::XAccessControlContext > const & xRestriction )
414 : throw (Exception, std::exception) SAL_OVERRIDE;
415 : virtual Any SAL_CALL doPrivileged(
416 : Reference< security::XAction > const & xAction,
417 : Reference< security::XAccessControlContext > const & xRestriction )
418 : throw (Exception, std::exception) SAL_OVERRIDE;
419 : virtual Reference< security::XAccessControlContext > SAL_CALL getContext()
420 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
421 :
422 : // XServiceInfo impl
423 : virtual OUString SAL_CALL getImplementationName()
424 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
425 : virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName )
426 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
427 : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
428 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
429 : };
430 :
431 0 : AccessController::AccessController( Reference< XComponentContext > const & xComponentContext )
432 : SAL_THROW( (RuntimeException) )
433 : : t_helper( m_mutex )
434 : , m_xComponentContext( xComponentContext )
435 : , m_mode( ON ) // default
436 : , m_defaultPerm_init( false )
437 : , m_singleUser_init( false )
438 0 : , m_rec( 0 )
439 : {
440 : // The .../mode value had originally been set in
441 : // cppu::add_access_control_entries (cppuhelper/source/servicefactory.cxx)
442 : // to something other than "off" depending on various UNO_AC* bootstrap
443 : // variables that are no longer supported, so this is mostly dead code now:
444 0 : OUString mode;
445 0 : if (m_xComponentContext->getValueByName( "/services/" SERVICE_NAME "/mode" ) >>= mode)
446 : {
447 0 : if ( mode == "off" )
448 : {
449 0 : m_mode = OFF;
450 : }
451 0 : else if ( mode == "on" )
452 : {
453 0 : m_mode = ON;
454 : }
455 0 : else if ( mode == "dynamic-only" )
456 : {
457 0 : m_mode = DYNAMIC_ONLY;
458 : }
459 0 : else if ( mode == "single-user" )
460 : {
461 0 : m_xComponentContext->getValueByName(
462 0 : "/services/" SERVICE_NAME "/single-user-id" ) >>= m_singleUserId;
463 0 : if (m_singleUserId.isEmpty())
464 : {
465 : throw RuntimeException(
466 : "expected a user id in component context entry "
467 : "\"/services/" SERVICE_NAME "/single-user-id\"!",
468 0 : (OWeakObject *)this );
469 : }
470 0 : m_mode = SINGLE_USER;
471 : }
472 0 : else if ( mode == "single-default-user" )
473 : {
474 0 : m_mode = SINGLE_DEFAULT_USER;
475 : }
476 : }
477 :
478 : // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process)
479 0 : if (ON == m_mode || DYNAMIC_ONLY == m_mode)
480 : {
481 0 : sal_Int32 cacheSize = 0; // multi-user cache size
482 0 : if (! (m_xComponentContext->getValueByName(
483 0 : "/services/" SERVICE_NAME "/user-cache-size" ) >>= cacheSize))
484 : {
485 0 : cacheSize = 128; // reasonable default?
486 : }
487 : #ifdef __CACHE_DIAGNOSE
488 : cacheSize = 2;
489 : #endif
490 0 : m_user2permissions.setSize( cacheSize );
491 0 : }
492 0 : }
493 :
494 0 : AccessController::~AccessController()
495 : SAL_THROW(())
496 0 : {}
497 :
498 0 : void AccessController::disposing()
499 : {
500 0 : m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY?
501 0 : m_xPolicy.clear();
502 0 : m_xComponentContext.clear();
503 0 : }
504 :
505 : // XInitialization impl
506 :
507 0 : void AccessController::initialize(
508 : Sequence< Any > const & arguments )
509 : throw (Exception, std::exception)
510 : {
511 : // xxx todo: review for forking
512 : // portal forking hack: re-initialize for another user-id
513 0 : if (SINGLE_USER != m_mode) // only if in single-user mode
514 : {
515 : throw RuntimeException(
516 0 : "invalid call: ac must be in \"single-user\" mode!", (OWeakObject *)this );
517 : }
518 0 : OUString userId;
519 0 : arguments[ 0 ] >>= userId;
520 0 : if ( userId.isEmpty() )
521 : {
522 : throw RuntimeException(
523 0 : "expected a user-id as first argument!", (OWeakObject *)this );
524 : }
525 : // assured that no sync is necessary: no check happens at this forking time
526 0 : m_singleUserId = userId;
527 0 : m_singleUser_init = false;
528 0 : }
529 :
530 :
531 0 : Reference< security::XPolicy > const & AccessController::getPolicy()
532 : SAL_THROW( (RuntimeException) )
533 : {
534 : // get policy singleton
535 0 : if (! m_xPolicy.is())
536 : {
537 0 : Reference< security::XPolicy > xPolicy;
538 0 : m_xComponentContext->getValueByName(
539 0 : "/singletons/com.sun.star.security.thePolicy" ) >>= xPolicy;
540 0 : if (xPolicy.is())
541 : {
542 0 : MutexGuard guard( m_mutex );
543 0 : if (! m_xPolicy.is())
544 : {
545 0 : m_xPolicy = xPolicy;
546 0 : }
547 : }
548 : else
549 : {
550 : throw SecurityException(
551 0 : "cannot get policy singleton!", (OWeakObject *)this );
552 0 : }
553 : }
554 0 : return m_xPolicy;
555 : }
556 :
557 : #ifdef __DIAGNOSE
558 : static void dumpPermissions(
559 : PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW(())
560 : {
561 : OUStringBuffer buf( 48 );
562 : if (!userId.isEmpty())
563 : {
564 : buf.append( "> dumping permissions of user \"" );
565 : buf.append( userId );
566 : buf.append( "\":" );
567 : }
568 : else
569 : {
570 : buf.append( "> dumping default permissions:" );
571 : }
572 : OString str( OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
573 : OSL_TRACE( "%s", str.getStr() );
574 : Sequence< OUString > permissions( collection.toStrings() );
575 : OUString const * p = permissions.getConstArray();
576 : for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos )
577 : {
578 : OString str( OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) );
579 : OSL_TRACE( "%s", str.getStr() );
580 : }
581 : OSL_TRACE( "> permission dump done" );
582 : }
583 : #endif
584 :
585 :
586 :
587 0 : inline void AccessController::clearPostPoned() SAL_THROW(())
588 : {
589 0 : delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
590 0 : m_rec.setData( 0 );
591 0 : }
592 :
593 0 : void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) )
594 : {
595 : // check postponed permissions
596 0 : boost::scoped_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) );
597 0 : m_rec.setData( 0 ); // takeover ownership
598 : OSL_ASSERT( rec.get() );
599 0 : if (rec.get())
600 : {
601 0 : t_rec_vec const & vec = *rec.get();
602 0 : switch (m_mode)
603 : {
604 : case SINGLE_USER:
605 : {
606 : OSL_ASSERT( m_singleUser_init );
607 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
608 : {
609 0 : pair< OUString, Any > const & p = vec[ nPos ];
610 : OSL_ASSERT( m_singleUserId.equals( p.first ) );
611 0 : m_singleUserPermissions.checkPermission( p.second );
612 : }
613 0 : break;
614 : }
615 : case SINGLE_DEFAULT_USER:
616 : {
617 : OSL_ASSERT( m_defaultPerm_init );
618 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
619 : {
620 0 : pair< OUString, Any > const & p = vec[ nPos ];
621 : OSL_ASSERT( p.first.isEmpty() ); // default-user
622 0 : m_defaultPermissions.checkPermission( p.second );
623 : }
624 0 : break;
625 : }
626 : case ON:
627 : {
628 0 : for ( size_t nPos = 0; nPos < vec.size(); ++nPos )
629 : {
630 0 : pair< OUString, Any > const & p = vec[ nPos ];
631 : PermissionCollection const * pPermissions;
632 : // lookup policy for user
633 : {
634 0 : MutexGuard guard( m_mutex );
635 0 : pPermissions = m_user2permissions.lookup( p.first );
636 : }
637 : OSL_ASSERT( pPermissions );
638 0 : if (pPermissions)
639 : {
640 0 : pPermissions->checkPermission( p.second );
641 : }
642 : }
643 0 : break;
644 : }
645 : default:
646 : OSL_FAIL( "### this should never be called in this ac mode!" );
647 0 : break;
648 : }
649 0 : }
650 0 : }
651 :
652 : /** this is the only function calling the policy singleton and thus has to take care
653 : of recurring calls!
654 :
655 : @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call
656 : which will be postponed for recurring calls
657 : */
658 0 : PermissionCollection AccessController::getEffectivePermissions(
659 : Reference< XCurrentContext > const & xContext,
660 : Any const & demanded_perm )
661 : SAL_THROW( (RuntimeException) )
662 : {
663 0 : OUString userId;
664 :
665 0 : switch (m_mode)
666 : {
667 : case SINGLE_USER:
668 : {
669 0 : if (m_singleUser_init)
670 0 : return m_singleUserPermissions;
671 0 : userId = m_singleUserId;
672 0 : break;
673 : }
674 : case SINGLE_DEFAULT_USER:
675 : {
676 0 : if (m_defaultPerm_init)
677 0 : return m_defaultPermissions;
678 0 : break;
679 : }
680 : case ON:
681 : {
682 0 : if (xContext.is())
683 : {
684 0 : xContext->getValueByName( USER_CREDS ".id" ) >>= userId;
685 : }
686 0 : if ( userId.isEmpty() )
687 : {
688 : throw SecurityException(
689 0 : "cannot determine current user in multi-user ac!", (OWeakObject *)this );
690 : }
691 :
692 : // lookup policy for user
693 0 : MutexGuard guard( m_mutex );
694 0 : PermissionCollection const * pPermissions = m_user2permissions.lookup( userId );
695 0 : if (pPermissions)
696 0 : return *pPermissions;
697 0 : break;
698 : }
699 : default:
700 : OSL_FAIL( "### this should never be called in this ac mode!" );
701 0 : return PermissionCollection();
702 : }
703 :
704 : // call on policy
705 : // iff this is a recurring call for the default user, then grant all permissions
706 0 : t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() );
707 0 : if (rec) // tls entry exists => this is recursive call
708 : {
709 0 : if (demanded_perm.hasValue())
710 : {
711 : // enqueue
712 0 : rec->push_back( pair< OUString, Any >( userId, demanded_perm ) );
713 : }
714 : #ifdef __DIAGNOSE
715 : OUStringBuffer buf( 48 );
716 : buf.append( "> info: recurring call of user \"" );
717 : buf.append( userId );
718 : buf.append( "\"" );
719 : OString str(
720 : OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
721 : OSL_TRACE( "%s", str.getStr() );
722 : #endif
723 0 : return PermissionCollection( new AllPermission() );
724 : }
725 : else // no tls
726 : {
727 0 : rec = new t_rec_vec;
728 0 : m_rec.setData( rec );
729 : }
730 :
731 : try // calls on API
732 : {
733 : // init default permissions
734 0 : if (! m_defaultPerm_init)
735 : {
736 : PermissionCollection defaultPermissions(
737 0 : getPolicy()->getDefaultPermissions() );
738 : // assign
739 0 : MutexGuard guard( m_mutex );
740 0 : if (! m_defaultPerm_init)
741 : {
742 0 : m_defaultPermissions = defaultPermissions;
743 0 : m_defaultPerm_init = true;
744 0 : }
745 : #ifdef __DIAGNOSE
746 : dumpPermissions( m_defaultPermissions );
747 : #endif
748 : }
749 :
750 0 : PermissionCollection ret;
751 :
752 : // init user permissions
753 0 : switch (m_mode)
754 : {
755 : case SINGLE_USER:
756 : {
757 0 : ret = PermissionCollection(
758 0 : getPolicy()->getPermissions( userId ), m_defaultPermissions );
759 : {
760 : // assign
761 0 : MutexGuard guard( m_mutex );
762 0 : if (m_singleUser_init)
763 : {
764 0 : ret = m_singleUserPermissions;
765 : }
766 : else
767 : {
768 0 : m_singleUserPermissions = ret;
769 0 : m_singleUser_init = true;
770 0 : }
771 : }
772 : #ifdef __DIAGNOSE
773 : dumpPermissions( ret, userId );
774 : #endif
775 0 : break;
776 : }
777 : case SINGLE_DEFAULT_USER:
778 : {
779 0 : ret = m_defaultPermissions;
780 0 : break;
781 : }
782 : case ON:
783 : {
784 0 : ret = PermissionCollection(
785 0 : getPolicy()->getPermissions( userId ), m_defaultPermissions );
786 : {
787 : // cache
788 0 : MutexGuard guard( m_mutex );
789 0 : m_user2permissions.set( userId, ret );
790 : }
791 : #ifdef __DIAGNOSE
792 : dumpPermissions( ret, userId );
793 : #endif
794 0 : break;
795 : }
796 : default:
797 0 : break;
798 : }
799 :
800 : // check postponed
801 0 : checkAndClearPostPoned();
802 0 : return ret;
803 : }
804 0 : catch (const security::AccessControlException & exc) // wrapped into DeploymentException
805 : {
806 0 : clearPostPoned(); // safety: exception could have happened before checking postponed?
807 0 : OUStringBuffer buf( 64 );
808 0 : buf.append( "deployment error (AccessControlException occurred): " );
809 0 : buf.append( exc.Message );
810 0 : throw DeploymentException( buf.makeStringAndClear(), exc.Context );
811 : }
812 0 : catch (RuntimeException &)
813 : {
814 : // dont check postponed, just cleanup
815 0 : clearPostPoned();
816 0 : delete reinterpret_cast< t_rec_vec * >( m_rec.getData() );
817 0 : m_rec.setData( 0 );
818 0 : throw;
819 : }
820 0 : catch (Exception &)
821 : {
822 : // check postponed permissions first
823 : // => AccessControlExceptions are errors, user exceptions not!
824 0 : checkAndClearPostPoned();
825 0 : throw;
826 : }
827 0 : catch (...)
828 : {
829 : // dont check postponed, just cleanup
830 0 : clearPostPoned();
831 0 : throw;
832 0 : }
833 : }
834 :
835 : // XAccessController impl
836 :
837 0 : void AccessController::checkPermission(
838 : Any const & perm )
839 : throw (RuntimeException, std::exception)
840 : {
841 0 : if (rBHelper.bDisposed)
842 : {
843 : throw lang::DisposedException(
844 0 : "checkPermission() call on disposed AccessController!", (OWeakObject *)this );
845 : }
846 :
847 0 : if (OFF == m_mode)
848 0 : return;
849 :
850 : // first dynamic check of ac contexts
851 0 : Reference< XCurrentContext > xContext;
852 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
853 0 : Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) );
854 0 : if (xACC.is())
855 : {
856 0 : xACC->checkPermission( perm );
857 : }
858 :
859 0 : if (DYNAMIC_ONLY == m_mode)
860 0 : return;
861 :
862 : // then static check
863 0 : getEffectivePermissions( xContext, perm ).checkPermission( perm );
864 : }
865 :
866 0 : Any AccessController::doRestricted(
867 : Reference< security::XAction > const & xAction,
868 : Reference< security::XAccessControlContext > const & xRestriction )
869 : throw (Exception, std::exception)
870 : {
871 0 : if (rBHelper.bDisposed)
872 : {
873 : throw lang::DisposedException(
874 0 : "doRestricted() call on disposed AccessController!", (OWeakObject *)this );
875 : }
876 :
877 0 : if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
878 0 : return xAction->run();
879 :
880 0 : if (xRestriction.is())
881 : {
882 0 : Reference< XCurrentContext > xContext;
883 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
884 :
885 : // override restriction
886 : Reference< XCurrentContext > xNewContext(
887 : new acc_CurrentContext( xContext, acc_Intersection::create(
888 0 : xRestriction, getDynamicRestriction( xContext ) ) ) );
889 0 : ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
890 0 : cc_reset reset( xContext.get() );
891 0 : return xAction->run();
892 : }
893 : else
894 : {
895 0 : return xAction->run();
896 : }
897 : }
898 :
899 0 : Any AccessController::doPrivileged(
900 : Reference< security::XAction > const & xAction,
901 : Reference< security::XAccessControlContext > const & xRestriction )
902 : throw (Exception, std::exception)
903 : {
904 0 : if (rBHelper.bDisposed)
905 : {
906 : throw lang::DisposedException(
907 0 : "doPrivileged() call on disposed AccessController!", (OWeakObject *)this );
908 : }
909 :
910 0 : if (OFF == m_mode) // no dynamic check will be performed
911 : {
912 0 : return xAction->run();
913 : }
914 :
915 0 : Reference< XCurrentContext > xContext;
916 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
917 :
918 : Reference< security::XAccessControlContext > xOldRestr(
919 0 : getDynamicRestriction( xContext ) );
920 :
921 0 : if (xOldRestr.is()) // previous restriction
922 : {
923 : // override restriction
924 : Reference< XCurrentContext > xNewContext(
925 0 : new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) );
926 0 : ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 );
927 0 : cc_reset reset( xContext.get() );
928 0 : return xAction->run();
929 : }
930 : else // no previous restriction => never current restriction
931 : {
932 0 : return xAction->run();
933 0 : }
934 : }
935 :
936 0 : Reference< security::XAccessControlContext > AccessController::getContext()
937 : throw (RuntimeException, std::exception)
938 : {
939 0 : if (rBHelper.bDisposed)
940 : {
941 : throw lang::DisposedException(
942 0 : "getContext() call on disposed AccessController!", (OWeakObject *)this );
943 : }
944 :
945 0 : if (OFF == m_mode) // optimize this way, because no dynamic check will be performed
946 : {
947 0 : return new acc_Policy( PermissionCollection( new AllPermission() ) );
948 : }
949 :
950 0 : Reference< XCurrentContext > xContext;
951 0 : ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 );
952 :
953 : return acc_Intersection::create(
954 : getDynamicRestriction( xContext ),
955 0 : new acc_Policy( getEffectivePermissions( xContext, Any() ) ) );
956 : }
957 :
958 : // XServiceInfo impl
959 :
960 0 : OUString AccessController::getImplementationName()
961 : throw (RuntimeException, std::exception)
962 : {
963 0 : return OUString("com.sun.star.security.comp.stoc.AccessController");
964 : }
965 :
966 0 : sal_Bool AccessController::supportsService( OUString const & serviceName )
967 : throw (RuntimeException, std::exception)
968 : {
969 0 : return cppu::supportsService(this, serviceName);
970 : }
971 :
972 0 : Sequence< OUString > AccessController::getSupportedServiceNames()
973 : throw (RuntimeException, std::exception)
974 : {
975 0 : Sequence< OUString > aSNS( 1 );
976 0 : aSNS[0] = OUString(SERVICE_NAME);
977 0 : return aSNS;
978 : }
979 :
980 : }
981 :
982 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
983 0 : com_sun_star_security_comp_stoc_AccessController_get_implementation(
984 : css::uno::XComponentContext *context,
985 : css::uno::Sequence<css::uno::Any> const &)
986 : {
987 0 : return cppu::acquire(new AccessController(context));
988 0 : }
989 :
990 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|