Skip to content

Commit 7e69350

Browse files
authoredJun 29, 2017
Fix SSL connections on Firefox 54+ (qzind#201)
* Fix SSL connections on Firefox 54+ Closes qzind#200
1 parent 655425d commit 7e69350

12 files changed

+488
-503
lines changed
 

‎ant/apple/apple-keygen.sh.in

+127-160
Original file line numberDiff line numberDiff line change
@@ -7,241 +7,208 @@
77
# 2. Exports public certificate from Java Keystore #
88
# 3. Imports into Apple OS X Trusted Root Certs #
99
# #
10-
# Note: If [sslcert] and [sslkey] are specified, import to browser/OS is omitted. #
10+
# Note: If [trustedcert] and [trustedkey] are specified, import to browser/OS is #
11+
# omitted. #
1112
# #
1213
# Depends: #
1314
# java #
1415
# #
1516
# Optional: #
16-
# openssl - Required if providing [sslcert], [sslkey] parameters #
17+
# openssl - Required if providing [trustedcert], [trustedkey] parameters #
1718
# #
1819
# Usage: #
19-
# $ ./${apple.keygen.name} "install" [hostname] [sslcert] [sslkey] #
20+
# $ ./${apple.keygen.name} "install" [hostname] [trustedcert] [trustedkey] #
2021
# $ ./${apple.keygen.name} "uninstall" #
2122
# #
2223
##########################################################################################
2324

24-
# Random password hash
25-
password=$(cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-z0-9' | fold -w ${jks.passlength} | head -n 1)
26-
27-
# Check for java
28-
${apple.jvmver} > /dev/null 2>&1
29-
fallback=$?
25+
# Handle CN=${ssl.cn} override
26+
cnoverride="$2"
3027

31-
#
3228
# Handle trusted ssl certificate
3329
if [[ -n $3 && -n $4 ]]; then
34-
sslcertpath="$3"
35-
sslkeypath="$4"
36-
makekeystore="${ssl.convert}"
37-
else
38-
makekeystore="${jks.command}"
39-
fi
40-
41-
42-
makedercert="${der.command}"
43-
installdir="${apple.installdir}"
44-
45-
# Substitution variables (!storepass, !keypass, !install, etc)
46-
install="${jks.install}"
47-
storepass="${jks.storepass}"
48-
keypass="${jks.keypass}"
49-
keystore="${jks.keystore}"
50-
dercert="${der.cert}"
51-
props="${jks.properties}"
52-
keytool="${jks.keytool}"
53-
keytoolfallback="${apple.jvmfallback}/${jks.keytool}"
54-
55-
# Keystore generation variable substitutions
56-
keystorepath=$(echo "$keystore" | sed -e "s|$install|$installdir|g")
57-
makekeystore=$(echo "$makekeystore" | sed -e "s|$storepass|$password|g")
58-
makekeystore=$(echo "$makekeystore" | sed -e "s|$keypass|$password|g")
59-
makekeystore=$(echo "$makekeystore" | sed -e "s|$keystore|$keystorepath|g")
60-
61-
62-
if [ $fallback -eq 0 ]; then
63-
# Prefix with java_home --exec
64-
makekeystore="${apple.jvmcmd} $makekeystore"
65-
else
66-
# Fallback on Internet Plug-Ins version if needed
67-
makekeystore=$(echo "$makekeystore" | sed -e "s|$keytool|$keytoolfallback|g")
30+
trustedcertpath="$3"
31+
trustedkeypath="$4"
6832
fi
6933

70-
# Cert export variable substitutions
71-
dercertpath=$(echo "$dercert" | sed -e "s|$install|$installdir|g")
72-
makedercert=$(echo "$makedercert" | sed -e "s|$storepass|$password|g")
73-
makedercert=$(echo "$makedercert" | sed -e "s|$keypass|$password|g")
74-
makedercert=$(echo "$makedercert" | sed -e "s|$keystore|$keystorepath|g")
75-
makedercert=$(echo "$makedercert" | sed -e "s|$dercert|$dercertpath|g")
34+
# Random password hash
35+
password=$(cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-z0-9' | fold -w ${ssl.passlength} | head -n 1)
7636

77-
if [ $fallback -eq 0 ]; then
37+
if ${apple.jvmver} > /dev/null 2>&1; then
7838
# Prefix with java_home --exec
79-
makedercert="${apple.jvmcmd} $makedercert"
39+
keytoolcmd="${apple.jvmcmd} keytool"
8040
else
8141
# Fallback on Internet Plug-Ins version if needed
82-
makedercert=$(echo "$makedercert" | sed -e "s|$keytool|$keytoolfallback|g")
83-
fi
84-
85-
# // Handle "community" mode, custom signing auth cert
86-
if [ -n "${build.type}" ]; then
87-
authcert="${authcert.install}"
88-
authcertpath=$(echo "$authcert" | sed -e "s|$install|$installdir|g")
42+
keytoolcmd="${apple.jvmfallback}/keytool"
8943
fi
9044

45+
# Check for IPv4 address
46+
function ip4 {
47+
if [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
48+
return 0
49+
fi
50+
return 1
51+
}
9152

92-
# Property file containing jks signing info
93-
propspath=$(echo "$props" | sed -e "s|$install|$installdir|g")
94-
95-
# Convert trusted SSL cert to jks
96-
function create_pkcs12 {
97-
echo "Creating PKCS12 keypair..."
98-
keypair="${ssl.keypair}"
99-
sslcert="${ssl.cert}"
100-
sslkey="${ssl.key}"
101-
generated="${ssl.command}"
102-
103-
keypairpath=$(echo "$keypair" | sed -e "s|$install|$installdir|g")
104-
generated=$(echo "$generated" | sed -e "s|$keypair|$keypairpath|g")
105-
generated=$(echo "$generated" | sed -e "s|$sslcert|$sslcertpath|g")
106-
generated=$(echo "$generated" | sed -e "s|$sslkey|$sslkeypath|g")
107-
generated=$(echo "$generated" | sed -e "s|$keypass|$password|g")
108-
109-
makekeystore=$(echo "$makekeystore" | sed -e "s|$keypair|$keypairpath|g")
110-
111-
eval "$generated" > /dev/null 2>&1
112-
check_exists "$keypairpath"
113-
114-
if [ $? -ne 0 ]; then
115-
echo "Error creating PKCS12 keypair from $sslcertpath, $sslkeypath to $keypairpath"
116-
echo -e "${bash.failure}\n"
117-
exit 1
53+
# Replace all install-time variables
54+
function replace_vars {
55+
cmd=$(echo "$1" | sed -e "s|\"keytool\"|$keytoolcmd|g")
56+
57+
# Handle CN=${ssl.cn} override
58+
if [ -n "$cnoverride" ]; then
59+
cmd=$(echo "$cmd" | sed -e "s|CN=${ssl.cn},|CN=$cnoverride,|g")
60+
if ip4 "$cnoverride"; then
61+
cmd=$(echo "$cmd" | sed -e "s|san=dns:${ssl.cn},|san=ip:$cnoverride,|g")
62+
else
63+
cmd=$(echo "$cmd" | sed -e "s|san=dns:${ssl.cn},|san=dns:$cnoverride,|g")
64+
fi
65+
# Remove dangling san
66+
cmd=$(echo "$cmd" | sed -e "s|,dns:${ssl.cnalt}||g")
11867
fi
11968

120-
# Remove lingering self-signed certs
121-
rm "$dercertpath" > /dev/null 2>&1
69+
cmd=$(echo "$cmd" | sed -e "s|\!install|${apple.installdir}|g")
70+
cmd=$(echo "$cmd" | sed -e "s|\!storepass|$password|g")
71+
cmd=$(echo "$cmd" | sed -e "s|\!keypass|$password|g")
72+
cmd=$(echo "$cmd" | sed -e "s|\!sslcert|$trustedcertpath|g")
73+
cmd=$(echo "$cmd" | sed -e "s|\!sslkey|$trustedkeypath|g")
12274

75+
echo "$cmd"
12376
return 0
12477
}
12578

79+
# Handle "community" mode, custom signing auth cert
80+
if [ -n '${build.type}' ]; then
81+
authcertpath=$(echo "${authcert.install}" | sed -e "s|\!install|${apple.installdir}|g")
82+
fi
83+
12684
# Write out the secure websocket properties file
12785
function write_properties {
128-
echo "Writing properties file..."
129-
echo "wss.alias=${jks.alias}" > "$propspath"
86+
propspath=$(echo "$1" | sed -e "s|\!install|${apple.installdir}|g")
87+
keystorepath=$(echo "${ssl.jks}" | sed -e "s|\!install|${apple.installdir}|g")
88+
echo "wss.alias=${ssl.alias}" > "$propspath"
13089
echo "wss.keystore=$keystorepath" >> "$propspath"
13190
echo "wss.keypass=$password" >> "$propspath"
13291
echo "wss.storepass=$password" >> "$propspath"
133-
echo "wss.host=${jks.host}" >> "$propspath"
92+
echo "wss.host=${ssl.host}" >> "$propspath"
13493
if [ -n "$authcertpath" ]; then
13594
echo "authcert.override=$authcertpath" >> "$propspath"
13695
fi
13796
echo "" >> "$propspath"
138-
check_exists "$propspath"
97+
check_exists "$propspath"
13998
return $?
14099
}
141100

142-
# Check to see if file exists
101+
# Delete a file if exists
102+
function delete_file {
103+
testfile=$(echo "$1" | sed -e "s|\!install|${apple.installdir}|g")
104+
rm -f "$testfile" > /dev/null 2>&1
105+
return 0
106+
}
107+
108+
# Check to see if file exists with optional message
143109
function check_exists {
144-
if [ -e "$1" ]; then
145-
echo -e "${bash.success}\n"
110+
testfile=$(echo "$1" | sed -e "s|\!install|${apple.installdir}|g")
111+
if [ -e "$testfile" ]; then
112+
if [ -n "$2" ]; then
113+
echo -e "${bash.success} $2 $testfile"
114+
else
115+
echo -e "${bash.success} $testfile"
116+
fi
146117
return 0
147118
fi
148-
echo -e "${bash.failure}\n"
119+
echo -e "${bash.failure} $testfile"
149120
return 1
150121
}
151122

152123
# Remove all matching system certificates
153124
function remove_certs {
154-
hash=$(security find-certificate -e "${vendor.email}" -Z |grep ^SHA-1|rev|cut -d' ' -f1|rev)
155-
if [ -n "$hash" ]; then
156-
security delete-certificate -Z "$hash" > /dev/null 2>&1
157-
# Recurse on self
158-
remove_certs
159-
return 0
125+
if security find-certificate -e "${vendor.email}" -Z > /dev/null 2>&1; then
126+
echo -e "${bash.success} Found certificate matching ${vendor.email}"
127+
hash=$(security find-certificate -e "${vendor.email}" -Z |grep ^SHA-1|rev|cut -d' ' -f1|rev)
128+
if [ -n "$hash" ]; then
129+
# Remove and recurse
130+
security delete-certificate -Z "$hash" > /dev/null 2>&1 && remove_certs
131+
fi
132+
else
133+
echo -e "${bash.success} No more matching certificates found"
160134
fi
161-
# No certs found, exit
162-
return 1
135+
136+
return 0
163137
}
164138

165-
# Check for IPv4 address
166-
function ip4 {
167-
if [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
168-
return 0
139+
# Runs a steps, optionally checks for a file
140+
# e.g: run_step "Description" "ls -al *.txt > ./out" "./out"
141+
function run_step {
142+
if eval "$(replace_vars "$2") > /dev/null 2>&1"; then
143+
if [ -z "$3" ]; then
144+
echo -e "${bash.success} $1"
145+
return 0
146+
elif check_exists "$3" "$1"; then
147+
return 0
148+
else
149+
return 1
150+
fi
169151
fi
152+
echo -e "${bash.failure}\n"
170153
return 1
171154
}
172155

173-
# Handle CN=${jks.cn} override
174-
if [ -n "$2" ]; then
175-
cname="CN=${jks.cn},"
176-
newcname="CN=$2,"
177-
san="san=dns:${jks.cn},"
178-
newsan="san=dns:$2,"
179-
newipsan="san=ip:$2,"
180-
cnalt=",dns:${jks.cnalt}"
181-
newcnalt=""
182-
183-
makekeystore=$(echo "$makekeystore" | sed -e "s|$cname|$newcname|g")
184-
if ip4 "$2"; then
185-
makekeystore=$(echo "$makekeystore" | sed -e "s|$san|$newipsan|g")
186-
else
187-
makekeystore=$(echo "$makekeystore" | sed -e "s|$san|$newsan|g")
188-
fi
189-
makekeystore=$(echo "$makekeystore" | sed -e "s|$cnalt|$newcnalt|g")
190-
fi
191-
192156
#
193157
# Uninstall mode
194158
#
195159
if [ "$1" == "uninstall" ]; then
196-
echo "Removing installed certificates (warnings are safe to ignore)..."
160+
echo -e "\nRemoving installed certificates..."
197161
remove_certs
198-
echo -e "${bash.success}\n"
162+
echo -e "\n[Finished ${apple.keygen.name}]\n"
199163
exit 0
200164
fi
201165

202166
#
203167
# Install mode
204168
#
205169

206-
# Delete old keystore, if exists
207-
rm -f "$keystorepath" > /dev/null 2>&1
170+
# Delete old files if exist
171+
delete_file "${ssl.jks}"
172+
delete_file "${ssl.crt}"
208173

209174
# Handle trusted ssl certificate, if specified
210-
if [ -n "$sslcertpath" ]; then
211-
create_pkcs12
212-
echo "Creating keystore for secure websockets..."
213-
eval "$makekeystore" > /dev/null 2>&1
214-
check_exists "$keystorepath"
215-
write_properties
216-
status=$?
217-
echo "Finished"
218-
exit $status
175+
if [ -n "$trustedcertpath" ]; then
176+
echo -e "\nCreating keystore for secure websockets..."
177+
run_step "\nConverting to PKCS12 keypair" "${trusted.command}" "${trusted.keypair}"
178+
run_step "\nConverting to jks format" "${trusted.convert}" "${ssl.jks}"
179+
write_properties "${ssl.properties}" || exit 1
180+
echo -e "\n[Finished ${apple.keygen.name}]\n"
181+
exit 0
219182
fi
220183

221184
# Handle self-signed certificate
222-
echo "Creating keystore for secure websockets..."
223-
eval "$makekeystore" > /dev/null 2>&1
224-
check_exists "$keystorepath"
225-
226-
echo "Converting keystore to native certificate..."
227-
eval "$makedercert" > /dev/null 2>&1
228-
check_exists "$dercertpath"
229-
230-
write_properties
231-
232-
echo "Removing old certificates (warnings are safe to ignore)..."
185+
echo -e "\nCreating keystore for secure websockets..."
186+
# Delete old files if exist
187+
delete_file "${ca.jks}"
188+
delete_file "${ca.crt}"
189+
delete_file "${ssl.csr}"
190+
191+
run_step "Creating a CA keypair" "${ca.jkscmd}" "${ca.jks}" || exit 1
192+
run_step "Exporting CA certificate" "${ca.crtcmd}" "${ca.crt}" || exit 1
193+
run_step "Creating an SSL keypair" "${ssl.jkscmd}" "${ssl.jks}" || exit 1
194+
run_step "Creating an SSL CSR" "${ssl.jkscsr}" "${ssl.csr}" || exit 1
195+
run_step "Issuing SSL certificate from CA" "${ssl.crtcmd}" "${ssl.crt}" || exit 1
196+
run_step "Importing CA certificate into SSL keypair" "${ssl.importca}" "" || exit 1
197+
run_step "Importing chained SSL certificate into SSL keypair" "${ssl.importssl}" "" || exit 1
198+
199+
echo -e "\nWriting properties file..."
200+
write_properties "${ssl.properties}" || exit 1
201+
202+
echo -e "\nRemoving installed certificates..."
233203
remove_certs
234-
echo -e "${bash.success}\n"
235-
236-
echo "Installing certificate..."
237204

238205
# Install new certificate
239-
security add-trusted-cert -d -r "${apple.keygen.store}" -k "${apple.keychain}" "$dercertpath"
240-
if [ $? -eq 0 ]; then
241-
echo -e "${bash.success}\n"
242-
else
243-
echo -e "${bash.failure}\n"
244-
fi
206+
run_step "Installing certificate" "${apple.keygen.install}" "" || exit 1
207+
208+
echo -e "\nCleaning up..."
209+
delete_file "${ca.jks}"
210+
delete_file "${ssl.csr}"
211+
delete_file "${ssl.crt}"
245212

246-
echo "Finished"
213+
echo -e "\n[Finished ${apple.keygen.name}]\n"
247214
exit 0

‎ant/apple/apple.properties

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ apple.keygen.store=trustRoot
1414
apple.keygen.name=apple-keygen.sh
1515
apple.keygen.in=${basedir}/ant/apple/${apple.keygen.name}.in
1616
apple.keygen.out=${dist.dir}/auth/${apple.keygen.name}
17+
apple.keygen.install=security add-trusted-cert -d -r \\"${apple.keygen.store}\\" -k \\"${apple.keychain}\\" \\"${ca.crt}\\"
1718
apple.jvmver=/usr/libexec/java_home -v ${javac.target}+
1819
apple.jvmcmd=${apple.jvmver} --exec
1920
apple.jvmfallback=/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin

‎ant/firefox/firefox-cert.sh.in

+8-13
Original file line numberDiff line numberDiff line change
@@ -76,29 +76,22 @@ else
7676
echo -e "${bash.success} $ffdir"
7777
fi
7878

79-
80-
# Substitution variables (!install, etc)
81-
install="${jks.install}"
82-
cname="${jks.cn}"
83-
dercert="${der.cert}"
84-
prefs="${firefoxprefs.install}"
85-
config="${firefoxconfig.install}"
86-
87-
# Handle CN=${jks.cn} override
79+
# Handle CN=${ssl.cn} override
80+
cname="${ssl.cn}"
8881
if [ -n "$2" ]; then
8982
cname="$2"
9083
fi
9184

9285
# Perform substitutions
93-
dercertpath=$(echo "$dercert" | sed -e "s|$install|$installdir|g")
94-
prefspath=$(echo "$prefs" | sed -e "s|$install|$installdir|g")
95-
configpath=$(echo "$config" | sed -e "s|$install|$installdir|g")
86+
dercertpath=$(echo "${ca.crt}" | sed -e "s|\!install|$installdir|g")
87+
prefspath=$(echo "${firefoxprefs.install}" | sed -e "s|\!install|$installdir|g")
88+
configpath=$(echo "${firefoxconfig.install}" | sed -e "s|\!install|$installdir|g")
9689

9790
#
9891
# Uninstall mode
9992
#
10093
if [ "$1" == "uninstall" ]; then
101-
echo "Searching for ${project.name} AutoConfig..."
94+
echo -e "\nSearching for ${project.name} AutoConfig..."
10295
if [ -f "$bindir/${firefoxconfig.name}" ]; then
10396
echo -e "${bash.success} Check Firefox config exists"
10497
cp "$configpath" "$bindir/${firefoxconfig.name}"
@@ -123,6 +116,7 @@ if [ "$1" == "uninstall" ]; then
123116
else
124117
echo -e "${bash.skipped} ${project.name} AutoConfig not found"
125118
fi
119+
echo -e "\n[Finished ${firefoxcert.name}]\n"
126120
exit 0
127121
fi
128122

@@ -195,5 +189,6 @@ else
195189
exit 1
196190
fi
197191

192+
echo -e "\n[Finished ${firefoxcert.name}]\n"
198193
exit 0
199194

‎ant/firefox/firefox-config.cfg.in

+7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
//##############################################################################
22
//# Firefox AutoConfig for ${project.name} Software ${vendor.website} #
33
//##############################################################################
4+
//# Copyright (C) 2017 Tres Finocchiaro, QZ Industries, LLC #
5+
//# #
6+
//# LGPL 2.1 This is free software. This software and source code are #
7+
//# released under the "LGPL 2.1 License". A copy of this license should be #
8+
//# distributed with this software. http://www.gnu.org/licenses/lgpl-2.1.html #
9+
//# #
410
//# NOTE: This certificate is unique and private to THIS PC ONLY. It was #
511
//# created on-the-fly at install time for secure websockets to function with #
612
//# ${project.name} software. #
13+
//# #
714
//# For questions please visit ${vendor.website}/support #
815
//##############################################################################
916

‎ant/linux/linux-installer.sh.in

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@
99
# 4. Installs certificate to OS using certutil #
1010
# 5. Installs certificate into Firefox (if installed) #
1111
# #
12-
# Note: If [sslcert] and [sslkey] are specified, import to browser/OS is omitted. #
12+
# Note: If [trustedcert] and [trustedkey] are specified, import to browser/OS is #
13+
# omitted. #
1314
# #
1415
# Depends: #
1516
# java, certutil #
1617
# #
1718
# Optional: #
18-
# openssl - Required if providing [sslcert], [sslkey] parameters #
19+
# openssl - Required if providing [trustedcert], [trustedkey] parameters #
1920
# #
2021
# Usage: #
2122
# $ chmod +x ${linux.installer.name} #
22-
# $ sudo ./${linux.installer.name} [noprompt] [hostname] [sslcert] [sslkey] #
23+
# $ sudo ./${linux.installer.name} [noprompt] [hostname] [trustedcert] [trustedkey] #
2324
# #
2425
##########################################################################################
2526

@@ -31,8 +32,8 @@ fi
3132

3233
noprompt="$1"
3334
cname="$2"
34-
sslcert="$3"
35-
sslkey="$4"
35+
trustedcert="$3"
36+
trustedkey="$4"
3637
mask=755
3738
destdir="${linux.installdir}"
3839
shortcut="/usr/share/applications/${project.filename}.desktop"
@@ -159,9 +160,9 @@ fi
159160

160161
progress_dialog 70 "Generating certificate..."
161162
chmod $mask "$destdir/auth/${linux.keygen.name}" > /dev/null 2>&1
162-
"$destdir/auth/${linux.keygen.name}" "$cname" "$sslcert" "$sslkey"
163+
"$destdir/auth/${linux.keygen.name}" "$cname" "$trustedcert" "$trustedkey"
163164

164-
if [[ -n $sslcert && -n $sslkey ]]; then
165+
if [[ -n $trustedcert && -n $trustedkey ]]; then
165166
progress_dialog 75 "Skipping OS/browser cert import..."
166167
else
167168
progress_dialog 75 "Importing Firefox locator..."
@@ -191,6 +192,7 @@ chmod -R $mask "${destdir}"
191192
progress_dialog 92 "Installing usb/udev rules..."
192193
rm -f "/lib/udev/rules.d/${linux.udev.name}" > /dev/null 2>&1
193194
mv "$destdir/${linux.udev.name}" "/lib/udev/rules.d/${linux.udev.name}" > /dev/null 2>&1
195+
udevadm control --reload-rules > /dev/null 2>&1
194196

195197
cd "${destdir}"
196198
progress_dialog 95 "Installation complete... Starting ${project.name}..."

‎ant/linux/linux-keygen.sh.in

+112-122
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,36 @@
11
#!/bin/bash
22
##########################################################################################
3-
# ${project.name} Linux KeyGen Util #
3+
# ${project.name} Linux KeyGen Utility #
44
##########################################################################################
55
# Description: #
6-
# 1. Creates a self-signed Java Keystore for jetty wss://localhost or [hostname] #
7-
# 2. Exports public certificate from Java Keystore
8-
#
9-
# Note: If [sslcert] and [sslkey] are specified, import to browser/OS is omitted. #
6+
# 1. Creates a self-signed Java Keystore for jetty wss://localhost or [hostname] #
7+
# 2. Exports public certificate from Java Keystore #
8+
# #
9+
# Note: If [trustedcert] and [trustedkey] are specified, import to browser/OS is #
10+
# omitted. #
1011
# #
1112
# Depends: #
1213
# java #
1314
# #
1415
# Optional: #
15-
# openssl - Required if providing [sslcert], [sslkey] parameters #
16+
# openssl - Required if providing [trustedcert], [trustedkey] parameters #
1617
# #
1718
# Usage: #
18-
# $ ./${linux.keygen.name} [hostname] [sslcert] [sslkey] #
19+
# $ ./${linux.keygen.name} [hostname] [trustedcert] [trustedkey] #
1920
# #
2021
##########################################################################################
2122

22-
# Random password hash
23-
password=$(cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-z0-9' | fold -w ${jks.passlength} | head -n 1)
23+
# Handle CN=${ssl.cn} override
24+
cnoverride="$1"
2425

2526
# Handle trusted ssl certificate
2627
if [[ -n $2 && -n $3 ]]; then
27-
sslcertpath="$2"
28-
sslkeypath="$3"
29-
makekeystore="${ssl.convert}"
30-
else
31-
makekeystore="${jks.command}"
28+
trustedcertpath="$2"
29+
trustedkeypath="$3"
3230
fi
3331

34-
makedercert="${der.command}"
35-
installdir="${linux.installdir}"
36-
37-
# Substitution variables (!storepass, !keypass, !install, etc)
38-
install="${jks.install}"
39-
storepass="${jks.storepass}"
40-
keypass="${jks.keypass}"
41-
keystore="${jks.keystore}"
42-
dercert="${der.cert}"
43-
props="${jks.properties}"
44-
45-
# Keystore generation variable substitutions
46-
keystorepath="${keystore/$install/$installdir}"
47-
makekeystore="${makekeystore/$storepass/$password}"
48-
makekeystore="${makekeystore/$keypass/$password}"
49-
makekeystore="${makekeystore/$keystore/$keystorepath}"
32+
# Random password hash
33+
password=$(cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-z0-9' | fold -w ${ssl.passlength} | head -n 1)
5034

5135
# Check for IPv4 address
5236
function ip4 {
@@ -56,124 +40,130 @@ function ip4 {
5640
return 1
5741
}
5842

59-
# Handle CN=${jks.cn} override
60-
if [ -n "$1" ]; then
61-
cname="CN=${jks.cn},"
62-
newcname="CN=$1,"
63-
san="san=dns:${jks.cn},"
64-
newsan="san=dns:$1,"
65-
newipsan="san=ip:$1,"
66-
cnalt=",dns:${jks.cnalt}"
67-
newcnalt=""
68-
69-
makekeystore="${makekeystore/$cname/$newcname}"
70-
if ip4 "$1"; then
71-
makekeystore="${makekeystore/$san/$newipsan}"
72-
else
73-
makekeystore="${makekeystore/$san/$newsan}"
43+
# Replace all install-time variables
44+
function replace_vars {
45+
# TODO: OpenSUSE as well as some others don't have keytool in $PATH
46+
cmd=$(echo "$1" | sed -e "s|\"keytool\"|keytool|g")
47+
48+
# Handle CN=${ssl.cn} override
49+
if [ -n "$cnoverride" ]; then
50+
cmd=$(echo "$cmd" | sed -e "s|CN=${ssl.cn},|CN=$cnoverride,|g")
51+
if ip4 "$cnoverride"; then
52+
cmd=$(echo "$cmd" | sed -e "s|san=dns:${ssl.cn},|san=ip:$cnoverride,|g")
53+
else
54+
cmd=$(echo "$cmd" | sed -e "s|san=dns:${ssl.cn},|san=dns:$cnoverride,|g")
55+
fi
56+
# Remove dangling san
57+
cmd=$(echo "$cmd" | sed -e "s|,dns:${ssl.cnalt}||g")
7458
fi
75-
makekeystore="${makekeystore/$cnalt/$newcnalt}"
76-
fi
7759

78-
# Cert export variable substitutions
79-
dercertpath="${dercert/$install/$installdir}"
80-
makedercert="${makedercert/$storepass/$password}"
81-
makedercert="${makedercert/$keypass/$password}"
82-
makedercert="${makedercert/$keystore/$keystorepath}"
83-
makedercert="${makedercert/$dercert/$dercertpath}"
84-
85-
# // Handle "community" mode, custom signing auth cert
86-
if [ -n "${build.type}" ]; then
87-
authcert="${authcert.install}"
88-
authcertpath="${authcert/$install/$installdir}"
89-
fi
90-
91-
# Property file containing jks signing info
92-
propspath="${props/$install/$installdir}"
93-
94-
# Convert trusted SSL cert to jks
95-
function create_pkcs12 {
96-
echo "Creating PKCS12 keypair..."
97-
keypair="${ssl.keypair}"
98-
sslcert="${ssl.cert}"
99-
sslkey="${ssl.key}"
100-
generated="${ssl.command}"
101-
102-
keypairpath="${keypair/$install/$installdir}"
103-
generated="${generated/$keypair/$keypairpath}"
104-
generated="${generated/$sslcert/$sslcertpath}"
105-
generated="${generated/$sslkey/$sslkeypath}"
106-
generated="${generated/$keypass/$password}"
107-
108-
makekeystore="${makekeystore/$keypair/$keypairpath}"
109-
makekeystore="${makekeystore/$keypass/$password}" # second ${jks.keypass}
110-
111-
eval "$generated" > /dev/null 2>&1
112-
check_exists "$keypairpath"
113-
114-
if [ $? -ne 0 ]; then
115-
echo "Error creating PKCS12 keypair from $sslcertpath, $sslkeypath to $keypairpath"
116-
echo -e "${bash.failure}\n"
117-
exit 1
118-
fi
119-
120-
# Remove lingering self-signed certs
121-
rm "$dercertpath" > /dev/null 2>&1
60+
cmd=$(echo "$cmd" | sed -e "s|\!install|${linux.installdir}|g")
61+
cmd=$(echo "$cmd" | sed -e "s|\!storepass|$password|g")
62+
cmd=$(echo "$cmd" | sed -e "s|\!keypass|$password|g")
63+
cmd=$(echo "$cmd" | sed -e "s|\!sslcert|$trustedcertpath|g")
64+
cmd=$(echo "$cmd" | sed -e "s|\!sslkey|$trustedkeypath|g")
12265

66+
echo "$cmd"
12367
return 0
12468
}
12569

70+
# Handle "community" mode, custom signing auth cert
71+
if [ -n "${build.type}" ]; then
72+
authcertpath=$(echo "${authcert.install}" | sed -e "s|\!install|${linux.installdir}|g")
73+
fi
74+
12675
# Write out the secure websocket properties file
12776
function write_properties {
128-
echo "Writing properties file..."
129-
echo "wss.alias=${jks.alias}" > "$propspath"
77+
propspath=$(echo "$1" | sed -e "s|\!install|${linux.installdir}|g")
78+
keystorepath=$(echo "${ssl.jks}" | sed -e "s|\!install|${linux.installdir}|g")
79+
echo "wss.alias=${ssl.alias}" > "$propspath"
13080
echo "wss.keystore=$keystorepath" >> "$propspath"
13181
echo "wss.keypass=$password" >> "$propspath"
13282
echo "wss.storepass=$password" >> "$propspath"
133-
echo "wss.host=${jks.host}" >> "$propspath"
83+
echo "wss.host=${ssl.host}" >> "$propspath"
13484
if [ -n "$authcertpath" ]; then
13585
echo "authcert.override=$authcertpath" >> "$propspath"
13686
fi
13787
echo "" >> "$propspath"
138-
check_exists "$propspath"
88+
check_exists "$propspath"
13989
return $?
14090
}
14191

142-
# Check to see if file exists
92+
# Delete a file if exists
93+
function delete_file {
94+
testfile=$(echo "$1" | sed -e "s|\!install|${linux.installdir}|g")
95+
rm -f "$testfile" > /dev/null 2>&1
96+
return 0
97+
}
98+
99+
# Check to see if file exists with optional message
143100
function check_exists {
144-
if [ -e "$1" ]; then
145-
echo -e "${bash.success}\n"
101+
testfile=$(echo "$1" | sed -e "s|\!install|${linux.installdir}|g")
102+
if [ -e "$testfile" ]; then
103+
if [ -n "$2" ]; then
104+
echo -e "${bash.success} $2 $testfile"
105+
else
106+
echo -e "${bash.success} $testfile"
107+
fi
146108
return 0
147109
fi
148-
echo -e "${bash.failure}\n"
110+
echo -e "${bash.failure} $testfile"
149111
return 1
150112
}
151113

114+
# Runs a steps, optionally checks for a file
115+
# e.g: run_step "Description" "ls -al *.txt > ./out" "./out"
116+
function run_step {
117+
if eval "$(replace_vars "$2") > /dev/null 2>&1"; then
118+
if [ -z "$3" ]; then
119+
echo -e "${bash.success} $1"
120+
return 0
121+
elif check_exists "$3" "$1"; then
122+
return 0
123+
else
124+
return 1
125+
fi
126+
fi
127+
echo -e "${bash.failure}\n"
128+
return 1
129+
}
152130

153-
# Delete old keystore, if exists
154-
rm -f "$keystorepath" > /dev/null 2>&1
131+
# Delete old files if exist
132+
delete_file "${ssl.jks}"
133+
delete_file "${ssl.crt}"
155134

156135
# Handle trusted ssl certificate, if specified
157-
if [ -n "$sslcertpath" ]; then
158-
create_pkcs12
159-
echo "Creating keystore for secure websockets..."
160-
eval "$makekeystore" > /dev/null 2>&1
161-
check_exists "$keystorepath"
162-
write_properties
163-
status=$?
164-
echo "Finished"
165-
exit $status
136+
if [ -n "$trustedcertpath" ]; then
137+
echo -e "\nCreating keystore for secure websockets..."
138+
run_step "\nConverting to PKCS12 keypair" "${trusted.command}" "${trusted.keypair}"
139+
run_step "\nConverting to jks format" "${trusted.convert}" "${ssl.jks}"
140+
write_properties "${ssl.properties}" || exit 1
141+
echo -e "\n[Finished ${linux.keygen.name}]\n"
142+
exit 0
166143
fi
167144

168-
echo "Creating keystore for secure websockets..."
169-
eval "$makekeystore" > /dev/null 2>&1
170-
check_exists "$keystorepath"
171-
172-
echo "Converting keystore to native certificate..."
173-
eval "$makedercert" > /dev/null 2>&1
174-
check_exists "$dercertpath"
175-
176-
write_properties
177-
status=$?
178-
echo "Finished"
179-
exit $status
145+
# Handle self-signed certificate
146+
echo -e "\nCreating keystore for secure websockets..."
147+
# Delete old files if exist
148+
delete_file "${ca.jks}"
149+
delete_file "${ca.crt}"
150+
delete_file "${ssl.csr}"
151+
152+
run_step "Creating a CA keypair" "${ca.jkscmd}" "${ca.jks}" || exit 1
153+
run_step "Exporting CA certificate" "${ca.crtcmd}" "${ca.crt}" || exit 1
154+
run_step "Creating an SSL keypair" "${ssl.jkscmd}" "${ssl.jks}" || exit 1
155+
run_step "Creating an SSL CSR" "${ssl.jkscsr}" "${ssl.csr}" || exit 1
156+
run_step "Issuing SSL certificate from CA" "${ssl.crtcmd}" "${ssl.crt}" || exit 1
157+
run_step "Importing CA certificate into SSL keypair" "${ssl.importca}" "" || exit 1
158+
run_step "Importing chained SSL certificate into SSL keypair" "${ssl.importssl}" "" || exit 1
159+
160+
echo -e "\nWriting properties file..."
161+
write_properties "${ssl.properties}" || exit 1
162+
163+
echo -e "\nCleaning up..."
164+
delete_file "${ca.jks}"
165+
delete_file "${ssl.csr}"
166+
delete_file "${ssl.crt}"
167+
168+
echo -e "\n[Finished ${linux.keygen.name}]\n"
169+
exit 0

‎ant/self-sign.properties

-52
This file was deleted.

‎ant/ssl.properties

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Platform-independent info used at install time for wss:// signing
2+
# Values prefixed with an !exclamation-mark can't be determined until install time
3+
ssl.cn=localhost
4+
ssl.cnalt=localhost.qz.io
5+
ssl.city=Canastota
6+
ssl.state=NY
7+
ssl.country=US
8+
ssl.company=QZ Industries\\\\, LLC
9+
ssl.validity=7305
10+
11+
ssl.dname=\\"CN=${ssl.cn}, EMAILADDRESS=${vendor.email}, OU=${ssl.company}, O=${ssl.company}, L=${ssl.city}, S=${ssl.state}, C=${ssl.country}\\"
12+
ssl.properties=!install/${project.filename}.properties
13+
ssl.host=0.0.0.0
14+
ssl.passlength=10
15+
16+
ca.jks=!install/auth/root-ca.jks
17+
ca.crt=!install/auth/root-ca.crt
18+
ca.alias=root-ca
19+
ca.jkscmd=\\"keytool\\" -genkeypair -noprompt -alias ${ca.alias} -keyalg RSA -keysize 2048 -dname ${ssl.dname} -validity ${ssl.validity} -keystore \\"${ca.jks}\\" -keypass !keypass -storepass !storepass -ext ku:critical=cRLSign,keyCertSign -ext bc:critical=ca:true,pathlen:1
20+
ca.crtcmd=\\"keytool\\" -exportcert -alias root-ca -keystore \\"${ca.jks}\\" -keypass !keypass -storepass !storepass -file \\"${ca.crt}\\" -rfc -ext ku:critical=cRLSign,keyCertSign -ext bc:critical=ca:true,pathlen:1
21+
22+
ssl.jks=!install/auth/${project.filename}.jks
23+
ssl.crt=!install/auth/${project.filename}.crt
24+
ssl.csr=!install/auth/${project.filename}.csr
25+
ssl.alias=${project.filename}
26+
ssl.jkscmd=\\"keytool\\" -genkeypair -noprompt -alias ${ssl.alias} -keyalg RSA -keysize 2048 -dname ${ssl.dname} -validity ${ssl.validity} -keystore \\"${ssl.jks}\\" -storepass !storepass -keypass !keypass -ext ku:critical=digitalSignature,keyEncipherment -ext eku=serverAuth,clientAuth -ext san=dns:${ssl.cn},dns:${ssl.cnalt} -ext bc:critical=ca:false
27+
ssl.jkscsr=\\"keytool\\" -certreq -keyalg RSA -alias ${ssl.alias} -file \\"${ssl.csr}\\" -keystore \\"${ssl.jks}\\" -keypass !keypass -storepass !storepass
28+
ssl.crtcmd=\\"keytool\\" -keypass !keypass -storepass !storepass -validity ${ssl.validity} -keystore \\"${ca.jks}\\" -gencert -alias ${ca.alias} -infile \\"${ssl.csr}\\" -ext ku:critical=digitalSignature,keyEncipherment -ext eku=serverAuth,clientAuth -ext san=dns:${ssl.cn},dns:${ssl.cnalt} -ext bc:critical=ca:false -rfc -outfile \\"${ssl.crt}\\"
29+
ssl.importca=\\"keytool\\" -noprompt -import -trustcacerts -alias ${ca.alias} -file \\"${ca.crt}\\" -keystore \\"${ssl.jks}\\" -keypass !keypass -storepass !storepass
30+
ssl.importssl=\\"keytool\\" -noprompt -import -trustcacerts -alias ${ssl.alias} -file \\"${ssl.crt}\\" -keystore \\"${ssl.jks}\\" -keypass !keypass -storepass !storepass
31+
32+
firefoxconfig.name=firefox-config.cfg
33+
firefoxconfig.in=${basedir}/ant/firefox/${firefoxconfig.name}.in
34+
firefoxconfig.out=${dist.dir}/auth/firefox/${firefoxconfig.name}
35+
firefoxconfig.install=!install/auth/firefox/${firefoxconfig.name}
36+
37+
firefoxprefs.name=firefox-prefs.js
38+
firefoxprefs.in=${basedir}/ant/firefox/${firefoxprefs.name}.in
39+
firefoxprefs.out=${dist.dir}/auth/firefox/${firefoxprefs.name}
40+
firefoxprefs.install=!install/auth/firefox/${firefoxprefs.name}
41+
42+
firefoxcert.name=firefox-cert.sh
43+
firefoxcert.in=${basedir}/ant/firefox/${firefoxcert.name}.in
44+
firefoxcert.out=${dist.dir}/auth/firefox/${firefoxcert.name}
45+
46+
locator.name=locator.sh
47+
locator.in=${basedir}/ant/firefox/${locator.name}.in
48+
locator.out=${dist.dir}/auth/firefox/${locator.name}
49+
50+
# Trusted SSL installs only
51+
trusted.crt=!sslcert
52+
trusted.jks=!sslkey
53+
trusted.keypair=!install/auth/${project.filename}.p12
54+
trusted.command=openssl pkcs12 -export -in \\"${trusted.crt}\\" -inkey \\"${trusted.jks}\\" -out \\"${trusted.keypair}\\" -name ${ssl.alias} -passout pass:!keypass
55+
trusted.convert=\\"keytool\\" -importkeystore -deststorepass !storepass -destkeypass !keypass -destkeystore \\"${ssl.jks}\\" -srckeystore \\"${trusted.keypair}\\" -srcstoretype PKCS12 -srcstorepass !storepass -alias ${ssl.alias}

‎ant/windows/windows-keygen.js.in

+164-146
Large diffs are not rendered by default.

‎ant/windows/windows.properties

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ windows.keygen.name=windows-keygen.js
66
windows.keygen.in=${basedir}/ant/windows/${windows.keygen.name}.in
77
windows.keygen.out=${dist.dir}/auth/${windows.keygen.name}
88
windows.keygen.tool=certutil.exe
9+
windows.keygen.install=${windows.keygen.tool} -addstore -f \\"${windows.keygen.store}\\" \\"${ca.crt}\\"
10+
windows.keygen.uninstall=${windows.keygen.tool} -delstore \\"${windows.keygen.store}\\" \\"!match\\"
911

1012
windows.nsis.addons=${basedir}/ant/windows/nsis
1113
windows.packager.in=${basedir}/ant/windows/windows-packager.nsi.in

‎build.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@
179179
-->
180180
<target name="prepackage">
181181
<echo>Processing self-signing variables</echo>
182-
<property file="ant/self-sign.properties"/>
182+
<property file="ant/ssl.properties"/>
183183

184184
<echo>Creating Firefox certificate config files</echo>
185185
<copy file="${firefoxconfig.in}" tofile="${firefoxconfig.out}" >

‎src/qz/deploy/LinuxCertificate.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ public class LinuxCertificate {
2727
private static String nssdb = "sql:" + System.getenv("HOME") + "/.pki/nssdb";
2828

2929
private static String getCertificatePath() {
30-
// We assume that if the keystore is "qz-tray.jks", the cert must be "qz-tray.crt"
30+
// We assume that if the keystore is "qz-tray.jks", the cert must be "root-ca.crt"
3131
Properties sslProperties = DeployUtilities.loadTrayProperties();
3232
if (sslProperties != null) {
33-
return sslProperties.getProperty("wss.keystore").replaceAll("\\.jks$", ".crt");
33+
return sslProperties.getProperty("wss.keystore").replace(Constants.PROPS_FILE + ".jks", "root-ca.crt");
3434
}
3535

3636
return null;

0 commit comments

Comments
 (0)
Please sign in to comment.