local s_match = string.match;
local type = type
-local string = string
-local tostring = tostring;
local base64 = require "util.encodings".base64;
local hmac_sha1 = require "util.hashes".hmac_sha1;
local sha1 = require "util.hashes".sha1;
local default_i = 4096
-local function bp( b )
- local result = ""
- for i=1, b:len() do
- result = result.."\\"..b:byte(i)
- end
- return result
-end
-
local xor_map = {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;1;0;3;2;5;4;7;6;9;8;11;10;13;12;15;14;2;3;0;1;6;7;4;5;10;11;8;9;14;15;12;13;3;2;1;0;7;6;5;4;11;10;9;8;15;14;13;12;4;5;6;7;0;1;2;3;12;13;14;15;8;9;10;11;5;4;7;6;1;0;3;2;13;12;15;14;9;8;11;10;6;7;4;5;2;3;0;1;14;15;12;13;10;11;8;9;7;6;5;4;3;2;1;0;15;14;13;12;11;10;9;8;8;9;10;11;12;13;14;15;0;1;2;3;4;5;6;7;9;8;11;10;13;12;15;14;1;0;3;2;5;4;7;6;10;11;8;9;14;15;12;13;2;3;0;1;6;7;4;5;11;10;9;8;15;14;13;12;3;2;1;0;7;6;5;4;12;13;14;15;8;9;10;11;4;5;6;7;0;1;2;3;13;12;15;14;9;8;11;10;5;4;7;6;1;0;3;2;14;15;12;13;10;11;8;9;6;7;4;5;2;3;0;1;15;14;13;12;11;10;9;8;7;6;5;4;3;2;1;0;};
local result = {};
-- TODO: fail if authzid is provided, since we don't support them yet
self.state["client_first_message"] = client_first_message;
self.state["gs2_cbind_flag"], self.state["gs2_cbind_name"], self.state["authzid"], self.state["name"], self.state["clientnonce"]
- = client_first_message:match("^(%a)=?([%a%-]*),(.*),n=(.*),r=([^,]*).*");
+ = client_first_message:match("^([ynp])=?([%a%-]*),(.*),n=(.*),r=([^,]*).*");
- -- check for invalid gs2_flag_type start
- local gs2_flag_type = string.sub(self.state.gs2_cbind_flag, 0, 1)
- if gs2_flag_type ~= "y" and gs2_flag_type ~= "n" and gs2_flag_type ~= "p" then
- return "failure", "malformed-request", "The GS2 header has to start with 'y', 'n', or 'p'."
+ local gs2_cbind_flag = self.state.gs2_cbind_flag;
+
+ if not gs2_cbind_flag then
+ return "failure", "malformed-request";
end
- if support_channel_binding then
- if string.sub(self.state.gs2_cbind_flag, 0, 1) == "y" then
+ if support_channel_binding and gs2_cbind_flag == "y" then
+ -- "y" -> client does support channel binding
+ -- but thinks the server does not.
return "failure", "malformed-request";
end
-
+
+ if gs2_cbind_flag == "n" then
+ -- "n" -> client doesn't support channel binding.
+ support_channel_binding = false;
+ end
+
+ if support_channel_binding and gs2_cbind_flag == "p" then
-- check whether we support the proposed channel binding type
if not self.profile.cb[self.state.gs2_cbind_name] then
return "failure", "malformed-request", "Proposed channel binding type isn't supported.";
end
else
- -- we don't support channelbinding,
- if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then
- return "failure", "malformed-request";
- end
+ -- no channel binding,
+ self.state.gs2_cbind_name = nil;
end
if not self.state.name or not self.state.clientnonce then
function init(registerMechanism)
local function registerSCRAMMechanism(hash_name, hash, hmac_hash)
registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash));
-
+
-- register channel binding equivalent
registerMechanism("SCRAM-"..hash_name.."-PLUS", {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash), {"tls-unique"});
end