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