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