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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "tcn.h"
18 #include "apr_file_io.h"
19 #include "apr_thread_mutex.h"
20 #include "apr_atomic.h"
21 #include "apr_poll.h"
22
23 #ifdef HAVE_OPENSSL
24 #include "ssl_private.h"
25
26 static int ssl_initialized = 0;
27 static char *ssl_global_rand_file = NULL;
28 extern apr_pool_t *tcn_global_pool;
29
30 ENGINE *tcn_ssl_engine = NULL;
31 tcn_pass_cb_t tcn_password_callback;
32
33 #ifdef HAVE_KEYLOG_CALLBACK
34 static BIO *key_log_file = NULL;
35
ssl_keylog_callback(const SSL * ssl,const char * line)36 static void ssl_keylog_callback(const SSL *ssl, const char *line)
37 {
38 if (key_log_file && line && *line) {
39 BIO_puts(key_log_file, line);
40 BIO_puts(key_log_file, "\n");
41 }
42 }
43 #endif
44
45 /* From netty-tcnative */
46 static jclass byteArrayClass;
47 static jclass stringClass;
48
49 #if OPENSSL_VERSION_NUMBER < 0x10100000L
50 /* Global reference to the pool used by the dynamic mutexes */
51 static apr_pool_t *dynlockpool = NULL;
52
53 /* Dynamic lock structure */
54 struct CRYPTO_dynlock_value {
55 apr_pool_t *pool;
56 const char* file;
57 int line;
58 apr_thread_mutex_t *mutex;
59 };
60
61 #if ! (defined(WIN32) || defined(WIN64))
62 apr_threadkey_t *thread_exit_key;
63 static int threadkey_initialized = 0;
64 #endif
65 #endif
66
67 /*
68 * supported_ssl_opts is a bitmask that contains all supported SSL_OP_*
69 * options at compile-time. This is used in hasOp to determine which
70 * SSL_OP_* options are available at runtime.
71 *
72 * Note that at least up through OpenSSL 0.9.8o, checking SSL_OP_ALL will
73 * return JNI_FALSE because SSL_OP_ALL is a mask that covers all bug
74 * workarounds for OpenSSL including future workarounds that are defined
75 * to be in the least-significant 3 nibbles of the SSL_OP_* bit space.
76 *
77 * This implementation has chosen NOT to simply set all those lower bits
78 * so that the return value for SSL_OP_FUTURE_WORKAROUND will only be
79 * reported by versions that actually support that specific workaround.
80 */
81 static const jint supported_ssl_opts = 0
82 /*
83 Specifically skip SSL_OP_ALL
84 #ifdef SSL_OP_ALL
85 | SSL_OP_ALL
86 #endif
87 */
88 #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
89 | SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
90 #endif
91
92 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
93 | SSL_OP_CIPHER_SERVER_PREFERENCE
94 #endif
95
96 #ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG
97 | SSL_OP_CRYPTOPRO_TLSEXT_BUG
98 #endif
99
100 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
101 | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
102 #endif
103
104 #ifdef SSL_OP_EPHEMERAL_RSA
105 | SSL_OP_EPHEMERAL_RSA
106 #endif
107
108 #ifdef SSL_OP_LEGACY_SERVER_CONNECT
109 | SSL_OP_LEGACY_SERVER_CONNECT
110 #endif
111
112 #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
113 | SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
114 #endif
115
116 #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
117 | SSL_OP_MICROSOFT_SESS_ID_BUG
118 #endif
119
120 #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
121 | SSL_OP_MSIE_SSLV2_RSA_PADDING
122 #endif
123
124 #ifdef SSL_OP_NETSCAPE_CA_DN_BUG
125 | SSL_OP_NETSCAPE_CA_DN_BUG
126 #endif
127
128 #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
129 | SSL_OP_NETSCAPE_CHALLENGE_BUG
130 #endif
131
132 #ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
133 | SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
134 #endif
135
136 #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
137 | SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
138 #endif
139
140 #ifdef SSL_OP_NO_COMPRESSION
141 | SSL_OP_NO_COMPRESSION
142 #endif
143
144 #ifdef SSL_OP_NO_QUERY_MTU
145 | SSL_OP_NO_QUERY_MTU
146 #endif
147
148 #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
149 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
150 #endif
151
152 #ifdef SSL_OP_NO_SSLv2
153 | SSL_OP_NO_SSLv2
154 #endif
155
156 #ifdef SSL_OP_NO_SSLv3
157 | SSL_OP_NO_SSLv3
158 #endif
159
160 #ifdef SSL_OP_NO_TICKET
161 | SSL_OP_NO_TICKET
162 #endif
163
164 #ifdef SSL_OP_NO_TLSv1
165 | SSL_OP_NO_TLSv1
166 #endif
167
168 #ifdef SSL_OP_PKCS1_CHECK_1
169 | SSL_OP_PKCS1_CHECK_1
170 #endif
171
172 #ifdef SSL_OP_PKCS1_CHECK_2
173 | SSL_OP_PKCS1_CHECK_2
174 #endif
175
176 #ifdef SSL_OP_NO_TLSv1_1
177 | SSL_OP_NO_TLSv1_1
178 #endif
179
180 #ifdef SSL_OP_NO_TLSv1_2
181 | SSL_OP_NO_TLSv1_2
182 #endif
183
184 #ifdef SSL_OP_SINGLE_DH_USE
185 | SSL_OP_SINGLE_DH_USE
186 #endif
187
188 #ifdef SSL_OP_SINGLE_ECDH_USE
189 | SSL_OP_SINGLE_ECDH_USE
190 #endif
191
192 #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
193 | SSL_OP_SSLEAY_080_CLIENT_DH_BUG
194 #endif
195
196 #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
197 | SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
198 #endif
199
200 #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
201 | SSL_OP_TLS_BLOCK_PADDING_BUG
202 #endif
203
204 #ifdef SSL_OP_TLS_D5_BUG
205 | SSL_OP_TLS_D5_BUG
206 #endif
207
208 #ifdef SSL_OP_TLS_ROLLBACK_BUG
209 | SSL_OP_TLS_ROLLBACK_BUG
210 #endif
211 | 0;
212
213 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
214 /* OpenSSL Pre-1.1.0 compatibility */
215 /* Taken from OpenSSL 1.1.0 snapshot 20160410 */
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)216 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
217 {
218 /* q is optional */
219 if (p == NULL || g == NULL)
220 return 0;
221 BN_free(dh->p);
222 BN_free(dh->q);
223 BN_free(dh->g);
224 dh->p = p;
225 dh->q = q;
226 dh->g = g;
227
228 if (q != NULL) {
229 dh->length = BN_num_bits(q);
230 }
231
232 return 1;
233 }
234 #endif
235
236 /*
237 * Grab well-defined DH parameters from OpenSSL, see the BN_get_rfc*
238 * functions in <openssl/bn.h> for all available primes.
239 */
make_dh_params(BIGNUM * (* prime)(BIGNUM *))240 static DH *make_dh_params(BIGNUM *(*prime)(BIGNUM *))
241 {
242 DH *dh = DH_new();
243 BIGNUM *p, *g;
244
245 if (!dh) {
246 return NULL;
247 }
248 p = prime(NULL);
249 g = BN_new();
250 if (g != NULL) {
251 BN_set_word(g, 2);
252 }
253 if (!p || !g || !DH_set0_pqg(dh, p, NULL, g)) {
254 DH_free(dh);
255 BN_free(p);
256 BN_free(g);
257 return NULL;
258 }
259 return dh;
260 }
261
262 /* Storage and initialization for DH parameters. */
263 static struct dhparam {
264 BIGNUM *(*const prime)(BIGNUM *); /* function to generate... */
265 DH *dh; /* ...this, used for keys.... */
266 const unsigned int min; /* ...of length >= this. */
267 } dhparams[] = {
268 { BN_get_rfc3526_prime_8192, NULL, 6145 },
269 { BN_get_rfc3526_prime_6144, NULL, 4097 },
270 { BN_get_rfc3526_prime_4096, NULL, 3073 },
271 { BN_get_rfc3526_prime_3072, NULL, 2049 },
272 { BN_get_rfc3526_prime_2048, NULL, 1025 },
273 { BN_get_rfc2409_prime_1024, NULL, 0 }
274 };
275
init_dh_params(void)276 static void init_dh_params(void)
277 {
278 unsigned n;
279
280 for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++)
281 dhparams[n].dh = make_dh_params(dhparams[n].prime);
282 }
283
free_dh_params(void)284 static void free_dh_params(void)
285 {
286 unsigned n;
287
288 /* DH_free() is a noop for a NULL parameter, so these are harmless
289 * in the (unexpected) case where these variables are already
290 * NULL. */
291 for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) {
292 DH_free(dhparams[n].dh);
293 dhparams[n].dh = NULL;
294 }
295 }
296
297 #ifdef HAVE_KEYLOG_CALLBACK
SSL_callback_add_keylog(SSL_CTX * ctx)298 void SSL_callback_add_keylog(SSL_CTX *ctx)
299 {
300 if (key_log_file) {
301 SSL_CTX_set_keylog_callback(ctx, ssl_keylog_callback);
302 }
303 }
304 #endif
305
306 /* Hand out the same DH structure though once generated as we leak
307 * memory otherwise and freeing the structure up after use would be
308 * hard to track and in fact is not needed at all as it is safe to
309 * use the same parameters over and over again security wise (in
310 * contrast to the keys itself) and code safe as the returned structure
311 * is duplicated by OpenSSL anyway. Hence no modification happens
312 * to our copy. */
SSL_get_dh_params(unsigned keylen)313 DH *SSL_get_dh_params(unsigned keylen)
314 {
315 unsigned n;
316
317 for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++)
318 if (keylen >= dhparams[n].min)
319 return dhparams[n].dh;
320
321 return NULL; /* impossible to reach. */
322 }
323
324 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
325 static void init_bio_methods(void);
326 static void free_bio_methods(void);
327 #endif
328
TCN_IMPLEMENT_CALL(jint,SSL,version)329 TCN_IMPLEMENT_CALL(jint, SSL, version)(TCN_STDARGS)
330 {
331 UNREFERENCED_STDARGS;
332 return OpenSSL_version_num();
333 }
334
TCN_IMPLEMENT_CALL(jstring,SSL,versionString)335 TCN_IMPLEMENT_CALL(jstring, SSL, versionString)(TCN_STDARGS)
336 {
337 UNREFERENCED(o);
338 return AJP_TO_JSTRING(OpenSSL_version(OPENSSL_VERSION));
339 }
340
341 /*
342 * the various processing hooks
343 */
ssl_init_cleanup(void * data)344 static apr_status_t ssl_init_cleanup(void *data)
345 {
346 UNREFERENCED(data);
347
348 if (!ssl_initialized)
349 return APR_SUCCESS;
350 ssl_initialized = 0;
351
352 #if OPENSSL_VERSION_NUMBER < 0x10100000L && ! (defined(WIN32) || defined(WIN64))
353 if (threadkey_initialized) {
354 threadkey_initialized = 0;
355 apr_threadkey_private_delete(thread_exit_key);
356 }
357 #endif
358 if (tcn_password_callback.cb.obj) {
359 JNIEnv *env;
360 tcn_get_java_env(&env);
361 TCN_UNLOAD_CLASS(env,
362 tcn_password_callback.cb.obj);
363 }
364
365 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
366 free_bio_methods();
367 #endif
368 free_dh_params();
369
370 /*
371 * Try to kill the internals of the SSL library.
372 */
373 #ifdef OPENSSL_FIPS
374 FIPS_mode_set(0);
375 #endif
376 /* Corresponds to OPENSSL_load_builtin_modules() */
377 CONF_modules_free();
378 /* Corresponds to SSL_library_init: */
379 EVP_cleanup();
380 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
381 ENGINE_cleanup();
382 #endif
383 #if OPENSSL_VERSION_NUMBER >= 0x1000200fL
384 #ifndef OPENSSL_NO_COMP
385 SSL_COMP_free_compression_methods();
386 #endif
387 #endif
388 CRYPTO_cleanup_all_ex_data();
389 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
390 ERR_remove_thread_state(NULL);
391 #endif
392
393 #ifdef HAVE_KEYLOG_CALLBACK
394 if (key_log_file) {
395 BIO_free(key_log_file);
396 key_log_file = NULL;
397 }
398 #endif
399
400 /* Don't call ERR_free_strings here; ERR_load_*_strings only
401 * actually load the error strings once per process due to static
402 * variable abuse in OpenSSL. */
403
404 /*
405 * TODO: determine somewhere we can safely shove out diagnostics
406 * (when enabled) at this late stage in the game:
407 * CRYPTO_mem_leaks_fp(stderr);
408 */
409 return APR_SUCCESS;
410 }
411
412 #ifndef OPENSSL_NO_ENGINE
413 /* Try to load an engine in a shareable library */
ssl_try_load_engine(const char * engine)414 static ENGINE *ssl_try_load_engine(const char *engine)
415 {
416 ENGINE *e = ENGINE_by_id("dynamic");
417 if (e) {
418 if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
419 || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
420 ENGINE_free(e);
421 e = NULL;
422 }
423 }
424 return e;
425 }
426 #endif
427
428 /*
429 * To ensure thread-safetyness in OpenSSL
430 */
431
432 #if OPENSSL_VERSION_NUMBER < 0x10100000L
433 static apr_thread_mutex_t **ssl_lock_cs;
434 static int ssl_lock_num_locks;
435
ssl_thread_lock(int mode,int type,const char * file,int line)436 static void ssl_thread_lock(int mode, int type,
437 const char *file, int line)
438 {
439 UNREFERENCED(file);
440 UNREFERENCED(line);
441 if (type < ssl_lock_num_locks) {
442 if (mode & CRYPTO_LOCK) {
443 apr_thread_mutex_lock(ssl_lock_cs[type]);
444 }
445 else {
446 apr_thread_mutex_unlock(ssl_lock_cs[type]);
447 }
448 }
449 }
450 #endif
451
ssl_thread_id(void)452 static unsigned long ssl_thread_id(void)
453 {
454 return (unsigned long)tcn_get_thread_id();
455 }
456
457 #if OPENSSL_VERSION_NUMBER < 0x10100000L
458 #if ! (defined(WIN32) || defined(WIN64))
SSL_thread_exit(void)459 void SSL_thread_exit(void) {
460 ERR_remove_thread_state(NULL);
461 apr_threadkey_private_set(NULL, thread_exit_key);
462 }
463
SSL_ERR_get()464 unsigned long SSL_ERR_get() {
465 apr_threadkey_private_set(thread_exit_key, thread_exit_key);
466 return ERR_get_error();
467 }
468
SSL_ERR_clear()469 void SSL_ERR_clear() {
470 apr_threadkey_private_set(thread_exit_key, thread_exit_key);
471 ERR_clear_error();
472 }
473
_ssl_thread_exit(void * data)474 static void _ssl_thread_exit(void *data) {
475 UNREFERENCED(data);
476 SSL_thread_exit();
477 }
478 #endif
479
ssl_set_thread_id(CRYPTO_THREADID * id)480 static void ssl_set_thread_id(CRYPTO_THREADID *id)
481 {
482 CRYPTO_THREADID_set_numeric(id, ssl_thread_id());
483 }
484
ssl_thread_cleanup(void * data)485 static apr_status_t ssl_thread_cleanup(void *data)
486 {
487 UNREFERENCED(data);
488 CRYPTO_THREADID_set_callback(NULL);
489 CRYPTO_set_locking_callback(NULL);
490 CRYPTO_set_dynlock_create_callback(NULL);
491 CRYPTO_set_dynlock_lock_callback(NULL);
492 CRYPTO_set_dynlock_destroy_callback(NULL);
493
494 dynlockpool = NULL;
495
496 /* Let the registered mutex cleanups do their own thing
497 */
498 return APR_SUCCESS;
499 }
500
501 /*
502 * Dynamic lock creation callback
503 */
ssl_dyn_create_function(const char * file,int line)504 static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file,
505 int line)
506 {
507 struct CRYPTO_dynlock_value *value;
508 apr_pool_t *p;
509 apr_status_t rv;
510
511 /*
512 * We need a pool to allocate our mutex. Since we can't clear
513 * allocated memory from a pool, create a subpool that we can blow
514 * away in the destruction callback.
515 */
516 rv = apr_pool_create(&p, dynlockpool);
517 if (rv != APR_SUCCESS) {
518 /* TODO log that fprintf(stderr, "Failed to create subpool for dynamic lock"); */
519 return NULL;
520 }
521
522 value = (struct CRYPTO_dynlock_value *)apr_palloc(p,
523 sizeof(struct CRYPTO_dynlock_value));
524 if (!value) {
525 /* TODO log that fprintf(stderr, "Failed to allocate dynamic lock structure"); */
526 return NULL;
527 }
528
529 value->pool = p;
530 /* Keep our own copy of the place from which we were created,
531 using our own pool. */
532 value->file = apr_pstrdup(p, file);
533 value->line = line;
534 rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT,
535 p);
536 if (rv != APR_SUCCESS) {
537 /* TODO log that fprintf(stderr, "Failed to create thread mutex for dynamic lock"); */
538 apr_pool_destroy(p);
539 return NULL;
540 }
541 return value;
542 }
543
544 /*
545 * Dynamic locking and unlocking function
546 */
547
ssl_dyn_lock_function(int mode,struct CRYPTO_dynlock_value * l,const char * file,int line)548 static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
549 const char *file, int line)
550 {
551
552
553 if (mode & CRYPTO_LOCK) {
554 apr_thread_mutex_lock(l->mutex);
555 }
556 else {
557 apr_thread_mutex_unlock(l->mutex);
558 }
559 }
560
561 /*
562 * Dynamic lock destruction callback
563 */
ssl_dyn_destroy_function(struct CRYPTO_dynlock_value * l,const char * file,int line)564 static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l,
565 const char *file, int line)
566 {
567 apr_status_t rv;
568 rv = apr_thread_mutex_destroy(l->mutex);
569 if (rv != APR_SUCCESS) {
570 /* TODO log that fprintf(stderr, "Failed to destroy mutex for dynamic lock %s:%d", l->file, l->line); */
571 }
572 /* Trust that whomever owned the CRYPTO_dynlock_value we were
573 * passed has no future use for it...
574 */
575 apr_pool_destroy(l->pool);
576 }
577
ssl_thread_setup(apr_pool_t * p)578 static void ssl_thread_setup(apr_pool_t *p)
579 {
580 int i;
581
582 CRYPTO_THREADID_set_callback(ssl_set_thread_id);
583 ssl_lock_num_locks = CRYPTO_num_locks();
584 ssl_lock_cs = apr_palloc(p, ssl_lock_num_locks * sizeof(*ssl_lock_cs));
585
586 for (i = 0; i < ssl_lock_num_locks; i++) {
587 apr_thread_mutex_create(&(ssl_lock_cs[i]),
588 APR_THREAD_MUTEX_DEFAULT, p);
589 }
590
591 CRYPTO_set_locking_callback(ssl_thread_lock);
592 /* Set up dynamic locking scaffolding for OpenSSL to use at its
593 * convenience.
594 */
595 dynlockpool = p;
596 CRYPTO_set_dynlock_create_callback(ssl_dyn_create_function);
597 CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock_function);
598 CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy_function);
599
600 apr_pool_cleanup_register(p, NULL, ssl_thread_cleanup,
601 apr_pool_cleanup_null);
602 }
603 #endif
604
ssl_rand_choosenum(int l,int h)605 static int ssl_rand_choosenum(int l, int h)
606 {
607 int i;
608 char buf[50];
609
610 apr_snprintf(buf, sizeof(buf), "%.0f",
611 (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
612 i = atoi(buf)+1;
613 if (i < l) i = l;
614 if (i > h) i = h;
615 return i;
616 }
617
ssl_rand_load_file(const char * file)618 static int ssl_rand_load_file(const char *file)
619 {
620 char buffer[APR_PATH_MAX];
621 int n;
622
623 if (file == NULL)
624 file = ssl_global_rand_file;
625 if (file && (strcmp(file, "builtin") == 0))
626 return -1;
627 if (file == NULL)
628 file = RAND_file_name(buffer, sizeof(buffer));
629 if (file) {
630 if (strncmp(file, "egd:", 4) == 0) {
631 #ifndef OPENSSL_NO_EGD
632 if ((n = RAND_egd(file + 4)) > 0)
633 return n;
634 else
635 #endif
636 return -1;
637 }
638 if ((n = RAND_load_file(file, -1)) > 0)
639 return n;
640 }
641 return -1;
642 }
643
644 /*
645 * writes a number of random bytes (currently 1024) to
646 * file which can be used to initialize the PRNG by calling
647 * RAND_load_file() in a later session
648 */
ssl_rand_save_file(const char * file)649 static int ssl_rand_save_file(const char *file)
650 {
651 char buffer[APR_PATH_MAX];
652 #ifndef OPENSSL_NO_EGD
653 int n;
654 #endif
655
656 if (file == NULL)
657 file = RAND_file_name(buffer, sizeof(buffer));
658 #ifndef OPENSSL_NO_EGD
659 else if ((n = RAND_egd(file)) > 0) {
660 return 0;
661 }
662 #endif
663 if (file == NULL || !RAND_write_file(file))
664 return 0;
665 else
666 return 1;
667 }
668
SSL_rand_seed(const char * file)669 int SSL_rand_seed(const char *file)
670 {
671 unsigned char stackdata[256];
672 static volatile apr_uint32_t counter = 0;
673
674 if (ssl_rand_load_file(file) < 0) {
675 int n;
676 struct {
677 apr_time_t t;
678 pid_t p;
679 unsigned long i;
680 apr_uint32_t u;
681 } _ssl_seed;
682 if (counter == 0) {
683 apr_generate_random_bytes(stackdata, 256);
684 RAND_seed(stackdata, 128);
685 }
686 _ssl_seed.t = apr_time_now();
687 _ssl_seed.p = getpid();
688 _ssl_seed.i = ssl_thread_id();
689 apr_atomic_inc32(&counter);
690 _ssl_seed.u = counter;
691 RAND_seed((unsigned char *)&_ssl_seed, sizeof(_ssl_seed));
692 /*
693 * seed in some current state of the run-time stack (128 bytes)
694 */
695 n = ssl_rand_choosenum(0, sizeof(stackdata)-128-1);
696 RAND_seed(stackdata + n, 128);
697 }
698 return RAND_status();
699 }
700
ssl_rand_make(const char * file,int len,int base64)701 static int ssl_rand_make(const char *file, int len, int base64)
702 {
703 int r;
704 int num = len;
705 BIO *out = NULL;
706
707 out = BIO_new(BIO_s_file());
708 if (out == NULL)
709 return 0;
710 if ((r = BIO_write_filename(out, (char *)file)) < 0) {
711 BIO_free_all(out);
712 return 0;
713 }
714 if (base64) {
715 BIO *b64 = BIO_new(BIO_f_base64());
716 if (b64 == NULL) {
717 BIO_free_all(out);
718 return 0;
719 }
720 out = BIO_push(b64, out);
721 }
722 while (num > 0) {
723 unsigned char buf[4096];
724 int len = num;
725 if (len > sizeof(buf))
726 len = sizeof(buf);
727 r = RAND_bytes(buf, len);
728 if (r <= 0) {
729 BIO_free_all(out);
730 return 0;
731 }
732 BIO_write(out, buf, len);
733 num -= len;
734 }
735 r = BIO_flush(out);
736 BIO_free_all(out);
737 return r > 0 ? 1 : 0;
738 }
739
TCN_IMPLEMENT_CALL(jint,SSL,initialize)740 TCN_IMPLEMENT_CALL(jint, SSL, initialize)(TCN_STDARGS, jstring engine)
741 {
742 jclass clazz;
743 jclass sClazz;
744 #if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER < 0x10100000L
745 apr_status_t err = APR_SUCCESS;
746 #endif
747
748 TCN_ALLOC_CSTRING(engine);
749
750 UNREFERENCED(o);
751 if (!tcn_global_pool) {
752 TCN_FREE_CSTRING(engine);
753 tcn_ThrowAPRException(e, APR_EINVAL);
754 return (jint)APR_EINVAL;
755 }
756 /* Check if already initialized */
757 if (ssl_initialized++) {
758 TCN_FREE_CSTRING(engine);
759 return (jint)APR_SUCCESS;
760 }
761
762 /* We must register the library in full, to ensure our configuration
763 * code can successfully test the SSL environment.
764 */
765 OPENSSL_malloc_init();
766 ERR_load_crypto_strings();
767 SSL_load_error_strings();
768 SSL_library_init();
769 OpenSSL_add_all_algorithms();
770 #if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
771 ENGINE_load_builtin_engines();
772 #endif
773 OPENSSL_load_builtin_modules();
774
775 #if OPENSSL_VERSION_NUMBER < 0x10100000L
776 #if ! (defined(WIN32) || defined(WIN64))
777 err = apr_threadkey_private_create(&thread_exit_key, _ssl_thread_exit,
778 tcn_global_pool);
779 if (err != APR_SUCCESS) {
780 ssl_init_cleanup(NULL);
781 tcn_ThrowAPRException(e, err);
782 return (jint)err;
783 }
784 threadkey_initialized = 1;
785 #endif
786 /* Initialize thread support */
787 ssl_thread_setup(tcn_global_pool);
788 #endif
789
790 #ifndef OPENSSL_NO_ENGINE
791 if (J2S(engine)) {
792 ENGINE *ee = NULL;
793 if(strcmp(J2S(engine), "auto") == 0) {
794 ENGINE_register_all_complete();
795 }
796 else {
797 if ((ee = ENGINE_by_id(J2S(engine))) == NULL
798 && (ee = ssl_try_load_engine(J2S(engine))) == NULL)
799 err = APR_ENOTIMPL;
800 else {
801 #ifdef ENGINE_CTRL_CHIL_SET_FORKCHECK
802 if (strcmp(J2S(engine), "chil") == 0)
803 ENGINE_ctrl(ee, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
804 #endif
805 if (!ENGINE_set_default(ee, ENGINE_METHOD_ALL))
806 err = APR_ENOTIMPL;
807 }
808 /* Free our "structural" reference. */
809 if (ee)
810 ENGINE_free(ee);
811 }
812 if (err != APR_SUCCESS) {
813 TCN_FREE_CSTRING(engine);
814 ssl_init_cleanup(NULL);
815 tcn_ThrowAPRException(e, err);
816 return (jint)err;
817 }
818 tcn_ssl_engine = ee;
819 }
820 #endif
821
822 memset(&tcn_password_callback, 0, sizeof(tcn_pass_cb_t));
823 /* Initialize PRNG
824 * This will in most cases call the builtin
825 * low entropy seed.
826 */
827 SSL_rand_seed(NULL);
828 /* For SSL_get_app_data2(), SSL_get_app_data3() and SSL_get_app_data4() at request time */
829 SSL_init_app_data_idx();
830
831 init_dh_params();
832 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
833 init_bio_methods();
834 #endif
835
836 /*
837 * Let us cleanup the ssl library when the library is unloaded
838 */
839 apr_pool_cleanup_register(tcn_global_pool, NULL,
840 ssl_init_cleanup,
841 apr_pool_cleanup_null);
842 TCN_FREE_CSTRING(engine);
843
844 /* Cache the byte[].class for performance reasons */
845 clazz = (*e)->FindClass(e, "[B");
846 byteArrayClass = (jclass) (*e)->NewGlobalRef(e, clazz);
847
848 /* Cache the String.class for performance reasons */
849 sClazz = (*e)->FindClass(e, "java/lang/String");
850 stringClass = (jclass) (*e)->NewGlobalRef(e, sClazz);
851
852 #ifdef HAVE_KEYLOG_CALLBACK
853 if (!key_log_file) {
854 char *key_log_file_name = getenv("SSLKEYLOGFILE");
855 if (key_log_file_name) {
856 FILE *file = fopen(key_log_file_name, "a");
857 if (file) {
858 if (setvbuf(file, NULL, _IONBF, 0)) {
859 fclose(file);
860 } else {
861 key_log_file = BIO_new_fp(file, BIO_CLOSE);
862 }
863 }
864 }
865 }
866 #endif
867
868 return (jint)APR_SUCCESS;
869 }
870
TCN_IMPLEMENT_CALL(jboolean,SSL,randLoad)871 TCN_IMPLEMENT_CALL(jboolean, SSL, randLoad)(TCN_STDARGS, jstring file)
872 {
873 TCN_ALLOC_CSTRING(file);
874 int r;
875 UNREFERENCED(o);
876 r = SSL_rand_seed(J2S(file));
877 TCN_FREE_CSTRING(file);
878 return r ? JNI_TRUE : JNI_FALSE;
879 }
880
TCN_IMPLEMENT_CALL(jboolean,SSL,randSave)881 TCN_IMPLEMENT_CALL(jboolean, SSL, randSave)(TCN_STDARGS, jstring file)
882 {
883 TCN_ALLOC_CSTRING(file);
884 int r;
885 UNREFERENCED(o);
886 r = ssl_rand_save_file(J2S(file));
887 TCN_FREE_CSTRING(file);
888 return r ? JNI_TRUE : JNI_FALSE;
889 }
890
TCN_IMPLEMENT_CALL(jboolean,SSL,randMake)891 TCN_IMPLEMENT_CALL(jboolean, SSL, randMake)(TCN_STDARGS, jstring file,
892 jint length, jboolean base64)
893 {
894 TCN_ALLOC_CSTRING(file);
895 int r;
896 UNREFERENCED(o);
897 r = ssl_rand_make(J2S(file), length, base64);
898 TCN_FREE_CSTRING(file);
899 return r ? JNI_TRUE : JNI_FALSE;
900 }
901
TCN_IMPLEMENT_CALL(void,SSL,randSet)902 TCN_IMPLEMENT_CALL(void, SSL, randSet)(TCN_STDARGS, jstring file)
903 {
904 TCN_ALLOC_CSTRING(file);
905 UNREFERENCED(o);
906 if (J2S(file)) {
907 ssl_global_rand_file = apr_pstrdup(tcn_global_pool, J2S(file));
908 }
909 TCN_FREE_CSTRING(file);
910 }
911
TCN_IMPLEMENT_CALL(jint,SSL,fipsModeGet)912 TCN_IMPLEMENT_CALL(jint, SSL, fipsModeGet)(TCN_STDARGS)
913 {
914 UNREFERENCED(o);
915 #ifdef OPENSSL_FIPS
916 return FIPS_mode();
917 #else
918 /* FIPS is unavailable */
919 tcn_ThrowException(e, "FIPS was not available to tcnative at build time. You will need to re-build tcnative against an OpenSSL with FIPS.");
920
921 return 0;
922 #endif
923 }
924
TCN_IMPLEMENT_CALL(jint,SSL,fipsModeSet)925 TCN_IMPLEMENT_CALL(jint, SSL, fipsModeSet)(TCN_STDARGS, jint mode)
926 {
927 int r = 0;
928 UNREFERENCED(o);
929
930 #ifdef OPENSSL_FIPS
931 if(1 != (r = (jint)FIPS_mode_set((int)mode))) {
932 /* arrange to get a human-readable error message */
933 unsigned long err = SSL_ERR_get();
934 char msg[256];
935
936 /* ERR_load_crypto_strings() already called in initialize() */
937
938 ERR_error_string_n(err, msg, 256);
939
940 tcn_ThrowException(e, msg);
941 }
942 #else
943 /* FIPS is unavailable */
944 tcn_ThrowException(e, "FIPS was not available to tcnative at build time. You will need to re-build tcnative against an OpenSSL with FIPS.");
945 #endif
946
947 return r;
948 }
949
950 /* OpenSSL Java Stream BIO */
951
952 typedef struct {
953 int refcount;
954 apr_pool_t *pool;
955 tcn_callback_t cb;
956 } BIO_JAVA;
957
958
generic_bio_cleanup(void * data)959 static apr_status_t generic_bio_cleanup(void *data)
960 {
961 BIO *b = (BIO *)data;
962
963 if (b) {
964 BIO_free(b);
965 }
966 return APR_SUCCESS;
967 }
968
SSL_BIO_close(BIO * bi)969 void SSL_BIO_close(BIO *bi)
970 {
971 BIO_JAVA *j;
972 if (bi == NULL)
973 return;
974 j = (BIO_JAVA *)BIO_get_data(bi);
975 if (j != NULL && BIO_test_flags(bi, SSL_BIO_FLAG_CALLBACK)) {
976 j->refcount--;
977 if (j->refcount == 0) {
978 if (j->pool)
979 apr_pool_cleanup_run(j->pool, bi, generic_bio_cleanup);
980 else
981 BIO_free(bi);
982 }
983 }
984 else
985 BIO_free(bi);
986 }
987
SSL_BIO_doref(BIO * bi)988 void SSL_BIO_doref(BIO *bi)
989 {
990 BIO_JAVA *j;
991 if (bi == NULL)
992 return;
993 j = (BIO_JAVA *)BIO_get_data(bi);
994 if (j != NULL && BIO_test_flags(bi, SSL_BIO_FLAG_CALLBACK)) {
995 j->refcount++;
996 }
997 }
998
999
jbs_new(BIO * bi)1000 static int jbs_new(BIO *bi)
1001 {
1002 BIO_JAVA *j;
1003
1004 if ((j = OPENSSL_malloc(sizeof(BIO_JAVA))) == NULL)
1005 return 0;
1006 j->pool = NULL;
1007 j->refcount = 1;
1008 BIO_set_shutdown(bi, 1);
1009 BIO_set_init(bi, 0);
1010 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1011 /* No setter method for OpenSSL 1.1.0 available,
1012 * but I can't find any functional use of the
1013 * "num" field there either.
1014 */
1015 bi->num = -1;
1016 #endif
1017 BIO_set_data(bi, (void *)j);
1018
1019 return 1;
1020 }
1021
jbs_free(BIO * bi)1022 static int jbs_free(BIO *bi)
1023 {
1024 BIO_JAVA *j;
1025 if (bi == NULL)
1026 return 0;
1027 j = (BIO_JAVA *)BIO_get_data(bi);
1028 if (j != NULL) {
1029 if (BIO_get_init(bi)) {
1030 JNIEnv *e = NULL;
1031 BIO_set_init(bi, 0);
1032 tcn_get_java_env(&e);
1033 TCN_UNLOAD_CLASS(e, j->cb.obj);
1034 }
1035 OPENSSL_free(j);
1036 }
1037 BIO_set_data(bi, NULL);
1038 return 1;
1039 }
1040
jbs_write(BIO * b,const char * in,int inl)1041 static int jbs_write(BIO *b, const char *in, int inl)
1042 {
1043 jint ret = -1;
1044 if (BIO_get_init(b) && in != NULL) {
1045 BIO_JAVA *j = (BIO_JAVA *)BIO_get_data(b);
1046 JNIEnv *e = NULL;
1047 jbyteArray jb;
1048 tcn_get_java_env(&e);
1049 jb = (*e)->NewByteArray(e, inl);
1050 if (!(*e)->ExceptionOccurred(e)) {
1051 BIO_clear_retry_flags(b);
1052 (*e)->SetByteArrayRegion(e, jb, 0, inl, (jbyte *)in);
1053 ret = (*e)->CallIntMethod(e, j->cb.obj,
1054 j->cb.mid[0], jb);
1055 (*e)->ReleaseByteArrayElements(e, jb, (jbyte *)in, JNI_ABORT);
1056 (*e)->DeleteLocalRef(e, jb);
1057 }
1058 }
1059 /* From netty-tc-native, in the AF we were returning 0 */
1060 if (ret == 0) {
1061 BIO_set_retry_write(b);
1062 ret = -1;
1063 }
1064 return ret;
1065 }
1066
jbs_read(BIO * b,char * out,int outl)1067 static int jbs_read(BIO *b, char *out, int outl)
1068 {
1069 jint ret = 0;
1070 if (BIO_get_init(b) && out != NULL) {
1071 BIO_JAVA *j = (BIO_JAVA *)BIO_get_data(b);
1072 JNIEnv *e = NULL;
1073 jbyteArray jb;
1074 tcn_get_java_env(&e);
1075 jb = (*e)->NewByteArray(e, outl);
1076 if (!(*e)->ExceptionOccurred(e)) {
1077 BIO_clear_retry_flags(b);
1078 ret = (*e)->CallIntMethod(e, j->cb.obj,
1079 j->cb.mid[1], jb);
1080 if (ret > 0) {
1081 jbyte *jout = (*e)->GetPrimitiveArrayCritical(e, jb, NULL);
1082 memcpy(out, jout, ret);
1083 (*e)->ReleasePrimitiveArrayCritical(e, jb, jout, 0);
1084 } else if (outl != 0) {
1085 ret = -1;
1086 BIO_set_retry_read(b);
1087 }
1088 (*e)->DeleteLocalRef(e, jb);
1089 }
1090 }
1091 return ret;
1092 }
1093
jbs_puts(BIO * b,const char * in)1094 static int jbs_puts(BIO *b, const char *in)
1095 {
1096 int ret = 0;
1097 if (BIO_get_init(b) && in != NULL) {
1098 BIO_JAVA *j = (BIO_JAVA *)BIO_get_data(b);
1099 JNIEnv *e = NULL;
1100 tcn_get_java_env(&e);
1101 ret = (*e)->CallIntMethod(e, j->cb.obj,
1102 j->cb.mid[2],
1103 tcn_new_string(e, in));
1104 }
1105 return ret;
1106 }
1107
jbs_gets(BIO * b,char * out,int outl)1108 static int jbs_gets(BIO *b, char *out, int outl)
1109 {
1110 int ret = 0;
1111 if (BIO_get_init(b) && out != NULL) {
1112 BIO_JAVA *j = (BIO_JAVA *)BIO_get_data(b);
1113 JNIEnv *e = NULL;
1114 jobject o;
1115 tcn_get_java_env(&e);
1116 if ((o = (*e)->CallObjectMethod(e, j->cb.obj,
1117 j->cb.mid[3], (jint)(outl - 1)))) {
1118 TCN_ALLOC_CSTRING(o);
1119 if (J2S(o)) {
1120 int l = (int)strlen(J2S(o));
1121 if (l < outl) {
1122 strcpy(out, J2S(o));
1123 ret = outl;
1124 }
1125 }
1126 TCN_FREE_CSTRING(o);
1127 }
1128 }
1129 return ret;
1130 }
1131
jbs_ctrl(BIO * b,int cmd,long num,void * ptr)1132 static long jbs_ctrl(BIO *b, int cmd, long num, void *ptr)
1133 {
1134 int ret = 0;
1135 switch (cmd) {
1136 case BIO_CTRL_FLUSH:
1137 ret = 1;
1138 break;
1139 default:
1140 ret = 0;
1141 break;
1142 }
1143 return ret;
1144 }
1145
1146 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
1147 static BIO_METHOD jbs_methods = {
1148 BIO_TYPE_FILE,
1149 "Java Callback",
1150 jbs_write,
1151 jbs_read,
1152 jbs_puts,
1153 jbs_gets,
1154 jbs_ctrl,
1155 jbs_new,
1156 jbs_free,
1157 NULL
1158 };
1159 #else
1160 static BIO_METHOD *jbs_methods = NULL;
1161
init_bio_methods(void)1162 static void init_bio_methods(void)
1163 {
1164 jbs_methods = BIO_meth_new(BIO_TYPE_FILE, "Java Callback");
1165 BIO_meth_set_write(jbs_methods, &jbs_write);
1166 BIO_meth_set_read(jbs_methods, &jbs_read);
1167 BIO_meth_set_puts(jbs_methods, &jbs_puts);
1168 BIO_meth_set_gets(jbs_methods, &jbs_gets);
1169 BIO_meth_set_ctrl(jbs_methods, &jbs_ctrl);
1170 BIO_meth_set_create(jbs_methods, &jbs_new);
1171 BIO_meth_set_destroy(jbs_methods, &jbs_free);
1172 }
1173
free_bio_methods(void)1174 static void free_bio_methods(void)
1175 {
1176 BIO_meth_free(jbs_methods);
1177 }
1178 #endif
1179
BIO_jbs()1180 static BIO_METHOD *BIO_jbs()
1181 {
1182 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
1183 return(&jbs_methods);
1184 #else
1185 return jbs_methods;
1186 #endif
1187 }
1188
TCN_IMPLEMENT_CALL(jlong,SSL,newBIO)1189 TCN_IMPLEMENT_CALL(jlong, SSL, newBIO)(TCN_STDARGS, jlong pool,
1190 jobject callback)
1191 {
1192 BIO *bio = NULL;
1193 BIO_JAVA *j;
1194 jclass cls;
1195
1196 UNREFERENCED(o);
1197
1198 if ((bio = BIO_new(BIO_jbs())) == NULL) {
1199 tcn_ThrowException(e, "Create BIO failed");
1200 goto init_failed;
1201 }
1202 j = (BIO_JAVA *)BIO_get_data(bio);
1203 if (j == NULL) {
1204 tcn_ThrowException(e, "Create BIO failed");
1205 goto init_failed;
1206 }
1207 j->pool = J2P(pool, apr_pool_t *);
1208 if (j->pool) {
1209 apr_pool_cleanup_register(j->pool, (const void *)bio,
1210 generic_bio_cleanup,
1211 apr_pool_cleanup_null);
1212 }
1213
1214 cls = (*e)->GetObjectClass(e, callback);
1215 j->cb.mid[0] = (*e)->GetMethodID(e, cls, "write", "([B)I");
1216 j->cb.mid[1] = (*e)->GetMethodID(e, cls, "read", "([B)I");
1217 j->cb.mid[2] = (*e)->GetMethodID(e, cls, "puts", "(Ljava/lang/String;)I");
1218 j->cb.mid[3] = (*e)->GetMethodID(e, cls, "gets", "(I)Ljava/lang/String;");
1219 /* TODO: Check if method id's are valid */
1220 j->cb.obj = (*e)->NewGlobalRef(e, callback);
1221
1222 BIO_set_init(bio, 1);
1223 BIO_set_flags(bio, SSL_BIO_FLAG_CALLBACK);
1224 return P2J(bio);
1225 init_failed:
1226 return 0;
1227 }
1228
TCN_IMPLEMENT_CALL(jint,SSL,closeBIO)1229 TCN_IMPLEMENT_CALL(jint, SSL, closeBIO)(TCN_STDARGS, jlong bio)
1230 {
1231 BIO *b = J2P(bio, BIO *);
1232 UNREFERENCED_STDARGS;
1233 SSL_BIO_close(b);
1234 return APR_SUCCESS;
1235 }
1236
TCN_IMPLEMENT_CALL(void,SSL,setPasswordCallback)1237 TCN_IMPLEMENT_CALL(void, SSL, setPasswordCallback)(TCN_STDARGS,
1238 jobject callback)
1239 {
1240 jclass cls;
1241
1242 UNREFERENCED(o);
1243 if (tcn_password_callback.cb.obj) {
1244 TCN_UNLOAD_CLASS(e,
1245 tcn_password_callback.cb.obj);
1246 }
1247 cls = (*e)->GetObjectClass(e, callback);
1248 tcn_password_callback.cb.mid[0] = (*e)->GetMethodID(e, cls, "callback",
1249 "(Ljava/lang/String;)Ljava/lang/String;");
1250 /* TODO: Check if method id is valid */
1251 tcn_password_callback.cb.obj = (*e)->NewGlobalRef(e, callback);
1252
1253 }
1254
TCN_IMPLEMENT_CALL(void,SSL,setPassword)1255 TCN_IMPLEMENT_CALL(void, SSL, setPassword)(TCN_STDARGS, jstring password)
1256 {
1257 TCN_ALLOC_CSTRING(password);
1258 UNREFERENCED(o);
1259 if (J2S(password)) {
1260 strncpy(tcn_password_callback.password, J2S(password), SSL_MAX_PASSWORD_LEN);
1261 tcn_password_callback.password[SSL_MAX_PASSWORD_LEN-1] = '\0';
1262 }
1263 TCN_FREE_CSTRING(password);
1264 }
1265
TCN_IMPLEMENT_CALL(jstring,SSL,getLastError)1266 TCN_IMPLEMENT_CALL(jstring, SSL, getLastError)(TCN_STDARGS)
1267 {
1268 char buf[256];
1269 UNREFERENCED(o);
1270 ERR_error_string(SSL_ERR_get(), buf);
1271 return tcn_new_string(e, buf);
1272 }
1273
TCN_IMPLEMENT_CALL(jboolean,SSL,hasOp)1274 TCN_IMPLEMENT_CALL(jboolean, SSL, hasOp)(TCN_STDARGS, jint op)
1275 {
1276 return op == (op & supported_ssl_opts) ? JNI_TRUE : JNI_FALSE;
1277 }
1278
1279 /*** Begin Twitter 1:1 API addition ***/
TCN_IMPLEMENT_CALL(jint,SSL,getLastErrorNumber)1280 TCN_IMPLEMENT_CALL(jint, SSL, getLastErrorNumber)(TCN_STDARGS) {
1281 UNREFERENCED_STDARGS;
1282 return SSL_ERR_get();
1283 }
1284
ssl_info_callback(const SSL * ssl,int where,int ret)1285 static void ssl_info_callback(const SSL *ssl, int where, int ret) {
1286 int *handshakeCount = NULL;
1287 if (0 != (where & SSL_CB_HANDSHAKE_DONE)) {
1288 handshakeCount = (int*) SSL_get_app_data3(ssl);
1289 if (handshakeCount != NULL) {
1290 ++(*handshakeCount);
1291 }
1292 }
1293 }
1294
ssl_con_pool_cleanup(void * data)1295 static apr_status_t ssl_con_pool_cleanup(void *data)
1296 {
1297 SSL *ssl = (SSL*) data;
1298 int *destroyCount;
1299
1300 TCN_ASSERT(ssl != 0);
1301
1302 destroyCount = SSL_get_app_data4(ssl);
1303 if (destroyCount != NULL) {
1304 ++(*destroyCount);
1305 }
1306
1307 return APR_SUCCESS;
1308 }
1309
TCN_IMPLEMENT_CALL(jlong,SSL,newSSL)1310 TCN_IMPLEMENT_CALL(jlong /* SSL * */, SSL, newSSL)(TCN_STDARGS,
1311 jlong ctx /* tcn_ssl_ctxt_t * */,
1312 jboolean server) {
1313 tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
1314 int *handshakeCount = malloc(sizeof(int));
1315 int *destroyCount = malloc(sizeof(int));
1316 SSL *ssl;
1317 apr_pool_t *p = NULL;
1318 tcn_ssl_conn_t *con;
1319
1320 UNREFERENCED_STDARGS;
1321
1322 TCN_ASSERT(ctx != 0);
1323
1324 ssl = SSL_new(c->ctx);
1325 if (ssl == NULL) {
1326 free(handshakeCount);
1327 free(destroyCount);
1328 tcn_ThrowException(e, "cannot create new ssl");
1329 return 0;
1330 }
1331
1332 apr_pool_create(&p, c->pool);
1333 if (p == NULL) {
1334 free(handshakeCount);
1335 free(destroyCount);
1336 SSL_free(ssl);
1337 tcn_ThrowAPRException(e, apr_get_os_error());
1338 return 0;
1339 }
1340
1341 if ((con = apr_pcalloc(p, sizeof(tcn_ssl_conn_t))) == NULL) {
1342 free(handshakeCount);
1343 free(destroyCount);
1344 SSL_free(ssl);
1345 apr_pool_destroy(p);
1346 tcn_ThrowAPRException(e, apr_get_os_error());
1347 return 0;
1348 }
1349 con->pool = p;
1350 con->ctx = c;
1351 con->ssl = ssl;
1352 con->shutdown_type = c->shutdown_type;
1353
1354 /* Store the handshakeCount in the SSL instance. */
1355 *handshakeCount = 0;
1356 SSL_set_app_data3(ssl, handshakeCount);
1357
1358 /* Store the destroyCount in the SSL instance. */
1359 *destroyCount = 0;
1360 SSL_set_app_data4(ssl, destroyCount);
1361
1362 /* Add callback to keep track of handshakes. */
1363 SSL_CTX_set_info_callback(c->ctx, ssl_info_callback);
1364
1365 if (server) {
1366 SSL_set_accept_state(ssl);
1367 } else {
1368 SSL_set_connect_state(ssl);
1369 }
1370
1371 /* Setup verify and seed */
1372 SSL_set_verify_result(ssl, X509_V_OK);
1373 SSL_rand_seed(c->rand_file);
1374
1375 /* Store for later usage in SSL_callback_SSL_verify */
1376 SSL_set_app_data2(ssl, c);
1377 SSL_set_app_data(ssl, con);
1378 /* Register cleanup that prevent double destruction */
1379 apr_pool_cleanup_register(con->pool, (const void *)ssl,
1380 ssl_con_pool_cleanup,
1381 apr_pool_cleanup_null);
1382
1383 return P2J(ssl);
1384 }
1385
TCN_IMPLEMENT_CALL(void,SSL,setBIO)1386 TCN_IMPLEMENT_CALL(void, SSL, setBIO)(TCN_STDARGS,
1387 jlong ssl /* SSL * */,
1388 jlong rbio /* BIO * */,
1389 jlong wbio /* BIO * */) {
1390 UNREFERENCED_STDARGS;
1391 SSL_set_bio(J2P(ssl, SSL *), J2P(rbio, BIO *), J2P(wbio, BIO *));
1392 return;
1393 }
1394
TCN_IMPLEMENT_CALL(jint,SSL,getError)1395 TCN_IMPLEMENT_CALL(jint, SSL, getError)(TCN_STDARGS,
1396 jlong ssl /* SSL * */,
1397 jint ret) {
1398 UNREFERENCED_STDARGS;
1399 return SSL_get_error(J2P(ssl, SSL*), ret);
1400 }
1401
1402 /* How much did SSL write into this BIO? */
TCN_IMPLEMENT_CALL(jint,SSL,pendingWrittenBytesInBIO)1403 TCN_IMPLEMENT_CALL(jint /* nbytes */, SSL, pendingWrittenBytesInBIO)(TCN_STDARGS,
1404 jlong bio /* BIO * */) {
1405 UNREFERENCED_STDARGS;
1406
1407 return BIO_ctrl_pending(J2P(bio, BIO *));
1408 }
1409
1410 /* How much is available for reading in the given SSL struct? */
TCN_IMPLEMENT_CALL(jint,SSL,pendingReadableBytesInSSL)1411 TCN_IMPLEMENT_CALL(jint, SSL, pendingReadableBytesInSSL)(TCN_STDARGS, jlong ssl /* SSL * */) {
1412 UNREFERENCED_STDARGS;
1413
1414 return SSL_pending(J2P(ssl, SSL *));
1415 }
1416
1417 /* Write wlen bytes from wbuf into bio */
TCN_IMPLEMENT_CALL(jint,SSL,writeToBIO)1418 TCN_IMPLEMENT_CALL(jint /* status */, SSL, writeToBIO)(TCN_STDARGS,
1419 jlong bio /* BIO * */,
1420 jlong wbuf /* char* */,
1421 jint wlen /* sizeof(wbuf) */) {
1422 UNREFERENCED_STDARGS;
1423
1424 return BIO_write(J2P(bio, BIO *), J2P(wbuf, void *), wlen);
1425
1426 }
1427
1428 /* Read up to rlen bytes from bio into rbuf */
TCN_IMPLEMENT_CALL(jint,SSL,readFromBIO)1429 TCN_IMPLEMENT_CALL(jint /* status */, SSL, readFromBIO)(TCN_STDARGS,
1430 jlong bio /* BIO * */,
1431 jlong rbuf /* char * */,
1432 jint rlen /* sizeof(rbuf) - 1 */) {
1433 UNREFERENCED_STDARGS;
1434
1435 return BIO_read(J2P(bio, BIO *), J2P(rbuf, void *), rlen);
1436 }
1437
1438 /* Write up to wlen bytes of application data to the ssl BIO (encrypt) */
TCN_IMPLEMENT_CALL(jint,SSL,writeToSSL)1439 TCN_IMPLEMENT_CALL(jint /* status */, SSL, writeToSSL)(TCN_STDARGS,
1440 jlong ssl /* SSL * */,
1441 jlong wbuf /* char * */,
1442 jint wlen /* sizeof(wbuf) */) {
1443 UNREFERENCED_STDARGS;
1444
1445 return SSL_write(J2P(ssl, SSL *), J2P(wbuf, void *), wlen);
1446 }
1447
1448 /* Read up to rlen bytes of application data from the given SSL BIO (decrypt) */
TCN_IMPLEMENT_CALL(jint,SSL,readFromSSL)1449 TCN_IMPLEMENT_CALL(jint /* status */, SSL, readFromSSL)(TCN_STDARGS,
1450 jlong ssl /* SSL * */,
1451 jlong rbuf /* char * */,
1452 jint rlen /* sizeof(rbuf) - 1 */) {
1453 UNREFERENCED_STDARGS;
1454
1455 return SSL_read(J2P(ssl, SSL *), J2P(rbuf, void *), rlen);
1456 }
1457
1458 /* Get the shutdown status of the engine */
TCN_IMPLEMENT_CALL(jint,SSL,getShutdown)1459 TCN_IMPLEMENT_CALL(jint /* status */, SSL, getShutdown)(TCN_STDARGS,
1460 jlong ssl /* SSL * */) {
1461 UNREFERENCED_STDARGS;
1462
1463 return SSL_get_shutdown(J2P(ssl, SSL *));
1464 }
1465
1466 /* Called when the peer closes the connection */
TCN_IMPLEMENT_CALL(void,SSL,setShutdown)1467 TCN_IMPLEMENT_CALL(void, SSL, setShutdown)(TCN_STDARGS,
1468 jlong ssl /* SSL * */,
1469 jint mode) {
1470 UNREFERENCED_STDARGS;
1471
1472 SSL_set_shutdown(J2P(ssl, SSL *), mode);
1473 }
1474
1475 /* Free the SSL * and its associated internal BIO */
TCN_IMPLEMENT_CALL(void,SSL,freeSSL)1476 TCN_IMPLEMENT_CALL(void, SSL, freeSSL)(TCN_STDARGS,
1477 jlong ssl /* SSL * */) {
1478 SSL *ssl_ = J2P(ssl, SSL *);
1479 int *handshakeCount = SSL_get_app_data3(ssl_);
1480 int *destroyCount = SSL_get_app_data4(ssl_);
1481 tcn_ssl_conn_t *con = SSL_get_app_data(ssl_);
1482
1483 UNREFERENCED_STDARGS;
1484
1485 if (destroyCount != NULL) {
1486 if (*destroyCount == 0) {
1487 apr_pool_destroy(con->pool);
1488 }
1489 free(destroyCount);
1490 }
1491 if (handshakeCount != NULL) {
1492 free(handshakeCount);
1493 }
1494 SSL_free(ssl_);
1495 }
1496
1497 /* Make a BIO pair (network and internal) for the provided SSL * and return the network BIO */
TCN_IMPLEMENT_CALL(jlong,SSL,makeNetworkBIO)1498 TCN_IMPLEMENT_CALL(jlong, SSL, makeNetworkBIO)(TCN_STDARGS,
1499 jlong ssl /* SSL * */) {
1500 SSL *ssl_ = J2P(ssl, SSL *);
1501 BIO *internal_bio;
1502 BIO *network_bio;
1503
1504 UNREFERENCED(o);
1505
1506 if (ssl_ == NULL) {
1507 tcn_ThrowException(e, "ssl is null");
1508 goto fail;
1509 }
1510
1511 if (BIO_new_bio_pair(&internal_bio, 0, &network_bio, 0) != 1) {
1512 tcn_ThrowException(e, "BIO_new_bio_pair failed");
1513 goto fail;
1514 }
1515
1516 SSL_set_bio(ssl_, internal_bio, internal_bio);
1517
1518 return P2J(network_bio);
1519 fail:
1520 return 0;
1521 }
1522
1523 /* Free a BIO * (typically, the network BIO) */
TCN_IMPLEMENT_CALL(void,SSL,freeBIO)1524 TCN_IMPLEMENT_CALL(void, SSL, freeBIO)(TCN_STDARGS,
1525 jlong bio /* BIO * */) {
1526 BIO *bio_;
1527 UNREFERENCED_STDARGS;
1528
1529 bio_ = J2P(bio, BIO *);
1530 BIO_free(bio_);
1531 }
1532
1533 /* Send CLOSE_NOTIFY to peer */
TCN_IMPLEMENT_CALL(jint,SSL,shutdownSSL)1534 TCN_IMPLEMENT_CALL(jint /* status */, SSL, shutdownSSL)(TCN_STDARGS,
1535 jlong ssl /* SSL * */) {
1536 UNREFERENCED_STDARGS;
1537
1538 return SSL_shutdown(J2P(ssl, SSL *));
1539 }
1540
1541 /* Read which cipher was negotiated for the given SSL *. */
TCN_IMPLEMENT_CALL(jstring,SSL,getCipherForSSL)1542 TCN_IMPLEMENT_CALL(jstring, SSL, getCipherForSSL)(TCN_STDARGS,
1543 jlong ssl /* SSL * */)
1544 {
1545 UNREFERENCED_STDARGS;
1546
1547 return AJP_TO_JSTRING(SSL_get_cipher(J2P(ssl, SSL*)));
1548 }
1549
1550 /* Read which protocol was negotiated for the given SSL *. */
TCN_IMPLEMENT_CALL(jstring,SSL,getVersion)1551 TCN_IMPLEMENT_CALL(jstring, SSL, getVersion)(TCN_STDARGS,
1552 jlong ssl /* SSL * */)
1553 {
1554 UNREFERENCED_STDARGS;
1555
1556 return AJP_TO_JSTRING(SSL_get_version(J2P(ssl, SSL*)));
1557 }
1558
1559 /* Is the handshake over yet? */
TCN_IMPLEMENT_CALL(jint,SSL,isInInit)1560 TCN_IMPLEMENT_CALL(jint, SSL, isInInit)(TCN_STDARGS,
1561 jlong ssl /* SSL * */) {
1562 SSL *ssl_ = J2P(ssl, SSL *);
1563
1564 UNREFERENCED(o);
1565
1566 if (ssl_ == NULL) {
1567 tcn_ThrowException(e, "ssl is null");
1568 return 0;
1569 } else {
1570 return SSL_in_init(ssl_);
1571 }
1572 }
1573
TCN_IMPLEMENT_CALL(jint,SSL,doHandshake)1574 TCN_IMPLEMENT_CALL(jint, SSL, doHandshake)(TCN_STDARGS,
1575 jlong ssl /* SSL * */) {
1576 SSL *ssl_ = J2P(ssl, SSL *);
1577 if (ssl_ == NULL) {
1578 tcn_ThrowException(e, "ssl is null");
1579 return 0;
1580 }
1581
1582 UNREFERENCED(o);
1583
1584 return SSL_do_handshake(ssl_);
1585 }
1586
TCN_IMPLEMENT_CALL(jint,SSL,renegotiate)1587 TCN_IMPLEMENT_CALL(jint, SSL, renegotiate)(TCN_STDARGS,
1588 jlong ssl /* SSL * */) {
1589 SSL *ssl_ = J2P(ssl, SSL *);
1590 if (ssl_ == NULL) {
1591 tcn_ThrowException(e, "ssl is null");
1592 return 0;
1593 }
1594
1595 UNREFERENCED(o);
1596
1597 return SSL_renegotiate(ssl_);
1598 }
1599
TCN_IMPLEMENT_CALL(jint,SSL,renegotiatePending)1600 TCN_IMPLEMENT_CALL(jint, SSL, renegotiatePending)(TCN_STDARGS,
1601 jlong ssl /* SSL * */) {
1602 SSL *ssl_ = J2P(ssl, SSL *);
1603 if (ssl_ == NULL) {
1604 tcn_ThrowException(e, "ssl is null");
1605 return 0;
1606 }
1607
1608 UNREFERENCED(o);
1609
1610 return SSL_renegotiate_pending(ssl_);
1611 }
1612
TCN_IMPLEMENT_CALL(jint,SSL,verifyClientPostHandshake)1613 TCN_IMPLEMENT_CALL(jint, SSL, verifyClientPostHandshake)(TCN_STDARGS,
1614 jlong ssl /* SSL * */) {
1615 #if defined(SSL_OP_NO_TLSv1_3)
1616 SSL *ssl_ = J2P(ssl, SSL *);
1617 tcn_ssl_conn_t *con;
1618
1619 if (ssl_ == NULL) {
1620 tcn_ThrowException(e, "ssl is null");
1621 return 0;
1622 }
1623
1624 UNREFERENCED(o);
1625
1626 con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl_);
1627 con->pha_state = PHA_STARTED;
1628
1629 return SSL_verify_client_post_handshake(ssl_);
1630 #else
1631 return 0;
1632 #endif
1633 }
1634
TCN_IMPLEMENT_CALL(jint,SSL,getPostHandshakeAuthInProgress)1635 TCN_IMPLEMENT_CALL(jint, SSL, getPostHandshakeAuthInProgress)(TCN_STDARGS,
1636 jlong ssl /* SSL * */) {
1637 #if defined(SSL_OP_NO_TLSv1_3)
1638 SSL *ssl_ = J2P(ssl, SSL *);
1639 tcn_ssl_conn_t *con;
1640
1641 if (ssl_ == NULL) {
1642 tcn_ThrowException(e, "ssl is null");
1643 return 0;
1644 }
1645
1646 UNREFERENCED(o);
1647
1648 con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl_);
1649
1650 return (con->pha_state == PHA_STARTED);
1651 #else
1652 return 0;
1653 #endif
1654 }
1655
1656 /* Read which protocol was negotiated for the given SSL *. */
TCN_IMPLEMENT_CALL(jstring,SSL,getNextProtoNegotiated)1657 TCN_IMPLEMENT_CALL(jstring, SSL, getNextProtoNegotiated)(TCN_STDARGS,
1658 jlong ssl /* SSL * */) {
1659 SSL *ssl_ = J2P(ssl, SSL *);
1660 const unsigned char *proto;
1661 unsigned int proto_len;
1662
1663 if (ssl_ == NULL) {
1664 tcn_ThrowException(e, "ssl is null");
1665 return NULL;
1666 }
1667
1668 UNREFERENCED(o);
1669
1670 SSL_get0_next_proto_negotiated(ssl_, &proto, &proto_len);
1671 return tcn_new_stringn(e, (const char *)proto, (size_t) proto_len);
1672 }
1673
1674 /*** End Twitter API Additions ***/
1675
1676 /*** Apple API Additions ***/
1677
TCN_IMPLEMENT_CALL(jstring,SSL,getAlpnSelected)1678 TCN_IMPLEMENT_CALL(jstring, SSL, getAlpnSelected)(TCN_STDARGS,
1679 jlong ssl /* SSL * */) {
1680 /* Looks fishy we have the same in sslnetwork.c, it set by socket/connection */
1681 SSL *ssl_ = J2P(ssl, SSL *);
1682 const unsigned char *proto;
1683 unsigned int proto_len;
1684
1685 if (ssl_ == NULL) {
1686 tcn_ThrowException(e, "ssl is null");
1687 return NULL;
1688 }
1689
1690 UNREFERENCED(o);
1691
1692 SSL_get0_alpn_selected(ssl_, &proto, &proto_len);
1693 return tcn_new_stringn(e, (const char *) proto, (size_t) proto_len);
1694 }
1695
TCN_IMPLEMENT_CALL(jobjectArray,SSL,getPeerCertChain)1696 TCN_IMPLEMENT_CALL(jobjectArray, SSL, getPeerCertChain)(TCN_STDARGS,
1697 jlong ssl /* SSL * */)
1698 {
1699 STACK_OF(X509) *sk;
1700 int len;
1701 int i;
1702 X509 *cert;
1703 int length;
1704 unsigned char *buf;
1705 jobjectArray array;
1706 jbyteArray bArray;
1707
1708 SSL *ssl_ = J2P(ssl, SSL *);
1709
1710 if (ssl_ == NULL) {
1711 tcn_ThrowException(e, "ssl is null");
1712 return NULL;
1713 }
1714
1715 UNREFERENCED(o);
1716
1717 // Get a stack of all certs in the chain.
1718 sk = SSL_get_peer_cert_chain(ssl_);
1719
1720 len = sk_X509_num(sk);
1721 if (len <= 0) {
1722 /* No peer certificate chain as no auth took place yet, or the auth was not successful. */
1723 return NULL;
1724 }
1725 /* Create the byte[][] array that holds all the certs */
1726 array = (*e)->NewObjectArray(e, len, byteArrayClass, NULL);
1727
1728 for(i = 0; i < len; i++) {
1729 cert = (X509*) sk_X509_value(sk, i);
1730
1731 buf = NULL;
1732 length = i2d_X509(cert, &buf);
1733 if (length < 0) {
1734 OPENSSL_free(buf);
1735 /* In case of error just return an empty byte[][] */
1736 return (*e)->NewObjectArray(e, 0, byteArrayClass, NULL);
1737 }
1738 bArray = (*e)->NewByteArray(e, length);
1739 (*e)->SetByteArrayRegion(e, bArray, 0, length, (jbyte*) buf);
1740 (*e)->SetObjectArrayElement(e, array, i, bArray);
1741
1742 /*
1743 * Delete the local reference as we not know how long the chain is and local references are otherwise
1744 * only freed once jni method returns.
1745 */
1746 (*e)->DeleteLocalRef(e, bArray);
1747
1748 OPENSSL_free(buf);
1749 }
1750 return array;
1751 }
1752
TCN_IMPLEMENT_CALL(jbyteArray,SSL,getPeerCertificate)1753 TCN_IMPLEMENT_CALL(jbyteArray, SSL, getPeerCertificate)(TCN_STDARGS,
1754 jlong ssl /* SSL * */)
1755 {
1756 X509 *cert;
1757 int length;
1758 unsigned char *buf = NULL;
1759 jbyteArray bArray;
1760
1761 SSL *ssl_ = J2P(ssl, SSL *);
1762
1763 if (ssl_ == NULL) {
1764 tcn_ThrowException(e, "ssl is null");
1765 return NULL;
1766 }
1767
1768 UNREFERENCED(o);
1769
1770 /* Get a stack of all certs in the chain */
1771 cert = SSL_get_peer_certificate(ssl_);
1772 if (cert == NULL) {
1773 return NULL;
1774 }
1775
1776 length = i2d_X509(cert, &buf);
1777
1778 bArray = (*e)->NewByteArray(e, length);
1779 (*e)->SetByteArrayRegion(e, bArray, 0, length, (jbyte*) buf);
1780
1781 /*
1782 * We need to free the cert as the reference count is incremented by one and it is not destroyed when the
1783 * session is freed.
1784 * See https://www.openssl.org/docs/ssl/SSL_get_peer_certificate.html
1785 */
1786 X509_free(cert);
1787
1788 OPENSSL_free(buf);
1789
1790 return bArray;
1791 }
1792
TCN_IMPLEMENT_CALL(jstring,SSL,getErrorString)1793 TCN_IMPLEMENT_CALL(jstring, SSL, getErrorString)(TCN_STDARGS, jlong number)
1794 {
1795 char buf[256];
1796 UNREFERENCED(o);
1797 ERR_error_string(number, buf);
1798 return tcn_new_string(e, buf);
1799 }
1800
TCN_IMPLEMENT_CALL(jlong,SSL,getTime)1801 TCN_IMPLEMENT_CALL(jlong, SSL, getTime)(TCN_STDARGS, jlong ssl)
1802 {
1803 const SSL *ssl_ = J2P(ssl, SSL *);
1804 const SSL_SESSION *session;
1805
1806 if (ssl_ == NULL) {
1807 tcn_ThrowException(e, "ssl is null");
1808 return 0;
1809 }
1810
1811 UNREFERENCED(o);
1812
1813 session = SSL_get_session(ssl_);
1814 if (session) {
1815 return SSL_get_time(session);
1816 } else {
1817 tcn_ThrowException(e, "ssl session is null");
1818 return 0;
1819 }
1820 }
1821
TCN_IMPLEMENT_CALL(void,SSL,setVerify)1822 TCN_IMPLEMENT_CALL(void, SSL, setVerify)(TCN_STDARGS, jlong ssl,
1823 jint level, jint depth)
1824 {
1825 tcn_ssl_ctxt_t *c;
1826 int verify;
1827 SSL *ssl_ = J2P(ssl, SSL *);
1828
1829 if (ssl_ == NULL) {
1830 tcn_ThrowException(e, "ssl is null");
1831 return;
1832 }
1833
1834 c = SSL_get_app_data2(ssl_);
1835
1836 verify = SSL_VERIFY_NONE;
1837
1838 UNREFERENCED(o);
1839
1840 if (c == NULL) {
1841 tcn_ThrowException(e, "context is null");
1842 return;
1843 }
1844 c->verify_mode = level;
1845
1846 if (c->verify_mode == SSL_CVERIFY_UNSET)
1847 c->verify_mode = SSL_CVERIFY_NONE;
1848 if (depth > 0)
1849 c->verify_depth = depth;
1850 /*
1851 * Configure callbacks for SSL context
1852 */
1853 if (c->verify_mode == SSL_CVERIFY_REQUIRE)
1854 verify |= SSL_VERIFY_PEER_STRICT;
1855 if ((c->verify_mode == SSL_CVERIFY_OPTIONAL) ||
1856 (c->verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
1857 verify |= SSL_VERIFY_PEER;
1858 if (!c->store) {
1859 if (SSL_CTX_set_default_verify_paths(c->ctx)) {
1860 c->store = SSL_CTX_get_cert_store(c->ctx);
1861 X509_STORE_set_flags(c->store, 0);
1862 }
1863 else {
1864 /* XXX: See if this is fatal */
1865 }
1866 }
1867
1868 SSL_set_verify(ssl_, verify, SSL_callback_SSL_verify);
1869 }
1870
TCN_IMPLEMENT_CALL(void,SSL,setOptions)1871 TCN_IMPLEMENT_CALL(void, SSL, setOptions)(TCN_STDARGS, jlong ssl,
1872 jint opt)
1873 {
1874 SSL *ssl_ = J2P(ssl, SSL *);
1875
1876 UNREFERENCED_STDARGS;
1877
1878 if (ssl_ == NULL) {
1879 tcn_ThrowException(e, "ssl is null");
1880 return;
1881 }
1882
1883 #ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
1884 /* Clear the flag if not supported */
1885 if (opt & 0x00040000) {
1886 opt &= ~0x00040000;
1887 }
1888 #endif
1889 SSL_set_options(ssl_, opt);
1890 }
1891
TCN_IMPLEMENT_CALL(jint,SSL,getOptions)1892 TCN_IMPLEMENT_CALL(jint, SSL, getOptions)(TCN_STDARGS, jlong ssl)
1893 {
1894 SSL *ssl_ = J2P(ssl, SSL *);
1895
1896 UNREFERENCED_STDARGS;
1897
1898 if (ssl_ == NULL) {
1899 tcn_ThrowException(e, "ssl is null");
1900 return 0;
1901 }
1902
1903 return SSL_get_options(ssl_);
1904 }
1905
TCN_IMPLEMENT_CALL(jobjectArray,SSL,getCiphers)1906 TCN_IMPLEMENT_CALL(jobjectArray, SSL, getCiphers)(TCN_STDARGS, jlong ssl)
1907 {
1908 STACK_OF(SSL_CIPHER) *sk;
1909 int len;
1910 jobjectArray array;
1911 SSL_CIPHER *cipher;
1912 const char *name;
1913 int i;
1914 jstring c_name;
1915 SSL *ssl_ = J2P(ssl, SSL *);
1916
1917 UNREFERENCED_STDARGS;
1918
1919 if (ssl_ == NULL) {
1920 tcn_ThrowException(e, "ssl is null");
1921 return NULL;
1922 }
1923
1924 sk = SSL_get_ciphers(ssl_);
1925 len = sk_SSL_CIPHER_num(sk);
1926
1927 if (len <= 0) {
1928 /* No peer certificate chain as no auth took place yet, or the auth was not successful. */
1929 return NULL;
1930 }
1931
1932 /* Create the byte[][] array that holds all the certs */
1933 array = (*e)->NewObjectArray(e, len, stringClass, NULL);
1934
1935 for (i = 0; i < len; i++) {
1936 cipher = (SSL_CIPHER*) sk_SSL_CIPHER_value(sk, i);
1937 name = SSL_CIPHER_get_name(cipher);
1938
1939 c_name = (*e)->NewStringUTF(e, name);
1940 (*e)->SetObjectArrayElement(e, array, i, c_name);
1941 }
1942 return array;
1943 }
1944
TCN_IMPLEMENT_CALL(jboolean,SSL,setCipherSuites)1945 TCN_IMPLEMENT_CALL(jboolean, SSL, setCipherSuites)(TCN_STDARGS, jlong ssl,
1946 jstring ciphers)
1947 {
1948 jboolean rv = JNI_TRUE;
1949 SSL *ssl_ = J2P(ssl, SSL *);
1950 TCN_ALLOC_CSTRING(ciphers);
1951
1952 UNREFERENCED_STDARGS;
1953
1954 if (ssl_ == NULL) {
1955 TCN_FREE_CSTRING(ciphers);
1956 tcn_ThrowException(e, "ssl is null");
1957 return JNI_FALSE;
1958 }
1959
1960 UNREFERENCED(o);
1961 if (!J2S(ciphers)) {
1962 TCN_FREE_CSTRING(ciphers);
1963 return JNI_FALSE;
1964 }
1965 if (!SSL_set_cipher_list(ssl_, J2S(ciphers))) {
1966 char err[256];
1967 ERR_error_string(SSL_ERR_get(), err);
1968 tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
1969 rv = JNI_FALSE;
1970 }
1971 TCN_FREE_CSTRING(ciphers);
1972 return rv;
1973 }
1974
TCN_IMPLEMENT_CALL(jbyteArray,SSL,getSessionId)1975 TCN_IMPLEMENT_CALL(jbyteArray, SSL, getSessionId)(TCN_STDARGS, jlong ssl)
1976 {
1977
1978 unsigned int len;
1979 const unsigned char *session_id;
1980 const SSL_SESSION *session;
1981 jbyteArray bArray;
1982 SSL *ssl_ = J2P(ssl, SSL *);
1983 if (ssl_ == NULL) {
1984 tcn_ThrowException(e, "ssl is null");
1985 return NULL;
1986 }
1987 UNREFERENCED(o);
1988 session = SSL_get_session(ssl_);
1989 session_id = SSL_SESSION_get_id(session, &len);
1990
1991 if (len == 0 || session_id == NULL) {
1992 return NULL;
1993 }
1994
1995 bArray = (*e)->NewByteArray(e, len);
1996 (*e)->SetByteArrayRegion(e, bArray, 0, len, (jbyte*) session_id);
1997 return bArray;
1998 }
1999
TCN_IMPLEMENT_CALL(jint,SSL,getHandshakeCount)2000 TCN_IMPLEMENT_CALL(jint, SSL, getHandshakeCount)(TCN_STDARGS, jlong ssl)
2001 {
2002 int *handshakeCount = NULL;
2003 SSL *ssl_ = J2P(ssl, SSL *);
2004 if (ssl_ == NULL) {
2005 tcn_ThrowException(e, "ssl is null");
2006 return -1;
2007 }
2008 UNREFERENCED(o);
2009
2010 handshakeCount = SSL_get_app_data3(ssl_);
2011 if (handshakeCount != NULL) {
2012 return *handshakeCount;
2013 }
2014 return 0;
2015 }
2016
2017 /*** End Apple API Additions ***/
2018
2019 #else /* HAVE_OPENSSL */
2020 /* OpenSSL is not supported.
2021 * Create empty stubs.
2022 */
2023
TCN_IMPLEMENT_CALL(jint,SSL,version)2024 TCN_IMPLEMENT_CALL(jint, SSL, version)(TCN_STDARGS)
2025 {
2026 UNREFERENCED_STDARGS;
2027 return 0;
2028 }
2029
TCN_IMPLEMENT_CALL(jstring,SSL,versionString)2030 TCN_IMPLEMENT_CALL(jstring, SSL, versionString)(TCN_STDARGS)
2031 {
2032 UNREFERENCED_STDARGS;
2033 return NULL;
2034 }
2035
TCN_IMPLEMENT_CALL(jint,SSL,initialize)2036 TCN_IMPLEMENT_CALL(jint, SSL, initialize)(TCN_STDARGS, jstring engine)
2037 {
2038 UNREFERENCED(o);
2039 UNREFERENCED(engine);
2040 tcn_ThrowAPRException(e, APR_ENOTIMPL);
2041 return (jint)APR_ENOTIMPL;
2042 }
2043
TCN_IMPLEMENT_CALL(jboolean,SSL,randLoad)2044 TCN_IMPLEMENT_CALL(jboolean, SSL, randLoad)(TCN_STDARGS, jstring file)
2045 {
2046 UNREFERENCED_STDARGS;
2047 UNREFERENCED(file);
2048 return JNI_FALSE;
2049 }
2050
TCN_IMPLEMENT_CALL(jboolean,SSL,randSave)2051 TCN_IMPLEMENT_CALL(jboolean, SSL, randSave)(TCN_STDARGS, jstring file)
2052 {
2053 UNREFERENCED_STDARGS;
2054 return JNI_FALSE;
2055 }
2056
TCN_IMPLEMENT_CALL(jboolean,SSL,randMake)2057 TCN_IMPLEMENT_CALL(jboolean, SSL, randMake)(TCN_STDARGS, jstring file,
2058 jint length, jboolean base64)
2059 {
2060 UNREFERENCED_STDARGS;
2061 UNREFERENCED(file);
2062 UNREFERENCED(length);
2063 UNREFERENCED(base64);
2064 return JNI_FALSE;
2065 }
2066
TCN_IMPLEMENT_CALL(void,SSL,randSet)2067 TCN_IMPLEMENT_CALL(void, SSL, randSet)(TCN_STDARGS, jstring file)
2068 {
2069 UNREFERENCED_STDARGS;
2070 UNREFERENCED(file);
2071 }
2072
TCN_IMPLEMENT_CALL(jint,SSL,fipsModeGet)2073 TCN_IMPLEMENT_CALL(jint, SSL, fipsModeGet)(TCN_STDARGS)
2074 {
2075 UNREFERENCED(o);
2076 tcn_ThrowException(e, "FIPS was not available to tcnative at build time. You will need to re-build tcnative against an OpenSSL with FIPS.");
2077 return 0;
2078 }
2079
TCN_IMPLEMENT_CALL(jint,SSL,fipsModeSet)2080 TCN_IMPLEMENT_CALL(jint, SSL, fipsModeSet)(TCN_STDARGS, jint mode)
2081 {
2082 UNREFERENCED(o);
2083 UNREFERENCED(mode);
2084 tcn_ThrowException(e, "FIPS was not available to tcnative at build time. You will need to re-build tcnative against an OpenSSL with FIPS.");
2085 return 0;
2086 }
2087
TCN_IMPLEMENT_CALL(jlong,SSL,newBIO)2088 TCN_IMPLEMENT_CALL(jlong, SSL, newBIO)(TCN_STDARGS, jlong pool,
2089 jobject callback)
2090 {
2091 UNREFERENCED_STDARGS;
2092 UNREFERENCED(pool);
2093 UNREFERENCED(callback);
2094 return 0;
2095 }
2096
TCN_IMPLEMENT_CALL(jint,SSL,closeBIO)2097 TCN_IMPLEMENT_CALL(jint, SSL, closeBIO)(TCN_STDARGS, jlong bio)
2098 {
2099 UNREFERENCED_STDARGS;
2100 UNREFERENCED(bio);
2101 return (jint)APR_ENOTIMPL;
2102 }
2103
TCN_IMPLEMENT_CALL(void,SSL,setPasswordCallback)2104 TCN_IMPLEMENT_CALL(void, SSL, setPasswordCallback)(TCN_STDARGS,
2105 jobject callback)
2106 {
2107 UNREFERENCED_STDARGS;
2108 UNREFERENCED(callback);
2109 }
2110
TCN_IMPLEMENT_CALL(void,SSL,setPassword)2111 TCN_IMPLEMENT_CALL(void, SSL, setPassword)(TCN_STDARGS, jstring password)
2112 {
2113 UNREFERENCED_STDARGS;
2114 UNREFERENCED(password);
2115 }
2116
TCN_IMPLEMENT_CALL(jboolean,SSL,generateRSATempKey)2117 TCN_IMPLEMENT_CALL(jboolean, SSL, generateRSATempKey)(TCN_STDARGS, jint idx)
2118 {
2119 UNREFERENCED_STDARGS;
2120 UNREFERENCED(idx);
2121 return JNI_FALSE;
2122 }
2123
TCN_IMPLEMENT_CALL(jboolean,SSL,loadDSATempKey)2124 TCN_IMPLEMENT_CALL(jboolean, SSL, loadDSATempKey)(TCN_STDARGS, jint idx,
2125 jstring file)
2126 {
2127 UNREFERENCED_STDARGS;
2128 UNREFERENCED(idx);
2129 UNREFERENCED(file);
2130 return JNI_FALSE;
2131 }
2132
TCN_IMPLEMENT_CALL(jstring,SSL,getLastError)2133 TCN_IMPLEMENT_CALL(jstring, SSL, getLastError)(TCN_STDARGS)
2134 {
2135 UNREFERENCED_STDARGS;
2136 return NULL;
2137 }
2138
TCN_IMPLEMENT_CALL(jboolean,SSL,hasOp)2139 TCN_IMPLEMENT_CALL(jboolean, SSL, hasOp)(TCN_STDARGS, jint op)
2140 {
2141 UNREFERENCED_STDARGS;
2142 UNREFERENCED(op);
2143 return JNI_FALSE;
2144 }
2145
2146 /*** Begin Twitter 1:1 API addition ***/
TCN_IMPLEMENT_CALL(jint,SSL,getLastErrorNumber)2147 TCN_IMPLEMENT_CALL(jint, SSL, getLastErrorNumber)(TCN_STDARGS) {
2148 UNREFERENCED(o);
2149 tcn_ThrowException(e, "Not implemented");
2150 return 0;
2151 }
2152
TCN_IMPLEMENT_CALL(jlong,SSL,newSSL)2153 TCN_IMPLEMENT_CALL(jlong /* SSL * */, SSL, newSSL)(TCN_STDARGS,
2154 jlong ctx /* tcn_ssl_ctxt_t * */,
2155 jboolean server) {
2156 UNREFERENCED(o);
2157 UNREFERENCED(ctx);
2158 UNREFERENCED(server);
2159 tcn_ThrowException(e, "Not implemented");
2160 return 0;
2161 }
2162
TCN_IMPLEMENT_CALL(void,SSL,setBIO)2163 TCN_IMPLEMENT_CALL(void, SSL, setBIO)(TCN_STDARGS, jlong ssl, jlong rbio, jlong wbio) {
2164 UNREFERENCED(o);
2165 UNREFERENCED(ssl);
2166 UNREFERENCED(rbio);
2167 UNREFERENCED(wbio);
2168 tcn_ThrowException(e, "Not implemented");
2169 }
2170
TCN_IMPLEMENT_CALL(jint,SSL,pendingWrittenBytesInBIO)2171 TCN_IMPLEMENT_CALL(jint, SSL, pendingWrittenBytesInBIO)(TCN_STDARGS, jlong bio) {
2172 UNREFERENCED(o);
2173 UNREFERENCED(bio);
2174 tcn_ThrowException(e, "Not implemented");
2175 return 0;
2176 }
2177
TCN_IMPLEMENT_CALL(jint,SSL,pendingReadableBytesInSSL)2178 TCN_IMPLEMENT_CALL(jint, SSL, pendingReadableBytesInSSL)(TCN_STDARGS, jlong ssl) {
2179 UNREFERENCED(o);
2180 UNREFERENCED(ssl);
2181 tcn_ThrowException(e, "Not implemented");
2182 return 0;
2183 }
2184
TCN_IMPLEMENT_CALL(jint,SSL,writeToBIO)2185 TCN_IMPLEMENT_CALL(jint, SSL, writeToBIO)(TCN_STDARGS, jlong bio, jlong wbuf, jint wlen) {
2186 UNREFERENCED(o);
2187 UNREFERENCED(bio);
2188 UNREFERENCED(wbuf);
2189 UNREFERENCED(wlen);
2190 tcn_ThrowException(e, "Not implemented");
2191 return 0;
2192 }
2193
TCN_IMPLEMENT_CALL(jint,SSL,readFromBIO)2194 TCN_IMPLEMENT_CALL(jint, SSL, readFromBIO)(TCN_STDARGS, jlong bio, jlong rbuf, jint rlen) {
2195 UNREFERENCED(o);
2196 UNREFERENCED(bio);
2197 UNREFERENCED(rbuf);
2198 UNREFERENCED(rlen);
2199 tcn_ThrowException(e, "Not implemented");
2200 return 0;
2201 }
2202
TCN_IMPLEMENT_CALL(jint,SSL,writeToSSL)2203 TCN_IMPLEMENT_CALL(jint, SSL, writeToSSL)(TCN_STDARGS, jlong ssl, jlong wbuf, jint wlen) {
2204 UNREFERENCED(o);
2205 UNREFERENCED(ssl);
2206 UNREFERENCED(wbuf);
2207 UNREFERENCED(wlen);
2208 tcn_ThrowException(e, "Not implemented");
2209 return 0;
2210 }
2211
TCN_IMPLEMENT_CALL(jint,SSL,readFromSSL)2212 TCN_IMPLEMENT_CALL(jint, SSL, readFromSSL)(TCN_STDARGS, jlong ssl, jlong rbuf, jint rlen) {
2213 UNREFERENCED(o);
2214 UNREFERENCED(ssl);
2215 UNREFERENCED(rbuf);
2216 UNREFERENCED(rlen);
2217 tcn_ThrowException(e, "Not implemented");
2218 return 0;
2219 }
2220
TCN_IMPLEMENT_CALL(jint,SSL,getShutdown)2221 TCN_IMPLEMENT_CALL(jint, SSL, getShutdown)(TCN_STDARGS, jlong ssl) {
2222 UNREFERENCED(o);
2223 UNREFERENCED(ssl);
2224 tcn_ThrowException(e, "Not implemented");
2225 return 0;
2226 }
2227
TCN_IMPLEMENT_CALL(void,SSL,setShutdown)2228 TCN_IMPLEMENT_CALL(void, SSL, setShutdown)(TCN_STDARGS, jlong ssl, jint mode) {
2229 UNREFERENCED(o);
2230 UNREFERENCED(ssl);
2231 UNREFERENCED(mode);
2232 tcn_ThrowException(e, "Not implemented");
2233 }
2234
TCN_IMPLEMENT_CALL(void,SSL,freeSSL)2235 TCN_IMPLEMENT_CALL(void, SSL, freeSSL)(TCN_STDARGS, jlong ssl) {
2236 UNREFERENCED(o);
2237 UNREFERENCED(ssl);
2238 tcn_ThrowException(e, "Not implemented");
2239 }
2240
TCN_IMPLEMENT_CALL(jlong,SSL,makeNetworkBIO)2241 TCN_IMPLEMENT_CALL(jlong, SSL, makeNetworkBIO)(TCN_STDARGS, jlong ssl) {
2242 UNREFERENCED(o);
2243 UNREFERENCED(ssl);
2244 tcn_ThrowException(e, "Not implemented");
2245 return 0;
2246 }
2247
TCN_IMPLEMENT_CALL(void,SSL,freeBIO)2248 TCN_IMPLEMENT_CALL(void, SSL, freeBIO)(TCN_STDARGS, jlong bio) {
2249 UNREFERENCED(o);
2250 UNREFERENCED(bio);
2251 tcn_ThrowException(e, "Not implemented");
2252 }
2253
TCN_IMPLEMENT_CALL(jint,SSL,shutdownSSL)2254 TCN_IMPLEMENT_CALL(jint, SSL, shutdownSSL)(TCN_STDARGS, jlong ssl) {
2255 UNREFERENCED(o);
2256 UNREFERENCED(ssl);
2257 tcn_ThrowException(e, "Not implemented");
2258 return 0;
2259 }
2260
TCN_IMPLEMENT_CALL(jstring,SSL,getCipherForSSL)2261 TCN_IMPLEMENT_CALL(jstring, SSL, getCipherForSSL)(TCN_STDARGS, jlong ssl) {
2262 UNREFERENCED(o);
2263 UNREFERENCED(ssl);
2264 tcn_ThrowException(e, "Not implemented");
2265 return NULL;
2266 }
2267
TCN_IMPLEMENT_CALL(jint,SSL,isInInit)2268 TCN_IMPLEMENT_CALL(jint, SSL, isInInit)(TCN_STDARGS, jlong ssl) {
2269 UNREFERENCED(o);
2270 UNREFERENCED(ssl);
2271 tcn_ThrowException(e, "Not implemented");
2272 return 0;
2273 }
2274
TCN_IMPLEMENT_CALL(jint,SSL,doHandshake)2275 TCN_IMPLEMENT_CALL(jint, SSL, doHandshake)(TCN_STDARGS, jlong ssl) {
2276 UNREFERENCED(o);
2277 UNREFERENCED(ssl);
2278 tcn_ThrowException(e, "Not implemented");
2279 return 0;
2280 }
2281
TCN_IMPLEMENT_CALL(jint,SSL,renegotiate)2282 TCN_IMPLEMENT_CALL(jint, SSL, renegotiate)(TCN_STDARGS, jlong ssl) {
2283 UNREFERENCED(o);
2284 UNREFERENCED(ssl);
2285 tcn_ThrowException(e, "Not implemented");
2286 return 0;
2287 }
2288
TCN_IMPLEMENT_CALL(jint,SSL,renegotiatePending)2289 TCN_IMPLEMENT_CALL(jint, SSL, renegotiatePending)(TCN_STDARGS, jlong ssl) {
2290 UNREFERENCED(o);
2291 UNREFERENCED(ssl);
2292 tcn_ThrowException(e, "Not implemented");
2293 return 0;
2294 }
2295
TCN_IMPLEMENT_CALL(jint,SSL,verifyClientPostHandshake)2296 TCN_IMPLEMENT_CALL(jint, SSL, verifyClientPostHandshake)(TCN_STDARGS, jlong ssl) {
2297 UNREFERENCED(o);
2298 UNREFERENCED(ssl);
2299 tcn_ThrowException(e, "Not implemented");
2300 return 0;
2301 }
2302
TCN_IMPLEMENT_CALL(jint,SSL,getPostHandshakeAuthInProgress)2303 TCN_IMPLEMENT_CALL(jint, SSL, getPostHandshakeAuthInProgress)(TCN_STDARGS, jlong ssl) {
2304 UNREFERENCED(o);
2305 UNREFERENCED(ssl);
2306 tcn_ThrowException(e, "Not implemented");
2307 return 0;
2308 }
2309
TCN_IMPLEMENT_CALL(jstring,SSL,getNextProtoNegotiated)2310 TCN_IMPLEMENT_CALL(jstring, SSL, getNextProtoNegotiated)(TCN_STDARGS, jlong ssl) {
2311 UNREFERENCED(o);
2312 UNREFERENCED(ssl);
2313 tcn_ThrowException(e, "Not implemented");
2314 return NULL;
2315 }
2316
2317 /*** End Twitter 1:1 API addition ***/
2318
2319 /*** Begin Apple 1:1 API addition ***/
2320
TCN_IMPLEMENT_CALL(jstring,SSL,getAlpnSelected)2321 TCN_IMPLEMENT_CALL(jstring, SSL, getAlpnSelected)(TCN_STDARGS, jlong ssl) {
2322 UNREFERENCED(o);
2323 UNREFERENCED(ssl);
2324 tcn_ThrowException(e, "Not implemented");
2325 return NULL;
2326 }
2327
TCN_IMPLEMENT_CALL(jobjectArray,SSL,getPeerCertChain)2328 TCN_IMPLEMENT_CALL(jobjectArray, SSL, getPeerCertChain)(TCN_STDARGS, jlong ssl)
2329 {
2330 UNREFERENCED(o);
2331 UNREFERENCED(ssl);
2332 tcn_ThrowException(e, "Not implemented");
2333 return NULL;
2334 }
2335
TCN_IMPLEMENT_CALL(jbyteArray,SSL,getPeerCertificate)2336 TCN_IMPLEMENT_CALL(jbyteArray, SSL, getPeerCertificate)(TCN_STDARGS, jlong ssl)
2337 {
2338 UNREFERENCED(o);
2339 UNREFERENCED(ssl);
2340 tcn_ThrowException(e, "Not implemented");
2341 return NULL;
2342 }
2343
TCN_IMPLEMENT_CALL(jstring,SSL,getErrorString)2344 TCN_IMPLEMENT_CALL(jstring, SSL, getErrorString)(TCN_STDARGS, jlong number)
2345 {
2346 UNREFERENCED(o);
2347 UNREFERENCED(number);
2348 tcn_ThrowException(e, "Not implemented");
2349 return NULL;
2350 }
2351
TCN_IMPLEMENT_CALL(jstring,SSL,getVersion)2352 TCN_IMPLEMENT_CALL(jstring, SSL, getVersion)(TCN_STDARGS, jlong ssl)
2353 {
2354 UNREFERENCED(o);
2355 UNREFERENCED(ssl);
2356 tcn_ThrowException(e, "Not implemented");
2357 return NULL;
2358 }
2359
TCN_IMPLEMENT_CALL(jlong,SSL,getTime)2360 TCN_IMPLEMENT_CALL(jlong, SSL, getTime)(TCN_STDARGS, jlong ssl)
2361 {
2362 UNREFERENCED(o);
2363 UNREFERENCED(ssl);
2364 tcn_ThrowException(e, "Not implemented");
2365 return 0;
2366 }
2367
TCN_IMPLEMENT_CALL(void,SSL,setVerify)2368 TCN_IMPLEMENT_CALL(void, SSL, setVerify)(TCN_STDARGS, jlong ssl,
2369 jint level, jint depth)
2370 {
2371 UNREFERENCED(o);
2372 UNREFERENCED(ssl);
2373 tcn_ThrowException(e, "Not implemented");
2374 }
2375
TCN_IMPLEMENT_CALL(void,SSL,setOptions)2376 TCN_IMPLEMENT_CALL(void, SSL, setOptions)(TCN_STDARGS, jlong ssl,
2377 jint opt)
2378 {
2379 UNREFERENCED_STDARGS;
2380 UNREFERENCED(ssl);
2381 UNREFERENCED(opt);
2382 tcn_ThrowException(e, "Not implemented");
2383 }
2384
TCN_IMPLEMENT_CALL(jint,SSL,getOptions)2385 TCN_IMPLEMENT_CALL(jint, SSL, getOptions)(TCN_STDARGS, jlong ssl)
2386 {
2387 UNREFERENCED_STDARGS;
2388 UNREFERENCED(ssl);
2389 tcn_ThrowException(e, "Not implemented");
2390 return 0;
2391 }
TCN_IMPLEMENT_CALL(jobjectArray,SSL,getCiphers)2392 TCN_IMPLEMENT_CALL(jobjectArray, SSL, getCiphers)(TCN_STDARGS, jlong ssl)
2393 {
2394 UNREFERENCED_STDARGS;
2395 UNREFERENCED(ssl);
2396 tcn_ThrowException(e, "Not implemented");
2397 return 0;
2398 }
TCN_IMPLEMENT_CALL(jboolean,SSL,setCipherSuites)2399 TCN_IMPLEMENT_CALL(jboolean, SSL, setCipherSuites)(TCN_STDARGS, jlong ssl,
2400 jstring ciphers)
2401 {
2402 UNREFERENCED_STDARGS;
2403 UNREFERENCED(ssl);
2404 UNREFERENCED(ciphers);
2405 tcn_ThrowException(e, "Not implemented");
2406 return JNI_FALSE;
2407 }
TCN_IMPLEMENT_CALL(jbyteArray,SSL,getSessionId)2408 TCN_IMPLEMENT_CALL(jbyteArray, SSL, getSessionId)(TCN_STDARGS, jlong ssl)
2409 {
2410 UNREFERENCED(o);
2411 UNREFERENCED(ssl);
2412 tcn_ThrowException(e, "Not implemented");
2413 return 0;
2414 }
TCN_IMPLEMENT_CALL(jint,SSL,getHandshakeCount)2415 TCN_IMPLEMENT_CALL(jint, SSL, getHandshakeCount)(TCN_STDARGS, jlong ssl)
2416 {
2417 UNREFERENCED(o);
2418 UNREFERENCED(ssl);
2419 tcn_ThrowException(e, "Not implemented");
2420 return 0;
2421 }
2422 /*** End Apple API Additions ***/
2423 #endif /* HAVE_OPENSSL */
2424