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