Home | History | Annotate | Download | only in cups
      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 */
     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 */
    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
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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
    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 */
    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 */
    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
    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 */
    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   return (0);
    422 }
    423 
    424 
    425 /*
    426  * '_httpTLSStop()' - Shut down SSL/TLS on a connection.
    427  */
    428 
    429 void
    430 _httpTLSStop(http_t *http)		/* I - Connection to server */
    431 {
    432   unsigned long	error;			/* Error code */
    433 
    434   switch (SSL_shutdown(http->tls))
    435   {
    436     case 1 :
    437 	break;
    438 
    439     case -1 :
    440         _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
    441 			"Fatal error during SSL shutdown!", 0);
    442     default :
    443 	while ((error = ERR_get_error()) != 0)
    444         {
    445 	  char	buf[256];
    446 	  ERR_error_string_n(error, buf, sizeof(buf));
    447 	  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, buf, 0);
    448         }
    449 	break;
    450   }
    451 
    452   SSL_free(http->tls);
    453   http->tls = NULL;
    454 }
    455 
    456 /*
    457  * '_httpTLSWrite()' - Write to a SSL/TLS connection.
    458  */
    459 
    460 int					/* O - Bytes written */
    461 _httpTLSWrite(http_t     *http,		/* I - Connection to server */
    462 	      const char *buf,		/* I - Buffer holding data */
    463 	      int        len)		/* I - Length of buffer */
    464 {
    465   int	result;			/* Return value */
    466 
    467 
    468   DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
    469 
    470   result = SSL_write((SSL *)(http->tls), buf, len);
    471 
    472   DEBUG_printf(("3http_write_ssl: Returning %d.", result));
    473 
    474   return result;
    475 }
    476