1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_svl.hxx" 26*b1cdbd2cSJim Jagielski #include <svl/restrictedpaths.hxx> 27*b1cdbd2cSJim Jagielski 28*b1cdbd2cSJim Jagielski #include <algorithm> 29*b1cdbd2cSJim Jagielski #include <osl/process.h> 30*b1cdbd2cSJim Jagielski #include <tools/urlobj.hxx> 31*b1cdbd2cSJim Jagielski #include <unotools/localfilehelper.hxx> 32*b1cdbd2cSJim Jagielski #include <unotools/syslocale.hxx> 33*b1cdbd2cSJim Jagielski 34*b1cdbd2cSJim Jagielski namespace svt 35*b1cdbd2cSJim Jagielski { 36*b1cdbd2cSJim Jagielski namespace 37*b1cdbd2cSJim Jagielski { 38*b1cdbd2cSJim Jagielski // ---------------------------------------------------------------- 39*b1cdbd2cSJim Jagielski /** retrieves the value of an environment variable 40*b1cdbd2cSJim Jagielski @return <TRUE/> if and only if the retrieved string value is not empty 41*b1cdbd2cSJim Jagielski */ lcl_getEnvironmentValue(const sal_Char * _pAsciiEnvName,::rtl::OUString & _rValue)42*b1cdbd2cSJim Jagielski bool lcl_getEnvironmentValue( const sal_Char* _pAsciiEnvName, ::rtl::OUString& _rValue ) 43*b1cdbd2cSJim Jagielski { 44*b1cdbd2cSJim Jagielski _rValue = ::rtl::OUString(); 45*b1cdbd2cSJim Jagielski ::rtl::OUString sEnvName = ::rtl::OUString::createFromAscii( _pAsciiEnvName ); 46*b1cdbd2cSJim Jagielski osl_getEnvironment( sEnvName.pData, &_rValue.pData ); 47*b1cdbd2cSJim Jagielski return _rValue.getLength() != 0; 48*b1cdbd2cSJim Jagielski } 49*b1cdbd2cSJim Jagielski 50*b1cdbd2cSJim Jagielski //----------------------------------------------------------------- lcl_convertStringListToUrls(const String & _rColonSeparatedList,::std::vector<String> & _rTokens,bool _bFinalSlash)51*b1cdbd2cSJim Jagielski void lcl_convertStringListToUrls( const String& _rColonSeparatedList, ::std::vector< String >& _rTokens, bool _bFinalSlash ) 52*b1cdbd2cSJim Jagielski { 53*b1cdbd2cSJim Jagielski const sal_Unicode s_cSeparator = 54*b1cdbd2cSJim Jagielski #if defined(WNT) 55*b1cdbd2cSJim Jagielski ';' 56*b1cdbd2cSJim Jagielski #else 57*b1cdbd2cSJim Jagielski ':' 58*b1cdbd2cSJim Jagielski #endif 59*b1cdbd2cSJim Jagielski ; 60*b1cdbd2cSJim Jagielski xub_StrLen nTokens = _rColonSeparatedList.GetTokenCount( s_cSeparator ); 61*b1cdbd2cSJim Jagielski _rTokens.resize( 0 ); _rTokens.reserve( nTokens ); 62*b1cdbd2cSJim Jagielski for ( xub_StrLen i=0; i<nTokens; ++i ) 63*b1cdbd2cSJim Jagielski { 64*b1cdbd2cSJim Jagielski // the current token in the list 65*b1cdbd2cSJim Jagielski String sCurrentToken = _rColonSeparatedList.GetToken( i, s_cSeparator ); 66*b1cdbd2cSJim Jagielski if ( !sCurrentToken.Len() ) 67*b1cdbd2cSJim Jagielski continue; 68*b1cdbd2cSJim Jagielski 69*b1cdbd2cSJim Jagielski INetURLObject aCurrentURL; 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski String sURL; 72*b1cdbd2cSJim Jagielski if ( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCurrentToken, sURL ) ) 73*b1cdbd2cSJim Jagielski aCurrentURL = INetURLObject( sURL ); 74*b1cdbd2cSJim Jagielski else 75*b1cdbd2cSJim Jagielski { 76*b1cdbd2cSJim Jagielski // smart URL parsing, assuming FILE protocol 77*b1cdbd2cSJim Jagielski aCurrentURL = INetURLObject( sCurrentToken, INET_PROT_FILE ); 78*b1cdbd2cSJim Jagielski } 79*b1cdbd2cSJim Jagielski 80*b1cdbd2cSJim Jagielski if ( _bFinalSlash ) 81*b1cdbd2cSJim Jagielski aCurrentURL.setFinalSlash( ); 82*b1cdbd2cSJim Jagielski else 83*b1cdbd2cSJim Jagielski aCurrentURL.removeFinalSlash( ); 84*b1cdbd2cSJim Jagielski _rTokens.push_back( aCurrentURL.GetMainURL( INetURLObject::NO_DECODE ) ); 85*b1cdbd2cSJim Jagielski } 86*b1cdbd2cSJim Jagielski } 87*b1cdbd2cSJim Jagielski 88*b1cdbd2cSJim Jagielski } 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski //===================================================================== 91*b1cdbd2cSJim Jagielski //= CheckURLAllowed 92*b1cdbd2cSJim Jagielski //===================================================================== 93*b1cdbd2cSJim Jagielski struct CheckURLAllowed 94*b1cdbd2cSJim Jagielski { 95*b1cdbd2cSJim Jagielski protected: 96*b1cdbd2cSJim Jagielski #ifdef WNT 97*b1cdbd2cSJim Jagielski SvtSysLocale m_aSysLocale; 98*b1cdbd2cSJim Jagielski #endif 99*b1cdbd2cSJim Jagielski String m_sCheckURL; // the URL to check 100*b1cdbd2cSJim Jagielski bool m_bAllowParent; 101*b1cdbd2cSJim Jagielski public: CheckURLAllowedsvt::CheckURLAllowed102*b1cdbd2cSJim Jagielski inline CheckURLAllowed( const String& _rCheckURL, bool bAllowParent = true ) 103*b1cdbd2cSJim Jagielski :m_sCheckURL( _rCheckURL ), m_bAllowParent( bAllowParent ) 104*b1cdbd2cSJim Jagielski { 105*b1cdbd2cSJim Jagielski #ifdef WNT 106*b1cdbd2cSJim Jagielski // on windows, assume that the relevant file systems are case insensitive, 107*b1cdbd2cSJim Jagielski // thus normalize the URL 108*b1cdbd2cSJim Jagielski m_sCheckURL = m_aSysLocale.GetCharClass().toLower( m_sCheckURL, 0, m_sCheckURL.Len() ); 109*b1cdbd2cSJim Jagielski #endif 110*b1cdbd2cSJim Jagielski } 111*b1cdbd2cSJim Jagielski operator ()svt::CheckURLAllowed112*b1cdbd2cSJim Jagielski bool operator()( const String& _rApprovedURL ) 113*b1cdbd2cSJim Jagielski { 114*b1cdbd2cSJim Jagielski #ifdef WNT 115*b1cdbd2cSJim Jagielski // on windows, assume that the relevant file systems are case insensitive, 116*b1cdbd2cSJim Jagielski // thus normalize the URL 117*b1cdbd2cSJim Jagielski String sApprovedURL( m_aSysLocale.GetCharClass().toLower( _rApprovedURL, 0, _rApprovedURL.Len() ) ); 118*b1cdbd2cSJim Jagielski #else 119*b1cdbd2cSJim Jagielski String sApprovedURL( _rApprovedURL ); 120*b1cdbd2cSJim Jagielski #endif 121*b1cdbd2cSJim Jagielski 122*b1cdbd2cSJim Jagielski xub_StrLen nLenApproved = sApprovedURL.Len(); 123*b1cdbd2cSJim Jagielski xub_StrLen nLenChecked = m_sCheckURL.Len(); 124*b1cdbd2cSJim Jagielski 125*b1cdbd2cSJim Jagielski if ( nLenApproved > nLenChecked ) 126*b1cdbd2cSJim Jagielski { 127*b1cdbd2cSJim Jagielski if ( m_bAllowParent ) 128*b1cdbd2cSJim Jagielski { 129*b1cdbd2cSJim Jagielski if ( sApprovedURL.Search( m_sCheckURL ) == 0 ) 130*b1cdbd2cSJim Jagielski { 131*b1cdbd2cSJim Jagielski if ( ( m_sCheckURL.GetChar( nLenChecked - 1 ) == '/' ) 132*b1cdbd2cSJim Jagielski || ( sApprovedURL.GetChar( nLenChecked ) == '/' ) ) 133*b1cdbd2cSJim Jagielski return true; 134*b1cdbd2cSJim Jagielski } 135*b1cdbd2cSJim Jagielski } 136*b1cdbd2cSJim Jagielski else 137*b1cdbd2cSJim Jagielski { 138*b1cdbd2cSJim Jagielski // just a difference in final slash? 139*b1cdbd2cSJim Jagielski if ( ( nLenApproved == ( nLenChecked + 1 ) ) && 140*b1cdbd2cSJim Jagielski ( sApprovedURL.GetChar( nLenApproved - 1 ) == '/' ) ) 141*b1cdbd2cSJim Jagielski return true; 142*b1cdbd2cSJim Jagielski } 143*b1cdbd2cSJim Jagielski return false; 144*b1cdbd2cSJim Jagielski } 145*b1cdbd2cSJim Jagielski else if ( nLenApproved < nLenChecked ) 146*b1cdbd2cSJim Jagielski { 147*b1cdbd2cSJim Jagielski if ( m_sCheckURL.Search( sApprovedURL ) == 0 ) 148*b1cdbd2cSJim Jagielski { 149*b1cdbd2cSJim Jagielski if ( ( sApprovedURL.GetChar( nLenApproved - 1 ) == '/' ) 150*b1cdbd2cSJim Jagielski || ( m_sCheckURL.GetChar( nLenApproved ) == '/' ) ) 151*b1cdbd2cSJim Jagielski return true; 152*b1cdbd2cSJim Jagielski } 153*b1cdbd2cSJim Jagielski return false; 154*b1cdbd2cSJim Jagielski } 155*b1cdbd2cSJim Jagielski else 156*b1cdbd2cSJim Jagielski { 157*b1cdbd2cSJim Jagielski // strings have equal length 158*b1cdbd2cSJim Jagielski return ( sApprovedURL == m_sCheckURL ); 159*b1cdbd2cSJim Jagielski } 160*b1cdbd2cSJim Jagielski } 161*b1cdbd2cSJim Jagielski }; 162*b1cdbd2cSJim Jagielski 163*b1cdbd2cSJim Jagielski //===================================================================== 164*b1cdbd2cSJim Jagielski //= RestrictedPaths 165*b1cdbd2cSJim Jagielski //===================================================================== 166*b1cdbd2cSJim Jagielski //--------------------------------------------------------------------- RestrictedPaths()167*b1cdbd2cSJim Jagielski RestrictedPaths::RestrictedPaths() 168*b1cdbd2cSJim Jagielski :m_bFilterIsEnabled( true ) 169*b1cdbd2cSJim Jagielski { 170*b1cdbd2cSJim Jagielski ::rtl::OUString sRestrictedPathList; 171*b1cdbd2cSJim Jagielski if ( lcl_getEnvironmentValue( "RestrictedPath", sRestrictedPathList ) ) 172*b1cdbd2cSJim Jagielski // append a final slash. This ensures that when we later on check 173*b1cdbd2cSJim Jagielski // for unrestricted paths, we don't allow paths like "/home/user35" just because 174*b1cdbd2cSJim Jagielski // "/home/user3" is allowed - with the final slash, we make it "/home/user3/". 175*b1cdbd2cSJim Jagielski lcl_convertStringListToUrls( sRestrictedPathList, m_aUnrestrictedURLs, true ); 176*b1cdbd2cSJim Jagielski } 177*b1cdbd2cSJim Jagielski ~RestrictedPaths()178*b1cdbd2cSJim Jagielski RestrictedPaths::~RestrictedPaths() {} 179*b1cdbd2cSJim Jagielski 180*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------- isUrlAllowed(const String & _rURL) const181*b1cdbd2cSJim Jagielski bool RestrictedPaths::isUrlAllowed( const String& _rURL ) const 182*b1cdbd2cSJim Jagielski { 183*b1cdbd2cSJim Jagielski if ( m_aUnrestrictedURLs.empty() || !m_bFilterIsEnabled ) 184*b1cdbd2cSJim Jagielski return true; 185*b1cdbd2cSJim Jagielski 186*b1cdbd2cSJim Jagielski ::std::vector< String >::const_iterator aApprovedURL = ::std::find_if( 187*b1cdbd2cSJim Jagielski m_aUnrestrictedURLs.begin(), 188*b1cdbd2cSJim Jagielski m_aUnrestrictedURLs.end(), 189*b1cdbd2cSJim Jagielski CheckURLAllowed( _rURL, true ) 190*b1cdbd2cSJim Jagielski ); 191*b1cdbd2cSJim Jagielski 192*b1cdbd2cSJim Jagielski return ( aApprovedURL != m_aUnrestrictedURLs.end() ); 193*b1cdbd2cSJim Jagielski } 194*b1cdbd2cSJim Jagielski 195*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------- isUrlAllowed(const String & _rURL,bool allowParents) const196*b1cdbd2cSJim Jagielski bool RestrictedPaths::isUrlAllowed( const String& _rURL, bool allowParents ) const 197*b1cdbd2cSJim Jagielski { 198*b1cdbd2cSJim Jagielski if ( m_aUnrestrictedURLs.empty() || !m_bFilterIsEnabled ) 199*b1cdbd2cSJim Jagielski return true; 200*b1cdbd2cSJim Jagielski 201*b1cdbd2cSJim Jagielski ::std::vector< String >::const_iterator aApprovedURL = ::std::find_if( 202*b1cdbd2cSJim Jagielski m_aUnrestrictedURLs.begin(), 203*b1cdbd2cSJim Jagielski m_aUnrestrictedURLs.end(), 204*b1cdbd2cSJim Jagielski CheckURLAllowed( _rURL, allowParents ) 205*b1cdbd2cSJim Jagielski ); 206*b1cdbd2cSJim Jagielski 207*b1cdbd2cSJim Jagielski return ( aApprovedURL != m_aUnrestrictedURLs.end() ); 208*b1cdbd2cSJim Jagielski } 209*b1cdbd2cSJim Jagielski 210*b1cdbd2cSJim Jagielski } // namespace svt 211