lua-nginx-module icon indicating copy to clipboard operation
lua-nginx-module copied to clipboard

feature: ngx_http_lua_ffi_ssl_ciphers

Open bjne opened this issue 3 years ago • 3 comments

Add ngx_http_lua_ffi_ssl_ciphers that returns a uint16_t array of tls_protocol_id supported (and enabled) by both server and client

consider this pull request a request for comment example usage from resty-core:

ffi.cdef[[
int ngx_http_lua_ffi_ssl_ciphers(ngx_http_request_t *r, uint16_t *ciphers,
        uint16_t *nciphers, char **err);

typedef struct {
    uint16_t nciphers;
    uint16_t ciphers[?];
} ngx_lua_ssl_ciphers;
]]

do
    local tls_proto_id = {
        [0x1305] = {
            iana_name = "TLS_AES_128_CCM_8_SHA256",
            tls_version = 1.3,
            kex = "none",
            auth = "none",
            enc = "AES 128 CCM 8",
            hash = "SHA256"
        },
        ...
   }

      local unknown_cipher = {
            iana_name = "UNKNOWN",
            tls_version = 0,
            kex = "UNKNOWN",
            auth = "UNKNOWN",
            enc = "UNKNOWN",
            hash = "UNKNOWN"
    }

    setmetatable(tls_proto_id, {
        __index = function(t,k)
            t[k] = unknown_cipher

            return unknown_cipher
        end
    })

    local iterate_ciphers = function(ciphers, n)
        if ciphers.nciphers > n then
            return n+1, tls_proto_id[ciphers.ciphers[n]]
        end
    end

    local ciphers_t = {}

    ffi.metatype('ngx_lua_ssl_ciphers', {
        __ipairs = function(ciphers)
            return iterate_ciphers, ciphers, 0
        end,
        __tostring = function(ciphers)
            for n,c in ipairs(ciphers) do
                ciphers_t[n] = type(c) == "table" and c.iana_name or format("0x%.4x", c)
            end

            return concat(ciphers_t, ":", 1, ciphers.nciphers)
        end
    })
end

local ciphers_typ = ffi.typeof("ngx_lua_ssl_ciphers")


local ciphers_buf = ffi.new("uint16_t [?]", 256)

_M.ciphers = function()
    local r = get_request()
    if not r then
        ngx.log(ngx.ERR, "no request found")
    end

    ciphers_buf[0] = 255
    local rc = C.ngx_http_lua_ffi_ssl_ciphers(r, ciphers_buf+1, ciphers_buf, errmsg)
    if rc ~= FFI_OK then
        return nil, ffi_str(errmsg[0])
    end
   
    local ciphers = ciphers_typ(ciphers_buf[0])

    ffi.copy(ciphers, ciphers_buf, (ciphers_buf[0] + 1) * ffi.sizeof('uint16_t'))

    return ciphers
end

I hereby granted the copyright of the changes in this pull request to the authors of this lua-nginx-module project.

bjne avatar Nov 03 '21 11:11 bjne

need to add some test cases. @bjne

zhuizhuhaomeng avatar Nov 11 '21 01:11 zhuizhuhaomeng

need to add some test cases. @bjne

Yeah absolutely, just wanted to know if this is a way you would accept this implemented first

bjne avatar Nov 12 '21 11:11 bjne

@bjne this implementation is OK. But this only works in openssl, boringssl does not have the APIs in your PR. we need to add macro to guard the code.

zhuizhuhaomeng avatar Jan 09 '22 03:01 zhuizhuhaomeng