Everywhere printer configuration.
return (CUPS_BACKEND_STOP);
}
- if (!lcreds)
- {
- /*
- * Could not load the credentials, let's save the ones we have so we
- * can detect changes...
- */
+ /*
+ * Save the credentials we have so we can detect changes...
+ */
- cupsSaveCredentials(NULL, hostname, creds, /*key*/NULL);
- }
+ cupsSaveCredentials(NULL, hostname, creds, /*key*/NULL);
free(lcreds);
free(creds);
lresource[256]; // URI resource (local copy)
int lport; // URI port (local copy)
http_encryption_t encryption; // Type of encryption to use
+ http_uri_status_t uri_status; // URI separation status
DEBUG_printf("httpConnectURI(uri=\"%s\", host=%p, hsize=%u, port=%p, resource=%p, rsize=%u, blocking=%d, msec=%d, cancel=%p, require_ca=%s)", uri, (void *)host, (unsigned)hsize, (void *)port, (void *)resource, (unsigned)rsize, blocking, msec, (void *)cancel, require_ca ? "true" : "false");
}
// Get the URI components...
- if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, hsize, port, resource, rsize) < HTTP_URI_STATUS_OK)
+ if ((uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, hsize, port, resource, rsize)) < HTTP_URI_STATUS_OK)
+ {
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, httpURIStatusString(uri_status), 0);
return (NULL);
+ }
DEBUG_printf("1httpConnectURI: scheme=\"%s\", host=\"%s\", port=%d, resource=\"%s\"", scheme, host, *port, resource);
http = httpConnect2(host, *port, /*addrlist*/NULL, AF_UNSPEC, encryption, blocking, msec, cancel);
- if (httpIsEncrypted(http) && require_ca)
+ if (httpIsEncrypted(http))
{
// Validate trust with service...
char *creds; // Peer credentials...
creds = httpCopyPeerCredentials(http);
trust = cupsGetCredentialsTrust(/*path*/NULL, host, creds, require_ca);
- free(creds);
-
- if (trust != HTTP_TRUST_OK)
+ if (trust == HTTP_TRUST_OK)
{
+ // Pin the trusted credentials (for TOFU)...
+ cupsSaveCredentials(/*path*/NULL, host, creds, /*key*/NULL);
+ }
+ else if (trust != HTTP_TRUST_RENEWED)
+ {
+ // Don't allow the connection...
httpClose(http);
http = NULL;
}
+
+ free(creds);
}
return (http);
// Load the credentials...
if (!gnutls_import_certs(credentials, &num_certs, certs))
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to import credentials."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Unable to import credentials."), 1);
return (HTTP_TRUST_UNKNOWN);
}
if (!cg->trust_first || require_ca)
{
// Do not trust certificates on first use...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (cupsGetCredentialsExpiration(credentials) <= cupsGetCredentialsExpiration(tcreds))
{
// The new credentials are not newly issued...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are older than stored credentials."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are older than stored credentials."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cupsAreCredentialsValidForName(common_name, credentials))
{
// The common name does not match the issued certificate...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are not valid for name."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are not valid for name."), 1);
trust = HTTP_TRUST_INVALID;
}
}
else if ((cg->validate_certs || require_ca) && !cupsAreCredentialsValidForName(common_name, credentials))
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No stored credentials, not valid for name."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("No stored credentials, not valid for name."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (num_certs > 1)
}
if (trust != HTTP_TRUST_OK)
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials do not validate against site CA certificate."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials do not validate against site CA certificate."), 1);
free(tcreds);
}
}
else if (require_ca)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials are not CA-signed."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials are not CA-signed."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cg->trust_first)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cg->any_root || require_ca)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Self-signed credentials are blocked."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Self-signed credentials are blocked."), 1);
trust = HTTP_TRUST_INVALID;
}
time(&curtime);
if (curtime < gnutls_x509_crt_get_activation_time(certs[0]) || curtime > gnutls_x509_crt_get_expiration_time(certs[0]))
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials have expired."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), 1);
trust = HTTP_TRUST_EXPIRED;
}
}
// Load the credentials...
if ((certs = openssl_load_x509(credentials)) == NULL)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to import credentials."), true);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Unable to import credentials."), true);
return (HTTP_TRUST_UNKNOWN);
}
if (!cg->trust_first || require_ca)
{
// Do not trust certificates on first use...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (cupsGetCredentialsExpiration(credentials) <= cupsGetCredentialsExpiration(tcreds))
{
// The new credentials are not newly issued...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are older than stored credentials."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are older than stored credentials."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cupsAreCredentialsValidForName(common_name, credentials))
{
// The common name does not match the issued certificate...
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are not valid for name."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are not valid for name."), 1);
trust = HTTP_TRUST_INVALID;
}
}
else if ((cg->validate_certs || require_ca) && !cupsAreCredentialsValidForName(common_name, credentials))
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No stored credentials, not valid for name."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("No stored credentials, not valid for name."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (sk_X509_num(certs) > 1)
}
if (trust != HTTP_TRUST_OK)
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials do not validate against site CA certificate."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials do not validate against site CA certificate."), 1);
free(tcreds);
}
}
else if (require_ca)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials are not CA-signed."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials are not CA-signed."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cg->trust_first)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), 1);
trust = HTTP_TRUST_INVALID;
}
else if (!cg->any_root || require_ca)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Self-signed credentials are blocked."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Self-signed credentials are blocked."), 1);
trust = HTTP_TRUST_INVALID;
}
time(&curtime);
if (curtime < openssl_get_date(cert, 0) || curtime > openssl_get_date(cert, 1))
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials have expired."), 1);
+ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), 1);
trust = HTTP_TRUST_EXPIRED;
}
}
/*
* IPP routines for the CUPS scheduler.
*
- * Copyright © 2020-2023 by OpenPrinting
+ * Copyright © 2020-2024 by OpenPrinting
* Copyright © 2007-2021 by Apple Inc.
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
* information.
*/
-/*
- * Include necessary headers...
- */
-
#include "cupsd.h"
#include <cups/ppd-private.h>
char device_uri[1024], /* Device URI */
fromppd[1024], /* Source PPD */
toppd[1024], /* Destination PPD */
- scheme[32], /* URI scheme */
- userpass[256], /* User:pass */
host[256], /* Hostname */
resource[1024], /* Resource path */
uri[1024], /* Resolved URI, if needed */
line[1024]; /* Line from PPD */
int port; /* Port number */
- http_encryption_t encryption; /* Type of encryption to use */
http_t *http; /* Connection to printer */
ipp_t *request, /* Request to printer */
*response = NULL; /* Response from printer */
cupsCopyString(device_uri, uri, sizeof(device_uri));
}
- if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ if ((http = httpConnectURI(device_uri, host, sizeof(host), &port, resource, sizeof(resource), /*blocking*/true, /*msec*/30000, /*cancel*/NULL, /*require_ca*/false)) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Bad device URI \"%s\".", printer->name, device_uri);
-
- /* Force printer to timeout and be deleted */
- cupsRWLockWrite(&printer->lock);
- printer->state_time = 0;
- cupsRWUnlock(&printer->lock);
-
- send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("Bad device URI \"%s\"."), device_uri);
- goto finish_response;
- }
-
- if (!strcmp(scheme, "ipps") || port == 443)
- encryption = HTTP_ENCRYPTION_ALWAYS;
- else
- encryption = HTTP_ENCRYPTION_IF_REQUESTED;
-
- if ((http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to %s:%d: %s", printer->name, host, port, cupsGetErrorString());
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: Unable to connect to '%s': %s", printer->name, device_uri, cupsGetErrorString());
/* Force printer to timeout and be deleted */
cupsRWLockWrite(&printer->lock);
* Query the printer for its capabilities...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Connected to %s:%d, sending Get-Printer-Attributes request...", printer->name, host, port);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Connected to '%s', sending Get-Printer-Attributes request...", printer->name, device_uri);
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
ippSetVersion(request, 2, 0);
* try to get it separately
*/
- if (ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION) ==
- NULL)
+ if (ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION) == NULL)
{
- ipp_t *response2;
+ ipp_t *response2; /* Second response */
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Polling \"media-col-database\" attribute separately.");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s: Querying \"media-col-database\" attribute separately.", printer->name);
request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
ippSetVersion(request, 2, 0);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
- "printer-uri", NULL, device_uri);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "media-col-database");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, device_uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "media-col-database");
response2 = cupsDoRequest(http, request, resource);
//ipp_status = cupsGetError();
if (response2)
{
- if ((attr = ippFindAttribute(response2, "media-col-database",
- IPP_TAG_ZERO)) != NULL)
+ if ((attr = ippFindAttribute(response2, "media-col-database", IPP_TAG_BEGIN_COLLECTION)) != NULL)
{
- cupsdLogMessage(CUPSD_LOG_WARN, "The printer %s does not support requests"
- " with attribute set \"all,media-col-database\", which breaks IPP"
- " conformance (RFC 8011, 4.2.5.1 \"requested-attributes\")"
- " - report the issue to your printer manufacturer", printer->name);
/*
* Copy "media-col-database" attribute into the original
* IPP response
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "\"media-col-database\" attribute found.");
+ cupsdLogMessage(CUPSD_LOG_WARN, "%s: The printer does not support requests with attribute set \"all,media-col-database\", which breaks IPP conformance (RFC 8011, 4.2.5.1 \"requested-attributes\") - report the issue to your printer manufacturer", printer->name);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "\"media-col-database\" attribute found.");
ippCopyAttribute(response, attr, 0);
}
ippDelete(response2);
}
}
- if (ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION) == NULL
- && ippFindAttribute(response, "media-supported", IPP_TAG_ZERO) == NULL
- && ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION) == NULL)
+ if (ippFindAttribute(response, "media-col-database", IPP_TAG_BEGIN_COLLECTION) == NULL && ippFindAttribute(response, "media-supported", IPP_TAG_ZERO) == NULL && ippFindAttribute(response, "media-size-supported", IPP_TAG_BEGIN_COLLECTION) == NULL)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "The printer %s doesn't provide attributes \"media-col-database\", \"media-size-supported\" or \"media-supported\" required for generating printer capabilities.", printer->name);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "%s: The printer doesn't provide attributes \"media-col-database\", \"media-size-supported\", or \"media-supported\" required for generating the PPD file.", printer->name);
/* Force printer to timeout and be deleted */
cupsRWLockWrite(&printer->lock);
printer->state_time = 0;
cupsRWUnlock(&printer->lock);
- send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("The printer %s does not provide attributes required for IPP Everywhere."), printer->name);
+ send_ipp_status(con, IPP_STATUS_ERROR_DEVICE, _("The printer does not provide attributes required for IPP Everywhere."));
goto finish_response;
}