Project

General

Profile

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

    
25
require_once("globals.inc");
26
if ($argc < 2) {
27
	echo "Starting the {$g['product_label']} developer shell";
28
}
29
require_once("functions.inc");
30
if ($argc < 2) {
31
	echo ".";
32
}
33
require_once("config.inc");
34
if ($argc < 2) {
35
	echo ".";
36
}
37
require_once("util.inc");
38
if ($argc < 2) {
39
	echo ".";
40
}
41

    
42
$shell_cmds = array("alias", "alloc", "bg", "bind", "bindkey", "break",
43
	 "breaksw", "builtins", "case", "cd", "chdir", "command", "complete", "continue", "default",
44
	 "dirs", "do", "done", "echo", "echotc", "elif", "else", "end", "endif", "endsw", "esac", "eval",
45
	 "exec", "exit", "export", "false", "fc", "fg", "filetest", "fi", "for", "foreach", "getopts",
46
	 "glob", "goto", "hash", "hashstat", "history", "hup", "if", "jobid", "jobs", "kill", "limit",
47
	 "local", "log", "login", "logout", "ls-F", "nice", "nohup", "notify", "onintr", "popd",
48
	 "printenv", "pushd", "pwd", "read", "readonly", "rehash", "repeat", "return", "sched", "set",
49
	 "setenv", "settc", "setty", "setvar", "shift", "source", "stop", "suspend", "switch",
50
	 "telltc", "test", "then", "time", "trap", "true", "type", "ulimit", "umask", "unalias",
51
	 "uncomplete", "unhash", "unlimit", "unset", "unsetenv", "until", "wait", "where", "which",
52
	 "while");
