Project

General

Profile

Download (37.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	firewall_aliases_edit.php
5
	Copyright (C) 2004 Scott Ullrich
6
	Copyright (C) 2009 Ermal Luçi
7
	Copyright (C) 2010 Jim Pingle
8
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
9
	All rights reserved.
10

    
11
	originally part of m0n0wall (http://m0n0.ch/wall)
12
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
	All rights reserved.
14

    
15
	Redistribution and use in source and binary forms, with or without
16
	modification, are permitted provided that the following conditions are met:
17

    
18
	1. Redistributions of source code must retain the above copyright notice,
19
	   this list of conditions and the following disclaimer.
20

    
21
	2. Redistributions in binary form must reproduce the above copyright
22
	   notice, this list of conditions and the following disclaimer in the
23
	   documentation and/or other materials provided with the distribution.
24

    
25
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
	POSSIBILITY OF SUCH DAMAGE.
35
*/
36
/*
37
	pfSense_BUILDER_BINARIES:	/bin/rm	/bin/mkdir	/usr/bin/fetch
38
	pfSense_MODULE:	aliases
39
*/
40

    
41
##|+PRIV
42
##|*IDENT=page-firewall-alias-edit
43
##|*NAME=Firewall: Alias: Edit page
44
##|*DESCR=Allow access to the 'Firewall: Alias: Edit' page.
45
##|*MATCH=firewall_aliases_edit.php*
46
##|-PRIV
47

    
48
require("guiconfig.inc");
49
require_once("functions.inc");
50
require_once("filter.inc");
51
require_once("shaper.inc");
52

    
53
$pgtitle = array(gettext("Firewall"),gettext("Aliases"),gettext("Edit"));
54

    
55
if (isset($_POST['referer'])) {
56
	$referer = $_POST['referer'];
57
} else {
58
	$referer = (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '/firewall_aliases.php');
59
}
60

    
61
// Keywords not allowed in names
62
$reserved_keywords = array("all", "pass", "block", "out", "queue", "max", "min", "pptp", "pppoe", "L2TP", "OpenVPN", "IPsec");
63

    
64
// Add all Load balance names to reserved_keywords
65
if (is_array($config['load_balancer']['lbpool']))
66
	foreach ($config['load_balancer']['lbpool'] as $lbpool)
67
		$reserved_keywords[] = $lbpool['name'];
68

    
69
$reserved_ifs = get_configured_interface_list(false, true);
70
$reserved_keywords = array_merge($reserved_keywords, $reserved_ifs, $reserved_table_names);
71
$max_alias_addresses = 5000;
72

    
73
if (!is_array($config['aliases']['alias']))
74
	$config['aliases']['alias'] = array();
75
$a_aliases = &$config['aliases']['alias'];
76

    
77
$tab = $_REQUEST['tab'];
78

    
79
if($_POST)
80
	$origname = $_POST['origname'];
81

    
82
// Debugging
83
if($debug)
84
	unlink_if_exists("{$g['tmp_path']}/alias_rename_log.txt");
85

    
86
function alias_same_type($name, $type) {
87
	global $config;
88

    
89
	foreach ($config['aliases']['alias'] as $alias) {
90
		if ($name == $alias['name']) {
91
			if (in_array($type, array("host", "network")) &&
92
				in_array($alias['type'], array("host", "network")))
93
				return true;
94
			if ($type  == $alias['type'])
95
				return true;
96
			else
97
				return false;
98
		}
99
	}
100
	return true;
101
}
102

    
103
if (is_numericint($_GET['id']))
104
	$id = $_GET['id'];
105
if (isset($_POST['id']) && is_numericint($_POST['id']))
106
	$id = $_POST['id'];
107

    
108
if (isset($id) && $a_aliases[$id]) {
109
	$original_alias_name = $a_aliases[$id]['name'];
110
	$pconfig['name'] = $a_aliases[$id]['name'];
111
	$pconfig['detail'] = $a_aliases[$id]['detail'];
112
	$pconfig['address'] = $a_aliases[$id]['address'];
113
	$pconfig['type'] = $a_aliases[$id]['type'];
114
	$pconfig['descr'] = html_entity_decode($a_aliases[$id]['descr']);
115

    
116
	if(preg_match("/urltable/i", $a_aliases[$id]['type'])) {
117
		$pconfig['address'] = $a_aliases[$id]['url'];
118
		$pconfig['updatefreq'] = $a_aliases[$id]['updatefreq'];
119
	}
120
	if($a_aliases[$id]['aliasurl'] <> "") {
121
		if(is_array($a_aliases[$id]['aliasurl']))
122
			$pconfig['address'] = implode(" ", $a_aliases[$id]['aliasurl']);
123
		else
124
			$pconfig['address'] = $a_aliases[$id]['aliasurl'];
125
	}
126
}
127

    
128
if ($_POST) {
129
	unset($input_errors);
130
	$vertical_bar_err_text = gettext("Vertical bars (|) at start or end, or double in the middle of descriptions not allowed. Descriptions have been cleaned. Check and save again.");
131

    
132
	/* input validation */
133

    
134
	$reqdfields = explode(" ", "name");
135
	$reqdfieldsn = array(gettext("Name"));
136

    
137
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
138

    
139
	$x = is_validaliasname($_POST['name']);
140
	if (!isset($x)) {
141
		$input_errors[] = gettext("Reserved word used for alias name.");
142
	} else if ($_POST['type'] == "port" && (getservbyname($_POST['name'], "tcp") || getservbyname($_POST['name'], "udp"))) {
143
		$input_errors[] = gettext("Reserved word used for alias name.");
144
	} else {
145
		if (is_validaliasname($_POST['name']) == false)
146
			$input_errors[] = gettext("The alias name must be less than 32 characters long, may not consist of only numbers, and may only contain the following characters") . " a-z, A-Z, 0-9, _.";
147
	}
148
	/* check for name conflicts */
149
	if (empty($a_aliases[$id])) {
150
		foreach ($a_aliases as $alias) {
151
			if ($alias['name'] == $_POST['name']) {
152
				$input_errors[] = gettext("An alias with this name already exists.");
153
				break;
154
			}
155
		}
156
	}
157

    
158
	/* Check for reserved keyword names */
159
	foreach($reserved_keywords as $rk)
160
		if($rk == $_POST['name'])
161
			$input_errors[] = sprintf(gettext("Cannot use a reserved keyword as alias name %s"), $rk);
162

    
163
	/* check for name interface description conflicts */
164
	foreach($config['interfaces'] as $interface) {
165
		if($interface['descr'] == $_POST['name']) {
166
			$input_errors[] = gettext("An interface description with this name already exists.");
167
			break;
168
		}
169
	}
170

    
171
	$alias = array();
172
	$address = array();
173
	$final_address_details = array();
174
	$alias['name'] = $_POST['name'];
175

    
176
	if (preg_match("/urltable/i", $_POST['type'])) {
177
		$address = "";
178

    
179
		/* item is a url table type */
180
		if ($_POST['address0']) {
181
			/* fetch down and add in */
182
			$_POST['address0'] = trim($_POST['address0']);
183
			$address[] = $_POST['address0'];
184
			$alias['url'] = $_POST['address0'];
185
			$alias['updatefreq'] = $_POST['address_subnet0'] ? $_POST['address_subnet0'] : 7;
186
			if (!is_URL($alias['url']) || empty($alias['url'])) {
187
				$input_errors[] = gettext("You must provide a valid URL.");
188
			} elseif (! process_alias_urltable($alias['name'], $alias['url'], 0, true)) {
189
				$input_errors[] = gettext("Unable to fetch usable data.");
190
			}
191
			if ($_POST["detail0"] <> "") {
192
				if ((strpos($_POST["detail0"], "||") === false) && (substr($_POST["detail0"], 0, 1) != "|") && (substr($_POST["detail0"], -1, 1) != "|")) {
193
					$final_address_details[] = $_POST["detail0"];
194
				} else {
195
					/* Remove leading and trailing vertical bars and replace multiple vertical bars with single, */
196
					/* and put in the output array so the text is at least redisplayed for the user. */
197
					$final_address_details[] = preg_replace('/\|\|+/', '|', trim($_POST["detail0"], "|"));
198
					$input_errors[] = $vertical_bar_err_text;
199
				}
200
			} else
201
				$final_address_details[] = sprintf(gettext("Entry added %s"), date('r'));
202
		}
203
	} else if ($_POST['type'] == "url" || $_POST['type'] == "url_ports") {
204
		$desc_fmt_err_found = false;
205

    
206
		/* item is a url type */
207
		for($x=0; $x<$max_alias_addresses-1; $x++) {
208
			$_POST['address' . $x] = trim($_POST['address' . $x]);
209
			if($_POST['address' . $x]) {
210
				/* fetch down and add in */
211
				$temp_filename = tempnam("{$g['tmp_path']}/", "alias_import");
212
				unlink_if_exists($temp_filename);
213
				$verify_ssl = isset($config['system']['checkaliasesurlcert']);
214
				mkdir($temp_filename);
215
				download_file($_POST['address' . $x], $temp_filename . "/aliases", $verify_ssl);
216

    
217
				/* if the item is tar gzipped then extract */
218
				if(stristr($_POST['address' . $x], ".tgz"))
219
					process_alias_tgz($temp_filename);
220
				else if(stristr($_POST['address' . $x], ".zip"))
221
					process_alias_unzip($temp_filename);
222

    
223
				if (!isset($alias['aliasurl']))
224
					$alias['aliasurl'] = array();
225

    
226
				$alias['aliasurl'][] = $_POST['address' . $x];
227
				if ($_POST["detail{$x}"] <> "") {
228
					if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) {
229
						$final_address_details[] = $_POST["detail{$x}"];
230
					} else {
231
						/* Remove leading and trailing vertical bars and replace multiple vertical bars with single, */
232
						/* and put in the output array so the text is at least redisplayed for the user. */
233
						$final_address_details[] = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|"));
234
						if (!$desc_fmt_err_found) {
235
							$input_errors[] = $vertical_bar_err_text;
236
							$desc_fmt_err_found = true;
237
						}
238
					}
239
				} else
240
					$final_address_details[] = sprintf(gettext("Entry added %s"), date('r'));
241

    
242
				if(file_exists("{$temp_filename}/aliases")) {
243
					$address = parse_aliases_file("{$temp_filename}/aliases", $_POST['type'], 3000);
244
					if($address == null) {
245
						/* nothing was found */
246
						$input_errors[] = sprintf(gettext("You must provide a valid URL. Could not fetch usable data from '%s'."), $_POST['address' . $x]);
247
					}
248
					mwexec("/bin/rm -rf " . escapeshellarg($temp_filename));
249
				} else {
250
					$input_errors[] = sprintf(gettext("URL '%s' is not valid."), $_POST['address' . $x]);
251
				}
252
			}
253
		}
254
		unset($desc_fmt_err_found);
255
		if ($_POST['type'] == "url_ports")
256
			$address = group_ports($address);
257
	} else {
258
		/* item is a normal alias type */
259
		$wrongaliases = "";
260
		$desc_fmt_err_found = false;
261
		$alias_address_count = 0;
262
		$input_addresses = array();
263

    
264
		// First trim and expand the input data. 
265
		// Users can paste strings like "10.1.2.0/24 10.3.0.0/16 9.10.11.0/24" into an address box.
266
		// They can also put an IP range.
267
		// This loop expands out that stuff so it can easily be validated.
268
		for($x=0; $x<($max_alias_addresses-1); $x++) {
269
			if($_POST["address{$x}"] <> "") {
270
				if ($_POST["detail{$x}"] <> "") {
271
					if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) {
272
						$detail_text = $_POST["detail{$x}"];
273
					} else {
274
						/* Remove leading and trailing vertical bars and replace multiple vertical bars with single, */
275
						/* and put in the output array so the text is at least redisplayed for the user. */
276
						$detail_text = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|"));
277
						if (!$desc_fmt_err_found) {
278
							$input_errors[] = $vertical_bar_err_text;
279
							$desc_fmt_err_found = true;
280
						}
281
					}
282
				} else {
283
					$detail_text = sprintf(gettext("Entry added %s"), date('r'));
284
				}
285
				$address_items = explode(" ", trim($_POST["address{$x}"]));
286
				foreach ($address_items as $address_item) {
287
					$iprange_type = is_iprange($address_item);
288
					if ($iprange_type == 4) {
289
						list($startip, $endip) = explode('-', $address_item);
290
						if ($_POST['type'] == "network") {
291
							// For network type aliases, expand an IPv4 range into an array of subnets.
292
							$rangesubnets = ip_range_to_subnet_array($startip, $endip);
293
							foreach ($rangesubnets as $rangesubnet) {
294
								if ($alias_address_count > $max_alias_addresses) {
295
									break;
296
								}
297
								list($address_part, $subnet_part) = explode("/", $rangesubnet);
298
								$input_addresses[] = $address_part;
299
								$input_address_subnet[] = $subnet_part;
300
								$final_address_details[] = $detail_text;
301
								$alias_address_count++;
302
							}
303
						} else {
304
							// For host type aliases, expand an IPv4 range into a list of individual IPv4 addresses.
305
							$rangeaddresses = ip_range_to_address_array($startip, $endip, $max_alias_addresses - $alias_address_count);
306
							if (is_array($rangeaddresses)) {
307
								foreach ($rangeaddresses as $rangeaddress) {
308
									$input_addresses[] = $rangeaddress;
309
									$input_address_subnet[] = "";
310
									$final_address_details[] = $detail_text;
311
									$alias_address_count++;
312
								}
313
							} else {
314
								$input_errors[] = sprintf(gettext('Range is too large to expand into individual host IP addresses (%s)'), $address_item);
315
								$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
316
								// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
317
								$input_addresses[] = $address_item;
318
								$input_address_subnet[] = "";
319
								$final_address_details[] = $detail_text;
320
							}
321
						}
322
					} else if ($iprange_type == 6) {
323
						$input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $address_item);
324
						// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
325
						$input_addresses[] = $address_item;
326
						$input_address_subnet[] = "";
327
						$final_address_details[] = $detail_text;
328
					} else {
329
						$subnet_type = is_subnet($address_item);
330
						if (($_POST['type'] == "host") && $subnet_type) {
331
							if ($subnet_type == 4) {
332
								// For host type aliases, if the user enters an IPv4 subnet, expand it into a list of individual IPv4 addresses.
333
								if (subnet_size($address_item) <= ($max_alias_addresses - $alias_address_count)) {
334
									$rangeaddresses = subnetv4_expand($address_item);
335
									foreach ($rangeaddresses as $rangeaddress) {
336
										$input_addresses[] = $rangeaddress;
337
										$input_address_subnet[] = "";
338
										$final_address_details[] = $detail_text;
339
										$alias_address_count++;
340
									}
341
								} else {
342
									$input_errors[] = sprintf(gettext('Subnet is too large to expand into individual host IP addresses (%s)'), $address_item);
343
									$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
344
									// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
345
									$input_addresses[] = $address_item;
346
									$input_address_subnet[] = "";
347
									$final_address_details[] = $detail_text;
348
								}
349
							} else {
350
								$input_errors[] = sprintf(gettext('IPv6 subnets are not supported in host aliases (%s)'), $address_item);
351
								// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
352
								$input_addresses[] = $address_item;
353
								$input_address_subnet[] = "";
354
								$final_address_details[] = $detail_text;
355
							}
356
						} else {
357
							list($address_part, $subnet_part) = explode("/", $address_item);
358
							if (!empty($subnet_part)) {
359
								if (is_subnet($address_item)) {
360
									$input_addresses[] = $address_part;
361
									$input_address_subnet[] = $subnet_part;
362
								} else {
363
									// The user typed something like "1.2.3.444/24" or "1.2.3.0/36" or similar rubbish.
364
									// Feed it through without splitting it apart, then it will be caught by the validation loop below.
365
									$input_addresses[] = $address_item;
366
									$input_address_subnet[] = "";
367
								}
368
							} else {
369
								$input_addresses[] = $address_part;
370
								$input_address_subnet[] = $_POST["address_subnet{$x}"];
371
							}
372
							$final_address_details[] = $detail_text;
373
							$alias_address_count++;
374
						}
375
					}
376
					if ($alias_address_count > $max_alias_addresses) {
377
						$input_errors[] = sprintf(gettext('The maximum number of entries in an alias has been exceeded (%s)'), $max_alias_addresses);
378
						break;
379
					}
380
				}
381
			}
382
		}
383

    
384
		// Validate the input data expanded above.
385
		foreach($input_addresses as $idx => $input_address) {
386
			if (is_alias($input_address)) {
387
				if (!alias_same_type($input_address, $_POST['type']))
388
					// But alias type network can include alias type urltable. Feature#1603.
389
					if (!($_POST['type'] == 'network' &&
390
						  preg_match("/urltable/i", alias_get_type($input_address))))
391
						$wrongaliases .= " " . $input_address;
392
			} else if ($_POST['type'] == "port") {
393
				if (!is_port($input_address) && !is_portrange($input_address))
394
					$input_errors[] = $input_address . " " . gettext("is not a valid port or alias.");
395
			} else if ($_POST['type'] == "host" || $_POST['type'] == "network") {
396
				if (is_subnet($input_address) || 
397
					(!is_ipaddr($input_address) && !is_hostname($input_address)))
398
					$input_errors[] = sprintf(gettext('%1$s is not a valid %2$s address, FQDN or alias.'), $input_address, $_POST['type']);
399
			}
400
			$tmpaddress = $input_address;
401
			if ($_POST['type'] != "host" && is_ipaddr($input_address) && $input_address_subnet[$idx] <> "") {
402
				if (!is_subnet($input_address . "/" . $input_address_subnet[$idx]))
403
					$input_errors[] = sprintf(gettext('%s/%s is not a valid subnet.'), $input_address, $input_address_subnet[$idx]);
404
				else
405
					$tmpaddress .= "/" . $input_address_subnet[$idx];
406
			}
407
			$address[] = $tmpaddress;
408
		}
409
		unset($desc_fmt_err_found);
410
		if ($wrongaliases <> "")
411
			$input_errors[] = sprintf(gettext('The alias(es): %s cannot be nested because they are not of the same type.'), $wrongaliases);
412
	}
