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