From 58c47774fb9686a9ea60dbce71df328e1f742a1a Mon Sep 17 00:00:00 2001 From: Till Kamppeter Date: Wed, 29 Dec 2021 23:12:00 -0300 Subject: [PATCH] libcupsfilters: Fix resolver functions for DNS-SD-based URIs CUPS and cups-browsed use DNS-SD-service-name-based URIs, so that the printer URIs are robust against changes of network details, for example of the port, if Printer Applications on a system come up in different order at every boot. To be able to access the printer these URIs have to get resolved, which means to get converted into standard IPP URIs. This is done by two functions with their source being in cupsfilters/ipp.c. Unfortunately both functions have a bug and in this commit we fix these bugs to make the functions correctly working in all cases. 1. resolve_uri() This function calls cupsBackendDeviceURI() of libcups which resolves device URIs for the CUPS backends. As it is designed for only using in CUPS backends it needs some workarounds to make it usuable as universal library function and make it work in a wide range of system environments. One workaround was already applied from the beginning on, re-directing stderr into the Nirwana, to avoid messages to stderr. Another is needed and now added: We need to unset the DEVICE_URI environment variable as the function searches for the device URI to resolve there at first and not as argc[0]. Otherwise, if we are running under CUPS, in a backend, we get the print queue's device URI resolved and not the one which we supply. We save and restore the value of DEVICE_URI to keep the impact as low as possible. 2. ippfind_based_uri_converter() In this function the ippfind utility is called in a fork and the foreground (parent process) is getting ippfind's stdout through a pipe. The main process is picking up the data to use it for resolving the given URI. Here the parent process has unnecessarily: "dup"ed the read end of the pipe to stdin, and then read the lines from stdin. This prevents the calling program to use stdin by itself, for example to receive print job data. Now this is fixed by directly reading from the read end of the pipe. --- cupsfilters/ipp.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/cupsfilters/ipp.c b/cupsfilters/ipp.c index 5078d2a98..3bfcb0a3c 100644 --- a/cupsfilters/ipp.c +++ b/cupsfilters/ipp.c @@ -75,6 +75,7 @@ resolve_uri(const char *raw_uri) char *pseudo_argv[2]; const char *uri; int fd1, fd2; + char *save_device_uri_var; /* Eliminate any output to stderr, to get rid of the CUPS-backend-specific output of the cupsBackendDeviceURI() function */ @@ -83,12 +84,28 @@ resolve_uri(const char *raw_uri) dup2(fd2, 2); close(fd2); + /* If set, save the DEVICE_URI environment and then unset it, so that + if we are running under CUPS (as filter or backend) our raw_uri gets + resolved and not whatever URI is set in DEVICE_URI */ + if ((save_device_uri_var = getenv("DEVICE_URI")) != NULL) + { + save_device_uri_var = strdup(save_device_uri_var); + unsetenv("DEVICE_URI"); + } + /* Use the URI resolver of libcups to support DNS-SD-service-name-based URIs. The function returns the corresponding host-name-based URI */ pseudo_argv[0] = (char *)raw_uri; pseudo_argv[1] = NULL; uri = cupsBackendDeviceURI(pseudo_argv); + /* Restore DEVICE_URI envidonment variable if we had unset it */ + if (save_device_uri_var) + { + setenv("DEVICE_URI", save_device_uri_var, 1); + free(save_device_uri_var); + } + /* Re-activate stderr output */ dup2(fd1, 2); close(fd1); @@ -540,11 +557,9 @@ ippfind_based_uri_converter (const char *uri, int is_fax) goto error; } - dup2(post_proc_pipe[0], 0); - close(post_proc_pipe[0]); close(post_proc_pipe[1]); - fp = cupsFileStdin(); + fp = cupsFileOpenFd(post_proc_pipe[0], "r"); buffer = (char*)malloc(MAX_OUTPUT_LEN * sizeof(char)); if (buffer == NULL) { @@ -604,6 +619,8 @@ ippfind_based_uri_converter (const char *uri, int is_fax) memset(buffer, 0, MAX_OUTPUT_LEN); } + cupsFileClose(fp); + if (buffer != NULL) free(buffer); -- 2.47.3