mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-05-06 05:31:48 +02:00
Merge 981fcd4e3f
into 03b3c9eba8
This commit is contained in:
commit
613a73c3ed
4 changed files with 50 additions and 9 deletions
|
@ -42,6 +42,11 @@ def print_header(s: str) -> None:
|
||||||
type=click.UNPROCESSED,
|
type=click.UNPROCESSED,
|
||||||
callback=args.validate_input_filenames,
|
callback=args.validate_input_filenames,
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--debug",
|
||||||
|
"debug",
|
||||||
|
flag_value=True,
|
||||||
|
help="Run Dangerzone in debug mode, and get more logs from the conversion process.")
|
||||||
@click.version_option(version=get_version(), message="%(version)s")
|
@click.version_option(version=get_version(), message="%(version)s")
|
||||||
@errors.handle_document_errors
|
@errors.handle_document_errors
|
||||||
def cli_main(
|
def cli_main(
|
||||||
|
@ -50,6 +55,7 @@ def cli_main(
|
||||||
filenames: List[str],
|
filenames: List[str],
|
||||||
archive: bool,
|
archive: bool,
|
||||||
dummy_conversion: bool,
|
dummy_conversion: bool,
|
||||||
|
debug: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
setup_logging()
|
setup_logging()
|
||||||
|
|
||||||
|
@ -58,7 +64,7 @@ def cli_main(
|
||||||
elif is_qubes_native_conversion():
|
elif is_qubes_native_conversion():
|
||||||
dangerzone = DangerzoneCore(Qubes())
|
dangerzone = DangerzoneCore(Qubes())
|
||||||
else:
|
else:
|
||||||
dangerzone = DangerzoneCore(Container())
|
dangerzone = DangerzoneCore(Container(debug=debug))
|
||||||
|
|
||||||
display_banner()
|
display_banner()
|
||||||
if len(filenames) == 1 and output_filename:
|
if len(filenames) == 1 and output_filename:
|
||||||
|
|
|
@ -18,11 +18,20 @@ class ConversionException(Exception):
|
||||||
error_message = "Unspecified error"
|
error_message = "Unspecified error"
|
||||||
error_code = ERROR_SHIFT
|
error_code = ERROR_SHIFT
|
||||||
|
|
||||||
def __init__(self, error_message: Optional[str] = None) -> None:
|
def __init__(
|
||||||
|
self, error_message: Optional[str] = None, logs: Optional[str] = None
|
||||||
|
) -> None:
|
||||||
if error_message:
|
if error_message:
|
||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
|
self.logs = logs
|
||||||
super().__init__(self.error_message)
|
super().__init__(self.error_message)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
msg = f"{self.error_message}"
|
||||||
|
if self.logs:
|
||||||
|
msg += f" {self.logs}"
|
||||||
|
return msg
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_subclasses(cls) -> List[Type["ConversionException"]]:
|
def get_subclasses(cls) -> List[Type["ConversionException"]]:
|
||||||
subclasses = [cls]
|
subclasses = [cls]
|
||||||
|
@ -100,9 +109,10 @@ class UnexpectedConversionError(ConversionException):
|
||||||
|
|
||||||
def exception_from_error_code(
|
def exception_from_error_code(
|
||||||
error_code: int,
|
error_code: int,
|
||||||
|
logs: Optional[str] = None,
|
||||||
) -> Union[ConversionException, ValueError]:
|
) -> Union[ConversionException, ValueError]:
|
||||||
"""returns the conversion exception corresponding to the error code"""
|
"""returns the conversion exception corresponding to the error code"""
|
||||||
for cls in ConversionException.get_subclasses():
|
for cls in ConversionException.get_subclasses():
|
||||||
if cls.error_code == error_code:
|
if cls.error_code == error_code:
|
||||||
return cls()
|
return cls(logs=logs)
|
||||||
return UnexpectedConversionError(f"Unknown error code '{error_code}'")
|
return UnexpectedConversionError(f"Unknown error code '{error_code}', logs= {logs}")
|
||||||
|
|
|
@ -5,6 +5,7 @@ import platform
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import IO, Callable, Iterator, Optional
|
from typing import IO, Callable, Iterator, Optional
|
||||||
|
@ -87,12 +88,19 @@ class IsolationProvider(ABC):
|
||||||
Abstracts an isolation provider
|
Abstracts an isolation provider
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, debug) -> None:
|
||||||
if getattr(sys, "dangerzone_dev", False) is True:
|
self.debug = debug
|
||||||
|
if self.should_display_errors():
|
||||||
self.proc_stderr = subprocess.PIPE
|
self.proc_stderr = subprocess.PIPE
|
||||||
else:
|
else:
|
||||||
|
# We do not trust STDERR from the inner container,
|
||||||
|
# which could be exploited to ask users to open the document with
|
||||||
|
# a default PDF reader for instance.
|
||||||
self.proc_stderr = subprocess.DEVNULL
|
self.proc_stderr = subprocess.DEVNULL
|
||||||
|
|
||||||
|
def should_display_errors(self) -> bool:
|
||||||
|
return self.debug or getattr(sys, "dangerzone_dev", False)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def install(self) -> bool:
|
def install(self) -> bool:
|
||||||
pass
|
pass
|
||||||
|
@ -220,6 +228,17 @@ class IsolationProvider(ABC):
|
||||||
text = "Successfully converted document"
|
text = "Successfully converted document"
|
||||||
self.print_progress(document, False, text, 100)
|
self.print_progress(document, False, text, 100)
|
||||||
|
|
||||||
|
if self.should_display_errors():
|
||||||
|
assert p.stderr
|
||||||
|
debug_log = read_debug_text(p.stderr, MAX_CONVERSION_LOG_CHARS)
|
||||||
|
p.stderr.close()
|
||||||
|
log.debug(
|
||||||
|
"Conversion output (doc to pixels)\n"
|
||||||
|
f"{DOC_TO_PIXELS_LOG_START}\n"
|
||||||
|
f"{debug_log}" # no need for an extra newline here
|
||||||
|
f"{DOC_TO_PIXELS_LOG_END}"
|
||||||
|
)
|
||||||
|
|
||||||
def print_progress(
|
def print_progress(
|
||||||
self, document: Document, error: bool, text: str, percentage: float
|
self, document: Document, error: bool, text: str, percentage: float
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -252,7 +271,10 @@ class IsolationProvider(ABC):
|
||||||
"Encountered an I/O error during document to pixels conversion,"
|
"Encountered an I/O error during document to pixels conversion,"
|
||||||
f" but the status of the conversion process is unknown (PID: {p.pid})"
|
f" but the status of the conversion process is unknown (PID: {p.pid})"
|
||||||
)
|
)
|
||||||
return errors.exception_from_error_code(error_code)
|
logs = None
|
||||||
|
if self.debug:
|
||||||
|
logs = "".join([line.decode() for line in p.stderr.readlines()])
|
||||||
|
return errors.exception_from_error_code(error_code, logs=logs)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_max_parallel_conversions(self) -> int:
|
def get_max_parallel_conversions(self) -> int:
|
||||||
|
|
|
@ -93,7 +93,7 @@ class Container(IsolationProvider):
|
||||||
return runtime
|
return runtime
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_runtime_security_args() -> List[str]:
|
def get_runtime_security_args(debug: bool) -> List[str]:
|
||||||
"""Security options applicable to the outer Dangerzone container.
|
"""Security options applicable to the outer Dangerzone container.
|
||||||
|
|
||||||
Our security precautions for the outer Dangerzone container are the following:
|
Our security precautions for the outer Dangerzone container are the following:
|
||||||
|
@ -137,6 +137,9 @@ class Container(IsolationProvider):
|
||||||
security_args += ["--network=none"]
|
security_args += ["--network=none"]
|
||||||
security_args += ["-u", "dangerzone"]
|
security_args += ["-u", "dangerzone"]
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
security_args += ["-e", "RUNSC_DEBUG=1"]
|
||||||
|
|
||||||
return security_args
|
return security_args
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -250,7 +253,7 @@ class Container(IsolationProvider):
|
||||||
extra_args: List[str] = [],
|
extra_args: List[str] = [],
|
||||||
) -> subprocess.Popen:
|
) -> subprocess.Popen:
|
||||||
container_runtime = self.get_runtime()
|
container_runtime = self.get_runtime()
|
||||||
security_args = self.get_runtime_security_args()
|
security_args = self.get_runtime_security_args(self.debug)
|
||||||
enable_stdin = ["-i"]
|
enable_stdin = ["-i"]
|
||||||
set_name = ["--name", name]
|
set_name = ["--name", name]
|
||||||
prevent_leakage_args = ["--rm"]
|
prevent_leakage_args = ["--rm"]
|
||||||
|
|
Loading…
Reference in a new issue