1diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c 2new file mode 100644 3index 00000000..cc33e17d 4--- /dev/null 5+++ b/cups-2.4.0/cups/tls-openssl.c 6@@ -0,0 +1,1676 @@ 7+/* 8+ * TLS support code for CUPS using OpenSSL/LibreSSL. 9+ * 10+ * Copyright © 2020-2023 by OpenPrinting 11+ * Copyright © 2007-2019 by Apple Inc. 12+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved. 13+ * 14+ * Licensed under Apache License v2.0. See the file "LICENSE" for more 15+ * information. 16+ */ 17+ 18+/**** This file is included from tls.c ****/ 19+ 20+/* 21+ * Include necessary headers... 22+ */ 23+ 24+#include <sys/stat.h> 25+#include <openssl/x509v3.h> 26+#include <openssl/ssl.h> 27+#include "cups-private.h" 28+#include "debug-internal.h" 29+/* 30+ * Local functions... 31+ */ 32+static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); 33+static int http_bio_free(BIO *data); 34+static int http_bio_new(BIO *h); 35+static int http_bio_puts(BIO *h, const char *str); 36+static int http_bio_read(BIO *h, char *buf, int size); 37+static int http_bio_write(BIO *h, const char *buf, int num); 38+ 39+static X509 *http_create_credential(http_credential_t *credential); 40+static const char *http_default_path(char *buffer, size_t bufsize); 41+static time_t http_get_date(X509 *cert, int which); 42+//static void http_load_crl(void); 43+static const char *http_make_path(char *buffer, size_t bufsize, const char *dirname, const char *filename, const char *ext); 44+static int http_x509_add_ext(X509 *cert, int nid, const char *value); 45+static void http_x509_add_san(GENERAL_NAMES *gens, const char *name); 46+ 47+ 48+/* 49+ * Local globals... 50+ */ 51+ 52+static int tls_auto_create = 0; 53+ /* Auto-create self-signed certs? */ 54+static BIO_METHOD *tls_bio_method = NULL; 55+ /* OpenSSL BIO method */ 56+static char *tls_common_name = NULL; 57+ /* Default common name */ 58+//static X509_CRL *tls_crl = NULL;/* Certificate revocation list */ 59+static char *tls_keypath = NULL; 60+ /* Server cert keychain path */ 61+static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER; 62+ /* Mutex for keychain/certs */ 63+static int tls_options = -1,/* Options for TLS connections */ 64+ tls_min_version = _HTTP_TLS_1_0, 65+ tls_max_version = _HTTP_TLS_MAX; 66+ 67+static void setErrorToCups(ipp_status_t status, unsigned long error) 68+{ 69+ char buffer[128] = {0}; 70+ ERR_error_string_n(error, buffer, sizeof(buffer)); 71+ _cupsSetError(status, buffer, 0); 72+} 73+/* 74+ * 'cupsMakeServerCredentials()' - Make a self-signed certificate and private key pair. 75+ * 76+ * @since CUPS 2.0/OS 10.10@ 77+ */ 78+ 79+int // O - 1 on success, 0 on failure 80+cupsMakeServerCredentials( 81+ const char *path, // I - Path to keychain/directory 82+ const char *common_name, // I - Common name 83+ int num_alt_names, // I - Number of subject alternate names 84+ const char **alt_names, // I - Subject Alternate Names 85+ time_t expiration_date) // I - Expiration date 86+{ 87+ int result = 0; // Return value 88+ EVP_PKEY *pkey; // Private key 89+ RSA *rsa; // RSA key pair 90+ X509 *cert; // Certificate 91+ cups_lang_t *language; // Default language info 92+ time_t curtime; // Current time 93+ X509_NAME *name; // Subject/issuer name 94+ ASN1_INTEGER *serial; // Serial number 95+ ASN1_TIME *notBefore, // Initial date 96+ *notAfter; // Expiration date 97+ BIO *bio; // Output file 98+ char temp[1024], // Temporary directory name 99+ crtfile[1024], // Certificate filename 100+ keyfile[1024]; // Private key filename 101+ const char *common_ptr; // Pointer into common name 102+ GENERAL_NAMES *gens; // Names for SubjectAltName certificate extension 103+ 104+ 105+ 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)); 106+ 107+ // Filenames... 108+ if (!path) 109+ path = http_default_path(temp, sizeof(temp)); 110+ 111+ if (!path || !common_name) 112+ { 113+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 114+ return (0); 115+ } 116+ 117+ http_make_path(crtfile, sizeof(crtfile), path, common_name, "crt"); 118+ http_make_path(keyfile, sizeof(keyfile), path, common_name, "key"); 119+ 120+ // Create the encryption key... 121+ DEBUG_puts("1cupsMakeServerCredentials: Creating key pair."); 122+ 123+ if ((rsa = RSA_generate_key(3072, RSA_F4, NULL, NULL)) == NULL) 124+ { 125+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create key pair."), 1); 126+ return (0); 127+ } 128+ 129+ if ((pkey = EVP_PKEY_new()) == NULL) 130+ { 131+ RSA_free(rsa); 132+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create private key."), 1); 133+ return (0); 134+ } 135+ 136+ EVP_PKEY_assign_RSA(pkey, rsa); 137+ 138+ DEBUG_puts("1cupsMakeServerCredentials: Key pair created."); 139+ 140+ // Create the X.509 certificate... 141+ DEBUG_puts("1cupsMakeServerCredentials: Generating self-signed X.509 certificate."); 142+ 143+ if ((cert = X509_new()) == NULL) 144+ { 145+ EVP_PKEY_free(pkey); 146+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create X.509 certificate."), 1); 147+ return (0); 148+ } 149+ 150+ curtime = time(NULL); 151+ 152+ notBefore = ASN1_TIME_new(); 153+ ASN1_TIME_set(notBefore, curtime); 154+ X509_set_notBefore(cert, notBefore); 155+ ASN1_TIME_free(notBefore); 156+ 157+ notAfter = ASN1_TIME_new(); 158+ ASN1_TIME_set(notAfter, expiration_date); 159+ X509_set_notAfter(cert, notAfter); 160+ ASN1_TIME_free(notAfter); 161+ 162+ serial = ASN1_INTEGER_new(); 163+ ASN1_INTEGER_set(serial, (int)curtime); 164+ X509_set_serialNumber(cert, serial); 165+ ASN1_INTEGER_free(serial); 166+ 167+ X509_set_pubkey(cert, pkey); 168+ 169+ language = cupsLangDefault(); 170+ name = X509_NAME_new(); 171+ if (strlen(language->language) == 5) 172+ X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)language->language + 3, -1, -1, 0); 173+ else 174+ X509_NAME_add_entry_by_txt(name, SN_countryName, MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); 175+ X509_NAME_add_entry_by_txt(name, SN_commonName, MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); 176+ X509_NAME_add_entry_by_txt(name, SN_organizationName, MBSTRING_ASC, (unsigned char *)common_name, -1, -1, 0); 177+ X509_NAME_add_entry_by_txt(name, SN_organizationalUnitName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); 178+ X509_NAME_add_entry_by_txt(name, SN_stateOrProvinceName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); 179+ X509_NAME_add_entry_by_txt(name, SN_localityName, MBSTRING_ASC, (unsigned char *)"Unknown", -1, -1, 0); 180+ 181+ X509_set_issuer_name(cert, name); 182+ X509_set_subject_name(cert, name); 183+ X509_NAME_free(name); 184+ 185+ gens = sk_GENERAL_NAME_new_null(); 186+ http_x509_add_san(gens, common_name); 187+ if ((common_ptr = strstr(common_name, ".local")) == NULL) 188+ { 189+ // Add common_name.local to the list, too... 190+ char localname[256], // hostname.local 191+ *localptr; // Pointer into localname 192+ 193+ strlcpy(localname, common_name, sizeof(localname)); 194+ if ((localptr = strchr(localname, '.')) != NULL) 195+ *localptr = '\0'; 196+ strlcat(localname, ".local", sizeof(localname)); 197+ 198+ http_x509_add_san(gens, localname); 199+ } 200+ 201+ if (num_alt_names > 0) 202+ { 203+ int i; // Looping var... 204+ 205+ for (i = 0; i < num_alt_names; i ++) 206+ { 207+ if (strcmp(alt_names[i], "localhost")) 208+ http_x509_add_san(gens, alt_names[i]); 209+ } 210+ } 211+ 212+ // Add extension with DNS names and free buffer for GENERAL_NAME 213+ X509_add1_ext_i2d(cert, NID_subject_alt_name, gens, 0, X509V3_ADD_DEFAULT); 214+ sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 215+ 216+ // Add extensions that are required to make Chrome happy... 217+ http_x509_add_ext(cert, NID_basic_constraints, "critical,CA:FALSE,pathlen:0"); 218+ http_x509_add_ext(cert, NID_key_usage, "critical,digitalSignature,keyEncipherment"); 219+ http_x509_add_ext(cert, NID_ext_key_usage, "1.3.6.1.5.5.7.3.1"); 220+ http_x509_add_ext(cert, NID_subject_key_identifier, "hash"); 221+ http_x509_add_ext(cert, NID_authority_key_identifier, "keyid,issuer"); 222+ X509_set_version(cert, 2); // v3 223+ 224+ X509_sign(cert, pkey, EVP_sha256()); 225+ 226+ // Save them... 227+ if ((bio = BIO_new_file(keyfile, "wb")) == NULL) 228+ { 229+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 230+ goto done; 231+ } 232+ 233+ if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) 234+ { 235+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write private key."), 1); 236+ BIO_free(bio); 237+ goto done; 238+ } 239+ 240+ BIO_free(bio); 241+ 242+ if ((bio = BIO_new_file(crtfile, "wb")) == NULL) 243+ { 244+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); 245+ goto done; 246+ } 247+ 248+ if (!PEM_write_bio_X509(bio, cert)) 249+ { 250+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write X.509 certificate."), 1); 251+ BIO_free(bio); 252+ goto done; 253+ } 254+ 255+ BIO_free(bio); 256+ 257+ result = 1; 258+ DEBUG_puts("1cupsMakeServerCredentials: Successfully created credentials."); 259+ 260+ // Cleanup... 261+ done: 262+ 263+ X509_free(cert); 264+ EVP_PKEY_free(pkey); 265+ 266+ return (result); 267+} 268+ 269+ 270+/* 271+ * 'cupsSetServerCredentials()' - Set the default server credentials. 272+ * 273+ * Note: The server credentials are used by all threads in the running process. 274+ * This function is threadsafe. 275+ * 276+ * @since CUPS 2.0/OS 10.10@ 277+ */ 278+ 279+int // O - 1 on success, 0 on failure 280+cupsSetServerCredentials( 281+ const char *path, // I - Path to keychain/directory 282+ const char *common_name, // I - Default common name for server 283+ int auto_create) // I - 1 = automatically create self-signed certificates 284+{ 285+ char temp[1024]; // Default path buffer 286+ 287+ 288+ DEBUG_printf(("cupsSetServerCredentials(path=\"%s\", common_name=\"%s\", auto_create=%d)", path, common_name, auto_create)); 289+ 290+ /* 291+ * Use defaults as needed... 292+ */ 293+ 294+ if (!path) 295+ path = http_default_path(temp, sizeof(temp)); 296+ 297+ /* 298+ * Range check input... 299+ */ 300+ 301+ if (!path || !common_name) 302+ { 303+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); 304+ return (0); 305+ } 306+ 307+ _cupsMutexLock(&tls_mutex); 308+ 309+ /* 310+ * Free old values... 311+ */ 312+ 313+ if (tls_keypath) 314+ _cupsStrFree(tls_keypath); 315+ 316+ if (tls_common_name) 317+ _cupsStrFree(tls_common_name); 318+ 319+ /* 320+ * Save the new values... 321+ */ 322+ 323+ tls_keypath = _cupsStrAlloc(path); 324+ tls_auto_create = auto_create; 325+ tls_common_name = _cupsStrAlloc(common_name); 326+ 327+ _cupsMutexUnlock(&tls_mutex); 328+ 329+ return (1); 330+} 331+ 332+ 333+/* 334+ * 'httpCopyCredentials()' - Copy the credentials associated with the peer in 335+ * an encrypted connection. 336+ * 337+ * @since CUPS 1.5/macOS 10.7@ 338+ */ 339+ 340+int // O - Status of call (0 = success) 341+httpCopyCredentials( 342+ http_t *http, // I - Connection to server 343+ cups_array_t **credentials) // O - Array of credentials 344+{ 345+ STACK_OF(X509) *chain; // Certificate chain 346+ 347+ 348+ DEBUG_printf(("httpCopyCredentials(http=%p, credentials=%p)", http, credentials)); 349+ 350+ if (credentials) 351+ *credentials = NULL; 352+ 353+ if (!http || !http->tls || !credentials) 354+ return (-1); 355+ 356+ *credentials = cupsArrayNew(NULL, NULL); 357+ chain = SSL_get_peer_cert_chain(http->tls); 358+ 359+ DEBUG_printf(("1httpCopyCredentials: chain=%p", chain)); 360+ 361+ if (chain) 362+ { 363+ int i, // Looping var 364+ count; // Number of certs 365+ 366+ for (i = 0, count = sk_X509_num(chain); i < count; i ++) 367+ { 368+ X509 *cert = sk_X509_value(chain, i); 369+ // Current certificate 370+ BIO *bio = BIO_new(BIO_s_mem()); 371+ // Memory buffer for cert 372+ 373+ if (bio) 374+ { 375+ long bytes; // Number of bytes 376+ char *buffer; // Pointer to bytes 377+ 378+ if (PEM_write_bio_X509(bio, cert)) 379+ { 380+ bytes = BIO_get_mem_data(bio, &buffer); 381+ httpAddCredential(*credentials, buffer, (int)bytes); 382+ } 383+ 384+ BIO_free(bio); 385+ } 386+ } 387+ } 388+ 389+ return (0); 390+} 391+ 392+ 393+/* 394+ * '_httpCreateCredentials()' - Create credentials in the internal format. 395+ */ 396+ 397+http_tls_credentials_t // O - Internal credentials 398+_httpCreateCredentials( 399+ cups_array_t *credentials) // I - Array of credentials 400+{ 401+ (void)credentials; 402+ 403+ return (NULL); 404+} 405+ 406+ 407+/* 408+ * '_httpFreeCredentials()' - Free internal credentials. 409+ */ 410+ 411+void 412+_httpFreeCredentials( 413+ http_tls_credentials_t credentials) // I - Internal credentials 414+{ 415+ X509_free(credentials); 416+} 417+ 418+ 419+/* 420+ * 'httpCredentialsAreValidForName()' - Return whether the credentials are valid for the given name. 421+ * 422+ * @since CUPS 2.0/OS 10.10@ 423+ */ 424+ 425+int // O - 1 if valid, 0 otherwise 426+httpCredentialsAreValidForName( 427+ cups_array_t *credentials, // I - Credentials 428+ const char *common_name) // I - Name to check 429+{ 430+ X509 *cert; // Certificate 431+ int result = 0; // Result 432+ 433+ 434+ cert = http_create_credential((http_credential_t *)cupsArrayFirst(credentials)); 435+ if (cert) 436+ { 437+ result = X509_check_host(cert, common_name, strlen(common_name), 0, NULL); 438+ 439+ X509_free(cert); 440+ } 441+ 442+ return (result); 443+} 444+ 445+ 446+/* 447+ * 'httpCredentialsGetTrust()' - Return the trust of credentials. 448+ * 449+ * @since CUPS 2.0/OS 10.10@ 450+ */ 451+ 452+http_trust_t // O - Level of trust 453+httpCredentialsGetTrust( 454+ cups_array_t *credentials, // I - Credentials 455+ const char *common_name) // I - Common name for trust lookup 456+{ 457+ http_trust_t trust = HTTP_TRUST_OK; // Trusted? 458+ X509 *cert; // Certificate 459+ cups_array_t *tcreds = NULL; // Trusted credentials 460+ _cups_globals_t *cg = _cupsGlobals(); // Per-thread globals 461+ 462+ 463+ if (!common_name) 464+ { 465+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No common name specified."), 1); 466+ return (HTTP_TRUST_UNKNOWN); 467+ } 468+ 469+ if ((cert = http_create_credential((http_credential_t *)cupsArrayFirst(credentials))) == NULL) 470+ { 471+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create credentials from array."), 1); 472+ return (HTTP_TRUST_UNKNOWN); 473+ } 474+ 475+ if (cg->any_root < 0) 476+ { 477+ _cupsSetDefaults(); 478+// http_load_crl(); 479+ } 480+ 481+ // Look this common name up in the default keychains... 482+ httpLoadCredentials(NULL, &tcreds, common_name); 483+ 484+ if (tcreds) 485+ { 486+ char credentials_str[1024], /* String for incoming credentials */ 487+ tcreds_str[1024]; /* String for saved credentials */ 488+ 489+ httpCredentialsString(credentials, credentials_str, sizeof(credentials_str)); 490+ httpCredentialsString(tcreds, tcreds_str, sizeof(tcreds_str)); 491+ 492+ if (strcmp(credentials_str, tcreds_str)) 493+ { 494+ // Credentials don't match, let's look at the expiration date of the new 495+ // credentials and allow if the new ones have a later expiration... 496+ if (!cg->trust_first) 497+ { 498+ // Do not trust certificates on first use... 499+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1); 500+ 501+ trust = HTTP_TRUST_INVALID; 502+ } 503+ else if (httpCredentialsGetExpiration(credentials) <= httpCredentialsGetExpiration(tcreds)) 504+ { 505+ // The new credentials are not newly issued... 506+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are older than stored credentials."), 1); 507+ 508+ trust = HTTP_TRUST_INVALID; 509+ } 510+ else if (!httpCredentialsAreValidForName(credentials, common_name)) 511+ { 512+ // The common name does not match the issued certificate... 513+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("New credentials are not valid for name."), 1); 514+ 515+ trust = HTTP_TRUST_INVALID; 516+ } 517+ else if (httpCredentialsGetExpiration(tcreds) < time(NULL)) 518+ { 519+ // Save the renewed credentials... 520+ trust = HTTP_TRUST_RENEWED; 521+ 522+ httpSaveCredentials(NULL, credentials, common_name); 523+ } 524+ } 525+ 526+ httpFreeCredentials(tcreds); 527+ } 528+ else if (cg->validate_certs && !httpCredentialsAreValidForName(credentials, common_name)) 529+ { 530+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No stored credentials, not valid for name."), 1); 531+ trust = HTTP_TRUST_INVALID; 532+ } 533+ else if (!cg->trust_first) 534+ { 535+ // See if we have a site CA certificate we can compare... 536+ if (!httpLoadCredentials(NULL, &tcreds, "site")) 537+ { 538+ if (cupsArrayCount(credentials) != (cupsArrayCount(tcreds) + 1)) 539+ { 540+ // Certificate isn't directly generated from the CA cert... 541+ trust = HTTP_TRUST_INVALID; 542+ } 543+ else 544+ { 545+ // Do a tail comparison of the two certificates... 546+ http_credential_t *a, *b; // Certificates 547+ 548+ for (a = (http_credential_t *)cupsArrayFirst(tcreds), b = (http_credential_t *)cupsArrayIndex(credentials, 1); a && b; a = (http_credential_t *)cupsArrayNext(tcreds), b = (http_credential_t *)cupsArrayNext(credentials)) 549+ { 550+ if (a->datalen != b->datalen || memcmp(a->data, b->data, a->datalen)) 551+ break; 552+ } 553+ 554+ if (a || b) 555+ trust = HTTP_TRUST_INVALID; 556+ } 557+ 558+ if (trust != HTTP_TRUST_OK) 559+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials do not validate against site CA certificate."), 1); 560+ } 561+ else 562+ { 563+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Trust on first use is disabled."), 1); 564+ trust = HTTP_TRUST_INVALID; 565+ } 566+ } 567+ 568+ if (trust == HTTP_TRUST_OK && !cg->expired_certs) 569+ { 570+ time_t curtime; // Current date/time 571+ 572+ time(&curtime); 573+ if (curtime < http_get_date(cert, 0) || curtime > http_get_date(cert, 1)) 574+ { 575+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Credentials have expired."), 1); 576+ trust = HTTP_TRUST_EXPIRED; 577+ } 578+ } 579+ 580+ if (trust == HTTP_TRUST_OK && !cg->any_root && cupsArrayCount(credentials) == 1) 581+ { 582+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Self-signed credentials are blocked."), 1); 583+ trust = HTTP_TRUST_INVALID; 584+ } 585+ 586+ X509_free(cert); 587+ 588+ return (trust); 589+} 590+ 591+ 592+/* 593+ * 'httpCredentialsGetExpiration()' - Return the expiration date of the credentials. 594+ * 595+ * @since CUPS 2.0/OS 10.10@ 596+ */ 597+ 598+time_t // O - Expiration date of credentials 599+httpCredentialsGetExpiration( 600+ cups_array_t *credentials) // I - Credentials 601+{ 602+ time_t result = 0; // Result 603+ X509 *cert; // Certificate 604+ 605+ 606+ if ((cert = http_create_credential((http_credential_t *)cupsArrayFirst(credentials))) != NULL) 607+ { 608+ result = http_get_date(cert, 1); 609+ X509_free(cert); 610+ } 611+ 612+ return (result); 613+} 614+ 615+ 616+/* 617+ * 'httpCredentialsString()' - Return a string representing the credentials. 618+ * 619+ * @since CUPS 2.0/OS 10.10@ 620+ */ 621+ 622+size_t // O - Total size of credentials string 623+httpCredentialsString( 624+ cups_array_t *credentials, // I - Credentials 625+ char *buffer, // I - Buffer 626+ size_t bufsize) // I - Size of buffer 627+{ 628+ http_credential_t *first; // First certificate 629+ X509 *cert; // Certificate 630+ 631+ 632+ DEBUG_printf(("httpCredentialsString(credentials=%p, buffer=%p, bufsize=" CUPS_LLFMT ")", credentials, buffer, CUPS_LLCAST bufsize)); 633+ 634+ if (!buffer) 635+ return (0); 636+ 637+ if (bufsize > 0) 638+ *buffer = '\0'; 639+ 640+ first = (http_credential_t *)cupsArrayFirst(credentials); 641+ cert = http_create_credential(first); 642+ 643+ if (cert) 644+ { 645+ char name[256], // Common name associated with cert 646+ issuer[256]; // Issuer associated with cert 647+ time_t expiration; // Expiration date of cert 648+ const char *sigalg; // Signature algorithm 649+ unsigned char md5_digest[16]; // MD5 result 650+ 651+ 652+ X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, name, sizeof(name)); 653+ X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), NID_commonName, issuer, sizeof(issuer)); 654+ expiration = http_get_date(cert, 1); 655+ 656+ switch (X509_get_signature_nid(cert)) 657+ { 658+ case NID_ecdsa_with_SHA1 : 659+ sigalg = "SHA1WithECDSAEncryption"; 660+ break; 661+ case NID_ecdsa_with_SHA224 : 662+ sigalg = "SHA224WithECDSAEncryption"; 663+ break; 664+ case NID_ecdsa_with_SHA256 : 665+ sigalg = "SHA256WithECDSAEncryption"; 666+ break; 667+ case NID_ecdsa_with_SHA384 : 668+ sigalg = "SHA384WithECDSAEncryption"; 669+ break; 670+ case NID_ecdsa_with_SHA512 : 671+ sigalg = "SHA512WithECDSAEncryption"; 672+ break; 673+ case NID_sha1WithRSAEncryption : 674+ sigalg = "SHA1WithRSAEncryption"; 675+ break; 676+ case NID_sha224WithRSAEncryption : 677+ sigalg = "SHA224WithRSAEncryption"; 678+ break; 679+ case NID_sha256WithRSAEncryption : 680+ sigalg = "SHA256WithRSAEncryption"; 681+ break; 682+ case NID_sha384WithRSAEncryption : 683+ sigalg = "SHA384WithRSAEncryption"; 684+ break; 685+ case NID_sha512WithRSAEncryption : 686+ sigalg = "SHA512WithRSAEncryption"; 687+ break; 688+ default : 689+ sigalg = "Unknown"; 690+ break; 691+ } 692+ 693+ cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest)); 694+ 695+ snprintf(buffer, bufsize, "%s (issued by %s) / %s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, issuer, httpGetDateString(expiration), sigalg, md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]); 696+ X509_free(cert); 697+ } 698+ 699+ DEBUG_printf(("1httpCredentialsString: Returning \"%s\".", buffer)); 700+ 701+ return (strlen(buffer)); 702+} 703+ 704+ 705+/* 706+ * 'httpLoadCredentials()' - Load X.509 credentials from a keychain file. 707+ * 708+ * @since CUPS 2.0/OS 10.10@ 709+ */ 710+ 711+int // O - 0 on success, -1 on error 712+httpLoadCredentials( 713+ const char *path, // I - Keychain/PKCS#12 path 714+ cups_array_t **credentials, // IO - Credentials 715+ const char *common_name) // I - Common name for credentials 716+{ 717+ cups_file_t *fp; // Certificate file 718+ char filename[1024], // filename.crt 719+ temp[1024], // Temporary string 720+ line[256]; // Base64-encoded line 721+ unsigned char *data = NULL; // Buffer for cert data 722+ size_t alloc_data = 0, // Bytes allocated 723+ num_data = 0; // Bytes used 724+ int decoded; // Bytes decoded 725+ int in_certificate = 0; 726+ // In a certificate? 727+ 728+ 729+ if (!credentials || !common_name) 730+ return (-1); 731+ 732+ if (!path) 733+ path = http_default_path(temp, sizeof(temp)); 734+ if (!path) 735+ return (-1); 736+ 737+ http_make_path(filename, sizeof(filename), path, common_name, "crt"); 738+ 739+ if ((fp = cupsFileOpen(filename, "r")) == NULL) 740+ return (-1); 741+ 742+ while (cupsFileGets(fp, line, sizeof(line))) 743+ { 744+ if (!strcmp(line, "-----BEGIN CERTIFICATE-----")) 745+ { 746+ if (in_certificate) 747+ { 748+ /* 749+ * Missing END CERTIFICATE... 750+ */ 751+ 752+ httpFreeCredentials(*credentials); 753+ *credentials = NULL; 754+ break; 755+ } 756+ 757+ in_certificate = 1; 758+ } 759+ else if (!strcmp(line, "-----END CERTIFICATE-----")) 760+ { 761+ if (!in_certificate || !num_data) 762+ { 763+ /* 764+ * Missing data... 765+ */ 766+ 767+ httpFreeCredentials(*credentials); 768+ *credentials = NULL; 769+ break; 770+ } 771+ 772+ if (!*credentials) 773+ *credentials = cupsArrayNew(NULL, NULL); 774+ 775+ if (httpAddCredential(*credentials, data, num_data)) 776+ { 777+ httpFreeCredentials(*credentials); 778+ *credentials = NULL; 779+ break; 780+ } 781+ 782+ num_data = 0; 783+ in_certificate = 0; 784+ } 785+ else if (in_certificate) 786+ { 787+ if (alloc_data == 0) 788+ { 789+ data = malloc(2048); 790+ alloc_data = 2048; 791+ 792+ if (!data) 793+ break; 794+ } 795+ else if ((num_data + strlen(line)) >= alloc_data) 796+ { 797+ unsigned char *tdata = realloc(data, alloc_data + 1024); 798+ /* Expanded buffer */ 799+ 800+ if (!tdata) 801+ { 802+ httpFreeCredentials(*credentials); 803+ *credentials = NULL; 804+ break; 805+ } 806+ 807+ data = tdata; 808+ alloc_data += 1024; 809+ } 810+ 811+ decoded = alloc_data - num_data; 812+ httpDecode64_2((char *)data + num_data, &decoded, line); 813+ num_data += (size_t)decoded; 814+ } 815+ } 816+ 817+ cupsFileClose(fp); 818+ 819+ if (in_certificate) 820+ { 821+ /* 822+ * Missing END CERTIFICATE... 823+ */ 824+ 825+ httpFreeCredentials(*credentials); 826+ *credentials = NULL; 827+ } 828+ 829+ if (data) 830+ free(data); 831+ 832+ return (*credentials ? 0 : -1); 833+} 834+ 835+ 836+/* 837+ * 'httpSaveCredentials()' - Save X.509 credentials to a keychain file. 838+ * 839+ * @since CUPS 2.0/OS 10.10@ 840+ */ 841+ 842+int // O - -1 on error, 0 on success 843+httpSaveCredentials( 844+ const char *path, // I - Keychain/PKCS#12 path 845+ cups_array_t *credentials, // I - Credentials 846+ const char *common_name) // I - Common name for credentials 847+{ 848+ cups_file_t *fp; // Certificate file 849+ char filename[1024], // filename.crt 850+ nfilename[1024],// filename.crt.N 851+ temp[1024], // Temporary string 852+ line[256]; // Base64-encoded line 853+ const unsigned char *ptr; // Pointer into certificate 854+ ssize_t remaining; // Bytes left 855+ http_credential_t *cred; // Current credential 856+ 857+ 858+ if (!credentials || !common_name) 859+ return (-1); 860+ 861+ if (!path) 862+ path = http_default_path(temp, sizeof(temp)); 863+ if (!path) 864+ return (-1); 865+ 866+ http_make_path(filename, sizeof(filename), path, common_name, "crt"); 867+ snprintf(nfilename, sizeof(nfilename), "%s.N", filename); 868+ 869+ if ((fp = cupsFileOpen(nfilename, "w")) == NULL) 870+ return (-1); 871+ 872+#ifndef _WIN32 873+ fchmod(cupsFileNumber(fp), 0600); 874+#endif // !_WIN32 875+ 876+ for (cred = (http_credential_t *)cupsArrayFirst(credentials); 877+ cred; 878+ cred = (http_credential_t *)cupsArrayNext(credentials)) 879+ { 880+ cupsFilePuts(fp, "-----BEGIN CERTIFICATE-----\n"); 881+ for (ptr = cred->data, remaining = (ssize_t)cred->datalen; remaining > 0; remaining -= 45, ptr += 45) 882+ { 883+ httpEncode64_2(line, sizeof(line), (char *)ptr, remaining > 45 ? 45 : remaining); 884+ cupsFilePrintf(fp, "%s\n", line); 885+ } 886+ cupsFilePuts(fp, "-----END CERTIFICATE-----\n"); 887+ } 888+ 889+ cupsFileClose(fp); 890+ 891+ return (rename(nfilename, filename)); 892+} 893+ 894+ 895+/* 896+ * '_httpTLSInitialize()' - Initialize the TLS stack. 897+ */ 898+ 899+void 900+_httpTLSInitialize(void) 901+{ 902+ // OpenSSL no longer requires explicit initialization... 903+} 904+ 905+ 906+/* 907+ * '_httpTLSPending()' - Return the number of pending TLS-encrypted bytes. 908+ */ 909+ 910+size_t // O - Bytes available 911+_httpTLSPending(http_t *http) // I - HTTP connection 912+{ 913+ return ((size_t)SSL_pending(http->tls)); 914+} 915+ 916+ 917+/* 918+ * '_httpTLSRead()' - Read from a SSL/TLS connection. 919+ */ 920+ 921+int // O - Bytes read 922+_httpTLSRead(http_t *http, // I - Connection to server 923+ char *buf, // I - Buffer to store data 924+ int len) // I - Length of buffer 925+{ 926+ return (SSL_read((SSL *)(http->tls), buf, len)); 927+} 928+ 929+ 930+/* 931+ * '_httpTLSSetOptions()' - Set TLS protocol and cipher suite options. 932+ */ 933+ 934+void 935+_httpTLSSetOptions(int options, // I - Options 936+ int min_version, // I - Minimum TLS version 937+ int max_version) // I - Maximum TLS version 938+{ 939+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0) 940+ { 941+ tls_options = options; 942+ tls_min_version = min_version; 943+ tls_max_version = max_version; 944+ } 945+} 946+ 947+ 948+/* 949+ * '_httpTLSStart()' - Set up SSL/TLS support on a connection. 950+ */ 951+ 952+int // O - 0 on success, -1 on failure 953+_httpTLSStart(http_t *http) // I - Connection to server 954+{ 955+ BIO *bio; // Basic input/output context 956+ SSL_CTX *context; // Encryption context 957+ char hostname[256], // Hostname 958+ cipherlist[256]; // List of cipher suites 959+ unsigned long error; // Error code, if any 960+ static const int versions[] = // SSL/TLS versions 961+ { 962+ TLS1_VERSION, // No more SSL support in OpenSSL 963+ TLS1_VERSION, // TLS/1.0 964+ TLS1_1_VERSION, // TLS/1.1 965+ TLS1_2_VERSION, // TLS/1.2 966+#ifdef TLS1_3_VERSION 967+ TLS1_3_VERSION, // TLS/1.3 968+ TLS1_3_VERSION // TLS/1.3 (max) 969+#else 970+ TLS1_2_VERSION, // TLS/1.2 971+ TLS1_2_VERSION // TLS/1.2 (max) 972+#endif // TLS1_3_VERSION 973+ }; 974+ 975+ 976+ DEBUG_printf(("3_httpTLSStart(http=%p)", http)); 977+ 978+ if (tls_options < 0) 979+ { 980+ DEBUG_puts("4_httpTLSStart: Setting defaults."); 981+ _cupsSetDefaults(); 982+ DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options)); 983+ } 984+ 985+ if (http->mode == _HTTP_MODE_SERVER && !tls_keypath) 986+ { 987+ DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called."); 988+ http->error = errno = EINVAL; 989+ http->status = HTTP_STATUS_ERROR; 990+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Server credentials not set."), 1); 991+ 992+ return (-1); 993+ } 994+ 995+ if (http->mode == _HTTP_MODE_CLIENT) 996+ { 997+ // Negotiate a TLS connection as a client... 998+ context = SSL_CTX_new(TLS_client_method()); 999+ } 1000+ else 1001+ { 1002+ // Negotiate a TLS connection as a server 1003+ char crtfile[1024], // Certificate file 1004+ keyfile[1024]; // Private key file 1005+ const char *cn, // Common name to lookup 1006+ *cnptr; // Pointer into common name 1007+ int have_creds = 0; // Have credentials? 1008+ int key_status, crt_status; // Key and certificate load status 1009+ 1010+ context = SSL_CTX_new(TLS_server_method()); 1011+ 1012+ // Find the TLS certificate... 1013+ if (http->fields[HTTP_FIELD_HOST]) 1014+ { 1015+ // Use hostname for TLS upgrade... 1016+ strlcpy(hostname, http->fields[HTTP_FIELD_HOST], sizeof(hostname)); 1017+ } 1018+ else 1019+ { 1020+ // Resolve hostname from connection address... 1021+ http_addr_t addr; // Connection address 1022+ socklen_t addrlen; // Length of address 1023+ 1024+ addrlen = sizeof(addr); 1025+ if (getsockname(http->fd, (struct sockaddr *)&addr, &addrlen)) 1026+ { 1027+ // Unable to get local socket address so use default... 1028+ DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno))); 1029+ hostname[0] = '\0'; 1030+ } 1031+ else if (httpAddrLocalhost(&addr)) 1032+ { 1033+ // Local access top use default... 1034+ hostname[0] = '\0'; 1035+ } 1036+ else 1037+ { 1038+ // Lookup the socket address... 1039+ httpAddrLookup(&addr, hostname, sizeof(hostname)); 1040+ DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname)); 1041+ } 1042+ } 1043+ 1044+ if (isdigit(hostname[0] & 255) || hostname[0] == '[') 1045+ hostname[0] = '\0'; // Don't allow numeric addresses 1046+ 1047+ if (hostname[0]) 1048+ cn = hostname; 1049+ else 1050+ cn = tls_common_name; 1051+ 1052+ _cupsMutexLock(&tls_mutex); 1053+ 1054+ if (cn) 1055+ { 1056+ // First look in the CUPS keystore... 1057+ http_make_path(crtfile, sizeof(crtfile), tls_keypath, cn, "crt"); 1058+ http_make_path(keyfile, sizeof(keyfile), tls_keypath, cn, "key"); 1059+ 1060+ if (access(crtfile, R_OK) || access(keyfile, R_OK)) 1061+ { 1062+ // No CUPS-managed certs, look for CA certs... 1063+ char cacrtfile[1024], cakeyfile[1024]; // CA cert files 1064+ 1065+ snprintf(cacrtfile, sizeof(cacrtfile), "/etc/letsencrypt/live/%s/fullchain.pem", cn); 1066+ snprintf(cakeyfile, sizeof(cakeyfile), "/etc/letsencrypt/live/%s/privkey.pem", cn); 1067+ 1068+ if ((access(cacrtfile, R_OK) || access(cakeyfile, R_OK)) && (cnptr = strchr(cn, '.')) != NULL) 1069+ { 1070+ // Try just domain name... 1071+ cnptr ++; 1072+ if (strchr(cnptr, '.')) 1073+ { 1074+ snprintf(cacrtfile, sizeof(cacrtfile), "/etc/letsencrypt/live/%s/fullchain.pem", cnptr); 1075+ snprintf(cakeyfile, sizeof(cakeyfile), "/etc/letsencrypt/live/%s/privkey.pem", cnptr); 1076+ } 1077+ } 1078+ 1079+ if (!access(cacrtfile, R_OK) && !access(cakeyfile, R_OK)) 1080+ { 1081+ // Use the CA certs... 1082+ strlcpy(crtfile, cacrtfile, sizeof(crtfile)); 1083+ strlcpy(keyfile, cakeyfile, sizeof(keyfile)); 1084+ } 1085+ } 1086+ 1087+ have_creds = !access(crtfile, R_OK) && !access(keyfile, R_OK); 1088+ } 1089+ 1090+ if (!have_creds && tls_auto_create && cn) 1091+ { 1092+ DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", cn)); 1093+ 1094+ if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 3650 * 86400)) 1095+ { 1096+ DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed."); 1097+ http->error = errno = EINVAL; 1098+ http->status = HTTP_STATUS_ERROR; 1099+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1); 1100+ SSL_CTX_free(context); 1101+ _cupsMutexUnlock(&tls_mutex); 1102+ 1103+ return (-1); 1104+ } 1105+ } 1106+ 1107+ _cupsMutexUnlock(&tls_mutex); 1108+ 1109+ DEBUG_printf(("4_httpTLSStart: Using private key file '%s'.", keyfile)); 1110+ DEBUG_printf(("4_httpTLSStart: Using certificate file '%s'.", crtfile)); 1111+ 1112+ crt_status = SSL_CTX_use_certificate_chain_file(context, crtfile); 1113+ key_status = SSL_CTX_use_PrivateKey_file(context, keyfile, SSL_FILETYPE_PEM); 1114+ 1115+ if (!key_status || !crt_status) 1116+ { 1117+ // Unable to load private key or certificate... 1118+ DEBUG_puts("4_httpTLSStart: Unable to use private key or certificate chain file."); 1119+ if ((error = ERR_get_error()) != 0) 1120+ setErrorToCups(IPP_STATUS_ERROR_CUPS_PKI, error); 1121+ 1122+ http->status = HTTP_STATUS_ERROR; 1123+ http->error = EIO; 1124+ 1125+ SSL_CTX_free(context); 1126+ 1127+ return (-1); 1128+ } 1129+ } 1130+ 1131+ // Set TLS options... 1132+ strlcpy(cipherlist, "HIGH:!DH:+DHE", sizeof(cipherlist)); 1133+ if ((tls_options & _HTTP_TLS_ALLOW_RC4) && http->mode == _HTTP_MODE_CLIENT) 1134+ strlcat(cipherlist, ":+RC4", sizeof(cipherlist)); 1135+ else 1136+ strlcat(cipherlist, ":!RC4", sizeof(cipherlist)); 1137+ if (tls_options & _HTTP_TLS_DENY_CBC) 1138+ strlcat(cipherlist, ":!SHA1:!SHA256:!SHA384", sizeof(cipherlist)); 1139+ strlcat(cipherlist, ":@STRENGTH", sizeof(cipherlist)); 1140+ 1141+ DEBUG_printf(("4_httpTLSStart: cipherlist='%s', tls_min_version=%d, tls_max_version=%d", cipherlist, tls_min_version, tls_max_version)); 1142+ 1143+ SSL_CTX_set_min_proto_version(context, versions[tls_min_version]); 1144+ SSL_CTX_set_max_proto_version(context, versions[tls_max_version]); 1145+ SSL_CTX_set_cipher_list(context, cipherlist); 1146+ 1147+ // Setup a TLS session 1148+ _cupsMutexLock(&tls_mutex); 1149+ if (!tls_bio_method) 1150+ { 1151+ tls_bio_method = BIO_meth_new(BIO_get_new_index(), "http"); 1152+ BIO_meth_set_ctrl(tls_bio_method, http_bio_ctrl); 1153+ BIO_meth_set_create(tls_bio_method, http_bio_new); 1154+ BIO_meth_set_destroy(tls_bio_method, http_bio_free); 1155+ BIO_meth_set_read(tls_bio_method, http_bio_read); 1156+ BIO_meth_set_puts(tls_bio_method, http_bio_puts); 1157+ BIO_meth_set_write(tls_bio_method, http_bio_write); 1158+ } 1159+ _cupsMutexUnlock(&tls_mutex); 1160+ 1161+ bio = BIO_new(tls_bio_method); 1162+ BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http); 1163+ 1164+ http->tls = SSL_new(context); 1165+ SSL_set_bio(http->tls, bio, bio); 1166+ 1167+ if (http->mode == _HTTP_MODE_CLIENT) 1168+ { 1169+ // Negotiate as a client... 1170+ DEBUG_puts("4_httpTLSStart: Calling SSL_connect..."); 1171+ if (SSL_connect(http->tls) < 1) 1172+ { 1173+ // Failed 1174+ if ((error = ERR_get_error()) != 0) 1175+ setErrorToCups(IPP_STATUS_ERROR_CUPS_PKI, error); 1176+ 1177+ http->status = HTTP_STATUS_ERROR; 1178+ http->error = EPIPE; 1179+ 1180+ SSL_CTX_free(context); 1181+ 1182+ SSL_free(http->tls); 1183+ http->tls = NULL; 1184+ 1185+ DEBUG_printf(("4_httpTLSStart: Returning -1 (%lu)", error)); 1186+ 1187+ return (-1); 1188+ } 1189+ } 1190+ else 1191+ { 1192+ // Negotiate as a server... 1193+ DEBUG_puts("4_httpTLSStart: Calling SSL_accept..."); 1194+ if (SSL_accept(http->tls) < 1) 1195+ { 1196+ // Failed 1197+ if ((error = ERR_get_error()) != 0) 1198+ setErrorToCups(IPP_STATUS_ERROR_CUPS_PKI, error); 1199+ 1200+ http->status = HTTP_STATUS_ERROR; 1201+ http->error = EPIPE; 1202+ 1203+ SSL_CTX_free(context); 1204+ 1205+ SSL_free(http->tls); 1206+ http->tls = NULL; 1207+ 1208+ DEBUG_printf(("4_httpTLSStart: Returning -1 (%lu)", error)); 1209+ 1210+ return (-1); 1211+ } 1212+ } 1213+ 1214+ DEBUG_puts("4_httpTLSStart: Returning 0."); 1215+ 1216+ return (0); 1217+} 1218+ 1219+ 1220+/* 1221+ * '_httpTLSStop()' - Shut down SSL/TLS on a connection. 1222+ */ 1223+ 1224+void 1225+_httpTLSStop(http_t *http) // I - Connection to server 1226+{ 1227+ SSL_CTX *context; // Context for encryption 1228+ 1229+ 1230+ context = SSL_get_SSL_CTX(http->tls); 1231+ 1232+ SSL_shutdown(http->tls); 1233+ SSL_CTX_free(context); 1234+ SSL_free(http->tls); 1235+ 1236+ http->tls = NULL; 1237+} 1238+ 1239+ 1240+/* 1241+ * '_httpTLSWrite()' - Write to a SSL/TLS connection. 1242+ */ 1243+ 1244+int // O - Bytes written 1245+_httpTLSWrite(http_t *http, // I - Connection to server 1246+ const char *buf, // I - Buffer holding data 1247+ int len) // I - Length of buffer 1248+{ 1249+ return (SSL_write(http->tls, buf, len)); 1250+} 1251+ 1252+ 1253+/* 1254+ * 'http_bio_ctrl()' - Control the HTTP connection. 1255+ */ 1256+ 1257+static long // O - Result/data 1258+http_bio_ctrl(BIO *h, // I - BIO data 1259+ int cmd, // I - Control command 1260+ long arg1, // I - First argument 1261+ void *arg2) // I - Second argument 1262+{ 1263+ switch (cmd) 1264+ { 1265+ default : 1266+ return (0); 1267+ 1268+ case BIO_CTRL_RESET : 1269+ BIO_set_data(h, NULL); 1270+ return (0); 1271+ 1272+ case BIO_C_SET_FILE_PTR : 1273+ BIO_set_data(h, arg2); 1274+ BIO_set_init(h, 1); 1275+ return (1); 1276+ 1277+ case BIO_C_GET_FILE_PTR : 1278+ if (arg2) 1279+ { 1280+ *((void **)arg2) = BIO_get_data(h); 1281+ return (1); 1282+ } 1283+ else 1284+ return (0); 1285+ 1286+ case BIO_CTRL_DUP : 1287+ case BIO_CTRL_FLUSH : 1288+ return (1); 1289+ } 1290+} 1291+ 1292+ 1293+/* 1294+ * 'http_bio_free()' - Free OpenSSL data. 1295+ */ 1296+ 1297+static int // O - 1 on success, 0 on failure 1298+http_bio_free(BIO *h) // I - BIO data 1299+{ 1300+ if (!h) 1301+ return (0); 1302+ 1303+ if (BIO_get_shutdown(h)) 1304+ BIO_set_init(h, 0); 1305+ 1306+ return (1); 1307+} 1308+ 1309+ 1310+/* 1311+ * 'http_bio_new()' - Initialize an OpenSSL BIO structure. 1312+ */ 1313+ 1314+static int // O - 1 on success, 0 on failure 1315+http_bio_new(BIO *h) // I - BIO data 1316+{ 1317+ if (!h) 1318+ return (0); 1319+ 1320+ BIO_set_init(h, 0); 1321+ BIO_set_data(h, NULL); 1322+ 1323+ return (1); 1324+} 1325+ 1326+ 1327+/* 1328+ * 'http_bio_puts()' - Send a string for OpenSSL. 1329+ */ 1330+ 1331+static int // O - Bytes written 1332+http_bio_puts(BIO *h, // I - BIO data 1333+ const char *str) // I - String to write 1334+{ 1335+#ifdef WIN32 1336+ return (send(((http_t *)BIO_get_data(h))->fd, str, (int)strlen(str), 0)); 1337+#else 1338+ return ((int)send(((http_t *)BIO_get_data(h))->fd, str, strlen(str), 0)); 1339+#endif // WIN32 1340+} 1341+ 1342+ 1343+/* 1344+ * 'http_bio_read()' - Read data for OpenSSL. 1345+ */ 1346+ 1347+static int // O - Bytes read 1348+http_bio_read(BIO *h, // I - BIO data 1349+ char *buf, // I - Buffer 1350+ int size) // I - Number of bytes to read 1351+{ 1352+ http_t *http; // HTTP connection 1353+ 1354+ 1355+ http = (http_t *)BIO_get_data(h); 1356+ 1357+ if (!http->blocking) 1358+ { 1359+ /* 1360+ * Make sure we have data before we read... 1361+ */ 1362+ 1363+ if (!_httpWait(http, 10000, 0)) 1364+ { 1365+#ifdef WIN32 1366+ http->error = WSAETIMEDOUT; 1367+#else 1368+ http->error = ETIMEDOUT; 1369+#endif // WIN32 1370+ 1371+ return (-1); 1372+ } 1373+ } 1374+ 1375+ return ((int)recv(http->fd, buf, (size_t)size, 0)); 1376+} 1377+ 1378+ 1379+/* 1380+ * 'http_bio_write()' - Write data for OpenSSL. 1381+ */ 1382+ 1383+static int // O - Bytes written 1384+http_bio_write(BIO *h, // I - BIO data 1385+ const char *buf, // I - Buffer to write 1386+ int num) // I - Number of bytes to write 1387+{ 1388+ return (send(((http_t *)BIO_get_data(h))->fd, buf, num, 0)); 1389+} 1390+ 1391+ 1392+/* 1393+ * 'http_create_credential()' - Create a single credential in the internal format. 1394+ */ 1395+ 1396+static X509 * // O - Certificate 1397+http_create_credential( 1398+ http_credential_t *credential) // I - Credential 1399+{ 1400+ X509 *cert = NULL; // Certificate 1401+ BIO *bio; // Basic I/O for string 1402+ 1403+ 1404+ if (!credential) 1405+ return (NULL); 1406+ 1407+ if ((bio = BIO_new_mem_buf(credential->data, credential->datalen)) == NULL) 1408+ return (NULL); 1409+ 1410+ PEM_read_bio_X509(bio, &cert, NULL, (void *)""); 1411+ 1412+ BIO_free(bio); 1413+ 1414+ return (cert); 1415+} 1416+ 1417+ 1418+/* 1419+ * 'http_default_path()' - Get the default credential store path. 1420+ */ 1421+ 1422+static const char * // O - Path or NULL on error 1423+http_default_path( 1424+ char *buffer, // I - Path buffer 1425+ size_t bufsize) // I - Size of path buffer 1426+{ 1427+ _cups_globals_t *cg = _cupsGlobals(); 1428+ // Pointer to library globals 1429+ 1430+ 1431+#ifdef _WIN32 1432+ if (cg->home) 1433+#else 1434+ if (cg->home && getuid()) 1435+#endif // _WIN32 1436+ { 1437+ snprintf(buffer, bufsize, "%s/.cups", cg->home); 1438+ if (access(buffer, 0)) 1439+ { 1440+ DEBUG_printf(("1http_default_path: Making directory \"%s\".", buffer)); 1441+ if (mkdir(buffer, 0700)) 1442+ { 1443+ DEBUG_printf(("1http_default_path: Failed to make directory: %s", strerror(errno))); 1444+ return (NULL); 1445+ } 1446+ } 1447+ 1448+ snprintf(buffer, bufsize, "%s/.cups/ssl", cg->home); 1449+ if (access(buffer, 0)) 1450+ { 1451+ DEBUG_printf(("1http_default_path: Making directory \"%s\".", buffer)); 1452+ if (mkdir(buffer, 0700)) 1453+ { 1454+ DEBUG_printf(("1http_default_path: Failed to make directory: %s", strerror(errno))); 1455+ return (NULL); 1456+ } 1457+ } 1458+ } 1459+ else 1460+ strlcpy(buffer, CUPS_SERVERROOT "/ssl", bufsize); 1461+ 1462+ DEBUG_printf(("1http_default_path: Using default path \"%s\".", buffer)); 1463+ 1464+ return (buffer); 1465+} 1466+ 1467+ 1468+// 1469+// 'http_get_date()' - Get the notBefore or notAfter date of a certificate. 1470+// 1471+ 1472+static time_t // O - UNIX time in seconds 1473+http_get_date(X509 *cert, // I - Certificate 1474+ int which) // I - 0 for notBefore, 1 for notAfter 1475+{ 1476+ struct tm exptm; // Expiration date components 1477+ 1478+ 1479+ if (which) 1480+ ASN1_TIME_to_tm(X509_get0_notAfter(cert), &exptm); 1481+ else 1482+ ASN1_TIME_to_tm(X509_get0_notBefore(cert), &exptm); 1483+ 1484+ return (mktime(&exptm)); 1485+} 1486+ 1487+ 1488+#if 0 1489+/* 1490+ * 'http_load_crl()' - Load the certificate revocation list, if any. 1491+ */ 1492+ 1493+static void 1494+http_load_crl(void) 1495+{ 1496+ _cupsMutexLock(&tls_mutex); 1497+ 1498+ if (!openssl_x509_crl_init(&tls_crl)) 1499+ { 1500+ cups_file_t *fp; // CRL file 1501+ char filename[1024], // site.crl 1502+ line[256]; // Base64-encoded line 1503+ unsigned char *data = NULL; // Buffer for cert data 1504+ size_t alloc_data = 0, // Bytes allocated 1505+ num_data = 0; // Bytes used 1506+ int decoded; // Bytes decoded 1507+ openssl_datum_t datum; // Data record 1508+ 1509+ 1510+ http_make_path(filename, sizeof(filename), CUPS_SERVERROOT, "site", "crl"); 1511+ 1512+ if ((fp = cupsFileOpen(filename, "r")) != NULL) 1513+ { 1514+ while (cupsFileGets(fp, line, sizeof(line))) 1515+ { 1516+ if (!strcmp(line, "-----BEGIN X509 CRL-----")) 1517+ { 1518+ if (num_data) 1519+ { 1520+ /* 1521+ * Missing END X509 CRL... 1522+ */ 1523+ 1524+ break; 1525+ } 1526+ } 1527+ else if (!strcmp(line, "-----END X509 CRL-----")) 1528+ { 1529+ if (!num_data) 1530+ { 1531+ /* 1532+ * Missing data... 1533+ */ 1534+ 1535+ break; 1536+ } 1537+ 1538+ datum.data = data; 1539+ datum.size = num_data; 1540+ 1541+ openssl_x509_crl_import(tls_crl, &datum, GNUTLS_X509_FMT_PEM); 1542+ 1543+ num_data = 0; 1544+ } 1545+ else 1546+ { 1547+ if (alloc_data == 0) 1548+ { 1549+ data = malloc(2048); 1550+ alloc_data = 2048; 1551+ 1552+ if (!data) 1553+ break; 1554+ } 1555+ else if ((num_data + strlen(line)) >= alloc_data) 1556+ { 1557+ unsigned char *tdata = realloc(data, alloc_data + 1024); 1558+ // Expanded buffer 1559+ 1560+ if (!tdata) 1561+ break; 1562+ 1563+ data = tdata; 1564+ alloc_data += 1024; 1565+ } 1566+ 1567+ decoded = alloc_data - num_data; 1568+ httpDecode64_2((char *)data + num_data, &decoded, line); 1569+ num_data += (size_t)decoded; 1570+ } 1571+ } 1572+ 1573+ cupsFileClose(fp); 1574+ 1575+ if (data) 1576+ free(data); 1577+ } 1578+ } 1579+ 1580+ _cupsMutexUnlock(&tls_mutex); 1581+} 1582+#endif // 0 1583+ 1584+ 1585+/* 1586+ * 'http_make_path()' - Format a filename for a certificate or key file. 1587+ */ 1588+ 1589+static const char * // O - Filename 1590+http_make_path( 1591+ char *buffer, // I - Filename buffer 1592+ size_t bufsize, // I - Size of buffer 1593+ const char *dirname, // I - Directory 1594+ const char *filename, // I - Filename (usually hostname) 1595+ const char *ext) // I - Extension 1596+{ 1597+ char *bufptr, // Pointer into buffer 1598+ *bufend = buffer + bufsize - 1; // End of buffer 1599+ 1600+ 1601+ snprintf(buffer, bufsize, "%s/", dirname); 1602+ bufptr = buffer + strlen(buffer); 1603+ 1604+ while (*filename && bufptr < bufend) 1605+ { 1606+ if (_cups_isalnum(*filename) || *filename == '-' || *filename == '.') 1607+ *bufptr++ = *filename; 1608+ else 1609+ *bufptr++ = '_'; 1610+ 1611+ filename ++; 1612+ } 1613+ 1614+ if (bufptr < bufend && filename[-1] != '.') 1615+ *bufptr++ = '.'; 1616+ 1617+ strlcpy(bufptr, ext, (size_t)(bufend - bufptr + 1)); 1618+ 1619+ return (buffer); 1620+} 1621+ 1622+ 1623+// 1624+// 'http_x509_add_ext()' - Add an extension to a certificate. 1625+// 1626+ 1627+static int // O - 1 on success, 0 on failure 1628+http_x509_add_ext(X509 *cert, // I - Certificate 1629+ int nid, // I - Extension ID 1630+ const char *value) // I - Value 1631+{ 1632+ int ret; // Return value 1633+ X509_EXTENSION *ex = NULL; // Extension 1634+ X509V3_CTX ctx; // Certificate context 1635+ 1636+ 1637+ DEBUG_printf(("3http_x509_add_ext(cert=%p, nid=%d, value=\"%s\")", (void *)cert, nid, value)); 1638+ 1639+ // Don't use a configuration database... 1640+ X509V3_set_ctx_nodb(&ctx); 1641+ 1642+ // Self-signed certificates use the same issuer and subject... 1643+ X509V3_set_ctx(&ctx, /*issuer*/cert, /*subject*/cert, /*req*/NULL, /*crl*/NULL, /*flags*/0); 1644+ 1645+ // Create and add the extension... 1646+ if ((ex = X509V3_EXT_conf_nid(/*conf*/NULL, &ctx, nid, value)) == NULL) 1647+ { 1648+ DEBUG_puts("4http_x509_add_ext: Unable to create extension, returning false."); 1649+ return (0); 1650+ } 1651+ 1652+ ret = X509_add_ext(cert, ex, -1) != 0; 1653+ 1654+ DEBUG_printf(("4http_x509_add_ext: X509_add_ext returned %s.", ret ? "true" : "false")); 1655+ 1656+ // Free the extension and return... 1657+ X509_EXTENSION_free(ex); 1658+ 1659+ return (ret); 1660+} 1661+ 1662+ 1663+// 1664+// 'http_x509_add_san()' - Add a subjectAltName to GENERAL_NAMES used for 1665+// the extension to an X.509 certificate. 1666+// 1667+ 1668+static void 1669+http_x509_add_san(GENERAL_NAMES *gens, // I - Concatenation of DNS names 1670+ const char *name) // I - Hostname 1671+{ 1672+ GENERAL_NAME *gen_dns = GENERAL_NAME_new(); 1673+ // DNS: name 1674+ ASN1_IA5STRING *ia5 = ASN1_IA5STRING_new(); 1675+ // Hostname string 1676+ 1677+ 1678+ // Set the strings and push it on the GENERAL_NAMES list... 1679+ ASN1_STRING_set(ia5, name, strlen(name)); 1680+ GENERAL_NAME_set0_value(gen_dns, GEN_DNS, ia5); 1681+ sk_GENERAL_NAME_push(gens, gen_dns); 1682+} 1683