OpenPrinting / ipp-usb

ipp-usb -- HTTP reverse proxy, backed by IPP-over-USB connection to device
BSD 2-Clause "Simplified" License
129 stars 11 forks source link

This program requires root privileges #49

Closed ahcodedthat closed 2 years ago

ahcodedthat commented 2 years ago

Running anything related to printing as root is very risky. Yet this program refuses to run without root, regardless of capabilities or file system permissions. Why is this?

alexpevzner commented 2 years ago

This program requires root privileges due to the need of USB access.

It is written in Go and uses Go native HTTP stack, which is tested on millions installations worldwide and proven to be safe, so I assume this program is quite safe.

alexpevzner commented 2 years ago

Note also, it was reviewed by many people from Canonical (Ubuntu), Debian, RedHat, Google etc teams and considered to be trusted. It's not a decision of a single person.

ahcodedthat commented 2 years ago

Are you sure USB access actually requires root? CUPS never needed it to print directly to USB; it only needed the device file permissions to be set up appropriately (which a standard udev rule takes care of). ipp-usb still seems to work correctly even with a very restrictive systemd configuration where it's pretty much root-in-name-only:

[Unit]
Description=Daemon for IPP over USB printer support
Documentation=man:ipp-usb(8)
After=cups.service avahi-daemon.service
Wants=avahi-daemon.service

[Service]
Type=simple
ExecStart=/sbin/ipp-usb udev
ProtectProc=invisible
ProcSubset=pid
TemporaryFileSystem=/etc:ro /run /var:ro
BindReadOnlyPaths=/etc/ipp-usb /run/avahi-daemon /run/dbus/system_bus_socket /run/systemd/journal/dev-log /run/systemd/journal/socket /run/systemd/journal/stdout /var/run
BindPaths=/dev/bus/usb /var/ipp-usb /var/log/ipp-usb
InaccessiblePaths=/boot /lost+found /media /mnt /opt /srv /usr/local
CapabilityBoundingSet=
NoNewPrivileges=yes
SecureBits=no-setuid-fixup no-setuid-fixup-locked noroot noroot-locked
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
DevicePolicy=closed
DeviceAllow=char-usb_device
PrivateIPC=yes
ProtectHostname=yes
ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
PrivateMounts=yes

Between that and the fact that ipp-usb is written in Go, that's pretty good security, but it could still be better. This configuration grants access to all USB devices, not just printers. If ipp-usb could be run as non-root, then it could be added to the lp group and therefore only have access to printers. Since any USB device could potentially be a printer, I don't believe there's any way to block access to non-printers with systemd.

alexpevzner commented 2 years ago

IPP over USB devices don't have a class-specific kernel driver, so ipp-usb uses a generic-level USB access.

Probably, ipp-usb permissions could be better fine tuned that now, but it is a noticeable amount of work in coordination with the maintainers of the major Linux distros (at least, Debian/Ubuntu/Fedora/RHEL, and I believe, there are nuances).

If you want to take this initiative, you are welcome and you can count on my help, but I don't have enough personal resources to drive this work solely by myself.

And in any case, I believe that from practical point of view, the existing implementation is secure enough.

P.S. At least on Fedora 35, cupsd runs as root

ahcodedthat commented 2 years ago

Okay, fair enough.

For what it's worth, I tried removing the root check myself, rebuilt it, ran it as lp on my Debian system, and it still prints and scans fine. But of course that doesn't mean it'll work without root on every computer and printer, only that it happens to work on mine.

You're right that cupsd normally runs as root. I thought it had its own uid, which it did on very old Debian versions, but it has run as root for a long time now. My mistake.

alexpevzner commented 2 years ago

Closed -- this is by design