Skip to content
Permalink
Browse files

Add Firefox policies.json support for Linux (#404)

Uses policies.json "Install:" technique, unique to Linux
  • Loading branch information...
tresf committed Jan 30, 2019
1 parent ef3d2aa commit ec2f876e45403285602d5a412bee9eb2954a07c4
Showing with 72 additions and 28 deletions.
  1. +45 −26 ant/firefox/firefox-cert.sh.in
  2. +24 −2 ant/firefox/firefox-json-writer.py
  3. +3 −0 build.xml
@@ -4,12 +4,14 @@
###############################################################################
# Description: #
# INSTALL: #
# 1. Searches for Firefox installation path #
# 2. Parses defaults/pref for potential Firefox AutoConfig conflicts #
# 3. Imports certificate into Firefox web browser using AutoConfig file #
# * Searches for Firefox installation path #
# * Automatically installs (or toggles on) the use of a custom SSL #
# certificate based on Firefox version and OS using a combination of #
# legacy AutoConfig or polcies.json #
# #
# UNINSTALL: #
# 1. Deletes certificate from Firefox web browser using AutoConfig file #
# * If necessary, automatically deletes the custom SSL certificate using #
# a combination of legacy AutoConfig or policies.json #
# #
# Depends: #
# - lsregister (Apple-only, provided by launch services) #
@@ -48,42 +50,43 @@ echo "Searching for Firefox..."

ffdir=""
if [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OSX
# macOS
locationdir=$(cd "$(dirname "$0")"; pwd)
get_ffdir

# Use policies.json deployment (Firefox 63+)
if [ -n "$ffdir" ]; then
version=$(HOME=/tmp "$ffdir/Contents/MacOS/firefox" --version|rev|cut -d' ' -f1|rev|cut -d. -f1)
if [ "$version" -ge "63" ]; then
policy='{ "policies": { "Certificates": { "ImportEnterpriseRoots": true } } }'
policypath="$ffdir/Contents/Resources/distribution/policies.json"
fi
fi

bindir="$ffdir/Contents/Resources/"
prefdir="$ffdir/Contents/Resources/defaults/pref"
installdir="${apple.installdir}"
trayapp="$installdir" # use .app package

# Use policies.json deployment (Firefox 63+)
if [ -n "$ffdir" ]; then
version=$(HOME=/tmp "$ffdir/Contents/MacOS/firefox" --version|rev|cut -d' ' -f1|rev|cut -d. -f1)
if [ "$version" -ge "63" ]; then
policy='{ "policies": { "Certificates": { "ImportEnterpriseRoots": true } } }'
policypath="$ffdir/Contents/Resources/distribution/policies.json"
fi
fi
else
# Linux, etc
location=$(readlink -f "$0")
locationdir=$(dirname "$location")
get_ffdir

# Use policies.json deployment (Firefox 64+)
if [ -n "$ffdir" ]; then
version=$(HOME=/tmp XAUTHORITY=/tmp $ffdir/firefox --version|rev|cut -d' ' -f1|rev|cut -d. -f1)
if [ "$version" -ge "64" ]; then
policy='' # TODO
policypath="$ffdir/distribution/policies.json"
fi
fi

bindir="$ffdir"
prefdir="$ffdir/defaults/pref"
installdir="${linux.installdir}"
dercertpath=$(echo "${ca.crt}" | sed -e "s|\!install|$installdir|g")
trayapp="" # skip

# Use policies.json deployment (Firefox 65+)
if [ -n "$ffdir" ]; then
version=$(HOME=/tmp XAUTHORITY=/tmp $ffdir/firefox --version|rev|cut -d' ' -f1|rev|cut -d. -f1)
if [ "$version" -ge "65" ]; then
policy='{ "policies": { "Certificates": { "Install": ["'$dercertpath'"] } } }'
policypath="$ffdir/distribution/policies.json"
fi
fi
fi

# Firefox was not found, skip Firefox certificate installation
@@ -111,10 +114,24 @@ configpath=$(echo "${firefoxconfig.install}" | sed -e "s|\!install|$installdir|g
if [ "$1" == "uninstall" ]; then
# Newer Firefox versions don't use AutoConfig
if [ -n "$policy" ]; then
echo -e "${bash.skipped} Configured via policies.json, no uninstall needed"
exit 0
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
echo -e "${bash.skipped} Configured via policies.json, no uninstall needed"
exit 0
else
# Linux, etc
echo -e "\nSearching for $policypath..."
if [ -f "$policypath" ]; then
# Delete cert entry
"$locationdir/${jsonwriter.name}" "$policypath" "$policy" "" "true"
echo -e "${bash.success} Deleted cert entry"
exit 0
else
echo -e "${bash.skipped} $policypath not found"
exit 0
fi
fi
fi

echo -e "\nSearching for ${project.name} AutoConfig..."
if [ -f "$bindir/${firefoxconfig.name}" ]; then
echo -e "${bash.success} Check Firefox config exists"
@@ -151,6 +168,8 @@ fi
# Use policy file
if [ -n "$policy" ]; then
"$locationdir/${jsonwriter.name}" "$policypath" "$policy"
chmod go+r "$policypath"
chmod go+rx "$(dirname "$policypath")"
echo -e "${bash.success} Installed $policypath"
exit 0
fi
@@ -8,10 +8,12 @@
DEFAULT_PATH = '/Applications/Firefox.app/Contents/Resources/distribution/policies.json'
DEFAULT_DATA = '{ "policies": { "Certificates": { "ImportEnterpriseRoots": true } } }'
DEFAULT_OVERWRITE = False
DEFAULT_DELETE = False

path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_PATH
merge = json.loads(sys.argv[2]) if len(sys.argv) > 2 else json.loads(DEFAULT_DATA)
overwrite = sys.argv[3].lower() == 'true' if len(sys.argv) > 3 else DEFAULT_OVERWRITE
deletion = sys.argv[4].lower() == 'true' if len(sys.argv) > 4 else DEFAULT_DELETE


def mkdir_p(path):
@@ -51,11 +53,31 @@ def merge_json(base, append):
base[key] = val
elif type(base_val) is list and type(val) is list:
# merge list if not overwritten
base[key] = base_val + val
for v in val:
if v not in base_val:
base_val.append(v)


def delete_json(base, append):
""" Removes values in append from base """
for key, val in append.items():
base_val = base.get(key)

if type(base_val) is dict and type(val) is dict:
delete_json(base_val, val)
elif type(base_val) is list and type(val) is list:
for v in val:
if v in base_val:
base_val.remove(v)
elif base_val is not None:
base.pop(key)


policy = load_json(path)
merge_json(policy, merge)
if deletion:
delete_json(policy, merge)
else:
merge_json(policy, merge)

mkdir_p(os.path.dirname(path))
stream = open(path, "w+")
@@ -503,6 +503,9 @@
</copy>
<chmod perm="u+x" file="${locator.out}"/>

<copy file="${jsonwriter.in}" tofile="${jsonwriter.out}" ></copy>
<chmod perm="u+x" file="${jsonwriter.out}"/>

<exec executable="${linux.packager.out}" failonerror="true" />

<!-- Cleanup lingering icon (for other OS installers) -->

0 comments on commit ec2f876

Please sign in to comment.
You can’t perform that action at this time.