Skip to content

Commit 0eedd19

Browse files
committed
Update httpConnectURI to do X.509 pinning.
1 parent ec4f59e commit 0eedd19

4 files changed

Lines changed: 36 additions & 26 deletions

File tree

cups/http.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ httpConnectURI(const char *uri, // I - Service to connect to
485485
lresource[256]; // URI resource (local copy)
486486
int lport; // URI port (local copy)
487487
http_encryption_t encryption; // Type of encryption to use
488+
http_uri_status_t uri_status; // URI separation status
488489

489490

490491
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");
@@ -520,8 +521,11 @@ httpConnectURI(const char *uri, // I - Service to connect to
520521
}
521522

522523
// Get the URI components...
523-
if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, hsize, port, resource, rsize) < HTTP_URI_STATUS_OK)
524+
if ((uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, hsize, port, resource, rsize)) < HTTP_URI_STATUS_OK)
525+
{
526+
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, httpURIStatusString(uri_status), 0);
524527
return (NULL);
528+
}
525529

526530
DEBUG_printf("1httpConnectURI: scheme=\"%s\", host=\"%s\", port=%d, resource=\"%s\"", scheme, host, *port, resource);
527531

@@ -532,7 +536,7 @@ httpConnectURI(const char *uri, // I - Service to connect to
532536

533537
http = httpConnect(host, *port, /*addrlist*/NULL, AF_UNSPEC, encryption, blocking, msec, cancel);
534538

535-
if (httpIsEncrypted(http) && require_ca)
539+
if (httpIsEncrypted(http))
536540
{
537541
// Validate trust with service...
538542
char *creds; // Peer credentials...
@@ -541,13 +545,19 @@ httpConnectURI(const char *uri, // I - Service to connect to
541545
creds = httpCopyPeerCredentials(http);
542546
trust = cupsGetCredentialsTrust(/*path*/NULL, host, creds, require_ca);
543547

544-
free(creds);
545-
546-
if (trust != HTTP_TRUST_OK)
548+
if (trust == HTTP_TRUST_OK)
547549
{
550+
// Pin the trusted credentials (for TOFU)...
551+
cupsSaveCredentials(/*path*/NULL, host, creds, /*key*/NULL);
552+
}
553+
else if (trust != HTTP_TRUST_RENEWED)
554+
{
555+
// Don't allow the connection...
548556
httpClose(http);
549557
http = NULL;
550558
}
559+
560+
free(creds);
551561
}
552562

553563
return (http);

cups/tls-gnutls.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ cupsGetCredentialsTrust(
818818
// Load the credentials...
819819
if (!gnutls_import_certs(credentials, &num_certs, certs))
820820
{
821-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to import credentials."), true);
821+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Unable to import credentials."), true);
822822
return (HTTP_TRUST_UNKNOWN);
823823
}
824824

@@ -844,21 +844,21 @@ cupsGetCredentialsTrust(
844844
if (!cg->trust_first || require_ca)
845845
{
846846
// Do not trust certificates on first use...
847-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), true);
847+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), true);
848848

849849
trust = HTTP_TRUST_INVALID;
850850
}
851851
else if (cupsGetCredentialsExpiration(credentials) <= cupsGetCredentialsExpiration(tcreds))
852852
{
853853
// The new credentials are not newly issued...
854-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are older than stored credentials."), true);
854+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are older than stored credentials."), true);
855855

856856
trust = HTTP_TRUST_INVALID;
857857
}
858858
else if (!cupsAreCredentialsValidForName(common_name, credentials))
859859
{
860860
// The common name does not match the issued certificate...
861-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are not valid for name."), true);
861+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are not valid for name."), true);
862862

863863
trust = HTTP_TRUST_INVALID;
864864
}
@@ -875,7 +875,7 @@ cupsGetCredentialsTrust(
875875
}
876876
else if ((cg->validate_certs || require_ca) && !cupsAreCredentialsValidForName(common_name, credentials))
877877
{
878-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No stored credentials, not valid for name."), true);
878+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("No stored credentials, not valid for name."), true);
879879
trust = HTTP_TRUST_INVALID;
880880
}
881881
else if (num_certs > 1)
@@ -899,25 +899,25 @@ cupsGetCredentialsTrust(
899899
}
900900

