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