Skip to content
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

Correct c-struct 'null' checks, fix failing tests due to expired certs, improve openssl error handling #74

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
9 changes: 5 additions & 4 deletions ci
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ case "${1:?}" in
;;
script)
docker run \
-a stdin -a stdout -a stderr -i \
-i \
--rm \
--entrypoint="" \
-v "$(pwd)":/lua-resty-jwt -w /lua-resty-jwt \
--entrypoint=/bin/sh \
-v "$(pwd)":/lua-resty-jwt \
-w /lua-resty-jwt \
--name lua-resty-jwt-tests \
skylothar/openresty-testsuite:latest \
/bin/sh -c 'luarocks make lua-resty-jwt-dev-0.rockspec && prove -r t'
-c 'luarocks make lua-resty-jwt-dev-0.rockspec && prove -r t'
;;
esac
36 changes: 23 additions & 13 deletions lib/resty/evp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,18 @@ int X509_digest(const X509 *data,const EVP_MD *type,


local function _err(ret)
-- The openssl error queue can have multiple items, print them all separated by ': '
local errs = {}
local code = _C.ERR_get_error()
if code == 0 then
while code ~= 0 do
table.insert(errs, 1, ffi.string(_C.ERR_reason_error_string(code)))
code = _C.ERR_get_error()
end

if #errs == 0 then
return ret, "Zero error code (null arguments?)"
end
return ret, ffi.string(_C.ERR_reason_error_string(code))
return ret, table.concat(errs, ": ")
end


Expand All @@ -134,10 +141,13 @@ function RSASigner.new(self, pem_private_key)

-- TODO might want to support password protected private keys...
local rsa = _C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil)
if rsa == nil then
return _err()
end
ffi.gc(rsa, _C.RSA_free)

local evp_pkey = _C.EVP_PKEY_new()
if not evp_pkey then
if evp_pkey == nil then
return _err()
end
ffi.gc(evp_pkey, _C.EVP_PKEY_free)
Expand All @@ -158,13 +168,13 @@ function RSASigner.sign(self, message, digest_name)
local len = ffi.new("size_t[1]", 1024)

local ctx = _C.EVP_MD_CTX_create()
if not ctx then
if ctx == nil then
return _err()
end
ffi.gc(ctx, _C.EVP_MD_CTX_destroy)

local md = _C.EVP_get_digestbyname(digest_name)
if not md then
if md == nil then
return _err()
end

Expand Down Expand Up @@ -209,12 +219,12 @@ end
-- @returns bool, error_string
function RSAVerifier.verify(self, message, sig, digest_name)
local md = _C.EVP_get_digestbyname(digest_name)
if not md then
if md == nil then
return _err(false)
end

local ctx = _C.EVP_MD_CTX_create()
if not ctx then
if ctx == nil then
return _err(false)
end
ffi.gc(ctx, _C.EVP_MD_CTX_destroy)
Expand Down Expand Up @@ -265,7 +275,7 @@ function Cert.new(self, payload)
end
x509 = _C.d2i_X509_bio(bio, nil)
end
if not x509 then
if x509 == nil then
return _err()
end
ffi.gc(x509, _C.X509_free)
Expand Down Expand Up @@ -299,7 +309,7 @@ end
-- @returns fingerprint_string
function Cert.get_fingerprint(self, digest_name)
local md = _C.EVP_get_digestbyname(digest_name)
if not md then
if md == nil then
return _err()
end
local buf = ffi.new("unsigned char[?]", 32)
Expand All @@ -317,7 +327,7 @@ end
-- @returns An OpenSSL EVP PKEY object representing the public key
function Cert.get_public_key(self)
local evp_pkey = _C.X509_get_pubkey(self.x509)
if not evp_pkey then
if evp_pkey == nil then
return _err()
end

Expand All @@ -329,7 +339,7 @@ end
-- @return bool, error_string
function Cert.verify_trust(self, trusted_cert_file)
local store = _C.X509_STORE_new()
if not store then
if store == nil then
return _err(false)
end
ffi.gc(store, _C.X509_STORE_free)
Expand All @@ -338,7 +348,7 @@ function Cert.verify_trust(self, trusted_cert_file)
end

local ctx = _C.X509_STORE_CTX_new()
if not store then
if store == nil then
return _err(false)
end
ffi.gc(ctx, _C.X509_STORE_CTX_free)
Expand Down Expand Up @@ -386,7 +396,7 @@ function PublicKey.new(self, payload)
end
pkey = _C.d2i_PUBKEY_bio(bio, nil)
end
if not pkey then
if pkey == nil then
return _err()
end
ffi.gc(pkey, _C.EVP_PKEY_free)
Expand Down
4 changes: 2 additions & 2 deletions lib/resty/jwt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ local function is_nil_or_boolean(arg_value)
return true
end