413

    
414
	unset($vertical_bar_err_text);
415

    
416
	// Allow extending of the firewall edit page and include custom input validation
417
	pfSense_handle_custom_code("/usr/local/pkg/firewall_aliases_edit/input_validation");
418

    
419
	if (!$input_errors) {
420
		$alias['address'] = is_array($address) ? implode(" ", $address) : $address;
421
		$alias['descr'] = $_POST['descr'];
422
		$alias['type'] = $_POST['type'];
423
		$alias['detail'] = implode("||", $final_address_details);
424

    
425
		/*   Check to see if alias name needs to be
426
		 *   renamed on referenced rules and such
427
		 */
428
		if ($_POST['name'] <> $_POST['origname']) {
429
			// Firewall rules
430
			update_alias_names_upon_change(array('filter', 'rule'), array('source', 'address'), $_POST['name'], $origname);
431
			update_alias_names_upon_change(array('filter', 'rule'), array('destination', 'address'), $_POST['name'], $origname);
432
			update_alias_names_upon_change(array('filter', 'rule'), array('source', 'port'), $_POST['name'], $origname);
433
			update_alias_names_upon_change(array('filter', 'rule'), array('destination', 'port'), $_POST['name'], $origname);
434
			// NAT Rules
435
			update_alias_names_upon_change(array('nat', 'rule'), array('source', 'address'), $_POST['name'], $origname);
436
			update_alias_names_upon_change(array('nat', 'rule'), array('source', 'port'), $_POST['name'], $origname);
437
			update_alias_names_upon_change(array('nat', 'rule'), array('destination', 'address'), $_POST['name'], $origname);
438
			update_alias_names_upon_change(array('nat', 'rule'), array('destination', 'port'), $_POST['name'], $origname);
439
			update_alias_names_upon_change(array('nat', 'rule'), array('target'), $_POST['name'], $origname);
440
			update_alias_names_upon_change(array('nat', 'rule'), array('local-port'), $_POST['name'], $origname);
441
			// NAT 1:1 Rules
442
			//update_alias_names_upon_change(array('nat', 'onetoone'), array('external'), $_POST['name'], $origname);
443
			//update_alias_names_upon_change(array('nat', 'onetoone'), array('source', 'address'), $_POST['name'], $origname);
444
			update_alias_names_upon_change(array('nat', 'onetoone'), array('destination', 'address'), $_POST['name'], $origname);
445
			// NAT Outbound Rules
446
			update_alias_names_upon_change(array('nat', 'outbound', 'rule'), array('source', 'network'), $_POST['name'], $origname);
447
			update_alias_names_upon_change(array('nat', 'outbound', 'rule'), array('sourceport'), $_POST['name'], $origname);
448
			update_alias_names_upon_change(array('nat', 'outbound', 'rule'), array('destination', 'address'), $_POST['name'], $origname);
449
			update_alias_names_upon_change(array('nat', 'outbound', 'rule'), array('dstport'), $_POST['name'], $origname);
450
			update_alias_names_upon_change(array('nat', 'outbound', 'rule'), array('target'), $_POST['name'], $origname);
451
			// Alias in an alias
452
			update_alias_names_upon_change(array('aliases', 'alias'), array('address'), $_POST['name'], $origname);
453
		}
454

    
455
		pfSense_handle_custom_code("/usr/local/pkg/firewall_aliases_edit/pre_write_config");
456

    
457
		if (isset($id) && $a_aliases[$id]) {
458
			if ($a_aliases[$id]['name'] <> $alias['name']) {
459
				foreach ($a_aliases as $aliasid => $aliasd) {
460
					if ($aliasd['address'] <> "") {
461
						$tmpdirty = false;
462
						$tmpaddr = explode(" ", $aliasd['address']);
463
						foreach ($tmpaddr as $tmpidx => $tmpalias) {
464
							if ($tmpalias == $a_aliases[$id]['name']) {
465
								$tmpaddr[$tmpidx] = $alias['name'];
466
								$tmpdirty = true;
467
							}
468
						}
469
						if ($tmpdirty == true)
470
							$a_aliases[$aliasid]['address'] = implode(" ", $tmpaddr);
471
					}
472
				}
473
			}
474
			$a_aliases[$id] = $alias;
475
		} else
476
			$a_aliases[] = $alias;
477

    
478
		// Sort list
479
		$a_aliases = msort($a_aliases, "name");
480

    
481
		if (write_config())
482
			mark_subsystem_dirty('aliases');
483

    
484
		if(!empty($tab))
485
			header("Location: firewall_aliases.php?tab=" . htmlspecialchars ($tab));
486
		else
487
			header("Location: firewall_aliases.php");
488
		exit;
489
	}
