{"action":"created","comment":{"url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/comments/102471502","pull_request_review_id":23217556,"id":102471502,"diff_hunk":"@@ -4409,4 +4415,834 @@ EOD;\n \tconf_mount_ro();\n }\n \n+/*\n+ * FreeRADIUS input validation\n+ */\n+\n+/* Users input validation */\n+function freeradius_validate_users($post, &$input_errors) {\n+\n+\t// Username\n+\tif ($post['varusersmotpenable'] == 'on' && !preg_match('/^[a-zA-Z0-9_.-]*$/', $post['varusersusername'])) {\n+\t\t$input_errors[] = \"The 'Username' field may only contain a-z, A-Z, 0-9, underscore, period and hyphen (regex /^[a-zA-Z0-9_.-]*$/) when 'Enable One-Time-Password for this user' is checked.\";\n+\t}\n+\n+\t// Password\n+\tif ($post['varusersmotpenable'] == 'on' && $post['varuserspassword'] != '') {\n+\t\t$input_errors[] = \"The 'Password' field must be left empty when 'Enable One-Time-Password for this user' is checked.\";\n+\t}\n+\n+\t// Init-Secret\n+\tif ($post['varusersmotpenable'] == 'on') {\n+\t\tif ($post['varusersmotpinitsecret'] == '') {\n+\t\t\t$input_errors[] = \"The 'Init-Secret' field may not be empty when 'Enable One-Time-Password for this user' is checked.\";\n+\t\t} elseif (!preg_match('/^[0-9a-f]{16,}$/', $post['varusersmotpinitsecret'])) {\n+\t\t\t$input_errors[] = \"The 'Init-Secret' field may only contain 0-9 and a-f (regex /^[0-9a-f]*$/) and must contain at least 16 characters.\";\n+\t\t}\n+\t}\n+\n+\t// PIN\n+\tif ($post['varusersmotpenable'] == 'on') {\n+\t\tif ($post['varusersmotppin'] == '') {\n+\t\t\t$input_errors[] = \"The 'PIN' field may not be empty when 'Enable One-Time-Password for this user' is checked.\";\n+\t\t} elseif (!preg_match('/^[0-9]{4,8}$/', $post['varusersmotppin'])) {\n+\t\t\t$input_errors[] = \"The 'PIN' field may only contain a PIN consisting of 4-8 digits.\";\n+\t\t}\n+\t}\n+\n+\t// Time Offset\n+\tif ($post['varusersmotpoffset']) {\n+\t\tif (!preg_match('/^-?[0-9]{2,4}$/', $post['varusersmotpoffset'])) {\n+\t\t\t$input_errors[] = \"The 'Time Offset' field may only contain a valid TZ offset in minutes, with optional leading minus character.\";\n+\t\t} else {\n+\t\t\t// Only accept sane values divisible by 15\n+\t\t\t$offset = str_replace('-', '', $post['varusersmotpoffset']);\n+\t\t\tif ((is_numericint($offset)) && ($offset %15 != 0)) {\n+\t\t\t\t$input_errors[] = \"The 'Time Offset' value '{$offset}' is not a valid TZ offset.\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// Redirection URL\n+\tif (!empty($post['varuserswisprredirectionurl'])) {\n+\t\tif (!filter_var($post['varuserswisprredirectionurl'], FILTER_VALIDATE_URL)) {\n+\t\t\t$input_errors[] = \"The 'Redirection URL' field must contain a valid URL.\";\n+\t\t}\n+\t}\n+\n+\t// Number of Simultaneous Connections\n+\tif ($post['varuserssimultaneousconnect'] != '' && !is_numericint($post['varuserssimultaneousconnect'])) {\n+\t\t$input_errors[] = \"The 'Number of Simultaneous Connections' field must contain an integer value.\";\n+\t}\n+\n+\t// Description\n+\tif ($post['description'] && !preg_match(\"/^[a-zA-Z0-9 _,.;:+=()-]*$/\", $post['description'])) {\n+\t\t$input_errors[] = \"Do not use special characters in the 'Description' field; only /^[a-zA-Z0-9 _,.;:+=()-]*$/ allowed.\";\n+\t}\n+\n+\t// IP Address; may contain a single trailing '+' for simultaneous connections\n+\tif ($post['varusersframedipaddress']) {\n+\t\t$framedip = str_replace('+', '', $post['varusersframedipaddress'], $pluscnt);\n+\t\tif (!is_ipaddrv4($framedip)) {\n+\t\t\t$input_errors[] = \"The 'IP Address' field must contain a valid IPv4 address.\";\n+\t\t}\n+\t\tif ($pluscnt > 1) {\n+\t\t\t$input_errors[] = \"The 'IP Address' field may optionally contain only a single trailing '+'.\";\n+\t\t}\n+\t}\n+\n+\t// Subnet Mask\n+\tif ($post['varusersframedipnetmask']) {\n+\t\tif ($post['varusersframedipaddress'] == '') {\n+\t\t\t$input_errors[] = \"To specify a 'Subnet Mask', the 'IP Address' field must not be empty.\";\n+\t\t} elseif (is_ipaddrv4($framedip)) {\n+\t\t\t$ip = long2ip(ip2long($framedip) & ip2long($post['varusersframedipnetmask']));\n+\t\t\t$mask = 32 - log((ip2long($post['varusersframedipnetmask']) ^ ip2long('255.255.255.255')) +1, 2);\n+\t\t\tif (!is_subnetv4(\"{$ip}/{$mask}\")) {\n+\t\t\t\t$input_errors[] = \"The 'Subnet Mask' field must contain a valid subnet mask.\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// Gateway\n+\tif ($post['varusersframedroute'] != '') {\n+\t\t$framedroute = explode(\" \", $post['varusersframedroute']);\n+\t\t$cnt = count($framedroute);\n+\t\t// One or more metrics are allowed per RFC2865 (5.22)\n+\t\tif ($cnt < 3) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field must match the required format: Subnet Gateway Metric(s) (e.g. 192.168.10.0/24 192.168.10.1 1).\";\n+\t\t}\n+\t\t// The subnet CIDR is optional per RFC2865 (5.22)\n+\t\tif (!is_ipaddrv4($framedroute[0]) && !is_subnetv4($framedroute[0])) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field's subnet part '{$framedroute[0]}' must be a valid IPv4 subnet.\";\n+\t\t}\n+\t\tif (!is_ipaddrv4($framedroute[1])) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field's gateway part '{$framedroute[1]}' must be a valid IPv4 gateway address.\";\n+\t\t}\n+\t\t// One or more metrics are allowed per RFC2865 (5.22)\n+\t\tfor ($i = 2; $i < $cnt; $i++) {\n+\t\t\tif (!is_numericint($framedroute[$i])) {\n+\t\t\t\t$input_errors[] = \"The 'Gateway' field's metric part '{$framedroute[$i]}' must contain an integer value.\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// VLAN ID\n+\tif ($post['varusersvlanid'] != '') {\n+\t\tif (!is_numericint($post['varusersvlanid'])) {\n+\t\t\t$input_errors[] = \"The 'VLAN ID' field must contain an integer value.\";\n+\t\t} elseif ($post['varusersvlanid'] < 1 || $post['varusersvlanid'] > 4095) {\n+\t\t\t$input_errors[] = \"The 'VLAN ID' must be in the 1-4095 range.\";\n+\t\t}\n+\t}\n+\n+\t// Expiration Date\n+\tif ($post['varusersexpiration'] != '') {\n+\t\t$expires = date_parse_from_format(\"M d Y\", $post['varusersexpiration']);\n+\t\tif ($expires['error_count'] > 0 || $expires['warning_count'] > 0) {\n+\t\t\t$input_errors[] = \"The 'Expiration Date' format is invalid. | Error(s): \" .\n+\t\t\t    implode('. ', $expires['errors']) . \" | Warning(s): \" .\n+\t\t\t    implode('. ', $expires['warnings']);\n+\t\t}\n+\t\t// Hack around date_parse_from_format() bugs, such as expanding \"Jan 199\" to \"Jan 1 99\"\n+\t\tif ($expires['year'] < 1970) {\n+\t\t\t$input_errors[] = \"The 'Expiration Date' contains an invalid year.\";\n+\t\t}\n+\t}\n+\n+\t// Session Timeout\n+\tif ($post['varuserssessiontimeout'] != '' && !is_numericint($post['varuserssessiontimeout'])) {\n+\t\t$input_errors[] = \"The 'Session Timeout' field must contain an integer value.\";\n+\t}\n+\n+\t// Possible Login Times\n+\t// TODO: Produce some regex or better check here\n+\tif ($post['varuserslogintime'] && !preg_match(\"/^[a-zA-Z0-9,|-]*$/\", $post['varuserslogintime'])) {\n+\t\t$input_errors[] = \"The 'Possible Login Times' field may only contain a-z, A-Z, 0-9, comma, vertical bar and hyphen (regex /^[a-zA-Z0-9,|-]*$/)\";\n+\t}\n+\n+\t// Amount of Time\n+\tif ($post['varusersamountoftime'] != '' && !is_numericint($post['varusersamountoftime'])) {\n+\t\t$input_errors[] = \"The 'Amount of Time' field must contain an integer value.\";\n+\t}\n+\n+\t// Amount of Download and Upload Traffic\n+\tif ($post['varusersmaxtotaloctets'] != '' && !is_numericint($post['varusersmaxtotaloctets'])) {\n+\t\t$input_errors[] = \"The 'Amount of Download and Upload Traffic' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Bandwidth Down\n+\tif ($post['varusersmaxbandwidthdown'] != '' && !is_numericint($post['varusersmaxbandwidthdown'])) {\n+\t\t$input_errors[] = \"The 'Maximum Bandwidth Down' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Bandwidth Up\n+\tif ($post['varusersmaxbandwidthup'] != '' && !is_numericint($post['varusersmaxbandwidthup'])) {\n+\t\t$input_errors[] = \"The 'Maximum Bandwidth Up' field must contain an integer value.\";\n+\t}\n+\n+\t// Accounting Interim Interval\n+\tif ($post['varusersacctinteriminterval'] != '') {\n+\t\tif (!is_numericint($post['varusersacctinteriminterval'])) {\n+\t\t\t$input_errors[] = \"The 'Accounting Interim Interval' field must contain an integer value.\";\n+\t\t} elseif ($post['varusersacctinteriminterval'] <= 60) {\n+\t\t\t$input_errors[] = \"The 'Accounting Interim Interval' value must be higher than 60 (seconds).\";\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * TODO:\n+\t * Additional RADIUS Attributes on the TOP of this entry, Additional RADIUS Attributes (CHECK-ITEM), Additional RADIUS Attributes (REPLY-ITEM)\n+\t */\n+\n+}\n+ \n+/* MACs input validation */\n+function freeradius_validate_macs($post, &$input_errors) {\n+\n+\t// MAC Address\n+\tif (!empty($post['varmacsaddress'])) {\n+\t\tif (!preg_match('/^[0-9A-F]{2}(?:[-][0-9A-F]{2}){5}$/i', $post['varmacsaddress'])) {\n+\t\t\t$input_errors[] = \"The 'MAC Address' field must contain a valid MAC address, delimited with '-' character.\";\n+\t\t}\n+\t}\n+\n+\t// Redirection URL\n+\tif (!empty($post['varmacsswisprredirectionurl'])) {\n+\t\tif (!filter_var($post['varmacsswisprredirectionurl'], FILTER_VALIDATE_URL)) {\n+\t\t\t$input_errors[] = \"The 'Redirection URL' field must contain a valid URL.\";\n+\t\t}\n+\t}\n+\n+\t// Number of Simultaneous Connections\n+\tif ($post['varmacssimultaneousconnect'] != '' && !is_numericint($post['varmacssimultaneousconnect'])) {\n+\t\t$input_errors[] = \"The 'Number of Simultaneous Connections' field must contain an integer value.\";\n+\t}\n+\n+\t// Description\n+\tif ($post['description'] && !preg_match(\"/^[a-zA-Z0-9 _,.;:+=()-]*$/\", $post['description'])) {\n+\t\t$input_errors[] = \"Do not use special characters in the 'Description' field; only /^[a-zA-Z0-9 _,.;:+=()-]*$/ allowed.\";\n+\t}\n+\n+\t// IP Address; may contain a single trailing '+' for simultaneous connections\n+\tif ($post['varmacsframedipaddress']) {\n+\t\t$framedip = str_replace('+', '', $post['varmacsframedipaddress'], $pluscnt);\n+\t\tif (!is_ipaddrv4($framedip)) {\n+\t\t\t$input_errors[] = \"The 'IP Address' field must contain a valid IPv4 address.\";\n+\t\t}\n+\t\tif ($pluscnt > 1) {\n+\t\t\t$input_errors[] = \"The 'IP Address' field may optionally contain only a single trailing '+'.\";\n+\t\t}\n+\t}\n+\n+\t// Subnet Mask\n+\tif ($post['varmacsframedipnetmask']) {\n+\t\tif ($post['varmacsframedipaddress'] == '') {\n+\t\t\t$input_errors[] = \"To specify a 'Subnet Mask', the 'IP Address' field must not be empty.\";\n+\t\t} elseif (is_ipaddrv4($framedip)) {\n+\t\t\t$ip = long2ip(ip2long($framedip) & ip2long($post['varmacsframedipnetmask']));\n+\t\t\t$mask = 32 - log((ip2long($post['varmacsframedipnetmask']) ^ ip2long('255.255.255.255')) +1, 2);\n+\t\t\tif (!is_subnetv4(\"{$ip}/{$mask}\")) {\n+\t\t\t\t$input_errors[] = \"The 'Subnet Mask' field must contain a valid subnet mask.\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// Gateway\n+\tif ($post['varmacsframedroute'] != '') {\n+\t\t$framedroute = explode(\" \", $post['varmacsframedroute']);\n+\t\t$cnt = count($framedroute);\n+\t\t// One or more metrics are allowed per RFC2865 (5.22)\n+\t\tif ($cnt < 3) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field must match the required format: Subnet Gateway Metric(s) (e.g. 192.168.10.0/24 192.168.10.1 1).\";\n+\t\t}\n+\t\t// The subnet CIDR is optional per RFC2865 (5.22)\n+\t\tif (!is_ipaddrv4($framedroute[0]) && !is_subnetv4($framedroute[0])) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field's subnet part '{$framedroute[0]}' must be a valid IPv4 subnet.\";\n+\t\t}\n+\t\tif (!is_ipaddrv4($framedroute[1])) {\n+\t\t\t$input_errors[] = \"The 'Gateway' field's gateway part '{$framedroute[1]}' must be a valid IPv4 gateway address.\";\n+\t\t}\n+\t\t// One or more metrics are allowed per RFC2865 (5.22)\n+\t\tfor ($i = 2; $i < $cnt; $i++) {\n+\t\t\tif (!is_numericint($framedroute[$i])) {\n+\t\t\t\t$input_errors[] = \"The 'Gateway' field's metric part '{$framedroute[$i]}' must contain an integer value.\";\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t// VLAN ID\n+\tif ($post['varmacsvlanid'] != '') {\n+\t\tif (!is_numericint($post['varmacsvlanid'])) {\n+\t\t\t$input_errors[] = \"The 'VLAN ID' field must contain an integer value.\";\n+\t\t} elseif ($post['varmacsvlanid'] < 1 || $post['varmacsvlanid'] > 4095) {\n+\t\t\t$input_errors[] = \"The 'VLAN ID' must be in the 1-4095 range.\";\n+\t\t}\n+\t}\n+\n+\t// Expiration Date\n+\tif ($post['varmacsexpiration'] != '') {\n+\t\t$expires = date_parse_from_format(\"M d Y\", $post['varmacsexpiration']);\n+\t\tif ($expires['error_count'] > 0 || $expires['warning_count'] > 0) {\n+\t\t\t$input_errors[] = \"The 'Expiration Date' format is invalid. | Error(s): \" .\n+\t\t\t    implode('. ', $expires['errors']) . \" | Warning(s): \" .\n+\t\t\t    implode('. ', $expires['warnings']);\n+\t\t}\n+\t\t// Hack around date_parse_from_format() bugs, such as expanding \"Jan 199\" to \"Jan 1 99\"\n+\t\tif ($expires['year'] < 1970) {\n+\t\t\t$input_errors[] = \"The 'Expiration Date' contains an invalid year.\";\n+\t\t}\n+\t}\n+\n+\t// Session Timeout\n+\tif ($post['varmacssessiontimeout'] != '' && !is_numericint($post['varmacssessiontimeout'])) {\n+\t\t$input_errors[] = \"The 'Session Timeout' field must contain an integer value.\";\n+\t}\n+\n+\t// Possible Login Times\n+\t// TODO: Produce some regex or better check here\n+\tif ($post['varmacslogintime'] && !preg_match(\"/^[a-zA-Z0-9,|-]*$/\", $post['varmacslogintime'])) {\n+\t\t$input_errors[] = \"The 'Possible Login Times' field may only contain a-z, A-Z, 0-9, comma, vertical bar and hyphen (regex /^[a-zA-Z0-9,|-]*$/)\";\n+\t}\n+\n+\t// Amount of Time\n+\tif ($post['varmacsamountoftime'] != '' && !is_numericint($post['varmacsamountoftime'])) {\n+\t\t$input_errors[] = \"The 'Amount of Time' field must contain an integer value.\";\n+\t}\n+\n+\t// Amount of Download and Upload Traffic\n+\tif ($post['varmacsmaxtotaloctets'] != '' && !is_numericint($post['varmacsmaxtotaloctets'])) {\n+\t\t$input_errors[] = \"The 'Amount of Download and Upload Traffic' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Bandwidth Down\n+\tif ($post['varmacsmaxbandwidthdown'] != '' && !is_numericint($post['varmacsmaxbandwidthdown'])) {\n+\t\t$input_errors[] = \"The 'Maximum Bandwidth Down' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Bandwidth Up\n+\tif ($post['varmacsmaxbandwidthup'] != '' && !is_numericint($post['varmacsmaxbandwidthup'])) {\n+\t\t$input_errors[] = \"The 'Maximum Bandwidth Up' field must contain an integer value.\";\n+\t}\n+\n+\t// Accounting Interim Interval\n+\tif ($post['varmacsacctinteriminterval'] != '') {\n+\t\tif (!is_numericint($post['varmacsacctinteriminterval'])) {\n+\t\t\t$input_errors[] = \"The 'Accounting Interim Interval' field must contain an integer value.\";\n+\t\t} elseif ($post['varmacsacctinteriminterval'] <= 60) {\n+\t\t\t$input_errors[] = \"The 'Accounting Interim Interval' value must be higher than 60 (seconds).\";\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * TODO:\n+\t * Additional RADIUS Attributes on the TOP of this entry, Additional RADIUS Attributes (CHECK-ITEM), Additional RADIUS Attributes (REPLY-ITEM)\n+\t */\n+\n+}\n+\n+/* NAS/Clients input validation */\n+function freeradius_validate_clients($post, &$input_errors) {\n+\n+\t// Client IP Address\n+\tif ($post['varclientip'] != '*') {\n+\t\tif ($post['varclientipversion'] == 'ipaddr' && !is_ipaddrv4($post['varclientip'])) {\n+\t\t\t$input_errors[] = \"The 'Client IP Address' field must contain a valid IPv4 address when IPv4 is selected under 'Client IP Version'.\";\n+\t\t}\n+\t\tif ($post['varclientipversion'] == 'ipv6addr' && !is_ipaddrv6($post['varclientip'])) {\n+\t\t\t$input_errors[] = \"The 'Client IP Address' field must contain a valid IPv6 address when IPv6 is selected under 'Client IP Version'.\";\n+\t\t}\n+\t}\n+\n+\t// Client Shortname\n+\tif ($post['varclientshortname'] && !preg_match(\"/^[a-zA-Z0-9_.-]*$/\", $post['varclientshortname'])) {\n+\t\t$input_errors[] = \"The 'Client Shortname' field may only contain a-z, A-Z, 0-9, underscore, period and hyphen (regex /^[a-zA-Z0-9_.-]*$/)\";\n+\t}\n+\n+\t// Client Shared Secret\n+\tif (strlen($post['varclientsharedsecret']) > 31) {\n+\t\t$input_errors[] = \"The 'Client Shared Secret' fields contains too many characters. FreeRADIUS is limited to 31 characters for shared secret.\";\n+\t}\n+\n+\t// Description\n+\tif ($post['description'] && !preg_match(\"/^[a-zA-Z0-9 _,.;:+=()-]*$/\", $post['description'])) {\n+\t\t$input_errors[] = \"Do not use special characters in the 'Description' field; only /^[a-zA-Z0-9 _,.;:+=()-]*$/ allowed.\";\n+\t}\n+\n+\t/*\n+\t * TODO: Check NAS Login for sanity.\n+\t */\n+\n+}\n+\n+/* Interfaces input validation */\n+function freeradius_validate_interfaces($post, &$input_errors) {\n+\n+\t// Interface IP Address\n+\tif (empty($post['varinterfaceip'])) {\n+\t\t$input_errors[] = \"The 'Interface IP Address' field must not be empty.\";\n+\t} elseif ($post['varinterfaceip'] != '*') {\n+\t\tif ($post['varinterfaceipversion'] == 'ipaddr' && !is_ipaddrv4($post['varinterfaceip'])) {\n+\t\t\t$input_errors[] = \"The 'Interface IP Address' must contain a valid IPv4 address when IPv4 is selected under 'IP Version'.\";\n+\t\t}\n+\t\tif ($post['varinterfaceipversion'] == 'ipv6addr' && !is_ipaddrv6($post['varinterfaceip'])) {\n+\t\t\t$input_errors[] = \"The 'Interface IP Address' must contain a valid IPv6 address when IPv6 is selected under 'IP Version'.\";\n+\t\t}\n+\t\tif (!is_ipaddr_configured($post['varinterfaceip'])) {\n+\t\t\t$input_errors[] = \"The 'Interface IP Address' must contain a valid, locally configured IP address!\";\n+\t\t}\n+\t}\n+\n+\t// Port\n+\tif (empty($post['varinterfaceport'])) {\n+\t\t$input_errors[] = \"The 'Port' field must not be empty.\";\n+\t} elseif (!is_port($post['varinterfaceport'])) {\n+\t\t$input_errors[] = \"The 'Port' field must contain a valid port.\";\n+\t}\n+\n+\t// Description\n+\tif ($post['description'] && !preg_match(\"/^[a-zA-Z0-9 _,.;:+=()-]*$/\", $post['description'])) {\n+\t\t$input_errors[] = \"Do not use special characters in the 'Description' field; only /^[a-zA-Z0-9 _,.;:+=()-]*$/ allowed.\";\n+\t}\n+\n+\t/*\n+\t * TODO: Check that the configured port is unique for the selected Interface Type/IP address.\n+\t */\n+\n+}\n+\n+/* General Settings input validation */\n+function freeradius_validate_settings($post, &$input_errors) {\n+\n+\t// Maximum Requests Tracked\n+\tif ($post['varsettingsmaxrequests'] != '' && !is_numericint($post['varsettingsmaxrequests'])) {\n+\t\t$input_errors[] = \"The 'Maximum Requests Tracked' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Request Timeout\n+\tif ($post['varsettingsmaxrequesttime'] != '' && !is_numericint($post['varsettingsmaxrequesttime'])) {\n+\t\t$input_errors[] = \"The 'Maximum Request Timeout' field must contain an integer value.\";\n+\t}\n+\n+\t// Cleanup Delay\n+\tif ($post['varsettingscleanupdelay'] != '' && !is_numericint($post['varsettingscleanupdelay'])) {\n+\t\t$input_errors[] = \"The 'Cleanup Delay' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Number of Attributes\n+\tif ($post['varsettingsmaxattributes'] != '' && !is_numericint($post['varsettingsmaxattributes'])) {\n+\t\t$input_errors[] = \"The 'Maximum Number of Attributes' field must contain an integer value.\";\n+\t}\n+\n+\t// Access-Reject Delay\n+\tif ($post['varsettingsrejectdelay'] != '' && !is_numericint($post['varsettingsrejectdelay'])) {\n+\t\t$input_errors[] = \"The 'Access-Reject Delay' field must contain an integer value.\";\n+\t}\n+\n+\t// Number of Threads After Start\n+\tif ($post['varsettingsstartservers'] != '' && !is_numericint($post['varsettingsstartservers'])) {\n+\t\t$input_errors[] = \"The 'Number of Threads After Start' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Number of Threads\n+\tif ($post['varsettingsmaxservers'] != '' && !is_numericint($post['varsettingsmaxservers'])) {\n+\t\t$input_errors[] = \"The 'Maximum Number of Threads' field must contain an integer value.\";\n+\t}\n+\n+\t// Minimum Spare Servers\n+\tif ($post['varsettingsminspareservers'] != '' && !is_numericint($post['varsettingsminspareservers'])) {\n+\t\t$input_errors[] = \"The 'Minimum Spare Servers' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Spare Servers\n+\tif ($post['varsettingsmaxspareservers'] != '' && !is_numericint($post['varsettingsmaxspareservers'])) {\n+\t\t$input_errors[] = \"The 'Maximum Spare Servers' field must contain an integer value.\";\n+\t}\n+\n+\t// Server Packet Queue Size\n+\tif ($post['varsettingsmaxqueuesize'] != '' && !is_numericint($post['varsettingsmaxqueuesize'])) {\n+\t\t$input_errors[] = \"The 'Server Packet Queue Size' field must contain an integer value.\";\n+\t}\n+\n+\t// Maximum Requests Per Server\n+\tif ($post['varsettingsmaxrequestsperserver'] != '' && !is_numericint($post['varsettingsmaxrequestsperserver'])) {\n+\t\t$input_errors[] = \"The 'Maximum Requests Per Server' field must contain an integer value.\";\n+\t}\n+\n+\t// OTP Lifetime\n+\tif ($post['varsettingsmotpenable'] == 'on') {\n+\t\tif ($post['varsettingsmotptimespan'] === 0) {\n+\t\t\t$input_errors[] = \"The 'OTP Lifetime' field must not be 0.\";\n+\t\t} elseif (empty($post['varsettingsmotptimespan'])) {\n+\t\t\t$input_errors[] = \"The 'OTP Lifetime' field must not be empty.\";\n+\t\t} elseif (!is_numericint($post['varsettingsmotptimespan'])) {\n+\t\t\t$input_errors[] = \"The 'OTP Lifetime' field must contain an integer value.\";\n+\t\t} elseif ($post['varsettingsmotptimespan'] > 12) {\n+\t\t\t$input_errors[] = \"The 'OTP Lifetime' field should contain only sane secure values. Values higher than 12 (~120 seconds) are not allowed.\";\n+\t\t}\n+\t}\n+\n+\t// Number of Invalid Password Attempts\n+\tif ($post['varsettingsmotpenable'] == 'on') {\n+\t\tif ($post['varsettingsmotppasswordattempts'] === 0) {\n+\t\t\t$input_errors[] = \"The 'Invalid Password Attempts' field must not be 0.\";\n+\t\t} elseif (empty($post['varsettingsmotppasswordattempts'])) {\n+\t\t\t$input_errors[] = \"The 'Invalid Password Attempts' field must not be empty.\";\n+\t\t} elseif (!is_numericint($post['varsettingsmotppasswordattempts'])) {\n+\t\t\t$input_errors[] = \"The 'Invalid Password Attempts' field must contain an integer value.\";\n+\t\t} elseif ($post['varsettingsmotppasswordattempts'] > 20) {\n+\t\t\t$input_errors[] = \"The 'Invalid Password Attempts' field should contain only sane secure values. Values higher than 20 are not allowed.\";","path":"net/pfSense-pkg-freeradius2/files/usr/local/pkg/freeradius.inc","position":539,"original_position":539,"commit_id":"3de2ec898f33ae1045774506a5d8ad5f07aa2b68","original_commit_id":"3de2ec898f33ae1045774506a5d8ad5f07aa2b68","user":{"login":"jim-p","id":174434,"avatar_url":"https://avatars.githubusercontent.com/u/174434?v=3","gravatar_id":"","url":"https://api.github.com/users/jim-p","html_url":"https://github.com/jim-p","followers_url":"https://api.github.com/users/jim-p/followers","following_url":"https://api.github.com/users/jim-p/following{/other_user}","gists_url":"https://api.github.com/users/jim-p/gists{/gist_id}","starred_url":"https://api.github.com/users/jim-p/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jim-p/subscriptions","organizations_url":"https://api.github.com/users/jim-p/orgs","repos_url":"https://api.github.com/users/jim-p/repos","events_url":"https://api.github.com/users/jim-p/events{/privacy}","received_events_url":"https://api.github.com/users/jim-p/received_events","type":"User","site_admin":false},"body":"Same as above, re: s/sane//","created_at":"2017-02-22T14:19:10Z","updated_at":"2017-02-22T14:43:17Z","html_url":"https://github.com/pfsense/FreeBSD-ports/pull/308#discussion_r102471502","pull_request_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308","_links":{"self":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/comments/102471502"},"html":{"href":"https://github.com/pfsense/FreeBSD-ports/pull/308#discussion_r102471502"},"pull_request":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308"}}},"pull_request":{"url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308","id":106334356,"html_url":"https://github.com/pfsense/FreeBSD-ports/pull/308","diff_url":"https://github.com/pfsense/FreeBSD-ports/pull/308.diff","patch_url":"https://github.com/pfsense/FreeBSD-ports/pull/308.patch","issue_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/308","number":308,"state":"open","locked":false,"title":"FreeRADIUS - Add input validation (Bug #7263)","user":{"login":"doktornotor","id":1075960,"avatar_url":"https://avatars.githubusercontent.com/u/1075960?v=3","gravatar_id":"","url":"https://api.github.com/users/doktornotor","html_url":"https://github.com/doktornotor","followers_url":"https://api.github.com/users/doktornotor/followers","following_url":"https://api.github.com/users/doktornotor/following{/other_user}","gists_url":"https://api.github.com/users/doktornotor/gists{/gist_id}","starred_url":"https://api.github.com/users/doktornotor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doktornotor/subscriptions","organizations_url":"https://api.github.com/users/doktornotor/orgs","repos_url":"https://api.github.com/users/doktornotor/repos","events_url":"https://api.github.com/users/doktornotor/events{/privacy}","received_events_url":"https://api.github.com/users/doktornotor/received_events","type":"User","site_admin":false},"body":"This adds input validation to FreeRADIUS package (Bug #7263).","created_at":"2017-02-15T15:32:29Z","updated_at":"2017-02-22T14:43:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e9350afd56d32d7f8c8ddd30f88d6e1da97ef16c","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308/commits","review_comments_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308/comments","review_comment_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/308/comments","statuses_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/statuses/3de2ec898f33ae1045774506a5d8ad5f07aa2b68","head":{"label":"doktornotor:patch-5","ref":"patch-5","sha":"3de2ec898f33ae1045774506a5d8ad5f07aa2b68","user":{"login":"doktornotor","id":1075960,"avatar_url":"https://avatars.githubusercontent.com/u/1075960?v=3","gravatar_id":"","url":"https://api.github.com/users/doktornotor","html_url":"https://github.com/doktornotor","followers_url":"https://api.github.com/users/doktornotor/followers","following_url":"https://api.github.com/users/doktornotor/following{/other_user}","gists_url":"https://api.github.com/users/doktornotor/gists{/gist_id}","starred_url":"https://api.github.com/users/doktornotor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doktornotor/subscriptions","organizations_url":"https://api.github.com/users/doktornotor/orgs","repos_url":"https://api.github.com/users/doktornotor/repos","events_url":"https://api.github.com/users/doktornotor/events{/privacy}","received_events_url":"https://api.github.com/users/doktornotor/received_events","type":"User","site_admin":false},"repo":{"id":77488397,"name":"FreeBSD-ports","full_name":"doktornotor/FreeBSD-ports","owner":{"login":"doktornotor","id":1075960,"avatar_url":"https://avatars.githubusercontent.com/u/1075960?v=3","gravatar_id":"","url":"https://api.github.com/users/doktornotor","html_url":"https://github.com/doktornotor","followers_url":"https://api.github.com/users/doktornotor/followers","following_url":"https://api.github.com/users/doktornotor/following{/other_user}","gists_url":"https://api.github.com/users/doktornotor/gists{/gist_id}","starred_url":"https://api.github.com/users/doktornotor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doktornotor/subscriptions","organizations_url":"https://api.github.com/users/doktornotor/orgs","repos_url":"https://api.github.com/users/doktornotor/repos","events_url":"https://api.github.com/users/doktornotor/events{/privacy}","received_events_url":"https://api.github.com/users/doktornotor/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/doktornotor/FreeBSD-ports","description":"FreeBSD ports tree with pfSense changes","fork":true,"url":"https://api.github.com/repos/doktornotor/FreeBSD-ports","forks_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/forks","keys_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/keys{/key_id}","collaborators_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/teams","hooks_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/hooks","issue_events_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/issues/events{/number}","events_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/events","assignees_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/assignees{/user}","branches_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/branches{/branch}","tags_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/tags","blobs_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/git/refs{/sha}","trees_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/git/trees{/sha}","statuses_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/statuses/{sha}","languages_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/languages","stargazers_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/stargazers","contributors_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/contributors","subscribers_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/subscribers","subscription_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/subscription","commits_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/commits{/sha}","git_commits_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/git/commits{/sha}","comments_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/comments{/number}","issue_comment_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/issues/comments{/number}","contents_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/contents/{+path}","compare_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/compare/{base}...{head}","merges_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/merges","archive_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/downloads","issues_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/issues{/number}","pulls_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/pulls{/number}","milestones_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/milestones{/number}","notifications_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/labels{/name}","releases_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/releases{/id}","deployments_url":"https://api.github.com/repos/doktornotor/FreeBSD-ports/deployments","created_at":"2016-12-27T23:23:33Z","updated_at":"2016-12-26T23:52:02Z","pushed_at":"2017-02-22T11:29:26Z","git_url":"git://github.com/doktornotor/FreeBSD-ports.git","ssh_url":"git@github.com:doktornotor/FreeBSD-ports.git","clone_url":"https://github.com/doktornotor/FreeBSD-ports.git","svn_url":"https://github.com/doktornotor/FreeBSD-ports","homepage":null,"size":1013489,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"devel"}},"base":{"label":"pfsense:devel","ref":"devel","sha":"35a0d64d9cd5f0b7c9b7e9af7448ab8166604969","user":{"login":"pfsense","id":3716965,"avatar_url":"https://avatars.githubusercontent.com/u/3716965?v=3","gravatar_id":"","url":"https://api.github.com/users/pfsense","html_url":"https://github.com/pfsense","followers_url":"https://api.github.com/users/pfsense/followers","following_url":"https://api.github.com/users/pfsense/following{/other_user}","gists_url":"https://api.github.com/users/pfsense/gists{/gist_id}","starred_url":"https://api.github.com/users/pfsense/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pfsense/subscriptions","organizations_url":"https://api.github.com/users/pfsense/orgs","repos_url":"https://api.github.com/users/pfsense/repos","events_url":"https://api.github.com/users/pfsense/events{/privacy}","received_events_url":"https://api.github.com/users/pfsense/received_events","type":"Organization","site_admin":false},"repo":{"id":41116288,"name":"FreeBSD-ports","full_name":"pfsense/FreeBSD-ports","owner":{"login":"pfsense","id":3716965,"avatar_url":"https://avatars.githubusercontent.com/u/3716965?v=3","gravatar_id":"","url":"https://api.github.com/users/pfsense","html_url":"https://github.com/pfsense","followers_url":"https://api.github.com/users/pfsense/followers","following_url":"https://api.github.com/users/pfsense/following{/other_user}","gists_url":"https://api.github.com/users/pfsense/gists{/gist_id}","starred_url":"https://api.github.com/users/pfsense/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pfsense/subscriptions","organizations_url":"https://api.github.com/users/pfsense/orgs","repos_url":"https://api.github.com/users/pfsense/repos","events_url":"https://api.github.com/users/pfsense/events{/privacy}","received_events_url":"https://api.github.com/users/pfsense/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pfsense/FreeBSD-ports","description":"FreeBSD ports tree with pfSense changes","fork":false,"url":"https://api.github.com/repos/pfsense/FreeBSD-ports","forks_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/forks","keys_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/teams","hooks_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/hooks","issue_events_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/events{/number}","events_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/events","assignees_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/assignees{/user}","branches_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/branches{/branch}","tags_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/tags","blobs_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/git/refs{/sha}","trees_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/statuses/{sha}","languages_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/languages","stargazers_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/stargazers","contributors_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/contributors","subscribers_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/subscribers","subscription_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/subscription","commits_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/commits{/sha}","git_commits_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/git/commits{/sha}","comments_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/comments{/number}","issue_comment_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/comments{/number}","contents_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/contents/{+path}","compare_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/merges","archive_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/downloads","issues_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues{/number}","pulls_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls{/number}","milestones_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/milestones{/number}","notifications_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/labels{/name}","releases_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/releases{/id}","deployments_url":"https://api.github.com/repos/pfsense/FreeBSD-ports/deployments","created_at":"2015-08-20T20:02:11Z","updated_at":"2017-02-21T04:34:59Z","pushed_at":"2017-02-22T13:20:26Z","git_url":"git://github.com/pfsense/FreeBSD-ports.git","ssh_url":"git@github.com:pfsense/FreeBSD-ports.git","clone_url":"https://github.com/pfsense/FreeBSD-ports.git","svn_url":"https://github.com/pfsense/FreeBSD-ports","homepage":null,"size":1034698,"stargazers_count":65,"watchers_count":65,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":100,"mirror_url":null,"open_issues_count":8,"forks":100,"open_issues":8,"watchers":65,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308"},"html":{"href":"https://github.com/pfsense/FreeBSD-ports/pull/308"},"issue":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/308"},"comments":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/issues/308/comments"},"review_comments":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308/comments"},"review_comment":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/pulls/308/commits"},"statuses":{"href":"https://api.github.com/repos/pfsense/FreeBSD-ports/statuses/3de2ec898f33ae1045774506a5d8ad5f07aa2b68"}}}}
{"actor":{"display_login":"jim-p"}}