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