Updated to Ghostscript 9.27 and latest 64-bit Chromium Sandbox.

This commit is contained in:
Jobo Kapunan 2019-06-11 14:17:12 +10:00 committed by Tom Clift
parent bfa9330199
commit 512d57bf90
14 changed files with 424 additions and 342 deletions

0
LICENSE.rtf Normal file → Executable file
View File

0
LICENSE.txt Normal file → Executable file
View File

98
README.md Normal file → Executable file
View File

@ -93,6 +93,12 @@ escape vectors.
## Release History
**2019-06-03**
* Now using the latest 64-bit Chromium sandbox
* Recompiled against the latest version of Ghostscript (9.27)
* Compiled using Clang by leveraging Chromium's BUILD.gn system
* Rolled to version 1.3.9.27
**2013-10-11**
* Recompiled against latest version of Ghostscript (9.10)
* Rolled to version 1.2.9.10
@ -119,41 +125,101 @@ The following future refinements are planned:
* Sandbox other executable in the GhostPDL project (e.g ```pcl6.exe```).
* Support custom FONT and LIB paths defined on the command line (read only access).
* Look at sandbox options on Linux.
* 64bit version when/if the Chromium sandbox supports it.
## Authors
![PaperCut Software Logo](http://www.papercut.com/images/logo_papercut.png)
## Building GhostTrap
*Ghost Trap* is open source software developed by Chris Dance with the support of
[PaperCut Software](http://www.papercut.com/).
### Requirements
* [GhostTrap Source Code](https://github.com/PaperCutSoftware/GhostTrap)
* [Chromium (source checkout and build instructions)](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md)
* [GhostPDL Source Code](https://www.ghostscript.com/download/gpdldnld.html)
* [Inno Setup](http://www.jrsoftware.org/isinfo.php)
## Developers
### Building
To build Ghost Trap from source, here is a brief flow:
##### Download the GhostTrap source code. You should have the following directory layout:
1. Clone this git repo.
```bash
GhostTrap
├── build.bat
├── images
│   ├── ghostbusters-ghost-trap.jpg
│   └── ghostbusters-ghost-trap-sized.jpg
├── installer
│   └── win
│   ├── ghost-trap.iss
│   ├── installer-logo-large.bmp
│   └── install-info.rtf
├── LICENSE.rtf
├── LICENSE.txt
├── README.md
├── src
│   ├── gstrapped.cpp
│   ├── sandbox_procmgmt.cpp
│   └── sandbox_procmgmt.h
├── tests
└── third-party
└── README.txt
```
2. Download Google Chromium source into the third-party directory as documented in ```[ghost-trap]/third-party/README.txt```
##### Fetch the Chromium source code and setup the build environtment.
_Follow the instructions carefully!_
3. Download GhostPDL source into the third-party directory as documented in ```[ghost-trap]/third-party/README.txt```
Note: Build your chromium directory inside the GhostTrap\third-party folder.
4. Perform a ```32bit Release``` compile on each dependency (follow the project's documentation).
Note: Building Chromium is very involved! Follow the directions carefully. You will not need to compile whole
Chromium source. Just the "sandbox" sub project will be enough to generate the required dependencies.
```bash
GhostTrap
├── build.bat
├── *
├── src
├── tests
└── third-party
└── chromium ⬅ ⬅ ⬅
```
5. Install [INNO setup](http://www.jrsoftware.org/isinfo.php).
Before the next step, make sure you're able to run the following command:
```bash
GhostTrap\third-party\chromium\src> gn gen out\Default
```
6. Run ```build.bat```
##### Download the GhostPDL source code and copy the whole folder inside third-party as ghostpdl.
Compile 64-bit exe's of Ghostscript, GhostPCL and GhostXPS
```bash
GhostTrap
├── build.bat
├── *
├── src
├── tests
└── third-party
├── chromium
└── ghostpdl ⬅ ⬅ ⬅
```
##### Install Inno Setup
##### Run the build script
```bash
GhostTrap> build.bat
```
##### The installer will be built in GhostTrap\target\ghost-trap-installer-1.2.9.27
### _Successfully built with the following versions:_
##### _Ghostscript source code: 9.27_
##### _Chromium source code commit: 2d57e5b8afc6d01b344a8d95d3470d46b35845c5_
>>>>>>> Updated to Ghostscript 9.27 and latest 64-bit Chromium Sandbox.
## License
*Ghost Trap* is open source software licensed under the Affero GPL:
Copyright (c) 2012-2014 PaperCut Software Int. Pty. Ltd. http://www.papercut.com/
Copyright (c) 2012-2019 PaperCut Software Int. Pty. Ltd. http://www.papercut.com/
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -168,3 +234,5 @@ To build Ghost Trap from source, here is a brief flow:
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

185
build.bat Normal file → Executable file
View File

@ -1,74 +1,133 @@
@echo off
set GHOST_TRAP_VERSION=1.2
set INNO_COMPILER=%programfiles(x86)%\Inno Setup 5\ISCC.exe
set GHOST_TRAP_VERSION=1.3
set INNO_COMPILER=%programfiles(x86)%\Inno Setup 6\ISCC.exe
SETLOCAL ENABLEDELAYEDEXPANSION
set starttime=%time%
set startdir=%cd%
set gsversion=9.27
echo .-. ___ _ _ _____
echo (o o) / _ \ ^|__ ___ ___^| ^|/__ \_ __ __ _ _ __
echo ^| O \ / /_\/ '_ \ / _ \/ __^| __^|/ /\/ '__/ _` ^| '_ \
echo \ \ / /_\\^| ^| ^| ^| (_) \__ \ ^|_/ / ^| ^| ^| (_^| ^| ^|_) ^|
echo `~~~'\____/^|_^| ^|_^|\___/^|___/\__\/ ^|_^| \__,_^| .__/
echo ^|_^|
echo.
rem Make the current dir the script dir
cd %~dp0
if %errorlevel% NEQ 0 goto builderror
REM #
REM # Verify that our 3rd party dependencies exist and are built.
REM # Verify that our required dependencies exists
REM #
if exist third-party\chromium\src\sandbox goto chromesrcok
if exist "%~dp0third-party\ghostpdl\bin\gsdll64.dll" goto gsinsok
echo Error: Unable to locate the GhostPDL files
echo Please ensure its at:
echo %~dp0third-party\ghostpdl\bin\gsdll64.dll
goto builderror
:gsinsok
if exist %~dp0third-party\chromium\src\sandbox goto chromesrcok
echo Error: Unable to locate the chromium source.
echo Please ensure the chromium source is located at:
echo %~dp0third-party\chromium\src
goto builderror
:chromesrcok
if exist third-party\chromium\src\build\Release\lib\sandbox*.lib goto chromelibok
echo Error: Unable to locate the chromium sandbox.lib files.
echo Please ensure the chromium sandbox project has been built.
echo The sandbox.lib file should exist at:
echo %~dp0third-party\chromium\build\Release\lib\sandbox.lib
if exist %~dp0src goto ghosttrapsrcok
echo Error: Unable to locate the GhostTrap project source.
echo Please ensure the GhostTrap source is located at:
echo %~dp0src
goto builderror
:chromelibok
:ghosttrapsrcok
if exist third-party\ghostpdl\win32 goto ghostpdlsrcok
if exist %~dp0third-party\ghostpdl\psi\ goto ghostscriptsrcok
echo Error: Unable to locate the GhostPDL project source.
echo Please ensure the GhostPDL source is located at:
echo %~dp0third-party\ghostpdl
goto builderror
:ghostpdlsrcok
if exist third-party\ghostpdl\gs\bin\gswin32c.exe goto ghostpdllibok
echo Error: Unable to locate Ghostscript binaries.
echo Please ensure that the GhostPDL solution has been built.
echo The gswin32c.exe file should exist at:
echo %~dp0third-party\ghostpdl\gs\bin\gswin32c.exe
goto builderror
:ghostpdllibok
:ghostscriptsrcok
REM #
REM # Get Ghostscript version info
REM #
for /f "usebackq delims=" %%x in (`findstr /B /C:GS_VERSION_M third-party\ghostpdl\gs\base\version.mak`) do (set "%%x")
for /f "usebackq delims=" %%x in (`findstr /B /C:GS_VERSION_M %~dp0third-party\ghostpdl\base\version.mak`) do (set "%%x")
echo Ghostscript version is %GS_VERSION_MAJOR%.%GS_VERSION_MINOR%
echo.
REM #
REM # Build Ghost Trap
REM #
@if "%VSINSTALLDIR%"=="" call "%VS100COMNTOOLS%\vsvars32.bat"
echo.
echo ==== Compiling 64-bit ====
REM Build 32 bit
echo ==== Compiling 32-bit ====
devenv src\ghost-trap.sln /rebuild "release|Win32"
REM Append extra build info to the BUILD.gn
>nul find "gswin64c" %~dp0third-party\chromium\src\sandbox\win\BUILD.gn && (
goto buildinfoexists
) || (
goto buildinfomissing
)
:buildinfomissing
echo.>>%~dp0chromium\src\sandbox\win\BUILD.gn
echo executable("gswin64c-trapped") {>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo sources = [>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo "ghosttrap/gstrapped.cpp",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo "ghosttrap/sandbox_procmgmt.cpp",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo "ghosttrap/sandbox_procmgmt.h",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo ]>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo.>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo include_dirs = [>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo "ghosttrap/ghostscript/psi",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo "ghosttrap/ghostscript/base",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo ]>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo.>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo deps = [>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo ":sandbox",>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo ]>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
echo }>>%~dp0third-party\chromium\src\sandbox\win\BUILD.gn
:buildinfoexists
REM Copy the ghosttrap source code to the Chromium project
call mkdir %~dp0third-party\chromium\src\sandbox\win\ghosttrap > NUL
call xcopy %~dp0src %~dp0third-party\chromium\src\sandbox\win\ghosttrap\ /Y /E /s > NUL
REM Copy the ghosttrap source code to the Chromium project
call mkdir %~dp0third-party\chromium\src\sandbox\win\ghosttrap\ghostscript > NUL
call xcopy %~dp0third-party\ghostpdl %~dp0third-party\chromium\src\sandbox\win\ghosttrap\ghostscript\ /Y /E /s > NUL
REM #
REM # REM Start the build
REM #
call cd third-party\chromium\src\ > NUL
if %errorlevel% NEQ 0 goto builderror
call gn gen out\Default --args="is_debug=false" > NUL
if %errorlevel% NEQ 0 goto builderror
call autoninja -C out\Default sandbox/win:gswin64c-trapped > NUL
if %errorlevel% NEQ 0 goto builderror
REM #
REM # Test GhostTrap
REM #
call cd out\Default\ > NUL
echo Testing GhostTrap...
call gswin64c-trapped.exe --test-sandbox -sOutputFile="C:\output\outputtest.txt" "C:\input\inputtest.txt"
if %errorlevel% NEQ 0 goto builderror
call cd %startdir% > NUL
if %errorlevel% NEQ 0 goto builderror
REM #
REM # Create target dir mirroring Ghostscript standard install.
REM #
rmdir /s /q "target" > NUL
REM # Small sleep so we don't hit locked files.
@ -80,43 +139,63 @@ mkdir target > NUL
mkdir target\installfiles > NUL
mkdir target\installfiles\bin > NUL
mkdir target\installfiles\doc > NUL
mkdir target\installfiles\doc\images > NUL
mkdir target\installfiles\doc\pclxps > NUL
mkdir target\installfiles\examples > NUL
mkdir target\installfiles\examples\cjk > NUL
mkdir target\installfiles\iccprofiles > NUL
mkdir target\installfiles\lib > NUL
mkdir target\installfiles\zlib > NUL
mkdir target\installfiles\zlib\doc > NUL
mkdir target\installfiles\Resource > NUL
mkdir target\installfiles\Resource\CIDFont > NUL
mkdir target\installfiles\Resource\CIDFSubst > NUL
mkdir target\installfiles\Resource\CMap > NUL
mkdir target\installfiles\Resource\ColorSpace > NUL
mkdir target\installfiles\Resource\Decoding > NUL
mkdir target\installfiles\Resource\Encoding > NUL
mkdir target\installfiles\Resource\Font > NUL
mkdir target\installfiles\Resource\IdiomSet > NUL
mkdir target\installfiles\Resource\Init > NUL
mkdir target\installfiles\Resource\SubstCID > NUL
REM # Ghost Trap exe, README and LICENSE files
copy src\Release\gswin32c-trapped.exe target\installfiles\bin /Y > NUL
REM # Chrome sandbox wow helper
copy third-party\chromium\src\build\Release\wow_helper.exe target\installfiles\bin /Y > NUL
copy "third-party\chromium\src\out\Default\gswin64c-trapped.exe" target\installfiles\bin\gsc-trapped.exe /Y > NUL
copy "third-party\chromium\src\out\Default\gswin64c-trapped.exe" target\installfiles\bin\gswin32c-trapped.exe /Y > NUL
copy LICENSE* target\installfiles /Y > NUL
copy README* target\installfiles /Y > NUL
REM # Ghostscript files (mirroring standard install structure)
copy third-party\ghostpdl\gs\bin\gswin32*.exe target\installfiles\bin /Y > NUL
copy third-party\ghostpdl\gs\bin\gsdll32*.dll target\installfiles\bin /Y > NUL
copy third-party\ghostpdl\gs\doc\*.* target\installfiles\doc /Y > NUL
copy third-party\ghostpdl\gs\examples\*.* target\installfiles\examples /Y > NUL
copy third-party\ghostpdl\gs\lib\*.* target\installfiles\lib /Y > NUL
copy third-party\ghostpdl\gs\zlib\doc\*.* target\installfiles\zlib\doc /Y > NUL
REM # Also include pcl6.exe (PCL support) and gxps.exe (XPS support) for convenience.
REM # Note: These do not (yet) have trapped varients.
copy third-party\ghostpdl\main\obj\pcl6.exe target\installfiles\bin /Y > NUL
copy third-party\ghostpdl\xps\obj\gxps.exe target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\bin\gswin64.exe" target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\bin\gswin64.exe" target\installfiles\bin\gswin32.exe /Y > NUL
copy "third-party\ghostpdl\bin\gswin64c.exe" target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\bin\gswin64c.exe" target\installfiles\bin\gswin32c.exe /Y > NUL
copy "third-party\ghostpdl\bin\gsdll64.dll" target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\bin\gpcl6win64.exe" target\installfiles\bin\pcl6.exe /Y > NUL
copy "third-party\ghostpdl\bin\gpcl6dll64.dll" target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\bin\gxpswin64.exe" target\installfiles\bin\gxps.exe /Y > NUL
copy "third-party\ghostpdl\bin\gxpsdll64.dll" target\installfiles\bin /Y > NUL
copy "third-party\ghostpdl\doc\*.*" target\installfiles\doc /Y > NUL
copy "third-party\ghostpdl\doc\images\*.*" target\installfiles\doc\images /Y > NUL
copy "third-party\ghostpdl\doc\pclxps\*.*" target\installfiles\doc\pclxps /Y > NUL
copy "third-party\ghostpdl\examples\*.*" target\installfiles\examples /Y > NUL
copy "third-party\ghostpdl\examples\cjk\*.*" target\installfiles\examples\cjk /Y > NUL
copy "third-party\ghostpdl\iccprofiles\*.*" target\installfiles\iccprofiles /Y > NUL
copy "third-party\ghostpdl\lib\*.*" target\installfiles\lib /Y > NUL
copy "third-party\ghostpdl\Resource\CIDFont\*.*" target\installfiles\Resource\CIDFont /Y > NUL
copy "third-party\ghostpdl\Resource\CIDFSubst\*.*" target\installfiles\Resource\CIDFSubst /Y > NUL
copy "third-party\ghostpdl\Resource\CMap\*.*" target\installfiles\Resource\CMap /Y > NUL
copy "third-party\ghostpdl\Resource\ColorSpace\*.*" target\installfiles\Resource\ColorSpace /Y > NUL
copy "third-party\ghostpdl\Resource\Decoding\*.*" target\installfiles\Resource\Decoding /Y > NUL
copy "third-party\ghostpdl\Resource\Encoding\*.*" target\installfiles\Resource\Encoding /Y > NUL
copy "third-party\ghostpdl\Resource\Font\*.*" target\installfiles\Resource\Font /Y > NUL
copy "third-party\ghostpdl\Resource\IdiomSet\*.*" target\installfiles\Resource\IdiomSet /Y > NUL
copy "third-party\ghostpdl\Resource\Init\*.*" target\installfiles\Resource\Init /Y > NUL
copy "third-party\ghostpdl\Resource\SubstCID\*.*" target\installfiles\Resource\SubstCID /Y > NUL
REM #
REM # Run Inno install script to build the installer
REM #
echo Building installer...
"%INNO_COMPILER%" "/dapp_version=%GHOST_TRAP_VERSION%" "/dgs_version=%GS_VERSION_MAJOR%.%GS_VERSION_MINOR%" installer\win\ghost-trap.iss /q
if %errorlevel% NEQ 0 goto builderror
@ -138,4 +217,4 @@ cd %startdir%
echo Build complete.
echo started at: %starttime%
echo now it is : %time%
echo now it is : %time%

49
installer/win/ghost-trap.iss Normal file → Executable file
View File

@ -1,4 +1,4 @@
; Copyright (c) 2012-2014 PaperCut Software International Pty. Ltd.
; Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd.
; Author: Chris Dance <chris.dance@papercut.com>
;
; License: GNU Affero GPL v3 - See project LICENSE file.
@ -6,6 +6,7 @@
; Ghost Trap Inno Setup based installer script.
;
[Setup]
#define app_name "Ghost Trap"
#define app_name_no_space "GhostTrap"
@ -16,23 +17,21 @@
#define gs_name "GPL Ghostscript"
#ifndef gs_version
#define gs_version "9.06"
#define gs_version "9.27"
#endif
#define gs_c_exe "gswin32c.exe"
#define gs_dll "gsdll32.dll"
#define gs_c_exe "gswin64c.exe"
#define gs_dll "gsdll64.dll"
[Setup]
AppName={#app_name}
AppVerName="{#app_name} {#app_version}.{#gs_version}"
AppPublisher="PaperCut Software Int. Pty. Ltd."
AppPublisherURL=https://github.com/PaperCutSoftware/GhostTrap
AppSupportURL=https://github.com/PaperCutSoftware/GhostTrap/issues
AppUpdatesURL=https://github.com/PaperCutSoftware/GhostTrap
DefaultDirName={pf}\{#app_name_no_space}
VersionInfoVersion={#app_version}.{#gs_version}
DefaultDirName={commonpf}\{#app_name_no_space}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
LicenseFile=..\..\LICENSE.rtf
InfoBeforeFile=..\..\installer\win\install-info.rtf
@ -51,7 +50,6 @@ PrivilegesRequired=admin
WizardImageFile=..\..\installer\win\installer-logo-large.bmp
;WizardSmallImageFile=setup-logo.bmp
[Messages]
BeveledLabel={#app_name} {#app_version}
@ -60,7 +58,6 @@ BeveledLabel={#app_name} {#app_version}
[Files]
Source: *; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs
[Registry]
; Add some keys that might help us in the future
Root: HKLM; Subkey: "Software\{#app_name_no_space}"; Flags: uninsdeletekey
@ -78,11 +75,9 @@ Root: HKLM; Subkey: "Software\{#gs_name}\{#gs_version}"; ValueType: string; Valu
; Generate Windows font map (mirror Ghostscript installer)
Filename: {app}\bin\{#gs_c_exe}; Parameters: "-q -dBATCH ""-sFONTDIR={code:FontsDirWithForwardSlashes}"" ""-sCIDFMAP={app}\lib\cidfmap"" ""{app}\lib\mkcidfm.ps"""; Description: "Generating font map for Windows TrueType fonts..."; Flags: runhidden;
[UninstallDelete]
Type: filesandordirs; Name: {app}\lib\cidfmap;
[Code]
function FontsDirWithForwardSlashes(Param: String): String;
begin
@ -91,8 +86,28 @@ begin
StringChangeEx(Result, '\', '/', True);
end;
function GetUninstallString: string;
var
sUnInstPath: string;
sUnInstallString: String;
begin
Result := '';
sUnInstPath := ExpandConstant('Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Ghost Trap_is1');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
Result := sUnInstallString;
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
iResultCode: Integer;
sUnInstallString: string;
begin
if RegValueExists(HKEY_LOCAL_MACHINE,'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Ghost Trap_is1', 'UninstallString') then { Your App GUID/ID }
begin
sUnInstallString := GetUninstallString();
sUnInstallString := RemoveQuotes(sUnInstallString);
Exec(ExpandConstant(sUnInstallString), '/VERYSILENT', '', SW_SHOW, ewWaitUntilTerminated, iResultCode);
end;
end;

2
installer/win/install-info.rtf Normal file → Executable file
View File

@ -21,7 +21,7 @@ For more information about Ghostscript, visit: \uc0\u8232 {\field{\*\fldinst{HY
For more information about Google Chromium sandbox, visit:\uc0\u8232 {\field{\*\fldinst{HYPERLINK "http://dev.chromium.org/developers/design-documents/sandbox"}}{\fldrslt \cf2 \ul \ulc2 http://dev.chromium.org/developers/design-documents/sandbox}}\
\
\pard\pardeftab720\sl276\slmult1\sa200
\cf0 Ghost Trap is distributed under the GNU Affero General Public License Version 3 and Copyright (c) 2012-2014 PaperCut Software International Pty. Ltd. Ghost Trap source code distribution, and the Ghost Trap executable code, include the following libraries obtained from other parties:\
\cf0 Ghost Trap is distributed under the GNU Affero General Public License Version 3 and Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd. Ghost Trap source code distribution, and the Ghost Trap executable code, include the following libraries obtained from other parties:\
\pard\pardeftab720
\fs16 \cf0 Ghostscript created by Aladdin Enterprises. For more information, please see {\field{\*\fldinst{HYPERLINK "http://www.ghostscript.com/"}}{\fldrslt \cf2 \ul \ulc2 http://www.ghostscript.com/}} and the LICENSE file in the GhostPDL project.\

View File

@ -1,34 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ghost-trap", "ghost-trap.vcxproj", "{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Memento|Win32 = Memento|Win32
Memento|x64 = Memento|x64
Profile|Win32 = Profile|Win32
Profile|x64 = Profile|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Debug|Win32.ActiveCfg = Debug|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Debug|Win32.Build.0 = Debug|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Debug|x64.ActiveCfg = Debug|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Memento|Win32.ActiveCfg = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Memento|Win32.Build.0 = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Memento|x64.ActiveCfg = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Profile|Win32.ActiveCfg = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Profile|Win32.Build.0 = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Profile|x64.ActiveCfg = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Release|Win32.ActiveCfg = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Release|Win32.Build.0 = Release|Win32
{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,96 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E1E8773D-0B39-4BEE-8670-D60B0CEB7E99}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ghosttrap</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>gswin32c-trapped</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>gswin32c-trapped</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\third-party\ghostpdl\pl;..\third-party\ghostpdl\gs\psi;..\third-party\chromium\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\third-party\chromium\src\build\Debug\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>base.lib;base_static.lib;dynamic_annotations.lib;dbghelp.lib;sandbox.lib;wininet.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\third-party\ghostpdl\gs\psi;..\third-party\chromium\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>base.lib;base_static.lib;dbghelp.lib;sandbox.lib;wininet.lib;psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\third-party\chromium\src\build\Release\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="sandbox_procmgmt.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="gstrapped.cpp" />
<ClCompile Include="sandbox_procmgmt.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="sandbox_procmgmt.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="gstrapped.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sandbox_procmgmt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

161
src/gstrapped.cpp Normal file → Executable file
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 PaperCut Software International Pty. Ltd.
* Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd.
* http://www.papercut.com/
*
* Author: Chris Dance <chris.dance@papercut.com>
@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <fstream>
// Ghostscript DLL Header files
#include <ierrors.h>
@ -42,8 +43,8 @@
* Ghost Trap version number starts at 1 and suffixes the Ghostscript version we've
* tested/written against.
*/
#define GHOST_TRAP_VERSION "1.0.9.06"
#define GHOST_TRAP_COPYRIGHT "Copyright (c) 2012-2013 PaperCut Software International Pty. Ltd."
#define GHOST_TRAP_VERSION "1.3.9.27"
#define GHOST_TRAP_COPYRIGHT "Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd."
// Definitions
typedef struct GSDLL_S {
@ -57,7 +58,6 @@ typedef struct GSDLL_S {
PFN_gsapi_init_with_args init_with_args;
PFN_gsapi_run_string run_string;
PFN_gsapi_exit exit;
PFN_gsapi_set_visual_tracer set_visual_tracer;
} GSDLL;
// Globals
@ -66,6 +66,7 @@ void *global_gsinstance;
/*
* Load the Ghostscript Windows DLL and store implementation in GSDLL instances.
* Any errors are printed on STDOUT.
@ -170,8 +171,7 @@ static bool LoadGSDLL(GSDLL *gsdll) {
/*
* A convenience wrapper to read a registry keys using wstrings.
*/
static LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{
static LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue) {
strValue = strDefaultValue;
WCHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
@ -190,7 +190,8 @@ static LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::ws
* parent directory (all files) is allowed. Passing a relative file path will raise an error
* and no white listing will occure.
*/
static void AllowAccessToFile(sandbox::TargetPolicy* policy, wchar_t *file, BOOL parent_dir) {
static void AllowAccessToFile(scoped_refptr<sandbox::TargetPolicy> policy, wchar_t *file, BOOL parent_dir) {
wchar_t drive[8];
wchar_t dir[512];
wchar_t filename[512];
@ -219,7 +220,7 @@ static void AllowAccessToFile(sandbox::TargetPolicy* policy, wchar_t *file, BOOL
fprintf(stderr, "Ghost Trap: Invalid resource. Please use absolute paths on a local drive.\n");
return;
}
if (parent_dir) {
_snwprintf_s(path_rule, MAX_PATH - 1, L"%s%s*",
drive,
@ -231,31 +232,29 @@ static void AllowAccessToFile(sandbox::TargetPolicy* policy, wchar_t *file, BOOL
filename,
ext);
}
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
path_rule
);
}
}
/*
* Look through the standard Ghostscript cmd-line arguments looking for paths.
* Expand relative and normalize all paths. This is required as at the time of
* writing any open file request in the Google Chrome sandbox must be an absolute
* writing, any open file request in the Google Chrome sandbox must be an absolute
* path. This function will pass back a new **argv instance any any expanded
* paths will be malloced buffers.
*
* TODO: The input file argument is assumed to be the last argument. This is not
* necasserially so via the -f option.
* necessarily so via the -f option.
*
* FIXME: What about other paths such as defining a custom libary files or fonts?
*/
static wchar_t ** ExpandPathsInArgs(int argc, wchar_t *argv[]) {
wchar_t **full_path_argv = (wchar_t **) calloc(argc, sizeof(full_path_argv[0]));
if (full_path_argv == NULL) {
@ -309,8 +308,7 @@ static wchar_t ** ExpandPathsInArgs(int argc, wchar_t *argv[]) {
*
* IMPORTANT: This code does not run in the sandbox (runs in the parent process). Take care!
*/
static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]) {
static void ApplyPolicy(scoped_refptr<sandbox::TargetPolicy> policy, int argc, wchar_t* argv[]) {
// Fix up and expand paths in the args
wchar_t **nargv = ExpandPathsInArgs(argc, argv);
@ -336,11 +334,10 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
return;
}
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_LOCAL_MACHINE"
L"HKEY_CURRENT_USER"
);
// Allow READ access to OS keys (e.g. Locale lookup)
@ -369,7 +366,7 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
_snwprintf(gs_key, 256, L"SOFTWARE\\%hs\\%s",
rv.product,
dotversion);
// Allow READ access to directory on lib path. Find this by looking
// up the registry key HKLM/Software/GPL Ghostscript/9.02/GS_LIB.
// The value is stored is a ";" seperated path.
@ -396,7 +393,7 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
RegCloseKey(hKey);
}
// Allow READ and WRITE access to default temp directory.
{
wchar_t temp_dir[MAX_PATH];
@ -409,7 +406,7 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
dir_rule
);
}
// Allow READ access to C:\Windows\Fonts directory.
{
@ -426,14 +423,67 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
// Allow WRITE access to OutputFile target directory
BOOL has_outfile = FALSE;
BOOL test_enabled = FALSE;
int i;
for (i = 0; i < argc; ++i) {
wchar_t *p;
if ((p = wcsstr(nargv[i], L"OutputFile=")) != NULL) {
p += 11;
AllowAccessToFile(policy, p, TRUE);
has_outfile = TRUE;
}
if ((p = wcsstr(nargv[i], L"--test-sandbox")) != NULL) {
test_enabled = TRUE;
}
// Sandbox Testing - whitelist test data
if ((p = wcsstr(nargv[i], L"--fail-test=")) != NULL) {
p += 9;
/* Setup Test 1 for failure
* Allow write access to C:\Windows\Temp folder
*/
if(wcscmp(p, L"1") == 0 && test_enabled) {
wchar_t win_dir[MAX_PATH];
GetWindowsDirectory(win_dir, MAX_PATH - 1);
wchar_t dir_rule[MAX_PATH];
_snwprintf(dir_rule, MAX_PATH - 1, L"%s\\Temp\\*", win_dir);
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
dir_rule
);
}
/* Setup Test 2 for failure
* Allow read-only access to C:\Windows\notepad.exe
*/
if(wcscmp(p, L"2") == 0 && test_enabled) {
wchar_t win_dir[MAX_PATH];
GetWindowsDirectory(win_dir, MAX_PATH - 1);
wchar_t dir_rule[MAX_PATH];
_snwprintf(dir_rule, MAX_PATH - 1, L"%s\\notepad.exe", win_dir);
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_READONLY,
dir_rule
);
}
/* Setup Test 3 for failure
* Allow read access to registry key HKCU\Environment
*/
if(wcscmp(p, L"3") == 0 && test_enabled) {
//
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER\\Environment"
);
}
}
}
// If no OutputFile, add READ/WRITE access to current working directory?
@ -446,7 +496,6 @@ static void ApplyPolicy(sandbox::TargetPolicy* policy, int argc, wchar_t* argv[]
if (*last_arg != L'-') {
AllowAccessToFile(policy, last_arg, FALSE);
}
}
@ -468,13 +517,12 @@ static int PreSandboxedInit(int argc, wchar_t* argv[]) {
* Convert wchar to unicode. Similar to function in gp_wutf8.c in Ghostscript,
* however without the buffer length calculation problem on generation.
*/
static int wchar_to_utf8(char *out, const wchar_t *in)
{
static int wchar_to_utf8(char *out, const wchar_t *in) {
unsigned int i;
unsigned int len = 1;
if (out) {
while (i = (unsigned int)*in++) {
while ((i = (unsigned int)*in++)) {
if (i < 0x80) {
*out++ = (char)i;
len++;
@ -491,7 +539,7 @@ static int wchar_to_utf8(char *out, const wchar_t *in)
}
*out = 0;
} else {
while (i = (unsigned int)*in++) {
while ((i = (unsigned int)*in++)) {
if (i < 0x80) {
len++;
} else if (i < 0x800) {
@ -504,13 +552,64 @@ static int wchar_to_utf8(char *out, const wchar_t *in)
return len;
}
/*
* This is an internal method to do a few simple checks to make sure our sandbox is working.
* The build script will use this to verify that everything is working as expected.
* A non-zero exit code indicates a possible error that should be looked at.
*
* For the moment our tests are:
* 1 - Check that we can't write a file we should not - i.e. file in c:\Windows\Temp
* 2 - Check that we can't read files from the general os filesystem (c:\Windows\notepad.exe)
* 3 - Check that we can't read general registry entries (HKEY_CURRENT_USER\\Environment)
*
* The tests can be setup to fail (whitelisted parameters) by adding the --fail-test flag.
* e.g.
* --fail-test=1 [will fail test 1]
* --fail-test=2 [will fail test 2]
*/
static int TestSandbox() {
/*
* If C:\Windows\Temp\test.txt is whitelisted via -sOutputFile or the last param
* then this will fail
*/
std::ofstream output("C:\\Windows\\Temp\\test.txt");
if (output.is_open()) {
// We shouldn't be able to read this file
return 61;
}
/*
* Test 2
* If C:\Windows\\notepad.exe is the last parameter, this will succeed as we
* are whitelisting the input file.
*/
std::ifstream input("C:\\Windows\\notepad.exe", std::ios::binary);
if (input.is_open()) {
// Oh... we can read it! Oh no.... we can read something we were not expecting!!!
return 62;
}
/*
* Test 3
* Check that we can't read the registry
*/
HKEY hKey;
DWORD Ret;
wchar_t skey[256] = L"Environment";
Ret = RegOpenKeyEx(HKEY_CURRENT_USER, skey, 0, KEY_READ, &hKey);
if (Ret == ERROR_SUCCESS) {
return 63;
}
return 0;
}
/*
* The main method (sandboxed). Here we do the heavy lifting in the sandbox. i.e.
* We hand the hard work off to the Ghostscript DLL :-)
*/
static int SandboxedMain(int argc, wchar_t* argv[]) {
// If -h, print out Ghost Trap information as well.
for (int i = 0; i < argc; ++i) {
if (wcscmp(argv[i], L"-h") == 0) {
@ -520,8 +619,12 @@ static int SandboxedMain(int argc, wchar_t* argv[]) {
printf("\n");
break;
}
// Used for developer testing only (not documented in usage)
if (wcscmp(argv[i], L"--test-sandbox") == 0) {
return TestSandbox();
}
}
wchar_t **full_path_argv = ExpandPathsInArgs(argc, argv);
/* Duplicate wide args as utf8 */
@ -566,7 +669,7 @@ static int SandboxedMain(int argc, wchar_t* argv[]) {
code1 = global_gsdll.exit(global_gsinstance);
if ((code == 0) || (code == e_Quit)) {
if ((code == 0) || (code == gs_error_Quit)) {
code = code1;
}
@ -583,7 +686,7 @@ error:
free(nargv);
}
if (!((code == 0) || (code == e_Quit))) {
if (!((code == 0) || (code == gs_error_Quit))) {
return abs(code);
}
return 0;

76
src/sandbox_procmgmt.cpp Normal file → Executable file
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 PaperCut Software International Pty. Ltd.
* Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd.
* http://www.papercut.com/
*
* Author: Chris Dance <chris.dance@papercut.com>
@ -163,7 +163,7 @@ static DWORD WINAPI ProvideStdIn(void *param) {
/*
* The parent (unsandboxed process). This function intializes the sandbox service broker,
* setups up the piples, applies the security policy, and exec's and monitors the child
* sets up the pipes, applies the security policy, and then executes and monitors the child
* process.
*/
static int RunParent(int argc, wchar_t* argv[],
@ -171,17 +171,18 @@ static int RunParent(int argc, wchar_t* argv[],
SandboxPolicyFn policy_provider) {
DWORD process_id = GetCurrentProcessId();
sandbox::ResultCode result;
// Start setting up the sandbox.
if (0 != broker_service->Init()) {
if (0 != (result = broker_service->Init())) {
fprintf(stderr, "Sandbox: Failed to initialize the sandbox - BrokerServices object\n");
return 50;
}
// Apply our policy
sandbox::TargetPolicy* targetPolicy = broker_service->CreatePolicy();
scoped_refptr<sandbox::TargetPolicy> targetPolicy = broker_service->CreatePolicy();
// By defult we'll apply full sandbox. Your own policy then applied over this.
// By default we'll apply full sandbox. Your own policy is then applied over this.
targetPolicy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
targetPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, sandbox::USER_LOCKDOWN);
targetPolicy->SetAlternateDesktop(true);
@ -193,8 +194,9 @@ static int RunParent(int argc, wchar_t* argv[],
}
PROCESS_INFORMATION pi;
sandbox::ResultCode result;
sandbox::ResultCode warning_result = sandbox::SBOX_ALL_OK;
DWORD last_error = ERROR_SUCCESS;
{
wchar_t *orig_args = GetCommandLineW();
int arg_max_len = wcslen(orig_args) + 50;
@ -202,12 +204,10 @@ static int RunParent(int argc, wchar_t* argv[],
swprintf(args_plus_id, arg_max_len, L"%s %d", orig_args, process_id);
args_plus_id[arg_max_len - 1] = L'\0';
result = broker_service->SpawnTarget(argv[0], args_plus_id, targetPolicy, &pi);
result = broker_service->SpawnTarget(argv[0], args_plus_id, targetPolicy, &warning_result, &last_error, &pi);
delete[] args_plus_id;
}
targetPolicy->Release();
targetPolicy = NULL;
if (sandbox::SBOX_ALL_OK != result) {
@ -230,7 +230,9 @@ static int RunParent(int argc, wchar_t* argv[],
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
// Set the security on
if (!sandbox::AddKnownSidToKernelObject(stdout_pipe, WinCreatorOwnerSid, FILE_ALL_ACCESS)) {
if (!sandbox::AddKnownSidToObject(stdout_pipe, SE_KERNEL_OBJECT,
WinWorldSid,
GRANT_ACCESS, FILE_ALL_ACCESS)) {
fprintf(stderr, "Sandbox: Failed to set security on stdout pipe.\n");
return 52;
}
@ -259,7 +261,9 @@ static int RunParent(int argc, wchar_t* argv[],
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (!sandbox::AddKnownSidToKernelObject(stderr_pipe, WinCreatorOwnerSid, FILE_ALL_ACCESS)) {
if (!sandbox::AddKnownSidToObject(stderr_pipe, SE_KERNEL_OBJECT,
WinCreatorOwnerSid,
GRANT_ACCESS, FILE_ALL_ACCESS)) {
fprintf(stderr, "Sandbox: Failed to set security on stderr pipe.\n");
return 52;
}
@ -285,31 +289,25 @@ static int RunParent(int argc, wchar_t* argv[],
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (!sandbox::AddKnownSidToKernelObject(stdin_pipe, WinCreatorOwnerSid, FILE_ALL_ACCESS)) {
if (!sandbox::AddKnownSidToObject(stdin_pipe, SE_KERNEL_OBJECT,
WinCreatorOwnerSid,
GRANT_ACCESS, FILE_ALL_ACCESS)) {
fprintf(stderr, "Sandbox: Failed to set security on stdin pipe.\n");
return 52;
}
// Push STDIN
DWORD thread_id;
::CreateThread(NULL, // Default security attributes
NULL, // Default stack size
&ProvideStdIn,
stdin_pipe,
0, // No flags
&thread_id);
// All pipes are ready. We can now resume the sandboxed child's execution.
::ResumeThread(pi.hThread);
// Wait for the child to connect to our STDIN pipe before we start pushing data.
BOOL fConnected = ConnectNamedPipe(stdin_pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected) {
// Client is connected so we can no push in STDIN
DWORD thread_id;
::CreateThread(NULL, // Default security attributes
NULL, // Default stack size
&ProvideStdIn,
stdin_pipe,
0, // No flags
&thread_id);
} else {
fprintf(stderr, "Sandbox: Client did not start\n");
return 53;
}
::WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code = 0;
@ -325,6 +323,7 @@ static int RunParent(int argc, wchar_t* argv[],
// Wait for BOTH our consuming std(out|err) threads to finish.
WaitForSingleObject(stdout_thread, 1000);
WaitForSingleObject(stderr_thread, 1000);
return exit_code;
}
@ -333,7 +332,7 @@ static int RunParent(int argc, wchar_t* argv[],
* Fix standard stream as outlined here: http://support.microsoft.com/kb/105305
*/
static void ReattachStreamToPipe(FILE *stream, DWORD handle, char *mode) {
int hCrt = _open_osfhandle(
(long) GetStdHandle(handle),
_O_BINARY
@ -408,14 +407,13 @@ int RunChild(ConsoleWMainFn pre_sandbox_init,
::SetStdHandle(STD_ERROR_HANDLE, stderr_pipe);
// Fix up C runtime output to console as per: http://support.microsoft.com/kb/105305
ReattachStreamToPipe(stdin, STD_INPUT_HANDLE, "r");
ReattachStreamToPipe(stdout, STD_OUTPUT_HANDLE, "w");
ReattachStreamToPipe(stderr, STD_ERROR_HANDLE, "w");
ReattachStreamToPipe(stdin, STD_INPUT_HANDLE, (char*)"r");
ReattachStreamToPipe(stdout, STD_OUTPUT_HANDLE, (char*)"w");
ReattachStreamToPipe(stderr, STD_ERROR_HANDLE, (char*)"w");
// Init Sandbox
sandbox::TargetServices* target_service = sandbox::SandboxFactory::GetTargetServices();
if (NULL == target_service) {
fprintf(stderr, "Sandbox: Unable to setup sandbox service - GetTargetServices()\n");
return 55;
@ -426,7 +424,7 @@ int RunChild(ConsoleWMainFn pre_sandbox_init,
return 56;
}
// The child has an extra arg passed in (to assist with uniq pipe names) - ignore moving forward.
// The child has an extra arg passed in (to assist with unique pipe names) - ignore moving forward.
int argc_less_id = argc - 1;
// If we have pre-sandbox initalization code, run now.
@ -447,7 +445,7 @@ int RunChild(ConsoleWMainFn pre_sandbox_init,
return 50;
}
// We're now in our standbox. Run our code.
// We're now in our sandbox, run our code.
int exit_code = sandboxed_wmain(argc_less_id, argv);
::CloseHandle(stdin_pipe);

14
src/sandbox_procmgmt.h Normal file → Executable file
View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013 PaperCut Software International Pty. Ltd.
* Copyright (c) 2012-2019 PaperCut Software International Pty. Ltd.
* http://www.papercut.com/
*
* Author: Chris Dance <chris.dance@papercut.com>
@ -9,18 +9,18 @@
* Dual License: GPL or MIT
*
* ----
* Library code to help wrap a Windows command-line (console) application is the
* Google Chromium Sandbox. This code was originally develop for the Ghost Trap
* Library code to help wrap a Windows command-line (console) application to the
* Google Chromium Sandbox. This code was originally developed for the Ghost Trap
* open source project, however may also serve as a useful library for sandboxing
* any console application.
*
* This sandboxing library wraps the Google Chromium Sandbox sub-project and
* provides the required infastructure required to support most Windows console
* applications. The sandbox works by applying a policy in a parent process,
* then exec'ing a child to run restricted code. Communication between the parent
* and child to facilitate the trasfer of STDIN/STDOUT/STDERR, is via named pipes.
* then executing a child to run restricted code. Communication between the parent
* and child to facilitate the transfer of STDIN/STDOUT/STDERR, is via named pipes.
*
* The general approch for wrapping an console application would be as follows:
* The general approach for wrapping an console application would be as follows:
*
* 1) Rename your wmain method to sandboxed_wmain.
*
@ -63,7 +63,7 @@
#include <sandbox/win/src/sandbox.h>
typedef void (*SandboxPolicyFn)(sandbox::TargetPolicy *policy, int argc, wchar_t* argv[]);
typedef void (*SandboxPolicyFn)(scoped_refptr<sandbox::TargetPolicy> policy, int argc, wchar_t* argv[]);
typedef int (*ConsoleWMainFn)(int argc, wchar_t* argv[]);
int RunConsoleAppInSandbox(SandboxPolicyFn policy_provider,

0
third-party/.gitkeep vendored Normal file
View File

View File

@ -1,21 +0,0 @@
Ghost Trap 3rd Party Dependencies
* Google Chromium (sandbox sub project)
* GhostPDL - Ghostscript PDL project
Instructions:
1) Place the source code for Ghost Trap's 3rd party dependencies in this
directory. After this you should be able to find the following directories:
[ghost-trap]/third-party/chromium/src/sandbox
[ghost-trap]/third-party/ghostpdl/win32
Note: You may need to remove the version number from the top level
directories.
2) Perform a 32bit Release compile on each dependency. Take care following
the build instructions for Google Chromium. It's very involved! You will not
need to compile the whole Chromium source - just the "sandbox" sub project
will be enough to generate the required dependencies.