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