util/sasl/scram.lua

Sat, 22 May 2010 14:58:24 +0200

author
Tobias Markmann <tm@ayena.de>
date
Sat, 22 May 2010 14:58:24 +0200
changeset 3078
22c22f8a6eb8
parent 3077
3ee311f21d54
child 3079
e144a4989e70
permissions
-rw-r--r--

util.sasl.scram: Split up long line.

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;
3078
22c22f8a6eb8 util.sasl.scram: Split up long line.
Tobias Markmann <tm@ayena.de>
parents: 3077
diff changeset
105 self.state["gs2_cbind_flag"], self.state["authzid"], self.state["name"], self.state["clientnonce"]
22c22f8a6eb8 util.sasl.scram: Split up long line.
Tobias Markmann <tm@ayena.de>
parents: 3077
diff changeset
106 = client_first_message:match("^(%a),(.*),n=(.*),r=([^,]*).*");
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
107
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
108 -- 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
109 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
110 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
111 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
112
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
113 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
114 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
115 end
2195
08a6b91bfe7b SASLprep usernames and passwords.
Tobias Markmann <tm@ayena.de>
parents: 2194
diff changeset
116
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
117 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
118 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
119 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
120 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
121 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
122
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
123 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
124
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 -- 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
126 if self.profile.plain then
3016
b6046df19898 util.sasl.scram: Fixed global access.
Waqas Hussain <waqas20@gmail.com>
parents: 2996
diff changeset
127 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
128 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
129 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
130
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 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
132 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
133 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
134 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
135 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
136 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
137 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
138 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
139 elseif self.profile["scram_"..hash_name] then
3016
b6046df19898 util.sasl.scram: Fixed global access.
Waqas Hussain <waqas20@gmail.com>
parents: 2996
diff changeset
140 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
141 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
142 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
143
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.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
145 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
146 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
147 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
148
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
149 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
150 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
151 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
152 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
153 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
154 -- 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
155 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
156
3077
3ee311f21d54 util.sasl.scram: Parsing client-final-message in a more strict way. (thanks Marc Santamaria)
Tobias Markmann <tm@ayena.de>
parents: 3076
diff changeset
157 self.state["channelbinding"], self.state["nonce"], self.state["proof"] = client_final_message:match("^c=(.*),r=(.*),.*p=(.*)");
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
158
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
159 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
160 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
161 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
162
3076
d19b2db64496 util.sasl.scram: Fix in nonce check of client-final-message.
Tobias Markmann <tm@ayena.de>
parents: 3075
diff changeset
163 if self.state.nonce ~= self.state.clientnonce..self.state.servernonce then
d19b2db64496 util.sasl.scram: Fix in nonce check of client-final-message.
Tobias Markmann <tm@ayena.de>
parents: 3075
diff changeset
164 return "failure", "malformed-request", "Wrong nonce in client-final-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
165 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
166
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
167 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
168 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
169 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
170 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
171 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
172 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
173 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
174 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
175
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
176 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
177 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
178 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
179 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
180 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
181 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
182 end
2192
614c839c30c5 Completed SCRAM-SHA-1 implementation to a ready-to-test state.
Tobias Markmann <tm@ayena.de>
parents: 2190
diff changeset
183 end
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
184 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
185 return scram_hash;
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
186 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
187
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
188 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
189 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
190 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
191 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
192
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 registerSCRAMMechanism("SHA-1", sha1, hmac_sha1);
2190
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
194 end
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
195
41d42d253a1d Initial commit of SCRAM SASL mechanism.
Tobias Markmann <tm@ayena.de>
parents:
diff changeset
196 return _M;

mercurial