490
	//we received input errors, copy data to prevent retype
491
	else
492
	{
493
		$pconfig['name'] = $_POST['name'];
494
		$pconfig['descr'] = $_POST['descr'];
495
		if (($_POST['type'] == 'url') || ($_POST['type'] == 'url_ports'))
496
			$pconfig['address'] = implode(" ", $alias['aliasurl']);
497
		else
498
			$pconfig['address'] = implode(" ", $address);
499
		$pconfig['type'] = $_POST['type'];
500
		$pconfig['detail'] = implode("||", $final_address_details);
501
	}
502
}
503

    
504
include("head.inc");
505

    
506
$jscriptstr = <<<EOD
507

    
508
<script type="text/javascript">
509
//<![CDATA[
510
var objAlias = new Array(4999);
511
function typesel_change() {
512
	var field_disabled = 0;
513
	var field_value = "";
514
	var set_value = false;
515
	switch (document.iform.type.selectedIndex) {
516
		case 0:	/* host */
517
			field_disabled = 1;
518
			field_value = "";
519
			set_value = true;
520
			break;
521
		case 1:	/* network */
522
			field_disabled = 0;
523
			break;
524
		case 2:	/* port */
525
			field_disabled = 1;
526
			field_value = "128";
527
			set_value = true;
528
			break;
529
		case 3:	/* url */
530
			field_disabled = 1;
531
			break;
532
		case 4:	/* url_ports */
533
			field_disabled = 1;
534
			break;
535
		case 5:	/* urltable */
536
			field_disabled = 0;
537
			break;
538
		case 6:	/* urltable_ports */
539
			field_disabled = 0;
540
			break;
541
	}
542

    
543
	jQuery("select[id^='address_subnet']").prop("disabled", field_disabled);
544
	if (set_value == true)
545
		jQuery("select[id^='address_subnet']").prop("value", field_value);
546
}
547

    
548
function add_alias_control() {
549
	var name = "address" + (totalrows - 1);
550
	obj = document.getElementById(name);
551
	obj.setAttribute('class', 'formfldalias');
552
	obj.setAttribute('autocomplete', 'off');
553
	objAlias[totalrows - 1] = new AutoSuggestControl(obj, new StateSuggestions(addressarray));
554
}
555
EOD;
556

    
557
$network_str = gettext("Network or FQDN");
558
$networks_str = gettext("Network(s)");
559
$cidr_str = gettext("CIDR");
560
$description_str = gettext("Description");
561
$hosts_str = gettext("Host(s)");
562
$ip_str = gettext("IP or FQDN");
563
$ports_str = gettext("Port(s)");
564
$port_str = gettext("Port");
565
$url_str = gettext("URL (IPs)");
566
$url_ports_str = gettext("URL (Ports)");
567
$urltable_str = gettext("URL Table (IPs)");
568
$urltable_ports_str = gettext("URL Table (Ports)");
569
$update_freq_str = gettext("Update Freq. (days)");
570

    
571
$networks_help = gettext("Networks are specified in CIDR format.  Select the CIDR mask that pertains to each entry. /32 specifies a single IPv4 host, /128 specifies a single IPv6 host, /24 specifies 255.255.255.0, /64 specifies a normal IPv6 network, etc. Hostnames (FQDNs) may also be specified, using a /32 mask for IPv4 or /128 for IPv6. You may also enter an IP range such as 192.168.1.1-192.168.1.254 and a list of CIDR networks will be derived to fill the range.");
572
$hosts_help = gettext("Enter as many hosts as you would like.  Hosts must be specified by their IP address or fully qualified domain name (FQDN). FQDN hostnames are periodically re-resolved and updated. If multiple IPs are returned by a DNS query, all are used. You may also enter an IP range such as 192.168.1.1-192.168.1.10 or a small subnet such as 192.168.1.16/28 and a list of individual IP addresses will be generated.");
573
$ports_help = gettext("Enter as many ports as you wish.  Port ranges can be expressed by separating with a colon.");
574
$url_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of IP addresses (less than 3000)."), $g['product_name']);
575
$url_ports_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of Ports (less than 3000)."), $g['product_name']);
576
$urltable_help = sprintf(gettext("Enter a single URL containing a large number of IPs and/or Subnets. After saving %s will download the URL and create a table file containing these addresses. This will work with large numbers of addresses (30,000+) or small numbers."), $g['product_name']);
577
$urltable_ports_help = sprintf(gettext("Enter a single URL containing a list of Port numbers and/or Port ranges. After saving %s will download the URL."), $g['product_name']);
578

    
579
$openvpn_str = gettext("Username");
580
$openvpn_user_str = gettext("OpenVPN Users");
581
$openvpn_help = gettext("Enter as many usernames as you wish.");
582
$openvpn_freq = "";
583

    
584
$jscriptstr .= <<<EOD
585

    
586
function update_box_type() {
587
	var indexNum = document.forms[0].type.selectedIndex;
588
	var selected = document.forms[0].type.options[indexNum].text;
589
	if(selected == '{$networks_str}') {
590
		document.getElementById ("addressnetworkport").firstChild.data = "{$networks_str}";
591
		document.getElementById ("onecolumn").firstChild.data = "{$network_str}";
592
		document.getElementById ("twocolumn").firstChild.data = "{$cidr_str}";
593
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
594
		document.getElementById ("threecolumn").style.display = 'block';
595
		document.getElementById ("itemhelp").firstChild.data = "{$networks_help}";
596
		document.getElementById ("addrowbutton").style.display = 'block';
597
	} else if(selected == '{$hosts_str}') {
598
		document.getElementById ("addressnetworkport").firstChild.data = "{$hosts_str}";
599
		document.getElementById ("onecolumn").firstChild.data = "{$ip_str}";
600
		document.getElementById ("twocolumn").firstChild.data = "";
601
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
602
		document.getElementById ("threecolumn").style.display = 'block';
603
		document.getElementById ("itemhelp").firstChild.data = "{$hosts_help}";
604
		document.getElementById ("addrowbutton").style.display = 'block';
605
	} else if(selected == '{$ports_str}') {
606
		document.getElementById ("addressnetworkport").firstChild.data = "{$ports_str}";
607
		document.getElementById ("onecolumn").firstChild.data = "{$port_str}";
608
		document.getElementById ("twocolumn").firstChild.data = "";
609
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
610
		document.getElementById ("threecolumn").style.display = 'block';
611
		document.getElementById ("itemhelp").firstChild.data = "{$ports_help}";
612
		document.getElementById ("addrowbutton").style.display = 'block';
613
	} else if(selected == '{$url_str}') {
614
		document.getElementById ("addressnetworkport").firstChild.data = "{$url_str}";
615
		document.getElementById ("onecolumn").firstChild.data = "{$url_str}";
616
		document.getElementById ("twocolumn").firstChild.data = "";
617
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
618
		document.getElementById ("threecolumn").style.display = 'block';
619
		document.getElementById ("itemhelp").firstChild.data = "{$url_help}";
620
		document.getElementById ("addrowbutton").style.display = 'block';
621
	} else if(selected == '{$url_ports_str}') {
622
		document.getElementById ("addressnetworkport").firstChild.data = "{$url_ports_str}";
623
		document.getElementById ("onecolumn").firstChild.data = "{$url_ports_str}";
624
		document.getElementById ("twocolumn").firstChild.data = "";
625
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
626
		document.getElementById ("threecolumn").style.display = 'block';
627
		document.getElementById ("itemhelp").firstChild.data = "{$url_ports_help}";
628
		document.getElementById ("addrowbutton").style.display = 'block';
629
	} else if(selected == '{$openvpn_user_str}') {
630
		document.getElementById ("addressnetworkport").firstChild.data = "{$openvpn_user_str}";
631
		document.getElementById ("onecolumn").firstChild.data = "{$openvpn_str}";
632
		document.getElementById ("twocolumn").firstChild.data = "{$openvpn_freq}";
633
		document.getElementById ("threecolumn").firstChild.data = "{$description_str}";
634
		document.getElementById ("threecolumn").style.display = 'block';
635
		document.getElementById ("itemhelp").firstChild.data = "{$openvpn_help}";
636
		document.getElementById ("addrowbutton").style.display = 'block';
637
	} else if(selected == '{$urltable_str}') {
638
		if ((typeof(totalrows) == "undefined") || (totalrows < 1)) {
639
			addRowTo('maintable', 'formfldalias');
640
			typesel_change();
641
			add_alias_control(this);
642
		}
643
		document.getElementById ("addressnetworkport").firstChild.data = "{$urltable_str}";
644
		document.getElementById ("onecolumn").firstChild.data = "{$urltable_str}";
645
		document.getElementById ("twocolumn").firstChild.data = "{$update_freq_str}";
646
		document.getElementById ("threecolumn").firstChild.data = "";
647
		document.getElementById ("threecolumn").style.display = 'none';
648
		document.getElementById ("itemhelp").firstChild.data = "{$urltable_help}";
649
		document.getElementById ("addrowbutton").style.display = 'none';
650
	} else if(selected == '{$urltable_ports_str}') {
651
		if ((typeof(totalrows) == "undefined") || (totalrows < 1)) {
652
			addRowTo('maintable', 'formfldalias');
653
			typesel_change();
654
			add_alias_control(this);
655
		}
656
		document.getElementById ("addressnetworkport").firstChild.data = "{$urltable_ports_str}";
657
		document.getElementById ("onecolumn").firstChild.data = "{$urltable_ports_str}";
658
		document.getElementById ("twocolumn").firstChild.data = "{$update_freq_str}";
659
		document.getElementById ("threecolumn").firstChild.data = "";
660
		document.getElementById ("threecolumn").style.display = 'none';
661
		document.getElementById ("itemhelp").firstChild.data = "{$urltable_ports_help}";
662
		document.getElementById ("addrowbutton").style.display = 'none';
663
	}
664
}
665
//]]>
666
</script>
667

    
668
EOD;
669

    
670
?>
671

    
672
<body link="#0000CC" vlink="#0000CC" alink="#0000CC" onload="<?= $jsevents["body"]["onload"] ?>">
673
<?php
674
	include("fbegin.inc");
