- local function parse(data)
- message = {}
- for k, v in gmatch(data, [[([%w%-]+)="?([^",]*)"?,?]]) do -- FIXME The hacky regex makes me shudder
- message[k] = v;
- end
- return message;
- end
-
- local object = { mechanism = "DIGEST-MD5", realm = realm, credentials_handler = credentials_handler};
-
- object.nonce = generate_uuid();
- object.step = 0;
- object.nonce_count = {};
-
- function object.feed(self, message)
- self.step = self.step + 1;
- if (self.step == 1) then
- local challenge = serialize({ nonce = object.nonce,
- qop = "auth",
- charset = "utf-8",
- algorithm = "md5-sess",
- realm = self.realm});
- return "challenge", challenge;
- elseif (self.step == 2) then
- local response = parse(message);
- -- check for replay attack
- if response["nc"] then
- if self.nonce_count[response["nc"]] then return "failure", "not-authorized" end
- end
-
- -- check for username, it's REQUIRED by RFC 2831
- if not response["username"] then
- return "failure", "malformed-request";
- end
- self["username"] = response["username"];
-
- -- check for nonce, ...
- if not response["nonce"] then
- return "failure", "malformed-request";
- else
- -- check if it's the right nonce
- if response["nonce"] ~= tostring(self.nonce) then return "failure", "malformed-request" end
- end
-
- if not response["cnonce"] then return "failure", "malformed-request", "Missing entry for cnonce in SASL message." end
- if not response["qop"] then response["qop"] = "auth" end