Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for IPP / driverless printing #2332

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Description: securedrop client for qubes workstation

Package: securedrop-export
Architecture: all
Depends: ${misc:Depends}, python3, udisks2, cups, printer-driver-brlaser, printer-driver-hpcups, system-config-printer, xpp, libcups2, gnome-disk-utility, libreoffice,
Depends: ${misc:Depends}, python3, udisks2, cups, cups-ipp-utils, printer-driver-brlaser, printer-driver-hpcups,
avahi-daemon, system-config-printer, xpp, libcups2, gnome-disk-utility, libreoffice,
desktop-file-utils, shared-mime-info, libfile-mimeinfo-perl
Description: Submission export scripts for SecureDrop Workstation
This package provides scripts used by the SecureDrop Qubes Workstation to
Expand Down
1 change: 1 addition & 0 deletions debian/securedrop-export.install
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export/files/application-x-sd-export.xml usr/share/mime/packages
export/files/send-to-usb.desktop usr/share/applications
export/files/sd-logo.png usr/share/securedrop/icons
export/files/tcrypt.conf etc/udisks2
export/files/60-securedrop-export.preset usr/lib/systemd/system-preset
4 changes: 4 additions & 0 deletions export/files/60-securedrop-export.preset
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# avahi-daemon so that driverless printers are detected when
# plugged in via USB, overriding 75-qubes-vm.preset

enable avahi-daemon.service
58 changes: 44 additions & 14 deletions export/securedrop_export/print/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,32 +143,59 @@ def _check_printer_setup(self) -> None:
Check printer setup.
Raise ExportException if supported setup is not found.
"""
legacy_printers=False
try:
logger.info("Searching for printer")
output = subprocess.check_output(["sudo", "lpinfo", "-v"])
printers = [x for x in output.decode("utf-8").split() if "usb://" in x]

printers = self._get_printers_ipp()
if not printers:
logger.info("No usb printers connected")
raise ExportException(sdstatus=Status.ERROR_PRINTER_NOT_FOUND)
# look for legacy printers after no IPP ones are detected
printers = self._get_printers_legacy()
legacy_printers=True

supported_printers = [
p for p in printers if any(sub in p for sub in self.SUPPORTED_PRINTERS)
]
if not supported_printers:
logger.info(f"{printers} are unsupported printers")
raise ExportException(sdstatus=Status.ERROR_PRINTER_NOT_SUPPORTED)
if not printers:
logger.info("No supported printers connected")
raise ExportException(sdstatus=Status.ERROR_PRINTER_NOT_FOUND)

if len(supported_printers) > 1:
logger.info("Too many usb printers connected")
if len(printers) > 1:
logger.info("Too many printers connected")
raise ExportException(sdstatus=Status.ERROR_MULTIPLE_PRINTERS_FOUND)

printer_uri = printers[0]
printer_ppd = self._install_printer_ppd(printer_uri)
self._setup_printer(printer_uri, printer_ppd)
if legacy_printers: # IPP printers are auto-detected by the print dialog
self._setup_printer(printer_uri)
except subprocess.CalledProcessError as e:
logger.error(e)
raise ExportException(sdstatus=Status.ERROR_UNKNOWN)

def _get_printers_legacy(self) -> list[str]:
logger.info("Searching for legacy printers")
output = subprocess.check_output(["sudo", "lpinfo", "-v"])
discovered_printers = [x for x in output.decode("utf-8").split() if "usb://" in x]

supported_printers = [
p for p in discovered_printers if any(sub in p for sub in self.SUPPORTED_PRINTERS)
]
if not supported_printers:
logger.info(f"{discovered_printers} are unsupported printers")
raise ExportException(sdstatus=Status.ERROR_PRINTER_NOT_SUPPORTED)

return supported_printers

def _get_printers_ipp(self) -> list[str]:
logger.info("Searching for IPP printers (driverless)")
discovered_printers = subprocess.check_output(
["ippfind"],
universal_newlines=True
).split()

if discovered_printers:
logger.debug(f"Found IPP printers: {', '.join(discovered_printers)}")
else:
logger.debug(f"No IPP were found")

return discovered_printers

def _get_printer_uri(self) -> str:
"""
Get the URI via lpinfo. Only accept URIs of supported printers.
Expand Down Expand Up @@ -202,6 +229,9 @@ def _get_printer_uri(self) -> str:
return printer_uri

def _install_printer_ppd(self, uri):
"""
Discovery and installation of PPD driver (for legacy printers)
"""
if not any(x in uri for x in self.SUPPORTED_PRINTERS):
logger.error(f"Cannot install printer ppd for unsupported printer: {uri}")
raise ExportException(sdstatus=Status.ERROR_PRINTER_NOT_SUPPORTED)
Expand Down
Loading