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