Marius Cramer
2013-11-20 56364927166c1a0e15166433613add7f300ef7f6
commit | author | age
532ae5 1 <?php
L 2
3 /*
4 Copyright (c) 2007, Till Brehm, projektfarm Gmbh
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32     DNS validation
33 */
34
35 class validate_dns {
36
7fe908 37     function validate_field($field, $area, $zoneid, $wildcard_allowed = 1){
MC 38         //$desc: Name, Data, RP mbox, RP txtref, SRV target, Zone origin, Name server, Admin email
39         global $app, $conf;
532ae5 40
7fe908 41         switch ($area) {
MC 42         case "Name":
43             $desc = $app->tform->wordbook['name_txt'];
44             break;
45         case "Data":
46             $desc = $app->tform->wordbook['data_txt'];
47             break;
48         case "RP mbox":
49             $desc = $app->tform->wordbook['rp_mbox_txt'];
50             break;
51         case "RP txtref":
52             $desc = $app->tform->wordbook['rp_txtref_txt'];
53             break;
54         case "SRV target":
55             $desc = $app->tform->wordbook['srv_target_txt'];
56             break;
57         case "Zone origin":
58             $desc = $app->tform->wordbook['zone_origin_txt'];
59             break;
60         case "Name server":
61             $desc = $app->tform->wordbook['ns_txt'];
62             break;
63         case "Admin email":
64             $desc = $app->tform->wordbook['mbox_txt'];
65             break;
66         }
532ae5 67
7fe908 68         $error = '';
532ae5 69
7fe908 70         $valid_characters = "*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_";
532ae5 71
7fe908 72         if(strlen($field) > 255) $error .= $desc." ".$app->tform->wordbook['error_255_characters']."<br>\r\n";
532ae5 73
7fe908 74         $parts = explode(".", $field);
MC 75         $i = 0;
76         $empty = 0;
77         foreach ($parts as $part){
78             $i++;
532ae5 79
7fe908 80             if(trim($part) == '') $empty += 1;
532ae5 81
7fe908 82             if(strlen($part) > 63) $error .= $desc." ".$app->tform->wordbook['error_63_characters']."<br>\r\n";
532ae5 83
7fe908 84             if(strspn($part, $valid_characters) != strlen($part)) $error .= $desc." ".$app->tform->wordbook['error_invalid_characters']."<br>\r\n";
532ae5 85
7fe908 86             if(substr($part, 0, 1) == '-') $error .= $desc." ".$app->tform->wordbook['error_hyphen_begin']."<br>\r\n";
MC 87             if(substr($part, -1) == '-') $error .= $desc." ".$app->tform->wordbook['error_hyphen_end']."<br>\r\n";
532ae5 88
7fe908 89             if(strstr($part, "*")){
MC 90                 if($wildcard_allowed){
91                     if($i != 1) $error .= $desc." ".$app->tform->wordbook['error_wildcard_non_initial_part']."<br>\r\n";
532ae5 92
7fe908 93                     if($part != "*") $error .= $desc." ".$app->tform->wordbook['error_wildcard_mix']."<br>\r\n";
MC 94                 } else {
95                     $error .= $desc." ".$app->tform->wordbook['error_no_wildcard_allowed']."<br>\r\n";
96                 }
97             }
98         }
532ae5 99
7fe908 100         if(substr($field, -1) == '.'){
MC 101             if($i > 2 && $empty > 1) $error .= $desc." ".$app->tform->wordbook['error_invalid_characters']."<br>\r\n";
102         } else {
103             if($empty > 0 && $field != '') $error .= $desc." ".$app->tform->wordbook['error_invalid_characters']."<br>\r\n";
104         }
532ae5 105
7fe908 106         if(substr($field, -1) == '.' && $area == 'Name'){
35509d 107             $soa = $app->db->queryOneRecord("SELECT * FROM soa WHERE id = ".intval($zoneid));
7fe908 108             if(substr($field, (strlen($field) - strlen($soa['origin']))) != $soa['origin']) $error .= $desc." ".$app->tform->wordbook['error_out_of_zone']."<br>\r\n";
MC 109         }
532ae5 110
7fe908 111         return $error;
MC 112     }
113
114     function validate_rp_data(&$data, $zoneid){
115         global $app, $conf;
116         $error = '';
117         $fields = explode(" ", trim($data));
118         if(count($fields) != 2) return $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_invalid_rp']."<br>\r\n";
119         $mbox = $fields[0];
120         $txtref = $fields[1];
121
122         $error .= $this->validate_field($mbox, 'RP mbox', $zoneid, 0);
123         $error .= $this->validate_field($txtref, 'RP txtref', $zoneid, 0);
124
125         $data = $mbox." ".$txtref;
126         return $error;
127     }
128
129     function validate_srv_data(&$data, $zoneid){
130         global $app, $conf;
131         $error = '';
132
133         $fields = explode(" ", trim($data));
134         if(count($fields) != 3) return $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_invalid_srv']."<br>\r\n";
135
136         $weight = $fields[0];
137         $port = $fields[1];
138         $target = $fields[2];
139         if($weight < 0 || $weight > 65535) $error .= $app->tform->wordbook['weight_txt']." (\"<i>" . htmlentities($weight, ENT_QUOTES, $conf["html_content_encoding"])."</i>\") ".$app->tform->wordbook['error_srv_out_of_range']."<br>\r\n";
140         if($port < 0 || $port > 65535) $error .= $app->tform->wordbook['port_txt']." (\"<i>".htmlentities($port, ENT_QUOTES, $conf["html_content_encoding"])."</i>\") ".$app->tform->wordbook['error_srv_out_of_range']."<br>\r\n";
141
142         $error .= $this->validate_field($target, "SRV target", $zoneid, 0);
143
144         $data = (int)$weight." ".(int)$port." ".$target;
145         return $error;
146     }
147
148     function is_integer($value, $fieldname, $zero_allowed = 0){
149         global $app, $conf;
150
151         $error = '';
152
153         if($app->functions->intval($value, true) != $value || !is_numeric($value)) $error .= $fieldname." ".$app->tform->wordbook['error_must_be_integer']."<br>\r\n";
154         if($value > 2147483647) $error .= $fieldname." ".$app->tform->wordbook['error_must_not_be_greater_than_2147483647']."<br>\r\n";
155         if(!$zero_allowed){
156             if($value <= 0) $error .= $fieldname." ".$app->tform->wordbook['error_must_be_positive']."<br>\r\n";
157         } else {
158             if($value < 0) $error .= $fieldname." ".$app->tform->wordbook['error_must_not_be_negative']."<br>\r\n";
159         }
160
161         return $error;
162     }
163
164     function validate_rr(&$rr){
165         global $app, $conf;
166
167         $error = '';
168
169         $tmp_rr = $rr;
170         foreach($tmp_rr as $key => $val){
171             $rr[$key] = trim($val);
172         }
173         unset($tmp_rr);
174
175         $error .= $this->validate_field($rr['name'], 'Name', $rr['zone'], 1);
176
177         switch ($rr['type']) {
178         case "A":
179             $ip_parts = explode(".", $rr['data']);
180             if(count($ip_parts) != 4){
181                 $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_a']."<br>\r\n";
182             } else {
183                 for($n = 0; $n < 4; $n++){
184                     $q = $ip_parts[$n];
185                     if(!is_numeric($q) || (int)$q < 0 || (int)$q > 255 || trim($q) !== $q) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_a']."<br>\r\n";
186                 }
187             }
188             $rr['data'] = (int)$ip_parts[0].".".(int)$ip_parts[1].".".(int)$ip_parts[2].".".(int)$ip_parts[3];
189             break;
190         case "AAAA":
191             $valid_chars = "ABCDEFabcdef1234567890:";
192
193             if(strspn($rr['data'], $valid_chars) != strlen($rr['data'])) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_aaaa']."<br>\r\n";
194             break;
195         case "ALIAS":
196             $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
197             break;
198         case "CNAME":
199             $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
200             break;
201         case "HINFO":
202             if(!strchr($rr['data'], ' ')) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_hinfo']."<br>\r\n";
203             break;
204         case "MX":
205             $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
206             $error .= $this->is_integer($rr['aux'], $app->tform->wordbook['aux_txt'], 1);
207             break;
208         case "NS":
209             $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
210             break;
211         case "PTR":
212             $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
213             if(substr($rr['data'], -1) != '.') $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_ptr']."<br>\r\n";
214             break;
215         case "RP":
216             $error .= $this->validate_rp_data($rr['data'], $rr['zone']);
217             break;
218         case "SRV":
219             $error .= $this->validate_srv_data($rr['data'], $rr['zone']);
220             $error .= $this->is_integer($rr['aux'], $app->tform->wordbook['aux_txt'], 1);
221             break;
222         case "TXT":
223             break;
224         }
225
226         $error .= $this->is_integer($rr['ttl'], $app->tform->wordbook['ttl_txt']);
227
228
229         return $error;
230     }
231
232     function validate_soa(&$soa){
233         global $app, $conf;
234
235         $error = '';
236
237         $tmp_soa = $soa;
238         foreach($tmp_soa as $key => $val){
239             if($key != 'active') $soa[$key] = trim($val);
240         }
241         unset($tmp_soa);
242
243         if($soa['origin'] == '') $error .= $app->tform->wordbook['origin_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
244         if(substr($soa['origin'], -1) != '.') $error .= $app->tform->wordbook['origin_txt']." ".$app->tform->wordbook['error_dot']."<br>\r\n";
245         $error .= $this->validate_field($soa['origin'], "Zone origin", $soa['id'], 0);
246
247         $error .= $this->is_integer($soa['ttl'], $app->tform->wordbook['ttl_txt']);
248
249         if($soa['ns'] == '') $error .= $app->tform->wordbook['ns_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
250         $error .= $this->validate_field($soa['ns'], "Name server", $soa['id'], 0);
251
252         if($soa['mbox'] == '') $error .= $app->tform->wordbook['mbox_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
253         $error .= $this->validate_field($soa['mbox'], "Admin email", $soa['id'], 0);
254
255         $error .= $this->is_integer($soa['refresh'], $app->tform->wordbook['refresh_txt']);
256
257         $error .= $this->is_integer($soa['retry'], $app->tform->wordbook['retry_txt']);
258
259         $error .= $this->is_integer($soa['expire'], $app->tform->wordbook['expire_txt']);
260
261         $error .= $this->is_integer($soa['minimum'], $app->tform->wordbook['minimum_txt']);
262
263         return $error;
264     }
265
266     function increase_serial($serial){
267         global $app, $conf;
268
269         // increase serial
35509d 270         $serial_date = $app->functions->intval(substr($serial, 0, 8));
7fe908 271         $count = $app->functions->intval(substr($serial, 8, 2));
MC 272         $current_date = date("Ymd");
273         if($serial_date >= $current_date){
274             $count += 1;
275             if ($count > 99) {
276                 $serial_date += 1;
277                 $count = 0;
278             }
279             $count = str_pad($count, 2, "0", STR_PAD_LEFT);
280             $new_serial = $serial_date.$count;
281         } else {
282             $new_serial = $current_date.'01';
283         }
284         return $new_serial;
285     }
286
532ae5 287 }