util/sasl/scram.lua

changeset 362
d8c3e94d765d
parent 359
a7aa761a436d
child 363
056ccefa6acf
equal deleted inserted replaced
361:451dbad2a8e6 362:d8c3e94d765d
41 end 41 end
42 42
43 local function scram(stream, name) 43 local function scram(stream, name)
44 local username = "n=" .. value_safe(stream.username); 44 local username = "n=" .. value_safe(stream.username);
45 local c_nonce = base64(crypto.rand.bytes(15)); 45 local c_nonce = base64(crypto.rand.bytes(15));
46 local nonce = "r=" .. c_nonce; 46 local our_nonce = "r=" .. c_nonce;
47 local client_first_message_bare = username .. "," .. nonce; 47 local client_first_message_bare = username .. "," .. our_nonce;
48 local cbind_data = ""; 48 local cbind_data = "";
49 local gs2_cbind_flag = "y"; 49 local gs2_cbind_flag = "y";
50 if name == "SCRAM-SHA-1-PLUS" then 50 if name == "SCRAM-SHA-1-PLUS" then
51 cbind_data = stream.conn:socket():getfinished(); 51 cbind_data = stream.conn:socket():getfinished();
52 gs2_cbind_flag = "p=tls-unique"; 52 gs2_cbind_flag = "p=tls-unique";
54 local gs2_header = gs2_cbind_flag .. ",,"; 54 local gs2_header = gs2_cbind_flag .. ",,";
55 local client_first_message = gs2_header .. client_first_message_bare; 55 local client_first_message = gs2_header .. client_first_message_bare;
56 local cont, server_first_message = coroutine.yield(client_first_message); 56 local cont, server_first_message = coroutine.yield(client_first_message);
57 if cont ~= "challenge" then return false end 57 if cont ~= "challenge" then return false end
58 58
59 local salt, iteration_count; 59 local nonce, salt, iteration_count = server_first_message:match("(r=[^,]+),s=([^,]*),i=(%d+)");
60 nonce, salt, iteration_count = server_first_message:match("(r=[^,]+),s=([^,]*),i=(%d+)");
61 local i = tonumber(iteration_count); 60 local i = tonumber(iteration_count);
62 salt = unbase64(salt); 61 salt = unbase64(salt);
63 if not nonce or not salt or not i then 62 if not nonce or not salt or not i then
64 return false, "Could not parse server_first_message"; 63 return false, "Could not parse server_first_message";
65 elseif nonce:find(c_nonce, 3, true) ~= 3 then 64 elseif nonce:find(c_nonce, 3, true) ~= 3 then
66 return false, "nonce sent by server does not match our nonce"; 65 return false, "nonce sent by server does not match our nonce";
67 elseif nonce == c_nonce then 66 elseif nonce == our_nonce then
68 return false, "server did not append s-nonce to nonce"; 67 return false, "server did not append s-nonce to nonce";
69 end 68 end
70 69
71 local cbind_input = gs2_header .. cbind_data; 70 local cbind_input = gs2_header .. cbind_data;
72 local channel_binding = "c=" .. base64(cbind_input); 71 local channel_binding = "c=" .. base64(cbind_input);

mercurial