Project

General

Profile

Download (7.39 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/usr/local/bin/php-cgi -q
2
<?php
3
/*
4
 * ecl.php
5
 *
6
 * Copyright (c) 2010-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2025 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 * http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23

    
24
require_once("globals.inc");
25
require_once("functions.inc");
26
require_once("config.lib.inc");
27
require_once("config.inc");
28

    
29
$debug = false;
30

    
31
function get_boot_disk() {
32
	global $g, $debug;
33
	$disk = exec("/sbin/mount | /usr/bin/grep \"on / \" | /usr/bin/cut -d'/' -f3 | /usr/bin/cut -d' ' -f1");
34
	return $disk;
35
}
36

    
37
function get_swap_disks() {
38
	exec("/usr/sbin/swapinfo | /usr/bin/sed '/^\/dev/!d; s,^/dev/,,; s, .*\$,,'", $disks);
39
	return $disks;
40
}
41

    
42
function get_disk_slices($disk) {
43
	global $g, $debug;
44

    
45
	if (str_starts_with($disk, 'cd')) {
46
		$slices[] = $disk;
47
	} else {
48
		$slices = glob("/dev/" . $disk . "[ps]*");
49
		$slices = str_replace("/dev/", "", $slices);
50
	}
51
	return $slices;
52
}
53

    
54
function get_disks() {
55
	global $g, $debug;
56
	$disks_array = array();
57
	$disks_s = explode(" ", get_single_sysctl("kern.disks"));
58
	foreach ($disks_s as $disk) {
59
		/* Ignore the flash devices (ARM). */
60
		if (strstr($disk, "flash")) {
61
			continue;
62
		}
63
		if (trim($disk)) {
64
			$disks_array[] = $disk;
65
		}
66
	}
67
	return $disks_array;
