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 reghost, which is used
  for saving listen-hostname,
- new public accessors for that member, papplSystemSetRegHostName()
  and papplSystemGetRegHostName() - user can set the member to localhost
  or to the current hostname
- dnssd functions will check this member, and if it is localhost,
  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 1, 2024
1 parent 988b90a commit ab81728
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 15 deletions.
28 changes: 14 additions & 14 deletions pappl/dnssd.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,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->reghost || !printer->system->reghost)
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->reghost);

if_index = !strcmp(system->hostname, "localhost") ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;
if_index = !strcasecmp(system->reghost, "localhost") ? 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 +134,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->reghost, printer->system->port, "%s/", printer->uriname);

// Rename the service as needed...
if (printer->dns_sd_collision)
Expand Down Expand Up @@ -210,7 +210,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->reghost, /*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 +221,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->reghost, (uint16_t)system->port, num_txt, txt);
}

if (ret && !(printer->system->options & PAPPL_SOPTIONS_NO_TLS))
Expand All @@ -231,7 +231,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->reghost, (uint16_t)system->port, num_txt, txt);
}

// Add a geo-location record...
Expand All @@ -244,7 +244,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->reghost, (uint16_t)(9099 + printer->printer_id), num_txt, txt);
}

cupsFreeOptions(num_txt, txt);
Expand All @@ -255,7 +255,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->reghost, (uint16_t)system->port, num_txt, txt);
cupsFreeOptions(num_txt, txt);
}

Expand Down Expand Up @@ -298,12 +298,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->reghost || !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->reghost);

if_index = !strcmp(system->hostname, "localhost") ? CUPS_DNSSD_IF_INDEX_LOCAL : CUPS_DNSSD_IF_INDEX_ANY;
if_index = !strcasecmp(system->reghost, "localhost") ? 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 +359,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->reghost, (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->reghost, (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
6 changes: 5 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 @@ -1743,10 +1745,12 @@ default_system_cb(
if (server_hostname)
papplSystemSetHostName(system, server_hostname);

papplSystemSetRegHostName(system, listen_hostname);

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
81 changes: 81 additions & 0 deletions pappl/system-accessors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,35 @@ papplSystemGetPort(
}


//
// 'papplSystemGetRegHostName()' - Get hostname under which the services are
// registered.
//
// This function copies hostname used for service registration into the specified buffer.
//

char * // O - Hostname for service registration
papplSystemGetRegHostName(
pappl_system_t *system, // I - System
char *buffer, // I - String buffer
size_t bufsize) // I - Size of string buffer
{
if (system && buffer && bufsize > 0)
{
_papplRWLockRead(system);

if (system->reghost)
cupsCopyString(buffer, system->reghost, bufsize);

_papplRWUnlock(system);
}
else if (buffer)
buffer[0] = '\0';

return (buffer);
}


//
// 'papplSystemGetServerHeader()' - Get the Server: header for HTTP responses.
//
Expand Down Expand Up @@ -2006,6 +2035,15 @@ _papplSystemSetHostNameNoLock(
free(system->hostname);
system->hostname = strdup(value);

// Update registration hostname as well if it is not set or localhost
if (!system->reghost || strcasecmp(system->reghost, "localhost"))
{
if (system->reghost)
free(system->reghost);

system->reghost = strdup(value);
}

// Set the system TLS credentials...
cupsSetServerCredentials(NULL, system->hostname, 1);
}
Expand Down Expand Up @@ -2555,6 +2593,49 @@ papplSystemSetPrinterDrivers(
}


//
// 'papplSystemSetRegHostName()' - Set hostname under which the services will be
// registered.
//
// This function sets the hostname under which services will be registered - it can
// be localhost or the current hostname, otherwise registration hostname will be empty
// and service registration will be disabled (to prevent publishing service for
// different machine or when application listens on domain socket). In case 'name' is NULL,
// the current hostname is set as registration hostname.
//

void
papplSystemSetRegHostName(
pappl_system_t *system, // I - System
const char *name) // I - Hostname
{
const char *value = NULL; // New value

if (!system)
return;

_papplRWLockWrite(system);

if (system->hostname)
{
if (!name)
value = system->hostname;
else if (!strcasecmp(name, system->hostname))
goto end;
else if (!strcasecmp(name, "localhost"))
value = "localhost";

if (system->reghost)
free(system->reghost);

system->reghost = value ? strdup(value) : NULL;
}

end:
_papplRWUnlock(system);
}


//
// 'papplSystemSetSaveCallback()' - Set the save callback.
//
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 *reghost; // Hostname for registering services
};

typedef struct _pappl_timer_s // Timer callback data
Expand Down
2 changes: 2 additions & 0 deletions pappl/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ extern char *papplSystemGetOrganization(pappl_system_t *system, char *buffer, s
extern char *papplSystemGetOrganizationalUnit(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC;
extern char *papplSystemGetPassword(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC;
extern int papplSystemGetPort(pappl_system_t *system) _PAPPL_DEPRECATED("Use papplSystemGetHostPort instead.");
extern char *papplSystemGetRegHostName(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC;
extern const char *papplSystemGetServerHeader(pappl_system_t *system) _PAPPL_PUBLIC;
extern char *papplSystemGetSessionKey(pappl_system_t *system, char *buffer, size_t bufsize) _PAPPL_PUBLIC;
extern bool papplSystemGetTLSOnly(pappl_system_t *system) _PAPPL_PUBLIC;
Expand Down Expand Up @@ -232,6 +233,7 @@ extern void papplSystemSetOrganization(pappl_system_t *system, const char *valu
extern void papplSystemSetOrganizationalUnit(pappl_system_t *system, const char *value) _PAPPL_PUBLIC;
extern void papplSystemSetPassword(pappl_system_t *system, const char *hash) _PAPPL_PUBLIC;
extern void papplSystemSetPrinterDrivers(pappl_system_t *system, size_t num_drivers, pappl_pr_driver_t *drivers, pappl_pr_autoadd_cb_t autoadd_cb, pappl_pr_create_cb_t create_cb, pappl_pr_driver_cb_t driver_cb, void *data) _PAPPL_PUBLIC;
extern void papplSystemSetRegHostName(pappl_system_t *system, const char *name) _PAPPL_PUBLIC;
extern void papplSystemSetSaveCallback(pappl_system_t *system, pappl_save_cb_t cb, void *data) _PAPPL_PUBLIC;
extern void papplSystemSetUUID(pappl_system_t *system, const char *value) _PAPPL_PUBLIC;
extern void papplSystemSetVersions(pappl_system_t *system, size_t num_versions, pappl_version_t *versions) _PAPPL_PUBLIC;
Expand Down

0 comments on commit ab81728

Please sign in to comment.