util/sasl/scram.lua
author Waqas Hussain <waqas20@gmail.com>
Tue, 01 Dec 2009 01:45:56 +0500
changeset 2267 0a675bb365a9
parent 2266 6e662e4f7ab2
child 2290 ef7027a0f0c9
permissions -rw-r--r--
util.sasl.scram: Optimized binaryXOR.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     1
-- sasl.lua v0.4
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     2
-- Copyright (C) 2008-2009 Tobias Markmann
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     3
--
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     4
--    All rights reserved.
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     5
--
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     6
--    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     7
--
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     8
--        * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
     9
--        * 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.
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    10
--        * 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.
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    11
--
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    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.
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    13
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    14
local s_match = string.match;
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    15
local type = type
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    16
local string = string
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    17
local base64 = require "util.encodings".base64;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    18
local xor = require "bit".bxor
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    19
local hmac_sha1 = require "util.hmac".sha1;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    20
local sha1 = require "util.hashes".sha1;
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    21
local generate_uuid = require "util.uuid".generate;
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
    22
local saslprep = require "util.encodings".stringprep.saslprep;
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
    23
local log = require "util.logger".init("sasl");
2267
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    24
local t_concat = table.concat;
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    25
local char = string.char;
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    26
local byte = string.byte;
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    27
2206
Tobias Markmann <tm@ayena.de>
parents: 2205
diff changeset
    28
module "scram"
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    29
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    30
--=========================
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    31
--SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    32
local default_i = 4096
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    33
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    34
local function bp( b )
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    35
	local result = ""
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    36
	for i=1, b:len() do
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    37
		result = result.."\\"..b:byte(i)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    38
	end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    39
	return result
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    40
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    41
2267
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    42
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;};
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    43
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    44
local result = {};
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    45
local function binaryXOR( a, b )
2267
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    46
	for i=1, #a do
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    47
		local x, y = byte(a, i), byte(b, i);
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    48
		local lowx, lowy = x % 16, y % 16;
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    49
		local hix, hiy = (x - lowx) / 16, (y - lowy) / 16;
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    50
		local lowr, hir = xor_map[lowx * 16 + lowy + 1], xor_map[hix * 16 + hiy + 1];
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    51
		local r = hir * 16 + lowr;
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    52
		result[i] = char(r)
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    53
	end
2267
0a675bb365a9 util.sasl.scram: Optimized binaryXOR.
Waqas Hussain <waqas20@gmail.com>
parents: 2266
diff changeset
    54
	return t_concat(result);
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    55
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    56
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    57
-- hash algorithm independent Hi(PBKDF2) implementation
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    58
local function Hi(hmac, str, salt, i)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    59
	local Ust = hmac(str, salt.."\0\0\0\1");
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    60
	local res = Ust;	
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    61
	for n=1,i-1 do
2255
92e329e1cd99 Make some more variables to locals.
Tobias Markmann <tm@ayena.de>
parents: 2210
diff changeset
    62
		local Und = hmac(str, Ust)
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    63
		res = binaryXOR(res, Und)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    64
		Ust = Und
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    65
	end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    66
	return res
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    67
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    68
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    69
local function validate_username(username)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    70
	-- check for forbidden char sequences
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    71
	for eq in username:gmatch("=(.?.?)") do
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    72
		if eq ~= "2D" and eq ~= "3D" then
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    73
			return false 
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    74
		end 
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    75
	end
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    76
	
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    77
	-- replace =2D with , and =3D with =
2265
7fe644057dc2 util.sasl.scram: Making =2D and =3D substitution actually work.
Tobias Markmann <tm@ayena.de>
parents: 2255
diff changeset
    78
	username = username:gsub("=2D", ",");