901901
if (trust != HTTP_TRUST_OK)
902-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials do not validate against site CA certificate."), true);
902+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials do not validate against site CA certificate."), true);
903903

904904
free(tcreds);
905905
}
906906
}
907907
}
908908
else if (require_ca)
909909
{
910-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials are not CA-signed."), true);
910+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials are not CA-signed."), true);
911911
trust = HTTP_TRUST_INVALID;
912912
}
913913
else if (!cg->trust_first)
914914
{
915-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), true);
915+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), true);
916916
trust = HTTP_TRUST_INVALID;
917917
}
918918
else if (!cg->any_root || require_ca)
919919
{
920-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Self-signed credentials are blocked."), true);
920+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Self-signed credentials are blocked."), true);
921921
trust = HTTP_TRUST_INVALID;
922922
}
923923

@@ -928,7 +928,7 @@ cupsGetCredentialsTrust(
928928
time(&curtime);
929929
if (curtime < gnutls_x509_crt_get_activation_time(certs[0]) || curtime > gnutls_x509_crt_get_expiration_time(certs[0]))
930930
{
931-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials have expired."), true);
931+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), true);
932932
trust = HTTP_TRUST_EXPIRED;
933933
}
934934
}

cups/tls-openssl.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ cupsGetCredentialsTrust(
877877
// Load the credentials...
878878
if ((certs = openssl_load_x509(credentials)) == NULL)
879879
{
880-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to import credentials."), true);
880+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Unable to import credentials."), true);
881881
return (HTTP_TRUST_UNKNOWN);
882882
}
883883

@@ -905,21 +905,21 @@ cupsGetCredentialsTrust(
905905
if (!cg->trust_first || require_ca)
906906
{
907907
// Do not trust certificates on first use...
908-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), true);
908+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), true);
909909

910910
trust = HTTP_TRUST_INVALID;
911911
}
912912
else if (cupsGetCredentialsExpiration(credentials) <= cupsGetCredentialsExpiration(tcreds))
913913
{
914914
// The new credentials are not newly issued...
915-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are older than stored credentials."), true);
915+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are older than stored credentials."), true);
916916

917917
trust = HTTP_TRUST_INVALID;
918918
}
919919
else if (!cupsAreCredentialsValidForName(common_name, credentials))
920920
{
921921
// The common name does not match the issued certificate...
922-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are not valid for name."), true);
922+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("New credentials are not valid for name."), true);
923923

924924
trust = HTTP_TRUST_INVALID;
925925
}
@@ -936,7 +936,7 @@ cupsGetCredentialsTrust(
936936
}
937937
else if ((cg->validate_certs || require_ca) && !cupsAreCredentialsValidForName(common_name, credentials))
938938
{
939-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No stored credentials, not valid for name."), true);
939+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("No stored credentials, not valid for name."), true);
940940
trust = HTTP_TRUST_INVALID;
941941
}
942942
else if (sk_X509_num(certs) > 1)
@@ -960,25 +960,25 @@ cupsGetCredentialsTrust(
960960
}
961961

962962
if (trust != HTTP_TRUST_OK)
963-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials do not validate against site CA certificate."), true);
963+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials do not validate against site CA certificate."), true);
964964

965965
free(tcreds);
966966
}
967967
}
968968
}
969969
else if (require_ca)
970970
{
971-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials are not CA-signed."), true);
971+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials are not CA-signed."), true);
972972
trust = HTTP_TRUST_INVALID;
973973
}
974974
else if (!cg->trust_first)
975975
{
976-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), true);
976+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Trust on first use is disabled."), true);
977977
trust = HTTP_TRUST_INVALID;
978978
}
979979
else if (!cg->any_root || require_ca)
980980
{
981-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Self-signed credentials are blocked."), true);
981+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Self-signed credentials are blocked."), true);
982982
trust = HTTP_TRUST_INVALID;
983983
}
984984

@@ -989,7 +989,7 @@ cupsGetCredentialsTrust(
989989
time(&curtime);
990990
if (curtime < openssl_get_date(cert, 0) || curtime > openssl_get_date(cert, 1))
991991
{
992-
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials have expired."), true);
992+
_cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Credentials have expired."), true);
993993
trust = HTTP_TRUST_EXPIRED;
994994
}
995995
}

0 commit comments

Comments
 (0)