1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_stoc.hxx"
30 
31 #include <stdio.h>
32 
33 #include <sal/main.h>
34 #include <osl/diagnose.h>
35 #include <osl/socket.hxx>
36 #include <rtl/string.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <uno/current_context.hxx>
39 
40 #include <cppuhelper/implbase1.hxx>
41 #include <cppuhelper/bootstrap.hxx>
42 #include <cppuhelper/access_control.hxx>
43 
44 #include <com/sun/star/lang/XComponent.hpp>
45 #include <com/sun/star/uno/XCurrentContext.hpp>
46 
47 #include <com/sun/star/io/FilePermission.hpp>
48 
49 #define USER_CREDS "access-control.user-credentials"
50 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
51 
52 
53 using namespace ::osl;
54 using namespace ::rtl;
55 using namespace ::cppu;
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 
59 //--------------------------------------------------------------------------------------------------
60 static OUString localhost( OUString const & addition ) SAL_THROW( () )
61 {
62     static OUString ip;
63     if (! ip.getLength())
64     {
65         // dns lookup
66         SocketAddr addr;
67         SocketAddr::resolveHostname( OUSTR("localhost"), addr );
68         ::oslSocketResult rc = ::osl_getDottedInetAddrOfSocketAddr( addr.getHandle(), &ip.pData );
69         if (::osl_Socket_Ok != rc)
70             fprintf(stdout, "### cannot resolve localhost!" );
71     }
72     OUStringBuffer buf( 48 );
73     buf.append( ip );
74     buf.append( addition );
75     return buf.makeStringAndClear();
76 }
77 
78 //--------------------------------------------------------------------------------------------------
79 static inline void dispose( Reference< XInterface > const & x )
80     SAL_THROW( (RuntimeException) )
81 {
82     Reference< lang::XComponent > xComp( x, UNO_QUERY );
83     if (xComp.is())
84     {
85         xComp->dispose();
86     }
87 }
88 //==================================================================================================
89 class user_CurrentContext
90     : public ImplHelper1< XCurrentContext >
91 {
92     oslInterlockedCount m_refcount;
93 
94     Reference< XCurrentContext > m_xDelegate;
95     Any m_userId;
96 
97 public:
98     inline user_CurrentContext(
99         Reference< XCurrentContext > const & xDelegate,
100         OUString const & userId )
101         SAL_THROW( () )
102         : m_refcount( 0 )
103         , m_xDelegate( xDelegate )
104         , m_userId( makeAny( userId ) )
105         {}
106 
107     // XInterface impl
108     virtual void SAL_CALL acquire()
109         throw ();
110     virtual void SAL_CALL release()
111         throw ();
112 
113     // XCurrentContext impl
114     virtual Any SAL_CALL getValueByName( OUString const & name )
115         throw (RuntimeException);
116 };
117 //__________________________________________________________________________________________________
118 void user_CurrentContext::acquire()
119     throw ()
120 {
121     ::osl_incrementInterlockedCount( &m_refcount );
122 }
123 //__________________________________________________________________________________________________
124 void user_CurrentContext::release()
125     throw ()
126 {
127     if (! ::osl_decrementInterlockedCount( &m_refcount ))
128     {
129         delete this;
130     }
131 }
132 //__________________________________________________________________________________________________
133 Any user_CurrentContext::getValueByName( OUString const & name )
134     throw (RuntimeException)
135 {
136     if (name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(USER_CREDS ".id") ))
137     {
138         return m_userId;
139     }
140     else if (m_xDelegate.is())
141     {
142         return m_xDelegate->getValueByName( name );
143     }
144     else
145     {
146         return Any();
147     }
148 }
149 
150 // prepends line number
151 #define CHECK( check, negative_test ) \
152 { \
153     try \
154     { \
155         if (negative_test) \
156         { \
157             bool thrown = true; \
158             try \
159             { \
160                 check; \
161                 thrown = false; \
162             } \
163             catch (RuntimeException &) \
164             { \
165             } \
166             if (! thrown) \
167             { \
168                 throw RuntimeException( \
169                     OUSTR("expected RuntimeException upon check!"), Reference< XInterface >() ); \
170             } \
171         } \
172         else \
173         { \
174             check; \
175         } \
176     } \
177     catch (RuntimeException & exc) \
178     { \
179         OUStringBuffer buf( 64 ); \
180         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[line ") ); \
181         buf.append( (sal_Int32)__LINE__ ); \
182         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); \
183         buf.append( exc.Message ); \
184         throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); \
185     } \
186 }
187 
188 /*
189 grant
190 {
191 permission com.sun.star.io.FilePermission "file:///usr/bin/ *", "read";
192 permission com.sun.star.io.FilePermission "file:///tmp/-", "read,write";
193 permission com.sun.star.io.FilePermission "file:///etc/profile", "read";
194 
195 permission com.sun.star.security.RuntimePermission "DEF";
196 
197 permission com.sun.star.connection.SocketPermission "127.0.0.1:-1023", "resolve, connect, listen";
198 permission com.sun.star.connection.SocketPermission "localhost:1024-", "accept, connect, listen, resolve,";
199 permission com.sun.star.connection.SocketPermission "*.sun.com:1024-", "resolve";
200 };
201 */
202 static void check_defaults_pos( AccessControl & ac, bool invert = false )
203 {
204     // positive tests
205     CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("read") ), invert );
206     CHECK( ac.checkFilePermission( OUSTR("file:///tmp/bla"), OUSTR("read,write") ), invert );
207     CHECK( ac.checkFilePermission( OUSTR("file:///tmp/path/path/bla"), OUSTR("write") ), invert );
208     CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile"), OUSTR("read") ), invert );
209     CHECK( ac.checkRuntimePermission( OUSTR("DEF") ), invert );
210     CHECK( ac.checkSocketPermission( OUSTR("localhost:1024"), OUSTR("connect") ), invert );
211     CHECK( ac.checkSocketPermission( OUSTR("localhost:65535"), OUSTR("resolve") ), invert );
212     CHECK( ac.checkSocketPermission( localhost(OUSTR(":2048")), OUSTR("accept,listen") ), invert );
213     CHECK( ac.checkSocketPermission( localhost(OUSTR(":1024-")), OUSTR("accept,connect,listen,resolve") ), invert );
214     CHECK( ac.checkSocketPermission( OUSTR("localhost:-1023"), OUSTR("resolve,listen,connect") ), invert );
215     CHECK( ac.checkSocketPermission( OUSTR("jl-1036.germany.sun.com:1024-"), OUSTR("resolve") ), invert );
216 }
217 static void check_defaults_neg( AccessControl & ac, bool invert = false )
218 {
219     // negative tests
220     CHECK( ac.checkFilePermission( OUSTR("file:///usr/tmp"), OUSTR("read") ), !invert );
221     CHECK( ac.checkFilePermission( OUSTR("file:///"), OUSTR("read") ), !invert );
222     CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin"), OUSTR("read") ), !invert );
223     CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("write") ), !invert );
224     CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("execute") ), !invert );
225     CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/path/bla"), OUSTR("read") ), !invert );
226     CHECK( ac.checkFilePermission( OUSTR("file:///tmp"), OUSTR("read") ), !invert );
227     CHECK( ac.checkFilePermission( OUSTR("file:///tmp/"), OUSTR("read") ), !invert );
228     CHECK( ac.checkFilePermission( OUSTR("file:///tm"), OUSTR("read") ), !invert );
229     CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile"), OUSTR("write") ), !invert );
230     CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile/bla"), OUSTR("read") ), !invert );
231     CHECK( ac.checkFilePermission( OUSTR("file:///etc/blabla"), OUSTR("read,write,execute") ), !invert );
232     CHECK( ac.checkFilePermission( OUSTR("file:///home/root"), OUSTR("read,write,execute") ), !invert );
233     CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("read,write,execute") ), !invert );
234     CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("delete") ), !invert );
235     CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUString() ), !invert );
236     CHECK( ac.checkRuntimePermission( OUSTR("ROOT") ), !invert );
237     CHECK( ac.checkSocketPermission( OUSTR("localhost:1023"), OUSTR("accept") ), !invert );
238     CHECK( ac.checkSocketPermission( OUSTR("localhost:123-"), OUSTR("accept") ), !invert );
239     CHECK( ac.checkSocketPermission( localhost(OUSTR(":-1023")), OUSTR("accept") ), !invert );
240     CHECK( ac.checkSocketPermission( OUSTR("localhost:-1023"), OUSTR("accept,resolve") ), !invert );
241     CHECK( ac.checkSocketPermission( OUSTR("sun.com:1024-"), OUSTR("resolve") ), !invert );
242 }
243 
244 /*
245 grant user "dbo"
246 {
247 permission com.sun.star.io.FilePermission "file:///home/dbo/-", "read,write";
248 permission com.sun.star.io.FilePermission "-", "read,write";
249 permission com.sun.star.io.FilePermission "file:///usr/local/dbo/ *", "read";
250 
251 permission com.sun.star.security.RuntimePermission "DBO";
252 
253 permission com.sun.star.connection.SocketPermission "dbo-1:1024-", "listen";
254 permission com.sun.star.connection.SocketPermission "dbo-11081:-1023", "resolve";
255 permission com.sun.star.connection.SocketPermission "dbo-11081:18", "listen";
256 permission com.sun.star.connection.SocketPermission "dbo-11081:20-24", "listen";
257 permission com.sun.star.connection.SocketPermission "dbo-11081", "connect";
258 };
259 */
260 static void check_dbo_pos( AccessControl & ac, bool invert = false )
261 {
262     check_defaults_pos( ac, invert );
263     // positive tests
264     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read") ), invert );
265     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("write") ), invert );
266     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), invert );
267     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/bla"), OUSTR("read,write") ), invert );
268     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read,write") ), invert );
269     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/*"), OUSTR("read") ), invert );
270     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/bla"), OUSTR("read") ), invert );
271     CHECK( ac.checkRuntimePermission( OUSTR("DBO") ), invert );
272     CHECK( ac.checkSocketPermission( OUSTR("dbo-1:1024-"), OUSTR("listen") ), invert );
273     CHECK( ac.checkSocketPermission( OUSTR("dbo-1:2048-3122"), OUSTR("listen") ), invert );
274     CHECK( ac.checkSocketPermission( OUSTR("dbo-1:2048-"), OUSTR("listen") ), invert );
275     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:-1023"), OUSTR("resolve") ), invert );
276     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:20-1023"), OUSTR("resolve") ), invert );
277     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:18"), OUSTR("listen") ), invert );
278     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:20-24"), OUSTR("listen") ), invert );
279     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("listen") ), invert );
280     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("connect") ), invert );
281     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("connect") ), invert );
282 }
283 static void check_dbo_neg( AccessControl & ac, bool invert = false )
284 {
285     check_defaults_neg( ac, invert );
286     // negative tests
287     CHECK( ac.checkFilePermission( OUSTR("file:///home/-"), OUSTR("read") ), !invert );
288     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read") ), !invert );
289     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("write") ), !invert );
290     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read,write") ), !invert );
291     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/bla"), OUSTR("read") ), !invert );
292     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read,execute") ), !invert );
293     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/-"), OUSTR("read") ), !invert );
294     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/bla"), OUSTR("read") ), !invert );
295     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/path/bla"), OUSTR("read") ), !invert );
296     CHECK( ac.checkRuntimePermission( OUSTR("JBU") ), !invert );
297     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("listen") ), !invert );
298     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("accept") ), !invert );
299     CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:22"), OUSTR("resolve") ), !invert );
300 }
301 
302 /*
303 grant user "jbu"
304 {
305 permission com.sun.star.io.FilePermission  "file:///home/jbu/-", "read,write";
306 permission com.sun.star.io.FilePermission "*", "read,write";
307 
308 permission com.sun.star.security.RuntimePermission "JBU";
309 
310 permission com.sun.star.connection.SocketPermission "jbu-11096","resolve";
311 };
312 */
313 static void check_jbu_pos( AccessControl & ac, bool invert = false )
314 {
315     check_defaults_pos( ac, invert );
316     // positive tests
317     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read") ), invert );
318     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("write") ), invert );
319     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read,write") ), invert );
320     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/bla"), OUSTR("read,write") ), invert );
321     CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/path/bla"), OUSTR("read,write") ), invert );
322     CHECK( ac.checkRuntimePermission( OUSTR("JBU") ), invert );
323     CHECK( ac.checkSocketPermission( OUSTR("jbu-11096"), OUSTR("resolve") ), invert );
324     CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:20-24"), OUSTR("resolve") ), invert );
325     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081.germany.sun.com:2048"), OUSTR("resolve") ), invert );
326 }
327 static void check_jbu_neg( AccessControl & ac, bool invert = false )
328 {
329     check_defaults_neg( ac, invert );
330     // negative tests
331     CHECK( ac.checkFilePermission( OUSTR("file:///home/-"), OUSTR("read") ), !invert );
332     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/bla"), OUSTR("read") ), !invert );
333     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read") ), !invert );
334     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read") ), !invert );
335     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("write") ), !invert );
336     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), !invert );
337     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/-"), OUSTR("read") ), !invert );
338     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/bla"), OUSTR("read") ), !invert );
339     CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/path/bla"), OUSTR("read") ), !invert );
340     CHECK( ac.checkRuntimePermission( OUSTR("DBO") ), !invert );
341     CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:20-24"), OUSTR("accept") ), !invert );
342     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("connect") ), !invert );
343     CHECK( ac.checkSocketPermission( OUSTR("dbo-11081.germany.sun.com"), OUSTR("connect") ), !invert );
344 }
345 
346 /*
347 grant principal "root"
348 {
349 permission com.sun.star.security.AllPermission;
350 };
351 */
352 //==================================================================================================
353 static void check_root_pos( AccessControl & ac, bool invert = false )
354 {
355     check_defaults_pos( ac, invert );
356     check_defaults_neg( ac, !invert );
357     check_dbo_pos( ac, invert );
358     check_dbo_neg( ac, !invert );
359     check_jbu_pos( ac, invert );
360     check_jbu_neg( ac, !invert );
361     // some more root positive
362     CHECK( ac.checkFilePermission( OUSTR("file:///etc/blabla"), OUSTR("read,write,execute") ), invert );
363     CHECK( ac.checkFilePermission( OUSTR("file:///home/root"), OUSTR("read,write,execute") ), invert );
364     CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("read,write,execute") ), invert );
365     CHECK( ac.checkRuntimePermission( OUSTR("ROOT") ), invert );
366 }
367 
368 //==================================================================================================
369 class acc_Restr
370     : public WeakImplHelper1< security::XAccessControlContext >
371 {
372     Any m_perm;
373 
374 public:
375     inline acc_Restr( Any const & perm = Any() ) SAL_THROW( () )
376         : m_perm( perm )
377         {}
378 
379     // XAccessControlContext impl
380     virtual void SAL_CALL checkPermission( Any const & perm )
381         throw (RuntimeException);
382 };
383 //__________________________________________________________________________________________________
384 void acc_Restr::checkPermission( Any const & perm )
385     throw (RuntimeException)
386 {
387     if (perm != m_perm)
388     {
389         throw security::AccessControlException(
390             OUSTR("dyn violation!"), Reference< XInterface >(), perm );
391     }
392 }
393 
394 typedef void (* t_action)( AccessControl &, Any const & arg );
395 
396 //==================================================================================================
397 class Action
398     : public WeakImplHelper1< security::XAction >
399 {
400     t_action m_action;
401     AccessControl & m_ac;
402     Any m_arg;
403 
404 public:
405     inline Action( t_action action, AccessControl & ac, Any const & arg = Any() ) SAL_THROW( () )
406         : m_action( action )
407         , m_ac( ac )
408         , m_arg( arg )
409         {}
410 
411     // XAction impl
412     virtual Any SAL_CALL run()
413         throw (Exception);
414 };
415 //__________________________________________________________________________________________________
416 Any Action::run()
417     throw (Exception)
418 {
419     (*m_action)( m_ac, m_arg );
420     return Any();
421 }
422 
423 //==================================================================================================
424 // static void restr_file_permissions( AccessControl & ac )
425 // {
426 //     // running in dbo's domain
427 //     /* permission com.sun.star.io.FilePermission "file:///home/dbo/-", ",,read , write "; */
428 //     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write,execute") ), true );
429 //     CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), false );
430 // }
431 //==================================================================================================
432 static void all_dbo_permissions( AccessControl & ac, Any const & )
433 {
434     check_dbo_pos( ac );
435     check_dbo_neg( ac );
436 }
437 //==================================================================================================
438 static void no_permissions( AccessControl & ac, Any const & arg )
439 {
440     check_dbo_pos( ac, true );
441     check_dbo_neg( ac );
442     // set privs to old dbo restr
443     Reference< security::XAccessControlContext > xContext;
444     OSL_VERIFY( arg >>= xContext );
445     ac->doPrivileged(
446         new Action( all_dbo_permissions, ac ),
447         xContext );
448 }
449 //==================================================================================================
450 static void check_dbo_dynamic( AccessControl & ac )
451 {
452     Any arg( makeAny( ac->getContext() ) );
453     ac->doRestricted(
454         new Action( no_permissions, ac, arg ),
455         new acc_Restr() );
456 }
457 
458 SAL_IMPLEMENT_MAIN()
459 {
460     try
461     {
462         // single-user test
463         Reference< XComponentContext > xContext( defaultBootstrap_InitialComponentContext(
464             OUSTR("../../test/security/test_security_singleuser.ini") ) );
465         {
466         ::fprintf( stderr, "[security test] single-user checking dbo..." );
467         AccessControl ac( xContext );
468         check_dbo_pos( ac );
469         check_dbo_neg( ac );
470         check_dbo_dynamic( ac );
471         ::fprintf( stderr, "dbo checked.\n" );
472         }
473 
474         // multi-user test
475         dispose( xContext );
476         xContext = defaultBootstrap_InitialComponentContext(
477             OUSTR("../../test/security/test_security.ini") ); // UNO_AC=on
478         AccessControl ac( xContext );
479 
480         {
481         // set up dbo current context
482         ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("dbo") ) );
483         ::fprintf( stderr, "[security test] multi-user checking dbo..." );
484         check_dbo_pos( ac );
485         check_dbo_neg( ac );
486         check_dbo_dynamic( ac );
487         ::fprintf( stderr, "dbo checked.\n" );
488         }
489         {
490         // set up jbu current context
491         ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("jbu") ) );
492         ::fprintf( stderr, "[security test] multi-user checking jbu..." );
493         check_jbu_pos( ac );
494         check_jbu_neg( ac );
495         ::fprintf( stderr, "jbu checked.\n" );
496         }
497         {
498         // set up root current context
499         ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("root") ) );
500         ::fprintf( stderr, "[security test] multi-user checking root..." );
501         check_root_pos( ac );
502         ::fprintf( stderr, "root checked.\n" );
503         }
504         {
505         // set up unknown guest user current context => default permissions
506         ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("guest") ) );
507         ::fprintf( stderr, "[security test] multi-user checking guest..." );
508         check_defaults_pos( ac );
509         check_defaults_neg( ac );
510         ::fprintf( stderr, "guest checked.\n" );
511         }
512 
513         dispose( xContext );
514         ::fprintf( stderr, "security test succeeded.\n" );
515         return 0;
516     }
517     catch (Exception & exc)
518     {
519         OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
520         ::fprintf( stderr, "[security test] error: %s!\n", str.getStr() );
521         return 1;
522     }
523 }
524