From 508172e195a5e26820aeb30fad7f822d43a50bfe Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 23 Jun 2018 20:35:36 +0100 Subject: [PATCH 1/2] Allows user to disable strict validation when connecting to master --- hblink.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/hblink.py b/hblink.py index 9ffbb84..2872950 100644 --- a/hblink.py +++ b/hblink.py @@ -143,6 +143,16 @@ class HBSYSTEM(DatagramProtocol): return self._logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) + def validate_radio_id(self, _id): + + if self._config['STRICT']: + if _id == self._config['RADIO_ID']: + return True + else: + return False + else: + return True + def startProtocol(self): # Set up periodic loop for tracking pings from clients. Run every 'PING_TIME' seconds self._system_maintenance = task.LoopingCall(self.maintenance_loop) @@ -377,7 +387,7 @@ class HBSYSTEM(DatagramProtocol): _command = _data[:4] if _command == 'DMRD': # DMRData -- encapsulated DMR data frame _radio_id = _data[11:15] - if _radio_id == self._config['RADIO_ID']: # Validate the source and intended target + if self.validate_radio_id(_radio_id): # Validate the source and intended target _seq = _data[4:5] _rf_src = _data[5:8] _dst_id = _data[8:11] @@ -401,9 +411,11 @@ class HBSYSTEM(DatagramProtocol): elif _command == 'MSTN': # Actually MSTNAK -- a NACK from the master _radio_id = _data[6:10] # - if _radio_id == self._config['RADIO_ID']: # Validate the source and intended target + if self.validate_radio_id(_radio_id): # Validate the source and intended target # Validate the source and intended target self._logger.warning('(%s) MSTNAK Received. Resetting connection to the Master.', self._system) self._stats['CONNECTION'] = 'NO' # Disconnect ourselves and re-register + else: + self._logger.debug('(%s) MSTNAK contained wrong ID - Ignoring', self._system) elif _command == 'RPTA': # Actually RPTACK -- an ACK from the master # Depending on the state, an RPTACK means different things, in each clause, we check and/or set the state @@ -416,7 +428,8 @@ class HBSYSTEM(DatagramProtocol): self._stats['CONNECTION'] = 'AUTHENTICATED' elif self._stats['CONNECTION'] == 'AUTHENTICATED': # If we've sent the login challenge... - if _data[6:10] == self._config['RADIO_ID']: + _radio_id = _data[6:10] + if self.validate_radio_id(_radio_id): # Validate the source and intended target self._logger.info('(%s) Repeater Authentication Accepted', self._system) _config_packet = self._config['RADIO_ID']+\ self._config['CALLSIGN']+\ @@ -442,8 +455,8 @@ class HBSYSTEM(DatagramProtocol): self._logger.error('(%s) Master ACK Contained wrong ID - Connection Reset', self._system) elif self._stats['CONNECTION'] == 'CONFIG-SENT': # If we've sent out configuration to the master - if _data[6:10] == self._config['RADIO_ID']: - self._logger.info('(%s) Repeater Configuration Accepted', self._system) + _radio_id = _data[6:10] + if self.validate_radio_id(_radio_id): # Validate the source and intended target if self._config['OPTIONS']: self.send_master('RPTO'+self._config['RADIO_ID']+self._config['OPTIONS']) self._stats['CONNECTION'] = 'OPTIONS-SENT' @@ -456,7 +469,8 @@ class HBSYSTEM(DatagramProtocol): self._logger.error('(%s) Master ACK Contained wrong ID - Connection Reset', self._system) elif self._stats['CONNECTION'] == 'OPTIONS-SENT': # If we've sent out options to the master - if _data[6:10] == self._config['RADIO_ID']: + _radio_id = _data[6:10] + if self.validate_radio_id(_radio_id): # Validate the source and intended target self._logger.info('(%s) Repeater Options Accepted', self._system) self._stats['CONNECTION'] = 'YES' self._logger.info('(%s) Connection to Master Completed with options', self._system) @@ -465,16 +479,22 @@ class HBSYSTEM(DatagramProtocol): self._logger.error('(%s) Master ACK Contained wrong ID - Connection Reset', self._system) elif _command == 'MSTP': # Actually MSTPONG -- a reply to RPTPING (send by client) - if _data [7:11] == self._config['RADIO_ID']: + _radio_id = _data[7:11] + if self.validate_radio_id(_radio_id): # Validate the source and intended target self._stats['PING_OUTSTANDING'] = False self._stats['NUM_OUTSTANDING'] = 0 self._stats['PINGS_ACKD'] += 1 self._logger.debug('(%s) MSTPONG Received. Pongs Since Connected: %s', self._system, self._stats['PINGS_ACKD']) + else: + self._logger.debug('(%s) MSTPONG contained wrong ID - Ignoring', self._system) elif _command == 'MSTC': # Actually MSTCL -- notify us the master is closing down - if _data[5:9] == self._config['RADIO_ID']: + _radio_id = _data[5:9] + if self.validate_radio_id(_radio_id): # Validate the source and intended target self._stats['CONNECTION'] = 'NO' self._logger.info('(%s) MSTCL Recieved', self._system) + else: + self._logger.debug('(%s) MSTCL contained wrong ID - Ignoring', self._system) else: self._logger.error('(%s) Received an invalid command in packet: %s', self._system, ahex(_data)) From dc753bf2db1abc64660b1242de569adaaa5613ef Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 25 Jun 2018 16:44:19 +0100 Subject: [PATCH 2/2] Refactor validation to optimise code --- hb_config.py | 1 + hblink-SAMPLE.cfg | 1 + hblink.py | 22 ++++++---------------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/hb_config.py b/hb_config.py index 110b493..0f18db2 100755 --- a/hb_config.py +++ b/hb_config.py @@ -93,6 +93,7 @@ def build_config(_config_file): CONFIG['SYSTEMS'].update({section: { 'MODE': config.get(section, 'MODE'), 'ENABLED': config.getboolean(section, 'ENABLED'), + 'LOOSE': config.getboolean(section, 'LOOSE'), 'EXPORT_AMBE': config.getboolean(section, 'EXPORT_AMBE'), 'IP': gethostbyname(config.get(section, 'IP')), 'PORT': config.getint(section, 'PORT'), diff --git a/hblink-SAMPLE.cfg b/hblink-SAMPLE.cfg index c798405..13e98f4 100644 --- a/hblink-SAMPLE.cfg +++ b/hblink-SAMPLE.cfg @@ -80,6 +80,7 @@ GROUP_HANGTIME: 5 [REPEATER-1] MODE: CLIENT ENABLED: False +LOOSE: False EXPORT_AMBE: False IP: PORT: 54001 diff --git a/hblink.py b/hblink.py index 2872950..4433855 100644 --- a/hblink.py +++ b/hblink.py @@ -143,16 +143,6 @@ class HBSYSTEM(DatagramProtocol): return self._logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) - def validate_radio_id(self, _id): - - if self._config['STRICT']: - if _id == self._config['RADIO_ID']: - return True - else: - return False - else: - return True - def startProtocol(self): # Set up periodic loop for tracking pings from clients. Run every 'PING_TIME' seconds self._system_maintenance = task.LoopingCall(self.maintenance_loop) @@ -411,7 +401,7 @@ class HBSYSTEM(DatagramProtocol): elif _command == 'MSTN': # Actually MSTNAK -- a NACK from the master _radio_id = _data[6:10] # - if self.validate_radio_id(_radio_id): # Validate the source and intended target # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target # Validate the source and intended target self._logger.warning('(%s) MSTNAK Received. Resetting connection to the Master.', self._system) self._stats['CONNECTION'] = 'NO' # Disconnect ourselves and re-register else: @@ -429,7 +419,7 @@ class HBSYSTEM(DatagramProtocol): elif self._stats['CONNECTION'] == 'AUTHENTICATED': # If we've sent the login challenge... _radio_id = _data[6:10] - if self.validate_radio_id(_radio_id): # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target self._logger.info('(%s) Repeater Authentication Accepted', self._system) _config_packet = self._config['RADIO_ID']+\ self._config['CALLSIGN']+\ @@ -456,7 +446,7 @@ class HBSYSTEM(DatagramProtocol): elif self._stats['CONNECTION'] == 'CONFIG-SENT': # If we've sent out configuration to the master _radio_id = _data[6:10] - if self.validate_radio_id(_radio_id): # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target if self._config['OPTIONS']: self.send_master('RPTO'+self._config['RADIO_ID']+self._config['OPTIONS']) self._stats['CONNECTION'] = 'OPTIONS-SENT' @@ -470,7 +460,7 @@ class HBSYSTEM(DatagramProtocol): elif self._stats['CONNECTION'] == 'OPTIONS-SENT': # If we've sent out options to the master _radio_id = _data[6:10] - if self.validate_radio_id(_radio_id): # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target self._logger.info('(%s) Repeater Options Accepted', self._system) self._stats['CONNECTION'] = 'YES' self._logger.info('(%s) Connection to Master Completed with options', self._system) @@ -480,7 +470,7 @@ class HBSYSTEM(DatagramProtocol): elif _command == 'MSTP': # Actually MSTPONG -- a reply to RPTPING (send by client) _radio_id = _data[7:11] - if self.validate_radio_id(_radio_id): # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target self._stats['PING_OUTSTANDING'] = False self._stats['NUM_OUTSTANDING'] = 0 self._stats['PINGS_ACKD'] += 1 @@ -490,7 +480,7 @@ class HBSYSTEM(DatagramProtocol): elif _command == 'MSTC': # Actually MSTCL -- notify us the master is closing down _radio_id = _data[5:9] - if self.validate_radio_id(_radio_id): # Validate the source and intended target + if self._config['LOOSE'] or _radio_id == self._config['RADIO_ID']: # Validate the source and intended target self._stats['CONNECTION'] = 'NO' self._logger.info('(%s) MSTCL Recieved', self._system) else: