From 03e17022ef1117321cd3898e7282f396692d824a Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sun, 28 Feb 2010 22:32:12 +0100 Subject: util.sasl: Moving SASL authentication backends documentation to the mechanism files. --- util/sasl.lua | 21 --------------------- util/sasl/digest-md5.lua | 15 +++++++++++++++ util/sasl/plain.lua | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/util/sasl.lua b/util/sasl.lua index eb71956b..306acc0c 100644 --- a/util/sasl.lua +++ b/util/sasl.lua @@ -41,27 +41,6 @@ Authentication Backend Prototypes: state = false : disabled state = true : enabled state = nil : non-existant - -plain: - function(username, realm) - return password, state; - end - -plain-test: - function(username, realm, password) - return true or false, state; - end - -digest-md5: - function(username, domain, realm, encoding) -- domain and realm are usually the same; for some broken - -- implementations it's not - return digesthash, state; - end - -digest-md5-test: - function(username, domain, realm, encoding, digesthash) - return true or false, state; - end ]] local method = {}; diff --git a/util/sasl/digest-md5.lua b/util/sasl/digest-md5.lua index 04acf04d..fc2107bc 100644 --- a/util/sasl/digest-md5.lua +++ b/util/sasl/digest-md5.lua @@ -29,6 +29,21 @@ module "digest-md5" --========================= --SASL DIGEST-MD5 according to RFC 2831 +--[[ +Supported Authentication Backends + +digest-md5: + function(username, domain, realm, encoding) -- domain and realm are usually the same; for some broken + -- implementations it's not + return digesthash, state; + end + +digest-md5-test: + function(username, domain, realm, encoding, digesthash) + return true or false, state; + end +]] + local function digest(self, message) --TODO complete support for authzid diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index ae5c777a..43bb239f 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -19,6 +19,21 @@ module "plain" -- ================================ -- SASL PLAIN according to RFC 4616 + +--[[ +Supported Authentication Backends + +plain: + function(username, realm) + return password, state; + end + +plain-test: + function(username, realm, password) + return true or false, state; + end +]] + local function plain(self, message) if not message then return "failure", "malformed-request"; -- cgit v1.2.3 From 866437fa873a62c35bc84aad821343cd9fbf377e Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sun, 28 Feb 2010 22:50:25 +0100 Subject: util.sasl.plain: Adding plain_hashed authentication backend support. --- util/sasl/plain.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index 43bb239f..6369face 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -32,6 +32,11 @@ plain-test: function(username, realm, password) return true or false, state; end + +plain-hashed: + function(username, realm) + return hashed_password, hash_function, state; + end ]] local function plain(self, message) @@ -61,6 +66,10 @@ local function plain(self, message) if correct_password == password then correct = true; else correct = false; end elseif self.profile.plain_test then correct, state = self.profile.plain_test(authentication, self.realm, password); + elseif self.profile.plain_hashed then + local hashed_password, hash_f; + hashed_password, hash_f, state = self.profile.plain_hashed(authentication, self.realm); + if hashed_password == hash_f(password) then correct = true; else correct = false; end end self.username = authentication @@ -76,7 +85,7 @@ local function plain(self, message) end function init(registerMechanism) - registerMechanism("PLAIN", {"plain", "plain_test"}, plain); + registerMechanism("PLAIN", {"plain", "plain_test", "plain_hashed"}, plain); end return _M; -- cgit v1.2.3 From ddc193c83165e2f37c21889aeaf22c7a3cd9deab Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Fri, 12 Mar 2010 18:37:51 +0100 Subject: util.sasl: 2009 -> 2010 in copyright header. --- util/sasl/anonymous.lua | 2 +- util/sasl/digest-md5.lua | 2 +- util/sasl/plain.lua | 2 +- util/sasl/scram.lua | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/util/sasl/anonymous.lua b/util/sasl/anonymous.lua index 65650294..7b5a5081 100644 --- a/util/sasl/anonymous.lua +++ b/util/sasl/anonymous.lua @@ -1,5 +1,5 @@ -- sasl.lua v0.4 --- Copyright (C) 2008-2009 Tobias Markmann +-- Copyright (C) 2008-2010 Tobias Markmann -- -- All rights reserved. -- diff --git a/util/sasl/digest-md5.lua b/util/sasl/digest-md5.lua index fc2107bc..8986ca45 100644 --- a/util/sasl/digest-md5.lua +++ b/util/sasl/digest-md5.lua @@ -1,5 +1,5 @@ -- sasl.lua v0.4 --- Copyright (C) 2008-2009 Tobias Markmann +-- Copyright (C) 2008-2010 Tobias Markmann -- -- All rights reserved. -- diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index 6369face..2abbc53a 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -1,5 +1,5 @@ -- sasl.lua v0.4 --- Copyright (C) 2008-2009 Tobias Markmann +-- Copyright (C) 2008-2010 Tobias Markmann -- -- All rights reserved. -- diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 103e8a90..19fb7a18 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -1,5 +1,5 @@ -- sasl.lua v0.4 --- Copyright (C) 2008-2009 Tobias Markmann +-- Copyright (C) 2008-2010 Tobias Markmann -- -- All rights reserved. -- -- cgit v1.2.3 From e169b45da9cfc3a6d19cfedc2cb7d18248b6a019 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Fri, 21 May 2010 23:40:29 +0200 Subject: util.sasl.plain: Removing plain_hashed authentication provider. Just do hashing and comparison yourself in a plain_test authentication provider. --- util/sasl/plain.lua | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index 2abbc53a..f1e04f32 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -32,11 +32,6 @@ plain-test: function(username, realm, password) return true or false, state; end - -plain-hashed: - function(username, realm) - return hashed_password, hash_function, state; - end ]] local function plain(self, message) @@ -66,10 +61,6 @@ local function plain(self, message) if correct_password == password then correct = true; else correct = false; end elseif self.profile.plain_test then correct, state = self.profile.plain_test(authentication, self.realm, password); - elseif self.profile.plain_hashed then - local hashed_password, hash_f; - hashed_password, hash_f, state = self.profile.plain_hashed(authentication, self.realm); - if hashed_password == hash_f(password) then correct = true; else correct = false; end end self.username = authentication @@ -85,7 +76,7 @@ local function plain(self, message) end function init(registerMechanism) - registerMechanism("PLAIN", {"plain", "plain_test", "plain_hashed"}, plain); + registerMechanism("PLAIN", {"plain", "plain_test"}, plain); end return _M; -- cgit v1.2.3 From eb398e4d08506202d9a67fed60c355afd70c0f81 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sun, 28 Feb 2010 22:23:03 +0100 Subject: util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support. --- util/sasl/scram.lua | 132 +++++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 57 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 19fb7a18..4e52f5cd 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -82,77 +82,95 @@ local function validate_username(username) return username; end -local function scram_sha_1(self, message) - if not self.state then self["state"] = {} end +local function scram_gen(hash_name, H_f, HMAC_f) + local function scram_hash(self, message) + if not self.state then self["state"] = {} end - if not self.state.name then - -- we are processing client_first_message - local client_first_message = message; - self.state["client_first_message"] = client_first_message; - self.state["name"] = client_first_message:match("n=(.+),r=") - self.state["clientnonce"] = client_first_message:match("r=([^,]+)") - - if not self.state.name or not self.state.clientnonce then - return "failure", "malformed-request"; - end - - self.state.name = validate_username(self.state.name); if not self.state.name then - log("debug", "Username violates either SASLprep or contains forbidden character sequences.") - return "failure", "malformed-request", "Invalid username."; - end + -- we are processing client_first_message + local client_first_message = message; + self.state["client_first_message"] = client_first_message; + self.state["name"] = client_first_message:match("n=(.+),r=") + self.state["clientnonce"] = client_first_message:match("r=([^,]+)") - self.state["servernonce"] = generate_uuid(); - self.state["salt"] = generate_uuid(); + if not self.state.name or not self.state.clientnonce then + return "failure", "malformed-request"; + end - local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..default_i; - self.state["server_first_message"] = server_first_message; - return "challenge", server_first_message - else - if type(message) ~= "string" then return "failure", "malformed-request" end - -- we are processing client_final_message - local client_final_message = message; + self.state.name = validate_username(self.state.name); + if not self.state.name then + log("debug", "Username violates either SASLprep or contains forbidden character sequences.") + return "failure", "malformed-request", "Invalid username."; + end - self.state["proof"] = client_final_message:match("p=(.+)"); - self.state["nonce"] = client_final_message:match("r=(.+),p="); - self.state["channelbinding"] = client_final_message:match("c=(.+),r="); - if not self.state.proof or not self.state.nonce or not self.state.channelbinding then - return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; - end + self.state["servernonce"] = generate_uuid(); + + -- retreive credentials + if self.profile.plain then + password, state = self.profile.plain(self.state.name, self.realm) + if state == nil then return "failure", "not-authorized" + elseif state == false then return "failure", "account-disabled" end + + password = saslprep(password); + if not password then + log("debug", "Password violates SASLprep."); + return "failure", "not-authorized", "Invalid password." + end + self.state.salt = generate_uuid(); + self.state.iteration_count = default_i; + self.state.salted_password = Hi(HMAC_f, password, self.state.salt, default_i); + elseif self.profile["scram-"..hash_name] then + salted_password, iteration_count, salt, state = self.profile["scram-"..hash_name](self.state.name, self.realm); + if state == nil then return "failure", "not-authorized" + elseif state == false then return "failure", "account-disabled" end + + self.state.salted_password = salted_password; + self.state.iteration_count = iteration_count; + self.state.salt = salt + end - local password, state; - if self.profile.plain then - password, state = self.profile.plain(self.state.name, self.realm) - if state == nil then return "failure", "not-authorized" - elseif state == false then return "failure", "account-disabled" end - password = saslprep(password); - if not password then - log("debug", "Password violates SASLprep."); - return "failure", "not-authorized", "Invalid password." + local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..self.state.iteration_count; + self.state["server_first_message"] = server_first_message; + return "challenge", server_first_message + else + if type(message) ~= "string" then return "failure", "malformed-request" end + -- we are processing client_final_message + local client_final_message = message; + + self.state["proof"] = client_final_message:match("p=(.+)"); + self.state["nonce"] = client_final_message:match("r=(.+),p="); + self.state["channelbinding"] = client_final_message:match("c=(.+),r="); + if not self.state.proof or not self.state.nonce or not self.state.channelbinding then + return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; end - end - local SaltedPassword = Hi(hmac_sha1, password, self.state.salt, default_i) - local ClientKey = hmac_sha1(SaltedPassword, "Client Key") - local ServerKey = hmac_sha1(SaltedPassword, "Server Key") - local StoredKey = sha1(ClientKey) - local AuthMessage = "n=" .. s_match(self.state.client_first_message,"n=(.+)") .. "," .. self.state.server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+") - local ClientSignature = hmac_sha1(StoredKey, AuthMessage) - local ClientProof = binaryXOR(ClientKey, ClientSignature) - local ServerSignature = hmac_sha1(ServerKey, AuthMessage) + local SaltedPassword = self.state.salted_password; + local ClientKey = HMAC_f(SaltedPassword, "Client Key") + local ServerKey = HMAC_f(SaltedPassword, "Server Key") + local StoredKey = H_f(ClientKey) + local AuthMessage = "n=" .. s_match(self.state.client_first_message,"n=(.+)") .. "," .. self.state.server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+") + local ClientSignature = HMAC_f(StoredKey, AuthMessage) + local ClientProof = binaryXOR(ClientKey, ClientSignature) + local ServerSignature = HMAC_f(ServerKey, AuthMessage) - if base64.encode(ClientProof) == self.state.proof then - local server_final_message = "v="..base64.encode(ServerSignature); - self["username"] = self.state.name; - return "success", server_final_message; - else - return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated."; + if base64.encode(ClientProof) == self.state.proof then + local server_final_message = "v="..base64.encode(ServerSignature); + self["username"] = self.state.name; + return "success", server_final_message; + else + return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated."; + end end end + return scram_hash; end function init(registerMechanism) - registerMechanism("SCRAM-SHA-1", {"plain"}, scram_sha_1); + local function registerSCRAMMechanism(hash_name, hash, hmac_hash) + registerMechanism("SCRAM-"..hash_name, {"plain", "scram-"..(hash_name:lower())}, scram_gen(hash_name:lower(), hash, hmac_hash)); + end + + registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); end return _M; \ No newline at end of file -- cgit v1.2.3 From 1d5c54a2f55c1e60313c6aa4cc411edd7c7578c5 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sun, 28 Feb 2010 22:42:53 +0100 Subject: util.sasl.scram: Adding documentation on SCRAM authentication backend. --- util/sasl/scram.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 4e52f5cd..14fb8beb 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -28,6 +28,16 @@ module "scram" --========================= --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10 + +--[[ +Supported Authentication Backends + +scram-{MECH}: + function(username, realm) + return salted_password, iteration_count, salt, state; + end +]] + local default_i = 4096 local function bp( b ) -- cgit v1.2.3 From e1b9d33130e9eda7c9dc656880f2aaf25f7b22cc Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Thu, 6 May 2010 15:19:20 +0500 Subject: util.sasl.scram: Fixed global access. --- util/sasl/scram.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 14fb8beb..ed7d7bc3 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -117,7 +117,7 @@ local function scram_gen(hash_name, H_f, HMAC_f) -- retreive credentials if self.profile.plain then - password, state = self.profile.plain(self.state.name, self.realm) + local password, state = self.profile.plain(self.state.name, self.realm) if state == nil then return "failure", "not-authorized" elseif state == false then return "failure", "account-disabled" end @@ -129,8 +129,8 @@ local function scram_gen(hash_name, H_f, HMAC_f) self.state.salt = generate_uuid(); self.state.iteration_count = default_i; self.state.salted_password = Hi(HMAC_f, password, self.state.salt, default_i); - elseif self.profile["scram-"..hash_name] then - salted_password, iteration_count, salt, state = self.profile["scram-"..hash_name](self.state.name, self.realm); + elseif self.profile["scram_"..hash_name] then + local salted_password, iteration_count, salt, state = self.profile["scram-"..hash_name](self.state.name, self.realm); if state == nil then return "failure", "not-authorized" elseif state == false then return "failure", "account-disabled" end @@ -177,7 +177,7 @@ end function init(registerMechanism) local function registerSCRAMMechanism(hash_name, hash, hmac_hash) - registerMechanism("SCRAM-"..hash_name, {"plain", "scram-"..(hash_name:lower())}, scram_gen(hash_name:lower(), hash, hmac_hash)); + registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hash_name:lower())}, scram_gen(hash_name:lower(), hash, hmac_hash)); end registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); -- cgit v1.2.3 From b7a87c093211d21bb626c13505d8c6b5575e4bd2 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 01:48:31 +0200 Subject: util.sasl.scram: Check nonce in client final message. Check channel binding flag in client first message. Adding some TODOs on more strict parsing. (thanks Marc Santamaria) --- util/sasl/scram.lua | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index ed7d7bc3..ffca171c 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -1,15 +1,15 @@ -- sasl.lua v0.4 -- Copyright (C) 2008-2010 Tobias Markmann -- --- All rights reserved. +-- All rights reserved. -- --- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -- --- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. --- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. --- * Neither the name of Tobias Markmann nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +-- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +-- * Neither the name of Tobias Markmann nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -- --- 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. +-- 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. local s_match = string.match; local type = type @@ -99,13 +99,21 @@ local function scram_gen(hash_name, H_f, HMAC_f) if not self.state.name then -- we are processing client_first_message local client_first_message = message; + + -- TODO: more strict parsing of client_first_message + -- TODO: fail if authzid is provided, since we don't support them yet self.state["client_first_message"] = client_first_message; self.state["name"] = client_first_message:match("n=(.+),r=") self.state["clientnonce"] = client_first_message:match("r=([^,]+)") - - if not self.state.name or not self.state.clientnonce then + self.state["gs2_cbind_flag"] = client_first_message:sub(1, 1) + -- we don't do any channel binding yet + if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then return "failure", "malformed-request"; end + + if not self.state.name or not self.state.clientnonce then + return "failure", "malformed-request", "Channel binding isn't support at this time."; + end self.state.name = validate_username(self.state.name); if not self.state.name then @@ -146,14 +154,20 @@ local function scram_gen(hash_name, H_f, HMAC_f) if type(message) ~= "string" then return "failure", "malformed-request" end -- we are processing client_final_message local client_final_message = message; - + + -- TODO: more strict parsing of client_final_message self.state["proof"] = client_final_message:match("p=(.+)"); self.state["nonce"] = client_final_message:match("r=(.+),p="); self.state["channelbinding"] = client_final_message:match("c=(.+),r="); + if not self.state.proof or not self.state.nonce or not self.state.channelbinding then return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; end - + + if self.state.nonce ~= self.state.servernonce then + return "failure", "malformed-request", "Wrong nonce in client-second-message."; + end + local SaltedPassword = self.state.salted_password; local ClientKey = HMAC_f(SaltedPassword, "Client Key") local ServerKey = HMAC_f(SaltedPassword, "Server Key") @@ -162,7 +176,7 @@ local function scram_gen(hash_name, H_f, HMAC_f) local ClientSignature = HMAC_f(StoredKey, AuthMessage) local ClientProof = binaryXOR(ClientKey, ClientSignature) local ServerSignature = HMAC_f(ServerKey, AuthMessage) - + if base64.encode(ClientProof) == self.state.proof then local server_final_message = "v="..base64.encode(ServerSignature); self["username"] = self.state.name; @@ -179,7 +193,7 @@ function init(registerMechanism) local function registerSCRAMMechanism(hash_name, hash, hmac_hash) registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hash_name:lower())}, scram_gen(hash_name:lower(), hash, hmac_hash)); end - + registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); end -- cgit v1.2.3 From a69a0446406c8b2b76aefce317e1c1820e55e4f8 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 13:58:15 +0200 Subject: util.sasl.scram: Parsing client-first-message in a more strict way. (thanks Marc Santamaria) --- util/sasl/scram.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index ffca171c..4c5df11a 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -100,12 +100,10 @@ local function scram_gen(hash_name, H_f, HMAC_f) -- we are processing client_first_message local client_first_message = message; - -- TODO: more strict parsing of client_first_message -- TODO: fail if authzid is provided, since we don't support them yet self.state["client_first_message"] = client_first_message; - self.state["name"] = client_first_message:match("n=(.+),r=") - self.state["clientnonce"] = client_first_message:match("r=([^,]+)") - self.state["gs2_cbind_flag"] = client_first_message:sub(1, 1) + self.state["gs2_cbind_flag"], self.state["authzid"], self.state["name"], self.state["clientnonce"] = client_first_message:match("^(%a),(.*),n=(.*),r=([^,]*).*"); + -- we don't do any channel binding yet if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then return "failure", "malformed-request"; -- cgit v1.2.3 From 1f64550d6c9be4511288bb72d2ebc88223918dd6 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 13:59:58 +0200 Subject: util.sasl.scram: Fix in nonce check of client-final-message. --- util/sasl/scram.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 4c5df11a..7b9123ee 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -162,8 +162,8 @@ local function scram_gen(hash_name, H_f, HMAC_f) return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; end - if self.state.nonce ~= self.state.servernonce then - return "failure", "malformed-request", "Wrong nonce in client-second-message."; + if self.state.nonce ~= self.state.clientnonce..self.state.servernonce then + return "failure", "malformed-request", "Wrong nonce in client-final-message."; end local SaltedPassword = self.state.salted_password; -- cgit v1.2.3 From 621f91d4a67b07ad89853e2197fc9a62302a75fd Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 14:47:21 +0200 Subject: util.sasl.scram: Parsing client-final-message in a more strict way. (thanks Marc Santamaria) --- util/sasl/scram.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 7b9123ee..0188d5cf 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -153,10 +153,7 @@ local function scram_gen(hash_name, H_f, HMAC_f) -- we are processing client_final_message local client_final_message = message; - -- TODO: more strict parsing of client_final_message - self.state["proof"] = client_final_message:match("p=(.+)"); - self.state["nonce"] = client_final_message:match("r=(.+),p="); - self.state["channelbinding"] = client_final_message:match("c=(.+),r="); + self.state["channelbinding"], self.state["nonce"], self.state["proof"] = client_final_message:match("^c=(.*),r=(.*),.*p=(.*)"); if not self.state.proof or not self.state.nonce or not self.state.channelbinding then return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; -- cgit v1.2.3 From 47c7c633170ae0d947a7f22e720f1868fec63332 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 14:58:24 +0200 Subject: util.sasl.scram: Split up long line. --- util/sasl/scram.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 0188d5cf..13b9932f 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -102,7 +102,8 @@ local function scram_gen(hash_name, H_f, HMAC_f) -- 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["authzid"], self.state["name"], self.state["clientnonce"] = client_first_message:match("^(%a),(.*),n=(.*),r=([^,]*).*"); + self.state["gs2_cbind_flag"], self.state["authzid"], self.state["name"], self.state["clientnonce"] + = client_first_message:match("^(%a),(.*),n=(.*),r=([^,]*).*"); -- we don't do any channel binding yet if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then -- cgit v1.2.3 From 229d07afa05408750fbc8314bd4e51243b9daf4d Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 19:04:53 +0200 Subject: util.sasl.scram: Providing an API function to generate a salted password for the SCRAM-SHA-1 mechanism. --- util/sasl/scram.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 13b9932f..39daf397 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -92,6 +92,18 @@ local function validate_username(username) return username; end +function saltedPasswordSHA1(password, salt, iteration_count) + local salted_password + if type(password) ~= "string" and type(salt) ~= "string" and type(iteration_count) ~= "number" then + return false, "inappropriate argument types" + end + if iteration_count < 4096 then + log("warning", "Iteration count < 4096 which is the suggested minimum according to RFC 5802.") + end + + return true, Hi(hmac_sha1, password, salt, iteration_count); +end + local function scram_gen(hash_name, H_f, HMAC_f) local function scram_hash(self, message) if not self.state then self["state"] = {} end @@ -133,9 +145,16 @@ local function scram_gen(hash_name, H_f, HMAC_f) log("debug", "Password violates SASLprep."); return "failure", "not-authorized", "Invalid password." end + self.state.salt = generate_uuid(); self.state.iteration_count = default_i; - self.state.salted_password = Hi(HMAC_f, password, self.state.salt, default_i); + + local succ = false; + succ, self.state.salted_password = saltedPasswordSHA1(password, self.state.salt, default_i, self.state.iteration_count); + if not succ then + log("error", "Generating salted password failed. Reason: %s", self.state.salted_password); + return "failure", "temporary-auth-failure"; + end elseif self.profile["scram_"..hash_name] then local salted_password, iteration_count, salt, state = self.profile["scram-"..hash_name](self.state.name, self.realm); if state == nil then return "failure", "not-authorized" -- cgit v1.2.3 From 44b60251257f7ca176c3436dad3220137a1eb5b7 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 20:34:32 +0200 Subject: util.sasl.plain: Typo. --- util/sasl/plain.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/sasl/plain.lua b/util/sasl/plain.lua index f1e04f32..39821182 100644 --- a/util/sasl/plain.lua +++ b/util/sasl/plain.lua @@ -28,7 +28,7 @@ plain: return password, state; end -plain-test: +plain_test: function(username, realm, password) return true or false, state; end -- cgit v1.2.3 From 7847a8a20fc9fc0b057bf7f99fd0d0a80b4d85e3 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 22 May 2010 20:51:01 +0200 Subject: util.sasl.scram: Fixing issue #177. --- util/sasl/scram.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 39daf397..47e8e7b3 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -108,6 +108,7 @@ local function scram_gen(hash_name, H_f, HMAC_f) local function scram_hash(self, message) if not self.state then self["state"] = {} end + if type(message) ~= "string" or #message == 0 then return "failure", "malformed-request" end if not self.state.name then -- we are processing client_first_message local client_first_message = message; @@ -169,7 +170,6 @@ local function scram_gen(hash_name, H_f, HMAC_f) self.state["server_first_message"] = server_first_message; return "challenge", server_first_message else - if type(message) ~= "string" then return "failure", "malformed-request" end -- we are processing client_final_message local client_final_message = message; -- cgit v1.2.3 From 4b31a9798fee915ced267f8196af658d74075652 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sun, 28 Feb 2010 22:58:43 +0100 Subject: util.sasl.scram: Adjusting authentication backend name to conform with the style already used by the plain module. --- util/sasl/scram.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/sasl/scram.lua b/util/sasl/scram.lua index 47e8e7b3..6040c402 100644 --- a/util/sasl/scram.lua +++ b/util/sasl/scram.lua @@ -212,4 +212,4 @@ function init(registerMechanism) registerSCRAMMechanism("SHA-1", sha1, hmac_sha1); end -return _M; \ No newline at end of file +return _M; -- cgit v1.2.3 From 017a5331582d4dbdf0512547491c0a680db3afb2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 21 May 2010 19:44:31 +0100 Subject: Backed out changeset c75c22c316d6 (the XMPP spec now gives a better way to do this) --- plugins/mod_presence.lua | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 648c78b3..a39d9c19 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -38,42 +38,23 @@ function core_route_stanza(origin, stanza) _core_route_stanza(origin, stanza); end -local select_top_resources; -local bare_message_delivery_policy = module:get_option("bare_message_delivery_policy") or "priority"; -if bare_message_delivery_policy == "broadcast" then - function select_top_resources(user) - local recipients = {}; - for _, session in pairs(user.sessions) do -- find resources with non-negative priority +local function select_top_resources(user) + local priority = 0; + local recipients = {}; + for _, session in pairs(user.sessions) do -- find resource with greatest priority + if session.presence then + -- TODO check active privacy list for session local p = session.priority; - if p and p >= 0 then + if p > priority then + priority = p; + recipients = {session}; + elseif p == priority then t_insert(recipients, session); end end - return recipients; - end -else - if bare_message_delivery_policy ~= "priority" then - module:log("warn", "Invalid value for config option bare_message_delivery_policy"); - end - function select_top_resources(user) - local priority = 0; - local recipients = {}; - for _, session in pairs(user.sessions) do -- find resource with greatest priority - if session.presence then - -- TODO check active privacy list for session - local p = session.priority; - if p > priority then - priority = p; - recipients = {session}; - elseif p == priority then - t_insert(recipients, session); - end - end - end - return recipients; end + return recipients; end - local function recalc_resource_map(user) if user then user.top_resources = select_top_resources(user); -- cgit v1.2.3 From 3aedbba6788ca1ca7fcd491c2797af93c9dd6c35 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 03:20:43 +0500 Subject: mod_presence: Added option 'ignore_presence_priority'. --- plugins/mod_presence.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 108ab0d3..535e65d7 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -62,7 +62,17 @@ local function recalc_resource_map(user) end end +local ignore_presence_priority = module:get_option("ignore_presence_priority"); + function handle_normal_presence(origin, stanza, core_route_stanza) + if ignore_presence_priority then + local priority = stanza:child_with_name("priority"); + if priority and priority[1] ~= "0" then + for i=#priority.tags,1,-1 do priority.tags[i] = nil; end + for i=#priority,1,-1 do priority[i] = nil; end + priority[1] = "0"; + end + end if full_sessions[origin.full_jid] then -- if user is still connected origin.send(stanza); -- reflect their presence back to them end -- cgit v1.2.3 From d2f33e44a085ee597cfece627c2e7c540ef74af0 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 03:54:50 +0500 Subject: mod_privacy: Improved logging. --- plugins/mod_privacy.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/mod_privacy.lua b/plugins/mod_privacy.lua index 3e9dbe49..ca5d51fa 100644 --- a/plugins/mod_privacy.lua +++ b/plugins/mod_privacy.lua @@ -307,7 +307,7 @@ function checkIfNeedToBeBlocked(e, session) local is_to_user = bare_jid == jid_bare(to); local is_from_user = bare_jid == jid_bare(from); - module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(to), tostring(from)); + --module:log("debug", "stanza: %s, to: %s, from: %s", tostring(stanza.name), tostring(to), tostring(from)); if privacy_lists.lists == nil or not (session.activePrivacyList or privacy_lists.default) @@ -315,7 +315,7 @@ function checkIfNeedToBeBlocked(e, session) return; -- Nothing to block, default is Allow all end if is_from_user and is_to_user then - module:log("debug", "Not blocking communications between user's resources"); + --module:log("debug", "Not blocking communications between user's resources"); return; -- from one of a user's resource to another => HANDS OFF! end @@ -325,8 +325,8 @@ function checkIfNeedToBeBlocked(e, session) listname = privacy_lists.default; -- no active list selected, use default list end local list = privacy_lists.lists[listname]; - if not list then - module:log("debug", "given privacy list not found. name: %s", listname); + if not list then -- should never happen + module:log("warn", "given privacy list not found. name: %s for user %s", listname, bare_jid); return; end for _,item in ipairs(list.items) do @@ -345,10 +345,10 @@ function checkIfNeedToBeBlocked(e, session) local evilJid = {}; apply = false; if is_to_user then - module:log("debug", "evil jid is (from): %s", from); + --module:log("debug", "evil jid is (from): %s", from); evilJid.node, evilJid.host, evilJid.resource = jid_split(from); else - module:log("debug", "evil jid is (to): %s", to); + --module:log("debug", "evil jid is (to): %s", to); evilJid.node, evilJid.host, evilJid.resource = jid_split(to); end if item.type == "jid" and @@ -394,7 +394,7 @@ function checkIfNeedToBeBlocked(e, session) end return true; -- stanza blocked ! else - module:log("debug", "stanza explicitly allowed!") + --module:log("debug", "stanza explicitly allowed!") return; end end @@ -425,7 +425,7 @@ function preCheckIncoming(e) if session ~= nil then return checkIfNeedToBeBlocked(e, session); else - module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource)); + --module:log("debug", "preCheckIncoming: Couldn't get session for jid: %s@%s/%s", tostring(node), tostring(host), tostring(resource)); end end end -- cgit v1.2.3 From 4499df4f45b9101ccd9078099f9a224b82822cb0 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 05:49:21 +0500 Subject: util.datamanager: When failing to load a file, and the file exists, return nil, error. --- util/datamanager.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/util/datamanager.lua b/util/datamanager.lua index 01c7aab2..9d96e5b3 100644 --- a/util/datamanager.lua +++ b/util/datamanager.lua @@ -21,12 +21,13 @@ local next = next; local t_insert = table.insert; local append = require "util.serialization".append; local path_separator = "/"; if os.getenv("WINDIR") then path_separator = "\\" end +local lfs = require "lfs"; local raw_mkdir; if prosody.platform == "posix" then raw_mkdir = require "util.pposix".mkdir; -- Doesn't trample on umask else - raw_mkdir = require "lfs".mkdir; + raw_mkdir = lfs.mkdir; end module "datamanager" @@ -111,14 +112,21 @@ end function load(username, host, datastore) local data, ret = loadfile(getpath(username, host, datastore)); if not data then - log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil")); - return nil; + local mode = lfs.attributes(getpath(username, host, datastore), "mode"); + if not mode then + log("debug", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil")); + return nil; + else -- file exists, but can't be read + -- TODO more detailed error checking and logging? + log("error", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil")); + return nil, "Error reading storage"; + end end setfenv(data, {}); local success, ret = pcall(data); if not success then log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or "nil").."@"..(host or "nil")); - return nil; + return nil, "Error reading storage"; end return ret; end -- cgit v1.2.3 From 2bf0d50232994a42e4a250b124fbbba01dfef57a Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 05:50:47 +0500 Subject: rostermanager: When loading the roster, also return a datamanager error if available. --- core/rostermanager.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/rostermanager.lua b/core/rostermanager.lua index e2a92696..a8eb806c 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -93,7 +93,8 @@ function load_roster(username, host) else -- Attempt to load roster for non-loaded user log("debug", "load_roster: loading for offline user: "..username.."@"..host); end - roster = datamanager.load(username, host, "roster") or {}; + local data, err = datamanager.load(username, host, "roster"); + roster = data or {}; if user then user.roster = roster; end if not roster[false] then roster[false] = { }; end if roster[jid] then @@ -101,7 +102,7 @@ function load_roster(username, host) log("warn", "roster for "..jid.." has a self-contact"); end hosts[host].events.fire_event("roster-load", username, host, roster); - return roster; + return roster, err; end function save_roster(username, host, roster) -- cgit v1.2.3 From f77c1fc2d0378297e4d31ff2f7420515291d9988 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 05:52:24 +0500 Subject: sessionmanager: If roster loading fails during resource bind, kick the user with an internal-server-error. --- core/sessionmanager.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 6e771a84..3537d2d2 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -174,7 +174,19 @@ function bind_resource(session, resource) hosts[session.host].sessions[session.username].sessions[resource] = session; full_sessions[session.full_jid] = session; - session.roster = rm_load_roster(session.username, session.host); + local err; + session.roster, err = rm_load_roster(session.username, session.host); + if err then + full_sessions[session.full_jid] = nil; + hosts[session.host].sessions[session.username].sessions[resource] = nil; + session.full_jid = nil; + session.resource = nil; + if next(bare_sessions[session.username..'@'..session.host]) == nil then + bare_sessions[session.username..'@'..session.host] = nil; + hosts[session.host].sessions[session.username] = nil; + end + return nil, "cancel", "internal-server-error", "Error loading roster"; + end hosts[session.host].events.fire_event("resource-bind", {session=session}); -- cgit v1.2.3 From c1257c7435697f4ed47c823ac0ebc8f676f1c773 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 22 May 2010 05:53:27 +0500 Subject: sessionmanager: Change error for reaching resource limit from 'conflict' to 'resource-constraint' during session bind. --- core/sessionmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 3537d2d2..48990de3 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -136,7 +136,7 @@ function bind_resource(session, resource) local sessions = hosts[session.host].sessions[session.username].sessions; local limit = config_get(session.host, "core", "max_resources") or 10; if #sessions >= limit then - return nil, "cancel", "conflict", "Resource limit reached; only "..limit.." resources allowed"; + return nil, "cancel", "resource-constraint", "Resource limit reached; only "..limit.." resources allowed"; end if sessions[resource] then -- Resource conflict -- cgit v1.2.3 From 41d45e0c64b94de227f048d5f376699dd6041735 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 22 May 2010 12:20:22 +0100 Subject: rostermanager: Don't fire roster-load event if there was an error loading the roster --- core/rostermanager.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/rostermanager.lua b/core/rostermanager.lua index a8eb806c..a3315245 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -101,7 +101,9 @@ function load_roster(username, host) roster[jid] = nil; log("warn", "roster for "..jid.." has a self-contact"); end - hosts[host].events.fire_event("roster-load", username, host, roster); + if not err then + hosts[host].events.fire_event("roster-load", username, host, roster); + end return roster, err; end -- cgit v1.2.3 From 8abd2f2c24bd83acb36e9c8ace40ac3751f09663 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sun, 23 May 2010 05:46:52 +0500 Subject: rostermanager: Correctly clear the bare_sessions table on roster load errors during bind. --- core/sessionmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 48990de3..fd6ed96e 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -181,7 +181,7 @@ function bind_resource(session, resource) hosts[session.host].sessions[session.username].sessions[resource] = nil; session.full_jid = nil; session.resource = nil; - if next(bare_sessions[session.username..'@'..session.host]) == nil then + if next(bare_sessions[session.username..'@'..session.host].sessions) == nil then bare_sessions[session.username..'@'..session.host] = nil; hosts[session.host].sessions[session.username] = nil; end -- cgit v1.2.3 From 42f63b21d79733a2198952245df0673434bd31d2 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sun, 23 May 2010 23:55:01 +0500 Subject: util.datamanager: Return an error string when failing to save. --- util/datamanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/datamanager.lua b/util/datamanager.lua index 9d96e5b3..57cd2594 100644 --- a/util/datamanager.lua +++ b/util/datamanager.lua @@ -145,7 +145,7 @@ function store(username, host, datastore, data) local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+"); if not f then log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or "nil").."@"..(host or "nil")); - return; + return nil, "Error saving to storage"; end f:write("return "); append(f, data); -- cgit v1.2.3 From 1ee72fdb1161361d653bead96ea4fb140e9054cc Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 00:04:22 +0500 Subject: mod_presence: Removed a useless check when handling incoming presence probes and subscriptions. --- plugins/mod_presence.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 535e65d7..255faecc 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -227,10 +227,6 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b stanza.attr.from, stanza.attr.to = from_bare, to_bare; log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare); - if not node then - log("debug", "dropping presence sent to host or invalid address '%s'", tostring(to_bare)); - end - if stanza.attr.type == "probe" then if rostermanager.is_contact_subscribed(node, host, from_bare) then if 0 == send_presence_of_available_resources(node, host, st_from, origin, core_route_stanza) then -- cgit v1.2.3 From 054a2d38c1ab12bf6bda2c22b775a91b9fb4dd4a Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 00:29:45 +0500 Subject: rostermanager: Mark rosters which fail to load as broken, and never save them. --- core/rostermanager.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/rostermanager.lua b/core/rostermanager.lua index a3315245..285cf4f6 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -96,7 +96,7 @@ function load_roster(username, host) local data, err = datamanager.load(username, host, "roster"); roster = data or {}; if user then user.roster = roster; end - if not roster[false] then roster[false] = { }; end + if not roster[false] then roster[false] = { broken = err or nil }; end if roster[jid] then roster[jid] = nil; log("warn", "roster for "..jid.." has a self-contact"); @@ -125,6 +125,7 @@ function save_roster(username, host, roster) if metadata.version ~= true then metadata.version = (metadata.version or 0) + 1; end + if roster[false].broken then return nil, "Not saving broken roster" end return datamanager.store(username, host, "roster", roster); end log("warn", "save_roster: user had no roster to save"); -- cgit v1.2.3 From e1b4298fde007769a41c0a97fbfcc2f44bb383f9 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 00:35:08 +0500 Subject: rostermanager: Return an error string when subscription test fails due to an error. --- core/rostermanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/rostermanager.lua b/core/rostermanager.lua index 285cf4f6..506cf205 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -191,9 +191,9 @@ function process_inbound_unsubscribe(username, host, jid) end function is_contact_subscribed(username, host, jid) - local roster = load_roster(username, host); + local roster, err = load_roster(username, host); local item = roster[jid]; - return item and (item.subscription == "from" or item.subscription == "both"); + return item and (item.subscription == "from" or item.subscription == "both"), err; end function is_contact_pending_in(username, host, jid) -- cgit v1.2.3 From 6523b2bbe5e7ae92e241e10c587acbb61ec8eb77 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 00:37:15 +0500 Subject: mod_presence: Don't send 'unsubscribed' in response to probes when roster loading fails. --- plugins/mod_presence.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/mod_presence.lua b/plugins/mod_presence.lua index 255faecc..9071ae4c 100644 --- a/plugins/mod_presence.lua +++ b/plugins/mod_presence.lua @@ -228,11 +228,12 @@ function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_b log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare); if stanza.attr.type == "probe" then - if rostermanager.is_contact_subscribed(node, host, from_bare) then + local result, err = rostermanager.is_contact_subscribed(node, host, from_bare); + if result then if 0 == send_presence_of_available_resources(node, host, st_from, origin, core_route_stanza) then core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity end - else + elseif not err then core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"})); end elseif stanza.attr.type == "subscribe" then -- cgit v1.2.3 From 4353f95a958a306dfb990d84abe7a922ece80126 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 00:49:12 +0500 Subject: usermanager: Take datamanager errors into account when determining account existance. --- core/usermanager.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/usermanager.lua b/core/usermanager.lua index 42e49d38..698d2f10 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -69,7 +69,8 @@ end function user_exists(username, host) if not(require_provisioning) and is_cyrus(host) then return true; end - return datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials + local account, err = datamanager.load(username, host, "accounts"); + return (account or err) ~= nil; -- FIXME also check for empty credentials end function create_user(username, password, host) -- cgit v1.2.3 From c918263d056fa6c099bbc704d8e0a17b24d546d7 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 24 May 2010 01:00:30 +0500 Subject: mod_private: Detect datamanager read errors, and respond with 'internal-server-error'. --- plugins/mod_private.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/mod_private.lua b/plugins/mod_private.lua index 859bf45a..abf1ec03 100644 --- a/plugins/mod_private.lua +++ b/plugins/mod_private.lua @@ -26,7 +26,11 @@ module:add_iq_handler("c2s", "jabber:iq:private", if #query.tags == 1 then local tag = query.tags[1]; local key = tag.name..":"..tag.attr.xmlns; - local data = datamanager.load(node, host, "private"); + local data, err = datamanager.load(node, host, "private"); + if err then + session.send(st.error_reply(stanza, "wait", "internal-server-error")); + return true; + end if stanza.attr.type == "get" then if data and data[key] then session.send(st.reply(stanza):tag("query", {xmlns = "jabber:iq:private"}):add_child(st.deserialize(data[key]))); -- cgit v1.2.3