update dev300-m58
[ooovba.git] / stoc / source / security / permissions.cxx
blob45e96b3b05da7c45c1e0318c5b08e47a291a31d5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: permissions.cxx,v $
10 * $Revision: 1.11.16.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_stoc.hxx"
34 #include <vector>
36 #include <osl/process.h>
37 #include <osl/socket.hxx>
38 #include <osl/mutex.hxx>
40 #include <rtl/string.hxx>
41 #include <rtl/ustrbuf.hxx>
43 #include <com/sun/star/security/RuntimePermission.hpp>
44 #include <com/sun/star/security/AllPermission.hpp>
45 #include <com/sun/star/io/FilePermission.hpp>
46 #include <com/sun/star/connection/SocketPermission.hpp>
47 #include <com/sun/star/security/AccessControlException.hpp>
49 #include "permissions.h"
51 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
54 using namespace ::std;
55 using namespace ::osl;
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using ::rtl::OUString;
59 using ::rtl::OUStringBuffer;
61 namespace stoc_sec
64 //--------------------------------------------------------------------------------------------------
65 static inline sal_Int32 makeMask(
66 OUString const & items, char const * const * strings ) SAL_THROW( () )
68 sal_Int32 mask = 0;
70 sal_Int32 n = 0;
73 OUString item( items.getToken( 0, ',', n ).trim() );
74 if (! item.getLength())
75 continue;
76 sal_Int32 nPos = 0;
77 while (strings[ nPos ])
79 if (item.equalsAscii( strings[ nPos ] ))
81 mask |= (0x80000000 >> nPos);
82 break;
84 ++nPos;
86 #if OSL_DEBUG_LEVEL > 0
87 if (! strings[ nPos ])
89 OUStringBuffer buf( 48 );
90 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("### ignoring unknown socket action: ") );
91 buf.append( item );
92 ::rtl::OString str( ::rtl::OUStringToOString(
93 buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
94 OSL_TRACE( str.getStr() );
96 #endif
98 while (n >= 0); // all items
99 return mask;
101 //--------------------------------------------------------------------------------------------------
102 static inline OUString makeStrings(
103 sal_Int32 mask, char const * const * strings ) SAL_THROW( () )
105 OUStringBuffer buf( 48 );
106 while (mask)
108 if (0x80000000 & mask)
110 buf.appendAscii( *strings );
111 if (mask << 1) // more items following
112 buf.append( (sal_Unicode)',' );
114 mask = (mask << 1);
115 ++strings;
117 return buf.makeStringAndClear();
120 //##################################################################################################
122 //==================================================================================================
123 class SocketPermission : public Permission
125 static char const * s_actions [];
126 sal_Int32 m_actions;
128 OUString m_host;
129 sal_Int32 m_lowerPort;
130 sal_Int32 m_upperPort;
131 mutable OUString m_ip;
132 mutable bool m_resolveErr;
133 mutable bool m_resolvedHost;
134 bool m_wildCardHost;
136 inline bool resolveHost() const SAL_THROW( () );
138 public:
139 SocketPermission(
140 connection::SocketPermission const & perm,
141 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
142 SAL_THROW( () );
143 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
144 virtual OUString toString() const SAL_THROW( () );
146 //__________________________________________________________________________________________________
147 char const * SocketPermission::s_actions [] = { "accept", "connect", "listen", "resolve", 0 };
148 //__________________________________________________________________________________________________
149 SocketPermission::SocketPermission(
150 connection::SocketPermission const & perm,
151 ::rtl::Reference< Permission > const & next )
152 SAL_THROW( () )
153 : Permission( SOCKET, next )
154 , m_actions( makeMask( perm.Actions, s_actions ) )
155 , m_host( perm.Host )
156 , m_lowerPort( 0 )
157 , m_upperPort( 65535 )
158 , m_resolveErr( false )
159 , m_resolvedHost( false )
160 , m_wildCardHost( perm.Host.getLength() && '*' == perm.Host.pData->buffer[ 0 ] )
162 if (0xe0000000 & m_actions) // if any (except resolve) is given => resolve implied
163 m_actions |= 0x10000000;
165 // separate host from portrange
166 sal_Int32 colon = m_host.indexOf( ':' );
167 if (colon >= 0) // port [range] given
169 sal_Int32 minus = m_host.indexOf( '-', colon +1 );
170 if (minus < 0)
172 m_lowerPort = m_upperPort = m_host.copy( colon +1 ).toInt32();
174 else if (minus == (colon +1)) // -N
176 m_upperPort = m_host.copy( minus +1 ).toInt32();
178 else if (minus == (m_host.getLength() -1)) // N-
180 m_lowerPort = m_host.copy( colon +1, m_host.getLength() -1 -colon -1 ).toInt32();
182 else // A-B
184 m_lowerPort = m_host.copy( colon +1, minus - colon -1 ).toInt32();
185 m_upperPort = m_host.copy( minus +1, m_host.getLength() -minus -1 ).toInt32();
187 m_host = m_host.copy( 0, colon );
190 //__________________________________________________________________________________________________
191 inline bool SocketPermission::resolveHost() const SAL_THROW( () )
193 if (m_resolveErr)
194 return false;
196 if (! m_resolvedHost)
198 // dns lookup
199 SocketAddr addr;
200 SocketAddr::resolveHostname( m_host, addr );
201 OUString ip;
202 m_resolveErr = (::osl_Socket_Ok != ::osl_getDottedInetAddrOfSocketAddr(
203 addr.getHandle(), &ip.pData ));
204 if (m_resolveErr)
205 return false;
207 MutexGuard guard( Mutex::getGlobalMutex() );
208 if (! m_resolvedHost)
210 m_ip = ip;
211 m_resolvedHost = true;
214 return m_resolvedHost;
216 //__________________________________________________________________________________________________
217 bool SocketPermission::implies( Permission const & perm ) const SAL_THROW( () )
219 // check type
220 if (SOCKET != perm.m_type)
221 return false;
222 SocketPermission const & demanded = static_cast< SocketPermission const & >( perm );
224 // check actions
225 if ((m_actions & demanded.m_actions) != demanded.m_actions)
226 return false;
228 // check ports
229 if (demanded.m_lowerPort < m_lowerPort)
230 return false;
231 if (demanded.m_upperPort > m_upperPort)
232 return false;
234 // quick check host (DNS names: RFC 1034/1035)
235 if (m_host.equalsIgnoreAsciiCase( demanded.m_host ))
236 return true;
237 // check for host wildcards
238 if (m_wildCardHost)
240 OUString const & demanded_host = demanded.m_host;
241 if (demanded_host.getLength() <= m_host.getLength())
242 return false;
243 sal_Int32 len = m_host.getLength() -1; // skip star
244 return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
245 demanded_host.getStr() + demanded_host.getLength() - len, len,
246 m_host.pData->buffer + 1, len ));
248 if (demanded.m_wildCardHost)
249 return false;
251 // compare IP addresses
252 if (! resolveHost())
253 return false;
254 if (! demanded.resolveHost())
255 return false;
256 return (sal_False != m_ip.equals( demanded.m_ip ));
258 //__________________________________________________________________________________________________
259 OUString SocketPermission::toString() const SAL_THROW( () )
261 OUStringBuffer buf( 48 );
262 // host
263 buf.appendAscii(
264 RTL_CONSTASCII_STRINGPARAM("com.sun.star.connection.SocketPermission (host=\"") );
265 buf.append( m_host );
266 if (m_resolvedHost)
268 buf.append( (sal_Unicode)'[' );
269 buf.append( m_ip );
270 buf.append( (sal_Unicode)']' );
272 // port
273 if (0 != m_lowerPort || 65535 != m_upperPort)
275 buf.append( (sal_Unicode)':' );
276 if (m_lowerPort > 0)
277 buf.append( m_lowerPort );
278 if (m_upperPort > m_lowerPort)
280 buf.append( (sal_Unicode)'-' );
281 if (m_upperPort < 65535)
282 buf.append( m_upperPort );
285 // actions
286 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") );
287 buf.append( makeStrings( m_actions, s_actions ) );
288 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
289 return buf.makeStringAndClear();
292 //##################################################################################################
294 //==================================================================================================
295 class FilePermission : public Permission
297 static char const * s_actions [];
298 sal_Int32 m_actions;
300 OUString m_url;
301 bool m_allFiles;
303 public:
304 FilePermission(
305 io::FilePermission const & perm,
306 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
307 SAL_THROW( () );
308 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
309 virtual OUString toString() const SAL_THROW( () );
311 //__________________________________________________________________________________________________
312 char const * FilePermission::s_actions [] = { "read", "write", "execute", "delete", 0 };
313 //--------------------------------------------------------------------------------------------------
314 static OUString const & getWorkingDir() SAL_THROW( () )
316 static OUString * s_workingDir = 0;
317 if (! s_workingDir)
319 OUString workingDir;
320 ::osl_getProcessWorkingDir( &workingDir.pData );
322 MutexGuard guard( Mutex::getGlobalMutex() );
323 if (! s_workingDir)
325 static OUString s_dir( workingDir );
326 s_workingDir = &s_dir;
329 return *s_workingDir;
331 //__________________________________________________________________________________________________
332 FilePermission::FilePermission(
333 io::FilePermission const & perm,
334 ::rtl::Reference< Permission > const & next )
335 SAL_THROW( () )
336 : Permission( FILE, next )
337 , m_actions( makeMask( perm.Actions, s_actions ) )
338 , m_url( perm.URL )
339 , m_allFiles( sal_False != perm.URL.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("<<ALL FILES>>")) )
341 if (! m_allFiles)
343 if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") ))
345 OUStringBuffer buf( 64 );
346 buf.append( getWorkingDir() );
347 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/*") );
348 m_url = buf.makeStringAndClear();
350 else if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("-") ))
352 OUStringBuffer buf( 64 );
353 buf.append( getWorkingDir() );
354 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/-") );
355 m_url = buf.makeStringAndClear();
357 else if (0 != m_url.compareToAscii( RTL_CONSTASCII_STRINGPARAM("file:///") ))
359 // relative path
360 OUString out;
361 oslFileError rc = ::osl_getAbsoluteFileURL(
362 getWorkingDir().pData, perm.URL.pData, &out.pData );
363 m_url = (osl_File_E_None == rc ? out : perm.URL); // fallback
365 #ifdef SAL_W32
366 // correct win drive letters
367 if (9 < m_url.getLength() && '|' == m_url[ 9 ]) // file:///X|
369 static OUString s_colon = OUSTR(":");
370 // common case in API is a ':' (sal), so convert '|' to ':'
371 m_url = m_url.replaceAt( 9, 1, s_colon );
373 #endif
376 //__________________________________________________________________________________________________
377 bool FilePermission::implies( Permission const & perm ) const SAL_THROW( () )
379 // check type
380 if (FILE != perm.m_type)
381 return false;
382 FilePermission const & demanded = static_cast< FilePermission const & >( perm );
384 // check actions
385 if ((m_actions & demanded.m_actions) != demanded.m_actions)
386 return false;
388 // check url
389 if (m_allFiles)
390 return true;
391 if (demanded.m_allFiles)
392 return false;
394 #ifdef SAL_W32
395 if (m_url.equalsIgnoreAsciiCase( demanded.m_url ))
396 return true;
397 #else
398 if (m_url.equals( demanded.m_url ))
399 return true;
400 #endif
401 if (m_url.getLength() > demanded.m_url.getLength())
402 return false;
403 // check /- wildcard: all files and recursive in that path
404 if (1 < m_url.getLength() &&
405 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/-" ))
407 // demanded url must start with granted path (including path trailing path sep)
408 sal_Int32 len = m_url.getLength() -1;
409 #ifdef SAL_W32
410 return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
411 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len ));
412 #else
413 return (0 == ::rtl_ustr_reverseCompare_WithLength(
414 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len ));
415 #endif
417 // check /* wildcard: all files in that path (not recursive!)
418 if (1 < m_url.getLength() &&
419 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/*" ))
421 // demanded url must start with granted path (including path trailing path sep)
422 sal_Int32 len = m_url.getLength() -1;
423 #ifdef SAL_W32
424 return ((0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength(
425 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) &&
426 (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes
427 #else
428 return ((0 == ::rtl_ustr_reverseCompare_WithLength(
429 demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) &&
430 (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes
431 #endif
433 return false;
435 //__________________________________________________________________________________________________
436 OUString FilePermission::toString() const SAL_THROW( () )
438 OUStringBuffer buf( 48 );
439 // url
440 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.io.FilePermission (url=\"") );
441 buf.append( m_url );
442 // actions
443 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") );
444 buf.append( makeStrings( m_actions, s_actions ) );
445 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
446 return buf.makeStringAndClear();
449 //##################################################################################################
451 //==================================================================================================
452 class RuntimePermission : public Permission
454 OUString m_name;
456 public:
457 inline RuntimePermission(
458 security::RuntimePermission const & perm,
459 ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() )
460 SAL_THROW( () )
461 : Permission( RUNTIME, next )
462 , m_name( perm.Name )
464 virtual bool implies( Permission const & perm ) const SAL_THROW( () );
465 virtual OUString toString() const SAL_THROW( () );
467 //__________________________________________________________________________________________________
468 bool RuntimePermission::implies( Permission const & perm ) const SAL_THROW( () )
470 // check type
471 if (RUNTIME != perm.m_type)
472 return false;
473 RuntimePermission const & demanded = static_cast< RuntimePermission const & >( perm );
475 // check name
476 return (sal_False != m_name.equals( demanded.m_name ));
478 //__________________________________________________________________________________________________
479 OUString RuntimePermission::toString() const SAL_THROW( () )
481 OUStringBuffer buf( 48 );
482 buf.appendAscii(
483 RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.RuntimePermission (name=\"") );
484 buf.append( m_name );
485 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") );
486 return buf.makeStringAndClear();
489 //##################################################################################################
491 //__________________________________________________________________________________________________
492 bool AllPermission::implies( Permission const & ) const SAL_THROW( () )
494 return true;
496 //__________________________________________________________________________________________________
497 OUString AllPermission::toString() const SAL_THROW( () )
499 return OUSTR("com.sun.star.security.AllPermission");
502 //##################################################################################################
504 //__________________________________________________________________________________________________
505 PermissionCollection::PermissionCollection(
506 Sequence< Any > const & permissions, PermissionCollection const & addition )
507 SAL_THROW( (RuntimeException) )
508 : m_head( addition.m_head )
510 Any const * perms = permissions.getConstArray();
511 for ( sal_Int32 nPos = permissions.getLength(); nPos--; )
513 Any const & perm = perms[ nPos ];
514 Type const & perm_type = perm.getValueType();
516 // supported permission types
517 if (perm_type.equals( ::getCppuType( (io::FilePermission const *)0 ) ))
519 m_head = new FilePermission(
520 *reinterpret_cast< io::FilePermission const * >( perm.pData ), m_head );
522 else if (perm_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) ))
524 m_head = new SocketPermission(
525 *reinterpret_cast< connection::SocketPermission const * >( perm.pData ), m_head );
527 else if (perm_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) ))
529 m_head = new RuntimePermission(
530 *reinterpret_cast< security::RuntimePermission const * >( perm.pData ), m_head );
532 else if (perm_type.equals( ::getCppuType( (security::AllPermission const *)0 ) ))
534 m_head = new AllPermission( m_head );
536 else
538 OUStringBuffer buf( 48 );
539 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
540 "checking for unsupported permission type: ") );
541 buf.append( perm_type.getTypeName() );
542 throw RuntimeException(
543 buf.makeStringAndClear(), Reference< XInterface >() );
547 #ifdef __DIAGNOSE
548 //__________________________________________________________________________________________________
549 Sequence< OUString > PermissionCollection::toStrings() const SAL_THROW( () )
551 vector< OUString > strings;
552 strings.reserve( 8 );
553 for ( Permission * perm = m_head.get(); perm; perm = perm->m_next.get() )
555 strings.push_back( perm->toString() );
557 return Sequence< OUString >(
558 strings.empty() ? 0 : &strings[ 0 ], strings.size() );
560 #endif
561 //__________________________________________________________________________________________________
562 inline static bool __implies(
563 ::rtl::Reference< Permission > const & head, Permission const & demanded ) SAL_THROW( () )
565 for ( Permission * perm = head.get(); perm; perm = perm->m_next.get() )
567 if (perm->implies( demanded ))
568 return true;
570 return false;
573 #ifdef __DIAGNOSE
574 //--------------------------------------------------------------------------------------------------
575 static void demanded_diag(
576 Permission const & perm )
577 SAL_THROW( () )
579 OUStringBuffer buf( 48 );
580 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("demanding ") );
581 buf.append( perm.toString() );
582 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ok.") );
583 ::rtl::OString str(
584 ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
585 OSL_TRACE( str.getStr() );
587 #endif
588 //--------------------------------------------------------------------------------------------------
589 static void throwAccessControlException(
590 Permission const & perm, Any const & demanded_perm )
591 SAL_THROW( (security::AccessControlException) )
593 OUStringBuffer buf( 48 );
594 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") );
595 buf.append( perm.toString() );
596 throw security::AccessControlException(
597 buf.makeStringAndClear(), Reference< XInterface >(), demanded_perm );
599 //==================================================================================================
600 void PermissionCollection::checkPermission( Any const & perm ) const
601 SAL_THROW( (RuntimeException) )
603 Type const & demanded_type = perm.getValueType();
605 // supported permission types
606 // stack object of SimpleReferenceObject are ok, as long as they are not
607 // assigned to a ::rtl::Reference<> (=> delete this)
608 if (demanded_type.equals( ::getCppuType( (io::FilePermission const *)0 ) ))
610 FilePermission demanded(
611 *reinterpret_cast< io::FilePermission const * >( perm.pData ) );
612 if (__implies( m_head, demanded ))
614 #ifdef __DIAGNOSE
615 demanded_diag( demanded );
616 #endif
617 return;
619 throwAccessControlException( demanded, perm );
621 else if (demanded_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) ))
623 SocketPermission demanded(
624 *reinterpret_cast< connection::SocketPermission const * >( perm.pData ) );
625 if (__implies( m_head, demanded ))
627 #ifdef __DIAGNOSE
628 demanded_diag( demanded );
629 #endif
630 return;
632 throwAccessControlException( demanded, perm );
634 else if (demanded_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) ))
636 RuntimePermission demanded(
637 *reinterpret_cast< security::RuntimePermission const * >( perm.pData ) );
638 if (__implies( m_head, demanded ))
640 #ifdef __DIAGNOSE
641 demanded_diag( demanded );
642 #endif
643 return;
645 throwAccessControlException( demanded, perm );
647 else if (demanded_type.equals( ::getCppuType( (security::AllPermission const *)0 ) ))
649 AllPermission demanded;
650 if (__implies( m_head, demanded ))
652 #ifdef __DIAGNOSE
653 demanded_diag( demanded );
654 #endif
655 return;
657 throwAccessControlException( demanded, perm );
659 else
661 OUStringBuffer buf( 48 );
662 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("checking for unsupported permission type: ") );
663 buf.append( demanded_type.getTypeName() );
664 throw RuntimeException(
665 buf.makeStringAndClear(), Reference< XInterface >() );