Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed Firefox customization issue and added support for addons in my-resources #120

Merged
merged 8 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions sources/exegol/load_supported_setups.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ function run_user_setup() {
echo "[$(date +'%d-%m-%Y_%H-%M-%S')] ==== End of custom setups loading ===="
}

function deploy_firefox_addons() {
if [ -d "$MY_Setup_PATH/firefox/" ]; then
if [ -d "$MY_Setup_PATH/firefox/addons" ]; then
ADDON_FOLDER="-D $MY_Setup_PATH/firefox/addons"
fi
if [ -f "$MY_Setup_PATH/firefox/addons.txt" ]; then
ADDON_LIST="-L $MY_Setup_PATH/firefox/addons.txt"
fi
python3 /opt/tools/firefox/user-setup.py $ADDON_LIST $ADDON_FOLDER
fi
Skileau marked this conversation as resolved.
Show resolved Hide resolved
}

# Starting
# This procedure is supposed to be executed only once at the first startup, using a lockfile check

Expand All @@ -124,7 +136,10 @@ deploy_tmux
deploy_vim
deploy_apt
deploy_python3
deploy_firefox_addons
Dramelac marked this conversation as resolved.
Show resolved Hide resolved

run_user_setup

exit 0

}
3 changes: 2 additions & 1 deletion sources/firefox/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
R2Log
R2Log
requests
48 changes: 26 additions & 22 deletions sources/firefox/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,21 @@
# Date created : 27 February 2023
# Python Version : 3.*

import glob
import json
import os
import re
import shutil
import subprocess
import time
import zipfile
import sqlite3
from pathlib import Path

import requests
from pathlib import Path
from time import sleep
from R2Log import logger
from glob import glob

PATHNAME = "/root/.mozilla/firefox/**.Exegol/"

