]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl_support.cc
Bootstrapped
[thirdparty/squid.git] / src / ssl_support.cc
CommitLineData
f484cdf5 1
2/*
84f2d773 3 * $Id: ssl_support.cc,v 1.5 2001/10/24 06:55:44 hno Exp $
f484cdf5 4 *
5 * AUTHOR: Benno Rice
6 * DEBUG: section 81 SSL accelerator support
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36#include "squid.h"
37
38extern int commUnsetNonBlocking(int fd);
39extern int commSetNonBlocking(int fd);
40
41void clientNegotiateSSL(int fd, void *data);
42void clientReadSSLRequest(int fd, void *data);
f484cdf5 43
44static RSA *
45ssl_temp_rsa_cb(SSL * ssl, int export, int keylen)
46{
47 static RSA *rsa = NULL;
48
49 if (rsa == NULL)
50 rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
51 return rsa;
52}
53
54static int
55ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
56{
57 char buffer[256];
58
59 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buffer,
60 sizeof(buffer));
61 if (ok)
62 debug(81, 5) ("SSL Certificate OK: %s\n", buffer);
63 else {
64 switch (ctx->error) {
65 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
66 debug(81, 5) ("SSL Certficate error: CA not known: %s\n", buffer);
67 break;
68 case X509_V_ERR_CERT_NOT_YET_VALID:
69 debug(81, 5) ("SSL Certficate not yet valid: %s\n", buffer);
70 break;
71 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
72 debug(81, 5) ("SSL Certificate has illegal \'not before\' field: %s\n", buffer);
73 break;
74 case X509_V_ERR_CERT_HAS_EXPIRED:
75 debug(81, 5) ("SSL Certificate expired: %s\n", buffer);
76 break;
77 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
78 debug(81, 5) ("SSL Certificate has invalid \'not after\' field: %s\n", buffer);
79 break;
80 default:
81 debug(81, 5) ("SSL unknown certificate error %d in %s\n",
82 ctx->error, buffer);
83 break;
84 }
85 }
86 return ok;
87}
88
79d4ccdf 89static struct ssl_option {
90 const char *name;
91 long value;
92} ssl_options[] = {
93
94 {
95 "MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG
96 },
97 {
98 "NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG
99 },
100 {
101 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
102 },
103 {
104 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
105 },
106 {
107 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
108 },
109 {
110 "MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING
111 },
112 {
113 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
114 },
115 {
116 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
117 },
118 {
119 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
120 },
121 {
122 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
123 },
124 {
125 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
126 },
127 {
128 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
129 },
130 {
131 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
132 },
133 {
134 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
135 },
136 {
137 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
138 },
139 {
140 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
141 },
142 {
143 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
144 },
145 {
146 "ALL", SSL_OP_ALL
147 },
148 {
149 "NO_SSLv2", SSL_OP_NO_SSLv2
150 },
151 {
152 "NO_SSLv3", SSL_OP_NO_SSLv3
153 },
154 {
155 "NO_TLSv1", SSL_OP_NO_TLSv1
156 },
157 {
158 "", 0
159 },
160 {
161 NULL, 0
162 }
163};
164
84f2d773 165static long
79d4ccdf 166ssl_parse_options(const char *options)
167{
168 long op = SSL_OP_ALL;
169 char *tmp;
170 char *option;
171
172 if (!options)
173 goto no_options;
174
175 tmp = xstrdup(options);
176 option = strtok(tmp, ":,");
177 while (option) {
178 struct ssl_option *opt = NULL, *opttmp;
179 long value = 0;
180 enum {
181 MODE_ADD, MODE_REMOVE
182 } mode;
183 switch (*option) {
184 case '!':
185 case '-':
186 mode = MODE_REMOVE;
187 option++;
188 break;
189 case '+':
190 mode = MODE_ADD;
191 option++;
192 break;
193 default:
194 mode = MODE_ADD;
195 break;
196 }
197 for (opttmp = ssl_options; opttmp->name; opttmp++) {
198 if (strcmp(opttmp->name, option) == 0) {
199 opt = opttmp;
200 break;
201 }
202 }
203 if (opt)
204 value = opt->value;
205 else if (strncmp(option, "0x", 2) == 0) {
206 /* Special case.. hex specification */
207 value = strtol(option + 2, NULL, 16);
208 } else {
209 fatalf("Unknown SSL option '%s'", option);
210 value = 0; /* Keep GCC happy */
211 }
212 switch (mode) {
213 case MODE_ADD:
214 op |= value;
215 break;
216 case MODE_REMOVE:
217 op &= ~value;
218 break;
219 }
220 option = strtok(NULL, ":,");
221 }
222
223 safe_free(tmp);
224 no_options:
225 return op;
226}
227
d193a436 228SSL_CTX *
79d4ccdf 229sslCreateContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options)
f484cdf5 230{
231 int ssl_error;
232 SSL_METHOD *method;
d193a436 233 SSL_CTX *sslContext;
234 static int ssl_initialized = 0;
235 if (!ssl_initialized) {
236 ssl_initialized = 1;
237 SSL_load_error_strings();
238 SSLeay_add_ssl_algorithms();
239 }
f484cdf5 240 if (!keyfile)
241 keyfile = certfile;
242 if (!certfile)
243 certfile = keyfile;
244
245 debug(81, 1) ("Initialising SSL.\n");
79d4ccdf 246 switch (version) {
f484cdf5 247 case 2:
248 debug(81, 5) ("Using SSLv2.\n");
249 method = SSLv2_server_method();
250 break;
251 case 3:
252 debug(81, 5) ("Using SSLv3.\n");
253 method = SSLv3_server_method();
254 break;
255 case 4:
256 debug(81, 5) ("Using TLSv1.\n");
257 method = TLSv1_server_method();
258 break;
259 case 1:
260 default:
261 debug(81, 5) ("Using SSLv2/SSLv3.\n");
262 method = SSLv23_server_method();
263 break;
264 }
265
266 sslContext = SSL_CTX_new(method);
267 if (sslContext == NULL) {
268 ssl_error = ERR_get_error();
269 fatalf("Failed to allocate SSL context: %s\n",
270 ERR_error_string(ssl_error, NULL));
271 }
79d4ccdf 272 SSL_CTX_set_options(sslContext, ssl_parse_options(options));
f484cdf5 273
79d4ccdf 274 if (cipher) {
275 debug(81, 5) ("Using chiper suite %s.\n", cipher);
276 if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
277 ssl_error = ERR_get_error();
278 fatalf("Failed to set SSL cipher suite: %s\n",
279 ERR_error_string(ssl_error, NULL));
280 }
281 }
f484cdf5 282 debug(81, 1) ("Using certificate in %s\n", certfile);
283 if (!SSL_CTX_use_certificate_file(sslContext, certfile, SSL_FILETYPE_PEM)) {
284 ssl_error = ERR_get_error();
285 fatalf("Failed to acquire SSL certificate: %s\n",
286 ERR_error_string(ssl_error, NULL));
287 }
288 debug(81, 1) ("Using private key in %s\n", keyfile);
289 if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
290 ssl_error = ERR_get_error();
291 fatalf("Failed to acquire SSL private key: %s\n",
292 ERR_error_string(ssl_error, NULL));
293 }
294 debug(81, 5) ("Comparing private and public SSL keys.\n");
295 if (!SSL_CTX_check_private_key(sslContext))
296 fatal("SSL private key does not match public key: %s\n");
297
298 debug(81, 9) ("Setting RSA key generation callback.\n");
299 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
300
301 debug(81, 9) ("Setting certificate verification callback.\n");
302 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb);
303
304 debug(81, 9) ("Setting default CA certificate location.\n");
305 if (!SSL_CTX_set_default_verify_paths(sslContext)) {
306 ssl_error = ERR_get_error();
307 debug(81, 1) ("Error error setting default CA certificate location: %s\n",
308 ERR_error_string(ssl_error, NULL));
309 debug(81, 1) ("continuing anyway...\n");
310 }
311 debug(81, 9) ("Set client certifying authority list.\n");
312 SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile));
d193a436 313 return sslContext;
f484cdf5 314}
315
d193a436 316int
f484cdf5 317ssl_read_method(fd, buf, len)
318 int fd;
319 char *buf;
320 int len;
321{
79d4ccdf 322 int i;
323
324 i = SSL_read(fd_table[fd].ssl, buf, len);
325
326 if (i > 0 && SSL_pending(fd_table[fd].ssl) > 0) {
327 debug(81, 2) ("SSL fd %d is pending\n", fd);
328 fd_table[fd].flags.read_pending = 1;
329 } else
330 fd_table[fd].flags.read_pending = 0;
331
332 return i;
f484cdf5 333}
334
d193a436 335int
f484cdf5 336ssl_write_method(fd, buf, len)
337 int fd;
338 const char *buf;
339 int len;
340{
341 return (SSL_write(fd_table[fd].ssl, buf, len));
342}
79d4ccdf 343
344void
345ssl_shutdown_method(fd)
346{
347 SSL *ssl = fd_table[fd].ssl;
348 if (!fd_table[fd].ssl_shutdown) {
349 fd_table[fd].ssl_shutdown = 1;
350 if (Config.SSL.unclean_shutdown)
351 SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
352 else
353 SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
354 }
355 SSL_shutdown(ssl);
356}