/** * epc_tls_certificate_new: * @hostname: the name of the host that will use this certificate * @validity: the number of days the certificate will remain valid * @key: the private key for signing the certificate * @error: return location for a #GError, or %NULL * * Creates a self signed X.509 certificate. The certificate will mention * @hostname as common name and as DNS host name, and it will be valid * for @validity days. * * If the call was successful, the newly created certificate is returned. This * certificate can be used with functions of the <citetitle>GNU TLS</citetitle> * library. If the call was not successful, it returns %NULL and sets @error. * The error domain is #EPC_TLS_ERROR. Error codes are taken from the * <citetitle>GNU TLS</citetitle> library. * * Returns: The newly created certificate object, or %NULL. */ gnutls_x509_crt_t epc_tls_certificate_new (const gchar *hostname, guint validity, gnutls_x509_privkey_t key, GError **error) { gint rc = GNUTLS_E_SUCCESS; gnutls_x509_crt_t crt = NULL; time_t now = time (NULL); uuid_t serial; g_return_val_if_fail (NULL != key, NULL); g_return_val_if_fail (NULL != hostname, NULL); if (EPC_DEBUG_LEVEL (1)) g_debug ("%s: Generating self signed server certificate for `%s'", G_STRLOC, hostname); uuid_generate_time (serial); epc_tls_check (rc = gnutls_x509_crt_init (&crt)); epc_tls_check (rc = gnutls_x509_crt_set_version (crt, 1)); epc_tls_check (rc = gnutls_x509_crt_set_key (crt, key)); epc_tls_check (rc = gnutls_x509_crt_set_serial (crt, serial, sizeof serial)); epc_tls_check (rc = gnutls_x509_crt_set_activation_time (crt, now)); epc_tls_check (rc = gnutls_x509_crt_set_expiration_time (crt, now + validity)); epc_tls_check (rc = gnutls_x509_crt_set_subject_alternative_name (crt, GNUTLS_SAN_DNSNAME, hostname)); epc_tls_check (rc = gnutls_x509_crt_set_dn_by_oid (crt, GNUTLS_OID_X520_COMMON_NAME, 0, hostname, strlen (hostname))); epc_tls_check (rc = gnutls_x509_crt_sign (crt, crt, key)); out: if (GNUTLS_E_SUCCESS != rc) { g_set_error (error, EPC_TLS_ERROR, rc, _("Cannot create self signed server key for '%s': %s"), hostname, gnutls_strerror (rc)); if (crt) gnutls_x509_crt_deinit (crt); crt = NULL; } return crt; }
static int /* O - 1 on success, 0 on failure */ make_certificate(cupsd_client_t *con) /* I - Client connection */ { gnutls_x509_crt crt; /* Self-signed certificate */ gnutls_x509_privkey key; /* Encryption key */ 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 */ /* * Create the encryption key... */ cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key..."); gnutls_x509_privkey_init(&key); gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s", gnutls_strerror(result)); gnutls_x509_privkey_deinit(key); return (0); } else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", ServerKey); } else { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key file \"%s\" - %s", ServerKey, strerror(errno)); gnutls_x509_privkey_deinit(key); return (0); } /* * Create the self-signed certificate... */ cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate..."); language = cupsLangDefault(); curtime = time(NULL); serial[0] = curtime >> 24; serial[1] = curtime >> 16; serial[2] = curtime >> 8; serial[3] = curtime; gnutls_x509_crt_init(&crt); if (strlen(language->language) == 5) gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, language->language + 3, 2); else gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, "US", 2); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, ServerName, strlen(ServerName)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, ServerName, strlen(ServerName)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, ServerAdmin, strlen(ServerAdmin)); gnutls_x509_crt_set_key(crt, key); gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); gnutls_x509_crt_set_activation_time(crt, curtime); gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); gnutls_x509_crt_set_ca_status(crt, 0); gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, ServerName); gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); gnutls_x509_crt_set_version(crt, 3); bytes = sizeof(buffer); if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); gnutls_x509_crt_sign(crt, crt, key); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server certificate - %s", gnutls_strerror(result)); else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL) { cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\"...", ServerCertificate); } else cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server certificate file \"%s\" - %s", ServerCertificate, strerror(errno)); /* * Cleanup... */ gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (1); }
int /* O - 1 on success, 0 on failure */ cupsMakeServerCredentials( const char *path, /* I - Path to keychain/directory */ const char *common_name, /* I - Common name */ int num_alt_names, /* I - Number of subject alternate names */ const char **alt_names, /* I - Subject Alternate Names */ time_t expiration_date) /* I - Expiration date */ { gnutls_x509_crt_t crt; /* Self-signed certificate */ gnutls_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 */ 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... */ if (!path) path = http_gnutls_default_path(temp, sizeof(temp)); if (!path || !common_name) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); return (0); } http_gnutls_make_path(crtfile, sizeof(crtfile), path, common_name, "crt"); http_gnutls_make_path(keyfile, sizeof(keyfile), path, common_name, "key"); /* * Create the encryption key... */ DEBUG_puts("1cupsMakeServerCredentials: Creating key pair."); gnutls_x509_privkey_init(&key); gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); DEBUG_puts("1cupsMakeServerCredentials: Key pair created."); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { DEBUG_printf(("1cupsMakeServerCredentials: Unable to export private key: %s", gnutls_strerror(result))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(result), 0); gnutls_x509_privkey_deinit(key); 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 { DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file \"%s\": %s", keyfile, strerror(errno))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); gnutls_x509_privkey_deinit(key); return (0); } /* * Create the self-signed 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; gnutls_x509_crt_init(&crt); if (strlen(language->language) == 5) gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, language->language + 3, 2); else gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, "US", 2); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, common_name, strlen(common_name)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, common_name, strlen(common_name)); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, "Unknown", 7); gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, "Unknown", 7); /* gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, ServerAdmin, strlen(ServerAdmin));*/ gnutls_x509_crt_set_key(crt, key); gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); gnutls_x509_crt_set_activation_time(crt, curtime); gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); gnutls_x509_crt_set_ca_status(crt, 0); if (num_alt_names > 0) gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, alt_names[0]); gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); gnutls_x509_crt_set_version(crt, 3); bytes = sizeof(buffer); if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); gnutls_x509_crt_sign(crt, crt, key); /* * Save it... */ bytes = sizeof(buffer); if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, buffer, &bytes)) < 0) { DEBUG_printf(("1cupsMakeServerCredentials: Unable to export public key and X.509 certificate: %s", gnutls_strerror(result))); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, gnutls_strerror(result), 0); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (0); } else if ((fp = cupsFileOpen(crtfile, "w")) != NULL) { DEBUG_printf(("1cupsMakeServerCredentials: Writing public key and X.509 certificate to \"%s\".", crtfile)); cupsFileWrite(fp, (char *)buffer, bytes); cupsFileClose(fp); } else { 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); gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); return (0); } /* * Cleanup... */ gnutls_x509_crt_deinit(crt); gnutls_x509_privkey_deinit(key); DEBUG_puts("1cupsMakeServerCredentials: Successfully created credentials."); return (1); }