OLD | NEW |
| (Empty) |
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 /** SSL network wrapper | |
18 * | |
19 * @author Mladen Turk | |
20 * @version $Id: sslnetwork.c 1658646 2015-02-10 09:00:11Z rjung $ | |
21 */ | |
22 | |
23 #include "tcn.h" | |
24 #include "apr_thread_mutex.h" | |
25 #include "apr_poll.h" | |
26 | |
27 | |
28 #ifdef HAVE_OPENSSL | |
29 #include "ssl_private.h" | |
30 | |
31 #ifdef TCN_DO_STATISTICS | |
32 #include "apr_atomic.h" | |
33 | |
34 static volatile apr_uint32_t ssl_created = 0; | |
35 static volatile apr_uint32_t ssl_closed = 0; | |
36 static volatile apr_uint32_t ssl_cleared = 0; | |
37 static volatile apr_uint32_t ssl_accepted = 0; | |
38 | |
39 void ssl_network_dump_statistics() | |
40 { | |
41 fprintf(stderr, "SSL Network Statistics ..\n"); | |
42 fprintf(stderr, "Sockets created : %d\n", ssl_created); | |
43 fprintf(stderr, "Sockets accepted : %d\n", ssl_accepted); | |
44 fprintf(stderr, "Sockets closed : %d\n", ssl_closed); | |
45 fprintf(stderr, "Sockets cleared : %d\n", ssl_cleared); | |
46 } | |
47 | |
48 #endif | |
49 | |
50 static int ssl_smart_shutdown(SSL *ssl, int shutdown_type) | |
51 { | |
52 int i; | |
53 int rc = 0; | |
54 | |
55 switch (shutdown_type) { | |
56 case SSL_SHUTDOWN_TYPE_UNCLEAN: | |
57 /* perform no close notify handshake at all | |
58 * (violates the SSL/TLS standard!) | |
59 */ | |
60 shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN; | |
61 break; | |
62 case SSL_SHUTDOWN_TYPE_ACCURATE: | |
63 /* send close notify and wait for clients close notify | |
64 * (standard compliant, but usually causes connection hangs) | |
65 */ | |
66 shutdown_type = 0; | |
67 break; | |
68 default: | |
69 /* | |
70 * case SSL_SHUTDOWN_TYPE_UNSET: | |
71 * case SSL_SHUTDOWN_TYPE_STANDARD: | |
72 * send close notify, but don't wait for clients close notify | |
73 * (standard compliant and safe, so it's the DEFAULT!) | |
74 */ | |
75 shutdown_type = SSL_RECEIVED_SHUTDOWN; | |
76 break; | |
77 } | |
78 | |
79 SSL_set_shutdown(ssl, shutdown_type); | |
80 /* | |
81 * Repeat the calls, because SSL_shutdown internally dispatches through a | |
82 * little state machine. Usually only one or two interation should be | |
83 * needed, so we restrict the total number of restrictions in order to | |
84 * avoid process hangs in case the client played bad with the socket | |
85 * connection and OpenSSL cannot recognize it. | |
86 * max 2x pending + 2x data = 4 | |
87 */ | |
88 for (i = 0; i < 4; i++) { | |
89 if ((rc = SSL_shutdown(ssl))) | |
90 break; | |
91 } | |
92 return rc; | |
93 } | |
94 | |
95 static apr_status_t ssl_cleanup(void *data) | |
96 { | |
97 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)data; | |
98 | |
99 if (con) { | |
100 /* Pollset was already destroyed by | |
101 * the pool cleanup/destroy. | |
102 */ | |
103 con->pollset = NULL; | |
104 if (con->ssl) { | |
105 SSL *ssl = con->ssl; | |
106 con->ssl = NULL; | |
107 ssl_smart_shutdown(ssl, con->shutdown_type); | |
108 SSL_free(ssl); | |
109 } | |
110 if (con->peer) { | |
111 X509_free(con->peer); | |
112 con->peer = NULL; | |
113 } | |
114 } | |
115 | |
116 #ifdef TCN_DO_STATISTICS | |
117 apr_atomic_inc32(&ssl_cleared); | |
118 #endif | |
119 return APR_SUCCESS; | |
120 } | |
121 | |
122 static tcn_ssl_conn_t *ssl_create(JNIEnv *env, tcn_ssl_ctxt_t *ctx, apr_pool_t *
pool) | |
123 { | |
124 tcn_ssl_conn_t *con; | |
125 SSL *ssl; | |
126 | |
127 if ((con = apr_pcalloc(pool, sizeof(tcn_ssl_conn_t))) == NULL) { | |
128 tcn_ThrowAPRException(env, apr_get_os_error()); | |
129 return NULL; | |
130 } | |
131 if ((ssl = SSL_new(ctx->ctx)) == NULL) { | |
132 char err[256]; | |
133 ERR_error_string(ERR_get_error(), err); | |
134 tcn_Throw(env, "SSL_new failed (%s)", err); | |
135 con = NULL; | |
136 return NULL; | |
137 } | |
138 SSL_clear(ssl); | |
139 con->pool = pool; | |
140 con->ctx = ctx; | |
141 con->ssl = ssl; | |
142 con->shutdown_type = ctx->shutdown_type; | |
143 apr_pollset_create(&(con->pollset), 1, pool, 0); | |
144 | |
145 SSL_set_app_data(ssl, (void *)con); | |
146 | |
147 // Store for later usage in SSL_callback_SSL_verify | |
148 SSL_set_app_data2(ssl, ctx); | |
149 | |
150 if (ctx->mode) { | |
151 /* | |
152 * Configure callbacks for SSL connection | |
153 */ | |
154 SSL_set_tmp_rsa_callback(ssl, SSL_callback_tmp_RSA); | |
155 SSL_set_tmp_dh_callback(ssl, SSL_callback_tmp_DH); | |
156 SSL_set_session_id_context(ssl, &(ctx->context_id[0]), | |
157 sizeof ctx->context_id); | |
158 } | |
159 SSL_set_verify_result(ssl, X509_V_OK); | |
160 SSL_rand_seed(ctx->rand_file); | |
161 | |
162 #ifdef TCN_DO_STATISTICS | |
163 ssl_created++; | |
164 #endif | |
165 return con; | |
166 } | |
167 | |
168 #ifdef WIN32 | |
169 #define APR_INVALID_SOCKET INVALID_SOCKET | |
170 #else | |
171 #define APR_INVALID_SOCKET -1 | |
172 #endif | |
173 | |
174 static apr_status_t wait_for_io_or_timeout(tcn_ssl_conn_t *con, | |
175 int for_what, | |
176 apr_interval_time_t timeout) | |
177 { | |
178 apr_pollfd_t pfd; | |
179 int type; | |
180 apr_status_t status; | |
181 apr_os_sock_t sock; | |
182 | |
183 if (!con->pollset) | |
184 return APR_ENOPOLL; | |
185 if (!con->sock) | |
186 return APR_ENOTSOCK; | |
187 if (con->reneg_state == RENEG_ABORT) { | |
188 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
189 return APR_ECONNABORTED; | |
190 } | |
191 | |
192 /* Check if the socket was already closed | |
193 */ | |
194 apr_os_sock_get(&sock, con->sock); | |
195 if (sock == APR_INVALID_SOCKET) | |
196 return APR_ENOTSOCK; | |
197 | |
198 /* Figure out the the poll direction */ | |
199 switch (for_what) { | |
200 case SSL_ERROR_WANT_WRITE: | |
201 case SSL_ERROR_WANT_CONNECT: | |
202 case SSL_ERROR_WANT_ACCEPT: | |
203 type = APR_POLLOUT; | |
204 break; | |
205 case SSL_ERROR_WANT_READ: | |
206 type = APR_POLLIN; | |
207 break; | |
208 default: | |
209 return APR_EINVAL; | |
210 break; | |
211 } | |
212 if (timeout <= 0) { | |
213 /* Waiting on zero or infinite timeouts is not allowed | |
214 */ | |
215 return APR_EAGAIN; | |
216 } | |
217 pfd.desc_type = APR_POLL_SOCKET; | |
218 pfd.desc.s = con->sock; | |
219 pfd.reqevents = type; | |
220 | |
221 /* Remove the object if it was in the pollset, then add in the new | |
222 * object with the correct reqevents value. Ignore the status result | |
223 * on the remove, because it might not be in there (yet). | |
224 */ | |
225 apr_pollset_remove(con->pollset, &pfd); | |
226 | |
227 /* ### check status code */ | |
228 apr_pollset_add(con->pollset, &pfd); | |
229 | |
230 do { | |
231 int numdesc; | |
232 const apr_pollfd_t *pdesc; | |
233 | |
234 status = apr_pollset_poll(con->pollset, timeout, &numdesc, &pdesc); | |
235 if (numdesc == 1 && (pdesc[0].rtnevents & type) != 0) | |
236 return APR_SUCCESS; | |
237 } while (APR_STATUS_IS_EINTR(status)); | |
238 | |
239 return status; | |
240 } | |
241 | |
242 static apr_status_t APR_THREAD_FUNC | |
243 ssl_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) | |
244 { | |
245 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
246 return apr_socket_timeout_set(con->sock, t); | |
247 } | |
248 | |
249 static apr_status_t APR_THREAD_FUNC | |
250 ssl_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) | |
251 { | |
252 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
253 return apr_socket_timeout_get(con->sock, t); | |
254 } | |
255 | |
256 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
257 ssl_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on) | |
258 { | |
259 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
260 return apr_socket_opt_set(con->sock, opt, on); | |
261 } | |
262 | |
263 static APR_INLINE apr_status_t APR_THREAD_FUNC | |
264 ssl_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on) | |
265 { | |
266 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
267 return apr_socket_opt_get(con->sock, opt, on); | |
268 } | |
269 | |
270 static apr_status_t APR_THREAD_FUNC | |
271 ssl_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how) | |
272 { | |
273 apr_status_t rv = APR_SUCCESS; | |
274 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
275 | |
276 if (con->ssl) { | |
277 SSL *ssl = con->ssl; | |
278 con->ssl = NULL; | |
279 if (how < 1) | |
280 how = con->shutdown_type; | |
281 rv = ssl_smart_shutdown(ssl, how); | |
282 /* TODO: Translate OpenSSL Error codes */ | |
283 SSL_free(ssl); | |
284 } | |
285 return rv; | |
286 } | |
287 | |
288 static apr_status_t APR_THREAD_FUNC | |
289 ssl_socket_close(apr_socket_t *sock) | |
290 { | |
291 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
292 apr_status_t rv = APR_SUCCESS; | |
293 | |
294 #ifdef TCN_DO_STATISTICS | |
295 apr_atomic_inc32(&ssl_closed); | |
296 #endif | |
297 if (con->ssl) { | |
298 SSL *ssl = con->ssl; | |
299 con->ssl = NULL; | |
300 rv = ssl_smart_shutdown(ssl, con->shutdown_type); | |
301 SSL_free(ssl); | |
302 } | |
303 if (con->peer) { | |
304 X509_free(con->peer); | |
305 con->peer = NULL; | |
306 } | |
307 return rv; | |
308 } | |
309 | |
310 TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) | |
311 { | |
312 tcn_socket_t *ss = J2P(sock, tcn_socket_t *); | |
313 tcn_ssl_conn_t *con; | |
314 apr_interval_time_t timeout; | |
315 int s, i; | |
316 long vr; | |
317 apr_status_t rv; | |
318 X509 *peer; | |
319 | |
320 UNREFERENCED_STDARGS; | |
321 TCN_ASSERT(sock != 0); | |
322 if (ss->net->type != TCN_SOCKET_SSL) | |
323 return APR_EINVAL; | |
324 con = (tcn_ssl_conn_t *)ss->opaque; | |
325 | |
326 apr_socket_timeout_get(con->sock, &timeout); | |
327 while (!SSL_is_init_finished(con->ssl)) { | |
328 ERR_clear_error(); | |
329 if ((s = SSL_do_handshake(con->ssl)) <= 0) { | |
330 if (!con->ssl) | |
331 return APR_ENOTSOCK; | |
332 rv = apr_get_netos_error(); | |
333 i = SSL_get_error(con->ssl, s); | |
334 switch (i) { | |
335 case SSL_ERROR_NONE: | |
336 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
337 return APR_SUCCESS; | |
338 break; | |
339 case SSL_ERROR_WANT_READ: | |
340 case SSL_ERROR_WANT_WRITE: | |
341 if ((rv = wait_for_io_or_timeout(con, i, timeout)) != APR_SU
CCESS) { | |
342 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
343 return rv; | |
344 } | |
345 break; | |
346 case SSL_ERROR_SYSCALL: | |
347 #if !defined(_WIN32) | |
348 if (APR_STATUS_IS_EINTR(rv)) { | |
349 /* Interrupted by signal */ | |
350 continue; | |
351 } | |
352 #endif | |
353 /* Fall trough */ | |
354 default: | |
355 /* | |
356 * Anything else is a fatal error | |
357 */ | |
358 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
359 return SSL_TO_APR_ERROR(i); | |
360 break; | |
361 } | |
362 } | |
363 if (!con->ssl) | |
364 return APR_ENOTSOCK; | |
365 | |
366 /* | |
367 * Check for failed client authentication | |
368 */ | |
369 if ((vr = SSL_get_verify_result(con->ssl)) != X509_V_OK) { | |
370 if (SSL_VERIFY_ERROR_IS_OPTIONAL(vr) && | |
371 con->ctx->verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA) { | |
372 /* TODO: Log optionalNoCA */ | |
373 } | |
374 else { | |
375 /* TODO: Log SSL client authentication failed */ | |
376 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
377 /* TODO: Figure out the correct return value */ | |
378 return APR_EGENERAL; | |
379 } | |
380 } | |
381 | |
382 /* | |
383 * Remember the peer certificate | |
384 */ | |
385 if ((peer = SSL_get_peer_certificate(con->ssl)) != NULL) { | |
386 if (con->peer) | |
387 X509_free(con->peer); | |
388 con->peer = peer; | |
389 } | |
390 } | |
391 return APR_SUCCESS; | |
392 } | |
393 | |
394 static apr_status_t APR_THREAD_FUNC | |
395 ssl_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len) | |
396 { | |
397 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
398 int s, i, rd = (int)(*len); | |
399 apr_status_t rv; | |
400 apr_interval_time_t timeout; | |
401 | |
402 *len = 0; | |
403 if (con->reneg_state == RENEG_ABORT) { | |
404 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
405 return APR_ECONNABORTED; | |
406 } | |
407 apr_socket_timeout_get(con->sock, &timeout); | |
408 for (;;) { | |
409 ERR_clear_error(); | |
410 if ((s = SSL_read(con->ssl, buf, rd)) <= 0) { | |
411 if (!con->ssl) | |
412 return APR_ENOTSOCK; | |
413 rv = apr_get_netos_error(); | |
414 i = SSL_get_error(con->ssl, s); | |
415 /* Special case if the "close notify" alert send by peer */ | |
416 if (s == 0 && (SSL_get_shutdown(con->ssl) & SSL_RECEIVED_SHUTDOWN))
{ | |
417 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
418 return APR_EOF; | |
419 } | |
420 switch (i) { | |
421 case SSL_ERROR_WANT_READ: | |
422 case SSL_ERROR_WANT_WRITE: | |
423 if ((rv = wait_for_io_or_timeout(con, i, timeout)) != APR_SU
CCESS) { | |
424 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
425 return rv; | |
426 } | |
427 break; | |
428 case SSL_ERROR_SYSCALL: | |
429 if (APR_STATUS_IS_EPIPE(rv) || APR_STATUS_IS_ECONNRESET(rv))
{ | |
430 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
431 return APR_EOF; | |
432 } | |
433 #if !defined(_WIN32) | |
434 else if (APR_STATUS_IS_EINTR(rv)) { | |
435 /* Interrupted by signal | |
436 */ | |
437 continue; | |
438 } | |
439 #endif | |
440 /* Fall trough */ | |
441 case SSL_ERROR_ZERO_RETURN: | |
442 if (s == 0) { | |
443 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
444 return APR_EOF; | |
445 } | |
446 /* Fall trough */ | |
447 default: | |
448 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
449 return APR_EGENERAL; | |
450 break; | |
451 } | |
452 } | |
453 else { | |
454 *len = s; | |
455 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
456 break; | |
457 } | |
458 } | |
459 return APR_SUCCESS; | |
460 } | |
461 | |
462 static apr_status_t APR_THREAD_FUNC | |
463 ssl_socket_send(apr_socket_t *sock, const char *buf, | |
464 apr_size_t *len) | |
465 { | |
466 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
467 int s, i, wr = (int)(*len); | |
468 apr_status_t rv; | |
469 apr_interval_time_t timeout; | |
470 | |
471 *len = 0; | |
472 if (con->reneg_state == RENEG_ABORT) { | |
473 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
474 return APR_ECONNABORTED; | |
475 } | |
476 if (!SSL_is_init_finished(con->ssl)) { | |
477 /* XXX: Is this a correct retval ? */ | |
478 return APR_EINPROGRESS; | |
479 } | |
480 if (wr == 0) { | |
481 /* According to docs calling SSL_write() with num=0 bytes | |
482 * to be sent the behaviour is undefined. | |
483 */ | |
484 return APR_EINVAL; | |
485 } | |
486 apr_socket_timeout_get(con->sock, &timeout); | |
487 for (;;) { | |
488 ERR_clear_error(); | |
489 if ((s = SSL_write(con->ssl, buf, wr)) <= 0) { | |
490 if (!con->ssl) | |
491 return APR_ENOTSOCK; | |
492 rv = apr_get_netos_error(); | |
493 i = SSL_get_error(con->ssl, s); | |
494 switch (i) { | |
495 case SSL_ERROR_WANT_READ: | |
496 case SSL_ERROR_WANT_WRITE: | |
497 if ((rv = wait_for_io_or_timeout(con, i, timeout)) != APR_SU
CCESS) { | |
498 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
499 return rv; | |
500 } | |
501 break; | |
502 case SSL_ERROR_SYSCALL: | |
503 if (s == -1) { | |
504 if (APR_STATUS_IS_EPIPE(rv) || APR_STATUS_IS_ECONNRESET(
rv)) { | |
505 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
506 return APR_EOF; | |
507 } | |
508 #if !defined(_WIN32) | |
509 else if (APR_STATUS_IS_EINTR(rv)) { | |
510 /* Interrupted by signal | |
511 */ | |
512 continue; | |
513 } | |
514 #endif | |
515 } | |
516 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
517 return rv; | |
518 break; | |
519 case SSL_ERROR_SSL: | |
520 /* Probably caused by buffer missmatch */ | |
521 rv = APR_EINVAL; | |
522 case SSL_ERROR_ZERO_RETURN: | |
523 if (s == 0) { | |
524 con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; | |
525 return APR_EOF; | |
526 } | |
527 /* Fall trough */ | |
528 default: | |
529 con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; | |
530 return rv; | |
531 break; | |
532 } | |
533 } | |
534 else { | |
535 *len = s; | |
536 break; | |
537 } | |
538 } | |
539 return APR_SUCCESS; | |
540 } | |
541 | |
542 static apr_status_t APR_THREAD_FUNC | |
543 ssl_socket_sendv(apr_socket_t *sock, | |
544 const struct iovec *vec, | |
545 apr_int32_t nvec, apr_size_t *len) | |
546 { | |
547 tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; | |
548 apr_status_t rv; | |
549 apr_size_t written = 0; | |
550 apr_int32_t i; | |
551 | |
552 for (i = 0; i < nvec; i++) { | |
553 apr_size_t rd = vec[i].iov_len; | |
554 if ((rv = ssl_socket_send((apr_socket_t *)con, | |
555 vec[i].iov_base, &rd)) != APR_SUCCESS) { | |
556 *len = written; | |
557 return rv; | |
558 } | |
559 written += rd; | |
560 } | |
561 *len = written; | |
562 return APR_SUCCESS; | |
563 } | |
564 | |
565 static tcn_nlayer_t ssl_socket_layer = { | |
566 TCN_SOCKET_SSL, | |
567 ssl_cleanup, | |
568 ssl_socket_close, | |
569 ssl_socket_shutdown, | |
570 ssl_socket_opt_get, | |
571 ssl_socket_opt_set, | |
572 ssl_socket_timeout_get, | |
573 ssl_socket_timeout_set, | |
574 ssl_socket_send, | |
575 ssl_socket_sendv, | |
576 ssl_socket_recv | |
577 }; | |
578 | |
579 | |
580 TCN_IMPLEMENT_CALL(jint, SSLSocket, attach)(TCN_STDARGS, jlong ctx, | |
581 jlong sock) | |
582 { | |
583 tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *); | |
584 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
585 tcn_ssl_conn_t *con; | |
586 apr_os_sock_t oss; | |
587 apr_status_t rv; | |
588 | |
589 UNREFERENCED(o); | |
590 TCN_ASSERT(ctx != 0); | |
591 TCN_ASSERT(sock != 0); | |
592 | |
593 if (!s->sock) | |
594 return APR_ENOTSOCK; | |
595 | |
596 if ((rv = apr_os_sock_get(&oss, s->sock)) != APR_SUCCESS) | |
597 return rv; | |
598 if (oss == APR_INVALID_SOCKET) | |
599 return APR_ENOTSOCK; | |
600 | |
601 if ((con = ssl_create(e, c, s->pool)) == NULL) | |
602 return APR_EGENERAL; | |
603 con->sock = s->sock; | |
604 | |
605 SSL_set_fd(con->ssl, (int)oss); | |
606 if (c->mode) | |
607 SSL_set_accept_state(con->ssl); | |
608 else | |
609 SSL_set_connect_state(con->ssl); | |
610 /* Change socket type */ | |
611 s->net = &ssl_socket_layer; | |
612 s->opaque = con; | |
613 | |
614 return APR_SUCCESS; | |
615 } | |
616 | |
617 TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS, | |
618 jlong sock) | |
619 { | |
620 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
621 tcn_ssl_conn_t *con; | |
622 int retVal; | |
623 int ecode = SSL_ERROR_WANT_READ; | |
624 apr_status_t rv; | |
625 apr_interval_time_t timeout; | |
626 | |
627 UNREFERENCED_STDARGS; | |
628 TCN_ASSERT(sock != 0); | |
629 con = (tcn_ssl_conn_t *)s->opaque; | |
630 | |
631 /* Sequence to renegotiate is | |
632 * SSL_renegotiate() | |
633 * SSL_do_handshake() | |
634 * ssl->state = SSL_ST_ACCEPT | |
635 * SSL_do_handshake() | |
636 */ | |
637 | |
638 /* Toggle the renegotiation state to allow the new | |
639 * handshake to proceed. | |
640 */ | |
641 con->reneg_state = RENEG_ALLOW; | |
642 retVal = SSL_renegotiate(con->ssl); | |
643 if (retVal <= 0) | |
644 return APR_EGENERAL; | |
645 | |
646 retVal = SSL_do_handshake(con->ssl); | |
647 if (retVal <= 0) | |
648 return APR_EGENERAL; | |
649 | |
650 if (SSL_get_state(con->ssl) != SSL_ST_OK) { | |
651 return APR_EGENERAL; | |
652 } | |
653 SSL_set_state(con->ssl, SSL_ST_ACCEPT); | |
654 | |
655 apr_socket_timeout_get(con->sock, &timeout); | |
656 ecode = SSL_ERROR_WANT_READ; | |
657 while (ecode == SSL_ERROR_WANT_READ) { | |
658 retVal = SSL_do_handshake(con->ssl); | |
659 if (retVal <= 0) { | |
660 ecode = SSL_get_error(con->ssl, retVal); | |
661 if (ecode == SSL_ERROR_WANT_READ) { | |
662 if ((rv = wait_for_io_or_timeout(con, ecode, timeout)) != APR_SU
CCESS) | |
663 return rv; /* Can't wait */ | |
664 continue; /* It should be ok now */ | |
665 } | |
666 else | |
667 return APR_EGENERAL; | |
668 } else | |
669 break; | |
670 } | |
671 con->reneg_state = RENEG_REJECT; | |
672 | |
673 if (SSL_get_state(con->ssl) != SSL_ST_OK) { | |
674 return APR_EGENERAL; | |
675 } | |
676 | |
677 return APR_SUCCESS; | |
678 } | |
679 | |
680 TCN_IMPLEMENT_CALL(void, SSLSocket, setVerify)(TCN_STDARGS, | |
681 jlong sock, | |
682 jint cverify, | |
683 jint depth) | |
684 { | |
685 tcn_socket_t *s = J2P(sock, tcn_socket_t *); | |
686 tcn_ssl_conn_t *con; | |
687 int verify = SSL_VERIFY_NONE; | |
688 | |
689 UNREFERENCED_STDARGS; | |
690 TCN_ASSERT(sock != 0); | |
691 con = (tcn_ssl_conn_t *)s->opaque; | |
692 | |
693 if (cverify == SSL_CVERIFY_UNSET) | |
694 cverify = SSL_CVERIFY_NONE; | |
695 if (depth > 0) | |
696 SSL_set_verify_depth(con->ssl, depth); | |
697 | |
698 if (cverify == SSL_CVERIFY_REQUIRE) | |
699 verify |= SSL_VERIFY_PEER_STRICT; | |
700 if ((cverify == SSL_CVERIFY_OPTIONAL) || | |
701 (cverify == SSL_CVERIFY_OPTIONAL_NO_CA)) | |
702 verify |= SSL_VERIFY_PEER; | |
703 | |
704 SSL_set_verify(con->ssl, verify, NULL); | |
705 } | |
706 | |
707 #else | |
708 /* OpenSSL is not supported. | |
709 * Create empty stubs. | |
710 */ | |
711 | |
712 TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) | |
713 { | |
714 UNREFERENCED_STDARGS; | |
715 UNREFERENCED(sock); | |
716 return (jint)APR_ENOTIMPL; | |
717 } | |
718 | |
719 TCN_IMPLEMENT_CALL(jint, SSLSocket, attach)(TCN_STDARGS, jlong ctx, | |
720 jlong sock) | |
721 { | |
722 UNREFERENCED_STDARGS; | |
723 UNREFERENCED(ctx); | |
724 UNREFERENCED(sock); | |
725 return (jint)APR_ENOTIMPL; | |
726 } | |
727 | |
728 TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS, | |
729 jlong sock) | |
730 { | |
731 UNREFERENCED_STDARGS; | |
732 UNREFERENCED(sock); | |
733 return (jint)APR_ENOTIMPL; | |
734 } | |
735 | |
736 #endif | |
OLD | NEW |