diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-03-29 14:01:19 +0100 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2019-04-10 07:25:57 -0700 |
commit | f9f1c8c3ac8d300d9f28accd4880e8ca08341838 (patch) | |
tree | 68cf9a50d722ad2d9a9db0aaefc5921968677caa | |
parent | e601e7bcadeb0fa1877a54d86f3d8c384574ab72 (diff) |
Filter out problematic file URLs
Change-Id: I87fd37e56326bef4888354b923407530c6f70760
Reviewed-on: https://gerrit.libreoffice.org/70177
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
-rw-r--r-- | shell/source/unix/exec/shellexec.cxx | 37 | ||||
-rw-r--r-- | shell/source/win32/SysShExec.cxx | 114 |
2 files changed, 151 insertions, 0 deletions
diff --git a/shell/source/unix/exec/shellexec.cxx b/shell/source/unix/exec/shellexec.cxx index 71f01e764a56..f94c2ef6eff0 100644 --- a/shell/source/unix/exec/shellexec.cxx +++ b/shell/source/unix/exec/shellexec.cxx @@ -42,6 +42,10 @@ #include <errno.h> #include <unistd.h> +#if defined MACOSX +#include <sys/stat.h> +#endif + using com::sun::star::system::XSystemShellExecute; using com::sun::star::system::SystemShellExecuteException; @@ -122,6 +126,39 @@ void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aPar } #ifdef MACOSX + if (uri->getScheme().equalsIgnoreAsciiCase("file")) { + OUString pathname; + auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname); + if (e1 != osl::FileBase::E_None) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, getSystemPathFromFileURL <" + aCommand + + "> failed with " + OUString::number(e1)), + {}, 0); + } + OString pathname8; + if (!pathname.convertToString( + &pathname8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot convert \"" + pathname + "\" to UTF-8", {}, + 0); + } + struct stat st; + auto const e2 = stat(pathname8.getStr(), &st); + if (e2 != 0) { + auto const e3 = errno; + SAL_INFO("shell", "stat(" << pathname8 << ") failed with errno " << e3); + } + if (e2 != 0 || !S_ISREG(st.st_mode) + || (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + } + //TODO: Using open(1) with an argument that syntactically is an absolute // URI reference does not necessarily give expected results: // 1 If the given URI reference matches a supported scheme (e.g., diff --git a/shell/source/win32/SysShExec.cxx b/shell/source/win32/SysShExec.cxx index 5edb22a1a821..3197ba42db5e 100644 --- a/shell/source/win32/SysShExec.cxx +++ b/shell/source/win32/SysShExec.cxx @@ -18,8 +18,11 @@ */ #include <algorithm> +#include <cassert> #include <osl/diagnose.h> +#include <osl/process.h> +#include <sal/log.hxx> #include "SysShExec.hxx" #include <osl/file.hxx> #include <sal/macros.h> @@ -27,6 +30,7 @@ #include <com/sun/star/system/SystemShellExecuteFlags.hpp> #include <com/sun/star/uri/UriReferenceFactory.hpp> #include <cppuhelper/supportsservice.hxx> +#include <o3tl/runtimetooustring.hxx> #define WIN32_LEAN_AND_MEAN #if defined _MSC_VER @@ -34,7 +38,9 @@ #endif #include <windows.h> #include <shellapi.h> +#include <Shobjidl.h> #include <objbase.h> +#include <systools/win32/comtools.hxx> #if defined _MSC_VER #pragma warning(pop) #endif @@ -245,6 +251,18 @@ CSysShExec::CSysShExec( const Reference< css::uno::XComponentContext >& xContext namespace { +bool checkExtension(OUString const & extension, OUString const & blacklist) { + assert(!extension.isEmpty()); + for (sal_Int32 i = 0; i != -1;) { + OUString tok = blacklist.getToken(0, ';', i); + tok.startsWith(".", &tok); + if (extension.equalsIgnoreAsciiCase(tok)) { + return false; + } + } + return true; +} + // This callback checks if the found window is the specified process's top-level window, // and activates the first found such window. BOOL CALLBACK FindAndActivateProcWnd(HWND hwnd, LPARAM lParam) @@ -299,6 +317,102 @@ void SAL_CALL CSysShExec::execute( const OUString& aCommand, const OUString& aPa + aCommand, static_cast< cppu::OWeakObject * >(this), 0); } + if (uri->getScheme().equalsIgnoreAsciiCase("file")) { + OUString pathname; + auto const e1 = osl::FileBase::getSystemPathFromFileURL(aCommand, pathname); + if (e1 != osl::FileBase::E_None) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, getSystemPathFromFileURL <" + aCommand + + "> failed with " + OUString::number(e1)), + {}, 0); + } + for (int i = 0;; ++i) { + SHFILEINFOW info; + if (SHGetFileInfoW( + reinterpret_cast<LPCWSTR>(pathname.getStr()), 0, &info, sizeof info, SHGFI_EXETYPE) + != 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + if (SHGetFileInfoW( + reinterpret_cast<LPCWSTR>(pathname.getStr()), 0, &info, sizeof info, SHGFI_ATTRIBUTES) + == 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, SHGetFileInfoW(" + pathname + ") failed", {}, + 0); + } + if ((info.dwAttributes & SFGAO_LINK) == 0) { + break; + } + sal::systools::COMReference<IShellLinkW> link; + auto e2 = CoCreateInstance( + CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + reinterpret_cast<LPVOID *>(&link)); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, CoCreateInstance failed with " + + OUString::number(e2)), + {}, 0); + } + sal::systools::COMReference<IPersistFile> file; + try { + file = link.QueryInterface<IPersistFile>(IID_IPersistFile); + } catch(sal::systools::ComError & e3) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, QueryInterface failed with: " + + o3tl::runtimeToOUString(e3.what())), + {}, 0); + } + e2 = file->Load(reinterpret_cast<LPCWSTR>(pathname.getStr()), STGM_READ); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IPersistFile.Load failed with " + + OUString::number(e2)), + {}, 0); + } + e2 = link->Resolve(nullptr, SLR_UPDATE | SLR_NO_UI); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IShellLink.Resolve failed with " + + OUString::number(e2)), + {}, 0); + } + wchar_t path[MAX_PATH]; + WIN32_FIND_DATAW wfd; + e2 = link->GetPath(path, MAX_PATH, &wfd, SLGP_RAWPATH); + if (FAILED(e2)) { + throw css::lang::IllegalArgumentException( + ("XSystemShellExecute.execute, IShellLink.GetPath failed with " + + OUString::number(e2)), + {}, 0); + } + pathname = OUString( reinterpret_cast<const sal_Unicode*>(path) ); + // Fail at some arbitrary nesting depth, to avoid an infinite loop: + if (i == 30) { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, link depth exceeded for <" + aCommand + ">", + {}, 0); + } + } + auto const n = pathname.lastIndexOf('.'); + if (n > pathname.lastIndexOf('\\')) { + auto const ext = pathname.copy(n + 1); + OUString env; + if (osl_getEnvironment(OUString("PATHEXT").pData, &env.pData) != osl_Process_E_None) + { + SAL_INFO("shell", "osl_getEnvironment(PATHEXT) failed"); + } + if (!(checkExtension(ext, env) + && checkExtension( + ext, ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY"))) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + } + } } /* #i4789#; jump mark detection on system paths |