apple / cups

Apple CUPS Sources
https://www.cups.org
Apache License 2.0
1.96k stars 464 forks source link

Allow cupsEnumDests() to filter/not show discovered printers via config file #5011

Closed tillkamppeter closed 7 years ago

tillkamppeter commented 7 years ago

Print dialogs are supposed to show all printers listed by cupsEnumDests(). These are all CUPS queues of the local CUPS daemon and in addition IPP printers discovered via DNS-SD (IPP network printers, IPP-over-USB printers, remote CUPS queues). For the discovered printers CUPS generates a temporary queue if one accesses them. In small networks this works well, but imagine a network with 10000s of printers. The user does not easily find the printers relevant for him. Now my idea is to allow a possibility to let cupsEnumDests() show only the CUPS queues of the local daemon or apply filters to decide whether to show or not show a discovered printer. This configuration (filters, no discovered printers at all) should be definable in config files, a system-wide one for the administrator (in /etc/cups/) and a by-user one (in ~/.cups/).

jsmeix commented 7 years ago

System-wide filtering by the admin of what printing destinations are directly available for normal users via CUPS library calls is not only a usability feature for printing in huge networks but also needed functionality for administrative reasons and even (to some extent) for security reasons (see below).

In company or corporate internal network environments where workstations (or whatever other "client" systems) are configured by admins, the admin must be able to set up system-wide filtering rules what CUPS printing destinations are available for the user.

For example the admin may not want that users print directly on printer devices that are discovered via DNS-SD. Instead all users may have to print only via print queues on one or more company CUPS servers (e.g. because some kind of printing accounting happens on the servers or the queues on the servers have some economical default settings like "toner saving" and "duplex printing").

Or the admin may not want that users print directly on some printer devices that are discovered via DNS-SD (e.g. because he knows those devices do not behave well or because some devices are not intended for common usage) while printing directly on other DNS-SD printer devices is allowed.

I wrote "even (to some extent) for security reasons" because when some printing destinations are not directly available for normal users via CUPS library calls it is - strictly speaking - no real hard security. Strictly speaking it is only "security by obscurity" when an experienced user could still access them manually (e.g. via a self-written program). Nevertheless I think in practice it makes a difference if also any "unwanted" printing destinations would be "just available for normal users" versus when the user must do special actions to get access. There could be even a legal difference when prohibited access is "just possible" (even accidentally) versus when prohibited access is impossible by "usual means".

michaelrsweet commented 7 years ago

@jsmeix DNS-SD does not offer filtering based on user/privilege - it is a public service discovery protocol. You want LDAP (which is something that we plan on supporting in the future).

@tillkamppeter The kinds of filtering you are asking for was tried and discarded 15 years ago. The CUPS printer attributes and Bonjour TXT record fields were added specifically for this but have never been used enough to justify their existence. Moreover, Bonjour is typically limited by subnet and/or subdomain, which will keep the printer list to a more manageable size (and if you don't split things up then you will have serious performance issues outside of CUPS from Bonjour alone...)

So as well-intentioned as this feature request is, I do not see us implementing primitive client-side filters. The real solution is to support enterprise discovery protocols (e.g. LDAP) and point people at network management/design guides that show how to best architect networks for performance and usability.

tillkamppeter commented 7 years ago

But could we not at least put a simple boolean switch into a config file in /etc/cups/ which allows turning off the listing of network-discovered printers in cupsEnumDests()?

jsmeix commented 7 years ago

@michaelrsweet many thanks for your explanation of the reasons behind.

I suggest that this topic should be well documented to avoid that users and admins use DNS-SD discovery with false expectations.

@tillkamppeter I assume turning off the listing of network-discovered printers means turning off DNS-SD discovery completely because as far as I understand it DNS-SD cannot distinguish between e.g. a DNS-SD discovered remote CUPS printserver queue versus a DNS-SD discovered remote "raw" printer device.

As far as I understand it DNS-SD is an "all or nothing" discovery protocol for services that are public/generally available in the local subnet and/or subdomain which means when an admin does not what that something is generally available, he must not advertise it via DNS-SD.

Therefore - as far as I understand it - in my above example when the admin does not want that users print directly on some printer devices, he must change the settings in those printer devices so that those printer devices do no longer advertise themselves via DNS-SD.

@michaelrsweet please correct me if I misunderstand things.

michaelrsweet commented 7 years ago

@tillkamppeter A boolean flag would break the new "lpstat -e" functionality. Better to build the proper smarts into the print dialog and let network administrators control whether Bonjour is used/available on specific network segments. I will also document how to a) know whether a destination already has an associated local queue and b) how to only enumerate local queues.

