Revision 46245a43
Added by Reid Linnemann over 2 years ago
src/usr/local/pfSense/include/www/alias-utils.inc | ||
---|---|---|
35 | 35 |
$a_aliases = &$config['aliases']['alias']; |
36 | 36 |
|
37 | 37 |
function deleteAlias($id, $apply = false) { |
38 |
global $config; |
|
39 |
|
|
40 | 38 |
/* make sure rule is not being referenced by any nat or filter rules */ |
41 | 39 |
init_config_arr(array('aliases', 'alias')); |
42 |
$a_aliases = &$config['aliases']['alias'];
|
|
40 |
$a_aliases = config_get_path('aliases/alias', []);
|
|
43 | 41 |
|
44 | 42 |
$delete_error = ""; |
45 | 43 |
$is_alias_referenced = false; |
46 | 44 |
$referenced_by = array(); |
47 | 45 |
$alias_name = $a_aliases[$id]['name']; |
48 |
// Firewall rules |
|
49 |
find_alias_reference(array('filter', 'rule'), array('source', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
50 |
find_alias_reference(array('filter', 'rule'), array('destination', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
51 |
find_alias_reference(array('filter', 'rule'), array('source', 'port'), $alias_name, $is_alias_referenced, $referenced_by); |
|
52 |
find_alias_reference(array('filter', 'rule'), array('destination', 'port'), $alias_name, $is_alias_referenced, $referenced_by); |
|
53 |
// NAT Rules |
|
54 |
find_alias_reference(array('nat', 'rule'), array('source', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
55 |
find_alias_reference(array('nat', 'rule'), array('source', 'port'), $alias_name, $is_alias_referenced, $referenced_by); |
|
56 |
find_alias_reference(array('nat', 'rule'), array('destination', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
57 |
find_alias_reference(array('nat', 'rule'), array('destination', 'port'), $alias_name, $is_alias_referenced, $referenced_by); |
|
58 |
find_alias_reference(array('nat', 'rule'), array('target'), $alias_name, $is_alias_referenced, $referenced_by); |
|
59 |
find_alias_reference(array('nat', 'rule'), array('local-port'), $alias_name, $is_alias_referenced, $referenced_by); |
|
60 |
// NAT 1:1 Rules |
|
61 |
find_alias_reference(array('nat', 'onetoone'), array('destination', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
62 |
// NAT Outbound Rules |
|
63 |
find_alias_reference(array('nat', 'outbound', 'rule'), array('source', 'network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
64 |
find_alias_reference(array('nat', 'outbound', 'rule'), array('sourceport'), $alias_name, $is_alias_referenced, $referenced_by); |
|
65 |
find_alias_reference(array('nat', 'outbound', 'rule'), array('destination', 'address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
66 |
find_alias_reference(array('nat', 'outbound', 'rule'), array('dstport'), $alias_name, $is_alias_referenced, $referenced_by); |
|
67 |
find_alias_reference(array('nat', 'outbound', 'rule'), array('target'), $alias_name, $is_alias_referenced, $referenced_by); |
|
68 |
// Alias in an alias |
|
69 |
find_alias_reference(array('aliases', 'alias'), array('address'), $alias_name, $is_alias_referenced, $referenced_by); |
|
70 |
// Static routes |
|
71 |
find_alias_reference(array('staticroutes', 'route'), array('network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
72 |
// OpenVPN |
|
73 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
74 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
75 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('local_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
76 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('local_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
77 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
78 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
79 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
80 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
81 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
82 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
83 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
84 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
85 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('local_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
86 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('local_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
87 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
88 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
46 |
$section_fields = [ |
|
47 |
// Firewall rules |
|
48 |
'filter/rule' => [ |
|
49 |
'source/address', |
|
50 |
'destination/address', |
|
51 |
'destination/port' |
|
52 |
], |
|
53 |
// NAT Rules |
|
54 |
'nat/rule' => [ |
|
55 |
'source/address', |
|
56 |
'source/port', |
|
57 |
'destination/address', |
|
58 |
'destination/port', |
|
59 |
'target', |
|
60 |
'local-port' |
|
61 |
], |
|
62 |
// NAT 1:1 Rules |
|
63 |
'nat/onetoone' => [ |
|
64 |
'destination/address' |
|
65 |
], |
|
66 |
// NAT Outbound Rules |
|
67 |
'nat/outbound/rule' => [ |
|
68 |
'source/network', |
|
69 |
'sourceport', |
|
70 |
'destination/address', |
|
71 |
'dstport', |
|
72 |
'target' |
|
73 |
], |
|
74 |
// Alias in an alias |
|
75 |
'aliases/alias' => [ |
|
76 |
'address' |
|
77 |
], |
|
78 |
// Static routes |
|
79 |
'staticroutes/route' => [ |
|
80 |
'network' |
|
81 |
], |
|
82 |
// OpenVPN |
|
83 |
'openvpn/openvpn-server' => [ |
|
84 |
'tunnel_network', |
|
85 |
'tunnel_networkv6', |
|
86 |
'local_network', |
|
87 |
'local_networkv6', |
|
88 |
'remote_network', |
|
89 |
'remote_networkv6', |
|
90 |
'tunnel_network', |
|
91 |
'tunnel_networkv6', |
|
92 |
'remote_network', |
|
93 |
'remote_networkv6' |
|
94 |
], |
|
95 |
'openvpn/openvpn-csc' => [ |
|
96 |
'tunnel_network', |
|
97 |
'tunnel_networkv6', |
|
98 |
'local_network', |
|
99 |
'local_networkv6', |
|
100 |
'remote_network', |
|
101 |
'remote_networkv6' |
|
102 |
], |
|
103 |
]; |
|
104 |
|
|
105 |
foreach ($section_fields as $section => $fields) { |
|
106 |
foreach ($fields as $field) { |
|
107 |
find_alias_reference_by_path($section, $field, $alias_name, $is_alias_referenced, $referenced_by); |
|
108 |
} |
|
109 |
} |
|
110 |
|
|
89 | 111 |
if ($is_alias_referenced == true) { |
90 | 112 |
$delete_error = sprintf(gettext("Cannot delete alias. Currently in use by %s."), htmlspecialchars(implode(", ", $referenced_by))); |
91 | 113 |
} else { |
... | ... | |
94 | 116 |
unlink_if_exists("/var/db/aliastables/" . $a_aliases[$id]['name'] . ".txt"); |
95 | 117 |
} |
96 | 118 |
unset($a_aliases[$id]); |
119 |
config_set_path('aliases/alias', $a_aliases); |
|
97 | 120 |
if (write_config(gettext("Deleted firewall alias " . $a_aliases[$id]['name']))) { |
98 | 121 |
if (!$apply) { |
99 | 122 |
mark_subsystem_dirty('aliases'); |
... | ... | |
121 | 144 |
return false; |
122 | 145 |
} |
123 | 146 |
|
124 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
125 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
126 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('local_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
127 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('local_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
128 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
129 |
find_alias_reference(array('openvpn', 'openvpn-server'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
130 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
131 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
132 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
133 |
find_alias_reference(array('openvpn', 'openvpn-client'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
134 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('tunnel_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
135 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('tunnel_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
136 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('local_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
137 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('local_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
138 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('remote_network'), $alias_name, $is_alias_referenced, $referenced_by); |
|
139 |
find_alias_reference(array('openvpn', 'openvpn-csc'), array('remote_networkv6'), $alias_name, $is_alias_referenced, $referenced_by); |
|
147 |
$section_fields = [ |
|
148 |
'openvpn/openvpn-server' => [ |
|
149 |
'tunnel_network', |
|
150 |
'tunnel_networkv6', |
|
151 |
'local_network', |
|
152 |
'local_networkv6', |
|
153 |
'remote_network', |
|
154 |
'remote_networkv6' |
|
155 |
], |
|
156 |
'openvpn/openvpn-client' => [ |
|
157 |
'tunnel_network', |
|
158 |
'tunnel_networkv6', |
|
159 |
'remote_network', |
|
160 |
'remote_networkv6' |
|
161 |
], |
|
162 |
'openvpn/openvpn-csc' => [ |
|
163 |
'tunnel_network', |
|
164 |
'tunnel_networkv6', |
|
165 |
'local_network', |
|
166 |
'local_networkv6', |
|
167 |
'remote_network', |
|
168 |
'remote_networkv6' |
|
169 |
] |
|
170 |
]; |
|
171 |
|
|
172 |
foreach ($section_fields as $section => $fields) { |
|
173 |
foreach ($fields as $field) { |
|
174 |
find_alias_reference_by_path($section, $field, $alias_name, $is_alias_referenced, $referenced_by); |
|
175 |
} |
|
176 |
} |
|
177 |
|
|
140 | 178 |
if ($is_alias_referenced == true) { |
141 | 179 |
$alarm_message = sprintf(gettext("Alias is in use by OpenVPN. Pressing save will restart instances: %s."), htmlspecialchars(implode(", ", $referenced_by))); |
142 | 180 |
} |
... | ... | |
144 | 182 |
return $alarm_message; |
145 | 183 |
} |
146 | 184 |
|
147 |
function find_alias_reference($section, $field, $origname, &$is_alias_referenced, &$referenced_by) { |
|
148 |
global $config; |
|
185 |
/** |
|
186 |
* Find references to an alias by path. |
|
187 |
* |
|
188 |
* @param string $section Section part of path, slash delimited. The section must identify an indexed array of items |
|
189 |
* @param string $field Field part of path, slash delimited. The part is appended to each element in the section to search for an alias. |
|
190 |
* @param string $origname Alias name. |
|
191 |
* @param bool $is_alias_referenced Set to true if a match is found. |
|
192 |
* @param string[] $referenced_by Array recording descriptions of paths referencing the alias. |
|
193 |
*/ |
|
194 |
function find_alias_reference_by_path($section, $field, $origname, &$is_alias_referenced, &$referenced_by) { |
|
149 | 195 |
if (!$origname) { |
150 | 196 |
return; |
151 | 197 |
} |
152 | 198 |
|
153 |
$sectionref = &$config; |
|
154 |
foreach ($section as $sectionname) { |
|
155 |
if (is_array($sectionref) && isset($sectionref[$sectionname])) { |
|
156 |
$sectionref = &$sectionref[$sectionname]; |
|
157 |
} else { |
|
158 |
return; |
|
159 |
} |
|
160 |
} |
|
161 |
|
|
162 |
if (is_array($sectionref)) { |
|
163 |
foreach ($sectionref as $itemkey => $item) { |
|
164 |
$fieldfound = true; |
|
165 |
$fieldref = &$sectionref[$itemkey]; |
|
166 |
foreach ($field as $fieldname) { |
|
167 |
if (is_array($fieldref) && isset($fieldref[$fieldname])) { |
|
168 |
$fieldref = &$fieldref[$fieldname]; |
|
169 |
} else { |
|
170 |
$fieldfound = false; |
|
171 |
break; |
|
172 |
} |
|
199 |
$items = config_get_path($section, []); |
|
200 |
|
|
201 |
foreach ($items as $id => $item) { |
|
202 |
if (array_get_path($item, $field) == $origname) { |
|
203 |
$is_alias_referenced = true; |
|
204 |
/* This is a bad hack to make rule descriptions more verbose, |
|
205 |
* ideally the object should be providing its own text presentation, |
|
206 |
* but our values are arrays at this time |
|
207 |
*/ |
|
208 |
if (basename($section) == 'rule') { |
|
209 |
$descr = str_replace('/', ' ', $section) . ' '; |
|
210 |
} else { |
|
211 |
$descr = basename($section) . ' '; |
|
173 | 212 |
} |
174 |
/* explode() alias address string, see https://redmine.pfsense.org/issues/11372 */ |
|
175 |
if ($fieldfound && (in_array($origname, explode(' ', $fieldref)) || |
|
176 |
in_array($origname, explode(',', $fieldref)))) { |
|
177 |
$is_alias_referenced = true; |
|
178 |
if (is_array($item)) { |
|
179 |
if (!empty($item['descr'])) { |
|
180 |
$referenced_by[] = $item['descr']; |
|
181 |
} elseif (!empty($item['description'])) { |
|
182 |
$referenced_by[] = $item['description']; |
|
183 |
} |
|
184 |
} |
|
213 |
if (!empty($item['descr'])) { |
|
214 |
$descr .= "'{$item['descr']}'"; |
|
215 |
} elseif (!empty($item['description'])) { |
|
216 |
$descr .= "'{$item['description']}'"; |
|
217 |
} elseif (!empty($item['name'])) { |
|
218 |
$descr .= "'{$item['name']}'"; |
|
219 |
} else { |
|
220 |
$descr .= "id {$id}"; |
|
185 | 221 |
} |
222 |
|
|
223 |
$referenced_by[] = $descr; |
|
186 | 224 |
} |
187 | 225 |
} |
188 | 226 |
} |
189 | 227 |
|
228 |
|
|
229 |
function find_alias_reference($section, $field, $origname, &$is_alias_referenced, &$referenced_by) { |
|
230 |
$section_path = join('/', $section); |
|
231 |
$field_path = join('/', $field); |
|
232 |
|
|
233 |
return (find_alias_reference_by_path($section_path, $field_path, $origname, $is_alias_referenced, $referenced_by)); |
|
234 |
} |
|
235 |
|
|
190 | 236 |
function staticrouteAlias($id) { |
191 | 237 |
global $config; |
192 | 238 |
|
... | ... | |
202 | 248 |
return false; |
203 | 249 |
} |
204 | 250 |
|
205 |
find_alias_reference(array('staticroutes', 'route'), array('network'), $alias_name, $is_alias_referenced, $referenced_by);
|
|
251 |
find_alias_reference_by_path('staticroutes/route', 'network', $alias_name, $is_alias_referenced, $referenced_by);
|
|
206 | 252 |
|
207 | 253 |
if ($is_alias_referenced) { |
208 | 254 |
$alarm_message = sprintf(gettext("Alias is used in static routes. Pressing save will reload static routes: %s."), htmlspecialchars(implode(", ", $referenced_by))); |
Also available in: Unified diff
Make a better effort to describe an alias reference. Fixes #13539
Each of deleteAlias(), openvpnAlias(), and staticrouteAlias() are called when
deleting or modifying an alias to indicate that it is referenced by some other
configuration item, which in turn call find_alias_reference() which returns
descriptions of configuration references that can be displayed in warnings and
errors.
find_alias_reference() is refactored into find_alias_reference_by_path() which
accepts configlib paths instead of arrays, and makes a stronger attempt at
picking a descriptive text for the item, enclosed in single quotes, cascading
through descr, description, name. If none of these attributes exist, an ID
description is chosen as a last resort.
For compatibility, find_alias_reference() is retained as a wrapper around
find_alias_reference_by_path().
Each of deleteAlias(), openvpnAlias(), and staticrouteAlias() are refactored to
adapt to the path interface and for better readability, calling
find_alias_reference_by_path() in a loop over an associative array of section
paths indexing arrays of field paths (where more than onesection/field pair is
used).