From 2f1347f3415249cb116501af1f5e3282afca24be Mon Sep 17 00:00:00 2001 From: Ember 'n0emis' Keske Date: Wed, 20 Jul 2022 23:39:58 +0200 Subject: [PATCH] allow to claim extensions --- README.md | 3 +++ fieldpoc/controller.py | 22 +++++++++++++++++----- fieldpoc/dect.py | 22 ++++++++++++++++++++-- fieldpoc/fieldpoc.py | 4 ++++ fieldpoc/routing.py | 8 ++++++-- fieldpoc_config.json | 1 + fieldpoc_extensions.json | 4 ++-- 7 files changed, 53 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 085442c..2120dba 100644 --- a/README.md +++ b/README.md @@ -333,6 +333,8 @@ cdr_finalize=UPDATE users SET inuse=(CASE WHEN inuse>0 THEN inuse-1 ELSE 0 END) Just choose one of your RFPs as your OMM. Find out the MAC address and fill it in the according fields in the kea config before. +To be able to have secure sip connections between the OMM and yate, generate a 16-characters long hexadecimal sip-secret. + Create a privileged user account and add the credentials to `fieldpoc_config.json`: ``` @@ -341,6 +343,7 @@ Create a privileged user account and add the credentials to `fieldpoc_config.jso "host": "10.222.222.11", "username": "omm", "password": "" + "sipsecret": "" } } ``` diff --git a/fieldpoc/controller.py b/fieldpoc/controller.py index 716d4f0..594b65a 100644 --- a/fieldpoc/controller.py +++ b/fieldpoc/controller.py @@ -41,12 +41,16 @@ class Controller: if data == "help": self.request.sendall("""Availiable commands: -help Show this info -handlers Show currently running handlers -sync Start syncing -queues Show queue stats -exit Disconnect +help Show this info +handlers Show currently running handlers +sync Start syncing +queues Show queue stats +reload Reload extension config file +claim claim dect extension +exit Disconnect """.encode("utf-8")) + elif data == "": + continue elif data == "quit" or data == "exit": self.request.sendall("disconnecting\n".encode("utf-8")) return @@ -56,6 +60,14 @@ exit Disconnect self.fp.queue_all({"type": "sync"}) elif data == "queues": self.request.sendall(("\n".join(["{} {}".format(name, queue.qsize()) for name, queue in self.fp.queues.items()]) + "\n").encode("utf-8")) + elif data == "reload": + self.fp.reload_config() + elif data.startswith("claim"): + data = data.split(" ") + if len(data) == 3: + self.fp.queue_all({"type": "claim", "extension": data[1], "token": data[2]}) + else: + self.request.sendall("error: You have to specify calling extension and token\n".encode("utf-8")) else: self.request.sendall("Unknown command, type 'help'\n".encode("utf-8")) diff --git a/fieldpoc/dect.py b/fieldpoc/dect.py index bc428d8..0fd995c 100644 --- a/fieldpoc/dect.py +++ b/fieldpoc/dect.py @@ -3,6 +3,7 @@ import logging import mitel_ommclient2 import time +import hashlib logger = logging.getLogger("fieldpoc.dect") @@ -45,7 +46,7 @@ class Dect: return "{}{:0>4}".format(self.temp_num_prefix, current_temp_extension) def get_sip_password_for_number(self, num): - return num + return hashlib.sha256(bytes.fromhex((self.fp.config.dect.sipsecret + str(num))[-16:])).hexdigest()[:16] def create_and_bind_user(self, d, num): u = self.c.create_user(num) @@ -79,10 +80,12 @@ class Dect: e = extensions_by_num.get(user.num) if not e: # user in omm, but not as dect in nerd - # TODO: delete in omm if user.num.startswith(next(self.fp.extensions.extensions_by_type("temp")).num): users_by_ext[user.num] = user users_by_uid[user.uid] = user + else: + pass + # TODO: delete in omm continue elif e._c['name'] != user.name: self.c.set_user_name(user.uid, e._c['name']) @@ -135,4 +138,19 @@ class Dect: if created_tmp_ext: self.fp.queues['routing'].put({"type": "sync"}) + elif msg.get("type") == "claim": + e = None + for ext in self.fp.extensions.extensions_by_type("dect"): + if ext._c.get('dect_claim_token') and ext._c['dect_claim_token'] == msg.get("token")[4:]: + e = ext + break + + if e: + user = next(self.c.find_users(lambda u: u.num == msg.get("extension"))) + if self.fp.temp_extensions.get(user.num): + self.fp.temp_extensions.pop(user.num) + self.c.set_user_num(user.uid, e.num) + self.c.set_user_sipauth(user.uid, e.num, self.get_sip_password_for_number(e.num)) + self.c.set_user_name(user.uid, e._c['name']) + self.c.connection.close() diff --git a/fieldpoc/fieldpoc.py b/fieldpoc/fieldpoc.py index bd452d3..d1cdde3 100644 --- a/fieldpoc/fieldpoc.py +++ b/fieldpoc/fieldpoc.py @@ -76,6 +76,10 @@ class FieldPOC: logger.info("started components") + def reload_config(self): + self._load_extensions() + self.queue_all({"type": "sync"}) + def _load_config(self): self.config = config.Config(json.loads(self.config_file_path.read_text())) diff --git a/fieldpoc/routing.py b/fieldpoc/routing.py index fddd85f..962b3dc 100644 --- a/fieldpoc/routing.py +++ b/fieldpoc/routing.py @@ -313,6 +313,10 @@ class BackendNerd(diffsync.DiffSync): top_level = ["yate", "extension", "user", "forkrank", "forkrankmember"] + def __init__(self, fp, *args, **kwargs): + self.fp = fp + super().__init__(*args, **kwargs) + def load(self, data): #yate_dect = self.yate( # guru3_identifier="dect", hostname="dect", voip_listener="local" @@ -366,7 +370,7 @@ class BackendNerd(diffsync.DiffSync): user = self.user( username=key, displayname=value["name"], - password=value.get("sip_password", key), + password=value.get("sip_password", self.fp._dect.get_sip_password_for_number(key)), user_type=user_type[value["type"]], trunk=value["trunk"], static_target=value.get("static_target", ""), @@ -487,7 +491,7 @@ class Routing: logger.info("syncing") - state_fieldpoc = BackendNerd() + state_fieldpoc = BackendNerd(self.fp) extensions = self.fp.extensions._c.copy() extensions['extensions'].update(self.fp.temp_extensions) state_fieldpoc.load(extensions) diff --git a/fieldpoc_config.json b/fieldpoc_config.json index 7ad91a7..d1fcedb 100644 --- a/fieldpoc_config.json +++ b/fieldpoc_config.json @@ -7,6 +7,7 @@ "host": "10.222.222.11", "username": "omm", "password": "xxx" + "sipsecret": "51df84aace052b0e75b8c1da5a6da9e2" }, "yate": { "host": "127.0.0.1", diff --git a/fieldpoc_extensions.json b/fieldpoc_extensions.json index cff74c5..b63e63d 100644 --- a/fieldpoc_extensions.json +++ b/fieldpoc_extensions.json @@ -97,12 +97,12 @@ "dialout_allowed": true, "type": "temp" }, - "9999": { + "9997": { "name": "DECT Claim Extensions", "type": "static", "dialout_allowed": false, "trunk": true, - "static_target": "external/nodata//opt/nerdsync/claim.py" + "static_target": "external/nodata//run/current-system/sw/bin/dect_claim" } } }