Skip to content

Commit 4ea75b0

Browse files
Merge pull request #55 from jaredhendrickson13/firewall_gw
Firewall rule enhancements
2 parents 1ba1e80 + d8b4341 commit 4ea75b0

5 files changed

Lines changed: 170 additions & 44 deletions

File tree

pfSense-pkg-API/files/etc/inc/api/framework/APIResponse.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,12 @@ function get($id, $data=[], $all=false) {
15441544
"return" => $id,
15451545
"message" => "Firewall alias cannot be deleted while in use"
15461546
],
1547+
4109 => [
1548+
"status" => "bad request",
1549+
"code" => 400,
1550+
"return" => $id,
1551+
"message" => "Firewall rule gateway must match IP protocol"
1552+
],
15471553

15481554
//5000-5999 reserved for /users API calls
15491555
5000 => [

pfSense-pkg-API/files/etc/inc/api/framework/APITools.inc

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -521,22 +521,28 @@ function sort_firewall_rules($mode=null, $data=null) {
521521
$config["filter"]["rule"] = $master_arr;
522522
}
523523

524-
// Checks if inputted routing gateway exists
525-
function is_gateway($gw) {
526-
// Local variables
527-
$gw_config = return_gateways_array(true, true);
528-
$gw_exists = false;
529-
// Check that we have gateways configured
524+
# Checks if routing gateway exists
525+
function is_gateway($gw, $ret_protocol=false) {
526+
# Local variables
527+
$gw_config = return_gateways_array();
528+
$gw_group_config = return_gateway_groups_array();
529+
530+
# Loop through each gateway/gateway group and check if our gw matches the name
530531
if (is_array($gw_config)) {
531-
// Loop through each gateway and see if name matches
532+
# Loop through each gateway and see if name matches
532533
foreach ($gw_config as $gw_name => $gw_item) {
533534
if ($gw === $gw_name) {
534-
$gw_exists = true;
535-
break;
535+
return ($ret_protocol) ? $gw_item["ipprotocol"] : true;
536+
}
537+
}
538+
# Loop through each gateway and see if name matches
539+
foreach ($gw_group_config as $gwg_name => $gwg_item) {
540+
if ($gw === $gwg_name) {
541+
return ($ret_protocol) ? $gwg_item["ipprotocol"] : true;
536542
}
537543
}
538544
}
539-
return $gw_exists;
545+
return false;
540546
}
541547

542548
// Duplicate function from /firewall_aliases.php: accept input and check if alias exists

pfSense-pkg-API/files/etc/inc/api/models/APIFirewallRuleCreate.inc

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ class APIFirewallRuleCreate extends APIModel {
3333
return APIResponse\get(0, $this->validated_data);
3434
}
3535

36-
public function validate_payload() {
37-
# Include static rule ID
38-
$this->validated_data["id"] = "";
39-
36+
private function __validate_type() {
4037
# Check for our required 'type' payload value
4138
if (isset($this->initial_data["type"])) {
4239
$type_options = array("pass", "block", "reject");
@@ -49,7 +46,9 @@ class APIFirewallRuleCreate extends APIModel {
4946
} else {
5047
$this->errors[] = APIResponse\get(4033);
5148
}
49+
}
5250

51+
private function __validate_interface() {
5352
# Check for our required 'interface' payload value
5453
if (isset($this->initial_data['interface'])) {
5554
$this->initial_data['interface'] = APITools\get_pfsense_if_id($this->initial_data['interface']);
@@ -62,7 +61,9 @@ class APIFirewallRuleCreate extends APIModel {
6261
} else {
6362
$this->errors[] = APIResponse\get(4034);
6463
}
64+
}
6565

66+
private function __validate_ipprotocol() {
6667
# Check for our required 'ipprotocol' payload value
6768
if (isset($this->initial_data['ipprotocol'])) {
6869
$ipprotocol_options = array("inet", "inet6", "inet46");
@@ -75,7 +76,9 @@ class APIFirewallRuleCreate extends APIModel {
7576
} else {
7677
$this->errors[] = APIResponse\get(4035);
7778
}
79+
}
7880

81+
private function __validate_protocol() {
7982
# Check for our required 'protocol' payload value
8083
if (isset($this->initial_data['protocol'])) {
8184
$protocol_options = [
@@ -91,11 +94,12 @@ class APIFirewallRuleCreate extends APIModel {
9194
} else {
9295
$this->errors[] = APIResponse\get(4042);
9396
}
94-
$protocol = $this->initial_data['protocol'];
9597
} else {
9698
$this->errors[] = APIResponse\get(4036);
9799
}
100+
}
98101

102+
private function __validate_icmptype() {
99103
# Check for our optional 'icmpsubtype' payload value when our protocol is set to ICMP
100104
if (isset($this->initial_data["icmptype"]) and $this->validated_data["protocol"] === "icmp") {
101105
$icmptype_options = [
@@ -118,7 +122,9 @@ class APIFirewallRuleCreate extends APIModel {
118122
$this->validated_data["icmptype"] = implode(",", $this->initial_data["icmptype"]);
119123
}
120124
}
125+
}
121126

127+
private function __validate_src() {
122128
# Check for our required 'src' payload value
123129
if (isset($this->initial_data['src'])) {
124130
// Check if our source and destination values are valid
@@ -131,7 +137,9 @@ class APIFirewallRuleCreate extends APIModel {
131137
} else {
132138
$this->errors[] = APIResponse\get(4037);
133139
}
140+
}
134141

142+
private function __validate_dst() {
135143
# Check for our required 'src' payload value
136144
if (isset($this->initial_data['dst'])) {
137145
// Check if our source and destination values are valid
@@ -144,8 +152,10 @@ class APIFirewallRuleCreate extends APIModel {
144152
} else {
145153
$this->errors[] = APIResponse\get(4038);
146154
}
155+
}
147156

148-
# Check for our required 'srcport' and 'dstport' payload values if protocol is TCP, UDP or TCP/UDP
157+
private function __validate_srcport() {
158+
# Check for our required 'srcport' payload values if protocol is TCP, UDP or TCP/UDP
149159
if (in_array($this->validated_data["protocol"], ["tcp", "udp", "tcp/udp"])) {
150160
if (isset($this->initial_data['srcport'])) {
151161
$val = str_replace("-", ":", $this->initial_data['srcport']);
@@ -157,7 +167,12 @@ class APIFirewallRuleCreate extends APIModel {
157167
} else {
158168
$this->errors[] = APIResponse\get(4047);
159169
}
170+
}
171+
}
160172

173+
private function __validate_dstport() {
174+
# Check for our required 'dstport' payload values if protocol is TCP, UDP or TCP/UDP
175+
if (in_array($this->validated_data["protocol"], ["tcp", "udp", "tcp/udp"])) {
161176
if (isset($this->initial_data['dstport'])) {
162177
$val = str_replace("-", ":", $this->initial_data['dstport']);
163178
if (!is_port_or_range_or_alias($val) and $val !== "any") {
@@ -169,37 +184,70 @@ class APIFirewallRuleCreate extends APIModel {
169184
$this->errors[] = APIResponse\get(4047);
170185
}
171186
}
187+
}
172188

189+
private function __validate_gateway() {
173190
# Check for our optional 'gateway' payload value
174191
if (isset($this->initial_data['gateway'])) {
175-
# Check that the specified gateway exists
176-
if (APITools\is_gateway($this->initial_data["gateway"])) {
177-
$this->validated_data["gateway"] = $this->initial_data["gateway"];
178-
} else {
192+
$gw_protocol = APITools\is_gateway($this->initial_data["gateway"], true);
193+
# Check if we were able to locate the gateway
194+
if ($gw_protocol === false) {
179195
$this->errors[] = APIResponse\get(4043);
180196
}
197+
# Check if the gateway IP protocol matches our rule's IP protocol
198+
elseif ($gw_protocol !== $this->validated_data["ipprotocol"]) {
199+
$this->errors[] = APIResponse\get(4109);
200+
}
201+
# Otherwise, the gateway is valid
202+
else {
203+
$this->validated_data["gateway"] = $this->initial_data["gateway"];
204+
}
181205
}
206+
}
182207

183-
208+
private function __validate_disabled() {
184209
# Check for our optional 'disabled' payload value
185210
if ($this->initial_data['disabled'] === true) {
186211
$this->validated_data["disabled"] = "";
187212
}
213+
}
188214

215+
private function __validate_descr() {
189216
# Check for our optional 'descr' payload value
190217
if (isset($this->initial_data['descr'])) {
191218
$this->validated_data["descr"] = strval($this->initial_data['descr']);
192219
}
220+
}
193221

222+
private function __validate_log() {
194223
# Check for our optional 'log' payload value
195224
if ($this->initial_data['log'] === true) {
196225
$this->validated_data["log"] = "";
197226
}
227+
}
198228

229+
private function __validate_top() {
199230
# Check for our optional 'top' payload value
200231
if ($this->initial_data['top'] === true) {
201232
$this->initial_data['top'] = "top";
202233
}
234+
}
235+
236+
public function validate_payload() {
237+
$this->__validate_type();
238+
$this->__validate_interface();
239+
$this->__validate_ipprotocol();
240+
$this->__validate_protocol();
241+
$this->__validate_icmptype();
242+
$this->__validate_src();
243+
$this->__validate_dst();
244+
$this->__validate_srcport();
245+
$this->__validate_dstport();
246+
$this->__validate_gateway();
247+
$this->__validate_disabled();
248+
$this->__validate_descr();
249+
$this->__validate_log();
250+
$this->__validate_top();
203251

204252
# Add our static 'tracker', 'created' and 'updated' values
205253
$this->validated_data["tracker"] = (int)microtime(true);

0 commit comments

Comments
 (0)