From patchwork Wed Apr 26 12:32:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Adolf Belka X-Patchwork-Id: 6815 Return-Path: Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384 client-signature ECDSA (P-384) client-digest SHA384) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4Q5ytz0S55z3x1n for ; Wed, 26 Apr 2023 12:32:43 +0000 (UTC) Received: from mail02.haj.ipfire.org (mail02.haj.ipfire.org [172.28.1.201]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) client-signature ECDSA (P-384)) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4Q5ytv5kQ6z2vs; Wed, 26 Apr 2023 12:32:39 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4Q5ytv4HkFz2y4g; Wed, 26 Apr 2023 12:32:39 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384 client-signature ECDSA (P-384) client-digest SHA384) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4Q5ytt48szz2xGX for ; Wed, 26 Apr 2023 12:32:38 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by mail01.ipfire.org (Postfix) with ESMTPSA id 4Q5yts0GC6zkj; Wed, 26 Apr 2023 12:32:36 +0000 (UTC) DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003ed25519; t=1682512357; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=354m3eTOLfztiYBTSAZUB2BU3WsFxo/Zs1MhThbbSXQ=; b=rXazh5Y1VEo60T/x5n0+MHpsZKEkMQSn0zF9vgCPpPaRuKmv8MXN2CVXYsEC4XeZrrXvZU iMvreumQGINXCGCA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003rsa; t=1682512357; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=354m3eTOLfztiYBTSAZUB2BU3WsFxo/Zs1MhThbbSXQ=; b=kOlBniiOKGNT0yS8PzfMWOHum5gAtBy9X+vIqk7YGDoEauG/6i6aQoQOa9z5ToZ+iCxSvF 26rcd/a8XCmWw8zJGYFzpM/Cv5q1Jc2pqB+MuQeVuXAfi6OgHMNw59p3ht8UiTSW7hWz+b 3mv/4EbBt+tqxGxH/EDjF/2UVdS7K4V6bbh1j/Cvf58/hyAEE540oRwxXiEfRC7JHOt+wX obR8BFjnsyHr4jiggGZ3gBD/S2j/OcLE3zHmUrjifoOfIXLPX+yaapGKQBD8vYyBHmM7KW DwmFRpA5d8L7uaGAJj+Tq92ZvlWKn21zO2P7x+c/fVYZF3DiOdB0nw6oww0YbQ== From: Adolf Belka To: development@lists.ipfire.org Subject: [PATCH] cups: Fixes Bug#12924 - Can't access https pages in cups Date: Wed, 26 Apr 2023 14:32:28 +0200 Message-Id: <20230426123229.4385-1-adolf.belka@ipfire.org> MIME-Version: 1.0 X-BeenThere: development@lists.ipfire.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: IPFire development talk List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: development-bounces@lists.ipfire.org Sender: "Development" - Version 2.4.2 had some bugs that caused the self signed certificates to not be read or created properly. The two involved bug fix patches are applied in this submission. - Corrected the configure options related to avahi and TLS. Using Openssl for the TLS. - Built .ipfire package installed into vm testbed and tested. With existing 2.4.2 any https pages come up with an error for the secure connection. With this version the https admin page opens up and config file was able to be successfully modified via it. Fixes: Bug#12924 Tested-by: Adolf Belka Signed-off-by: Adolf Belka --- lfs/cups | 8 +- ...ificate_generation_bugs_with_openssl.patch | 337 ++++++++++++++++++ ..._default_cupsd_keychain_with_OpenSSL.patch | 16 + 3 files changed, 358 insertions(+), 3 deletions(-) create mode 100644 src/patches/cups-2.4.2_Fix_TLS_certificate_generation_bugs_with_openssl.patch create mode 100644 src/patches/cups-2.4.2_Fix_default_cupsd_keychain_with_OpenSSL.patch diff --git a/lfs/cups b/lfs/cups index 6485f8df4..f1b8df1c7 100644 --- a/lfs/cups +++ b/lfs/cups @@ -33,7 +33,7 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/cups-$(VER) TARGET = $(DIR_INFO)/$(THISAPP) PROG = cups -PAK_VER = 33 +PAK_VER = 34 DEPS = avahi cups-filters dbus ghostscript @@ -80,6 +80,8 @@ $(subst %,%_BLAKE2,$(objects)) : $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/cups-2.4.2_Fix_default_cupsd_keychain_with_OpenSSL.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/cups-2.4.2_Fix_TLS_certificate_generation_bugs_with_openssl.patch $(UPDATE_AUTOMAKE) cd $(DIR_APP) && \ ./configure \ @@ -87,9 +89,9 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) --sysconfdir=/var/ipfire \ --localstatedir=/var \ --enable-debug \ - --enable-avahi \ + --with-dnssd=avahi \ --enable-dbus \ - --enable-gnutls \ + --with-tls=openssl \ --enable-libusb cd $(DIR_APP) && make $(MAKETUNING) diff --git a/src/patches/cups-2.4.2_Fix_TLS_certificate_generation_bugs_with_openssl.patch b/src/patches/cups-2.4.2_Fix_TLS_certificate_generation_bugs_with_openssl.patch new file mode 100644 index 000000000..a356474d2 --- /dev/null +++ b/src/patches/cups-2.4.2_Fix_TLS_certificate_generation_bugs_with_openssl.patch @@ -0,0 +1,337 @@ +--- cups-2.4.2/cups/tls-openssl.c.orig 2022-05-26 08:17:21.000000000 +0200 ++++ cups-2.4.2/cups/tls-openssl.c 2023-04-24 20:13:16.431108315 +0200 +@@ -1,7 +1,7 @@ + /* + * TLS support code for CUPS using OpenSSL/LibreSSL. + * +- * Copyright © 2020-2022 by OpenPrinting ++ * Copyright © 2020-2023 by OpenPrinting + * Copyright © 2007-2019 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. + * +@@ -35,7 +35,8 @@ + static time_t http_get_date(X509 *cert, int which); + //static void http_load_crl(void); + static const char *http_make_path(char *buffer, size_t bufsize, const char *dirname, const char *filename, const char *ext); +-static void http_x509_add_san(X509 *cert, const char *name); ++static int http_x509_add_ext(X509 *cert, int nid, const char *value); ++static void http_x509_add_san(GENERAL_NAMES *gens, const char *name); + + + /* +@@ -79,11 +80,15 @@ + cups_lang_t *language; // Default language info + time_t curtime; // Current time + X509_NAME *name; // Subject/issuer name ++ ASN1_INTEGER *serial; // Serial number ++ ASN1_TIME *notBefore, // Initial date ++ *notAfter; // Expiration date + BIO *bio; // Output file + char temp[1024], // Temporary directory name + crtfile[1024], // Certificate filename + keyfile[1024]; // Private key filename + const char *common_ptr; // Pointer into common name ++ GENERAL_NAMES *gens; // Names for SubjectAltName certificate extension + + + DEBUG_printf(("cupsMakeServerCredentials(path=\"%s\", common_name=\"%s\", num_alt_names=%d, alt_names=%p, expiration_date=%d)", path, common_name, num_alt_names, alt_names, (int)expiration_date)); +@@ -104,7 +109,7 @@ + // Create the encryption key... + DEBUG_puts("1cupsMakeServerCredentials: Creating key pair."); + +- if ((rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL)) == NULL) ++ if ((rsa = RSA_generate_key(3072, RSA_F4, NULL, NULL)) == NULL) + { + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create key pair."), 1); + return (0); +@@ -131,25 +136,43 @@ + return (0); + } + +- curtime = time(NULL); +- language = cupsLangDefault(); ++ curtime = time(NULL); ++ ++ notBefore = ASN1_TIME_new(); ++ ASN1_TIME_set(notBefore, curtime); ++ X509_set_notBefore(cert, notBefore); ++ ASN1_TIME_free(notBefore); ++ ++ notAfter = ASN1_TIME_new(); ++ ASN1_TIME_set(notAfter, expiration_date); ++ X509_set_notAfter(cert, notAfter); ++ ASN1_TIME_free(notAfter); ++ ++ serial = ASN1_INTEGER_new(); ++ ASN1_INTEGER_set(serial, (int)curtime); ++ X509_set_serialNumber(cert, serial); ++ ASN1_INTEGER_free(serial); + +- ASN1_TIME_set(X509_get_notBefore(cert), curtime); +- ASN1_TIME_set(X509_get_notAfter(cert), expiration_date); +- ASN1_INTEGER_set(X509_get_serialNumber(cert), (int)curtime); + X509_set_pubkey(cert, pkey); + +- name = X509_get_subject_name(cert); ++ language = cupsLangDefault(); ++ name = X509_NAME_new(); + if (strlen(language->language) == 5) +- X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)language->language + 3, -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)language->language + 3, -1, -1, 0); + else +- X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); +- X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); +- X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_commonName, MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_organizationName, MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_organizationalUnitName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_stateOrProvinceName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); ++ X509_NAME_add_entry_by_txt(name, SN_localityName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); + + X509_set_issuer_name(cert, name); ++ X509_set_subject_name(cert, name); ++ X509_NAME_free(name); + +- http_x509_add_san(cert, common_name); ++ gens = sk_GENERAL_NAME_new_null(); ++ http_x509_add_san(gens, common_name); + if ((common_ptr = strstr(common_name, ".local")) == NULL) + { + // Add common_name.local to the list, too... +@@ -161,7 +184,7 @@ + *localptr = '\0'; + strlcat(localname, ".local", sizeof(localname)); + +- http_x509_add_san(cert, localname); ++ http_x509_add_san(gens, localname); + } + + if (num_alt_names > 0) +@@ -171,10 +194,22 @@ + for (i = 0; i < num_alt_names; i ++) + { + if (strcmp(alt_names[i], "localhost")) +- http_x509_add_san(cert, alt_names[i]); ++ http_x509_add_san(gens, alt_names[i]); + } + } + ++ // Add extension with DNS names and free buffer for GENERAL_NAME ++ X509_add1_ext_i2d(cert, NID_subject_alt_name, gens, 0, X509V3_ADD_DEFAULT); ++ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); ++ ++ // Add extensions that are required to make Chrome happy... ++ http_x509_add_ext(cert, NID_basic_constraints, "critical,CA:FALSE,pathlen:0"); ++ http_x509_add_ext(cert, NID_key_usage, "critical,digitalSignature,keyEncipherment"); ++ http_x509_add_ext(cert, NID_ext_key_usage, "1.3.6.1.5.5.7.3.1"); ++ http_x509_add_ext(cert, NID_subject_key_identifier, "hash"); ++ http_x509_add_ext(cert, NID_authority_key_identifier, "keyid,issuer"); ++ X509_set_version(cert, 2); // v3 ++ + X509_sign(cert, pkey, EVP_sha256()); + + // Save them... +@@ -959,6 +994,7 @@ + const char *cn, // Common name to lookup + *cnptr; // Pointer into common name + int have_creds = 0; // Have credentials? ++ int key_status, crt_status; // Key and certificate load status + + context = SSL_CTX_new(TLS_server_method()); + +@@ -1002,6 +1038,8 @@ + else + cn = tls_common_name; + ++ _cupsMutexLock(&tls_mutex); ++ + if (cn) + { + // First look in the CUPS keystore... +@@ -1042,20 +1080,41 @@ + { + DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", cn)); + +- if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 365 * 86400)) ++ if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 3650 * 86400)) + { + DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed."); + http->error = errno = EINVAL; + http->status = HTTP_STATUS_ERROR; + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1); +- SSL_CTX_free(context); ++ SSL_CTX_free(context); ++ _cupsMutexUnlock(&tls_mutex); + + return (-1); + } + } + +- SSL_CTX_use_PrivateKey_file(context, keyfile, SSL_FILETYPE_PEM); +- SSL_CTX_use_certificate_file(context, crtfile, SSL_FILETYPE_PEM); ++ _cupsMutexUnlock(&tls_mutex); ++ ++ DEBUG_printf(("4_httpTLSStart: Using private key file '%s'.", keyfile)); ++ DEBUG_printf(("4_httpTLSStart: Using certificate file '%s'.", crtfile)); ++ ++ crt_status = SSL_CTX_use_certificate_chain_file(context, crtfile); ++ key_status = SSL_CTX_use_PrivateKey_file(context, keyfile, SSL_FILETYPE_PEM); ++ ++ if (!key_status || !crt_status) ++ { ++ // Unable to load private key or certificate... ++ DEBUG_puts("4_httpTLSStart: Unable to use private key or certificate chain file."); ++ if ((error = ERR_get_error()) != 0) ++ _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, ERR_error_string(error, NULL), 0); ++ ++ http->status = HTTP_STATUS_ERROR; ++ http->error = EIO; ++ ++ SSL_CTX_free(context); ++ ++ return (-1); ++ } + } + + // Set TLS options... +@@ -1068,6 +1127,8 @@ + strlcat(cipherlist, ":!SHA1:!SHA256:!SHA384", sizeof(cipherlist)); + strlcat(cipherlist, ":@STRENGTH", sizeof(cipherlist)); + ++ DEBUG_printf(("4_httpTLSStart: cipherlist='%s', tls_min_version=%d, tls_max_version=%d", cipherlist, tls_min_version, tls_max_version)); ++ + SSL_CTX_set_min_proto_version(context, versions[tls_min_version]); + SSL_CTX_set_max_proto_version(context, versions[tls_max_version]); + SSL_CTX_set_cipher_list(context, cipherlist); +@@ -1094,7 +1155,8 @@ + + if (http->mode == _HTTP_MODE_CLIENT) + { +- // Negotiate as a server... ++ // Negotiate as a client... ++ DEBUG_puts("4_httpTLSStart: Calling SSL_connect..."); + if (SSL_connect(http->tls) < 1) + { + // Failed +@@ -1109,12 +1171,15 @@ + SSL_free(http->tls); + http->tls = NULL; + ++ DEBUG_printf(("4_httpTLSStart: Returning -1 (%s)", ERR_error_string(error, NULL))); ++ + return (-1); + } + } + else + { + // Negotiate as a server... ++ DEBUG_puts("4_httpTLSStart: Calling SSL_accept..."); + if (SSL_accept(http->tls) < 1) + { + // Failed +@@ -1129,10 +1194,14 @@ + SSL_free(http->tls); + http->tls = NULL; + ++ DEBUG_printf(("4_httpTLSStart: Returning -1 (%s)", ERR_error_string(error, NULL))); ++ + return (-1); + } + } + ++ DEBUG_puts("4_httpTLSStart: Returning 0."); ++ + return (0); + } + +@@ -1152,6 +1221,8 @@ + SSL_shutdown(http->tls); + SSL_CTX_free(context); + SSL_free(http->tls); ++ ++ http->tls = NULL; + } + + +@@ -1564,32 +1635,62 @@ + + + // +-// 'http_x509_add_san()' - Add a subjectAltName extension to an X.509 certificate. ++// 'http_x509_add_ext()' - Add an extension to a certificate. + // + +-static void +-http_x509_add_san(X509 *cert, // I - Certificate +- const char *name) // I - Hostname ++static int // O - 1 on success, 0 on failure ++http_x509_add_ext(X509 *cert, // I - Certificate ++ int nid, // I - Extension ID ++ const char *value) // I - Value + { +- char dns_name[1024]; // DNS: prefixed hostname +- X509_EXTENSION *san_ext; // Extension for subjectAltName +- ASN1_OCTET_STRING *san_asn1; // ASN1 string ++ int ret; // Return value ++ X509_EXTENSION *ex = NULL; // Extension ++ X509V3_CTX ctx; // Certificate context + + +- // The subjectAltName value for DNS names starts with a DNS: prefix... +- snprintf(dns_name, sizeof(dns_name), "DNS: %s", name); ++ DEBUG_printf(("3http_x509_add_ext(cert=%p, nid=%d, value=\"%s\")", (void *)cert, nid, value)); + +- if ((san_asn1 = ASN1_OCTET_STRING_new()) == NULL) +- return; ++ // Don't use a configuration database... ++ X509V3_set_ctx_nodb(&ctx); + +- ASN1_OCTET_STRING_set(san_asn1, (unsigned char *)dns_name, strlen(dns_name)); +- if ((san_ext = X509_EXTENSION_create_by_NID(NULL, NID_subject_alt_name, 0, san_asn1)) == NULL) ++ // Self-signed certificates use the same issuer and subject... ++ X509V3_set_ctx(&ctx, /*issuer*/cert, /*subject*/cert, /*req*/NULL, /*crl*/NULL, /*flags*/0); ++ ++ // Create and add the extension... ++ if ((ex = X509V3_EXT_conf_nid(/*conf*/NULL, &ctx, nid, value)) == NULL) + { +- ASN1_OCTET_STRING_free(san_asn1); +- return; ++ DEBUG_puts("4http_x509_add_ext: Unable to create extension, returning false."); ++ return (0); + } + +- X509_add_ext(cert, san_ext, -1); +- X509_EXTENSION_free(san_ext); +- ASN1_OCTET_STRING_free(san_asn1); ++ ret = X509_add_ext(cert, ex, -1) != 0; ++ ++ DEBUG_printf(("4http_x509_add_ext: X509_add_ext returned %s.", ret ? "true" : "false")); ++ ++ // Free the extension and return... ++ X509_EXTENSION_free(ex); ++ ++ return (ret); ++} ++ ++ ++// ++// 'http_x509_add_san()' - Add a subjectAltName to GENERAL_NAMES used for ++// the extension to an X.509 certificate. ++// ++ ++static void ++http_x509_add_san(GENERAL_NAMES *gens, // I - Concatenation of DNS names ++ const char *name) // I - Hostname ++{ ++ GENERAL_NAME *gen_dns = GENERAL_NAME_new(); ++ // DNS: name ++ ASN1_IA5STRING *ia5 = ASN1_IA5STRING_new(); ++ // Hostname string ++ ++ ++ // Set the strings and push it on the GENERAL_NAMES list... ++ ASN1_STRING_set(ia5, name, strlen(name)); ++ GENERAL_NAME_set0_value(gen_dns, GEN_DNS, ia5); ++ sk_GENERAL_NAME_push(gens, gen_dns); + } diff --git a/src/patches/cups-2.4.2_Fix_default_cupsd_keychain_with_OpenSSL.patch b/src/patches/cups-2.4.2_Fix_default_cupsd_keychain_with_OpenSSL.patch new file mode 100644 index 000000000..ebd3a4843 --- /dev/null +++ b/src/patches/cups-2.4.2_Fix_default_cupsd_keychain_with_OpenSSL.patch @@ -0,0 +1,16 @@ +--- cups-2.4.2/scheduler/conf.c.orig 2022-05-26 08:17:21.000000000 +0200 ++++ cups-2.4.2/scheduler/conf.c 2023-04-23 15:37:48.521145700 +0200 +@@ -605,11 +605,11 @@ + ClassifyOverride = 0; + + #ifdef HAVE_TLS +-# ifdef HAVE_GNUTLS ++# if defined HAVE_GNUTLS || defined HAVE_OPENSSL + cupsdSetString(&ServerKeychain, "ssl"); + # else + cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain"); +-# endif /* HAVE_GNUTLS */ ++# endif /* HAVE_GNUTLS || HAVE_OPENSSL */ + + _httpTLSSetOptions(_HTTP_TLS_NONE, _HTTP_TLS_1_0, _HTTP_TLS_MAX); + #endif /* HAVE_TLS */