Merge remote-tracking branch 'upstream/master' into patch-1

This commit is contained in:
gerard780
2020-01-14 16:10:30 -05:00
29 changed files with 1056 additions and 353 deletions

View File

@ -154,7 +154,7 @@ class AutoUpdate(plugins.Plugin):
self.lock = Lock()
def on_loaded(self):
if 'interval' not in self.options or ('interval' in self.options and self.options['interval'] is None):
if 'interval' not in self.options or ('interval' in self.options and not self.options['interval']):
logging.error("[update] main.plugins.auto-update.interval is not set")
return
self.ready = True

View File

@ -437,7 +437,7 @@ class BTTether(plugins.Plugin):
for device_opt in ['enabled', 'priority', 'scantime', 'search_order',
'max_tries', 'share_internet', 'mac', 'ip',
'netmask', 'interval']:
if device_opt not in options or (device_opt in options and options[device_opt] is None):
if device_opt not in options or (device_opt in options and not options[device_opt]):
logging.error("BT-TETHER: Please specify the %s for device %s.",
device_opt, device)
break
@ -448,7 +448,7 @@ class BTTether(plugins.Plugin):
# legacy
if 'mac' in self.options:
for opt in ['share_internet', 'mac', 'ip', 'netmask', 'interval']:
if opt not in self.options or (opt in self.options and self.options[opt] is None):
if opt not in self.options or (opt in self.options and not self.options[opt]):
logging.error("BT-TETHER: Please specify the %s in your config.yml.", opt)
return

View File

@ -26,7 +26,7 @@ class NetPos(plugins.Plugin):
self.lock = threading.Lock()
def on_loaded(self):
if 'api_key' not in self.options or ('api_key' in self.options and self.options['api_key'] is None):
if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):
logging.error("NET-POS: api_key isn't set. Can't use mozilla's api.")
return

View File

@ -28,7 +28,7 @@ class OnlineHashCrack(plugins.Plugin):
"""
Gets called when the plugin gets loaded
"""
if 'email' not in self.options or ('email' in self.options and self.options['email'] is None):
if 'email' not in self.options or ('email' in self.options and not self.options['email']):
logging.error("OHC: Email isn't set. Can't upload to onlinehashcrack.com")
return

View File

