1 /*
2  * TLS support code for CUPS using Google BoringSSL.
3  *
4  * Copyright 2007-2016 by Apple Inc.
5  * Copyright 1997-2007 by Easy Software Products, all rights reserved.
6  *
7  * These coded instructions, statements, and computer programs are the
8  * property of Apple Inc. and are protected by Federal copyright
9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10  * which should have been included with this file.  If this file is
11  * file is missing or damaged, see the license at "http://www.cups.org/".
12  *
13  * This file is subject to the Apple OS-Developed Software exception.
14  */
15 
16 /**** This file is included from tls.c ****/
17 
18 /*
19  * Local globals...
20  */
21 
22 #include "cups-private.h"
23 #include "http.h"
24 #include "thread-private.h"
25 #include <openssl/err.h>
26 #include <openssl/ssl.h>
27 
28 #include <sys/stat.h>
29 
30 static char		*tls_keypath = NULL;
31 					/* Server cert keychain path */
32 static int		tls_options = -1;/* Options for TLS connections */
33 
34 
35 /*
36  * Local functions...
37  */
38 
39 static BIO_METHOD *     _httpBIOMethods(void);
40 static int              http_bio_write(BIO *h, const char *buf, int num);
41 static int              http_bio_read(BIO *h, char *buf, int size);
42 static int              http_bio_puts(BIO *h, const char *str);
43 static long             http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
44 static int              http_bio_new(BIO *h);
45 static int              http_bio_free(BIO *data);
46 
47 static BIO_METHOD	http_bio_methods =
48 			{
49 			  BIO_TYPE_SSL,
50 			  "http",
51 			  http_bio_write,
52 			  http_bio_read,
53 			  http_bio_puts,
54 			  NULL, /* http_bio_gets, */
55 			  http_bio_ctrl,
56 			  http_bio_new,
57 			  http_bio_free,
58 			  NULL,
59 			};
60 
61 /*
62  * 'cupsMakeServerCredentials()' - Make a self-signed certificate and private key pair.
63  *
64  * @since CUPS 2.0/OS 10.10@
65  */
66 
67 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)68 cupsMakeServerCredentials(
69     const char *path,			/* I - Path to keychain/directory */
70     const char *common_name,		/* I - Common name */
71     int        num_alt_names,		/* I - Number of subject alternate names */
72     const char **alt_names,		/* I - Subject Alternate Names */
73     time_t     expiration_date)		/* I - Expiration date */
74 {
75   int		pid,			/* Process ID of command */
76 		status;			/* Status of command */
77   char		command[1024],		/* Command */
78 		*argv[12],		/* Command-line arguments */
79 		*envp[1000],	        /* Environment variables */
80 		infofile[1024],		/* Type-in information for cert */
81 		seedfile[1024];		/* Random number seed file */
82   int		envc,			/* Number of environment variables */
83 		bytes;			/* Bytes written */
84   cups_file_t	*fp;			/* Seed/info file */
85   int		infofd;			/* Info file descriptor */
86   char          temp[1024],	        /* Temporary directory name */
87                 crtfile[1024],	        /* Certificate filename */
88                 keyfile[1024];	        /* Private key filename */
89 
90   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));
91 
92   return 0;
93 }
94 
95 
96 /*
97  * '_httpCreateCredentials()' - Create credentials in the internal format.
98  */
99 
100 http_tls_credentials_t			/* O - Internal credentials */
_httpCreateCredentials(cups_array_t * credentials)101 _httpCreateCredentials(
102     cups_array_t *credentials)		/* I - Array of credentials */
103 {
104   (void)credentials;
105 
106   return (NULL);
107 }
108 
109 
110 /*
111  * '_httpFreeCredentials()' - Free internal credentials.
112  */
113 
114 void
_httpFreeCredentials(http_tls_credentials_t credentials)115 _httpFreeCredentials(
116     http_tls_credentials_t credentials)	/* I - Internal credentials */
117 {
118   (void)credentials;
119 }
120 
121 
122 /*
123  * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
124  */
125 
126 static BIO_METHOD *                            /* O - BIO methods for OpenSSL */
_httpBIOMethods(void)127 _httpBIOMethods(void)
128 {
129   return (&http_bio_methods);
130 }
131 
132 
133 /*
134  * 'http_bio_ctrl()' - Control the HTTP connection.
135  */
136 
137 static long				/* O - Result/data */
http_bio_ctrl(BIO * h,int cmd,long arg1,void * arg2)138 http_bio_ctrl(BIO  *h,			/* I - BIO data */
139               int  cmd,			/* I - Control command */
140 	      long arg1,		/* I - First argument */
141 	      void *arg2)		/* I - Second argument */
142 {
143   switch (cmd)
144   {
145     default :
146         return (0);
147 
148     case BIO_CTRL_RESET :
149         h->ptr = NULL;
150 	return (0);
151 
152     case BIO_C_SET_FILE_PTR :
153         h->ptr  = arg2;
154 	h->init = 1;
155 	return (1);
156 
157     case BIO_C_GET_FILE_PTR :
158         if (arg2)
159 	{
160 	  *((void **)arg2) = h->ptr;
161 	  return (1);
162 	}
163 	else
164 	  return (0);
165 
166     case BIO_CTRL_DUP :
167     case BIO_CTRL_FLUSH :
168         return (1);
169   }
170 }
171 
172 
173 /*
174  * 'http_bio_free()' - Free OpenSSL data.
175  */
176 
177 static int				/* O - 1 on success, 0 on failure */
http_bio_free(BIO * h)178 http_bio_free(BIO *h)			/* I - BIO data */
179 {
180   if (!h)
181     return (0);
182 
183   if (h->shutdown)
184   {
185     h->init  = 0;
186     h->flags = 0;
187   }
188 
189   return (1);
190 }
191 
192 
193 /*
194  * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
195  */
196 
197 static int				/* O - 1 on success, 0 on failure */
http_bio_new(BIO * h)198 http_bio_new(BIO *h)			/* I - BIO data */
199 {
200   if (!h)
201     return (0);
202 
203   h->init  = 0;
204   h->num   = 0;
205   h->ptr   = NULL;
206   h->flags = 0;
207 
208   return (1);
209 }
210 
211 
212 /*
213  * 'http_bio_puts()' - Send a string for OpenSSL.
214  */
215 
216 static int				/* O - Bytes written */
http_bio_puts(BIO * h,const char * str)217 http_bio_puts(BIO        *h,		/* I - BIO data */
218               const char *str)		/* I - String to write */
219 {
220   return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
221 }
222 
223 
224 /*
225  * 'http_bio_read()' - Read data for OpenSSL.
226  */
227 
228 static int				/* O - Bytes read */
http_bio_read(BIO * h,char * buf,int size)229 http_bio_read(BIO  *h,			/* I - BIO data */
230               char *buf,		/* I - Buffer */
231 	      int  size)		/* I - Number of bytes to read */
232 {
233   http_t	*http;			/* HTTP connection */
234 
235 
236   http = (http_t *)h->ptr;
237 
238   if (!http->blocking)
239   {
240    /*
241     * Make sure we have data before we read...
242     */
243 
244     while (!_httpWait(http, http->wait_value, 0))
245     {
246       if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
247 	continue;
248 
249       http->error = ETIMEDOUT;
250 
251       return (-1);
252     }
253   }
254 
255   return (recv(http->fd, buf, size, 0));
256 }
257 
258 
259 /*
260  * 'http_bio_write()' - Write data for OpenSSL.
261  */
262 
263 static int				/* O - Bytes written */
http_bio_write(BIO * h,const char * buf,int num)264 http_bio_write(BIO        *h,		/* I - BIO data */
265                const char *buf,		/* I - Buffer to write */
266 	       int        num)		/* I - Number of bytes to write */
267 {
268   return (send(((http_t *)h->ptr)->fd, buf, num, 0));
269 }
270 
271 
272 /*
273  * '_httpTLSInitialize()' - Initialize the TLS stack.
274  */
275 
276 void
_httpTLSInitialize(void)277 _httpTLSInitialize(void)
278 {
279   SSL_library_init();
280 }
281 
282 
283 /*
284  * '_httpTLSPending()' - Return the number of pending TLS-encrypted bytes.
285  */
286 
287 size_t					/* O - Bytes available */
_httpTLSPending(http_t * http)288 _httpTLSPending(http_t *http)		/* I - HTTP connection */
289 {
290   return (SSL_pending(http->tls));
291 }
292 
293 
294 /*
295  * '_httpTLSRead()' - Read from a SSL/TLS connection.
296  */
297 
298 int					/* O - Bytes read */
_httpTLSRead(http_t * http,char * buf,int len)299 _httpTLSRead(http_t *http,		/* I - Connection to server */
300 	     char   *buf,		/* I - Buffer to store data */
301 	     int    len)		/* I - Length of buffer */
302 {
303   return (SSL_read((SSL *)(http->tls), buf, len));
304 }
305 
306 
307 /*
308  * '_httpTLSSetOptions()' - Set TLS protocol and cipher suite options.
309  */
310 
311 void
_httpTLSSetOptions(int options)312 _httpTLSSetOptions(int options)		/* I - Options */
313 {
314   tls_options = options;
315 }
316 
317 
318 /*
319  * '_httpTLSStart()' - Set up SSL/TLS support on a connection.
320  */
321 
322 int					/* O - 0 on success, -1 on failure */
_httpTLSStart(http_t * http)323 _httpTLSStart(http_t *http)		/* I - Connection to server */
324 {
325   char			hostname[256],	/* Hostname */
326 			*hostptr;	/* Pointer into hostname */
327 
328   SSL_CTX		*context;	/* Context for encryption */
329   BIO			*bio;		/* BIO data */
330   const char		*message = NULL;/* Error message */
331 
332   DEBUG_printf(("3_httpTLSStart(http=%p)", (void *)http));
333 
334   if (tls_options < 0)
335   {
336     DEBUG_puts("4_httpTLSStart: Setting defaults.");
337     _cupsSetDefaults();
338     DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options));
339   }
340 
341   if (http->mode == _HTTP_MODE_SERVER && !tls_keypath)
342   {
343     DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
344     http->error  = errno = EINVAL;
345     http->status = HTTP_STATUS_ERROR;
346     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Server credentials not set."), 1);
347 
348     return (-1);
349   }
350 
351   context = SSL_CTX_new(TLS_method());
352   if (tls_options & _HTTP_TLS_DENY_TLS10)
353     SSL_CTX_set_min_proto_version(context, TLS1_1_VERSION);
354 
355   bio = BIO_new(_httpBIOMethods());
356   BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
357 
358   http->tls = SSL_new(context);
359   SSL_set_bio(http->tls, bio, bio);
360 
361   /* http->tls retains an internal reference to the SSL_CTX. */
362   SSL_CTX_free(context);
363 
364   if (http->mode == _HTTP_MODE_CLIENT)
365   {
366     SSL_set_connect_state(http->tls);
367 
368    /*
369     * Client: get the hostname to use for TLS...
370     */
371 
372     if (httpAddrLocalhost(http->hostaddr))
373     {
374       strlcpy(hostname, "localhost", sizeof(hostname));
375     }
376     else
377     {
378      /*
379       * Otherwise make sure the hostname we have does not end in a trailing dot.
380       */
381 
382       strlcpy(hostname, http->hostname, sizeof(hostname));
383       if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
384 	  *hostptr == '.')
385 	*hostptr = '\0';
386     }
387     SSL_set_tlsext_host_name(http->tls, hostname);
388   }
389   else
390   {
391 /* @@@ TODO @@@ */
392     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, "Server not supported", 0);
393   }
394 
395 
396   if (SSL_do_handshake(http->tls) != 1)
397   {
398     unsigned long	error;	/* Error code */
399     char		buf[256];
400 
401     while ((error = ERR_get_error()) != 0)
402     {
403       ERR_error_string_n(error, buf, sizeof(buf));
404       DEBUG_printf(("8http_setup_ssl: %s", buf));
405     }
406 
407     SSL_free(http->tls);
408     http->tls = NULL;
409 
410     http->error  = errno;
411     http->status = HTTP_STATUS_ERROR;
412 
413     if (!message)
414       message = _("Unable to establish a secure connection to host.");
415 
416     _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, message, 1);
417 
418     return (-1);
419   }
420 
421   _cups_globals_t *cg = _cupsGlobals();
422   if (cg->server_cert_cb)
423   {
424     int error = 0;
425     X509 *peer_certificate = SSL_get_peer_certificate(http->tls);
426     if (peer_certificate)
427     {
428       ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(peer_certificate);
429       cups_array_t *credentials = cupsArrayNew(NULL, NULL);
430 
431       if (credentials != NULL)
432       {
433         httpAddCredential(credentials, key->data, key->length);
434         error = cg->server_cert_cb(http, http->tls, credentials, cg->server_cert_data);
435         httpFreeCredentials(credentials);
436       }
437       X509_free(peer_certificate);
438     }
439 
440     if (error != 0)
441     {
442       http->error  = errno = EINVAL;
443       http->status = HTTP_STATUS_ERROR;
444       _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Client rejected the server certificate."), 1);
445     }
446 
447     return (error);
448   }
449 
450   return (0);
451 }
452 
453 
454 /*
455  * '_httpTLSStop()' - Shut down SSL/TLS on a connection.
456  */
457 
458 void
_httpTLSStop(http_t * http)459 _httpTLSStop(http_t *http)		/* I - Connection to server */
460 {
461   unsigned long	error;			/* Error code */
462 
463   switch (SSL_shutdown(http->tls))
464   {
465     case 1 :
466 	break;
467 
468     case -1 :
469         _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
470 			"Fatal error during SSL shutdown!", 0);
471     default :
472 	while ((error = ERR_get_error()) != 0)
473         {
474 	  char	buf[256];
475 	  ERR_error_string_n(error, buf, sizeof(buf));
476 	  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, buf, 0);
477         }
478 	break;
479   }
480 
481   SSL_free(http->tls);
482   http->tls = NULL;
483 }
484 
485 /*
486  * '_httpTLSWrite()' - Write to a SSL/TLS connection.
487  */
488 
489 int					/* O - Bytes written */
_httpTLSWrite(http_t * http,const char * buf,int len)490 _httpTLSWrite(http_t     *http,		/* I - Connection to server */
491 	      const char *buf,		/* I - Buffer holding data */
492 	      int        len)		/* I - Length of buffer */
493 {
494   int	result;			/* Return value */
495 
496 
497   DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
498 
499   result = SSL_write((SSL *)(http->tls), buf, len);
500 
501   DEBUG_printf(("3http_write_ssl: Returning %d.", result));
502 
503   return result;
504 }
505