-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathwakeup.py
executable file
·138 lines (115 loc) · 4.47 KB
/
wakeup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python
# coding: utf-8
#
# (c)2017-2021 n0rc
import argparse
import getpass
import hashlib
import json
import os
import requests
import sys
from lxml import etree
from packaging import version
from requests.exceptions import SSLError
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
SID_NOAUTH = '0000000000000000'
def error_exit(msg):
print("[error] {}".format(msg))
sys.exit(1)
def ssl_error_exit():
error_exit("ssl certificate verification failed")
def get_config(config_file):
if os.path.isfile(config_file):
with open(config_file, 'r') as jf:
config = json.load(jf)
config['url_login'] = 'https://{}:{}/login_sid.lua'.format(config['host'], config['port'])
config['url_data'] = 'https://{}:{}/data.lua'.format(config['host'], config['port'])
return config
else:
error_exit("config file not found")
def get_sid(config):
try:
password = config['password']
except:
password = getpass.getpass()
try:
r = requests.get(config['url_login'], verify=config['verify_ssl'])
t = etree.XML(r.content)
challenge = t.xpath('//Challenge/text()')[0]
response = '{}-{}'.format(challenge, hashlib.md5('{}-{}'.format(challenge, password).encode('utf-16-le')).hexdigest())
r = requests.get('{}?username={}&response={}'.format(config['url_login'], config['username'], response), verify=config['verify_ssl'])
t = etree.XML(r.content)
return t.xpath('//SID/text()')[0]
except SSLError:
ssl_error_exit()
def get_uid(config, sid, mac):
try:
payload = {'sid': sid, 'page': 'netDev', 'xhrId': 'all'}
r = requests.post(config['url_data'], data=payload, verify=config['verify_ssl'])
devs = json.loads(r.content)
for dev in devs['data']['passive']:
if dev['mac'] == mac:
return dev['UID']
for dev in devs['data']['active']:
if dev['mac'] == mac:
return dev['UID']
return ''
except SSLError:
ssl_error_exit()
def get_version(config, sid):
try:
payload = {'sid': sid, 'page': 'overview'}
r = requests.post(config['url_data'], data=payload, verify=config['verify_ssl'])
reply = json.loads(r.content)
return reply['data']['fritzos']['nspver'].split().pop(0)
except SSLError:
ssl_error_exit()
except KeyError:
return '0.0'
def wake_up(config, sid, uid):
try:
payload = {'sid': sid, 'dev': uid, 'oldpage': 'net/edit_device.lua', 'page': 'edit_device', 'btn_wake': ''}
vers = get_version(config, sid)
if version.parse(vers) <= version.parse('7.24'):
payload['page'] += '2'
r = requests.post(config['url_data'], data=payload, verify=config['verify_ssl'])
if r.headers.get("content-type").startswith('application/json'):
reply = json.loads(r.content)
try:
if reply['data']['btn_wake'] == 'ok':
return True
except KeyError:
pass
return False
elif '"pid":"netDev"' in r.text:
return True
else:
return False
except SSLError:
ssl_error_exit()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('device', help='device name (from config file) to sent wakeup to', default='default', nargs='?')
parser.add_argument('--config', '-c', default='wakeup.json', metavar='wakeup.json', help='use specified config file')
parser.add_argument('--ssl-no-verify', '-k', action='store_true', help='ignore ssl certificate verification')
args, _ = parser.parse_known_args()
config = get_config(args.config)
config['verify_ssl'] = not args.ssl_no_verify
if args.device in config['devices']:
target_mac = config['devices'][args.device]
else:
error_exit("unknown device {}".format(args.device))
sid = get_sid(config)
if sid == SID_NOAUTH:
error_exit("authentication failed")
else:
uid = get_uid(config, sid, target_mac)
if uid:
if wake_up(config, sid, uid):
print("[success] wakeup sent to {}".format(target_mac))
else:
error_exit("something went wrong while sending wakeup to {}".format(target_mac))
else:
error_exit("unknown mac {}".format(target_mac))