# pip3 install R2Log
# Define addons urls
urls = [
"https://addons.mozilla.org/fr/firefox/addon/foxyproxy-standard/",
Expand Down Expand Up @@ -51,30 +49,30 @@ def download_addon(link, addon_name):
logger.info(f"Downloading addon {addon_name}")
addon_dl = requests.get(link)
# Save xpi addon on filesystem
with open(addon_name, 'wb') as addon_file:
with open("/tmp/" + addon_name, 'wb') as addon_file:
addon_file.write(addon_dl.content)


def read_manifest(addon_name):
archive = zipfile.ZipFile(addon_name, 'r')
def read_manifest(addon_path):
archive = zipfile.ZipFile(addon_path, 'r')
manifest = archive.read('manifest.json').decode()
# Read the id in the manifest
addon_id = re.search(reid, manifest).group(1)
return addon_id


def install_addons(addon_name, addon_id):
def install_addons(addon_name, addon_id, addon_path):
logger.info(f"Installing addon {addon_name} with id {addon_id}")
# Get the path of the Exegol profile
try:
dest = glob.glob("%s" % PATHNAME)[0]
dest = glob("%s" % PATHNAME)[0]
except:
logger.error("Firefox profile Exegol does not exist")
raise
# Create the extensions folder
Path(dest + "/extensions").mkdir(parents=True, exist_ok=True)
# Move the addon to the extensions folder
shutil.move(addon_name, dest + "/extensions/" + addon_id + ".xpi")
shutil.move(addon_path + "/" + addon_name, dest + "/extensions/" + addon_id + ".xpi")


def activate_addons(addon_list):
Expand All @@ -85,7 +83,7 @@ def activate_addons(addon_list):
else:
logger.info(f"Enabling {addon_name}")
try:
with open(Path(glob.glob("%s" % PATHNAME)[0] + "/extensions.json"), 'r+') as extensions_file:
with open(Path(glob("%s" % PATHNAME)[0] + "/extensions.json"), 'r+') as extensions_file:
extensions_config = json.load(extensions_file)
for addon in extensions_config["addons"]:
if addon["id"] == addon_id:
Expand All @@ -107,7 +105,7 @@ def activate_addons(addon_list):
pass

def adjust_ui():
with open(Path(glob.glob("%s" % PATHNAME)[0] + "/prefs.js"), 'r+') as pref_js:
with open(Path(glob("%s" % PATHNAME)[0] + "/prefs.js"), 'r+') as pref_js:
new_pref = re.sub(r'\\"import-button\\",', '', pref_js.read())
new_pref = re.sub(r'\\"save-to-pocket-button\\",', '', new_pref)
new_pref = re.sub('"extensions.activeThemeID", "default-theme@mozilla.org"', '"extensions.activeThemeID", "firefox-compact-dark@mozilla.org"', new_pref)
Expand All @@ -119,7 +117,7 @@ def import_bookmarks():
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, './places.sqlite')
src = sqlite3.connect(filename)
dst = sqlite3.connect(glob.glob("%s" % PATHNAME)[0] + "places.sqlite")
dst = sqlite3.connect(glob("%s" % PATHNAME)[0] + "places.sqlite")
with dst:
src.backup(dst)
dst.close()
Expand All @@ -131,7 +129,7 @@ def import_bookmarks():
logger.info("Creating Firefox profile")
try:
subprocess.run(["firefox", "-CreateProfile", "Exegol", "-headless"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
assert(Path(glob.glob("%s" % PATHNAME)[0]).is_dir())
assert(Path(glob("%s" % PATHNAME)[0]).is_dir())
logger.success("Firefox profile Exegol created\n")
except:
logger.error("Could not create Firefox profile Exegol")
Expand All @@ -147,8 +145,8 @@ def import_bookmarks():
# Download the addon
download_addon(link, addon_name)
# Read manifest.json in the archive
addon_id = read_manifest(addon_name)
install_addons(addon_name, addon_id)
addon_id = read_manifest("/tmp/" + addon_name)
install_addons(addon_name, addon_id, "/tmp/")
logger.success(f"{addon_name} installed sucessfully\n")
addon_list.append((addon_id, addon_name[0:-4], False))

Expand All @@ -158,9 +156,11 @@ def import_bookmarks():
logger.info("Initialising Firefox profile")
try:
p_firefox = subprocess.Popen(["firefox", "-P", "Exegol", "-headless"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
time.sleep(5)
# Wait for firefox to be initialised
while not b'sessionstore-backups' in subprocess.check_output(["ls", glob("%s" % PATHNAME)[0]]):
sleep(0.5)
p_firefox.kill()
assert(Path(glob.glob("%s" % PATHNAME)[0] + "/extensions.json").is_file())
assert(Path(glob("%s" % PATHNAME)[0] + "/extensions.json").is_file())
logger.success("Firefox profile initialised sucessfully\n")
except:
logger.error("Could not initialise Firefox profile")
Expand All @@ -178,10 +178,11 @@ def import_bookmarks():
try:
adjust_ui()
# Remove existing sessions
shutil.rmtree(glob.glob("%s" % PATHNAME)[0] + "sessionstore-backups")
shutil.rmtree(glob("%s" % PATHNAME)[0] + "sessionstore-backups")
logger.success("User interface successfully updated\n")
except:
logger.error("An error has occurred while trying to update user interface\n")
raise

# Restore bookmarks
logger.info("Setting up profile's bookmarks")
Expand All @@ -195,7 +196,7 @@ def import_bookmarks():
# Remove backup file interfering with addons activation
logger.info("Removing backup file interfering with addons activation")
try:
Path(glob.glob("%s" % PATHNAME)[0] + "/addonStartup.json.lz4").unlink()
Path(glob("%s" % PATHNAME)[0] + "/addonStartup.json.lz4").unlink()
logger.success("Backup file successfully removed\n")
except:
logger.error("Could not remove the backup file")
Expand All @@ -205,8 +206,11 @@ def import_bookmarks():
logger.info("Restarting firefox to apply modifications")
try:
p_firefox = subprocess.Popen(["firefox", "-headless"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
time.sleep(5)
# Wait for modifications to be applied
while not b'addonStartup.json.lz4' in subprocess.check_output(["ls", glob("%s" % PATHNAME)[0]]):
sleep(0.5)
p_firefox.kill()
logger.success("Modifications successfully applied")
except:
logger.error("Could not restart firefox")
raise
110 changes: 110 additions & 0 deletions sources/firefox/user-setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
# -- coding: utf-8 --
# File name : user-setup.py
# Author : Skilo (@askilow - Alexis Marquois)
# Date created : 07 march 2023
# Python Version : 3.*

from setup import get_link, download_addon, read_manifest, install_addons, activate_addons
from R2Log import logger
from pathlib import Path
from glob import glob
from time import sleep
import re
import subprocess
import argparse

PATHNAME = "/root/.mozilla/firefox/**.Exegol/"
re_links = r'https://addons\.mozilla\.org/fr/firefox/addon/[^/]+'

def parse_args():
arg_parser = argparse.ArgumentParser(description="Automatically installs addons from a list or folder containing .xpi files.")
arg_parser.add_argument('-L', dest="addon_links", help="txt document containing addon link (ie: https://addons.mozilla.org/fr/firefox/addon/duckduckgo-for-firefox).")
arg_parser.add_argument('-D', dest="addon_folder", help="Path to a folder containing .xpi files to install.")
args = arg_parser.parse_args()
return args

if __name__ == "__main__":

args = parse_args()
addon_links = args.addon_links
addon_folder = args.addon_folder
install_ok = False

# Define a list containing all addons names and ids
addon_list = []

if addon_links is not None:
# Read the list input by the user
with open(addon_links, "r") as url_file:
urls = url_file.read().splitlines()

# Iterate through addons
for url in urls:
if re.findall(re_links, url):
# Make a request to the URL
link, addon_name = get_link(url)
# Download the addon
download_addon(link, addon_name)
# Read manifest.json in the archive
addon_id = read_manifest("/tmp/" + addon_name)
install_addons(addon_name, addon_id, "/tmp/")
logger.success(f"{addon_name} installed sucessfully\n")
addon_list.append((addon_id, addon_name[0:-4], False))
install_ok = True
logger.success("All addons from the list were installed sucessfully\n")

if addon_folder is not None:
if glob(addon_folder + "/*.xpi"):
for addon_path in glob(addon_folder + "/*.xpi"):
addon_name = addon_path.split("/")[-1]
addon_id = read_manifest(addon_path)
install_addons(addon_name, addon_id, addon_folder)
logger.success(f"{addon_name} installed sucessfully\n")
addon_list.append((addon_id, addon_name[0:-4], False))
install_ok = True
logger.success("All addons from the folder %s were installed sucessfully\n" % addon_folder)
else:
logger.error("No addons were found in the folder %s." % addon_folder)

if install_ok:
# Run firefox to initialise profile
logger.info("Initialising Firefox profile")
try:
p_firefox = subprocess.Popen(["firefox", "-P", "Exegol", "-headless"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
# Wait for firefox to be initialised
while not addon_list[0][0].encode() in subprocess.check_output(["cat", glob("%s" % PATHNAME)[0] + "/extensions.json"]):
sleep(0.5)
p_firefox.kill()
assert(Path(glob("%s" % PATHNAME)[0] + "/extensions.json").is_file())
logger.success("Firefox profile initialised sucessfully\n")
except:
logger.error("Could not initialise Firefox profile")
raise

# Activate all addons
activate_addons(addon_list)

# Remove backup file interfering with addons activation
logger.info("Removing backup file interfering with addons activation")
try:
Path(glob("%s" % PATHNAME)[0] + "/addonStartup.json.lz4").unlink()
logger.success("Backup file successfully removed\n")
except:
logger.error("Could not remove the backup file")
raise

# Restart firefox to apply modifications
logger.info("Restarting firefox to apply modifications")
try:
p_firefox = subprocess.Popen(["firefox", "-headless"], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
# Wait for modifications to be applied
while not b'addonStartup.json.lz4' in subprocess.check_output(["ls", glob("%s" % PATHNAME)[0]]):
sleep(0.5)
p_firefox.kill()
logger.success("Modifications successfully applied")
except:
logger.error("Could not restart firefox")
raise
else:
logger.error("No addons were found.")
3 changes: 2 additions & 1 deletion sources/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3270,11 +3270,12 @@ function install_ctf-party() {

function install_firefox() {
colorecho "Installing firefox"
fapt firefox-esr
mkdir /opt/tools/firefox
mv /root/sources/firefox/* /opt/tools/firefox/
python3 -m pip install -r /opt/tools/firefox/requirements.txt
python3 /opt/tools/firefox/setup.py
add-test-command "firefox --version"
Skileau marked this conversation as resolved.
Show resolved Hide resolved
add-test-command "file /root/.mozilla/firefox/*.Exegol"
}

# Package dedicated to the basic things the env needs
Expand Down