Skip to content

Commit 991e708

Browse files
authored
feature: proxy_ssl_verify_by_lua directives.
* better prefix for proxy ssl verify ffi functions
1 parent 09f6391 commit 991e708

4 files changed

Lines changed: 485 additions & 16 deletions

File tree

lib/ngx/ssl/proxysslverify.lua

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
-- Copyright (C) Yichun Zhang (agentzh)
2+
3+
4+
local base = require "resty.core.base"
5+
base.allows_subsystem('http', 'stream')
6+
7+
8+
local ffi = require "ffi"
9+
local C = ffi.C
10+
local ffi_gc = ffi.gc
11+
local ffi_str = ffi.string
12+
local get_request = base.get_request
13+
local error = error
14+
local errmsg = base.get_errmsg_ptr()
15+
16+
local FFI_OK = base.FFI_OK
17+
local FFI_ERROR = base.FFI_ERROR
18+
local subsystem = ngx.config.subsystem
19+
local ngx_phase = ngx.get_phase
20+
21+
local ngx_lua_ffi_proxy_ssl_set_verify_result
22+
local ngx_lua_ffi_proxy_ssl_get_verify_result
23+
local ngx_lua_ffi_proxy_ssl_get_verify_cert
24+
local ngx_lua_ffi_proxy_ssl_free_verify_cert
25+
26+
27+
if subsystem == 'http' then
28+
ffi.cdef[[
29+
int ngx_http_lua_ffi_proxy_ssl_set_verify_result(ngx_http_request_t *r,
30+
int verify_result, char **err);
31+
32+
int ngx_http_lua_ffi_proxy_ssl_get_verify_result(ngx_http_request_t *r,
33+
char **err);
34+
35+
void *ngx_http_lua_ffi_proxy_ssl_get_verify_cert(ngx_http_request_t *r,
36+
char **err);
37+
38+
void ngx_http_lua_ffi_proxy_ssl_free_verify_cert(void *cdata);
39+
]]
40+
41+
ngx_lua_ffi_proxy_ssl_set_verify_result =
42+
C.ngx_http_lua_ffi_proxy_ssl_set_verify_result
43+
ngx_lua_ffi_proxy_ssl_get_verify_result =
44+
C.ngx_http_lua_ffi_proxy_ssl_get_verify_result
45+
ngx_lua_ffi_proxy_ssl_get_verify_cert =
46+
C.ngx_http_lua_ffi_proxy_ssl_get_verify_cert
47+
ngx_lua_ffi_proxy_ssl_free_verify_cert =
48+
C.ngx_http_lua_ffi_proxy_ssl_free_verify_cert
49+
50+
51+
52+
elseif subsystem == 'stream' then
53+
ffi.cdef[[
54+
int ngx_stream_lua_ffi_proxy_ssl_set_verify_result(
55+
ngx_stream_lua_request_t *r, int verify_result, char **err);
56+
57+
int ngx_stream_lua_ffi_proxy_ssl_get_verify_result(
58+
ngx_stream_lua_request_t *r, char **err);
59+
60+
void *ngx_stream_lua_ffi_proxy_ssl_get_verify_cert(
61+
ngx_stream_lua_request_t *r, char **err);
62+
63+
void ngx_stream_lua_ffi_proxy_ssl_free_verify_cert(void *cdata);
64+
]]
65+
66+
ngx_lua_ffi_proxy_ssl_set_verify_result =
67+
C.ngx_stream_lua_ffi_proxy_ssl_set_verify_result
68+
ngx_lua_ffi_proxy_ssl_get_verify_result =
69+
C.ngx_stream_lua_ffi_proxy_ssl_get_verify_result
70+
ngx_lua_ffi_proxy_ssl_get_verify_cert =
71+
C.ngx_stream_lua_ffi_proxy_ssl_get_verify_cert
72+
ngx_lua_ffi_proxy_ssl_free_verify_cert =
73+
C.ngx_stream_lua_ffi_proxy_ssl_free_verify_cert
74+
end
75+
76+
77+
local _M = { version = base.version }
78+
79+
80+
-- return ok, err
81+
function _M.set_verify_result(verify_result)
82+
local r = get_request()
83+
if not r then
84+
error("no request found")
85+
end
86+
87+
if ngx_phase() ~= "proxy_ssl_verify" then
88+
error("API disabled in the current context")
89+
end
90+
91+
local rc = ngx_lua_ffi_proxy_ssl_set_verify_result(r, verify_result, errmsg)
92+
if rc == FFI_OK then
93+
return true
94+
end
95+
96+
return nil, ffi_str(errmsg[0])
97+
end
98+
99+
100+
-- return verify_result, err
101+
function _M.get_verify_result()
102+
local r = get_request()
103+
if not r then
104+
error("no request found")
105+
end
106+
107+
if ngx_phase() ~= "proxy_ssl_verify" then
108+
error("API disabled in the current context")
109+
end
110+
111+
local rc = ngx_lua_ffi_proxy_ssl_get_verify_result(r, errmsg)
112+
if rc == FFI_ERROR then
113+
return nil, ffi_str(errmsg[0])
114+
end
115+
116+
return rc
117+
end
118+
119+
120+
-- return cert, err
121+
function _M.get_verify_cert()
122+
local r = get_request()
123+
if not r then
124+
error("no request found")
125+
end
126+
127+
if ngx_phase() ~= "proxy_ssl_verify" then
128+
error("API disabled in the current context")
129+
end
130+
131+
local cert = ngx_lua_ffi_proxy_ssl_get_verify_cert(r, errmsg)
132+
if cert ~= nil then
133+
return ffi_gc(cert, ngx_lua_ffi_proxy_ssl_free_verify_cert)
134+
end
135+
136+
return nil, ffi_str(errmsg[0])
137+
end
138+
139+
140+
return _M