@jsmeix Your understanding of Bonjour/DNS-SD is correct. Even in the context of CUPS sharing, if you configure a print queue with a policy/ACL that restricts access, users without access will still be able to see the printer but will not be able to submit print jobs. We may be able to do something smarter for LDAP in the future.

ghomem commented 2 years ago

Hello from the future,

What is the current process by which we can ensure that:

?

This is how CUPS used to work.

What I am currently seeing is:

  1. if we disable cups-browsed on the client we get the cups "network destinations" (the IPP ones from lpstat -e) on Libreoffice and oKular but not on Firefox and Chrome; seems that some apps use cups libraries to obtain "network destination" whereas others are expecting traditional local queues
  2. if we enable cups-browsed we have the tradidional local queues visible on Firefox and Chrome (and lp, lpstat -a) but we have both the local queues and the "network destinations" on Libreoffice and oKular, which leads to user confusion.

I completely understand what @tillkamppeter @jsmeix expressed above.

michaelrsweet commented 2 years ago

@ghomem If you want only print servers to communicate with printers, you can either put the printers on a separate subnet and/or disable DNS-SD on the printers themselves.

ghomem commented 2 years ago

Thank you for your answer @michaelrsweet .

The admins of Linux desktops are not always the network admins and are not always the printer admins. Sometimes the network team is separate. Sometimes the printers are shared across operating systems. Sometimes some of the printers are managed by an external company that leases them. So, changing the network or the printer configuration to benefit a certain OS might not be possible. Furthermore, disabling DNS-SD on the printers, when possible, scales in effort proportionally to the number of printers.

What I am trying to understand is why CUPS lost one of its best selling points, which was driverless structured printing achieved by means of a central print server.

If I understand correctly, the suggestion by @tillkamppeter

allow a possibility to let cupsEnumDests() show only the CUPS queues of the local daemon or apply filters to decide whether to show or not show a discovered printer

would re-enable such a possibility, a situation which would be very welcome.

Please let me know if I misunderstood something. Thanks again.

michaelrsweet commented 2 years ago

@ghomem It would be better if we could move this discussion over to OpenPrinting CUPS...

Right now the way the code should be working is that setting ServerName in "client.conf" to a remote server will cause cupsEnumDests to only report the queues on that server. If that isn't working it is a bug...

ghomem commented 2 years ago

@michaelrsweet thanks for the answer. I can file a bug report at OpenPrinting CUPS if there is a bug, but let me confirm first if there is a bug or just lack of clarity on how to acheive a certain goal with the current CUPS.

By creating a /etc/cups/client.conf file do you mean to not have a local CUPS, like described here:

https://wiki.debian.org/CUPSPrintQueues#Printing_Without_a_Local_CUPS_Server

So, I should stop avahi-daemon and cups-browsed and the client space (lpq, lpstat, kde print dialogue, gtk print dialog) would find the queues anyway? (sorry if it is a silly question, I always used a local CUPS daemon that would find the printers on the CUPS print server).

michaelrsweet commented 2 years ago

@ghomem You might need avahi-daemon for other services, but yes cupsd and cups-browsed don't need to run in this configuration.

ghomem commented 2 years ago

Thanks for the answer @michaelrsweet . We will try to that and report how it goes.

tillkamppeter commented 2 years ago
  1. if we enable cups-browsed we have the tradidional local queues visible on Firefox and Chrome (and lp, lpstat -a) but we have both the local queues and the "network destinations" on Libreoffice and oKular, which leads to user confusion.

@ghomem The problem with the duplicate appearing of printers (temporary CUPS queue and cups-browsed-generated queue I have fixed already in the GIT of cups-filters).

ghomem commented 2 years ago

Thanks for the answer @michaelrsweet . We will try to that and report how it goes.

