feature: applied the ssl_pending_session.patch to the nginx core to support the ssl_session_fetch_by_lua* and ssl_session_store_by_lua* in ngx_lua.

also added an openssl patch to support yieldable callback set by
SSL_CTX_sess_set_get_cb().
This commit is contained in:
Yichun Zhang (agentzh) 2016-07-19 19:26:08 -07:00
parent 09ca92f51f
commit 97901f3357
3 changed files with 253 additions and 0 deletions

View File

@ -0,0 +1,16 @@
--- nginx-1.11.2/src/event/ngx_event_openssl.c 2016-07-17 19:20:30.411137606 -0700
+++ nginx-1.11.2-patched/src/event/ngx_event_openssl.c 2016-07-19 16:53:35.539768477 -0700
@@ -1307,7 +1307,12 @@ ngx_ssl_handshake(ngx_connection_t *c)
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (sslerr == SSL_ERROR_WANT_X509_LOOKUP) {
+ if (sslerr == SSL_ERROR_WANT_X509_LOOKUP
+# ifdef SSL_ERROR_PENDING_SESSION
+ || sslerr == SSL_ERROR_PENDING_SESSION
+# endif
+ )
+ {
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;

View File

@ -0,0 +1,233 @@
diff -urp openssl-1.0.2h/ssl/s3_srvr.c openssl-1.0.2h-patched/ssl/s3_srvr.c
--- openssl-1.0.2h/ssl/s3_srvr.c 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/s3_srvr.c 2016-07-19 19:18:03.779159083 -0700
@@ -358,14 +358,20 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SR_CLNT_HELLO_A:
case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C:
+ case SSL3_ST_SR_CLNT_HELLO_D:
s->shutdown = 0;
ret = ssl3_get_client_hello(s);
+ if (ret == PENDING_SESSION) {
+ s->state = SSL3_ST_SR_CLNT_HELLO_D;
+ s->rwstate = SSL_PENDING_SESSION;
+ goto end;
+ }
if (ret <= 0)
goto end;
#ifndef OPENSSL_NO_SRP
- s->state = SSL3_ST_SR_CLNT_HELLO_D;
- case SSL3_ST_SR_CLNT_HELLO_D:
+ s->state = SSL3_ST_SR_CLNT_HELLO_E;
+ case SSL3_ST_SR_CLNT_HELLO_E:
{
int al;
if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
@@ -925,16 +931,25 @@ int ssl3_get_client_hello(SSL *s)
if (s->state == SSL3_ST_SR_CLNT_HELLO_A) {
s->state = SSL3_ST_SR_CLNT_HELLO_B;
}
- s->first_packet = 1;
- n = s->method->ssl_get_message(s,
- SSL3_ST_SR_CLNT_HELLO_B,
- SSL3_ST_SR_CLNT_HELLO_C,
- SSL3_MT_CLIENT_HELLO,
- SSL3_RT_MAX_PLAIN_LENGTH, &ok);
-
- if (!ok)
- return ((int)n);
- s->first_packet = 0;
+
+ if (s->state != SSL3_ST_SR_CLNT_HELLO_D) {
+ s->first_packet = 1;
+ n = s->method->ssl_get_message(s,
+ SSL3_ST_SR_CLNT_HELLO_B,
+ SSL3_ST_SR_CLNT_HELLO_C,
+ SSL3_MT_CLIENT_HELLO,
+ SSL3_RT_MAX_PLAIN_LENGTH, &ok);
+
+ if (!ok)
+ return ((int)n);
+ s->first_packet = 0;
+ } else {
+ /* We have previously parsed the ClientHello message, and can't
+ * call ssl_get_message again without hashing the message into
+ * the Finished digest again. */
+ n = s->init_num;
+ }
+
d = p = (unsigned char *)s->init_msg;
/*
@@ -1041,15 +1056,26 @@ int ssl3_get_client_hello(SSL *s)
if (i == 1 && s->version == s->session->ssl_version) { /* previous
* session */
s->hit = 1;
- } else if (i == -1)
+ } else if (i == -1) {
+ goto err;
+ } else if (i == PENDING_SESSION) {
+ ret = PENDING_SESSION;
goto err;
- else { /* i == 0 */
+ } else { /* i == 0 */
if (!ssl_get_new_session(s, 1))
goto err;
}
}
+ /*
+ * Switch to server state ClientHello C once the session lookup
+ * is finished so it can proceed with original state loop.
+ */
+ if (s->state == SSL3_ST_SR_CLNT_HELLO_D) {
+ s->state = SSL3_ST_SR_CLNT_HELLO_C;
+ }
+
p += j;
if (SSL_IS_DTLS(s)) {
diff -urp openssl-1.0.2h/ssl/ssl3.h openssl-1.0.2h-patched/ssl/ssl3.h
--- openssl-1.0.2h/ssl/ssl3.h 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl3.h 2016-07-19 19:15:54.117778328 -0700
@@ -698,6 +698,7 @@ typedef struct ssl3_state_st {
# define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT)
# define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT)
# define SSL3_ST_SR_CLNT_HELLO_D (0x115|SSL_ST_ACCEPT)
+# define SSL3_ST_SR_CLNT_HELLO_E (0x116|SSL_ST_ACCEPT)
/* write to client */
# define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT)
# define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT)
diff -urp openssl-1.0.2h/ssl/ssl.h openssl-1.0.2h-patched/ssl/ssl.h
--- openssl-1.0.2h/ssl/ssl.h 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl.h 2016-07-19 19:19:44.699562938 -0700
@@ -1243,6 +1243,13 @@ void SSL_CTX_sess_set_get_cb(SSL_CTX *ct
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
unsigned char *Data,
int len, int *copy);
+
+/* SSL_magic_pending_session_ptr returns a magic SSL_SESSION* which indicates
+ * that the session isn't currently unavailable. SSL_get_error will then return
+ * SSL_ERROR_PENDING_SESSION and the handshake can be retried later when the
+ * lookup has completed. */
+SSL_SESSION *SSL_magic_pending_session_ptr(void);
+
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
void (*cb) (const SSL *ssl, int type,
int val));
@@ -1408,11 +1415,14 @@ int SSL_extension_supported(unsigned int
# define SSL_READING 3
# define SSL_X509_LOOKUP 4
+# define SSL_PENDING_SESSION 7
+
/* These will only be used when doing non-blocking IO */
# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
# define SSL_want_read(s) (SSL_want(s) == SSL_READING)
# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
+# define SSL_want_session(s) (SSL_want(s) == SSL_PENDING_SESSION)
# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
@@ -1865,6 +1875,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_ERROR_ZERO_RETURN 6
# define SSL_ERROR_WANT_CONNECT 7
# define SSL_ERROR_WANT_ACCEPT 8
+# define SSL_ERROR_PENDING_SESSION 11
# define SSL_CTRL_NEED_TMP_RSA 1
# define SSL_CTRL_SET_TMP_RSA 2
# define SSL_CTRL_SET_TMP_DH 3
diff -urp openssl-1.0.2h/ssl/ssl_lib.c openssl-1.0.2h-patched/ssl/ssl_lib.c
--- openssl-1.0.2h/ssl/ssl_lib.c 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl_lib.c 2016-07-19 19:21:04.032021549 -0700
@@ -2709,6 +2709,9 @@ int SSL_get_error(const SSL *s, int i)
return (SSL_ERROR_SSL);
}
+ if ((i < 0) && SSL_want_session(s))
+ return (SSL_ERROR_PENDING_SESSION);
+
if ((i < 0) && SSL_want_read(s)) {
bio = SSL_get_rbio(s);
if (BIO_should_read(bio))
diff -urp openssl-1.0.2h/ssl/ssl_locl.h openssl-1.0.2h-patched/ssl/ssl_locl.h
--- openssl-1.0.2h/ssl/ssl_locl.h 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl_locl.h 2016-07-19 19:15:54.117778328 -0700
@@ -518,6 +518,8 @@
#define CERT_PRIVATE_KEY 2
*/
+# define PENDING_SESSION -10000
+
# ifndef OPENSSL_NO_EC
/*
* From ECC-TLS draft, used in encoding the curve type in ECParameters
diff -urp openssl-1.0.2h/ssl/ssl_sess.c openssl-1.0.2h-patched/ssl/ssl_sess.c
--- openssl-1.0.2h/ssl/ssl_sess.c 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl_sess.c 2016-07-19 19:15:54.118778298 -0700
@@ -143,10 +143,20 @@
#endif
#include "ssl_locl.h"
+/* The address of this is a magic value, a pointer to which is returned by
+ * SSL_magic_pending_session_ptr(). It allows a session callback to indicate
+ * that it needs to asynchronously fetch session information. */
+static char g_pending_session_magic;
+
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
+SSL_SESSION *SSL_magic_pending_session_ptr()
+{
+ return (SSL_SESSION*) &g_pending_session_magic;
+}
+
SSL_SESSION *SSL_get_session(const SSL *ssl)
/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
{
@@ -626,6 +636,12 @@ int ssl_get_prev_session(SSL *s, unsigne
int copy = 1;
if ((ret = s->session_ctx->get_session_cb(s, session_id, len, &copy))) {
+ if (ret == SSL_magic_pending_session_ptr()) {
+ /* This is a magic value which indicates that
+ * the callback needs to unwind the stack and
+ * figure out the session asynchronously. */
+ return PENDING_SESSION;
+ }
s->session_ctx->stats.sess_cb_hit++;
/*
diff -urp openssl-1.0.2h/ssl/ssl_stat.c openssl-1.0.2h-patched/ssl/ssl_stat.c
--- openssl-1.0.2h/ssl/ssl_stat.c 2016-05-03 06:44:42.000000000 -0700
+++ openssl-1.0.2h-patched/ssl/ssl_stat.c 2016-07-19 19:15:54.118778298 -0700
@@ -353,6 +353,12 @@ const char *SSL_state_string_long(const
case SSL3_ST_SR_CLNT_HELLO_C:
str = "SSLv3 read client hello C";
break;
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ str = "SSLv3 read client hello D";
+ break;
+ case SSL3_ST_SR_CLNT_HELLO_E:
+ str = "SSLv3 read client hello E";
+ break;
case SSL3_ST_SW_HELLO_REQ_A:
str = "SSLv3 write hello request A";
break;
@@ -737,6 +743,12 @@ const char *SSL_state_string(const SSL *
case SSL3_ST_SR_CLNT_HELLO_C:
str = "3RCH_C";
break;
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ str = "3RCH_D";
+ break;
+ case SSL3_ST_SR_CLNT_HELLO_E:
+ str = "3RCH_E";
+ break;
case SSL3_ST_SW_SRVR_HELLO_A:
str = "3WSH_A";
break;

View File

@ -325,6 +325,10 @@ echo "$info_txt applying the ssl_cert_cb_yield.patch patch to nginx"
patch -p1 < $root/patches/nginx-$main_ver-ssl_cert_cb_yield.patch
echo
echo "$info_txt applying the ssl_pending_session.patch patch to nginx"
patch -p1 < $root/patches/nginx-$main_ver-ssl_pending_session.patch
echo
echo "$info_txt applying the upstream_timeout_fields patch for nginx"
patch -p1 < $root/patches/nginx-$main_ver-upstream_timeout_fields.patch || exit 1
echo