--@function get the row part
--@function get the raw part
--@param part_name
--@param jwt_obj
local function get_raw_part(part_name, jwt_obj)
Expand Down Expand Up @@ -485,7 +485,7 @@ function _M.sign(self, secret_key, jwt_obj)
-- header alg check
local raw_header = get_raw_part(str_const.header, jwt_obj)
local raw_payload = get_raw_part(str_const.payload, jwt_obj)
local message = string_format(str_const.regex_join_msg, raw_header , raw_payload)
local message = string_format(str_const.regex_join_msg, raw_header, raw_payload)

local alg = jwt_obj[str_const.header][str_const.alg]
local signature = ""
Expand Down
67 changes: 54 additions & 13 deletions t/load-verify.t
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use Test::Nginx::Socket::Lua;



repeat_each(2);

plan tests => repeat_each() * (3 * blocks());
Expand Down Expand Up @@ -348,7 +350,6 @@ everything is awesome~ :p
--- http_config eval: $::HttpConfig
--- config
location /t {
set $cert '-----BEGIN CERTIFICATE-----\nMIIC2jCCAkMCAg38MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\nA1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\nMRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\nYiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\nODIyMDUyNzQxWhcNMTcwODIxMDUyNzQxWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\nCAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\nZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0z9FeMynsC8+u\ndvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut\nbMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J\nNRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW\n+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic\n7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2\n4DDHCPhZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQMv+BFvGdMVzkQaQ3/+2noVz\n/uAKbzpEL8xTcxYyP3lkOeh4FoxiSWqy5pGFALdPONoDuYFpLhjJSZaEwuvjI/Tr\nrGhLV1pRG9frwDFshqD2Vaj4ENBCBh6UpeBop5+285zQ4SI7q4U9oSebUDJiuOx6\n+tZ9KynmrbJpTSi0+BM=\n-----END CERTIFICATE-----';
content_by_lua '
local jwt = require "resty.jwt"

Expand All @@ -361,19 +362,17 @@ everything is awesome~ :p
error("Unexpected kid has been passed. Duh :(")
end

return ngx.var.cert
local f = io.open("/lua-resty-jwt/testcerts/cert.pem", "rb");
local cert = f:read("*all");
f:close()
return cert
end

jwt:set_trusted_certs_file("/lua-resty-jwt/testcerts/root.pem")
jwt:set_alg_whitelist({ RS256 = 1 })
jwt:set_x5u_content_retriever(get_public_key)

local jwt_token = "eyJ4NXUiOiJodHRwczpcL1wvZHVtbXkuY29tXC9jZXJ0cyIsImFsZyI6IlJTMjU2IiwidHlwIjoiSldUIn0"
.. ".eyJmb28iOiJiYXIifQ"
.. ".h4fOshUFSiVoSjV0zoJNXSaAFGIzFScI_VRHQYLefZ5uuGWWEd69q6GBx1XVN4er67WuKDTmgbsW5b_ya2eU89U6LC"
.. "3r2Rdu9FtYmm4aoQ5WesvC7UI63gJrhLFcbQGv1eDDPANZh-k_aOhGQLBjxdx_J2n95eKlYfqH3aZHTPtSnF7lEV4ZR"
.. "RsHbX3jgS2Kcx-DvNQ77A81yQsTWtECKE-fiUZ5nOMn172rOPWM-DYTimsyOzuRErqE0xoB1u8ClVxmb1Mrg4LWSPoz"
.. "nv5vhd8JkOXMg_5zYii6p5eIegH58IpxNYuDQ-rSo320nOvZOU7d8UOeYixYeEcEc1fMlQ"
local jwt_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsIng1dSI6Imh0dHBzOi8vZHVtbXkuY29tL2NlcnRzIn0.eyJmb28iOiJiYXIiLCJpYXQiOjE1MTkyODQ4NDZ9.1DoCMZN2qEyyGm8KhHU-XVPkUqM3qQ2pyrTFIg8ZExm1eJX5E7gZFeIOIb6VyqZmadSNDTl2nZY127RClk7volMJnEeX4lMSugf_CFKAo9bLeI-jjYxjimd159uAxCeZu9vS7Z5gEIAAlRLp-IsxLpCx4ZvsR8Od21gPCS5WVHEF_KagQn6-bwbpnDfkguW1yByNPy1Ke8SDuw9l8FABJEa7mkJ6Sjx6qKzB5QoMFXI-xgLE3xQbzO0BLBo7bSpoB-LM1uZaEpXLOS3SNH63PQTq_tWSHhpR7d1ZOJW1lb-SxiWFBNFIDHkMaSBttiDGuc4BqXED-Thq_dhsPZwyiA"

local jwt_obj = jwt:verify(nil, jwt_token)
ngx.say(jwt_obj["verified"])
Expand All @@ -395,12 +394,14 @@ bar
--- http_config eval: $::HttpConfig
--- config
location /t {
set $cert '-----BEGIN CERTIFICATE-----\nMIIC2jCCAkMCAg38MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\nA1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\nMRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\nYiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\nODIyMDUyNzQxWhcNMTcwODIxMDUyNzQxWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\nCAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\nZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0z9FeMynsC8+u\ndvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut\nbMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J\nNRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW\n+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic\n7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2\n4DDHCPhZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQMv+BFvGdMVzkQaQ3/+2noVz\n/uAKbzpEL8xTcxYyP3lkOeh4FoxiSWqy5pGFALdPONoDuYFpLhjJSZaEwuvjI/Tr\nrGhLV1pRG9frwDFshqD2Vaj4ENBCBh6UpeBop5+285zQ4SI7q4U9oSebUDJiuOx6\n+tZ9KynmrbJpTSi0+BM=\n-----END CERTIFICATE-----';
content_by_lua '
local jwt = require "resty.jwt"

local function get_public_key(url)
return ngx.var.cert
local f = io.open("/lua-resty-jwt/testcerts/cert.pem", "rb");
local cert = f:read("*all");
f:close()
return cert
end

jwt:set_trusted_certs_file("/lua-resty-jwt/testcerts/root.pem")
Expand Down Expand Up @@ -437,7 +438,6 @@ Wrongly encoded signature
content_by_lua '
local jwt = require "resty.jwt"

-- pubkey.pem
local public_key = [[
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtM/RXjMp7AvPrnb1/i3I
Expand Down Expand Up @@ -528,7 +528,6 @@ Wrongly encoded signature
--- http_config eval: $::HttpConfig
--- config
location /t {
set $cert '-----BEGIN CERTIFICATE-----\nMIIC2jCCAkMCAg38MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG\nA1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE\nMRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl\nYiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw\nODIyMDUyNzQxWhcNMTcwODIxMDUyNzQxWjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE\nCAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs\nZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0z9FeMynsC8+u\ndvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut\nbMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J\nNRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW\n+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic\n7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2\n4DDHCPhZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQMv+BFvGdMVzkQaQ3/+2noVz\n/uAKbzpEL8xTcxYyP3lkOeh4FoxiSWqy5pGFALdPONoDuYFpLhjJSZaEwuvjI/Tr\nrGhLV1pRG9frwDFshqD2Vaj4ENBCBh6UpeBop5+285zQ4SI7q4U9oSebUDJiuOx6\n+tZ9KynmrbJpTSi0+BM=\n-----END CERTIFICATE-----';
content_by_lua '
local jwt = require "resty.jwt"

Expand All @@ -541,7 +540,10 @@ Wrongly encoded signature
error("Unexpected kid has been passed. Duh :(")
end

return ngx.var.cert
local f = io.open("/lua-resty-jwt/testcerts/cert.pem", "rb");
local cert = f:read("*all");
f:close()
return cert
end

jwt:set_trusted_certs_file("/lua-resty-jwt/testcerts/root.pem")
Expand All @@ -567,3 +569,42 @@ false
Verification failed
--- no_error_log
[error]


=== TEST 20: invalid public key is not constructed
--- http_config eval: $::HttpConfig
--- config
location /t {
content_by_lua '
local jwt = require "resty.jwt"

local public_key = [[
-----BEGIN PUBLIC KEY-----
R0FSQkFHRQo=
-----END PUBLIC KEY-----
]]
jwt:set_alg_whitelist({ RS256 = 1 })
local jwt_token = "eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiJ9."
.. "eyJpc3MiOiAidGVzdCIsICJpYXQiOiAxNDYxOTE0MDE3fQ."
.. "dng6Vc-p_ISwiWc61ifWahbFYKBNWfaIr-W3bTPpgL-awG8"
.. "UlaCONkQk2PHJw_xndbpenQYl_-hipCKynokeFBTXVcSL6H"
.. "7XL4D9laQVDVFnI63hcXOMQxgICsQPVdcfVSBl2jHyV8kuw"
.. "XpUHbXQTxMawlE9SkI1-7UukxL9OyFIkT1D1uW7P96irVDs"
.. "GkEdTLVUPJerH-jlW4rRbW9twSHsgzHgkaqnQ41giW_e2Zz"
.. "r0U2euFH-AxlyvWBJd8Y7rQ_aD40USKsJilZ5qSykGZ7KHd"
.. "PzuwTXioCwB8bGVE2YoL-DKYj7-tOwoNsMK7UJzyjqzHqwuqvZWtbhmeRlww"

local jwt_obj = jwt:verify(public_key, jwt_token)
ngx.say(jwt_obj["verified"])
ngx.say(jwt_obj["reason"])
ngx.say(jwt_obj["payload"]["iss"])
';
}
--- request
GET /t
--- response_body
false
Decode secret is not a valid cert/public key: ASN1 lib: nested asn1 error: bad object header: too long
test
--- no_error_log
[error]
Loading