Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ Download lua-resty-openssl
make openssl
```

Install lua module

```
make install
```

## Examples:

**test/mtls.conf:**
Expand Down
36 changes: 36 additions & 0 deletions lib/resty/tls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ local type = type
local tostring = tostring

local get_request = base.get_request
local get_size_ptr = base.get_size_ptr
local ffi = require "ffi"
local ffi_new = ffi.new
local ffi_str = ffi.string
local C = ffi.C

local _M = {}

local NGX_OK = ngx.OK
local NGX_ERROR = ngx.ERROR
local NGX_DECLINED = ngx.DECLINED

local ngx_http_apicast_ffi_get_full_client_certificate_chain;
local ngx_http_apicast_ffi_set_proxy_cert_key;
local ngx_http_apicast_ffi_set_proxy_ca_cert;
local ngx_http_apicast_ffi_set_ssl_verify

local value_ptr = ffi_new("unsigned char *[1]")

ffi.cdef[[
int ngx_http_apicast_ffi_get_full_client_certificate_chain(
ngx_http_request_t *r, char **value, size_t *value_len);
int ngx_http_apicast_ffi_set_proxy_cert_key(
ngx_http_request_t *r, void *cdata_chain, void *cdata_key);
int ngx_http_apicast_ffi_set_proxy_ca_cert(
Expand All @@ -24,6 +34,7 @@ ffi.cdef[[
ngx_http_request_t *r, int verify, int verify_deph);
]]

ngx_http_apicast_ffi_get_full_client_certificate_chain = C.ngx_http_apicast_ffi_get_full_client_certificate_chain
ngx_http_apicast_ffi_set_proxy_cert_key = C.ngx_http_apicast_ffi_set_proxy_cert_key
ngx_http_apicast_ffi_set_proxy_ca_cert = C.ngx_http_apicast_ffi_set_proxy_ca_cert
ngx_http_apicast_ffi_set_ssl_verify = C.ngx_http_apicast_ffi_set_ssl_verify
Expand Down Expand Up @@ -89,4 +100,29 @@ function _M.set_upstream_ssl_verify(verify, verify_depth)
end
end

-- Retrieve the full client certificate chain
function _M.get_full_client_certificate_chain()
local r = get_request()
if not r then
error("no request found")
end

local size_ptr = get_size_ptr()

local rc = ngx_http_apicast_ffi_get_full_client_certificate_chain(r, value_ptr, size_ptr)

if rc == NGX_OK then
return ffi_str(value_ptr[0], size_ptr[0])
end

if rc == NGX_ERROR then
return nil, "error while obtaining client certificate chain"
end


if rc == NGX_DECLINED then
return nil
end
end

return _M
103 changes: 97 additions & 6 deletions src/ngx_http_apicast_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,102 @@ ngx_http_apicast_set_ctx(ngx_http_request_t *r)
}


static ngx_int_t ngx_http_apicast_handler(ngx_http_request_t *r)
static ngx_int_t
ngx_http_apicast_handler(ngx_http_request_t *r)
{
/* @TODO validate here that the ctx is deleted and it's not leaking */
ngx_http_apicast_set_ctx(r);
return NGX_OK;
}


int ngx_http_apicast_ffi_set_proxy_cert_key(
int
ngx_http_apicast_ffi_get_full_client_certificate_chain(ngx_http_request_t *r,
u_char **value, size_t *value_len)
{
ngx_connection_t *c;
X509 *cert;
STACK_OF(X509) *chain;
BIO *bio;
int i, numcerts;
size_t len;
ngx_str_t s;

if (r->connection == NULL || r->connection->ssl == NULL) {
return NGX_ERROR;
}

c = r->connection;
if (c == NULL) {
return NGX_ERROR;
}

s.len = 0;

// First get peer's certificate
// See: https://docs.openssl.org/1.1.1/man3/SSL_get_peer_cert_chain
cert = SSL_get_peer_certificate(c->ssl->connection);
if (cert == NULL) {
/* client did not present a certificate or server did not request it */
return NGX_DECLINED;
}

bio = BIO_new(BIO_s_mem());
if(!bio) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "BIO_new() failed");
X509_free(cert);
return NGX_ERROR;
}

if (PEM_write_bio_X509(bio, cert) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "PEM_write_bio_X509() failed");
X509_free(cert);
goto failed;
}

X509_free(cert);

chain = SSL_get_peer_cert_chain(c->ssl->connection);
if(!chain) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_get_peer_cert_chain() failed");
goto failed;
}

numcerts = sk_X509_num(chain);

for(i = 0; i < numcerts; i++) {
cert = sk_X509_value(chain, i);

if (PEM_write_bio_X509(bio, cert) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "PEM_write_bio_X509() failed");
goto failed;
}
}

len = BIO_pending(bio);
s.len = len;
s.data = ngx_pnalloc(r->pool, len);
if (s.data == NULL) {
goto failed;
}

BIO_read(bio, s.data, len);
*value = s.data;
*value_len = s.len;

BIO_free(bio);
return NGX_OK;

failed:

BIO_free(bio);

return NGX_ERROR;
}


int
ngx_http_apicast_ffi_set_proxy_cert_key(
ngx_http_request_t *r, void *cdata_chain, void *cdata_key)
{
char *err = "";
Expand Down Expand Up @@ -227,7 +314,8 @@ ngx_http_apicast_ffi_set_ssl_verify(ngx_http_request_t *r, int verify,
}


ngx_int_t ngx_http_apicast_set_proxy_cert_if_set(
ngx_int_t
ngx_http_apicast_set_proxy_cert_if_set(
ngx_http_apicast_ctx_t *ctx, ngx_connection_t *conn)
{
char *err = "";
Expand Down Expand Up @@ -274,7 +362,8 @@ ngx_int_t ngx_http_apicast_set_proxy_cert_if_set(
}


ngx_int_t ngx_http_apicast_set_proxy_cert_key_if_set(
ngx_int_t
ngx_http_apicast_set_proxy_cert_key_if_set(
ngx_http_apicast_ctx_t *ctx,
ngx_connection_t *conn)
{
Expand Down Expand Up @@ -306,7 +395,8 @@ ngx_int_t ngx_http_apicast_set_proxy_cert_key_if_set(
}


ngx_int_t ngx_http_apicast_set_proxy_ca_cert_if_set(
ngx_int_t
ngx_http_apicast_set_proxy_ca_cert_if_set(
ngx_http_apicast_ctx_t *ctx,
ngx_connection_t *conn)
{
Expand All @@ -332,7 +422,8 @@ ngx_int_t ngx_http_apicast_set_proxy_ca_cert_if_set(
}


ngx_int_t ngx_http_apicast_set_proxy_ssl_verify(ngx_http_apicast_ctx_t *ctx,
ngx_int_t
ngx_http_apicast_set_proxy_ssl_verify(ngx_http_apicast_ctx_t *ctx,
ngx_connection_t *conn)
{
if (ctx == NULL) {
Expand Down
Loading