1
0
mirror of https://github.com/Tafkas/fritzbox-munin.git synced 2023-10-10 13:36:55 +02:00

use lxml for parsing and better error handling

This commit is contained in:
Christian Stade-Schuldt 2017-11-04 17:04:00 +01:00
parent a2fb8f7dc7
commit bfdeb190f3

View File

@ -14,80 +14,94 @@
This plugin supports the following munin configuration parameters: This plugin supports the following munin configuration parameters:
#%# family=auto contrib #%# family=auto contrib
#%# capabilities=autoconf #%# capabilities=autoconf
The initial script was inspired by
https://www.linux-tips-and-tricks.de/en/programming/389-read-data-from-a-fritzbox-7390-with-python-and-bash
framp at linux-tips-and-tricks dot de
""" """
import hashlib import hashlib
import httplib
import re
import sys import sys
from xml.dom import minidom
USER_AGENT = "Mozilla/5.0 (U; Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0" import requests
from lxml import etree
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:10.0) Gecko/20100101 Firefox/10.0"
def get_sid(server, password, port=80): def get_session_id(server, password, port=80):
"""Obtains the sid after login into the fritzbox""" """Obtains the session id after login into the Fritzbox.
conn = httplib.HTTPConnection(server + ':' + str(port)) See https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_Technical_Note_-_Session_ID.pdf
for deteils (in German).
:param server: the ip address of the Fritzbox
:param password: the password to log into the Fritzbox webinterface
:param port: the port the Fritzbox webserver runs on
:return: the session id
"""
headers = {"Accept": "application/xml", headers = {"Accept": "application/xml",
"Content-Type": "text/plain", "Content-Type": "text/plain",
"User-Agent": USER_AGENT} "User-Agent": USER_AGENT}
initial_page = '/login_sid.lua' url = 'http://{}:{}/login_sid.lua'.format(server, port)
conn.request("GET", initial_page, '', headers) try:
response = conn.getresponse() r = requests.get(url, headers=headers)
data = response.read() r.raise_for_status()
if response.status != 200: except requests.exceptions.HTTPError as err:
print "%s %s" % (response.status, response.reason) print(err)
sys.exit(0) sys.exit(1)
else:
xml_data = minidom.parseString(data) root = etree.fromstring(r.content)
sid_info = xml_data.getElementsByTagName('SID') session_id = root.xpath('//SessionInfo/SID/text()')[0]
sid = sid_info[0].firstChild.data if session_id == "0000000000000000":
if sid == "0000000000000000": challenge = root.xpath('//SessionInfo/Challenge/text()')[0]
challenge_info = xml_data.getElementsByTagName('Challenge') challenge_bf = ('{}-{}'.format(challenge, password)).decode('iso-8859-1').encode('utf-16le')
challenge = challenge_info[0].firstChild.data
challenge_bf = (challenge + '-' + password).decode('iso-8859-1').encode('utf-16le')
m = hashlib.md5() m = hashlib.md5()
m.update(challenge_bf) m.update(challenge_bf)
response_bf = challenge + '-' + m.hexdigest().lower() response_bf = '{}-{}'.format(challenge, m.hexdigest().lower())
else: else:
return sid return session_id
headers = {"Accept": "text/html,application/xhtml+xml,application/xml", headers = {"Accept": "text/html,application/xhtml+xml,application/xml",
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
"User-Agent": USER_AGENT} "User-Agent": USER_AGENT}
login_page = "/login_sid.lua?&response=" + response_bf url = 'http://{}:{}/login_sid.lua?&response={}'.format(server, port, response_bf)
conn.request("GET", login_page, '', headers) try:
response = conn.getresponse() r = requests.get(url, headers=headers)
data = response.read() r.raise_for_status()
if response.status != 200: except requests.exceptions.HTTPError as err:
print "%s %s" % (response.status, response.reason) print(err)
sys.exit(1)
root = etree.fromstring(r.content)
session_id = root.xpath('//SessionInfo/SID/text()')[0]
if session_id == "0000000000000000":
print("ERROR - No SID received because of invalid password")
sys.exit(0) sys.exit(0)
else: return session_id
sid = re.search("<SID>(.*?)</SID>", data).group(1)
if sid == "0000000000000000":
print "ERROR - No SID received because of invalid password"
sys.exit(0)
return sid
def get_page(server, sid, page, port=80): def get_page_content(server, session_id, page, port=80):
"""Fetches a page from the Fritzbox and returns its content""" """Fetches a page from the Fritzbox and returns its content
conn = httplib.HTTPConnection(server + ':' + str(port))
:param server: the ip address of the Fritzbox
:param session_id: a valid session id
:param page: the page you are regquesting
:param port: the port the Fritzbox webserver runs on
:return: the content of the page
"""
headers = {"Accept": "application/xml", headers = {"Accept": "application/xml",
"Content-Type": "text/plain", "Content-Type": "text/plain",
"User-Agent": USER_AGENT} "User-Agent": USER_AGENT}
page_with_sid = page + "?sid=" + sid url = 'http://{}:{}/{}?sid={}'.format(server, port, page, session_id)
conn.request("GET", page_with_sid, '', headers) try:
response = conn.getresponse() r = requests.get(url, headers=headers)
data = response.read() r.raise_for_status()
if response.status != 200: except requests.exceptions.HTTPError as err:
print "%s %s" % (response.status, response.reason) print(err)
print data sys.exit(1)
sys.exit(0) return r.content
else:
return data