util/sasl/scram.lua

Sat, 22 May 2010 13:58:15 +0200

author
Tobias Markmann <tm@ayena.de>
date
Sat, 22 May 2010 13:58:15 +0200
changeset 3075
39a86b0d108b
parent 3074
7bd0dae5c84f
child 3076
d19b2db64496
permissions
-rw-r--r--

util.sasl.scram: Parsing client-first-message in a more strict way. (thanks Marc Santamaria)

2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
1 -- sasl.lua v0.4
2996
b0515ed4d9d7 util.sasl: 2009 -> 2010 in copyright header.
Tobias Markmann <tm@ayena.de>
parents: 2995
diff changeset
2 -- Copyright (C) 2008-2010 Tobias Markmann
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
3 --
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
4 -- All rights reserved.
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
5 --
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
6 -- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
7 --
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
8 -- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
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.
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
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.
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
11 --
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
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.
2190
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;
2194
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
15 local type = type
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
16 local string = string
2190
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 hmac_sha1 = require "util.hmac".sha1;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
19 local sha1 = require "util.hashes".sha1;
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
20 local generate_uuid = require "util.uuid".generate;
2195
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
21 local saslprep = require "util.encodings".stringprep.saslprep;
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
22 local log = require "util.logger".init("sasl");
2314
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
23 local t_concat = table.concat;
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
24 local char = string.char;
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
25 local byte = string.byte;
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
26
2202
Tobias Markmann <tm@ayena.de>
parents: 2201
diff changeset
27 module "scram"
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
28
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 --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10
2993
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
31
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
32 --[[
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
33 Supported Authentication Backends
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
34
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
35 scram-{MECH}:
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
36 function(username, realm)
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
37 return salted_password, iteration_count, salt, state;
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
38 end
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
39 ]]
06d06fdd190b util.sasl.scram: Adding documentation on SCRAM authentication backend.
Tobias Markmann <tm@ayena.de>
parents: 2990
diff changeset
40
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
41 local default_i = 4096
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
42
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
43 local function bp( b )
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
44 local result = ""
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
45 for i=1, b:len() do
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
46 result = result.."\\"..b:byte(i)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
47 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
48 return result
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
49 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
50
2314
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
51 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;};
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
52
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
53 local result = {};
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
54 local function binaryXOR( a, b )
2314
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
55 for i=1, #a do
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
56 local x, y = byte(a, i), byte(b, i);
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
57 local lowx, lowy = x % 16, y % 16;
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
58 local hix, hiy = (x - lowx) / 16, (y - lowy) / 16;
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
59 local lowr, hir = xor_map[lowx * 16 + lowy + 1], xor_map[hix * 16 + hiy + 1];
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
60 local r = hir * 16 + lowr;
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
61 result[i] = char(r)
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
62 end
2314
c2e1bde4d84d Redo merge with Waqas' PBKDF2 optimizations.
Tobias Markmann <tm@ayena.de>
parents: 2288
diff changeset
63 return t_concat(result);
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
64 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
65
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
66 -- hash algorithm independent Hi(PBKDF2) implementation
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
67 local function Hi(hmac, str, salt, i)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
68 local Ust = hmac(str, salt.."\0\0\0\1");
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
69 local res = Ust;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
70 for n=1,i-1 do
2255
92e329e1cd99 Make some more variables to locals.
Tobias Markmann <tm@ayena.de>
parents: 2206
diff changeset
71 local Und = hmac(str, Ust)
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
72 res = binaryXOR(res, Und)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
73 Ust = Und
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
74 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
75 return res
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
76 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
77
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
78 local function validate_username(username)
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
79 -- check for forbidden char sequences
2194
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
80 for eq in username:gmatch("=(.?.?)") do
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
81 if eq ~= "2D" and eq ~= "3D" then
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
82 return false
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
83 end
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
84 end
d18b4d22b8da Making interop with libpurple. (Thanks darkrain).
Tobias Markmann <tm@ayena.de>
parents: 2193
diff changeset
85
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
86 -- 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
87 username = username:gsub("=2D", ",");
7fe644057dc2 util.sasl.scram: Making =2D and =3D substitution actually work.
Tobias Markmann <tm@ayena.de>
parents: 2255
diff changeset
88 username = username:gsub("=3D", "=");
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
89
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
90 -- apply SASLprep
2195
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
91 username = saslprep(username);
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
92 return username;
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
93 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
94
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
95 local function scram_gen(hash_name, H_f, HMAC_f)
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
96 local function scram_hash(self, message)
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
97 if not self.state then self["state"] = {} end
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
98
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
99 if not self.state.name then
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
100 -- we are processing client_first_message
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
101 local client_first_message = message;
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
102
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
103 -- TODO: fail if authzid is provided, since we don't support them yet
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
104 self.state["client_first_message"] = client_first_message;
3075
39a86b0d108b util.sasl.scram: Parsing client-first-message in a more strict way. (thanks Marc Santamaria)
Tobias Markmann <tm@ayena.de>
parents: 3074
diff changeset
105 self.state["gs2_cbind_flag"], self.state["authzid"], self.state["name"], self.state["clientnonce"] = client_first_message:match("^(%a),(.*),n=(.*),r=([^,]*).*");
39a86b0d108b util.sasl.scram: Parsing client-first-message in a more strict way. (thanks Marc Santamaria)
Tobias Markmann <tm@ayena.de>
parents: 3074
diff changeset
106
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
107 -- we don't do any channel binding yet
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
108 if self.state.gs2_cbind_flag ~= "n" and self.state.gs2_cbind_flag ~= "y" then
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
109 return "failure", "malformed-request";
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
110 end
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
111
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
112 if not self.state.name or not self.state.clientnonce then
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
113 return "failure", "malformed-request", "Channel binding isn't support at this time.";
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
114 end
2195
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
115
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
116 self.state.name = validate_username(self.state.name);
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
117 if not self.state.name then
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
118 log("debug", "Username violates either SASLprep or contains forbidden character sequences.")
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
119 return "failure", "malformed-request", "Invalid username.";
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
120 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
121
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
122 self.state["servernonce"] = generate_uuid();
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
123
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
124 -- retreive credentials
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
125 if self.profile.plain then
3016
b6046df19898 util.sasl.scram: Fixed global access.
Waqas Hussain <waqas20@gmail.com>
parents: 2996
diff changeset
126 local password, state = self.profile.plain(self.state.name, self.realm)
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
127 if state == nil then return "failure", "not-authorized"
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
128 elseif state == false then return "failure", "account-disabled" end
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
129
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
130 password = saslprep(password);
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
131 if not password then
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
132 log("debug", "Password violates SASLprep.");
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
133 return "failure", "not-authorized", "Invalid password."
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
134 end
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
135 self.state.salt = generate_uuid();
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
136 self.state.iteration_count = default_i;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
137 self.state.salted_password = Hi(HMAC_f, password, self.state.salt, default_i);
2995
175002d404b8 util.sasl.scram: Adjusting authentication backend name to conform with the style already used by the plain module.
Tobias Markmann <tm@ayena.de>
parents: 2993
diff changeset
138 elseif self.profile["scram_"..hash_name] then
3016
b6046df19898 util.sasl.scram: Fixed global access.
Waqas Hussain <waqas20@gmail.com>
parents: 2996
diff changeset
139 local salted_password, iteration_count, salt, state = self.profile["scram-"..hash_name](self.state.name, self.realm);
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
140 if state == nil then return "failure", "not-authorized"
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
141 elseif state == false then return "failure", "account-disabled" end
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
142
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
143 self.state.salted_password = salted_password;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
144 self.state.iteration_count = iteration_count;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
145 self.state.salt = salt
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
146 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
147
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
148 local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..self.state.iteration_count;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
149 self.state["server_first_message"] = server_first_message;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
150 return "challenge", server_first_message
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
151 else
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
152 if type(message) ~= "string" then return "failure", "malformed-request" end
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
153 -- we are processing client_final_message
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
154 local client_final_message = message;
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
155
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
156 -- TODO: more strict parsing of client_final_message
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
157 self.state["proof"] = client_final_message:match("p=(.+)");
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
158 self.state["nonce"] = client_final_message:match("r=(.+),p=");
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
159 self.state["channelbinding"] = client_final_message:match("c=(.+),r=");
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
160
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
161 if not self.state.proof or not self.state.nonce or not self.state.channelbinding then
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
162 return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message.";
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
163 end
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
164
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
165 if self.state.nonce ~= self.state.servernonce then
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
166 return "failure", "malformed-request", "Wrong nonce in client-second-message.";
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
167 end
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
168
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
169 local SaltedPassword = self.state.salted_password;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
170 local ClientKey = HMAC_f(SaltedPassword, "Client Key")
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
171 local ServerKey = HMAC_f(SaltedPassword, "Server Key")
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
172 local StoredKey = H_f(ClientKey)
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
173 local AuthMessage = "n=" .. s_match(self.state.client_first_message,"n=(.+)") .. "," .. self.state.server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+")
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
174 local ClientSignature = HMAC_f(StoredKey, AuthMessage)
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
175 local ClientProof = binaryXOR(ClientKey, ClientSignature)
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
176 local ServerSignature = HMAC_f(ServerKey, AuthMessage)
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
177
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
178 if base64.encode(ClientProof) == self.state.proof then
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
179 local server_final_message = "v="..base64.encode(ServerSignature);
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
180 self["username"] = self.state.name;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
181 return "success", server_final_message;
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
182 else
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
183 return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated.";
2195
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
184 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
185 end
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
186 end
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
187 return scram_hash;
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
188 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
189
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
190 function init(registerMechanism)
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
191 local function registerSCRAMMechanism(hash_name, hash, hmac_hash)
2995
175002d404b8 util.sasl.scram: Adjusting authentication backend name to conform with the style already used by the plain module.
Tobias Markmann <tm@ayena.de>
parents: 2993
diff changeset
192 registerMechanism("SCRAM-"..hash_name, {"plain", "scram_"..(hash_name:lower())}, scram_gen(hash_name:lower(), hash, hmac_hash));
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
193 end
3074
7bd0dae5c84f 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)
Tobias Markmann <tm@ayena.de>
parents: 3016
diff changeset
194
2990
21933063dd9f util.sasl: Abstracting out the hash function used since SCRAM is independent of it. Adding scram-{mech} authentication backend support.
Tobias Markmann <tm@ayena.de>
parents: 2648
diff changeset
195 registerSCRAMMechanism("SHA-1", sha1, hmac_sha1);
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
196 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
197
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
198 return _M;

mercurial