|
1
|
#!/usr/bin/env php
|
|
2
|
<?php
|
|
3
|
|
|
4
|
/**
|
|
5
|
* Import SSL certificates from a pre-determined place on the filesystem.
|
|
6
|
* Once imported, set them for use in the GUI
|
|
7
|
*/
|
|
8
|
|
|
9
|
if (empty($argc)) {
|
|
10
|
echo "Only accessible from the CLI.\r\n";
|
|
11
|
die(1);
|
|
12
|
}
|
|
13
|
|
|
14
|
if ($argc != 3) {
|
|
15
|
echo "Usage: php " . $argv[0] . " /path/to/certificate.crt /path/to/private/key.pem \r\n";
|
|
16
|
die(1);
|
|
17
|
}
|
|
18
|
|
|
19
|
require_once "certs.inc";
|
|
20
|
require_once "pfsense-utils.inc";
|
|
21
|
require_once "functions.inc";
|
|
22
|
require_once "filter.inc";
|
|
23
|
require_once "shaper.inc";
|
|
24
|
|
|
25
|
$certificate = trim(file_get_contents($argv[1]));
|
|
26
|
$key = trim(file_get_contents($argv[2]));
|
|
27
|
|
|
28
|
// Do some quick verification of the certificate, similar to what the GUI does
|
|
29
|
if (empty($certificate)) {
|
|
30
|
echo "The certificate is empty.\r\n";
|
|
31
|
die(1);
|
|
32
|
}
|
|
33
|
if (!strstr($certificate, "BEGIN CERTIFICATE") || !strstr($certificate, "END CERTIFICATE")) {
|
|
34
|
echo "This certificate does not appear to be valid.\r\n";
|
|
35
|
die(1);
|
|
36
|
}
|
|
37
|
|
|
38
|
// Verification that the certificate matches the key
|
|
39
|
if (empty($key)) {
|
|
40
|
echo "The key is empty.\r\n";
|
|
41
|
die(1);
|
|
42
|
}
|
|
43
|
if (cert_get_publickey($certificate, false) != cert_get_publickey($key, false, 'prv')) {
|
|
44
|
echo "The private key does not match the certificate.\r\n";
|
|
45
|
die(1);
|
|
46
|
}
|
|
47
|
|
|
48
|
$cert = array();
|
|
49
|
//$cert['refid'] = uniqid();
|
|
50
|
$cert['refid'] = hash('sha256', $certificate); // if we don't take a hash each iteration will have a new unique id and update each time
|
|
51
|
$cert['descr'] = "Certificate added to pfsense through " . $argv[0] . " on " . date("Y/m/d");
|
|
52
|
|
|
53
|
echo "Certificate sha256: ".$cert['refid']."\r\n";
|
|
54
|
|
|
55
|
cert_import($cert, $certificate, $key);
|
|
56
|
|
|
57
|
// Set up the existing certificate store
|
|
58
|
// Copied from system_certmanager.php
|
|
59
|
if (!is_array($config['ca'])) {
|
|
60
|
$config['ca'] = array();
|
|
61
|
}
|
|
62
|
|
|
63
|
$a_ca =& $config['ca'];
|
|
64
|
|
|
65
|
if (!is_array($config['cert'])) {
|
|
66
|
$config['cert'] = array();
|
|
67
|
}
|
|
68
|
|
|
69
|
$a_cert =& $config['cert'];
|
|
70
|
|
|
71
|
echo "Current Web GUI Certificate ID: `".$config['system']['webgui']['ssl-certref']."`\r\n";
|
|
72
|
echo "Current Unbound Certificate ID: `".$config['unbound']['sslcertref']."`\r\n";
|
|
73
|
|
|
74
|
$updateConfig = true;
|
|
75
|
// Check if the certificate we just parsed is already imported (we'll check the certificate portion)
|
|
76
|
foreach ($a_cert as $existing_cert) {
|
|
77
|
if ($existing_cert['crt'] === $cert['crt']) {
|
|
78
|
$updateConfig = false; // no need to update cert configuration
|
|
79
|
}
|
|
80
|
}
|
|
81
|
|
|
82
|
if ($updateConfig) {
|
|
83
|
// Append the final certificate
|
|
84
|
$a_cert[] = $cert;
|
|
85
|
// Write out the updated configuration
|
|
86
|
write_config("Save new certificate config, from pfsense-import-certificate.php");
|
|
87
|
sleep(3); //sleep to space out the write_config calls so they show distinctly
|
|
88
|
} else {
|
|
89
|
echo "Certificate is already installed, skipping configuration update.\r\n";
|
|
90
|
}
|
|
91
|
|
|
92
|
echo "Checking if services are using the latest certificate.\r\n";
|
|
93
|
|
|
94
|
$updateCertWebGui = false;
|
|
95
|
|
|
96
|
if ($config['system']['webgui']['ssl-certref'] !== $cert['refid']) {
|
|
97
|
echo "Web GUI certificate changed, installing!\r\n";
|
|
98
|
$updateCertWebGui = true;
|
|
99
|
}
|
|
100
|
|
|
101
|
// Assuming that all worked, we now need to set the new certificate for use in the GUI
|
|
102
|
$config['system']['webgui']['ssl-certref'] = $cert['refid'];
|
|
103
|
|
|
104
|
$updateCertUnbound = false;
|
|
105
|
|
|
106
|
// If Unbound is set to use TLS, then set the new certificate to be used by Unbound also.
|
|
107
|
if (isset($config['unbound']['enable']) and isset($config['unbound']['enablessl'])) {
|
|
108
|
if ($config['unbound']['sslcertref'] !== $cert['refid']) {
|
|
109
|
echo "Unbound certificate changed, installing!\r\n";
|
|
110
|
$updateCertUnbound = true;
|
|
111
|
}
|
|
112
|
$config['unbound']['sslcertref'] = $cert['refid'];
|
|
113
|
} else {
|
|
114
|
echo "Unbound SSL is disabled, ignoring.\r\n";
|
|
115
|
}
|
|
116
|
|
|
117
|
$updateCertCaptivePortal = false;
|
|
118
|
|
|
119
|
// If captive portal is set to use TLS, then set the new certificate
|
|
120
|
// to be used by captive portals
|
|
121
|
foreach ($config['captiveportal'] as $cpid => $cportal) {
|
|
122
|
if(isset($cportal['enable']) and isset($cportal['httpslogin'])){
|
|
123
|
if ($config['captiveportal'][$cpid]['certref'] !== $cert['refid']) {
|
|
124
|
echo "Captive Portal certificate changed, installing!\r\n";
|
|
125
|
$updateCertCaptivePortal = true;
|
|
126
|
}
|
|
127
|
$config['captiveportal'][$cpid]['certref'] = $cert['refid'];
|
|
128
|
}
|
|
129
|
}
|
|
130
|
|
|
131
|
if (!$updateCertWebGui and !$updateCertUnbound and !$updateCertCaptivePortal) {
|
|
132
|
echo "No certificate changes, no need to update config.\r\n";
|
|
133
|
die(); // exit with a valid error code, as this is intended behaviour
|
|
134
|
}
|
|
135
|
|
|
136
|
write_config("Set new certificate as active for webgui, from pfsense-import-certificate.php");
|
|
137
|
sleep(3); //sleep to space out the write_config calls
|
|
138
|
|
|
139
|
//Use cert_get_all_services to grab all services now using the new cert.
|
|
140
|
|
|
141
|
$services = cert_get_all_services($cert['refid']);
|
|
142
|
|
|
143
|
//Restart all services that are using the new cert.
|
|
144
|
echo "Restart services that are using the new certificate.\r\n";
|
|
145
|
var_dump($services);
|
|
146
|
log_error(gettext("Restart services that are using the new cert"));
|
|
147
|
|
|
148
|
cert_restart_services($services);
|
|
149
|
//All except unbound, there is a bug in cert_restart_services... it doesn't restart unbound
|
|
150
|
//https://redmine.pfsense.org/issues/15062
|
|
151
|
|
|
152
|
echo "Completed! New certificate installed.\r\n";
|
|
153
|
|
|
154
|
// If unbound cert was updated, then restart unbound.
|
|
155
|
// Remove once bug fixed
|
|
156
|
if ($updateCertUnbound) {
|
|
157
|
echo "Restart Unbound\n";
|
|
158
|
log_error(gettext("Unbound configuration has changed. Restarting Unbound."));
|
|
159
|
service_control_restart('unbound','');
|
|
160
|
}
|
|
161
|
|
|
162
|
|
|
163
|
// Delete unused certificates added by this script
|
|
164
|
|
|
165
|
$a_cert =& $config['cert'];
|
|
166
|
$name = '';
|
|
167
|
foreach ($a_cert as $cid => $acrt) {
|
|
168
|
echo "Validating certificate $cid for deletion.\r\n";
|
|
169
|
if (!cert_in_use($acrt['refid']) and preg_match("/pfsense-import-certificate\.php/",$acrt['descr'])) {
|
|
170
|
echo "--> Delete, no longer in use.\r\n";
|
|
171
|
// cert not in use and matches description pattern
|
|
172
|
$name.=htmlspecialchars($acrt['descr'])." ";
|
|
173
|
unset($a_cert[$cid]);
|
|
174
|
} else {
|
|
175
|
echo "--> Ignoring.\r\n";
|
|
176
|
}
|
|
177
|
}
|
|
178
|
|
|
179
|
if($name){
|
|
180
|
echo "Deleted old certificates: save the config.\r\n";
|
|
181
|
$savemsg = sprintf(gettext("Deleted certificate: %s , from pfsense-import-certificate.php"), $name);
|
|
182
|
write_config($savemsg);
|
|
183
|
}
|