util/sasl/scram.lua

changeset 2195
08a6b91bfe7b
parent 2194
d18b4d22b8da
child 2201
e091b308732f
equal deleted inserted replaced
2194:d18b4d22b8da 2195:08a6b91bfe7b
17 local base64 = require "util.encodings".base64; 17 local base64 = require "util.encodings".base64;
18 local xor = require "bit".bxor 18 local xor = require "bit".bxor
19 local hmac_sha1 = require "util.hmac".sha1; 19 local hmac_sha1 = require "util.hmac".sha1;
20 local sha1 = require "util.hashes".sha1; 20 local sha1 = require "util.hashes".sha1;
21 local generate_uuid = require "util.uuid".generate; 21 local generate_uuid = require "util.uuid".generate;
22 local saslprep = require "util.encodings".stringprep.saslprep;
23 local log = require "util.logger".init("sasl");
22 24
23 module "plain" 25 module "plain"
24 26
25 --========================= 27 --=========================
26 --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10 28 --SASL SCRAM-SHA-1 according to draft-ietf-sasl-scram-10
68 end 70 end
69 71
70 -- replace =2D with , and =3D with = 72 -- replace =2D with , and =3D with =
71 73
72 -- apply SASLprep 74 -- apply SASLprep
75 username = saslprep(username);
73 return username; 76 return username;
74 end 77 end
75 78
76 local function scram_sha_1(self, message) 79 local function scram_sha_1(self, message)
77 if not self.state then self["state"] = {} end 80 if not self.state then self["state"] = {} end
81 local client_first_message = message; 84 local client_first_message = message;
82 self.state["client_first_message"] = client_first_message; 85 self.state["client_first_message"] = client_first_message;
83 self.state["name"] = client_first_message:match("n=(.+),r=") 86 self.state["name"] = client_first_message:match("n=(.+),r=")
84 self.state["clientnonce"] = client_first_message:match("r=([^,]+)") 87 self.state["clientnonce"] = client_first_message:match("r=([^,]+)")
85 88
86 self.state.name = validate_username(self.state.name);
87 if not self.state.name or not self.state.clientnonce then 89 if not self.state.name or not self.state.clientnonce then
88 return "failure", "malformed-request"; 90 return "failure", "malformed-request";
89 end 91 end
92
93 self.state.name = validate_username(self.state.name);
94 if not self.state.name then
95 log("debug", "Username violates either SASLprep or contains forbidden character sequences.")
96 return "failure", "malformed-request";
97 end
98
90 self.state["servernonce"] = generate_uuid(); 99 self.state["servernonce"] = generate_uuid();
91 self.state["salt"] = generate_uuid(); 100 self.state["salt"] = generate_uuid();
92 101
93 local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..default_i; 102 local server_first_message = "r="..self.state.clientnonce..self.state.servernonce..",s="..base64.encode(self.state.salt)..",i="..default_i;
94 self.state["server_first_message"] = server_first_message; 103 self.state["server_first_message"] = server_first_message;
108 local password; 117 local password;
109 if self.profile.plain then 118 if self.profile.plain then
110 password, state = self.profile.plain(self.state.name, self.realm) 119 password, state = self.profile.plain(self.state.name, self.realm)
111 if state == nil then return "failure", "not-authorized" 120 if state == nil then return "failure", "not-authorized"
112 elseif state == false then return "failure", "account-disabled" end 121 elseif state == false then return "failure", "account-disabled" end
122 password = saslprep(password);
123 if not password then
124 log("debug", "Password violates SASLprep.");
125 return "failure", "not-authorized"
126 end
113 end 127 end
114 128
115 local SaltedPassword = Hi(hmac_sha1, password, self.state.salt, default_i) 129 local SaltedPassword = Hi(hmac_sha1, password, self.state.salt, default_i)
116 local ClientKey = hmac_sha1(SaltedPassword, "Client Key") 130 local ClientKey = hmac_sha1(SaltedPassword, "Client Key")
117 local ServerKey = hmac_sha1(SaltedPassword, "Server Key") 131 local ServerKey = hmac_sha1(SaltedPassword, "Server Key")

mercurial