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