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 ;
164
+ − 38
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 39
break ;
+ − 40
+ − 41
case "AAAA" :
+ − 42
if ( ! is_valid_ipv6 ( $content )) return false ;
164
+ − 43
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 44
break ;
1
+ − 45
140
+ − 46
case "CNAME" :
+ − 47
if ( ! is_valid_rr_cname_name ( $name )) return false ;
164
+ − 48
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 49
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
+ − 50
break ;
1
+ − 51
140
+ − 52
case "HINFO" :
+ − 53
if ( ! is_valid_rr_hinfo_content ( $content )) return false ;
164
+ − 54
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 55
break ;
+ − 56
+ − 57
case "MX" :
158
+ − 58
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
164
+ − 59
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
+ − 60
if ( ! is_valid_non_alias_target ( $content )) return false ;
140
+ − 61
break ;
1
+ − 62
140
+ − 63
case "NS" :
+ − 64
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
164
+ − 65
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
+ − 66
if ( ! is_valid_non_alias_target ( $content )) return false ;
140
+ − 67
break ;
+ − 68
+ − 69
case "PTR" :
+ − 70
if ( ! is_valid_hostname_fqdn ( $content , 0 )) return false ;
164
+ − 71
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 72
break ;
+ − 73
+ − 74
case "SOA" :
+ − 75
if ( ! is_valid_rr_soa_name ( $name , $zone )) return false ;
164
+ − 76
if ( ! is_valid_hostname_fqdn ( $name , 1 )) return false ;
140
+ − 77
if ( ! is_valid_rr_soa_content ( $content )) return false ;
+ − 78
break ;
164
+ − 79
+ − 80
case "SRV" :
+ − 81
if ( ! is_valid_rr_srv_name ( $name )) return false ;
+ − 82
if ( ! is_valid_rr_srv_content ( $content )) return false ;
+ − 83
break ;
1
+ − 84
140
+ − 85
case "TXT" :
164
+ − 86
if ( ! is_valid_printable ( $name )) return false ;
+ − 87
if ( ! is_valid_printable ( $content )) return false ;
140
+ − 88
break ;
+ − 89
+ − 90
case "MBOXFW" :
+ − 91
case "NAPTR" :
+ − 92
case "URL" :
+ − 93
// These types are supported by PowerDNS, but there is not
+ − 94
// yet code for validation. Validation needs to be added
+ − 95
// for these types. One Day Real Soon Now. [tm]
+ − 96
break ;
+ − 97
+ − 98
default :
+ − 99
error ( ERR_DNS_RR_TYPE );
82
+ − 100
return false ;
1
+ − 101
}
+ − 102
140
+ − 103
if ( ! is_valid_rr_prio ( $prio , $type )) return false ;
+ − 104
if ( ! is_valid_rr_ttl ( $ttl )) return false ;
1
+ − 105
+ − 106
return true ;
+ − 107
}
+ − 108
140
+ − 109
function is_valid_hostname_fqdn ( $hostname , $wildcard ) {
1
+ − 110
138
+ − 111
global $dns_strict_tld_check ;
+ − 112
global $valid_tlds ;
+ − 113
+ − 114
$hostname = ereg_replace ( "\.$" , "" , $hostname );
1
+ − 115
138
+ − 116
if ( strlen ( $hostname ) > 255 ) {
+ − 117
error ( ERR_DNS_HN_TOO_LONG );
+ − 118
return false ;
+ − 119
}
+ − 120
+ − 121
$hostname_labels = explode ( '.' , $hostname );
+ − 122
$label_count = count ( $hostname_labels );
+ − 123
140
+ − 124
foreach ( $hostname_labels as $hostname_label ) {
+ − 125
if ( $wildcard == 1 && ! isset ( $first )) {
+ − 126
if ( ! preg_match ( '/^(\*|[\w-\/]+)$/' , $hostname_label )) { error ( ERR_DNS_HN_INV_CHARS ); return false ; }
+ − 127
$first = 1 ;
+ − 128
} else {
+ − 129
if ( ! preg_match ( '/^[\w-\/]+$/' , $hostname_label )) { error ( ERR_DNS_HN_INV_CHARS ); return false ; }
+ − 130
}
+ − 131
if ( substr ( $hostname_label , 0 , 1 ) == "-" ) { error ( ERR_DNS_HN_DASH ); return false ; }
+ − 132
if ( substr ( $hostname_label , - 1 , 1 ) == "-" ) { error ( ERR_DNS_HN_DASH ); return false ; }
+ − 133
if ( strlen ( $hostname_label ) < 1 || strlen ( $hostname_label ) > 63 ) { error ( ERR_DNS_HN_LENGTH ); return false ; }
+ − 134
}
+ − 135
+ − 136
if ( $hostname_labels [ $label_count - 1 ] == "arpa" && ( substr_count ( $hostname_labels [ 0 ], "/" ) == 1 XOR substr_count ( $hostname_labels [ 1 ], "/" ) == 1 )) {
+ − 137
if ( substr_count ( $hostname_labels [ 0 ], "/" ) == 1 ) {
+ − 138
$array = explode ( "/" , $hostname_labels [ 0 ]);
+ − 139
} else {
+ − 140
$array = explode ( "/" , $hostname_labels [ 1 ]);
+ − 141
}
+ − 142
if ( count ( $array ) != 2 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 143
if ( ! is_numeric ( $array [ 0 ]) || $array [ 0 ] < 0 || $array [ 0 ] > 255 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 144
if ( ! is_numeric ( $array [ 1 ]) || $array [ 1 ] < 25 || $array [ 1 ] > 31 ) { error ( ERR_DNS_HOSTNAME ) ; return false ; }
+ − 145
} else {
+ − 146
if ( substr_count ( $hostname , "/" ) > 0 ) { error ( ERR_DNS_HN_SLASH ) ; return false ; }
+ − 147
}
+ − 148
138
+ − 149
if ( $dns_strict_tld_check == "1" && ! in_array ( $hostname_labels [ $label_count - 1 ], $valid_tlds )) {
140
+ − 150
error ( ERR_DNS_INV_TLD ); return false ;
1
+ − 151
}
+ − 152
140
+ − 153
return true ;
+ − 154
}
+ − 155
+ − 156
function is_valid_ipv4 ( $ipv4 ) {
+ − 157
+ − 158
// 20080424/RZ: The current code may be replaced by the following if()
+ − 159
// statement, but it will raise the required PHP version to ">= 5.2.0".
+ − 160
// Not sure if we want that now.
+ − 161
//
+ − 162
// if(filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === FALSE) {
+ − 163
// error(ERR_DNS_IPV4); return false;
+ − 164
// }
+ − 165
162
+ − 166
if ( ! preg_match ( "/^[0-9\.]{7,15}$/" , $ipv4 )) {
140
+ − 167
error ( ERR_DNS_IPV4 ); return false ;
+ − 168
}
+ − 169
+ − 170
$quads = explode ( '.' , $ipv4 );
+ − 171
$numquads = count ( $quads );
+ − 172
+ − 173
if ( $numquads != 4 ) {
+ − 174
error ( ERR_DNS_IPV4 ); return false ;
+ − 175
}
+ − 176
+ − 177
for ( $i = 0 ; $i < 4 ; $i ++ ) {
+ − 178
if ( $quads [ $i ] > 255 ) {
+ − 179
error ( ERR_DNS_IPV4 ); return false ;
138
+ − 180
}
+ − 181
}
140
+ − 182
138
+ − 183
return true ;
+ − 184
}
+ − 185
140
+ − 186
function is_valid_ipv6 ( $ipv6 ) {
+ − 187
+ − 188
// 20080424/RZ: The current code may be replaced by the following if()
+ − 189
// statement, but it will raise the required PHP version to ">= 5.2.0".
+ − 190
// Not sure if we want that now.
+ − 191
//
+ − 192
// if(filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === FALSE) {
+ − 193
// error(ERR_DNS_IPV6); return false;
+ − 194
// }
+ − 195
162
+ − 196
if ( ! preg_match ( "/^[0-9a-f]{0,4}:([0-9a-f]{0,4}:){0,6}[0-9a-f]{0,4}$/i" , $ipv6 )) {
140
+ − 197
error ( ERR_DNS_IPV6 ); return false ;
+ − 198
}
+ − 199
+ − 200
$quads = explode ( ':' , $ipv6 );
+ − 201
$numquads = count ( $quads );
+ − 202
+ − 203
if ( $numquads > 8 || $numquads < 3 ) {
+ − 204
error ( ERR_DNS_IPV6 ); return false ;
+ − 205
}
+ − 206
+ − 207
$emptyquads = 0 ;
+ − 208
for ( $i = 1 ; $i < $numquads - 1 ; $i ++ ) {
+ − 209
if ( $quads [ $i ] == "" ) $emptyquads ++ ;
+ − 210
}
+ − 211
+ − 212
if ( $emptyquads > 1 ) {
+ − 213
error ( ERR_DNS_IPV6 ); return false ;
+ − 214
}
+ − 215
+ − 216
if ( $emptyquads == 0 && $numquads != 8 ) {
+ − 217
error ( ERR_DNS_IPV6 ); return false ;
+ − 218
}
+ − 219
+ − 220
return true ;
+ − 221
}
+ − 222
164
+ − 223
function is_valid_printable ( $string ) {
+ − 224
if ( ! ereg ( '^[[:print:]]+$' , trim ( $string ))) { error ( ERR_DNS_PRINTABLE ); return false ; }
+ − 225
return true ;
+ − 226
}
+ − 227
140
+ − 228
function is_valid_rr_cname_name ( $name ) {
+ − 229
global $db ;
+ − 230
+ − 231
$query = "SELECT type, content
+ − 232
FROM records
+ − 233
WHERE content = " . $db -> quote ( $name ) . "
+ − 234
AND (type = 'MX' OR type = 'NS')" ;
+ − 235
+ − 236
$response = $db -> query ( $query );
+ − 237
if ( PEAR :: isError ( $response )) { error ( $response -> getMessage ()); return false ; };
1
+ − 238
140
+ − 239
if ( $response -> numRows () > 0 ) {
+ − 240
error ( ERR_DNS_CNAME ); return false ;
+ − 241
}
+ − 242
+ − 243
return true ;
+ − 244
}
+ − 245
164
+ − 246
function is_valid_non_alias_target ( $target ) {
140
+ − 247
global $db ;
+ − 248
+ − 249
$query = "SELECT type, name
+ − 250
FROM records
164
+ − 251
WHERE name = " . $db -> quote ( $target ) . "
140
+ − 252
AND TYPE = 'CNAME'" ;
+ − 253
+ − 254
$response = $db -> query ( $query );
+ − 255
if ( PEAR :: isError ( $response )) { error ( $response -> getMessage ()); return false ; };
+ − 256
if ( $response -> numRows () > 0 ) {
167
+ − 257
error ( ERR_DNS_NON_ALIAS_TARGET ); return false ;
140
+ − 258
}
+ − 259
return true ;
+ − 260
}
+ − 261
+ − 262
function is_valid_rr_hinfo_content ( $content ) {
+ − 263
+ − 264
if ( $content [ 0 ] == " \" " ) {
+ − 265
$fields = preg_split ( '/(?<=") /' , $content , 2 );
+ − 266
} else {
+ − 267
$fields = preg_split ( '/ /' , $content , 2 );
+ − 268
}
+ − 269
+ − 270
for ( $i = 0 ; ( $i < 2 ); $i ++ ) {
+ − 271
if ( ! preg_match ( "/^([^\s]{1,1000}| \" ([^ \" ]{1,998} \" )$/i" , $fields [ $i ])) {
+ − 272
error ( ERR_DNS_HINFO_INV_CONTENT ); return false ;
+ − 273
}
+ − 274
}
+ − 275
+ − 276
return true ;
+ − 277
}
+ − 278
+ − 279
function is_valid_rr_soa_content ( & $content ) {
138
+ − 280
+ − 281
$fields = preg_split ( "/\s+/" , trim ( $content ));
+ − 282
$field_count = count ( $fields );
+ − 283
+ − 284
if ( $field_count == 0 || $field_count > 7 ) {
+ − 285
return false ;
+ − 286
} else {
173
+ − 287
if ( ! is_valid_hostname_fqdn ( $fields [ 0 ], 0 ) || preg_match ( '/\.arpa\.?$/' , $fields [ 0 ])) {
138
+ − 288
return false ;
+ − 289
}
+ − 290
$final_soa = $fields [ 0 ];
121
+ − 291
138
+ − 292
if ( isset ( $fields [ 1 ])) {
+ − 293
$addr_input = $fields [ 1 ];
+ − 294
} else {
+ − 295
global $dns_hostmaster ;
+ − 296
$addr_input = $dns_hostmaster ;
+ − 297
}
+ − 298
if ( ! preg_match ( "/@/" , $addr_input )) {
+ − 299
$addr_input = preg_split ( '/(?<!\\\)\./' , $addr_input , 2 );
+ − 300
$addr_to_check = str_replace ( " \\ " , "" , $addr_input [ 0 ]) . "@" . $addr_input [ 1 ];
+ − 301
} else {
+ − 302
$addr_to_check = $addr_input ;
+ − 303
}
+ − 304
+ − 305
if ( ! is_valid_email ( $addr_to_check )) {
+ − 306
return false ;
+ − 307
} else {
+ − 308
$addr_final = explode ( '@' , $addr_to_check , 2 );
+ − 309
$final_soa .= " " . str_replace ( "." , " \\ ." , $addr_final [ 0 ]) . "." . $addr_final [ 1 ];
+ − 310
}
+ − 311
+ − 312
if ( isset ( $fields [ 2 ])) {
+ − 313
if ( ! is_numeric ( $fields [ 2 ])) {
+ − 314
return false ;
1
+ − 315
}
138
+ − 316
$final_soa .= " " . $fields [ 2 ];
+ − 317
} else {
+ − 318
$final_soa .= " 0" ;
+ − 319
}
+ − 320
+ − 321
if ( $field_count == 7 ) {
+ − 322
for ( $i = 3 ; ( $i < 7 ); $i ++ ) {
+ − 323
if ( ! is_numeric ( $fields [ $i ])) {
+ − 324
return false ;
121
+ − 325
} else {
138
+ − 326
$final_soa .= " " . $fields [ $i ];
1
+ − 327
}
+ − 328
}
+ − 329
}
+ − 330
}
138
+ − 331
$content = $final_soa ;
+ − 332
return true ;
1
+ − 333
}
+ − 334
140
+ − 335
function is_valid_rr_soa_name ( $name , $zone ) {
+ − 336
if ( $name != $zone ) {
+ − 337
error ( ERR_DNS_SOA_NAME ); return false ;
+ − 338
}
+ − 339
return true ;
1
+ − 340
}
+ − 341
140
+ − 342
function is_valid_rr_prio ( & $prio , $type ) {
164
+ − 343
if ( $type == "MX" || $type == "SRV" ) {
140
+ − 344
if ( ! is_numeric ( $prio ) || $prio < 0 || $prio > 65535 ) {
+ − 345
error ( ERR_DNS_INV_PRIO ); return false ;
+ − 346
}
+ − 347
} else {
+ − 348
$prio = "" ;
+ − 349
}
+ − 350
+ − 351
return true ;
+ − 352
}
+ − 353
164
+ − 354
function is_valid_rr_srv_name ( $name ){
186
+ − 355
+ − 356
if ( strlen ( $name ) > 255 ) {
+ − 357
error ( ERR_DNS_HN_TOO_LONG );
+ − 358
return false ;
+ − 359
}
+ − 360
164
+ − 361
$fields = explode ( '.' , $name , 3 );
186
+ − 362
if ( ! preg_match ( '/^_[\w-]+$/i' , $fields [ 0 ])) { error ( ERR_DNS_SRV_NAME ) ; return false ; }
+ − 363
if ( ! preg_match ( '/^_[\w]+$/i' , $fields [ 1 ])) { error ( ERR_DNS_SRV_NAME ) ; return false ; }
164
+ − 364
if ( ! is_valid_hostname_fqdn ( $fields [ 2 ], 0 )) { error ( ERR_DNS_SRV_NAME ) ; return false ; }
+ − 365
return true ;
+ − 366
}
+ − 367
+ − 368
function is_valid_rr_srv_content ( $content ) {
+ − 369
$fields = preg_split ( "/\s+/" , trim ( $content ), 3 );
+ − 370
if ( ! is_numeric ( $fields [ 0 ]) || $fields [ 0 ] < 0 || $fields [ 0 ] > 65535 ) { error ( ERR_DNS_SRV_WGHT ) ; return false ; }
+ − 371
if ( ! is_numeric ( $fields [ 1 ]) || $fields [ 1 ] < 0 || $fields [ 1 ] > 65535 ) { error ( ERR_DNS_SRV_PORT ) ; return false ; }
+ − 372
if ( $fields [ 2 ] == "" || ( $fields [ 2 ] != "." && ! is_valid_hostname_fqdn ( $fields [ 2 ], 0 ))) {
+ − 373
error ( ERR_DNS_SRV_TRGT ) ; return false ;
+ − 374
}
+ − 375
return true ;
+ − 376
}
+ − 377
140
+ − 378
function is_valid_rr_ttl ( & $ttl ) {
+ − 379
+ − 380
if ( ! isset ( $ttl ) || $ttl == "" ) {
+ − 381
global $dns_ttl ;
+ − 382
$ttl = $dns_ttl ;
+ − 383
}
+ − 384
182
+ − 385
if ( ! is_numeric ( $ttl ) || $ttl < 0 || $ttl > 2147483647 ) {
140
+ − 386
error ( ERR_DNS_INV_TTL ); return false ;
+ − 387
}
+ − 388
+ − 389
return true ;
+ − 390
}
+ − 391
+ − 392
function is_valid_search ( $holygrail ) {
+ − 393
62
+ − 394
// Only allow for alphanumeric, numeric, dot, dash, underscore and
+ − 395
// percent in search string. The last two are wildcards for SQL.
+ − 396
// Needs extension probably for more usual record types.
+ − 397
+ − 398
return preg_match ( '/^[a-z0-9.\-%_]+$/i' , $holygrail );
+ − 399
}
+ − 400
1
+ − 401
?>