Merge 0.10->trunk
[prosody.git] / util / sslconfig.lua
index 71f27c9460f6548ab816e843d8012ddef25425c1..c849aa28697a54fdfe1ad897f5a4da56b0d28dad 100644 (file)
@@ -1,3 +1,5 @@
+-- util to easily merge multiple sets of LuaSec context options
+
 local type = type;
 local pairs = pairs;
 local rawset = rawset;
@@ -11,70 +13,93 @@ local handlers = { };
 local finalisers = { };
 local id = function (v) return v end
 
-function handlers.options(a, k, b)
-       local o = a[k] or { };
-       if type(b) ~= "table" then b = { b } end
-       for key, value in pairs(b) do
+-- All "handlers" behave like extended rawset(table, key, value) with extra
+-- processing usually merging the new value with the old in some reasonable
+-- way
+-- If a field does not have a defined handler then a new value simply
+-- replaces the old.
+
+
+-- Convert either a list or a set into a special type of set where each
+-- item is either positive or negative in order for a later set of options
+-- to be able to remove options from this set by filtering out the negative ones
+function handlers.options(config, field, new)
+       local options = config[field] or { };
+       if type(new) ~= "table" then new = { new } end
+       for key, value in pairs(new) do
                if value == true or value == false then
-                       o[key] = value;
-               else
-                       o[value] = true;
+                       options[key] = value;
+               else -- list item
+                       options[value] = true;
                end
        end
-       a[k] = o;
+       config[field] = options;
 end
 
 handlers.verify = handlers.options;
 handlers.verifyext = handlers.options;
 
-function finalisers.options(a)
-       local o = {};
-       for opt, enable in pairs(a) do
+-- finalisers take something produced by handlers and return what luasec
+-- expects it to be
+
+-- Produce a list of "positive" options from the set
+function finalisers.options(options)
+       local output = {};
+       for opt, enable in pairs(options) do
                if enable then
-                       o[#o+1] = opt;
+                       output[#output+1] = opt;
                end
        end
-       return o;
+       return output;
 end
 
 finalisers.verify = finalisers.options;
 finalisers.verifyext = finalisers.options;
 
-function finalisers.ciphers(a)
-       if type(a) == "table" then
-               return t_concat(a, ":");
+-- We allow ciphers to be a list
+
+function finalisers.ciphers(cipherlist)
+       if type(cipherlist) == "table" then
+               return t_concat(cipherlist, ":");
        end
-       return a;
+       return cipherlist;
 end
 
+-- protocol = "x" should enable only that protocol
+-- protocol = "x+" should enable x and later versions
+
 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2" };
 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end
 
-local function protocol(a)
-       local min_protocol = protocols[a.protocol];
+-- this interacts with ssl.options as well to add no_x
+local function protocol(config)
+       local min_protocol = protocols[config.protocol];
        if min_protocol then
-               a.protocol = "sslv23";
+               config.protocol = "sslv23";
                for i = 1, min_protocol do
-                       t_insert(a.options, "no_"..protocols[i]);
+                       t_insert(config.options, "no_"..protocols[i]);
                end
        end
 end
 
-local function apply(a, b)
-       if type(b) == "table" then
-               for k,v in pairs(b) do
-                       (handlers[k] or rawset)(a, k, v);
+-- Merge options from 'new' config into 'config'
+local function apply(config, new)
+       if type(new) == "table" then
+               for field, value in pairs(new) do
+                       (handlers[field] or rawset)(config, field, value);
                end
        end
 end
 
-local function final(a)
-       local f = { };
-       for k,v in pairs(a) do
-               f[k] = (finalisers[k] or id)(v);
+-- Finalize the config into the form LuaSec expects
+local function final(config)
+       local output = { };
+       for field, value in pairs(config) do
+               output[field] = (finalisers[field] or id)(value);
        end
-       protocol(f);
-       return f;
+       -- Need to handle protocols last because it adds to the options list
+       protocol(output);
+       return output;
 end
 
 local sslopts_mt = {