1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
/** SSL Context wrapper
20
* @version $Revision: 607875 $, $Date: 2008-01-01 18:33:12 +0100 (Tue, 01 Jan 2008) $
25
#include "apr_file_io.h"
26
#include "apr_thread_mutex.h"
30
#include "ssl_private.h"
32
static apr_status_t ssl_context_cleanup(void *data)
34
tcn_ssl_ctxt_t *c = (tcn_ssl_ctxt_t *)data;
38
X509_STORE_free(c->crl);
43
for (i = 0; i < SSL_AIDX_MAX; i++) {
45
X509_free(c->certs[i]);
49
EVP_PKEY_free(c->keys[i]);
54
SSL_BIO_close(c->bio_is);
58
SSL_BIO_close(c->bio_os);
65
/* Initialize server context */
66
TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
67
jint protocol, jint mode)
69
apr_pool_t *p = J2P(pool, apr_pool_t *);
70
tcn_ssl_ctxt_t *c = NULL;
75
case SSL_PROTOCOL_SSLV2:
76
case SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_TLSV1:
77
if (mode == SSL_MODE_CLIENT)
78
ctx = SSL_CTX_new(SSLv2_client_method());
79
else if (mode == SSL_MODE_SERVER)
80
ctx = SSL_CTX_new(SSLv2_server_method());
82
ctx = SSL_CTX_new(SSLv2_method());
84
case SSL_PROTOCOL_SSLV3:
85
case SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1:
86
if (mode == SSL_MODE_CLIENT)
87
ctx = SSL_CTX_new(SSLv3_client_method());
88
else if (mode == SSL_MODE_SERVER)
89
ctx = SSL_CTX_new(SSLv3_server_method());
91
ctx = SSL_CTX_new(SSLv3_method());
93
case SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_SSLV3:
94
case SSL_PROTOCOL_ALL:
95
if (mode == SSL_MODE_CLIENT)
96
ctx = SSL_CTX_new(SSLv23_client_method());
97
else if (mode == SSL_MODE_SERVER)
98
ctx = SSL_CTX_new(SSLv23_server_method());
100
ctx = SSL_CTX_new(SSLv23_method());
102
case SSL_PROTOCOL_TLSV1:
103
if (mode == SSL_MODE_CLIENT)
104
ctx = SSL_CTX_new(TLSv1_client_method());
105
else if (mode == SSL_MODE_SERVER)
106
ctx = SSL_CTX_new(TLSv1_server_method());
108
ctx = SSL_CTX_new(TLSv1_method());
112
tcn_ThrowException(e, "Invalid Server SSL Protocol");
115
if ((c = apr_pcalloc(p, sizeof(tcn_ssl_ctxt_t))) == NULL) {
116
tcn_ThrowAPRException(e, apr_get_os_error());
120
c->protocol = protocol;
124
c->bio_os = BIO_new(BIO_s_file());
125
if (c->bio_os != NULL)
126
BIO_set_fp(c->bio_os, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
127
SSL_CTX_set_options(c->ctx, SSL_OP_ALL);
128
if (!(protocol & SSL_PROTOCOL_SSLV2))
129
SSL_CTX_set_options(c->ctx, SSL_OP_NO_SSLv2);
130
if (!(protocol & SSL_PROTOCOL_SSLV3))
131
SSL_CTX_set_options(c->ctx, SSL_OP_NO_SSLv3);
132
if (!(protocol & SSL_PROTOCOL_TLSV1))
133
SSL_CTX_set_options(c->ctx, SSL_OP_NO_TLSv1);
135
* Configure additional context ingredients
137
SSL_CTX_set_options(c->ctx, SSL_OP_SINGLE_DH_USE);
139
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
141
* Disallow a session from being resumed during a renegotiation,
142
* so that an acceptable cipher suite can be negotiated.
144
SSL_CTX_set_options(c->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
146
/* Default session context id and cache size */
147
SSL_CTX_sess_set_cache_size(c->ctx, SSL_DEFAULT_CACHE_SIZE);
148
MD5((const unsigned char *)SSL_DEFAULT_VHOST_NAME,
149
(unsigned long)(sizeof(SSL_DEFAULT_VHOST_NAME) - 1),
150
&(c->context_id[0]));
152
SSL_CTX_set_tmp_rsa_callback(c->ctx, SSL_callback_tmp_RSA);
153
SSL_CTX_set_tmp_dh_callback(c->ctx, SSL_callback_tmp_DH);
155
/* Set default Certificate verification level
156
* and depth for the Client Authentication
159
c->verify_mode = SSL_CVERIFY_UNSET;
160
c->shutdown_type = SSL_SHUTDOWN_TYPE_UNSET;
162
/* Set default password callback */
163
SSL_CTX_set_default_passwd_cb(c->ctx, (pem_password_cb *)SSL_password_callback);
164
SSL_CTX_set_default_passwd_cb_userdata(c->ctx, (void *)(&tcn_password_callback));
166
* Let us cleanup the ssl context when the pool is destroyed
168
apr_pool_cleanup_register(p, (const void *)c,
170
apr_pool_cleanup_null);
177
TCN_IMPLEMENT_CALL(jint, SSLContext, free)(TCN_STDARGS, jlong ctx)
179
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
180
UNREFERENCED_STDARGS;
181
TCN_ASSERT(ctx != 0);
182
/* Run and destroy the cleanup callback */
183
return apr_pool_cleanup_run(c->pool, c, ssl_context_cleanup);
186
TCN_IMPLEMENT_CALL(void, SSLContext, setContextId)(TCN_STDARGS, jlong ctx,
189
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
190
TCN_ALLOC_CSTRING(id);
192
TCN_ASSERT(ctx != 0);
195
MD5((const unsigned char *)J2S(id),
196
(unsigned long)strlen(J2S(id)),
197
&(c->context_id[0]));
199
TCN_FREE_CSTRING(id);
202
TCN_IMPLEMENT_CALL(void, SSLContext, setBIO)(TCN_STDARGS, jlong ctx,
205
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
206
BIO *bio_handle = J2P(bio, BIO *);
208
UNREFERENCED_STDARGS;
209
TCN_ASSERT(ctx != 0);
211
if (c->bio_os && c->bio_os != bio_handle)
212
SSL_BIO_close(c->bio_os);
213
c->bio_os = bio_handle;
216
if (c->bio_is && c->bio_is != bio_handle)
217
SSL_BIO_close(c->bio_is);
218
c->bio_is = bio_handle;
222
SSL_BIO_doref(bio_handle);
225
TCN_IMPLEMENT_CALL(void, SSLContext, setOptions)(TCN_STDARGS, jlong ctx,
228
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
230
UNREFERENCED_STDARGS;
231
TCN_ASSERT(ctx != 0);
232
SSL_CTX_set_options(c->ctx, opt);
235
TCN_IMPLEMENT_CALL(void, SSLContext, setQuietShutdown)(TCN_STDARGS, jlong ctx,
238
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
240
UNREFERENCED_STDARGS;
241
TCN_ASSERT(ctx != 0);
242
SSL_CTX_set_quiet_shutdown(c->ctx, mode ? 1 : 0);
245
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
248
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
249
TCN_ALLOC_CSTRING(ciphers);
250
jboolean rv = JNI_TRUE;
253
TCN_ASSERT(ctx != 0);
257
if (!SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers))) {
259
ERR_error_string(ERR_get_error(), err);
260
tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
263
TCN_FREE_CSTRING(ciphers);
267
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCARevocation)(TCN_STDARGS, jlong ctx,
271
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
272
TCN_ALLOC_CSTRING(file);
273
TCN_ALLOC_CSTRING(path);
274
jboolean rv = JNI_FALSE;
279
TCN_ASSERT(ctx != 0);
280
if (J2S(file) == NULL && J2S(path) == NULL)
284
if ((c->crl = X509_STORE_new()) == NULL)
288
lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_file());
289
if (lookup == NULL) {
290
ERR_error_string(ERR_get_error(), err);
291
X509_STORE_free(c->crl);
293
tcn_Throw(e, "Lookup failed for file %s (%s)", J2S(file), err);
296
X509_LOOKUP_load_file(lookup, J2S(file), X509_FILETYPE_PEM);
299
lookup = X509_STORE_add_lookup(c->crl, X509_LOOKUP_hash_dir());
300
if (lookup == NULL) {
301
ERR_error_string(ERR_get_error(), err);
302
X509_STORE_free(c->crl);
304
tcn_Throw(e, "Lookup failed for path %s (%s)", J2S(file), err);
307
X509_LOOKUP_add_dir(lookup, J2S(path), X509_FILETYPE_PEM);
311
TCN_FREE_CSTRING(file);
312
TCN_FREE_CSTRING(path);
316
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainFile)(TCN_STDARGS, jlong ctx,
320
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
321
jboolean rv = JNI_FALSE;
322
TCN_ALLOC_CSTRING(file);
325
TCN_ASSERT(ctx != 0);
328
if (SSL_CTX_use_certificate_chain(c->ctx, J2S(file), skipfirst) > 0)
330
TCN_FREE_CSTRING(file);
334
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCACertificate)(TCN_STDARGS,
339
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
340
jboolean rv = JNI_TRUE;
341
TCN_ALLOC_CSTRING(file);
342
TCN_ALLOC_CSTRING(path);
345
TCN_ASSERT(ctx != 0);
346
if (file == NULL && path == NULL)
350
* Configure Client Authentication details
352
if (!SSL_CTX_load_verify_locations(c->ctx,
353
J2S(file), J2S(path))) {
355
ERR_error_string(ERR_get_error(), err);
356
tcn_Throw(e, "Unable to configure locations "
357
"for client authentication (%s)", err);
361
c->store = SSL_CTX_get_cert_store(c->ctx);
363
STACK_OF(X509_NAME) *ca_certs;
365
ca_certs = SSL_CTX_get_client_CA_list(c->ctx);
366
if (ca_certs == NULL) {
367
SSL_load_client_CA_file(J2S(file));
368
if (ca_certs != NULL)
369
SSL_CTX_set_client_CA_list(c->ctx, (STACK *)ca_certs);
372
if (!SSL_add_file_cert_subjects_to_stack((STACK *)ca_certs, J2S(file)))
375
if (ca_certs == NULL && c->verify_mode == SSL_CVERIFY_REQUIRE) {
377
* Give a warning when no CAs were configured but client authentication
378
* should take place. This cannot work.
380
BIO_printf(c->bio_os,
381
"[WARN] Oops, you want to request client "
382
"authentication, but no CAs are known for "
387
TCN_FREE_CSTRING(file);
388
TCN_FREE_CSTRING(path);
392
TCN_IMPLEMENT_CALL(void, SSLContext, setShutdownType)(TCN_STDARGS, jlong ctx,
395
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
397
UNREFERENCED_STDARGS;
398
TCN_ASSERT(ctx != 0);
399
c->shutdown_type = type;
402
TCN_IMPLEMENT_CALL(void, SSLContext, setVerify)(TCN_STDARGS, jlong ctx,
403
jint level, jint depth)
405
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
406
int verify = SSL_VERIFY_NONE;
409
TCN_ASSERT(ctx != 0);
410
c->verify_mode = level;
412
if (c->verify_mode == SSL_CVERIFY_UNSET)
413
c->verify_mode = SSL_CVERIFY_NONE;
415
c->verify_depth = depth;
417
* Configure callbacks for SSL context
419
if (c->verify_mode == SSL_CVERIFY_REQUIRE)
420
verify |= SSL_VERIFY_PEER_STRICT;
421
if ((c->verify_mode == SSL_CVERIFY_OPTIONAL) ||
422
(c->verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
423
verify |= SSL_VERIFY_PEER;
425
if (SSL_CTX_set_default_verify_paths(c->ctx)) {
426
c->store = SSL_CTX_get_cert_store(c->ctx);
427
X509_STORE_set_flags(c->store, 0);
430
/* XXX: See if this is fatal */
434
SSL_CTX_set_verify(c->ctx, verify, SSL_callback_SSL_verify);
437
static EVP_PKEY *load_pem_key(tcn_ssl_ctxt_t *c, const char *file)
440
EVP_PKEY *key = NULL;
441
tcn_pass_cb_t *cb_data = c->cb_data;
444
if ((bio = BIO_new(BIO_s_file())) == NULL) {
447
if (BIO_read_filename(bio, file) <= 0) {
452
cb_data = &tcn_password_callback;
453
for (i = 0; i < 3; i++) {
454
key = PEM_read_bio_PrivateKey(bio, NULL,
455
(pem_password_cb *)SSL_password_callback,
459
cb_data->password[0] = '\0';
460
BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
466
static X509 *load_pem_cert(tcn_ssl_ctxt_t *c, const char *file)
470
tcn_pass_cb_t *cb_data = c->cb_data;
473
if ((bio = BIO_new(BIO_s_file())) == NULL) {
476
if (BIO_read_filename(bio, file) <= 0) {
480
for (i = 0; i < 3; i++) {
481
cert = PEM_read_bio_X509_AUX(bio, NULL,
482
(pem_password_cb *)SSL_password_callback,
486
cb_data->password[0] = '\0';
487
BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
493
TCN_IMPLEMENT_CALL(void, SSLContext, setRandom)(TCN_STDARGS, jlong ctx,
496
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
497
TCN_ALLOC_CSTRING(file);
499
TCN_ASSERT(ctx != 0);
502
c->rand_file = apr_pstrdup(c->pool, J2S(file));
503
TCN_FREE_CSTRING(file);
506
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
507
jstring cert, jstring key,
508
jstring password, jint idx)
510
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
511
jboolean rv = JNI_TRUE;
512
TCN_ALLOC_CSTRING(cert);
513
TCN_ALLOC_CSTRING(key);
514
TCN_ALLOC_CSTRING(password);
515
const char *key_file, *cert_file;
519
TCN_ASSERT(ctx != 0);
521
if (idx < 0 || idx >= SSL_AIDX_MAX) {
522
/* TODO: Throw something */
528
c->cb_data = &tcn_password_callback;
529
strncpy(c->cb_data->password, J2S(password), SSL_MAX_PASSWORD_LEN);
530
c->cb_data->password[SSL_MAX_PASSWORD_LEN-1] = '\0';
533
cert_file = J2S(cert);
535
key_file = cert_file;
537
tcn_Throw(e, "No Certificate file specified or invalid file format");
541
if ((c->keys[idx] = load_pem_key(c, key_file)) == NULL) {
542
ERR_error_string(ERR_get_error(), err);
543
tcn_Throw(e, "Unable to load certificate key %s (%s)",
548
if ((c->certs[idx] = load_pem_cert(c, cert_file)) == NULL) {
549
ERR_error_string(ERR_get_error(), err);
550
tcn_Throw(e, "Unable to load certificate %s (%s)",
555
if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
556
ERR_error_string(ERR_get_error(), err);
557
tcn_Throw(e, "Error setting certificate (%s)", err);
561
if (SSL_CTX_use_PrivateKey(c->ctx, c->keys[idx]) <= 0) {
562
ERR_error_string(ERR_get_error(), err);
563
tcn_Throw(e, "Error setting private key (%s)", err);
567
if (SSL_CTX_check_private_key(c->ctx) <= 0) {
568
ERR_error_string(ERR_get_error(), err);
569
tcn_Throw(e, "Private key does not match the certificate public key (%s)",
575
TCN_FREE_CSTRING(cert);
576
TCN_FREE_CSTRING(key);
577
TCN_FREE_CSTRING(password);
582
/* OpenSSL is not supported.
583
* Create empty stubs.
586
TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
587
jint protocol, jint mode)
589
UNREFERENCED_STDARGS;
591
UNREFERENCED(protocol);
596
TCN_IMPLEMENT_CALL(jint, SSLContext, free)(TCN_STDARGS, jlong ctx)
598
UNREFERENCED_STDARGS;
603
TCN_IMPLEMENT_CALL(void, SSLContext, setContextId)(TCN_STDARGS, jlong ctx,
606
UNREFERENCED_STDARGS;
611
TCN_IMPLEMENT_CALL(void, SSLContext, setBIO)(TCN_STDARGS, jlong ctx,
614
UNREFERENCED_STDARGS;
620
TCN_IMPLEMENT_CALL(void, SSLContext, setOptions)(TCN_STDARGS, jlong ctx,
623
UNREFERENCED_STDARGS;
628
TCN_IMPLEMENT_CALL(void, SSLContext, setQuietShutdown)(TCN_STDARGS, jlong ctx,
631
UNREFERENCED_STDARGS;
636
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
639
UNREFERENCED_STDARGS;
641
UNREFERENCED(ciphers);
645
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCARevocation)(TCN_STDARGS, jlong ctx,
649
UNREFERENCED_STDARGS;
656
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificateChainFile)(TCN_STDARGS, jlong ctx,
660
UNREFERENCED_STDARGS;
663
UNREFERENCED(skipfirst);
667
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCACertificate)(TCN_STDARGS,
672
UNREFERENCED_STDARGS;
679
TCN_IMPLEMENT_CALL(void, SSLContext, setShutdownType)(TCN_STDARGS, jlong ctx,
682
UNREFERENCED_STDARGS;
687
TCN_IMPLEMENT_CALL(void, SSLContext, setVerify)(TCN_STDARGS, jlong ctx,
688
jint level, jint depth)
690
UNREFERENCED_STDARGS;
696
TCN_IMPLEMENT_CALL(void, SSLContext, setRandom)(TCN_STDARGS, jlong ctx,
699
UNREFERENCED_STDARGS;
704
TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCertificate)(TCN_STDARGS, jlong ctx,
705
jstring cert, jstring key,
706
jstring password, jint idx)
708
UNREFERENCED_STDARGS;
712
UNREFERENCED(password);