From 2dc8e74142a40ad585c3f41a4dc7c6b952572700 Mon Sep 17 00:00:00 2001 From: detailyang Date: Thu, 2 Feb 2017 22:44:45 +0800 Subject: [PATCH 1/9] feature: support load private key with password --- src/ngx_http_lua_ssl.c | 31 + src/ngx_http_lua_ssl.h | 2 + src/ngx_http_lua_ssl_certby.c | 79 ++ t/140-ssl-c-api.t | 705 +++++++++++++++++- t/cert/test_ecdsa_with_password_openresty.key | 8 + t/cert/test_with_password_openresty.key | 18 + 6 files changed, 842 insertions(+), 1 deletion(-) create mode 100644 t/cert/test_ecdsa_with_password_openresty.key create mode 100644 t/cert/test_with_password_openresty.key diff --git a/src/ngx_http_lua_ssl.c b/src/ngx_http_lua_ssl.c index 8ed7b95417..d631a23adb 100644 --- a/src/ngx_http_lua_ssl.c +++ b/src/ngx_http_lua_ssl.c @@ -34,4 +34,35 @@ ngx_http_lua_ssl_init(ngx_log_t *log) } +int +ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, + void *userdata) +{ + ngx_str_t *pwd = userdata; + + if (rwflag) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ngx_http_lua_ssl_password_callback() " + "is called for encryption"); + return 0; + } + + if (pwd->len == 0) { + return 0; + } + + if (pwd->len > (size_t) size) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "password is truncated to %d bytes", size); + + } else { + size = pwd->len; + } + + ngx_memcpy(buf, pwd->data, size); + + return size; +} + + #endif /* NGX_HTTP_SSL */ diff --git a/src/ngx_http_lua_ssl.h b/src/ngx_http_lua_ssl.h index 7a245ffda7..190f703bd2 100644 --- a/src/ngx_http_lua_ssl.h +++ b/src/ngx_http_lua_ssl.h @@ -35,6 +35,8 @@ typedef struct { ngx_int_t ngx_http_lua_ssl_init(ngx_log_t *log); +int ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, + void *userdata); extern int ngx_http_lua_ssl_ctx_index; diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c index 84e309316a..d2272f0784 100644 --- a/src/ngx_http_lua_ssl_certby.c +++ b/src/ngx_http_lua_ssl_certby.c @@ -982,6 +982,51 @@ ngx_http_lua_ffi_priv_key_pem_to_der(const u_char *pem, size_t pem_len, } +int +ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const u_char *pem, + size_t pem_len, const u_char *pwd, size_t pwd_len, u_char *der, char **err) +{ + int len; + BIO *in; + EVP_PKEY *pkey; + ngx_str_t password; + + password.data = (u_char *) pwd; + password.len = pwd_len; + + in = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (in == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NGX_ERROR; + } + + pkey = PEM_read_bio_PrivateKey(in, NULL, + ngx_http_lua_ssl_password_callback, + (void *) &password); + if (pkey == NULL) { + BIO_free(in); + *err = "PEM_read_bio_PrivateKey() failed"; + ERR_clear_error(); + return NGX_ERROR; + } + + BIO_free(in); + + len = i2d_PrivateKey(pkey, &der); + if (len < 0) { + EVP_PKEY_free(pkey); + *err = "i2d_PrivateKey() failed"; + ERR_clear_error(); + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + return len; +} + + void * ngx_http_lua_ffi_parse_pem_cert(const u_char *pem, size_t pem_len, char **err) @@ -1102,6 +1147,40 @@ ngx_http_lua_ffi_parse_pem_priv_key(const u_char *pem, size_t pem_len, } +void * +ngx_http_lua_ffi_parse_pem_priv_key_with_password(const u_char *pem, + size_t pem_len, const u_char *pwd, size_t pwd_len, char **err) +{ + BIO *in; + EVP_PKEY *pkey; + ngx_str_t password; + + password.data = (u_char *) pwd; + password.len = pwd_len; + + in = BIO_new_mem_buf((char *) pem, (int) pem_len); + if (in == NULL) { + *err = "BIO_new_mem_buf() failed"; + ERR_clear_error(); + return NULL; + } + + pkey = PEM_read_bio_PrivateKey(in, NULL, + ngx_http_lua_ssl_password_callback, + (void *) &password); + if (pkey == NULL) { + *err = "PEM_read_bio_PrivateKey() failed"; + BIO_free(in); + ERR_clear_error(); + return NULL; + } + + BIO_free(in); + + return pkey; +} + + void ngx_http_lua_ffi_free_priv_key(void *cdata) { diff --git a/t/140-ssl-c-api.t b/t/140-ssl-c-api.t index 44ad93d1c0..6dd4758452 100644 --- a/t/140-ssl-c-api.t +++ b/t/140-ssl-c-api.t @@ -11,7 +11,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` }; if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); } else { - plan tests => repeat_each() * (blocks() * 5 + 1); + plan tests => repeat_each() * (blocks() * 5); } $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -34,6 +34,9 @@ ffi.cdef[[ int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, size_t pem_len, unsigned char *der, char **err); + int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, size_t pem_len, unsigned char *der, char **err); @@ -51,6 +54,9 @@ ffi.cdef[[ void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, size_t pem_len, char **err); + void *ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char*pwd, size_t pwd_len, char **err); + int ngx_http_lua_ffi_set_cert(void *r, void *cdata, char **err); @@ -811,3 +817,700 @@ lua ssl server name: "test.com" --- no_error_log [error] [alert] + + + +=== TEST 6: simple cert + private key with password +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + require "defines" + local ffi = require "ffi" + + 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 + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert = f:read("*all") + f:close() + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local cert_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey = f:read("*all") + f:close() + + out = ffi.new("char [?]", #pkey) + + local pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( + pkey, #pkey, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local pkey_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + 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; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + 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", true) + 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 receive 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] + + + +=== TEST 7: ECDSA cert + private key with password +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + 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 + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert = f:read("*all") + f:close() + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local cert_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) + local pkey = f:read("*all") + f:close() + + out = ffi.new("char [?]", #pkey) + + local pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( + pkey, #pkey, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local pkey_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + 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; + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + location /t { + 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", true) + 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 receive 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] + + + +=== TEST 8: simple cert + private key cdata with password +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + 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 + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(cert) + + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( + pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + 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; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + 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", true) + 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] + + + +=== TEST 9: ECDSA cert + private key cdata with password +--- http_config + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + 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 + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert_data = f:read("*all") + f:close() + + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_cert(cert) + + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( + pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + 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; + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + location /t { + 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", true) + 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] + + + +=== TEST 10: ffi private key with password +--- config + server_tokens off; + + location /t { + content_by_lua_block { + local ffi = require "ffi" + ffi.cdef[[ + int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); + + void * ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char*pwd, size_t pwd_len, char **err); + void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, + size_t pem_len, char **err); + ]] + + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local errmsg = ffi.new("char *[1]") + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.say("parse key with right password: error") + else + ngx.say("parse key with right password: success") + end + + pwd = "wrongpassword" + pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key with wrong password: ", + ffi.string(errmsg[0])) + ngx.say("parse key with wrong password: success") + else + ngx.say("parse key with right password: error") + end + + local cert = pkey_data + local out = ffi.new("char [?]", #cert) + + pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.say("pem to der with right password: error") + else + ngx.say("pem to der with right password: success") + end + + pwd = "wrongpassword" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to transform PEM to DER with wrong password: ", + ffi.string(errmsg[0])) + ngx.say("pem to der with wrong password: success") + else + ngx.say("pem to der with wrong password: error") + end + } + } + +--- request +GET /t +--- response_body +parse key with right password: success +parse key with wrong password: success +pem to der with right password: success +pem to der with wrong password: success + +--- error_log +failed to parse PEM priv key with wrong password: PEM_read_bio_PrivateKey +failed to transform PEM to DER with wrong password: PEM_read_bio_PrivateKey + diff --git a/t/cert/test_ecdsa_with_password_openresty.key b/t/cert/test_ecdsa_with_password_openresty.key new file mode 100644 index 0000000000..1b7d1ef78c --- /dev/null +++ b/t/cert/test_ecdsa_with_password_openresty.key @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,E10D3514C833E7DB + +i14NkITdIEUw16Bs9tWKKgdFbgVrOda2lNTuo+wEsetKUkeGN/+c+1ocEy3wnGoc +tQJjATOML+zn0FK3DjnnamjrTSmuI2T4cCwNsMdfVmxajaZ/ru8NG9j4R5yOnfb0 +5dTJaOimLR9rLatazNyBX5EySaxdV6qcqjueLxQSvjs= +-----END EC PRIVATE KEY----- diff --git a/t/cert/test_with_password_openresty.key b/t/cert/test_with_password_openresty.key new file mode 100644 index 0000000000..6d366fe7c0 --- /dev/null +++ b/t/cert/test_with_password_openresty.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1B6334AB2218970F + +bGEgmiXQS+UcYFQ6E7y7HyIg/W6ZHmrIKJRdGpq1jWSGiBAZQq5xMI4IzHywhnfi +uv6ZQ4PcbxZs5fRAR6jtH0Pewak6XCYYEMHp7xbuvo5dO05yh5gXJmYpxaJ4twjB +PVan6UkTTT/nzis3Auo2YZOqW0W+J+ZYVrzl905BWsslaK+GGYBIYfnJgrVtPTbo +uo6kfLDAf1n90AejdbATWY83USOgRufWi1/IMz7kFSR8f3QUJd2tjutHb79VTW/6 +OFq4L1hDOeL2NpPRcwUS3PjSJD9Sar33mbdZPZagBivZcwyxh0lMOst7fB+pLD+v +RLYHUCdT6akFgAuu2/Hs+xjHtPQBnaPvn1C/802Wpbh3ulDmn3UCaOBzm1RD8yw2 +XWna2HlefjnIdcTkQom0gcPSRUmCo8//0oF1GGmJM+A+3vrg6tLvZqZwoO+kU4s1 +3x1B1zNl2jSMpZRoUlHFfOVh+FdAITMaihHQjQ6OmxXEhTTHPAiy2gRkFWKmKQFw +4tupvGHaLA1/rjiMzu1lwvZ8OD0UmJG1GlLqHVVJuZ/NC5SvnuBI+AUQS9mALPTB ++PyOhDIa3hIvpzICbNLxaG58nOwySZqeWWMvpvpd9SU+Ui7JCOz6picyEzzWTVtz +Xwhrx2Hw0ghenEwdsaidECIPI/pf82wdPMkqmaMkI3y11YQXMHJoTvRybRYHYZzg +pkxjmnOflrvX1PWb2ZiOZf0k6fA9nYAyM3xsSR74qNxVKibo0GIxPop3Z/7imJZq +4TV+yPHEM8VpdJjubhkEAp3cmZ6cuXjorXmCCqO/MZCnFXaV7aMWug== +-----END RSA PRIVATE KEY----- From e52023850b1810909dee6250dc1dc0be0bd0f949 Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:14:26 +0800 Subject: [PATCH 2/9] style: align --- src/ngx_http_lua_ssl_certby.c | 4 ++-- t/{141-luajit.t => 151-luajit.t} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename t/{141-luajit.t => 151-luajit.t} (100%) diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c index d2272f0784..06a30b6aa5 100644 --- a/src/ngx_http_lua_ssl_certby.c +++ b/src/ngx_http_lua_ssl_certby.c @@ -989,7 +989,7 @@ ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const u_char *pem, int len; BIO *in; EVP_PKEY *pkey; - ngx_str_t password; + ngx_str_t password; password.data = (u_char *) pwd; password.len = pwd_len; @@ -1153,7 +1153,7 @@ ngx_http_lua_ffi_parse_pem_priv_key_with_password(const u_char *pem, { BIO *in; EVP_PKEY *pkey; - ngx_str_t password; + ngx_str_t password; password.data = (u_char *) pwd; password.len = pwd_len; diff --git a/t/141-luajit.t b/t/151-luajit.t similarity index 100% rename from t/141-luajit.t rename to t/151-luajit.t From c3b9a38c2dd8b589e976f7a684061a95e28520fb Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:14:49 +0800 Subject: [PATCH 3/9] tests: move password test to new .t --- t/141-ssl-c-api-password.t | 536 +++++++++++++++++++++++++++++++++++++ 1 file changed, 536 insertions(+) create mode 100644 t/141-ssl-c-api-password.t diff --git a/t/141-ssl-c-api-password.t b/t/141-ssl-c-api-password.t new file mode 100644 index 0000000000..b17b92f1b6 --- /dev/null +++ b/t/141-ssl-c-api-password.t @@ -0,0 +1,536 @@ +# vim:set ft= ts=4 sw=4 et fdm=marker: + +use Test::Nginx::Socket::Lua; + +repeat_each(3); + +# All these tests need to have new openssl +my $NginxBinary = $ENV{'TEST_NGINX_BINARY'} || 'nginx'; +my $openssl_version = eval { `$NginxBinary -V 2>&1` }; + +if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { + plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); +} else { + plan tests => repeat_each() * (blocks() * 5 - 1); +} + +$ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); + +log_level 'debug'; +no_long_string(); + +add_block_preprocessor(sub { + my $block = shift; + + if (!defined $block->user_files) { + $block->set_value("user_files", <<'_EOC_'); +>>> defines.lua +local ffi = require "ffi" + +ffi.cdef[[ + int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, + size_t pem_len, unsigned char *der, char **err); + + int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); + + void *ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, + const unsigned char*pwd, size_t pwd_len, char **err); + + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); + + int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, + const char *data, size_t len, char **err); + + int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, + const char *data, size_t len, char **err); + + void *ngx_http_lua_ffi_parse_pem_cert(const unsigned char *pem, + size_t pem_len, char **err); + + int ngx_http_lua_ffi_set_cert(void *r, + void *cdata, char **err); + + int ngx_http_lua_ffi_set_priv_key(void *r, + void *cdata, char **err); + + void ngx_http_lua_ffi_free_cert(void *cdata); + + void ngx_http_lua_ffi_free_priv_key(void *cdata); +]] +_EOC_ + } + + my $http_config = $block->http_config || ''; + $http_config .= <<'_EOC_'; +lua_package_path "$prefix/html/?.lua;;"; +_EOC_ + $block->set_value("http_config", $http_config); + + my $config = $block->config || ''; + if (!defined($block->config)) { + $config = <<_EOC_; +server_tokens off; + +location /t { + 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", true) + 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 receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } +} +_EOC_ + $block->set_value("config", $config); + } + + if (!defined $block->response_body) { + my $response_body = <<_EOC_; +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 +_EOC_ + $block->set_value("response_body", $response_body); + } +}); + +run_tests(); + +__DATA__ + +=== TEST 1: simple cert + private key with password +--- http_config + lua_ssl_trusted_certificate ../../cert/test.crt; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + + ssl_certificate_by_lua_block { + collectgarbage() + + require "defines" + local ffi = require "ffi" + + 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 + + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert = f:read("*all") + f:close() + + local out = ffi.new("char [?]", #cert) + + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + + local cert_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey = f:read("*all") + f:close() + + out = ffi.new("char [?]", #pkey) + + local pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( + pkey, #pkey, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + + local pkey_der = ffi.string(out, rc) + + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + + 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; + } + } + +--- request +GET /t + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 2: ECDSA cert + private key with password +--- http_config + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert = f:read("*all") + f:close() + local out = ffi.new("char [?]", #cert) + local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + local cert_der = ffi.string(out, rc) + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER cert: ", + ffi.string(errmsg[0])) + return + end + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) + local pkey = f:read("*all") + f:close() + out = ffi.new("char [?]", #pkey) + local pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( + pkey, #pkey, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + local pkey_der = ffi.string(out, rc) + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set DER priv key: ", + ffi.string(errmsg[0])) + return + end + } + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + 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; + } + } + +--- request +GET /t + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 3: simple cert + private key cdata with password +--- http_config + lua_ssl_trusted_certificate ../../cert/test.crt; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test.crt", "rb")) + local cert_data = f:read("*all") + f:close() + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + ffi.C.ngx_http_lua_ffi_free_cert(cert) + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( + pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + 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; + } + } + +--- request +GET /t + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 4: ECDSA cert + private key cdata with password +--- http_config + lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) + local cert_data = f:read("*all") + f:close() + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) + if not cert then + ngx.log(ngx.ERR, "failed to parse PEM cert: ", + ffi.string(errmsg[0])) + return + end + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata cert: ", + ffi.string(errmsg[0])) + return + end + ffi.C.ngx_http_lua_ffi_free_cert(cert) + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( + pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key: ", + ffi.string(errmsg[0])) + return + end + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) + if rc ~= 0 then + ngx.log(ngx.ERR, "failed to set cdata priv key: ", + ffi.string(errmsg[0])) + return + end + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) + } + ssl_certificate ../../cert/test2.crt; + ssl_certificate_key ../../cert/test2.key; + 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; + } + } + +--- request +GET /t + +--- error_log +lua ssl server name: "test.com" + +--- no_error_log +[error] +[alert] + + + +=== TEST 5: ffi private key with password +--- config + server_tokens off; + + location /t { + content_by_lua_block { + local ffi = require "ffi" + require "defines" + + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) + local pkey_data = f:read("*all") + f:close() + + local errmsg = ffi.new("char *[1]") + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.say("parse key with right password: error") + else + ngx.say("parse key with right password: success") + end + + pwd = "wrongpassword" + pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) + if pkey == nil then + ngx.log(ngx.ERR, "failed to parse PEM priv key with wrong password: ", + ffi.string(errmsg[0])) + ngx.say("parse key with wrong password: success") + else + ngx.say("parse key with right password: error") + end + + local cert = pkey_data + local out = ffi.new("char [?]", #cert) + + pwd = "openresty" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.say("pem to der with right password: error") + else + ngx.say("pem to der with right password: success") + end + + pwd = "wrongpassword" + local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) + if rc < 1 then + ngx.log(ngx.ERR, "failed to transform PEM to DER with wrong password: ", + ffi.string(errmsg[0])) + ngx.say("pem to der with wrong password: success") + else + ngx.say("pem to der with wrong password: error") + end + } + } + +--- request +GET /t +--- response_body +parse key with right password: success +parse key with wrong password: success +pem to der with right password: success +pem to der with wrong password: success + +--- error_log +failed to parse PEM priv key with wrong password: PEM_read_bio_PrivateKey +failed to transform PEM to DER with wrong password: PEM_read_bio_PrivateKey + From 1a1162f9f7dfef46ed973407c4dffcb0f307f240 Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:16:26 +0800 Subject: [PATCH 4/9] revert t/140-ssl-c-api.t to old version --- t/140-ssl-c-api.t | 705 +--------------------------------------------- 1 file changed, 1 insertion(+), 704 deletions(-) diff --git a/t/140-ssl-c-api.t b/t/140-ssl-c-api.t index 6dd4758452..44ad93d1c0 100644 --- a/t/140-ssl-c-api.t +++ b/t/140-ssl-c-api.t @@ -11,7 +11,7 @@ my $openssl_version = eval { `$NginxBinary -V 2>&1` }; if ($openssl_version =~ m/built with OpenSSL (0|1\.0\.(?:0|1[^\d]|2[a-d]).*)/) { plan(skip_all => "too old OpenSSL, need 1.0.2e, was $1"); } else { - plan tests => repeat_each() * (blocks() * 5); + plan tests => repeat_each() * (blocks() * 5 + 1); } $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); @@ -34,9 +34,6 @@ ffi.cdef[[ int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, size_t pem_len, unsigned char *der, char **err); - int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, - const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); - int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, size_t pem_len, unsigned char *der, char **err); @@ -54,9 +51,6 @@ ffi.cdef[[ void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, size_t pem_len, char **err); - void *ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, - const unsigned char*pwd, size_t pwd_len, char **err); - int ngx_http_lua_ffi_set_cert(void *r, void *cdata, char **err); @@ -817,700 +811,3 @@ lua ssl server name: "test.com" --- no_error_log [error] [alert] - - - -=== TEST 6: simple cert + private key with password ---- http_config - server { - listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; - server_name test.com; - - ssl_certificate_by_lua_block { - collectgarbage() - - require "defines" - local ffi = require "ffi" - - 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 - - ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) - - local f = assert(io.open("t/cert/test.crt", "rb")) - local cert = f:read("*all") - f:close() - - local out = ffi.new("char [?]", #cert) - - local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) - if rc < 1 then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", - ffi.string(errmsg[0])) - return - end - - local cert_der = ffi.string(out, rc) - - local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set DER cert: ", - ffi.string(errmsg[0])) - return - end - - f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) - local pkey = f:read("*all") - f:close() - - out = ffi.new("char [?]", #pkey) - - local pwd = "openresty" - local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( - pkey, #pkey, pwd, #pwd, out, errmsg) - if rc < 1 then - ngx.log(ngx.ERR, "failed to parse PEM priv key: ", - ffi.string(errmsg[0])) - return - end - - local pkey_der = ffi.string(out, rc) - - local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set DER priv key: ", - ffi.string(errmsg[0])) - return - end - } - - ssl_certificate ../../cert/test2.crt; - ssl_certificate_key ../../cert/test2.key; - - 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; - lua_ssl_trusted_certificate ../../cert/test.crt; - - location /t { - 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", true) - 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 receive 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] - - - -=== TEST 7: ECDSA cert + private key with password ---- http_config - server { - listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; - server_name test.com; - - 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 - - ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) - - local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) - local cert = f:read("*all") - f:close() - - local out = ffi.new("char [?]", #cert) - - local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) - if rc < 1 then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", - ffi.string(errmsg[0])) - return - end - - local cert_der = ffi.string(out, rc) - - local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set DER cert: ", - ffi.string(errmsg[0])) - return - end - - f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) - local pkey = f:read("*all") - f:close() - - out = ffi.new("char [?]", #pkey) - - local pwd = "openresty" - local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( - pkey, #pkey, pwd, #pwd, out, errmsg) - if rc < 1 then - ngx.log(ngx.ERR, "failed to parse PEM priv key: ", - ffi.string(errmsg[0])) - return - end - - local pkey_der = ffi.string(out, rc) - - local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set DER priv key: ", - ffi.string(errmsg[0])) - return - end - } - - ssl_certificate ../../cert/test2.crt; - ssl_certificate_key ../../cert/test2.key; - - 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; - lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; - - location /t { - 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", true) - 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 receive 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] - - - -=== TEST 8: simple cert + private key cdata with password ---- http_config - server { - listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; - server_name test.com; - - 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 - - ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) - - local f = assert(io.open("t/cert/test.crt", "rb")) - local cert_data = f:read("*all") - f:close() - - local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) - if not cert then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", - ffi.string(errmsg[0])) - return - end - - local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set cdata cert: ", - ffi.string(errmsg[0])) - return - end - - ffi.C.ngx_http_lua_ffi_free_cert(cert) - - f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) - local pkey_data = f:read("*all") - f:close() - - local pwd = "openresty" - local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( - pkey_data, #pkey_data, pwd, #pwd, errmsg) - if pkey == nil then - ngx.log(ngx.ERR, "failed to parse PEM priv key: ", - ffi.string(errmsg[0])) - return - end - - local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set cdata priv key: ", - ffi.string(errmsg[0])) - return - end - - ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) - } - - ssl_certificate ../../cert/test2.crt; - ssl_certificate_key ../../cert/test2.key; - - 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; - lua_ssl_trusted_certificate ../../cert/test.crt; - - location /t { - 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", true) - 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] - - - -=== TEST 9: ECDSA cert + private key cdata with password ---- http_config - server { - listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; - server_name test.com; - - 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 - - ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) - - local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) - local cert_data = f:read("*all") - f:close() - - local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) - if not cert then - ngx.log(ngx.ERR, "failed to parse PEM cert: ", - ffi.string(errmsg[0])) - return - end - - local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set cdata cert: ", - ffi.string(errmsg[0])) - return - end - - ffi.C.ngx_http_lua_ffi_free_cert(cert) - - f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) - local pkey_data = f:read("*all") - f:close() - - local pwd = "openresty" - local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( - pkey_data, #pkey_data, pwd, #pwd, errmsg) - if pkey == nil then - ngx.log(ngx.ERR, "failed to parse PEM priv key: ", - ffi.string(errmsg[0])) - return - end - - local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) - if rc ~= 0 then - ngx.log(ngx.ERR, "failed to set cdata priv key: ", - ffi.string(errmsg[0])) - return - end - - ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) - } - - ssl_certificate ../../cert/test2.crt; - ssl_certificate_key ../../cert/test2.key; - - 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; - lua_ssl_trusted_certificate ../../cert/test_ecdsa.crt; - - location /t { - 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", true) - 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] - - - -=== TEST 10: ffi private key with password ---- config - server_tokens off; - - location /t { - content_by_lua_block { - local ffi = require "ffi" - ffi.cdef[[ - int ngx_http_lua_ffi_priv_key_pem_to_der(const unsigned char *pem, - size_t pem_len, unsigned char *der, char **err); - - int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, - const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); - - void * ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, - const unsigned char*pwd, size_t pwd_len, char **err); - void *ngx_http_lua_ffi_parse_pem_priv_key(const unsigned char *pem, - size_t pem_len, char **err); - ]] - - f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) - local pkey_data = f:read("*all") - f:close() - - local errmsg = ffi.new("char *[1]") - local pwd = "openresty" - local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) - if pkey == nil then - ngx.say("parse key with right password: error") - else - ngx.say("parse key with right password: success") - end - - pwd = "wrongpassword" - pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) - if pkey == nil then - ngx.log(ngx.ERR, "failed to parse PEM priv key with wrong password: ", - ffi.string(errmsg[0])) - ngx.say("parse key with wrong password: success") - else - ngx.say("parse key with right password: error") - end - - local cert = pkey_data - local out = ffi.new("char [?]", #cert) - - pwd = "openresty" - local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) - if rc < 1 then - ngx.say("pem to der with right password: error") - else - ngx.say("pem to der with right password: success") - end - - pwd = "wrongpassword" - local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) - if rc < 1 then - ngx.log(ngx.ERR, "failed to transform PEM to DER with wrong password: ", - ffi.string(errmsg[0])) - ngx.say("pem to der with wrong password: success") - else - ngx.say("pem to der with wrong password: error") - end - } - } - ---- request -GET /t ---- response_body -parse key with right password: success -parse key with wrong password: success -pem to der with right password: success -pem to der with wrong password: success - ---- error_log -failed to parse PEM priv key with wrong password: PEM_read_bio_PrivateKey -failed to transform PEM to DER with wrong password: PEM_read_bio_PrivateKey - From 5c60231e9671c2083f9aa64100aa6e1e732e9bb0 Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:24:17 +0800 Subject: [PATCH 5/9] style: remove unused whitespace --- t/141-ssl-c-api-password.t | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/t/141-ssl-c-api-password.t b/t/141-ssl-c-api-password.t index b17b92f1b6..6e80160665 100644 --- a/t/141-ssl-c-api-password.t +++ b/t/141-ssl-c-api-password.t @@ -30,27 +30,27 @@ local ffi = require "ffi" ffi.cdef[[ int ngx_http_lua_ffi_cert_pem_to_der(const unsigned char *pem, size_t pem_len, unsigned char *der, char **err); - + int ngx_http_lua_ffi_priv_key_pem_to_der_with_password(const unsigned char *pem, size_t pem_len, const unsigned char *pwd, size_t pwd_len, unsigned char *der, char **err); void *ngx_http_lua_ffi_parse_pem_priv_key_with_password(const unsigned char *pem, size_t pem_len, const unsigned char*pwd, size_t pwd_len, char **err); - + int ngx_http_lua_ffi_ssl_clear_certs(void *r, char **err); - + int ngx_http_lua_ffi_ssl_set_der_certificate(void *r, const char *data, size_t len, char **err); - + int ngx_http_lua_ffi_ssl_set_der_private_key(void *r, const char *data, size_t len, char **err); - + void *ngx_http_lua_ffi_parse_pem_cert(const unsigned char *pem, size_t pem_len, char **err); - + int ngx_http_lua_ffi_set_cert(void *r, void *cdata, char **err); - + int ngx_http_lua_ffi_set_priv_key(void *r, void *cdata, char **err); @@ -66,7 +66,7 @@ _EOC_ lua_package_path "$prefix/html/?.lua;;"; _EOC_ $block->set_value("http_config", $http_config); - + my $config = $block->config || ''; if (!defined($block->config)) { $config = <<_EOC_; @@ -123,7 +123,7 @@ location /t { _EOC_ $block->set_value("config", $config); } - + if (!defined $block->response_body) { my $response_body = <<_EOC_; connected: 1 @@ -320,7 +320,7 @@ lua ssl server name: "test.com" === TEST 3: simple cert + private key cdata with password --- http_config lua_ssl_trusted_certificate ../../cert/test.crt; - + server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; From ab2d04fd8ef5986997435cf18f25797efbb8db02 Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:45:38 +0800 Subject: [PATCH 6/9] style: add blank line for .t file --- t/141-ssl-c-api-password.t | 53 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/t/141-ssl-c-api-password.t b/t/141-ssl-c-api-password.t index 6e80160665..622c8c3e56 100644 --- a/t/141-ssl-c-api-password.t +++ b/t/141-ssl-c-api-password.t @@ -249,18 +249,23 @@ lua ssl server name: "test.com" server_name test.com; 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) local cert = f:read("*all") f:close() + local out = ffi.new("char [?]", #cert) local rc = ffi.C.ngx_http_lua_ffi_cert_pem_to_der(cert, #cert, out, errmsg) if rc < 1 then @@ -268,17 +273,22 @@ lua ssl server name: "test.com" ffi.string(errmsg[0])) return end + local cert_der = ffi.string(out, rc) + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_certificate(r, cert_der, #cert_der, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set DER cert: ", ffi.string(errmsg[0])) return end + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) local pkey = f:read("*all") f:close() + out = ffi.new("char [?]", #pkey) + local pwd = "openresty" local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password( pkey, #pkey, pwd, #pwd, out, errmsg) @@ -287,7 +297,9 @@ lua ssl server name: "test.com" ffi.string(errmsg[0])) return end + local pkey_der = ffi.string(out, rc) + local rc = ffi.C.ngx_http_lua_ffi_ssl_set_der_private_key(r, pkey_der, #pkey_der, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set DER priv key: ", @@ -295,9 +307,12 @@ lua ssl server name: "test.com" return end } + ssl_certificate ../../cert/test2.crt; ssl_certificate_key ../../cert/test2.key; + server_tokens off; + location /foo { default_type 'text/plain'; content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } @@ -326,35 +341,46 @@ lua ssl server name: "test.com" server_name test.com; 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test.crt", "rb")) local cert_data = f:read("*all") f:close() + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) if not cert then ngx.log(ngx.ERR, "failed to parse PEM cert: ", ffi.string(errmsg[0])) return end + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set cdata cert: ", ffi.string(errmsg[0])) return end + ffi.C.ngx_http_lua_ffi_free_cert(cert) + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) local pkey_data = f:read("*all") f:close() + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( pkey_data, #pkey_data, pwd, #pwd, errmsg) if pkey == nil then @@ -362,17 +388,22 @@ lua ssl server name: "test.com" ffi.string(errmsg[0])) return end + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set cdata priv key: ", ffi.string(errmsg[0])) return end + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) } + ssl_certificate ../../cert/test2.crt; ssl_certificate_key ../../cert/test2.key; + server_tokens off; + location /foo { default_type 'text/plain'; content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } @@ -399,36 +430,47 @@ lua ssl server name: "test.com" server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; + 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 + ffi.C.ngx_http_lua_ffi_ssl_clear_certs(r, errmsg) + local f = assert(io.open("t/cert/test_ecdsa.crt", "rb")) local cert_data = f:read("*all") f:close() + local cert = ffi.C.ngx_http_lua_ffi_parse_pem_cert(cert_data, #cert_data, errmsg) if not cert then ngx.log(ngx.ERR, "failed to parse PEM cert: ", ffi.string(errmsg[0])) return end + local rc = ffi.C.ngx_http_lua_ffi_set_cert(r, cert, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set cdata cert: ", ffi.string(errmsg[0])) return end + ffi.C.ngx_http_lua_ffi_free_cert(cert) + f = assert(io.open("t/cert/test_ecdsa_with_password_openresty.key", "rb")) local pkey_data = f:read("*all") f:close() + local pwd = "openresty" local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password( pkey_data, #pkey_data, pwd, #pwd, errmsg) @@ -437,17 +479,22 @@ lua ssl server name: "test.com" ffi.string(errmsg[0])) return end + local rc = ffi.C.ngx_http_lua_ffi_set_priv_key(r, pkey, errmsg) if rc ~= 0 then ngx.log(ngx.ERR, "failed to set cdata priv key: ", ffi.string(errmsg[0])) return end + ffi.C.ngx_http_lua_ffi_free_priv_key(pkey) } + ssl_certificate ../../cert/test2.crt; ssl_certificate_key ../../cert/test2.key; + server_tokens off; + location /foo { default_type 'text/plain'; content_by_lua_block { ngx.status = 201 ngx.say("foo") ngx.exit(201) } @@ -475,13 +522,15 @@ lua ssl server name: "test.com" content_by_lua_block { local ffi = require "ffi" require "defines" - + f = assert(io.open("t/cert/test_with_password_openresty.key", "rb")) local pkey_data = f:read("*all") f:close() local errmsg = ffi.new("char *[1]") + local pwd = "openresty" + local pkey = ffi.C.ngx_http_lua_ffi_parse_pem_priv_key_with_password(pkey_data, #pkey_data, pwd, #pwd, errmsg) if pkey == nil then ngx.say("parse key with right password: error") @@ -509,7 +558,7 @@ lua ssl server name: "test.com" else ngx.say("pem to der with right password: success") end - + pwd = "wrongpassword" local rc = ffi.C.ngx_http_lua_ffi_priv_key_pem_to_der_with_password(cert, #cert, pwd, #pwd, out, errmsg) if rc < 1 then From a42f837dc11a18bd67cb8f11c07bc62c6adbe132 Mon Sep 17 00:00:00 2001 From: detailyang Date: Fri, 3 Feb 2017 22:46:36 +0800 Subject: [PATCH 7/9] tests: optimize add_block_preprocessor --- t/141-ssl-c-api-password.t | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/t/141-ssl-c-api-password.t b/t/141-ssl-c-api-password.t index 622c8c3e56..a52d6a3670 100644 --- a/t/141-ssl-c-api-password.t +++ b/t/141-ssl-c-api-password.t @@ -67,9 +67,8 @@ lua_package_path "$prefix/html/?.lua;;"; _EOC_ $block->set_value("http_config", $http_config); - my $config = $block->config || ''; - if (!defined($block->config)) { - $config = <<_EOC_; + if (!defined $block->config) { + my $config = <<_EOC_; server_tokens off; location /t { From cacdcfa5b80e0b6f30097a6cc95fd43182d8aa3f Mon Sep 17 00:00:00 2001 From: detailyang Date: Mon, 6 Feb 2017 13:05:43 +0800 Subject: [PATCH 8/9] rename 151-luajit.t and 141-ssl-c-api-password.t --- t/{151-luajit.t => 141-luajit.t} | 0 t/{141-ssl-c-api-password.t => 151-ssl-c-api-password.t} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename t/{151-luajit.t => 141-luajit.t} (100%) rename t/{141-ssl-c-api-password.t => 151-ssl-c-api-password.t} (100%) diff --git a/t/151-luajit.t b/t/141-luajit.t similarity index 100% rename from t/151-luajit.t rename to t/141-luajit.t diff --git a/t/141-ssl-c-api-password.t b/t/151-ssl-c-api-password.t similarity index 100% rename from t/141-ssl-c-api-password.t rename to t/151-ssl-c-api-password.t From 66d45b8e162c5a192d2d0dafc3f3482660d88bc1 Mon Sep 17 00:00:00 2001 From: detailyang Date: Mon, 6 Feb 2017 13:09:29 +0800 Subject: [PATCH 9/9] set ngx_http_lua_ssl_password_callback is static --- src/ngx_http_lua_ssl.c | 31 ------------------------------- src/ngx_http_lua_ssl.h | 2 -- src/ngx_http_lua_ssl_certby.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/ngx_http_lua_ssl.c b/src/ngx_http_lua_ssl.c index d631a23adb..8ed7b95417 100644 --- a/src/ngx_http_lua_ssl.c +++ b/src/ngx_http_lua_ssl.c @@ -34,35 +34,4 @@ ngx_http_lua_ssl_init(ngx_log_t *log) } -int -ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, - void *userdata) -{ - ngx_str_t *pwd = userdata; - - if (rwflag) { - ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "ngx_http_lua_ssl_password_callback() " - "is called for encryption"); - return 0; - } - - if (pwd->len == 0) { - return 0; - } - - if (pwd->len > (size_t) size) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "password is truncated to %d bytes", size); - - } else { - size = pwd->len; - } - - ngx_memcpy(buf, pwd->data, size); - - return size; -} - - #endif /* NGX_HTTP_SSL */ diff --git a/src/ngx_http_lua_ssl.h b/src/ngx_http_lua_ssl.h index 190f703bd2..7a245ffda7 100644 --- a/src/ngx_http_lua_ssl.h +++ b/src/ngx_http_lua_ssl.h @@ -35,8 +35,6 @@ typedef struct { ngx_int_t ngx_http_lua_ssl_init(ngx_log_t *log); -int ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, - void *userdata); extern int ngx_http_lua_ssl_ctx_index; diff --git a/src/ngx_http_lua_ssl_certby.c b/src/ngx_http_lua_ssl_certby.c index 06a30b6aa5..c253242d5a 100644 --- a/src/ngx_http_lua_ssl_certby.c +++ b/src/ngx_http_lua_ssl_certby.c @@ -36,6 +36,8 @@ static u_char *ngx_http_lua_log_ssl_cert_error(ngx_log_t *log, u_char *buf, size_t len); static ngx_int_t ngx_http_lua_ssl_cert_by_chunk(lua_State *L, ngx_http_request_t *r); +static int ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, + void *userdata); ngx_int_t @@ -557,6 +559,37 @@ ngx_http_lua_ffi_ssl_get_tls1_version(ngx_http_request_t *r, char **err) } +static int +ngx_http_lua_ssl_password_callback(char *buf, int size, int rwflag, + void *userdata) +{ + ngx_str_t *pwd = userdata; + + if (rwflag) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ngx_http_lua_ssl_password_callback() " + "is called for encryption"); + return 0; + } + + if (pwd->len == 0) { + return 0; + } + + if (pwd->len > (size_t) size) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "password is truncated to %d bytes", size); + + } else { + size = pwd->len; + } + + ngx_memcpy(buf, pwd->data, size); + + return size; +} + + int ngx_http_lua_ffi_ssl_clear_certs(ngx_http_request_t *r, char **err) {