Ejemplo n.º 1
0
 function validate_custom_records($data_orig = array())
 {
     log_debug("domain", "Executing validate_custom_records(array_data)");
     if (!isset($this->data)) {
         // we need the domain details if we don't already have them
         $this->load_data();
     }
     $data = array();
     $data_tmp = array();
     if (!empty($data_orig)) {
         /*
          				Supplied Array Data - this data has some amount of pre-processing
         	done, having already run through the javascript validation.
         */
         log_debug("domain", "Using supplied array data in \$data_orig");
         /*
         	Fetch Data
         */
         $data["custom"]["num_records"] = count(array_keys($data_orig));
         for ($i = 0; $i < $data["custom"]["num_records"]; $i++) {
             $data_tmp[$i]["id"] = @security_script_input_predefined("int", $data_orig[$i]["id"], 1);
             $data_tmp[$i]["type"] = @security_script_input_predefined("any", $data_orig[$i]["type"], 1);
             $data_tmp[$i]["ttl"] = @security_script_input_predefined("int", $data_orig[$i]["ttl"], 1);
             $data_tmp[$i]["name"] = @security_script_input_predefined("any", $data_orig[$i]["name"], 1);
             $data_tmp[$i]["prio"] = @security_script_input_predefined("int", $data_orig[$i]["prio"], 0);
             $data_tmp[$i]["content"] = @security_script_input_predefined("any", $data_orig[$i]["content"], 1);
             $data_tmp[$i]["reverse_ptr"] = @security_script_input_predefined("checkbox", $data_orig[$i]["reverse_ptr"], 1);
             $data_tmp[$i]["reverse_ptr_orig"] = @security_script_input_predefined("checkbox", $data_orig[$i]["reverse_ptr_orig"], 1);
             $data_tmp[$i]["delete_undo"] = @security_script_input_predefined("any", $data_orig[$i]["delete_undo"], 1);
             if (empty($data_tmp[$i]["mode"]) || $data_tmp[$i]["mode"] != "delete" && $data_tmp[$i]["mode"] != "update") {
                 // mode undetermined, run check
                 if ($data_tmp[$i]["id"] && $data_tmp[$i]["delete_undo"] == "true") {
                     $data_tmp[$i]["mode"] = "delete";
                 } else {
                     if (!empty($data_tmp[$i]["content"]) && $data_tmp[$i]["delete_undo"] == "false") {
                         $data_tmp[$i]["mode"] = "update";
                     }
                 }
             }
         }
     } elseif (isset($_POST['record_custom_page'])) {
         /*
         	Fetch data from POST - easiest way, since we can take advantage of smart
         	error handling functions built in.
         */
         // fetch number of records
         $data["custom"]["num_records"] = @security_form_input_predefined("int", "num_records_custom", 0, "");
         for ($i = 0; $i < $data["custom"]["num_records"]; $i++) {
             /*
             	Fetch Data
             */
             $data_tmp[$i]["id"] = @security_form_input_predefined("int", "record_custom_" . $i . "_id", 0, "");
             $data_tmp[$i]["type"] = @security_form_input_predefined("any", "record_custom_" . $i . "_type", 0, "");
             $data_tmp[$i]["ttl"] = @security_form_input_predefined("int", "record_custom_" . $i . "_ttl", 0, "");
             $data_tmp[$i]["name"] = @security_form_input_predefined("any", "record_custom_" . $i . "_name", 0, "");
             $data_tmp[$i]["content"] = @security_form_input_predefined("any", "record_custom_" . $i . "_content", 0, "");
             $data_tmp[$i]["reverse_ptr"] = @security_form_input_predefined("checkbox", "record_custom_" . $i . "_reverse_ptr", 0, "");
             $data_tmp[$i]["reverse_ptr_orig"] = @security_form_input_predefined("checkbox", "record_custom_" . $i . "_reverse_ptr_orig", 0, "");
             $data_tmp[$i]["delete_undo"] = @security_form_input_predefined("any", "record_custom_" . $i . "_delete_undo", 0, "");
             /*
             	Process Raw Data
             */
             if ($data_tmp[$i]["id"] && $data_tmp[$i]["delete_undo"] == "true") {
                 $data_tmp[$i]["mode"] = "delete";
             } else {
                 if (!empty($data_tmp[$i]["content"]) && $data_tmp[$i]["delete_undo"] == "false") {
                     $data_tmp[$i]["mode"] = "update";
                 }
             }
         }
     }
     /*
     	Process Validated Inputs
     */
     if (!empty($data_tmp)) {
         log_write("debug", "domains", "Record values obtained, running detailed check");
         for ($i = 0; $i < $data["custom"]["num_records"]; $i++) {
             /*
             	Error Handling
             */
             // verify name syntax
             if ($data_tmp[$i]["name"] == "*" || preg_match("/^\\*\\.[A-Za-z0-9\\p{L}:._-]+\$/", $data_tmp[$i]["name"])) {
                 // wildcard records are annoying - wildcards must be standalone, and can't be part of a sring
                 // OK  -> *
                 // OK  -> *.example.com
                 // BAD -> abc*.example.com
                 // BAD -> std*abc.example.com
                 // nothing todo
             } elseif ($data_tmp[$i]["name"] != "@" && !preg_match("/^[A-Za-z0-9\\p{L}:._-]*\$/", $data_tmp[$i]["name"])) {
                 // all other record types
                 log_write("error", "process", "Sorry, the value you have entered for record " . $data_tmp[$i]["name"] . " contains invalid charactors");
                 error_flag_field("record_custom_" . $i . "");
             }
             // validate content and name formatting per domain type
             if ($data_tmp[$i]["name"] != "") {
                 switch ($data_tmp[$i]["type"]) {
                     case "A":
                         // validate IPv4
                         if (!preg_match("/^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:[.](?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}\$/", $data_tmp[$i]["content"])) {
                             // invalid IP address
                             log_write("error", "process", "A record for " . $data_tmp[$i]["name"] . " did not validate as an IPv4 address");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "AAAA":
                         // validate IPv6
                         if (filter_var($data_tmp[$i]["content"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) == FALSE) {
                             // invalid IP address
                             log_write("error", "process", "AAAA record for " . $data_tmp[$i]["name"] . " did not validate as an IPv6 address");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "CNAME":
                         // validate CNAME
                         if ($data_tmp[$i]["content"] != "@" && !preg_match("/^[A-Za-z0-9\\p{L}._-]*\$/", $data_tmp[$i]["content"])) {
                             // invalid CNAME
                             log_write("error", "process", "CNAME record for " . $data_tmp[$i]["name"] . " contains invalid characters.");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         // make sure it's not an IP
                         if (filter_var($data_tmp[$i]["content"], FILTER_VALIDATE_IP) == $data_tmp[$i]["content"]) {
                             // CNAME is pointing at an IP
                             log_write("error", "process", "CNAME record for " . $data_tmp[$i]["name"] . " is incorrectly referencing an IP address.");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "SRV":
                         // validate SRV name (_service._proto.name OR _service._proto))
                         if (!preg_match("/^_[A-Za-z0-9\\p{L}.-]*\\._[A-Za-z\\p{L}]*\\.[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["name"]) && !preg_match("/^_[A-Za-z0-9\\p{L}.-]*\\._[A-Za-z\\p{L}]*\$/", $data_tmp[$i]["name"])) {
                             log_write("error", "process", "SRV record for " . $data_tmp[$i]["name"] . " is not correctly formatted - name must be: _service._proto.name");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         // validate SRV content (priority, weight, port, target/host)
                         if (!preg_match("/^[0-9]*\\s[0-9]*\\s[0-9]*\\s[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) {
                             log_write("error", "process", "SRV record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must be: priority weight port target/hostname");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "SPF":
                     case "TXT":
                         // TXT string could be almost anything, just make sure it's quoted.
                         $data_tmp[$i]["content"] = str_replace("'", "", $data_tmp[$i]["content"]);
                         $data_tmp[$i]["content"] = str_replace('"', "", $data_tmp[$i]["content"]);
                         $data_tmp[$i]["content"] = '"' . $data_tmp[$i]["content"] . '"';
                         break;
                     case "PTR":
                         if (strpos($this->data["domain_name"], "in-addr.arpa")) {
                             // IPv4 PTR Record
                             // We only pass through the 4th octet to the end user.
                             if (!preg_match("/^[0-9]*\$/", $data_tmp[$i]["name"])) {
                                 log_write("error", "process", "PTR reverse record for " . $data_tmp[$i]["content"] . " should be a single octet.");
                                 error_flag_field("record_custom_" . $i . "");
                             }
                             if (!preg_match("/^[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) {
                                 log_write("error", "process", "PTR reverse record for " . $data_tmp[$i]["name"] . " is not correctly formatted.");
                                 error_flag_field("record_custom_" . $i . "");
                             }
                         } elseif (strpos($this->data["domain_name"], "ip6.arpa")) {
                             // IPv6 PTR Record
                             // If the record is already in reverse ARPA format, we should convert it first
                             if (strpos($data_tmp[$i]["name"], "ip6.arpa")) {
                                 $data_tmp[$i]["name"] = ipv6_convert_fromarpa($data_tmp[$i]["name"]);
                             }
                             // We pass through a full IPv6 address and maybe a CIDR value - if provided,
                             // we should strip off the CIDR and then validate the address and process.
                             $data_tmp[$i]["name"] = preg_replace("/\\/[0-9]*\$/", '', $data_tmp[$i]["name"]);
                             if (!filter_var($data_tmp[$i]["name"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                                 log_write("error", "process", "Provided PTR IPv6 address for " . $data_tmp[$i]["name"] . " is not a valid IPv6 address.");
                                 error_flag_field("record_custom_" . $i . "");
                             }
                             if (!preg_match("/^[A-Za-z0-9\\p{L}.-]*\$/", $data_tmp[$i]["content"])) {
                                 log_write("error", "process", "Provided PTR IPv6 reverse record for " . $data_tmp[$i]["name"] . " is not correctly formatted.");
                                 error_flag_field("record_custom_" . $i . "");
                             }
                             // convert the record into PTR formatted value
                             $data_tmp[$i]["name"] = ipv6_convert_arpa($data_tmp[$i]["name"]);
                         }
                         break;
                     case "SSHFP":
                         // validate SSHFP content (algorithm, type, key/fingerprint)
                         if (!preg_match("/^[1-4] [1-2] [a-fA-F0-9]+\$/", $data_tmp[$i]["content"])) {
                             log_write("error", "process", "SSHFP record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must be: algorithm(1-4) type(1-2) <key/fingerprint>");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "LOC":
                         // validate SSHFP content (algorithm, type, key/fingerprint)
                         if (!preg_match("/^[0-9]+( [0-9]+( [0-9]+\\.[0-9]+)?)? N|S [0-9]+( [0-9]+( [0-9]+\\.[0-9]+)?)? E|W \\-?[0-9]+\\.[0-9]+m?( [0-9]+\\.[0-9]+m?)?( [0-9]+\\.[0-9]+m?)?/", $data_tmp[$i]["content"])) {
                             log_write("error", "process", "LOC record for " . $data_tmp[$i]["name"] . " is not correctly formatted - content must follow RFC 1876");
                             error_flag_field("record_custom_" . $i . "");
                         }
                         break;
                     case "NS":
                     case "MX":
                     case "HINFO":
                         // nothing todo.
                         break;
                     default:
                         log_write("error", "process", "Unknown record type " . $data_tmp[$i]["type"] . "");
                         break;
                 }
                 // remove excess "." which might have been added
                 $data_tmp[$i]["name"] = rtrim($data_tmp[$i]["name"], ".");
                 $data_tmp[$i]["content"] = rtrim($data_tmp[$i]["content"], ".");
                 // verify reverse PTR options
                 if ($data_tmp[$i]["reverse_ptr"]) {
                     if ($data_tmp[$i]["type"] == "A" || $data_tmp[$i]["type"] == "AAAA") {
                         // check if the appropiate reverse DNS domain exists
                         $obj_record = new domain_records();
                         if (!$obj_record->find_reverse_domain($data_tmp[$i]["content"])) {
                             // no match
                             log_write("error", "process", "Sorry, we can't set a reverse PTR for " . $data_tmp[$i]["content"] . " --&gt; " . $data_tmp[$i]["name"] . ", since there is no reverse domain record for that IP address");
                             error_flag_field("record_custom_" . $i . "");
                         } else {
                             // match, record the domain ID and record ID to save a lookup
                             $data_tmp[$i]["reverse_ptr_id_domain"] = $obj_record->id;
                             $data_tmp[$i]["reverse_ptr_id_record"] = $obj_record->id_record;
                         }
                         // add to the reverse domain list - we use this list to avoid reloading for every record
                         if (@(!in_array($obj_record->id, $data["reverse"]))) {
                             $data["reverse"][] = $obj_record->id;
                         }
                         unset($obj_record);
                     } else {
                         log_write("error", "process", "A reverse PTR record is only valid for an A or AAAA record");
                         error_flag_field("record_custom_" . $i . "");
                     }
                 }
                 // add to processing array
                 $data["records"][] = $data_tmp[$i];
             } else {
                 /*
                 	No record name exists - this is only valid if no content is also supplied
                 */
                 if (!empty($data_tmp[$i]['content'])) {
                     log_write("error", "process", "Name cannot be empty for IP address: " . $data_tmp[$i]['content']);
                     error_flag_field("record_custom_" . $i . "");
                 }
             }
         }
         // end of loop through records
     } else {
         log_write("debug", "domains", "No records provided, no validation performed");
     }
     // return structured array
     return $data;
 }
Ejemplo n.º 2
0
         $obj_domain->data["ipv6_autofill_reverse_from_forward"] = security_form_input_predefined("checkbox", "ipv6_autofill_reverse_from_forward", 0, "");
         //$obj_domain->data["ipv6_autofill_domain"]		= security_form_input_predefined("any", "ipv6_autofill_domain", 0, "");
         $obj_domain->data["domain_description"] = security_form_input_predefined("any", "domain_description", 0, "");
         // check CIDR
         $matches = explode("/", $obj_domain->data["ipv6_network"]);
         if (!empty($matches[0]) && !empty($matches[1])) {
             // set network
             $obj_domain->data["ipv6_network"] = $matches[0];
             $obj_domain->data["ipv6_cidr"] = $matches[1];
             // check CIDR
             if ($obj_domain->data["ipv6_cidr"] > 128 || $obj_domain->data["ipv6_cidr"] < 1) {
                 log_write("error", "process", "Invalid CIDR, IPv6 CIDRs are between /0 and /128");
                 error_flag_field("ipv6_network");
             }
             // generate domain name (IPv6 CIDR)
             $obj_domain->data["domain_name"] = ipv6_convert_arpa($obj_domain->data["ipv6_network"] . "/" . $obj_domain->data["ipv6_cidr"]);
             // if no description, set to original IP
             if (!$obj_domain->data["domain_description"]) {
                 $obj_domain->data["domain_description"] = "Reverse domain for range " . $obj_domain->data["ipv6_network"] . "/" . $obj_domain->data["ipv6_cidr"];
             }
         }
     } else {
         log_write("error", "process", "Unexpected domain type, unable to process.");
     }
 }
 // standard fields
 $obj_domain->data["soa_hostmaster"] = security_form_input_predefined("email", "soa_hostmaster", 1, "");
 $obj_domain->data["soa_serial"] = security_form_input_predefined("int", "soa_serial", 1, "");
 $obj_domain->data["soa_refresh"] = security_form_input_predefined("int", "soa_refresh", 1, "");
 $obj_domain->data["soa_retry"] = security_form_input_predefined("int", "soa_retry", 1, "");
 $obj_domain->data["soa_expire"] = security_form_input_predefined("int", "soa_expire", 1, "");
Ejemplo n.º 3
0
 */
 if ($record["reverse_ptr"]) {
     log_write("debug", "process", "Updating reverse PTR record for " . $record["name"] . "--&gt; " . $record["content"] . "");
     $obj_ptr = new domain_records();
     $obj_ptr->id = $record["reverse_ptr_id_domain"];
     // will always be set
     $obj_ptr->id_record = $record["reverse_ptr_id_record"];
     // might be set, if not, a new record will be added
     $obj_ptr->load_data();
     if ($obj_ptr->id_record) {
         $obj_ptr->load_data_record();
     }
     // fetch host portion of IP address
     switch (ip_type_detect($record["content"])) {
         case "6":
             $ip_ptr = ipv6_convert_arpa($record["content"]);
             break;
         case "4":
         default:
             $tmp = explode(".", $record["content"]);
             $ip_ptr = $tmp[3];
             break;
     }
     // standard reverse record details
     $obj_ptr->data_record["type"] = "PTR";
     $obj_ptr->data_record["ttl"] = $record["ttl"];
     $obj_ptr->data_record["name"] = $ip_ptr;
     // make sure we are using the FQDN
     if ($record["name"] == "@" || $record["name"] == "*" || preg_match("/^\\*\\.[A-Za-z0-9:._-]+\$/", $record["name"])) {
         // @ is a special value, means set to the domain name
         // * is a wild card, reverse DNS can only be the domain name itself