apple / cups

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

CUPS's implementation of Expect: 100-continue is not compatible with ippusbxd #5801

Closed alexpevzner closed 3 years ago

alexpevzner commented 4 years ago

CUPS HTTP client sends HTTP requests with Expect: 100-continue header, immediately following by request body. It doesn't wait for the HTTP/1.1 100 Continue response from the device.

Actually, there is no good approach, how to correctly implement client-size Expect: handling. There are two possible situations, that client cannot distinguish a-priori:

  1. Server properly implements Expect: protocol, and responds with HTTP/1.1 100 Continue before body is received. At this case if client will not wait for response, everything will work correctly. However, if server will respond with any other status (which is allowed), request body will be unexpected for the server
  2. Server doesn't implement Expect: header properly, it simple ignores it. At this case, server will not send response before entire request (header + body) is received. If client will wait forever for the HTTP/1.1 100 Continue, a deadlock will occur. If it will wait with some timeout, and timeout was not big enough, we will get a situation similar to 1

So using Expect: header may cause client and server to disagree about connection state.

This more or less works over TCP, because in a case of unexpected error, there is a simple exit: TCP connection can be closed, which causes HTTP request to be effectively cancelled.

However, it doesn't work via IPP-over-USB. For the USB-backed HTTP connections, there is no equivalence of TCP connection close, and unconsumed bytes from the abandoned "connection" will arrive when next request will be arranged.

When IPP-over-USB is handled by the modern ipp-usb daemon, it also not a problem: ipp-usb acts as a full-scale HTTP proxy, and takes care about similar situations by itself (it sends HTTP/1.1 100 Continue up to the client, and strips Expect: header from request before forwarding it to device). But when widely-deployed old-fashion ippusbxd is in use, it doesn't understand HTTP protocol and can't do anything with that.

I propose to do one of the following:

  1. Completely disable client-side Expect: 100-continue. This is simple, but may slow down things a bit, when HTTP-level authentication is used and first request has a large body
  2. Disable Expect: 100-continue when printer's address is localhost or one of its aliases. ippusbxd is rarely used with non-localhost addresses
michaelrsweet commented 3 years ago

The CUPS client code waits for a response briefly before sending the document data for a print job. With IPP requests the authentication challenge won't come until the first part of the message body (with the IPP request) has been received since the auth requirements depend on the IPP operation and target (printer/job). Any IPP-USB code needs to monitor state transitions (at least) and serialize requests - see my IPP-USB gadget code in PAPPL, specifically the httpmon interface.

Nothing to be "fixed" here for CUPS...