Skip to content

Commit

Permalink
feat(tls) adds a new plugin for TLS/https support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tieske committed Feb 23, 2023
1 parent 4f06b81 commit 9f854df
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 3 deletions.
21 changes: 21 additions & 0 deletions example/app.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
-- setup path to find the project source files of Pegasus
package.path = './src/?.lua;./src/?/init.lua;' .. package.path

-- For this example to work with the https version, you need LuaSec
-- to be installed, and you need to generate the test certificates from
-- its examples. Copy the 'A' certificates into this example directory
-- to make it work.
-- Then uncomment the TLS plugin section below.

local Pegasus = require 'pegasus'
local Compress = require 'pegasus.plugins.compress'
local Downloads = require 'pegasus.plugins.downloads'
-- local TLS = require 'pegasus.plugins.tls'

local server = Pegasus:new({
port = '9090',
location = '/example/root/',
plugins = {
-- TLS:new { -- the tls specific configuration
-- wrap = {
-- mode = "server",
-- protocol = "any",
-- key = "./example/serverAkey.pem",
-- certificate = "./example/serverA.pem",
-- cafile = "./example/rootA.pem",
-- verify = {"none"},
-- options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"},
-- },
-- sni = nil,
-- },

Downloads:new {
prefix = "downloads",
stripPrefix = true,
},

Compress:new(),
}
})
Expand Down
3 changes: 2 additions & 1 deletion rockspecs/pegasus-dev-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ build = {
['pegasus.response'] = 'src/pegasus/response.lua',
['pegasus.compress'] = 'src/pegasus/compress.lua',
['pegasus.plugins.compress'] = 'src/pegasus/plugins/compress.lua',
['pegasus.plugins.downloads'] = 'src/pegasus/plugins/downloads.lua'
['pegasus.plugins.downloads'] = 'src/pegasus/plugins/downloads.lua',
['pegasus.plugins.tls'] = 'src/pegasus/plugins/tls.lua',
}
}
18 changes: 17 additions & 1 deletion src/pegasus/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ function Handler:pluginsAlterRequestResponseMetatable()
end
end

function Handler:pluginsNewConnection(client)
for _, plugin in ipairs(self.plugins) do
if plugin.newConnection then
client = plugin:newConnection(client)
if not client then
return false
end
end
end
return client
end

function Handler:pluginsNewRequestResponse(request, response)
for _, plugin in ipairs(self.plugins) do
if plugin.newRequestResponse then
Expand Down Expand Up @@ -92,8 +104,12 @@ function Handler:processBodyData(data, stayOpen, response)
end

function Handler:processRequest(port, client, server)
local request = Request:new(port, client, server)
client = self:pluginsNewConnection(client)
if not client then
return false
end

local request = Request:new(port, client, server)
if not request:method() then
client:close()
return
Expand Down
1 change: 1 addition & 0 deletions src/pegasus/plugins/downloads.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Downloads.__index = Downloads
-- @tparam options.stripPrefix bool whether to strip the prefix from the file path when looking
-- for the file in the filesystem. Defaults to `false`, unless `options.prefix` is omitted,
-- then it defaults to `true`.
-- @return the new plugin
function Downloads:new(options)
options = options or {}
local plugin = {}
Expand Down
55 changes: 55 additions & 0 deletions src/pegasus/plugins/tls.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--- A plugin that enables TLS (https).
-- This plugin should not be used with Copas. Since Copas has native TLS support
-- and can handle simultaneous `http` and `https` connections. See the Copas example
-- to learn how to set that up.
local ssl = require("ssl")


local TLS = {}
TLS.__index = TLS


--- Creates a new plugin instance.
-- IMPORTANT: this must be the first plugin to execute before the client-socket is accessed!
-- @tparam sslparams table the data-structure that contains the properties for the luasec functions.
-- The structure is set up to mimic the LuaSec functions for the handshake.
-- @return the new plugin
-- @usage
-- local sslparams = {
-- wrap = table | context, -- parameter to LuaSec 'wrap()'
-- sni = { -- parameters to LuaSec 'sni()'
-- names = string | table -- 1st parameter
-- strict = bool -- 2nd parameter
-- }
-- }
-- local tls_plugin = require("pegasus.plugins.tls"):new(sslparams)
function TLS:new(sslparams)
sslparams = sslparams or {}
assert(sslparams.wrap, "'sslparam.wrap' is a required option")

return setmetatable({
sslparams = sslparams
}, TLS)
end

function TLS:newConnection(client)
local params = self.sslparams

-- wrap the client socket and replace it
client = assert(ssl.wrap(client, params.wrap))

if params.sni then
assert(client:sni(params.sni.names, params.sni.strict))
end

if not client:dohandshake() then
print"handshake failed"
return false
end
print"running TLS"

return client
end


return TLS
2 changes: 1 addition & 1 deletion src/pegasus/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function Request:new(port, client, server)
obj.client = client
obj.server = server
obj.port = port
obj.ip = client:getpeername()
obj.ip = (client.getpeername or function() end)(client) -- luasec doesn't support this method
obj.querystring = {}
obj._firstLine = nil
obj._method = nil
Expand Down

0 comments on commit 9f854df

Please sign in to comment.