xref: /aosp_15_r20/external/libcups/cups/tls-boringssl.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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