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