Skip to content

Commit

Permalink
dnssd.c: Enable service registration on loopback only
Browse files Browse the repository at this point in the history
In case users would like to prevent sharing services from printer
 applications to local network, restrict it to localhost and let CUPS
 do the sharing.

This can be done by setting listen-hostname in PAPPL API - this prevents
accessing the public addresses, but the service is still published
on those public addresses. This can be prevented if the machine hostname
is changed to localhost, but that's not desired on machines IIUC.

The PR does the following:

- introduced new pappl system member listen_hostname, which is used
  for saving listen-hostname,
- the member will be set in `papplSystemAddListeners()` - in case
  the listener is domain socket or the listener name is not defined
  and no hostname is set, listen_hostname is NULL and disables advertising,
- dnssd functions will check this member, and if it is localhost or matching
  IP address, it will use loopback index,
- in case of Avahi it passes NULL as hostname to let Avahi decide
  what hostname to use (in case of hostname conflicts - and Avahi forbids
  using localhost if it is not FQDN).

The result is that if reghost is set to localhost, the service is published
on .local address, but resolved to loopback because CUPS uses DNS-SD names in URIs.

PAPPL 2.x version requires CUPS PR OpenPrinting/cups#902
to have it working.
  • Loading branch information
zdohnal committed Mar 6, 2024
1 parent 988b90a commit 78c654e
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 15 deletions.
48 changes: 34 additions & 14 deletions pappl/dnssd.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

static void dns_sd_printer_callback(cups_dnssd_service_t *service, pappl_printer_t *printer, cups_dnssd_flags_t flags);
static void dns_sd_system_callback(cups_dnssd_service_t *service, pappl_system_t *system, cups_dnssd_flags_t flags);
static bool dns_sd_is_loopback(const char *name);


//
Expand Down Expand Up @@ -51,12 +52,12 @@ _papplPrinterRegisterDNSSDNoLock(
const char *papermax; // PaperMax string value (legacy)


if (!printer->dns_sd_name || !printer->system->is_running || (printer->system->options & PAPPL_SOPTIONS_NO_DNS_SD))
if (!printer->dns_sd_name || !printer->system->is_running || (printer->system->options & PAPPL_SOPTIONS_NO_DNS_SD) || !system->listen_hostname || !printer->system->listen_hostname)
return (false);

papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s' on '%s'", printer->dns_sd_name, printer->system->hostname);
papplLogPrinter(printer, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s' on '%s'", printer->dns_sd_name, printer->system->listen_hostname);

if_index = !strcmp(system->hostname, "localhost") ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;
if_index = dns_sd_is_loopback(system->listen_hostname) ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;

// Get attributes and values for the TXT record...
color_supported = ippFindAttribute(printer->driver_attrs, "color-supported", IPP_TAG_BOOLEAN);
Expand Down Expand Up @@ -134,7 +135,7 @@ _papplPrinterRegisterDNSSDNoLock(
break;
}

httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl, sizeof(adminurl), "http", NULL, printer->system->hostname, printer->system->port, "%s/", printer->uriname);
httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl, sizeof(adminurl), "http", NULL, printer->system->listen_hostname, printer->system->port, "%s/", printer->uriname);

// Rename the service as needed...
if (printer->dns_sd_collision)
Expand Down Expand Up @@ -210,7 +211,7 @@ _papplPrinterRegisterDNSSDNoLock(
// Register the _printer._tcp (LPD) service type with a port number of 0 to
// defend our service name but not actually support LPD...
if (ret)
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_printer._tcp", /*domain*/NULL, system->hostname, /*port*/0, /*num_txt*/0, /*txt*/NULL);
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_printer._tcp", /*domain*/NULL, system->listen_hostname, /*port*/0, /*num_txt*/0, /*txt*/NULL);

// Then register the corresponding IPP service types with the real port
// number to advertise our printer...
Expand All @@ -221,7 +222,7 @@ _papplPrinterRegisterDNSSDNoLock(
else
cupsCopyString(regtype, "_ipp._tcp", sizeof(regtype));

ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, regtype, /*domain*/NULL, system->hostname, (uint16_t)system->port, num_txt, txt);
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, regtype, /*domain*/NULL, system->listen_hostname, (uint16_t)system->port, num_txt, txt);
}

if (ret && !(printer->system->options & PAPPL_SOPTIONS_NO_TLS))
Expand All @@ -231,7 +232,7 @@ _papplPrinterRegisterDNSSDNoLock(
else
cupsCopyString(regtype, "_ipps._tcp", sizeof(regtype));

ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, regtype, /*domain*/NULL, system->hostname, (uint16_t)system->port, num_txt, txt);
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, regtype, /*domain*/NULL, system->listen_hostname, (uint16_t)system->port, num_txt, txt);
}

// Add a geo-location record...
Expand All @@ -244,7 +245,7 @@ _papplPrinterRegisterDNSSDNoLock(
num_txt = cupsRemoveOption("rp", num_txt, &txt);
num_txt = cupsRemoveOption("TLS", num_txt, &txt);

ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_pdl-datastream._tcp", /*domain*/NULL, system->hostname, (uint16_t)(9099 + printer->printer_id), num_txt, txt);
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_pdl-datastream._tcp", /*domain*/NULL, system->listen_hostname, (uint16_t)(9099 + printer->printer_id), num_txt, txt);
}

cupsFreeOptions(num_txt, txt);
Expand All @@ -255,7 +256,7 @@ _papplPrinterRegisterDNSSDNoLock(
snprintf(adminurl, sizeof(adminurl), "%s/", printer->uriname);
num_txt = cupsAddOption("path", adminurl, 0, &txt);

ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_http._tcp,_printer", /*domain*/NULL, system->hostname, (uint16_t)system->port, num_txt, txt);
ret &= cupsDNSSDServiceAdd(printer->dns_sd_services, "_http._tcp,_printer", /*domain*/NULL, system->listen_hostname, (uint16_t)system->port, num_txt, txt);
cupsFreeOptions(num_txt, txt);
}