68
}
69

    
70
function discover_config($mountpoint) {
71
	global $g, $debug;
72
	/* List of locations to check. Requires trailing slash.
73
	 * See https://redmine.pfsense.org/issues/9066 */
74
	$locations_to_check = array("/", "/config/");
75
	foreach ($locations_to_check as $ltc) {
76
		$tocheck = "/tmp/mnt/cf{$ltc}config.xml";
77
		if ($debug) {
78
			echo "\nChecking for $tocheck";
79
			if (file_exists($tocheck)) {
80
				echo " -> found!";
81
			}
82
		}
83
		if (file_exists($tocheck)) {
84
			return $tocheck;
85
		}
86
	}
87
	return "";
88
}
89

    
90
function test_config($file_location) {
91
	global $g, $debug;
92
	if (!$file_location) {
93
		return;
94
	}
95
	// config.xml was found.  ensure it is sound.
96
	$root_obj = trim("<{$g['xml_rootobj']}>");
97
	$enc_root_obj = "---- BEGIN config.xml ----";
98
	$xml_file_head = exec("/usr/bin/head -2 " . escapeshellarg($file_location) . " | /usr/bin/tail -n1");
99
	$enc_file_head = exec("/usr/bin/head -1 " . escapeshellarg($file_location));
100
	if ($debug) {
101
		echo "\nroot obj  = $root_obj";
102
		echo "\nfile head = $xml_file_head";
103
	}
104
	if ($xml_file_head == $root_obj) {
105
		// Now parse config to make sure
106
		$config_status = config_validate($file_location);
107
		if ($config_status) {
108
			return 'xml';
109
		}
110
	} elseif ($enc_file_head == $enc_root_obj) {
111
		return 'enc';
112
	}
113
	return false;
114
}
115

    
116
// Probes all disks looking for config.xml
117
function find_config_xml() {
118
	global $g, $debug;
119
	$disks = get_disks();
120
	// Safety check.
121
	if (!is_array($disks)) {
122
		return;
123
	}
124
	$boot_disk = get_boot_disk();
125
	$swap_disks = get_swap_disks();
126
	exec("/bin/mkdir -p /tmp/mnt/cf");
127
	foreach ($disks as $disk) {
128
		$slices = get_disk_slices($disk);
129
		if (is_array($slices)) {
130
			foreach ($slices as $slice) {
131
				if ($slice == "") {
132
					continue;
133
				}
134
				if (stristr($slice, $boot_disk)) {
135
					if ($debug) {
136
						echo "\nSkipping boot device slice $slice";
137
					}
138
					continue;
139
				}
140
				if (in_array($slice, $swap_disks)) {
141
					if ($debug) {
142
						echo "\nSkipping swap device slice $slice";
143
					}
144
					continue;
145
				}
146
				echo " $slice";
147
				// try msdos fs
148
				if ($debug) {
149
					echo "\n/sbin/mount -t msdosfs /dev/{$slice} /tmp/mnt/cf 2>/dev/null \n";
150
				}
151
				$_out = exec("/sbin/mount -t msdosfs /dev/{$slice} /tmp/mnt/cf 2>/dev/null", $stdout, $status);
152
				// try regular fs (ufs)
153
				if ($_out === false || $status != 0) {
154
					if ($debug) {
155
						echo "\n/sbin/mount /dev/{$slice} /tmp/mnt/cf 2>/dev/null \n";
156
					}
157
					$_out = exec("/sbin/mount /dev/{$slice} /tmp/mnt/cf 2>/dev/null", $stdout, $status);
158
				}
159
				// try cd9660 (standard CD-ROM format)
160
				if ($_out === false || $status != 0) {
161
					if ($debug) {
162
						echo "\n/sbin/mount -t cd9660 /dev/{$slice} /tmp/mnt/cf 2>/dev/null \n";
163
					}
164
					$_out = exec("/sbin/mount -t cd9660 /dev/{$slice} /tmp/mnt/cf 2>/dev/null", $stdout, $status);
165
				}
166
				// try udf (common for modern DVDs and some CDs)
167
				if ($_out === false || $status != 0) {
168
					if ($debug) {
169
						echo "\n/sbin/mount -t udf /dev/{$slice} /tmp/mnt/cf 2>/dev/null \n";
170
					}
171
					$_out = exec("/sbin/mount -t udf /dev/{$slice} /tmp/mnt/cf 2>/dev/null", $stdout, $status);
172
				}
173
				$mounted = trim(exec("/sbin/mount | /usr/bin/grep -v grep | /usr/bin/grep '/tmp/mnt/cf' | /usr/bin/wc -l"));
174
				if ($debug) {
175
					echo "\nmounted: $mounted ";
176
				}
177
				if ($status == 0 && intval($mounted) > 0) {
178
					// Item was mounted - look for config.xml file
179
					$config_location = discover_config($slice);
180
					if ($config_location) {
181
						$config_type = test_config($config_location);
182
						if ($config_type) {
183
							if (($config_type == 'enc') && !password_prompt($config_location)) {
184
								exec("/sbin/umount /tmp/mnt/cf");
185
								rmdir("/tmp/mnt/cf");
186
								exit;
187
							} elseif ($config_type == 'xml') {
188
								// We have a valid configuration.  Install it.
189
								echo " -> found config.xml\n";
190
							}
191
							echo "Backing up old configuration...\n";
192
							backup_config();
193
							echo "Restoring [{$slice}] {$config_location}...\n";
194
							restore_backup($config_location);
195
							if (file_exists('/cf/conf/trigger_initial_wizard')) {
196
								echo "First boot after install, setting flag for package sync and disabling wizard...\n";
197
								touch('/cf/conf/needs_package_sync');
198
								@unlink('/cf/conf/trigger_initial_wizard');
199
							}
200
							echo "Cleaning up...\n";
201
							exec("/sbin/umount /tmp/mnt/cf");
202
							rmdir("/tmp/mnt/cf");
203
							exit;
204
						}
205
					}
206
					exec("/sbin/umount /tmp/mnt/cf");
207
				}
208
			}
209
		}
210
	}
211
	rmdir("/tmp/mnt/cf");
212
}
213

    
214
function password_prompt($config_location) {
215
	echo " -> found encrypted config.xml\n";
216

    
217
	$configtxt = file_get_contents($config_location);
218

    
219
	if (tagfile_deformat($configtxt, $configtxt, "config.xml")) {
220
		$fp = fopen('php://stdin', 'r');
221
		$read = array($fp);
222
		$write = $except = array();
223
		$timeout = 60; // skip after 60s of inactivity
224
		do {
225
			echo gettext("Enter the password to decrypt config.xml, or press <ENTER> to skip:") . "\n";
226
			if (stream_select($read, $write, $except, $timeout)) {
227
				$decrypt_password = chop(fgets($fp));
228
			} else {
229
				echo gettext("Input timeout, skipping config.xml restore...") . "\n";
230
				return false;
231
			}
232
			$data = decrypt_data($configtxt, $decrypt_password);
233
			if (!empty($decrypt_password)) {
234
				$decrypted_data = decrypt_data($configtxt, $decrypt_password);
235
				if (empty($decrypted_data)) {
236
					echo gettext("Invalid password entered. Please try again.") . "\n";
237
				}
238
			}
239
		} while (!empty($decrypt_password) && empty($data));
240
		fclose($fp);
241
	}
242

    
243
	if (!empty($data)) {
244
		echo gettext("Config.xml unlocked.") . "\n";
245
		file_put_contents($config_location, $decrypted_data);
246
		return true;
247
	} else {
248
		echo gettext("Skipping config.xml restore...") . "\n";
249
		return false;
250
	}
251
}
252

    
253
echo "External config loader 1.0 is now starting...";
254
find_config_xml();
255
echo "\n";
256

    
257
?>
(31-31/84)