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_svl.hxx" 26 #include <svl/restrictedpaths.hxx> 27 28 #include <algorithm> 29 #include <osl/process.h> 30 #include <tools/urlobj.hxx> 31 #include <unotools/localfilehelper.hxx> 32 #include <unotools/syslocale.hxx> 33 34 namespace svt 35 { 36 namespace 37 { 38 // ---------------------------------------------------------------- 39 /** retrieves the value of an environment variable 40 @return <TRUE/> if and only if the retrieved string value is not empty 41 */ lcl_getEnvironmentValue(const sal_Char * _pAsciiEnvName,::rtl::OUString & _rValue)42 bool lcl_getEnvironmentValue( const sal_Char* _pAsciiEnvName, ::rtl::OUString& _rValue ) 43 { 44 _rValue = ::rtl::OUString(); 45 ::rtl::OUString sEnvName = ::rtl::OUString::createFromAscii( _pAsciiEnvName ); 46 osl_getEnvironment( sEnvName.pData, &_rValue.pData ); 47 return _rValue.getLength() != 0; 48 } 49 50 //----------------------------------------------------------------- lcl_convertStringListToUrls(const String & _rColonSeparatedList,::std::vector<String> & _rTokens,bool _bFinalSlash)51 void lcl_convertStringListToUrls( const String& _rColonSeparatedList, ::std::vector< String >& _rTokens, bool _bFinalSlash ) 52 { 53 const sal_Unicode s_cSeparator = 54 #if defined(WNT) 55 ';' 56 #else 57 ':' 58 #endif 59 ; 60 xub_StrLen nTokens = _rColonSeparatedList.GetTokenCount( s_cSeparator ); 61 _rTokens.resize( 0 ); _rTokens.reserve( nTokens ); 62 for ( xub_StrLen i=0; i<nTokens; ++i ) 63 { 64 // the current token in the list 65 String sCurrentToken = _rColonSeparatedList.GetToken( i, s_cSeparator ); 66 if ( !sCurrentToken.Len() ) 67 continue; 68 69 INetURLObject aCurrentURL; 70 71 String sURL; 72 if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCurrentToken, sURL ) ) 73 aCurrentURL = INetURLObject( sURL ); 74 else 75 { 76 // smart URL parsing, assuming FILE protocol 77 aCurrentURL = INetURLObject( sCurrentToken, INET_PROT_FILE ); 78 } 79 80 if ( _bFinalSlash ) 81 aCurrentURL.setFinalSlash( ); 82 else 83 aCurrentURL.removeFinalSlash( ); 84 _rTokens.push_back( aCurrentURL.GetMainURL( INetURLObject::NO_DECODE ) ); 85 } 86 } 87 88 } 89 90 //===================================================================== 91 //= CheckURLAllowed 92 //===================================================================== 93 struct CheckURLAllowed 94 { 95 protected: 96 #ifdef WNT 97 SvtSysLocale m_aSysLocale; 98 #endif 99 String m_sCheckURL; // the URL to check 100 bool m_bAllowParent; 101 public: CheckURLAllowedsvt::CheckURLAllowed102 inline CheckURLAllowed( const String& _rCheckURL, bool bAllowParent = true ) 103 :m_sCheckURL( _rCheckURL ), m_bAllowParent( bAllowParent ) 104 { 105 #ifdef WNT 106 // on windows, assume that the relevant file systems are case insensitive, 107 // thus normalize the URL 108 m_sCheckURL = m_aSysLocale.GetCharClass().toLower( m_sCheckURL, 0, m_sCheckURL.Len() ); 109 #endif 110 } 111 operator ()svt::CheckURLAllowed112 bool operator()( const String& _rApprovedURL ) 113 { 114 #ifdef WNT 115 // on windows, assume that the relevant file systems are case insensitive, 116 // thus normalize the URL 117 String sApprovedURL( m_aSysLocale.GetCharClass().toLower( _rApprovedURL, 0, _rApprovedURL.Len() ) ); 118 #else 119 String sApprovedURL( _rApprovedURL ); 120 #endif 121 122 xub_StrLen nLenApproved = sApprovedURL.Len(); 123 xub_StrLen nLenChecked = m_sCheckURL.Len(); 124 125 if ( nLenApproved > nLenChecked ) 126 { 127 if ( m_bAllowParent ) 128 { 129 if ( sApprovedURL.Search( m_sCheckURL ) == 0 ) 130 { 131 if ( ( m_sCheckURL.GetChar( nLenChecked - 1 ) == '/' ) 132 || ( sApprovedURL.GetChar( nLenChecked ) == '/' ) ) 133 return true; 134 } 135 } 136 else 137 { 138 // just a difference in final slash? 139 if ( ( nLenApproved == ( nLenChecked + 1 ) ) && 140 ( sApprovedURL.GetChar( nLenApproved - 1 ) == '/' ) ) 141 return true; 142 } 143 return false; 144 } 145 else if ( nLenApproved < nLenChecked ) 146 { 147 if ( m_sCheckURL.Search( sApprovedURL ) == 0 ) 148 { 149 if ( ( sApprovedURL.GetChar( nLenApproved - 1 ) == '/' ) 150 || ( m_sCheckURL.GetChar( nLenApproved ) == '/' ) ) 151 return true; 152 } 153 return false; 154 } 155 else 156 { 157 // strings have equal length 158 return ( sApprovedURL == m_sCheckURL ); 159 } 160 } 161 }; 162 163 //===================================================================== 164 //= RestrictedPaths 165 //===================================================================== 166 //--------------------------------------------------------------------- RestrictedPaths()167 RestrictedPaths::RestrictedPaths() 168 :m_bFilterIsEnabled( true ) 169 { 170 ::rtl::OUString sRestrictedPathList; 171 if ( lcl_getEnvironmentValue( "RestrictedPath", sRestrictedPathList ) ) 172 // append a final slash. This ensures that when we later on check 173 // for unrestricted paths, we don't allow paths like "/home/user35" just because 174 // "/home/user3" is allowed - with the final slash, we make it "/home/user3/". 175 lcl_convertStringListToUrls( sRestrictedPathList, m_aUnrestrictedURLs, true ); 176 } 177 ~RestrictedPaths()178 RestrictedPaths::~RestrictedPaths() {} 179 180 // -------------------------------------------------------------------- isUrlAllowed(const String & _rURL) const181 bool RestrictedPaths::isUrlAllowed( const String& _rURL ) const 182 { 183 if ( m_aUnrestrictedURLs.empty() || !m_bFilterIsEnabled ) 184 return true; 185 186 ::std::vector< String >::const_iterator aApprovedURL = ::std::find_if( 187 m_aUnrestrictedURLs.begin(), 188 m_aUnrestrictedURLs.end(), 189 CheckURLAllowed( _rURL, true ) 190 ); 191 192 return ( aApprovedURL != m_aUnrestrictedURLs.end() ); 193 } 194 195 // -------------------------------------------------------------------- isUrlAllowed(const String & _rURL,bool allowParents) const196 bool RestrictedPaths::isUrlAllowed( const String& _rURL, bool allowParents ) const 197 { 198 if ( m_aUnrestrictedURLs.empty() || !m_bFilterIsEnabled ) 199 return true; 200 201 ::std::vector< String >::const_iterator aApprovedURL = ::std::find_if( 202 m_aUnrestrictedURLs.begin(), 203 m_aUnrestrictedURLs.end(), 204 CheckURLAllowed( _rURL, allowParents ) 205 ); 206 207 return ( aApprovedURL != m_aUnrestrictedURLs.end() ); 208 } 209 210 } // namespace svt 211