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