]>
Commit | Line | Data |
---|---|---|
7460295f | 1 | // ssl.c -- Support functions that find and load SSL support, if available |
e0bb8a33 | 2 | // Copyright (C) 2008-2009 Markus Gutschke <markus@shellinabox.com> |
7460295f MG |
3 | // |
4 | // This program is free software; you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License version 2 as | |
6 | // published by the Free Software Foundation. | |
7 | // | |
8 | // This program is distributed in the hope that it will be useful, | |
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | // GNU General Public License for more details. | |
12 | // | |
13 | // You should have received a copy of the GNU General Public License along | |
14 | // with this program; if not, write to the Free Software Foundation, Inc., | |
15 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
16 | // | |
17 | // In addition to these license terms, the author grants the following | |
18 | // additional rights: | |
19 | // | |
20 | // If you modify this program, or any covered work, by linking or | |
21 | // combining it with the OpenSSL project's OpenSSL library (or a | |
22 | // modified version of that library), containing parts covered by the | |
23 | // terms of the OpenSSL or SSLeay licenses, the author | |
24 | // grants you additional permission to convey the resulting work. | |
25 | // Corresponding Source for a non-source form of such a combination | |
26 | // shall include the source code for the parts of OpenSSL used as well | |
27 | // as that of the covered work. | |
28 | // | |
29 | // You may at your option choose to remove this additional permission from | |
30 | // the work, or from any part of it. | |
31 | // | |
32 | // It is possible to build this program in a way that it loads OpenSSL | |
33 | // libraries at run-time. If doing so, the following notices are required | |
34 | // by the OpenSSL and SSLeay licenses: | |
35 | // | |
36 | // This product includes software developed by the OpenSSL Project | |
37 | // for use in the OpenSSL Toolkit. (http://www.openssl.org/) | |
38 | // | |
39 | // This product includes cryptographic software written by Eric Young | |
40 | // (eay@cryptsoft.com) | |
41 | // | |
42 | // | |
43 | // The most up-to-date version of this program is always available from | |
44 | // http://shellinabox.com | |
45 | ||
46 | #define _GNU_SOURCE | |
bdd01e84 | 47 | #include "config.h" |
7460295f | 48 | |
c593cf68 MG |
49 | #define pthread_once x_pthread_once |
50 | #define pthread_sigmask x_pthread_sigmask | |
51 | ||
7460295f MG |
52 | #include <dlfcn.h> |
53 | #include <errno.h> | |
ad24d9a9 | 54 | #include <fcntl.h> |
7460295f MG |
55 | #include <netdb.h> |
56 | #include <signal.h> | |
57 | #include <stdlib.h> | |
58 | #include <string.h> | |
ad24d9a9 MG |
59 | #include <sys/types.h> |
60 | #include <sys/stat.h> | |
7460295f MG |
61 | #include <unistd.h> |
62 | ||
63 | #include "libhttp/ssl.h" | |
64 | #include "libhttp/httpconnection.h" | |
65 | #include "logging/logging.h" | |
66 | ||
c593cf68 MG |
67 | #undef pthread_once |
68 | #undef pthread_sigmask | |
69 | ||
bdd01e84 MG |
70 | #if defined(HAVE_OPENSSL) && !defined(OPENSSL_NO_TLSEXT) && \ |
71 | defined(TLSEXT_NAMETYPE_host_name) && defined(SSL_TLSEXT_ERR_OK) | |
d04f7ca7 MG |
72 | #define HAVE_TLSEXT |
73 | #endif | |
74 | ||
7460295f MG |
75 | #if defined(HAVE_PTHREAD_H) |
76 | // Pthread support is optional. Only enable it, if the library has been | |
77 | // linked into the program | |
78 | #include <pthread.h> | |
bf1ec4d2 | 79 | #if defined(__linux__) |
7460295f | 80 | extern int pthread_once(pthread_once_t *, void (*)(void))__attribute__((weak)); |
bf1ec4d2 | 81 | #endif |
7460295f MG |
82 | extern int pthread_sigmask(int, const sigset_t *, sigset_t *) |
83 | __attribute__((weak)); | |
84 | ||
85 | #endif | |
86 | ||
bf1ec4d2 | 87 | #if defined(HAVE_DLOPEN) |
7460295f | 88 | // SSL support is optional. Only enable it, if the library can be loaded. |
03cd76e1 MG |
89 | long (*BIO_ctrl)(BIO *, int, long, void *); |
90 | BIO_METHOD * (*BIO_f_buffer)(void); | |
91 | void (*BIO_free_all)(BIO *); | |
92 | BIO * (*BIO_new)(BIO_METHOD *); | |
93 | BIO * (*BIO_new_socket)(int, int); | |
94 | BIO * (*BIO_pop)(BIO *); | |
95 | BIO * (*BIO_push)(BIO *, BIO *); | |
96 | void (*ERR_clear_error)(void); | |
97 | void (*ERR_clear_error)(void); | |
98 | unsigned long (*ERR_peek_error)(void); | |
99 | unsigned long (*ERR_peek_error)(void); | |
100 | long (*SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void)); | |
101 | int (*SSL_CTX_check_private_key)(const SSL_CTX *); | |
102 | long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *); | |
103 | void (*SSL_CTX_free)(SSL_CTX *); | |
104 | SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *); | |
105 | int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int); | |
dc6575f2 MG |
106 | int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *, |
107 | const unsigned char *, long); | |
03cd76e1 | 108 | int (*SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int); |
dc6575f2 MG |
109 | int (*SSL_CTX_use_certificate_ASN1)(SSL_CTX *, long, |
110 | const unsigned char *); | |
03cd76e1 MG |
111 | long (*SSL_ctrl)(SSL *, int, long, void *); |
112 | void (*SSL_free)(SSL *); | |
113 | int (*SSL_get_error)(const SSL *, int); | |
114 | void * (*SSL_get_ex_data)(const SSL *, int); | |
115 | BIO * (*SSL_get_rbio)(const SSL *); | |
116 | const char * (*SSL_get_servername)(const SSL *, int); | |
117 | BIO * (*SSL_get_wbio)(const SSL *); | |
118 | int (*SSL_library_init)(void); | |
119 | SSL * (*SSL_new)(SSL_CTX *); | |
120 | int (*SSL_read)(SSL *, void *, int); | |
121 | SSL_CTX * (*SSL_set_SSL_CTX)(SSL *, SSL_CTX *); | |
122 | void (*SSL_set_accept_state)(SSL *); | |
123 | void (*SSL_set_bio)(SSL *, BIO *, BIO *); | |
124 | int (*SSL_set_ex_data)(SSL *, int, void *); | |
125 | int (*SSL_shutdown)(SSL *); | |
126 | int (*SSL_write)(SSL *, const void *, int); | |
127 | SSL_METHOD * (*SSLv23_server_method)(void); | |
ad24d9a9 MG |
128 | X509 * (*d2i_X509)(X509 **px, const unsigned char **in, int len); |
129 | void (*X509_free)(X509 *a); | |
bf1ec4d2 | 130 | #endif |
7460295f MG |
131 | |
132 | static void sslDestroyCachedContext(void *ssl_, char *context_) { | |
133 | struct SSLSupport *ssl = (struct SSLSupport *)ssl_; | |
134 | SSL_CTX *context = (SSL_CTX *)context_; | |
03cd76e1 | 135 | #if defined(HAVE_OPENSSL) |
7460295f MG |
136 | if (context != ssl->sslContext) { |
137 | SSL_CTX_free(context); | |
138 | } | |
03cd76e1 MG |
139 | #else |
140 | check(!context); | |
141 | check(!ssl->sslContext); | |
142 | #endif | |
7460295f MG |
143 | } |
144 | ||
145 | struct SSLSupport *newSSL(void) { | |
146 | struct SSLSupport *ssl; | |
147 | check(ssl = malloc(sizeof(struct SSLSupport))); | |
148 | initSSL(ssl); | |
149 | return ssl; | |
150 | } | |
151 | ||
152 | void initSSL(struct SSLSupport *ssl) { | |
153 | ssl->enabled = serverSupportsSSL(); | |
154 | ssl->sslContext = NULL; | |
155 | ssl->sniCertificatePattern = NULL; | |
156 | ssl->generateMissing = 0; | |
157 | initTrie(&ssl->sniContexts, sslDestroyCachedContext, ssl); | |
158 | } | |
159 | ||
160 | void destroySSL(struct SSLSupport *ssl) { | |
161 | if (ssl) { | |
162 | free(ssl->sniCertificatePattern); | |
163 | destroyTrie(&ssl->sniContexts); | |
03cd76e1 | 164 | #if defined(HAVE_OPENSSL) |
7460295f MG |
165 | if (ssl->sslContext) { |
166 | dcheck(!ERR_peek_error()); | |
167 | SSL_CTX_free(ssl->sslContext); | |
168 | } | |
03cd76e1 MG |
169 | #else |
170 | check(!ssl->sslContext); | |
171 | #endif | |
7460295f MG |
172 | } |
173 | } | |
174 | ||
175 | void deleteSSL(struct SSLSupport *ssl) { | |
176 | destroySSL(ssl); | |
177 | free(ssl); | |
178 | } | |
179 | ||
bf1ec4d2 | 180 | #if defined(HAVE_OPENSSL) && defined(HAVE_DLOPEN) |
10d0a6b0 MG |
181 | static int maybeLoadCrypto(void) { |
182 | // Some operating systems cannot automatically load dependent dynamic | |
183 | // libraries. As libssl.so can depend on libcrypto.so, we try to load | |
184 | // it, iff we haven't tried loading it before and iff libssl.so does not | |
185 | // work by itself. | |
186 | static int crypto; | |
187 | if (!crypto++) { | |
188 | #ifdef RTLD_NOLOAD | |
189 | if (dlopen("libcrypto.so", RTLD_LAZY|RTLD_GLOBAL|RTLD_NOLOAD)) | |
190 | return 1; | |
191 | else | |
192 | #endif | |
193 | if (dlopen("libcrypto.so", RTLD_LAZY|RTLD_GLOBAL)) | |
194 | return 1; | |
195 | } | |
196 | return 0; | |
197 | } | |
198 | ||
7460295f | 199 | static void *loadSymbol(const char *lib, const char *fn) { |
10d0a6b0 MG |
200 | int err = NOINTR(dup(2)); |
201 | if (err > 2) { | |
202 | int null = NOINTR(open("/dev/null", O_WRONLY)); | |
203 | if (null >= 0) { | |
204 | NOINTR(dup2(null, 2)); | |
205 | NOINTR(close(null)); | |
206 | } | |
207 | } | |
7460295f MG |
208 | void *dl = RTLD_DEFAULT; |
209 | void *rc = dlsym(dl, fn); | |
210 | if (!rc) { | |
10d0a6b0 | 211 | for (int i = 0; i < 2; i++) { |
47e62a9c | 212 | #ifdef RTLD_NOLOAD |
10d0a6b0 | 213 | dl = dlopen(lib, RTLD_LAZY|RTLD_GLOBAL|RTLD_NOLOAD); |
47e62a9c | 214 | #else |
10d0a6b0 | 215 | dl = NULL; |
47e62a9c | 216 | #endif |
10d0a6b0 MG |
217 | if (dl == NULL) { |
218 | dl = dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); | |
219 | } | |
220 | if (dl != NULL || !maybeLoadCrypto()) { | |
221 | break; | |
222 | } | |
7460295f MG |
223 | } |
224 | if (dl != NULL) { | |
10d0a6b0 MG |
225 | rc = dlsym(RTLD_DEFAULT, fn); |
226 | if (rc == NULL && maybeLoadCrypto()) { | |
227 | rc = dlsym(RTLD_DEFAULT, fn); | |
228 | } | |
7460295f MG |
229 | } |
230 | } | |
10d0a6b0 MG |
231 | if (err > 2) { |
232 | NOINTR(dup2(err, 2)); | |
233 | } | |
234 | NOINTR(close(err)); | |
7460295f MG |
235 | return rc; |
236 | } | |
237 | ||
238 | static void loadSSL(void) { | |
239 | check(!SSL_library_init); | |
240 | struct { | |
88b579e2 MG |
241 | union { |
242 | void *avoid_gcc_warning_about_type_punning; | |
243 | void **var; | |
244 | }; | |
7460295f MG |
245 | const char *fn; |
246 | } symbols[] = { | |
03cd76e1 MG |
247 | { { &BIO_ctrl }, "BIO_ctrl" }, |
248 | { { &BIO_f_buffer }, "BIO_f_buffer" }, | |
249 | { { &BIO_free_all }, "BIO_free_all" }, | |
250 | { { &BIO_new }, "BIO_new" }, | |
251 | { { &BIO_new_socket }, "BIO_new_socket" }, | |
252 | { { &BIO_pop }, "BIO_pop" }, | |
253 | { { &BIO_push }, "BIO_push" }, | |
254 | { { &ERR_clear_error }, "ERR_clear_error" }, | |
255 | { { &ERR_clear_error }, "ERR_clear_error" }, | |
256 | { { &ERR_peek_error }, "ERR_peek_error" }, | |
257 | { { &ERR_peek_error }, "ERR_peek_error" }, | |
258 | { { &SSL_CTX_callback_ctrl }, "SSL_CTX_callback_ctrl" }, | |
259 | { { &SSL_CTX_check_private_key }, "SSL_CTX_check_private_key" }, | |
260 | { { &SSL_CTX_ctrl }, "SSL_CTX_ctrl" }, | |
261 | { { &SSL_CTX_free }, "SSL_CTX_free" }, | |
262 | { { &SSL_CTX_new }, "SSL_CTX_new" }, | |
263 | { { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" }, | |
dc6575f2 | 264 | { { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" }, |
03cd76e1 | 265 | { { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"}, |
dc6575f2 | 266 | { { &SSL_CTX_use_certificate_ASN1 },"SSL_CTX_use_certificate_ASN1"}, |
03cd76e1 MG |
267 | { { &SSL_ctrl }, "SSL_ctrl" }, |
268 | { { &SSL_free }, "SSL_free" }, | |
269 | { { &SSL_get_error }, "SSL_get_error" }, | |
270 | { { &SSL_get_ex_data }, "SSL_get_ex_data" }, | |
271 | { { &SSL_get_rbio }, "SSL_get_rbio" }, | |
d04f7ca7 | 272 | #ifdef HAVE_TLSEXT |
03cd76e1 | 273 | { { &SSL_get_servername }, "SSL_get_servername" }, |
a42d111c | 274 | #endif |
03cd76e1 MG |
275 | { { &SSL_get_wbio }, "SSL_get_wbio" }, |
276 | { { &SSL_library_init }, "SSL_library_init" }, | |
277 | { { &SSL_new }, "SSL_new" }, | |
278 | { { &SSL_read }, "SSL_read" }, | |
d04f7ca7 | 279 | #ifdef HAVE_TLSEXT |
03cd76e1 | 280 | { { &SSL_set_SSL_CTX }, "SSL_set_SSL_CTX" }, |
a42d111c | 281 | #endif |
03cd76e1 MG |
282 | { { &SSL_set_accept_state }, "SSL_set_accept_state" }, |
283 | { { &SSL_set_bio }, "SSL_set_bio" }, | |
284 | { { &SSL_set_ex_data }, "SSL_set_ex_data" }, | |
285 | { { &SSL_shutdown }, "SSL_shutdown" }, | |
286 | { { &SSL_write }, "SSL_write" }, | |
ad24d9a9 MG |
287 | { { &SSLv23_server_method }, "SSLv23_server_method" }, |
288 | { { &d2i_X509 }, "d2i_X509" }, | |
289 | { { &X509_free }, "X509_free" } | |
7460295f MG |
290 | }; |
291 | for (int i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) { | |
292 | if (!(*symbols[i].var = loadSymbol("libssl.so", symbols[i].fn))) { | |
293 | debug("Failed to load SSL support. Could not find \"%s\"", | |
294 | symbols[i].fn); | |
295 | for (int j = 0; j < sizeof(symbols)/sizeof(symbols[0]); j++) { | |
296 | *symbols[j].var = NULL; | |
297 | } | |
298 | return; | |
299 | } | |
300 | } | |
301 | SSL_library_init(); | |
302 | dcheck(!ERR_peek_error()); | |
303 | debug("Loaded SSL suppport"); | |
304 | } | |
305 | #endif | |
306 | ||
307 | int serverSupportsSSL(void) { | |
bf1ec4d2 MG |
308 | #if defined(HAVE_OPENSSL) && !defined(HAVE_DLOPEN) |
309 | return SSL_library_init(); | |
310 | #else | |
7460295f MG |
311 | #if defined(HAVE_OPENSSL) |
312 | // We want to call loadSSL() exactly once. For single-threaded applications, | |
313 | // this is straight-forward. For threaded applications, we need to call | |
314 | // pthread_once(), instead. We perform run-time checks for whether we are | |
315 | // single- or multi-threaded, so that the same code can be used. | |
a3876a41 | 316 | // This currently only works on Linux. |
9d758d39 | 317 | #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__) |
7460295f MG |
318 | if (!!&pthread_once) { |
319 | static pthread_once_t once = PTHREAD_ONCE_INIT; | |
320 | pthread_once(&once, loadSSL); | |
321 | } else | |
322 | #endif | |
323 | { | |
324 | static int initialized; | |
325 | if (!initialized) { | |
326 | initialized = 1; | |
327 | loadSSL(); | |
328 | } | |
329 | } | |
330 | return !!SSL_library_init; | |
331 | #else | |
332 | return 0; | |
333 | #endif | |
bf1ec4d2 | 334 | #endif |
7460295f MG |
335 | } |
336 | ||
bdd01e84 | 337 | #if defined(HAVE_OPENSSL) |
39e8401e MG |
338 | static void sslGenerateCertificate(const char *certificate, |
339 | const char *serverName) { | |
7460295f MG |
340 | debug("Auto-generating missing certificate \"%s\" for \"%s\"", |
341 | certificate, serverName); | |
342 | char *cmd = stringPrintf(NULL, | |
343 | "set -e; " | |
344 | "exec 2>/dev/null </dev/null; " | |
345 | "umask 0377; " | |
10d0a6b0 | 346 | "PATH=/usr/bin:/usr/sbin " |
7460295f MG |
347 | "openssl req -x509 -nodes -days 7300 -newkey rsa:1024 -keyout /dev/stdout " |
348 | "-out /dev/stdout -subj '/CN=%s/' | cat>'%s'", | |
349 | serverName, certificate); | |
350 | if (system(cmd)) { | |
351 | warn("Failed to generate self-signed certificate \"%s\"", certificate); | |
352 | } | |
353 | free(cmd); | |
354 | } | |
ad24d9a9 MG |
355 | |
356 | static const unsigned char *sslSecureReadASCIIFileToMem(int fd) { | |
357 | size_t inc = 16384; | |
358 | size_t bufSize = inc; | |
359 | size_t len = 0; | |
360 | unsigned char *buf; | |
361 | check((buf = malloc(bufSize)) != NULL); | |
362 | for (;;) { | |
363 | check(len < bufSize - 1); | |
364 | size_t readLen = bufSize - len - 1; | |
365 | ssize_t bytesRead = NOINTR(read(fd, buf + len, readLen)); | |
366 | if (bytesRead > 0) { | |
367 | len += bytesRead; | |
368 | } | |
369 | if (bytesRead != readLen) { | |
370 | break; | |
371 | } | |
372 | ||
373 | // Instead of calling realloc(), allocate a new buffer, copy the data, | |
374 | // and then clear the old buffer. This way, we are not accidentally | |
375 | // leaving key material in memory. | |
376 | unsigned char *newBuf; | |
377 | check((newBuf = malloc(bufSize + inc)) != NULL); | |
378 | memcpy(newBuf, buf, len); | |
379 | memset(buf, 0, bufSize); | |
380 | free(buf); | |
381 | buf = newBuf; | |
382 | bufSize += inc; | |
383 | } | |
384 | check(len < bufSize); | |
385 | buf[len] = '\000'; | |
386 | return buf; | |
387 | } | |
388 | ||
389 | static const unsigned char *sslPEMtoASN1(const unsigned char *pem, | |
390 | const char *record, | |
391 | long *size, | |
392 | const unsigned char **eor) { | |
393 | if (eor) { | |
394 | *eor = NULL; | |
395 | } | |
396 | *size = 0; | |
397 | char *marker; | |
398 | check((marker = stringPrintf(NULL, "-----BEGIN %s-----",record))!=NULL); | |
399 | unsigned char *ptr = (unsigned char *)strstr((char *)pem, marker); | |
400 | if (!ptr) { | |
401 | free(marker); | |
402 | return NULL; | |
403 | } else { | |
404 | ptr += strlen(marker); | |
405 | } | |
406 | *marker = '\000'; | |
407 | check((marker = stringPrintf(marker, "-----END %s-----",record))!=NULL); | |
408 | unsigned char *end = (unsigned char *)strstr((char *)ptr, marker); | |
409 | if (eor) { | |
410 | *eor = end + strlen(marker); | |
411 | } | |
412 | free(marker); | |
413 | if (!end) { | |
414 | return NULL; | |
415 | } | |
416 | unsigned char *ret; | |
417 | size_t maxSize = (((end - ptr)*6)+7)/8; | |
418 | check((ret = malloc(maxSize)) != NULL); | |
419 | unsigned char *out = ret; | |
420 | unsigned bits = 0; | |
421 | int count = 0; | |
422 | while (ptr < end) { | |
423 | unsigned char ch = *ptr++; | |
424 | if (ch >= 'A' && ch <= 'Z') { | |
425 | ch -= 'A'; | |
426 | } else if (ch >= 'a' && ch <= 'z') { | |
427 | ch -= 'a' - 26; | |
428 | } else if (ch >= '0' && ch <= '9') { | |
429 | ch += 52 - '0'; | |
430 | } else if (ch == '+') { | |
431 | ch += 62 - '+'; | |
432 | } else if (ch == '/') { | |
433 | ch += 63 - '/'; | |
434 | } else if (ch == '=') { | |
435 | while (ptr < end) { | |
436 | if ((ch = *ptr++) != '=' && ch > ' ') { | |
437 | goto err; | |
438 | } | |
439 | } | |
440 | break; | |
441 | } else if (ch <= ' ') { | |
442 | continue; | |
443 | } else { | |
444 | err: | |
445 | free(ret); | |
446 | return NULL; | |
447 | } | |
448 | check(ch <= 63); | |
449 | check(count >= 0); | |
450 | check(count <= 6); | |
451 | bits = (bits << 6) | ch; | |
452 | count += 6; | |
453 | if (count >= 8) { | |
454 | *out++ = (bits >> (count -= 8)) & 0xFF; | |
455 | } | |
456 | } | |
457 | check(out - ret <= maxSize); | |
458 | *size = out - ret; | |
459 | return ret; | |
460 | } | |
461 | ||
462 | static int sslSetCertificateFromFd(SSL_CTX *context, int fd) { | |
463 | int rc = 0; | |
464 | check(serverSupportsSSL()); | |
465 | check(fd >= 0); | |
466 | const unsigned char *data = sslSecureReadASCIIFileToMem(fd); | |
467 | check(!NOINTR(close(fd))); | |
468 | long dataSize = (long)strlen((const char *)data); | |
469 | long certSize, rsaSize, dsaSize, ecSize; | |
470 | const unsigned char *record; | |
471 | const unsigned char *cert = sslPEMtoASN1(data, "CERTIFICATE", &certSize, | |
472 | &record); | |
473 | const unsigned char *rsa = sslPEMtoASN1(data, "RSA PRIVATE KEY",&rsaSize, | |
474 | NULL); | |
475 | const unsigned char *dsa = sslPEMtoASN1(data, "DSA PRIVATE KEY",&dsaSize, | |
476 | NULL); | |
477 | const unsigned char *ec = sslPEMtoASN1(data, "EC PRIVATE KEY", &ecSize, | |
478 | NULL); | |
479 | if (certSize && (rsaSize || dsaSize | |
480 | #ifdef EVP_PKEY_EC | |
481 | || ecSize | |
482 | #endif | |
483 | ) && | |
484 | SSL_CTX_use_certificate_ASN1(context, certSize, cert) && | |
485 | (!rsaSize || | |
486 | SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, context, rsa, rsaSize)) && | |
487 | (!dsaSize || | |
488 | SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_DSA, context, dsa, dsaSize)) | |
489 | #ifdef EVP_PKEY_EC | |
490 | && | |
491 | (!ecSize || | |
492 | SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC, context, ec, ecSize)) | |
493 | #endif | |
494 | ) { | |
495 | memset((char *)cert, 0, certSize); | |
496 | free((char *)cert); | |
497 | while (record) { | |
498 | cert = sslPEMtoASN1(record, "CERTIFICATE", &certSize, | |
499 | &record); | |
500 | if (cert) { | |
501 | X509 *x509; | |
502 | const unsigned char *c = cert; | |
503 | check(x509 = d2i_X509(NULL, &c, certSize)); | |
504 | memset((char *)cert, 0, certSize); | |
505 | free((char *)cert); | |
506 | if (!SSL_CTX_add_extra_chain_cert(context, x509)) { | |
507 | X509_free(x509); | |
508 | break; | |
509 | } | |
510 | } | |
511 | } | |
512 | if (!record && SSL_CTX_check_private_key(context)) { | |
513 | rc = 1; | |
514 | } | |
515 | dcheck(!ERR_peek_error()); | |
516 | ERR_clear_error(); | |
517 | } else { | |
518 | memset((char *)cert, 0, certSize); | |
519 | free((char *)cert); | |
520 | } | |
521 | memset((char *)data, 0, dataSize); | |
522 | free((char *)data); | |
523 | memset((char *)rsa, 0, rsaSize); | |
524 | free((char *)rsa); | |
525 | memset((char *)dsa, 0, dsaSize); | |
526 | free((char *)dsa); | |
527 | memset((char *)ec, 0, ecSize); | |
528 | free((char *)ec); | |
529 | return rc; | |
530 | } | |
531 | ||
532 | static int sslSetCertificateFromFile(SSL_CTX *context, | |
533 | const char *filename) { | |
534 | int fd = open(filename, O_RDONLY); | |
535 | if (fd < 0) { | |
536 | return -1; | |
537 | } | |
538 | int rc = sslSetCertificateFromFd(context, fd); | |
ad24d9a9 MG |
539 | return rc; |
540 | } | |
bdd01e84 | 541 | #endif |
7460295f | 542 | |
d04f7ca7 | 543 | #ifdef HAVE_TLSEXT |
7460295f MG |
544 | static int sslSNICallback(SSL *sslHndl, int *al, struct SSLSupport *ssl) { |
545 | check(!ERR_peek_error()); | |
546 | const char *name = SSL_get_servername(sslHndl, | |
547 | TLSEXT_NAMETYPE_host_name); | |
548 | if (name == NULL || !*name) { | |
549 | return SSL_TLSEXT_ERR_OK; | |
550 | } | |
551 | struct HttpConnection *http = | |
552 | (struct HttpConnection *)SSL_get_app_data(sslHndl); | |
553 | debug("Received SNI callback for virtual host \"%s\" from \"%s:%d\"", | |
554 | name, httpGetPeerName(http), httpGetPort(http)); | |
555 | char *serverName; | |
556 | check(serverName = malloc(strlen(name)+2)); | |
557 | serverName[0] = '-'; | |
558 | for (int i = 0;;) { | |
559 | char ch = name[i]; | |
560 | if (ch >= 'A' && ch <= 'Z') { | |
561 | ch |= 0x20; | |
562 | } else if (ch != '\000' && ch != '.' && ch != '-' && | |
563 | (ch < '0' ||(ch > '9' && ch < 'A') || (ch > 'Z' && | |
564 | ch < 'a')|| ch > 'z')) { | |
565 | i++; | |
566 | continue; | |
567 | } | |
568 | serverName[++i] = ch; | |
569 | if (!ch) { | |
570 | break; | |
571 | } | |
572 | } | |
573 | if (!*serverName) { | |
574 | free(serverName); | |
575 | return SSL_TLSEXT_ERR_OK; | |
576 | } | |
577 | SSL_CTX *context = (SSL_CTX *)getFromTrie(&ssl->sniContexts, | |
578 | serverName+1, | |
579 | NULL); | |
580 | if (context == NULL) { | |
581 | check(context = SSL_CTX_new(SSLv23_server_method())); | |
582 | check(ssl->sniCertificatePattern); | |
9b850878 MG |
583 | char *certificate = stringPrintfUnchecked(NULL, |
584 | ssl->sniCertificatePattern, | |
585 | serverName); | |
ad24d9a9 | 586 | if (sslSetCertificateFromFile(context, certificate) < 0) { |
7460295f MG |
587 | if (ssl->generateMissing) { |
588 | sslGenerateCertificate(certificate, serverName + 1); | |
ad24d9a9 MG |
589 | |
590 | // No need to check the certificate. If we fail to set it, we will use | |
591 | // the default certificate, instead. | |
592 | sslSetCertificateFromFile(context, certificate); | |
7460295f | 593 | } else { |
7460295f MG |
594 | warn("Could not find matching certificate \"%s\" for \"%s\"", |
595 | certificate, serverName + 1); | |
596 | SSL_CTX_free(context); | |
597 | context = ssl->sslContext; | |
598 | } | |
599 | } | |
600 | ERR_clear_error(); | |
601 | free(certificate); | |
602 | addToTrie(&ssl->sniContexts, serverName+1, (char *)context); | |
603 | } | |
604 | free(serverName); | |
605 | if (context != ssl->sslContext) { | |
606 | check(SSL_set_SSL_CTX(sslHndl, context) > 0); | |
607 | } | |
608 | check(!ERR_peek_error()); | |
609 | return SSL_TLSEXT_ERR_OK; | |
610 | } | |
611 | #endif | |
612 | ||
e027583c | 613 | #if defined(HAVE_OPENSSL) |
572ac014 MG |
614 | // This is a not-thread-safe replacement for gethostbyname_r() |
615 | #define gethostbyname_r x_gethostbyname_r | |
616 | static int gethostbyname_r(const char *name, struct hostent *ret, | |
617 | char *buf, size_t buflen, | |
618 | struct hostent **result, int *h_errnop) { | |
619 | if (result) { | |
620 | *result = NULL; | |
621 | } | |
622 | if (h_errnop) { | |
623 | *h_errnop = ERANGE; | |
624 | } | |
625 | if (!ret) { | |
626 | return -1; | |
627 | } | |
628 | struct hostent *he = gethostbyname(name); | |
629 | *ret = *he; | |
630 | if (result) { | |
631 | *result = ret; | |
632 | } | |
633 | if (h_errnop) { | |
634 | *h_errnop = h_errno; | |
635 | } | |
636 | return 0; | |
637 | } | |
638 | #endif | |
639 | ||
7460295f MG |
640 | void sslSetCertificate(struct SSLSupport *ssl, const char *filename, |
641 | int autoGenerateMissing) { | |
642 | #if defined(HAVE_OPENSSL) | |
643 | check(serverSupportsSSL()); | |
644 | ||
645 | char *defaultCertificate; | |
646 | check(defaultCertificate = strdup(filename)); | |
647 | char *ptr = strchr(defaultCertificate, '%'); | |
648 | if (ptr != NULL) { | |
649 | check(!strchr(ptr+1, '%')); | |
650 | check(ptr[1] == 's'); | |
651 | memmove(ptr, ptr + 2, strlen(ptr)-1); | |
652 | } | |
653 | ||
ad24d9a9 | 654 | // Try to set the default certificate. If necessary, (re-)generate it. |
7460295f MG |
655 | check(ssl->sslContext = SSL_CTX_new(SSLv23_server_method())); |
656 | if (autoGenerateMissing) { | |
ad24d9a9 | 657 | if (sslSetCertificateFromFile(ssl->sslContext, defaultCertificate) < 0) { |
7460295f MG |
658 | char hostname[256], buf[4096]; |
659 | check(!gethostname(hostname, sizeof(hostname))); | |
660 | struct hostent he_buf, *he; | |
661 | int h_err; | |
662 | if (gethostbyname_r(hostname, &he_buf, buf, sizeof(buf), | |
663 | &he, &h_err)) { | |
664 | sslGenerateCertificate(defaultCertificate, hostname); | |
665 | } else { | |
666 | sslGenerateCertificate(defaultCertificate, he->h_name); | |
667 | } | |
668 | } else { | |
669 | goto valid_certificate; | |
670 | } | |
671 | } | |
ad24d9a9 | 672 | if (sslSetCertificateFromFile(ssl->sslContext, defaultCertificate) < 0) { |
7460295f MG |
673 | fatal("Cannot read valid certificate from \"%s\". " |
674 | "Check file permissions and file format.", defaultCertificate); | |
675 | } | |
676 | valid_certificate: | |
677 | free(defaultCertificate); | |
678 | ||
ad24d9a9 MG |
679 | // Enable SNI support so that we can set a different certificate, if the |
680 | // client asked for it. | |
d04f7ca7 | 681 | #ifdef HAVE_TLSEXT |
7460295f MG |
682 | if (ptr != NULL) { |
683 | check(ssl->sniCertificatePattern = strdup(filename)); | |
684 | check(SSL_CTX_set_tlsext_servername_callback(ssl->sslContext, | |
685 | sslSNICallback)); | |
686 | check(SSL_CTX_set_tlsext_servername_arg(ssl->sslContext, ssl)); | |
687 | } | |
688 | #endif | |
689 | dcheck(!ERR_peek_error()); | |
690 | ERR_clear_error(); | |
691 | ||
692 | ssl->generateMissing = autoGenerateMissing; | |
693 | #endif | |
694 | } | |
695 | ||
ad24d9a9 MG |
696 | // Convert the file descriptor to a human-readable format. Attempts to |
697 | // retrieve the original file name where possible. | |
dc6575f2 | 698 | #ifdef HAVE_OPENSSL |
ad24d9a9 MG |
699 | static char *sslFdToFilename(int fd) { |
700 | char *proc, *buf; | |
701 | int len = 128; | |
702 | check(proc = stringPrintf(NULL, "/proc/self/fd/%d", fd)); | |
703 | check(buf = malloc(len)); | |
dc6575f2 | 704 | for (;;) { |
ad24d9a9 MG |
705 | ssize_t i; |
706 | if ((i = readlink(proc, buf + 1, len-3)) < 0) { | |
707 | free(proc); | |
708 | free(buf); | |
709 | check(buf = stringPrintf(NULL, "fd %d", fd)); | |
710 | return buf; | |
711 | } else if (i >= len-3) { | |
712 | len += 512; | |
713 | check(buf = realloc(buf, len)); | |
dc6575f2 | 714 | } else { |
ad24d9a9 MG |
715 | free(proc); |
716 | check(i >= 0 && i < len); | |
717 | buf[i+1] = '\000'; | |
718 | struct stat sb; | |
719 | if (!stat(buf + 1, &sb) && S_ISREG(sb.st_mode)) { | |
720 | *buf = '"'; | |
721 | buf[i + 1] = '"'; | |
722 | buf[i + 2] = '\000'; | |
723 | return buf; | |
724 | } else { | |
725 | free(buf); | |
726 | check(buf = stringPrintf(NULL, "fd %d", fd)); | |
727 | return buf; | |
728 | } | |
dc6575f2 MG |
729 | } |
730 | } | |
dc6575f2 MG |
731 | } |
732 | #endif | |
733 | ||
734 | void sslSetCertificateFd(struct SSLSupport *ssl, int fd) { | |
735 | #ifdef HAVE_OPENSSL | |
ad24d9a9 | 736 | check(ssl->sslContext = SSL_CTX_new(SSLv23_server_method())); |
48f25965 | 737 | char *filename = sslFdToFilename(fd); |
ad24d9a9 MG |
738 | if (!sslSetCertificateFromFd(ssl->sslContext, fd)) { |
739 | fatal("Cannot read valid certificate from %s. Check file format.", | |
48f25965 | 740 | filename); |
dc6575f2 | 741 | } |
48f25965 | 742 | free(filename); |
ad24d9a9 | 743 | ssl->generateMissing = 0; |
dc6575f2 MG |
744 | #endif |
745 | } | |
746 | ||
7460295f MG |
747 | int sslEnable(struct SSLSupport *ssl, int enabled) { |
748 | int old = ssl->enabled; | |
749 | ssl->enabled = enabled; | |
750 | return old; | |
751 | } | |
752 | ||
753 | void sslBlockSigPipe(void) { | |
754 | sigset_t set; | |
755 | sigemptyset(&set); | |
756 | sigaddset(&set, SIGPIPE); | |
9d758d39 | 757 | #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__) |
c593cf68 MG |
758 | if (&pthread_sigmask) { |
759 | dcheck(!pthread_sigmask(SIG_BLOCK, &set, NULL)); | |
9d758d39 MG |
760 | } else |
761 | #endif | |
762 | { | |
c593cf68 MG |
763 | dcheck(!sigprocmask(SIG_BLOCK, &set, NULL)); |
764 | } | |
7460295f MG |
765 | } |
766 | ||
572ac014 MG |
767 | #ifndef HAVE_SIGWAIT |
768 | // This is a non-thread-safe replacement for sigwait() | |
769 | static int dummysignalno; | |
770 | static void dummysignal(int signo) { | |
771 | dummysignalno = signo; | |
772 | } | |
773 | ||
774 | #define sigwait x_sigwait | |
775 | static int sigwait(const sigset_t *set, int *sig) { | |
776 | sigset_t mask, old_mask; | |
777 | sigfillset(&mask); | |
9d758d39 | 778 | #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__) |
572ac014 MG |
779 | if (&pthread_sigmask) { |
780 | dcheck(!pthread_sigmask(SIG_BLOCK, &mask, &old_mask)); | |
9d758d39 MG |
781 | } else |
782 | #endif | |
783 | { | |
572ac014 MG |
784 | dcheck(!sigprocmask(SIG_BLOCK, &mask, &old_mask)); |
785 | } | |
786 | #ifndef NSIG | |
787 | #define NSIG 32 | |
788 | #endif | |
789 | struct sigaction sa[NSIG]; | |
790 | memset(sa, 0, sizeof(sa)); | |
791 | sa->sa_handler = dummysignal; | |
792 | for (int i = 1; i <= NSIG; i++) { | |
793 | if (sigismember(set, i)) { | |
794 | sigdelset(&mask, i); | |
795 | sigaction(i, sa, sa + i); | |
796 | } | |
797 | } | |
798 | dummysignalno = -1; | |
799 | sigsuspend(&mask); | |
9d758d39 | 800 | #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__) |
572ac014 MG |
801 | if (&pthread_sigmask) { |
802 | dcheck(!pthread_sigmask(SIG_SETMASK, &old_mask, NULL)); | |
9d758d39 MG |
803 | } else |
804 | #endif | |
805 | { | |
572ac014 MG |
806 | dcheck(!sigprocmask(SIG_BLOCK, &old_mask, NULL)); |
807 | } | |
808 | return dummysignalno; | |
809 | } | |
810 | #endif | |
811 | ||
7460295f MG |
812 | int sslUnblockSigPipe(void) { |
813 | int signum = 0; | |
814 | sigset_t set; | |
815 | check(!sigpending(&set)); | |
816 | if (sigismember(&set, SIGPIPE)) { | |
817 | sigwait(&set, &signum); | |
818 | } | |
819 | sigemptyset(&set); | |
820 | sigaddset(&set, SIGPIPE); | |
9d758d39 | 821 | #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__) |
c593cf68 MG |
822 | if (&pthread_sigmask) { |
823 | dcheck(!pthread_sigmask(SIG_UNBLOCK, &set, NULL)); | |
9d758d39 MG |
824 | } else |
825 | #endif | |
826 | { | |
c593cf68 MG |
827 | dcheck(!sigprocmask(SIG_UNBLOCK, &set, NULL)); |
828 | } | |
7460295f MG |
829 | return signum; |
830 | } | |
831 | ||
832 | int sslPromoteToSSL(struct SSLSupport *ssl, SSL **sslHndl, int fd, | |
833 | const char *buf, int len) { | |
834 | #if defined(HAVE_OPENSSL) | |
835 | sslBlockSigPipe(); | |
836 | int rc = 0; | |
837 | check(!*sslHndl); | |
838 | dcheck(!ERR_peek_error()); | |
839 | dcheck(*sslHndl = SSL_new(ssl->sslContext)); | |
840 | if (*sslHndl == NULL) { | |
841 | ERR_clear_error(); | |
842 | errno = EINVAL; | |
843 | rc = -1; | |
844 | } else { | |
845 | SSL_set_mode(*sslHndl, SSL_MODE_ENABLE_PARTIAL_WRITE); | |
846 | BIO *writeBIO = BIO_new_socket(fd, 0); | |
847 | BIO *readBIO = writeBIO; | |
848 | if (len > 0) { | |
849 | readBIO = BIO_new(BIO_f_buffer()); | |
850 | BIO_push(readBIO, writeBIO); | |
851 | check(BIO_set_buffer_read_data(readBIO, (char *)buf, len)); | |
852 | } | |
853 | SSL_set_bio(*sslHndl, readBIO, writeBIO); | |
854 | SSL_set_accept_state(*sslHndl); | |
855 | dcheck(!ERR_peek_error()); | |
856 | } | |
857 | sslUnblockSigPipe(); | |
858 | return rc; | |
859 | #else | |
860 | errno = EINVAL; | |
861 | return -1; | |
862 | #endif | |
863 | } | |
864 | ||
865 | void sslFreeHndl(SSL **sslHndl) { | |
866 | #if defined(HAVE_OPENSSL) | |
867 | if (*sslHndl) { | |
868 | // OpenSSL does not always correctly perform reference counting for stacked | |
869 | // BIOs. This is particularly a problem if an SSL connection has two | |
870 | // different BIOs for the read and the write end, with one being a stacked | |
871 | // derivative of the other. Unfortunately, this is exactly the scenario | |
872 | // that we set up. | |
873 | // As a work-around, we un-stack the BIOs prior to freeing the SSL | |
874 | // connection. | |
875 | ERR_clear_error(); | |
876 | BIO *writeBIO, *readBIO; | |
877 | check(writeBIO = SSL_get_wbio(*sslHndl)); | |
878 | check(readBIO = SSL_get_rbio(*sslHndl)); | |
879 | if (writeBIO != readBIO) { | |
880 | if (readBIO->next_bio == writeBIO) { | |
881 | // OK, that's exactly the bug we are looking for. We know how to | |
882 | // fix it. | |
883 | check(BIO_pop(readBIO) == writeBIO); | |
884 | check(readBIO->references == 1); | |
885 | check(writeBIO->references == 1); | |
886 | check(!readBIO->next_bio); | |
887 | check(!writeBIO->prev_bio); | |
888 | } else if (readBIO->next_bio == writeBIO->next_bio && | |
889 | writeBIO->next_bio->prev_bio == writeBIO) { | |
890 | // Things get even more confused, if the SSL handshake is aborted | |
891 | // prematurely. | |
892 | // OpenSSL appears to internally stack a BIO onto the read end that | |
893 | // does not get removed afterwards. We end up with the original | |
894 | // socket BIO having two different BIOs prepended to it (one for | |
895 | // reading and one for writing). In this case, not only is the | |
896 | // reference count wrong, but the chain of next_bio/prev_bio pairs | |
897 | // is corrupted, too. | |
898 | BIO *sockBIO; | |
899 | check(sockBIO = BIO_pop(readBIO)); | |
900 | check(sockBIO == BIO_pop(writeBIO)); | |
901 | check(readBIO->references == 1); | |
902 | check(writeBIO->references == 1); | |
903 | check(sockBIO->references == 1); | |
904 | check(!readBIO->next_bio); | |
905 | check(!writeBIO->next_bio); | |
906 | check(!sockBIO->prev_bio); | |
907 | BIO_free_all(sockBIO); | |
908 | } else { | |
909 | // We do not know, how to fix this situation. Something must have | |
910 | // changed in the OpenSSL internals. Either, this is a new bug, or | |
911 | // somebody fixed the code in a way that we did not anticipate. | |
912 | fatal("Unexpected corruption of OpenSSL data structures"); | |
913 | } | |
914 | } | |
915 | SSL_free(*sslHndl); | |
916 | dcheck(!ERR_peek_error()); | |
917 | } | |
918 | #endif | |
919 | *sslHndl = NULL; | |
920 | } |