Software / code / prosody
Comparison
util/sasl/scram.lua @ 2199:08a6b91bfe7b
SASLprep usernames and passwords.
| author | Tobias Markmann <tm@ayena.de> |
|---|---|
| date | Wed, 18 Nov 2009 11:59:50 +0100 |
| parent | 2198:d18b4d22b8da |
| child | 2205:e091b308732f |
comparison
equal
deleted
inserted
replaced
| 2198:d18b4d22b8da | 2199: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") |