@ -0,0 +1,147 @@
import os
import logging
from threading import Lock
from functools import partial
from pwnagotchi import plugins
from pwnagotchi import reboot
def systemd_dropin(name, content):
if not name.endswith('.service'):
name = '%s.service' % name
dropin_dir = "/etc/systemd/system/%s.d/" % name
os.makedirs(dropin_dir, exist_ok=True)
with open(os.path.join(dropin_dir, "switcher.conf"), "wt") as dropin:
dropin.write(content)
systemctl("daemon-reload")
def systemctl(command, unit=None):
if unit:
os.system("/bin/systemctl %s %s" % (command, unit))
else:
os.system("/bin/systemctl %s" % command)
def run_task(name, options):
task_service_name = "switcher-%s-task.service" % name
# save all the commands to a shell script
script_dir = '/usr/local/bin/'
script_path = os.path.join(script_dir, 'switcher-%s.sh' % name)
os.makedirs(script_dir, exist_ok=True)
with open(script_path, 'wt') as script_file:
script_file.write('#!/bin/bash\n')
for cmd in options['commands']:
script_file.write('%s\n' % cmd)
os.system("chmod a+x %s" % script_path)
# here we create the service which runs the tasks
with open('/etc/systemd/system/%s' % task_service_name, 'wt') as task_service:
task_service.write("""
[Unit]
Description=Executes the tasks of the pwnagotchi switcher plugin
After=pwnagotchi.service bettercap.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/local/bin/switcher-%s.sh
ExecStart=-/bin/rm /etc/systemd/system/%s
ExecStart=-/bin/rm /usr/local/bin/switcher-%s.sh
[Install]
WantedBy=multi-user.target
""" % (name, task_service_name, name))
if 'reboot' in options and options['reboot']:
# create a indication file!
# if this file is set, we want the switcher-tasks to run
open('/root/.switcher', 'a').close()
# add condition
systemd_dropin("pwnagotchi.service", """
[Unit]
ConditionPathExists=!/root/.switcher""")
systemd_dropin("bettercap.service", """
[Unit]
ConditionPathExists=!/root/.switcher""")
systemd_dropin(task_service_name, """
[Service]
ExecStart=-/bin/rm /root/.switcher
ExecStart=-/bin/rm /etc/systemd/system/switcher-reboot.timer""")
with open('/etc/systemd/system/switcher-reboot.timer', 'wt') as reboot_timer:
reboot_timer.write("""
[Unit]
Description=Reboot when time is up
ConditionPathExists=/root/.switcher
[Timer]
OnBootSec=%sm
Unit=reboot.target
[Install]
WantedBy=timers.target
""" % options['stopwatch'])
systemctl("daemon-reload")
systemctl("enable", "switcher-reboot.timer")
systemctl("enable", task_service_name)
reboot()
return
systemctl("daemon-reload")
systemctl("start", task_service_name)
class Switcher(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '0.0.1'
__name__ = 'switcher'
__license__ = 'GPL3'
__description__ = 'This plugin is a generic task scheduler.'
def __init__(self):
self.ready = False
self.lock = Lock()
def trigger(self, name, *args, **kwargs):
with self.lock:
function_name = name.lstrip('on_')
if function_name in self.tasks:
task = self.tasks[function_name]
# is this task enabled?
if 'enabled' not in task or ('enabled' in task and not task['enabled']):
return
run_task(function_name, task)
def on_loaded(self):
if 'tasks' in self.options and self.options['tasks']:
self.tasks = self.options['tasks']
else:
logging.debug('[switcher] No tasks found...')
return
logging.info("[switcher] is loaded.")
# create hooks
logging.debug("[switcher] creating hooks...")
methods = ['webhook', 'internet_available', 'ui_setup', 'ui_update',
'unload', 'display_setup', 'ready', 'ai_ready', 'ai_policy',
'ai_training_start', 'ai_training_step', 'ai_training_end',
'ai_best_reward', 'ai_worst_reward', 'free_channel',
'bored', 'sad', 'excited', 'lonely', 'rebooting', 'wait',
'sleep', 'wifi_update', 'unfiltered_ap_list', 'association',
'deauthentication', 'channel_hop', 'handshake', 'epoch',
'peer_detected', 'peer_lost']
for m in methods:
setattr(Switcher, 'on_%s' % m, partial(self.trigger, m))
logging.debug("[switcher] triggers are ready to fire...")

View File

@ -7,12 +7,14 @@
# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4
# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310
# https://www.aliexpress.com/item/32888533624.html
import logging
import struct
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
import pwnagotchi.ui.fonts as fonts
import pwnagotchi.plugins as plugins
import pwnagotchi
# TODO: add enable switch in config.yml an cleanup all to the best place
@ -63,4 +65,9 @@ class UPSLite(plugins.Plugin):
ui.remove_element('ups')
def on_ui_update(self, ui):
ui.set('ups', "%2i%%" % self.ups.capacity())
capacity = self.ups.capacity()
ui.set('ups', "%2i%%" % capacity)
if capacity <= self.options['shutdown']:
logging.info('[ups_lite] Empty battery (<= %s%%): shuting down' % self.options['shutdown'])
ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'})
pwnagotchi.shutdown()

View File

@ -1,13 +1,12 @@
import logging
import json
import yaml
import toml
import _thread
import pwnagotchi.plugins as plugins
from pwnagotchi import restart
from flask import abort
from flask import render_template_string
INDEX = """
<html>
<head>
@ -500,13 +499,13 @@ class WebConfig(plugins.Plugin):
elif request.method == "POST":
if path == "save-config":
try:
parsed_yaml = yaml.safe_load(str(request.get_json()))
with open('/etc/pwnagotchi/config.yml', 'w') as config_file:
yaml.safe_dump(parsed_yaml, config_file, encoding='utf-8',
allow_unicode=True, default_flow_style=False)
parsed_toml = toml.loads(request.get_json())
with open('/etc/pwnagotchi/config.toml') as config_file:
toml.dump(parsed_toml, config_file)
_thread.start_new_thread(restart, (self.mode,))
return "success"
except yaml.YAMLError as yaml_ex:
except Exception as ex:
logging.error(ex)
return "config error"
abort(404)

View File

@ -270,5 +270,16 @@
positionsLoaded = true;
drawPositions();
});
// get current position and set marker in interval
var myLocationMarker = {};
function onLocationFound(e) {
if (myLocationMarker != undefined) {
mymap.removeLayer(myLocationMarker);
};
myLocationMarker = L.marker(e.latlng).addTo(mymap);
setTimeout(function(){ mymap.locate(); }, 30000);
}
mymap.on('locationfound', onLocationFound);
mymap.locate({setView: true});
</script>
</body></html>

View File

@ -23,7 +23,7 @@ from dateutil.parser import parse
class Webgpsmap(plugins.Plugin):
__author__ = 'https://github.com/xenDE and https://github.com/dadav'
__version__ = '1.3.0'
__version__ = '1.3.1'
__name__ = 'webgpsmap'
__license__ = 'GPL3'
__description__ = 'a plugin for pwnagotchi that shows a openstreetmap with positions of ap-handshakes in your webbrowser'
@ -50,6 +50,7 @@ class Webgpsmap(plugins.Plugin):
"""
# defaults:
response_header_contenttype = None
response_header_contentdisposition = None
response_mimetype = "application/xhtml+xml"
if not self.ready:
try:
@ -90,6 +91,21 @@ class Webgpsmap(plugins.Plugin):
except Exception as error:
logging.error(f"[webgpsmap] error: {error}")
return
elif path.startswith('offlinemap'):
# for download an all-in-one html file with positions.json inside
try:
self.ALREADY_SENT = list()
json_data = json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes']))
html_data = self.get_html()
html_data = html_data.replace('var positions = [];', 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();')
response_data = bytes(html_data, "utf-8")
response_status = 200
response_mimetype = "application/xhtml+xml"
response_header_contenttype = 'text/html'
response_header_contentdisposition = 'attachment; filename=webgpsmap.html';
except Exception as error:
logging.error(f"[webgpsmap] offlinemap: error: {error}")
return
# elif path.startswith('/newest'):
# # returns all positions newer then timestamp
# response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes']), newest_only=True), "utf-8")
@ -120,6 +136,8 @@ class Webgpsmap(plugins.Plugin):
r = Response(response=response_data, status=response_status, mimetype=response_mimetype)
if response_header_contenttype is not None:
r.headers["Content-Type"] = response_header_contenttype
if response_header_contentdisposition is not None:
r.headers["Content-Disposition"] = response_header_contentdisposition
return r
except Exception as error:
logging.error(f"[webgpsmap] error: {error}")

View File

@ -70,11 +70,11 @@ class WpaSec(plugins.Plugin):
"""
Gets called when the plugin gets loaded
"""
if 'api_key' not in self.options or ('api_key' in self.options and self.options['api_key'] is None):
if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):
logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org")
return
if 'api_url' not in self.options or ('api_url' in self.options and self.options['api_url'] is None):
if 'api_url' not in self.options or ('api_url' in self.options and not self.options['api_url']):
logging.error("WPA_SEC: API-URL isn't set. Can't upload, no endpoint configured.")
return