def signal_strength(self): '''Returns a signal strength from 0 to 5 (where 5 is the best), based on the rsrp value''' response = self.signal root = ET.fromstring(response) rsrp = int(root.findall('./rsrp')[0].text[:-3]) rsrp_q = utils.getRange([-90, -105, -112, -125, -136], rsrp) result = xmlobjects.CustomXml({'SignalStrength': 5 - rsrp_q}) return result.buildXmlResponse()
def remove_ddns(self, config): domain = self._get_param(config, 'domain') xml = ET.fromstring(self.ddns) ele = xml.findall('.//ddns[domainname="%s"]' % domain) if ele is None: raise ValueError('Unable to find domain: %s' % domain) index = ele[0].find('.//index').text settings = xmlobjects.DdnsCollection() settings.setToDelete() settings.ddnss.append(xmlobjects.CustomXml({'index': index}, 'ddns')) return self.enc_api('ddns/ddns-list', settings)
def connection(self): ''' Returns current connection mode and state e.g. <ConnectionStatus>Connected</ConnectionStatus> <ConnectionMode>AUTO</ConnectionMode> ''' state = xmlobjects.CustomXml({'connectionmode': 0, 'connectstatus': 0}) state.parseXML(self.status) connection_mode = self.CONNECTION_MODE[int(state.connectionmode)] connection_status = 'Unknown' if int(state.connectstatus) in self.CONNECTION_STATUS.keys(): connection_status = self.CONNECTION_STATUS[int( state.connectstatus)] xml = xmlobjects.CustomXml({ 'ConnectionStatus': connection_status, 'ConnectionMode': connection_mode }) return xml.buildXmlResponse()
def modelist2(self): net = xmlobjects.NetworkMode() net.parseXML(self.mode) net_bands = [] for band in xmlobjects.NetworkMode.band_from_hex(net.NetworkBand): if (band == 'EXTRA'): continue net_bands.append(xmlobjects.CustomXml({'Band': band})) lte_bands = [] for band in xmlobjects.NetworkMode.lte_from_hex(net.LTEBand): lte_bands.append(xmlobjects.CustomXml({'Band': band})) xml = xmlobjects.CustomXml({ 'NetworkMode': xmlobjects.NetworkMode.get_mode(net.NetworkMode), 'NetworkBands': net_bands, 'LTEBands': lte_bands }) return xml.buildXmlResponse()
def remove_account(self, config): ''' Remove a configured account by name, config -> { 'account': 'TPG' } ''' account = self._get_param(config, 'account') xml = ET.fromstring(self.sip_accounts) ele = xml.findall('.//account[directorynumber="%s"]' % account) if ele is None: raise ValueError('Unable to find account: %s' % account) index = ele[0].find('.//index').text settings = xmlobjects.SipCollection() settings.account.append( xmlobjects.CustomXml({'index': index}, 'account')) return self.enc_api('voice/deletesipaccount', settings)
def __api_challenge(self): self.__setup_session() token = self.__get_server_token() url = "http://%s/api/user/challenge_login" % self.router self.clientnonce = crypto.generate_nonce() xml = xmlobjects.CustomXml({ 'username': self.username, 'firstnonce': self.clientnonce, 'mode': 1 }).buildXML() headers = {'Content-type': 'text/html', self.REQUEST_TOKEN: token[32:]} response = self.__post(url=url, data=xml, headers=headers) if RouterError.hasError(response.text): raise RouterError(response.text) return response
def api(self, url, data=None, encrypted=False): """ Handles all api calls to the router """ #Check if the session has timed out, and login again if it has timed_out = datetime.now() - self.__last_login if (timed_out.total_seconds() >= self.__timeout and self.__is_logged_in): with self.__lock: if (timed_out.total_seconds() >= self.__timeout and self.__is_logged_in): logger.debug('Session timeout - establishing new login...') self.__login() verification_token = self.__get_server_token()[32:] if isinstance(data, dict): data = xmlobjects.CustomXml(data).buildXML() elif isinstance(data, xmlobjects.XmlObject): data = data.buildXML() url = "http://%s/api/%s" % (self.router, url) headers = {} headers[self.REQUEST_TOKEN] = verification_token if (encrypted): headers[ 'Content-type'] = 'application/x-www-form-urlencoded; charset=UTF-8;enc' else: headers[ 'Content-type'] = 'application/x-www-form-urlencoded; charset=UTF-8' #print(data) if data is None or data == '': response = self.__get(url, headers).text else: if encrypted: data = crypto.rsa_encrypt(self.__rsae, self.__rsan, data) response = self.__post(url, data, headers).text #print(response) #Add error message if known and missing if RouterError.hasError(response): error = xmlobjects.Error() error.parseXML(response) response = error.buildXmlError() return response
def __login(self): """ logs in to the router using SCRAM method of authentication """ logger.info('LOGIN for user [%s]' % self.username) response = self.__api_challenge() verification_token = response.headers[self.REQUEST_TOKEN] scram_data = ET.fromstring(response.text) servernonce = scram_data.findall('./servernonce')[0].text salt = scram_data.findall('./salt')[0].text iterations = int(scram_data.findall('./iterations')[0].text) client_proof = crypto.get_client_proof(self.clientnonce, servernonce, self.__password, salt, iterations).decode('UTF-8') login_request = xmlobjects.CustomXml({ 'clientproof': client_proof, 'finalnonce': servernonce }).buildXML() headers = { 'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8', self.REQUEST_TOKEN: verification_token } url = "http://%s/api/user/authentication_login" % self.router result = self.__post(url=url, data=login_request, headers=headers) if RouterError.hasError(result.text): raise RouterError(result.text) verification_token = result.headers[self.REQUEST_TOKEN] self.__last_login = datetime.now() ''' The SCRAM protocol would normally validate the server signatures We're assuming this is ok e.g. var serverProof = scram.serverProof(psd, salt, iter, authMsg); if (ret.response.serversignature == serverProof) { var publicKeySignature = scram.signature(CryptoJS.enc.Hex.parse(ret.response.rsan), CryptoJS.enc.Hex.parse(serverKey)).toString(); if (ret.response.rsapubkeysignature == publicKeySignature) { ''' xml = ET.fromstring(result.text) self.__rsae = xml.find('.//rsae').text self.__rsan = xml.find('.//rsan').text self.__is_logged_in = True