Merge pull request #747 from dadav/feature/migrate_to_toml
Switch to toml
This commit is contained in:
commit
f691f737ab
@ -90,9 +90,9 @@ def do_auto_mode(agent):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('-C', '--config', action='store', dest='config', default='/etc/pwnagotchi/default.yml',
|
parser.add_argument('-C', '--config', action='store', dest='config', default='/etc/pwnagotchi/default.toml',
|
||||||
help='Main configuration file.')
|
help='Main configuration file.')
|
||||||
parser.add_argument('-U', '--user-config', action='store', dest='user_config', default='/etc/pwnagotchi/config.yml',
|
parser.add_argument('-U', '--user-config', action='store', dest='user_config', default='/etc/pwnagotchi/config.toml',
|
||||||
help='If this file exists, configuration will be merged and this will override default values.')
|
help='If this file exists, configuration will be merged and this will override default values.')
|
||||||
|
|
||||||
parser.add_argument('--manual', dest="do_manual", action="store_true", default=False, help="Manual mode.")
|
parser.add_argument('--manual', dest="do_manual", action="store_true", default=False, help="Manual mode.")
|
||||||
@ -119,7 +119,7 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
config = utils.load_config(args)
|
config = utils.load_config(args)
|
||||||
if args.print_config:
|
if args.print_config:
|
||||||
print(yaml.dump(config, default_flow_style=False))
|
print(toml.dumps(config))
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
utils.setup_logging(args, config)
|
utils.setup_logging(args, config)
|
||||||
|
@ -30,7 +30,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
|
|||||||
AsyncTrainer.__init__(self, config)
|
AsyncTrainer.__init__(self, config)
|
||||||
|
|
||||||
self._started_at = time.time()
|
self._started_at = time.time()
|
||||||
self._filter = None if config['main']['filter'] is None else re.compile(config['main']['filter'])
|
self._filter = None if not config['main']['filter'] else re.compile(config['main']['filter'])
|
||||||
self._current_channel = 0
|
self._current_channel = 0
|
||||||
self._tot_aps = 0
|
self._tot_aps = 0
|
||||||
self._aps_on_channel = 0
|
self._aps_on_channel = 0
|
||||||
|
205
pwnagotchi/defaults.toml
Normal file
205
pwnagotchi/defaults.toml
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
main.name = ""
|
||||||
|
main.lang = "en"
|
||||||
|
main.custom_plugins = ""
|
||||||
|
main.iface = "mon0"
|
||||||
|
main.mon_start_cmd = "/usr/bin/monstart"
|
||||||
|
main.mon_stop_cmd = "/usr/bin/monstop"
|
||||||
|
main.mon_max_blind_epochs = 50.0
|
||||||
|
main.no_restart = false
|
||||||
|
main.whitelist = [
|
||||||
|
"EXAMPLE_NETWORK",
|
||||||
|
"ANOTHER_EXAMPLE_NETWORK",
|
||||||
|
"fo:od:ba:be:fo:od",
|
||||||
|
"fo:od:ba"
|
||||||
|
]
|
||||||
|
main.filter = ""
|
||||||
|
|
||||||
|
|
||||||
|
main.plugins.grid.enabled = true
|
||||||
|
main.plugins.grid.report = false
|
||||||
|
main.plugins.grid.exclude = [
|
||||||
|
"YourHomeNetworkHere"
|
||||||
|
]
|
||||||
|
|
||||||
|
main.plugins.auto-update.enabled = true
|
||||||
|
main.plugins.auto-update.install = true
|
||||||
|
main.plugins.auto-update.interval = 1.0
|
||||||
|
|
||||||
|
main.plugins.net-pos.enabled = false
|
||||||
|
main.plugins.net-pos.api_key = "test"
|
||||||
|
|
||||||
|
main.plugins.gps.enabled = false
|
||||||
|
main.plugins.gps.speed = 19200.0
|
||||||
|
main.plugins.gps.device = "/dev/ttyUSB0"
|
||||||
|
|
||||||
|
main.plugins.webgpsmap.enabled = false
|
||||||
|
|
||||||
|
main.plugins.onlinehashcrack.enabled = false
|
||||||
|
main.plugins.onlinehashcrack.email = ""
|
||||||
|
|
||||||
|
main.plugins.wpa-sec.enabled = false
|
||||||
|
main.plugins.wpa-sec.api_key = ""
|
||||||
|
main.plugins.wpa-sec.api_url = "https://wpa-sec.stanev.org"
|
||||||
|
main.plugins.wpa-sec.download_results = false
|
||||||
|
|
||||||
|
main.plugins.wigle.enabled = false
|
||||||
|
main.plugins.wigle.api_key = ""
|
||||||
|
|
||||||
|
main.plugins.bt-tether.enabled = false
|
||||||
|
|
||||||
|
main.plugins.bt-tether.devices.android-phone.enabled = false
|
||||||
|
main.plugins.bt-tether.devices.android-phone.search_order = 1.0
|
||||||
|
main.plugins.bt-tether.devices.android-phone.mac = ""
|
||||||
|
main.plugins.bt-tether.devices.android-phone.ip = "192.168.44.44"
|
||||||
|
main.plugins.bt-tether.devices.android-phone.netmask = 24.0
|
||||||
|
main.plugins.bt-tether.devices.android-phone.interval = 1.0
|
||||||
|
main.plugins.bt-tether.devices.android-phone.scantime = 10.0
|
||||||
|
main.plugins.bt-tether.devices.android-phone.max_tries = 10.0
|
||||||
|
main.plugins.bt-tether.devices.android-phone.share_internet = false
|
||||||
|
main.plugins.bt-tether.devices.android-phone.priority = 1.0
|
||||||
|
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.enabled = false
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.search_order = 2.0
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.mac = ""
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.ip = "172.20.10.6"
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.netmask = 24.0
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.interval = 5.0
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.scantime = 20.0
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.max_tries = 0.0
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.share_internet = false
|
||||||
|
main.plugins.bt-tether.devices.ios-phone.priority = 999.0
|
||||||
|
|
||||||
|
main.plugins.memtemp.enabled = false
|
||||||
|
main.plugins.memtemp.scale = "celsius"
|
||||||
|
main.plugins.memtemp.orientation = "horizontal"
|
||||||
|
|
||||||
|
main.plugins.paw-gps.enabled = false
|
||||||
|
main.plugins.paw-gps.ip = ""
|
||||||
|
|
||||||
|
main.plugins.gpio_buttons.enabled = false
|
||||||
|
|
||||||
|
main.plugins.led.enabled = true
|
||||||
|
main.plugins.led.led = 0.0
|
||||||
|
main.plugins.led.delay = 200.0
|
||||||
|
main.plugins.led.patterns.loaded = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.updating = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.unread_inbox = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.ready = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.ai_ready = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.ai_training_start = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.ai_best_reward = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.ai_worst_reward = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.bored = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.sad = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.excited = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.lonely = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.rebooting = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.wait = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.sleep = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.wifi_update = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.association = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.deauthentication = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.handshake = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.epoch = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.peer_detected = "oo oo oo oo oo oo oo"
|
||||||
|
main.plugins.led.patterns.peer_lost = "oo oo oo oo oo oo oo"
|
||||||
|
|
||||||
|
main.plugins.session-stats.enabled = true
|
||||||
|
|
||||||
|
main.log.path = "/var/log/pwnagotchi.log"
|
||||||
|
main.log.rotation.enabled = true
|
||||||
|
main.log.rotation.size = "10M"
|
||||||
|
|
||||||
|
ai.enabled = true
|
||||||
|
ai.path = "/root/brain.nn"
|
||||||
|
ai.laziness = 0.1
|
||||||
|
ai.epochs_per_episode = 50.0
|
||||||
|
|
||||||
|
ai.params.gamma = 0.99
|
||||||
|
ai.params.n_steps = 1.0
|
||||||
|
ai.params.vf_coef = 0.25
|
||||||
|
ai.params.ent_coef = 0.01
|
||||||
|
ai.params.max_grad_norm = 0.5
|
||||||
|
ai.params.learning_rate = 0.001
|
||||||
|
ai.params.alpha = 0.99
|
||||||
|
ai.params.epsilon = 0.00001
|
||||||
|
ai.params.verbose = 1.0
|
||||||
|
ai.params.lr_schedule = "constant"
|
||||||
|
|
||||||
|
personality.advertise = true
|
||||||
|
personality.deauth = true
|
||||||
|
personality.associate = true
|
||||||
|
personality.channels = []
|
||||||
|
personality.min_rssi = -200.0
|
||||||
|
personality.ap_ttl = 120.0
|
||||||
|
personality.sta_ttl = 300.0
|
||||||
|
personality.recon_time = 30.0
|
||||||
|
personality.max_inactive_scale = 2.0
|
||||||
|
personality.recon_inactive_multiplier = 2.0
|
||||||
|
personality.hop_recon_time = 10.0
|
||||||
|
personality.min_recon_time = 5.0
|
||||||
|
personality.max_interactions = 3.0
|
||||||
|
personality.max_misses_for_recon = 5.0
|
||||||
|
personality.excited_num_epochs = 10.0
|
||||||
|
personality.bored_num_epochs = 15.0
|
||||||
|
personality.sad_num_epochs = 25.0
|
||||||
|
personality.bond_encounters_factor = 20000.0
|
||||||
|
|
||||||
|
ui.fps = 0.0
|
||||||
|
|
||||||
|
ui.faces.look_r = "( ⚆_⚆)"
|
||||||
|
ui.faces.look_l = "(☉_☉ )"
|
||||||
|
ui.faces.look_r_happy = "( ◕‿◕)"
|
||||||
|
ui.faces.look_l_happy = "(◕‿◕ )"
|
||||||
|
ui.faces.sleep = "(⇀‿‿↼)"
|
||||||
|
ui.faces.sleep2 = "(≖‿‿≖)"
|
||||||
|
ui.faces.awake = "(◕‿‿◕)"
|
||||||
|
ui.faces.bored = "(-__-)"
|
||||||
|
ui.faces.intense = "(°▃▃°)"
|
||||||
|
ui.faces.cool = "(⌐■_■)"
|
||||||
|
ui.faces.happy = "(•‿‿•)"
|
||||||
|
ui.faces.excited = "(ᵔ◡◡ᵔ)"
|
||||||
|
ui.faces.grateful = "(^‿‿^)"
|
||||||
|
ui.faces.motivated = "(☼‿‿☼)"
|
||||||
|
ui.faces.demotivated = "(≖__≖)"
|
||||||
|
ui.faces.smart = "(✜‿‿✜)"
|
||||||
|
ui.faces.lonely = "(ب__ب)"
|
||||||
|
ui.faces.sad = "(╥☁╥ )"
|
||||||
|
ui.faces.angry = "(-_-')"
|
||||||
|
ui.faces.friend = "(♥‿‿♥)"
|
||||||
|
ui.faces.broken = "(☓‿‿☓)"
|
||||||
|
ui.faces.debug = "(#__#)"
|
||||||
|
|
||||||
|
ui.web.enabled = true
|
||||||
|
ui.web.address = "0.0.0.0"
|
||||||
|
ui.web.username = "changeme"
|
||||||
|
ui.web.password = "changeme"
|
||||||
|
ui.web.origin = ""
|
||||||
|
ui.web.port = 8080.0
|
||||||
|
ui.web.on_frame = ""
|
||||||
|
|
||||||
|
ui.display.enabled = true
|
||||||
|
ui.display.rotation = 180.0
|
||||||
|
ui.display.type = "waveshare_2"
|
||||||
|
ui.display.color = "black"
|
||||||
|
|
||||||
|
bettercap.scheme = "http"
|
||||||
|
bettercap.hostname = "localhost"
|
||||||
|
bettercap.port = 8081.0
|
||||||
|
bettercap.username = "pwnagotchi"
|
||||||
|
bettercap.password = "pwnagotchi"
|
||||||
|
bettercap.handshakes = "/root/handshakes"
|
||||||
|
bettercap.silence = [
|
||||||
|
"ble.device.new",
|
||||||
|
"ble.device.lost",
|
||||||
|
"ble.device.disconnected",
|
||||||
|
"ble.device.connected",
|
||||||
|
"ble.device.service.discovered",
|
||||||
|
"ble.device.characteristic.discovered",
|
||||||
|
"wifi.client.new",
|
||||||
|
"wifi.client.lost",
|
||||||
|
"wifi.client.probe",
|
||||||
|
"wifi.ap.new",
|
||||||
|
"wifi.ap.lost",
|
||||||
|
"mod.started"
|
||||||
|
]
|
@ -1,307 +0,0 @@
|
|||||||
#
|
|
||||||
# This file is recreated with default settings on every pwnagotchi restart,
|
|
||||||
# use /etc/pwnagotchi/config.yml to configure this unit.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# main algorithm configuration
|
|
||||||
main:
|
|
||||||
# if set this will set the hostname of the unit. min length is 2, max length 25, only a-zA-Z0-9- allowed
|
|
||||||
name: ''
|
|
||||||
# currently implemented: en (default), de, el, fr, it, mk, nl, ru, se, pt-BR, es, pt
|
|
||||||
lang: en
|
|
||||||
# custom plugins path, if null only default plugins with be loaded
|
|
||||||
custom_plugins:
|
|
||||||
# which plugins to load and enable
|
|
||||||
plugins:
|
|
||||||
switcher:
|
|
||||||
enabled: false
|
|
||||||
tasks:
|
|
||||||
bored:
|
|
||||||
enabled: false
|
|
||||||
reboot: true
|
|
||||||
commands:
|
|
||||||
- systemctl start fisch # see https://github.com/dadav/fisch
|
|
||||||
stopwatch: 15 # timeout of the task (in minutes)
|
|
||||||
grid:
|
|
||||||
enabled: true
|
|
||||||
report: false # don't report pwned networks by default!
|
|
||||||
exclude: # do not report the following networks (accepts both ESSIDs and BSSIDs)
|
|
||||||
- YourHomeNetworkHere
|
|
||||||
auto-update:
|
|
||||||
enabled: true
|
|
||||||
install: true # if false, it will only warn that updates are available, if true it will install them
|
|
||||||
interval: 1 # every 1 hour
|
|
||||||
net-pos:
|
|
||||||
enabled: false
|
|
||||||
api_key: 'test'
|
|
||||||
gps:
|
|
||||||
enabled: false
|
|
||||||
speed: 19200
|
|
||||||
device: /dev/ttyUSB0
|
|
||||||
webgpsmap:
|
|
||||||
enabled: false
|
|
||||||
onlinehashcrack:
|
|
||||||
enabled: false
|
|
||||||
email: ~
|
|
||||||
wpa-sec:
|
|
||||||
enabled: false
|
|
||||||
api_key: ~
|
|
||||||
api_url: "https://wpa-sec.stanev.org"
|
|
||||||
download_results: false
|
|
||||||
wigle:
|
|
||||||
enabled: false
|
|
||||||
api_key: ~
|
|
||||||
bt-tether:
|
|
||||||
enabled: false # if you want to use this, set ui.display.web.address to 0.0.0.0
|
|
||||||
devices:
|
|
||||||
android-phone:
|
|
||||||
enabled: false
|
|
||||||
search_order: 1 # search for this first
|
|
||||||
mac: ~ # mac of your bluetooth device
|
|
||||||
ip: '192.168.44.44' # ip from which your pwnagotchi should be reachable
|
|
||||||
netmask: 24
|
|
||||||
interval: 1 # check every minute for device
|
|
||||||
scantime: 10 # search for 10 seconds
|
|
||||||
max_tries: 10 # after 10 tries of "not found"; don't try anymore
|
|
||||||
share_internet: false
|
|
||||||
priority: 1 # low routing priority; ios (prio: 999) would win here
|
|
||||||
ios-phone:
|
|
||||||
enabled: false
|
|
||||||
search_order: 2 # search for this second
|
|
||||||
mac: ~ # mac of your bluetooth device
|
|
||||||
ip: '172.20.10.6' # ip from which your pwnagotchi should be reachable
|
|
||||||
netmask: 24
|
|
||||||
interval: 5 # check every 5 minutes for device
|
|
||||||
scantime: 20
|
|
||||||
max_tries: 0 # infinity
|
|
||||||
share_internet: false
|
|
||||||
priority: 999 # routing priority
|
|
||||||
memtemp: # Display memory usage, cpu load and cpu temperature on screen
|
|
||||||
enabled: false
|
|
||||||
scale: celsius
|
|
||||||
orientation: horizontal # horizontal/vertical
|
|
||||||
paw-gps:
|
|
||||||
enabled: false
|
|
||||||
#The IP Address of your phone with Paw Server running, default (option is empty) is 192.168.44.1
|
|
||||||
ip: ''
|
|
||||||
gpio_buttons:
|
|
||||||
enabled: false
|
|
||||||
#The following is a list of the GPIO number for your button, and the command you want to run when it is pressed
|
|
||||||
gpios:
|
|
||||||
#20: 'touch /root/.pwnagotchi-auto && systemctl restart pwnagotchi'
|
|
||||||
#21: 'shutdown -h now'
|
|
||||||
led:
|
|
||||||
enabled: true
|
|
||||||
# for /sys/class/leds/led0/brightness
|
|
||||||
led: 0
|
|
||||||
# time in milliseconds for each element of the patterns
|
|
||||||
delay: 200
|
|
||||||
# o=on space=off, comment the ones you don't want
|
|
||||||
patterns:
|
|
||||||
loaded: 'oo oo oo oo oo oo oo'
|
|
||||||
updating: 'oo oo oo oo oo oo oo'
|
|
||||||
# internet_available: 'oo oo oo oo oo oo oo'
|
|
||||||
unread_inbox: 'oo oo oo oo oo oo oo'
|
|
||||||
ready: 'oo oo oo oo oo oo oo'
|
|
||||||
ai_ready: 'oo oo oo oo oo oo oo'
|
|
||||||
ai_training_start: 'oo oo oo oo oo oo oo'
|
|
||||||
ai_best_reward: 'oo oo oo oo oo oo oo'
|
|
||||||
ai_worst_reward: 'oo oo oo oo oo oo oo'
|
|
||||||
bored: 'oo oo oo oo oo oo oo'
|
|
||||||
sad: 'oo oo oo oo oo oo oo'
|
|
||||||
excited: 'oo oo oo oo oo oo oo'
|
|
||||||
lonely: 'oo oo oo oo oo oo oo'
|
|
||||||
rebooting: 'oo oo oo oo oo oo oo'
|
|
||||||
wait: 'oo oo oo oo oo oo oo'
|
|
||||||
sleep: 'oo oo oo oo oo oo oo'
|
|
||||||
wifi_update: 'oo oo oo oo oo oo oo'
|
|
||||||
association: 'oo oo oo oo oo oo oo'
|
|
||||||
deauthentication: 'oo oo oo oo oo oo oo'
|
|
||||||
handshake: 'oo oo oo oo oo oo oo'
|
|
||||||
epoch: 'oo oo oo oo oo oo oo'
|
|
||||||
peer_detected: 'oo oo oo oo oo oo oo'
|
|
||||||
peer_lost: 'oo oo oo oo oo oo oo'
|
|
||||||
webcfg:
|
|
||||||
enabled: false
|
|
||||||
session-stats:
|
|
||||||
enabled: true
|
|
||||||
ups_lite:
|
|
||||||
enabled: false
|
|
||||||
shutdown: 2 # Auto-shutdown when <= 2%
|
|
||||||
# monitor interface to use
|
|
||||||
iface: mon0
|
|
||||||
# command to run to bring the mon interface up in case it's not up already
|
|
||||||
mon_start_cmd: /usr/bin/monstart
|
|
||||||
mon_stop_cmd: /usr/bin/monstop
|
|
||||||
mon_max_blind_epochs: 50
|
|
||||||
# if true, will not restart the wifi module
|
|
||||||
no_restart: false
|
|
||||||
# access points to ignore. Could be the ssid, bssid or the vendor part of bssid.
|
|
||||||
whitelist:
|
|
||||||
- EXAMPLE_NETWORK
|
|
||||||
- ANOTHER_EXAMPLE_NETWORK
|
|
||||||
- fo:od:ba:be:fo:od # BSSID
|
|
||||||
- fo:od:ba # Vendor BSSID
|
|
||||||
# if not null, filter access points by this regular expression
|
|
||||||
filter: null
|
|
||||||
# logging
|
|
||||||
log:
|
|
||||||
# file to log to
|
|
||||||
path: /var/log/pwnagotchi.log
|
|
||||||
rotation:
|
|
||||||
enabled: true
|
|
||||||
# specify a maximum size to rotate ( format is 10/10B, 10K, 10M 10G )
|
|
||||||
size: '10M'
|
|
||||||
|
|
||||||
ai:
|
|
||||||
# if false, only the default 'personality' will be used
|
|
||||||
enabled: true
|
|
||||||
path: /root/brain.nn
|
|
||||||
# 1.0 - laziness = probability of start training
|
|
||||||
laziness: 0.1
|
|
||||||
# how many epochs to train on
|
|
||||||
epochs_per_episode: 50
|
|
||||||
params:
|
|
||||||
# discount factor
|
|
||||||
gamma: 0.99
|
|
||||||
# the number of steps to run for each environment per update
|
|
||||||
n_steps: 1
|
|
||||||
# value function coefficient for the loss calculation
|
|
||||||
vf_coef: 0.25
|
|
||||||
# entropy coefficient for the loss calculation
|
|
||||||
ent_coef: 0.01
|
|
||||||
# maximum value for the gradient clipping
|
|
||||||
max_grad_norm: 0.5
|
|
||||||
# the learning rate
|
|
||||||
learning_rate: 0.0010
|
|
||||||
# rmsprop decay parameter
|
|
||||||
alpha: 0.99
|
|
||||||
# rmsprop epsilon
|
|
||||||
epsilon: 0.00001
|
|
||||||
# the verbosity level: 0 none, 1 training information, 2 tensorflow debug
|
|
||||||
verbose: 1
|
|
||||||
# type of scheduler for the learning rate update ('linear', 'constant', 'double_linear_con', 'middle_drop' or 'double_middle_drop')
|
|
||||||
lr_schedule: 'constant'
|
|
||||||
# the log location for tensorboard (if None, no logging)
|
|
||||||
tensorboard_log: null
|
|
||||||
|
|
||||||
personality:
|
|
||||||
# advertise our presence
|
|
||||||
advertise: true
|
|
||||||
# perform a deauthentication attack to client stations in order to get full or half handshakes
|
|
||||||
deauth: true
|
|
||||||
# send association frames to APs in order to get the PMKID
|
|
||||||
associate: true
|
|
||||||
# list of channels to recon on, or empty for all channels
|
|
||||||
channels: []
|
|
||||||
# minimum WiFi signal strength in dBm
|
|
||||||
min_rssi: -200
|
|
||||||
# number of seconds for wifi.ap.ttl
|
|
||||||
ap_ttl: 120
|
|
||||||
# number of seconds for wifi.sta.ttl
|
|
||||||
sta_ttl: 300
|
|
||||||
# time in seconds to wait during channel recon
|
|
||||||
recon_time: 30
|
|
||||||
# number of inactive epochs after which recon_time gets multiplied by recon_inactive_multiplier
|
|
||||||
max_inactive_scale: 2
|
|
||||||
# if more than max_inactive_scale epochs are inactive, recon_time *= recon_inactive_multiplier
|
|
||||||
recon_inactive_multiplier: 2
|
|
||||||
# time in seconds to wait during channel hopping if activity has been performed
|
|
||||||
hop_recon_time: 10
|
|
||||||
# time in seconds to wait during channel hopping if no activity has been performed
|
|
||||||
min_recon_time: 5
|
|
||||||
# maximum amount of deauths/associations per BSSID per session
|
|
||||||
max_interactions: 3
|
|
||||||
# maximum amount of misses before considering the data stale and triggering a new recon
|
|
||||||
max_misses_for_recon: 5
|
|
||||||
# number of active epochs that triggers the excited state
|
|
||||||
excited_num_epochs: 10
|
|
||||||
# number of inactive epochs that triggers the bored state
|
|
||||||
bored_num_epochs: 15
|
|
||||||
# number of inactive epochs that triggers the sad state
|
|
||||||
sad_num_epochs: 25
|
|
||||||
# number of encounters (times met on a channel) with another unit before considering it a friend and bond
|
|
||||||
# also used for cumulative bonding score of nearby units
|
|
||||||
bond_encounters_factor: 20000
|
|
||||||
|
|
||||||
# ui configuration
|
|
||||||
ui:
|
|
||||||
# here you can customize the faces
|
|
||||||
faces:
|
|
||||||
look_r: '( ⚆_⚆)'
|
|
||||||
look_l: '(☉_☉ )'
|
|
||||||
look_r_happy: '( ◕‿◕)'
|
|
||||||
look_l_happy: '(◕‿◕ )'
|
|
||||||
sleep: '(⇀‿‿↼)'
|
|
||||||
sleep2: '(≖‿‿≖)'
|
|
||||||
awake: '(◕‿‿◕)'
|
|
||||||
bored: '(-__-)'
|
|
||||||
intense: '(°▃▃°)'
|
|
||||||
cool: '(⌐■_■)'
|
|
||||||
happy: '(•‿‿•)'
|
|
||||||
excited: '(ᵔ◡◡ᵔ)'
|
|
||||||
grateful: '(^‿‿^)'
|
|
||||||
motivated: '(☼‿‿☼)'
|
|
||||||
demotivated: '(≖__≖)'
|
|
||||||
smart: '(✜‿‿✜)'
|
|
||||||
lonely: '(ب__ب)'
|
|
||||||
sad: '(╥☁╥ )'
|
|
||||||
angry: "(-_-')"
|
|
||||||
friend: '(♥‿‿♥)'
|
|
||||||
broken: '(☓‿‿☓)'
|
|
||||||
debug: '(#__#)'
|
|
||||||
# ePaper display can update every 3 secs anyway, set to 0 to only refresh for major data changes
|
|
||||||
# IMPORTANT: The lifespan of an eINK display depends on the cumulative amount of refreshes. If you want to
|
|
||||||
# preserve your display over time, you should set this value to 0.0 so that the display will be refreshed only
|
|
||||||
# if any of the important data fields changed (the uptime and blinking cursor won't trigger a refresh).
|
|
||||||
fps: 0.0
|
|
||||||
# web ui
|
|
||||||
web:
|
|
||||||
enabled: true
|
|
||||||
address: '0.0.0.0'
|
|
||||||
username: changeme # !!! CHANGE THIS !!!
|
|
||||||
password: changeme # !!! CHANGE THIS !!!
|
|
||||||
origin: null
|
|
||||||
port: 8080
|
|
||||||
# command to be executed when a new png frame is available
|
|
||||||
# for instance, to use with framebuffer based displays:
|
|
||||||
# on_frame: 'fbi --noverbose -a -d /dev/fb1 -T 1 /root/pwnagotchi.png > /dev/null 2>&1'
|
|
||||||
on_frame: ''
|
|
||||||
# hardware display
|
|
||||||
display:
|
|
||||||
enabled: true
|
|
||||||
rotation: 180
|
|
||||||
# Possible options inkyphat/inky, papirus/papi, waveshare_1/ws_1 or waveshare_2/ws_2, oledhat, lcdhat, waveshare154inch, waveshare27inch, waveshare29inch, dfrobot/df, waveshare144lcd/ws144inch
|
|
||||||
type: 'waveshare_2'
|
|
||||||
# Possible options red/yellow/black (black used for monocromatic displays)
|
|
||||||
# Waveshare tri-color 2.13in display can be over-driven with color set as 'fastAndFurious'
|
|
||||||
# THIS IS POTENTIALLY DANGEROUS. DO NOT USE UNLESS YOU UNDERSTAND THAT IT COULD KILL YOUR DISPLAY
|
|
||||||
color: 'black'
|
|
||||||
|
|
||||||
# bettercap rest api configuration
|
|
||||||
bettercap:
|
|
||||||
# api scheme://hostname:port username and password
|
|
||||||
scheme: http
|
|
||||||
hostname: localhost
|
|
||||||
port: 8081
|
|
||||||
username: pwnagotchi
|
|
||||||
password: pwnagotchi
|
|
||||||
# folder where bettercap stores the WPA handshakes, given that
|
|
||||||
# wifi.handshakes.aggregate will be set to false and individual
|
|
||||||
# pcap files will be created in order to minimize the chances
|
|
||||||
# of a single pcap file to get corrupted
|
|
||||||
handshakes: /root/handshakes
|
|
||||||
# events to mute in bettercap's events stream
|
|
||||||
silence:
|
|
||||||
- ble.device.new
|
|
||||||
- ble.device.lost
|
|
||||||
- ble.device.disconnected
|
|
||||||
- ble.device.connected
|
|
||||||
- ble.device.service.discovered
|
|
||||||
- ble.device.characteristic.discovered
|
|
||||||
- wifi.client.new
|
|
||||||
- wifi.client.lost
|
|
||||||
- wifi.client.probe
|
|
||||||
- wifi.ap.new
|
|
||||||
- wifi.ap.lost
|
|
||||||
- mod.started
|
|
@ -154,7 +154,7 @@ class AutoUpdate(plugins.Plugin):
|
|||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
|
|
||||||
def on_loaded(self):
|
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")
|
logging.error("[update] main.plugins.auto-update.interval is not set")
|
||||||
return
|
return
|
||||||
self.ready = True
|
self.ready = True
|
||||||
|
@ -437,7 +437,7 @@ class BTTether(plugins.Plugin):
|
|||||||
for device_opt in ['enabled', 'priority', 'scantime', 'search_order',
|
for device_opt in ['enabled', 'priority', 'scantime', 'search_order',
|
||||||
'max_tries', 'share_internet', 'mac', 'ip',
|
'max_tries', 'share_internet', 'mac', 'ip',
|
||||||
'netmask', 'interval']:
|
'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.",
|
logging.error("BT-TETHER: Please specify the %s for device %s.",
|
||||||
device_opt, device)
|
device_opt, device)
|
||||||
break
|
break
|
||||||
@ -448,7 +448,7 @@ class BTTether(plugins.Plugin):
|
|||||||
# legacy
|
# legacy
|
||||||
if 'mac' in self.options:
|
if 'mac' in self.options:
|
||||||
for opt in ['share_internet', 'mac', 'ip', 'netmask', 'interval']:
|
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)
|
logging.error("BT-TETHER: Please specify the %s in your config.yml.", opt)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class NetPos(plugins.Plugin):
|
|||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
def on_loaded(self):
|
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.")
|
logging.error("NET-POS: api_key isn't set. Can't use mozilla's api.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class OnlineHashCrack(plugins.Plugin):
|
|||||||
"""
|
"""
|
||||||
Gets called when the plugin gets loaded
|
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")
|
logging.error("OHC: Email isn't set. Can't upload to onlinehashcrack.com")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import yaml
|
import toml
|
||||||
import _thread
|
import _thread
|
||||||
import pwnagotchi.plugins as plugins
|
import pwnagotchi.plugins as plugins
|
||||||
from pwnagotchi import restart
|
from pwnagotchi import restart
|
||||||
from flask import abort
|
from flask import abort
|
||||||
from flask import render_template_string
|
from flask import render_template_string
|
||||||
|
|
||||||
|
|
||||||
INDEX = """
|
INDEX = """
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@ -500,13 +499,13 @@ class WebConfig(plugins.Plugin):
|
|||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
if path == "save-config":
|
if path == "save-config":
|
||||||
try:
|
try:
|
||||||
parsed_yaml = yaml.safe_load(str(request.get_json()))
|
parsed_toml = toml.loads(request.get_json())
|
||||||
with open('/etc/pwnagotchi/config.yml', 'w') as config_file:
|
with open('/etc/pwnagotchi/config.toml') as config_file:
|
||||||
yaml.safe_dump(parsed_yaml, config_file, encoding='utf-8',
|
toml.dump(parsed_toml, config_file)
|
||||||
allow_unicode=True, default_flow_style=False)
|
|
||||||
|
|
||||||
_thread.start_new_thread(restart, (self.mode,))
|
_thread.start_new_thread(restart, (self.mode,))
|
||||||
return "success"
|
return "success"
|
||||||
except yaml.YAMLError as yaml_ex:
|
except Exception as ex:
|
||||||
|
logging.error(ex)
|
||||||
return "config error"
|
return "config error"
|
||||||
abort(404)
|
abort(404)
|
||||||
|
@ -70,11 +70,11 @@ class WpaSec(plugins.Plugin):
|
|||||||
"""
|
"""
|
||||||
Gets called when the plugin gets loaded
|
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")
|
logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org")
|
||||||
return
|
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.")
|
logging.error("WPA_SEC: API-URL isn't set. Can't upload, no endpoint configured.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import shutil
|
|||||||
import gzip
|
import gzip
|
||||||
import contextlib
|
import contextlib
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import toml
|
||||||
|
|
||||||
import pwnagotchi
|
import pwnagotchi
|
||||||
|
|
||||||
@ -32,15 +33,17 @@ def load_config(args):
|
|||||||
if not os.path.exists(default_config_path):
|
if not os.path.exists(default_config_path):
|
||||||
os.makedirs(default_config_path)
|
os.makedirs(default_config_path)
|
||||||
|
|
||||||
ref_defaults_file = os.path.join(os.path.dirname(pwnagotchi.__file__), 'defaults.yml')
|
ref_defaults_file = os.path.join(os.path.dirname(pwnagotchi.__file__), 'defaults.toml')
|
||||||
ref_defaults_data = None
|
ref_defaults_data = None
|
||||||
|
|
||||||
# check for a config.yml file on /boot/
|
# check for a config.yml file on /boot/
|
||||||
if os.path.exists("/boot/config.yml"):
|
for boot_conf in ['/boot/config.yml', '/boot/config.toml']:
|
||||||
# logging not configured here yet
|
if os.path.exists(boot_conf):
|
||||||
print("installing /boot/config.yml to %s ...", args.user_config)
|
# logging not configured here yet
|
||||||
# https://stackoverflow.com/questions/42392600/oserror-errno-18-invalid-cross-device-link
|
print("installing %s to %s ...", boot_conf, args.user_config)
|
||||||
shutil.move("/boot/config.yml", args.user_config)
|
# https://stackoverflow.com/questions/42392600/oserror-errno-18-invalid-cross-device-link
|
||||||
|
shutil.move(boot_conf, args.user_config)
|
||||||
|
break
|
||||||
|
|
||||||
# check for an entire pwnagotchi folder on /boot/
|
# check for an entire pwnagotchi folder on /boot/
|
||||||
if os.path.isdir('/boot/pwnagotchi'):
|
if os.path.isdir('/boot/pwnagotchi'):
|
||||||
@ -54,6 +57,7 @@ def load_config(args):
|
|||||||
shutil.copy(ref_defaults_file, args.config)
|
shutil.copy(ref_defaults_file, args.config)
|
||||||
else:
|
else:
|
||||||
# check if the user messed with the defaults
|
# check if the user messed with the defaults
|
||||||
|
|
||||||
with open(ref_defaults_file) as fp:
|
with open(ref_defaults_file) as fp:
|
||||||
ref_defaults_data = fp.read()
|
ref_defaults_data = fp.read()
|
||||||
|
|
||||||
@ -66,18 +70,28 @@ def load_config(args):
|
|||||||
|
|
||||||
# load the defaults
|
# load the defaults
|
||||||
with open(args.config) as fp:
|
with open(args.config) as fp:
|
||||||
config = yaml.safe_load(fp)
|
config = toml.load(fp)
|
||||||
|
|
||||||
# load the user config
|
# load the user config
|
||||||
try:
|
try:
|
||||||
if os.path.exists(args.user_config):
|
user_config = None
|
||||||
with open(args.user_config) as fp:
|
# migrate
|
||||||
user_config = yaml.safe_load(fp)
|
yaml_name = args.user_config.replace('.toml', '.yml')
|
||||||
# if the file is empty, safe_load will return None and merge_config will boom.
|
if not os.path.exists(args.user_config) and os.path.exists(yaml_name):
|
||||||
if user_config:
|
# no toml found; convert yaml
|
||||||
config = merge_config(user_config, config)
|
logging.info('Old yaml-config found. Converting to toml...')
|
||||||
except yaml.YAMLError as ex:
|
with open(args.user_config, 'w') as toml_file, open(yaml_name) as yaml_file:
|
||||||
print("There was an error processing the configuration file:\n%s " % ex)
|
user_config = yaml.safe_load(yaml_file)
|
||||||
|
# convert to toml but use loaded yaml
|
||||||
|
toml.dump(user_config, toml_file)
|
||||||
|
elif os.path.exists(args.user_config):
|
||||||
|
with open(args.user_config) as toml_file:
|
||||||
|
user_config = toml.load(toml_file)
|
||||||
|
|
||||||
|
if user_config:
|
||||||
|
config = merge_config(user_config, config)
|
||||||
|
except Exception as ex:
|
||||||
|
logging.error("There was an error processing the configuration file:\n%s ",ex)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# the very first step is to normalize the display name so we don't need dozens of if/elif around
|
# the very first step is to normalize the display name so we don't need dozens of if/elif around
|
||||||
|
@ -18,3 +18,4 @@ gast==0.2.2
|
|||||||
flask==1.0.2
|
flask==1.0.2
|
||||||
flask-cors==3.0.7
|
flask-cors==3.0.7
|
||||||
flask-wtf==0.14.2
|
flask-wtf==0.14.2
|
||||||
|
toml==0.10.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user