lib/ngx/ssl/proxysslverify.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
Name
2+
====
3+
4+
ngx.ssl.proxysslverify - Lua API for post-processing SSL server certificate message for NGINX upstream SSL connections.
5+
6+
Table of Contents
7+
=================
8+
9+
* [Name](#name)
10+
* [Status](#status)
11+
* [Synopsis](#synopsis)
12+
* [Description](#description)
13+
* [Methods](#methods)
14+
* [set_verify_result](#set_verify_result)
15+
* [get_verify_result](#get_verify_result)
16+
* [get_verify_cert](#get_verify_cert)
17+
* [Community](#community)
18+
* [English Mailing List](#english-mailing-list)
19+
* [Chinese Mailing List](#chinese-mailing-list)
20+
* [Bugs and Patches](#bugs-and-patches)
21+
* [Author](#author)
22+
* [Copyright and License](#copyright-and-license)
23+
* [See Also](#see-also)
24+
25+
Status
26+
======
27+
28+
This Lua module is production ready.
29+
30+
Synopsis
31+
========
32+
33+
```nginx
34+
# nginx.conf
35+
36+
server {
37+
listen 443 ssl;
38+
server_name test.com;
39+
ssl_certificate /path/to/cert.crt;
40+
ssl_certificate_key /path/to/key.key;
41+
42+
location /t {
43+
proxy_ssl_certificate /path/to/cert.crt;
44+
proxy_ssl_certificate_key /path/to/key.key;
45+
proxy_pass https://upstream;
46+
47+
proxy_ssl_verify_by_lua_block {
48+
local proxy_ssl_vfy = require "ngx.ssl.proxysslverify"
49+
50+
local cert, err = proxy_ssl_vfy.get_verify_cert()
51+
52+
-- ocsp to verify cert
53+
-- check crl
54+
55+
proxy_ssl_vfy.set_verify_result(0)
56+
}
57+
}
58+
...
59+
}
60+
```
61+
62+
Description
63+
===========
64+
65+
This Lua module provides API functions for post-processing SSL server certificate message for NGINX upstream connections.
66+
67+
It must to be used in the contexts [proxy_ssl_verify_by_lua*](https://github.com/openresty/lua-nginx-module/#proxy_ssl_verify_by_lua_block).
68+
69+
This directive runs user Lua code when Nginx is about to post-process the SSL server certificate message for the upstream SSL (https) connections.
70+
71+
It is particularly useful to parse upstream server certificate and do some custom operations in pure lua.
72+
73+
To load the `ngx.ssl.proxysslverify` module in Lua, just write
74+
75+
```lua
76+
local proxy_ssl_vfy = require "ngx.ssl.proxysslverify"
77+
```
78+
79+
[Back to TOC](#table-of-contents)
80+
81+
Methods
82+
=======
83+
84+
set_verify_result
85+
-----------------
86+
**syntax:** *ok, err = proxy_ssl_vfy.set_verify_result(0)*
87+
88+
**context:** *proxy_ssl_verify_by_lua**
89+
90+
According to openssl's doc of SSL_CTX_set_cert_verify_callback: In any case a viable verification result value must be reflected in the error member of x509_store_ctx, which can be done using X509_STORE_CTX_set_error. So after using Lua code to verify server certificate, we need to call this function to setup verify result. Please refers to openssl's `include/openssl/x509_vfy.h` to see which verify result code can be used.
91+
92+
In case of errors, it returns `nil` and a string describing the error.
93+
94+
This function can only be called in the context of [proxy_ssl_verify_by_lua*](https://github.com/openresty/lua-nginx-module/#proxy_ssl_verify_by_lua_block).
95+
96+
[Back to TOC](#table-of-contents)
97+
98+
get_verify_result
99+
-----------------
100+
**syntax:** *verify_result, err = proxy_ssl_vfy.get_verify_result()*
101+
102+
**context:** *proxy_ssl_verify_by_lua**
103+
104+
Returns the verify result code.
105+
106+
In case of errors, it returns `nil` and a string describing the error.
107+
108+
This function can only be called in the context of [proxy_ssl_verify_by_lua*](https://github.com/openresty/lua-nginx-module/#proxy_ssl_verify_by_lua_block).
109+
110+
[Back to TOC](#table-of-contents)
111+
112+
get_verify_cert
113+
---------------
114+
**syntax:** *cert, err = proxy_ssl_vfy.get_verify_cert()*
115+
116+
**context:** *proxy_ssl_verify_by_lua**
117+
118+
Returns the server certificate Nginx received from upstream SSL connection.
119+
120+
In case of errors, it returns `nil` and a string describing the error.
121+
122+
This function can only be called in the context of [proxy_ssl_verify_by_lua*](https://github.com/openresty/lua-nginx-module/#proxy_ssl_verify_by_lua_block).
123+
124+
[Back to TOC](#table-of-contents)
125+
126+
Community
127+
=========
128+
129+
[Back to TOC](#table-of-contents)
130+
131+
English Mailing List
132+
--------------------
133+
134+
The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers.
135+
136+
[Back to TOC](#table-of-contents)
137+
138+
Chinese Mailing List
139+
--------------------
140+
141+
The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers.
142+
143+
[Back to TOC](#table-of-contents)
144+
145+
Bugs and Patches
146+
================
147+
148+
Please report bugs or submit patches by
149+
150+
1. creating a ticket on the [GitHub Issue Tracker](https://github.com/openresty/lua-resty-core/issues),
151+
1. or posting to the [OpenResty community](#community).
152+
153+
[Back to TOC](#table-of-contents)
154+
155+
Author
156+
======
157+
158+
Fuhong Ma <willmafh@hotmail.com> (willmafh)
159+
160+
[Back to TOC](#table-of-contents)
161+
162+
Copyright and License
163+
=====================
164+
165+
This module is licensed under the BSD license.
166+
167+
Copyright (C) 2016-2017, by Yichun "agentzh" Zhang, OpenResty Inc.
168+
169+
All rights reserved.
170+
171+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
172+
173+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
174+
175+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
176+
177+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
178+
179+
[Back to TOC](#table-of-contents)
180+
181+
See AlsoCopyright
182+
========
183+
* the ngx_lua module: https://github.com/openresty/lua-nginx-module
184+
* the [proxy_ssl_verify_by_lua*](https://github.com/openresty/lua-nginx-module/#proxy_ssl_verify_by_lua_block) directive.
185+
* the [lua-resty-core](https://github.com/openresty/lua-resty-core) library.
186+
* OpenResty: https://openresty.org
187+
188+
[Back to TOC](#table-of-contents)

lib/resty/core/phase.lua

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,23 @@ int ngx_http_lua_ffi_get_phase(ngx_http_request_t *r, char **err)
1515

1616
local errmsg = base.get_errmsg_ptr()
1717
local context_names = {
18-
[0x0001] = "set",
19-
[0x0002] = "rewrite",
20-
[0x0004] = "access",
21-
[0x0008] = "content",
22-
[0x0010] = "log",
23-
[0x0020] = "header_filter",
24-
[0x0040] = "body_filter",
25-
[0x0080] = "timer",
26-
[0x0100] = "init_worker",
27-
[0x0200] = "balancer",
28-
[0x0400] = "ssl_cert",
29-
[0x0800] = "ssl_session_store",
30-
[0x1000] = "ssl_session_fetch",
31-
[0x2000] = "exit_worker",
32-
[0x4000] = "ssl_client_hello",
33-
[0x8000] = "server_rewrite",
18+
[0x00000001] = "set",
19+
[0x00000002] = "rewrite",
20+
[0x00000004] = "access",
21+
[0x00000008] = "content",
22+
[0x00000010] = "log",
23+
[0x00000020] = "header_filter",
24+
[0x00000040] = "body_filter",
25+
[0x00000080] = "timer",
26+
[0x00000100] = "init_worker",
27+
[0x00000200] = "balancer",
28+
[0x00000400] = "ssl_cert",
29+
[0x00000800] = "ssl_session_store",
30+
[0x00001000] = "ssl_session_fetch",
31+
[0x00002000] = "exit_worker",
32+
[0x00004000] = "ssl_client_hello",
33+
[0x00008000] = "server_rewrite",
34+
[0x00010000] = "proxy_ssl_verify",
3435
}
3536

3637

0 commit comments

Comments
 (0)