From: Michael R Sweet Date: Wed, 30 Mar 2022 21:38:52 +0000 (-0400) Subject: Implement cupsMakeServerCredentials. X-Git-Tag: v2.4.2~29^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54dee2aef61d04eae2161dec093b4b103b4d3c57;p=thirdparty%2Fcups.git Implement cupsMakeServerCredentials. --- diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c index 29cf40e8ea..9255aa87ae 100644 --- a/cups/tls-openssl.c +++ b/cups/tls-openssl.c @@ -82,27 +82,22 @@ cupsMakeServerCredentials( const char **alt_names, // I - Subject Alternate Names time_t expiration_date) // I - Expiration date { -#if 0 - openssl_x509_crt_t crt; /* Self-signed certificate */ - openssl_x509_privkey_t key; /* Encryption private key */ - char temp[1024], /* Temporary directory name */ - crtfile[1024], /* Certificate filename */ - keyfile[1024]; /* Private key filename */ - cups_lang_t *language; /* Default language info */ - cups_file_t *fp; /* Key/cert file */ - unsigned char buffer[8192]; /* Buffer for x509 data */ - size_t bytes; /* Number of bytes of data */ - unsigned char serial[4]; /* Serial number buffer */ - time_t curtime; /* Current time */ - int result; /* Result of GNU TLS calls */ + int result = 0; // Return value + EVP_PKEY *pkey; // Private key + RSA *rsa; // RSA key pair + X509 *cert; // Certificate + cups_lang_t *language; // Default language info + time_t curtime; // Current time + X509_NAME *name; // Subject/issuer name + FILE *fp; // Output file + char temp[1024], // Temporary directory name + crtfile[1024], // Certificate filename + keyfile[1024]; // Private key filename 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)); - /* - * Filenames... - */ - + // Filenames... if (!path) path = http_default_path(temp, sizeof(temp)); @@ -115,81 +110,55 @@ cupsMakeServerCredentials( http_make_path(crtfile, sizeof(crtfile), path, common_name, "crt"); http_make_path(keyfile, sizeof(keyfile), path, common_name, "key"); - /* - * Create the encryption key... - */ - + // Create the encryption key... DEBUG_puts("1cupsMakeServerCredentials: Creating key pair."); - openssl_x509_privkey_init(&key); - openssl_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); - - DEBUG_puts("1cupsMakeServerCredentials: Key pair created."); - - /* - * Save it... - */ - - bytes = sizeof(buffer); - - if ((result = openssl_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) + if ((rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL)) == NULL) { - DEBUG_printf(("1cupsMakeServerCredentials: Unable to export private key: %s", openssl_strerror(result))); - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, openssl_strerror(result), 0); - openssl_x509_privkey_deinit(key); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create key pair."), 1); return (0); } - else if ((fp = cupsFileOpen(keyfile, "w")) != NULL) - { - DEBUG_printf(("1cupsMakeServerCredentials: Writing private key to \"%s\".", keyfile)); - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); - } - else + + if ((pkey = EVP_PKEY_new()) == NULL) { - DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file \"%s\": %s", keyfile, strerror(errno))); - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); - openssl_x509_privkey_deinit(key); + RSA_free(rsa); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create private key."), 1); return (0); } - /* - * Create the self-signed certificate... - */ + EVP_PKEY_assign_RSA(pkey, rsa); + + DEBUG_puts("1cupsMakeServerCredentials: Key pair created."); + // Create the X.509 certificate... DEBUG_puts("1cupsMakeServerCredentials: Generating self-signed X.509 certificate."); - language = cupsLangDefault(); - curtime = time(NULL); - serial[0] = curtime >> 24; - serial[1] = curtime >> 16; - serial[2] = curtime >> 8; - serial[3] = curtime; + if ((cert = X509_new()) == NULL) + { + EVP_PKEY_free(pkey); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create X.509 certificate."), 1); + return (0); + } + + curtime = time(NULL); + language = cupsLangDefault(); - openssl_x509_crt_init(&crt); + 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); if (strlen(language->language) == 5) - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - language->language + 3, 2); + X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)language->language + 3, -1, -1, 0); else - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - "US", 2); - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, - common_name, strlen(common_name)); - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, - common_name, strlen(common_name)); - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, - 0, "Unknown", 7); - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, - "Unknown", 7); - openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, - "Unknown", 7); -/* openssl_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, - ServerAdmin, strlen(ServerAdmin));*/ - openssl_x509_crt_set_key(crt, key); - openssl_x509_crt_set_serial(crt, serial, sizeof(serial)); - openssl_x509_crt_set_activation_time(crt, curtime); - openssl_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); - openssl_x509_crt_set_ca_status(crt, 0); + 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_set_issuer_name(cert, name); + +#if 0 // TODO: Implement Subject Alternate Name openssl_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME, common_name, (unsigned)strlen(common_name), GNUTLS_FSAN_SET); if (!strchr(common_name, '.')) { @@ -215,57 +184,53 @@ cupsMakeServerCredentials( } } } - openssl_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); - openssl_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); - openssl_x509_crt_set_version(crt, 3); - - bytes = sizeof(buffer); - if (openssl_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) - openssl_x509_crt_set_subject_key_id(crt, buffer, bytes); - - openssl_x509_crt_sign(crt, crt, key); +#endif // 0 - /* - * Save it... - */ + X509_sign(cert, pkey, EVP_sha256()); - bytes = sizeof(buffer); - if ((result = openssl_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) + // Save them... + // TODO: Probably want to change this to use the BIO methods to avoid stdio limits... + if ((fp = fopen(keyfile, "wb")) == NULL) { - DEBUG_printf(("1cupsMakeServerCredentials: Unable to export public key and X.509 certificate: %s", openssl_strerror(result))); - _cupsSetError(IPP_STATUS_ERROR_INTERNAL, openssl_strerror(result), 0); - openssl_x509_crt_deinit(crt); - openssl_x509_privkey_deinit(key); - return (0); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); + goto done; } - else if ((fp = cupsFileOpen(crtfile, "w")) != NULL) + + if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) { - DEBUG_printf(("1cupsMakeServerCredentials: Writing public key and X.509 certificate to \"%s\".", crtfile)); - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write private key."), 1); + fclose(fp); + goto done; } - else + + fclose(fp); + + if ((fp = fopen(crtfile, "wb")) == NULL) { - DEBUG_printf(("1cupsMakeServerCredentials: Unable to create public key and X.509 certificate file \"%s\": %s", crtfile, strerror(errno))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); - openssl_x509_crt_deinit(crt); - openssl_x509_privkey_deinit(key); - return (0); + goto done; } - /* - * Cleanup... - */ + if (!PEM_write_X509(fp, cert)) + { + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write X.509 certificate."), 1); + fclose(fp); + goto done; + } + + fclose(fp); - openssl_x509_crt_deinit(crt); - openssl_x509_privkey_deinit(key); + result = 1; DEBUG_puts("1cupsMakeServerCredentials: Successfully created credentials."); - return (1); -#else - return (0); -#endif // 0 + // Cleanup... + done: + + X509_free(cert); + EVP_PKEY_free(pkey); + + return (result); }