110 if not state then |
110 if not state then |
111 -- we are processing client_first_message |
111 -- we are processing client_first_message |
112 local client_first_message = message; |
112 local client_first_message = message; |
113 |
113 |
114 -- TODO: fail if authzid is provided, since we don't support them yet |
114 -- TODO: fail if authzid is provided, since we don't support them yet |
115 local gs2_header, gs2_cbind_flag, gs2_cbind_name, authzid, name, clientnonce |
115 local gs2_header, gs2_cbind_flag, gs2_cbind_name, authzid, client_first_message_bare, name, clientnonce |
116 = client_first_message:match("^(([ynp])=?([%a%-]*),(.*),)n=(.*),r=([^,]*).*"); |
116 = s_match(client_first_message, "^(([pny])=?([^,]*),([^,]*),)(m?=?[^,]*,?n=([^,]*),r=([^,]*),?.*)$"); |
117 |
117 |
118 if not gs2_cbind_flag then |
118 if not gs2_cbind_flag then |
119 return "failure", "malformed-request"; |
119 return "failure", "malformed-request"; |
120 end |
120 end |
121 |
121 |
183 name = name; |
183 name = name; |
184 nonce = nonce; |
184 nonce = nonce; |
185 |
185 |
186 server_key = server_key; |
186 server_key = server_key; |
187 stored_key = stored_key; |
187 stored_key = stored_key; |
188 client_first_message = client_first_message; |
188 client_first_message_bare = client_first_message_bare; |
189 server_first_message = server_first_message; |
189 server_first_message = server_first_message; |
190 } |
190 } |
191 return "challenge", server_first_message |
191 return "challenge", server_first_message |
192 else |
192 else |
193 -- we are processing client_final_message |
193 -- we are processing client_final_message |
194 local client_final_message = message; |
194 local client_final_message = message; |
195 |
195 |
196 local channelbinding, nonce, proof = client_final_message:match("^c=(.*),r=(.*),.*p=(.*)"); |
196 local client_final_message_without_proof, channelbinding, nonce, proof |
|
197 = s_match(client_final_message, "(c=([^,]*),r=([^,]*),?.-),p=(.*)$"); |
197 |
198 |
198 if not proof or not nonce or not channelbinding then |
199 if not proof or not nonce or not channelbinding then |
199 return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; |
200 return "failure", "malformed-request", "Missing an attribute(p, r or c) in SASL message."; |
200 end |
201 end |
201 |
202 |
214 end |
215 end |
215 |
216 |
216 local ServerKey = state.server_key; |
217 local ServerKey = state.server_key; |
217 local StoredKey = state.stored_key; |
218 local StoredKey = state.stored_key; |
218 |
219 |
219 local AuthMessage = "n=" .. s_match(state.client_first_message,"n=(.+)") .. "," .. state.server_first_message .. "," .. s_match(client_final_message, "(.+),p=.+") |
220 local AuthMessage = state.client_first_message_bare .. "," .. state.server_first_message .. "," .. client_final_message_without_proof |
220 local ClientSignature = HMAC_f(StoredKey, AuthMessage) |
221 local ClientSignature = HMAC_f(StoredKey, AuthMessage) |
221 local ClientKey = binaryXOR(ClientSignature, base64.decode(proof)) |
222 local ClientKey = binaryXOR(ClientSignature, base64.decode(proof)) |
222 local ServerSignature = HMAC_f(ServerKey, AuthMessage) |
223 local ServerSignature = HMAC_f(ServerKey, AuthMessage) |
223 |
224 |
224 if StoredKey == H_f(ClientKey) then |
225 if StoredKey == H_f(ClientKey) then |