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