diff options
Diffstat (limited to 'misc/freeswitch/scripts/common')
-rw-r--r-- | misc/freeswitch/scripts/common/array.lua | 13 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/call_forwarding.lua | 35 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/configuration_table.lua | 59 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/gateway.lua | 7 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/intruder.lua | 2 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/log.lua | 2 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/pager.lua | 75 | ||||
-rw-r--r-- | misc/freeswitch/scripts/common/perimeter.lua | 38 |
8 files changed, 204 insertions, 27 deletions
diff --git a/misc/freeswitch/scripts/common/array.lua b/misc/freeswitch/scripts/common/array.lua index b1b7a71..c3cabec 100644 --- a/misc/freeswitch/scripts/common/array.lua +++ b/misc/freeswitch/scripts/common/array.lua @@ -4,6 +4,8 @@ module(...,package.seeall) +MAX_JSON_DEPTH = 100; + function try(array, arguments) if type(arguments) ~= 'string' or type(array) ~= 'table' then return nil; @@ -79,12 +81,19 @@ function keys_to_s(array, separator, prefix, suffix) end -- convert to JSON -function to_json(array) +function to_json(array, max_depth) + max_depth = tonumber(max_depth) or MAX_JSON_DEPTH; + max_depth = max_depth - 1; + + if max_depth <= 0 then + return 'null'; + end + require 'common.str'; local buffer = '{'; for key, value in pairs(array) do if type(value) == 'table' then - buffer = buffer .. '"' .. key .. '":' .. to_json(value) .. ','; + buffer = buffer .. '"' .. key .. '":' .. to_json(value, max_depth) .. ','; else buffer = buffer .. '"' .. key .. '":' .. common.str.to_json(value) .. ','; end diff --git a/misc/freeswitch/scripts/common/call_forwarding.lua b/misc/freeswitch/scripts/common/call_forwarding.lua index 3429dc9..9556de3 100644 --- a/misc/freeswitch/scripts/common/call_forwarding.lua +++ b/misc/freeswitch/scripts/common/call_forwarding.lua @@ -17,6 +17,7 @@ function CallForwarding.new(self, arg, object) self.record = arg.record; self.domain = arg.domain; self.parent = arg.parent; + self.caller = arg.caller; return object; end @@ -70,12 +71,38 @@ function CallForwarding.list_by_owner(self, call_forwardable_id, call_forwardabl else local sources = common.str.strip_to_a(forwarding_entry.source, ',') for source_index=1, #sources do - for caller_id_index=1, #caller_ids do - if caller_ids[caller_id_index]:match(sources[source_index]) then - entry_match = true; - self.log:debug('CALL_FORWARDING - source match: ', sources[source_index], ' ~ ', caller_ids[caller_id_index] ); + local variable_name, pattern = common.str.partition(sources[source_index], '!=') + local invert = variable_name ~= nil; + if not variable_name then + variable_name, pattern = common.str.partition(sources[source_index], '=') + end + if variable_name and self.caller then + local search_string = tostring(common.array.try(self.caller, variable_name)); + local success, result = pcall(string.find, pattern, '^%d+-%d+$'); + + if success and result and tonumber(search_string) then + local min, max = common.str.partition(pattern, '-') + entry_match = tonumber(search_string) >= tonumber(min) and tonumber(search_string) <= tonumber(max); + else + local success, result = pcall(string.find, search_string, pattern); + entry_match = common.str.to_b(result); + end + if invert then + entry_match = not entry_match; + end + + if entry_match == false then break; end + self.log:debug('CALL_FORWARDING ', forwarding_entry.service, ' - element match: ', entry_match, ', variable: ', variable_name, ' = ', pattern, ' ~ ', search_string); + else + for caller_id_index=1, #caller_ids do + if caller_ids[caller_id_index]:match(sources[source_index]) then + entry_match = true; + self.log:debug('CALL_FORWARDING ', forwarding_entry.service, ' - source match: ', sources[source_index], ' ~ ', caller_ids[caller_id_index] ); + break; + end + end end end end diff --git a/misc/freeswitch/scripts/common/configuration_table.lua b/misc/freeswitch/scripts/common/configuration_table.lua index 85bc014..1b8d8b7 100644 --- a/misc/freeswitch/scripts/common/configuration_table.lua +++ b/misc/freeswitch/scripts/common/configuration_table.lua @@ -4,12 +4,43 @@ module(...,package.seeall) + +function cast(variable_type, value, default) + require 'common.str'; + + if variable_type == 'boolean' then + return common.str.to_b(value); + elseif variable_type == 'integer' then + if default and not tonumber(value) then + return default; + end + return common.str.to_i(value); + elseif variable_type == 'float' then + if default and not tonumber(value) then + return default; + end + return common.str.to_n(value); + elseif variable_type == 'string' then + if default and not value then + return default; + end + return common.str.to_s(value); + elseif variable_type == 'array' then + if default and not value then + return default; + end + return common.str.to_a(value, ','); + end +end + -- retrieve configuration from database -function get(database, entity, section) +function get(database, entity, section, defaults) if not database or not entity then return {}; end + defaults = defaults or {}; + require 'common.str' local sql_query = 'SELECT * FROM `gs_parameters` WHERE `entity` = "' .. entity .. '"'; @@ -17,7 +48,7 @@ function get(database, entity, section) sql_query = sql_query .. ' AND `section` = "' .. section .. '"'; end - local root = {} + local root = defaults[1] or {} local parameter_class = ''; database:query(sql_query, function(parameters) @@ -26,21 +57,27 @@ function get(database, entity, section) local p_name = common.str.strip(parameters.name); if not root[p_section] then - root[p_section] = {}; + root[p_section] = defaults[p_section] or {}; end - if p_class_type == 'boolean' then - root[p_section][p_name] = common.str.to_b(parameters.value); - elseif p_class_type == 'integer' then - root[p_section][p_name] = common.str.to_i(parameters.value); - else - root[p_section][p_name] = tostring(parameters.value); - end + root[p_section][p_name] = cast(p_class_type, parameters.value); end) if section then - return root[section]; + return root[section] or defaults[section]; end return root; end + + +function settings(database, table_name, key, value, defaults) + local sql_query = 'SELECT * FROM ' .. database:escape(table_name, '`') .. ' WHERE ' .. database:escape(key, '`') .. ' = ' .. database:escape(value, '"'); + + local settings_entries = defaults or {}; + database:query(sql_query, function(record) + settings_entries[record.name] = cast(record.class_type:lower(), record.value, settings_entries[record.name]); + end); + + return settings_entries; +end diff --git a/misc/freeswitch/scripts/common/gateway.lua b/misc/freeswitch/scripts/common/gateway.lua index ac38326..09e8c4b 100644 --- a/misc/freeswitch/scripts/common/gateway.lua +++ b/misc/freeswitch/scripts/common/gateway.lua @@ -34,6 +34,10 @@ end function Gateway.find_by_id(self, id) + if not tonumber(id) then + return nil; + end + local sql_query = 'SELECT `a`.*, `c`.`sip_host` AS `domain`, `c`.`contact` AS `contact_full`, `c`.`network_ip`, `c`.`network_port` \ FROM `gateways` `a` \ LEFT JOIN `gateway_settings` `b` ON `a`.`id` = `b`.`gateway_id` AND `b`.`name` = "inbound_username" \ @@ -57,6 +61,9 @@ function Gateway.find_by_id(self, id) if gateway then gateway.settings = self:config_table_get('gateway_settings', gateway.id); + if common.str.blank(gateway.domain) then + gateway.domain = gateway.settings.domain; + end end return gateway; diff --git a/misc/freeswitch/scripts/common/intruder.lua b/misc/freeswitch/scripts/common/intruder.lua index 7d12155..f5e7a41 100644 --- a/misc/freeswitch/scripts/common/intruder.lua +++ b/misc/freeswitch/scripts/common/intruder.lua @@ -35,7 +35,7 @@ function Intruder.update_blacklist(self, event) contacts_per_second_max = event.contacts_per_second_max, user_agent = event.user_agent, to_user = event.to_user, - comment = 'Permimeter', + comment = 'Perimeter', created_at = {'NOW()', raw = true }, updated_at = {'NOW()', raw = true }, }; diff --git a/misc/freeswitch/scripts/common/log.lua b/misc/freeswitch/scripts/common/log.lua index b9893ac..7201d2a 100644 --- a/misc/freeswitch/scripts/common/log.lua +++ b/misc/freeswitch/scripts/common/log.lua @@ -38,7 +38,7 @@ function Log.message(self, log_level, message_arguments ) if type(index) == 'number' then if type(value) == 'table' then require 'common.array'; - message = message .. common.array.to_json(value); + message = message .. common.array.to_json(value, 3); else message = message .. tostring(value); end diff --git a/misc/freeswitch/scripts/common/pager.lua b/misc/freeswitch/scripts/common/pager.lua new file mode 100644 index 0000000..d9440f4 --- /dev/null +++ b/misc/freeswitch/scripts/common/pager.lua @@ -0,0 +1,75 @@ +-- Gemeinschaft 5 module: pager class +-- (c) AMOOMA GmbH 2013 +-- + +module(...,package.seeall) + +Pager = {} + +function Pager.new(self, arg) + arg = arg or {} + pager = arg.pager or {} + setmetatable(pager, self); + self.__index = self; + self.class = 'pager'; + self.log = arg.log; + self.database = arg.database; + self.caller = arg.caller; + + return pager; +end + + +function Pager.find_by_id(self, id) + local sql_query = 'SELECT * FROM `pager_groups` WHERE `id`= '.. tonumber(id) .. ' LIMIT 1'; + local pager = nil; + + self.database:query(sql_query, function(entry) + pager = Pager:new(self); + pager.record = entry; + pager.id = tonumber(entry.id); + pager.uuid = entry.uuid; + pager.identifier = 'pager' .. entry.id; + end) + + return pager; +end + + +function Pager.enter(self) + local flags = 'mute'; + + if not self.caller.account or self.caller.account.class ~= 'sipaccount' then + return false; + end + + if tonumber(self.record.sip_account_id) == tonumber(self.caller.account.id) then + flags = 'moderator|endconf'; + end + + self:callback(); + + local result = self.caller:execute('conference', self.identifier .. "@profile_" .. self.identifier .. "++flags{" .. flags .. "}"); + self.caller:hangup('NORMAL_CLEARING'); + self:callback(); +end + + +function Pager.callback(self) + local destination = { + pager_group_id = self.id, + state = 'terminated', + } + + if self.caller.account and self.caller.account.class == 'sipaccount' then + destination.sip_account_id = self.caller.account.id; + end + + if self.caller and self.caller:ready() then + destination.state = 'active'; + end + + local command = 'http_request.lua ' .. self.caller.uuid .. ' ' .. common.array.expand_variables(self.record.callback_url, destination, self.caller); + require 'common.fapi'; + return common.fapi.FApi:new():execute('luarun', command); +end diff --git a/misc/freeswitch/scripts/common/perimeter.lua b/misc/freeswitch/scripts/common/perimeter.lua index d3b601c..fcef97c 100644 --- a/misc/freeswitch/scripts/common/perimeter.lua +++ b/misc/freeswitch/scripts/common/perimeter.lua @@ -47,6 +47,7 @@ function Perimeter.setup(self, event) self.ban_tries = 1; self.checks = { register = {}, call = {} }; self.bad_headers = { register = {}, call = {} }; + self.serial = freeswitch.getGlobalVariable('switch_serial'); if config and config.general then for key, value in pairs(config.general) do @@ -56,8 +57,14 @@ function Perimeter.setup(self, event) self.checks.register = config.checks_register or {}; self.checks.call = config.checks_call or {}; - self.bad_headers.register = config.bad_headers_register; - self.bad_headers.call = config.bad_headers_call; + + for header, patterns in pairs(config.bad_headers_register) do + self.bad_headers.register[header] = common.str.strip_to_a(patterns, ','); + end + + for header, patterns in pairs(config.bad_headers_call) do + self.bad_headers.call[header] = common.str.strip_to_a(patterns, ','); + end self.log:info('[perimeter] PERIMETER - setup perimeter defense'); end @@ -93,6 +100,7 @@ function Perimeter.record_update(self, event) event.record.span_start = event.span_start or event.record.span_start; event.record.span_contact_count = (event.span_contact_count or event.record.span_contact_count) + 1; event.record.users = event.users or event.record.users; + event.record.updated = event.updated or event.record.updated; end @@ -144,6 +152,7 @@ function Perimeter.check(self, event) end self:execute_ban(event); event.ban_time = os.time(); + event.banned = true; end event.record.banned = event.record.banned + 1; @@ -205,12 +214,14 @@ end function Perimeter.check_bad_headers(self, event) local points = nil; - for name, pattern in pairs(self.bad_headers[event.action]) do - pattern = common.array.expand_variables(pattern, event); - local success, result = pcall(string.find, event[name], pattern); - if success and result then - self.log:debug('[', event.key, '/', event.sequence, '] PERIMETER_BAD_HEADERS - ', name, '=', event[name], ' ~= ', pattern); - points = (points or 0) + 1; + for name, patterns in pairs(self.bad_headers[event.action]) do + for index, pattern in ipairs(patterns) do + pattern = common.array.expand_variables(pattern, event); + local success, result = pcall(string.find, event[name], pattern); + if success and result then + self.log:debug('[', event.key, '/', event.sequence, '] PERIMETER_BAD_HEADERS - ', name, '=', event[name], ' ~= ', pattern); + points = (points or 0) + 1; + end end end @@ -247,6 +258,17 @@ end function Perimeter.update_intruder(self, event) require 'common.intruder'; local result = common.intruder.Intruder:new{ log = self.log, database = self.database }:update_blacklist(event); + + if not common.str.blank(self.report_url) and (not event.record.updated or event.banned) then + event.serial = common.fapi.FApi:new():execute('md5', self.serial); + event.blacklisted = tostring(common.str.to_b(event.banned)); + local command = 'http_request.lua perimeter ' .. common.array.expand_variables(self.report_url, event); + require 'common.fapi' + common.fapi.FApi:new():execute('luarun', command); + self.log:devel(command); + end + + event.updated = common.str.to_i(event.updated) + 1; end |