53

    
54
function pipe_cmd($command, $text_to_pipe) {
55
	$descriptorspec = array(
56
		0 => array("pipe", "r"),  // stdin
57
		1 => array("pipe", "w"),  // stdout
58
		2 => array("pipe", "w")); // stderr ?? instead of a file
59

    
60
	$fd = proc_open("$command", $descriptorspec, $pipes);
61
	if (is_resource($fd)) {
62
		fwrite($pipes[0], "{$text_to_pipe}");
63
		fclose($pipes[0]);
64
		while ($s= fgets($pipes[1], 1024)) {
65
			// read from the pipe
66
			$buffer .= $s;
67
		}
68
		fclose($pipes[1]);
69
		fclose($pipes[2]);
70
	}
71
	return $buffer;
72
}
73

    
74
if (!function_exists("readline")) {
75
	function readline() {
76
		$fp = fopen('php://stdin', 'r');
77
		$textinput = chop(fgets($fp));
78
		fclose($fp);
79
		return $textinput;
80
	}
81
}
82

    
83
function more($text, $count=24) {
84
	$counter=0;
85
	$lines = explode("\n", $text);
86
	foreach ($lines as $line) {
87
		if ($counter > $count) {
88
			echo "Press RETURN to continue ...";
89
			$fp = fopen('php://stdin', 'r');
90
			$pressreturn = chop(fgets($fp));
91
			if ($pressreturn == "q" || $pressreturn == "quit") {
92
				return;
93
			}
94
			fclose($fp);
95
			$counter = 0;
96
		}
97
		echo "{$line}\n";
98
		$counter++;
99
	}
100
}
101

    
102
function show_help() {
103

    
104
$show_help_text = <<<EOF
105

    
106
	Enter a series of commands and then execute the set with "exec".
107

    
108
	For example:
109
	echo "foo"; // php command
110
	echo "foo2"; // php command
111
	! echo "heh" # shell command
112
	exec
113

    
114
	Example commands:
115

    
116
	record <recordingfilename>
117
	stoprecording
118
	showrecordings
119

    
120
	parse_config(true);  # reloads the \$config array
121

    
122
	\$temp = print_r(\$config, true);
123
	more(\$temp);
124

    
125
	/* to output a configuration array */
126
	print_r(\$config);
127

    
128
	/* to output the interfaces configuration portion of config.xml */
129
	print_r(\$config['interfaces']);
130

    
131
	/* to output the dhcp server configuration */
132
	print_r(\$config['dhcpd']);
133

    
134
	/* to exit the {$g['product_label']} developer shell */
135
	exit
136

    
137
	/* to output supported wireless modes for an interface */
138
	print_r(get_wireless_modes(\"ath0\"));
139

    
140
	/* to enable SSH */
141
	\$config['system']['ssh']['enable'] = "enabled";
142

    
143
	/* change OPTX to the OPT interface name such as BACKHAUL */
144
	\$config['interfaces']['optx']['wireless']['standard'] = "11a";
145
	\$config['interfaces']['optx']['wireless']['mode'] = "hostap";
146
	\$config['interfaces']['optx']['wireless']['channel'] = "6";
147

    
148
	/* to enable dhcp server for an optx interface */
149
	\$config['dhcpd']['optx']['enable'] = true;
150
	\$config['dhcpd']['optx']['range']['from'] = "192.168.31.100";
151
	\$config['dhcpd']['optx']['range']['to'] = "192.168.31.150";
152

    
153
	/* to disable the firewall filter */
154
	\$config['system']['disablefilter'] = true;
155

    
156
	/* to enable an interface and configure it as a DHCP client */
157
	\$config['interfaces']['optx']['disabled'] = false;
158
	\$config['interfaces']['optx']['ipaddr'] = "dhcp";
159

    
160
	/* to enable an interface and set a static IPv4 address */
161
	\$config['interfaces']['wan']['enable'] = true;
162
	\$config['interfaces']['wan']['ipaddr'] = "192.168.100.1";
163
	\$config['interfaces']['wan']['subnet'] = "24";
164

    
165
	/* to save out the new configuration (config.xml) */
166
	write_config();
167

    
168
	/* to reboot the system after saving */
169
	system_reboot_sync();
170

    
171
EOF;
172

    
173
	more($show_help_text);
174

    
175
}
176

    
177
$fp = fopen('php://stdin', 'r');
178

    
179
if ($argc < 2) {
180
	echo ".\n\n";
181
}
182

    
183
$pkg_interface='console';
184

    
185
$shell_active = true;
186
$tccommands = array();
187

    
188
function completion($string, $index) {
189
	global $tccommands;
190
	return $tccommands;
191
}
192

    
193
readline_completion_function("completion");
194

    
195
function get_playback_files() {
196
	$playback_files = array();
197
	$files = scandir("/etc/phpshellsessions/");
198
	foreach ($files as $file) {
199
		if ($file <> "." && $file <> "..") {
200
			$playback_files[] = $file;
201
		}
202
	}
203
	return $playback_files;
204
}
205

    
206
if ($argc < 2) {
207
	echo "Welcome to the {$g['product_label']} developer shell\n";
208
	echo "\nType \"help\" to show common usage scenarios.\n";
209
	echo "\nAvailable playback commands:\n     ";
210
	$tccommands[] = "playback";
211
	$playback_files = get_playback_files();
212
	foreach ($playback_files as $pbf) {
213
		echo "{$pbf} ";
214
		if (function_exists("readline_add_history")) {
215
			readline_add_history("playback $pbf");
216
			$tccommands[] = "$pbf";
217
		}
218
	}
219
	echo "\n\n";
220
}
221

    
222
$recording = false;
223
$playback_file_split = array();
224
$playbackbuffer = "";
225

    
226
if ($argv[1]=="playback" or $argv[1]=="run") {
227
	if (empty($argv[2]) || !file_exists("/etc/phpshellsessions/" . basename($argv[2]))) {
228
		echo "Error: Invalid playback file specified.\n\n";
229
		show_recordings();
230
		exit(-1);
231
	}
232
	playback_file(basename($argv[2]));
233
	exit;
234
}
235

    
236
// Define more commands
237
$tccommands[] = "exit";
238
$tccommands[] = "quit";
239
$tccommands[] = "?";
240
$tccommands[] = "exec";
241
$tccommands[] = "stoprecording";
242
$tccommands[] = "showrecordings";
243
$tccommands[] = "record";
244
$tccommands[] = "reset";
245
$tccommands[] = "master";
246
$tccommands[] = "RELENG_1_2";
247

    
248
while ($shell_active == true) {
249
	$command = readline("{$g['product_label']} shell: ");
250
	readline_add_history($command);
251
	$command_split = explode(" ", $command);
252
	$first_command = $command_split[0];
253
	if ($first_command == "playback" || $first_command == "run") {
254
		$playback_file = $command_split[1];
255
		if (!$playback_file || !file_exists("/etc/phpshellsessions/{$playback_file}")) {
256
			$command = "";
257
			echo "Could not locate playback file.\n";
258
		} else {
259
			$command = "";
260
			echo "\nPlayback of file {$command_split[1]} started.\n\n";
261
			playback_file("{$playback_file}");
262
			continue;
263
		}
264
	}
265
	if ($first_command == "exit" or $first_command == "quit") {
266
		die;
267
	}
268
	if ($first_command == "help" or $first_command == "?") {
269
		show_help();
270
		$playbackbuffer = "";
271
		continue;
272
	}
273
	if ($first_command == "exec" or $first_command == "exec;") {
274
		playback_text($playbackbuffer);
275
		$playbackbuffer = "";
276
		continue;
277
	}
278
	if ($first_command == "stoprecording" || $first_command == "stoprecord" || $first_command == "stop") {
279
		if ($recording) {
280
			fwrite($recording_fd, $playbackbuffer);
281
			fclose($recording_fd);
282
			$command = "";
283
			echo "Recording stopped.\n";
284
			$recording = false;
285
		} else {
286
			echo "No recording session in progress.\n";
287
			$command = "";
288
		}
289
	}
290
	if ($first_command == "showrecordings") {
291
		show_recordings();
292
		$command = "";
293
	}
294
	if ($first_command == "reset") {
295
		$playbackbuffer = "";
296
		echo "\nBuffer reset.\n\n";
297
		continue;
298
	}
299
	if ($first_command == "record") {
300
		if (!$command_split[1]) {
301
			echo "usage: record playbackname\n";
302
			echo "\tplaybackname will be created in /etc/phpshellsessions.\n";
303
			$command = "";
304
		} else {
305
			/* time to record */
306
			safe_mkdir("/etc/phpshellsessions");
307
			$recording_fn = basename($command_split[1]);
308
			$recording_fd = fopen("/etc/phpshellsessions/{$recording_fn}","w");
309
			if (!$recording_fd) {
310
				echo "Could not start recording session.\n";
311
				$command = "";
312
			} else {
313
				$recording = true;
314
				echo "Recording of {$recording_fn} started.\n";
315
				$command = "";
316
			}
317
		}
318
	}
319
	$playbackbuffer .= $command . "\n";
320
}
321

    
322
function show_recordings() {
323
	echo "==> Sessions available for playback are:\n";
324
	$playback_files = get_playback_files();
325
	foreach (get_playback_files() as $pbf) {
326
		echo "{$pbf} ";
327
	}
328
	echo "\n\n";
329
	echo "==> end of list.\n";
330
}
331

    
332
function returnlastchar($command) {
333
	$commandlen = strlen($command);
334
	$endofstring = substr($command, ($commandlen-1));
335
	return $endofstring;
336
}
337

    
338
function returnfirstchar($command) {
339
	$commandlen = strlen($command);
340
	$endofstring = substr($command, 0, 1);
341
	return $endofstring;
342
}
343

    
344
function str_replace_all($search,$replace,$subject) {
345
	while (strpos($subject,$search)!==false) {
346
		$subject = str_replace($search,$replace,$subject);
347
	}
348
	return $subject;
349
}
350

    
351
function playback_text($playback_file_contents) {
352
	$playback_file_split = explode("\n", $playback_file_contents);
353
	$playback_text  = "require_once('functions.inc');\n";
354
	$playback_text .= "require_once('globals.inc');\n";
355
	$playback_text .= "require_once('config.inc');\n";
356
	$toquote = '"';
357
	$toquotereplace = '\\"';
358
	foreach ($playback_file_split as $pfs) {
359
		$firstchar = returnfirstchar($pfs);
360
		$currentline = $pfs;
361
		if ($firstchar == "!") {
362
			/* XXX: encode " in $pfs */
363
			$pfsa = str_replace($toquote, $toquotereplace, $currentline);
364
			$playback_text .= str_replace("!", "system(\"", $pfsa) . "\");\n";
365
		} else if ($firstchar == "=") {
366
			/* XXX: encode " in $pfs */
367
			$pfsa = str_replace($toquote, $toquotereplace, $currentline);
368
			$currentline   .= str_replace("!", "system(\"", $pfsa) . "\");\n";
369
		} else {
370
			$playback_text .= $pfs . "\n";
371
		}
372
	}
373
	global $config;
374
	eval($playback_text);
375
}
376

    
377
function playback_file($playback_file) {
378
	$playback_file_contents = file_get_contents("/etc/phpshellsessions/{$playback_file}");
379
	playback_text($playback_file_contents);
380
}
381

    
382
?>
(19-19/37)