You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mod_turncredentials.lua 2.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. -- XEP-0215 implementation for time-limited turn credentials
  2. -- Copyright (C) 2012-2014 Philipp Hancke
  3. -- This file is MIT/X11 licensed.
  4. --turncredentials_secret = "keepthissecret";
  5. --turncredentials = {
  6. -- { type = "stun", host = "8.8.8.8" },
  7. -- { type = "turn", host = "8.8.8.8", port = "3478" },
  8. -- { type = "turn", host = "8.8.8.8", port = "80", transport = "tcp" }
  9. --}
  10. -- for stun servers, host is required, port defaults to 3478
  11. -- for turn servers, host is required, port defaults to tcp,
  12. -- transport defaults to udp
  13. -- hosts can be a list of server names / ips for random
  14. -- choice loadbalancing
  15. local st = require "util.stanza";
  16. local hmac_sha1 = require "util.hashes".hmac_sha1;
  17. local base64 = require "util.encodings".base64;
  18. local os_time = os.time;
  19. local secret = module:get_option_string("turncredentials_secret");
  20. local ttl = module:get_option_number("turncredentials_ttl", 86400);
  21. local hosts = module:get_option("turncredentials") or {};
  22. if not (secret) then
  23. module:log("error", "turncredentials not configured");
  24. return;
  25. end
  26. module:add_feature("urn:xmpp:extdisco:1");
  27. function random(arr)
  28. local index = math.random(1, #arr);
  29. return arr[index];
  30. end
  31. module:hook_global("config-reloaded", function()
  32. module:log("debug", "config-reloaded")
  33. secret = module:get_option_string("turncredentials_secret");
  34. ttl = module:get_option_number("turncredentials_ttl", 86400);
  35. hosts = module:get_option("turncredentials") or {};
  36. end);
  37. module:hook("iq-get/host/urn:xmpp:extdisco:1:services", function(event)
  38. local origin, stanza = event.origin, event.stanza;
  39. if origin.type ~= "c2s" then
  40. return;
  41. end
  42. local now = os_time() + ttl;
  43. local userpart = tostring(now);
  44. local nonce = base64.encode(hmac_sha1(secret, tostring(userpart), false));
  45. local reply = st.reply(stanza):tag("services", {xmlns = "urn:xmpp:extdisco:1"})
  46. for idx, item in pairs(hosts) do
  47. if item.type == "stun" or item.type == "stuns" then
  48. -- stun items need host and port (defaults to 3478)
  49. reply:tag("service",
  50. { type = item.type, host = item.host, port = tostring(item.port) or "3478" }
  51. ):up();
  52. elseif item.type == "turn" or item.type == "turns" then
  53. local turn = {}
  54. -- turn items need host, port (defaults to 3478),
  55. -- transport (defaults to udp)
  56. -- username, password, ttl
  57. turn.type = item.type;
  58. turn.port = tostring(item.port);
  59. turn.transport = item.transport;
  60. turn.username = userpart;
  61. turn.password = nonce;
  62. turn.ttl = tostring(ttl);
  63. if item.hosts then
  64. turn.host = random(item.hosts)
  65. else
  66. turn.host = item.host
  67. end
  68. reply:tag("service", turn):up();
  69. end
  70. end
  71. origin.send(reply);
  72. return true;
  73. end);