675
	echo $jscriptstr;
676
?>
677

    
678
<script type="text/javascript" src="/javascript/jquery.ipv4v6ify.js"></script>
679
<script type="text/javascript" src="/javascript/row_helper.js"></script>
680
<script type="text/javascript" src="/javascript/autosuggest.js?rev=1"></script>
681
<script type="text/javascript" src="/javascript/suggestions.js"></script>
682

    
683
<input type='hidden' name='address_type' value='textbox' />
684
<input type='hidden' name='address_subnet_type' value='select' />
685

    
686
<script type="text/javascript">
687
//<![CDATA[
688
	rowname[0] = "address";
689
	rowtype[0] = "textbox,ipv4v6";
690
	rowsize[0] = "30";
691

    
692
	rowname[1] = "address_subnet";
693
	rowtype[1] = "select,ipv4v6";
694
	rowsize[1] = "1";
695

    
696
	rowname[2] = "detail";
697
	rowtype[2] = "textbox";
698
	rowsize[2] = "50";
699
//]]>
700
</script>
701

    
702
<?php pfSense_handle_custom_code("/usr/local/pkg/firewall_aliases_edit/pre_input_errors"); ?>
703
<?php if ($input_errors) print_input_errors($input_errors); ?>
704
<div id="inputerrors"></div>
705

    
706
<form action="firewall_aliases_edit.php" method="post" name="iform" id="iform">
707
<?php
708
if (empty($tab)) {
709
	if (preg_match("/url/i", $pconfig['type']))
710
		$tab = 'url';
711
	else if ($pconfig['type'] == 'host')
712
		$tab = 'ip';
713
	else
714
		$tab = $pconfig['type'];
715
}
716
?>
717
<input name="tab" type="hidden" id="tab" value="<?=htmlspecialchars($tab);?>" />
718
<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0" summary="firewall aliases edit">
719
	<tr>
