30 if password_encoding == nil then claimed_password = password |
30 if password_encoding == nil then claimed_password = password |
31 else claimed_password = password_encoding(password) end |
31 else claimed_password = password_encoding(password) end |
32 |
32 |
33 self.username = authentication |
33 self.username = authentication |
34 if claimed_password == correct_password then |
34 if claimed_password == correct_password then |
35 log("debug", "success") |
|
36 return "success" |
35 return "success" |
37 else |
36 else |
38 log("debug", "failure") |
|
39 return "failure", "not-authorized" |
37 return "failure", "not-authorized" |
40 end |
38 end |
41 end |
39 end |
42 return object |
40 return object |
43 end |
41 end |
61 return data |
59 return data |
62 end |
60 end |
63 |
61 |
64 local function parse(data) |
62 local function parse(data) |
65 message = {} |
63 message = {} |
66 log("debug", "parse-message: "..data) |
|
67 for k, v in gmatch(data, [[([%w%-]+)="?([%w%-%/%.%+=]+)"?,?]]) do |
64 for k, v in gmatch(data, [[([%w%-]+)="?([%w%-%/%.%+=]+)"?,?]]) do |
68 message[k] = v |
65 message[k] = v |
69 log("debug", " "..k.." = "..v) |
|
70 end |
66 end |
71 return message |
67 return message |
72 end |
68 end |
73 |
69 |
74 local object = { mechanism = "DIGEST-MD5", realm = realm, password_handler = password_handler} |
70 local object = { mechanism = "DIGEST-MD5", realm = realm, password_handler = password_handler} |
77 object.nonce = generate_uuid() |
73 object.nonce = generate_uuid() |
78 object.step = 0 |
74 object.step = 0 |
79 object.nonce_count = {} |
75 object.nonce_count = {} |
80 |
76 |
81 function object.feed(self, message) |
77 function object.feed(self, message) |
82 log("debug", "SASL step: "..self.step) |
|
83 self.step = self.step + 1 |
78 self.step = self.step + 1 |
84 if (self.step == 1) then |
79 if (self.step == 1) then |
85 local challenge = serialize({ nonce = object.nonce, |
80 local challenge = serialize({ nonce = object.nonce, |
86 qop = "auth", |
81 qop = "auth", |
87 charset = "utf-8", |
82 charset = "utf-8", |
88 algorithm = "md5-sess", |
83 algorithm = "md5-sess", |
89 realm = self.realm}); |
84 realm = self.realm}); |
90 log("debug", "challenge: "..challenge) |
|
91 return "challenge", challenge |
85 return "challenge", challenge |
92 elseif (self.step == 2) then |
86 elseif (self.step == 2) then |
93 local response = parse(message) |
87 local response = parse(message) |
94 -- check for replay attack |
88 -- check for replay attack |
95 if response["nc"] then |
89 if response["nc"] then |
133 local HA2 = md5.sumhexa(A2) |
127 local HA2 = md5.sumhexa(A2) |
134 |
128 |
135 local KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2 |
129 local KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2 |
136 local response_value = md5.sumhexa(KD) |
130 local response_value = md5.sumhexa(KD) |
137 |
131 |
138 log("debug", "response_value: "..response_value); |
|
139 log("debug", "response: "..response["response"]); |
|
140 if response_value == response["response"] then |
132 if response_value == response["response"] then |
141 -- calculate rspauth |
133 -- calculate rspauth |
142 A2 = ":"..protocol.."/"..domain |
134 A2 = ":"..protocol.."/"..domain |
143 |
135 |
144 HA1 = md5.sumhexa(A1) |
136 HA1 = md5.sumhexa(A1) |