Software /
code /
prosody
Comparison
util/sasl/scram.lua @ 5844:4f545674b0bc
util.sasl.scram: Simplify validation of client-first-message
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 22 Sep 2013 04:29:27 +0200 |
parent | 5843:fb6573e191cf |
child | 5856:e3e593eb81d1 |
comparison
equal
deleted
inserted
replaced
5843:fb6573e191cf | 5844:4f545674b0bc |
---|---|
11 -- | 11 -- |
12 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 12 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
13 | 13 |
14 local s_match = string.match; | 14 local s_match = string.match; |
15 local type = type | 15 local type = type |
16 local string = string | |
17 local tostring = tostring; | 16 local tostring = tostring; |
18 local base64 = require "util.encodings".base64; | 17 local base64 = require "util.encodings".base64; |
19 local hmac_sha1 = require "util.hashes".hmac_sha1; | 18 local hmac_sha1 = require "util.hashes".hmac_sha1; |
20 local sha1 = require "util.hashes".sha1; | 19 local sha1 = require "util.hashes".sha1; |
21 local Hi = require "util.hashes".scram_Hi_sha1; | 20 local Hi = require "util.hashes".scram_Hi_sha1; |
122 local client_first_message = message; | 121 local client_first_message = message; |
123 | 122 |
124 -- TODO: fail if authzid is provided, since we don't support them yet | 123 -- TODO: fail if authzid is provided, since we don't support them yet |
125 self.state["client_first_message"] = client_first_message; | 124 self.state["client_first_message"] = client_first_message; |
126 self.state["gs2_cbind_flag"], self.state["gs2_cbind_name"], self.state["authzid"], self.state["name"], self.state["clientnonce"] | 125 self.state["gs2_cbind_flag"], self.state["gs2_cbind_name"], self.state["authzid"], self.state["name"], self.state["clientnonce"] |
127 = client_first_message:match("^(%a)=?([%a%-]*),(.*),n=(.*),r=([^,]*).*"); | 126 = client_first_message:match("^([ynp])=?([%a%-]*),(.*),n=(.*),r=([^,]*).*"); |
128 | 127 |
129 -- check for invalid gs2_flag_type start | 128 local gs2_cbind_flag = self.state.gs2_cbind_flag; |
130 local gs2_flag_type = string.sub(self.state.gs2_cbind_flag, 0, 1) | 129 |
131 if gs2_flag_type ~= "y" and gs2_flag_type ~= "n" and gs2_flag_type ~= "p" then | 130 if not gs2_cbind_flag then |
132 return "failure", "malformed-request", "The GS2 header has to start with 'y', 'n', or 'p'." | 131 return "failure", "malformed-request"; |
133 end | 132 end |
134 | 133 |
135 if support_channel_binding then | 134 if support_channel_binding and gs2_cbind_flag == "y" then |
136 if string.sub(self.state.gs2_cbind_flag, 0, 1) == "y" then | 135 -- "y" -> client does support channel binding |
136 -- but thinks the server does not. | |
137 return "failure", "malformed-request"; | 137 return "failure", "malformed-request"; |
138 end | 138 end |
139 | 139 |
140 if gs2_cbind_flag == "n" then | |
141 -- "n" -> client doesn't support channel binding. | |
142 support_channel_binding = false; | |
143 end | |
144 | |
145 if support_channel_binding and gs2_cbind_flag == "p" then | |
140 -- check whether we support the proposed channel binding type | 146 -- check whether we support the proposed channel binding type |
141 if not self.profile.cb[self.state.gs2_cbind_name] then | 147 if not self.profile.cb[self.state.gs2_cbind_name] then |
142 return "failure", "malformed-request", "Proposed channel binding type isn't supported."; | 148 return "failure", "malformed-request", "Proposed channel binding type isn't supported."; |
143 end | 149 end |
144 else | 150 else |
145 -- we don't support channelbinding, | 151 -- no channel binding, |
146 if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then | 152 self.state.gs2_cbind_name = nil; |
147 return "failure", "malformed-request"; | |
148 end | |
149 end | 153 end |
150 | 154 |
151 if not self.state.name or not self.state.clientnonce then | 155 if not self.state.name or not self.state.clientnonce then |
152 return "failure", "malformed-request", "Channel binding isn't support at this time."; | 156 return "failure", "malformed-request", "Channel binding isn't support at this time."; |
153 end | 157 end |
240 end | 244 end |
241 | 245 |
242 function init(registerMechanism) | 246 function init(registerMechanism) |
243 local function registerSCRAMMechanism(hash_name, hash, hmac_hash) | 247 local function registerSCRAMMechanism(hash_name, hash, hmac_hash) |
244 registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash)); | 248 registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash)); |
245 | 249 |
246 -- register channel binding equivalent | 250 -- register channel binding equivalent |
247 registerMechanism("SCRAM-"..hash_name.."-PLUS", {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash), {"tls-unique"}); | 251 registerMechanism("SCRAM-"..hash_name.."-PLUS", {"plain", "scram_"..(hashprep(hash_name))}, scram_gen(hash_name:lower(), hash, hmac_hash), {"tls-unique"}); |
248 end | 252 end |
249 | 253 |
250 registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); | 254 registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); |