|
@@ -33,26 +33,78 @@ PROJECT_NAME='freedombone'
|
33
|
33
|
export TEXTDOMAIN=${PROJECT_NAME}-pin-cert
|
34
|
34
|
export TEXTDOMAINDIR="/usr/share/locale"
|
35
|
35
|
|
|
36
|
+WEBSITES_DIRECTORY=/etc/nginx/sites-available
|
|
37
|
+
|
|
38
|
+function pin_all_certs {
|
|
39
|
+ if [ ! -d $WEBSITES_DIRECTORY ]; then
|
|
40
|
+ return
|
|
41
|
+ fi
|
|
42
|
+
|
|
43
|
+ cd $WEBSITES_DIRECTORY
|
|
44
|
+ for file in `dir -d *` ; do
|
|
45
|
+ if grep -q "Public-Key-Pins" $file; then
|
|
46
|
+ DOMAIN_NAME=$file
|
|
47
|
+ KEY_FILENAME=/etc/ssl/private/${DOMAIN_NAME}.key
|
|
48
|
+ if [ -f $KEY_FILENAME ]; then
|
|
49
|
+ BACKUP_KEY_FILENAME=/etc/ssl/certs/${DOMAIN_NAME}.pem
|
|
50
|
+ if [ -f $BACKUP_KEY_FILENAME ]; then
|
|
51
|
+ KEY_HASH=$(openssl rsa -in $KEY_FILENAME -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64)
|
|
52
|
+ BACKUP_KEY_HASH=$(openssl rsa -in $BACKUP_KEY_FILENAME -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64)
|
|
53
|
+ if [ ${#BACKUP_KEY_HASH} -gt 5 ]; then
|
|
54
|
+
|
|
55
|
+ PIN_HEADER="Public-Key-Pins 'pin-sha256=\"${KEY_HASH}\"; pin-sha256=\"${BACKUP_KEY_HASH}\"; max-age=5184000; includeSubDomains';"
|
|
56
|
+ sed -i "s|Public-Key-Pins.*|${PIN_HEADER}|g" $file
|
|
57
|
+ echo "Pinned $DOMAIN_NAME with keys $KEY_HASH $BACKUP_KEY_HASH"
|
|
58
|
+ fi
|
|
59
|
+ fi
|
|
60
|
+ fi
|
|
61
|
+ fi
|
|
62
|
+ done
|
|
63
|
+}
|
|
64
|
+
|
|
65
|
+if [[ $1 == "all" ]]; then
|
|
66
|
+ pin_all_certs
|
|
67
|
+ systemctl restart nginx
|
|
68
|
+ exit 0
|
|
69
|
+fi
|
|
70
|
+
|
36
|
71
|
DOMAIN_NAME=$1
|
37
|
72
|
KEY_FILENAME=/etc/ssl/private/${DOMAIN_NAME}.key
|
38
|
|
-SITE_FILENAME=/etc/nginx/sites-available/${DOMAIN_NAME}
|
|
73
|
+BACKUP_KEY_FILENAME=/etc/ssl/certs/${DOMAIN_NAME}.pem
|
|
74
|
+SITE_FILENAME=$WEBSITES_DIRECTORY/${DOMAIN_NAME}
|
|
75
|
+
|
|
76
|
+if [ ! -f "$SITE_FILENAME" ]; then
|
|
77
|
+ exit 0
|
|
78
|
+fi
|
39
|
79
|
|
40
|
80
|
if [ ! -f "$KEY_FILENAME" ]; then
|
41
|
|
- echo $"No certificate found for $DOMAIN_NAME"
|
|
81
|
+ echo $"No private key certificate found for $DOMAIN_NAME"
|
42
|
82
|
exit 1
|
43
|
83
|
fi
|
44
|
84
|
|
45
|
|
-if [ ! -f "$SITE_FILENAME" ]; then
|
46
|
|
- exit 0
|
|
85
|
+if [ ! -f "$BACKUP_KEY_FILENAME" ]; then
|
|
86
|
+ echo $"No fullchain certificate found for $DOMAIN_NAME"
|
|
87
|
+ exit 2
|
47
|
88
|
fi
|
48
|
89
|
|
49
|
90
|
KEY_HASH=$(openssl rsa -in $KEY_FILENAME -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64)
|
|
91
|
+BACKUP_KEY_HASH=$(openssl rsa -in $BACKUP_KEY_FILENAME -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64)
|
50
|
92
|
|
51
|
|
-PIN_HEADER="add_header Public-Key-Pins 'pin-sha256=\"${KEY_HASH}\"; max-age=5184000; includeSubDomains';"
|
52
|
|
-if ! grep -q "add_header Public-Key-Pins" $SITE_FILENAME; then
|
53
|
|
- sed -i "/ssl_ciphers.*/a $PIN_HEADER" $SITE_FILENAME
|
|
93
|
+if [ ${#KEY_HASH} -lt 5 ]; then
|
|
94
|
+ echo 'Pin hash unexpectedly short'
|
|
95
|
+ exit 3
|
|
96
|
+fi
|
|
97
|
+
|
|
98
|
+if [ ${#BACKUP_KEY_HASH} -lt 5 ]; then
|
|
99
|
+ echo 'Backup pin hash unexpectedly short'
|
|
100
|
+ exit 4
|
|
101
|
+fi
|
|
102
|
+
|
|
103
|
+PIN_HEADER="Public-Key-Pins 'pin-sha256=\"${KEY_HASH}\"; pin-sha256=\"${BACKUP_KEY_HASH}\"; max-age=5184000; includeSubDomains';"
|
|
104
|
+if ! grep -q "Public-Key-Pins" $SITE_FILENAME; then
|
|
105
|
+ sed -i "/ssl_ciphers.*/a add_header ${PIN_HEADER}" $SITE_FILENAME
|
54
|
106
|
else
|
55
|
|
- sed -i "s/add_header Public-Key-Pins.*/$PIN_HEADER/g" $SITE_FILENAME
|
|
107
|
+ sed -i "s|Public-Key-Pins.*|${PIN_HEADER}|g" $SITE_FILENAME
|
56
|
108
|
fi
|
57
|
109
|
|
58
|
110
|
systemctl restart nginx
|
|
@@ -61,6 +113,6 @@ if ! grep -q "add_header Public-Key-Pins" $SITE_FILENAME; then
|
61
|
113
|
echo $'Pinning failed'
|
62
|
114
|
fi
|
63
|
115
|
|
64
|
|
-echo "Pinned $DOMAIN_NAME with hash $KEY_HASH"
|
|
116
|
+echo "Pinned $DOMAIN_NAME with keys $KEY_HASH $BACKUP_KEY_HASH"
|
65
|
117
|
|
66
|
118
|
exit 0
|