-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: support ssl.create_ctx and tcp:setsslctx #997
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: detailyang <[email protected]>
Signed-off-by: detailyang <[email protected]>
It seems there is quite a lot of code duplication from NGINX which is unnecessary IMO. Why not make Then you can use that Also, the currently implemented tests are probably not enough to test the functionality. |
@ghedo Thanks for you review :D
These duplicated code will appear because I cannot reuse
Since we have provide API to feed the
Just simply test in @agentzh I think @ghedo' suggestion is almost good for me. How do you think of it ? By the way, I will continue to refactor until we agree on the API Design :D |
IMO it would still be better to have a string parameter in But really, configuring enabled protocols doesn't need to happen at
Well, yeah, but you also need to test the functionality you are adding. Something like creating a ctx, setting a user certificate on it, and using that ctx with a socket to connect to a server. |
Since we want to cache void *ngx_http_lua_ffi_ssl_ctx_init(ngx_uint_t protocols, char **err); We will alloc
Now that we are ready to reuse
That's good and it's worth to do to make sure the functionality is okay without |
Signed-off-by: detailyang <[email protected]>
@ghedo After refactor the codebase, It reuse the @agentzh How do you think of it? |
@detailyang We should not allocate SSL data structures in Also, we should not let the SSL CTX thing bound to |
@detailyang Your current implementation seems good. I'll need to have a closer look. @doujiang24 What do you think of it? @ghedo Thanks for your review! Appreciated! |
t/151-ssl-ctx.t
Outdated
lua_package_path "\$prefix/html/?.lua;$TEST_NGINX_LUA_PACKAGE_PATH/?.lua;;../lua-resty-lrucache/lib/?.lua;"; | ||
|
||
init_by_lua_block { | ||
local ffi = require "ffi" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lua-nginx-module's test suite already depends on lua-resty-core. I think we'd better avoid duplicating such lua-resty-core code here in the test suite, which adds maintenance overhead. We can just test against the lua-resty-core Lua API directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, these tests actually adds maintenance overhead for me, Since these tests is the same as lua-resty-core. According what you have said, Can I think that if we are adding the FFI C API, we should simply test it in lua-nginx-module
and specially test in lua-resty-core
?
src/ngx_http_lua_ssl.c
Outdated
@@ -13,6 +13,11 @@ | |||
#if (NGX_HTTP_SSL) | |||
|
|||
|
|||
#define ngx_http_lua_ssl_check_method(method, method_len, s) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use Lua inline functions instead of macros for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This macro is remaining after refactoring and should be removed.
src/ngx_http_lua_ssl.c
Outdated
|
||
# if OPENSSL_VERSION_NUMBER < 0x1000205fL | ||
|
||
*err = "at least OpenSSL 1.0.2e required but found " OPENSSL_VERSION_TEXT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really requiring OpenSSL 1.0.2e+?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API SSL_CTX_add1_chain_cert says
These functions were first added to OpenSSL 1.0.2.
So I choose to requiring 1.0.2e in order to keep consistent with other function requires
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@detailyang Okay. Good to know :)
@agentzh @doujiang24 @ghedo |
src/ngx_http_lua_socket_tcp.c
Outdated
|
||
/* expose tcp object metatable to global for FFI */ | ||
lua_pushvalue(L, -1); | ||
lua_setglobal(L, ngx_http_lua_ngx_socket_tcp_mt_key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we'd better set it into REGISTRY table? And we can get it by debug.getregistry
.
like: https://github.com/openresty/lua-resty-core/blob/master/lib/resty/core/ctx.lua#L12
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Put it into REGISTRY table is better than global table.
src/ngx_http_lua_ssl.c
Outdated
0, | ||
"lua ssl ctx free: %p:%d", | ||
ssl_ctx, | ||
ssl_ctx->references); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: maybe bellow can be better?
0, "lua ssl ctx free: %p:%d",
ssl_ctx, ssl_ctx->references);
I mean we don't need one argument one line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotacha :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's better as the following ?
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log,
0, "lua ssl ctx free: %p:%d", ssl_ctx, ssl_ctx->references);
It will do not exceed 80 columns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, one line is better :)
Hello :D |
t/151-ssl-ctx.t
Outdated
|
||
int ngx_http_lua_ffi_ssl_ctx_set_cert(void *cdata_ctx, | ||
void *cdata_cert, char **err); | ||
]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's simply test the lua-resty-core's Lua API wrappers here in lua-nginx-module's test suite. Such things add to maintenance overhead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well. The only thing I'm confused is what's the 'simply test' ? if we want to simply test the ngx_http_lua_ffi_ssl_ctx_set_priv_key
and ngx_http_lua_ffi_ssl_ctx_set_cert
, should we set the priv_key and cert then send it to server ? Or just set the priv_key and cert then test the return value.
@agentzh Sorry for my poor English :(.
I took a few minutes to understand what's your meaning again. You want to tell me that just require lua-resty-core API rather than call FFI.C.API to simply test functionality ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@detailyang Yeah, you got it :)
src/ngx_http_lua_ssl.c
Outdated
x509 = sk_X509_value(cert, 0); | ||
if (x509 == NULL) { | ||
*err = "sk_X509_value() failed"; | ||
ngx_ssl_error(NGX_LOG_ERR, ngx_cycle->log, 0, *err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of logging the real error message into nginx's error log file, we should propagate it to the Lua land via the err
output parameter (of course, the type of err
needs adjustment). Let's avoid direct logging in these FFI C functions. We should let the Lua land caller to handle these error and inspect these error messages, which is much more flexible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. propagating the OpenSSL error message to Lua land is more flexible. So I'm thinking expose the error code by unsigned long ERR_get_error(void);
, let the Lua land caller to get the error string with error code by these functions as the following:
#include <openssl/err.h>
char *ERR_error_string(unsigned long e, char *buf);
void ERR_error_string_n(unsigned long e, char *buf, size_t len);
const char *ERR_lib_error_string(unsigned long e);
const char *ERR_func_error_string(unsigned long e);
const char *ERR_reason_error_string(unsigned long e);
Also we will implement the FFI API upon these functions. @agentzh How about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@agentzh I think agentzh just means remove the ngx_ss_error
here :)
Seems we don't need ERR_get_error
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@doujiang24 uhh, It looks like I'm worrying. But how to actively get the specific error message in Lua land without call ERR_get_error
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@detailyang Okay, I see, yes we need ERR_get_error
.
But I think we should do it in C land, something like this:
int ffi_c_func(char *err, int *err_len) {
/* get message by ERR_get_error or something else */
err_len = sprintf(err, message) - err;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@doujiang24 Maybe the err_len
is no need. I check the API char *ERR_error_string(unsigned long e, char *buf);
It says:
ERR_error_string() generates a human-readable string representing the error code e, and places it at buf. buf must be at least 120 bytes long. If buf is NULL , the error string is placed in a static buffer.
So pointing the static buffer is not bad IMO as the following:
if (SSL_CTX_use_PrivateKey(ssl_ctx, key) == 0) {
e = ERR_get_error();
if (e == 0) {
*err = "SSL_CTX_use_PrivateKey() failed";
} else {
*err = ERR_error_string(e, NULL);
}
return NGX_ERROR;
}
@doujiang24 @agentzh How about this?
Is there any plan to implement setting Motivation: When you need to use SSL(with client verification) in Thanks for working on this! |
@daurnimator I can see your point. But I think this relatively low level API is better to be self-contained and minimally implemented. interfacing with other Lua libraries create undesired dependencies and could also be slow. |
return NGX_ERROR; | ||
} | ||
|
||
ssl->ctx = ssl_ctx; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should increment ref count of SSL_CTX*
?
I think those two goals are at odds: I was suggesting a minimal implementation (of just |
Also consider an API of |
@daurnimator By "minimal" I mean zero external dependencies for this thing. So as a whole, the software is minimized (including any external deps). Sorry for the confusion. |
@detailyang Would love to have this PR accepted. Are you still actively working on this? |
I am also curious. @detailyang will you be working on a merge? |
@@ -34,4 +38,504 @@ ngx_http_lua_ssl_init(ngx_log_t *log) | |||
} | |||
|
|||
|
|||
static size_t | |||
ngx_http_lua_ssl_get_error(u_long e, u_char *ssl_err, | |||
size_t ssl_err_len, const char *default_err, size_t default_err_len) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just put some notes here:
OpenSSL stores errors in a queue. And it might generate multiple errors in a call.
Therefore,
- You need to drain the error queue to get all errors.
- Someone might only fetch the first error, and leave the others in the queue.
Current implementation of this function doesn't satisfy the deduction 1 and is vulnerable to the deduction 2.
@detailyang @agentzh |
@thibaultcha do you have time to take a look this PR? thanks. |
This pull request is now in conflict :( |
f924579
to
fef2581
Compare
Hello, is there a plan to give support of mtls on this library? |
This pull request is now in conflict :( |
This pull request is now in conflict :( |
This pull request is now in conflict :( |
This pull request is now in conflict :( |
I hereby granted the copyright of the changes in this pull request
to the authors of this lua-nginx-module project.
This PR have been discussed at #957. These FFI API as the following:
ngx_http_lua_ffi_ssl_ctx_init(const u_char *method, size_t method_len, char **err)
ngx_http_lua_ffi_ssl_ctx_set_cert(void *cdata_ctx, void *cdata_cert, char **err)
ngx_http_lua_ffi_ssl_ctx_set_priv_key(void *cdata_ctx, void *cdata_key, char **err)
ngx_http_lua_ffi_ssl_ctx_free(void *cdata)
I refer to the Node.js C++ as a guide. Now It exposes
set_cert
andset_priv_key
to FFI and It's convenient that to feed more argument toSSL_CTX
object in future if we want.need sure we all agree on this API Design:)
These is a sister pr about
lua-resty-core
. The API usage is as the following:@agentzh @thibaultcha @doujiang24
have a look at this PR? Many thanks :D