1/* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18%{ 19#include <stdio.h> 20#include <stdlib.h> 21#include <string.h> 22#include "mDNSEmbeddedAPI.h" 23#include "DebugServices.h" 24#include "dnsextd.h" 25 26void yyerror( const char* error ); 27int yylex(void); 28 29 30typedef struct StringListElem 31{ 32 char * string; 33 struct StringListElem * next; 34} StringListElem; 35 36 37typedef struct OptionsInfo 38{ 39 char server_address[ 256 ]; 40 int server_port; 41 char source_address[ 256 ]; 42 int source_port; 43 int private_port; 44 int llq_port; 45} OptionsInfo; 46 47 48typedef struct ZoneInfo 49{ 50 char name[ 256 ]; 51 char certificate_name[ 256 ]; 52 char allow_clients_file[ 256 ]; 53 char allow_clients[ 256 ]; 54 char key[ 256 ]; 55} ZoneInfo; 56 57 58typedef struct KeySpec 59{ 60 char name[ 256 ]; 61 char algorithm[ 256 ]; 62 char secret[ 256 ]; 63 struct KeySpec * next; 64} KeySpec; 65 66 67typedef struct ZoneSpec 68{ 69 char name[ 256 ]; 70 DNSZoneSpecType type; 71 StringListElem * allowUpdate; 72 StringListElem * allowQuery; 73 char key[ 256 ]; 74 struct ZoneSpec * next; 75} ZoneSpec; 76 77 78static StringListElem * g_stringList = NULL; 79static KeySpec * g_keys; 80static ZoneSpec * g_zones; 81static ZoneSpec g_zoneSpec; 82static const char * g_filename; 83 84#define YYPARSE_PARAM context 85 86void 87SetupOptions 88 ( 89 OptionsInfo * info, 90 void * context 91 ); 92 93%} 94 95%union 96{ 97 int number; 98 char * string; 99} 100 101%token OPTIONS 102%token LISTEN_ON 103%token NAMESERVER 104%token PORT 105%token ADDRESS 106%token LLQ 107%token PUBLIC 108%token PRIVATE 109%token ALLOWUPDATE 110%token ALLOWQUERY 111%token KEY 112%token ALGORITHM 113%token SECRET 114%token ISSUER 115%token SERIAL 116%token ZONE 117%token TYPE 118%token ALLOW 119%token OBRACE 120%token EBRACE 121%token SEMICOLON 122%token IN 123%token <string> DOTTED_DECIMAL_ADDRESS 124%token <string> WILDCARD 125%token <string> DOMAINNAME 126%token <string> HOSTNAME 127%token <string> QUOTEDSTRING 128%token <number> NUMBER 129 130%type <string> addressstatement 131%type <string> networkaddress 132 133%% 134 135commands: 136 | 137 commands command SEMICOLON 138 ; 139 140 141command: 142 options_set 143 | 144 zone_set 145 | 146 key_set 147 ; 148 149 150options_set: 151 OPTIONS optionscontent 152 { 153 // SetupOptions( &g_optionsInfo, context ); 154 } 155 ; 156 157optionscontent: 158 OBRACE optionsstatements EBRACE 159 ; 160 161optionsstatements: 162 | 163 optionsstatements optionsstatement SEMICOLON 164 ; 165 166 167optionsstatement: 168 statements 169 | 170 LISTEN_ON addresscontent 171 { 172 } 173 | 174 LISTEN_ON PORT NUMBER addresscontent 175 { 176 } 177 | 178 NAMESERVER ADDRESS networkaddress 179 { 180 } 181 | 182 NAMESERVER ADDRESS networkaddress PORT NUMBER 183 { 184 } 185 | 186 PRIVATE PORT NUMBER 187 { 188 ( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( $3 ); 189 } 190 | 191 LLQ PORT NUMBER 192 { 193 ( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( $3 ); 194 } 195 ; 196 197key_set: 198 KEY QUOTEDSTRING OBRACE SECRET QUOTEDSTRING SEMICOLON EBRACE 199 { 200 KeySpec * keySpec; 201 202 keySpec = ( KeySpec* ) malloc( sizeof( KeySpec ) ); 203 204 if ( !keySpec ) 205 { 206 LogMsg("ERROR: memory allocation failure"); 207 YYABORT; 208 } 209 210 strncpy( keySpec->name, $2, sizeof( keySpec->name ) ); 211 strncpy( keySpec->secret, $5, sizeof( keySpec->secret ) ); 212 213 keySpec->next = g_keys; 214 g_keys = keySpec; 215 } 216 ; 217 218zone_set: 219 ZONE QUOTEDSTRING zonecontent 220 { 221 ZoneSpec * zoneSpec; 222 223 zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) ); 224 225 if ( !zoneSpec ) 226 { 227 LogMsg("ERROR: memory allocation failure"); 228 YYABORT; 229 } 230 231 strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) ); 232 zoneSpec->type = g_zoneSpec.type; 233 strcpy( zoneSpec->key, g_zoneSpec.key ); 234 zoneSpec->allowUpdate = g_zoneSpec.allowUpdate; 235 zoneSpec->allowQuery = g_zoneSpec.allowQuery; 236 237 zoneSpec->next = g_zones; 238 g_zones = zoneSpec; 239 } 240 | 241 ZONE QUOTEDSTRING IN zonecontent 242 { 243 ZoneSpec * zoneSpec; 244 245 zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) ); 246 247 if ( !zoneSpec ) 248 { 249 LogMsg("ERROR: memory allocation failure"); 250 YYABORT; 251 } 252 253 strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) ); 254 zoneSpec->type = g_zoneSpec.type; 255 strcpy( zoneSpec->key, g_zoneSpec.key ); 256 zoneSpec->allowUpdate = g_zoneSpec.allowUpdate; 257 zoneSpec->allowQuery = g_zoneSpec.allowQuery; 258 259 zoneSpec->next = g_zones; 260 g_zones = zoneSpec; 261 } 262 ; 263 264zonecontent: 265 OBRACE zonestatements EBRACE 266 267zonestatements: 268 | 269 zonestatements zonestatement SEMICOLON 270 ; 271 272zonestatement: 273 TYPE PUBLIC 274 { 275 g_zoneSpec.type = kDNSZonePublic; 276 } 277 | 278 TYPE PRIVATE 279 { 280 g_zoneSpec.type = kDNSZonePrivate; 281 } 282 | 283 ALLOWUPDATE keycontent 284 { 285 g_zoneSpec.allowUpdate = g_stringList; 286 g_stringList = NULL; 287 } 288 | 289 ALLOWQUERY keycontent 290 { 291 g_zoneSpec.allowQuery = g_stringList; 292 g_stringList = NULL; 293 } 294 ; 295 296addresscontent: 297 OBRACE addressstatements EBRACE 298 { 299 } 300 301addressstatements: 302 | 303 addressstatements addressstatement SEMICOLON 304 { 305 } 306 ; 307 308addressstatement: 309 DOTTED_DECIMAL_ADDRESS 310 { 311 } 312 ; 313 314 315keycontent: 316 OBRACE keystatements EBRACE 317 { 318 } 319 320keystatements: 321 | 322 keystatements keystatement SEMICOLON 323 { 324 } 325 ; 326 327keystatement: 328 KEY DOMAINNAME 329 { 330 StringListElem * elem; 331 332 elem = ( StringListElem* ) malloc( sizeof( StringListElem ) ); 333 334 if ( !elem ) 335 { 336 LogMsg("ERROR: memory allocation failure"); 337 YYABORT; 338 } 339 340 elem->string = $2; 341 342 elem->next = g_stringList; 343 g_stringList = elem; 344 } 345 ; 346 347 348networkaddress: 349 DOTTED_DECIMAL_ADDRESS 350 | 351 HOSTNAME 352 | 353 WILDCARD 354 ; 355 356block: 357 OBRACE zonestatements EBRACE SEMICOLON 358 ; 359 360statements: 361 | 362 statements statement 363 ; 364 365statement: 366 block 367 { 368 $<string>$ = NULL; 369 } 370 | 371 QUOTEDSTRING 372 { 373 $<string>$ = $1; 374 } 375%% 376 377int yywrap(void); 378 379extern int yylineno; 380 381void yyerror( const char *str ) 382{ 383 fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str ); 384} 385 386int yywrap() 387{ 388 return 1; 389} 390 391 392int 393ParseConfig 394 ( 395 DaemonInfo * d, 396 const char * file 397 ) 398 { 399 extern FILE * yyin; 400 DNSZone * zone; 401 DomainAuthInfo * key; 402 KeySpec * keySpec; 403 ZoneSpec * zoneSpec; 404 int err = 0; 405 406 g_filename = file; 407 408 // Tear down the current zone specifiers 409 410 zone = d->zones; 411 412 while ( zone ) 413 { 414 DNSZone * next = zone->next; 415 416 key = zone->updateKeys; 417 418 while ( key ) 419 { 420 DomainAuthInfo * nextKey = key->next; 421 422 free( key ); 423 424 key = nextKey; 425 } 426 427 key = zone->queryKeys; 428 429 while ( key ) 430 { 431 DomainAuthInfo * nextKey = key->next; 432 433 free( key ); 434 435 key = nextKey; 436 } 437 438 free( zone ); 439 440 zone = next; 441 } 442 443 d->zones = NULL; 444 445 yyin = fopen( file, "r" ); 446 require_action( yyin, exit, err = 0 ); 447 448 err = yyparse( ( void* ) d ); 449 require_action( !err, exit, err = 1 ); 450 451 for ( zoneSpec = g_zones; zoneSpec; zoneSpec = zoneSpec->next ) 452 { 453 StringListElem * elem; 454 mDNSu8 * ok; 455 456 zone = ( DNSZone* ) malloc( sizeof( DNSZone ) ); 457 require_action( zone, exit, err = 1 ); 458 memset( zone, 0, sizeof( DNSZone ) ); 459 460 zone->next = d->zones; 461 d->zones = zone; 462 463 // Fill in the domainname 464 465 ok = MakeDomainNameFromDNSNameString( &zone->name, zoneSpec->name ); 466 require_action( ok, exit, err = 1 ); 467 468 // Fill in the type 469 470 zone->type = zoneSpec->type; 471 472 // Fill in the allow-update keys 473 474 for ( elem = zoneSpec->allowUpdate; elem; elem = elem->next ) 475 { 476 mDNSBool found = mDNSfalse; 477 478 for ( keySpec = g_keys; keySpec; keySpec = keySpec->next ) 479 { 480 if ( strcmp( elem->string, keySpec->name ) == 0 ) 481 { 482 DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) ); 483 mDNSs32 keylen; 484 require_action( authInfo, exit, err = 1 ); 485 memset( authInfo, 0, sizeof( DomainAuthInfo ) ); 486 487 ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name ); 488 if (!ok) { free(authInfo); err = 1; goto exit; } 489 490 keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret ); 491 if (keylen < 0) { free(authInfo); err = 1; goto exit; } 492 493 authInfo->next = zone->updateKeys; 494 zone->updateKeys = authInfo; 495 496 found = mDNStrue; 497 498 break; 499 } 500 } 501 502 // Log this 503 require_action( found, exit, err = 1 ); 504 } 505 506 // Fill in the allow-query keys 507 508 for ( elem = zoneSpec->allowQuery; elem; elem = elem->next ) 509 { 510 mDNSBool found = mDNSfalse; 511 512 for ( keySpec = g_keys; keySpec; keySpec = keySpec->next ) 513 { 514 if ( strcmp( elem->string, keySpec->name ) == 0 ) 515 { 516 DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) ); 517 mDNSs32 keylen; 518 require_action( authInfo, exit, err = 1 ); 519 memset( authInfo, 0, sizeof( DomainAuthInfo ) ); 520 521 ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name ); 522 if (!ok) { free(authInfo); err = 1; goto exit; } 523 524 keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret ); 525 if (keylen < 0) { free(authInfo); err = 1; goto exit; } 526 527 authInfo->next = zone->queryKeys; 528 zone->queryKeys = authInfo; 529 530 found = mDNStrue; 531 532 break; 533 } 534 } 535 536 // Log this 537 require_action( found, exit, err = 1 ); 538 } 539 } 540 541exit: 542 543 return err; 544 } 545 546 547void 548SetupOptions 549 ( 550 OptionsInfo * info, 551 void * context 552 ) 553 { 554 DaemonInfo * d = ( DaemonInfo* ) context; 555 556 if ( strlen( info->source_address ) ) 557 { 558 inet_pton( AF_INET, info->source_address, &d->addr.sin_addr ); 559 } 560 561 if ( info->source_port ) 562 { 563 d->addr.sin_port = htons( ( mDNSu16 ) info->source_port ); 564 } 565 566 if ( strlen( info->server_address ) ) 567 { 568 inet_pton( AF_INET, info->server_address, &d->ns_addr.sin_addr ); 569 } 570 571 if ( info->server_port ) 572 { 573 d->ns_addr.sin_port = htons( ( mDNSu16 ) info->server_port ); 574 } 575 576 if ( info->private_port ) 577 { 578 d->private_port = mDNSOpaque16fromIntVal( info->private_port ); 579 } 580 581 if ( info->llq_port ) 582 { 583 d->llq_port = mDNSOpaque16fromIntVal( info->llq_port ); 584 } 585 } 586