diff --git a/.travis.yml b/.travis.yml
index 7448f65ac2..86581be635 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -84,7 +84,7 @@ install:
- git clone https://github.com/openresty/rds-json-nginx-module.git ../rds-json-nginx-module
- git clone https://github.com/openresty/srcache-nginx-module.git ../srcache-nginx-module
- git clone https://github.com/openresty/redis2-nginx-module.git ../redis2-nginx-module
- - git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core
+ - git clone -b ssl-psk https://github.com/vartiait/lua-resty-core.git ../lua-resty-core
- git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache
- git clone https://github.com/openresty/lua-resty-mysql.git ../lua-resty-mysql
- git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git
diff --git a/README.markdown b/README.markdown
index 28ba6e68c0..8562a227c0 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1076,6 +1076,7 @@ Directives
* [lua_need_request_body](#lua_need_request_body)
* [ssl_certificate_by_lua_block](#ssl_certificate_by_lua_block)
* [ssl_certificate_by_lua_file](#ssl_certificate_by_lua_file)
+* [ssl_psk_identity_hint](#ssl_psk_identity_hint)
* [ssl_session_fetch_by_lua_block](#ssl_session_fetch_by_lua_block)
* [ssl_session_fetch_by_lua_file](#ssl_session_fetch_by_lua_file)
* [ssl_session_store_by_lua_block](#ssl_session_store_by_lua_block)
@@ -1094,6 +1095,8 @@ Directives
* [lua_ssl_protocols](#lua_ssl_protocols)
* [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate)
* [lua_ssl_verify_depth](#lua_ssl_verify_depth)
+* [lua_ssl_psk_identity](#lua_ssl_psk_identity)
+* [lua_ssl_psk_key](#lua_ssl_psk_key)
* [lua_http10_buffering](#lua_http10_buffering)
* [rewrite_by_lua_no_postpone](#rewrite_by_lua_no_postpone)
* [access_by_lua_no_postpone](#access_by_lua_no_postpone)
@@ -2564,6 +2567,22 @@ This directive was first introduced in the `v0.10.0` release.
[Back to TOC](#directives)
+ssl_psk_identity_hint
+---------------------
+
+**syntax:** *ssl_psk_identity_hint <tls_psk_identity_hint>*
+
+**default:** *no*
+
+**context:** *http, server*
+
+Specifies the TLS-PSK identity hint string which NGINX will send to a client during
+the SSL handshake for the downstream SSL (https) connections.
+
+This directive was first introduced in the `v0.XX.YY` release.
+
+[Back to TOC](#directives)
+
ssl_session_fetch_by_lua_block
------------------------------
@@ -2958,6 +2977,36 @@ See also [lua_ssl_trusted_certificate](#lua_ssl_trusted_certificate).
[Back to TOC](#directives)
+lua_ssl_psk_identity
+--------------------
+
+**syntax:** *lua_ssl_psk_identity <tls_psk_identity>*
+
+**default:** *no*
+
+**context:** *http, server, location*
+
+Specifies the TLS-PSK identity string which NGINX will send to a SSL/TLS server in the [tcpsock:sslhandshake](#tcpsocksslhandshake) method.
+
+This directive was first introduced in the `v0.XX.YY` release.
+
+[Back to TOC](#directives)
+
+lua_ssl_psk_key
+---------------
+
+**syntax:** *lua_ssl_psk_key <tls_psk_key>*
+
+**default:** *no*
+
+**context:** *http, server, location*
+
+Specifies the TLS-PSK key string which NGINX will try use with a SSL/TLS server in the [tcpsock:sslhandshake](#tcpsocksslhandshake) method.
+
+This directive was first introduced in the `v0.XX.YY` release.
+
+[Back to TOC](#directives)
+
lua_http10_buffering
--------------------
diff --git a/config b/config
index 044deb974e..143ad92d12 100644
--- a/config
+++ b/config
@@ -359,6 +359,7 @@ HTTP_LUA_SRCS=" \
$ngx_addon_dir/src/ngx_http_lua_balancer.c \
$ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.c \
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.c \
+ $ngx_addon_dir/src/ngx_http_lua_ssl_pskby.c \
$ngx_addon_dir/src/ngx_http_lua_ssl.c \
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.c \
"
@@ -420,6 +421,7 @@ HTTP_LUA_DEPS=" \
$ngx_addon_dir/src/ngx_http_lua_balancer.h \
$ngx_addon_dir/src/ngx_http_lua_ssl_session_storeby.h \
$ngx_addon_dir/src/ngx_http_lua_ssl_session_fetchby.h \
+ $ngx_addon_dir/src/ngx_http_lua_ssl_pskby.h \
$ngx_addon_dir/src/ngx_http_lua_ssl.h \
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.h \
"
diff --git a/doc/HttpLuaModule.wiki b/doc/HttpLuaModule.wiki
index 8ad2b2d4a9..23aba0d30e 100644
--- a/doc/HttpLuaModule.wiki
+++ b/doc/HttpLuaModule.wiki
@@ -2159,6 +2159,19 @@ When a relative path like foo/bar.lua
is given, they will be turned
This directive was first introduced in the v0.10.0
release.
+== ssl_psk_identity_hint ==
+
+'''syntax:''' ''ssl_psk_identity_hint ''
+
+'''default:''' ''no''
+
+'''context:''' ''http, server''
+
+Specifies the TLS-PSK identity hint string which NGINX will send to a client during
+the SSL handshake for the downstream SSL (https) connections.
+
+This directive was first introduced in the v0.XX.YY
release.
+
== ssl_session_fetch_by_lua_block ==
'''syntax:''' ''ssl_session_fetch_by_lua_block { lua-script }''
@@ -2498,6 +2511,30 @@ This directive was first introduced in the v0.9.11
release.
See also [[#lua_ssl_trusted_certificate|lua_ssl_trusted_certificate]].
+== lua_ssl_psk_identity ==
+
+'''syntax:''' ''lua_ssl_psk_identity ''
+
+'''default:''' ''no''
+
+'''context:''' ''http, server, location''
+
+Specifies the TLS-PSK identity string which NGINX will send to a SSL/TLS server in the [[#tcpsock:sslhandshake|tcpsock:sslhandshake]] method.
+
+This directive was first introduced in the v0.XX.YY
release.
+
+== lua_ssl_psk_key ==
+
+'''syntax:''' ''lua_ssl_psk_key ''
+
+'''default:''' ''no''
+
+'''context:''' ''http, server, location''
+
+Specifies the TLS-PSK key string which NGINX will try use with a SSL/TLS server in the [[#tcpsock:sslhandshake|tcpsock:sslhandshake]] method.
+
+This directive was first introduced in the v0.XX.YY
release.
+
== lua_http10_buffering ==
'''syntax:''' ''lua_http10_buffering on|off''
diff --git a/src/ngx_http_lua_common.h b/src/ngx_http_lua_common.h
index e38978389c..2ed06b96ff 100644
--- a/src/ngx_http_lua_common.h
+++ b/src/ngx_http_lua_common.h
@@ -129,6 +129,7 @@ typedef struct {
#define NGX_HTTP_LUA_CONTEXT_SSL_CERT 0x0400
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE 0x0800
#define NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH 0x1000
+#define NGX_HTTP_LUA_CONTEXT_SSL_PSK 0x2000
#ifndef NGX_LUA_NO_FFI_API
@@ -248,6 +249,8 @@ union ngx_http_lua_srv_conf_u {
ngx_http_lua_srv_conf_handler_pt ssl_sess_fetch_handler;
ngx_str_t ssl_sess_fetch_src;
u_char *ssl_sess_fetch_src_key;
+
+ ngx_str_t ssl_psk_identity_hint;
} srv;
#endif
@@ -268,6 +271,8 @@ typedef struct {
ngx_uint_t ssl_verify_depth;
ngx_str_t ssl_trusted_certificate;
ngx_str_t ssl_crl;
+ ngx_str_t ssl_psk_identity;
+ ngx_str_t ssl_psk_key;
#endif
ngx_flag_t force_read_body; /* whether force request body to
diff --git a/src/ngx_http_lua_control.c b/src/ngx_http_lua_control.c
index ae36505f9d..45c31262d9 100644
--- a/src/ngx_http_lua_control.c
+++ b/src/ngx_http_lua_control.c
@@ -322,13 +322,15 @@ ngx_http_lua_ngx_exit(lua_State *L)
| NGX_HTTP_LUA_CONTEXT_BALANCER
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
- | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH);
+ | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
+ | NGX_HTTP_LUA_CONTEXT_SSL_PSK);
rc = (ngx_int_t) luaL_checkinteger(L, 1);
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
- | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH))
+ | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
+ | NGX_HTTP_LUA_CONTEXT_SSL_PSK))
{
#if (NGX_HTTP_SSL)
@@ -339,7 +341,8 @@ ngx_http_lua_ngx_exit(lua_State *L)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua exit with code %i", rc);
- if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE) {
+ if (ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
+ || ctx->context == NGX_HTTP_LUA_CONTEXT_SSL_PSK) {
return 0;
}
@@ -473,7 +476,8 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
| NGX_HTTP_LUA_CONTEXT_BALANCER
| NGX_HTTP_LUA_CONTEXT_SSL_CERT
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
- | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH,
+ | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
+ | NGX_HTTP_LUA_CONTEXT_SSL_PSK,
err, errlen)
!= NGX_OK)
{
@@ -482,7 +486,8 @@ ngx_http_lua_ffi_exit(ngx_http_request_t *r, int status, u_char *err,
if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
| NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE
- | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH))
+ | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
+ | NGX_HTTP_LUA_CONTEXT_SSL_PSK))
{
#if (NGX_HTTP_SSL)
diff --git a/src/ngx_http_lua_module.c b/src/ngx_http_lua_module.c
index 9d914e86e8..c3e67acedc 100644
--- a/src/ngx_http_lua_module.c
+++ b/src/ngx_http_lua_module.c
@@ -28,6 +28,7 @@
#include "ngx_http_lua_ssl_certby.h"
#include "ngx_http_lua_ssl_session_storeby.h"
#include "ngx_http_lua_ssl_session_fetchby.h"
+#include "ngx_http_lua_ssl_pskby.h"
#include "ngx_http_lua_headers.h"
@@ -557,6 +558,27 @@ static ngx_command_t ngx_http_lua_cmds[] = {
0,
(void *) ngx_http_lua_ssl_sess_fetch_handler_file },
+ { ngx_string("ssl_psk_identity_hint"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_lua_srv_conf_t, srv.ssl_psk_identity_hint),
+ NULL },
+
+ { ngx_string("lua_ssl_psk_identity"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_lua_loc_conf_t, ssl_psk_identity),
+ NULL },
+
+ { ngx_string("lua_ssl_psk_key"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_lua_loc_conf_t, ssl_psk_key),
+ NULL },
+
{ ngx_string("lua_ssl_verify_depth"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
@@ -922,6 +944,8 @@ ngx_http_lua_create_srv_conf(ngx_conf_t *cf)
* lscf->srv.ssl_session_fetch_src = { 0, NULL };
* lscf->srv.ssl_session_fetch_src_key = NULL;
*
+ * lscf->srv.ssl_psk_identity_hint = { 0, NULL };
+ *
* lscf->balancer.handler = NULL;
* lscf->balancer.src = { 0, NULL };
* lscf->balancer.src_key = NULL;
@@ -969,6 +993,8 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
SSL_CTX_set_cert_cb(sscf->ssl.ctx, ngx_http_lua_ssl_cert_handler, NULL);
+ SSL_CTX_set_psk_server_callback(sscf->ssl.ctx,
+ ngx_http_lua_ssl_psk_server_handler);
# else
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
@@ -1024,6 +1050,42 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
+ if (conf->srv.ssl_psk_identity_hint.len == 0) {
+ conf->srv.ssl_psk_identity_hint = prev->srv.ssl_psk_identity_hint;
+ }
+
+ if (conf->srv.ssl_psk_identity_hint.len) {
+ dd("ssl psk identity hint: %.*s",
+ (int) conf->srv.ssl_psk_identity_hint.len,
+ conf->srv.ssl_psk_identity_hint.data);
+
+ # if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+
+ sscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module);
+ if (sscf == NULL || sscf->ssl.ctx == NULL) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no ssl configured for the server");
+
+ return NGX_CONF_ERROR;
+ }
+
+ if (SSL_CTX_use_psk_identity_hint(sscf->ssl.ctx,
+ (const char *) conf->srv.ssl_psk_identity_hint.data) == 0) {
+ ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
+ "SSL_CTX_use_psk_identity_hint(\"%V\") failed",
+ &conf->srv.ssl_psk_identity_hint);
+ return NGX_CONF_ERROR;
+ }
+
+ # else
+
+ ngx_log_error(NGX_LOG_CRIT, cf->log, 0,
+ "OpenSSL too old to support ssl_psk_identity_hint");
+ return NGX_CONF_ERROR;
+
+ # endif
+ }
+
#endif /* NGX_HTTP_SSL */
return NGX_CONF_OK;
}
@@ -1067,6 +1129,8 @@ ngx_http_lua_create_loc_conf(ngx_conf_t *cf)
* conf->ssl_ciphers = { 0, NULL };
* conf->ssl_trusted_certificate = { 0, NULL };
* conf->ssl_crl = { 0, NULL };
+ * conf->ssl_psk_identity = { 0, NULL };
+ * conf->ssl_psk_key = {0, NULL };
*/
conf->force_read_body = NGX_CONF_UNSET;
@@ -1160,6 +1224,11 @@ ngx_http_lua_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
prev->ssl_trusted_certificate, "");
ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+ ngx_conf_merge_str_value(conf->ssl_psk_identity,
+ prev->ssl_psk_identity, "");
+ ngx_conf_merge_str_value(conf->ssl_psk_key,
+ prev->ssl_psk_key, "");
+
if (ngx_http_lua_set_ssl(cf, conf) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -1266,6 +1335,26 @@ ngx_http_lua_set_ssl(ngx_conf_t *cf, ngx_http_lua_loc_conf_t *llcf)
return NGX_ERROR;
}
+ if (llcf->ssl_psk_identity.len && llcf->ssl_psk_key.len) {
+ dd("ssl psk identity: %.*s", (int) llcf->ssl_psk_identity.len,
+ llcf->ssl_psk_identity.data);
+ dd("ssl psk key: %.*s", (int) llcf->ssl_psk_key.len,
+ llcf->ssl_psk_key.data);
+
+# if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+
+ SSL_CTX_set_psk_client_callback(llcf->ssl->ctx,
+ ngx_http_lua_ssl_psk_client_handler);
+
+# else
+
+ ngx_log_error(NGX_LOG_CRIT, cf->log, 0,
+ "OpenSSL too old to support ssl_psk_identity");
+ return NGX_ERROR;
+
+# endif
+ }
+
return NGX_OK;
}
diff --git a/src/ngx_http_lua_phase.c b/src/ngx_http_lua_phase.c
index 50c53110b8..7ed0ad105d 100644
--- a/src/ngx_http_lua_phase.c
+++ b/src/ngx_http_lua_phase.c
@@ -80,6 +80,10 @@ ngx_http_lua_ngx_get_phase(lua_State *L)
lua_pushliteral(L, "balancer");
break;
+ case NGX_HTTP_LUA_CONTEXT_SSL_PSK:
+ lua_pushliteral(L, "ssl_psk");
+ break;
+
case NGX_HTTP_LUA_CONTEXT_SSL_CERT:
lua_pushliteral(L, "ssl_cert");
break;
diff --git a/src/ngx_http_lua_socket_tcp.c b/src/ngx_http_lua_socket_tcp.c
index 85f9f6a04a..826cba11b5 100644
--- a/src/ngx_http_lua_socket_tcp.c
+++ b/src/ngx_http_lua_socket_tcp.c
@@ -22,6 +22,7 @@ static int ngx_http_lua_socket_tcp(lua_State *L);
static int ngx_http_lua_socket_tcp_connect(lua_State *L);
#if (NGX_HTTP_SSL)
static int ngx_http_lua_socket_tcp_sslhandshake(lua_State *L);
+static int ngx_http_lua_socket_tcp_sslgetpskidhint(lua_State *L);
#endif
static int ngx_http_lua_socket_tcp_receive(lua_State *L);
static int ngx_http_lua_socket_tcp_send(lua_State *L);
@@ -283,6 +284,9 @@ ngx_http_lua_inject_socket_tcp_api(ngx_log_t *log, lua_State *L)
lua_pushcfunction(L, ngx_http_lua_socket_tcp_sslhandshake);
lua_setfield(L, -2, "sslhandshake");
+ lua_pushcfunction(L, ngx_http_lua_socket_tcp_sslgetpskidhint);
+ lua_setfield(L, -2, "sslgetpskidhint");
+
#endif
lua_pushcfunction(L, ngx_http_lua_socket_tcp_receive);
@@ -1599,6 +1603,41 @@ ngx_http_lua_ssl_handshake_retval_handler(ngx_http_request_t *r,
return 1;
}
+
+static int
+ngx_http_lua_socket_tcp_sslgetpskidhint(lua_State *L)
+{
+ ngx_http_lua_socket_tcp_upstream_t *u;
+
+ if (lua_gettop(L) != 1) {
+ return luaL_error(L, "expecting 1 argument "
+ "(including the object), but got %d", lua_gettop(L));
+ }
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ lua_rawgeti(L, 1, SOCKET_CTX_INDEX);
+ u = lua_touserdata(L, -1);
+
+ if (u == NULL
+ || u->peer.connection == NULL
+ || (u->read_closed && u->write_closed))
+ {
+ lua_pushnil(L);
+ lua_pushliteral(L, "closed");
+ return 2;
+ }
+
+ if (u->ssl_psk_identity_hint.len == 0) {
+ lua_pushliteral(L, "");
+ return 1;
+ }
+
+ lua_pushlstring(L, (char *) u->ssl_psk_identity_hint.data,
+ u->ssl_psk_identity_hint.len);
+ return 1;
+}
+
#endif /* NGX_HTTP_SSL */
@@ -3493,6 +3532,11 @@ ngx_http_lua_socket_tcp_finalize(ngx_http_request_t *r,
u->ssl_name.data = NULL;
u->ssl_name.len = 0;
}
+ if (u->ssl_psk_identity_hint.data) {
+ ngx_free(u->ssl_psk_identity_hint.data);
+ u->ssl_psk_identity_hint.data = NULL;
+ u->ssl_psk_identity_hint.len = 0;
+ }
#endif
c = u->peer.connection;
diff --git a/src/ngx_http_lua_socket_tcp.h b/src/ngx_http_lua_socket_tcp.h
index dbdee41c6e..51f93ab921 100644
--- a/src/ngx_http_lua_socket_tcp.h
+++ b/src/ngx_http_lua_socket_tcp.h
@@ -92,6 +92,7 @@ struct ngx_http_lua_socket_tcp_upstream_s {
#if (NGX_HTTP_SSL)
ngx_str_t ssl_name;
+ ngx_str_t ssl_psk_identity_hint;
#endif
unsigned ft_type:16;
diff --git a/src/ngx_http_lua_ssl.h b/src/ngx_http_lua_ssl.h
index acb8c4b16c..a612316d93 100644
--- a/src/ngx_http_lua_ssl.h
+++ b/src/ngx_http_lua_ssl.h
@@ -24,6 +24,9 @@ typedef struct {
ngx_str_t session_id;
+ ngx_str_t psk_identity;
+ ngx_str_t psk_key;
+
int exit_code; /* exit code for openssl's
set_cert_cb callback */
@@ -32,6 +35,7 @@ typedef struct {
unsigned entered_cert_handler:1;
unsigned entered_sess_fetch_handler:1;
+ unsigned entered_psk_handler:1;
} ngx_http_lua_ssl_ctx_t;
diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c
index 95be47f6b5..708756b77e 100644
--- a/src/ngx_http_lua_ssl_certby.c
+++ b/src/ngx_http_lua_ssl_certby.c
@@ -461,6 +461,7 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r)
lua_State *co;
ngx_http_lua_ctx_t *ctx;
ngx_http_cleanup_t *cln;
+ ngx_http_lua_ssl_ctx_t *cctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
@@ -522,13 +523,19 @@ ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r)
ctx->cleanup = &cln->handler;
}
- ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_CERT;
+ cctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection);
+
+ if (cctx != NULL && cctx->entered_psk_handler) {
+ ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_PSK;
+ }
+ else {
+ ctx->context = NGX_HTTP_LUA_CONTEXT_SSL_CERT;
+ }
rc = ngx_http_lua_run_thread(L, r, ctx, 0);
if (rc == NGX_ERROR || rc >= NGX_OK) {
/* do nothing */
-
} else if (rc == NGX_AGAIN) {
rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0);
diff --git a/src/ngx_http_lua_ssl_pskby.c b/src/ngx_http_lua_ssl_pskby.c
new file mode 100644
index 0000000000..e075a7b950
--- /dev/null
+++ b/src/ngx_http_lua_ssl_pskby.c
@@ -0,0 +1,515 @@
+
+/*
+ * Based on ngx_http_lua_ssl_certby.c and ngx_http_lua_ssl_session_storeby.c
+ * by Yichun Zhang (agentzh)
+ *
+ * Author: Tuure Vartiainen (vartiait)
+ */
+
+
+#ifndef DDEBUG
+#define DDEBUG 0
+#endif
+#include "ddebug.h"
+
+
+#if (NGX_HTTP_SSL)
+
+#include "ngx_http_lua_cache.h"
+#include "ngx_http_lua_initworkerby.h"
+#include "ngx_http_lua_util.h"
+#include "ngx_http_ssl_module.h"
+#include "ngx_http_lua_contentby.h"
+#include "ngx_http_lua_ssl_pskby.h"
+#include "ngx_http_lua_directive.h"
+#include "ngx_http_lua_ssl.h"
+#include "ngx_http_lua_socket_tcp.h"
+
+
+static u_char *ngx_http_lua_log_ssl_psk_error(ngx_log_t *log, u_char *buf,
+ size_t len);
+
+
+unsigned int ngx_http_lua_ssl_psk_server_handler(ngx_ssl_conn_t *ssl_conn,
+ const char *identity, unsigned char *psk, unsigned int max_psk_len)
+{
+ lua_State *L;
+ ngx_int_t rc;
+ ngx_connection_t *c, *fc;
+ ngx_http_request_t *r = NULL;
+ ngx_http_connection_t *hc;
+ ngx_http_lua_srv_conf_t *lscf;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_lua_ssl_ctx_t *cctx;
+
+ c = ngx_ssl_get_connection(ssl_conn);
+
+ dd("c = %p", c);
+
+ cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection);
+
+ dd("ssl server psk handler, psk-ctx=%p", cctx);
+
+ hc = c->data;
+
+ fc = ngx_http_lua_create_fake_connection(NULL);
+ if (fc == NULL) {
+ goto failed;
+ }
+
+ fc->log->handler = ngx_http_lua_log_ssl_psk_error;
+ fc->log->data = fc;
+
+ fc->addr_text = c->addr_text;
+ fc->listening = c->listening;
+
+ r = ngx_http_lua_create_fake_request(fc);
+ if (r == NULL) {
+ goto failed;
+ }
+
+ r->main_conf = hc->conf_ctx->main_conf;
+ r->srv_conf = hc->conf_ctx->srv_conf;
+ r->loc_conf = hc->conf_ctx->loc_conf;
+
+ fc->log->file = c->log->file;
+ fc->log->log_level = c->log->log_level;
+ fc->ssl = c->ssl;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+#if defined(nginx_version) && nginx_version >= 1003014
+
+# if nginx_version >= 1009000
+
+ ngx_set_connection_log(fc, clcf->error_log);
+
+# else
+
+ ngx_http_set_connection_log(fc, clcf->error_log);
+
+# endif
+
+#else
+
+ fc->log->file = clcf->error_log->file;
+
+ if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
+ fc->log->log_level = clcf->error_log->log_level;
+ }
+
+#endif
+
+ if (cctx == NULL) {
+ cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t));
+ if (cctx == NULL) {
+ goto failed; /* error */
+ }
+ }
+
+ if (identity == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
+ "client did not send TLS-PSK identity");
+ goto failed;
+ }
+
+ cctx->exit_code = 0; /* unsuccessful by default */
+ cctx->connection = c;
+ cctx->request = r;
+ cctx->psk_identity.data = (u_char *) identity;
+ cctx->psk_identity.len = ngx_strlen(identity);
+ cctx->entered_psk_handler = 1;
+ cctx->done = 0;
+
+ dd("setting cctx = %p", cctx);
+
+ if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx)
+ == 0)
+ {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed");
+ goto failed;
+ }
+
+ lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module);
+
+ /* TODO honor lua_code_cache off */
+ L = ngx_http_lua_get_lua_vm(r, NULL);
+
+ c->log->action = "setting SSL PSK by lua";
+
+ rc = lscf->srv.ssl_cert_handler(r, lscf, L);
+
+ if (rc >= NGX_OK || rc == NGX_ERROR) {
+ cctx->done = 1;
+
+ if (cctx->cleanup) {
+ *cctx->cleanup = NULL;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "lua_certificate_by_lua: handler return value: %i, "
+ "psk server cb exit code: %d", rc, cctx->exit_code);
+
+ c->log->action = "SSL handshaking";
+
+ if (rc == NGX_ERROR || cctx->exit_code != NGX_OK) {
+ /* 0 == unknown_psk_identity */
+ return 0;
+ }
+
+ if (cctx->psk_key.data == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "psk_key.data == NULL");
+
+ return 0;
+ }
+
+ if (cctx->psk_key.len == 0) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "psk_key.len == 0");
+
+ return 0;
+ }
+
+ if (cctx->psk_key.len > (size_t) max_psk_len) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
+ "psk_key.len: %i > max_psk_len: %i",
+ cctx->psk_key.len, max_psk_len);
+
+ return 0;
+ }
+
+ ngx_memcpy(psk, cctx->psk_key.data, cctx->psk_key.len);
+
+ /* return length of psk key */
+ return cctx->psk_key.len;
+ }
+
+ /* impossible to reach here */
+ ngx_http_lua_assert(0);
+
+failed:
+
+ if (r && r->pool) {
+ ngx_http_lua_free_fake_request(r);
+ }
+
+ if (fc) {
+ ngx_http_lua_close_fake_connection(fc);
+ }
+
+ return 0;
+}
+
+
+unsigned int ngx_http_lua_ssl_psk_client_handler(ngx_ssl_conn_t *ssl_conn,
+ const char *hint, char *identity, unsigned int max_identity_len,
+ unsigned char *psk, unsigned int max_psk_len)
+{
+ ngx_connection_t *c;
+ ngx_connection_t *dc; /* downstream connection */
+ ngx_http_request_t *r = NULL;
+ ngx_http_lua_loc_conf_t *llcf;
+
+ ngx_http_lua_socket_tcp_upstream_t *u;
+
+ c = ngx_ssl_get_connection(ssl_conn);
+
+ if (c == NULL) {
+ goto failed;
+ }
+
+ dd("ssl psk client handler, c = %p", c);
+
+ u = c->data;
+
+ if (u == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "no upstream socket found");
+ goto failed;
+ }
+
+ r = u->request;
+
+ if (r == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "no http request found");
+ goto failed;
+ }
+
+ dc = r->connection;
+
+ if (dc == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "no downstream socket found");
+ goto failed;
+ }
+
+ llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
+
+ if (llcf == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0,
+ "getting module loc conf failed");
+ goto failed;
+ }
+
+ if (hint == NULL) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "sslhandshake: psk server hint was null");
+ }
+ else {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "sslhandshake: psk server hint: %s", hint);
+
+ size_t hint_len = ngx_strlen(hint);
+ if (u->ssl_psk_identity_hint.data) {
+ /* buffer already allocated */
+
+ if (u->ssl_psk_identity_hint.len > hint_len) {
+ /* reuse it */
+ ngx_memcpy(u->ssl_psk_identity_hint.data, hint, hint_len);
+ u->ssl_psk_identity_hint.len = hint_len;
+ } else {
+ ngx_free(u->ssl_psk_identity_hint.data);
+ goto new_ssl_psk_identity_hint;
+ }
+ }
+ else {
+
+new_ssl_psk_identity_hint:
+
+ u->ssl_psk_identity_hint.data = ngx_alloc(hint_len + 1,
+ ngx_cycle->log);
+ if (u->ssl_psk_identity_hint.data == NULL) {
+ u->ssl_psk_identity_hint.len = 0;
+
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0,
+ "could not allocate memory for ssl_psk_identity_hint");
+ goto failed;
+ }
+
+ ngx_memcpy(u->ssl_psk_identity_hint.data, hint, hint_len);
+ u->ssl_psk_identity_hint.len = hint_len;
+ }
+ }
+
+ if (llcf->ssl_psk_identity.len) {
+ if (llcf->ssl_psk_identity.len <= max_identity_len) {
+ ngx_snprintf((u_char *) identity, max_identity_len, "%V",
+ &llcf->ssl_psk_identity);
+ }
+ else {
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0,
+ "ssl_psk_identity.len: %i > max_identity_len: %i",
+ llcf->ssl_psk_identity.len, max_identity_len);
+ goto failed;
+ }
+ }
+ else {
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0,
+ "no ssl_psk_identity defined");
+ goto failed;
+ }
+
+ if (llcf->ssl_psk_key.len) {
+ if (llcf->ssl_psk_key.len <= max_psk_len) {
+ ngx_memcpy(psk, llcf->ssl_psk_key.data, llcf->ssl_psk_key.len);
+ return llcf->ssl_psk_key.len;
+ }
+ else {
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0,
+ "ssl_psk_key.len: %i > max_psk_len: %i",
+ llcf->ssl_psk_key.len, max_psk_len);
+ goto failed;
+ }
+ }
+ else {
+ ngx_ssl_error(NGX_LOG_ALERT, dc->log, 0, "no ssl_psk_key defined");
+ goto failed;
+ }
+
+ /* impossible to reach here */
+ ngx_http_lua_assert(0);
+
+failed:
+
+ return 0;
+}
+
+static u_char *
+ngx_http_lua_log_ssl_psk_error(ngx_log_t *log, u_char *buf, size_t len)
+{
+ u_char *p;
+ ngx_connection_t *c;
+
+ if (log->action) {
+ p = ngx_snprintf(buf, len, " while %s", log->action);
+ len -= p - buf;
+ buf = p;
+ }
+
+ p = ngx_snprintf(buf, len, ", context: ssl_psk_by_lua*");
+ len -= p - buf;
+ buf = p;
+
+ c = log->data;
+
+ if (c->addr_text.len) {
+ p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text);
+ len -= p - buf;
+ buf = p;
+ }
+
+ if (c && c->listening && c->listening->addr_text.len) {
+ p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text);
+ /* len -= p - buf; */
+ buf = p;
+ }
+
+ return buf;
+}
+
+
+#ifndef NGX_LUA_NO_FFI_API
+
+/* set psk key from key to lua context. */
+int
+ngx_http_lua_ffi_ssl_set_psk_key(ngx_http_request_t *r,
+ const char *key, size_t len, char **err)
+{
+ u_char *buf;
+ ngx_connection_t *c;
+ ngx_ssl_conn_t *ssl_conn;
+ ngx_http_lua_ssl_ctx_t *cctx;
+
+ c = r->connection;
+
+ if (c == NULL || c->ssl == NULL) {
+ *err = "bad request";
+ return NGX_ERROR;
+ }
+
+ ssl_conn = c->ssl->connection;
+ if (ssl_conn == NULL) {
+ *err = "bad ssl conn";
+ return NGX_ERROR;
+ }
+
+ dd("set cctx psk key");
+ cctx = ngx_http_lua_ssl_get_ctx(ssl_conn);
+ if (cctx == NULL) {
+ *err = "bad lua context";
+ return NGX_ERROR;
+ }
+
+ buf = ngx_palloc(cctx->connection->pool, len);
+ if (buf == NULL) {
+ *err = "unable to alloc memory for buffer";
+ return NGX_ERROR;
+ }
+ ngx_memcpy(buf, key, len);
+
+ cctx->psk_key.data = buf;
+ cctx->psk_key.len = len;
+
+ return NGX_OK;
+}
+
+
+/* get psk identity from lua context into buf.
+ * the memory allocation of buf should be handled externally. */
+int
+ngx_http_lua_ffi_ssl_get_psk_identity(ngx_http_request_t *r,
+ char *buf, char **err)
+{
+ int id_len;
+ u_char *id;
+ ngx_connection_t *c;
+ ngx_ssl_conn_t *ssl_conn;
+ ngx_http_lua_ssl_ctx_t *cctx;
+
+ c = r->connection;
+
+ if (c == NULL || c->ssl == NULL) {
+ *err = "bad request";
+ return NGX_ERROR;
+ }
+
+ ssl_conn = c->ssl->connection;
+ if (ssl_conn == NULL) {
+ *err = "bad ssl conn";
+ return NGX_ERROR;
+ }
+
+ dd("get cctx psk identity");
+ cctx = ngx_http_lua_ssl_get_ctx(ssl_conn);
+ if (cctx == NULL) {
+ *err = "bad lua context";
+ return NGX_ERROR;
+ }
+
+ if(!cctx->entered_psk_handler) {
+ *err = "not in psk context";
+ return NGX_ERROR;
+ }
+
+ id = cctx->psk_identity.data;
+ if (id == NULL) {
+ *err = "uninitialized psk identity in lua context";
+ return NGX_ERROR;
+ }
+
+ id_len = cctx->psk_identity.len;
+ if (id_len == 0) {
+ *err = "uninitialized psk identity len in lua context";
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(buf, id, id_len);
+
+ return NGX_OK;
+}
+
+
+/* return the size of psk identity. */
+int
+ngx_http_lua_ffi_ssl_get_psk_identity_size(ngx_http_request_t *r,
+ char **err)
+{
+ ngx_connection_t *c;
+ ngx_ssl_conn_t *ssl_conn;
+ ngx_http_lua_ssl_ctx_t *cctx;
+
+ c = r->connection;
+
+ if (c == NULL || c->ssl == NULL) {
+ *err = "bad request";
+ return NGX_ERROR;
+ }
+
+ ssl_conn = c->ssl->connection;
+ if (ssl_conn == NULL) {
+ *err = "bad ssl conn";
+ return NGX_ERROR;
+ }
+
+ dd("get cctx psk identity");
+ cctx = ngx_http_lua_ssl_get_ctx(ssl_conn);
+ if (cctx == NULL) {
+ *err = "bad lua context";
+ return NGX_ERROR;
+ }
+
+ if(!cctx->entered_psk_handler) {
+ *err = "not in psk context";
+ return NGX_ERROR;
+ }
+
+ if (cctx->psk_identity.len == 0) {
+ *err = "uninitialized psk identity len in lua context";
+ return NGX_ERROR;
+ }
+
+ return cctx->psk_identity.len;
+}
+
+
+#endif /* NGX_LUA_NO_FFI_API */
+
+
+#endif /* NGX_HTTP_SSL */
diff --git a/src/ngx_http_lua_ssl_pskby.h b/src/ngx_http_lua_ssl_pskby.h
new file mode 100644
index 0000000000..fcda5bee3b
--- /dev/null
+++ b/src/ngx_http_lua_ssl_pskby.h
@@ -0,0 +1,32 @@
+
+/*
+ * Based on ngx_http_lua_ssl_certby.h and ngx_http_lua_ssl_session_storeby.h
+ * by Yichun Zhang (agentzh)
+ *
+ * Author: Tuure Vartiainen (vartiait)
+ */
+
+
+#ifndef _NGX_HTTP_LUA_SSL_PSKBY_H_INCLUDED_
+#define _NGX_HTTP_LUA_SSL_PSKBY_H_INCLUDED_
+
+
+#include "ngx_http_lua_common.h"
+
+
+#if (NGX_HTTP_SSL)
+
+
+unsigned int ngx_http_lua_ssl_psk_server_handler(ngx_ssl_conn_t *ssl_conn,
+ const char *identity, unsigned char *psk, unsigned int max_psk_len);
+
+unsigned int ngx_http_lua_ssl_psk_client_handler(ngx_ssl_conn_t *ssl_conn,
+ const char *hint, char *identity, unsigned int max_identity_len,
+ unsigned char *psk, unsigned int max_psk_len);
+
+#endif /* NGX_HTTP_SSL */
+
+
+#endif /* _NGX_HTTP_LUA_SSL_PSKBY_H_INCLUDED_ */
+
+/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
diff --git a/src/ngx_http_lua_util.h b/src/ngx_http_lua_util.h
index 2f995e0455..9b731cfd9a 100644
--- a/src/ngx_http_lua_util.h
+++ b/src/ngx_http_lua_util.h
@@ -91,6 +91,7 @@ extern char ngx_http_lua_headers_metatable_key;
"ssl_session_store_by_lua*" \
: (c) == NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH ? \
"ssl_session_fetch_by_lua*" \
+ : (c) == NGX_HTTP_LUA_CONTEXT_SSL_PSK ? "ssl_psk_by_lua*" \
: "(unknown)")
diff --git a/t/129-ssl-socket.t b/t/129-ssl-socket.t
index e7447a7ced..8d7d97b789 100644
--- a/t/129-ssl-socket.t
+++ b/t/129-ssl-socket.t
@@ -1181,7 +1181,7 @@ lua ssl free session: ([0-9A-F]+):1
$/
--- error_log
lua ssl server name: "openresty.org"
-SSL: TLSv1.2, cipher: "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2
+SSL: TLSv1.2, cipher: "ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2
--- no_error_log
SSL reused session
[error]
@@ -1341,7 +1341,7 @@ lua ssl free session: ([0-9A-F]+):1
$/
--- error_log
lua ssl server name: "openresty.org"
-SSL: TLSv1, cipher: "ECDHE-RSA-AES128-SHA SSLv3
+SSL: TLSv1, cipher: "ECDHE-RSA-AES256-SHA SSLv3
--- no_error_log
SSL reused session
[error]
@@ -2034,7 +2034,7 @@ SSL reused session
content_by_lua '
local sock = ngx.socket.tcp()
- sock:settimeout(2000)
+ sock:settimeout(3000)
do
local ok, err = sock:connect("openresty.org", 443)
@@ -2103,7 +2103,7 @@ lua ssl server name: "openresty.org"
SSL reused session
[error]
[alert]
---- timeout: 5
+--- timeout: 6
diff --git a/t/140-ssl-c-api.t b/t/140-ssl-c-api.t
index 8734d1477d..d2ffee97cc 100644
--- a/t/140-ssl-c-api.t
+++ b/t/140-ssl-c-api.t
@@ -62,6 +62,15 @@ ffi.cdef[[
void ngx_http_lua_ffi_free_priv_key(void *cdata);
int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err);
+
+ int ngx_http_lua_ffi_ssl_set_psk_key(void *r,
+ const char *key, size_t len, char **err);
+
+ int ngx_http_lua_ffi_ssl_get_psk_identity(void *r,
+ char *buf, char **err);
+
+ int ngx_http_lua_ffi_ssl_get_psk_identity_size(void *r,
+ char **err);
]]
_EOC_
}
@@ -811,3 +820,160 @@ lua ssl server name: "test.com"
--- no_error_log
[error]
[alert]
+
+
+
+=== TEST 6: TLS-PSK
+--- http_config
+ server {
+ listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
+ server_name test.com;
+
+ ssl_protocols TLSv1;
+ ssl_ciphers PSK;
+
+ ssl_certificate_by_lua_block {
+ collectgarbage()
+
+ local ffi = require "ffi"
+ require "defines"
+
+ local errmsg = ffi.new("char *[1]")
+
+ local r = getfenv(0).__ngx_req
+ if not r then
+ ngx.log(ngx.ERR, "no request found")
+ return
+ end
+
+ local len = ffi.C.ngx_http_lua_ffi_ssl_get_psk_identity_size(r, errmsg)
+
+ if len < 0 then
+ local error_msg = ffi.string(errmsg[0])
+ if error_msg and error_msg == "not in psk context" then
+ -- handler was not called by TLS-PSK callback
+ return
+ end
+ ngx.log(ngx.ERR, "failed to get psk identity size: ", error_msg)
+ return
+ end
+
+ if len > 4096 then
+ ngx.log(ngx.ERR, "psk identity size too long")
+ return
+ end
+
+ local buf = ffi.new("char[?]", 4096)
+
+ local rc = ffi.C.ngx_http_lua_ffi_ssl_get_psk_identity(r, buf, errmsg)
+ if rc ~= 0 then
+ ngx.log(ngx.ERR, "failed to get psk identity: ", ffi.string(errmsg[0]))
+ return
+ end
+
+ local psk_identity = ffi.string(buf, len)
+ if not psk_identity then
+ ngx.log(ngx.ERR, "psk_identity is undefined")
+ return
+ end
+
+ local psk_key = "psk_test_key"
+
+ local rc = ffi.C.ngx_http_lua_ffi_ssl_set_psk_key(r, psk_key, #psk_key, errmsg)
+ if rc ~= 0 then
+ ngx.log(ngx.ERR, "failed to set psk key: ", ffi.string(errmsg[0]))
+ return
+ end
+
+ return ngx.OK
+ }
+
+ ssl_certificate ../../cert/test.crt;
+ ssl_certificate_key ../../cert/test.key;
+
+ ssl_psk_identity_hint psk_test_identity_hint;
+
+ server_tokens off;
+ location /foo {
+ default_type 'text/plain';
+ content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) }
+ more_clear_headers Date;
+ }
+ }
+--- config
+ server_tokens off;
+
+ location /t {
+ lua_ssl_ciphers PSK;
+ lua_ssl_psk_identity psk_test_identity;
+ lua_ssl_psk_key psk_test_key;
+
+ content_by_lua_block {
+ do
+ local sock = ngx.socket.tcp()
+
+ sock:settimeout(2000)
+
+ local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
+ if not ok then
+ ngx.say("failed to connect: ", err)
+ return
+ end
+
+ ngx.say("connected: ", ok)
+
+ local sess, err = sock:sslhandshake(nil, "test.com", false)
+ if not sess then
+ ngx.say("failed to do SSL handshake: ", err)
+ return
+ end
+
+ ngx.say("ssl handshake: ", type(sess))
+
+ local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
+ local bytes, err = sock:send(req)
+ if not bytes then
+ ngx.say("failed to send http request: ", err)
+ return
+ end
+
+ ngx.say("sent http request: ", bytes, " bytes.")
+
+ while true do
+ local line, err = sock:receive()
+ if not line then
+ -- ngx.say("failed to recieve response status line: ", err)
+ break
+ end
+
+ ngx.say("received: ", line)
+ end
+
+ local ok, err = sock:close()
+ ngx.say("close: ", ok, " ", err)
+ end -- do
+ -- collectgarbage()
+ }
+ }
+
+--- request
+GET /t
+--- response_body
+connected: 1
+ssl handshake: userdata
+sent http request: 56 bytes.
+received: HTTP/1.1 201 Created
+received: Server: nginx
+received: Content-Type: text/plain
+received: Content-Length: 4
+received: Connection: close
+received:
+received: foo
+close: 1 nil
+
+--- error_log
+lua ssl server name: "test.com"
+
+--- no_error_log
+[error]
+[alert]