720
		<td colspan="2" valign="top" class="listtopic"><?=gettext("Alias Edit"); ?></td>
721
	</tr>
722
	<tr>
723
		<td valign="top" class="vncellreq"><?=gettext("Name"); ?></td>
724
		<td class="vtable">
725
			<input name="origname" type="hidden" id="origname" class="formfld unknown" size="40" value="<?=htmlspecialchars($pconfig['name']);?>" />
726
			<input name="name" type="text" id="name" class="formfld unknown" size="40" maxlength="31" value="<?=htmlspecialchars($pconfig['name']);?>" />
727
			<?php if (isset($id) && $a_aliases[$id]): ?>
728
				<input name="id" type="hidden" value="<?=htmlspecialchars($id);?>" />
729
			<?php endif; ?>
730
			<br />
731
			<span class="vexpl">
732
				<?=gettext("The name of the alias may only consist of the characters \"a-z, A-Z, 0-9 and _\"."); ?>
733
			</span>
734
		</td>
735
	</tr>
736
	<?php pfSense_handle_custom_code("/usr/local/pkg/firewall_aliases_edit/after_first_tr"); ?>
737
	<tr>
738
		<td width="22%" valign="top" class="vncell"><?=gettext("Description"); ?></td>
739
		<td width="78%" class="vtable">