@ghomem It would be better if we could move this discussion over to OpenPrinting CUPS...

Right now the way the code should be working is that setting ServerName in "client.conf" to a remote server will cause cupsEnumDests to only report the queues on that server. If that isn't working it is a bug...

We have tried this but unfortunately Firefox crashes every second time we print. Libreoffice, oKular and Chrome do print correctly. Firefox prints without crashing in the traditional setup with local CUPS.

ghomem commented 2 years ago
  1. if we enable cups-browsed we have the tradidional local queues visible on Firefox and Chrome (and lp, lpstat -a) but we have both the local queues and the "network destinations" on Libreoffice and oKular, which leads to user confusion.

@ghomem The problem with the duplicate appearing of printers (temporary CUPS queue and cups-browsed-generated queue I have fixed already in the GIT of cups-filters).

Hi @tillkamppeter , nice to read from you. Thanks sharing this :-)

ghomem commented 2 years ago

This is what we needed to do, in order to achieve centralized management of print queues. Tested on Kubuntu 20.04.

Configuration of structured CUPS clients

Currently CUPS uses the DNS-SD protocol to advertise its printers to the LAN. Because we don't want multiplication of printer queues we need to ensure that we only accept DNS-SD traffic from the CUPS server. In order to achieve that, the firewall must only allow DNS-SD traffic between the CUPS client and the CUPS server. The firewall can be configured with a one time execution of a script on a local computer console:

# requirements
CUPS_SERVER=192.168.5.4
sudo apt install iptables-persistent

# IPv4
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -i lo  -j ACCEPT
iptables -A INPUT -d 127.0.0.0/8 ! -i lo -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22 -j ACCEPT
iptables -A INPUT -s ${CUPS_SERVER}/32 -p udp -m multiport --dports 5353 -j ACCEPT

# IPv6
ip6tables -F
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP

# saving the rules
service netfilter-persistent save

In order to further control the configuration of the client computer we must execute the following:

mv /etc/cups/cups-browsed.conf /etc/cups/cups-browsed.conf.orig
vim /etc/cups/cups-browsed.conf

and insert the following content:

# currently we need dnssd to be here for the printers to appear even if they are remote CUPS printers
# the browsing protocol and the queue type are different things
BrowseRemoteProtocols cups dnssd

# the original value is 60, we are using a smaller value to ease debugging
BrowseInterval 10

# this ensures that the local CUPS queues come only from the CUPS print server
# but does not affect the instant queues (network destinations) found by the print dialogues
BrowseOrder Deny,Allow
BrowseDeny All
BrowseAllow 192.168.5.4 # add as many lines as necessary

# this only applies to remote CUPS printers, regardless of how they are advertised
# but becasue we are only accepting printers from our printserver it applies to all of them
LocalQueueNamingRemoteCUPS DNS-SD

# This will make CUPS create local queues with the exact same name as the IPP "network destinations"
# with this set to No, Firefox and Chrome will take the normal CUPS local queues but Libreoffice and Firefox
# will see both those queues but also the IPP advertised "network destinations" (all that coming from our CUPS server)
CreateIPPPrinterQueues Yes

# this enables debug via /var/log/cups/cups-browsed_log
DebugLogging file

We must ensure that both cups and cups-browsed are enabled:

sudo systemctl enable cups.service
sudo systemctl enable cups-browsed.service

Once these changes are done, the computer must be rebooted.

With this setup, the desktop computer should list exactly the printers from our CUPS server without any duplications. One limitation of this setup is that we can't prevent that the queue names we configured in the server are extended by the DNS-SD protocol (ex: BROTHER-BW becoming BROTHER_BW_printserver_01) becoming longer queues on the desktop computer.

dholbert commented 2 years ago

We have tried this but unfortunately Firefox crashes every second time we print.

(Firefox developer here -- just dropping in to leave a quick note & close the loop on this^, after chatting briefly with @ghomem: I suspect the crash that ghomem referenced here was an instance of https://bugzilla.mozilla.org/show_bug.cgi?id=1750768 , which is really Firefox suffering from this upstream GTK bug: https://gitlab.gnome.org/GNOME/gtk/-/issues/4672 )