71
+ − 1
<?php
1
+ − 2
119
+ − 3
/* Poweradmin, a friendly web-based admin tool for PowerDNS.
47
+ − 4
* See <https://rejo.zenger.nl/poweradmin> for more details.
+ − 5
*
+ − 6
* Copyright 2007, 2008 Rejo Zenger <rejo@zenger.nl>
+ − 7
*
+ − 8
* This program is free software: you can redistribute it and/or modify
+ − 9
* it under the terms of the GNU General Public License as published by
+ − 10
* the Free Software Foundation, either version 3 of the License, or
+ − 11
* (at your option) any later version.
+ − 12
*
+ − 13
* This program is distributed in the hope that it will be useful,
+ − 14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ − 16
* GNU General Public License for more details.
+ − 17
*
+ − 18
* You should have received a copy of the GNU General Public License
+ − 19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
+ − 20
*/
+ − 21
140
+ − 22
function validate_input ( $zid , $type , & $content , & $name , & $prio , & $ttl ) {
+ − 23
+ − 24
$zone = get_zone_name_from_id ( $zid ); // TODO check for return
1
+ − 25
140
+ − 26
if ( ! ( preg_match ( "/ $zone $/i" , $name ))) {
+ − 27
if ( isset ( $name ) && $name != "" ) {
+ − 28
$name = $name . "." . $zone ;
82
+ − 29
} else {
140
+ − 30
$name = $zone ;
97
+ − 31
}
96
+ − 32
}
140
+ − 33
+ − 34
switch ( $type ) {
96
+ − 35
140
+ − 36
case "A" :
+ − 37
if ( ! is_valid_ipv4 ( $content )) return false ;
+ − 38
break ;
+ − 39
+ − 40
case "AAAA" :
+ − 41
if ( ! is_valid_ipv6 ( $content )) return false ;
+ − 42
break ;
1
+ − 43
140
+ − 44
case "CNAME" :
+ − 45
if ( ! is_valid_rr_cname_name ( $name )) return false ;
+ − 46
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
+ − 47
break ;
1
+ − 48
140
+ − 49
case "HINFO" :
+ − 50
if ( ! is_valid_rr_hinfo_content ( $content )) return false ;
+ − 51
break ;
+ − 52
+ − 53
case "MX" :
+ − 54
if ( ! is_valid_hostname_fqdn ( $contenti , 0 )) return false ;
+ − 55
if ( ! is_valid_mx_or_ns_target ( $content )) return false ;
+ − 56
break ;
1
+ − 57
140
+ − 58
case "NS" :
+ − 59
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
+ − 60
if ( ! is_valid_mx_or_ns_target ( $content )) return false ;
+ − 61
break ;
+ − 62
+ − 63
case "PTR" :
+ − 64
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
+ − 65
break ;
+ − 66
+ − 67
case "SOA" :
+ − 68
if ( ! is_valid_rr_soa_name ( $name , $zone )) return false ;
+ − 69
if ( ! is_valid_rr_soa_content ( $content )) return false ;
+ − 70
break ;
1
+ − 71
140
+ − 72
case "TXT" :
+ − 73
if ( ! is_valid_rr_txt_content ( $content )) return false ;
+ − 74
break ;
+ − 75
+ − 76
case "MBOXFW" :
+ − 77
case "NAPTR" :
+ − 78
case "URL" :
+ − 79
// These types are supported by PowerDNS, but there is not
+ − 80
// yet code for validation. Validation needs to be added
+ − 81
// for these types. One Day Real Soon Now. [tm]
+ − 82
break ;
+ − 83
+ − 84
default :
+ − 85
error ( ERR_DNS_RR_TYPE );
82
+ − 86
return false ;
1
+ − 87
}
+ − 88
140
+ − 89
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
+ − 90
if ( ! is_valid_rr_prio ( $prio , $type )) return false ;
+ − 91
if ( ! is_valid_rr_ttl ( $ttl )) return false ;
1
+ − 92
+ − 93
return true ;
+ − 94
}
+ − 95
140
+ − 96
function is_valid_hostname_fqdn ( $hostname , $wildcard ) {
1
+ − 97
138
+ − 98
global $dns_strict_tld_check ;
+ − 99
global $valid_tlds ;
+ − 100
+ − 101
$hostname = ereg_replace ( "\.$" , "" , $hostname );
1
+ − 102
138
+ − 103
if ( strlen ( $hostname ) > 255 ) {
+ − 104
error ( ERR_DNS_HN_TOO_LONG );
+ − 105
return false ;
+ − 106
}
+ − 107
+ − 108
$hostname_labels = explode ( '.' , $hostname );
+ − 109
$label_count = count ( $hostname_labels );
+ − 110
140
+ − 111
foreach ( $hostname_labels as $hostname_label ) {
+ − 112
if ( $wildcard == 1 && ! isset ( $first )) {
+ − 113
if ( ! preg_match ( '/^(\*|[\w-\/]+)$/' , $hostname_label )) { error ( ERR_DNS_HN_INV_CHARS ); return false ; }
+ − 114
$first = 1 ;
+ − 115
} else {
+ − 116
if ( ! preg_match ( '/^[\w-\/]+$/' , $hostname_label )) { error ( ERR_DNS_HN_INV_CHARS ); return false ; }
+ − 117
}
+ − 118
if ( substr ( $hostname_label , 0 , 1 ) == "-" ) { error ( ERR_DNS_HN_DASH ); return false ; }
+ − 119
if ( substr ( $hostname_label , - 1 , 1 ) == "-" ) { error ( ERR_DNS_HN_DASH ); return false ; }
+ − 120
if ( strlen ( $hostname_label ) < 1 || strlen ( $hostname_label ) > 63 ) { error ( ERR_DNS_HN_LENGTH ); return false ; }
+ − 121
}
+ − 122
+ − 123
if ( $hostname_labels [ $label_count - 1 ] == "arpa" && ( substr_count ( $hostname_labels [ 0 ], "/" ) == 1 XOR substr_count ( $hostname_labels [ 1 ], "/" ) == 1 )) {
+ − 124
if ( substr_count ( $hostname_labels [ 0 ], "/" ) == 1 ) {
+ − 125
$array = explode ( "/" , $hostname_labels [ 0 ]);
+ − 126
} else {
+ − 127
$array = explode ( "/" , $hostname_labels [ 1 ]);
+ − 128
}
+ − 129
if ( count ( $array ) != 2 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 130
if ( ! is_numeric ( $array [ 0 ]) || $array [ 0 ] < 0 || $array [ 0 ] > 255 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 131
if ( ! is_numeric ( $array [ 1 ]) || $array [ 1 ] < 25 || $array [ 1 ] > 31 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 132
} else {
+ − 133
if ( substr_count ( $hostname , "/" ) > 0 ) { error ( ERR_DNS_HN_SLASH ) ; return false ; }
+ − 134
}
+ − 135
138
+ − 136
if ( $dns_strict_tld_check == "1" && ! in_array ( $hostname_labels [ $label_count - 1 ], $valid_tlds )) {
140
+ − 137
error ( ERR_DNS_INV_TLD ); return false ;
1
+ − 138
}
+ − 139
140
+ − 140
return true ;
+ − 141
}
+ − 142
+ − 143
function is_valid_ipv4 ( $ipv4 ) {
+ − 144
+ − 145
// 20080424/RZ: The current code may be replaced by the following if()
+ − 146
// statement, but it will raise the required PHP version to ">= 5.2.0".
+ − 147
// Not sure if we want that now.
+ − 148
//
+ − 149
// if(filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
+ − 150
// error(ERR_DNS_IPV4); return false;
+ − 151
// }
+ − 152
+ − 153
if ( preg_match ( "/^[0-9\.]{7,15}$/" , $ipv4 )) {
+ − 154
error ( ERR_DNS_IPV4 ); return false ;
+ − 155
}
+ − 156
+ − 157
$quads = explode ( '.' , $ipv4 );
+ − 158
$numquads = count ( $quads );
+ − 159
+ − 160
if ( $numquads != 4 ) {
+ − 161
error ( ERR_DNS_IPV4 ); return false ;
+ − 162
}
+ − 163
+ − 164
for ( $i = 0 ; $i < 4 ; $i ++ ) {
+ − 165
if ( $quads [ $i ] > 255 ) {
+ − 166
error ( ERR_DNS_IPV4 ); return false ;
138
+ − 167
}
+ − 168
}
140
+ − 169
138
+ − 170
return true ;
+ − 171
}
+ − 172
140
+ − 173
function is_valid_ipv6 ( $ipv6 ) {
+ − 174
+ − 175
// 20080424/RZ: The current code may be replaced by the following if()
+ − 176
// statement, but it will raise the required PHP version to ">= 5.2.0".
+ − 177
// Not sure if we want that now.
+ − 178
//
+ − 179
// if(filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === FALSE) {
+ − 180
// error(ERR_DNS_IPV6); return false;
+ − 181
// }
+ − 182
+ − 183
if ( preg_match ( "/^[0-9a-f]{0,4}:([0-9a-f]{0,4}:){0,6}[0-9a-f]{0,4}$/i" , $ipv6 )) {
+ − 184
error ( ERR_DNS_IPV6 ); return false ;
+ − 185
}
+ − 186
+ − 187
$quads = explode ( ':' , $ipv6 );
+ − 188
$numquads = count ( $quads );
+ − 189
+ − 190
if ( $numquads > 8 || $numquads < 3 ) {
+ − 191
error ( ERR_DNS_IPV6 ); return false ;
+ − 192
}
+ − 193
+ − 194
$emptyquads = 0 ;
+ − 195
for ( $i = 1 ; $i < $numquads - 1 ; $i ++ ) {
+ − 196
if ( $quads [ $i ] == "" ) $emptyquads ++ ;
+ − 197
}
+ − 198
+ − 199
if ( $emptyquads > 1 ) {
+ − 200
error ( ERR_DNS_IPV6 ); return false ;
+ − 201
}
+ − 202
+ − 203
if ( $emptyquads == 0 && $numquads != 8 ) {
+ − 204
error ( ERR_DNS_IPV6 ); return false ;
+ − 205
}
+ − 206
+ − 207
return true ;
+ − 208
}
+ − 209
+ − 210
function is_valid_rr_cname_name ( $name ) {
+ − 211
global $db ;
+ − 212
+ − 213
$query = "SELECT type, content
+ − 214
FROM records
+ − 215
WHERE content = " . $db -> quote ( $name ) . "
+ − 216
AND (type = 'MX' OR type = 'NS')" ;
+ − 217
+ − 218
$response = $db -> query ( $query );
+ − 219
if ( PEAR :: isError ( $response )) { error ( $response -> getMessage ()); return false ; };
1
+ − 220
140
+ − 221
if ( $response -> numRows () > 0 ) {
+ − 222
error ( ERR_DNS_CNAME ); return false ;
+ − 223
}
+ − 224
+ − 225
return true ;
+ − 226
}
+ − 227
+ − 228
function is_valid_mx_or_ns_target ( $content ) {
+ − 229
global $db ;
+ − 230
+ − 231
$query = "SELECT type, name
+ − 232
FROM records
+ − 233
WHERE name = " . $db -> quote ( $content ) . "
+ − 234
AND TYPE = 'CNAME'" ;
+ − 235
+ − 236
$response = $db -> query ( $query );
+ − 237
if ( PEAR :: isError ( $response )) { error ( $response -> getMessage ()); return false ; };
+ − 238
+ − 239
if ( $response -> numRows () > 0 ) {
+ − 240
error ( ERR_DNS_MX_NS_TO_CNAME ); return false ;
+ − 241
}
+ − 242
+ − 243
return true ;
+ − 244
}
+ − 245
+ − 246
function is_valid_rr_txt_content ( $content ) {
+ − 247
+ − 248
if ( ! preg_match ( "/^([^\s]{1,1000}| \" ([^ \" ]{1,998} \" ))$/i" , $content )) {
+ − 249
error ( ERR_DNS_TXT_INV_CONTENT ); return false ;
+ − 250
}
+ − 251
+ − 252
return true ;
+ − 253
}
+ − 254
+ − 255
function is_valid_rr_hinfo_content ( $content ) {
+ − 256
+ − 257
if ( $content [ 0 ] == " \" " ) {
+ − 258
$fields = preg_split ( '/(?<=") /' , $content , 2 );
+ − 259
} else {
+ − 260
$fields = preg_split ( '/ /' , $content , 2 );
+ − 261
}
+ − 262
+ − 263
for ( $i = 0 ; ( $i < 2 ); $i ++ ) {
+ − 264
if ( ! preg_match ( "/^([^\s]{1,1000}| \" ([^ \" ]{1,998} \" )$/i" , $fields [ $i ])) {
+ − 265
error ( ERR_DNS_HINFO_INV_CONTENT ); return false ;
+ − 266
}
+ − 267
}
+ − 268
+ − 269
return true ;
+ − 270
}
+ − 271
+ − 272
function is_valid_rr_soa_content ( & $content ) {
138
+ − 273
+ − 274
$fields = preg_split ( "/\s+/" , trim ( $content ));
+ − 275
$field_count = count ( $fields );
+ − 276
+ − 277
if ( $field_count == 0 || $field_count > 7 ) {
+ − 278
return false ;
+ − 279
} else {
+ − 280
if ( ! is_valid_hostname_fqdn ( $fields [ 0 ]) || preg_match ( '/\.arpa\.?$/' , $fields [ 0 ])) {
+ − 281
return false ;
+ − 282
}
+ − 283
$final_soa = $fields [ 0 ];
121
+ − 284
138
+ − 285
if ( isset ( $fields [ 1 ])) {
+ − 286
$addr_input = $fields [ 1 ];
+ − 287
} else {
+ − 288
global $dns_hostmaster ;
+ − 289
$addr_input = $dns_hostmaster ;
+ − 290
}
+ − 291
if ( ! preg_match ( "/@/" , $addr_input )) {
+ − 292
$addr_input = preg_split ( '/(?<!\\\)\./' , $addr_input , 2 );
+ − 293
$addr_to_check = str_replace ( " \\ " , "" , $addr_input [ 0 ]) . "@" . $addr_input [ 1 ];
+ − 294
} else {
+ − 295
$addr_to_check = $addr_input ;
+ − 296
}
+ − 297
+ − 298
if ( ! is_valid_email ( $addr_to_check )) {
+ − 299
return false ;
+ − 300
} else {
+ − 301
$addr_final = explode ( '@' , $addr_to_check , 2 );
+ − 302
$final_soa .= " " . str_replace ( "." , " \\ ." , $addr_final [ 0 ]) . "." . $addr_final [ 1 ];
+ − 303
}
+ − 304
+ − 305
if ( isset ( $fields [ 2 ])) {
+ − 306
if ( ! is_numeric ( $fields [ 2 ])) {
+ − 307
return false ;
1
+ − 308
}
138
+ − 309
$final_soa .= " " . $fields [ 2 ];
+ − 310
} else {
+ − 311
$final_soa .= " 0" ;
+ − 312
}
+ − 313
+ − 314
if ( $field_count == 7 ) {
+ − 315
for ( $i = 3 ; ( $i < 7 ); $i ++ ) {
+ − 316
if ( ! is_numeric ( $fields [ $i ])) {
+ − 317
return false ;
121
+ − 318
} else {
138
+ − 319
$final_soa .= " " . $fields [ $i ];
1
+ − 320
}
+ − 321
}
+ − 322
}
+ − 323
}
138
+ − 324
$content = $final_soa ;
+ − 325
return true ;
1
+ − 326
}
+ − 327
140
+ − 328
function is_valid_rr_soa_name ( $name , $zone ) {
+ − 329
if ( $name != $zone ) {
+ − 330
error ( ERR_DNS_SOA_NAME ); return false ;
+ − 331
}
+ − 332
return true ;
1
+ − 333
}
+ − 334
140
+ − 335
function is_valid_rr_prio ( & $prio , $type ) {
+ − 336
+ − 337
if ( $type == "MX" ) {
+ − 338
if ( ! is_numeric ( $prio ) || $prio < 0 || $prio > 65535 ) {
+ − 339
error ( ERR_DNS_INV_PRIO ); return false ;
+ − 340
}
+ − 341
} else {
+ − 342
$prio = "" ;
+ − 343
}
+ − 344
+ − 345
return true ;
+ − 346
}
+ − 347
+ − 348
function is_valid_rr_ttl ( & $ttl ) {
+ − 349
+ − 350
if ( ! isset ( $ttl ) || $ttl == "" ) {
+ − 351
global $dns_ttl ;
+ − 352
$ttl = $dns_ttl ;
+ − 353
}
+ − 354
+ − 355
if ( ! is_numeric ( $ttl ) || $prio < 0 || $prio > 2147483647 ) {
+ − 356
error ( ERR_DNS_INV_TTL ); return false ;
+ − 357
}
+ − 358
+ − 359
return true ;
+ − 360
}
+ − 361
+ − 362
function is_valid_search ( $holygrail ) {
+ − 363
62
+ − 364
// Only allow for alphanumeric, numeric, dot, dash, underscore and
+ − 365
// percent in search string. The last two are wildcards for SQL.
+ − 366
// Needs extension probably for more usual record types.
+ − 367
+ − 368
return preg_match ( '/^[a-z0-9.\-%_]+$/i' , $holygrail );
+ − 369
}
+ − 370
1
+ − 371
?>