Project

General

Profile

Download (6.68 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-2023 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
	$slices = glob("/dev/" . $disk . "[ps]*");
45
	$slices = str_replace("/dev/", "", $slices);
46
	return $slices;
47
}
48

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

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

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

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

    
195
function password_prompt($config_location) {
196
	echo " -> found encrypted config.xml\n";
197

    
198
	$configtxt = file_get_contents($config_location);
199

    
200
	if (tagfile_deformat($configtxt, $configtxt, "config.xml")) {
201
		$fp = fopen('php://stdin', 'r');
202
		$read = array($fp);
203
		$write = $except = array();
204
		$timeout = 30; // skip after 30s of inactivity
205
		do {
206
			echo gettext("Enter the password to decrypt config.xml, or press <ENTER> to skip:") . "\n";
207
			if (stream_select($read, $write, $except, $timeout)) {
208
				$decrypt_password = chop(fgets($fp));
209
			} else {
210
				echo gettext("Input timeout, skipping config.xml restore...") . "\n";
211
				return false;
212
			}
213
			$data = decrypt_data($configtxt, $decrypt_password);
214
			if (!empty($decrypt_password)) {
215
				$decrypted_data = decrypt_data($configtxt, $decrypt_password);
216
				if (empty($decrypted_data)) {
217
					echo gettext("Invalid password entered. Please try again.") . "\n";
218
				}
219
			}
220
		} while (!empty($decrypt_password) && empty($data));
221
		fclose($fp);
222
	}
223

    
224
	if (!empty($data)) {
225
		echo gettext("Config.xml unlocked.") . "\n";
226
		file_put_contents($config_location, $decrypted_data);
227
		return true;
228
	} else {
229
		echo gettext("Skipping config.xml restore...") . "\n";
230
		return false;
231
	}
232
}
233

    
234
echo "External config loader 1.0 is now starting...";
235
find_config_xml();
236
echo "\n";
237

    
238
?>
(31-31/85)