Expand Down Expand Up @@ -298,12 +299,12 @@ _papplSystemRegisterDNSSDNoLock(


// Make sure we have all of the necessary information to register the system...
if (!system->dns_sd_name || !system->hostname || !system->uuid || !system->is_running || (system->options & PAPPL_SOPTIONS_NO_DNS_SD))
if (!system->dns_sd_name || !system->hostname || !system->listen_hostname || !system->uuid || !system->is_running || (system->options & PAPPL_SOPTIONS_NO_DNS_SD))
return (false);

papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s' on '%s'", system->dns_sd_name, system->hostname);
papplLog(system, PAPPL_LOGLEVEL_DEBUG, "Registering DNS-SD name '%s' on '%s'", system->dns_sd_name, system->listen_hostname);

if_index = !strcmp(system->hostname, "localhost") ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;
if_index = dns_sd_is_loopback(system->listen_hostname) ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;

// Rename the service as needed...
if (system->dns_sd_collision)
Expand Down Expand Up @@ -359,14 +360,14 @@ _papplSystemRegisterDNSSDNoLock(
if (system->location != NULL)
num_txt = cupsAddOption("note", system->location, num_txt, &txt);

ret &= cupsDNSSDServiceAdd(system->dns_sd_services, "_ipps-system._tcp", /*domain*/NULL, system->hostname, (uint16_t)system->port, num_txt, txt);
ret &= cupsDNSSDServiceAdd(system->dns_sd_services, "_ipps-system._tcp", /*domain*/NULL, system->listen_hostname, (uint16_t)system->port, num_txt, txt);

cupsFreeOptions(num_txt, txt);
}

// Then the web interface...
if (ret && (system->options & PAPPL_SOPTIONS_MULTI_QUEUE))
ret &= cupsDNSSDServiceAdd(system->dns_sd_services, "_http._tcp,_printer", /*domain*/NULL, system->hostname, (uint16_t)system->port, /*num_txt*/0, /*txt*/NULL);
ret &= cupsDNSSDServiceAdd(system->dns_sd_services, "_http._tcp,_printer", /*domain*/NULL, system->listen_hostname, (uint16_t)system->port, /*num_txt*/0, /*txt*/NULL);

if (ret && system->geo_location)
ret &= cupsDNSSDServiceSetLocation(system->dns_sd_services, system->geo_location);
Expand Down Expand Up @@ -460,3 +461,22 @@ dns_sd_system_callback(
if (flags & CUPS_DNSSD_FLAGS_ERROR)
papplLog(system, PAPPL_LOGLEVEL_ERROR, "DNS-SD registration of '%s' failed.", system->dns_sd_name);
}


//
// 'dns_sd_is_loopback()' - Find out whether the string means
// localhost
//

static bool
dns_sd_is_loopback(const char *name)
{
if (!strcasecmp(name, "localhost"))
return (true);
else if (!strcmp(name, "127.0.0.1"))
return (true);
else if (!strcmp(name, "[::1]"))
return (true);

return (false);
}
4 changes: 3 additions & 1 deletion pappl/mainloop-subcommands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,8 @@ default_system_cb(
// Log file
*server_hostname = cupsGetOption("server-hostname", num_options, options),
// Server hostname
*listen_hostname = cupsGetOption("listen-hostname", num_options, options),
// Hostname for listening
*value, // Other option
*valptr; // Pointer into option
pappl_loglevel_t loglevel = PAPPL_LOGLEVEL_WARN;
Expand Down Expand Up @@ -1746,7 +1748,7 @@ default_system_cb(
if (!cupsGetOption("private-server", num_options, options))
{
// Listen for TCP/IP connections...
papplSystemAddListeners(system, cupsGetOption("listen-hostname", num_options, options));
papplSystemAddListeners(system, listen_hostname);
}

return (system);
Expand Down
8 changes: 8 additions & 0 deletions pappl/system-accessors.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ papplSystemAddListeners(
ret = add_listeners(system, name, 0, AF_LOCAL);
if (ret && !system->domain_path)
system->domain_path = strdup(name);

system->listen_hostname = NULL;
}
else
#endif // !_WIN32
Expand Down Expand Up @@ -141,6 +143,8 @@ papplSystemAddListeners(
if (ret)
system->port = port;
}

system->listen_hostname = strdup(name);
}
else if (name && *name == '[')
{
Expand Down Expand Up @@ -169,6 +173,8 @@ papplSystemAddListeners(
if (ret)
system->port = port;
}

system->listen_hostname = strdup(name);
}
else
{
Expand Down Expand Up @@ -201,6 +207,8 @@ papplSystemAddListeners(
add_listeners(system, name, port, AF_INET6);
}
}

system->listen_hostname = system->hostname ? strdup(system->hostname) : NULL;
}

return (ret);
Expand Down
1 change: 1 addition & 0 deletions pappl/system-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ struct _pappl_system_s // System data
size_t max_image_size; // Maximum image file size (uncompressed)
int max_image_width, // Maximum image file width
max_image_height; // Maximum image file height
char *listen_hostname; // Listening and registration hostname
};

typedef struct _pappl_timer_s // Timer callback data
Expand Down
2 changes: 2 additions & 0 deletions pappl/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ papplSystemDelete(
free(system->name);
free(system->dns_sd_name);
free(system->hostname);
if (system->listen_hostname)
free(system->listen_hostname);
free(system->domain_path);
free(system->server_header);
free(system->directory);
Expand Down

0 comments on commit 78c654e

Please sign in to comment.