33 |
33 |
34 local function value_safe(str) |
34 local function value_safe(str) |
35 return (gsub(str, "[,=]", { [","] = "=2C", ["="] = "=3D" })); |
35 return (gsub(str, "[,=]", { [","] = "=2C", ["="] = "=3D" })); |
36 end |
36 end |
37 |
37 |
|
38 local function cb(conn) |
|
39 if conn:ssl() then |
|
40 if sock.getfinished then |
|
41 return "p=tls-unique", sock:getfinished(); |
|
42 end |
|
43 end |
|
44 end |
|
45 |
38 local function scram(stream, name) |
46 local function scram(stream, name) |
39 local username = "n=" .. value_safe(stream.username); |
47 local username = "n=" .. value_safe(stream.username); |
40 local c_nonce = base64(random.bytes(15)); |
48 local c_nonce = base64(random.bytes(15)); |
41 local our_nonce = "r=" .. c_nonce; |
49 local our_nonce = "r=" .. c_nonce; |
42 local client_first_message_bare = username .. "," .. our_nonce; |
50 local client_first_message_bare = username .. "," .. our_nonce; |
43 local cbind_data = ""; |
51 local cbind_data = ""; |
44 local gs2_cbind_flag = stream.conn:ssl() and "y" or "n"; |
52 local gs2_cbind_flag = "n"; |
45 if name == "SCRAM-SHA-1-PLUS" then |
53 if name == "SCRAM-SHA-1-PLUS" then |
46 cbind_data = stream.conn:socket():getfinished(); |
54 gs2_cbind_flag, cbind_data = cb(stream.conn); |
47 gs2_cbind_flag = "p=tls-unique"; |
55 elseif cb(stream.conn) then |
|
56 gs2_cbind_flag = "y"; |
48 end |
57 end |
49 local gs2_header = gs2_cbind_flag .. ",,"; |
58 local gs2_header = gs2_cbind_flag .. ",,"; |
50 local client_first_message = gs2_header .. client_first_message_bare; |
59 local client_first_message = gs2_header .. client_first_message_bare; |
51 local cont, server_first_message = coroutine.yield(client_first_message); |
60 local cont, server_first_message = coroutine.yield(client_first_message); |
52 if cont ~= "challenge" then return false end |
61 if cont ~= "challenge" then return false end |
105 return function (stream, name) |
114 return function (stream, name) |
106 if stream.username and (stream.password or (stream.client_key or stream.server_key)) then |
115 if stream.username and (stream.password or (stream.client_key or stream.server_key)) then |
107 if name == "SCRAM-SHA-1" then |
116 if name == "SCRAM-SHA-1" then |
108 return scram, 99; |
117 return scram, 99; |
109 elseif name == "SCRAM-SHA-1-PLUS" then |
118 elseif name == "SCRAM-SHA-1-PLUS" then |
110 local sock = stream.conn:ssl() and stream.conn:socket(); |
119 if cb(stream.conn) then |
111 if sock and sock.getfinished then |
|
112 return scram, 100; |
120 return scram, 100; |
113 end |
121 end |
114 end |
122 end |
115 end |
123 end |
116 end |
124 end |