1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26
27 #include <vector>
28
29 #include <osl/process.h>
30 #include <osl/socket.hxx>
31 #include <osl/mutex.hxx>
32
33 #include <rtl/string.hxx>
34 #include <rtl/ustrbuf.hxx>
35
36 #include <com/sun/star/security/RuntimePermission.hpp>
37 #include <com/sun/star/security/AllPermission.hpp>
38 #include <com/sun/star/io/FilePermission.hpp>
39 #include <com/sun/star/connection/SocketPermission.hpp>
40 #include <com/sun/star/security/AccessControlException.hpp>
41
42 #include "permissions.h"
43
44 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
45
46
47 using namespace ::std;
48 using namespace ::osl;
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using ::rtl::OUString;
52 using ::rtl::OUStringBuffer;
53
54 namespace stoc_sec
55 {
56
57 //--------------------------------------------------------------------------------------------------
makeMask(OUString const & items,char const * const * strings)58 static inline sal_Int32 makeMask(
59 OUString const & items, char const * const * strings ) SAL_THROW( () )
60 {
61 sal_Int32 mask = 0;
62
63 sal_Int32 n = 0;
64 do
65 {
66 OUString item( items.getToken( 0, ',', n ).trim() );
67 if (! item.getLength())
68 continue;
69 sal_Int32 nPos = 0;
70 while (strings[ nPos ])
71 {
72 if (item.equalsAscii( strings[ nPos ] ))
73 {
74 mask |= (0x80000000 >> nPos);
75 break;
76 }
77 ++nPos;
78 }
79 #if OSL_DEBUG_LEVEL > 0
80 if (! strings[ nPos ])
81 {
82 OUStringBuffer buf( 48 );
83 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("### ignoring unknown socket action: ") );
84 buf.append( item );
85 ::rtl::OString str( ::rtl::OUStringToOString(
86 buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
87 OSL_TRACE( str.getStr() );
88 }
89 #endif
90 }
91 while (n >= 0); // all items
92 return mask;
93 }
94 //--------------------------------------------------------------------------------------------------
makeStrings(sal_Int32 mask,char const * const * strings)95 static inline OUString makeStrings(
96 sal_Int32 mask, char const * const * strings ) SAL_THROW( () )
97 {
98 OUStringBuffer buf( 48 );
99 while (mask)
100 {
101 if (0x80000000 & mask)
102 {
103 buf.appendAscii( *strings );
104 if (mask << 1) // more items following
105 buf.append( (sal_Unicode)',' );
106 }
107 mask = (mask << 1);
108 ++strings;
109 }
110 return buf.makeStringAndClear();
111 }
112
113 //##################################################################################################
114
115 //==================================================================================================
116 class SocketPermission : public Permission
117 {
118 static char const * s_actions [];
119 sal_Int32 m_actions;
120
121 OUString m_host;
122 sal_Int32 m_lowerPort;
123 sal_Int32 m_upperPort;
124 mutable OUString m_ip;
125 mutable bool m_resolveErr;
126 mutable bool m_resolvedHost;
127 bool m_wildCardHost;
128
129 inline bool resolveHost() const SAL_THROW( () );
130
131 public:
132 SocketPermission(
133 connection::SocketPermission const & perm,
134 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
135 SAL_THROW( () );
136 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
137 virtual OUString toString() const SAL_THROW( () );
138 };
139 //__________________________________________________________________________________________________
140 char const * SocketPermission::s_actions [] = { "accept", "connect", "listen", "resolve", 0 };
141 //__________________________________________________________________________________________________
SocketPermission(connection::SocketPermission const & perm,::rtl::Reference<Permission> const & next)142 SocketPermission::SocketPermission(
143 connection::SocketPermission const & perm,
144 ::rtl::Reference< Permission > const & next )
145 SAL_THROW( () )
146 : Permission( SOCKET, next )
147 , m_actions( makeMask( perm.Actions, s_actions ) )
148 , m_host( perm.Host )
149 , m_lowerPort( 0 )
150 , m_upperPort( 65535 )
151 , m_resolveErr( false )
152 , m_resolvedHost( false )
153 , m_wildCardHost( perm.Host.getLength() && '*' == perm.Host.pData->buffer[ 0 ] )
154 {
155 if (0xe0000000 & m_actions) // if any (except resolve) is given => resolve implied
156 m_actions |= 0x10000000;
157
158 // separate host from portrange
159 sal_Int32 colon = m_host.indexOf( ':' );
160 if (colon >= 0) // port [range] given
161 {
162 sal_Int32 minus = m_host.indexOf( '-', colon +1 );
163 if (minus < 0)
164 {
165 m_lowerPort = m_upperPort = m_host.copy( colon +1 ).toInt32();
166 }
167 else if (minus == (colon +1)) // -N
168 {
169 m_upperPort = m_host.copy( minus +1 ).toInt32();
170 }
171 else if (minus == (m_host.getLength() -1)) // N-
172 {
173 m_lowerPort = m_host.copy( colon +1, m_host.getLength() -1 -colon -1 ).toInt32();
174 }
175 else // A-B
176 {
177 m_lowerPort = m_host.copy( colon +1, minus - colon -1 ).toInt32();
178 m_upperPort = m_host.copy( minus +1, m_host.getLength() -minus -1 ).toInt32();
179 }
180 m_host = m_host.copy( 0, colon );
181 }
182 }
183 //__________________________________________________________________________________________________
resolveHost() const184 inline bool SocketPermission::resolveHost() const SAL_THROW( () )
185 {
186 if (m_resolveErr)
187 return false;
188
189 if (! m_resolvedHost)
190 {
191 // dns lookup
192 SocketAddr addr;
193 SocketAddr::resolveHostname( m_host, addr );
194 OUString ip;
195 m_resolveErr = (::osl_Socket_Ok != ::osl_getDottedInetAddrOfSocketAddr(
196 addr.getHandle(), &ip.pData ));
197 if (m_resolveErr)
198 return false;
199
200 MutexGuard guard( Mutex::getGlobalMutex() );
201 if (! m_resolvedHost)
202 {
203 m_ip = ip;
204 m_resolvedHost = true;
205 }
206 }
207 return m_resolvedHost;
208 }
209 //__________________________________________________________________________________________________
implies(Permission const & perm) const210 bool SocketPermission::implies( Permission const & perm ) const SAL_THROW( () )
211 {
212 // check type
213 if (SOCKET != perm.m_type)
214 return false;
215 SocketPermission const & demanded = static_cast< SocketPermission const & >( perm );
216
217 // check actions
218 if ((m_actions & demanded.m_actions) != demanded.m_actions)
219 return false;
220
221 // check ports
222 if (demanded.m_lowerPort < m_lowerPort)
223 return false;
224 if (demanded.m_upperPort > m_upperPort)
225 return false;
226
227 // quick check host (DNS names: RFC 1034/1035)
228 if (m_host.equalsIgnoreAsciiCase( demanded.m_host ))
229 return true;
230 // check for host wildcards
231 if (m_wildCardHost)
232 {
233 OUString const & demanded_host = demanded.m_host;
234 if (demanded_host.getLength() <= m_host.getLength())
235 return false;
236 sal_Int32 len = m_host.getLength() -1; // skip star
237 return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
238 demanded_host.getStr() + demanded_host.getLength() - len, len,
239 m_host.pData->buffer + 1, len ));
240 }
241 if (demanded.m_wildCardHost)
242 return false;
243
244 // compare IP addresses
245 if (! resolveHost())
246 return false;
247 if (! demanded.resolveHost())
248 return false;
249 return (sal_False != m_ip.equals( demanded.m_ip ));
250 }
251 //__________________________________________________________________________________________________
toString() const252 OUString SocketPermission::toString() const SAL_THROW( () )
253 {
254 OUStringBuffer buf( 48 );
255 // host
256 buf.appendAscii(
257 RTL_CONSTASCII_STRINGPARAM("com.sun.star.connection.SocketPermission (host=\"") );
258 buf.append( m_host );
259 if (m_resolvedHost)
260 {
261 buf.append( (sal_Unicode)'[' );
262 buf.append( m_ip );
263 buf.append( (sal_Unicode)']' );
264 }
265 // port
266 if (0 != m_lowerPort || 65535 != m_upperPort)
267 {
268 buf.append( (sal_Unicode)':' );
269 if (m_lowerPort > 0)
270 buf.append( m_lowerPort );
271 if (m_upperPort > m_lowerPort)
272 {
273 buf.append( (sal_Unicode)'-' );
274 if (m_upperPort < 65535)
275 buf.append( m_upperPort );
276 }
277 }
278 // actions
279 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") );
280 buf.append( makeStrings( m_actions, s_actions ) );
281 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
282 return buf.makeStringAndClear();
283 }
284
285 //##################################################################################################
286
287 //==================================================================================================
288 class FilePermission : public Permission
289 {
290 static char const * s_actions [];
291 sal_Int32 m_actions;
292
293 OUString m_url;
294 bool m_allFiles;
295
296 public:
297 FilePermission(
298 io::FilePermission const & perm,
299 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
300 SAL_THROW( () );
301 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
302 virtual OUString toString() const SAL_THROW( () );
303 };
304 //__________________________________________________________________________________________________
305 char const * FilePermission::s_actions [] = { "read", "write", "execute", "delete", 0 };
306 //--------------------------------------------------------------------------------------------------
getWorkingDir()307 static OUString const & getWorkingDir() SAL_THROW( () )
308 {
309 static OUString * s_workingDir = 0;
310 if (! s_workingDir)
311 {
312 OUString workingDir;
313 ::osl_getProcessWorkingDir( &workingDir.pData );
314
315 MutexGuard guard( Mutex::getGlobalMutex() );
316 if (! s_workingDir)
317 {
318 static OUString s_dir( workingDir );
319 s_workingDir = &s_dir;
320 }
321 }
322 return *s_workingDir;
323 }
324 //__________________________________________________________________________________________________
FilePermission(io::FilePermission const & perm,::rtl::Reference<Permission> const & next)325 FilePermission::FilePermission(
326 io::FilePermission const & perm,
327 ::rtl::Reference< Permission > const & next )
328 SAL_THROW( () )
329 : Permission( FILE, next )
330 , m_actions( makeMask( perm.Actions, s_actions ) )
331 , m_url( perm.URL )
332 , m_allFiles( sal_False != perm.URL.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("<<ALL FILES>>")) )
333 {
334 if (! m_allFiles)
335 {
336 if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") ))
337 {
338 OUStringBuffer buf( 64 );
339 buf.append( getWorkingDir() );
340 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/*") );
341 m_url = buf.makeStringAndClear();
342 }
343 else if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("-") ))
344 {
345 OUStringBuffer buf( 64 );
346 buf.append( getWorkingDir() );
347 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/-") );
348 m_url = buf.makeStringAndClear();
349 }
350 else if (0 != m_url.compareToAscii( RTL_CONSTASCII_STRINGPARAM("file:///") ))
351 {
352 // relative path
353 OUString out;
354 oslFileError rc = ::osl_getAbsoluteFileURL(
355 getWorkingDir().pData, perm.URL.pData, &out.pData );
356 m_url = (osl_File_E_None == rc ? out : perm.URL); // fallback
357 }
358 #ifdef SAL_W32
359 // correct win drive letters
360 if (9 < m_url.getLength() && '|' == m_url[ 9 ]) // file:///X|
361 {
362 static OUString s_colon = OUSTR(":");
363 // common case in API is a ':' (sal), so convert '|' to ':'
364 m_url = m_url.replaceAt( 9, 1, s_colon );
365 }
366 #endif
367 }
368 }
369 //__________________________________________________________________________________________________
implies(Permission const & perm) const370 bool FilePermission::implies( Permission const & perm ) const SAL_THROW( () )
371 {
372 // check type
373 if (FILE != perm.m_type)
374 return false;
375 FilePermission const & demanded = static_cast< FilePermission const & >( perm );
376
377 // check actions
378 if ((m_actions & demanded.m_actions) != demanded.m_actions)
379 return false;
380
381 // check url
382 if (m_allFiles)
383 return true;
384 if (demanded.m_allFiles)
385 return false;
386
387 #ifdef SAL_W32
388 if (m_url.equalsIgnoreAsciiCase( demanded.m_url ))
389 return true;
390 #else
391 if (m_url.equals( demanded.m_url ))
392 return true;
393 #endif
394 if (m_url.getLength() > demanded.m_url.getLength())
395 return false;
396 // check /- wildcard: all files and recursive in that path
397 if (1 < m_url.getLength() &&
398 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/-" ))
399 {
400 // demanded url must start with granted path (including path trailing path sep)
401 sal_Int32 len = m_url.getLength() -1;
402 #ifdef SAL_W32
403 return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
404 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len ));
405 #else
406 return (0 == ::rtl_ustr_reverseCompare_WithLength(
407 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len ));
408 #endif
409 }
410 // check /* wildcard: all files in that path (not recursive!)
411 if (1 < m_url.getLength() &&
412 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/*" ))
413 {
414 // demanded url must start with granted path (including path trailing path sep)
415 sal_Int32 len = m_url.getLength() -1;
416 #ifdef SAL_W32
417 return ((0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
418 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) &&
419 (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes
420 #else
421 return ((0 == ::rtl_ustr_reverseCompare_WithLength(
422 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) &&
423 (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes
424 #endif
425 }
426 return false;
427 }
428 //__________________________________________________________________________________________________
toString() const429 OUString FilePermission::toString() const SAL_THROW( () )
430 {
431 OUStringBuffer buf( 48 );
432 // url
433 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.io.FilePermission (url=\"") );
434 buf.append( m_url );
435 // actions
436 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") );
437 buf.append( makeStrings( m_actions, s_actions ) );
438 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
439 return buf.makeStringAndClear();
440 }
441
442 //##################################################################################################
443
444 //==================================================================================================
445 class RuntimePermission : public Permission
446 {
447 OUString m_name;
448
449 public:
RuntimePermission(security::RuntimePermission const & perm,::rtl::Reference<Permission> const & next=::rtl::Reference<Permission> ())450 inline RuntimePermission(
451 security::RuntimePermission const & perm,
452 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
453 SAL_THROW( () )
454 : Permission( RUNTIME, next )
455 , m_name( perm.Name )
456 {}
457 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
458 virtual OUString toString() const SAL_THROW( () );
459 };
460 //__________________________________________________________________________________________________
implies(Permission const & perm) const461 bool RuntimePermission::implies( Permission const & perm ) const SAL_THROW( () )
462 {
463 // check type
464 if (RUNTIME != perm.m_type)
465 return false;
466 RuntimePermission const & demanded = static_cast< RuntimePermission const & >( perm );
467
468 // check name
469 return (sal_False != m_name.equals( demanded.m_name ));
470 }
471 //__________________________________________________________________________________________________
toString() const472 OUString RuntimePermission::toString() const SAL_THROW( () )
473 {
474 OUStringBuffer buf( 48 );
475 buf.appendAscii(
476 RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.RuntimePermission (name=\"") );
477 buf.append( m_name );
478 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
479 return buf.makeStringAndClear();
480 }
481
482 //##################################################################################################
483
484 //__________________________________________________________________________________________________
implies(Permission const &) const485 bool AllPermission::implies( Permission const & ) const SAL_THROW( () )
486 {
487 return true;
488 }
489 //__________________________________________________________________________________________________
toString() const490 OUString AllPermission::toString() const SAL_THROW( () )
491 {
492 return OUSTR("com.sun.star.security.AllPermission");
493 }
494
495 //##################################################################################################
496
497 //__________________________________________________________________________________________________
PermissionCollection(Sequence<Any> const & permissions,PermissionCollection const & addition)498 PermissionCollection::PermissionCollection(
499 Sequence< Any > const & permissions, PermissionCollection const & addition )
500 SAL_THROW( (RuntimeException) )
501 : m_head( addition.m_head )
502 {
503 Any const * perms = permissions.getConstArray();
504 for ( sal_Int32 nPos = permissions.getLength(); nPos--; )
505 {
506 Any const & perm = perms[ nPos ];
507 Type const & perm_type = perm.getValueType();
508
509 // supported permission types
510 if (perm_type.equals( ::getCppuType( (io::FilePermission const *)0 ) ))
511 {
512 m_head = new FilePermission(
513 *reinterpret_cast< io::FilePermission const * >( perm.pData ), m_head );
514 }
515 else if (perm_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) ))
516 {
517 m_head = new SocketPermission(
518 *reinterpret_cast< connection::SocketPermission const * >( perm.pData ), m_head );
519 }
520 else if (perm_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) ))
521 {
522 m_head = new RuntimePermission(
523 *reinterpret_cast< security::RuntimePermission const * >( perm.pData ), m_head );
524 }
525 else if (perm_type.equals( ::getCppuType( (security::AllPermission const *)0 ) ))
526 {
527 m_head = new AllPermission( m_head );
528 }
529 else
530 {
531 OUStringBuffer buf( 48 );
532 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
533 "checking for unsupported permission type: ") );
534 buf.append( perm_type.getTypeName() );
535 throw RuntimeException(
536 buf.makeStringAndClear(), Reference< XInterface >() );
537 }
538 }
539 }
540 #ifdef __DIAGNOSE
541 //__________________________________________________________________________________________________
toStrings() const542 Sequence< OUString > PermissionCollection::toStrings() const SAL_THROW( () )
543 {
544 vector< OUString > strings;
545 strings.reserve( 8 );
546 for ( Permission * perm = m_head.get(); perm; perm = perm->m_next.get() )
547 {
548 strings.push_back( perm->toString() );
549 }
550 return Sequence< OUString >(
551 strings.empty() ? 0 : &strings[ 0 ], strings.size() );
552 }
553 #endif
554 //__________________________________________________________________________________________________
__implies(::rtl::Reference<Permission> const & head,Permission const & demanded)555 inline static bool __implies(
556 ::rtl::Reference< Permission > const & head, Permission const & demanded ) SAL_THROW( () )
557 {
558 for ( Permission * perm = head.get(); perm; perm = perm->m_next.get() )
559 {
560 if (perm->implies( demanded ))
561 return true;
562 }
563 return false;
564 }
565
566 #ifdef __DIAGNOSE
567 //--------------------------------------------------------------------------------------------------
demanded_diag(Permission const & perm)568 static void demanded_diag(
569 Permission const & perm )
570 SAL_THROW( () )
571 {
572 OUStringBuffer buf( 48 );
573 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("demanding ") );
574 buf.append( perm.toString() );
575 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ok.") );
576 ::rtl::OString str(
577 ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
578 OSL_TRACE( str.getStr() );
579 }
580 #endif
581 //--------------------------------------------------------------------------------------------------
throwAccessControlException(Permission const & perm,Any const & demanded_perm)582 static void throwAccessControlException(
583 Permission const & perm, Any const & demanded_perm )
584 SAL_THROW( (security::AccessControlException) )
585 {
586 OUStringBuffer buf( 48 );
587 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") );
588 buf.append( perm.toString() );
589 throw security::AccessControlException(
590 buf.makeStringAndClear(), Reference< XInterface >(), demanded_perm );
591 }
592 //==================================================================================================
checkPermission(Any const & perm) const593 void PermissionCollection::checkPermission( Any const & perm ) const
594 SAL_THROW( (RuntimeException) )
595 {
596 Type const & demanded_type = perm.getValueType();
597
598 // supported permission types
599 // stack object of SimpleReferenceObject are ok, as long as they are not
600 // assigned to a ::rtl::Reference<> (=> delete this)
601 if (demanded_type.equals( ::getCppuType( (io::FilePermission const *)0 ) ))
602 {
603 FilePermission demanded(
604 *reinterpret_cast< io::FilePermission const * >( perm.pData ) );
605 if (__implies( m_head, demanded ))
606 {
607 #ifdef __DIAGNOSE
608 demanded_diag( demanded );
609 #endif
610 return;
611 }
612 throwAccessControlException( demanded, perm );
613 }
614 else if (demanded_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) ))
615 {
616 SocketPermission demanded(
617 *reinterpret_cast< connection::SocketPermission const * >( perm.pData ) );
618 if (__implies( m_head, demanded ))
619 {
620 #ifdef __DIAGNOSE
621 demanded_diag( demanded );
622 #endif
623 return;
624 }
625 throwAccessControlException( demanded, perm );
626 }
627 else if (demanded_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) ))
628 {
629 RuntimePermission demanded(
630 *reinterpret_cast< security::RuntimePermission const * >( perm.pData ) );
631 if (__implies( m_head, demanded ))
632 {
633 #ifdef __DIAGNOSE
634 demanded_diag( demanded );
635 #endif
636 return;
637 }
638 throwAccessControlException( demanded, perm );
639 }
640 else if (demanded_type.equals( ::getCppuType( (security::AllPermission const *)0 ) ))
641 {
642 AllPermission demanded;
643 if (__implies( m_head, demanded ))
644 {
645 #ifdef __DIAGNOSE
646 demanded_diag( demanded );
647 #endif
648 return;
649 }
650 throwAccessControlException( demanded, perm );
651 }
652 else
653 {
654 OUStringBuffer buf( 48 );
655 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("checking for unsupported permission type: ") );
656 buf.append( demanded_type.getTypeName() );
657 throw RuntimeException(
658 buf.makeStringAndClear(), Reference< XInterface >() );
659 }
660 }
661
662 }
663