740
			<input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>" />
741
			<br />
742
			<span class="vexpl">
743
				<?=gettext("You may enter a description here for your reference (not parsed)."); ?>
744
			</span>
745
		</td>
746
	</tr>
747
	<tr>
748
		<td valign="top" class="vncellreq"><?=gettext("Type"); ?></td>
749
		<td class="vtable">
750
			<select name="type" class="formselect" id="type" onchange="update_box_type(); typesel_change();">
751
				<option value="host" <?php if ($pconfig['type'] == "host") echo "selected=\"selected\""; ?>><?=gettext("Host(s)"); ?></option>
752
				<option value="network" <?php if ($pconfig['type'] == "network") echo "selected=\"selected\""; ?>><?=gettext("Network(s)"); ?></option>
753
				<option value="port" <?php if (($pconfig['type'] == "port") || (empty($pconfig['type']) && ($tab == "port"))) echo "selected=\"selected\""; ?>><?=gettext("Port(s)"); ?></option>
754
				<!--<option value="openvpn" <?php if ($pconfig['type'] == "openvpn") echo "selected=\"selected\""; ?>><?=gettext("OpenVPN Users"); ?></option> -->
755
				<option value="url" <?php if (($pconfig['type'] == "url") || (empty($pconfig['type']) && ($tab == "url"))) echo "selected=\"selected\""; ?>><?=gettext("URL (IPs)");?></option>