7fe644057dc2 util.sasl.scram: Making =2D and =3D substitution actually work.
Tobias Markmann <tm@ayena.de>
parents: 2255
diff changeset
    79
	username = username:gsub("=3D", "=");
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    80
	
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    81
	-- apply SASLprep
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
    82
	username = saslprep(username);
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    83
	return username;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    84
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    85
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    86
local function scram_sha_1(self, message)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    87
	if not self.state then self["state"] = {} end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    88
	
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    89
	if not self.state.name then
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    90
		-- we are processing client_first_message
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    91
		local client_first_message = message;
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
    92
		self.state["client_first_message"] = client_first_message;
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    93
		self.state["name"] = client_first_message:match("n=(.+),r=")
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    94
		self.state["clientnonce"] = client_first_message:match("r=([^,]+)")
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
    95
		
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    96
		if not self.state.name or not self.state.clientnonce then
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    97
			return "failure", "malformed-request";
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
    98
		end
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
    99
		
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   100
		self.state.name = validate_username(self.state.name);
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   101
		if not self.state.name then
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   102
			log("debug", "Username violates either SASLprep or contains forbidden character sequences.")
2210
78c9b5255b27 Adding some human readable error messages.
Tobias Markmann <tm@ayena.de>
parents: 2206
diff changeset
   103
			return "failure", "malformed-request", "Invalid username.";
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   104
		end
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   105
		
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   106
		self.state["servernonce"] = generate_uuid();
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   107
		self.state["salt"] = generate_uuid();
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   108
		
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   109
		local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..default_i;
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
   110
		self.state["server_first_message"] = server_first_message;
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   111
		return "challenge", server_first_message
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   112
	else
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
   113
		if type(message) ~= "string" then return "failure", "malformed-request" end
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   114
		-- we are processing client_final_message
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   115
		local client_final_message = message;
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   116
		
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   117
		self.state["proof"] = client_final_message:match("p=(.+)");
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   118
		self.state["nonce"] = client_final_message:match("r=(.+),p=");
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   119
		self.state["channelbinding"] = client_final_message:match("c=(.+),r=");
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   120
		if not self.state.proof or not self.state.nonce or not self.state.channelbinding then
2210
78c9b5255b27 Adding some human readable error messages.
Tobias Markmann <tm@ayena.de>
parents: 2206
diff changeset
   121
			return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message.";
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   122
		end
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   123
		
2266
6e662e4f7ab2 util.sasl.scram: Fixed a variable redeclaration.
Waqas Hussain <waqas20@gmail.com>
parents: 2265
diff changeset
   124
		local password, state;
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   125
		if self.profile.plain then
2266
6e662e4f7ab2 util.sasl.scram: Fixed a variable redeclaration.
Waqas Hussain <waqas20@gmail.com>
parents: 2265
diff changeset
   126
			password, state = self.profile.plain(self.state.name, self.realm)
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   127
			if state == nil then return "failure", "not-authorized"
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   128
			elseif state == false then return "failure", "account-disabled" end
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   129
			password = saslprep(password);
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   130
			if not password then
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   131
				log("debug", "Password violates SASLprep.");
2210
78c9b5255b27 Adding some human readable error messages.
Tobias Markmann <tm@ayena.de>
parents: 2206
diff changeset
   132
				return "failure", "not-authorized", "Invalid password."
2199
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2198
diff changeset
   133
			end
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   134
		end
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   135
		
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   136
		local SaltedPassword = Hi(hmac_sha1, password, self.state.salt, default_i)
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   137
		local ClientKey = hmac_sha1(SaltedPassword, "Client Key")
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   138
		local ServerKey = hmac_sha1(SaltedPassword, "Server Key")
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   139
		local StoredKey = sha1(ClientKey)
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
   140
		local AuthMessage = "n=" .. s_match(self.state.client_first_message,"n=(.+)") .. "," .. self.state.server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+")
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   141
		local ClientSignature = hmac_sha1(StoredKey, AuthMessage)
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   142
		local ClientProof     = binaryXOR(ClientKey, ClientSignature)
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   143
		local ServerSignature = hmac_sha1(ServerKey, AuthMessage)
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   144
		
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   145
		if base64.encode(ClientProof) == self.state.proof then
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   146
			local server_final_message = "v="..base64.encode(ServerSignature);
2198
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2197
diff changeset
   147
			self["username"] = self.state.name;
2196
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   148
			return "success", server_final_message;
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   149
		else
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   150
			return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated.";
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
   151
		end
2194
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   152
	end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   153
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   154
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   155
function init(registerMechanism)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   156
	registerMechanism("SCRAM-SHA-1", {"plain"}, scram_sha_1);
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   157
end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   158
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
   159
return _M;