From 046fb118f7cc400eab5c0a93db6e674ca2dc8bb8 Mon Sep 17 00:00:00 2001 From: lilinzhe Date: Sat, 18 Jan 2020 08:05:20 +0800 Subject: [PATCH] Alias Management: modify - network_address_aliases_update Signed-off-by: lilinzhe --- README.md | 54 +++++ .../files/etc/inc/fauxapi/fauxapi_actions.inc | 32 ++- .../fauxapi_pfsense_interface_alias.inc | 197 +++++------------- .../fauxapi_pfsense_interface_alias.priv.inc | 148 +++++++++++++ 4 files changed, 289 insertions(+), 142 deletions(-) create mode 100644 pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.priv.inc diff --git a/README.md b/README.md index d53c634..72b4fe9 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ tasks feasible. - [system_stats](#user-content-system_stats) - Returns various useful system stats. - [network_address_aliases_get](#user-content-network_address_aliases_get) - Returns address aliaes used by rules. - [network_address_aliases_create](#user-content-network_address_aliases_create) - Creates An network aliaes for rules + - [network_address_aliases_update](#user-content-network_address_aliases_update) - Update a address aliaes. Returns newest result - [filter_rules_get](#user-content-filter_rules_get) - Returns firewall filters. @@ -933,6 +934,59 @@ curl \ "https:///fauxapi/v1/?action=network_address_aliases_create" ``` +*Example Response* +```javascript +{ + "callid": "5e22393a9aa5a", + "action": "network_address_aliases_create", + "message": "ok", + "data": { + "aliases": { + "alias": [ + { + "name": "EasyRuleBlockHostsWAN", + "type": "network", + "address": "1.2.3.4/32 5.6.7.8/32", + "descr": "Hosts blocked from Firewall Log view", + "detail": "Entry added Fri, 27 Dec 2019 00:53:01 -0800||\u5df2\u6dfb\u52a0\u6761\u76ee Thu, 16 Jan 2020 03:42:37 -0800" + }, + { + "name": "wsdfan", + "descr": "Test", + "type": "network", + "address": "12.23.45.3/32", + "detail": "a" + } + ] + } + } +} +``` +--- +### network_address_aliases_update + - Update a address aliaes. Returns newest result + - HTTP: **POST** + - Params: none + - Request body: json + - **name** : name of aliases. identiy which aliases frr modify + - **type** : type of aliases. **MUST** be `network` for now. + - **cidr_addresses** : < list of > name alias what + - **address** an ip address or a network prefix. + - **details** a description of this address. for human readable documentation. + - **descr** : the description of current aliases. + - Response: json : the items after created + +*Example Request* +```bash +curl \ + -X GET \ + --silent \ + --insecure \ + --header "fauxapi-auth: " \ + --data '{"name": "wsdfan", "type": "network", "cidr_addresses": [{"address":"12.23.45.3/32", "details":"a"}], "descr":"Test"}' + "https:///fauxapi/v1/?action=network_address_aliases_create" +``` + *Example Response* ```javascript { diff --git a/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_actions.inc b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_actions.inc index b5c60ac..90102b7 100644 --- a/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_actions.inc +++ b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_actions.inc @@ -450,7 +450,7 @@ class fauxApiActions { return TRUE; } /** - * address_aliases_get() + * network_address_aliases_create() * * @return boolean */ @@ -460,7 +460,7 @@ class fauxApiActions { $name = $this->action_input_data["name"]; $type = $this->action_input_data["type"]; $cidr_addresses =$this->action_input_data['cidr_addresses']; - $descr=$this->action_input_data['descr'] or "Added by fauxapi"; + $descr=$this->action_input_data['descr']; $alias = $this->PfsenseInterface->network_address_aliases_create($name, $type, $cidr_addresses, $descr); @@ -476,6 +476,34 @@ class fauxApiActions { ); return TRUE; } + + /** + * network_address_aliases_update() + * + * @return boolean + */ + public function network_address_aliases_update() { + fauxApiLogger::debug(__METHOD__); + + $name = $this->action_input_data["name"]; + $type = $this->action_input_data["type"]; + $cidr_addresses =$this->action_input_data['cidr_addresses']; + $descr=$this->action_input_data['descr'] ; + + $alias = $this->PfsenseInterface->network_address_aliases_update($name, $type, $cidr_addresses, $descr); + + if (empty($alias)) { + $this->response->http_code = 500; + $this->response->message = 'unable to get address aliases'; + return FALSE; + } + $this->response->http_code = 200; + $this->response->message = 'ok'; + $this->response->data = array( + 'aliases' => $alias, + ); + return TRUE; + } /** * alias_update_urltables() diff --git a/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.inc b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.inc index e0eb4ba..d79c9b8 100644 --- a/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.inc +++ b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.inc @@ -2,108 +2,9 @@ namespace fauxapi\v1; -// write_config requires functions from this -include '/etc/inc/phpsessionmanager.inc'; -include '/etc/inc/auth.inc'; +include 'fauxapi_pfsense_interface_alias.priv.inc'; trait network_address_aliases { - - /* - From PFSENSE. copyed for old version. - If $return_message is true then - returns a text message about the reason that the name is invalid. - the text includes the type of "thing" that is being checked, passed in $object. (e.g. "alias", "gateway group", "schedule") - else - returns true if $name is a valid name for an alias - returns false if $name is not a valid name for an alias - - Aliases cannot be: - bad chars: anything except a-z 0-9 and underscore - bad names: empty string, pure numeric, pure underscore - reserved words: pre-defined service/protocol/port names which should not be ambiguous, and the words "port" and "pass" */ - - private function is_valid_network_address_alias_name($name) - { - global $config; - global $pf_reserved_keywords; - $reserved_table_names = array( - "bogons", - "bogonsv6", - "negate_networks", - "snort2c", - "sshguard", - "tonatsubnets", - "virusprot", - "vpn_networks", - ); - $reserved_ifs = get_configured_interface_list(true); - $pf_reserved_keywords = array_merge($pf_reserved_keywords, $reserved_ifs, $reserved_table_names); - - $object = "alias"; - /* Array of reserved words */ - $reserved = array("port", "pass"); - - if (!is_string($name) || strlen($name) >= 32 || preg_match('/(^_*$|^\d*$|[^a-z0-9_])/i', $name)) { - return sprintf(gettext('The %1$s name must be less than 32 characters long, may not consist of only numbers, may not consist of only underscores, and may only contain the following characters: %2$s'), $object, 'a-z, A-Z, 0-9, _'); - } - if (in_array($name, $reserved, true)) { - return sprintf(gettext('The %1$s name must not be either of the reserved words %2$s or %3$s.'), $object, "'port'", "'pass'"); - } - if (getprotobyname($name)) { - return sprintf(gettext('The %1$s name must not be an IP protocol name such as TCP, UDP, ICMP etc.'), $object); - } - if (getservbyname($name, "tcp") || getservbyname($name, "udp")) { - return sprintf(gettext('The %1$s name must not be a well-known or registered TCP or UDP port name such as ssh, smtp, pop3, tftp, http, openvpn etc.'), $object); - } - - /* Check for reserved keyword names */ - foreach ($pf_reserved_keywords as $rk) { - if (strcasecmp($rk, $name) == 0) { - return sprintf(gettext("Cannot use a reserved keyword as an alias name: %s"), $rk); - } - } - - /* - * Packages (e.g. tinc) create interface groups, reserve this - * namespace pkg_ for them. - * One namespace is shared by Interfaces, Interface Groups and Aliases. - */ - if (substr($name, 0, 4) == 'pkg_') { - return gettext("The alias name cannot start with pkg_"); - } - - /* check for name interface description conflicts */ - foreach ($config['interfaces'] as $interface) { - if (strcasecmp($interface['descr'], $name) == 0) { - return gettext("An interface description with this name already exists."); - } - } - - /* Is the description already used as an interface group name? */ - if (is_array($config['ifgroups']['ifgroupentry'])) { - foreach ($config['ifgroups']['ifgroupentry'] as $ifgroupentry) { - if ($ifgroupentry['ifname'] == $name) { - return gettext("Sorry, an interface group with this name already exists."); - } - } - } - - // SHELL NOT BE A IP address. for prevent infinite loops make sure the alias name does not equal the value - if (is_ipaddr($name)) { - return "name shell not be ip address"; - } - // CHECK NAME - foreach ($config["aliases"]["alias"] as $cfgitem) { - if ($cfgitem["name"] == $name) { - return gettext("An alias with this name already exists."); - } - } - - return NULL; - } - - - /** * network_address_aliases_get() * @@ -138,7 +39,7 @@ trait network_address_aliases fauxApiLogger::error($error_message, $error_data); throw new \Exception($error_message); } - $error_message = $this->is_valid_network_address_alias_name($name); + $error_message = fauxApiInterfaceAliasTools::is_valid_network_address_alias_name($name); if ($error_message !== NULL) { $error_data = array('name' => $name); fauxApiLogger::error($error_message, $error_data); @@ -150,69 +51,85 @@ trait network_address_aliases fauxApiLogger::error($error_message, $error_data); throw new \Exception($error_message); } - $address_cfg = array(); - $details_cfg = array(); - foreach ($cidr_addresses as $addresscfg) { - $address = $addresscfg["address"]; - if (!is_ipaddr($address) && !is_subnet($address)) { - $error_message = "must be a address or subnet"; - $error_data = array('address' => $addresscfg); - fauxApiLogger::error($error_message, $error_data); - throw new \Exception($error_message); - } - $details = $addresscfg["details"]; - $details = preg_replace('/\|\|+/', '|', trim($details, "|")); - array_push($address_cfg, $address); - array_push($details_cfg, $details); - } - $address_cfg = join(" ", $address_cfg); - $details_cfg = join("||", $details_cfg); + $result = fauxApiInterfaceAliasTools::parse_cidr_addresslist_to_config($cidr_addresses); # this shell saves to config. $pconfig['name'] = $name; $pconfig['descr'] = $descr; $pconfig['type'] = $type; - $pconfig['address'] = $address_cfg; - $pconfig['detail'] = $details_cfg; + $pconfig['address'] = $result["address"]; + $pconfig['detail'] = $result["detail"]; init_config_arr(array('aliases', 'alias')); $currsize = count($config['aliases']['alias']); $config["aliases"]['alias'][$currsize] = $pconfig; - $session_item = $_SESSION['Username']; - $_SESSION['Username'] = "admin"; // workaround to make writeconfig work - if (write_config(gettext("Edited a firewall alias."))) { - mark_subsystem_dirty('aliases'); - $_SESSION['Username'] = $session_item; - } else { - $_SESSION['Username'] = $session_item; - $error_message = "must be a address or subnet"; - $error_data = array('address' => $addresscfg); - fauxApiLogger::error($error_message, $error_data); - throw new \Exception($error_message); + if (!fauxApiInterfaceAliasTools::write_config_aliases()) { + return NULL; } - return $config["aliases"]; } /** - * network_address_aliases_get() + * network_address_aliases_update() * + * @param string $name - which alias to modify + * @param string $type - alias type, supports "network" only + * @param array $cidr_addresses - alias CIDRAddress {"address": "1.2.3.4/32", "details":"message"} + * @param string $descr - alias descr, use for UI item. * @return array */ - public function network_address_aliases_update() + public function network_address_aliases_update($name, $type, $cidr_addresses, $descr = "Added by fauxapi") { global $config; - fauxApiLogger::debug(__METHOD__); + fauxApiLogger::debug(__METHOD__, array( + 'name' => $name, 'type' => $type, 'cidr_addresses' => $cidr_addresses, 'descr' => $descr + )); + $pconfig=NULL; + for ($id = 0; $id < count($config["aliases"]["alias"]); $id+=1) { + $cfgitem = $config["aliases"]["alias"][$id]; + if ($cfgitem["name"] == $name){ + $pconfig=&$config["aliases"]["alias"][$id]; + } + } + if ($pconfig== NULL){ + //not find + $error_message = "not find name"; + $error_data = array('name' => $name); + fauxApiLogger::error($error_message, $error_data); + throw new \Exception($error_message); + } + if ($type != "network") { + $error_message = "can support type network only for now"; + $error_data = array('type' => $type); + fauxApiLogger::error($error_message, $error_data); + throw new \Exception($error_message); + } + $result = fauxApiInterfaceAliasTools::parse_cidr_addresslist_to_config($cidr_addresses); + # this shell saves to config. + $pconfig['name'] = $name; + $pconfig['descr'] = $descr; + $pconfig['type'] = $type; + $pconfig['address'] = $result["address"]; + $pconfig['detail'] = $result["detail"]; + if (!fauxApiInterfaceAliasTools::write_config_aliases()) { + return NULL; + } + return $config["aliases"]; } - /** - * network_address_aliases_get() + * network_address_aliases_delete() * + * @param string $name - which alias to modify * @return array */ - public function network_address_aliases_delete() + public function network_address_aliases_delete($name) { global $config; - fauxApiLogger::debug(__METHOD__); - return $config["aliases"]; + fauxApiLogger::debug(__METHOD__, array( + 'name' => $name + )); + $pconfig=NULL; + for ($id = 0; $id < count($config["aliases"]["alias"]); $id+=1) { + } + } } diff --git a/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.priv.inc b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.priv.inc new file mode 100644 index 0000000..3769d2d --- /dev/null +++ b/pfSense-pkg-FauxAPI/files/etc/inc/fauxapi/fauxapi_pfsense_interface_alias.priv.inc @@ -0,0 +1,148 @@ += 32 || preg_match('/(^_*$|^\d*$|[^a-z0-9_])/i', $name)) { + return sprintf(gettext('The %1$s name must be less than 32 characters long, may not consist of only numbers, may not consist of only underscores, and may only contain the following characters: %2$s'), $object, 'a-z, A-Z, 0-9, _'); + } + if (in_array($name, $reserved, true)) { + return sprintf(gettext('The %1$s name must not be either of the reserved words %2$s or %3$s.'), $object, "'port'", "'pass'"); + } + if (getprotobyname($name)) { + return sprintf(gettext('The %1$s name must not be an IP protocol name such as TCP, UDP, ICMP etc.'), $object); + } + if (getservbyname($name, "tcp") || getservbyname($name, "udp")) { + return sprintf(gettext('The %1$s name must not be a well-known or registered TCP or UDP port name such as ssh, smtp, pop3, tftp, http, openvpn etc.'), $object); + } + + /* Check for reserved keyword names */ + foreach ($pf_reserved_keywords as $rk) { + if (strcasecmp($rk, $name) == 0) { + return sprintf(gettext("Cannot use a reserved keyword as an alias name: %s"), $rk); + } + } + + /* + * Packages (e.g. tinc) create interface groups, reserve this + * namespace pkg_ for them. + * One namespace is shared by Interfaces, Interface Groups and Aliases. + */ + if (substr($name, 0, 4) == 'pkg_') { + return gettext("The alias name cannot start with pkg_"); + } + + /* check for name interface description conflicts */ + foreach ($config['interfaces'] as $interface) { + if (strcasecmp($interface['descr'], $name) == 0) { + return gettext("An interface description with this name already exists."); + } + } + + /* Is the description already used as an interface group name? */ + if (is_array($config['ifgroups']['ifgroupentry'])) { + foreach ($config['ifgroups']['ifgroupentry'] as $ifgroupentry) { + if ($ifgroupentry['ifname'] == $name) { + return gettext("Sorry, an interface group with this name already exists."); + } + } + } + + // SHELL NOT BE A IP address. for prevent infinite loops make sure the alias name does not equal the value + if (is_ipaddr($name)) { + return "name shell not be ip address"; + } + // CHECK NAME + foreach ($config["aliases"]["alias"] as $cfgitem) { + if ($cfgitem["name"] == $name) { + return gettext("An alias with this name already exists."); + } + } + + return NULL; + } + + public static function parse_cidr_addresslist_to_config($cidr_addresses) { + $address_cfg = array(); + $details_cfg = array(); + foreach ($cidr_addresses as $addresscfg) { + $address = $addresscfg["address"]; + if (!is_ipaddr($address) && !is_subnet($address)) { + $error_message = "must be a address or subnet"; + $error_data = array('address' => $addresscfg); + fauxApiLogger::error($error_message, $error_data); + throw new \Exception($error_message); + } + $details = $addresscfg["details"]; + $details = preg_replace('/\|\|+/', '|', trim($details, "|")); + array_push($address_cfg, $address); + array_push($details_cfg, $details); + } + $address_cfg = join(" ", $address_cfg); + $details_cfg = join("||", $details_cfg); + return array( + "address"=>$address_cfg, + "detail"=>$details, + ); + } + public static function write_config_aliases() { + global $config; + $session_item = $_SESSION['Username']; + $_SESSION['Username'] = "admin"; // workaround to make writeconfig work + if (write_config(gettext("Edited a firewall alias."))) { + mark_subsystem_dirty('aliases'); + $_SESSION['Username'] = $session_item; + return true; + } else{ + $_SESSION['Username'] = $session_item; + $error_message = "write config failed"; + $error_data = array('newcfg' => $config["aliases"]['alias']); + fauxApiLogger::error($error_message, $error_data); + throw new \Exception($error_message); + } + } + + +} + +?> \ No newline at end of file