diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2019-03-29 14:01:19 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2019-04-03 12:08:14 +0200 |
commit | d59ec4cd1660410fa1b18c50d2d83b1417a82ddc (patch) | |
tree | f42ff98ea0fec775c47ac277e6e79d1ace6363ec /shell | |
parent | 3b41abe6933046612c445f16c3879975eed650ba (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>
Diffstat (limited to 'shell')
-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 7deeb5caa8a7..7355eaea0db6 100644 --- a/shell/source/unix/exec/shellexec.cxx +++ b/shell/source/unix/exec/shellexec.cxx @@ -43,6 +43,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; @@ -113,6 +117,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 11ca42005b10..4786e4ddedc7 100644 --- a/shell/source/win32/SysShExec.cxx +++ b/shell/source/win32/SysShExec.cxx @@ -18,8 +18,10 @@ */ #include <algorithm> +#include <cassert> #include <osl/diagnose.h> +#include <osl/process.h> #include <sal/log.hxx> #include "SysShExec.hxx" #include <osl/file.hxx> @@ -30,12 +32,16 @@ #include <com/sun/star/uri/UriReferenceFactory.hpp> #include <cppuhelper/supportsservice.hxx> #include <o3tl/char16_t2wchar_t.hxx> +#include <o3tl/runtimetooustring.hxx> #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shellapi.h> +#include <Shobjidl.h> #include <objbase.h> +#include <systools/win32/comtools.hxx> + using com::sun::star::uno::Reference; using com::sun::star::uno::RuntimeException; using com::sun::star::uno::Sequence; @@ -242,6 +248,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) @@ -295,6 +313,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( + o3tl::toW(pathname.getStr()), 0, &info, sizeof info, SHGFI_EXETYPE) + != 0) + { + throw css::lang::IllegalArgumentException( + "XSystemShellExecute.execute, cannot process <" + aCommand + ">", {}, 0); + } + if (SHGetFileInfoW( + o3tl::toW(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(o3tl::toW(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 = o3tl::toU(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 |