• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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