756
				<option value="url_ports" <?php if ($pconfig['type'] == "url_ports") echo "selected=\"selected\""; ?>><?=gettext("URL (Ports)");?></option>
757
				<option value="urltable" <?php if ($pconfig['type'] == "urltable") echo "selected=\"selected\""; ?>><?=gettext("URL Table (IPs)"); ?></option>
758
				<option value="urltable_ports" <?php if ($pconfig['type'] == "urltable_ports") echo "selected=\"selected\""; ?>><?=gettext("URL Table (Ports)"); ?></option>
759
			</select>
760
		</td>
761
	</tr>
762
	<tr>
763
		<td width="22%" valign="top" class="vncellreq"><div id="addressnetworkport"><?=gettext("Host(s)"); ?></div></td>
764
		<td width="78%" class="vtable">
765
			<table id="maintable" summary="maintable">
766
				<tbody>
767
					<tr>
768
						<td colspan="4">
769
							<div style="padding:5px; margin-top: 16px; margin-bottom: 16px; border:1px dashed #000066; background-color: #ffffff; color: #000000; font-size: 8pt;" id="itemhelp"><?=gettext("Item information"); ?></div>
770
						</td>
771
					</tr>
772
					<tr>
773
						<td><div id="onecolumn"><?=gettext("Network"); ?></div></td>
774
						<td><div id="twocolumn">CIDR</div></td>
775
						<td><div id="threecolumn"><?=gettext("Description"); ?></div></td>
776
					</tr>
777

    
778
					<?php
779
					$counter = 0;
780
					if ($pconfig['address'] <> ""):
781
						$addresses = explode(" ", $pconfig['address']);
782
						$details = explode("||", $pconfig['detail']);
783
						while ($counter < count($addresses)):
784
							if (($pconfig['type'] != "host") && is_subnet($addresses[$counter])) {
785
								list($address, $address_subnet) = explode("/", $addresses[$counter]);
786
							} else {
787
								$address = $addresses[$counter];
788
								$address_subnet = "";
789
							}
790
					?>
791
					<tr>
792
						<td>
793
							<input autocomplete="off" name="address<?php echo $counter; ?>" type="text" class="formfldalias ipv4v6" id="address<?php echo $counter; ?>" size="30" value="<?=htmlspecialchars($address);?>" />
794
						</td>
795
						<td>
796
							<select name="address_subnet<?php echo $counter; ?>" class="formselect ipv4v6" id="address_subnet<?php echo $counter; ?>">
797
								<option></option>
798
								<?php for ($i = 128; $i >= 1; $i--): ?>
799
									<option value="<?=$i;?>" <?php if (($i == $address_subnet) || ($i == $pconfig['updatefreq'])) echo "selected=\"selected\""; ?>><?=$i;?></option>
800
								<?php endfor; ?>
801
							</select>
802
						</td>
803
						<td>
804
							<input name="detail<?php echo $counter; ?>" type="text" class="formfld unknown" id="detail<?php echo $counter; ?>" size="50" value="<?=htmlspecialchars($details[$counter]);?>" />
805
						</td>
806
						<td>
807
							<a onclick="removeRow(this); return false;" href="#"><img border="0" src="/themes/<?echo $g['theme'];?>/images/icons/icon_x.gif" alt="" title="<?=gettext("remove this entry"); ?>" /></a>
808
						</td>
809
					</tr>
810
					<?php
811
						$counter++;
812

    
813
						endwhile;
814
					endif;
815
					?>
816
				</tbody>
817
			</table>
818
			<div id="addrowbutton">
819
				<a onclick="javascript:addRowTo('maintable', 'formfldalias'); typesel_change(); add_alias_control(this); return false;" href="#">
820
					<img border="0" src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" alt="" title="<?=gettext("add another entry"); ?>" />
821
				</a>
822
			</div>
823
		</td>
824
	</tr>
825
	<tr>
826
		<td width="22%" valign="top">&nbsp;</td>
827
		<td width="78%">
828
			<input id="submit" name="submit" type="submit" class="formbtn" value="<?=gettext("Save"); ?>" />
829
			<input type="button" class="formbtn" value="<?=gettext("Cancel");?>" onclick="window.location.href='<?=$referer;?>'" />
830
			<input name="referer" type="hidden" value="<?=$referer;?>" />
831
		</td>
832
	</tr>
833
</table>
834
</form>
835

    
836
<script type="text/javascript">
837
//<![CDATA[
838
	field_counter_js = 3;
839
	rows = 1;
840
	totalrows = <?php echo $counter; ?>;
841
	loaded = <?php echo $counter; ?>;
842
	typesel_change();
843
	update_box_type();
844

    
845
	var addressarray = <?= json_encode(array_exclude($pconfig['name'], get_alias_list($pconfig['type']))) ?>;
846

    
847
	function createAutoSuggest() {
848
		<?php
849
		for ($jv = 0; $jv < $counter; $jv++)
850
			echo "objAlias[{$jv}] = new AutoSuggestControl(document.getElementById(\"address{$jv}\"), new StateSuggestions(addressarray));\n";
851
		?>
852
	}
853

    
854
	setTimeout("createAutoSuggest();", 500);
855
//]]>
856
</script>
857

    
858
<?php include("fend.inc"); ?>
859
</body>
860
</html>
(61-61/252)